1 /* MD reader for GCC.
2    Copyright (C) 1987-2021 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.c 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   struct md_name name;
906   struct enum_type *def;
907   struct enum_value *ev;
908   void **slot;
909   int c;
910 
911   enum_name = read_string (false);
912   slot = htab_find_slot (m_enum_types, &enum_name, INSERT);
913   if (*slot)
914     {
915       def = (struct enum_type *) *slot;
916       if (def->md_p != md_p)
917 	error_at (loc, "redefining `%s' as a different type of enum",
918 		  enum_name);
919     }
920   else
921     {
922       def = XNEW (struct enum_type);
923       def->name = enum_name;
924       def->md_p = md_p;
925       def->values = 0;
926       def->tail_ptr = &def->values;
927       def->num_values = 0;
928       *slot = def;
929     }
930 
931   require_char_ws ('[');
932 
933   while ((c = read_skip_spaces ()) != ']')
934     {
935       if (c == EOF)
936 	{
937 	  error_at (loc, "unterminated construct");
938 	  exit (1);
939 	}
940       unread_char (c);
941       read_name (&name);
942 
943       ev = XNEW (struct enum_value);
944       ev->next = 0;
945       if (md_p)
946 	{
947 	  value_name = concat (def->name, "_", name.string, NULL);
948 	  upcase_string (value_name);
949 	  ev->name = xstrdup (name.string);
950 	}
951       else
952 	{
953 	  value_name = xstrdup (name.string);
954 	  ev->name = value_name;
955 	}
956       ev->def = add_constant (get_md_constants (), value_name,
957 			      md_decimal_string (def->num_values), def);
958 
959       *def->tail_ptr = ev;
960       def->tail_ptr = &ev->next;
961       def->num_values++;
962     }
963 }
964 
965 /* Try to find the definition of the given enum.  Return null on failure.  */
966 
967 struct enum_type *
lookup_enum_type(const char * name)968 md_reader::lookup_enum_type (const char *name)
969 {
970   return (struct enum_type *) htab_find (m_enum_types, &name);
971 }
972 
973 /* For every enum definition, call CALLBACK with two arguments:
974    a pointer to the constant definition and INFO.  Stop when CALLBACK
975    returns zero.  */
976 
977 void
traverse_enum_types(htab_trav callback,void * info)978 md_reader::traverse_enum_types (htab_trav callback, void *info)
979 {
980   htab_traverse (m_enum_types, callback, info);
981 }
982 
983 
984 /* Constructor for md_reader.  */
985 
md_reader(bool compact)986 md_reader::md_reader (bool compact)
987 : m_compact (compact),
988   m_toplevel_fname (NULL),
989   m_base_dir (NULL),
990   m_read_md_file (NULL),
991   m_read_md_filename (NULL),
992   m_read_md_lineno (0),
993   m_read_md_colno (0),
994   m_first_dir_md_include (NULL),
995   m_last_dir_md_include_ptr (&m_first_dir_md_include),
996   m_first_line (0),
997   m_last_line (0),
998   m_first_overload (NULL),
999   m_next_overload_ptr (&m_first_overload),
1000   m_overloads_htab (NULL)
1001 {
1002   /* Set the global singleton pointer.  */
1003   md_reader_ptr = this;
1004 
1005   obstack_init (&m_string_obstack);
1006 
1007   m_ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1008   obstack_init (&m_ptr_loc_obstack);
1009 
1010   m_joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1011   obstack_init (&m_joined_conditions_obstack);
1012 
1013   m_md_constants = htab_create (31, leading_string_hash,
1014 				leading_string_eq_p, (htab_del) 0);
1015 
1016   m_enum_types = htab_create (31, leading_string_hash,
1017 			      leading_string_eq_p, (htab_del) 0);
1018 
1019   /* Unlock the stdio streams.  */
1020   unlock_std_streams ();
1021 }
1022 
1023 /* md_reader's destructor.  */
1024 
~md_reader()1025 md_reader::~md_reader ()
1026 {
1027   free (m_base_dir);
1028 
1029   htab_delete (m_enum_types);
1030 
1031   htab_delete (m_md_constants);
1032 
1033   obstack_free (&m_joined_conditions_obstack, NULL);
1034   htab_delete (m_joined_conditions);
1035 
1036   obstack_free (&m_ptr_loc_obstack, NULL);
1037   htab_delete (m_ptr_locs);
1038 
1039   obstack_free (&m_string_obstack, NULL);
1040 
1041   /* Clear the global singleton pointer.  */
1042   md_reader_ptr = NULL;
1043 }
1044 
1045 /* Process an "include" directive, starting with the optional space
1046    after the "include".  Read in the file and use HANDLE_DIRECTIVE
1047    to process each unknown directive.  LINENO is the line number on
1048    which the "include" occurred.  */
1049 
1050 void
handle_include(file_location loc)1051 md_reader::handle_include (file_location loc)
1052 {
1053   const char *filename;
1054   const char *old_filename;
1055   int old_lineno, old_colno;
1056   char *pathname;
1057   FILE *input_file, *old_file;
1058 
1059   filename = read_string (false);
1060   input_file = NULL;
1061 
1062   /* If the specified file name is absolute, skip the include stack.  */
1063   if (!IS_ABSOLUTE_PATH (filename))
1064     {
1065       struct file_name_list *stackp;
1066 
1067       /* Search the directory path, trying to open the file.  */
1068       for (stackp = m_first_dir_md_include; stackp; stackp = stackp->next)
1069 	{
1070 	  static const char sep[2] = { DIR_SEPARATOR, '\0' };
1071 
1072 	  pathname = concat (stackp->fname, sep, filename, NULL);
1073 	  input_file = fopen (pathname, "r");
1074 	  if (input_file != NULL)
1075 	    break;
1076 	  free (pathname);
1077 	}
1078     }
1079 
1080   /* If we haven't managed to open the file yet, try combining the
1081      filename with BASE_DIR.  */
1082   if (input_file == NULL)
1083     {
1084       if (m_base_dir)
1085 	pathname = concat (m_base_dir, filename, NULL);
1086       else
1087 	pathname = xstrdup (filename);
1088       input_file = fopen (pathname, "r");
1089     }
1090 
1091   if (input_file == NULL)
1092     {
1093       free (pathname);
1094       error_at (loc, "include file `%s' not found", filename);
1095       return;
1096     }
1097 
1098   /* Save the old cursor.  Note that the LINENO argument to this
1099      function is the beginning of the include statement, while
1100      read_md_lineno has already been advanced.  */
1101   old_file = m_read_md_file;
1102   old_filename = m_read_md_filename;
1103   old_lineno = m_read_md_lineno;
1104   old_colno = m_read_md_colno;
1105 
1106   if (include_callback)
1107     include_callback (pathname);
1108 
1109   m_read_md_file = input_file;
1110   m_read_md_filename = pathname;
1111 
1112   handle_file ();
1113 
1114   /* Restore the old cursor.  */
1115   m_read_md_file = old_file;
1116   m_read_md_filename = old_filename;
1117   m_read_md_lineno = old_lineno;
1118   m_read_md_colno = old_colno;
1119 
1120   /* Do not free the pathname.  It is attached to the various rtx
1121      queue elements.  */
1122 }
1123 
1124 /* Process the current file, assuming that read_md_file and
1125    read_md_filename are valid.  Use HANDLE_DIRECTIVE to handle
1126    unknown directives.  */
1127 
1128 void
handle_file()1129 md_reader::handle_file ()
1130 {
1131   struct md_name directive;
1132   int c;
1133 
1134   m_read_md_lineno = 1;
1135   m_read_md_colno = 0;
1136   while ((c = read_skip_spaces ()) != EOF)
1137     {
1138       file_location loc = get_current_location ();
1139       if (c != '(')
1140 	fatal_expected_char ('(', c);
1141 
1142       read_name (&directive);
1143       if (strcmp (directive.string, "define_constants") == 0)
1144 	handle_constants ();
1145       else if (strcmp (directive.string, "define_enum") == 0)
1146 	handle_enum (loc, true);
1147       else if (strcmp (directive.string, "define_c_enum") == 0)
1148 	handle_enum (loc, false);
1149       else if (strcmp (directive.string, "include") == 0)
1150 	handle_include (loc);
1151       else
1152 	handle_unknown_directive (loc, directive.string);
1153 
1154       require_char_ws (')');
1155     }
1156   fclose (m_read_md_file);
1157 }
1158 
1159 /* Like handle_file, but for top-level files.  Set up m_toplevel_fname
1160    and m_base_dir accordingly.  */
1161 
1162 void
handle_toplevel_file()1163 md_reader::handle_toplevel_file ()
1164 {
1165   const char *base;
1166 
1167   m_toplevel_fname = m_read_md_filename;
1168   base = lbasename (m_toplevel_fname);
1169   if (base == m_toplevel_fname)
1170     m_base_dir = NULL;
1171   else
1172     m_base_dir = xstrndup (m_toplevel_fname, base - m_toplevel_fname);
1173 
1174   handle_file ();
1175 }
1176 
1177 file_location
get_current_location()1178 md_reader::get_current_location () const
1179 {
1180   return file_location (m_read_md_filename, m_read_md_lineno, m_read_md_colno);
1181 }
1182 
1183 /* Parse a -I option with argument ARG.  */
1184 
1185 void
add_include_path(const char * arg)1186 md_reader::add_include_path (const char *arg)
1187 {
1188   struct file_name_list *dirtmp;
1189 
1190   dirtmp = XNEW (struct file_name_list);
1191   dirtmp->next = 0;
1192   dirtmp->fname = arg;
1193   *m_last_dir_md_include_ptr = dirtmp;
1194   m_last_dir_md_include_ptr = &dirtmp->next;
1195 }
1196 
1197 #ifdef GENERATOR_FILE
1198 
1199 /* The main routine for reading .md files.  Try to process all the .md
1200    files specified on the command line and return true if no error occurred.
1201 
1202    ARGC and ARGV are the arguments to main.
1203 
1204    PARSE_OPT, if nonnull, is passed all unknown command-line arguments.
1205    It should return true if it recognizes the argument or false if a
1206    generic error should be reported.  */
1207 
1208 bool
read_md_files(int argc,const char ** argv,bool (* parse_opt)(const char *))1209 md_reader::read_md_files (int argc, const char **argv,
1210 			  bool (*parse_opt) (const char *))
1211 {
1212   int i;
1213   bool no_more_options;
1214   bool already_read_stdin;
1215   int num_files;
1216 
1217   /* First we loop over all the options.  */
1218   for (i = 1; i < argc; i++)
1219     if (argv[i][0] == '-')
1220       {
1221 	/* An argument consisting of exactly one dash is a request to
1222 	   read stdin.  This will be handled in the second loop.  */
1223 	if (argv[i][1] == '\0')
1224 	  continue;
1225 
1226 	/* An argument consisting of just two dashes causes option
1227 	   parsing to cease.  */
1228 	if (argv[i][1] == '-' && argv[i][2] == '\0')
1229 	  break;
1230 
1231 	if (argv[i][1] == 'I')
1232 	  {
1233 	    if (argv[i][2] != '\0')
1234 	      add_include_path (argv[i] + 2);
1235 	    else if (++i < argc)
1236 	      add_include_path (argv[i]);
1237 	    else
1238 	      fatal ("directory name missing after -I option");
1239 	    continue;
1240 	  }
1241 
1242 	/* The program may have provided a callback so it can
1243 	   accept its own options.  */
1244 	if (parse_opt && parse_opt (argv[i]))
1245 	  continue;
1246 
1247 	fatal ("invalid option `%s'", argv[i]);
1248       }
1249 
1250   /* Now loop over all input files.  */
1251   num_files = 0;
1252   no_more_options = false;
1253   already_read_stdin = false;
1254   for (i = 1; i < argc; i++)
1255     {
1256       if (argv[i][0] == '-')
1257 	{
1258 	  if (argv[i][1] == '\0')
1259 	    {
1260 	      /* Read stdin.  */
1261 	      if (already_read_stdin)
1262 		fatal ("cannot read standard input twice");
1263 
1264 	      m_read_md_file = stdin;
1265 	      m_read_md_filename = "<stdin>";
1266 	      handle_toplevel_file ();
1267 	      already_read_stdin = true;
1268 	      continue;
1269 	    }
1270 	  else if (argv[i][1] == '-' && argv[i][2] == '\0')
1271 	    {
1272 	      /* No further arguments are to be treated as options.  */
1273 	      no_more_options = true;
1274 	      continue;
1275 	    }
1276 	  else if (!no_more_options)
1277 	    continue;
1278 	}
1279 
1280       /* If we get here we are looking at a non-option argument, i.e.
1281 	 a file to be processed.  */
1282       m_read_md_filename = argv[i];
1283       m_read_md_file = fopen (m_read_md_filename, "r");
1284       if (m_read_md_file == 0)
1285 	{
1286 	  perror (m_read_md_filename);
1287 	  return false;
1288 	}
1289       handle_toplevel_file ();
1290       num_files++;
1291     }
1292 
1293   /* If we get to this point without having seen any files to process,
1294      read the standard input now.  */
1295   if (num_files == 0 && !already_read_stdin)
1296     {
1297       m_read_md_file = stdin;
1298       m_read_md_filename = "<stdin>";
1299       handle_toplevel_file ();
1300     }
1301 
1302   return !have_error;
1303 }
1304 
1305 #endif /* #ifdef GENERATOR_FILE */
1306 
1307 /* Read FILENAME.  */
1308 
1309 bool
read_file(const char * filename)1310 md_reader::read_file (const char *filename)
1311 {
1312   m_read_md_filename = filename;
1313   m_read_md_file = fopen (m_read_md_filename, "r");
1314   if (m_read_md_file == 0)
1315     {
1316       perror (m_read_md_filename);
1317       return false;
1318     }
1319   handle_toplevel_file ();
1320   return !have_error;
1321 }
1322 
1323 /* Read FILENAME, filtering to just the given lines.  */
1324 
1325 bool
read_file_fragment(const char * filename,int first_line,int last_line)1326 md_reader::read_file_fragment (const char *filename,
1327 			       int first_line,
1328 			       int last_line)
1329 {
1330   m_read_md_filename = filename;
1331   m_read_md_file = fopen (m_read_md_filename, "r");
1332   if (m_read_md_file == 0)
1333     {
1334       perror (m_read_md_filename);
1335       return false;
1336     }
1337   m_first_line = first_line;
1338   m_last_line = last_line;
1339   handle_toplevel_file ();
1340   return !have_error;
1341 }
1342 
1343 /* class noop_reader : public md_reader */
1344 
1345 /* A dummy implementation which skips unknown directives.  */
1346 void
handle_unknown_directive(file_location loc,const char *)1347 noop_reader::handle_unknown_directive (file_location loc, const char *)
1348 {
1349   read_skip_construct (1, loc);
1350 }
1351