|
|
1.1 root 1: /* YACC parser for C syntax.
2: Copyright (C) 1987 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: %{
26: #include "config.h"
27: #include "tree.h"
28: #include "parse.h"
29: #include "c-tree.h"
30: %}
31:
32: %start program
33:
34: %union {long itype; tree ttype; enum tree_code code}
35:
36: /* all identifiers that are not reserved words
37: and are not declared typedefs in the current block */
38: %token IDENTIFIER
39: /* all identifiers that are declared typedefs in the current block.
40: In some contexts, they are treated just like IDENTIFIER,
41: but they can also serve as typespecs in declarations. */
42: %token TYPENAME
43:
44: /* reserved words that specify storage class.
45: yylval contains an IDENTIFER_NODE which indicates which one. */
46: %token SCSPEC
47:
48: /* reserved words that specify type.
49: yylval contains an IDENTIFER_NODE which indicates which one. */
50: %token TYPESPEC
51:
52: /* reserved words that modify type: "const" or "volatile".
53: yylval contains an IDENTIFER_NODE which indicates which one. */
54: %token TYPEMOD
55:
56: /* character or numeric constants.
57: yylval is the node for the constant. */
58: %token CONSTANT
59:
60: /* String constants in raw form.
61: yylval is a STRING_CST node. */
62: %token STRING
63:
64: /* "...", used for functions with variable arglists. */
65: %token ELLIPSIS
66:
67: /* the reserved words */
68: %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
69: %token BREAK CONTINUE RETURN GOTO ASM
70:
71: /* Define the operator tokens and their precedences.
72: The value is an integer because, if used, it is the tree code
73: to use in the expression made from the operator. */
74:
75: %right <code> ASSIGN '='
76: %right <code> '?' ':'
77: %left <code> OROR
78: %left <code> ANDAND
79: %left <code> '|'
80: %left <code> '^'
81: %left <code> '&'
82: %left <code> EQCOMPARE
83: %left <code> ARITHCOMPARE
84: %left <code> LSHIFT RSHIFT
85: %left <code> '+' '-'
86: %left <code> '*' '/' '%'
87: %right <code> UNARY PLUSPLUS MINUSMINUS
88: %left HYPERUNARY
89: %left <code> POINTSAT '.'
90:
91: %type <code> unop
92:
93: %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
94: %type <ttype> expr_no_commas primary string STRING
95: %type <ttype> typed_declspecs scspecs typespecs typespec SCSPEC TYPESPEC TYPEMOD
96: %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
97: %type <ttype> init initlist
98:
99: %type <ttype> declarator
100: %type <ttype> notype_declarator after_type_declarator
101:
102: %type <ttype> structsp component_decl_list component_decl components component_declarator
103: %type <ttype> enumlist enumerator
104: %type <ttype> typename absdcl absdcl1 typemods
105: %type <ttype> stmts
106: %type <ttype> pushlevel compstmt stmt xexpr parmlist parms parm identifiers
107:
108: %{
109: /* the declaration found for the last IDENTIFIER token read in.
110: yylex must look this up to detect typedefs, which get token type TYPENAME,
111: so it is left around in case the identifier is not a typedef but is
112: used in a context which makes it a reference to a variable. */
113: static tree lastiddecl;
114:
115: tree current_function_decl, current_switch_stmt, current_block;
116: tree current_continue_label, current_break_label;
117: tree continue_label_stack, break_label_stack;
118:
119: static void pushbreak(), popbreak();
120: static tree finish_compound_stmt();
121: static tree make_pointer_declarator ();
122: static tree combine_strings ();
123:
124: /* list of types and structure classes of the current declaration */
125: tree current_declspecs;
126:
127: char *input_filename; /* file being read */
128: %}
129:
130: %%
131: program:
132: extdefs
133: ;
134:
135: /* the reason for the strange actions in this rule
136: is so that notype_initdecls when reached via datadef
137: can find a valid list of type and sc specs in $0. */
138:
139: extdefs:
140: {$<ttype>$ = NULL_TREE} extdef
141: | extdefs {$<ttype>$ = NULL_TREE} extdef
142: ;
143:
144: extdef:
145: fndef
146: | datadef
147: | ASM '(' STRING ')' ';'
148: { assemble_asm ($3); }
149: ;
150:
151: datadef:
152: setspecs notype_initdecls ';'
153: | scspecs setspecs notype_initdecls ';'
154: {}
155: | typed_declspecs setspecs initdecls ';'
156: {}
157: | scspecs ';'
158: { yyerror ("empty declaration"); }
159: | typed_declspecs ';'
160: { shadow_tag ($1); }
161: | error ';'
162: | error '}'
163: | ';'
164: ;
165:
166: fndef:
167: typed_declspecs setspecs declarator
168: { if (! start_function ($1, $3))
169: YYFAIL; }
170: xdecls
171: { store_parm_decls (); }
172: compstmt
173: { finish_function (input_filename, @7.first_line, $7); }
174: | typed_declspecs setspecs declarator error
175: { }
176: | scspecs setspecs notype_declarator
177: { if (! start_function ($1, $3))
178: YYFAIL; }
179: xdecls
180: { store_parm_decls (); }
181: compstmt
182: { finish_function (input_filename, @7.first_line, $7); }
183: | scspecs setspecs notype_declarator error
184: { }
185: | setspecs notype_declarator
186: { if (! start_function (0, $2))
187: YYFAIL; }
188: xdecls
189: { store_parm_decls (); }
190: compstmt
191: { finish_function (input_filename, @6.first_line, $6); }
192: | setspecs notype_declarator error
193: ;
194:
195: identifier:
196: IDENTIFIER
197: | TYPENAME
198: ;
199:
200: unop: '&'
201: { $$ = ADDR_EXPR; }
202: | '-'
203: { $$ = NEGATE_EXPR; }
204: | '+'
205: { $$ = CONVERT_EXPR; }
206: | PLUSPLUS
207: { $$ = PREINCREMENT_EXPR; }
208: | MINUSMINUS
209: { $$ = PREDECREMENT_EXPR; }
210: | '~'
211: { $$ = BIT_NOT_EXPR; }
212: | '!'
213: { $$ = TRUTH_NOT_EXPR; }
214: ;
215:
216: expr: nonnull_exprlist
217: { $$ = build_compound_expr($1); }
218: ;
219:
220: exprlist:
221: /* empty */
222: { $$ = NULL_TREE; }
223: | nonnull_exprlist
224: ;
225:
226: nonnull_exprlist:
227: expr_no_commas
228: { $$ = build_tree_list (NULL_TREE, $1); }
229: | nonnull_exprlist ',' expr_no_commas
230: { chainon ($1, build_tree_list (NULL_TREE, $3)); }
231: ;
232:
233: expr_no_commas:
234: primary
235: | '*' expr_no_commas %prec UNARY
236: { $$ = build_indirect_ref ($2); }
237: | unop expr_no_commas %prec UNARY
238: { $$ = build_unary_op ($1, $2, 0); }
239: | '(' typename ')' expr_no_commas %prec UNARY
240: { $$ = build_c_cast (groktypename($2), $4); }
241: | SIZEOF expr_no_commas %prec UNARY
242: { $$ = c_sizeof (TREE_TYPE ($2)); }
243: | SIZEOF '(' typename ')' %prec HYPERUNARY
244: { $$ = c_sizeof (groktypename($3)); }
245: | expr_no_commas '+' expr_no_commas
246: { $$ = build_binary_op ($2, $1, $3); }
247: | expr_no_commas '-' expr_no_commas
248: { $$ = build_binary_op ($2, $1, $3); }
249: | expr_no_commas '*' expr_no_commas
250: { $$ = build_binary_op ($2, $1, $3); }
251: | expr_no_commas '/' expr_no_commas
252: { $$ = build_binary_op ($2, $1, $3); }
253: | expr_no_commas '%' expr_no_commas
254: { $$ = build_binary_op ($2, $1, $3); }
255: | expr_no_commas LSHIFT expr_no_commas
256: { $$ = build_binary_op ($2, $1, $3); }
257: | expr_no_commas RSHIFT expr_no_commas
258: { $$ = build_binary_op ($2, $1, $3); }
259: | expr_no_commas ARITHCOMPARE expr_no_commas
260: { $$ = build_binary_op ($2, $1, $3); }
261: | expr_no_commas EQCOMPARE expr_no_commas
262: { $$ = build_binary_op ($2, $1, $3); }
263: | expr_no_commas '&' expr_no_commas
264: { $$ = build_binary_op ($2, $1, $3); }
265: | expr_no_commas '|' expr_no_commas
266: { $$ = build_binary_op ($2, $1, $3); }
267: | expr_no_commas '^' expr_no_commas
268: { $$ = build_binary_op ($2, $1, $3); }
269: | expr_no_commas ANDAND expr_no_commas
270: { $$ = build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }
271: | expr_no_commas OROR expr_no_commas
272: { $$ = build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }
273: | expr_no_commas '?' expr ':' expr_no_commas
274: { $$ = build_conditional_expr($1, $3, $5); }
275: | expr_no_commas '=' expr_no_commas
276: { $$ = build_modify_expr($1, $3); }
277: | expr_no_commas ASSIGN expr_no_commas
278: { register tree tem
279: = duplicate_reference ($1);
280: $$ = build_modify_expr(tem, build_binary_op ($2, tem, $3)); }
281: ;
282:
283: primary:
284: IDENTIFIER
285: { $$ = lastiddecl;
286: if (!$$)
287: {
288: if (yychar == YYEMPTY)
289: yychar = YYLEX;
290: if (yychar == '(')
291: $$ = implicitly_declare($1);
292: else
293: {
294: yyerror("variable %s used but not declared",
295: IDENTIFIER_POINTER ($1));
296: $$ = error_mark_node;
297: }
298: }
299: if (TREE_CODE ($$) == CONST_DECL)
300: $$ = DECL_INITIAL ($$);
301: }
302: | CONSTANT
303: | string
304: { $$ = combine_strings ($1); }
305: | '(' expr ')'
306: { $$ = $2; }
307: | '(' error ')'
308: { $$ = error_mark_node; }
309: | primary '(' exprlist ')' %prec '.'
310: { $$ = build_function_call ($1, $3); }
311: | primary '[' expr ']' %prec '.'
312: { $$ = build_array_ref ($1, $3); }
313: | primary '.' identifier
314: { $$ = build_component_ref($1, $3); }
315: | primary POINTSAT identifier
316: { $$ = build_component_ref(build_indirect_ref ($1), $3); }
317: | primary PLUSPLUS
318: { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
319: | primary MINUSMINUS
320: { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
321: ;
322:
323: /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
324: string:
325: STRING
326: | string STRING
327: { $$ = chainon ($1, $2); }
328: ;
329:
330: xdecls:
331: /* empty */
332: | decls
333: ;
334:
335: decls:
336: decl
337: | errstmt
338: | decls decl
339: | decl errstmt
340: ;
341:
342: /* records the type and storage class specs to use for processing
343: the declarators that follow */
344: setspecs: /* empty */
345: { current_declspecs = $<ttype>0; }
346: ;
347:
348: decl:
349: typed_declspecs setspecs initdecls ';'
350: {}
351: | scspecs setspecs notype_initdecls ';'
352: {}
353: | typed_declspecs ';'
354: { shadow_tag ($1); }
355: | scspecs ';'
356: { warning ("empty declaration"); }
357: ;
358:
359: /* declspecs which contain at least one type specifier.
360: A typedef'd name following these is taken as a name to be declared. */
361: typed_declspecs:
362: typespec
363: { $$ = build_tree_list (NULL_TREE, $1); }
364: | scspecs typespec
365: { $$ = tree_cons (NULL_TREE, $2, $1); }
366: | typed_declspecs TYPESPEC
367: { $$ = tree_cons (NULL_TREE, $2, $1); }
368: | typed_declspecs TYPEMOD
369: { $$ = tree_cons (NULL_TREE, $2, $1); }
370: | typed_declspecs structsp
371: { $$ = tree_cons (NULL_TREE, $2, $1); }
372: | typed_declspecs SCSPEC
373: { $$ = tree_cons (NULL_TREE, $2, $1); }
374: ;
375:
376: /* declspecs which contain no type specifiers.
377: The identifier to which they apply must not be a typedef'd name. */
378: scspecs: SCSPEC
379: { $$ = build_tree_list (NULL_TREE, $1); }
380: | scspecs SCSPEC
381: { $$ = tree_cons (NULL_TREE, $2, $1); }
382: ;
383:
384: /* used instead of declspecs where storage classes are not allowed
385: (typenames, structure components, and parameters) */
386: typespecs:
387: typespec
388: { $$ = build_tree_list (NULL_TREE, $1); }
389: | typespecs TYPESPEC
390: { $$ = tree_cons (NULL_TREE, $2, $1); }
391: | typespecs TYPEMOD
392: { $$ = tree_cons (NULL_TREE, $2, $1); }
393: | typespecs structsp
394: { $$ = tree_cons (NULL_TREE, $2, $1); }
395: ;
396:
397: typespec: TYPESPEC
398: | TYPEMOD
399: | structsp
400: | TYPENAME
401: ;
402:
403: initdecls:
404: initdcl
405: | initdecls ',' initdcl
406: ;
407:
408: notype_initdecls:
409: notype_initdcl
410: | notype_initdecls ',' initdcl
411: ;
412:
413: initdcl:
414: declarator '='
415: { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
416: init
417: /* Note how the declaration of the variable is in effect while its init is parsed! */
418: { finish_decl (input_filename, @1.first_line, $<ttype>3, $4); }
419: | declarator
420: { tree d = start_decl ($1, current_declspecs, 0);
421: finish_decl (input_filename, @1.first_line, d, NULL_TREE); }
422: ;
423:
424: notype_initdcl:
425: notype_declarator '='
426: { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
427: init
428: /* Note how the declaration of the variable is in effect while its init is parsed! */
429: { finish_decl (input_filename, @1.first_line, $<ttype>3, $4); }
430: | notype_declarator
431: { tree d = start_decl ($1, current_declspecs, 0);
432: finish_decl (input_filename, @1.first_line, d, NULL_TREE); }
433: ;
434:
435: init:
436: expr_no_commas
437: | '{' initlist '}'
438: { $$ = build1 (CONSTRUCTOR, nreverse ($2)); }
439: | '{' initlist ',' '}'
440: { $$ = build1 (CONSTRUCTOR, nreverse ($2)); }
441: ;
442:
443: /* This chain is built in reverse order,
444: and put in forward order where initlist is used. */
445: initlist:
446: init
447: { $$ = build_tree_list (NULL_TREE, $1); }
448: | initlist ',' init
449: { $$ = tree_cons (NULL, $3, $1); }
450: ;
451:
452: /* Any kind of declarator (thus, all declarators allowed
453: after an explicit typespec). */
454:
455: declarator:
456: after_type_declarator
457: | notype_declarator
458: ;
459:
460: /* A declarator that is allowed only after an explicit typespec. */
461:
462: after_type_declarator:
463: after_type_declarator '(' parmlist ')' %prec '.'
464: { $$ = build2 (CALL_EXPR, $1, $3); }
465: | after_type_declarator '(' identifiers ')' %prec '.'
466: { $$ = build2 (CALL_EXPR, $1, $3); }
467: | after_type_declarator '(' error ')' %prec '.'
468: { $$ = build2 (CALL_EXPR, $1, NULL_TREE); }
469: | after_type_declarator '[' expr ']' %prec '.'
470: { $$ = build2 (ARRAY_REF, $1, $3); }
471: | after_type_declarator '[' ']' %prec '.'
472: { $$ = build2 (ARRAY_REF, $1, NULL_TREE); }
473: | TYPENAME
474: ;
475:
476: /* A declarator allowed whether or not there has been
477: an explicit typespec. These cannot redeclare a typedef-name. */
478:
479: notype_declarator:
480: notype_declarator '(' parmlist ')' %prec '.'
481: { $$ = build2 (CALL_EXPR, $1, $3); }
482: | notype_declarator '(' identifiers ')' %prec '.'
483: { $$ = build2 (CALL_EXPR, $1, $3); }
484: | notype_declarator '(' error ')' %prec '.'
485: { $$ = build2 (CALL_EXPR, $1, NULL_TREE); }
486: | '(' notype_declarator ')'
487: { $$ = $2; }
488: | '*' typemods notype_declarator %prec UNARY
489: { $$ = make_pointer_declarator ($2, $3); }
490: | notype_declarator '[' expr ']' %prec '.'
491: { $$ = build2 (ARRAY_REF, $1, $3); }
492: | notype_declarator '[' ']' %prec '.'
493: { $$ = build2 (ARRAY_REF, $1, NULL_TREE); }
494: | IDENTIFIER
495: ;
496:
497: structsp:
498: STRUCT identifier '{' component_decl_list '}'
499: { $$ = build_struct (RECORD_TYPE, input_filename, @1.first_line, $2, $4, 0); }
500: | STRUCT '{' component_decl_list '}'
501: { $$ = build_struct (RECORD_TYPE, input_filename, @1.first_line, NULL_TREE, $3, 0); }
502: | STRUCT identifier
503: { $$ = build_struct (RECORD_TYPE, input_filename, @1.first_line, $2, NULL_TREE, 1); }
504: | UNION identifier '{' component_decl_list '}'
505: { $$ = build_struct (UNION_TYPE, input_filename, @1.first_line, $2, $4, 0); }
506: | UNION '{' component_decl_list '}'
507: { $$ = build_struct (UNION_TYPE, input_filename, @1.first_line, NULL_TREE, $3, 0); }
508: | UNION identifier
509: { $$ = build_struct (UNION_TYPE, input_filename, @1.first_line, $2, NULL_TREE, 1); }
510: | ENUM identifier '{'
511: { $$ = start_enum ($2); }
512: enumlist '}'
513: { $$ = finish_enum ($<ttype>4, nreverse ($5)); }
514: | ENUM '{'
515: { $$ = start_enum (NULL_TREE); }
516: enumlist '}'
517: { $$ = finish_enum ($<ttype>3, nreverse ($4)); }
518: | ENUM identifier
519: { $$ = xref_enum ($2); }
520: ;
521:
522: component_decl_list: /* empty */
523: { $$ = NULL_TREE; }
524: | component_decl
525: | component_decl_list ';' component_decl
526: { $$ = chainon ($1, $3); }
527: | component_decl_list ';'
528: ;
529:
530: component_decl:
531: typespecs setspecs components
532: { $$ = $3; }
533: | error
534: { $$ == NULL_TREE; }
535: ;
536:
537: components:
538: /* empty */
539: { $$ = NULL_TREE; }
540: | component_declarator
541: | components ',' component_declarator
542: { $$ = chainon ($1, $3); }
543: ;
544:
545: component_declarator:
546: declarator
547: { $$ = grokfield (input_filename, @1.first_line, $1, current_declspecs, NULL_TREE); }
548: | declarator ':' expr_no_commas
549: { $$ = grokfield (input_filename, @1.first_line, $1, current_declspecs, $3); }
550: | ':' expr_no_commas
551: { $$ = grokfield (input_filename, @1.first_line, NULL_TREE, current_declspecs, $2); }
552: ;
553:
554: /* We chain the enumerators in reverse order.
555: They are put in forward order where enumlist is used.
556: (The order used to be significant, but no longer is so.
557: However, we still maintain the order, just to be clean.) */
558:
559: enumlist:
560: enumerator
561: | enumlist ',' enumerator
562: { $$ = chainon ($3, $1); }
563: | enumlist ','
564: ;
565:
566:
567: enumerator:
568: identifier
569: { $$ = build_enumerator ($1, NULL_TREE); }
570: | identifier '=' expr_no_commas
571: { $$ = build_enumerator ($1, $3); }
572: ;
573:
574: typename:
575: typespecs absdcl
576: { $$ = build_tree_list ($1, $2); }
577: ;
578:
579: absdcl: /* an absolute declarator */
580: /* empty */
581: { $$ = NULL_TREE; }
582: | absdcl1
583: ;
584:
585: typemods:
586: /* empty */
587: { $$ = NULL_TREE; }
588: | typemods TYPEMOD
589: { $$ = tree_cons (NULL_TREE, $2, $1); }
590: ;
591:
592: absdcl1: /* a nonempty absolute declarator */
593: '(' absdcl1 ')'
594: { $$ = $2; }
595: | '*' typemods absdcl1 %prec UNARY
596: { $$ = make_pointer_declarator ($2, $3); }
597: | '*' typemods %prec UNARY
598: { $$ = make_pointer_declarator ($2, NULL_TREE); }
599: | absdcl1 '(' parmlist ')' %prec '.'
600: { $$ = build2 (CALL_EXPR, $1, $3); }
601: | absdcl1 '[' expr ']' %prec '.'
602: { $$ = build2 (ARRAY_REF, $1, $3); }
603: | absdcl1 '[' ']' %prec '.'
604: { $$ = build2 (ARRAY_REF, $1, NULL_TREE); }
605: | '(' parmlist ')' %prec '.'
606: { $$ = build2 (CALL_EXPR, NULL_TREE, $2); }
607: | '[' expr ']' %prec '.'
608: { $$ = build2 (ARRAY_REF, NULL_TREE, $2); }
609: | '[' ']' %prec '.'
610: { $$ = build2 (ARRAY_REF, NULL_TREE, NULL_TREE); }
611: ;
612:
613: /* at least one statement, the first of which parses without error. */
614: /* stmts is used only after decls, so an invalid first statement
615: is actually regarded as an invalid decl and part of the decls. */
616:
617: /* To speed things up, we actually chain the statements in
618: reverse order and return them that way.
619: They are put into forward order where stmts is used. */
620: stmts:
621: stmt
622: | stmts stmt
623: { $$ = chainon ($2, $1); }
624: | stmts errstmt
625: ;
626:
627: errstmt: error ';'
628: ;
629:
630: /* build the LET_STMT node before parsing its contents,
631: so that any LET_STMTs within the context can have their display pointers
632: set up to point at this one. */
633:
634: pushlevel: /* empty */
635: { pushlevel();
636: $$ = current_block;
637: current_block
638: = build_let (input_filename, 0, 0, 0, $$, 0);
639: }
640: ;
641:
642: compstmt: '{' '}'
643: { $$ = build_compound (input_filename, @1.first_line, 0); }
644: | '{' pushlevel decls stmts '}'
645: { $$ = finish_compound_stmt (current_block, nreverse ($4),
646: $2, @1.first_line); }
647: | '{' pushlevel decls '}'
648: { $$ = finish_compound_stmt (current_block, NULL_TREE,
649: $2, @1.first_line); }
650: | '{' pushlevel error '}'
651: { $$ = error_mark_node;
652: current_block = $2;
653: poplevel(); }
654: | '{' pushlevel stmts '}'
655: { $$ = finish_compound_stmt (current_block, nreverse ($3), $2,
656: @1.first_line); }
657: ;
658:
659: stmt: compstmt
660: | expr ';'
661: { $$ = build_expr_stmt (input_filename, @1.first_line, $1); }
662: | IF '(' expr ')' stmt
663: { $$ = build_if (input_filename, @1.first_line, default_conversion ($3), $5, 0); }
664: | IF '(' expr ')' stmt ELSE stmt
665: { $$ = build_if (input_filename, @1.first_line, default_conversion ($3), $5, $7); }
666: | WHILE
667: { pushbreak(1); }
668: '(' expr ')' stmt
669: { $$ = build_loop (input_filename, @1.first_line,
670: chainon (build_exit (input_filename, @4.first_line,
671: default_conversion ($4)),
672: chainon ($6, current_continue_label)));
673: $$ = build_compound (input_filename, @1.first_line, chainon ($$, current_break_label));
674: popbreak(1); }
675: | DO
676: { pushbreak(1); }
677: stmt WHILE '(' expr ')' ';'
678: { $$ = build_loop (input_filename, @1.first_line,
679: chainon ($3, chainon(current_continue_label,
680: build_exit (input_filename, @6.first_line,
681: default_conversion ($6)))));
682: $$ = build_compound (input_filename, @1.first_line, chainon ($$, current_break_label));
683: popbreak(1); }
684: | FOR
685: { pushbreak(1); }
686: '(' xexpr ';' xexpr ';' xexpr ')' stmt
687: { $$ = build_compound (input_filename, @1.first_line,
688: chainon ($4 ? build_expr_stmt (input_filename, @4.first_line, $4) : NULL_TREE,
689: build_loop (input_filename, @1.first_line,
690: chainon ($6 ? build_exit (input_filename, @6.first_line,
691: default_conversion ($6))
692: : NULL_TREE,
693: chainon (chainon ($10, current_continue_label),
694: $8 ? build_expr_stmt (input_filename, @8.first_line, $8) : NULL_TREE)))));
695: $$ = build_compound (input_filename, @1.first_line, chainon ($$, current_break_label));
696: popbreak(1); }
697: | SWITCH '(' expr ')'
698: { $<ttype>$ = current_switch_stmt;
699: pushbreak(0);
700: current_switch_stmt
701: = build_switch_stmt (input_filename, @1.first_line,
702: default_conversion ($3)); }
703: stmt
704: { $$ = build_compound (input_filename, @1.first_line,
705: chainon(current_switch_stmt,
706: chainon($6, current_break_label)));
707: finish_switch_stmt (current_switch_stmt, current_break_label);
708: popbreak (0);
709: current_switch_stmt = $<ttype>5; }
710: | CASE expr ':' stmt
711: { register tree value = fold($2);
712: tree l = build_label (input_filename, @1.first_line, NULL_TREE, current_block);
713:
714: if (TREE_CODE (value) != INTEGER_CST)
715: {
716: yyerror("case label does not reduce to an integer constant");
717: value = error_mark_node;
718: }
719: pushcase(value, l);
720: $$ = build_compound (input_filename, @1.first_line, chainon(l, $4));
721: }
722: | DEFAULT ':' stmt
723: {
724: tree l = build_label (input_filename, @1.first_line, 0, current_block);
725: pushcase(NULL_TREE, l);
726: $$ = build_compound (input_filename, @1.first_line, chainon(l, $3));
727: }
728: | BREAK ';'
729: { if (current_break_label)
730: $$ = build_goto (input_filename, @1.first_line, STMT_BODY (current_break_label));
731: else
732: {
733: yyerror("break statement not within a do, for, while or switch statement");
734: $$ = error_mark_node;
735: }
736: }
737: | CONTINUE ';'
738: { if (current_continue_label)
739: $$ = build_goto (input_filename, @1.first_line, STMT_BODY (current_continue_label));
740: else
741: {
742: yyerror("continue statement not within a do, for or while statement");
743: $$ = error_mark_node;
744: }
745: }
746: | RETURN ';'
747: { $$ = build_return (input_filename, @1.first_line, NULL_TREE); }
748: | RETURN expr ';'
749: { $$ = build_return_stmt (input_filename, @1.first_line, $2); }
750: | GOTO identifier ';'
751: { pushgoto($$ = build_goto (input_filename, @1.first_line, $2)); }
752: | ASM '(' STRING ')' ';'
753: { $$ = build_asm_stmt (input_filename, @1.first_line, $3); }
754: | identifier ':' stmt
755: { $$ = build_compound (input_filename, @1.first_line, chainon (build_label (input_filename, @1.first_line, $1, current_block), $3)); }
756: | ';'
757: { $$ = build_compound (input_filename, @1.first_line, 0); }
758: ;
759:
760: xexpr:
761: /* empty */
762: { $$ = NULL_TREE; }
763: | expr
764: ;
765:
766: /* This is what appears inside the parens in a function declarator.
767: Is value is represented in the format that grokdeclarator expects. */
768: parmlist: /* empty */
769: { $$ = NULL_TREE; }
770: | parms
771: { $$ = chainon ($1, build_tree_list (NULL_TREE,
772: void_type_node)); }
773: | parms ',' ELLIPSIS
774: ;
775:
776: /* A nonempty list of parameter declarations or type names. */
777: parms:
778: parm
779: { $$ = build_tree_list (NULL_TREE, $1); }
780: | parms ',' parm
781: { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
782: ;
783:
784: parm:
785: typespecs declarator
786: { $$ = build_tree_list ($1, $2) ; }
787: | typespecs absdcl
788: { $$ = build_tree_list ($1, $2); }
789: ;
790:
791: /* A nonempty list of identifiers. */
792: identifiers:
793: IDENTIFIER
794: { $$ = build_tree_list (NULL_TREE, $1); }
795: | identifiers ',' IDENTIFIER
796: { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
797: ;
798: %%
799:
800: static tree
801: finish_compound_stmt(block, stmts, outer_block, line)
802: tree block, stmts, outer_block;
803: int line;
804: {
805: register tree decls = getdecls();
806: register tree tags = gettags ();
807:
808: if (decls || tags)
809: {
810: finish_block (block, decls, tags, stmts);
811: poplevel();
812: current_block = outer_block;
813: STMT_SOURCE_LINE (block) = line;
814: return block;
815: }
816: else
817: {
818: current_block = outer_block;
819: poplevel();
820: return build_compound (input_filename, line, stmts);
821: }
822: }
823:
824:
825:
826: static void
827: pushbreak(a)
828: int a;
829: {
830: if (current_break_label)
831: TREE_CHAIN (current_break_label) = break_label_stack;
832: break_label_stack = current_break_label;
833: current_break_label = build_label (0, 0, NULL_TREE, current_block);
834:
835: if (a)
836: {
837: if (current_continue_label)
838: TREE_CHAIN (current_continue_label) = continue_label_stack;
839: continue_label_stack = current_continue_label;
840: current_continue_label = build_label (0, 0, NULL_TREE, current_block);
841: }
842: }
843:
844: static void
845: popbreak(a)
846: int a;
847: {
848: current_break_label = break_label_stack;
849: if (current_break_label)
850: break_label_stack = TREE_CHAIN (break_label_stack);
851:
852: if (a)
853: {
854: current_continue_label = continue_label_stack;
855: if (current_continue_label)
856: continue_label_stack = TREE_CHAIN (continue_label_stack);
857: }
858:
859: if (current_break_label)
860: TREE_CHAIN (current_break_label) = NULL;
861: if (current_continue_label)
862: TREE_CHAIN (current_continue_label) = NULL;
863: }
864:
865: /* Return something to represent absolute declarators containing a *.
866: TARGET is the absolute declarator that the * contains.
867: TYPEMODS is a list of modifiers such as const or volatile
868: to apply to the pointer type, represented as identifiers.
869:
870: We return an INDIRECT_REF whose "contents" are TARGET
871: and whose type is the modifier list. */
872:
873: static tree
874: make_pointer_declarator (typemods, target)
875: tree typemods, target;
876: {
877: register tree t = build1 (INDIRECT_REF, target);
878: TREE_TYPE (t) = typemods;
879: return t;
880: }
881:
882: /* Given a chain of STRING_CST nodes,
883: concatenate them into one STRING_CST
884: and then return an ADDR_EXPR for it. */
885:
886: static tree
887: combine_strings (strings)
888: tree strings;
889: {
890: register tree value, t;
891:
892: if (TREE_CHAIN (strings))
893: {
894: /* More than one in the chain, so concatenate. */
895: register char *p, *q;
896: register int length = 1;
897:
898: /* Don't include the \0 at the end of each substring,
899: except for the last one. */
900: for (t = strings; t; t = TREE_CHAIN (t))
901: length += TREE_STRING_LENGTH (t) - 1;
902:
903: p = (char *) oballoc (length);
904:
905: q = p;
906: for (t = strings; t; t = TREE_CHAIN (t))
907: {
908: bcopy (TREE_STRING_POINTER (t), q, TREE_STRING_LENGTH (t) - 1);
909: q += TREE_STRING_LENGTH (t) - 1;
910: }
911: *q = 0;
912:
913: value = make_node (STRING_CST);
914: TREE_TYPE (value) = TREE_TYPE (strings);
915: TREE_STRING_POINTER (value) = p;
916: TREE_STRING_LENGTH (value) = length;
917: TREE_LITERAL (value) = 1;
918: }
919: else
920: value = strings;
921:
922: value = build1 (ADDR_EXPR, value);
923: TREE_TYPE (value) = string_type_node;
924: TREE_LITERAL (value) = 1;
925: return value;
926: }
927:
928: int lineno; /* current line number in file being read */
929:
930: FILE *finput; /* input file.
931: Normally a pipe from the preprocessor. */
932:
933: /* lexical analyzer */
934:
935: static int maxtoken; /* Current length of token buffer */
936: static char *token_buffer; /* Pointer to token buffer */
937:
938: /* frw[i] is index in rw of the first word whose length is i. */
939:
940: #define MAXRESERVED 9
941:
942: static char frw[10] =
943: { 0, 0, 0, 2, 5, 13, 19, 27, 29, 33 };
944:
945: static char *rw[] =
946: { "if", "do", "int", "for", "asm",
947: "case", "char", "auto", "goto", "else", "long", "void", "enum",
948: "float", "short", "union", "break", "while", "const",
949: "double", "static", "extern", "struct", "return", "sizeof", "switch", "signed",
950: "typedef", "default",
951: "unsigned", "continue", "register", "volatile" };
952:
953: static short rtoken[] =
954: { IF, DO, TYPESPEC, FOR, ASM,
955: CASE, TYPESPEC, SCSPEC, GOTO, ELSE, TYPESPEC, TYPESPEC, ENUM,
956: TYPESPEC, TYPESPEC, UNION, BREAK, WHILE, TYPEMOD,
957: TYPESPEC, SCSPEC, SCSPEC, STRUCT, RETURN, SIZEOF, SWITCH, TYPESPEC,
958: SCSPEC, DEFAULT,
959: TYPESPEC, CONTINUE, SCSPEC, TYPEMOD };
960:
961: /* This table corresponds to rw and rtoken.
962: Its element is an index in ridpointers */
963:
964: #define NORID (enum rid) 0
965:
966: static enum rid rid[] =
967: { NORID, NORID, RID_INT, NORID, NORID,
968: NORID, RID_CHAR, RID_AUTO, NORID, NORID, RID_LONG, RID_VOID, NORID,
969: RID_FLOAT, RID_SHORT, NORID, NORID, NORID, RID_CONST,
970: RID_DOUBLE, RID_STATIC, RID_EXTERN, NORID, NORID, NORID, NORID, RID_SIGNED,
971: RID_TYPEDEF, NORID,
972: RID_UNSIGNED, NORID, RID_REGISTER, RID_VOLATILE };
973:
974: /* The elements of `ridpointers' are identifier nodes
975: for the reserved type names and storage classes. */
976:
977: tree ridpointers[(int) RID_MAX];
978:
979: static tree line_identifier; /* The identifier node named "line" */
980:
981: void check_newline();
982:
983: void
984: init_lex()
985: {
986: extern char *malloc();
987:
988: /* Start it at 0, because check_newline is called atthe very beginning
989: and will increment it to 1. */
990: lineno = 0;
991: current_function_decl = NULL;
992: current_switch_stmt = NULL;
993: current_block = NULL;
994: current_break_label = NULL;
995: current_continue_label = NULL;
996: break_label_stack = NULL;
997: continue_label_stack = NULL;
998: line_identifier = get_identifier("line");
999:
1000: maxtoken = 40;
1001: token_buffer = malloc((unsigned)(maxtoken+1));
1002: ridpointers[(int) RID_INT] = get_identifier("int");
1003: ridpointers[(int) RID_CHAR] = get_identifier("char");
1004: ridpointers[(int) RID_VOID] = get_identifier("void");
1005: ridpointers[(int) RID_FLOAT] = get_identifier("float");
1006: ridpointers[(int) RID_DOUBLE] = get_identifier("double");
1007: ridpointers[(int) RID_SHORT] = get_identifier("short");
1008: ridpointers[(int) RID_LONG] = get_identifier("long");
1009: ridpointers[(int) RID_UNSIGNED] = get_identifier("unsigned");
1010: ridpointers[(int) RID_SIGNED] = get_identifier("signed");
1011: ridpointers[(int) RID_CONST] = get_identifier("const");
1012: ridpointers[(int) RID_VOLATILE] = get_identifier("volatile");
1013: ridpointers[(int) RID_AUTO] = get_identifier("auto");
1014: ridpointers[(int) RID_STATIC] = get_identifier("static");
1015: ridpointers[(int) RID_EXTERN] = get_identifier("extern");
1016: ridpointers[(int) RID_TYPEDEF] = get_identifier("typedef");
1017: ridpointers[(int) RID_REGISTER] = get_identifier("register");
1018: }
1019:
1020: static int
1021: skip_white_space()
1022: {
1023: register int c;
1024: register int inside;
1025:
1026: c = getc(finput);
1027:
1028: for (;;)
1029: {
1030: switch (c)
1031: {
1032: case '/':
1033: c = getc(finput);
1034: if (c != '*')
1035: {
1036: ungetc(c, finput);
1037: return '/';
1038: }
1039:
1040: c = getc(finput);
1041:
1042: inside = 1;
1043: while (inside)
1044: {
1045: if (c == '*')
1046: {
1047: while (c == '*')
1048: c = getc(finput);
1049:
1050: if (c == '/')
1051: {
1052: inside = 0;
1053: c = getc(finput);
1054: }
1055: }
1056: else if (c == '\n')
1057: {
1058: lineno++;
1059: c = getc(finput);
1060: }
1061: else if (c == EOF)
1062: yyerror("unterminated comment");
1063: else
1064: c = getc(finput);
1065: }
1066:
1067: break;
1068:
1069: case '\n':
1070: check_newline();
1071:
1072: case ' ':
1073: case '\t':
1074: case '\f':
1075: case '\r':
1076: case '\b':
1077: c = getc(finput);
1078: break;
1079:
1080: case '\\':
1081: c = getc(finput);
1082: if (c == '\n')
1083: lineno++;
1084: else
1085: yyerror("stray '\\' in program");
1086: c = getc(finput);
1087: break;
1088:
1089: default:
1090: return (c);
1091: }
1092: }
1093: }
1094:
1095:
1096:
1097: /* make the token buffer longer, preserving the data in it.
1098: p should point to just beyond the last valid character in the old buffer
1099: and the value points to the corresponding place in the new one. */
1100:
1101: static char *
1102: extend_token_buffer(p)
1103: char *p;
1104: {
1105: register char *newbuf;
1106: register char *value;
1107: int newlength = maxtoken * 2 + 10;
1108: register char *p2, *p1;
1109: extern char *malloc();
1110:
1111: newbuf = malloc((unsigned)(newlength+1));
1112:
1113: p2 = newbuf;
1114: p1 = newbuf + newlength + 1;
1115: while (p1 != p2) *p2++ = 0;
1116:
1117: value = newbuf;
1118: p2 = token_buffer;
1119: while (p2 != p)
1120: *value++ = *p2++;
1121:
1122: token_buffer = newbuf;
1123:
1124: maxtoken = newlength;
1125:
1126: return (value);
1127: }
1128:
1129:
1130:
1131: /* At the beginning of a line,
1132: increment the line number
1133: and handle a #line directive immediately following */
1134:
1135: void
1136: check_newline ()
1137: {
1138: register int c;
1139: register int token;
1140:
1141: while (1)
1142: {
1143: c = getc (finput);
1144: lineno++;
1145:
1146: if (c != '#')
1147: {
1148: /* If no #, unread the character,
1149: except don't bother if it is whitespace. */
1150: if (c == ' ' || c == '\t')
1151: return;
1152: ungetc (c, finput);
1153: return;
1154: }
1155:
1156: /* Skip whitespace after the #. */
1157:
1158: while (1)
1159: {
1160: c = getc (finput);
1161: if (! (c == ' ' || c == '\t'))
1162: break;
1163: }
1164:
1165: /* If the # is the only nonwhite char on the line,
1166: just ignore it. Check the new newline. */
1167: if (c == '\n')
1168: continue;
1169:
1170: /* Something follows the #; read a token. */
1171:
1172: ungetc (c, finput);
1173: token = yylex ();
1174:
1175: if (token == CONSTANT
1176: && TREE_CODE (yylval.ttype) == INTEGER_CST)
1177: {
1178: /* subtract one, because it is the following line that
1179: gets the specified number */
1180:
1181: int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
1182:
1183: token = yylex ();
1184: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1185: yyerror ("invalid #line");
1186:
1187: input_filename
1188: = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
1189: strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
1190: lineno = l;
1191: }
1192: else
1193: yyerror ("undefined or invalid # directive");
1194:
1195: /* skip the rest of this line. */
1196: while ((c = getc (finput)) != '\n');
1197: }
1198: }
1199:
1200:
1201:
1202: #define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9'))
1203: #define isdigit(char) (char >= '0' && char <= '9')
1204: #define ENDFILE -1 /* token that represents end-of-file */
1205:
1206:
1207: static int
1208: readescape ()
1209: {
1210: register int c = getc (finput);
1211: register int count, code;
1212:
1213: switch (c)
1214: {
1215: case 'x':
1216: code = 0;
1217: count = 0;
1218: while (1)
1219: {
1220: c = getc (finput);
1221: if (!(c >= 'a' && c <= 'f')
1222: && !(c >= 'A' && c <= 'F')
1223: && !(c >= '0' && c <= '9'))
1224: {
1225: ungetc (c, finput);
1226: break;
1227: }
1228: if (c >= 'a' && c <= 'z')
1229: c -= 'a' - 'A';
1230: code *= 16;
1231: if (c >= 'a' && c <= 'f')
1232: code += c - 'a' + 10;
1233: if (c >= 'A' && c <= 'F')
1234: code += c - 'A' + 10;
1235: if (c >= '0' && c <= '9')
1236: code += c - '0';
1237: count++;
1238: if (count == 3)
1239: break;
1240: }
1241: if (count == 0)
1242: yyerror ("\\x used with no following hex digits");
1243: return code;
1244:
1245: case '0': case '1': case '2': case '3': case '4':
1246: case '5': case '6': case '7':
1247: code = 0;
1248: count = 0;
1249: while ((c <= '7') && (c >= '0') && (count++ < 3))
1250: {
1251: code = (code * 8) + (c - '0');
1252: c = getc (finput);
1253: }
1254: ungetc (c, finput);
1255: return code;
1256:
1257: case '\\': case '\'': case '"':
1258: return c;
1259:
1260: case '\n':
1261: lineno++;
1262: return -1;
1263:
1264: case 'n':
1265: return TARGET_NEWLINE;
1266:
1267: case 't':
1268: return TARGET_TAB;
1269:
1270: case 'r':
1271: return TARGET_CR;
1272:
1273: case 'f':
1274: return TARGET_FF;
1275:
1276: case 'b':
1277: return TARGET_BS;
1278:
1279: case 'a':
1280: return TARGET_BELL;
1281:
1282: case 'v':
1283: return TARGET_VT;
1284: }
1285: return c;
1286: }
1287:
1288:
1289: static int
1290: yylex()
1291: {
1292: register int c;
1293: register char *p;
1294: register int value;
1295:
1296: c = skip_white_space();
1297:
1298: yylloc.first_line = lineno;
1299:
1300: switch (c)
1301: {
1302: case EOF:
1303: value = ENDFILE; break;
1304:
1305: case 'A': case 'B': case 'C': case 'D': case 'E':
1306: case 'F': case 'G': case 'H': case 'I': case 'J':
1307: case 'K': case 'L': case 'M': case 'N': case 'O':
1308: case 'P': case 'Q': case 'R': case 'S': case 'T':
1309: case 'U': case 'V': case 'W': case 'X': case 'Y':
1310: case 'Z':
1311: case 'a': case 'b': case 'c': case 'd': case 'e':
1312: case 'f': case 'g': case 'h': case 'i': case 'j':
1313: case 'k': case 'l': case 'm': case 'n': case 'o':
1314: case 'p': case 'q': case 'r': case 's': case 't':
1315: case 'u': case 'v': case 'w': case 'x': case 'y':
1316: case 'z':
1317: case '_':
1318: p = token_buffer;
1319: while (isalnum(c) || (c == '_'))
1320: {
1321: if (p >= token_buffer + maxtoken)
1322: p = extend_token_buffer(p);
1323: *p++ = c;
1324: c = getc(finput);
1325: }
1326:
1327: *p = 0;
1328: ungetc(c, finput);
1329:
1330: value = IDENTIFIER;
1331: yylval.itype = 0;
1332:
1333: if (p - token_buffer <= MAXRESERVED)
1334: {
1335: register int lim = frw [p - token_buffer + 1];
1336: register int i;
1337:
1338: for (i = frw[p - token_buffer]; i < lim; i++)
1339: if (rw[i][0] == token_buffer[0] && !strcmp(rw[i], token_buffer))
1340: {
1341: if (rid[i])
1342: yylval.ttype = ridpointers[(int) rid[i]];
1343: value = (int) rtoken[i];
1344: break;
1345: }
1346: }
1347:
1348: if (value == IDENTIFIER)
1349: {
1350: yylval.ttype = get_identifier(token_buffer);
1351: lastiddecl = lookup_name (yylval.ttype);
1352:
1353: if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL)
1354: value = TYPENAME;
1355: }
1356:
1357: break;
1358:
1359: case '0': case '1': case '2': case '3': case '4':
1360: case '5': case '6': case '7': case '8': case '9':
1361: case '.':
1362: {
1363: int base = 10;
1364: int count = 0;
1365: /* for multi-precision arithmetic, we store only 8 live bits in each short,
1366: giving us 64 bits of reliable precision */
1367: short shorts[8];
1368: char *floatflag = NULL; /* set nonzero if we learn this is a floating constant */
1369: /* in fact, it points to the first fractional digit. */
1370:
1371: for (count = 0; count < 8; count++)
1372: shorts[count] = 0;
1373:
1374: p = token_buffer;
1375: *p++ = c;
1376:
1377: if (c == '0')
1378: {
1379: *p++ = (c = getc(finput));
1380: if ((c == 'x') || (c == 'X'))
1381: {
1382: base = 16;
1383: *p++ = (c = getc(finput));
1384: }
1385: else
1386: {
1387: base = 8;
1388: }
1389: }
1390:
1391: while (c == '.'
1392: || (isalnum (c) && (c != 'l') && (c != 'L')
1393: && (c != 'u') && (c != 'U')))
1394: {
1395: if (c == '.')
1396: {
1397: floatflag = p - 1;
1398: p[-1] = c = getc(finput); /* omit the decimal point from
1399: the token buffer. */
1400: /* Accept '.' as the start of a floating-point number
1401: only when it is followed by a digit.
1402: Otherwise, unread the following non-digit
1403: and use the '.' as a structural token. */
1404: if (floatflag == token_buffer && !isdigit (c))
1405: {
1406: if (c == '.')
1407: {
1408: c = getc (finput);
1409: if (c == '.')
1410: return ELLIPSIS;
1411: yyerror ("syntax error");
1412: }
1413: ungetc (c, finput);
1414: return '.';
1415: }
1416: }
1417: else
1418: {
1419: if (isdigit(c))
1420: {
1421: c = c - '0';
1422: }
1423: else if (base <= 10)
1424: {
1425: if ((c&~040) == 'E')
1426: {
1427: if (floatflag == 0)
1428: floatflag = p - 1;
1429: break; /* start of exponent */
1430: }
1431: yyerror("nondigits in number and not hexadecimal");
1432: c = 0;
1433: }
1434: else if (c >= 'a')
1435: {
1436: c = c - 'a' + 10;
1437: }
1438: else
1439: {
1440: c = c - 'A' + 10;
1441: }
1442: if (c >= base)
1443: yyerror("numeric constant contains digits beyond the radix");
1444:
1445: for (count = 0; count < 8; count++)
1446: {
1447: (shorts[count] *= base);
1448: if (count)
1449: {
1450: shorts[count] += (shorts[count-1] >> 8);
1451: shorts[count-1] &= (1<<8)-1;
1452: }
1453: else shorts[0] += c;
1454: }
1455:
1456: *p++ = (c = getc(finput));
1457: }
1458: }
1459:
1460: /* Remove terminating char from the token buffer and delimit the string */
1461: *--p = 0;
1462:
1463: if (floatflag)
1464: {
1465: register ex = -(p - floatflag); /* exponent is minus # digits after decimal pt */
1466:
1467: tree type = double_type_node;
1468:
1469: /* read explicit exponent if any, and add into ex. */
1470:
1471: if ((c == 'e') || (c == 'E'))
1472: {
1473: register int exval = 0;
1474: register int exsign = 1;
1475:
1476: c = getc(finput);
1477: if ((c == '+') || (c == '-'))
1478: {
1479: if (c == '-') exsign = -1;
1480: c = getc(finput);
1481: }
1482: while (isdigit(c))
1483: {
1484: exval *= 10;
1485: exval += c - '0';
1486: c = getc(finput);
1487: }
1488: ex += exsign*exval;
1489: }
1490:
1491: while (1)
1492: {
1493: if (c == 'f' || c == 'F')
1494: type = float_type_node;
1495: else if (c == 'l' || c == 'L')
1496: type = long_double_type_node;
1497: else break;
1498: c = getc (finput);
1499: }
1500:
1501: ungetc(c, finput);
1502:
1503: yylval.ttype = build_real_from_string (token_buffer, ex);
1504: TREE_TYPE (yylval.ttype) = type;
1505: }
1506: else
1507: {
1508: tree type;
1509: int spec_unsigned = 0;
1510: int spec_long = 0;
1511:
1512: while (1)
1513: {
1514: if (c == 'u' || c == 'U')
1515: {
1516: spec_unsigned = 1;
1517: c = getc (finput);
1518: }
1519: else if (c == 'l' || c == 'L')
1520: {
1521: spec_long = 1;
1522: c = getc (finput);
1523: }
1524: else break;
1525: }
1526:
1527: ungetc (c, finput);
1528:
1529: /* This is simplified by the fact that our constant
1530: is always positive. */
1531: yylval.ttype
1532: = build_int_2 ((shorts[3]<<24) + (shorts[2]<<16) + (shorts[1]<<8) + shorts[0],
1533: (shorts[7]<<24) + (shorts[6]<<16) + (shorts[5]<<8) + shorts[4]);
1534:
1535: if (!spec_long && !spec_unsigned
1536: && int_fits_type_p (yylval.ttype, integer_type_node))
1537: type = integer_type_node;
1538:
1539: else if (!spec_long && base != 10
1540: && int_fits_type_p (yylval.ttype, unsigned_type_node))
1541: type = unsigned_type_node;
1542:
1543: else if (!spec_unsigned
1544: && int_fits_type_p (yylval.ttype, long_integer_type_node))
1545: type = long_integer_type_node;
1546:
1547: else
1548: type = long_unsigned_type_node;
1549:
1550: TREE_TYPE (yylval.ttype) = type;
1551: }
1552:
1553: value = CONSTANT; break;
1554: }
1555:
1556: case '\'':
1557: c = getc(finput);
1558: {
1559: register int code = 0;
1560:
1561: tryagain:
1562:
1563: if (c == '\\')
1564: {
1565: c = readescape ();
1566: if (c < 0)
1567: goto tryagain;
1568: }
1569: code = c;
1570: c = getc (finput);
1571: if (c != '\'')
1572: yyerror("malformatted character constant");
1573:
1574: if (char_type_node == unsigned_char_type_node
1575: || (c >> (BITS_PER_UNIT - 1)) == 0)
1576: yylval.ttype = build_int_2 (code, 0);
1577: else
1578: yylval.ttype = build_int_2 (code | (1 << BITS_PER_UNIT), -1);
1579:
1580: TREE_TYPE (yylval.ttype) = char_type_node;
1581: value = CONSTANT; break;
1582: }
1583:
1584: case '"':
1585: {
1586: c = getc(finput);
1587: p = token_buffer;
1588:
1589: while (c != '"')
1590: {
1591: if (c == '\\')
1592: {
1593: c = readescape ();
1594: if (c < 0)
1595: goto skipnewline;
1596: }
1597: else if (c == '\n')
1598: {
1599: lineno++;
1600: }
1601:
1602: if (p == token_buffer + maxtoken)
1603: p = extend_token_buffer(p);
1604: *p++ = c;
1605:
1606: skipnewline:
1607: c = getc (finput);
1608: }
1609:
1610: *p++ = 0;
1611:
1612: yylval.ttype = build_string (p - token_buffer, token_buffer);
1613: TREE_TYPE (yylval.ttype) = char_array_type_node;
1614:
1615: value = STRING; break;
1616: }
1617:
1618: case '+':
1619: case '-':
1620: case '&':
1621: case '|':
1622: case '<':
1623: case '>':
1624: case '*':
1625: case '/':
1626: case '%':
1627: case '^':
1628: case '!':
1629: case '=':
1630: {
1631: register int c1;
1632:
1633: combine:
1634:
1635: switch (c)
1636: {
1637: case '+':
1638: yylval.code = PLUS_EXPR; break;
1639: case '-':
1640: yylval.code = MINUS_EXPR; break;
1641: case '&':
1642: yylval.code = BIT_AND_EXPR; break;
1643: case '|':
1644: yylval.code = BIT_IOR_EXPR; break;
1645: case '*':
1646: yylval.code = MULT_EXPR; break;
1647: case '/':
1648: yylval.code = TRUNC_DIV_EXPR; break;
1649: case '%':
1650: yylval.code = TRUNC_MOD_EXPR; break;
1651: case '^':
1652: yylval.code = BIT_XOR_EXPR; break;
1653: case LSHIFT:
1654: yylval.code = LSHIFT_EXPR; break;
1655: case RSHIFT:
1656: yylval.code = RSHIFT_EXPR; break;
1657: case '<':
1658: yylval.code = LT_EXPR; break;
1659: case '>':
1660: yylval.code = GT_EXPR; break;
1661: }
1662:
1663: c1 = getc(finput);
1664:
1665: if (c1 == '=')
1666: {
1667: switch (c)
1668: {
1669: case '<':
1670: value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
1671: case '>':
1672: value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
1673: case '!':
1674: value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
1675: case '=':
1676: value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
1677: }
1678: value = ASSIGN; goto done;
1679: }
1680: else if (c == c1)
1681: switch (c)
1682: {
1683: case '+':
1684: value = PLUSPLUS; goto done;
1685: case '-':
1686: value = MINUSMINUS; goto done;
1687: case '&':
1688: value = ANDAND; goto done;
1689: case '|':
1690: value = OROR; goto done;
1691: case '<':
1692: c = LSHIFT;
1693: goto combine;
1694: case '>':
1695: c = RSHIFT;
1696: goto combine;
1697: }
1698: else if ((c == '-') && (c1 == '>'))
1699: { value = POINTSAT; goto done; }
1700: ungetc (c1, finput);
1701:
1702: if ((c == '<') || (c == '>'))
1703: value = ARITHCOMPARE;
1704: else value = c;
1705: goto done;
1706: }
1707:
1708: default:
1709: value = c;
1710: }
1711:
1712: done:
1713: yylloc.last_line = lineno;
1714:
1715: return (value);
1716: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.