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