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