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