Mercurial > hg > CbC > CbC_gcc
annotate gcc/gengtype-parse.c @ 59:5b5b9ea5b220
fix
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 15 Feb 2010 17:22:24 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
rev | line source |
---|---|
0 | 1 /* Process source files and output type information. |
2 Copyright (C) 2006, 2007 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 #include "bconfig.h" | |
21 #include "system.h" | |
22 #include "gengtype.h" | |
23 | |
24 /* This is a simple recursive-descent parser which understands a subset of | |
25 the C type grammar. | |
26 | |
27 Rule functions are suffixed _seq if they scan a sequence of items; | |
28 _opt if they may consume zero tokens; _seqopt if both are true. The | |
29 "consume_" prefix indicates that a sequence of tokens is parsed for | |
30 syntactic correctness and then thrown away. */ | |
31 | |
32 /* Simple one-token lookahead mechanism. */ | |
33 | |
34 struct token | |
35 { | |
36 const char *value; | |
37 int code; | |
38 bool valid; | |
39 }; | |
40 static struct token T; | |
41 | |
42 /* Retrieve the code of the current token; if there is no current token, | |
43 get the next one from the lexer. */ | |
44 static inline int | |
45 token (void) | |
46 { | |
47 if (!T.valid) | |
48 { | |
49 T.code = yylex (&T.value); | |
50 T.valid = true; | |
51 } | |
52 return T.code; | |
53 } | |
54 | |
55 /* Retrieve the value of the current token (if any) and mark it consumed. | |
56 The next call to token() will get another token from the lexer. */ | |
57 static inline const char * | |
58 advance (void) | |
59 { | |
60 T.valid = false; | |
61 return T.value; | |
62 } | |
63 | |
64 /* Diagnostics. */ | |
65 | |
66 /* This array is indexed by the token code minus CHAR_TOKEN_OFFSET. */ | |
67 static const char *const token_names[] = { | |
68 "GTY", | |
69 "typedef", | |
70 "extern", | |
71 "static", | |
72 "union", | |
73 "struct", | |
74 "enum", | |
75 "VEC", | |
76 "DEF_VEC_[OP]", | |
77 "DEF_VEC_I", | |
78 "DEF_VEC_ALLOC_[IOP]", | |
79 "...", | |
80 "ptr_alias", | |
81 "nested_ptr", | |
82 "a param<N>_is option", | |
83 "a number", | |
84 "a scalar type", | |
85 "an identifier", | |
86 "a string constant", | |
87 "a character constant", | |
88 "an array declarator", | |
89 }; | |
90 | |
91 /* This array is indexed by token code minus FIRST_TOKEN_WITH_VALUE. */ | |
92 static const char *const token_value_format[] = { | |
93 "%s", | |
94 "'%s'", | |
95 "'%s'", | |
96 "'%s'", | |
97 "'\"%s\"'", | |
98 "\"'%s'\"", | |
99 "'[%s]'", | |
100 }; | |
101 | |
102 /* Produce a printable representation for a token defined by CODE and | |
103 VALUE. This sometimes returns pointers into malloc memory and | |
104 sometimes not, therefore it is unsafe to free the pointer it | |
105 returns, so that memory is leaked. This does not matter, as this | |
106 function is only used for diagnostics, and in a successful run of | |
107 the program there will be none. */ | |
108 static const char * | |
109 print_token (int code, const char *value) | |
110 { | |
111 if (code < CHAR_TOKEN_OFFSET) | |
112 return xasprintf ("'%c'", code); | |
113 else if (code < FIRST_TOKEN_WITH_VALUE) | |
114 return xasprintf ("'%s'", token_names[code - CHAR_TOKEN_OFFSET]); | |
115 else if (!value) | |
116 return token_names[code - CHAR_TOKEN_OFFSET]; /* don't quote these */ | |
117 else | |
118 return xasprintf (token_value_format[code - FIRST_TOKEN_WITH_VALUE], | |
119 value); | |
120 } | |
121 | |
122 /* Convenience wrapper around print_token which produces the printable | |
123 representation of the current token. */ | |
124 static inline const char * | |
125 print_cur_token (void) | |
126 { | |
127 return print_token (T.code, T.value); | |
128 } | |
129 | |
130 /* Report a parse error on the current line, with diagnostic MSG. | |
131 Behaves as standard printf with respect to additional arguments and | |
132 format escapes. */ | |
133 static void ATTRIBUTE_PRINTF_1 | |
134 parse_error (const char *msg, ...) | |
135 { | |
136 va_list ap; | |
137 | |
138 fprintf (stderr, "%s:%d: parse error: ", lexer_line.file, lexer_line.line); | |
139 | |
140 va_start (ap, msg); | |
141 vfprintf (stderr, msg, ap); | |
142 va_end (ap); | |
143 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
144 fputc ('\n', stderr); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
145 |
0 | 146 hit_error = true; |
147 } | |
148 | |
149 /* If the next token does not have code T, report a parse error; otherwise | |
150 return the token's value. */ | |
151 static const char * | |
152 require (int t) | |
153 { | |
154 int u = token (); | |
155 const char *v = advance (); | |
156 if (u != t) | |
157 { | |
158 parse_error ("expected %s, have %s", | |
159 print_token (t, 0), print_token (u, v)); | |
160 return 0; | |
161 } | |
162 return v; | |
163 } | |
164 | |
165 /* If the next token does not have one of the codes T1 or T2, report a | |
166 parse error; otherwise return the token's value. */ | |
167 static const char * | |
168 require2 (int t1, int t2) | |
169 { | |
170 int u = token (); | |
171 const char *v = advance (); | |
172 if (u != t1 && u != t2) | |
173 { | |
174 parse_error ("expected %s or %s, have %s", | |
175 print_token (t1, 0), print_token (t2, 0), | |
176 print_token (u, v)); | |
177 return 0; | |
178 } | |
179 return v; | |
180 } | |
181 | |
182 /* Near-terminals. */ | |
183 | |
184 /* C-style string constant concatenation: STRING+ | |
185 Bare STRING should appear nowhere else in this file. */ | |
186 static const char * | |
187 string_seq (void) | |
188 { | |
189 const char *s1, *s2; | |
190 size_t l1, l2; | |
191 char *buf; | |
192 | |
193 s1 = require (STRING); | |
194 if (s1 == 0) | |
195 return ""; | |
196 while (token () == STRING) | |
197 { | |
198 s2 = advance (); | |
199 | |
200 l1 = strlen (s1); | |
201 l2 = strlen (s2); | |
202 buf = XRESIZEVEC (char, CONST_CAST(char *, s1), l1 + l2 + 1); | |
203 memcpy (buf + l1, s2, l2 + 1); | |
204 XDELETE (CONST_CAST (char *, s2)); | |
205 s1 = buf; | |
206 } | |
207 return s1; | |
208 } | |
209 | |
210 /* typedef_name: either an ID, or VEC(x,y) which is translated to VEC_x_y. | |
211 Use only where VEC(x,y) is legitimate, i.e. in positions where a | |
212 typedef name may appear. */ | |
213 static const char * | |
214 typedef_name (void) | |
215 { | |
216 if (token () == VEC_TOKEN) | |
217 { | |
218 const char *c1, *c2, *r; | |
219 advance (); | |
220 require ('('); | |
221 c1 = require2 (ID, SCALAR); | |
222 require (','); | |
223 c2 = require (ID); | |
224 require (')'); | |
225 r = concat ("VEC_", c1, "_", c2, (char *)0); | |
226 free (CONST_CAST (char *, c1)); | |
227 free (CONST_CAST (char *, c2)); | |
228 return r; | |
229 } | |
230 else | |
231 return require (ID); | |
232 } | |
233 | |
234 /* Absorb a sequence of tokens delimited by balanced ()[]{}. */ | |
235 static void | |
236 consume_balanced (int opener, int closer) | |
237 { | |
238 require (opener); | |
239 for (;;) | |
240 switch (token ()) | |
241 { | |
242 default: advance (); break; | |
243 case '(': consume_balanced ('(',')'); break; | |
244 case '[': consume_balanced ('[',']'); break; | |
245 case '{': consume_balanced ('{','}'); break; | |
246 | |
247 case '}': | |
248 case ']': | |
249 case ')': | |
250 if (token () != closer) | |
251 parse_error ("unbalanced delimiters - expected '%c', have '%c'", | |
252 closer, token ()); | |
253 advance (); | |
254 return; | |
255 | |
256 case EOF_TOKEN: | |
257 parse_error ("unexpected end of file within %c%c-delimited construct", | |
258 opener, closer); | |
259 return; | |
260 } | |
261 } | |
262 | |
263 /* Absorb a sequence of tokens, possibly including ()[]{}-delimited | |
264 expressions, until we encounter a semicolon outside any such | |
265 delimiters; absorb that too. If IMMEDIATE is true, it is an error | |
266 if the semicolon is not the first token encountered. */ | |
267 static void | |
268 consume_until_semi (bool immediate) | |
269 { | |
270 if (immediate && token () != ';') | |
271 require (';'); | |
272 for (;;) | |
273 switch (token ()) | |
274 { | |
275 case ';': advance (); return; | |
276 default: advance (); break; | |
277 | |
278 case '(': consume_balanced ('(',')'); break; | |
279 case '[': consume_balanced ('[',']'); break; | |
280 case '{': consume_balanced ('{','}'); break; | |
281 | |
282 case '}': | |
283 case ']': | |
284 case ')': | |
285 parse_error ("unmatched '%c' while scanning for ';'", token ()); | |
286 return; | |
287 | |
288 case EOF_TOKEN: | |
289 parse_error ("unexpected end of file while scanning for ';'"); | |
290 return; | |
291 } | |
292 } | |
293 | |
294 /* Absorb a sequence of tokens, possibly including ()[]{}-delimited | |
295 expressions, until we encounter a comma or semicolon outside any | |
296 such delimiters; absorb that too. If IMMEDIATE is true, it is an | |
297 error if the comma or semicolon is not the first token encountered. | |
298 Returns true if the loop ended with a comma. */ | |
299 static bool | |
300 consume_until_comma_or_semi (bool immediate) | |
301 { | |
302 if (immediate && token () != ',' && token () != ';') | |
303 require2 (',', ';'); | |
304 for (;;) | |
305 switch (token ()) | |
306 { | |
307 case ',': advance (); return true; | |
308 case ';': advance (); return false; | |
309 default: advance (); break; | |
310 | |
311 case '(': consume_balanced ('(',')'); break; | |
312 case '[': consume_balanced ('[',']'); break; | |
313 case '{': consume_balanced ('{','}'); break; | |
314 | |
315 case '}': | |
316 case ']': | |
317 case ')': | |
318 parse_error ("unmatched '%s' while scanning for ',' or ';'", | |
319 print_cur_token ()); | |
320 return false; | |
321 | |
322 case EOF_TOKEN: | |
323 parse_error ("unexpected end of file while scanning for ',' or ';'"); | |
324 return false; | |
325 } | |
326 } | |
327 | |
328 | |
329 /* GTY(()) option handling. */ | |
330 static type_p type (options_p *optsp, bool nested); | |
331 | |
332 /* Optional parenthesized string: ('(' string_seq ')')? */ | |
333 static options_p | |
334 str_optvalue_opt (options_p prev) | |
335 { | |
336 const char *name = advance (); | |
337 const char *value = ""; | |
338 if (token () == '(') | |
339 { | |
340 advance (); | |
341 value = string_seq (); | |
342 require (')'); | |
343 } | |
344 return create_option (prev, name, value); | |
345 } | |
346 | |
347 /* absdecl: type '*'* | |
348 -- a vague approximation to what the C standard calls an abstract | |
349 declarator. The only kinds that are actually used are those that | |
350 are just a bare type and those that have trailing pointer-stars. | |
351 Further kinds should be implemented if and when they become | |
352 necessary. Used only within GTY(()) option values, therefore | |
353 further GTY(()) tags within the type are invalid. Note that the | |
354 return value has already been run through adjust_field_type. */ | |
355 static type_p | |
356 absdecl (void) | |
357 { | |
358 type_p ty; | |
359 options_p opts; | |
360 | |
361 ty = type (&opts, true); | |
362 while (token () == '*') | |
363 { | |
364 ty = create_pointer (ty); | |
365 advance (); | |
366 } | |
367 | |
368 if (opts) | |
369 parse_error ("nested GTY(()) options are invalid"); | |
370 | |
371 return adjust_field_type (ty, 0); | |
372 } | |
373 | |
374 /* Type-option: '(' absdecl ')' */ | |
375 static options_p | |
376 type_optvalue (options_p prev, const char *name) | |
377 { | |
378 type_p ty; | |
379 require ('('); | |
380 ty = absdecl (); | |
381 require (')'); | |
382 return create_option (prev, name, ty); | |
383 } | |
384 | |
385 /* Nested pointer data: '(' type '*'* ',' string_seq ',' string_seq ')' */ | |
386 static options_p | |
387 nestedptr_optvalue (options_p prev) | |
388 { | |
389 type_p ty; | |
390 const char *from, *to; | |
391 | |
392 require ('('); | |
393 ty = absdecl (); | |
394 require (','); | |
395 to = string_seq (); | |
396 require (','); | |
397 from = string_seq (); | |
398 require (')'); | |
399 | |
400 return create_nested_ptr_option (prev, ty, to, from); | |
401 } | |
402 | |
403 /* One GTY(()) option: | |
404 ID str_optvalue_opt | |
405 | PTR_ALIAS type_optvalue | |
406 | PARAM_IS type_optvalue | |
407 | NESTED_PTR nestedptr_optvalue | |
408 */ | |
409 static options_p | |
410 option (options_p prev) | |
411 { | |
412 switch (token ()) | |
413 { | |
414 case ID: | |
415 return str_optvalue_opt (prev); | |
416 | |
417 case PTR_ALIAS: | |
418 advance (); | |
419 return type_optvalue (prev, "ptr_alias"); | |
420 | |
421 case PARAM_IS: | |
422 return type_optvalue (prev, advance ()); | |
423 | |
424 case NESTED_PTR: | |
425 advance (); | |
426 return nestedptr_optvalue (prev); | |
427 | |
428 default: | |
429 parse_error ("expected an option keyword, have %s", | |
430 print_cur_token ()); | |
431 advance (); | |
432 return create_option (prev, "", ""); | |
433 } | |
434 } | |
435 | |
436 /* One comma-separated list of options. */ | |
437 static options_p | |
438 option_seq (void) | |
439 { | |
440 options_p o; | |
441 | |
442 o = option (0); | |
443 while (token () == ',') | |
444 { | |
445 advance (); | |
446 o = option (o); | |
447 } | |
448 return o; | |
449 } | |
450 | |
451 /* GTY marker: 'GTY' '(' '(' option_seq? ')' ')' */ | |
452 static options_p | |
453 gtymarker (void) | |
454 { | |
455 options_p result = 0; | |
456 require (GTY_TOKEN); | |
457 require ('('); | |
458 require ('('); | |
459 if (token () != ')') | |
460 result = option_seq (); | |
461 require (')'); | |
462 require (')'); | |
463 return result; | |
464 } | |
465 | |
466 /* Optional GTY marker. */ | |
467 static options_p | |
468 gtymarker_opt (void) | |
469 { | |
470 if (token () != GTY_TOKEN) | |
471 return 0; | |
472 return gtymarker (); | |
473 } | |
474 | |
475 /* Declarators. The logic here is largely lifted from c-parser.c. | |
476 Note that we do not have to process abstract declarators, which can | |
477 appear only in parameter type lists or casts (but see absdecl, | |
478 above). Also, type qualifiers are thrown out in gengtype-lex.l so | |
479 we don't have to do it. */ | |
480 | |
481 /* array_and_function_declarators_opt: | |
482 \epsilon | |
483 array_and_function_declarators_opt ARRAY | |
484 array_and_function_declarators_opt '(' ... ')' | |
485 | |
486 where '...' indicates stuff we ignore except insofar as grouping | |
487 symbols ()[]{} must balance. | |
488 | |
489 Subroutine of direct_declarator - do not use elsewhere. */ | |
490 | |
491 static type_p | |
492 array_and_function_declarators_opt (type_p ty) | |
493 { | |
494 if (token () == ARRAY) | |
495 { | |
496 const char *array = advance (); | |
497 return create_array (array_and_function_declarators_opt (ty), array); | |
498 } | |
499 else if (token () == '(') | |
500 { | |
501 /* We don't need exact types for functions. */ | |
502 consume_balanced ('(', ')'); | |
503 array_and_function_declarators_opt (ty); | |
504 return create_scalar_type ("function type"); | |
505 } | |
506 else | |
507 return ty; | |
508 } | |
509 | |
510 static type_p inner_declarator (type_p, const char **, options_p *); | |
511 | |
512 /* direct_declarator: | |
513 '(' inner_declarator ')' | |
514 gtymarker_opt ID array_and_function_declarators_opt | |
515 | |
516 Subroutine of declarator, mutually recursive with inner_declarator; | |
517 do not use elsewhere. */ | |
518 static type_p | |
519 direct_declarator (type_p ty, const char **namep, options_p *optsp) | |
520 { | |
521 /* The first token in a direct-declarator must be an ID, a | |
522 GTY marker, or an open parenthesis. */ | |
523 switch (token ()) | |
524 { | |
525 case GTY_TOKEN: | |
526 *optsp = gtymarker (); | |
527 /* fall through */ | |
528 case ID: | |
529 *namep = require (ID); | |
530 break; | |
531 | |
532 case '(': | |
533 advance (); | |
534 ty = inner_declarator (ty, namep, optsp); | |
535 require (')'); | |
536 break; | |
537 | |
538 default: | |
539 parse_error ("expected '(', 'GTY', or an identifier, have %s", | |
540 print_cur_token ()); | |
541 /* Do _not_ advance if what we have is a close squiggle brace, as | |
542 we will get much better error recovery that way. */ | |
543 if (token () != '}') | |
544 advance (); | |
545 return 0; | |
546 } | |
547 return array_and_function_declarators_opt (ty); | |
548 } | |
549 | |
550 /* The difference between inner_declarator and declarator is in the | |
551 handling of stars. Consider this declaration: | |
552 | |
553 char * (*pfc) (void) | |
554 | |
555 It declares a pointer to a function that takes no arguments and | |
556 returns a char*. To construct the correct type for this | |
557 declaration, the star outside the parentheses must be processed | |
558 _before_ the function type, the star inside the parentheses must | |
559 be processed _after_ the function type. To accomplish this, | |
560 declarator() creates pointers before recursing (it is actually | |
561 coded as a while loop), whereas inner_declarator() recurses before | |
562 creating pointers. */ | |
563 | |
564 /* inner_declarator: | |
565 '*' inner_declarator | |
566 direct_declarator | |
567 | |
568 Mutually recursive subroutine of direct_declarator; do not use | |
569 elsewhere. */ | |
570 | |
571 static type_p | |
572 inner_declarator (type_p ty, const char **namep, options_p *optsp) | |
573 { | |
574 if (token () == '*') | |
575 { | |
576 type_p inner; | |
577 advance (); | |
578 inner = inner_declarator (ty, namep, optsp); | |
579 if (inner == 0) | |
580 return 0; | |
581 else | |
582 return create_pointer (ty); | |
583 } | |
584 else | |
585 return direct_declarator (ty, namep, optsp); | |
586 } | |
587 | |
588 /* declarator: '*'+ direct_declarator | |
589 | |
590 This is the sole public interface to this part of the grammar. | |
591 Arguments are the type known so far, a pointer to where the name | |
592 may be stored, and a pointer to where GTY options may be stored. | |
593 Returns the final type. */ | |
594 | |
595 static type_p | |
596 declarator (type_p ty, const char **namep, options_p *optsp) | |
597 { | |
598 *namep = 0; | |
599 *optsp = 0; | |
600 while (token () == '*') | |
601 { | |
602 advance (); | |
603 ty = create_pointer (ty); | |
604 } | |
605 return direct_declarator (ty, namep, optsp); | |
606 } | |
607 | |
608 /* Types and declarations. */ | |
609 | |
610 /* Structure field(s) declaration: | |
611 ( | |
612 type bitfield ';' | |
613 | type declarator bitfield? ( ',' declarator bitfield? )+ ';' | |
614 )+ | |
615 | |
616 Knows that such declarations must end with a close brace (or, | |
617 erroneously, at EOF). | |
618 */ | |
619 static pair_p | |
620 struct_field_seq (void) | |
621 { | |
622 pair_p f = 0; | |
623 type_p ty, dty; | |
624 options_p opts, dopts; | |
625 const char *name; | |
626 bool another; | |
627 | |
628 do | |
629 { | |
630 ty = type (&opts, true); | |
631 /* Another piece of the IFCVT_EXTRA_FIELDS special case, see type(). */ | |
632 if (!ty && token () == '}') | |
633 break; | |
634 | |
635 if (!ty || token () == ':') | |
636 { | |
637 consume_until_semi (false); | |
638 continue; | |
639 } | |
640 | |
641 do | |
642 { | |
643 dty = declarator (ty, &name, &dopts); | |
644 /* There could be any number of weird things after the declarator, | |
645 notably bitfield declarations and __attribute__s. If this | |
646 function returns true, the last thing was a comma, so we have | |
647 more than one declarator paired with the current type. */ | |
648 another = consume_until_comma_or_semi (false); | |
649 | |
650 if (!dty) | |
651 continue; | |
652 | |
653 if (opts && dopts) | |
654 parse_error ("two GTY(()) options for field %s", name); | |
655 if (opts && !dopts) | |
656 dopts = opts; | |
657 | |
658 f = create_field_at (f, dty, name, dopts, &lexer_line); | |
659 } | |
660 while (another); | |
661 } | |
662 while (token () != '}' && token () != EOF_TOKEN); | |
663 return nreverse_pairs (f); | |
664 } | |
665 | |
666 /* This is called type(), but what it parses (sort of) is what C calls | |
667 declaration-specifiers and specifier-qualifier-list: | |
668 | |
669 SCALAR | |
670 | ID // typedef | |
671 | (STRUCT|UNION) ID? gtymarker? ( '{' gtymarker? struct_field_seq '}' )? | |
672 | ENUM ID ( '{' ... '}' )? | |
673 | |
674 Returns a partial type; under some conditions (notably | |
675 "struct foo GTY((...)) thing;") it may write an options | |
676 structure to *OPTSP. | |
677 */ | |
678 static type_p | |
679 type (options_p *optsp, bool nested) | |
680 { | |
681 const char *s; | |
682 *optsp = 0; | |
683 switch (token ()) | |
684 { | |
685 case SCALAR: | |
686 s = advance (); | |
687 return create_scalar_type (s); | |
688 | |
689 case ID: | |
690 case VEC_TOKEN: | |
691 s = typedef_name (); | |
692 return resolve_typedef (s, &lexer_line); | |
693 | |
694 case STRUCT: | |
695 case UNION: | |
696 { | |
697 options_p opts = 0; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
698 /* GTY annotations follow attribute syntax |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
699 GTY_BEFORE_ID is for union/struct declarations |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
700 GTY_AFTER_ID is for variable declarations. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
701 enum { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
702 NO_GTY, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
703 GTY_BEFORE_ID, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
704 GTY_AFTER_ID |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
705 } is_gty = NO_GTY; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
706 bool is_union = (token () == UNION); |
0 | 707 advance (); |
708 | |
709 /* Top-level structures that are not explicitly tagged GTY(()) | |
710 are treated as mere forward declarations. This is because | |
711 there are a lot of structures that we don't need to know | |
712 about, and some of those have weird macro stuff in them | |
713 that we can't handle. */ | |
714 if (nested || token () == GTY_TOKEN) | |
715 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
716 is_gty = GTY_BEFORE_ID; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
717 opts = gtymarker_opt (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
718 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
719 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
720 if (token () == ID) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
721 s = advance (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
722 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
723 s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
724 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
725 /* Unfortunately above GTY_TOKEN check does not capture the |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
726 typedef struct_type GTY case. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
727 if (token () == GTY_TOKEN) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
728 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
729 is_gty = GTY_AFTER_ID; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
730 opts = gtymarker_opt (); |
0 | 731 } |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
732 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
733 if (is_gty) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
734 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
735 if (token () == '{') |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
736 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
737 pair_p fields; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
738 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
739 if (is_gty == GTY_AFTER_ID) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
740 parse_error ("GTY must be specified before identifier"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
741 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
742 advance (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
743 fields = struct_field_seq (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
744 require ('}'); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
745 return new_structure (s, is_union, &lexer_line, fields, opts); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
746 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
747 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
748 else if (token () == '{') |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
749 consume_balanced ('{', '}'); |
0 | 750 if (opts) |
751 *optsp = opts; | |
752 return find_structure (s, is_union); | |
753 } | |
754 | |
755 case ENUM: | |
756 advance (); | |
757 if (token () == ID) | |
758 s = advance (); | |
759 else | |
760 s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); | |
761 | |
762 if (token () == '{') | |
763 consume_balanced ('{','}'); | |
764 return create_scalar_type (s); | |
765 | |
766 default: | |
767 parse_error ("expected a type specifier, have %s", print_cur_token ()); | |
768 advance (); | |
769 return create_scalar_type ("erroneous type"); | |
770 } | |
771 } | |
772 | |
773 /* Top level constructs. */ | |
774 | |
775 /* Dispatch declarations beginning with 'typedef'. */ | |
776 | |
777 static void | |
778 typedef_decl (void) | |
779 { | |
780 type_p ty, dty; | |
781 const char *name; | |
782 options_p opts; | |
783 bool another; | |
784 | |
785 gcc_assert (token () == TYPEDEF); | |
786 advance (); | |
787 | |
788 ty = type (&opts, false); | |
789 if (!ty) | |
790 return; | |
791 if (opts) | |
792 parse_error ("GTY((...)) cannot be applied to a typedef"); | |
793 do | |
794 { | |
795 dty = declarator (ty, &name, &opts); | |
796 if (opts) | |
797 parse_error ("GTY((...)) cannot be applied to a typedef"); | |
798 | |
799 /* Yet another place where we could have junk (notably attributes) | |
800 after the declarator. */ | |
801 another = consume_until_comma_or_semi (false); | |
802 if (dty) | |
803 do_typedef (name, dty, &lexer_line); | |
804 } | |
805 while (another); | |
806 } | |
807 | |
808 /* Structure definition: type() does all the work. */ | |
809 | |
810 static void | |
811 struct_or_union (void) | |
812 { | |
813 options_p dummy; | |
814 type (&dummy, false); | |
815 /* There may be junk after the type: notably, we cannot currently | |
816 distinguish 'struct foo *function(prototype);' from 'struct foo;' | |
817 ... we could call declarator(), but it's a waste of time at | |
818 present. Instead, just eat whatever token is currently lookahead | |
819 and go back to lexical skipping mode. */ | |
820 advance (); | |
821 } | |
822 | |
823 /* GC root declaration: | |
824 (extern|static) gtymarker? type ID array_declarators_opt (';'|'=') | |
825 If the gtymarker is not present, we ignore the rest of the declaration. */ | |
826 static void | |
827 extern_or_static (void) | |
828 { | |
829 options_p opts, opts2, dopts; | |
830 type_p ty, dty; | |
831 const char *name; | |
832 require2 (EXTERN, STATIC); | |
833 | |
834 if (token () != GTY_TOKEN) | |
835 { | |
836 advance (); | |
837 return; | |
838 } | |
839 | |
840 opts = gtymarker (); | |
841 ty = type (&opts2, true); /* if we get here, it's got a GTY(()) */ | |
842 dty = declarator (ty, &name, &dopts); | |
843 | |
844 if ((opts && dopts) || (opts && opts2) || (opts2 && dopts)) | |
845 parse_error ("GTY((...)) specified more than once for %s", name); | |
846 else if (opts2) | |
847 opts = opts2; | |
848 else if (dopts) | |
849 opts = dopts; | |
850 | |
851 if (dty) | |
852 { | |
853 note_variable (name, adjust_field_type (dty, opts), opts, &lexer_line); | |
854 require2 (';', '='); | |
855 } | |
856 } | |
857 | |
858 /* Definition of a generic VEC structure: | |
859 | |
860 'DEF_VEC_[IPO]' '(' id ')' ';' | |
861 | |
862 Scalar VECs require slightly different treatment than otherwise - | |
863 that's handled in note_def_vec, we just pass it along.*/ | |
864 static void | |
865 def_vec (void) | |
866 { | |
867 bool is_scalar = (token() == DEFVEC_I); | |
868 const char *type; | |
869 | |
870 require2 (DEFVEC_OP, DEFVEC_I); | |
871 require ('('); | |
872 type = require2 (ID, SCALAR); | |
873 require (')'); | |
874 require (';'); | |
875 | |
876 if (!type) | |
877 return; | |
878 | |
879 note_def_vec (type, is_scalar, &lexer_line); | |
880 note_def_vec_alloc (type, "none", &lexer_line); | |
881 } | |
882 | |
883 /* Definition of an allocation strategy for a VEC structure: | |
884 | |
885 'DEF_VEC_ALLOC_[IPO]' '(' id ',' id ')' ';' | |
886 | |
887 For purposes of gengtype, this just declares a wrapper structure. */ | |
888 static void | |
889 def_vec_alloc (void) | |
890 { | |
891 const char *type, *astrat; | |
892 | |
893 require (DEFVEC_ALLOC); | |
894 require ('('); | |
895 type = require2 (ID, SCALAR); | |
896 require (','); | |
897 astrat = require (ID); | |
898 require (')'); | |
899 require (';'); | |
900 | |
901 if (!type || !astrat) | |
902 return; | |
903 | |
904 note_def_vec_alloc (type, astrat, &lexer_line); | |
905 } | |
906 | |
907 /* Parse the file FNAME for GC-relevant declarations and definitions. | |
908 This is the only entry point to this file. */ | |
909 void | |
910 parse_file (const char *fname) | |
911 { | |
912 yybegin (fname); | |
913 for (;;) | |
914 { | |
915 switch (token ()) | |
916 { | |
917 case EXTERN: | |
918 case STATIC: | |
919 extern_or_static (); | |
920 break; | |
921 | |
922 case STRUCT: | |
923 case UNION: | |
924 struct_or_union (); | |
925 break; | |
926 | |
927 case TYPEDEF: | |
928 typedef_decl (); | |
929 break; | |
930 | |
931 case DEFVEC_OP: | |
932 case DEFVEC_I: | |
933 def_vec (); | |
934 break; | |
935 | |
936 case DEFVEC_ALLOC: | |
937 def_vec_alloc (); | |
938 break; | |
939 | |
940 case EOF_TOKEN: | |
941 goto eof; | |
942 | |
943 default: | |
944 parse_error ("unexpected top level token, %s", print_cur_token ()); | |
945 goto eof; | |
946 } | |
947 lexer_toplevel_done = 1; | |
948 } | |
949 | |
950 eof: | |
951 advance (); | |
952 yyend (); | |
953 } |