Line data Source code
1 : /* MD reader for GCC.
2 : Copyright (C) 1987-2026 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 8930 : leading_string_hash (const void *def)
59 : {
60 8930 : 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 0 : leading_string_eq_p (const void *def1, const void *def2)
68 : {
69 0 : return strcmp (*(const char *const *) def1,
70 0 : *(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 118 : leading_ptr_hash (const void *def)
77 : {
78 118 : 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 1 : leading_ptr_eq_p (const void *def1, const void *def2)
85 : {
86 1 : 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 118 : md_reader::set_md_ptr_loc (const void *ptr, file_location file_loc)
93 : {
94 118 : struct ptr_loc *loc;
95 :
96 118 : loc = (struct ptr_loc *) obstack_alloc (&m_ptr_loc_obstack,
97 : sizeof (struct ptr_loc));
98 118 : loc->ptr = ptr;
99 118 : loc->loc = file_loc;
100 118 : *htab_find_slot (m_ptr_locs, loc, INSERT) = loc;
101 118 : }
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 0 : md_reader::get_md_ptr_loc (const void *ptr)
108 : {
109 0 : 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 0 : md_reader::copy_md_ptr_loc (const void *new_ptr, const void *old_ptr)
116 : {
117 0 : const struct ptr_loc *loc = get_md_ptr_loc (old_ptr);
118 0 : if (loc != 0)
119 0 : set_md_ptr_loc (new_ptr, loc->loc);
120 0 : }
121 :
122 : /* If PTR is associated with a known file position, print a #line
123 : directive for it to OUTF. */
124 :
125 : void
126 0 : md_reader::fprint_md_ptr_loc (FILE *outf, const void *ptr)
127 : {
128 0 : const struct ptr_loc *loc = get_md_ptr_loc (ptr);
129 0 : if (loc != 0)
130 0 : fprintf (outf, "#line %d \"%s\"\n", loc->loc.lineno, loc->loc.filename);
131 0 : }
132 :
133 : /* Special fprint_md_ptr_loc for writing to STDOUT. */
134 : void
135 0 : md_reader::print_md_ptr_loc (const void *ptr, FILE *file)
136 : {
137 0 : fprint_md_ptr_loc (file, ptr);
138 0 : }
139 :
140 : /* Return a condition that satisfies both COND1 and COND2. Either string
141 : may be null or empty. */
142 :
143 : const char *
144 0 : md_reader::join_c_conditions (const char *cond1, const char *cond2)
145 : {
146 0 : char *result;
147 0 : const void **entry;
148 :
149 0 : if (cond1 == 0 || cond1[0] == 0)
150 : return cond2;
151 :
152 0 : if (cond2 == 0 || cond2[0] == 0)
153 : return cond1;
154 :
155 0 : if (strcmp (cond1, cond2) == 0)
156 : return cond1;
157 :
158 0 : result = concat ("(", cond1, ") && (", cond2, ")", NULL);
159 0 : obstack_ptr_grow (&m_joined_conditions_obstack, result);
160 0 : obstack_ptr_grow (&m_joined_conditions_obstack, cond1);
161 0 : obstack_ptr_grow (&m_joined_conditions_obstack, cond2);
162 0 : entry = XOBFINISH (&m_joined_conditions_obstack, const void **);
163 0 : *htab_find_slot (m_joined_conditions, entry, INSERT) = entry;
164 0 : 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 0 : md_reader::fprint_c_condition (FILE *outf, const char *cond)
174 : {
175 0 : const char **halves = (const char **) htab_find (m_joined_conditions, &cond);
176 0 : if (halves != 0)
177 : {
178 0 : fprintf (outf, "(");
179 0 : fprint_c_condition (outf, halves[1]);
180 0 : fprintf (outf, " && ");
181 0 : fprint_c_condition (outf, halves[2]);
182 0 : fprintf (outf, ")");
183 : }
184 : else
185 : {
186 0 : fputc ('\n', outf);
187 0 : fprint_md_ptr_loc (outf, cond);
188 0 : fprintf (outf, "(%s)", cond);
189 : }
190 0 : }
191 :
192 : /* Special fprint_c_condition for writing to STDOUT. */
193 :
194 : void
195 0 : md_reader::print_c_condition (FILE *outf, const char *cond)
196 : {
197 0 : fprint_c_condition (outf, cond);
198 0 : }
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 0 : message_at_1 (file_location loc, const char *msg, va_list ap)
205 : {
206 0 : fprintf (stderr, "%s:%d:%d: ", loc.filename, loc.lineno, loc.colno);
207 0 : vfprintf (stderr, msg, ap);
208 0 : fputc ('\n', stderr);
209 0 : }
210 :
211 : /* A printf-like function for reporting a message against location LOC. */
212 :
213 : void
214 0 : message_at (file_location loc, const char *msg, ...)
215 : {
216 0 : va_list ap;
217 :
218 0 : va_start (ap, msg);
219 0 : message_at_1 (loc, msg, ap);
220 0 : va_end (ap);
221 0 : }
222 :
223 : /* Like message_at, but treat the condition as an error. */
224 :
225 : void
226 0 : error_at (file_location loc, const char *msg, ...)
227 : {
228 0 : va_list ap;
229 :
230 0 : va_start (ap, msg);
231 0 : message_at_1 (loc, msg, ap);
232 0 : va_end (ap);
233 0 : have_error = 1;
234 0 : }
235 :
236 : /* Like message_at, but treat the condition as a fatal error. */
237 :
238 : void
239 0 : fatal_at (file_location loc, const char *msg, ...)
240 : {
241 0 : va_list ap;
242 :
243 0 : va_start (ap, msg);
244 0 : message_at_1 (loc, msg, ap);
245 0 : va_end (ap);
246 0 : 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 1 : fatal_with_file_and_line (const char *msg, ...)
254 : {
255 1 : char context[64];
256 1 : size_t i;
257 1 : int c;
258 1 : va_list ap;
259 :
260 1 : va_start (ap, msg);
261 :
262 1 : fprintf (stderr, "%s:%d:%d: error: ", md_reader_ptr->get_filename (),
263 : md_reader_ptr->get_lineno (),
264 : md_reader_ptr->get_colno ());
265 1 : vfprintf (stderr, msg, ap);
266 1 : putc ('\n', stderr);
267 :
268 : /* Gather some following context. */
269 43 : for (i = 0; i < sizeof (context)-1; ++i)
270 : {
271 42 : c = read_char ();
272 42 : if (c == EOF)
273 : break;
274 42 : if (c == '\r' || c == '\n')
275 : {
276 1 : unread_char (c);
277 1 : break;
278 : }
279 41 : context[i] = c;
280 : }
281 1 : context[i] = '\0';
282 :
283 1 : 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 1 : va_end (ap);
289 1 : exit (1);
290 : }
291 :
292 : /* Report that we found character ACTUAL when we expected to find
293 : character EXPECTED. */
294 :
295 : void
296 0 : fatal_expected_char (int expected, int actual)
297 : {
298 0 : if (actual == EOF)
299 0 : fatal_with_file_and_line ("expected character `%c', found EOF",
300 : expected);
301 : else
302 0 : 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 21427 : read_skip_spaces (void)
311 : {
312 58399 : int c;
313 :
314 58399 : while (1)
315 : {
316 58399 : c = read_char ();
317 58399 : switch (c)
318 : {
319 : case ' ': case '\t': case '\f': case '\r': case '\n':
320 : break;
321 :
322 5390 : case ';':
323 5390 : do
324 5390 : c = read_char ();
325 5390 : while (c != '\n' && c != EOF);
326 : break;
327 :
328 4 : case '/':
329 4 : {
330 4 : int prevc;
331 4 : c = read_char ();
332 4 : if (c != '*')
333 : {
334 0 : unread_char (c);
335 0 : fatal_with_file_and_line ("stray '/' in file");
336 : }
337 :
338 : prevc = 0;
339 580 : while ((c = read_char ()) && c != EOF)
340 : {
341 580 : if (prevc == '*' && c == '/')
342 : break;
343 : prevc = c;
344 : }
345 : }
346 : break;
347 :
348 21427 : default:
349 21427 : 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 582 : md_reader::require_char (char expected)
359 : {
360 582 : int ch = read_char ();
361 582 : if (ch != expected)
362 0 : fatal_expected_char (expected, ch);
363 582 : }
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 5521 : md_reader::require_char_ws (char expected)
370 : {
371 5521 : int ch = read_skip_spaces ();
372 5521 : if (ch != expected)
373 0 : fatal_expected_char (expected, ch);
374 5521 : }
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 300 : md_reader::require_word_ws (const char *expected)
381 : {
382 300 : struct md_name name;
383 300 : read_name (&name);
384 300 : if (strcmp (name.string, expected))
385 0 : fatal_with_file_and_line ("missing '%s'", expected);
386 300 : }
387 :
388 : /* Read the next character from the file. */
389 :
390 : int
391 113320 : md_reader::read_char (void)
392 : {
393 113320 : int ch;
394 :
395 113320 : ch = getc (m_read_md_file);
396 113320 : if (ch == '\n')
397 : {
398 3295 : m_read_md_lineno++;
399 3295 : m_last_line_colno = m_read_md_colno;
400 3295 : m_read_md_colno = 0;
401 : }
402 : else
403 110025 : 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 113320 : if (m_first_line && m_last_line)
408 : {
409 72524 : if (m_read_md_lineno < m_first_line)
410 : return ' ';
411 58983 : if (m_read_md_lineno > m_last_line)
412 38 : 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 12371 : md_reader::unread_char (int ch)
422 : {
423 12371 : if (ch == '\n')
424 : {
425 453 : m_read_md_lineno--;
426 453 : m_read_md_colno = m_last_line_colno;
427 : }
428 : else
429 11918 : m_read_md_colno--;
430 12371 : ungetc (ch, m_read_md_file);
431 12371 : }
432 :
433 : /* Peek at the next character from the file without consuming it. */
434 :
435 : int
436 2320 : md_reader::peek_char (void)
437 : {
438 2320 : int ch = read_char ();
439 2320 : unread_char (ch);
440 2320 : 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 7310 : md_reader::read_name_1 (struct md_name *name, file_location *out_loc)
448 : {
449 7310 : int c;
450 7310 : size_t i;
451 7310 : int angle_bracket_depth;
452 :
453 7310 : c = read_skip_spaces ();
454 :
455 7310 : *out_loc = get_current_location ();
456 :
457 7310 : i = 0;
458 7310 : angle_bracket_depth = 0;
459 65976 : while (1)
460 : {
461 36643 : if (c == '<')
462 291 : angle_bracket_depth++;
463 :
464 36643 : if ((c == '>') && (angle_bracket_depth > 0))
465 291 : angle_bracket_depth--;
466 :
467 36643 : if (c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r'
468 : || c == EOF)
469 : break;
470 31897 : if (angle_bracket_depth == 0)
471 : {
472 31289 : if (c == ':' || c == ')' || c == ']'
473 : || c == '"' || c == '/' || c == '(' || c == '[')
474 : {
475 2564 : unread_char (c);
476 2564 : break;
477 : }
478 : }
479 :
480 29333 : if (i == sizeof (name->buffer) - 1)
481 0 : fatal_with_file_and_line ("name too long");
482 29333 : name->buffer[i++] = c;
483 :
484 29333 : c = read_char ();
485 : }
486 :
487 7310 : if (i == 0)
488 : return false;
489 :
490 7310 : name->buffer[i] = 0;
491 7310 : name->string = name->buffer;
492 :
493 7310 : if (m_md_constants)
494 : {
495 : /* Do constant expansion. */
496 7310 : struct md_constant *def;
497 :
498 7310 : do
499 : {
500 7310 : struct md_constant tmp_def;
501 :
502 7310 : tmp_def.name = name->string;
503 7310 : def = (struct md_constant *) htab_find (m_md_constants, &tmp_def);
504 7310 : if (def)
505 0 : name->string = def->value;
506 : }
507 7310 : 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 7310 : md_reader::read_name (struct md_name *name)
518 : {
519 7310 : file_location loc;
520 7310 : if (!read_name_1 (name, &loc))
521 0 : fatal_with_file_and_line ("missing name or number");
522 7310 : return loc;
523 : }
524 :
525 : file_location
526 0 : md_reader::read_name_or_nil (struct md_name *name)
527 : {
528 0 : file_location loc;
529 0 : if (!read_name_1 (name, &loc))
530 : {
531 0 : file_location loc = get_current_location ();
532 0 : read_skip_construct (0, loc);
533 : /* Skip the ')'. */
534 0 : read_char ();
535 0 : name->buffer[0] = 0;
536 0 : name->string = name->buffer;
537 : }
538 0 : 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 0 : md_reader::read_escape ()
546 : {
547 0 : int c = read_char ();
548 :
549 0 : 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 0 : case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
571 0 : case '0': case '1': case '2': case '3': case '4': case '5': case '6':
572 0 : case '7': case 'x':
573 0 : obstack_1grow (&m_string_obstack, '\\');
574 0 : break;
575 :
576 : /* \; makes stuff for a C string constant containing
577 : newline and tab. */
578 0 : case ';':
579 0 : obstack_grow (&m_string_obstack, "\\n\\t", 4);
580 0 : return;
581 :
582 : /* pass anything else through, but issue a warning. */
583 0 : default:
584 0 : fprintf (stderr, "%s:%d: warning: unrecognized escape \\%c\n",
585 : get_filename (), get_lineno (),
586 : c);
587 0 : obstack_1grow (&m_string_obstack, '\\');
588 0 : break;
589 : }
590 :
591 0 : 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 605 : md_reader::read_quoted_string ()
599 : {
600 11654 : int c;
601 :
602 11654 : while (1)
603 : {
604 11654 : c = read_char (); /* Read the string */
605 11654 : if (c == '\\')
606 : {
607 0 : read_escape ();
608 0 : continue;
609 : }
610 11654 : else if (c == '"' || c == EOF)
611 : break;
612 :
613 11049 : obstack_1grow (&m_string_obstack, c);
614 : }
615 :
616 605 : obstack_1grow (&m_string_obstack, 0);
617 605 : 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 0 : md_reader::read_braced_string ()
626 : {
627 0 : int c;
628 0 : int brace_depth = 1; /* caller-processed */
629 0 : unsigned long starting_read_md_lineno = get_lineno ();
630 :
631 0 : obstack_1grow (&m_string_obstack, '{');
632 0 : while (brace_depth)
633 : {
634 0 : c = read_char (); /* Read the string */
635 :
636 0 : if (c == '{')
637 0 : brace_depth++;
638 0 : else if (c == '}')
639 0 : brace_depth--;
640 0 : else if (c == '\\')
641 : {
642 0 : read_escape ();
643 0 : continue;
644 : }
645 0 : else if (c == EOF)
646 0 : fatal_with_file_and_line
647 0 : ("missing closing } for opening brace on line %lu",
648 : starting_read_md_lineno);
649 :
650 0 : obstack_1grow (&m_string_obstack, c);
651 : }
652 :
653 0 : obstack_1grow (&m_string_obstack, 0);
654 0 : 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 126 : md_reader::read_string (int star_if_braced)
663 : {
664 126 : char *stringbuf;
665 126 : int saw_paren = 0;
666 126 : int c;
667 :
668 126 : c = read_skip_spaces ();
669 126 : if (c == '(')
670 : {
671 26 : saw_paren = 1;
672 26 : c = read_skip_spaces ();
673 : }
674 :
675 126 : file_location loc = get_current_location ();
676 126 : if (c == '"')
677 118 : stringbuf = read_quoted_string ();
678 8 : else if (c == '{')
679 : {
680 0 : if (star_if_braced)
681 0 : obstack_1grow (&m_string_obstack, '*');
682 0 : stringbuf = read_braced_string ();
683 : }
684 8 : else if (saw_paren && c == 'n')
685 : {
686 : /* Handle (nil) by returning NULL. */
687 8 : require_char ('i');
688 8 : require_char ('l');
689 8 : require_char_ws (')');
690 8 : return NULL;
691 : }
692 : else
693 0 : fatal_with_file_and_line ("expected `\"' or `{', found `%c'", c);
694 :
695 118 : if (saw_paren)
696 18 : require_char_ws (')');
697 :
698 118 : set_md_ptr_loc (stringbuf, loc);
699 118 : 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 0 : md_reader::read_skip_construct (int depth, file_location loc)
707 : {
708 0 : struct md_name name;
709 0 : int c;
710 :
711 0 : do
712 : {
713 0 : c = read_skip_spaces ();
714 0 : if (c == EOF)
715 : {
716 0 : error_at (loc, "unterminated construct");
717 0 : exit (1);
718 : }
719 0 : switch (c)
720 : {
721 0 : case '(':
722 0 : depth++;
723 0 : break;
724 :
725 0 : case ')':
726 0 : depth--;
727 0 : break;
728 :
729 : case ':':
730 : case '[':
731 : case ']':
732 : case '/':
733 : break;
734 :
735 0 : case '\"':
736 0 : case '{':
737 0 : unread_char (c);
738 0 : read_string (false);
739 0 : break;
740 :
741 0 : default:
742 0 : unread_char (c);
743 0 : read_name (&name);
744 0 : break;
745 : }
746 : }
747 0 : while (depth > 0);
748 0 : unread_char (c);
749 0 : }
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 0 : n_comma_elts (const char *s)
756 : {
757 0 : int n;
758 :
759 0 : if (*s == '\0')
760 : return 0;
761 :
762 0 : for (n = 1; *s; s++)
763 0 : if (*s == ',')
764 0 : 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 0 : scan_comma_elt (const char **pstr)
777 : {
778 0 : const char *start;
779 0 : const char *p = *pstr;
780 :
781 0 : if (*p == ',')
782 0 : p++;
783 0 : while (ISSPACE (*p))
784 0 : p++;
785 :
786 0 : if (*p == '\0')
787 : return NULL;
788 :
789 : start = p;
790 :
791 0 : while (*p != ',' && *p != '\0')
792 0 : p++;
793 :
794 0 : *pstr = p;
795 0 : return start;
796 : }
797 :
798 : /* Convert STRING to uppercase. */
799 :
800 : void
801 0 : upcase_string (char *string)
802 : {
803 0 : int i;
804 :
805 0 : for (i = 0; string[i]; i++)
806 0 : string[i] = TOUPPER (string[i]);
807 0 : }
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 0 : add_constant (htab_t defs, char *name, char *value,
815 : struct enum_type *parent_enum)
816 : {
817 0 : struct md_constant *def, tmp_def;
818 0 : void **entry_ptr;
819 :
820 0 : tmp_def.name = name;
821 0 : entry_ptr = htab_find_slot (defs, &tmp_def, INSERT);
822 0 : if (*entry_ptr)
823 : {
824 0 : def = (struct md_constant *) *entry_ptr;
825 0 : if (strcmp (def->value, value) != 0)
826 0 : fatal_with_file_and_line ("redefinition of `%s', was `%s', now `%s'",
827 : def->name, def->value, value);
828 0 : else if (parent_enum || def->parent_enum)
829 0 : fatal_with_file_and_line ("redefinition of `%s'", def->name);
830 0 : free (name);
831 0 : free (value);
832 : }
833 : else
834 : {
835 0 : def = XNEW (struct md_constant);
836 0 : def->name = name;
837 0 : def->value = value;
838 0 : def->parent_enum = parent_enum;
839 0 : *entry_ptr = def;
840 : }
841 0 : return def;
842 : }
843 :
844 : /* Process a define_constants directive, starting with the optional space
845 : after the "define_constants". */
846 :
847 : void
848 0 : md_reader::handle_constants ()
849 : {
850 0 : int c;
851 0 : htab_t defs;
852 :
853 0 : require_char_ws ('[');
854 :
855 : /* Disable constant expansion during definition processing. */
856 0 : defs = m_md_constants;
857 0 : m_md_constants = 0;
858 0 : while ( (c = read_skip_spaces ()) != ']')
859 : {
860 0 : struct md_name name, value;
861 :
862 0 : if (c != '(')
863 0 : fatal_expected_char ('(', c);
864 :
865 0 : read_name (&name);
866 0 : read_name (&value);
867 0 : add_constant (defs, xstrdup (name.string), xstrdup (value.string), 0);
868 :
869 0 : require_char_ws (')');
870 : }
871 0 : m_md_constants = defs;
872 0 : }
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 0 : md_reader::traverse_md_constants (htab_trav callback, void *info)
880 : {
881 0 : htab_traverse (get_md_constants (), callback, info);
882 0 : }
883 :
884 : /* Return a malloc()ed decimal string that represents number NUMBER. */
885 :
886 : static char *
887 0 : md_decimal_string (int number)
888 : {
889 : /* A safe overestimate. +1 for sign, +1 for null terminator. */
890 0 : char buffer[sizeof (int) * CHAR_BIT + 1 + 1];
891 :
892 0 : sprintf (buffer, "%d", number);
893 0 : 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 0 : md_reader::handle_enum (file_location loc, bool md_p)
903 : {
904 0 : char *enum_name, *value_name;
905 0 : unsigned int cur_value;
906 0 : struct md_name name, value;
907 0 : struct enum_type *def;
908 0 : struct enum_value *ev;
909 0 : void **slot;
910 0 : int c;
911 :
912 0 : enum_name = read_string (false);
913 0 : slot = htab_find_slot (m_enum_types, &enum_name, INSERT);
914 0 : if (*slot)
915 : {
916 0 : def = (struct enum_type *) *slot;
917 0 : if (def->md_p != md_p)
918 0 : error_at (loc, "redefining `%s' as a different type of enum",
919 : enum_name);
920 : }
921 : else
922 : {
923 0 : def = XNEW (struct enum_type);
924 0 : def->name = enum_name;
925 0 : def->md_p = md_p;
926 0 : def->values = 0;
927 0 : def->tail_ptr = &def->values;
928 0 : def->num_values = 0;
929 0 : *slot = def;
930 : }
931 :
932 0 : cur_value = def->num_values;
933 0 : require_char_ws ('[');
934 :
935 0 : while ((c = read_skip_spaces ()) != ']')
936 : {
937 0 : if (c == EOF)
938 : {
939 0 : error_at (loc, "unterminated construct");
940 0 : exit (1);
941 : }
942 0 : if (c == '(')
943 : {
944 0 : read_name (&name);
945 0 : read_name (&value);
946 0 : require_char_ws (')');
947 0 : cur_value = atoi (value.string);
948 : }
949 : else
950 : {
951 0 : unread_char (c);
952 0 : read_name (&name);
953 : }
954 :
955 0 : ev = XNEW (struct enum_value);
956 0 : ev->next = 0;
957 0 : if (md_p)
958 : {
959 0 : value_name = concat (def->name, "_", name.string, NULL);
960 0 : upcase_string (value_name);
961 0 : ev->name = xstrdup (name.string);
962 : }
963 : else
964 : {
965 0 : value_name = xstrdup (name.string);
966 0 : ev->name = value_name;
967 : }
968 0 : ev->def = add_constant (get_md_constants (), value_name,
969 : md_decimal_string (cur_value), def);
970 :
971 0 : *def->tail_ptr = ev;
972 0 : def->tail_ptr = &ev->next;
973 0 : def->num_values++;
974 0 : cur_value++;
975 : }
976 0 : }
977 :
978 : /* Try to find the definition of the given enum. Return null on failure. */
979 :
980 : struct enum_type *
981 0 : md_reader::lookup_enum_type (const char *name)
982 : {
983 0 : 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 0 : md_reader::traverse_enum_types (htab_trav callback, void *info)
992 : {
993 0 : htab_traverse (m_enum_types, callback, info);
994 0 : }
995 :
996 :
997 : /* Constructor for md_reader. */
998 :
999 100 : md_reader::md_reader (bool compact)
1000 100 : : m_compact (compact),
1001 100 : m_toplevel_fname (NULL),
1002 100 : m_base_dir (NULL),
1003 100 : m_read_md_file (NULL),
1004 100 : m_read_md_filename (NULL),
1005 100 : m_read_md_lineno (0),
1006 100 : m_read_md_colno (0),
1007 100 : m_first_dir_md_include (NULL),
1008 100 : m_last_dir_md_include_ptr (&m_first_dir_md_include),
1009 100 : m_first_line (0),
1010 100 : m_last_line (0),
1011 100 : m_first_overload (NULL),
1012 100 : m_next_overload_ptr (&m_first_overload),
1013 100 : m_overloads_htab (NULL)
1014 : {
1015 : /* Set the global singleton pointer. */
1016 100 : md_reader_ptr = this;
1017 :
1018 100 : obstack_init (&m_string_obstack);
1019 :
1020 100 : m_ptr_locs = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1021 100 : obstack_init (&m_ptr_loc_obstack);
1022 :
1023 100 : m_joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
1024 100 : obstack_init (&m_joined_conditions_obstack);
1025 :
1026 100 : m_md_constants = htab_create (31, leading_string_hash,
1027 : leading_string_eq_p, (htab_del) 0);
1028 :
1029 100 : m_enum_types = htab_create (31, leading_string_hash,
1030 : leading_string_eq_p, (htab_del) 0);
1031 :
1032 : /* Unlock the stdio streams. */
1033 100 : unlock_std_streams ();
1034 100 : }
1035 :
1036 : /* md_reader's destructor. */
1037 :
1038 99 : md_reader::~md_reader ()
1039 : {
1040 99 : free (m_base_dir);
1041 :
1042 99 : htab_delete (m_enum_types);
1043 :
1044 99 : htab_delete (m_md_constants);
1045 :
1046 99 : obstack_free (&m_joined_conditions_obstack, NULL);
1047 99 : htab_delete (m_joined_conditions);
1048 :
1049 99 : obstack_free (&m_ptr_loc_obstack, NULL);
1050 99 : htab_delete (m_ptr_locs);
1051 :
1052 99 : obstack_free (&m_string_obstack, NULL);
1053 :
1054 : /* Clear the global singleton pointer. */
1055 99 : md_reader_ptr = NULL;
1056 99 : }
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 0 : md_reader::handle_include (file_location loc)
1065 : {
1066 0 : const char *filename;
1067 0 : const char *old_filename;
1068 0 : int old_lineno, old_colno;
1069 0 : char *pathname;
1070 0 : FILE *input_file, *old_file;
1071 :
1072 0 : filename = read_string (false);
1073 0 : input_file = NULL;
1074 :
1075 : /* If the specified file name is absolute, skip the include stack. */
1076 0 : if (!IS_ABSOLUTE_PATH (filename))
1077 : {
1078 0 : struct file_name_list *stackp;
1079 :
1080 : /* Search the directory path, trying to open the file. */
1081 0 : for (stackp = m_first_dir_md_include; stackp; stackp = stackp->next)
1082 : {
1083 0 : static const char sep[2] = { DIR_SEPARATOR, '\0' };
1084 :
1085 0 : pathname = concat (stackp->fname, sep, filename, NULL);
1086 0 : input_file = fopen (pathname, "r");
1087 0 : if (input_file != NULL)
1088 : break;
1089 0 : 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 0 : if (input_file == NULL)
1096 : {
1097 0 : if (m_base_dir)
1098 0 : pathname = concat (m_base_dir, filename, NULL);
1099 : else
1100 0 : pathname = xstrdup (filename);
1101 0 : input_file = fopen (pathname, "r");
1102 : }
1103 :
1104 0 : if (input_file == NULL)
1105 : {
1106 0 : free (pathname);
1107 0 : error_at (loc, "include file `%s' not found", filename);
1108 0 : 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 0 : old_file = m_read_md_file;
1115 0 : old_filename = m_read_md_filename;
1116 0 : old_lineno = m_read_md_lineno;
1117 0 : old_colno = m_read_md_colno;
1118 :
1119 0 : if (include_callback)
1120 0 : include_callback (pathname);
1121 :
1122 0 : m_read_md_file = input_file;
1123 0 : m_read_md_filename = pathname;
1124 :
1125 0 : handle_file ();
1126 :
1127 : /* Restore the old cursor. */
1128 0 : m_read_md_file = old_file;
1129 0 : m_read_md_filename = old_filename;
1130 0 : m_read_md_lineno = old_lineno;
1131 0 : 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 100 : md_reader::handle_file ()
1143 : {
1144 100 : struct md_name directive;
1145 100 : int c;
1146 :
1147 100 : m_read_md_lineno = 1;
1148 100 : m_read_md_colno = 0;
1149 199 : while ((c = read_skip_spaces ()) != EOF)
1150 : {
1151 100 : file_location loc = get_current_location ();
1152 100 : if (c != '(')
1153 0 : fatal_expected_char ('(', c);
1154 :
1155 100 : read_name (&directive);
1156 100 : if (strcmp (directive.string, "define_constants") == 0)
1157 0 : handle_constants ();
1158 100 : else if (strcmp (directive.string, "define_enum") == 0)
1159 0 : handle_enum (loc, true);
1160 100 : else if (strcmp (directive.string, "define_c_enum") == 0)
1161 0 : handle_enum (loc, false);
1162 100 : else if (strcmp (directive.string, "include") == 0)
1163 0 : handle_include (loc);
1164 : else
1165 100 : handle_unknown_directive (loc, directive.string);
1166 :
1167 99 : require_char_ws (')');
1168 : }
1169 99 : fclose (m_read_md_file);
1170 99 : }
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 100 : md_reader::handle_toplevel_file ()
1177 : {
1178 100 : const char *base;
1179 :
1180 100 : m_toplevel_fname = m_read_md_filename;
1181 100 : base = lbasename (m_toplevel_fname);
1182 100 : if (base == m_toplevel_fname)
1183 0 : m_base_dir = NULL;
1184 : else
1185 100 : m_base_dir = xstrndup (m_toplevel_fname, base - m_toplevel_fname);
1186 :
1187 100 : handle_file ();
1188 99 : }
1189 :
1190 : file_location
1191 9685 : md_reader::get_current_location () const
1192 : {
1193 9685 : 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 0 : md_reader::add_include_path (const char *arg)
1200 : {
1201 0 : struct file_name_list *dirtmp;
1202 :
1203 0 : dirtmp = XNEW (struct file_name_list);
1204 0 : dirtmp->next = 0;
1205 0 : dirtmp->fname = arg;
1206 0 : *m_last_dir_md_include_ptr = dirtmp;
1207 0 : m_last_dir_md_include_ptr = &dirtmp->next;
1208 0 : }
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 76 : md_reader::read_file (const char *filename)
1324 : {
1325 76 : m_read_md_filename = filename;
1326 76 : m_read_md_file = fopen (m_read_md_filename, "r");
1327 76 : if (m_read_md_file == 0)
1328 : {
1329 0 : perror (m_read_md_filename);
1330 0 : return false;
1331 : }
1332 76 : handle_toplevel_file ();
1333 76 : return !have_error;
1334 : }
1335 :
1336 : /* Read FILENAME, filtering to just the given lines. */
1337 :
1338 : bool
1339 24 : md_reader::read_file_fragment (const char *filename,
1340 : int first_line,
1341 : int last_line)
1342 : {
1343 24 : m_read_md_filename = filename;
1344 24 : m_read_md_file = fopen (m_read_md_filename, "r");
1345 24 : if (m_read_md_file == 0)
1346 : {
1347 0 : perror (m_read_md_filename);
1348 0 : return false;
1349 : }
1350 24 : m_first_line = first_line;
1351 24 : m_last_line = last_line;
1352 24 : handle_toplevel_file ();
1353 23 : return !have_error;
1354 : }
1355 :
1356 : /* class noop_reader : public md_reader */
1357 :
1358 : /* A dummy implementation which skips unknown directives. */
1359 : void
1360 0 : noop_reader::handle_unknown_directive (file_location loc, const char *)
1361 : {
1362 0 : read_skip_construct (1, loc);
1363 0 : }
|