|
|
1.1 root 1: /* YACC parser for C syntax.
2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* To whomever it may concern: I have heard that such a thing was once
23: written by AT&T, but I have never seen it. */
24:
25: %expect 23
26:
27: /* These are the 23 conflicts you should get in parse.output;
28: the state numbers may vary if minor changes in the grammar are made.
29:
30: State 41 contains 1 shift/reduce conflict. (Two ways to recover from error.)
31: State 90 contains 1 shift/reduce conflict. (Two ways to recover from error.)
32: State 97 contains 1 shift/reduce conflict. (Two ways to recover from error.)
33: State 101 contains 1 shift/reduce conflict. (Two ways to recover from error.)
34: State 117 contains 1 shift/reduce conflict. (See comment at component_decl.)
35: State 169 contains 2 shift/reduce conflicts. (make notype_declarator longer.)
36: State 181 contains 1 shift/reduce conflict. (Two ways to recover from error.)
37: State 191 contains 1 shift/reduce conflict. (Two ways to recover from error.)
38: State 197 contains 1 shift/reduce conflict. (Two ways to recover from error.)
39: State 239 contains 2 shift/reduce conflicts. (make absdcl1 longer if poss.)
40: State 269 contains 2 shift/reduce conflicts. (same for after_type_declarator).
41: State 299 contains 2 shift/reduce conflicts. (similar for absdcl1 again.)
42: State 362 contains 1 shift/reduce conflict. (dangling else.)
43: State 370 contains 2 shift/reduce conflicts. (like 241, other context.)
44: State 373 contains 2 shift/reduce conflicts. (like 241, other context.)
45: State 411 contains 2 shift/reduce conflicts. (like 166 for parm_declarator)?
46: */
47:
48: %{
49: #include "config.h"
50: #include "tree.h"
1.1.1.2 root 51: #include "c-parse.h"
1.1 root 52: #include "c-tree.h"
53:
54: #include <stdio.h>
55: #include <errno.h>
56:
57: #ifndef errno
58: extern int errno;
59: #endif
60:
61: /* Cause the `yydebug' variable to be defined. */
62: #define YYDEBUG
63: %}
64:
65: %start program
66:
67: %union {long itype; tree ttype; enum tree_code code; char *cptr; }
68:
69: /* All identifiers that are not reserved words
70: and are not declared typedefs in the current block */
71: %token IDENTIFIER
72:
73: /* All identifiers that are declared typedefs in the current block.
74: In some contexts, they are treated just like IDENTIFIER,
75: but they can also serve as typespecs in declarations. */
76: %token TYPENAME
77:
78: /* Reserved words that specify storage class.
79: yylval contains an IDENTIFIER_NODE which indicates which one. */
80: %token SCSPEC
81:
82: /* Reserved words that specify type.
83: yylval contains an IDENTIFIER_NODE which indicates which one. */
84: %token TYPESPEC
85:
86: /* Reserved words that qualify type: "const" or "volatile".
87: yylval contains an IDENTIFIER_NODE which indicates which one. */
88: %token TYPE_QUAL
89:
90: /* Character or numeric constants.
91: yylval is the node for the constant. */
92: %token CONSTANT
93:
94: /* String constants in raw form.
95: yylval is a STRING_CST node. */
96: %token STRING
97:
98: /* "...", used for functions with variable arglists. */
99: %token ELLIPSIS
100:
101: /* the reserved words */
102: %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
103: %token BREAK CONTINUE RETURN GOTO ASM TYPEOF ALIGNOF
104:
105: /* Define the operator tokens and their precedences.
106: The value is an integer because, if used, it is the tree code
107: to use in the expression made from the operator. */
108:
109: %right <code> ASSIGN '='
110: %right <code> '?' ':'
111: %left <code> OROR
112: %left <code> ANDAND
113: %left <code> '|'
114: %left <code> '^'
115: %left <code> '&'
116: %left <code> EQCOMPARE
117: %left <code> ARITHCOMPARE
118: %left <code> LSHIFT RSHIFT
119: %left <code> '+' '-'
120: %left <code> '*' '/' '%'
121: %right <code> UNARY PLUSPLUS MINUSMINUS
122: %left HYPERUNARY
123: %left <code> POINTSAT '.'
124:
125: %type <code> unop
126:
127: %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
128: %type <ttype> expr_no_commas primary string STRING
129: %type <ttype> typed_declspecs reserved_declspecs
130: %type <ttype> typed_typespecs reserved_typespecquals
131: %type <ttype> declmods typespec typespecqual_reserved
132: %type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
133: %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
134: %type <ttype> init initlist maybeasm
1.1.1.3 root 135: %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
1.1 root 136:
137: %type <ttype> declarator
138: %type <ttype> notype_declarator after_type_declarator
139: %type <ttype> parm_declarator
140:
141: %type <ttype> structsp component_decl_list component_decl components component_declarator
142: %type <ttype> enumlist enumerator
143: %type <ttype> typename absdcl absdcl1 type_quals
144: %type <ttype> xexpr parms parm identifiers
145:
146: %type <ttype> parmlist parmlist_1 parmlist_2
147: %type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
148:
149: %type <itype> setspecs
150:
151: %{
152: /* the declaration found for the last IDENTIFIER token read in.
153: yylex must look this up to detect typedefs, which get token type TYPENAME,
154: so it is left around in case the identifier is not a typedef but is
155: used in a context which makes it a reference to a variable. */
156: static tree lastiddecl;
157:
158: static tree make_pointer_declarator ();
159: static tree combine_strings ();
160: static void reinit_parse_for_function ();
161:
162: extern double atof ();
163:
164: /* List of types and structure classes of the current declaration */
165: tree current_declspecs;
166:
167: char *input_filename; /* source file current line is coming from */
168: char *main_input_filename; /* top-level source file */
169:
170: static int yylex ();
171: %}
172:
173: %%
174: program: /* empty */
175: | extdefs
176: ;
177:
178: /* the reason for the strange actions in this rule
179: is so that notype_initdecls when reached via datadef
180: can find a valid list of type and sc specs in $0. */
181:
182: extdefs:
183: {$<ttype>$ = NULL_TREE; } extdef
184: | extdefs {$<ttype>$ = NULL_TREE; } extdef
185: ;
186:
187: extdef:
188: fndef
189: | datadef
190: | ASM '(' string ')' ';'
191: { if (pedantic)
192: warning ("ANSI C forbids use of `asm' keyword");
193: if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
194: assemble_asm ($3); }
195: ;
196:
197: datadef:
198: setspecs notype_initdecls ';'
199: { if (pedantic)
200: error ("ANSI C forbids data definition lacking type or storage class");
1.1.1.3 root 201: else if (!flag_traditional)
1.1 root 202: warning ("data definition lacks type or storage class"); }
203: | declmods setspecs notype_initdecls ';'
204: {}
205: | typed_declspecs setspecs initdecls ';'
206: {}
207: | declmods ';'
208: { error ("empty declaration"); }
209: | typed_declspecs ';'
210: { shadow_tag ($1); }
211: | error ';'
212: | error '}'
213: | ';'
214: ;
215:
216: fndef:
217: typed_declspecs setspecs declarator
218: { if (! start_function ($1, $3))
1.1.1.4 ! root 219: YYERROR;
1.1 root 220: reinit_parse_for_function (); }
221: xdecls
222: { store_parm_decls (); }
223: compstmt_or_error
224: { finish_function (); }
225: | typed_declspecs setspecs declarator error
226: { }
227: | declmods setspecs notype_declarator
228: { if (! start_function ($1, $3))
1.1.1.4 ! root 229: YYERROR;
1.1 root 230: reinit_parse_for_function (); }
231: xdecls
232: { store_parm_decls (); }
233: compstmt_or_error
234: { finish_function (); }
235: | declmods setspecs notype_declarator error
236: { }
237: | setspecs notype_declarator
238: { if (! start_function (0, $2))
1.1.1.4 ! root 239: YYERROR;
1.1 root 240: reinit_parse_for_function (); }
241: xdecls
242: { store_parm_decls (); }
243: compstmt_or_error
244: { finish_function (); }
245: | setspecs notype_declarator error
246: { }
247: ;
248:
249: identifier:
250: IDENTIFIER
251: | TYPENAME
252: ;
253:
254: unop: '&'
255: { $$ = ADDR_EXPR; }
256: | '-'
257: { $$ = NEGATE_EXPR; }
258: | '+'
259: { $$ = CONVERT_EXPR; }
260: | PLUSPLUS
261: { $$ = PREINCREMENT_EXPR; }
262: | MINUSMINUS
263: { $$ = PREDECREMENT_EXPR; }
264: | '~'
265: { $$ = BIT_NOT_EXPR; }
266: | '!'
267: { $$ = TRUTH_NOT_EXPR; }
268: ;
269:
270: expr: nonnull_exprlist
271: { $$ = build_compound_expr ($1); }
272: ;
273:
274: exprlist:
275: /* empty */
276: { $$ = NULL_TREE; }
277: | nonnull_exprlist
278: ;
279:
280: nonnull_exprlist:
281: expr_no_commas
282: { $$ = build_tree_list (NULL_TREE, $1); }
283: | nonnull_exprlist ',' expr_no_commas
284: { chainon ($1, build_tree_list (NULL_TREE, $3)); }
285: ;
286:
287: expr_no_commas:
288: primary
289: | '*' expr_no_commas %prec UNARY
290: { $$ = build_indirect_ref ($2, "unary *"); }
291: | unop expr_no_commas %prec UNARY
292: { $$ = build_unary_op ($1, $2, 0); }
293: | '(' typename ')' expr_no_commas %prec UNARY
294: { tree type = groktypename ($2);
295: $$ = build_c_cast (type, $4); }
296: | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY
297: { tree type = groktypename ($2);
298: if (pedantic)
299: warning ("ANSI C forbids constructor-expressions");
300: $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0);
301: if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
302: {
303: int failure = complete_array_type (type, $$, 1);
304: if (failure)
305: abort ();
306: }
307: }
308: | SIZEOF expr_no_commas %prec UNARY
309: { if (TREE_CODE ($2) == COMPONENT_REF
310: && TREE_PACKED (TREE_OPERAND ($2, 1)))
311: error ("sizeof applied to a bit-field");
312: $$ = c_sizeof (TREE_TYPE ($2)); }
313: | SIZEOF '(' typename ')' %prec HYPERUNARY
314: { $$ = c_sizeof (groktypename ($3)); }
315: | ALIGNOF expr_no_commas %prec UNARY
316: { if (TREE_CODE ($2) == COMPONENT_REF
317: && TREE_PACKED (TREE_OPERAND ($2, 1)))
318: error ("__alignof applied to a bit-field");
319: $$ = c_alignof (TREE_TYPE ($2)); }
320: | ALIGNOF '(' typename ')' %prec HYPERUNARY
321: { $$ = c_alignof (groktypename ($3)); }
322: | expr_no_commas '+' expr_no_commas
323: { $$ = build_binary_op ($2, $1, $3); }
324: | expr_no_commas '-' expr_no_commas
325: { $$ = build_binary_op ($2, $1, $3); }
326: | expr_no_commas '*' expr_no_commas
327: { $$ = build_binary_op ($2, $1, $3); }
328: | expr_no_commas '/' expr_no_commas
329: { $$ = build_binary_op ($2, $1, $3); }
330: | expr_no_commas '%' expr_no_commas
331: { $$ = build_binary_op ($2, $1, $3); }
332: | expr_no_commas LSHIFT expr_no_commas
333: { $$ = build_binary_op ($2, $1, $3); }
334: | expr_no_commas RSHIFT expr_no_commas
335: { $$ = build_binary_op ($2, $1, $3); }
336: | expr_no_commas ARITHCOMPARE expr_no_commas
337: { $$ = build_binary_op ($2, $1, $3); }
338: | expr_no_commas EQCOMPARE expr_no_commas
339: { $$ = build_binary_op ($2, $1, $3); }
340: | expr_no_commas '&' expr_no_commas
341: { $$ = build_binary_op ($2, $1, $3); }
342: | expr_no_commas '|' expr_no_commas
343: { $$ = build_binary_op ($2, $1, $3); }
344: | expr_no_commas '^' expr_no_commas
345: { $$ = build_binary_op ($2, $1, $3); }
346: | expr_no_commas ANDAND expr_no_commas
347: { $$ = build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }
348: | expr_no_commas OROR expr_no_commas
349: { $$ = build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }
350: | expr_no_commas '?' xexpr ':' expr_no_commas
351: { $$ = build_conditional_expr ($1, $3, $5); }
352: | expr_no_commas '=' expr_no_commas
353: { $$ = build_modify_expr ($1, NOP_EXPR, $3); }
354: | expr_no_commas ASSIGN expr_no_commas
355: { $$ = build_modify_expr ($1, $2, $3); }
356: ;
357:
358: primary:
359: IDENTIFIER
360: { $$ = lastiddecl;
361: if (!$$)
362: {
363: if (yychar == YYEMPTY)
364: yychar = YYLEX;
365: if (yychar == '(')
366: $$ = implicitly_declare ($1);
367: else
368: {
369: if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node)
370: error ("undeclared variable `%s' (first use here)",
371: IDENTIFIER_POINTER ($1));
372: $$ = error_mark_node;
373: /* Prevent repeated error messages. */
374: IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node;
375: }
376: }
377: if (TREE_CODE ($$) == CONST_DECL)
378: $$ = DECL_INITIAL ($$);
379: }
380: | CONSTANT
381: | string
382: { $$ = combine_strings ($1); }
383: | '(' expr ')'
384: { $$ = $2; }
385: | '(' error ')'
386: { $$ = error_mark_node; }
387: | '('
388: { if (current_function_decl == 0)
389: {
390: error ("braced-group within expression allowed only inside a function");
1.1.1.4 ! root 391: YYERROR;
1.1 root 392: }
1.1.1.2 root 393: $<ttype>$ = expand_start_stmt_expr (); }
1.1 root 394: compstmt ')'
395: { if (pedantic)
396: warning ("ANSI C forbids braced-groups within expressions");
1.1.1.2 root 397: $$ = expand_end_stmt_expr ($<ttype>2); }
1.1 root 398: | primary '(' exprlist ')' %prec '.'
399: { $$ = build_function_call ($1, $3); }
400: | primary '[' expr ']' %prec '.'
401: { $$ = build_array_ref ($1, $3); }
402: | primary '.' identifier
403: { $$ = build_component_ref ($1, $3); }
404: | primary POINTSAT identifier
405: { $$ = build_component_ref (build_indirect_ref ($1, "->"), $3); }
406: | primary PLUSPLUS
407: { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
408: | primary MINUSMINUS
409: { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
410: ;
411:
412: /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
413: string:
414: STRING
415: | string STRING
416: { $$ = chainon ($1, $2); }
417: ;
418:
419: xdecls:
420: /* empty */
421: | decls
422: ;
423:
424: decls:
425: decl
426: | errstmt
427: | decls decl
428: | decl errstmt
429: ;
430:
431: /* records the type and storage class specs to use for processing
432: the declarators that follow */
433: setspecs: /* empty */
434: { current_declspecs = $<ttype>0;
435: $$ = suspend_momentary (); }
436: ;
437:
438: decl:
439: typed_declspecs setspecs initdecls ';'
440: { resume_momentary ($2); }
441: | declmods setspecs notype_initdecls ';'
442: { resume_momentary ($2); }
443: | typed_declspecs ';'
444: { shadow_tag ($1); }
445: | declmods ';'
446: { warning ("empty declaration"); }
447: ;
448:
449: /* Declspecs which contain at least one type specifier or typedef name.
450: (Just `const' or `volatile' is not enough.)
451: A typedef'd name following these is taken as a name to be declared. */
452:
453: typed_declspecs:
454: typespec reserved_declspecs
455: { $$ = tree_cons (NULL_TREE, $1, $2); }
456: | declmods typespec reserved_declspecs
457: { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
458: ;
459:
460: reserved_declspecs: /* empty */
461: { $$ = NULL_TREE; }
462: | reserved_declspecs typespecqual_reserved
463: { $$ = tree_cons (NULL_TREE, $2, $1); }
464: | reserved_declspecs SCSPEC
465: { $$ = tree_cons (NULL_TREE, $2, $1); }
466: ;
467:
468: /* List of just storage classes and type modifiers.
469: A declaration can start with just this, but then it cannot be used
470: to redeclare a typedef-name. */
471:
472: declmods:
473: TYPE_QUAL
474: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
475: | SCSPEC
476: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
477: | declmods TYPE_QUAL
478: { $$ = tree_cons (NULL_TREE, $2, $1); }
479: | declmods SCSPEC
480: { $$ = tree_cons (NULL_TREE, $2, $1); }
481: ;
482:
483:
484: /* Used instead of declspecs where storage classes are not allowed
485: (that is, for typenames and structure components).
486: Don't accept a typedef-name if anything but a modifier precedes it. */
487:
488: typed_typespecs:
489: typespec reserved_typespecquals
490: { $$ = tree_cons (NULL_TREE, $1, $2); }
491: | nonempty_type_quals typespec reserved_typespecquals
492: { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
493: ;
494:
495: reserved_typespecquals: /* empty */
496: { $$ = NULL_TREE; }
497: | reserved_typespecquals typespecqual_reserved
498: { $$ = tree_cons (NULL_TREE, $2, $1); }
499: ;
500:
501: /* A typespec (but not a type qualifier).
502: Once we have seen one of these in a declaration,
503: if a typedef name appears then it is being redeclared. */
504:
505: typespec: TYPESPEC
506: | structsp
507: | TYPENAME
508: | TYPEOF '(' expr ')'
509: { $$ = TREE_TYPE ($3);
510: if (pedantic)
511: warning ("ANSI C forbids `typeof'"); }
512: | TYPEOF '(' typename ')'
513: { $$ = groktypename ($3);
514: if (pedantic)
515: warning ("ANSI C forbids `typeof'"); }
516: ;
517:
518: /* A typespec that is a reserved word, or a type qualifier. */
519:
520: typespecqual_reserved: TYPESPEC
521: | TYPE_QUAL
522: | structsp
523: ;
524:
525: initdecls:
526: initdcl
527: | initdecls ',' initdcl
528: ;
529:
530: notype_initdecls:
531: notype_initdcl
532: | notype_initdecls ',' initdcl
533: ;
534:
535: maybeasm:
536: /* empty */
537: { $$ = NULL_TREE; }
538: | ASM '(' string ')'
539: { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
540: $$ = $3;
541: if (pedantic)
542: warning ("ANSI C forbids use of `asm' keyword");
543: }
544: ;
545:
546: initdcl:
547: declarator maybeasm '='
548: { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
549: init
550: /* Note how the declaration of the variable is in effect while its init is parsed! */
551: { finish_decl ($<ttype>4, $5, $2); }
552: | declarator maybeasm
553: { tree d = start_decl ($1, current_declspecs, 0);
554: finish_decl (d, NULL_TREE, $2); }
555: ;
556:
557: notype_initdcl:
558: notype_declarator maybeasm '='
559: { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
560: init
561: /* Note how the declaration of the variable is in effect while its init is parsed! */
562: { finish_decl ($<ttype>4, $5, $2); }
563: | notype_declarator maybeasm
564: { tree d = start_decl ($1, current_declspecs, 0);
565: finish_decl (d, NULL_TREE, $2); }
566: ;
567:
568: init:
569: expr_no_commas
1.1.1.2 root 570: | '{' '}'
571: { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
572: if (pedantic)
573: warning ("ANSI C forbids empty initializer braces"); }
1.1 root 574: | '{' initlist '}'
575: { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
576: | '{' initlist ',' '}'
577: { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
578: | error
579: { $$ = NULL_TREE; }
580: ;
581:
582: /* This chain is built in reverse order,
583: and put in forward order where initlist is used. */
584: initlist:
1.1.1.2 root 585: init
1.1 root 586: { $$ = build_tree_list (NULL_TREE, $1); }
587: | initlist ',' init
588: { $$ = tree_cons (NULL_TREE, $3, $1); }
589: ;
590:
591: /* Any kind of declarator (thus, all declarators allowed
592: after an explicit typespec). */
593:
594: declarator:
595: after_type_declarator
596: | notype_declarator
597: ;
598:
599: /* A declarator that is allowed only after an explicit typespec. */
600:
601: after_type_declarator:
602: '(' after_type_declarator ')'
603: { $$ = $2; }
604: | after_type_declarator '(' parmlist_or_identifiers %prec '.'
605: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
606: /* | after_type_declarator '(' error ')' %prec '.'
607: { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
608: poplevel (0, 0, 0); } */
609: | after_type_declarator '[' expr ']' %prec '.'
610: { $$ = build_nt (ARRAY_REF, $1, $3); }
611: | after_type_declarator '[' ']' %prec '.'
612: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
613: | '*' type_quals after_type_declarator %prec UNARY
614: { $$ = make_pointer_declarator ($2, $3); }
615: | TYPENAME
616: ;
617:
618: /* Kinds of declarator that can appear in a parameter list
619: in addition to notype_declarator. This is like after_type_declarator
620: but does not allow a typedef name in parentheses as an identifier
621: (because it would conflict with a function with that typedef as arg). */
622:
623: parm_declarator:
624: parm_declarator '(' parmlist_or_identifiers %prec '.'
625: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
626: /* | parm_declarator '(' error ')' %prec '.'
627: { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
628: poplevel (0, 0, 0); } */
629: | parm_declarator '[' expr ']' %prec '.'
630: { $$ = build_nt (ARRAY_REF, $1, $3); }
631: | parm_declarator '[' ']' %prec '.'
632: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
633: | '*' type_quals parm_declarator %prec UNARY
634: { $$ = make_pointer_declarator ($2, $3); }
635: | TYPENAME
636: ;
637:
638: /* A declarator allowed whether or not there has been
639: an explicit typespec. These cannot redeclare a typedef-name. */
640:
641: notype_declarator:
642: notype_declarator '(' parmlist_or_identifiers %prec '.'
643: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
644: /* | notype_declarator '(' error ')' %prec '.'
645: { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
646: poplevel (0, 0, 0); } */
647: | '(' notype_declarator ')'
648: { $$ = $2; }
649: | '*' type_quals notype_declarator %prec UNARY
650: { $$ = make_pointer_declarator ($2, $3); }
651: | notype_declarator '[' expr ']' %prec '.'
652: { $$ = build_nt (ARRAY_REF, $1, $3); }
653: | notype_declarator '[' ']' %prec '.'
654: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
655: | IDENTIFIER
656: ;
657:
658: structsp:
659: STRUCT identifier '{'
660: { $$ = start_struct (RECORD_TYPE, $2);
661: /* Start scope of tag before parsing components. */
662: }
663: component_decl_list '}'
664: { $$ = finish_struct ($<ttype>4, $5);
665: /* Really define the structure. */
666: }
667: | STRUCT '{' component_decl_list '}'
668: { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
669: $3); }
670: | STRUCT identifier
671: { $$ = xref_tag (RECORD_TYPE, $2); }
672: | UNION identifier '{'
673: { $$ = start_struct (UNION_TYPE, $2); }
674: component_decl_list '}'
675: { $$ = finish_struct ($<ttype>4, $5); }
676: | UNION '{' component_decl_list '}'
677: { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
678: $3); }
679: | UNION identifier
680: { $$ = xref_tag (UNION_TYPE, $2); }
681: | ENUM identifier '{'
682: { $<itype>3 = suspend_momentary ();
683: $$ = start_enum ($2); }
684: enumlist maybecomma '}'
685: { $$ = finish_enum ($<ttype>4, nreverse ($5));
686: resume_momentary ($<itype>3); }
687: | ENUM '{'
688: { $<itype>2 = suspend_momentary ();
689: $$ = start_enum (NULL_TREE); }
690: enumlist maybecomma '}'
691: { $$ = finish_enum ($<ttype>3, nreverse ($4));
692: resume_momentary ($<itype>2); }
693: | ENUM identifier
694: { $$ = xref_tag (ENUMERAL_TYPE, $2); }
695: ;
696:
697: maybecomma:
698: /* empty */
699: | ','
700: ;
701:
702: component_decl_list: /* empty */
703: { $$ = NULL_TREE; }
704: | component_decl_list component_decl ';'
705: { $$ = chainon ($1, $2); }
706: | component_decl_list ';'
707: { if (pedantic)
708: warning ("extra semicolon in struct or union specified"); }
709: ;
710:
711: /* There is a shift-reduce conflict here, because `components' may
712: start with a `typename'. It happens that shifting (the default resolution)
713: does the right thing, because it treats the `typename' as part of
714: a `typed_typespecs'.
715:
716: It is possible that this same technique would allow the distinction
717: between `notype_initdecls' and `initdecls' to be eliminated.
718: But I am being cautious and not trying it. */
719:
720: component_decl:
721: typed_typespecs setspecs components
722: { $$ = $3;
723: resume_momentary ($2); }
724: | nonempty_type_quals setspecs components
725: { $$ = $3;
726: resume_momentary ($2); }
727: | error
728: { $$ = NULL_TREE; }
729: ;
730:
731: components:
732: /* empty */
733: { $$ = NULL_TREE; }
734: | component_declarator
735: | components ',' component_declarator
736: { $$ = chainon ($1, $3); }
737: ;
738:
739: component_declarator:
740: declarator
741: { $$ = grokfield (input_filename, lineno, $1, current_declspecs, NULL_TREE); }
742: | declarator ':' expr_no_commas
743: { $$ = grokfield (input_filename, lineno, $1, current_declspecs, $3); }
744: | ':' expr_no_commas
745: { $$ = grokfield (input_filename, lineno, NULL_TREE, current_declspecs, $2); }
746: ;
747:
748: /* We chain the enumerators in reverse order.
749: They are put in forward order where enumlist is used.
750: (The order used to be significant, but no longer is so.
751: However, we still maintain the order, just to be clean.) */
752:
753: enumlist:
754: enumerator
755: | enumlist ',' enumerator
756: { $$ = chainon ($3, $1); }
757: ;
758:
759:
760: enumerator:
761: identifier
762: { $$ = build_enumerator ($1, NULL_TREE); }
763: | identifier '=' expr_no_commas
764: { $$ = build_enumerator ($1, $3); }
765: ;
766:
767: typename:
768: typed_typespecs absdcl
769: { $$ = build_tree_list ($1, $2); }
770: | nonempty_type_quals absdcl
771: { $$ = build_tree_list ($1, $2); }
772: ;
773:
774: absdcl: /* an absolute declarator */
775: /* empty */
776: { $$ = NULL_TREE; }
777: | absdcl1
778: ;
779:
780: nonempty_type_quals:
781: TYPE_QUAL
782: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
783: | nonempty_type_quals TYPE_QUAL
784: { $$ = tree_cons (NULL_TREE, $2, $1); }
785: ;
786:
787: type_quals:
788: /* empty */
789: { $$ = NULL_TREE; }
790: | type_quals TYPE_QUAL
791: { $$ = tree_cons (NULL_TREE, $2, $1); }
792: ;
793:
794: absdcl1: /* a nonempty absolute declarator */
795: '(' absdcl1 ')'
796: { $$ = $2; }
797: /* `(typedef)1' is `int'. */
798: | '*' type_quals absdcl1 %prec UNARY
799: { $$ = make_pointer_declarator ($2, $3); }
800: | '*' type_quals %prec UNARY
801: { $$ = make_pointer_declarator ($2, NULL_TREE); }
802: | absdcl1 '(' parmlist %prec '.'
803: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
804: | absdcl1 '[' expr ']' %prec '.'
805: { $$ = build_nt (ARRAY_REF, $1, $3); }
806: | absdcl1 '[' ']' %prec '.'
807: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
808: | '(' parmlist %prec '.'
809: { $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); }
810: | '[' expr ']' %prec '.'
811: { $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
812: | '[' ']' %prec '.'
813: { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
814: ;
815:
816: /* at least one statement, the first of which parses without error. */
817: /* stmts is used only after decls, so an invalid first statement
818: is actually regarded as an invalid decl and part of the decls. */
819:
820: stmts:
821: stmt
822: | stmts stmt
823: | stmts errstmt
824: ;
825:
826: xstmts:
827: /* empty */
828: | stmts
829: ;
830:
831: errstmt: error ';'
832: ;
833:
834: pushlevel: /* empty */
835: { pushlevel (0);
836: clear_last_expr ();
837: push_momentary ();
838: expand_start_bindings (0); }
839: ;
840:
841: /* This is the body of a function definition.
842: It causes syntax errors to ignore to the next openbrace. */
843: compstmt_or_error:
844: compstmt
845: | error compstmt
846: ;
847:
848: compstmt: '{' '}'
849: | '{' pushlevel decls xstmts '}'
1.1.1.2 root 850: { expand_end_bindings (getdecls (), 1, 0);
1.1 root 851: poplevel (1, 1, 0);
852: pop_momentary (); }
853: | '{' pushlevel error '}'
1.1.1.2 root 854: { expand_end_bindings (getdecls (), 0, 0);
1.1 root 855: poplevel (0, 0, 0);
856: pop_momentary (); }
857: | '{' pushlevel stmts '}'
1.1.1.2 root 858: { expand_end_bindings (getdecls (), 0, 0);
1.1 root 859: poplevel (0, 0, 0);
860: pop_momentary (); }
861: ;
862:
863: simple_if:
864: IF '(' expr ')'
865: { emit_note (input_filename, lineno);
866: expand_start_cond (truthvalue_conversion ($3), 0); }
867: stmt
868: ;
869:
870: stmt:
871: compstmt
872: | expr ';'
873: { emit_note (input_filename, lineno);
874: expand_expr_stmt ($1);
875: clear_momentary (); }
876: | simple_if ELSE
877: { expand_start_else (); }
878: stmt
879: { expand_end_else (); }
880: | simple_if
881: { expand_end_cond (); }
882: | WHILE
883: { emit_note (input_filename, lineno);
884: expand_start_loop (1); }
885: '(' expr ')'
886: { emit_note (input_filename, lineno);
887: expand_exit_loop_if_false (truthvalue_conversion ($4)); }
888: stmt
889: { expand_end_loop (); }
890: | DO
891: { emit_note (input_filename, lineno);
892: expand_start_loop_continue_elsewhere (1); }
893: stmt WHILE
894: { expand_loop_continue_here (); }
895: '(' expr ')' ';'
896: { emit_note (input_filename, lineno);
897: expand_exit_loop_if_false (truthvalue_conversion ($7));
898: expand_end_loop ();
899: clear_momentary (); }
900: | FOR
901: '(' xexpr ';'
902: { emit_note (input_filename, lineno);
903: if ($3) expand_expr_stmt ($3);
904: expand_start_loop_continue_elsewhere (1); }
905: xexpr ';'
906: { emit_note (input_filename, lineno);
907: if ($6)
908: expand_exit_loop_if_false (truthvalue_conversion ($6)); }
909: xexpr ')'
910: /* Don't let the tree nodes for $9 be discarded
911: by clear_momentary during the parsing of the next stmt. */
912: { push_momentary ();
913: $<itype>10 = lineno; }
914: stmt
915: { emit_note (input_filename, $<itype>10);
916: expand_loop_continue_here ();
917: if ($9)
918: expand_expr_stmt ($9);
919: pop_momentary ();
920: expand_end_loop (); }
921: | SWITCH '(' expr ')'
922: { emit_note (input_filename, lineno);
923: c_expand_start_case ($3);
924: /* Don't let the tree nodes for $3 be discarded by
925: clear_momentary during the parsing of the next stmt. */
926: push_momentary (); }
927: stmt
928: { expand_end_case ();
929: pop_momentary (); }
930: | CASE expr ':'
931: { register tree value = fold ($2);
932: register tree label
933: = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
934:
935: if (TREE_CODE (value) != INTEGER_CST
936: && value != error_mark_node)
937: {
938: error ("case label does not reduce to an integer constant");
939: value = error_mark_node;
940: }
941: else
942: /* Promote char or short to int. */
943: value = default_conversion (value);
944: if (value != error_mark_node)
945: {
946: int success = pushcase (value, label);
947: if (success == 1)
948: error ("case label not within a switch statement");
949: else if (success == 2)
950: error ("duplicate case value");
951: else if (success == 3)
952: warning ("case value out of range");
953: }
954: }
955: stmt
956: | DEFAULT ':'
957: {
958: register tree label
959: = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
960: int success = pushcase (NULL_TREE, label);
961: if (success == 1)
962: error ("default label not within a switch statement");
963: else if (success == 2)
964: error ("multiple default labels in one switch");
965: }
966: stmt
967: | BREAK ';'
968: { emit_note (input_filename, lineno);
969: if ( ! expand_exit_something ())
970: error ("break statement not within loop or switch"); }
971: | CONTINUE ';'
972: { emit_note (input_filename, lineno);
973: if (! expand_continue_loop ())
974: error ("continue statement not within a loop"); }
975: | RETURN ';'
976: { emit_note (input_filename, lineno);
977: c_expand_return (NULL_TREE); }
978: | RETURN expr ';'
979: { emit_note (input_filename, lineno);
980: c_expand_return ($2); }
981: | ASM maybe_type_qual '(' string ')' ';'
982: { if (pedantic)
983: warning ("ANSI C forbids use of `asm' keyword");
984: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
985: expand_asm ($4); }
986: /* This is the case with just output operands. */
987: | ASM maybe_type_qual '(' string ':' asm_operands ')' ';'
988: { if (pedantic)
989: warning ("ANSI C forbids use of `asm' keyword");
990: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1.1.1.3 root 991: c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
1.1 root 992: $2 == ridpointers[(int)RID_VOLATILE]); }
993: /* This is the case with input operands as well. */
994: | ASM maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';'
995: { if (pedantic)
996: warning ("ANSI C forbids use of `asm' keyword");
997: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1.1.1.3 root 998: c_expand_asm_operands ($4, $6, $8, NULL_TREE,
999: $2 == ridpointers[(int)RID_VOLATILE]); }
1000: /* This is the case with clobbered registers as well. */
1001: | ASM maybe_type_qual '(' string ':' asm_operands ':'
1002: asm_operands ':' asm_clobbers ')' ';'
1003: { if (pedantic)
1004: warning ("ANSI C forbids use of `asm' keyword");
1005: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1006: c_expand_asm_operands ($4, $6, $8, $10,
1.1 root 1007: $2 == ridpointers[(int)RID_VOLATILE]); }
1008: | GOTO identifier ';'
1009: { tree decl;
1010: emit_note (input_filename, lineno);
1011: decl = lookup_label ($2);
1012: expand_goto (decl); }
1013: | identifier ':'
1014: { tree label = define_label (input_filename, lineno, $1);
1015: if (label)
1016: expand_label (label); }
1017: stmt
1018: | ';'
1019: ;
1020:
1021: maybe_type_qual:
1022: /* empty */
1023: { emit_note (input_filename, lineno); }
1024: | TYPE_QUAL
1025: { emit_note (input_filename, lineno); }
1026: ;
1027:
1028: xexpr:
1029: /* empty */
1030: { $$ = NULL_TREE; }
1031: | expr
1032: ;
1033:
1034: /* These are the operands other than the first string and colon
1035: in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
1036: asm_operands: /* empty */
1037: { $$ = NULL_TREE; }
1038: | nonnull_asm_operands
1039: ;
1040:
1041: nonnull_asm_operands:
1042: asm_operand
1043: | nonnull_asm_operands ',' asm_operand
1044: { $$ = chainon ($1, $3); }
1045: ;
1046:
1047: asm_operand:
1.1.1.3 root 1048: STRING '(' expr ')'
1.1 root 1049: { $$ = build_tree_list ($1, $3); }
1050: ;
1051:
1.1.1.3 root 1052: asm_clobbers:
1053: STRING
1054: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
1055: | asm_clobbers ',' STRING
1056: { $$ = tree_cons (NULL_TREE, $3, $1); }
1057: ;
1058:
1.1 root 1059: /* This is what appears inside the parens in a function declarator.
1060: Its value is a list of ..._TYPE nodes. */
1061: parmlist:
1062: { pushlevel (0); }
1063: parmlist_1
1064: { $$ = $2; poplevel (0, 0, 0); }
1065: ;
1066:
1067: /* This is referred to where either a parmlist or an identifier list is ok.
1068: Its value is a list of ..._TYPE nodes or a list of identifiers. */
1069: parmlist_or_identifiers:
1070: { pushlevel (0); }
1071: parmlist_or_identifiers_1
1072: { $$ = $2; poplevel (0, 0, 0); }
1073: ;
1074:
1075: parmlist_or_identifiers_1:
1076: parmlist_2 ')'
1077: | identifiers ')'
1078: { $$ = tree_cons (NULL_TREE, NULL_TREE, $1); }
1079: | error ')'
1080: { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
1081: ;
1082:
1083: parmlist_1:
1084: parmlist_2 ')'
1085: | error ')'
1086: { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
1087: ;
1088:
1089: /* This is what appears inside the parens in a function declarator.
1090: Is value is represented in the format that grokdeclarator expects. */
1091: parmlist_2: /* empty */
1092: { $$ = get_parm_info (0); }
1093: | parms
1094: { $$ = get_parm_info (1); }
1095: | parms ',' ELLIPSIS
1096: { $$ = get_parm_info (0); }
1097: ;
1098:
1099: parms:
1100: parm
1101: { push_parm_decl ($1); }
1102: | parms ',' parm
1103: { push_parm_decl ($3); }
1104: ;
1105:
1106: /* A single parameter declaration or parameter type name,
1107: as found in a parmlist. */
1108: parm:
1109: typed_declspecs parm_declarator
1110: { $$ = build_tree_list ($1, $2) ; }
1111: | typed_declspecs notype_declarator
1112: { $$ = build_tree_list ($1, $2) ; }
1113: | typed_declspecs absdcl
1114: { $$ = build_tree_list ($1, $2); }
1115: | declmods notype_declarator
1116: { $$ = build_tree_list ($1, $2) ; }
1117: | declmods absdcl
1118: { $$ = build_tree_list ($1, $2); }
1119: ;
1120:
1121: /* A nonempty list of identifiers. */
1122: identifiers:
1123: IDENTIFIER
1124: { $$ = build_tree_list (NULL_TREE, $1); }
1125: | identifiers ',' IDENTIFIER
1126: { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
1127: ;
1128: %%
1129:
1130: /* Return something to represent absolute declarators containing a *.
1131: TARGET is the absolute declarator that the * contains.
1132: TYPE_QUALS is a list of modifiers such as const or volatile
1133: to apply to the pointer type, represented as identifiers.
1134:
1135: We return an INDIRECT_REF whose "contents" are TARGET
1136: and whose type is the modifier list. */
1137:
1138: static tree
1139: make_pointer_declarator (type_quals, target)
1140: tree type_quals, target;
1141: {
1142: return build (INDIRECT_REF, type_quals, target);
1143: }
1144:
1145: /* Given a chain of STRING_CST nodes,
1146: concatenate them into one STRING_CST
1147: and give it a suitable array-of-chars data type. */
1148:
1149: static tree
1150: combine_strings (strings)
1151: tree strings;
1152: {
1153: register tree value, t;
1154: register int length = 1;
1155: int wide_length = 0;
1156: int wide_flag = 0;
1157:
1158: if (TREE_CHAIN (strings))
1159: {
1160: /* More than one in the chain, so concatenate. */
1161: register char *p, *q;
1162:
1163: /* Don't include the \0 at the end of each substring,
1164: except for the last one.
1165: Count wide strings and ordinary strings separately. */
1166: for (t = strings; t; t = TREE_CHAIN (t))
1167: {
1168: if (TREE_TYPE (t) == int_array_type_node)
1169: {
1170: wide_length += (TREE_STRING_LENGTH (t) - 1);
1171: wide_flag = 1;
1172: }
1173: else
1174: length += (TREE_STRING_LENGTH (t) - 1);
1175: }
1176:
1177: /* If anything is wide, the non-wides will be converted,
1178: which makes them take more space. */
1179: if (wide_flag)
1180: length = length * UNITS_PER_WORD + wide_length;
1181:
1182: p = (char *) oballoc (length);
1183:
1184: /* Copy the individual strings into the new combined string.
1185: If the combined string is wide, convert the chars to ints
1186: for any individual strings that are not wide. */
1187:
1188: q = p;
1189: for (t = strings; t; t = TREE_CHAIN (t))
1190: {
1191: int len = TREE_STRING_LENGTH (t) - 1;
1192: if ((TREE_TYPE (t) == int_array_type_node) == wide_flag)
1193: {
1194: bcopy (TREE_STRING_POINTER (t), q, len);
1195: q += len;
1196: }
1197: else
1198: {
1199: int i;
1200: for (i = 0; i < len; i++)
1201: ((int *) q)[i] = TREE_STRING_POINTER (t)[i];
1202: q += len * UNITS_PER_WORD;
1203: }
1204: }
1205: *q = 0;
1206:
1207: value = make_node (STRING_CST);
1208: TREE_STRING_POINTER (value) = p;
1209: TREE_STRING_LENGTH (value) = length;
1210: TREE_LITERAL (value) = 1;
1211: }
1212: else
1213: {
1214: value = strings;
1215: length = TREE_STRING_LENGTH (value);
1216: if (TREE_TYPE (value) == int_array_type_node)
1217: wide_flag = 1;
1218: }
1219:
1.1.1.3 root 1220: /* Create the array type for the string constant.
1221: -Wwrite-strings says make the string constant an array of const char
1222: so that copying it to a non-const pointer will get a warning. */
1223: if (warn_write_strings)
1224: {
1225: tree elements
1226: = build_type_variant (wide_flag ? integer_type_node : char_type_node,
1227: 1, 0);
1228: TREE_TYPE (value)
1229: = build_array_type (elements,
1230: build_index_type (build_int_2 (length - 1, 0)));
1231: }
1232: else
1233: TREE_TYPE (value)
1234: = build_array_type (wide_flag ? integer_type_node : char_type_node,
1235: build_index_type (build_int_2 (length - 1, 0)));
1.1 root 1236: TREE_LITERAL (value) = 1;
1237: TREE_STATIC (value) = 1;
1238: return value;
1239: }
1240:
1241: int lineno; /* current line number in file being read */
1242:
1243: FILE *finput; /* input file.
1244: Normally a pipe from the preprocessor. */
1245:
1246: /* lexical analyzer */
1247:
1248: static int maxtoken; /* Current nominal length of token buffer */
1249: static char *token_buffer; /* Pointer to token buffer.
1250: Actual allocated length is maxtoken + 2. */
1251:
1.1.1.4 ! root 1252: #define MIN_WORD_SIZE 2 /* minimum size for C keyword */
! 1253: #define MAX_WORD_SIZE 9 /* maximum size for C keyword */
! 1254: #define MIN_KEY_SIZE 4 /* range of the hash keys values for the */
! 1255: #define MAX_KEY_SIZE 39 /* minimum perfect hash generator */
1.1 root 1256:
1257: #define NORID RID_UNUSED
1258:
1.1.1.4 ! root 1259: struct resword {char *name; short token; enum rid rid;};
! 1260:
! 1261: /* This is the hash table of keywords.
! 1262: The order of keywords has been chosen for perfect hashing.
! 1263: Therefore, this table cannot be updated by hand.
! 1264: Use the program perfect-hash to generate an updated table. */
! 1265:
! 1266: static struct resword reswords[]
! 1267: = {{NULL, 0, NORID},
! 1268: {NULL, 0, NORID}, /* these locations are not used. */
! 1269: {NULL, 0, NORID}, /* they simplify the hashing. */
! 1270: {NULL, 0, NORID},
1.1 root 1271: {"else", ELSE, NORID},
1272: {"enum", ENUM, NORID},
1273: {"while", WHILE, NORID},
1274: {"extern", SCSPEC, RID_EXTERN},
1.1.1.4 ! root 1275: {"double", TYPESPEC, RID_DOUBLE},
! 1276: {"default", DEFAULT, NORID},
! 1277: {"do", DO, NORID},
! 1278: {"goto", GOTO, NORID},
! 1279: {"short", TYPESPEC, RID_SHORT},
1.1 root 1280: {"struct", STRUCT, NORID},
1281: {"return", RETURN, NORID},
1.1.1.4 ! root 1282: {"signed", TYPESPEC, RID_SIGNED},
! 1283: {"float", TYPESPEC, RID_FLOAT},
1.1 root 1284: {"typeof", TYPEOF, NORID},
1.1.1.4 ! root 1285: {"typedef", SCSPEC, RID_TYPEDEF},
1.1 root 1286: {"switch", SWITCH, NORID},
1.1.1.4 ! root 1287: {"int", TYPESPEC, RID_INT},
! 1288: {"for", FOR, NORID},
! 1289: {"register", SCSPEC, RID_REGISTER},
! 1290: {"inline", SCSPEC, RID_INLINE},
! 1291: {"sizeof", SIZEOF, NORID},
! 1292: {"void", TYPESPEC, RID_VOID},
! 1293: {"__alignof", ALIGNOF, NORID},
! 1294: {"volatile", TYPE_QUAL, RID_VOLATILE},
! 1295: {"case", CASE, NORID},
! 1296: {"const", TYPE_QUAL, RID_CONST},
! 1297: {"if", IF, NORID},
! 1298: {"long", TYPESPEC, RID_LONG},
1.1 root 1299: {"continue", CONTINUE, NORID},
1.1.1.4 ! root 1300: {"asm", ASM, NORID},
! 1301: {"union", UNION, NORID},
! 1302: {"char", TYPESPEC, RID_CHAR},
! 1303: {"break", BREAK, NORID},
! 1304: {"static", SCSPEC, RID_STATIC},
! 1305: {"unsigned", TYPESPEC, RID_UNSIGNED},
! 1306: {"auto", SCSPEC, RID_AUTO}};
1.1 root 1307:
1308: /* The elements of `ridpointers' are identifier nodes
1309: for the reserved type names and storage classes.
1310: It is indexed by a RID_... value. */
1311:
1312: tree ridpointers[(int) RID_MAX];
1313:
1314: int check_newline ();
1.1.1.4 ! root 1315:
! 1316: /* This function performs the minimum-perfect hash mapping from input
! 1317: string to reswords table index. It only looks at the first and
! 1318: last characters in the string, thus assuring the O(1) lookup time
! 1319: (this keeps our constant down to an insignificant amount!). Compiling
! 1320: the following 2 functions as inline removes all overhead of the
! 1321: function calls. */
! 1322:
! 1323: #ifdef __GNUC__
! 1324: inline
! 1325: #endif
! 1326: static int
! 1327: hash (str, len)
! 1328: register char *str;
! 1329: register int len;
! 1330: {
! 1331: /* This table is used to build the hash table index that recognizes
! 1332: reserved words in 0(1) steps. It is larger than strictly necessary,
! 1333: but I'm trading off the space for the time-saving luxury of avoiding
! 1334: subtraction of an offset. */
! 1335:
! 1336: static char hash_table[]
! 1337: = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1338: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1339: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1340: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1341: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1342: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1343: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1344: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1345: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! 1346: 0, 0, 0, 0, 0, 6, 0, 29, 31, 24,
! 1347: 2, 0, 11, 1, 6, 17, 0, 0, 26, 1,
! 1348: 1, 6, 0, 0, 7, 7, 0, 28, 19, 1,
! 1349: 0, 0, 0, 0, 0, 0, 0, 0};
! 1350:
! 1351: /* The hash function couldn't be simpler: add the length of the string
! 1352: to the Hash_Table value of its first and last character. */
! 1353:
! 1354: return len + hash_table[(int) str[0]] + hash_table[(int) str[len - 1]];
! 1355: }
! 1356:
! 1357: /* This routine attempts to match the string found in the reswords with
! 1358: the one from the input stream. If all the relevant details match an
! 1359: actual strcmp comparison is performed. */
! 1360:
! 1361: #ifdef __GNUC__
! 1362: inline
! 1363: #endif
! 1364: static struct resword *
! 1365: is_reserved_word (str,len)
! 1366: register char *str;
! 1367: register int len;
! 1368: {
! 1369: if (len <= MAX_WORD_SIZE && len >= MIN_WORD_SIZE)
! 1370: {
! 1371: register int key = hash (str, len);
! 1372:
! 1373: if (key >= MIN_KEY_SIZE && key <= MAX_KEY_SIZE)
! 1374: if (reswords[key].name[0] == str[0]
! 1375: && !strcmp (reswords[key].name + 1, str + 1))
! 1376: return &reswords[key];
! 1377: }
! 1378: return NULL;
! 1379: }
1.1 root 1380:
1381: void
1382: init_lex ()
1383: {
1384: extern char *malloc ();
1385:
1386: /* Start it at 0, because check_newline is called at the very beginning
1387: and will increment it to 1. */
1388: lineno = 0;
1389:
1390: maxtoken = 40;
1391: token_buffer = malloc (maxtoken + 2);
1392: ridpointers[(int) RID_INT] = get_identifier ("int");
1393: ridpointers[(int) RID_CHAR] = get_identifier ("char");
1394: ridpointers[(int) RID_VOID] = get_identifier ("void");
1395: ridpointers[(int) RID_FLOAT] = get_identifier ("float");
1396: ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
1397: ridpointers[(int) RID_SHORT] = get_identifier ("short");
1398: ridpointers[(int) RID_LONG] = get_identifier ("long");
1399: ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
1400: ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
1401: ridpointers[(int) RID_INLINE] = get_identifier ("inline");
1402: ridpointers[(int) RID_CONST] = get_identifier ("const");
1403: ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
1404: ridpointers[(int) RID_AUTO] = get_identifier ("auto");
1405: ridpointers[(int) RID_STATIC] = get_identifier ("static");
1406: ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
1407: ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
1408: ridpointers[(int) RID_REGISTER] = get_identifier ("register");
1409: }
1410:
1411: static void
1412: reinit_parse_for_function ()
1413: {
1414: }
1415:
1416: /* If C is not whitespace, return C.
1417: Otherwise skip whitespace and return first nonwhite char read. */
1418:
1419: static int
1420: skip_white_space (c)
1421: register int c;
1422: {
1423: register int inside;
1424:
1425: for (;;)
1426: {
1427: switch (c)
1428: {
1429: case '/':
1430: c = getc (finput);
1431: if (c != '*')
1432: {
1433: ungetc (c, finput);
1434: return '/';
1435: }
1436:
1437: c = getc (finput);
1438:
1439: inside = 1;
1440: while (inside)
1441: {
1442: if (c == '*')
1443: {
1444: while (c == '*')
1445: c = getc (finput);
1446:
1447: if (c == '/')
1448: {
1449: inside = 0;
1450: c = getc (finput);
1451: }
1452: }
1453: else if (c == '\n')
1454: {
1455: lineno++;
1456: c = getc (finput);
1457: }
1458: else if (c == EOF)
1459: {
1460: error ("unterminated comment");
1461: break;
1462: }
1463: else
1464: c = getc (finput);
1465: }
1466:
1467: break;
1468:
1469: case '\n':
1470: c = check_newline ();
1471: break;
1472:
1473: case ' ':
1474: case '\t':
1475: case '\f':
1476: case '\r':
1477: case '\b':
1478: c = getc (finput);
1479: break;
1480:
1481: case '\\':
1482: c = getc (finput);
1483: if (c == '\n')
1484: lineno++;
1485: else
1486: error ("stray '\\' in program");
1487: c = getc (finput);
1488: break;
1489:
1490: default:
1491: return (c);
1492: }
1493: }
1494: }
1495:
1496:
1497:
1498: /* Make the token buffer longer, preserving the data in it.
1499: P should point to just beyond the last valid character in the old buffer.
1500: The value we return is a pointer to the new buffer
1501: at a place corresponding to P. */
1502:
1503: static char *
1504: extend_token_buffer (p)
1505: char *p;
1506: {
1507: int offset = p - token_buffer;
1508:
1509: maxtoken = maxtoken * 2 + 10;
1510: token_buffer = (char *) realloc (token_buffer, maxtoken + 2);
1511: if (token_buffer == 0)
1512: fatal ("virtual memory exceeded");
1513:
1514: return token_buffer + offset;
1515: }
1516:
1517: /* At the beginning of a line, increment the line number
1518: and handle a #line directive immediately following.
1519: Return first nonwhite char of first non-# line following. */
1520:
1521: int
1522: check_newline ()
1523: {
1524: register int c;
1525: register int token;
1526:
1527: while (1)
1528: {
1529: lineno++;
1530:
1531: /* Read first nonwhite char on the line. */
1532:
1533: c = getc (finput);
1534: while (c == ' ' || c == '\t')
1535: c = getc (finput);
1536:
1537: if (c != '#')
1538: {
1539: /* If not #, return it so caller will use it. */
1540: return c;
1541: }
1542:
1543: /* Read first nonwhite char after the `#'. */
1544:
1545: c = getc (finput);
1546: while (c == ' ' || c == '\t')
1547: c = getc (finput);
1548:
1549: /* If a letter follows, then if the word here is `line', skip
1550: it and ignore it; otherwise, ignore the line, with an error
1551: if the word isn't `pragma'. */
1552:
1553: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
1554: {
1555: if (c == 'p')
1556: {
1557: if (getc (finput) == 'r'
1558: && getc (finput) == 'a'
1559: && getc (finput) == 'g'
1560: && getc (finput) == 'm'
1561: && getc (finput) == 'a'
1562: && ((c = getc (finput)) == ' ' || c == '\t'))
1563: goto noerror;
1564: }
1565:
1566: else if (c == 'l')
1567: {
1568: if (getc (finput) == 'i'
1569: && getc (finput) == 'n'
1570: && getc (finput) == 'e'
1571: && ((c = getc (finput)) == ' ' || c == '\t'))
1572: goto linenum;
1573: }
1574: #ifdef IDENT_DIRECTIVE
1575: else if (c == 'i')
1576: {
1577: if (getc (finput) == 'd'
1578: && getc (finput) == 'e'
1579: && getc (finput) == 'n'
1580: && getc (finput) == 't'
1581: && ((c = getc (finput)) == ' ' || c == '\t'))
1582: {
1583: extern FILE *asm_out_file;
1584:
1585: if (pedantic)
1586: error ("ANSI C does not allow #ident");
1587:
1588: /* Here we have just seen `#ident '.
1589: A string constant should follow. */
1590:
1591: while (c == ' ' || c == '\t')
1592: c = getc (finput);
1593:
1594: /* If no argument, ignore the line. */
1595: if (c == '\n')
1596: continue;
1597:
1598: ungetc (c, finput);
1599: token = yylex ();
1600: if (token != STRING
1601: || TREE_CODE (yylval.ttype) != STRING_CST)
1602: {
1603: error ("invalid #ident");
1604: return getc (finput);
1605: }
1606:
1607: fprintf (asm_out_file, "\t.ident \"%s\"\n",
1608: TREE_STRING_POINTER (yylval.ttype));
1609:
1610: /* Skip the rest of this line. */
1611: while ((c = getc (finput)) && c != '\n');
1612: if (c == 0)
1613: return 0;
1614: continue;
1615: }
1616: }
1617: #endif
1618:
1619: error ("undefined or invalid # directive");
1620: noerror:
1621:
1622: while ((c = getc (finput)) && c != '\n');
1623:
1624: if (c == 0)
1625: return 0;
1626: continue;
1627: }
1628:
1629: linenum:
1630: /* Here we have either `#line' or `# <nonletter>'.
1631: In either case, it should be a line number; a digit should follow. */
1632:
1633: while (c == ' ' || c == '\t')
1634: c = getc (finput);
1635:
1636: /* If the # is the only nonwhite char on the line,
1637: just ignore it. Check the new newline. */
1638: if (c == '\n')
1639: continue;
1640:
1641: /* Something follows the #; read a token. */
1642:
1643: ungetc (c, finput);
1644: token = yylex ();
1645:
1646: if (token == CONSTANT
1647: && TREE_CODE (yylval.ttype) == INTEGER_CST)
1648: {
1649: /* subtract one, because it is the following line that
1650: gets the specified number */
1651:
1652: int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
1653:
1654: /* Is this the last nonwhite stuff on the line? */
1655: c = getc (finput);
1656: while (c == ' ' || c == '\t')
1657: c = getc (finput);
1658: if (c == '\n')
1659: {
1660: /* No more: store the line number and check following line. */
1661: lineno = l;
1662: continue;
1663: }
1664: ungetc (c, finput);
1665:
1666: /* More follows: it must be a string constant (filename). */
1667:
1668: token = yylex ();
1669: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1670: {
1671: error ("invalid #line");
1672: return getc (finput);
1673: }
1674:
1675: input_filename
1676: = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
1677: strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
1678: lineno = l;
1679:
1680: if (main_input_filename == 0)
1681: main_input_filename = input_filename;
1682: }
1683: else
1684: error ("invalid #line");
1685:
1686: /* skip the rest of this line. */
1687: while ((c = getc (finput)) && c != '\n');
1688: if (c == 0)
1689: return 0;
1690: }
1691: }
1692:
1693: #define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9'))
1694: #define isdigit(char) (char >= '0' && char <= '9')
1695: #define ENDFILE -1 /* token that represents end-of-file */
1696:
1697:
1698: static int
1699: readescape ()
1700: {
1701: register int c = getc (finput);
1702: register int count, code;
1703:
1704: switch (c)
1705: {
1706: case 'x':
1707: code = 0;
1708: count = 0;
1709: while (1)
1710: {
1711: c = getc (finput);
1712: if (!(c >= 'a' && c <= 'f')
1713: && !(c >= 'A' && c <= 'F')
1714: && !(c >= '0' && c <= '9'))
1715: {
1716: ungetc (c, finput);
1717: break;
1718: }
1719: code *= 16;
1720: if (c >= 'a' && c <= 'f')
1721: code += c - 'a' + 10;
1722: if (c >= 'A' && c <= 'F')
1723: code += c - 'A' + 10;
1724: if (c >= '0' && c <= '9')
1725: code += c - '0';
1726: count++;
1727: }
1728: if (count == 0)
1729: error ("\\x used with no following hex digits");
1730: return code;
1731:
1732: case '0': case '1': case '2': case '3': case '4':
1733: case '5': case '6': case '7':
1734: code = 0;
1735: count = 0;
1736: while ((c <= '7') && (c >= '0') && (count++ < 3))
1737: {
1738: code = (code * 8) + (c - '0');
1739: c = getc (finput);
1740: }
1741: ungetc (c, finput);
1742: return code;
1743:
1744: case '\\': case '\'': case '"':
1745: return c;
1746:
1747: case '\n':
1748: lineno++;
1749: return -1;
1750:
1751: case 'n':
1752: return TARGET_NEWLINE;
1753:
1754: case 't':
1755: return TARGET_TAB;
1756:
1757: case 'r':
1758: return TARGET_CR;
1759:
1760: case 'f':
1761: return TARGET_FF;
1762:
1763: case 'b':
1764: return TARGET_BS;
1765:
1766: case 'a':
1767: return TARGET_BELL;
1768:
1769: case 'v':
1770: return TARGET_VT;
1771:
1772: case 'E':
1773: return 033;
1774:
1775: case '?':
1.1.1.3 root 1776: /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
1.1.1.2 root 1777: case '(':
1.1.1.3 root 1778: case '{':
1779: case '[':
1.1 root 1780: return c;
1781: }
1782: if (c >= 040 && c <= 0177)
1783: warning ("unknown escape sequence `\\%c'", c);
1784: else
1785: warning ("unknown escape sequence: `\\' followed by char code 0x%x", c);
1786: return c;
1787: }
1788:
1789: void
1790: yyerror (string)
1791: char *string;
1792: {
1793: char buf[200];
1794:
1795: strcpy (buf, string);
1796:
1797: /* We can't print string and character constants well
1798: because the token_buffer contains the result of processing escapes. */
1799: if (token_buffer[0] == 0)
1800: strcat (buf, " at end of input");
1801: else if (token_buffer[0] == '"')
1802: strcat (buf, " before string constant");
1803: else if (token_buffer[0] == '\'')
1804: strcat (buf, " before character constant");
1805: else
1806: strcat (buf, " before `%s'");
1807:
1808: error (buf, token_buffer);
1809: }
1810:
1811: static int nextchar = -1;
1812:
1813: static int
1814: yylex ()
1815: {
1816: register int c;
1817: register char *p;
1818: register int value;
1819: int wide_flag = 0;
1820:
1821: if (nextchar >= 0)
1822: c = nextchar, nextchar = -1;
1823: else
1824: c = getc (finput);
1825:
1826: /* Effectively do c = skip_white_space (c)
1827: but do it faster in the usual cases. */
1828: while (1)
1829: switch (c)
1830: {
1831: case ' ':
1832: case '\t':
1833: case '\f':
1834: case '\r':
1835: case '\b':
1836: c = getc (finput);
1837: break;
1838:
1839: case '\n':
1840: case '/':
1841: case '\\':
1842: c = skip_white_space (c);
1843: default:
1844: goto found_nonwhite;
1845: }
1846: found_nonwhite:
1847:
1848: token_buffer[0] = c;
1849: token_buffer[1] = 0;
1850:
1851: /* yylloc.first_line = lineno; */
1852:
1853: switch (c)
1854: {
1855: case EOF:
1856: token_buffer[0] = 0;
1857: value = ENDFILE;
1858: break;
1859:
1860: case '$':
1861: if (dollars_in_ident)
1862: goto letter;
1863: return '$';
1864:
1865: case 'L':
1866: /* Capital L may start a wide-string or wide-character constant. */
1867: {
1868: register int c = getc (finput);
1869: if (c == '\'')
1870: {
1871: wide_flag = 1;
1872: goto char_constant;
1873: }
1874: if (c == '"')
1875: {
1876: wide_flag = 1;
1877: goto string_constant;
1878: }
1879: ungetc (c, finput);
1880: }
1881:
1882: case 'A': case 'B': case 'C': case 'D': case 'E':
1883: case 'F': case 'G': case 'H': case 'I': case 'J':
1884: case 'K': case 'M': case 'N': case 'O':
1885: case 'P': case 'Q': case 'R': case 'S': case 'T':
1886: case 'U': case 'V': case 'W': case 'X': case 'Y':
1887: case 'Z':
1888: case 'a': case 'b': case 'c': case 'd': case 'e':
1889: case 'f': case 'g': case 'h': case 'i': case 'j':
1890: case 'k': case 'l': case 'm': case 'n': case 'o':
1891: case 'p': case 'q': case 'r': case 's': case 't':
1892: case 'u': case 'v': case 'w': case 'x': case 'y':
1893: case 'z':
1894: case '_':
1895: letter:
1896: p = token_buffer;
1897: while (isalnum (c) || c == '_' || c == '$')
1898: {
1899: if (p >= token_buffer + maxtoken)
1900: p = extend_token_buffer (p);
1901: if (c == '$' && ! dollars_in_ident)
1902: break;
1903:
1904: *p++ = c;
1905: c = getc (finput);
1906: }
1907:
1908: *p = 0;
1909: nextchar = c;
1910:
1911: value = IDENTIFIER;
1912: yylval.itype = 0;
1913:
1.1.1.4 ! root 1914: /* Try to recognize a keyword. Uses minimum-perfect hash function */
! 1915:
! 1916: {
! 1917: register struct resword *ptr;
1.1 root 1918:
1.1.1.4 ! root 1919: if (ptr = is_reserved_word (token_buffer, p - token_buffer))
! 1920: {
! 1921: if (ptr->rid)
! 1922: yylval.ttype = ridpointers[(int) ptr->rid];
! 1923: if ((! flag_no_asm
! 1924: /* -fno-asm means don't recognize the non-ANSI keywords. */
! 1925: || ((int) ptr->token != ASM
! 1926: && (int) ptr->token != TYPEOF
! 1927: && ptr->rid != RID_INLINE))
! 1928: /* -ftraditional means don't recognize nontraditional keywords
! 1929: typeof, const, volatile, signed or inline. */
! 1930: && (! flag_traditional
! 1931: || ((int) ptr->token != TYPE_QUAL
! 1932: && (int) ptr->token != TYPEOF
! 1933: && ptr->rid != RID_SIGNED
! 1934: && ptr->rid != RID_INLINE)))
! 1935: value = (int) ptr->token;
! 1936: }
! 1937: }
1.1 root 1938:
1939: /* If we did not find a keyword, look for an identifier
1940: (or a typename). */
1941:
1942: if (value == IDENTIFIER)
1943: {
1944: yylval.ttype = get_identifier (token_buffer);
1945: lastiddecl = lookup_name (yylval.ttype);
1946:
1947: if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL)
1948: value = TYPENAME;
1949: }
1950:
1951: break;
1952:
1953: case '0': case '1': case '2': case '3': case '4':
1954: case '5': case '6': case '7': case '8': case '9':
1955: case '.':
1956: {
1957: int base = 10;
1958: int count = 0;
1959: int largest_digit = 0;
1960: int numdigits = 0;
1961: /* for multi-precision arithmetic,
1962: we store only 8 live bits in each short,
1963: giving us 64 bits of reliable precision */
1964: short shorts[8];
1.1.1.3 root 1965:
1966: enum { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
1967: = NOT_FLOAT;
1.1 root 1968:
1969: for (count = 0; count < 8; count++)
1970: shorts[count] = 0;
1971:
1972: p = token_buffer;
1973: *p++ = c;
1974:
1975: if (c == '0')
1976: {
1977: *p++ = (c = getc (finput));
1978: if ((c == 'x') || (c == 'X'))
1979: {
1980: base = 16;
1981: *p++ = (c = getc (finput));
1982: }
1983: else
1984: {
1985: base = 8;
1986: numdigits++;
1987: }
1988: }
1989:
1990: /* Read all the digits-and-decimal-points. */
1991:
1992: while (c == '.'
1993: || (isalnum (c) && (c != 'l') && (c != 'L')
1994: && (c != 'u') && (c != 'U')
1.1.1.3 root 1995: && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
1.1 root 1996: {
1997: if (c == '.')
1998: {
1999: if (base == 16)
2000: error ("floating constant may not be in radix 16");
1.1.1.3 root 2001: if (floatflag == AFTER_POINT)
2002: {
2003: error ("malformed floating constant");
2004: floatflag = TOO_MANY_POINTS;
2005: }
2006: else
2007: floatflag = AFTER_POINT;
2008:
1.1 root 2009: base = 10;
2010: *p++ = c = getc (finput);
2011: /* Accept '.' as the start of a floating-point number
2012: only when it is followed by a digit.
2013: Otherwise, unread the following non-digit
2014: and use the '.' as a structural token. */
2015: if (p == token_buffer + 2 && !isdigit (c))
2016: {
2017: if (c == '.')
2018: {
2019: c = getc (finput);
2020: if (c == '.')
2021: {
2022: *p++ = c;
2023: *p = 0;
2024: return ELLIPSIS;
2025: }
2026: error ("parse error at `..'");
2027: }
2028: ungetc (c, finput);
2029: token_buffer[1] = 0;
2030: value = '.';
2031: goto done;
2032: }
2033: }
2034: else
2035: {
2036: /* It is not a decimal point.
2037: It should be a digit (perhaps a hex digit). */
2038:
2039: if (isdigit (c))
2040: {
2041: c = c - '0';
2042: }
2043: else if (base <= 10)
2044: {
2045: if ((c&~040) == 'E')
2046: {
2047: base = 10;
1.1.1.3 root 2048: floatflag = AFTER_POINT;
1.1 root 2049: break; /* start of exponent */
2050: }
2051: error ("nondigits in number and not hexadecimal");
2052: c = 0;
2053: }
2054: else if (c >= 'a')
2055: {
2056: c = c - 'a' + 10;
2057: }
2058: else
2059: {
2060: c = c - 'A' + 10;
2061: }
2062: if (c >= largest_digit)
2063: largest_digit = c;
2064: numdigits++;
2065:
2066: for (count = 0; count < 8; count++)
2067: {
2068: (shorts[count] *= base);
2069: if (count)
2070: {
2071: shorts[count] += (shorts[count-1] >> 8);
2072: shorts[count-1] &= (1<<8)-1;
2073: }
2074: else shorts[0] += c;
2075: }
2076:
2077: if (p >= token_buffer + maxtoken - 3)
2078: p = extend_token_buffer (p);
2079: *p++ = (c = getc (finput));
2080: }
2081: }
2082:
2083: if (numdigits == 0)
2084: error ("numeric constant with no digits");
2085:
2086: if (largest_digit >= base)
2087: error ("numeric constant contains digits beyond the radix");
2088:
2089: /* Remove terminating char from the token buffer and delimit the string */
2090: *--p = 0;
2091:
1.1.1.3 root 2092: if (floatflag != NOT_FLOAT)
1.1 root 2093: {
2094: tree type = double_type_node;
2095: char f_seen = 0;
2096: char l_seen = 0;
2097: double value;
2098:
2099: /* Read explicit exponent if any, and put it in tokenbuf. */
2100:
2101: if ((c == 'e') || (c == 'E'))
2102: {
2103: if (p >= token_buffer + maxtoken - 3)
2104: p = extend_token_buffer (p);
2105: *p++ = c;
2106: c = getc (finput);
2107: if ((c == '+') || (c == '-'))
2108: {
2109: *p++ = c;
2110: c = getc (finput);
2111: }
2112: if (! isdigit (c))
2113: error ("floating constant exponent has no digits");
2114: while (isdigit (c))
2115: {
2116: if (p >= token_buffer + maxtoken - 3)
2117: p = extend_token_buffer (p);
2118: *p++ = c;
2119: c = getc (finput);
2120: }
2121: }
2122:
2123: *p = 0;
2124: errno = 0;
2125: value = atof (token_buffer);
2126: #ifdef ERANGE
2127: if (errno == ERANGE && !flag_traditional)
1.1.1.2 root 2128: warning ("floating point number exceeds range of `double'");
1.1 root 2129: #endif
2130:
2131: /* Read the suffixes to choose a data type. */
2132: while (1)
2133: {
2134: if (c == 'f' || c == 'F')
2135: {
2136: if (f_seen)
2137: error ("two `f's in floating constant");
2138: f_seen = 1;
2139: type = float_type_node;
2140: }
2141: else if (c == 'l' || c == 'L')
2142: {
2143: if (l_seen)
2144: error ("two `l's in floating constant");
2145: l_seen = 1;
2146: type = long_double_type_node;
2147: }
2148: else
2149: {
2150: if (isalnum (c))
2151: {
2152: error ("garbage at end of number");
2153: while (isalnum (c))
2154: {
2155: if (p >= token_buffer + maxtoken - 3)
2156: p = extend_token_buffer (p);
2157: *p++ = c;
2158: c = getc (finput);
2159: }
2160: }
2161: break;
2162: }
2163: if (p >= token_buffer + maxtoken - 3)
2164: p = extend_token_buffer (p);
2165: *p++ = c;
2166: c = getc (finput);
2167: }
2168:
2169: /* Create a node with determined type and value. */
2170: yylval.ttype = build_real (type, value);
2171:
2172: ungetc (c, finput);
2173: *p = 0;
2174: }
2175: else
2176: {
2177: tree type;
2178: int spec_unsigned = 0;
2179: int spec_long = 0;
2180:
2181: while (1)
2182: {
2183: if (c == 'u' || c == 'U')
2184: {
2185: if (spec_unsigned)
2186: error ("two `u's in integer constant");
2187: spec_unsigned = 1;
2188: }
2189: else if (c == 'l' || c == 'L')
2190: {
2191: if (spec_long)
2192: error ("two `l's in integer constant");
2193: spec_long = 1;
2194: }
2195: else
2196: {
2197: if (isalnum (c))
2198: {
2199: error ("garbage at end of number");
2200: while (isalnum (c))
2201: {
2202: if (p >= token_buffer + maxtoken - 3)
2203: p = extend_token_buffer (p);
2204: *p++ = c;
2205: c = getc (finput);
2206: }
2207: }
2208: break;
2209: }
2210: if (p >= token_buffer + maxtoken - 3)
2211: p = extend_token_buffer (p);
2212: *p++ = c;
2213: c = getc (finput);
2214: }
2215:
2216: ungetc (c, finput);
2217:
2218: if (shorts[7] | shorts[6] | shorts[5] | shorts[4])
2219: warning ("integer constant out of range");
2220:
2221: /* This is simplified by the fact that our constant
2222: is always positive. */
2223: yylval.ttype
2224: = build_int_2 ((shorts[3]<<24) + (shorts[2]<<16) + (shorts[1]<<8) + shorts[0],
2225: 0);
2226:
2227: if (!spec_long && !spec_unsigned
2228: && int_fits_type_p (yylval.ttype, integer_type_node))
2229: type = integer_type_node;
2230:
2231: else if (!spec_long && base != 10
2232: && int_fits_type_p (yylval.ttype, unsigned_type_node))
2233: type = unsigned_type_node;
2234:
2235: else if (!spec_unsigned
2236: && int_fits_type_p (yylval.ttype, long_integer_type_node))
2237: type = long_integer_type_node;
2238:
2239: else
2240: {
2241: type = long_unsigned_type_node;
2242: if (! int_fits_type_p (yylval.ttype, long_unsigned_type_node))
2243: warning ("integer constant out of range");
2244: }
2245: TREE_TYPE (yylval.ttype) = type;
2246: }
2247:
2248: value = CONSTANT; break;
2249: }
2250:
2251: case '\'':
2252: char_constant:
2253: c = getc (finput);
2254: {
2255: register int code = 0;
2256:
2257: tryagain:
2258:
2259: if (c == '\\')
2260: {
2261: c = readescape ();
2262: if (c < 0)
2263: goto tryagain;
2264: }
2265: else if (c == '\n')
2266: {
2267: if (pedantic)
2268: warning ("ANSI C forbids newline in character constant");
2269: lineno++;
2270: }
2271:
2272: code = c;
2273: token_buffer[1] = c;
2274: token_buffer[2] = '\'';
2275: token_buffer[3] = 0;
2276:
2277: c = getc (finput);
2278: if (c != '\'')
2279: error ("malformatted character constant");
2280:
2281: /* If char type is signed, sign-extend the constant. */
2282: if (TREE_UNSIGNED (char_type_node)
2283: || ((code >> (BITS_PER_UNIT - 1)) & 1) == 0)
2284: yylval.ttype = build_int_2 (code & ((1 << BITS_PER_UNIT) - 1), 0);
2285: else
2286: yylval.ttype = build_int_2 (code | ((-1) << BITS_PER_UNIT), -1);
2287:
2288: TREE_TYPE (yylval.ttype) = integer_type_node;
2289: value = CONSTANT; break;
2290: }
2291:
2292: case '"':
2293: string_constant:
2294: {
2295: c = getc (finput);
2296: p = token_buffer + 1;
2297:
2298: while (c != '"')
2299: {
2300: if (c == '\\')
2301: {
2302: c = readescape ();
2303: if (c < 0)
2304: goto skipnewline;
2305: }
2306: else if (c == '\n')
2307: {
2308: if (pedantic)
2309: warning ("ANSI C forbids newline in string constant");
2310: lineno++;
2311: }
2312:
2313: if (p == token_buffer + maxtoken)
2314: p = extend_token_buffer (p);
2315: *p++ = c;
2316:
2317: skipnewline:
2318: c = getc (finput);
2319: }
2320:
2321: *p = 0;
2322:
2323: if (wide_flag)
2324: {
2325: /* If this is a L"..." wide-string, convert each char
2326: to an int, making a vector of ints. */
2327: int *widebuf = (int *) alloca (p - token_buffer);
2328: char *p1 = token_buffer + 1;
2329: for (; p1 != p; p1++)
2330: widebuf[p1 - token_buffer - 1] = *p1;
2331: yylval.ttype = build_string ((p - token_buffer) * sizeof (int),
2332: widebuf);
2333: TREE_TYPE (yylval.ttype) = int_array_type_node;
2334: }
2335: else
2336: {
2337: yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
2338: TREE_TYPE (yylval.ttype) = char_array_type_node;
2339: }
2340:
2341: *p++ = '"';
2342: *p = 0;
2343:
2344: value = STRING; break;
2345: }
2346:
2347: case '+':
2348: case '-':
2349: case '&':
2350: case '|':
2351: case '<':
2352: case '>':
2353: case '*':
2354: case '/':
2355: case '%':
2356: case '^':
2357: case '!':
2358: case '=':
2359: {
2360: register int c1;
2361:
2362: combine:
2363:
2364: switch (c)
2365: {
2366: case '+':
2367: yylval.code = PLUS_EXPR; break;
2368: case '-':
2369: yylval.code = MINUS_EXPR; break;
2370: case '&':
2371: yylval.code = BIT_AND_EXPR; break;
2372: case '|':
2373: yylval.code = BIT_IOR_EXPR; break;
2374: case '*':
2375: yylval.code = MULT_EXPR; break;
2376: case '/':
2377: yylval.code = TRUNC_DIV_EXPR; break;
2378: case '%':
2379: yylval.code = TRUNC_MOD_EXPR; break;
2380: case '^':
2381: yylval.code = BIT_XOR_EXPR; break;
2382: case LSHIFT:
2383: yylval.code = LSHIFT_EXPR; break;
2384: case RSHIFT:
2385: yylval.code = RSHIFT_EXPR; break;
2386: case '<':
2387: yylval.code = LT_EXPR; break;
2388: case '>':
2389: yylval.code = GT_EXPR; break;
2390: }
2391:
2392: token_buffer[1] = c1 = getc (finput);
2393: token_buffer[2] = 0;
2394:
2395: if (c1 == '=')
2396: {
2397: switch (c)
2398: {
2399: case '<':
2400: value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
2401: case '>':
2402: value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
2403: case '!':
2404: value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
2405: case '=':
2406: value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
2407: }
2408: value = ASSIGN; goto done;
2409: }
2410: else if (c == c1)
2411: switch (c)
2412: {
2413: case '+':
2414: value = PLUSPLUS; goto done;
2415: case '-':
2416: value = MINUSMINUS; goto done;
2417: case '&':
2418: value = ANDAND; goto done;
2419: case '|':
2420: value = OROR; goto done;
2421: case '<':
2422: c = LSHIFT;
2423: goto combine;
2424: case '>':
2425: c = RSHIFT;
2426: goto combine;
2427: }
2428: else if ((c == '-') && (c1 == '>'))
2429: { value = POINTSAT; goto done; }
2430: ungetc (c1, finput);
2431: token_buffer[1] = 0;
2432:
2433: if ((c == '<') || (c == '>'))
2434: value = ARITHCOMPARE;
2435: else value = c;
2436: goto done;
2437: }
2438:
2439: default:
2440: value = c;
2441: }
2442:
2443: done:
2444: /* yylloc.last_line = lineno; */
2445:
2446: return value;
2447: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.