* recog.c (asm_operand_ok): Allow float CONST_VECTORs for 'F'.
[official-gcc.git] / gcc / gensupport.c
blob9e3d0bbcb1fa8a747da362045c4fbd9b1579cbf8
1 /* Support routines for the various generation passes.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
21 #include "hconfig.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "obstack.h"
25 #include "errors.h"
26 #include "gensupport.h"
29 /* In case some macros used by files we include need it, define this here. */
30 int target_flags;
32 static struct obstack obstack;
33 struct obstack *rtl_obstack = &obstack;
35 static int sequence_num;
36 static int errors;
38 static int predicable_default;
39 static const char *predicable_true;
40 static const char *predicable_false;
42 static char *base_dir = NULL;
44 /* We initially queue all patterns, process the define_insn and
45 define_cond_exec patterns, then return them one at a time. */
47 struct queue_elem
49 rtx data;
50 const char *filename;
51 int lineno;
52 struct queue_elem *next;
55 static struct queue_elem *define_attr_queue;
56 static struct queue_elem **define_attr_tail = &define_attr_queue;
57 static struct queue_elem *define_insn_queue;
58 static struct queue_elem **define_insn_tail = &define_insn_queue;
59 static struct queue_elem *define_cond_exec_queue;
60 static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
61 static struct queue_elem *other_queue;
62 static struct queue_elem **other_tail = &other_queue;
64 static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
65 const char *, int));
67 /* Current maximum length of directory names in the search path
68 for include files. (Altered as we get more of them.) */
70 size_t max_include_len;
72 struct file_name_list
74 struct file_name_list *next;
75 const char *fname;
78 struct file_name_list *first_dir_md_include = 0; /* First dir to search */
79 /* First dir to search for <file> */
80 struct file_name_list *first_bracket_include = 0;
81 struct file_name_list *last_dir_md_include = 0; /* Last in chain */
83 static void remove_constraints PARAMS ((rtx));
84 static void process_rtx PARAMS ((rtx, int));
86 static int is_predicable PARAMS ((struct queue_elem *));
87 static void identify_predicable_attribute PARAMS ((void));
88 static int n_alternatives PARAMS ((const char *));
89 static void collect_insn_data PARAMS ((rtx, int *, int *));
90 static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
91 static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
92 struct queue_elem *));
93 static char *shift_output_template PARAMS ((char *, const char *, int));
94 static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
95 struct queue_elem *,
96 int, int));
97 static void process_one_cond_exec PARAMS ((struct queue_elem *));
98 static void process_define_cond_exec PARAMS ((void));
99 static void process_include PARAMS ((rtx, int));
100 static char *save_string PARAMS ((const char *, int));
102 void
103 message_with_line VPARAMS ((int lineno, const char *msg, ...))
105 VA_OPEN (ap, msg);
106 VA_FIXEDARG (ap, int, lineno);
107 VA_FIXEDARG (ap, const char *, msg);
109 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
110 vfprintf (stderr, msg, ap);
111 fputc ('\n', stderr);
113 VA_CLOSE (ap);
116 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
117 the gensupport programs. */
120 gen_rtx_CONST_INT (mode, arg)
121 enum machine_mode mode ATTRIBUTE_UNUSED;
122 HOST_WIDE_INT arg;
124 rtx rt = rtx_alloc (CONST_INT);
126 XWINT (rt, 0) = arg;
127 return rt;
130 /* Queue PATTERN on LIST_TAIL. */
132 static void
133 queue_pattern (pattern, list_tail, filename, lineno)
134 rtx pattern;
135 struct queue_elem ***list_tail;
136 const char *filename;
137 int lineno;
139 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
140 e->data = pattern;
141 e->filename = filename;
142 e->lineno = lineno;
143 e->next = NULL;
144 **list_tail = e;
145 *list_tail = &e->next;
148 /* Recursively remove constraints from an rtx. */
150 static void
151 remove_constraints (part)
152 rtx part;
154 int i, j;
155 const char *format_ptr;
157 if (part == 0)
158 return;
160 if (GET_CODE (part) == MATCH_OPERAND)
161 XSTR (part, 2) = "";
162 else if (GET_CODE (part) == MATCH_SCRATCH)
163 XSTR (part, 1) = "";
165 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
167 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
168 switch (*format_ptr++)
170 case 'e':
171 case 'u':
172 remove_constraints (XEXP (part, i));
173 break;
174 case 'E':
175 if (XVEC (part, i) != NULL)
176 for (j = 0; j < XVECLEN (part, i); j++)
177 remove_constraints (XVECEXP (part, i, j));
178 break;
182 /* Process an include file assuming that it lives in gcc/config/{target}/
183 if the include looks like (include "file"). */
185 static void
186 process_include (desc, lineno)
187 rtx desc;
188 int lineno;
190 const char *filename = XSTR (desc, 0);
191 const char *old_filename;
192 int old_lineno;
193 char *pathname;
194 FILE *input_file;
196 /* If specified file name is absolute, skip the include stack. */
197 if (! IS_ABSOLUTE_PATHNAME (filename))
199 struct file_name_list *stackp;
201 /* Search directory path, trying to open the file. */
202 for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
204 static const char sep[2] = { DIR_SEPARATOR, '\0' };
206 pathname = concat (stackp->fname, sep, filename, NULL);
207 input_file = fopen (pathname, "r");
208 if (input_file != NULL)
209 goto success;
210 free (pathname);
214 if (base_dir)
215 pathname = concat (base_dir, filename, NULL);
216 else
217 pathname = xstrdup (filename);
218 input_file = fopen (pathname, "r");
219 if (input_file == NULL)
221 free (pathname);
222 message_with_line (lineno, "include file `%s' not found", filename);
223 errors = 1;
224 return;
226 success:
228 /* Save old cursor; setup new for the new file. Note that "lineno" the
229 argument to this function is the beginning of the include statement,
230 while read_rtx_lineno has already been advanced. */
231 old_filename = read_rtx_filename;
232 old_lineno = read_rtx_lineno;
233 read_rtx_filename = pathname;
234 read_rtx_lineno = 1;
236 /* Read the entire file. */
237 while (1)
239 rtx desc;
240 int c;
242 c = read_skip_spaces (input_file);
243 if (c == EOF)
244 break;
246 ungetc (c, input_file);
247 lineno = read_rtx_lineno;
248 desc = read_rtx (input_file);
249 process_rtx (desc, lineno);
252 /* Do not free pathname. It is attached to the various rtx queue
253 elements. */
255 read_rtx_filename = old_filename;
256 read_rtx_lineno = old_lineno;
258 fclose (input_file);
261 /* Process a top level rtx in some way, queueing as appropriate. */
263 static void
264 process_rtx (desc, lineno)
265 rtx desc;
266 int lineno;
268 switch (GET_CODE (desc))
270 case DEFINE_INSN:
271 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
272 break;
274 case DEFINE_COND_EXEC:
275 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
276 break;
278 case DEFINE_ATTR:
279 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
280 break;
282 case INCLUDE:
283 process_include (desc, lineno);
284 break;
286 case DEFINE_INSN_AND_SPLIT:
288 const char *split_cond;
289 rtx split;
290 rtvec attr;
291 int i;
293 /* Create a split with values from the insn_and_split. */
294 split = rtx_alloc (DEFINE_SPLIT);
296 i = XVECLEN (desc, 1);
297 XVEC (split, 0) = rtvec_alloc (i);
298 while (--i >= 0)
300 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
301 remove_constraints (XVECEXP (split, 0, i));
304 /* If the split condition starts with "&&", append it to the
305 insn condition to create the new split condition. */
306 split_cond = XSTR (desc, 4);
307 if (split_cond[0] == '&' && split_cond[1] == '&')
309 const char *insn_cond = XSTR (desc, 2);
310 size_t insn_cond_len = strlen (insn_cond);
311 size_t split_cond_len = strlen (split_cond);
312 char *combined;
314 combined = (char *) xmalloc (insn_cond_len + split_cond_len + 1);
315 memcpy (combined, insn_cond, insn_cond_len);
316 memcpy (combined + insn_cond_len, split_cond, split_cond_len + 1);
318 split_cond = combined;
320 XSTR (split, 1) = split_cond;
321 XVEC (split, 2) = XVEC (desc, 5);
322 XSTR (split, 3) = XSTR (desc, 6);
324 /* Fix up the DEFINE_INSN. */
325 attr = XVEC (desc, 7);
326 PUT_CODE (desc, DEFINE_INSN);
327 XVEC (desc, 4) = attr;
329 /* Queue them. */
330 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
331 queue_pattern (split, &other_tail, read_rtx_filename, lineno);
332 break;
335 default:
336 queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
337 break;
341 /* Return true if attribute PREDICABLE is true for ELEM, which holds
342 a DEFINE_INSN. */
344 static int
345 is_predicable (elem)
346 struct queue_elem *elem;
348 rtvec vec = XVEC (elem->data, 4);
349 const char *value;
350 int i;
352 if (! vec)
353 return predicable_default;
355 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
357 rtx sub = RTVEC_ELT (vec, i);
358 switch (GET_CODE (sub))
360 case SET_ATTR:
361 if (strcmp (XSTR (sub, 0), "predicable") == 0)
363 value = XSTR (sub, 1);
364 goto found;
366 break;
368 case SET_ATTR_ALTERNATIVE:
369 if (strcmp (XSTR (sub, 0), "predicable") == 0)
371 message_with_line (elem->lineno,
372 "multiple alternatives for `predicable'");
373 errors = 1;
374 return 0;
376 break;
378 case SET:
379 if (GET_CODE (SET_DEST (sub)) != ATTR
380 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
381 break;
382 sub = SET_SRC (sub);
383 if (GET_CODE (sub) == CONST_STRING)
385 value = XSTR (sub, 0);
386 goto found;
389 /* ??? It would be possible to handle this if we really tried.
390 It's not easy though, and I'm not going to bother until it
391 really proves necessary. */
392 message_with_line (elem->lineno,
393 "non-constant value for `predicable'");
394 errors = 1;
395 return 0;
397 default:
398 abort ();
402 return predicable_default;
404 found:
405 /* Verify that predicability does not vary on the alternative. */
406 /* ??? It should be possible to handle this by simply eliminating
407 the non-predicable alternatives from the insn. FRV would like
408 to do this. Delay this until we've got the basics solid. */
409 if (strchr (value, ',') != NULL)
411 message_with_line (elem->lineno,
412 "multiple alternatives for `predicable'");
413 errors = 1;
414 return 0;
417 /* Find out which value we're looking at. */
418 if (strcmp (value, predicable_true) == 0)
419 return 1;
420 if (strcmp (value, predicable_false) == 0)
421 return 0;
423 message_with_line (elem->lineno,
424 "unknown value `%s' for `predicable' attribute",
425 value);
426 errors = 1;
427 return 0;
430 /* Examine the attribute "predicable"; discover its boolean values
431 and its default. */
433 static void
434 identify_predicable_attribute ()
436 struct queue_elem *elem;
437 char *p_true, *p_false;
438 const char *value;
439 size_t len;
441 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
442 for (elem = define_attr_queue; elem ; elem = elem->next)
443 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
444 goto found;
446 message_with_line (define_cond_exec_queue->lineno,
447 "attribute `predicable' not defined");
448 errors = 1;
449 return;
451 found:
452 value = XSTR (elem->data, 1);
453 len = strlen (value);
454 p_false = (char *) xmalloc (len + 1);
455 memcpy (p_false, value, len + 1);
457 p_true = strchr (p_false, ',');
458 if (p_true == NULL || strchr (++p_true, ',') != NULL)
460 message_with_line (elem->lineno,
461 "attribute `predicable' is not a boolean");
462 errors = 1;
463 return;
465 p_true[-1] = '\0';
467 predicable_true = p_true;
468 predicable_false = p_false;
470 switch (GET_CODE (XEXP (elem->data, 2)))
472 case CONST_STRING:
473 value = XSTR (XEXP (elem->data, 2), 0);
474 break;
476 case CONST:
477 message_with_line (elem->lineno,
478 "attribute `predicable' cannot be const");
479 errors = 1;
480 return;
482 default:
483 message_with_line (elem->lineno,
484 "attribute `predicable' must have a constant default");
485 errors = 1;
486 return;
489 if (strcmp (value, p_true) == 0)
490 predicable_default = 1;
491 else if (strcmp (value, p_false) == 0)
492 predicable_default = 0;
493 else
495 message_with_line (elem->lineno,
496 "unknown value `%s' for `predicable' attribute",
497 value);
498 errors = 1;
502 /* Return the number of alternatives in constraint S. */
504 static int
505 n_alternatives (s)
506 const char *s;
508 int n = 1;
510 if (s)
511 while (*s)
512 n += (*s++ == ',');
514 return n;
517 /* Determine how many alternatives there are in INSN, and how many
518 operands. */
520 static void
521 collect_insn_data (pattern, palt, pmax)
522 rtx pattern;
523 int *palt, *pmax;
525 const char *fmt;
526 enum rtx_code code;
527 int i, j, len;
529 code = GET_CODE (pattern);
530 switch (code)
532 case MATCH_OPERAND:
533 i = n_alternatives (XSTR (pattern, 2));
534 *palt = (i > *palt ? i : *palt);
535 /* FALLTHRU */
537 case MATCH_OPERATOR:
538 case MATCH_SCRATCH:
539 case MATCH_PARALLEL:
540 case MATCH_INSN:
541 i = XINT (pattern, 0);
542 if (i > *pmax)
543 *pmax = i;
544 break;
546 default:
547 break;
550 fmt = GET_RTX_FORMAT (code);
551 len = GET_RTX_LENGTH (code);
552 for (i = 0; i < len; i++)
554 switch (fmt[i])
556 case 'e': case 'u':
557 collect_insn_data (XEXP (pattern, i), palt, pmax);
558 break;
560 case 'V':
561 if (XVEC (pattern, i) == NULL)
562 break;
563 /* FALLTHRU */
564 case 'E':
565 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
566 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
567 break;
569 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
570 break;
572 default:
573 abort ();
578 static rtx
579 alter_predicate_for_insn (pattern, alt, max_op, lineno)
580 rtx pattern;
581 int alt, max_op, lineno;
583 const char *fmt;
584 enum rtx_code code;
585 int i, j, len;
587 code = GET_CODE (pattern);
588 switch (code)
590 case MATCH_OPERAND:
592 const char *c = XSTR (pattern, 2);
594 if (n_alternatives (c) != 1)
596 message_with_line (lineno,
597 "too many alternatives for operand %d",
598 XINT (pattern, 0));
599 errors = 1;
600 return NULL;
603 /* Replicate C as needed to fill out ALT alternatives. */
604 if (c && *c && alt > 1)
606 size_t c_len = strlen (c);
607 size_t len = alt * (c_len + 1);
608 char *new_c = (char *) xmalloc (len);
610 memcpy (new_c, c, c_len);
611 for (i = 1; i < alt; ++i)
613 new_c[i * (c_len + 1) - 1] = ',';
614 memcpy (&new_c[i * (c_len + 1)], c, c_len);
616 new_c[len - 1] = '\0';
617 XSTR (pattern, 2) = new_c;
620 /* FALLTHRU */
622 case MATCH_OPERATOR:
623 case MATCH_SCRATCH:
624 case MATCH_PARALLEL:
625 case MATCH_INSN:
626 XINT (pattern, 0) += max_op;
627 break;
629 default:
630 break;
633 fmt = GET_RTX_FORMAT (code);
634 len = GET_RTX_LENGTH (code);
635 for (i = 0; i < len; i++)
637 rtx r;
639 switch (fmt[i])
641 case 'e': case 'u':
642 r = alter_predicate_for_insn (XEXP (pattern, i), alt,
643 max_op, lineno);
644 if (r == NULL)
645 return r;
646 break;
648 case 'E':
649 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
651 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
652 alt, max_op, lineno);
653 if (r == NULL)
654 return r;
656 break;
658 case 'i': case 'w': case '0': case 's':
659 break;
661 default:
662 abort ();
666 return pattern;
669 static const char *
670 alter_test_for_insn (ce_elem, insn_elem)
671 struct queue_elem *ce_elem, *insn_elem;
673 const char *ce_test, *insn_test;
674 char *new_test;
675 size_t len, ce_len, insn_len;
677 ce_test = XSTR (ce_elem->data, 1);
678 insn_test = XSTR (insn_elem->data, 2);
679 if (!ce_test || *ce_test == '\0')
680 return insn_test;
681 if (!insn_test || *insn_test == '\0')
682 return ce_test;
684 ce_len = strlen (ce_test);
685 insn_len = strlen (insn_test);
686 len = 1 + ce_len + 1 + 4 + 1 + insn_len + 1 + 1;
687 new_test = (char *) xmalloc (len);
689 sprintf (new_test, "(%s) && (%s)", ce_test, insn_test);
691 return new_test;
694 /* Adjust all of the operand numbers in OLD to match the shift they'll
695 get from an operand displacement of DISP. Return a pointer after the
696 adjusted string. */
698 static char *
699 shift_output_template (new, old, disp)
700 char *new;
701 const char *old;
702 int disp;
704 while (*old)
706 char c = *old++;
707 *new++ = c;
708 if (c == '%')
710 c = *old++;
711 if (ISDIGIT ((unsigned char) c))
712 c += disp;
713 else if (ISALPHA (c))
715 *new++ = c;
716 c = *old++ + disp;
718 *new++ = c;
722 return new;
725 static const char *
726 alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
727 struct queue_elem *ce_elem, *insn_elem;
728 int alt, max_op;
730 const char *ce_out, *insn_out;
731 char *new, *p;
732 size_t len, ce_len, insn_len;
734 /* ??? Could coordinate with genoutput to not duplicate code here. */
736 ce_out = XSTR (ce_elem->data, 2);
737 insn_out = XTMPL (insn_elem->data, 3);
738 if (!ce_out || *ce_out == '\0')
739 return insn_out;
741 ce_len = strlen (ce_out);
742 insn_len = strlen (insn_out);
744 if (*insn_out == '*')
745 /* You must take care of the predicate yourself. */
746 return insn_out;
748 if (*insn_out == '@')
750 len = (ce_len + 1) * alt + insn_len + 1;
751 p = new = xmalloc (len);
756 *p++ = *insn_out++;
757 while (ISSPACE ((unsigned char) *insn_out));
759 if (*insn_out != '#')
761 p = shift_output_template (p, ce_out, max_op);
762 *p++ = ' ';
766 *p++ = *insn_out++;
767 while (*insn_out && *insn_out != '\n');
769 while (*insn_out);
770 *p = '\0';
772 else
774 len = ce_len + 1 + insn_len + 1;
775 new = xmalloc (len);
777 p = shift_output_template (new, ce_out, max_op);
778 *p++ = ' ';
779 memcpy (p, insn_out, insn_len + 1);
782 return new;
785 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
787 static void
788 process_one_cond_exec (ce_elem)
789 struct queue_elem *ce_elem;
791 struct queue_elem *insn_elem;
792 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
794 int alternatives, max_operand;
795 rtx pred, insn, pattern;
797 if (! is_predicable (insn_elem))
798 continue;
800 alternatives = 1;
801 max_operand = -1;
802 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
803 max_operand += 1;
805 if (XVECLEN (ce_elem->data, 0) != 1)
807 message_with_line (ce_elem->lineno,
808 "too many patterns in predicate");
809 errors = 1;
810 return;
813 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
814 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
815 ce_elem->lineno);
816 if (pred == NULL)
817 return;
819 /* Construct a new pattern for the new insn. */
820 insn = copy_rtx (insn_elem->data);
821 XSTR (insn, 0) = "";
822 pattern = rtx_alloc (COND_EXEC);
823 XEXP (pattern, 0) = pred;
824 if (XVECLEN (insn, 1) == 1)
826 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
827 XVECEXP (insn, 1, 0) = pattern;
828 PUT_NUM_ELEM (XVEC (insn, 1), 1);
830 else
832 XEXP (pattern, 1) = rtx_alloc (PARALLEL);
833 XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
834 XVEC (insn, 1) = rtvec_alloc (1);
835 XVECEXP (insn, 1, 0) = pattern;
838 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
839 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
840 alternatives, max_operand);
842 /* ??? Set `predicable' to false. Not crucial since it's really
843 only used here, and we won't reprocess this new pattern. */
845 /* Put the new pattern on the `other' list so that it
846 (a) is not reprocessed by other define_cond_exec patterns
847 (b) appears after all normal define_insn patterns.
849 ??? B is debatable. If one has normal insns that match
850 cond_exec patterns, they will be preferred over these
851 generated patterns. Whether this matters in practice, or if
852 it's a good thing, or whether we should thread these new
853 patterns into the define_insn chain just after their generator
854 is something we'll have to experiment with. */
856 queue_pattern (insn, &other_tail, insn_elem->filename,
857 insn_elem->lineno);
861 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
862 patterns appropriately. */
864 static void
865 process_define_cond_exec ()
867 struct queue_elem *elem;
869 identify_predicable_attribute ();
870 if (errors)
871 return;
873 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
874 process_one_cond_exec (elem);
877 static char *
878 save_string (s, len)
879 const char *s;
880 int len;
882 register char *result = xmalloc (len + 1);
884 memcpy (result, s, len);
885 result[len] = 0;
886 return result;
890 /* The entry point for initializing the reader. */
893 init_md_reader_args (argc, argv)
894 int argc;
895 char **argv;
897 int i;
898 const char *in_fname;
900 max_include_len = 0;
901 in_fname = NULL;
902 for (i = 1; i < argc; i++)
904 if (argv[i][0] != '-')
906 if (in_fname == NULL)
907 in_fname = argv[i];
909 else
911 int c = argv[i][1];
912 switch (c)
914 case 'I': /* Add directory to path for includes. */
916 struct file_name_list *dirtmp;
918 dirtmp = (struct file_name_list *)
919 xmalloc (sizeof (struct file_name_list));
920 dirtmp->next = 0; /* New one goes on the end */
921 if (first_dir_md_include == 0)
922 first_dir_md_include = dirtmp;
923 else
924 last_dir_md_include->next = dirtmp;
925 last_dir_md_include = dirtmp; /* Tail follows the last one */
926 if (argv[i][1] == 'I' && argv[i][2] != 0)
927 dirtmp->fname = argv[i] + 2;
928 else if (i + 1 == argc)
929 fatal ("directory name missing after -I option");
930 else
931 dirtmp->fname = argv[++i];
932 if (strlen (dirtmp->fname) > max_include_len)
933 max_include_len = strlen (dirtmp->fname);
935 break;
936 default:
937 fatal ("invalid option `%s'", argv[i]);
942 return init_md_reader (in_fname);
945 /* The entry point for initializing the reader. */
948 init_md_reader (filename)
949 const char *filename;
951 FILE *input_file;
952 int c;
953 char *lastsl;
955 lastsl = strrchr (filename, '/');
956 if (lastsl != NULL)
957 base_dir = save_string (filename, lastsl - filename + 1 );
959 read_rtx_filename = filename;
960 input_file = fopen (filename, "r");
961 if (input_file == 0)
963 perror (filename);
964 return FATAL_EXIT_CODE;
967 obstack_init (rtl_obstack);
968 errors = 0;
969 sequence_num = 0;
971 /* Read the entire file. */
972 while (1)
974 rtx desc;
975 int lineno;
977 c = read_skip_spaces (input_file);
978 if (c == EOF)
979 break;
981 ungetc (c, input_file);
982 lineno = read_rtx_lineno;
983 desc = read_rtx (input_file);
984 process_rtx (desc, lineno);
986 fclose (input_file);
988 /* Process define_cond_exec patterns. */
989 if (define_cond_exec_queue != NULL)
990 process_define_cond_exec ();
992 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
995 /* The entry point for reading a single rtx from an md file. */
998 read_md_rtx (lineno, seqnr)
999 int *lineno;
1000 int *seqnr;
1002 struct queue_elem **queue, *elem;
1003 rtx desc;
1005 /* Read all patterns from a given queue before moving on to the next. */
1006 if (define_attr_queue != NULL)
1007 queue = &define_attr_queue;
1008 else if (define_insn_queue != NULL)
1009 queue = &define_insn_queue;
1010 else if (other_queue != NULL)
1011 queue = &other_queue;
1012 else
1013 return NULL_RTX;
1015 elem = *queue;
1016 *queue = elem->next;
1017 desc = elem->data;
1018 read_rtx_filename = elem->filename;
1019 *lineno = elem->lineno;
1020 *seqnr = sequence_num;
1022 free (elem);
1024 switch (GET_CODE (desc))
1026 case DEFINE_INSN:
1027 case DEFINE_EXPAND:
1028 case DEFINE_SPLIT:
1029 case DEFINE_PEEPHOLE:
1030 case DEFINE_PEEPHOLE2:
1031 sequence_num++;
1032 break;
1034 default:
1035 break;
1038 return desc;
1041 /* Given a string, return the number of comma-separated elements in it.
1042 Return 0 for the null string. */
1044 n_comma_elts (s)
1045 const char *s;
1047 int n;
1049 if (*s == '\0')
1050 return 0;
1052 for (n = 1; *s; s++)
1053 if (*s == ',')
1054 n++;
1056 return n;
1059 /* Given a pointer to a (char *), return a pointer to the beginning of the
1060 next comma-separated element in the string. Advance the pointer given
1061 to the end of that element. Return NULL if at end of string. Caller
1062 is responsible for copying the string if necessary. White space between
1063 a comma and an element is ignored. */
1065 const char *
1066 scan_comma_elt (pstr)
1067 const char **pstr;
1069 const char *start;
1070 const char *p = *pstr;
1072 if (*p == ',')
1073 p++;
1074 while (ISSPACE(*p))
1075 p++;
1077 if (*p == '\0')
1078 return NULL;
1080 start = p;
1082 while (*p != ',' && *p != '\0')
1083 p++;
1085 *pstr = p;
1086 return start;