]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/read-md.c
Introduce class rtx_reader
[thirdparty/gcc.git] / gcc / read-md.c
1 /* MD reader for GCC.
2 Copyright (C) 1987-2016 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "bconfig.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "errors.h"
24 #include "read-md.h"
25
26 /* Associates PTR (which can be a string, etc.) with the file location
27 specified by FILENAME and LINENO. */
28 struct ptr_loc {
29 const void *ptr;
30 const char *filename;
31 int lineno;
32 };
33
34 /* Obstack used for allocating MD strings. */
35 struct obstack string_obstack;
36
37 /* A table of ptr_locs, hashed on the PTR field. */
38 static htab_t ptr_locs;
39
40 /* An obstack for the above. Plain xmalloc is a bit heavyweight for a
41 small structure like ptr_loc. */
42 static struct obstack ptr_loc_obstack;
43
44 /* A hash table of triples (A, B, C), where each of A, B and C is a condition
45 and A is equivalent to "B && C". This is used to keep track of the source
46 of conditions that are made up of separate MD strings (such as the split
47 condition of a define_insn_and_split). */
48 static htab_t joined_conditions;
49
50 /* An obstack for allocating joined_conditions entries. */
51 static struct obstack joined_conditions_obstack;
52
53 /* This callback will be invoked whenever an md include directive is
54 processed. To be used for creation of the dependency file. */
55 void (*include_callback) (const char *);
56
57 /* Global singleton. */
58
59 rtx_reader *rtx_reader_ptr;
60
61 /* A table of md_constant structures, hashed by name. Null if no
62 constant expansion should occur. */
63 static htab_t md_constants;
64
65 /* A table of enum_type structures, hashed by name. */
66 static htab_t enum_types;
67
68 /* Given an object that starts with a char * name field, return a hash
69 code for its name. */
70
71 hashval_t
72 leading_string_hash (const void *def)
73 {
74 return htab_hash_string (*(const char *const *) def);
75 }
76
77 /* Given two objects that start with char * name fields, return true if
78 they have the same name. */
79
80 int
81 leading_string_eq_p (const void *def1, const void *def2)
82 {
83 return strcmp (*(const char *const *) def1,
84 *(const char *const *) def2) == 0;
85 }
86
87 /* Return a hash value for the pointer pointed to by DEF. */
88
89 static hashval_t
90 leading_ptr_hash (const void *def)
91 {
92 return htab_hash_pointer (*(const void *const *) def);
93 }
94
95 /* Return true if DEF1 and DEF2 are pointers to the same pointer. */
96
97 static int
98 leading_ptr_eq_p (const void *def1, const void *def2)
99 {
100 return *(const void *const *) def1 == *(const void *const *) def2;
101 }
102
103 /* Associate PTR with the file position given by FILENAME and LINENO. */
104
105 static void
106 set_md_ptr_loc (const void *ptr, const char *filename, int lineno)
107 {
108 struct ptr_loc *loc;
109
110 loc = (struct ptr_loc *) obstack_alloc (&ptr_loc_obstack,
111 sizeof (struct ptr_loc));
112 loc->ptr = ptr;
113 loc->filename = filename;
114 loc->lineno = lineno;
115 *htab_find_slot (ptr_locs, loc, INSERT) = loc;
116 }
117
118 /* Return the position associated with pointer PTR. Return null if no
119 position was set. */
120
121 static const struct ptr_loc *
122 get_md_ptr_loc (const void *ptr)
123 {
124 return (const struct ptr_loc *) htab_find (ptr_locs, &ptr);
125 }
126
127 /* Associate NEW_PTR with the same file position as OLD_PTR. */
128
129 void
130 copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
131 {
132 const struct ptr_loc *loc = get_md_ptr_loc (old_ptr);
133 if (loc != 0)
134 set_md_ptr_loc (new_ptr, loc->filename, loc->lineno);
135 }
136
137 /* If PTR is associated with a known file position, print a #line
138 directive for it to OUTF. */
139
140 void
141 fprint_md_ptr_loc (FILE *outf, const void *ptr)
142 {
143 const struct ptr_loc *loc = get_md_ptr_loc (ptr);
144 if (loc != 0)
145 fprintf (outf, "#line %d \"%s\"\n", loc->lineno, loc->filename);
146 }
147
148 /* Special fprint_md_ptr_loc for writing to STDOUT. */
149 void
150 print_md_ptr_loc (const void *ptr)
151 {
152 fprint_md_ptr_loc (stdout, ptr);
153 }
154
155 /* Return a condition that satisfies both COND1 and COND2. Either string
156 may be null or empty. */
157
158 const char *
159 join_c_conditions (const char *cond1, const char *cond2)
160 {
161 char *result;
162 const void **entry;
163
164 if (cond1 == 0 || cond1[0] == 0)
165 return cond2;
166
167 if (cond2 == 0 || cond2[0] == 0)
168 return cond1;
169
170 if (strcmp (cond1, cond2) == 0)
171 return cond1;
172
173 result = concat ("(", cond1, ") && (", cond2, ")", NULL);
174 obstack_ptr_grow (&joined_conditions_obstack, result);
175 obstack_ptr_grow (&joined_conditions_obstack, cond1);
176 obstack_ptr_grow (&joined_conditions_obstack, cond2);
177 entry = XOBFINISH (&joined_conditions_obstack, const void **);
178 *htab_find_slot (joined_conditions, entry, INSERT) = entry;
179 return result;
180 }
181
182 /* Print condition COND to OUTF, wrapped in brackets. If COND was created
183 by join_c_conditions, recursively invoke this function for the original
184 conditions and join the result with "&&". Otherwise print a #line
185 directive for COND if its original file position is known. */
186
187 void
188 fprint_c_condition (FILE *outf, const char *cond)
189 {
190 const char **halves = (const char **) htab_find (joined_conditions, &cond);
191 if (halves != 0)
192 {
193 fprintf (outf, "(");
194 fprint_c_condition (outf, halves[1]);
195 fprintf (outf, " && ");
196 fprint_c_condition (outf, halves[2]);
197 fprintf (outf, ")");
198 }
199 else
200 {
201 fputc ('\n', outf);
202 fprint_md_ptr_loc (outf, cond);
203 fprintf (outf, "(%s)", cond);
204 }
205 }
206
207 /* Special fprint_c_condition for writing to STDOUT. */
208
209 void
210 print_c_condition (const char *cond)
211 {
212 fprint_c_condition (stdout, cond);
213 }
214
215 /* A vfprintf-like function for reporting an error against line LINENO
216 of the current MD file. */
217
218 static void ATTRIBUTE_PRINTF(2,0)
219 message_at_1 (file_location loc, const char *msg, va_list ap)
220 {
221 fprintf (stderr, "%s:%d: ", loc.filename, loc.lineno);
222 vfprintf (stderr, msg, ap);
223 fputc ('\n', stderr);
224 }
225
226 /* A printf-like function for reporting a message against location LOC. */
227
228 void
229 message_at (file_location loc, const char *msg, ...)
230 {
231 va_list ap;
232
233 va_start (ap, msg);
234 message_at_1 (loc, msg, ap);
235 va_end (ap);
236 }
237
238 /* Like message_at, but treat the condition as an error. */
239
240 void
241 error_at (file_location loc, const char *msg, ...)
242 {
243 va_list ap;
244
245 va_start (ap, msg);
246 message_at_1 (loc, msg, ap);
247 va_end (ap);
248 have_error = 1;
249 }
250
251 /* Like message_at, but treat the condition as a fatal error. */
252
253 void
254 fatal_at (file_location loc, const char *msg, ...)
255 {
256 va_list ap;
257
258 va_start (ap, msg);
259 message_at_1 (loc, msg, ap);
260 va_end (ap);
261 exit (1);
262 }
263
264 /* A printf-like function for reporting an error against the current
265 position in the MD file. */
266
267 void
268 fatal_with_file_and_line (const char *msg, ...)
269 {
270 char context[64];
271 size_t i;
272 int c;
273 va_list ap;
274
275 va_start (ap, msg);
276
277 fprintf (stderr, "%s:%d: error: ", rtx_reader_ptr->get_filename (),
278 rtx_reader_ptr->get_lineno ());
279 vfprintf (stderr, msg, ap);
280 putc ('\n', stderr);
281
282 /* Gather some following context. */
283 for (i = 0; i < sizeof (context)-1; ++i)
284 {
285 c = read_char ();
286 if (c == EOF)
287 break;
288 if (c == '\r' || c == '\n')
289 {
290 unread_char (c);
291 break;
292 }
293 context[i] = c;
294 }
295 context[i] = '\0';
296
297 fprintf (stderr, "%s:%d: note: following context is `%s'\n",
298 rtx_reader_ptr->get_filename (), rtx_reader_ptr->get_lineno (),
299 context);
300
301 va_end (ap);
302 exit (1);
303 }
304
305 /* Report that we found character ACTUAL when we expected to find
306 character EXPECTED. */
307
308 void
309 fatal_expected_char (int expected, int actual)
310 {
311 if (actual == EOF)
312 fatal_with_file_and_line ("expected character `%c', found EOF",
313 expected);
314 else
315 fatal_with_file_and_line ("expected character `%c', found `%c'",
316 expected, actual);
317 }
318
319 /* Read chars from the MD file until a non-whitespace char and return that.
320 Comments, both Lisp style and C style, are treated as whitespace. */
321
322 int
323 read_skip_spaces (void)
324 {
325 int c;
326
327 while (1)
328 {
329 c = read_char ();
330 switch (c)
331 {
332 case ' ': case '\t': case '\f': case '\r': case '\n':
333 break;
334
335 case ';':
336 do
337 c = read_char ();
338 while (c != '\n' && c != EOF);
339 break;
340
341 case '/':
342 {
343 int prevc;
344 c = read_char ();
345 if (c != '*')
346 {
347 unread_char (c);
348 fatal_with_file_and_line ("stray '/' in file");
349 }
350
351 prevc = 0;
352 while ((c = read_char ()) && c != EOF)
353 {
354 if (prevc == '*' && c == '/')
355 break;
356 prevc = c;
357 }
358 }
359 break;
360
361 default:
362 return c;
363 }
364 }
365 }
366
367 /* Consume any whitespace, then consume the next non-whitespace
368 character, issuing a fatal error if it is not EXPECTED. */
369
370 void
371 require_char_ws (char expected)
372 {
373 int ch = read_skip_spaces ();
374 if (ch != expected)
375 fatal_expected_char (expected, ch);
376 }
377
378 /* Read the next character from the file. */
379
380 int
381 rtx_reader::read_char (void)
382 {
383 int ch;
384
385 ch = getc (m_read_md_file);
386 if (ch == '\n')
387 m_read_md_lineno++;
388
389 return ch;
390 }
391
392 /* Put back CH, which was the last character read from the file. */
393
394 void
395 rtx_reader::unread_char (int ch)
396 {
397 if (ch == '\n')
398 m_read_md_lineno--;
399 ungetc (ch, m_read_md_file);
400 }
401
402 /* Read an rtx code name into NAME. It is terminated by any of the
403 punctuation chars of rtx printed syntax. */
404
405 void
406 read_name (struct md_name *name)
407 {
408 int c;
409 size_t i;
410 int angle_bracket_depth;
411
412 c = read_skip_spaces ();
413
414 i = 0;
415 angle_bracket_depth = 0;
416 while (1)
417 {
418 if (c == '<')
419 angle_bracket_depth++;
420
421 if ((c == '>') && (angle_bracket_depth > 0))
422 angle_bracket_depth--;
423
424 if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r'
425 || c == EOF)
426 break;
427 if (angle_bracket_depth == 0)
428 {
429 if (c == ':' || c == ')' || c == ']'
430 || c == '"' || c == '/' || c == '(' || c == '[')
431 {
432 unread_char (c);
433 break;
434 }
435 }
436
437 if (i == sizeof (name->buffer) - 1)
438 fatal_with_file_and_line ("name too long");
439 name->buffer[i++] = c;
440
441 c = read_char ();
442 }
443
444 if (i == 0)
445 fatal_with_file_and_line ("missing name or number");
446
447 name->buffer[i] = 0;
448 name->string = name->buffer;
449
450 if (md_constants)
451 {
452 /* Do constant expansion. */
453 struct md_constant *def;
454
455 do
456 {
457 struct md_constant tmp_def;
458
459 tmp_def.name = name->string;
460 def = (struct md_constant *) htab_find (md_constants, &tmp_def);
461 if (def)
462 name->string = def->value;
463 }
464 while (def);
465 }
466 }
467
468 /* Subroutine of the string readers. Handles backslash escapes.
469 Caller has read the backslash, but not placed it into the obstack. */
470
471 static void
472 read_escape (void)
473 {
474 int c = read_char ();
475
476 switch (c)
477 {
478 /* Backslash-newline is replaced by nothing, as in C. */
479 case '\n':
480 return;
481
482 /* \" \' \\ are replaced by the second character. */
483 case '\\':
484 case '"':
485 case '\'':
486 break;
487
488 /* Standard C string escapes:
489 \a \b \f \n \r \t \v
490 \[0-7] \x
491 all are passed through to the output string unmolested.
492 In normal use these wind up in a string constant processed
493 by the C compiler, which will translate them appropriately.
494 We do not bother checking that \[0-7] are followed by up to
495 two octal digits, or that \x is followed by N hex digits.
496 \? \u \U are left out because they are not in traditional C. */
497 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
498 case '0': case '1': case '2': case '3': case '4': case '5': case '6':
499 case '7': case 'x':
500 obstack_1grow (&string_obstack, '\\');
501 break;
502
503 /* \; makes stuff for a C string constant containing
504 newline and tab. */
505 case ';':
506 obstack_grow (&string_obstack, "\\n\\t", 4);
507 return;
508
509 /* pass anything else through, but issue a warning. */
510 default:
511 fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
512 rtx_reader_ptr->get_filename (), rtx_reader_ptr->get_lineno (),
513 c);
514 obstack_1grow (&string_obstack, '\\');
515 break;
516 }
517
518 obstack_1grow (&string_obstack, c);
519 }
520
521 /* Read a double-quoted string onto the obstack. Caller has scanned
522 the leading quote. */
523
524 char *
525 read_quoted_string (void)
526 {
527 int c;
528
529 while (1)
530 {
531 c = read_char (); /* Read the string */
532 if (c == '\\')
533 {
534 read_escape ();
535 continue;
536 }
537 else if (c == '"' || c == EOF)
538 break;
539
540 obstack_1grow (&string_obstack, c);
541 }
542
543 obstack_1grow (&string_obstack, 0);
544 return XOBFINISH (&string_obstack, char *);
545 }
546
547 /* Read a braced string (a la Tcl) onto the string obstack. Caller
548 has scanned the leading brace. Note that unlike quoted strings,
549 the outermost braces _are_ included in the string constant. */
550
551 static char *
552 read_braced_string (void)
553 {
554 int c;
555 int brace_depth = 1; /* caller-processed */
556 unsigned long starting_read_md_lineno = rtx_reader_ptr->get_lineno ();
557
558 obstack_1grow (&string_obstack, '{');
559 while (brace_depth)
560 {
561 c = read_char (); /* Read the string */
562
563 if (c == '{')
564 brace_depth++;
565 else if (c == '}')
566 brace_depth--;
567 else if (c == '\\')
568 {
569 read_escape ();
570 continue;
571 }
572 else if (c == EOF)
573 fatal_with_file_and_line
574 ("missing closing } for opening brace on line %lu",
575 starting_read_md_lineno);
576
577 obstack_1grow (&string_obstack, c);
578 }
579
580 obstack_1grow (&string_obstack, 0);
581 return XOBFINISH (&string_obstack, char *);
582 }
583
584 /* Read some kind of string constant. This is the high-level routine
585 used by read_rtx. It handles surrounding parentheses, leading star,
586 and dispatch to the appropriate string constant reader. */
587
588 char *
589 read_string (int star_if_braced)
590 {
591 char *stringbuf;
592 int saw_paren = 0;
593 int c, old_lineno;
594
595 c = read_skip_spaces ();
596 if (c == '(')
597 {
598 saw_paren = 1;
599 c = read_skip_spaces ();
600 }
601
602 old_lineno = rtx_reader_ptr->get_lineno ();
603 if (c == '"')
604 stringbuf = read_quoted_string ();
605 else if (c == '{')
606 {
607 if (star_if_braced)
608 obstack_1grow (&string_obstack, '*');
609 stringbuf = read_braced_string ();
610 }
611 else
612 fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
613
614 if (saw_paren)
615 require_char_ws (')');
616
617 set_md_ptr_loc (stringbuf, rtx_reader_ptr->get_filename (), old_lineno);
618 return stringbuf;
619 }
620
621 /* Skip the rest of a construct that started at line LINENO and that
622 is currently nested by DEPTH levels of parentheses. */
623
624 static void
625 read_skip_construct (int depth, file_location loc)
626 {
627 struct md_name name;
628 int c;
629
630 do
631 {
632 c = read_skip_spaces ();
633 if (c == EOF)
634 {
635 error_at (loc, "unterminated construct");
636 exit (1);
637 }
638 switch (c)
639 {
640 case '(':
641 depth++;
642 break;
643
644 case ')':
645 depth--;
646 break;
647
648 case ':':
649 case '[':
650 case ']':
651 case '/':
652 break;
653
654 case '\"':
655 case '{':
656 unread_char (c);
657 read_string (false);
658 break;
659
660 default:
661 unread_char (c);
662 read_name (&name);
663 break;
664 }
665 }
666 while (depth > 0);
667 unread_char (c);
668 }
669
670 /* Given a string, return the number of comma-separated elements in it.
671 Return 0 for the null string. */
672
673 int
674 n_comma_elts (const char *s)
675 {
676 int n;
677
678 if (*s == '\0')
679 return 0;
680
681 for (n = 1; *s; s++)
682 if (*s == ',')
683 n++;
684
685 return n;
686 }
687
688 /* Given a pointer to a (char *), return a pointer to the beginning of the
689 next comma-separated element in the string. Advance the pointer given
690 to the end of that element. Return NULL if at end of string. Caller
691 is responsible for copying the string if necessary. White space between
692 a comma and an element is ignored. */
693
694 const char *
695 scan_comma_elt (const char **pstr)
696 {
697 const char *start;
698 const char *p = *pstr;
699
700 if (*p == ',')
701 p++;
702 while (ISSPACE (*p))
703 p++;
704
705 if (*p == '\0')
706 return NULL;
707
708 start = p;
709
710 while (*p != ',' && *p != '\0')
711 p++;
712
713 *pstr = p;
714 return start;
715 }
716
717 /* Convert STRING to uppercase. */
718
719 void
720 upcase_string (char *string)
721 {
722 int i;
723
724 for (i = 0; string[i]; i++)
725 string[i] = TOUPPER (string[i]);
726 }
727
728 /* Add a NAME = VALUE definition to md_constants-style hash table DEFS,
729 where both NAME and VALUE are malloc()ed strings. PARENT_ENUM is the
730 enum to which NAME belongs, or null if NAME is a stand-alone constant. */
731
732 static struct md_constant *
733 add_constant (htab_t defs, char *name, char *value,
734 struct enum_type *parent_enum)
735 {
736 struct md_constant *def, tmp_def;
737 void **entry_ptr;
738
739 tmp_def.name = name;
740 entry_ptr = htab_find_slot (defs, &tmp_def, INSERT);
741 if (*entry_ptr)
742 {
743 def = (struct md_constant *) *entry_ptr;
744 if (strcmp (def->value, value) != 0)
745 fatal_with_file_and_line ("redefinition of `%s', was `%s', now `%s'",
746 def->name, def->value, value);
747 else if (parent_enum || def->parent_enum)
748 fatal_with_file_and_line ("redefinition of `%s'", def->name);
749 free (name);
750 free (value);
751 }
752 else
753 {
754 def = XNEW (struct md_constant);
755 def->name = name;
756 def->value = value;
757 def->parent_enum = parent_enum;
758 *entry_ptr = def;
759 }
760 return def;
761 }
762
763 /* Process a define_constants directive, starting with the optional space
764 after the "define_constants". */
765
766 static void
767 handle_constants (void)
768 {
769 int c;
770 htab_t defs;
771
772 require_char_ws ('[');
773
774 /* Disable constant expansion during definition processing. */
775 defs = md_constants;
776 md_constants = 0;
777 while ( (c = read_skip_spaces ()) != ']')
778 {
779 struct md_name name, value;
780
781 if (c != '(')
782 fatal_expected_char ('(', c);
783
784 read_name (&name);
785 read_name (&value);
786 add_constant (defs, xstrdup (name.string), xstrdup (value.string), 0);
787
788 require_char_ws (')');
789 }
790 md_constants = defs;
791 }
792
793 /* For every constant definition, call CALLBACK with two arguments:
794 a pointer a pointer to the constant definition and INFO.
795 Stop when CALLBACK returns zero. */
796
797 void
798 traverse_md_constants (htab_trav callback, void *info)
799 {
800 htab_traverse (md_constants, callback, info);
801 }
802
803 /* Return a malloc()ed decimal string that represents number NUMBER. */
804
805 static char *
806 md_decimal_string (int number)
807 {
808 /* A safe overestimate. +1 for sign, +1 for null terminator. */
809 char buffer[sizeof (int) * CHAR_BIT + 1 + 1];
810
811 sprintf (buffer, "%d", number);
812 return xstrdup (buffer);
813 }
814
815 /* Process a define_enum or define_c_enum directive, starting with
816 the optional space after the "define_enum". LINENO is the line
817 number on which the directive started and MD_P is true if the
818 directive is a define_enum rather than a define_c_enum. */
819
820 static void
821 handle_enum (file_location loc, bool md_p)
822 {
823 char *enum_name, *value_name;
824 struct md_name name;
825 struct enum_type *def;
826 struct enum_value *ev;
827 void **slot;
828 int c;
829
830 enum_name = read_string (false);
831 slot = htab_find_slot (enum_types, &enum_name, INSERT);
832 if (*slot)
833 {
834 def = (struct enum_type *) *slot;
835 if (def->md_p != md_p)
836 error_at (loc, "redefining `%s' as a different type of enum",
837 enum_name);
838 }
839 else
840 {
841 def = XNEW (struct enum_type);
842 def->name = enum_name;
843 def->md_p = md_p;
844 def->values = 0;
845 def->tail_ptr = &def->values;
846 def->num_values = 0;
847 *slot = def;
848 }
849
850 require_char_ws ('[');
851
852 while ((c = read_skip_spaces ()) != ']')
853 {
854 if (c == EOF)
855 {
856 error_at (loc, "unterminated construct");
857 exit (1);
858 }
859 unread_char (c);
860 read_name (&name);
861
862 ev = XNEW (struct enum_value);
863 ev->next = 0;
864 if (md_p)
865 {
866 value_name = concat (def->name, "_", name.string, NULL);
867 upcase_string (value_name);
868 ev->name = xstrdup (name.string);
869 }
870 else
871 {
872 value_name = xstrdup (name.string);
873 ev->name = value_name;
874 }
875 ev->def = add_constant (md_constants, value_name,
876 md_decimal_string (def->num_values), def);
877
878 *def->tail_ptr = ev;
879 def->tail_ptr = &ev->next;
880 def->num_values++;
881 }
882 }
883
884 /* Try to find the definition of the given enum. Return null on failure. */
885
886 struct enum_type *
887 lookup_enum_type (const char *name)
888 {
889 return (struct enum_type *) htab_find (enum_types, &name);
890 }
891
892 /* For every enum definition, call CALLBACK with two arguments:
893 a pointer to the constant definition and INFO. Stop when CALLBACK
894 returns zero. */
895
896 void
897 traverse_enum_types (htab_trav callback, void *info)
898 {
899 htab_traverse (enum_types, callback, info);
900 }
901
902
903 /* Constructor for rtx_reader. */
904
905 rtx_reader::rtx_reader ()
906 : m_toplevel_fname (NULL),
907 m_base_dir (NULL),
908 m_read_md_file (NULL),
909 m_read_md_filename (NULL),
910 m_read_md_lineno (0),
911 m_first_dir_md_include (NULL),
912 m_last_dir_md_include_ptr (&m_first_dir_md_include)
913 {
914 /* Set the global singleton pointer. */
915 rtx_reader_ptr = this;
916 }
917
918 /* rtx_reader's destructor. */
919
920 rtx_reader::~rtx_reader ()
921 {
922 /* Clear the global singleton pointer. */
923 rtx_reader_ptr = NULL;
924 }
925
926 /* Process an "include" directive, starting with the optional space
927 after the "include". Read in the file and use HANDLE_DIRECTIVE
928 to process each unknown directive. LINENO is the line number on
929 which the "include" occurred. */
930
931 void
932 rtx_reader::handle_include (file_location loc)
933 {
934 const char *filename;
935 const char *old_filename;
936 int old_lineno;
937 char *pathname;
938 FILE *input_file, *old_file;
939
940 filename = read_string (false);
941 input_file = NULL;
942
943 /* If the specified file name is absolute, skip the include stack. */
944 if (!IS_ABSOLUTE_PATH (filename))
945 {
946 struct file_name_list *stackp;
947
948 /* Search the directory path, trying to open the file. */
949 for (stackp = m_first_dir_md_include; stackp; stackp = stackp->next)
950 {
951 static const char sep[2] = { DIR_SEPARATOR, '\0' };
952
953 pathname = concat (stackp->fname, sep, filename, NULL);
954 input_file = fopen (pathname, "r");
955 if (input_file != NULL)
956 break;
957 free (pathname);
958 }
959 }
960
961 /* If we haven't managed to open the file yet, try combining the
962 filename with BASE_DIR. */
963 if (input_file == NULL)
964 {
965 if (m_base_dir)
966 pathname = concat (m_base_dir, filename, NULL);
967 else
968 pathname = xstrdup (filename);
969 input_file = fopen (pathname, "r");
970 }
971
972 if (input_file == NULL)
973 {
974 free (pathname);
975 error_at (loc, "include file `%s' not found", filename);
976 return;
977 }
978
979 /* Save the old cursor. Note that the LINENO argument to this
980 function is the beginning of the include statement, while
981 read_md_lineno has already been advanced. */
982 old_file = m_read_md_file;
983 old_filename = m_read_md_filename;
984 old_lineno = m_read_md_lineno;
985
986 if (include_callback)
987 include_callback (pathname);
988
989 m_read_md_file = input_file;
990 m_read_md_filename = pathname;
991
992 handle_file ();
993
994 /* Restore the old cursor. */
995 m_read_md_file = old_file;
996 m_read_md_filename = old_filename;
997 m_read_md_lineno = old_lineno;
998
999 /* Do not free the pathname. It is attached to the various rtx
1000 queue elements. */
1001 }
1002
1003 /* Process the current file, assuming that read_md_file and
1004 read_md_filename are valid. Use HANDLE_DIRECTIVE to handle
1005 unknown directives. */
1006
1007 void
1008 rtx_reader::handle_file ()
1009 {
1010 struct md_name directive;
1011 int c;
1012
1013 m_read_md_lineno = 1;
1014 while ((c = read_skip_spaces ()) != EOF)
1015 {
1016 file_location loc = get_current_location ();
1017 if (c != '(')
1018 fatal_expected_char ('(', c);
1019
1020 read_name (&directive);
1021 if (strcmp (directive.string, "define_constants") == 0)
1022 handle_constants ();
1023 else if (strcmp (directive.string, "define_enum") == 0)
1024 handle_enum (loc, true);
1025 else if (strcmp (directive.string, "define_c_enum") == 0)
1026 handle_enum (loc, false);
1027 else if (strcmp (directive.string, "include") == 0)
1028 handle_include (loc);
1029 else
1030 handle_unknown_directive (loc, directive.string);
1031
1032 require_char_ws (')');
1033 }
1034 fclose (m_read_md_file);
1035 }
1036
1037 /* Like handle_file, but for top-level files. Set up m_toplevel_fname
1038 and m_base_dir accordingly. */
1039
1040 void
1041 rtx_reader::handle_toplevel_file ()
1042 {
1043 const char *base;
1044
1045 m_toplevel_fname = m_read_md_filename;
1046 base = lbasename (m_toplevel_fname);
1047 if (base == m_toplevel_fname)
1048 m_base_dir = NULL;
1049 else
1050 m_base_dir = xstrndup (m_toplevel_fname, base - m_toplevel_fname);
1051
1052 handle_file ();
1053 }
1054
1055 file_location
1056 rtx_reader::get_current_location () const
1057 {
1058 return file_location (m_read_md_filename, m_read_md_lineno);
1059 }
1060
1061 /* Parse a -I option with argument ARG. */
1062
1063 void
1064 rtx_reader::add_include_path (const char *arg)
1065 {
1066 struct file_name_list *dirtmp;
1067
1068 dirtmp = XNEW (struct file_name_list);
1069 dirtmp->next = 0;
1070 dirtmp->fname = arg;
1071 *m_last_dir_md_include_ptr = dirtmp;
1072 m_last_dir_md_include_ptr = &dirtmp->next;
1073 }
1074
1075 /* The main routine for reading .md files. Try to process all the .md
1076 files specified on the command line and return true if no error occurred.
1077
1078 ARGC and ARGV are the arguments to main.
1079
1080 PARSE_OPT, if nonnull, is passed all unknown command-line arguments.
1081 It should return true if it recognizes the argument or false if a
1082 generic error should be reported. */
1083
1084 bool
1085 rtx_reader::read_md_files (int argc, const char **argv,
1086 bool (*parse_opt) (const char *))
1087 {
1088 int i;
1089 bool no_more_options;
1090 bool already_read_stdin;
1091 int num_files;
1092
1093 /* Initialize global data. */
1094 obstack_init (&string_obstack);
1095 ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1096 obstack_init (&ptr_loc_obstack);
1097 joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1098 obstack_init (&joined_conditions_obstack);
1099 md_constants = htab_create (31, leading_string_hash,
1100 leading_string_eq_p, (htab_del) 0);
1101 enum_types = htab_create (31, leading_string_hash,
1102 leading_string_eq_p, (htab_del) 0);
1103
1104 /* Unlock the stdio streams. */
1105 unlock_std_streams ();
1106
1107 /* First we loop over all the options. */
1108 for (i = 1; i < argc; i++)
1109 if (argv[i][0] == '-')
1110 {
1111 /* An argument consisting of exactly one dash is a request to
1112 read stdin. This will be handled in the second loop. */
1113 if (argv[i][1] == '\0')
1114 continue;
1115
1116 /* An argument consisting of just two dashes causes option
1117 parsing to cease. */
1118 if (argv[i][1] == '-' && argv[i][2] == '\0')
1119 break;
1120
1121 if (argv[i][1] == 'I')
1122 {
1123 if (argv[i][2] != '\0')
1124 add_include_path (argv[i] + 2);
1125 else if (++i < argc)
1126 add_include_path (argv[i]);
1127 else
1128 fatal ("directory name missing after -I option");
1129 continue;
1130 }
1131
1132 /* The program may have provided a callback so it can
1133 accept its own options. */
1134 if (parse_opt && parse_opt (argv[i]))
1135 continue;
1136
1137 fatal ("invalid option `%s'", argv[i]);
1138 }
1139
1140 /* Now loop over all input files. */
1141 num_files = 0;
1142 no_more_options = false;
1143 already_read_stdin = false;
1144 for (i = 1; i < argc; i++)
1145 {
1146 if (argv[i][0] == '-')
1147 {
1148 if (argv[i][1] == '\0')
1149 {
1150 /* Read stdin. */
1151 if (already_read_stdin)
1152 fatal ("cannot read standard input twice");
1153
1154 m_read_md_file = stdin;
1155 m_read_md_filename = "<stdin>";
1156 handle_toplevel_file ();
1157 already_read_stdin = true;
1158 continue;
1159 }
1160 else if (argv[i][1] == '-' && argv[i][2] == '\0')
1161 {
1162 /* No further arguments are to be treated as options. */
1163 no_more_options = true;
1164 continue;
1165 }
1166 else if (!no_more_options)
1167 continue;
1168 }
1169
1170 /* If we get here we are looking at a non-option argument, i.e.
1171 a file to be processed. */
1172 m_read_md_filename = argv[i];
1173 m_read_md_file = fopen (m_read_md_filename, "r");
1174 if (m_read_md_file == 0)
1175 {
1176 perror (m_read_md_filename);
1177 return false;
1178 }
1179 handle_toplevel_file ();
1180 num_files++;
1181 }
1182
1183 /* If we get to this point without having seen any files to process,
1184 read the standard input now. */
1185 if (num_files == 0 && !already_read_stdin)
1186 {
1187 m_read_md_file = stdin;
1188 m_read_md_filename = "<stdin>";
1189 handle_toplevel_file ();
1190 }
1191
1192 return !have_error;
1193 }
1194
1195 /* class noop_reader : public rtx_reader */
1196
1197 /* A dummy implementation which skips unknown directives. */
1198 void
1199 noop_reader::handle_unknown_directive (file_location loc, const char *)
1200 {
1201 read_skip_construct (1, loc);
1202 }