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