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