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