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