Annotation of gcc/parse.y, revision 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.