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