|
|
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: {
1367: int len = TREE_STRING_LENGTH (t) - 1;
1368: if ((TREE_TYPE (t) == int_array_type_node) == wide_flag)
1369: {
1370: bcopy (TREE_STRING_POINTER (t), q, len);
1371: q += len;
1372: }
1373: else
1374: {
1375: int i;
1376: for (i = 0; i < len; i++)
1377: ((int *) q)[i] = TREE_STRING_POINTER (t)[i];
1378: q += len * UNITS_PER_WORD;
1379: }
1380: }
1381: *q = 0;
1382:
1383: value = make_node (STRING_CST);
1384: TREE_STRING_POINTER (value) = p;
1385: TREE_STRING_LENGTH (value) = length;
1386: TREE_LITERAL (value) = 1;
1387: }
1388: else
1389: {
1390: value = strings;
1391: length = TREE_STRING_LENGTH (value);
1392: if (TREE_TYPE (value) == int_array_type_node)
1393: wide_flag = 1;
1394: }
1395:
1.1.1.13! root 1396: /* Compute the number of elements, for the array type. */
! 1397: nchars = wide_flag ? length / UNITS_PER_WORD : length;
! 1398:
1.1.1.3 root 1399: /* Create the array type for the string constant.
1400: -Wwrite-strings says make the string constant an array of const char
1401: so that copying it to a non-const pointer will get a warning. */
1402: if (warn_write_strings)
1403: {
1404: tree elements
1405: = build_type_variant (wide_flag ? integer_type_node : char_type_node,
1406: 1, 0);
1407: TREE_TYPE (value)
1408: = build_array_type (elements,
1.1.1.13! root 1409: build_index_type (build_int_2 (nchars - 1, 0)));
1.1.1.3 root 1410: }
1411: else
1412: TREE_TYPE (value)
1413: = build_array_type (wide_flag ? integer_type_node : char_type_node,
1.1.1.13! root 1414: build_index_type (build_int_2 (nchars - 1, 0)));
1.1 root 1415: TREE_LITERAL (value) = 1;
1416: TREE_STATIC (value) = 1;
1417: return value;
1418: }
1419:
1420: FILE *finput; /* input file.
1421: Normally a pipe from the preprocessor. */
1422:
1423: /* lexical analyzer */
1424:
1.1.1.7 root 1425: static int maxtoken; /* Current nominal length of token buffer. */
1.1 root 1426: static char *token_buffer; /* Pointer to token buffer.
1427: Actual allocated length is maxtoken + 2. */
1.1.1.7 root 1428: static int max_wide; /* Current nominal length of wide_buffer. */
1429: static int *wide_buffer; /* Pointer to wide-string buffer.
1430: Actual allocated length is max_wide + 1. */
1431:
1432: /* Nonzero if end-of-file has been seen on input. */
1.1.1.5 root 1433: static int end_of_file;
1.1 root 1434:
1.1.1.9 root 1435: /* Data type that represents the GNU C reserved words. */
1436: struct resword { char *name; short token; enum rid rid; };
1.1 root 1437:
1.1.1.9 root 1438: #define MIN_WORD_LENGTH 2 /* minimum size for C keyword */
1.1.1.11 root 1439: #define MAX_WORD_LENGTH 13 /* maximum size for C keyword */
1440: #define MIN_HASH_VALUE 7 /* range of the hash keys values */
1441: #define MAX_HASH_VALUE 91 /* for the perfect hash generator */
1.1 root 1442: #define NORID RID_UNUSED
1443:
1.1.1.4 root 1444: /* This function performs the minimum-perfect hash mapping from input
1.1.1.11 root 1445: string to reswords table index. It only looks at the first and
1446: last characters in the string, thus assuring the O(1) lookup time
1.1.1.4 root 1447: (this keeps our constant down to an insignificant amount!). Compiling
1448: the following 2 functions as inline removes all overhead of the
1449: function calls. */
1450:
1451: #ifdef __GNUC__
1.1.1.11 root 1452: __inline
1.1.1.4 root 1453: #endif
1.1.1.11 root 1454: static int
1.1.1.4 root 1455: hash (str, len)
1.1.1.10 root 1456: register char *str;
1457: register int len;
1.1.1.4 root 1458: {
1.1.1.9 root 1459: /* This table is used to build the hash table index that recognizes
1.1.1.11 root 1460: reserved words in 0(1) steps. It is larger than strictly necessary,
1461: but I'm trading off the space for the time-saving luxury of avoiding
1462: subtraction of an offset. All those ``91's'' (actually just a
1463: short-hand for MAX_HASH_VALUE #defined above) are used to speed up
1464: the search when the string found on the input stream doesn't have a
1465: first or last character that is part of the set of alphabetic
1466: characters that comprise the first or last characters in C
1.1.1.9 root 1467: reserved words. */
1.1.1.4 root 1468:
1.1.1.11 root 1469: static int hash_table[] =
1.1.1.9 root 1470: {
1.1.1.11 root 1471: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1472: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1473: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1474: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1475: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1476: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1477: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1478: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1479: 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
1480: 91, 91, 91, 91, 91, 1, 91, 2, 1, 32,
1481: 7, 5, 18, 20, 1, 17, 91, 1, 18, 1,
1482: 28, 1, 23, 91, 12, 20, 1, 41, 7, 15,
1483: 91, 91, 10, 91, 91, 91, 91, 91,
1.1.1.9 root 1484: };
1.1.1.11 root 1485: register int hval = len ;
1.1.1.9 root 1486:
1.1.1.11 root 1487: switch (hval)
1488: {
1489: default:
1490: case 3:
1491: hval += hash_table[str[2]];
1492: case 2:
1493: case 1:
1494: return hval + hash_table[str[0]] + hash_table[str[len - 1]];
1495: }
1.1.1.4 root 1496: }
1497:
1.1.1.9 root 1498: /* This routine attempts to match the string found in the reswords table
1.1.1.11 root 1499: with the one from the input stream. If all the relevant details
1.1.1.9 root 1500: match then an actual strcmp comparison is performed and the address of
1.1.1.11 root 1501: correct struct resword entry is returned. Otherwise, a NULL
1.1.1.9 root 1502: pointer is returned. */
1.1.1.4 root 1503:
1504: #ifdef __GNUC__
1.1.1.11 root 1505: __inline
1.1.1.4 root 1506: #endif
1.1.1.10 root 1507: struct resword *
1.1.1.9 root 1508: is_reserved_word (str, len)
1.1.1.10 root 1509: register char *str;
1510: register int len;
1.1.1.4 root 1511: {
1.1.1.10 root 1512: /* This is the hash table of keywords.
1513: The order of keywords has been chosen for perfect hashing.
1514: Therefore, this table cannot be updated by hand.
1.1.1.11 root 1515: Use the program ``gperf,'' available with the latest libg++
1516: distribution, to generate an updated table. A file called
1517: c-parse.gperf, distributed with GNU C, contains the keyword file. */
1.1.1.9 root 1518:
1.1.1.11 root 1519: static struct resword reswords[] =
1.1.1.9 root 1520: {
1.1.1.11 root 1521: { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", },
1522: {"asm", ASM, NORID },
1523: {"auto", SCSPEC, RID_AUTO },
1524: {"__asm", ASM, NORID },
1525: {"do", DO, NORID },
1526: {"__asm__", ASM, NORID },
1527: {"break", BREAK, NORID },
1528: {"__typeof__", TYPEOF, NORID },
1529: { "", },
1530: {"__alignof__", ALIGNOF, NORID },
1531: { "", },
1532: {"__attribute__", ATTRIBUTE, NORID },
1533: { "", },
1534: {"__attribute", ATTRIBUTE, NORID },
1535: { "", },
1536: {"__volatile__", TYPE_QUAL, RID_VOLATILE },
1537: {"int", TYPESPEC, RID_INT },
1538: {"__volatile", TYPE_QUAL, RID_VOLATILE },
1539: { "", },
1540: {"float", TYPESPEC, RID_FLOAT },
1541: {"goto", GOTO, NORID },
1542: {"short", TYPESPEC, RID_SHORT },
1543: {"__typeof", TYPEOF, NORID },
1544: {"__inline__", SCSPEC, RID_INLINE },
1545: {"__alignof", ALIGNOF, NORID },
1546: {"__inline", SCSPEC, RID_INLINE },
1547: {"__signed__", TYPESPEC, RID_SIGNED },
1548: {"default", DEFAULT, NORID },
1549: {"else", ELSE, NORID },
1550: {"void", TYPESPEC, RID_VOID },
1551: {"__signed", TYPESPEC, RID_SIGNED },
1552: {"if", IF, NORID },
1553: {"volatile", TYPE_QUAL, RID_VOLATILE },
1554: {"struct", STRUCT, NORID },
1555: {"extern", SCSPEC, RID_EXTERN },
1556: {"__const", TYPE_QUAL, RID_CONST },
1557: {"while", WHILE, NORID },
1558: {"__const__", TYPE_QUAL, RID_CONST },
1559: {"switch", SWITCH, NORID },
1560: {"for", FOR, NORID },
1561: {"inline", SCSPEC, RID_INLINE },
1562: {"return", RETURN, NORID },
1563: {"typeof", TYPEOF, NORID },
1564: {"typedef", SCSPEC, RID_TYPEDEF },
1565: {"char", TYPESPEC, RID_CHAR },
1566: {"enum", ENUM, NORID },
1567: {"register", SCSPEC, RID_REGISTER },
1568: {"signed", TYPESPEC, RID_SIGNED },
1569: {"sizeof", SIZEOF, NORID },
1570: { "", }, { "", }, { "", }, { "", },
1571: {"double", TYPESPEC, RID_DOUBLE },
1572: {"static", SCSPEC, RID_STATIC },
1573: {"case", CASE, NORID },
1574: { "", }, { "", }, { "", }, { "", },
1575: {"const", TYPE_QUAL, RID_CONST },
1576: { "", }, { "", }, { "", },
1577: {"long", TYPESPEC, RID_LONG },
1578: { "", }, { "", },
1579: {"continue", CONTINUE, NORID },
1580: { "", }, { "", },
1581: {"unsigned", TYPESPEC, RID_UNSIGNED },
1582: { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", },
1583: { "", }, { "", }, { "", }, { "", }, { "", },
1584: {"union", UNION, NORID },
1.1.1.9 root 1585: };
1586:
1.1.1.11 root 1587: if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1.1.1.4 root 1588: {
1589: register int key = hash (str, len);
1590:
1.1.1.11 root 1591: if (key <= MAX_HASH_VALUE)
1.1.1.9 root 1592: {
1593: register char *s = reswords[key].name;
1594:
1.1.1.11 root 1595: if (*s == *str && !strcmp (str + 1, s + 1))
1.1.1.9 root 1596: return &reswords[key];
1597: }
1.1.1.4 root 1598: }
1.1.1.9 root 1599: return 0;
1.1.1.4 root 1600: }
1.1 root 1601:
1.1.1.9 root 1602: /* The elements of `ridpointers' are identifier nodes
1603: for the reserved type names and storage classes.
1604: It is indexed by a RID_... value. */
1605:
1606: tree ridpointers[(int) RID_MAX];
1607:
1608: int check_newline ();
1609:
1.1 root 1610: void
1611: init_lex ()
1612: {
1613: /* Start it at 0, because check_newline is called at the very beginning
1614: and will increment it to 1. */
1615: lineno = 0;
1616:
1617: maxtoken = 40;
1.1.1.7 root 1618: token_buffer = (char *) xmalloc (maxtoken + 2);
1619: max_wide = 40;
1620: wide_buffer = (int *) xmalloc (max_wide + 1);
1621:
1.1 root 1622: ridpointers[(int) RID_INT] = get_identifier ("int");
1623: ridpointers[(int) RID_CHAR] = get_identifier ("char");
1624: ridpointers[(int) RID_VOID] = get_identifier ("void");
1625: ridpointers[(int) RID_FLOAT] = get_identifier ("float");
1626: ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
1627: ridpointers[(int) RID_SHORT] = get_identifier ("short");
1628: ridpointers[(int) RID_LONG] = get_identifier ("long");
1629: ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
1630: ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
1631: ridpointers[(int) RID_INLINE] = get_identifier ("inline");
1632: ridpointers[(int) RID_CONST] = get_identifier ("const");
1633: ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
1634: ridpointers[(int) RID_AUTO] = get_identifier ("auto");
1635: ridpointers[(int) RID_STATIC] = get_identifier ("static");
1636: ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
1637: ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
1638: ridpointers[(int) RID_REGISTER] = get_identifier ("register");
1639: }
1640:
1641: static void
1642: reinit_parse_for_function ()
1643: {
1644: }
1645:
1646: /* If C is not whitespace, return C.
1647: Otherwise skip whitespace and return first nonwhite char read. */
1648:
1649: static int
1650: skip_white_space (c)
1651: register int c;
1652: {
1.1.1.7 root 1653: #if 0
1.1 root 1654: register int inside;
1.1.1.7 root 1655: #endif
1.1 root 1656:
1657: for (;;)
1658: {
1659: switch (c)
1660: {
1.1.1.6 root 1661: /* Don't recognize comments in cc1: all comments are removed by cpp,
1662: and cpp output can include / and * consecutively as operators. */
1663: #if 0
1.1 root 1664: case '/':
1665: c = getc (finput);
1666: if (c != '*')
1667: {
1668: ungetc (c, finput);
1669: return '/';
1670: }
1671:
1672: c = getc (finput);
1673:
1674: inside = 1;
1675: while (inside)
1676: {
1677: if (c == '*')
1678: {
1679: while (c == '*')
1680: c = getc (finput);
1681:
1682: if (c == '/')
1683: {
1684: inside = 0;
1685: c = getc (finput);
1686: }
1687: }
1688: else if (c == '\n')
1689: {
1690: lineno++;
1691: c = getc (finput);
1692: }
1693: else if (c == EOF)
1694: {
1695: error ("unterminated comment");
1696: break;
1697: }
1698: else
1699: c = getc (finput);
1700: }
1701:
1702: break;
1.1.1.6 root 1703: #endif
1.1 root 1704:
1705: case '\n':
1706: c = check_newline ();
1707: break;
1708:
1709: case ' ':
1710: case '\t':
1711: case '\f':
1712: case '\r':
1.1.1.11 root 1713: case '\v':
1.1 root 1714: case '\b':
1715: c = getc (finput);
1716: break;
1717:
1718: case '\\':
1719: c = getc (finput);
1720: if (c == '\n')
1721: lineno++;
1722: else
1723: error ("stray '\\' in program");
1724: c = getc (finput);
1725: break;
1726:
1727: default:
1728: return (c);
1729: }
1730: }
1731: }
1732:
1733:
1734:
1735: /* Make the token buffer longer, preserving the data in it.
1736: P should point to just beyond the last valid character in the old buffer.
1737: The value we return is a pointer to the new buffer
1738: at a place corresponding to P. */
1739:
1740: static char *
1741: extend_token_buffer (p)
1742: char *p;
1743: {
1744: int offset = p - token_buffer;
1745:
1746: maxtoken = maxtoken * 2 + 10;
1.1.1.7 root 1747: token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
1.1 root 1748:
1749: return token_buffer + offset;
1750: }
1751:
1752: /* At the beginning of a line, increment the line number
1.1.1.8 root 1753: and process any #-directive on this line.
1754: If the line is a #-directive, read the entire line and return a newline.
1755: Otherwise, return the line's first non-whitespace character. */
1.1 root 1756:
1757: int
1758: check_newline ()
1759: {
1760: register int c;
1761: register int token;
1762:
1.1.1.8 root 1763: lineno++;
1.1 root 1764:
1.1.1.8 root 1765: /* Read first nonwhite char on the line. */
1.1 root 1766:
1.1.1.8 root 1767: c = getc (finput);
1768: while (c == ' ' || c == '\t')
1769: c = getc (finput);
1.1 root 1770:
1.1.1.8 root 1771: if (c != '#')
1772: {
1773: /* If not #, return it so caller will use it. */
1774: return c;
1775: }
1.1 root 1776:
1.1.1.8 root 1777: /* Read first nonwhite char after the `#'. */
1.1 root 1778:
1.1.1.8 root 1779: c = getc (finput);
1780: while (c == ' ' || c == '\t')
1781: c = getc (finput);
1.1 root 1782:
1.1.1.8 root 1783: /* If a letter follows, then if the word here is `line', skip
1784: it and ignore it; otherwise, ignore the line, with an error
1785: if the word isn't `pragma'. */
1.1 root 1786:
1.1.1.8 root 1787: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
1788: {
1789: if (c == 'p')
1.1 root 1790: {
1.1.1.8 root 1791: if (getc (finput) == 'r'
1792: && getc (finput) == 'a'
1793: && getc (finput) == 'g'
1794: && getc (finput) == 'm'
1795: && getc (finput) == 'a'
1.1.1.10 root 1796: && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
1.1.1.8 root 1797: goto skipline;
1798: }
1.1 root 1799:
1.1.1.8 root 1800: else if (c == 'l')
1801: {
1802: if (getc (finput) == 'i'
1803: && getc (finput) == 'n'
1804: && getc (finput) == 'e'
1805: && ((c = getc (finput)) == ' ' || c == '\t'))
1806: goto linenum;
1807: }
1808: else if (c == 'i')
1809: {
1810: if (getc (finput) == 'd'
1811: && getc (finput) == 'e'
1812: && getc (finput) == 'n'
1813: && getc (finput) == 't'
1814: && ((c = getc (finput)) == ' ' || c == '\t'))
1.1 root 1815: {
1.1.1.8 root 1816: extern FILE *asm_out_file;
1.1 root 1817:
1.1.1.8 root 1818: if (pedantic)
1819: error ("ANSI C does not allow #ident");
1.1 root 1820:
1.1.1.8 root 1821: /* Here we have just seen `#ident '.
1822: A string constant should follow. */
1.1 root 1823:
1.1.1.8 root 1824: while (c == ' ' || c == '\t')
1825: c = getc (finput);
1.1 root 1826:
1.1.1.8 root 1827: /* If no argument, ignore the line. */
1828: if (c == '\n')
1829: return c;
1830:
1831: ungetc (c, finput);
1832: token = yylex ();
1833: if (token != STRING
1834: || TREE_CODE (yylval.ttype) != STRING_CST)
1835: {
1836: error ("invalid #ident");
1837: goto skipline;
1838: }
1.1 root 1839:
1.1.1.5 root 1840: #ifdef ASM_OUTPUT_IDENT
1.1.1.8 root 1841: ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype));
1.1.1.5 root 1842: #endif
1.1 root 1843:
1.1.1.8 root 1844: /* Skip the rest of this line. */
1845: goto skipline;
1.1 root 1846: }
1.1.1.8 root 1847: }
1.1 root 1848:
1.1.1.8 root 1849: error ("undefined or invalid # directive");
1850: goto skipline;
1851: }
1.1 root 1852:
1.1.1.8 root 1853: linenum:
1854: /* Here we have either `#line' or `# <nonletter>'.
1855: In either case, it should be a line number; a digit should follow. */
1.1 root 1856:
1.1.1.8 root 1857: while (c == ' ' || c == '\t')
1858: c = getc (finput);
1.1 root 1859:
1.1.1.8 root 1860: /* If the # is the only nonwhite char on the line,
1861: just ignore it. Check the new newline. */
1862: if (c == '\n')
1863: return c;
1.1 root 1864:
1.1.1.8 root 1865: /* Something follows the #; read a token. */
1.1 root 1866:
1.1.1.8 root 1867: ungetc (c, finput);
1868: token = yylex ();
1.1 root 1869:
1.1.1.8 root 1870: if (token == CONSTANT
1871: && TREE_CODE (yylval.ttype) == INTEGER_CST)
1872: {
1.1.1.11 root 1873: int old_lineno = lineno;
1.1.1.8 root 1874: /* subtract one, because it is the following line that
1875: gets the specified number */
1.1 root 1876:
1.1.1.8 root 1877: int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
1.1 root 1878:
1.1.1.8 root 1879: /* Is this the last nonwhite stuff on the line? */
1880: c = getc (finput);
1881: while (c == ' ' || c == '\t')
1882: c = getc (finput);
1883: if (c == '\n')
1.1 root 1884: {
1.1.1.8 root 1885: /* No more: store the line number and check following line. */
1.1 root 1886: lineno = l;
1.1.1.8 root 1887: return c;
1888: }
1889: ungetc (c, finput);
1890:
1891: /* More follows: it must be a string constant (filename). */
1.1 root 1892:
1.1.1.8 root 1893: token = yylex ();
1894: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1895: {
1896: error ("invalid #line");
1897: goto skipline;
1.1 root 1898: }
1899:
1.1.1.8 root 1900: input_filename
1901: = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
1902: strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
1903: lineno = l;
1904:
1905: if (main_input_filename == 0)
1906: main_input_filename = input_filename;
1.1.1.11 root 1907:
1908: /* Is this the last nonwhite stuff on the line? */
1909: c = getc (finput);
1910: while (c == ' ' || c == '\t')
1911: c = getc (finput);
1912: if (c == '\n')
1913: return c;
1914: ungetc (c, finput);
1915:
1916: token = yylex ();
1917:
1918: /* `1' after file name means entering new file.
1919: `2' after file name means just left a file. */
1920:
1921: if (token == CONSTANT
1922: && TREE_CODE (yylval.ttype) == INTEGER_CST)
1923: {
1924: if (TREE_INT_CST_LOW (yylval.ttype) == 1)
1925: {
1926: struct file_stack *p
1927: = (struct file_stack *) xmalloc (sizeof (struct file_stack));
1928: input_file_stack->line = old_lineno;
1929: p->next = input_file_stack;
1930: p->name = input_filename;
1931: input_file_stack = p;
1932: input_file_stack_tick++;
1933: }
1934: else if (input_file_stack->next)
1935: {
1936: struct file_stack *p = input_file_stack;
1937: input_file_stack = p->next;
1938: free (p);
1939: input_file_stack_tick++;
1940: }
1941: else
1942: error ("#-lines for entering and leaving files don't match");
1943: }
1.1 root 1944: }
1.1.1.8 root 1945: else
1.1.1.11 root 1946: error ("invalid #-line");
1.1.1.8 root 1947:
1948: /* skip the rest of this line. */
1949: skipline:
1.1.1.10 root 1950: if (c == '\n')
1951: return c;
1.1.1.9 root 1952: while ((c = getc (finput)) != EOF && c != '\n');
1.1.1.8 root 1953: return c;
1.1 root 1954: }
1955:
1956: #define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9'))
1957: #define isdigit(char) (char >= '0' && char <= '9')
1958: #define ENDFILE -1 /* token that represents end-of-file */
1959:
1960:
1961: static int
1962: readescape ()
1963: {
1964: register int c = getc (finput);
1965: register int count, code;
1.1.1.7 root 1966: int firstdig;
1.1 root 1967:
1968: switch (c)
1969: {
1970: case 'x':
1971: code = 0;
1972: count = 0;
1973: while (1)
1974: {
1975: c = getc (finput);
1976: if (!(c >= 'a' && c <= 'f')
1977: && !(c >= 'A' && c <= 'F')
1978: && !(c >= '0' && c <= '9'))
1979: {
1980: ungetc (c, finput);
1981: break;
1982: }
1983: code *= 16;
1984: if (c >= 'a' && c <= 'f')
1985: code += c - 'a' + 10;
1986: if (c >= 'A' && c <= 'F')
1987: code += c - 'A' + 10;
1988: if (c >= '0' && c <= '9')
1989: code += c - '0';
1.1.1.7 root 1990: if (count == 0)
1991: firstdig = code;
1.1 root 1992: count++;
1993: }
1994: if (count == 0)
1995: error ("\\x used with no following hex digits");
1.1.1.11 root 1996: else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
1.1.1.13! root 1997: || (count > 1
! 1998: && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
! 1999: <= firstdig)))
1.1.1.7 root 2000: warning ("hex escape out of range");
1.1 root 2001: return code;
2002:
2003: case '0': case '1': case '2': case '3': case '4':
2004: case '5': case '6': case '7':
2005: code = 0;
2006: count = 0;
2007: while ((c <= '7') && (c >= '0') && (count++ < 3))
2008: {
2009: code = (code * 8) + (c - '0');
2010: c = getc (finput);
2011: }
2012: ungetc (c, finput);
2013: return code;
2014:
2015: case '\\': case '\'': case '"':
2016: return c;
2017:
2018: case '\n':
2019: lineno++;
2020: return -1;
2021:
2022: case 'n':
2023: return TARGET_NEWLINE;
2024:
2025: case 't':
2026: return TARGET_TAB;
2027:
2028: case 'r':
2029: return TARGET_CR;
2030:
2031: case 'f':
2032: return TARGET_FF;
2033:
2034: case 'b':
2035: return TARGET_BS;
2036:
2037: case 'a':
2038: return TARGET_BELL;
2039:
2040: case 'v':
2041: return TARGET_VT;
2042:
2043: case 'E':
2044: return 033;
2045:
2046: case '?':
1.1.1.3 root 2047: /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
1.1.1.2 root 2048: case '(':
1.1.1.3 root 2049: case '{':
2050: case '[':
1.1 root 2051: return c;
2052: }
2053: if (c >= 040 && c <= 0177)
2054: warning ("unknown escape sequence `\\%c'", c);
2055: else
2056: warning ("unknown escape sequence: `\\' followed by char code 0x%x", c);
2057: return c;
2058: }
2059:
2060: void
2061: yyerror (string)
2062: char *string;
2063: {
2064: char buf[200];
2065:
2066: strcpy (buf, string);
2067:
2068: /* We can't print string and character constants well
2069: because the token_buffer contains the result of processing escapes. */
1.1.1.5 root 2070: if (end_of_file)
1.1 root 2071: strcat (buf, " at end of input");
1.1.1.5 root 2072: else if (token_buffer[0] == 0)
2073: strcat (buf, " at null character");
1.1 root 2074: else if (token_buffer[0] == '"')
2075: strcat (buf, " before string constant");
2076: else if (token_buffer[0] == '\'')
2077: strcat (buf, " before character constant");
1.1.1.7 root 2078: else if (token_buffer[0] < 040 || token_buffer[0] >= 0177)
2079: sprintf (buf + strlen (buf), " before character 0%o", token_buffer[0]);
1.1 root 2080: else
2081: strcat (buf, " before `%s'");
2082:
2083: error (buf, token_buffer);
2084: }
2085:
2086: static int nextchar = -1;
2087:
2088: static int
2089: yylex ()
2090: {
2091: register int c;
2092: register char *p;
2093: register int value;
2094: int wide_flag = 0;
2095:
2096: if (nextchar >= 0)
2097: c = nextchar, nextchar = -1;
2098: else
2099: c = getc (finput);
2100:
2101: /* Effectively do c = skip_white_space (c)
2102: but do it faster in the usual cases. */
2103: while (1)
2104: switch (c)
2105: {
2106: case ' ':
2107: case '\t':
2108: case '\f':
2109: case '\r':
1.1.1.11 root 2110: case '\v':
1.1 root 2111: case '\b':
2112: c = getc (finput);
2113: break;
2114:
2115: case '\n':
2116: case '/':
2117: case '\\':
2118: c = skip_white_space (c);
2119: default:
2120: goto found_nonwhite;
2121: }
2122: found_nonwhite:
2123:
2124: token_buffer[0] = c;
2125: token_buffer[1] = 0;
2126:
2127: /* yylloc.first_line = lineno; */
2128:
2129: switch (c)
2130: {
2131: case EOF:
1.1.1.5 root 2132: end_of_file = 1;
1.1 root 2133: token_buffer[0] = 0;
2134: value = ENDFILE;
2135: break;
2136:
2137: case '$':
2138: if (dollars_in_ident)
2139: goto letter;
2140: return '$';
2141:
2142: case 'L':
2143: /* Capital L may start a wide-string or wide-character constant. */
2144: {
2145: register int c = getc (finput);
2146: if (c == '\'')
2147: {
2148: wide_flag = 1;
2149: goto char_constant;
2150: }
2151: if (c == '"')
2152: {
2153: wide_flag = 1;
2154: goto string_constant;
2155: }
2156: ungetc (c, finput);
2157: }
2158:
2159: case 'A': case 'B': case 'C': case 'D': case 'E':
2160: case 'F': case 'G': case 'H': case 'I': case 'J':
2161: case 'K': case 'M': case 'N': case 'O':
2162: case 'P': case 'Q': case 'R': case 'S': case 'T':
2163: case 'U': case 'V': case 'W': case 'X': case 'Y':
2164: case 'Z':
2165: case 'a': case 'b': case 'c': case 'd': case 'e':
2166: case 'f': case 'g': case 'h': case 'i': case 'j':
2167: case 'k': case 'l': case 'm': case 'n': case 'o':
2168: case 'p': case 'q': case 'r': case 's': case 't':
2169: case 'u': case 'v': case 'w': case 'x': case 'y':
2170: case 'z':
2171: case '_':
2172: letter:
2173: p = token_buffer;
2174: while (isalnum (c) || c == '_' || c == '$')
2175: {
2176: if (p >= token_buffer + maxtoken)
2177: p = extend_token_buffer (p);
2178: if (c == '$' && ! dollars_in_ident)
2179: break;
2180:
2181: *p++ = c;
2182: c = getc (finput);
2183: }
2184:
2185: *p = 0;
2186: nextchar = c;
2187:
2188: value = IDENTIFIER;
2189: yylval.itype = 0;
2190:
1.1.1.4 root 2191: /* Try to recognize a keyword. Uses minimum-perfect hash function */
1.1.1.11 root 2192:
1.1.1.4 root 2193: {
2194: register struct resword *ptr;
1.1 root 2195:
1.1.1.4 root 2196: if (ptr = is_reserved_word (token_buffer, p - token_buffer))
2197: {
2198: if (ptr->rid)
2199: yylval.ttype = ridpointers[(int) ptr->rid];
2200: if ((! flag_no_asm
2201: /* -fno-asm means don't recognize the non-ANSI keywords. */
2202: || ((int) ptr->token != ASM
2203: && (int) ptr->token != TYPEOF
1.1.1.10 root 2204: && ptr->rid != RID_INLINE)
2205: /* Recognize __asm and __inline despite -fno-asm. */
2206: || token_buffer[0] == '_')
1.1.1.4 root 2207: /* -ftraditional means don't recognize nontraditional keywords
2208: typeof, const, volatile, signed or inline. */
2209: && (! flag_traditional
2210: || ((int) ptr->token != TYPE_QUAL
2211: && (int) ptr->token != TYPEOF
2212: && ptr->rid != RID_SIGNED
1.1.1.10 root 2213: && ptr->rid != RID_INLINE)
2214: /* Recognize __inline, etc. despite -ftraditional. */
2215: || token_buffer[0] == '_'))
1.1.1.4 root 2216: value = (int) ptr->token;
2217: }
2218: }
1.1 root 2219:
2220: /* If we did not find a keyword, look for an identifier
2221: (or a typename). */
2222:
2223: if (value == IDENTIFIER)
2224: {
2225: yylval.ttype = get_identifier (token_buffer);
2226: lastiddecl = lookup_name (yylval.ttype);
2227:
2228: if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL)
2229: value = TYPENAME;
2230: }
2231:
2232: break;
2233:
2234: case '0': case '1': case '2': case '3': case '4':
2235: case '5': case '6': case '7': case '8': case '9':
2236: case '.':
2237: {
2238: int base = 10;
2239: int count = 0;
2240: int largest_digit = 0;
2241: int numdigits = 0;
2242: /* for multi-precision arithmetic,
2243: we store only 8 live bits in each short,
2244: giving us 64 bits of reliable precision */
2245: short shorts[8];
1.1.1.11 root 2246: int overflow = 0;
1.1.1.3 root 2247:
1.1.1.5 root 2248: enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
1.1.1.3 root 2249: = NOT_FLOAT;
1.1 root 2250:
2251: for (count = 0; count < 8; count++)
2252: shorts[count] = 0;
2253:
2254: p = token_buffer;
2255: *p++ = c;
2256:
2257: if (c == '0')
2258: {
2259: *p++ = (c = getc (finput));
2260: if ((c == 'x') || (c == 'X'))
2261: {
2262: base = 16;
2263: *p++ = (c = getc (finput));
2264: }
2265: else
2266: {
2267: base = 8;
2268: numdigits++;
2269: }
2270: }
2271:
2272: /* Read all the digits-and-decimal-points. */
2273:
2274: while (c == '.'
2275: || (isalnum (c) && (c != 'l') && (c != 'L')
2276: && (c != 'u') && (c != 'U')
1.1.1.3 root 2277: && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
1.1 root 2278: {
2279: if (c == '.')
2280: {
2281: if (base == 16)
2282: error ("floating constant may not be in radix 16");
1.1.1.3 root 2283: if (floatflag == AFTER_POINT)
2284: {
2285: error ("malformed floating constant");
2286: floatflag = TOO_MANY_POINTS;
2287: }
2288: else
2289: floatflag = AFTER_POINT;
2290:
1.1 root 2291: base = 10;
2292: *p++ = c = getc (finput);
2293: /* Accept '.' as the start of a floating-point number
2294: only when it is followed by a digit.
2295: Otherwise, unread the following non-digit
2296: and use the '.' as a structural token. */
2297: if (p == token_buffer + 2 && !isdigit (c))
2298: {
2299: if (c == '.')
2300: {
2301: c = getc (finput);
2302: if (c == '.')
2303: {
2304: *p++ = c;
2305: *p = 0;
2306: return ELLIPSIS;
2307: }
2308: error ("parse error at `..'");
2309: }
2310: ungetc (c, finput);
2311: token_buffer[1] = 0;
2312: value = '.';
2313: goto done;
2314: }
2315: }
2316: else
2317: {
2318: /* It is not a decimal point.
2319: It should be a digit (perhaps a hex digit). */
2320:
2321: if (isdigit (c))
2322: {
2323: c = c - '0';
2324: }
2325: else if (base <= 10)
2326: {
2327: if ((c&~040) == 'E')
2328: {
2329: base = 10;
1.1.1.3 root 2330: floatflag = AFTER_POINT;
1.1 root 2331: break; /* start of exponent */
2332: }
2333: error ("nondigits in number and not hexadecimal");
2334: c = 0;
2335: }
2336: else if (c >= 'a')
2337: {
2338: c = c - 'a' + 10;
2339: }
2340: else
2341: {
2342: c = c - 'A' + 10;
2343: }
2344: if (c >= largest_digit)
2345: largest_digit = c;
2346: numdigits++;
1.1.1.11 root 2347:
1.1 root 2348: for (count = 0; count < 8; count++)
2349: {
1.1.1.11 root 2350: shorts[count] *= base;
1.1 root 2351: if (count)
2352: {
2353: shorts[count] += (shorts[count-1] >> 8);
2354: shorts[count-1] &= (1<<8)-1;
2355: }
2356: else shorts[0] += c;
2357: }
1.1.1.11 root 2358:
2359: if (shorts[7] >= 1<<8
2360: || shorts[7] < - (1 << 8))
2361: overflow = TRUE;
2362:
1.1 root 2363: if (p >= token_buffer + maxtoken - 3)
2364: p = extend_token_buffer (p);
2365: *p++ = (c = getc (finput));
2366: }
2367: }
2368:
2369: if (numdigits == 0)
2370: error ("numeric constant with no digits");
2371:
2372: if (largest_digit >= base)
2373: error ("numeric constant contains digits beyond the radix");
2374:
2375: /* Remove terminating char from the token buffer and delimit the string */
2376: *--p = 0;
2377:
1.1.1.3 root 2378: if (floatflag != NOT_FLOAT)
1.1 root 2379: {
2380: tree type = double_type_node;
2381: char f_seen = 0;
2382: char l_seen = 0;
1.1.1.8 root 2383: REAL_VALUE_TYPE value;
1.1 root 2384:
2385: /* Read explicit exponent if any, and put it in tokenbuf. */
2386:
2387: if ((c == 'e') || (c == 'E'))
2388: {
2389: if (p >= token_buffer + maxtoken - 3)
2390: p = extend_token_buffer (p);
2391: *p++ = c;
2392: c = getc (finput);
2393: if ((c == '+') || (c == '-'))
2394: {
2395: *p++ = c;
2396: c = getc (finput);
2397: }
2398: if (! isdigit (c))
2399: error ("floating constant exponent has no digits");
2400: while (isdigit (c))
2401: {
2402: if (p >= token_buffer + maxtoken - 3)
2403: p = extend_token_buffer (p);
2404: *p++ = c;
2405: c = getc (finput);
2406: }
2407: }
2408:
2409: *p = 0;
2410: errno = 0;
1.1.1.8 root 2411: value = REAL_VALUE_ATOF (token_buffer);
1.1 root 2412: #ifdef ERANGE
2413: if (errno == ERANGE && !flag_traditional)
1.1.1.5 root 2414: {
2415: char *p1 = token_buffer;
2416: /* Check for "0.0" and variants;
2417: Sunos 4 spuriously returns ERANGE for them. */
2418: while (*p1 == '0') p1++;
1.1.1.11 root 2419: if (*p1 == '.')
2420: {
2421: p1++;
2422: while (*p1 == '0') p1++;
2423: }
2424: if (*p1 == 'e' || *p1 == 'E')
2425: {
2426: /* with significand==0, ignore the exponent */
2427: p1++;
2428: while (*p1 != 0) p1++;
2429: }
1.1.1.12 root 2430: /* ERANGE is also reported for underflow,
2431: so test the value to distinguish overflow from that. */
1.1.1.13! root 2432: if (*p1 != 0 && (value > 1.0 || value < -1.0))
1.1.1.5 root 2433: warning ("floating point number exceeds range of `double'");
2434: }
1.1 root 2435: #endif
2436:
2437: /* Read the suffixes to choose a data type. */
2438: while (1)
2439: {
2440: if (c == 'f' || c == 'F')
2441: {
1.1.1.11 root 2442: float floater;
1.1 root 2443: if (f_seen)
2444: error ("two `f's in floating constant");
2445: f_seen = 1;
2446: type = float_type_node;
1.1.1.11 root 2447: floater = value;
2448: value = floater;
1.1 root 2449: }
2450: else if (c == 'l' || c == 'L')
2451: {
2452: if (l_seen)
2453: error ("two `l's in floating constant");
2454: l_seen = 1;
2455: type = long_double_type_node;
2456: }
2457: else
2458: {
2459: if (isalnum (c))
2460: {
2461: error ("garbage at end of number");
2462: while (isalnum (c))
2463: {
2464: if (p >= token_buffer + maxtoken - 3)
2465: p = extend_token_buffer (p);
2466: *p++ = c;
2467: c = getc (finput);
2468: }
2469: }
2470: break;
2471: }
2472: if (p >= token_buffer + maxtoken - 3)
2473: p = extend_token_buffer (p);
2474: *p++ = c;
2475: c = getc (finput);
2476: }
2477:
2478: /* Create a node with determined type and value. */
2479: yylval.ttype = build_real (type, value);
2480:
2481: ungetc (c, finput);
2482: *p = 0;
2483: }
2484: else
2485: {
2486: tree type;
2487: int spec_unsigned = 0;
2488: int spec_long = 0;
1.1.1.11 root 2489: int spec_long_long = 0;
1.1 root 2490:
2491: while (1)
2492: {
2493: if (c == 'u' || c == 'U')
2494: {
2495: if (spec_unsigned)
2496: error ("two `u's in integer constant");
2497: spec_unsigned = 1;
2498: }
2499: else if (c == 'l' || c == 'L')
2500: {
2501: if (spec_long)
1.1.1.11 root 2502: {
2503: if (spec_long_long)
2504: error ("three `l's in integer constant");
2505: else if (pedantic)
2506: warning ("ANSI C forbids long long integer constants");
2507: spec_long_long = 1;
2508: }
1.1 root 2509: spec_long = 1;
2510: }
2511: else
2512: {
2513: if (isalnum (c))
2514: {
2515: error ("garbage at end of number");
2516: while (isalnum (c))
2517: {
2518: if (p >= token_buffer + maxtoken - 3)
2519: p = extend_token_buffer (p);
2520: *p++ = c;
2521: c = getc (finput);
2522: }
2523: }
2524: break;
2525: }
2526: if (p >= token_buffer + maxtoken - 3)
2527: p = extend_token_buffer (p);
2528: *p++ = c;
2529: c = getc (finput);
2530: }
2531:
2532: ungetc (c, finput);
2533:
1.1.1.11 root 2534: if ((overflow || shorts[7] || shorts[6] || shorts[5] || shorts[4])
2535: && !spec_long_long)
1.1 root 2536: warning ("integer constant out of range");
2537:
1.1.1.11 root 2538: /* If it won't fit in a signed long long, make it unsigned.
2539: We can't distinguish based on the tree node because
2540: any integer constant fits any long long type. */
2541: if (shorts[7] >= (1<<8))
2542: spec_unsigned = 1;
2543:
1.1 root 2544: /* This is simplified by the fact that our constant
2545: is always positive. */
2546: yylval.ttype
1.1.1.11 root 2547: = (build_int_2
2548: ((shorts[3]<<24) + (shorts[2]<<16) + (shorts[1]<<8) + shorts[0],
2549: (spec_long_long
2550: ? (shorts[7]<<24) + (shorts[6]<<16) + (shorts[5]<<8) + shorts[4]
2551: : 0)));
2552:
1.1 root 2553: if (!spec_long && !spec_unsigned
2554: && int_fits_type_p (yylval.ttype, integer_type_node))
2555: type = integer_type_node;
2556:
1.1.1.13! root 2557: else if (!spec_long && (base != 10 || spec_unsigned)
1.1.1.11 root 2558: && int_fits_type_p (yylval.ttype, unsigned_type_node))
1.1 root 2559: type = unsigned_type_node;
2560:
1.1.1.11 root 2561: else if (!spec_unsigned && !spec_long_long
2562: && int_fits_type_p (yylval.ttype, long_integer_type_node))
1.1 root 2563: type = long_integer_type_node;
2564:
1.1.1.11 root 2565: else if (! spec_long_long
2566: && int_fits_type_p (yylval.ttype,
2567: long_unsigned_type_node))
2568: type = long_unsigned_type_node;
2569:
2570: else if (! spec_unsigned
2571: && int_fits_type_p (yylval.ttype,
2572: long_long_integer_type_node))
2573: type = long_long_integer_type_node;
2574:
2575: else if (int_fits_type_p (yylval.ttype,
2576: long_long_unsigned_type_node))
2577: type = long_long_unsigned_type_node;
2578:
1.1 root 2579: else
2580: {
1.1.1.11 root 2581: type = long_long_integer_type_node;
2582: warning ("integer constant out of range");
1.1 root 2583: }
1.1.1.11 root 2584:
1.1 root 2585: TREE_TYPE (yylval.ttype) = type;
1.1.1.13! root 2586: *p = 0;
1.1 root 2587: }
2588:
2589: value = CONSTANT; break;
2590: }
2591:
2592: case '\'':
2593: char_constant:
2594: {
1.1.1.11 root 2595: register int result = 0;
2596: register num_chars = 0;
2597: int width = TYPE_PRECISION (char_type_node);
2598: int max_chars;
1.1 root 2599:
1.1.1.11 root 2600: if (wide_flag) width = TYPE_PRECISION (integer_type_node);
1.1 root 2601:
1.1.1.11 root 2602: max_chars = TYPE_PRECISION (integer_type_node) / width;
2603:
2604: while (1)
1.1 root 2605: {
1.1.1.11 root 2606: tryagain:
2607:
2608: c = getc (finput);
2609:
2610: if (c == '\'' || c == EOF)
2611: break;
2612:
2613: if (c == '\\')
2614: {
2615: c = readescape ();
2616: if (c < 0)
2617: goto tryagain;
2618: if (width < HOST_BITS_PER_INT
2619: && (unsigned) c >= (1 << width))
2620: warning ("escape sequence out of range for character");
2621: }
2622: else if (c == '\n')
2623: {
2624: if (pedantic)
2625: warning ("ANSI C forbids newline in character constant");
2626: lineno++;
2627: }
2628:
2629: num_chars++;
2630: if (num_chars > maxtoken - 4)
2631: extend_token_buffer (token_buffer);
2632:
2633: token_buffer[num_chars] = c;
2634:
2635: /* Merge character into result; ignore excess chars. */
2636: if (num_chars < max_chars + 1)
2637: {
2638: if (width < HOST_BITS_PER_INT)
2639: result = (result << width) | (c & ((1 << width) - 1));
2640: else
2641: result = c;
2642: }
1.1 root 2643: }
2644:
1.1.1.11 root 2645: token_buffer[num_chars + 1] = '\'';
2646: token_buffer[num_chars + 2] = 0;
1.1 root 2647:
2648: if (c != '\'')
2649: error ("malformatted character constant");
1.1.1.11 root 2650: else if (num_chars == 0)
2651: error ("empty character constant");
2652: else if (num_chars > max_chars)
2653: {
2654: num_chars = max_chars;
2655: error ("character constant too long");
2656: }
2657: else if (num_chars != 1 && ! flag_traditional)
2658: warning ("multi-character character constant");
1.1 root 2659:
2660: /* If char type is signed, sign-extend the constant. */
1.1.1.7 root 2661: if (! wide_flag)
2662: {
1.1.1.11 root 2663: int num_bits = num_chars * width;
1.1.1.7 root 2664: if (TREE_UNSIGNED (char_type_node)
1.1.1.11 root 2665: || ((result >> (num_bits - 1)) & 1) == 0)
2666: yylval.ttype
2667: = build_int_2 (result & ((unsigned) ~0
2668: >> (HOST_BITS_PER_INT - num_bits)),
2669: 0);
1.1.1.7 root 2670: else
1.1.1.11 root 2671: yylval.ttype
2672: = build_int_2 (result | ~((unsigned) ~0
2673: >> (HOST_BITS_PER_INT - num_bits)),
2674: -1);
1.1.1.7 root 2675: }
1.1 root 2676: else
1.1.1.11 root 2677: yylval.ttype = build_int_2 (result, 0);
1.1 root 2678:
2679: TREE_TYPE (yylval.ttype) = integer_type_node;
2680: value = CONSTANT; break;
2681: }
2682:
2683: case '"':
2684: string_constant:
2685: {
1.1.1.7 root 2686: int *widep;
2687:
1.1 root 2688: c = getc (finput);
2689: p = token_buffer + 1;
2690:
1.1.1.7 root 2691: if (wide_flag)
2692: widep = wide_buffer;
2693:
1.1.1.9 root 2694: while (c != '"' && c >= 0)
1.1 root 2695: {
2696: if (c == '\\')
2697: {
2698: c = readescape ();
2699: if (c < 0)
2700: goto skipnewline;
1.1.1.11 root 2701: if (!wide_flag && c >= (1 << TYPE_PRECISION (char_type_node)))
1.1.1.7 root 2702: warning ("escape sequence out of range for character");
1.1 root 2703: }
2704: else if (c == '\n')
2705: {
2706: if (pedantic)
2707: warning ("ANSI C forbids newline in string constant");
2708: lineno++;
2709: }
2710:
1.1.1.7 root 2711: /* Store the char in C into the appropriate buffer. */
2712:
2713: if (wide_flag)
2714: {
2715: if (widep == wide_buffer + max_wide)
2716: {
2717: int n = widep - wide_buffer;
2718: max_wide *= 2;
2719: wide_buffer = (int *) xrealloc (wide_buffer, max_wide + 1);
2720: widep = wide_buffer + n;
2721: }
2722: *widep++ = c;
2723: }
2724: else
2725: {
2726: if (p == token_buffer + maxtoken)
2727: p = extend_token_buffer (p);
2728: *p++ = c;
2729: }
1.1 root 2730:
2731: skipnewline:
2732: c = getc (finput);
2733: }
2734:
1.1.1.7 root 2735: /* We have read the entire constant.
2736: Construct a STRING_CST for the result. */
1.1 root 2737:
2738: if (wide_flag)
2739: {
1.1.1.7 root 2740: /* If this is a L"..." wide-string, make a vector
2741: of the ints in wide_buffer. */
2742: *widep = 0;
2743: /* We have not implemented the case where `int'
2744: on the target and on the execution machine differ in size. */
2745: if (TYPE_PRECISION (integer_type_node)
2746: != sizeof (int) * BITS_PER_UNIT)
2747: abort ();
1.1.1.12 root 2748: yylval.ttype
2749: = build_string ((widep - wide_buffer + 1) * sizeof (int),
2750: wide_buffer);
1.1 root 2751: TREE_TYPE (yylval.ttype) = int_array_type_node;
2752: }
2753: else
2754: {
1.1.1.7 root 2755: *p = 0;
1.1 root 2756: yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
2757: TREE_TYPE (yylval.ttype) = char_array_type_node;
2758: }
2759:
2760: *p++ = '"';
2761: *p = 0;
2762:
2763: value = STRING; break;
2764: }
1.1.1.11 root 2765:
1.1 root 2766: case '+':
2767: case '-':
2768: case '&':
2769: case '|':
2770: case '<':
2771: case '>':
2772: case '*':
2773: case '/':
2774: case '%':
2775: case '^':
2776: case '!':
2777: case '=':
2778: {
2779: register int c1;
2780:
2781: combine:
2782:
2783: switch (c)
2784: {
2785: case '+':
2786: yylval.code = PLUS_EXPR; break;
2787: case '-':
2788: yylval.code = MINUS_EXPR; break;
2789: case '&':
2790: yylval.code = BIT_AND_EXPR; break;
2791: case '|':
2792: yylval.code = BIT_IOR_EXPR; break;
2793: case '*':
2794: yylval.code = MULT_EXPR; break;
2795: case '/':
2796: yylval.code = TRUNC_DIV_EXPR; break;
2797: case '%':
2798: yylval.code = TRUNC_MOD_EXPR; break;
2799: case '^':
2800: yylval.code = BIT_XOR_EXPR; break;
2801: case LSHIFT:
2802: yylval.code = LSHIFT_EXPR; break;
2803: case RSHIFT:
2804: yylval.code = RSHIFT_EXPR; break;
2805: case '<':
2806: yylval.code = LT_EXPR; break;
2807: case '>':
2808: yylval.code = GT_EXPR; break;
1.1.1.11 root 2809: }
1.1 root 2810:
2811: token_buffer[1] = c1 = getc (finput);
2812: token_buffer[2] = 0;
2813:
2814: if (c1 == '=')
2815: {
2816: switch (c)
2817: {
2818: case '<':
2819: value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
2820: case '>':
2821: value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
2822: case '!':
2823: value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
2824: case '=':
2825: value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
1.1.1.11 root 2826: }
1.1 root 2827: value = ASSIGN; goto done;
2828: }
2829: else if (c == c1)
2830: switch (c)
2831: {
2832: case '+':
2833: value = PLUSPLUS; goto done;
2834: case '-':
2835: value = MINUSMINUS; goto done;
2836: case '&':
2837: value = ANDAND; goto done;
2838: case '|':
2839: value = OROR; goto done;
2840: case '<':
2841: c = LSHIFT;
2842: goto combine;
2843: case '>':
2844: c = RSHIFT;
2845: goto combine;
2846: }
2847: else if ((c == '-') && (c1 == '>'))
2848: { value = POINTSAT; goto done; }
2849: ungetc (c1, finput);
2850: token_buffer[1] = 0;
2851:
2852: if ((c == '<') || (c == '>'))
2853: value = ARITHCOMPARE;
2854: else value = c;
2855: goto done;
2856: }
2857:
1.1.1.5 root 2858: case 0:
2859: /* Don't make yyparse think this is eof. */
2860: value = 1;
2861: break;
2862:
1.1 root 2863: default:
2864: value = c;
2865: }
2866:
2867: done:
2868: /* yylloc.last_line = lineno; */
2869:
2870: return value;
2871: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.