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