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