Annotation of gcc/parse.y, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.