|
|
1.1 root 1: /* YACC parser for C syntax.
1.1.1.2 root 2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
1.1 root 3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* To whomever it may concern: I have heard that such a thing was once
23: written by AT&T, but I have never seen it. */
24:
1.1.1.4 root 25: %expect 23
1.1.1.2 root 26:
1.1.1.4 root 27: /* These are the 23 conflicts you should get in parse.output;
1.1.1.2 root 28: the state numbers may vary if minor changes in the grammar are made.
29:
30: State 41 contains 1 shift/reduce conflict. (Two ways to recover from error.)
1.1.1.4 root 31: State 90 contains 1 shift/reduce conflict. (Two ways to recover from error.)
32: State 97 contains 1 shift/reduce conflict. (Two ways to recover from error.)
33: State 101 contains 1 shift/reduce conflict. (Two ways to recover from error.)
34: State 117 contains 1 shift/reduce conflict. (See comment at component_decl.)
35: State 169 contains 2 shift/reduce conflicts. (make notype_declarator longer.)
36: State 181 contains 1 shift/reduce conflict. (Two ways to recover from error.)
37: State 191 contains 1 shift/reduce conflict. (Two ways to recover from error.)
38: State 197 contains 1 shift/reduce conflict. (Two ways to recover from error.)
39: State 239 contains 2 shift/reduce conflicts. (make absdcl1 longer if poss.)
40: State 269 contains 2 shift/reduce conflicts. (same for after_type_declarator).
41: State 299 contains 2 shift/reduce conflicts. (similar for absdcl1 again.)
1.1.1.2 root 42: State 362 contains 1 shift/reduce conflict. (dangling else.)
1.1.1.4 root 43: State 370 contains 2 shift/reduce conflicts. (like 241, other context.)
44: State 373 contains 2 shift/reduce conflicts. (like 241, other context.)
45: State 411 contains 2 shift/reduce conflicts. (like 166 for parm_declarator)?
1.1.1.2 root 46: */
47:
1.1 root 48: %{
49: #include "config.h"
50: #include "tree.h"
51: #include "parse.h"
52: #include "c-tree.h"
1.1.1.2 root 53: #include "flags.h"
54:
55: #include <stdio.h>
1.1.1.4 root 56: #include <errno.h>
57:
58: extern int errno;
1.1.1.2 root 59:
60: /* Cause the `yydebug' variable to be defined. */
61: #define YYDEBUG
1.1 root 62: %}
63:
64: %start program
65:
1.1.1.2 root 66: %union {long itype; tree ttype; enum tree_code code; char *cptr; }
1.1 root 67:
1.1.1.2 root 68: /* All identifiers that are not reserved words
1.1 root 69: and are not declared typedefs in the current block */
70: %token IDENTIFIER
1.1.1.2 root 71:
72: /* All identifiers that are declared typedefs in the current block.
1.1 root 73: In some contexts, they are treated just like IDENTIFIER,
74: but they can also serve as typespecs in declarations. */
75: %token TYPENAME
76:
1.1.1.2 root 77: /* Reserved words that specify storage class.
78: yylval contains an IDENTIFIER_NODE which indicates which one. */
1.1 root 79: %token SCSPEC
80:
1.1.1.2 root 81: /* Reserved words that specify type.
82: yylval contains an IDENTIFIER_NODE which indicates which one. */
1.1 root 83: %token TYPESPEC
84:
1.1.1.2 root 85: /* Reserved words that qualify type: "const" or "volatile".
86: yylval contains an IDENTIFIER_NODE which indicates which one. */
87: %token TYPE_QUAL
1.1 root 88:
1.1.1.2 root 89: /* Character or numeric constants.
1.1 root 90: yylval is the node for the constant. */
91: %token CONSTANT
92:
93: /* String constants in raw form.
94: yylval is a STRING_CST node. */
95: %token STRING
96:
97: /* "...", used for functions with variable arglists. */
98: %token ELLIPSIS
99:
100: /* the reserved words */
101: %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
1.1.1.2 root 102: %token BREAK CONTINUE RETURN GOTO ASM TYPEOF ALIGNOF
1.1 root 103:
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
122: %left <code> POINTSAT '.'
123:
124: %type <code> unop
125:
126: %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
127: %type <ttype> expr_no_commas primary string STRING
1.1.1.2 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
1.1 root 132: %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
1.1.1.2 root 133: %type <ttype> init initlist maybeasm
1.1.1.4 root 134: %type <ttype> asm_operands nonnull_asm_operands asm_operand
1.1 root 135:
136: %type <ttype> declarator
137: %type <ttype> notype_declarator after_type_declarator
1.1.1.2 root 138: %type <ttype> parm_declarator
1.1 root 139:
140: %type <ttype> structsp component_decl_list component_decl components component_declarator
141: %type <ttype> enumlist enumerator
1.1.1.2 root 142: %type <ttype> typename absdcl absdcl1 type_quals
143: %type <ttype> xexpr parms parm identifiers
144:
145: %type <ttype> parmlist parmlist_1 parmlist_2
146: %type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
147:
148: %type <itype> setspecs
1.1 root 149:
150: %{
151: /* the declaration found for the last IDENTIFIER token read in.
152: yylex must look this up to detect typedefs, which get token type TYPENAME,
153: so it is left around in case the identifier is not a typedef but is
154: used in a context which makes it a reference to a variable. */
155: static tree lastiddecl;
156:
157: static tree make_pointer_declarator ();
158: static tree combine_strings ();
1.1.1.2 root 159: static void reinit_parse_for_function ();
1.1 root 160:
1.1.1.2 root 161: extern double atof ();
162:
163: /* List of types and structure classes of the current declaration */
1.1 root 164: tree current_declspecs;
165:
1.1.1.2 root 166: char *input_filename; /* source file current line is coming from */
167: char *main_input_filename; /* top-level source file */
1.1.1.4 root 168:
169: static int yylex ();
1.1 root 170: %}
171:
172: %%
1.1.1.2 root 173: program: /* empty */
174: | extdefs
1.1 root 175: ;
176:
177: /* the reason for the strange actions in this rule
178: is so that notype_initdecls when reached via datadef
179: can find a valid list of type and sc specs in $0. */
180:
181: extdefs:
1.1.1.2 root 182: {$<ttype>$ = NULL_TREE; } extdef
183: | extdefs {$<ttype>$ = NULL_TREE; } extdef
1.1 root 184: ;
185:
186: extdef:
187: fndef
188: | datadef
1.1.1.2 root 189: | ASM '(' string ')' ';'
190: { if (pedantic)
191: warning ("ANSI C forbids use of `asm' keyword");
192: if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
193: assemble_asm ($3); }
1.1 root 194: ;
195:
196: datadef:
197: setspecs notype_initdecls ';'
1.1.1.2 root 198: { if (pedantic)
199: error ("ANSI C forbids data definition lacking type or storage class");
200: else
201: warning ("data definition lacks type or storage class"); }
202: | declmods setspecs notype_initdecls ';'
1.1 root 203: {}
204: | typed_declspecs setspecs initdecls ';'
205: {}
1.1.1.2 root 206: | declmods ';'
207: { error ("empty declaration"); }
1.1 root 208: | typed_declspecs ';'
209: { shadow_tag ($1); }
210: | error ';'
211: | error '}'
212: | ';'
213: ;
214:
215: fndef:
216: typed_declspecs setspecs declarator
217: { if (! start_function ($1, $3))
1.1.1.2 root 218: YYFAIL;
219: reinit_parse_for_function (); }
1.1 root 220: xdecls
221: { store_parm_decls (); }
1.1.1.4 root 222: compstmt_or_error
1.1.1.3 root 223: { finish_function (); }
1.1 root 224: | typed_declspecs setspecs declarator error
225: { }
1.1.1.2 root 226: | declmods setspecs notype_declarator
1.1 root 227: { if (! start_function ($1, $3))
1.1.1.2 root 228: YYFAIL;
229: reinit_parse_for_function (); }
1.1 root 230: xdecls
231: { store_parm_decls (); }
1.1.1.4 root 232: compstmt_or_error
1.1.1.3 root 233: { finish_function (); }
1.1.1.2 root 234: | declmods setspecs notype_declarator error
1.1 root 235: { }
236: | setspecs notype_declarator
237: { if (! start_function (0, $2))
1.1.1.2 root 238: YYFAIL;
239: reinit_parse_for_function (); }
1.1 root 240: xdecls
241: { store_parm_decls (); }
1.1.1.4 root 242: compstmt_or_error
1.1.1.3 root 243: { finish_function (); }
1.1 root 244: | setspecs notype_declarator error
1.1.1.2 root 245: { }
1.1 root 246: ;
247:
248: identifier:
249: IDENTIFIER
250: | TYPENAME
251: ;
252:
253: unop: '&'
254: { $$ = ADDR_EXPR; }
255: | '-'
256: { $$ = NEGATE_EXPR; }
257: | '+'
258: { $$ = CONVERT_EXPR; }
259: | PLUSPLUS
260: { $$ = PREINCREMENT_EXPR; }
261: | MINUSMINUS
262: { $$ = PREDECREMENT_EXPR; }
263: | '~'
264: { $$ = BIT_NOT_EXPR; }
265: | '!'
266: { $$ = TRUTH_NOT_EXPR; }
267: ;
268:
269: expr: nonnull_exprlist
1.1.1.2 root 270: { $$ = build_compound_expr ($1); }
1.1 root 271: ;
272:
273: exprlist:
274: /* empty */
275: { $$ = NULL_TREE; }
276: | nonnull_exprlist
277: ;
278:
279: nonnull_exprlist:
280: expr_no_commas
281: { $$ = build_tree_list (NULL_TREE, $1); }
282: | nonnull_exprlist ',' expr_no_commas
283: { chainon ($1, build_tree_list (NULL_TREE, $3)); }
284: ;
285:
286: expr_no_commas:
287: primary
288: | '*' expr_no_commas %prec UNARY
1.1.1.2 root 289: { $$ = build_indirect_ref ($2, "unary *"); }
1.1 root 290: | unop expr_no_commas %prec UNARY
291: { $$ = build_unary_op ($1, $2, 0); }
292: | '(' typename ')' expr_no_commas %prec UNARY
1.1.1.2 root 293: { tree type = groktypename ($2);
294: $$ = build_c_cast (type, $4); }
295: | '(' typename ')' '{' initlist maybecomma '}' %prec UNARY
296: { tree type = groktypename ($2);
297: if (pedantic)
298: warning ("ANSI C forbids constructor-expressions");
299: $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0);
300: if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
301: {
302: int failure = complete_array_type (type, $$, 1);
303: if (failure)
304: abort ();
305: }
306: }
1.1 root 307: | SIZEOF expr_no_commas %prec UNARY
1.1.1.2 root 308: { if (TREE_CODE ($2) == COMPONENT_REF
309: && TREE_PACKED (TREE_OPERAND ($2, 1)))
310: error ("sizeof applied to a bit-field");
311: $$ = c_sizeof (TREE_TYPE ($2)); }
1.1 root 312: | SIZEOF '(' typename ')' %prec HYPERUNARY
1.1.1.2 root 313: { $$ = c_sizeof (groktypename ($3)); }
314: | ALIGNOF expr_no_commas %prec UNARY
315: { if (TREE_CODE ($2) == COMPONENT_REF
316: && TREE_PACKED (TREE_OPERAND ($2, 1)))
317: error ("__alignof applied to a bit-field");
318: $$ = c_alignof (TREE_TYPE ($2)); }
319: | ALIGNOF '(' typename ')' %prec HYPERUNARY
320: { $$ = c_alignof (groktypename ($3)); }
1.1 root 321: | expr_no_commas '+' expr_no_commas
322: { $$ = build_binary_op ($2, $1, $3); }
323: | expr_no_commas '-' expr_no_commas
324: { $$ = build_binary_op ($2, $1, $3); }
325: | expr_no_commas '*' expr_no_commas
326: { $$ = build_binary_op ($2, $1, $3); }
327: | expr_no_commas '/' expr_no_commas
328: { $$ = build_binary_op ($2, $1, $3); }
329: | expr_no_commas '%' expr_no_commas
330: { $$ = build_binary_op ($2, $1, $3); }
331: | expr_no_commas LSHIFT expr_no_commas
332: { $$ = build_binary_op ($2, $1, $3); }
333: | expr_no_commas RSHIFT expr_no_commas
334: { $$ = build_binary_op ($2, $1, $3); }
335: | expr_no_commas ARITHCOMPARE expr_no_commas
336: { $$ = build_binary_op ($2, $1, $3); }
337: | expr_no_commas EQCOMPARE expr_no_commas
338: { $$ = build_binary_op ($2, $1, $3); }
339: | expr_no_commas '&' expr_no_commas
340: { $$ = build_binary_op ($2, $1, $3); }
341: | expr_no_commas '|' expr_no_commas
342: { $$ = build_binary_op ($2, $1, $3); }
343: | expr_no_commas '^' expr_no_commas
344: { $$ = build_binary_op ($2, $1, $3); }
345: | expr_no_commas ANDAND expr_no_commas
346: { $$ = build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }
347: | expr_no_commas OROR expr_no_commas
348: { $$ = build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }
1.1.1.2 root 349: | expr_no_commas '?' xexpr ':' expr_no_commas
350: { $$ = build_conditional_expr ($1, $3, $5); }
1.1 root 351: | expr_no_commas '=' expr_no_commas
1.1.1.2 root 352: { $$ = build_modify_expr ($1, NOP_EXPR, $3); }
1.1 root 353: | expr_no_commas ASSIGN expr_no_commas
1.1.1.2 root 354: { $$ = build_modify_expr ($1, $2, $3); }
1.1 root 355: ;
356:
357: primary:
358: IDENTIFIER
359: { $$ = lastiddecl;
360: if (!$$)
361: {
362: if (yychar == YYEMPTY)
363: yychar = YYLEX;
364: if (yychar == '(')
1.1.1.2 root 365: $$ = implicitly_declare ($1);
1.1 root 366: else
367: {
1.1.1.2 root 368: if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node)
369: error ("undeclared variable `%s' (first use here)",
370: IDENTIFIER_POINTER ($1));
1.1 root 371: $$ = error_mark_node;
1.1.1.2 root 372: /* Prevent repeated error messages. */
373: IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node;
1.1 root 374: }
375: }
376: if (TREE_CODE ($$) == CONST_DECL)
377: $$ = DECL_INITIAL ($$);
378: }
379: | CONSTANT
380: | string
381: { $$ = combine_strings ($1); }
382: | '(' expr ')'
383: { $$ = $2; }
384: | '(' error ')'
385: { $$ = error_mark_node; }
1.1.1.2 root 386: | '('
387: { if (current_function_decl == 0)
388: {
389: error ("braced-group within expression allowed only inside a function");
390: YYFAIL;
391: }
392: expand_start_stmt_expr (); }
393: compstmt ')'
394: { if (pedantic)
395: warning ("ANSI C forbids braced-groups within expressions");
396: $$ = get_last_expr ();
397: expand_end_stmt_expr (); }
1.1 root 398: | primary '(' exprlist ')' %prec '.'
399: { $$ = build_function_call ($1, $3); }
400: | primary '[' expr ']' %prec '.'
401: { $$ = build_array_ref ($1, $3); }
402: | primary '.' identifier
1.1.1.2 root 403: { $$ = build_component_ref ($1, $3); }
1.1 root 404: | primary POINTSAT identifier
1.1.1.2 root 405: { $$ = build_component_ref (build_indirect_ref ($1, "->"), $3); }
1.1 root 406: | primary PLUSPLUS
407: { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
408: | primary MINUSMINUS
409: { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
410: ;
411:
412: /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
413: string:
414: STRING
415: | string STRING
416: { $$ = chainon ($1, $2); }
417: ;
418:
419: xdecls:
420: /* empty */
421: | decls
422: ;
423:
424: decls:
425: decl
426: | errstmt
427: | decls decl
428: | decl errstmt
429: ;
430:
431: /* records the type and storage class specs to use for processing
432: the declarators that follow */
433: setspecs: /* empty */
1.1.1.2 root 434: { current_declspecs = $<ttype>0;
435: $$ = suspend_momentary (); }
1.1 root 436: ;
437:
438: decl:
439: typed_declspecs setspecs initdecls ';'
1.1.1.2 root 440: { resume_momentary ($2); }
441: | declmods setspecs notype_initdecls ';'
442: { resume_momentary ($2); }
1.1 root 443: | typed_declspecs ';'
444: { shadow_tag ($1); }
1.1.1.2 root 445: | declmods ';'
1.1 root 446: { warning ("empty declaration"); }
447: ;
448:
1.1.1.2 root 449: /* Declspecs which contain at least one type specifier or typedef name.
450: (Just `const' or `volatile' is not enough.)
1.1 root 451: A typedef'd name following these is taken as a name to be declared. */
1.1.1.2 root 452:
1.1 root 453: typed_declspecs:
1.1.1.2 root 454: typespec reserved_declspecs
455: { $$ = tree_cons (NULL_TREE, $1, $2); }
456: | declmods typespec reserved_declspecs
457: { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
458: ;
459:
460: reserved_declspecs: /* empty */
461: { $$ = NULL_TREE; }
462: | reserved_declspecs typespecqual_reserved
1.1 root 463: { $$ = tree_cons (NULL_TREE, $2, $1); }
1.1.1.2 root 464: | reserved_declspecs SCSPEC
1.1 root 465: { $$ = tree_cons (NULL_TREE, $2, $1); }
1.1.1.2 root 466: ;
467:
468: /* List of just storage classes and type modifiers.
469: A declaration can start with just this, but then it cannot be used
470: to redeclare a typedef-name. */
471:
472: declmods:
473: TYPE_QUAL
474: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
475: | SCSPEC
476: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
477: | declmods TYPE_QUAL
1.1 root 478: { $$ = tree_cons (NULL_TREE, $2, $1); }
1.1.1.2 root 479: | declmods SCSPEC
1.1 root 480: { $$ = tree_cons (NULL_TREE, $2, $1); }
481: ;
482:
1.1.1.2 root 483:
484: /* Used instead of declspecs where storage classes are not allowed
485: (that is, for typenames and structure components).
486: Don't accept a typedef-name if anything but a modifier precedes it. */
487:
488: typed_typespecs:
489: typespec reserved_typespecquals
490: { $$ = tree_cons (NULL_TREE, $1, $2); }
491: | nonempty_type_quals typespec reserved_typespecquals
492: { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
1.1 root 493: ;
494:
1.1.1.2 root 495: reserved_typespecquals: /* empty */
496: { $$ = NULL_TREE; }
497: | reserved_typespecquals typespecqual_reserved
1.1 root 498: { $$ = tree_cons (NULL_TREE, $2, $1); }
499: ;
500:
1.1.1.2 root 501: /* A typespec (but not a type qualifier).
502: Once we have seen one of these in a declaration,
503: if a typedef name appears then it is being redeclared. */
504:
1.1 root 505: typespec: TYPESPEC
506: | structsp
507: | TYPENAME
1.1.1.2 root 508: | TYPEOF '(' expr ')'
509: { $$ = TREE_TYPE ($3);
510: if (pedantic)
1.1.1.4 root 511: warning ("ANSI C forbids `typeof'"); }
1.1.1.2 root 512: | TYPEOF '(' typename ')'
513: { $$ = groktypename ($3);
514: if (pedantic)
1.1.1.4 root 515: warning ("ANSI C forbids `typeof'"); }
1.1.1.2 root 516: ;
517:
518: /* A typespec that is a reserved word, or a type qualifier. */
519:
520: typespecqual_reserved: TYPESPEC
521: | TYPE_QUAL
522: | structsp
1.1 root 523: ;
524:
525: initdecls:
526: initdcl
527: | initdecls ',' initdcl
528: ;
529:
530: notype_initdecls:
531: notype_initdcl
532: | notype_initdecls ',' initdcl
533: ;
534:
1.1.1.2 root 535: maybeasm:
536: /* empty */
537: { $$ = NULL_TREE; }
538: | ASM '(' string ')'
539: { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
540: $$ = $3;
541: if (pedantic)
542: warning ("ANSI C forbids use of `asm' keyword");
543: }
544: ;
545:
1.1 root 546: initdcl:
1.1.1.2 root 547: declarator maybeasm '='
1.1 root 548: { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
549: init
550: /* Note how the declaration of the variable is in effect while its init is parsed! */
1.1.1.2 root 551: { finish_decl ($<ttype>4, $5, $2); }
552: | declarator maybeasm
1.1 root 553: { tree d = start_decl ($1, current_declspecs, 0);
1.1.1.2 root 554: finish_decl (d, NULL_TREE, $2); }
1.1 root 555: ;
556:
557: notype_initdcl:
1.1.1.2 root 558: notype_declarator maybeasm '='
1.1 root 559: { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
560: init
561: /* Note how the declaration of the variable is in effect while its init is parsed! */
1.1.1.2 root 562: { finish_decl ($<ttype>4, $5, $2); }
563: | notype_declarator maybeasm
1.1 root 564: { tree d = start_decl ($1, current_declspecs, 0);
1.1.1.2 root 565: finish_decl (d, NULL_TREE, $2); }
1.1 root 566: ;
567:
568: init:
569: expr_no_commas
570: | '{' initlist '}'
1.1.1.2 root 571: { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
1.1 root 572: | '{' initlist ',' '}'
1.1.1.2 root 573: { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
574: | error
575: { $$ = NULL_TREE; }
1.1 root 576: ;
577:
578: /* This chain is built in reverse order,
579: and put in forward order where initlist is used. */
580: initlist:
581: init
582: { $$ = build_tree_list (NULL_TREE, $1); }
583: | initlist ',' init
1.1.1.2 root 584: { $$ = tree_cons (NULL_TREE, $3, $1); }
1.1 root 585: ;
586:
587: /* Any kind of declarator (thus, all declarators allowed
588: after an explicit typespec). */
589:
590: declarator:
591: after_type_declarator
592: | notype_declarator
593: ;
594:
595: /* A declarator that is allowed only after an explicit typespec. */
596:
597: after_type_declarator:
1.1.1.2 root 598: '(' after_type_declarator ')'
599: { $$ = $2; }
600: | after_type_declarator '(' parmlist_or_identifiers %prec '.'
601: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
602: /* | after_type_declarator '(' error ')' %prec '.'
603: { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
604: poplevel (0, 0, 0); } */
1.1 root 605: | after_type_declarator '[' expr ']' %prec '.'
1.1.1.2 root 606: { $$ = build_nt (ARRAY_REF, $1, $3); }
1.1 root 607: | after_type_declarator '[' ']' %prec '.'
1.1.1.2 root 608: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
609: | '*' type_quals after_type_declarator %prec UNARY
610: { $$ = make_pointer_declarator ($2, $3); }
611: | TYPENAME
612: ;
613:
614: /* Kinds of declarator that can appear in a parameter list
615: in addition to notype_declarator. This is like after_type_declarator
616: but does not allow a typedef name in parentheses as an identifier
617: (because it would conflict with a function with that typedef as arg). */
618:
619: parm_declarator:
620: parm_declarator '(' parmlist_or_identifiers %prec '.'
621: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
622: /* | parm_declarator '(' error ')' %prec '.'
623: { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
624: poplevel (0, 0, 0); } */
625: | parm_declarator '[' expr ']' %prec '.'
626: { $$ = build_nt (ARRAY_REF, $1, $3); }
627: | parm_declarator '[' ']' %prec '.'
628: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
629: | '*' type_quals parm_declarator %prec UNARY
630: { $$ = make_pointer_declarator ($2, $3); }
1.1 root 631: | TYPENAME
632: ;
633:
634: /* A declarator allowed whether or not there has been
635: an explicit typespec. These cannot redeclare a typedef-name. */
636:
637: notype_declarator:
1.1.1.2 root 638: notype_declarator '(' parmlist_or_identifiers %prec '.'
639: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
640: /* | notype_declarator '(' error ')' %prec '.'
641: { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
642: poplevel (0, 0, 0); } */
1.1 root 643: | '(' notype_declarator ')'
644: { $$ = $2; }
1.1.1.2 root 645: | '*' type_quals notype_declarator %prec UNARY
1.1 root 646: { $$ = make_pointer_declarator ($2, $3); }
647: | notype_declarator '[' expr ']' %prec '.'
1.1.1.2 root 648: { $$ = build_nt (ARRAY_REF, $1, $3); }
1.1 root 649: | notype_declarator '[' ']' %prec '.'
1.1.1.2 root 650: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
1.1 root 651: | IDENTIFIER
652: ;
653:
654: structsp:
1.1.1.2 root 655: STRUCT identifier '{'
656: { $$ = start_struct (RECORD_TYPE, $2);
657: /* Start scope of tag before parsing components. */
658: }
659: component_decl_list '}'
660: { $$ = finish_struct ($<ttype>4, $5);
661: /* Really define the structure. */
662: }
1.1 root 663: | STRUCT '{' component_decl_list '}'
1.1.1.2 root 664: { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
665: $3); }
1.1 root 666: | STRUCT identifier
1.1.1.2 root 667: { $$ = xref_tag (RECORD_TYPE, $2); }
668: | UNION identifier '{'
669: { $$ = start_struct (UNION_TYPE, $2); }
670: component_decl_list '}'
671: { $$ = finish_struct ($<ttype>4, $5); }
1.1 root 672: | UNION '{' component_decl_list '}'
1.1.1.2 root 673: { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
674: $3); }
1.1 root 675: | UNION identifier
1.1.1.2 root 676: { $$ = xref_tag (UNION_TYPE, $2); }
1.1 root 677: | ENUM identifier '{'
1.1.1.2 root 678: { $<itype>3 = suspend_momentary ();
679: $$ = start_enum ($2); }
680: enumlist maybecomma '}'
681: { $$ = finish_enum ($<ttype>4, nreverse ($5));
682: resume_momentary ($<itype>3); }
1.1 root 683: | ENUM '{'
1.1.1.2 root 684: { $<itype>2 = suspend_momentary ();
685: $$ = start_enum (NULL_TREE); }
686: enumlist maybecomma '}'
687: { $$ = finish_enum ($<ttype>3, nreverse ($4));
688: resume_momentary ($<itype>2); }
1.1 root 689: | ENUM identifier
1.1.1.2 root 690: { $$ = xref_tag (ENUMERAL_TYPE, $2); }
691: ;
692:
693: maybecomma:
694: /* empty */
695: | ','
1.1 root 696: ;
697:
698: component_decl_list: /* empty */
699: { $$ = NULL_TREE; }
1.1.1.2 root 700: | component_decl_list component_decl ';'
701: { $$ = chainon ($1, $2); }
1.1 root 702: | component_decl_list ';'
1.1.1.2 root 703: { if (pedantic)
704: warning ("extra semicolon in struct or union specified"); }
1.1 root 705: ;
706:
1.1.1.2 root 707: /* There is a shift-reduce conflict here, because `components' may
708: start with a `typename'. It happens that shifting (the default resolution)
709: does the right thing, because it treats the `typename' as part of
710: a `typed_typespecs'.
711:
712: It is possible that this same technique would allow the distinction
713: between `notype_initdecls' and `initdecls' to be eliminated.
714: But I am being cautious and not trying it. */
715:
1.1 root 716: component_decl:
1.1.1.2 root 717: typed_typespecs setspecs components
718: { $$ = $3;
719: resume_momentary ($2); }
720: | nonempty_type_quals setspecs components
721: { $$ = $3;
722: resume_momentary ($2); }
1.1 root 723: | error
1.1.1.2 root 724: { $$ = NULL_TREE; }
1.1 root 725: ;
726:
727: components:
728: /* empty */
729: { $$ = NULL_TREE; }
730: | component_declarator
731: | components ',' component_declarator
732: { $$ = chainon ($1, $3); }
733: ;
734:
735: component_declarator:
736: declarator
1.1.1.3 root 737: { $$ = grokfield (input_filename, lineno, $1, current_declspecs, NULL_TREE); }
1.1 root 738: | declarator ':' expr_no_commas
1.1.1.3 root 739: { $$ = grokfield (input_filename, lineno, $1, current_declspecs, $3); }
1.1 root 740: | ':' expr_no_commas
1.1.1.3 root 741: { $$ = grokfield (input_filename, lineno, NULL_TREE, current_declspecs, $2); }
1.1 root 742: ;
743:
744: /* We chain the enumerators in reverse order.
745: They are put in forward order where enumlist is used.
746: (The order used to be significant, but no longer is so.
747: However, we still maintain the order, just to be clean.) */
748:
749: enumlist:
750: enumerator
751: | enumlist ',' enumerator
752: { $$ = chainon ($3, $1); }
753: ;
754:
755:
756: enumerator:
757: identifier
758: { $$ = build_enumerator ($1, NULL_TREE); }
759: | identifier '=' expr_no_commas
760: { $$ = build_enumerator ($1, $3); }
761: ;
762:
763: typename:
1.1.1.2 root 764: typed_typespecs absdcl
765: { $$ = build_tree_list ($1, $2); }
766: | nonempty_type_quals absdcl
1.1 root 767: { $$ = build_tree_list ($1, $2); }
768: ;
769:
770: absdcl: /* an absolute declarator */
771: /* empty */
772: { $$ = NULL_TREE; }
773: | absdcl1
774: ;
775:
1.1.1.2 root 776: nonempty_type_quals:
777: TYPE_QUAL
778: { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
779: | nonempty_type_quals TYPE_QUAL
780: { $$ = tree_cons (NULL_TREE, $2, $1); }
781: ;
782:
783: type_quals:
1.1 root 784: /* empty */
785: { $$ = NULL_TREE; }
1.1.1.2 root 786: | type_quals TYPE_QUAL
1.1 root 787: { $$ = tree_cons (NULL_TREE, $2, $1); }
788: ;
789:
790: absdcl1: /* a nonempty absolute declarator */
791: '(' absdcl1 ')'
792: { $$ = $2; }
1.1.1.2 root 793: /* `(typedef)1' is `int'. */
794: | '*' type_quals absdcl1 %prec UNARY
1.1 root 795: { $$ = make_pointer_declarator ($2, $3); }
1.1.1.2 root 796: | '*' type_quals %prec UNARY
1.1 root 797: { $$ = make_pointer_declarator ($2, NULL_TREE); }
1.1.1.2 root 798: | absdcl1 '(' parmlist %prec '.'
799: { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
1.1 root 800: | absdcl1 '[' expr ']' %prec '.'
1.1.1.2 root 801: { $$ = build_nt (ARRAY_REF, $1, $3); }
1.1 root 802: | absdcl1 '[' ']' %prec '.'
1.1.1.2 root 803: { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
804: | '(' parmlist %prec '.'
805: { $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); }
1.1 root 806: | '[' expr ']' %prec '.'
1.1.1.2 root 807: { $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
1.1 root 808: | '[' ']' %prec '.'
1.1.1.2 root 809: { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
1.1 root 810: ;
811:
812: /* at least one statement, the first of which parses without error. */
813: /* stmts is used only after decls, so an invalid first statement
814: is actually regarded as an invalid decl and part of the decls. */
815:
816: stmts:
817: stmt
818: | stmts stmt
819: | stmts errstmt
820: ;
821:
1.1.1.2 root 822: xstmts:
823: /* empty */
824: | stmts
1.1 root 825: ;
826:
1.1.1.2 root 827: errstmt: error ';'
828: ;
1.1 root 829:
830: pushlevel: /* empty */
1.1.1.2 root 831: { pushlevel (0);
832: clear_last_expr ();
833: push_momentary ();
834: expand_start_bindings (0); }
1.1 root 835: ;
836:
1.1.1.4 root 837: /* This is the body of a function definition.
838: It causes syntax errors to ignore to the next openbrace. */
839: compstmt_or_error:
840: compstmt
841: | error compstmt
842: ;
843:
1.1 root 844: compstmt: '{' '}'
1.1.1.2 root 845: | '{' pushlevel decls xstmts '}'
846: { expand_end_bindings (getdecls (), 1);
847: poplevel (1, 1, 0);
848: pop_momentary (); }
1.1 root 849: | '{' pushlevel error '}'
1.1.1.2 root 850: { expand_end_bindings (getdecls (), 0);
851: poplevel (0, 0, 0);
852: pop_momentary (); }
1.1 root 853: | '{' pushlevel stmts '}'
1.1.1.2 root 854: { expand_end_bindings (getdecls (), 0);
855: poplevel (0, 0, 0);
856: pop_momentary (); }
1.1 root 857: ;
858:
1.1.1.2 root 859: simple_if:
860: IF '(' expr ')'
1.1.1.3 root 861: { emit_note (input_filename, lineno);
1.1.1.2 root 862: expand_start_cond (truthvalue_conversion ($3), 0); }
863: stmt
864: ;
865:
866: stmt:
867: compstmt
1.1 root 868: | expr ';'
1.1.1.3 root 869: { emit_note (input_filename, lineno);
1.1.1.2 root 870: expand_expr_stmt ($1);
871: clear_momentary (); }
872: | simple_if ELSE
873: { expand_start_else (); }
874: stmt
875: { expand_end_else (); }
876: | simple_if
877: { expand_end_cond (); }
1.1 root 878: | WHILE
1.1.1.3 root 879: { emit_note (input_filename, lineno);
1.1.1.2 root 880: expand_start_loop (1); }
881: '(' expr ')'
1.1.1.3 root 882: { emit_note (input_filename, lineno);
883: expand_exit_loop_if_false (truthvalue_conversion ($4)); }
1.1.1.2 root 884: stmt
885: { expand_end_loop (); }
1.1 root 886: | DO
1.1.1.3 root 887: { emit_note (input_filename, lineno);
1.1.1.2 root 888: expand_start_loop_continue_elsewhere (1); }
889: stmt WHILE
890: { expand_loop_continue_here (); }
891: '(' expr ')' ';'
1.1.1.3 root 892: { emit_note (input_filename, lineno);
1.1.1.2 root 893: expand_exit_loop_if_false (truthvalue_conversion ($7));
894: expand_end_loop ();
895: clear_momentary (); }
1.1 root 896: | FOR
1.1.1.2 root 897: '(' xexpr ';'
1.1.1.3 root 898: { emit_note (input_filename, lineno);
1.1.1.2 root 899: if ($3) expand_expr_stmt ($3);
900: expand_start_loop_continue_elsewhere (1); }
901: xexpr ';'
1.1.1.3 root 902: { emit_note (input_filename, lineno);
1.1.1.2 root 903: if ($6)
904: expand_exit_loop_if_false (truthvalue_conversion ($6)); }
905: xexpr ')'
906: /* Don't let the tree nodes for $9 be discarded
907: by clear_momentary during the parsing of the next stmt. */
1.1.1.3 root 908: { push_momentary ();
909: $<itype>10 = lineno; }
1.1.1.2 root 910: stmt
1.1.1.3 root 911: { emit_note (input_filename, $<itype>10);
1.1.1.2 root 912: expand_loop_continue_here ();
913: if ($9)
1.1.1.3 root 914: expand_expr_stmt ($9);
1.1.1.2 root 915: pop_momentary ();
916: expand_end_loop (); }
1.1 root 917: | SWITCH '(' expr ')'
1.1.1.3 root 918: { emit_note (input_filename, lineno);
1.1.1.2 root 919: c_expand_start_case ($3);
920: /* Don't let the tree nodes for $3 be discarded by
921: clear_momentary during the parsing of the next stmt. */
922: push_momentary (); }
1.1 root 923: stmt
1.1.1.2 root 924: { expand_end_case ();
925: pop_momentary (); }
926: | CASE expr ':'
927: { register tree value = fold ($2);
928: register tree label
929: = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
1.1 root 930:
1.1.1.2 root 931: if (TREE_CODE (value) != INTEGER_CST
932: && value != error_mark_node)
1.1 root 933: {
1.1.1.2 root 934: error ("case label does not reduce to an integer constant");
1.1 root 935: value = error_mark_node;
936: }
937: else
1.1.1.2 root 938: /* Promote char or short to int. */
939: value = default_conversion (value);
940: if (value != error_mark_node)
1.1 root 941: {
1.1.1.2 root 942: int success = pushcase (value, label);
943: if (success == 1)
944: error ("case label not within a switch statement");
945: else if (success == 2)
946: error ("duplicate case value");
947: else if (success == 3)
948: warning ("case value out of range");
1.1 root 949: }
950: }
1.1.1.2 root 951: stmt
952: | DEFAULT ':'
953: {
954: register tree label
955: = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
956: int success = pushcase (NULL_TREE, label);
957: if (success == 1)
958: error ("default label not within a switch statement");
959: else if (success == 2)
960: error ("multiple default labels in one switch");
1.1 root 961: }
1.1.1.2 root 962: stmt
963: | BREAK ';'
1.1.1.3 root 964: { emit_note (input_filename, lineno);
1.1.1.2 root 965: if ( ! expand_exit_something ())
966: error ("break statement not within loop or switch"); }
967: | CONTINUE ';'
1.1.1.3 root 968: { emit_note (input_filename, lineno);
1.1.1.2 root 969: if (! expand_continue_loop ())
970: error ("continue statement not within a loop"); }
1.1 root 971: | RETURN ';'
1.1.1.3 root 972: { emit_note (input_filename, lineno);
1.1.1.2 root 973: c_expand_return (NULL_TREE); }
1.1 root 974: | RETURN expr ';'
1.1.1.3 root 975: { emit_note (input_filename, lineno);
1.1.1.2 root 976: c_expand_return ($2); }
977: | ASM maybe_type_qual '(' string ')' ';'
978: { if (pedantic)
979: warning ("ANSI C forbids use of `asm' keyword");
980: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
981: expand_asm ($4); }
982: /* This is the case with just output operands. */
983: | ASM maybe_type_qual '(' string ':' asm_operands ')' ';'
984: { if (pedantic)
985: warning ("ANSI C forbids use of `asm' keyword");
986: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
987: c_expand_asm_operands ($4, $6, NULL_TREE,
988: $2 == ridpointers[(int)RID_VOLATILE]); }
989: /* This is the case with input operands as well. */
990: | ASM maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';'
991: { if (pedantic)
992: warning ("ANSI C forbids use of `asm' keyword");
993: if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
994: c_expand_asm_operands ($4, $6, $8,
995: $2 == ridpointers[(int)RID_VOLATILE]); }
1.1 root 996: | GOTO identifier ';'
1.1.1.2 root 997: { tree decl;
1.1.1.3 root 998: emit_note (input_filename, lineno);
1.1.1.2 root 999: decl = lookup_label ($2);
1000: expand_goto (decl); }
1001: | identifier ':'
1.1.1.3 root 1002: { tree label = define_label (input_filename, lineno, $1);
1.1.1.2 root 1003: if (label)
1004: expand_label (label); }
1005: stmt
1.1 root 1006: | ';'
1.1.1.2 root 1007: ;
1008:
1009: maybe_type_qual:
1010: /* empty */
1.1.1.3 root 1011: { emit_note (input_filename, lineno); }
1.1.1.2 root 1012: | TYPE_QUAL
1.1.1.3 root 1013: { emit_note (input_filename, lineno); }
1.1 root 1014: ;
1015:
1016: xexpr:
1017: /* empty */
1018: { $$ = NULL_TREE; }
1019: | expr
1020: ;
1021:
1.1.1.4 root 1022: /* These are the operands other than the first string and colon
1023: in asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x)) */
1024: asm_operands: /* empty */
1025: { $$ = NULL_TREE; }
1026: | nonnull_asm_operands
1027: ;
1028:
1029: nonnull_asm_operands:
1030: asm_operand
1031: | nonnull_asm_operands ',' asm_operand
1.1.1.2 root 1032: { $$ = chainon ($1, $3); }
1033: ;
1034:
1035: asm_operand:
1.1.1.4 root 1036: STRING '(' expr ')'
1.1.1.2 root 1037: { $$ = build_tree_list ($1, $3); }
1038: ;
1039:
1.1 root 1040: /* This is what appears inside the parens in a function declarator.
1.1.1.3 root 1041: Its value is a list of ..._TYPE nodes. */
1.1.1.2 root 1042: parmlist:
1043: { pushlevel (0); }
1044: parmlist_1
1.1.1.3 root 1045: { $$ = $2; poplevel (0, 0, 0); }
1.1.1.2 root 1046: ;
1047:
1048: /* This is referred to where either a parmlist or an identifier list is ok.
1.1.1.3 root 1049: Its value is a list of ..._TYPE nodes or a list of identifiers. */
1.1.1.2 root 1050: parmlist_or_identifiers:
1051: { pushlevel (0); }
1052: parmlist_or_identifiers_1
1053: { $$ = $2; poplevel (0, 0, 0); }
1054: ;
1055:
1056: parmlist_or_identifiers_1:
1057: parmlist_2 ')'
1058: | identifiers ')'
1.1.1.3 root 1059: { $$ = tree_cons (NULL_TREE, NULL_TREE, $1); }
1.1.1.2 root 1060: | error ')'
1.1.1.3 root 1061: { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
1.1.1.2 root 1062: ;
1063:
1064: parmlist_1:
1065: parmlist_2 ')'
1066: | error ')'
1.1.1.3 root 1067: { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
1.1.1.2 root 1068: ;
1069:
1070: /* This is what appears inside the parens in a function declarator.
1071: Is value is represented in the format that grokdeclarator expects. */
1072: parmlist_2: /* empty */
1.1.1.3 root 1073: { $$ = get_parm_info (0); }
1.1 root 1074: | parms
1.1.1.3 root 1075: { $$ = get_parm_info (1); }
1.1 root 1076: | parms ',' ELLIPSIS
1.1.1.3 root 1077: { $$ = get_parm_info (0); }
1.1 root 1078: ;
1079:
1080: parms:
1081: parm
1.1.1.2 root 1082: { push_parm_decl ($1); }
1.1 root 1083: | parms ',' parm
1.1.1.2 root 1084: { push_parm_decl ($3); }
1.1 root 1085: ;
1086:
1.1.1.2 root 1087: /* A single parameter declaration or parameter type name,
1088: as found in a parmlist. */
1.1 root 1089: parm:
1.1.1.2 root 1090: typed_declspecs parm_declarator
1091: { $$ = build_tree_list ($1, $2) ; }
1092: | typed_declspecs notype_declarator
1.1 root 1093: { $$ = build_tree_list ($1, $2) ; }
1.1.1.2 root 1094: | typed_declspecs absdcl
1095: { $$ = build_tree_list ($1, $2); }
1096: | declmods notype_declarator
1097: { $$ = build_tree_list ($1, $2) ; }
1098: | declmods absdcl
1.1 root 1099: { $$ = build_tree_list ($1, $2); }
1100: ;
1101:
1102: /* A nonempty list of identifiers. */
1103: identifiers:
1104: IDENTIFIER
1105: { $$ = build_tree_list (NULL_TREE, $1); }
1106: | identifiers ',' IDENTIFIER
1107: { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
1108: ;
1109: %%
1110:
1111: /* Return something to represent absolute declarators containing a *.
1112: TARGET is the absolute declarator that the * contains.
1.1.1.2 root 1113: TYPE_QUALS is a list of modifiers such as const or volatile
1.1 root 1114: to apply to the pointer type, represented as identifiers.
1115:
1116: We return an INDIRECT_REF whose "contents" are TARGET
1117: and whose type is the modifier list. */
1118:
1119: static tree
1.1.1.2 root 1120: make_pointer_declarator (type_quals, target)
1121: tree type_quals, target;
1.1 root 1122: {
1.1.1.2 root 1123: return build (INDIRECT_REF, type_quals, target);
1.1 root 1124: }
1125:
1126: /* Given a chain of STRING_CST nodes,
1127: concatenate them into one STRING_CST
1.1.1.2 root 1128: and give it a suitable array-of-chars data type. */
1.1 root 1129:
1130: static tree
1131: combine_strings (strings)
1132: tree strings;
1133: {
1134: register tree value, t;
1.1.1.2 root 1135: register int length = 1;
1136: int wide_length = 0;
1137: int wide_flag = 0;
1.1 root 1138:
1139: if (TREE_CHAIN (strings))
1140: {
1141: /* More than one in the chain, so concatenate. */
1142: register char *p, *q;
1143:
1144: /* Don't include the \0 at the end of each substring,
1.1.1.2 root 1145: except for the last one.
1146: Count wide strings and ordinary strings separately. */
1.1 root 1147: for (t = strings; t; t = TREE_CHAIN (t))
1.1.1.2 root 1148: {
1149: if (TREE_TYPE (t) == int_array_type_node)
1150: {
1151: wide_length += (TREE_STRING_LENGTH (t) - 1);
1152: wide_flag = 1;
1153: }
1154: else
1155: length += (TREE_STRING_LENGTH (t) - 1);
1156: }
1157:
1158: /* If anything is wide, the non-wides will be converted,
1159: which makes them take more space. */
1160: if (wide_flag)
1161: length = length * UNITS_PER_WORD + wide_length;
1.1 root 1162:
1163: p = (char *) oballoc (length);
1164:
1.1.1.2 root 1165: /* Copy the individual strings into the new combined string.
1166: If the combined string is wide, convert the chars to ints
1167: for any individual strings that are not wide. */
1168:
1.1 root 1169: q = p;
1170: for (t = strings; t; t = TREE_CHAIN (t))
1171: {
1.1.1.2 root 1172: int len = TREE_STRING_LENGTH (t) - 1;
1173: if ((TREE_TYPE (t) == int_array_type_node) == wide_flag)
1174: {
1175: bcopy (TREE_STRING_POINTER (t), q, len);
1176: q += len;
1177: }
1178: else
1179: {
1180: int i;
1181: for (i = 0; i < len; i++)
1182: ((int *) q)[i] = TREE_STRING_POINTER (t)[i];
1183: q += len * UNITS_PER_WORD;
1184: }
1.1 root 1185: }
1186: *q = 0;
1187:
1188: value = make_node (STRING_CST);
1189: TREE_STRING_POINTER (value) = p;
1190: TREE_STRING_LENGTH (value) = length;
1191: TREE_LITERAL (value) = 1;
1192: }
1193: else
1.1.1.2 root 1194: {
1195: value = strings;
1196: length = TREE_STRING_LENGTH (value);
1197: if (TREE_TYPE (value) == int_array_type_node)
1198: wide_flag = 1;
1199: }
1.1 root 1200:
1.1.1.2 root 1201: TREE_TYPE (value)
1202: = build_array_type (wide_flag ? integer_type_node : char_type_node,
1203: make_index_type (build_int_2 (length - 1, 0)));
1.1 root 1204: TREE_LITERAL (value) = 1;
1.1.1.2 root 1205: TREE_STATIC (value) = 1;
1.1 root 1206: return value;
1207: }
1208:
1209: int lineno; /* current line number in file being read */
1210:
1211: FILE *finput; /* input file.
1212: Normally a pipe from the preprocessor. */
1213:
1214: /* lexical analyzer */
1215:
1.1.1.2 root 1216: static int maxtoken; /* Current nominal length of token buffer */
1217: static char *token_buffer; /* Pointer to token buffer.
1218: Actual allocated length is maxtoken + 2. */
1.1 root 1219:
1220: #define MAXRESERVED 9
1221:
1.1.1.2 root 1222: /* frw[I] is index in `reswords' of the first word whose length is I;
1223: frw[I+1] is one plus the index of the last word whose length is I.
1224: The length of frw must be MAXRESERVED + 2 so there is an element
1225: at MAXRESERVED+1 for the case I == MAXRESERVED. */
1226:
1227: static char frw[MAXRESERVED+2] =
1.1.1.4 root 1228: { 0, 0, 0, 2, 5, 13, 19, 29, 31, 35, 36 };
1.1.1.2 root 1229:
1230: /* Table of reserved words. */
1231:
1232: struct resword { char *name; short token; enum rid rid;};
1233:
1234: #define NORID RID_UNUSED
1235:
1236: static struct resword reswords[]
1237: = {{"if", IF, NORID},
1238: {"do", DO, NORID},
1239: {"int", TYPESPEC, RID_INT},
1240: {"for", FOR, NORID},
1241: {"asm", ASM, NORID},
1242: {"case", CASE, NORID},
1243: {"char", TYPESPEC, RID_CHAR},
1244: {"auto", SCSPEC, RID_AUTO},
1245: {"goto", GOTO, NORID},
1246: {"else", ELSE, NORID},
1247: {"long", TYPESPEC, RID_LONG},
1248: {"void", TYPESPEC, RID_VOID},
1249: {"enum", ENUM, NORID},
1250: {"float", TYPESPEC, RID_FLOAT},
1251: {"short", TYPESPEC, RID_SHORT},
1252: {"union", UNION, NORID},
1253: {"break", BREAK, NORID},
1254: {"while", WHILE, NORID},
1255: {"const", TYPE_QUAL, RID_CONST},
1256: {"double", TYPESPEC, RID_DOUBLE},
1257: {"static", SCSPEC, RID_STATIC},
1258: {"extern", SCSPEC, RID_EXTERN},
1259: {"struct", STRUCT, NORID},
1260: {"return", RETURN, NORID},
1261: {"sizeof", SIZEOF, NORID},
1262: {"typeof", TYPEOF, NORID},
1263: {"switch", SWITCH, NORID},
1264: {"signed", TYPESPEC, RID_SIGNED},
1265: {"inline", SCSPEC, RID_INLINE},
1266: {"typedef", SCSPEC, RID_TYPEDEF},
1267: {"default", DEFAULT, NORID},
1268: {"unsigned", TYPESPEC, RID_UNSIGNED},
1269: {"continue", CONTINUE, NORID},
1270: {"register", SCSPEC, RID_REGISTER},
1271: {"volatile", TYPE_QUAL, RID_VOLATILE},
1272: {"__alignof", ALIGNOF, NORID}};
1.1 root 1273:
1274: /* The elements of `ridpointers' are identifier nodes
1.1.1.2 root 1275: for the reserved type names and storage classes.
1276: It is indexed by a RID_... value. */
1.1 root 1277:
1278: tree ridpointers[(int) RID_MAX];
1279:
1.1.1.4 root 1280: int check_newline ();
1.1 root 1281:
1282: void
1.1.1.2 root 1283: init_lex ()
1.1 root 1284: {
1.1.1.2 root 1285: extern char *malloc ();
1.1 root 1286:
1.1.1.2 root 1287: /* Start it at 0, because check_newline is called at the very beginning
1.1 root 1288: and will increment it to 1. */
1289: lineno = 0;
1290:
1291: maxtoken = 40;
1.1.1.2 root 1292: token_buffer = malloc (maxtoken + 2);
1293: ridpointers[(int) RID_INT] = get_identifier ("int");
1294: ridpointers[(int) RID_CHAR] = get_identifier ("char");
1295: ridpointers[(int) RID_VOID] = get_identifier ("void");
1296: ridpointers[(int) RID_FLOAT] = get_identifier ("float");
1297: ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
1298: ridpointers[(int) RID_SHORT] = get_identifier ("short");
1299: ridpointers[(int) RID_LONG] = get_identifier ("long");
1300: ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
1301: ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
1302: ridpointers[(int) RID_INLINE] = get_identifier ("inline");
1303: ridpointers[(int) RID_CONST] = get_identifier ("const");
1304: ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
1305: ridpointers[(int) RID_AUTO] = get_identifier ("auto");
1306: ridpointers[(int) RID_STATIC] = get_identifier ("static");
1307: ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
1308: ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
1309: ridpointers[(int) RID_REGISTER] = get_identifier ("register");
1310: }
1311:
1312: static void
1313: reinit_parse_for_function ()
1314: {
1.1 root 1315: }
1316:
1.1.1.4 root 1317: /* If C is not whitespace, return C.
1318: Otherwise skip whitespace and return first nonwhite char read. */
1319:
1.1 root 1320: static int
1.1.1.4 root 1321: skip_white_space (c)
1322: register int c;
1.1 root 1323: {
1324: register int inside;
1325:
1326: for (;;)
1327: {
1328: switch (c)
1329: {
1330: case '/':
1.1.1.2 root 1331: c = getc (finput);
1.1 root 1332: if (c != '*')
1333: {
1.1.1.2 root 1334: ungetc (c, finput);
1.1 root 1335: return '/';
1336: }
1337:
1.1.1.2 root 1338: c = getc (finput);
1.1 root 1339:
1340: inside = 1;
1341: while (inside)
1342: {
1343: if (c == '*')
1344: {
1345: while (c == '*')
1.1.1.2 root 1346: c = getc (finput);
1.1 root 1347:
1348: if (c == '/')
1349: {
1350: inside = 0;
1.1.1.2 root 1351: c = getc (finput);
1.1 root 1352: }
1353: }
1354: else if (c == '\n')
1355: {
1356: lineno++;
1.1.1.2 root 1357: c = getc (finput);
1.1 root 1358: }
1359: else if (c == EOF)
1.1.1.2 root 1360: {
1361: error ("unterminated comment");
1362: break;
1363: }
1.1 root 1364: else
1.1.1.2 root 1365: c = getc (finput);
1.1 root 1366: }
1367:
1368: break;
1369:
1370: case '\n':
1.1.1.4 root 1371: c = check_newline ();
1372: break;
1.1 root 1373:
1374: case ' ':
1375: case '\t':
1376: case '\f':
1377: case '\r':
1378: case '\b':
1.1.1.2 root 1379: c = getc (finput);
1.1 root 1380: break;
1381:
1382: case '\\':
1.1.1.2 root 1383: c = getc (finput);
1.1 root 1384: if (c == '\n')
1385: lineno++;
1386: else
1.1.1.2 root 1387: error ("stray '\\' in program");
1388: c = getc (finput);
1.1 root 1389: break;
1390:
1391: default:
1392: return (c);
1393: }
1394: }
1395: }
1396:
1397:
1398:
1.1.1.2 root 1399: /* Make the token buffer longer, preserving the data in it.
1400: P should point to just beyond the last valid character in the old buffer.
1401: The value we return is a pointer to the new buffer
1402: at a place corresponding to P. */
1.1 root 1403:
1404: static char *
1.1.1.2 root 1405: extend_token_buffer (p)
1406: char *p;
1.1 root 1407: {
1.1.1.2 root 1408: int offset = p - token_buffer;
1.1 root 1409:
1.1.1.2 root 1410: maxtoken = maxtoken * 2 + 10;
1411: token_buffer = (char *) realloc (token_buffer, maxtoken + 2);
1412: if (token_buffer == 0)
1413: fatal ("virtual memory exceeded");
1.1 root 1414:
1.1.1.2 root 1415: return token_buffer + offset;
1.1 root 1416: }
1.1.1.4 root 1417:
1.1.1.2 root 1418: /* At the beginning of a line, increment the line number
1.1.1.4 root 1419: and handle a #line directive immediately following.
1420: Return first nonwhite char of first non-# line following. */
1.1 root 1421:
1.1.1.4 root 1422: int
1.1 root 1423: check_newline ()
1424: {
1425: register int c;
1426: register int token;
1427:
1428: while (1)
1429: {
1430: lineno++;
1431:
1.1.1.2 root 1432: /* Read first nonwhite char on the line. */
1433:
1434: c = getc (finput);
1435: while (c == ' ' || c == '\t')
1436: c = getc (finput);
1437:
1.1 root 1438: if (c != '#')
1439: {
1.1.1.4 root 1440: /* If not #, return it so caller will use it. */
1441: return c;
1.1 root 1442: }
1443:
1.1.1.2 root 1444: /* Read first nonwhite char after the `#'. */
1.1 root 1445:
1.1.1.2 root 1446: c = getc (finput);
1447: while (c == ' ' || c == '\t')
1448: c = getc (finput);
1449:
1450: /* If a letter follows, then if the word here is `line', skip
1451: it and ignore it; otherwise, ignore the line, with an error
1452: if the word isn't `pragma'. */
1453:
1454: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
1.1 root 1455: {
1.1.1.2 root 1456: if (c == 'p')
1457: {
1458: if (getc (finput) == 'r'
1459: && getc (finput) == 'a'
1460: && getc (finput) == 'g'
1461: && getc (finput) == 'm'
1462: && getc (finput) == 'a'
1463: && ((c = getc (finput)) == ' ' || c == '\t'))
1464: goto noerror;
1465: }
1466:
1467: else if (c == 'l')
1468: {
1469: if (getc (finput) == 'i'
1470: && getc (finput) == 'n'
1471: && getc (finput) == 'e'
1472: && ((c = getc (finput)) == ' ' || c == '\t'))
1473: goto linenum;
1474: }
1475:
1476: error ("undefined or invalid # directive");
1477: noerror:
1478:
1479: while ((c = getc (finput)) && c != '\n');
1480:
1481: continue;
1.1 root 1482: }
1483:
1.1.1.2 root 1484: linenum:
1485: /* Here we have either `#line' or `# <nonletter>'.
1.1.1.4 root 1486: In either case, it should be a line number; a digit should follow. */
1.1.1.2 root 1487:
1488: while (c == ' ' || c == '\t')
1489: c = getc (finput);
1490:
1.1 root 1491: /* If the # is the only nonwhite char on the line,
1492: just ignore it. Check the new newline. */
1493: if (c == '\n')
1494: continue;
1495:
1496: /* Something follows the #; read a token. */
1497:
1498: ungetc (c, finput);
1499: token = yylex ();
1500:
1501: if (token == CONSTANT
1502: && TREE_CODE (yylval.ttype) == INTEGER_CST)
1503: {
1504: /* subtract one, because it is the following line that
1505: gets the specified number */
1506:
1507: int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
1508:
1.1.1.2 root 1509: /* Is this the last nonwhite stuff on the line? */
1510: c = getc (finput);
1511: while (c == ' ' || c == '\t')
1512: c = getc (finput);
1513: if (c == '\n')
1514: {
1515: /* No more: store the line number and check following line. */
1516: lineno = l;
1517: continue;
1518: }
1519: ungetc (c, finput);
1520:
1521: /* More follows: it must be a string constant (filename). */
1522:
1.1 root 1523: token = yylex ();
1524: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1.1.1.2 root 1525: {
1526: error ("invalid #line");
1.1.1.4 root 1527: return getc (finput);
1.1.1.2 root 1528: }
1.1 root 1529:
1530: input_filename
1531: = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
1532: strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
1533: lineno = l;
1.1.1.2 root 1534:
1535: if (main_input_filename == 0)
1536: main_input_filename = input_filename;
1.1 root 1537: }
1538: else
1.1.1.2 root 1539: error ("invalid #line");
1.1 root 1540:
1541: /* skip the rest of this line. */
1542: while ((c = getc (finput)) != '\n');
1543: }
1544: }
1.1.1.4 root 1545:
1.1 root 1546: #define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9'))
1547: #define isdigit(char) (char >= '0' && char <= '9')
1548: #define ENDFILE -1 /* token that represents end-of-file */
1549:
1550:
1551: static int
1552: readescape ()
1553: {
1554: register int c = getc (finput);
1555: register int count, code;
1556:
1557: switch (c)
1558: {
1559: case 'x':
1560: code = 0;
1561: count = 0;
1562: while (1)
1563: {
1564: c = getc (finput);
1565: if (!(c >= 'a' && c <= 'f')
1566: && !(c >= 'A' && c <= 'F')
1567: && !(c >= '0' && c <= '9'))
1568: {
1569: ungetc (c, finput);
1570: break;
1571: }
1572: code *= 16;
1573: if (c >= 'a' && c <= 'f')
1574: code += c - 'a' + 10;
1575: if (c >= 'A' && c <= 'F')
1576: code += c - 'A' + 10;
1577: if (c >= '0' && c <= '9')
1578: code += c - '0';
1579: count++;
1580: }
1581: if (count == 0)
1.1.1.2 root 1582: error ("\\x used with no following hex digits");
1.1 root 1583: return code;
1584:
1585: case '0': case '1': case '2': case '3': case '4':
1586: case '5': case '6': case '7':
1587: code = 0;
1588: count = 0;
1589: while ((c <= '7') && (c >= '0') && (count++ < 3))
1590: {
1591: code = (code * 8) + (c - '0');
1592: c = getc (finput);
1593: }
1594: ungetc (c, finput);
1595: return code;
1596:
1597: case '\\': case '\'': case '"':
1598: return c;
1599:
1600: case '\n':
1601: lineno++;
1602: return -1;
1603:
1604: case 'n':
1605: return TARGET_NEWLINE;
1606:
1607: case 't':
1608: return TARGET_TAB;
1609:
1610: case 'r':
1611: return TARGET_CR;
1612:
1613: case 'f':
1614: return TARGET_FF;
1615:
1616: case 'b':
1617: return TARGET_BS;
1618:
1619: case 'a':
1620: return TARGET_BELL;
1621:
1622: case 'v':
1623: return TARGET_VT;
1.1.1.2 root 1624:
1625: case 'E':
1626: return 033;
1627:
1628: case '?':
1629: return c;
1.1 root 1630: }
1.1.1.2 root 1631: if (c >= 040 && c <= 0177)
1632: warning ("unknown escape sequence `\\%c'", c);
1633: else
1634: warning ("unknown escape sequence: `\\' followed by char code 0x%x", c);
1.1 root 1635: return c;
1636: }
1.1.1.4 root 1637:
1.1.1.2 root 1638: void
1.1.1.3 root 1639: yyerror (string)
1640: char *string;
1.1.1.2 root 1641: {
1.1.1.3 root 1642: char buf[200];
1643:
1644: strcpy (buf, string);
1645:
1.1.1.2 root 1646: /* We can't print string and character constants well
1647: because the token_buffer contains the result of processing escapes. */
1648: if (token_buffer[0] == 0)
1.1.1.3 root 1649: strcat (buf, " at end of input");
1.1.1.2 root 1650: else if (token_buffer[0] == '"')
1.1.1.3 root 1651: strcat (buf, " before string constant");
1.1.1.2 root 1652: else if (token_buffer[0] == '\'')
1.1.1.3 root 1653: strcat (buf, " before character constant");
1.1.1.2 root 1654: else
1.1.1.3 root 1655: strcat (buf, " before `%s'");
1656:
1657: error (buf, token_buffer);
1.1.1.2 root 1658: }
1.1 root 1659:
1.1.1.4 root 1660: static int nextchar = -1;
1661:
1.1 root 1662: static int
1.1.1.2 root 1663: yylex ()
1.1 root 1664: {
1665: register int c;
1666: register char *p;
1667: register int value;
1.1.1.2 root 1668: int wide_flag = 0;
1.1 root 1669:
1.1.1.4 root 1670: if (nextchar >= 0)
1671: c = nextchar, nextchar = -1;
1672: else
1673: c = getc (finput);
1674:
1675: /* Effectively do c = skip_white_space (c)
1.1.1.3 root 1676: but do it faster in the usual cases. */
1677: while (1)
1678: switch (c)
1679: {
1680: case ' ':
1681: case '\t':
1682: case '\f':
1683: case '\r':
1684: case '\b':
1685: c = getc (finput);
1686: break;
1687:
1688: case '\n':
1689: case '/':
1690: case '\\':
1.1.1.4 root 1691: c = skip_white_space (c);
1.1.1.3 root 1692: default:
1693: goto found_nonwhite;
1694: }
1695: found_nonwhite:
1696:
1697: token_buffer[0] = c;
1.1.1.2 root 1698: token_buffer[1] = 0;
1.1 root 1699:
1.1.1.4 root 1700: /* yylloc.first_line = lineno; */
1.1 root 1701:
1702: switch (c)
1703: {
1704: case EOF:
1.1.1.2 root 1705: token_buffer[0] = 0;
1706: value = ENDFILE;
1707: break;
1708:
1.1.1.4 root 1709: case '$':
1710: if (dollars_in_ident)
1711: goto letter;
1712: return '$';
1713:
1.1.1.2 root 1714: case 'L':
1715: /* Capital L may start a wide-string or wide-character constant. */
1716: {
1717: register int c = getc (finput);
1718: if (c == '\'')
1719: {
1720: wide_flag = 1;
1721: goto char_constant;
1722: }
1723: if (c == '"')
1724: {
1725: wide_flag = 1;
1726: goto string_constant;
1727: }
1728: ungetc (c, finput);
1729: }
1.1 root 1730:
1731: case 'A': case 'B': case 'C': case 'D': case 'E':
1732: case 'F': case 'G': case 'H': case 'I': case 'J':
1.1.1.2 root 1733: case 'K': case 'M': case 'N': case 'O':
1.1 root 1734: case 'P': case 'Q': case 'R': case 'S': case 'T':
1735: case 'U': case 'V': case 'W': case 'X': case 'Y':
1736: case 'Z':
1737: case 'a': case 'b': case 'c': case 'd': case 'e':
1738: case 'f': case 'g': case 'h': case 'i': case 'j':
1739: case 'k': case 'l': case 'm': case 'n': case 'o':
1740: case 'p': case 'q': case 'r': case 's': case 't':
1741: case 'u': case 'v': case 'w': case 'x': case 'y':
1742: case 'z':
1743: case '_':
1.1.1.4 root 1744: letter:
1.1 root 1745: p = token_buffer;
1.1.1.2 root 1746: while (isalnum (c) || c == '_' || c == '$')
1.1 root 1747: {
1748: if (p >= token_buffer + maxtoken)
1.1.1.2 root 1749: p = extend_token_buffer (p);
1.1.1.4 root 1750: if (c == '$' && ! dollars_in_ident)
1751: break;
1.1.1.2 root 1752:
1.1 root 1753: *p++ = c;
1.1.1.2 root 1754: c = getc (finput);
1.1 root 1755: }
1756:
1757: *p = 0;
1.1.1.4 root 1758: nextchar = c;
1.1 root 1759:
1760: value = IDENTIFIER;
1761: yylval.itype = 0;
1762:
1.1.1.2 root 1763: /* Try to recognize a keyword. */
1764:
1.1 root 1765: if (p - token_buffer <= MAXRESERVED)
1766: {
1767: register int lim = frw [p - token_buffer + 1];
1.1.1.2 root 1768: register int i = frw[p - token_buffer];
1769: register struct resword *p = &reswords[i];
1.1 root 1770:
1.1.1.2 root 1771: for (; i < lim; i++, p++)
1772: if (p->name[0] == token_buffer[0]
1773: && !strcmp (p->name, token_buffer))
1.1 root 1774: {
1.1.1.2 root 1775: if (p->rid)
1776: yylval.ttype = ridpointers[(int) p->rid];
1777: if ((! flag_no_asm
1778: || ((int) p->token != ASM
1779: && (int) p->token != TYPEOF
1780: && strcmp (p->name, "inline")))
1781: /* -ftraditional means don't recognize
1.1.1.4 root 1782: typeof, const, volatile, signed or inline. */
1.1.1.2 root 1783: && (! flag_traditional
1784: || ((int) p->token != TYPE_QUAL
1785: && (int) p->token != TYPEOF
1786: && strcmp (p->name, "signed")
1787: && strcmp (p->name, "inline"))))
1788: value = (int) p->token;
1.1 root 1789: break;
1790: }
1791: }
1792:
1.1.1.2 root 1793: /* If we did not find a keyword, look for an identifier
1794: (or a typename). */
1795:
1.1 root 1796: if (value == IDENTIFIER)
1797: {
1.1.1.2 root 1798: yylval.ttype = get_identifier (token_buffer);
1.1 root 1799: lastiddecl = lookup_name (yylval.ttype);
1800:
1801: if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL)
1802: value = TYPENAME;
1803: }
1804:
1805: break;
1806:
1807: case '0': case '1': case '2': case '3': case '4':
1808: case '5': case '6': case '7': case '8': case '9':
1809: case '.':
1810: {
1811: int base = 10;
1812: int count = 0;
1.1.1.2 root 1813: int largest_digit = 0;
1814: int numdigits = 0;
1815: /* for multi-precision arithmetic,
1816: we store only 8 live bits in each short,
1.1 root 1817: giving us 64 bits of reliable precision */
1818: short shorts[8];
1.1.1.2 root 1819: int floatflag = 0; /* Set 1 if we learn this is a floating constant */
1.1 root 1820:
1821: for (count = 0; count < 8; count++)
1822: shorts[count] = 0;
1823:
1824: p = token_buffer;
1825: *p++ = c;
1826:
1827: if (c == '0')
1828: {
1.1.1.2 root 1829: *p++ = (c = getc (finput));
1.1 root 1830: if ((c == 'x') || (c == 'X'))
1831: {
1832: base = 16;
1.1.1.2 root 1833: *p++ = (c = getc (finput));
1.1 root 1834: }
1835: else
1836: {
1837: base = 8;
1.1.1.2 root 1838: numdigits++;
1.1 root 1839: }
1840: }
1841:
1.1.1.2 root 1842: /* Read all the digits-and-decimal-points. */
1843:
1.1 root 1844: while (c == '.'
1845: || (isalnum (c) && (c != 'l') && (c != 'L')
1.1.1.2 root 1846: && (c != 'u') && (c != 'U')
1847: && (!floatflag || ((c != 'f') && (c != 'F')))))
1.1 root 1848: {
1849: if (c == '.')
1850: {
1.1.1.2 root 1851: if (base == 16)
1852: error ("floating constant may not be in radix 16");
1853: floatflag = 1;
1854: base = 10;
1855: *p++ = c = getc (finput);
1.1 root 1856: /* Accept '.' as the start of a floating-point number
1857: only when it is followed by a digit.
1858: Otherwise, unread the following non-digit
1859: and use the '.' as a structural token. */
1.1.1.2 root 1860: if (p == token_buffer + 2 && !isdigit (c))
1.1 root 1861: {
1862: if (c == '.')
1863: {
1864: c = getc (finput);
1865: if (c == '.')
1.1.1.2 root 1866: {
1867: *p++ = c;
1868: *p = 0;
1869: return ELLIPSIS;
1870: }
1871: error ("parse error at `..'");
1.1 root 1872: }
1873: ungetc (c, finput);
1.1.1.2 root 1874: token_buffer[1] = 0;
1875: value = '.';
1876: goto done;
1.1 root 1877: }
1878: }
1879: else
1880: {
1.1.1.2 root 1881: /* It is not a decimal point.
1882: It should be a digit (perhaps a hex digit). */
1883:
1884: if (isdigit (c))
1.1 root 1885: {
1886: c = c - '0';
1887: }
1888: else if (base <= 10)
1889: {
1890: if ((c&~040) == 'E')
1891: {
1.1.1.2 root 1892: base = 10;
1893: floatflag = 1;
1.1 root 1894: break; /* start of exponent */
1895: }
1.1.1.2 root 1896: error ("nondigits in number and not hexadecimal");
1.1 root 1897: c = 0;
1898: }
1899: else if (c >= 'a')
1900: {
1901: c = c - 'a' + 10;
1902: }
1903: else
1904: {
1905: c = c - 'A' + 10;
1906: }
1.1.1.2 root 1907: if (c >= largest_digit)
1908: largest_digit = c;
1909: numdigits++;
1.1 root 1910:
1911: for (count = 0; count < 8; count++)
1912: {
1913: (shorts[count] *= base);
1914: if (count)
1915: {
1916: shorts[count] += (shorts[count-1] >> 8);
1917: shorts[count-1] &= (1<<8)-1;
1918: }
1919: else shorts[0] += c;
1920: }
1921:
1.1.1.2 root 1922: if (p >= token_buffer + maxtoken - 3)
1923: p = extend_token_buffer (p);
1924: *p++ = (c = getc (finput));
1.1 root 1925: }
1926: }
1927:
1.1.1.2 root 1928: if (numdigits == 0)
1929: error ("numeric constant with no digits");
1930:
1931: if (largest_digit >= base)
1932: error ("numeric constant contains digits beyond the radix");
1933:
1.1 root 1934: /* Remove terminating char from the token buffer and delimit the string */
1935: *--p = 0;
1936:
1937: if (floatflag)
1938: {
1939: tree type = double_type_node;
1.1.1.2 root 1940: char f_seen = 0;
1941: char l_seen = 0;
1.1.1.4 root 1942: double value;
1.1 root 1943:
1.1.1.2 root 1944: /* Read explicit exponent if any, and put it in tokenbuf. */
1.1 root 1945:
1946: if ((c == 'e') || (c == 'E'))
1947: {
1.1.1.2 root 1948: if (p >= token_buffer + maxtoken - 3)
1949: p = extend_token_buffer (p);
1950: *p++ = c;
1951: c = getc (finput);
1.1 root 1952: if ((c == '+') || (c == '-'))
1953: {
1.1.1.2 root 1954: *p++ = c;
1955: c = getc (finput);
1.1 root 1956: }
1.1.1.2 root 1957: if (! isdigit (c))
1958: error ("floating constant exponent has no digits");
1959: while (isdigit (c))
1.1 root 1960: {
1.1.1.2 root 1961: if (p >= token_buffer + maxtoken - 3)
1962: p = extend_token_buffer (p);
1963: *p++ = c;
1964: c = getc (finput);
1.1 root 1965: }
1966: }
1967:
1.1.1.2 root 1968: *p = 0;
1.1.1.4 root 1969: errno = 0;
1970: value = atof (token_buffer);
1971: #ifdef ERANGE
1.1.1.5 ! root 1972: if (errno == ERANGE && !flag_traditional)
1.1.1.4 root 1973: error ("floating point number exceeds range of `double'");
1974: #endif
1.1.1.2 root 1975:
1.1.1.4 root 1976: /* Read the suffixes to choose a data type. */
1.1 root 1977: while (1)
1978: {
1979: if (c == 'f' || c == 'F')
1.1.1.2 root 1980: {
1981: if (f_seen)
1982: error ("two `f's in floating constant");
1983: f_seen = 1;
1984: type = float_type_node;
1985: }
1.1 root 1986: else if (c == 'l' || c == 'L')
1.1.1.2 root 1987: {
1988: if (l_seen)
1989: error ("two `l's in floating constant");
1990: l_seen = 1;
1991: type = long_double_type_node;
1992: }
1993: else
1994: {
1995: if (isalnum (c))
1996: {
1997: error ("garbage at end of number");
1998: while (isalnum (c))
1999: {
2000: if (p >= token_buffer + maxtoken - 3)
2001: p = extend_token_buffer (p);
2002: *p++ = c;
2003: c = getc (finput);
2004: }
2005: }
2006: break;
2007: }
2008: if (p >= token_buffer + maxtoken - 3)
2009: p = extend_token_buffer (p);
2010: *p++ = c;
1.1 root 2011: c = getc (finput);
2012: }
2013:
1.1.1.4 root 2014: /* Create a node with determined type and value. */
2015: yylval.ttype = build_real (type, value);
2016:
1.1.1.2 root 2017: ungetc (c, finput);
2018: *p = 0;
1.1 root 2019: }
2020: else
2021: {
2022: tree type;
2023: int spec_unsigned = 0;
2024: int spec_long = 0;
2025:
2026: while (1)
2027: {
2028: if (c == 'u' || c == 'U')
2029: {
1.1.1.2 root 2030: if (spec_unsigned)
2031: error ("two `u's in integer constant");
1.1 root 2032: spec_unsigned = 1;
2033: }
2034: else if (c == 'l' || c == 'L')
2035: {
1.1.1.2 root 2036: if (spec_long)
2037: error ("two `l's in integer constant");
1.1 root 2038: spec_long = 1;
2039: }
1.1.1.2 root 2040: else
2041: {
2042: if (isalnum (c))
2043: {
2044: error ("garbage at end of number");
2045: while (isalnum (c))
2046: {
2047: if (p >= token_buffer + maxtoken - 3)
2048: p = extend_token_buffer (p);
2049: *p++ = c;
2050: c = getc (finput);
2051: }
2052: }
2053: break;
2054: }
2055: if (p >= token_buffer + maxtoken - 3)
2056: p = extend_token_buffer (p);
2057: *p++ = c;
2058: c = getc (finput);
1.1 root 2059: }
2060:
2061: ungetc (c, finput);
2062:
1.1.1.2 root 2063: if (shorts[7] | shorts[6] | shorts[5] | shorts[4])
2064: warning ("integer constant out of range");
2065:
1.1 root 2066: /* This is simplified by the fact that our constant
2067: is always positive. */
2068: yylval.ttype
2069: = build_int_2 ((shorts[3]<<24) + (shorts[2]<<16) + (shorts[1]<<8) + shorts[0],
1.1.1.2 root 2070: 0);
1.1 root 2071:
2072: if (!spec_long && !spec_unsigned
2073: && int_fits_type_p (yylval.ttype, integer_type_node))
2074: type = integer_type_node;
2075:
2076: else if (!spec_long && base != 10
2077: && int_fits_type_p (yylval.ttype, unsigned_type_node))
2078: type = unsigned_type_node;
2079:
2080: else if (!spec_unsigned
2081: && int_fits_type_p (yylval.ttype, long_integer_type_node))
2082: type = long_integer_type_node;
2083:
2084: else
1.1.1.2 root 2085: {
2086: type = long_unsigned_type_node;
2087: if (! int_fits_type_p (yylval.ttype, long_unsigned_type_node))
2088: warning ("integer constant out of range");
2089: }
1.1 root 2090: TREE_TYPE (yylval.ttype) = type;
2091: }
2092:
2093: value = CONSTANT; break;
2094: }
2095:
2096: case '\'':
1.1.1.2 root 2097: char_constant:
2098: c = getc (finput);
1.1 root 2099: {
2100: register int code = 0;
2101:
2102: tryagain:
2103:
2104: if (c == '\\')
2105: {
2106: c = readescape ();
2107: if (c < 0)
2108: goto tryagain;
2109: }
1.1.1.2 root 2110: else if (c == '\n')
2111: {
2112: if (pedantic)
2113: warning ("ANSI C forbids newline in character constant");
2114: lineno++;
2115: }
2116:
1.1 root 2117: code = c;
1.1.1.2 root 2118: token_buffer[1] = c;
2119: token_buffer[2] = '\'';
2120: token_buffer[3] = 0;
2121:
1.1 root 2122: c = getc (finput);
2123: if (c != '\'')
1.1.1.2 root 2124: error ("malformatted character constant");
1.1 root 2125:
1.1.1.2 root 2126: /* If char type is signed, sign-extend the constant. */
2127: if (TREE_UNSIGNED (char_type_node)
2128: || ((code >> (BITS_PER_UNIT - 1)) & 1) == 0)
2129: yylval.ttype = build_int_2 (code & ((1 << BITS_PER_UNIT) - 1), 0);
1.1 root 2130: else
1.1.1.2 root 2131: yylval.ttype = build_int_2 (code | ((-1) << BITS_PER_UNIT), -1);
1.1 root 2132:
1.1.1.2 root 2133: TREE_TYPE (yylval.ttype) = integer_type_node;
1.1 root 2134: value = CONSTANT; break;
2135: }
2136:
2137: case '"':
1.1.1.2 root 2138: string_constant:
1.1 root 2139: {
1.1.1.2 root 2140: c = getc (finput);
2141: p = token_buffer + 1;
1.1 root 2142:
2143: while (c != '"')
2144: {
2145: if (c == '\\')
2146: {
2147: c = readescape ();
2148: if (c < 0)
2149: goto skipnewline;
2150: }
2151: else if (c == '\n')
2152: {
1.1.1.2 root 2153: if (pedantic)
2154: warning ("ANSI C forbids newline in string constant");
1.1 root 2155: lineno++;
2156: }
2157:
2158: if (p == token_buffer + maxtoken)
1.1.1.2 root 2159: p = extend_token_buffer (p);
1.1 root 2160: *p++ = c;
2161:
2162: skipnewline:
2163: c = getc (finput);
2164: }
2165:
1.1.1.2 root 2166: *p = 0;
2167:
2168: if (wide_flag)
2169: {
2170: /* If this is a L"..." wide-string, convert each char
2171: to an int, making a vector of ints. */
2172: int *widebuf = (int *) alloca (p - token_buffer);
2173: char *p1 = token_buffer + 1;
2174: for (; p1 == p; p1++)
2175: widebuf[p1 - token_buffer - 1] = *p1;
2176: yylval.ttype = build_string ((p - token_buffer) * sizeof (int),
2177: widebuf);
2178: TREE_TYPE (yylval.ttype) = int_array_type_node;
2179: }
2180: else
2181: {
2182: yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
2183: TREE_TYPE (yylval.ttype) = char_array_type_node;
2184: }
1.1 root 2185:
1.1.1.2 root 2186: *p++ = '"';
2187: *p = 0;
1.1 root 2188:
2189: value = STRING; break;
2190: }
2191:
2192: case '+':
2193: case '-':
2194: case '&':
2195: case '|':
2196: case '<':
2197: case '>':
2198: case '*':
2199: case '/':
2200: case '%':
2201: case '^':
2202: case '!':
2203: case '=':
2204: {
2205: register int c1;
2206:
2207: combine:
2208:
2209: switch (c)
2210: {
2211: case '+':
2212: yylval.code = PLUS_EXPR; break;
2213: case '-':
2214: yylval.code = MINUS_EXPR; break;
2215: case '&':
2216: yylval.code = BIT_AND_EXPR; break;
2217: case '|':
2218: yylval.code = BIT_IOR_EXPR; break;
2219: case '*':
2220: yylval.code = MULT_EXPR; break;
2221: case '/':
2222: yylval.code = TRUNC_DIV_EXPR; break;
2223: case '%':
2224: yylval.code = TRUNC_MOD_EXPR; break;
2225: case '^':
2226: yylval.code = BIT_XOR_EXPR; break;
2227: case LSHIFT:
2228: yylval.code = LSHIFT_EXPR; break;
2229: case RSHIFT:
2230: yylval.code = RSHIFT_EXPR; break;
2231: case '<':
2232: yylval.code = LT_EXPR; break;
2233: case '>':
2234: yylval.code = GT_EXPR; break;
2235: }
2236:
1.1.1.2 root 2237: token_buffer[1] = c1 = getc (finput);
2238: token_buffer[2] = 0;
1.1 root 2239:
2240: if (c1 == '=')
2241: {
2242: switch (c)
2243: {
2244: case '<':
2245: value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
2246: case '>':
2247: value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
2248: case '!':
2249: value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
2250: case '=':
2251: value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
2252: }
2253: value = ASSIGN; goto done;
2254: }
2255: else if (c == c1)
2256: switch (c)
2257: {
2258: case '+':
2259: value = PLUSPLUS; goto done;
2260: case '-':
2261: value = MINUSMINUS; goto done;
2262: case '&':
2263: value = ANDAND; goto done;
2264: case '|':
2265: value = OROR; goto done;
2266: case '<':
2267: c = LSHIFT;
2268: goto combine;
2269: case '>':
2270: c = RSHIFT;
2271: goto combine;
2272: }
2273: else if ((c == '-') && (c1 == '>'))
2274: { value = POINTSAT; goto done; }
2275: ungetc (c1, finput);
1.1.1.2 root 2276: token_buffer[1] = 0;
1.1 root 2277:
2278: if ((c == '<') || (c == '>'))
2279: value = ARITHCOMPARE;
2280: else value = c;
2281: goto done;
2282: }
2283:
2284: default:
2285: value = c;
2286: }
2287:
2288: done:
1.1.1.4 root 2289: /* yylloc.last_line = lineno; */
1.1 root 2290:
1.1.1.2 root 2291: return value;
1.1 root 2292: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.