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