xref: /netbsd/external/gpl3/gcc/dist/gcc/read-md.cc (revision f0fbc68b)
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
leading_string_hash(const void * def)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
leading_string_eq_p(const void * def1,const void * def2)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
leading_ptr_hash(const void * def)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
leading_ptr_eq_p(const void * def1,const void * def2)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
set_md_ptr_loc(const void * ptr,file_location file_loc)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 *
get_md_ptr_loc(const void * ptr)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
copy_md_ptr_loc(const void * new_ptr,const void * old_ptr)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
fprint_md_ptr_loc(FILE * outf,const void * ptr)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
print_md_ptr_loc(const void * ptr)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 *
join_c_conditions(const char * cond1,const char * cond2)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
fprint_c_condition(FILE * outf,const char * cond)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
print_c_condition(const char * cond)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)
message_at_1(file_location loc,const char * msg,va_list ap)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
message_at(file_location loc,const char * msg,...)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
error_at(file_location loc,const char * msg,...)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
fatal_at(file_location loc,const char * msg,...)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
fatal_with_file_and_line(const char * msg,...)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
fatal_expected_char(int expected,int actual)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
read_skip_spaces(void)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
require_char(char expected)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
require_char_ws(char expected)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
require_word_ws(const char * expected)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
read_char(void)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
unread_char(int ch)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
peek_char(void)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
read_name_1(struct md_name * name,file_location * out_loc)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
read_name(struct md_name * name)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
read_name_or_nil(struct md_name * name)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
read_escape()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 *
read_quoted_string()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 *
read_braced_string()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 *
read_string(int star_if_braced)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
read_skip_construct(int depth,file_location loc)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
n_comma_elts(const char * s)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 *
scan_comma_elt(const char ** pstr)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
upcase_string(char * string)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 *
add_constant(htab_t defs,char * name,char * value,struct enum_type * parent_enum)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
handle_constants()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
traverse_md_constants(htab_trav callback,void * info)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 *
md_decimal_string(int number)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
handle_enum(file_location loc,bool md_p)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 *
lookup_enum_type(const char * name)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
traverse_enum_types(htab_trav callback,void * info)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 
md_reader(bool compact)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 
~md_reader()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
handle_include(file_location loc)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
handle_file()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
handle_toplevel_file()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
get_current_location() const1191 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
add_include_path(const char * arg)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
read_md_files(int argc,const char ** argv,bool (* parse_opt)(const char *))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
read_file(const char * filename)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
read_file_fragment(const char * filename,int first_line,int last_line)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
handle_unknown_directive(file_location loc,const char *)1360 noop_reader::handle_unknown_directive (file_location loc, const char *)
1361 {
1362   read_skip_construct (1, loc);
1363 }
1364