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