|
|
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.