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