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