Annotation of gcc/c-parse.y, revision 1.1.1.15

1.1       root        1: /* YACC parser for C syntax.
1.1.1.9   root        2:    Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
1.1.1.9   root        6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 1, or (at your option)
                      9: any later version.
                     10: 
1.1       root       11: GNU CC is distributed in the hope that it will be useful,
1.1.1.9   root       12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
1.1       root       19: 
                     20: 
1.1.1.9   root       21: /* To whomever it may concern: I have heard that such a thing was once
                     22: written by AT&T, but I have never seen it.  */
1.1       root       23: 
1.1.1.10  root       24: %expect 8
1.1       root       25: 
1.1.1.11  root       26: /* These are the 8 conflicts you should get in parse.output;
1.1       root       27:    the state numbers may vary if minor changes in the grammar are made.
                     28: 
                     29: State 41 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
1.1.1.11  root       30: State 92 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
                     31: State 99 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
                     32: State 103 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
                     33: State 119 contains 1 shift/reduce conflict.  (See comment at component_decl.)
                     34: State 183 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
                     35: State 193 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
                     36: State 199 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
1.1       root       37: */
                     38: 
                     39: %{
                     40: #include "config.h"
                     41: #include "tree.h"
1.1.1.11  root       42: #include "input.h"
1.1.1.2   root       43: #include "c-parse.h"
1.1       root       44: #include "c-tree.h"
                     45: 
                     46: #include <stdio.h>
                     47: #include <errno.h>
                     48: 
                     49: #ifndef errno
                     50: extern int errno;
                     51: #endif
                     52: 
1.1.1.10  root       53: void yyerror ();
                     54: 
1.1       root       55: /* Cause the `yydebug' variable to be defined.  */
1.1.1.8   root       56: #define YYDEBUG 1
1.1       root       57: %}
                     58: 
                     59: %start program
                     60: 
1.1.1.9   root       61: %union {long itype; tree ttype; enum tree_code code; }
1.1       root       62: 
                     63: /* All identifiers that are not reserved words
                     64:    and are not declared typedefs in the current block */
                     65: %token IDENTIFIER
                     66: 
                     67: /* All identifiers that are declared typedefs in the current block.
                     68:    In some contexts, they are treated just like IDENTIFIER,
                     69:    but they can also serve as typespecs in declarations.  */
                     70: %token TYPENAME
                     71: 
                     72: /* Reserved words that specify storage class.
                     73:    yylval contains an IDENTIFIER_NODE which indicates which one.  */
                     74: %token SCSPEC
                     75: 
                     76: /* Reserved words that specify type.
                     77:    yylval contains an IDENTIFIER_NODE which indicates which one.  */
                     78: %token TYPESPEC
                     79: 
                     80: /* Reserved words that qualify type: "const" or "volatile".
                     81:    yylval contains an IDENTIFIER_NODE which indicates which one.  */
                     82: %token TYPE_QUAL
                     83: 
                     84: /* Character or numeric constants.
                     85:    yylval is the node for the constant.  */
                     86: %token CONSTANT
                     87: 
                     88: /* String constants in raw form.
                     89:    yylval is a STRING_CST node.  */
                     90: %token STRING
                     91: 
                     92: /* "...", used for functions with variable arglists.  */
                     93: %token ELLIPSIS
                     94: 
                     95: /* the reserved words */
                     96: %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
                     97: %token BREAK CONTINUE RETURN GOTO ASM TYPEOF ALIGNOF
1.1.1.11  root       98: %token ATTRIBUTE
1.1       root       99: 
1.1.1.10  root      100: /* Add precedence rules to solve dangling else s/r conflict */
                    101: %nonassoc IF
                    102: %nonassoc ELSE
                    103: 
1.1       root      104: /* Define the operator tokens and their precedences.
                    105:    The value is an integer because, if used, it is the tree code
                    106:    to use in the expression made from the operator.  */
                    107: 
                    108: %right <code> ASSIGN '='
                    109: %right <code> '?' ':'
                    110: %left <code> OROR
                    111: %left <code> ANDAND
                    112: %left <code> '|'
                    113: %left <code> '^'
                    114: %left <code> '&'
                    115: %left <code> EQCOMPARE
                    116: %left <code> ARITHCOMPARE
                    117: %left <code> LSHIFT RSHIFT
                    118: %left <code> '+' '-'
                    119: %left <code> '*' '/' '%'
                    120: %right <code> UNARY PLUSPLUS MINUSMINUS
                    121: %left HYPERUNARY
1.1.1.10  root      122: %left <code> POINTSAT '.' '(' '['
1.1       root      123: 
                    124: %type <code> unop
                    125: 
                    126: %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
1.1.1.8   root      127: %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
1.1       root      128: %type <ttype> typed_declspecs reserved_declspecs
                    129: %type <ttype> typed_typespecs reserved_typespecquals
                    130: %type <ttype> declmods typespec typespecqual_reserved
                    131: %type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
                    132: %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
                    133: %type <ttype> init initlist maybeasm
1.1.1.3   root      134: %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
1.1.1.11  root      135: %type <ttype> maybe_attribute attribute_list attrib
                    136: 
                    137: %type <ttype> compstmt
1.1       root      138: 
                    139: %type <ttype> declarator
                    140: %type <ttype> notype_declarator after_type_declarator
                    141: %type <ttype> parm_declarator
                    142: 
1.1.1.13  root      143: %type <ttype> structsp component_decl_list component_decl_list2
                    144: %type <ttype> component_decl components component_declarator
1.1       root      145: %type <ttype> enumlist enumerator
                    146: %type <ttype> typename absdcl absdcl1 type_quals
                    147: %type <ttype> xexpr parms parm identifiers
                    148: 
                    149: %type <ttype> parmlist parmlist_1 parmlist_2
                    150: %type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
                    151: 
                    152: %type <itype> setspecs
                    153: 
                    154: %{
                    155: /* the declaration found for the last IDENTIFIER token read in.
                    156:    yylex must look this up to detect typedefs, which get token type TYPENAME,
                    157:    so it is left around in case the identifier is not a typedef but is
                    158:    used in a context which makes it a reference to a variable.  */
                    159: static tree lastiddecl;
                    160: 
                    161: static tree make_pointer_declarator ();
                    162: static tree combine_strings ();
                    163: static void reinit_parse_for_function ();
                    164: 
1.1.1.11  root      165: /* List of types and structure classes of the current declaration.  */
1.1       root      166: tree current_declspecs;
                    167: 
1.1.1.11  root      168: /* Stack of saved values of current_declspecs.  */
                    169: tree declspec_stack;
1.1       root      170: 
1.1.1.11  root      171: int undeclared_variable_notice;        /* 1 if we explained undeclared var errors.  */
1.1.1.8   root      172: 
1.1       root      173: static int yylex ();
                    174: %}
                    175: 
                    176: %%
                    177: program: /* empty */
                    178:        | extdefs
                    179:        ;
                    180: 
                    181: /* the reason for the strange actions in this rule
                    182:  is so that notype_initdecls when reached via datadef
                    183:  can find a valid list of type and sc specs in $0. */
                    184: 
                    185: extdefs:
                    186:        {$<ttype>$ = NULL_TREE; } extdef
                    187:        | extdefs {$<ttype>$ = NULL_TREE; } extdef
                    188:        ;
                    189: 
                    190: extdef:
                    191:        fndef
                    192:        | datadef
                    193:        | ASM '(' string ')' ';'
1.1.1.15! root      194:                { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
1.1       root      195:                  assemble_asm ($3); }
                    196:        ;
                    197: 
                    198: datadef:
                    199:          setspecs notype_initdecls ';'
                    200:                { if (pedantic)
                    201:                    error ("ANSI C forbids data definition lacking type or storage class");
1.1.1.3   root      202:                  else if (!flag_traditional)
1.1       root      203:                    warning ("data definition lacks type or storage class"); }
                    204:         | declmods setspecs notype_initdecls ';'
                    205:          {}
                    206:        | typed_declspecs setspecs initdecls ';'
                    207:          {}
                    208:         | declmods ';'
                    209:          { error ("empty declaration"); }
                    210:        | typed_declspecs ';'
                    211:          { shadow_tag ($1); }
                    212:        | error ';'
                    213:        | error '}'
                    214:        | ';'
1.1.1.11  root      215:                { if (pedantic)
                    216:                    warning ("ANSI C does not allow extra `;' outside of a function"); }
1.1       root      217:        ;
                    218: 
                    219: fndef:
                    220:          typed_declspecs setspecs declarator
                    221:                { if (! start_function ($1, $3))
1.1.1.13  root      222:                    YYFAIL;
1.1       root      223:                  reinit_parse_for_function (); }
                    224:          xdecls
                    225:                { store_parm_decls (); }
                    226:          compstmt_or_error
1.1.1.11  root      227:                { finish_function (lineno); }
1.1       root      228:        | typed_declspecs setspecs declarator error
                    229:                { }
                    230:        | declmods setspecs notype_declarator
                    231:                { if (! start_function ($1, $3))
1.1.1.13  root      232:                    YYFAIL;
1.1       root      233:                  reinit_parse_for_function (); }
                    234:          xdecls
                    235:                { store_parm_decls (); }
                    236:          compstmt_or_error
1.1.1.11  root      237:                { finish_function (lineno); }
1.1       root      238:        | declmods setspecs notype_declarator error
                    239:                { }
                    240:        | setspecs notype_declarator
                    241:                { if (! start_function (0, $2))
1.1.1.13  root      242:                    YYFAIL;
1.1       root      243:                  reinit_parse_for_function (); }
                    244:          xdecls
                    245:                { store_parm_decls (); }
                    246:          compstmt_or_error
1.1.1.11  root      247:                { finish_function (lineno); }
1.1       root      248:        | setspecs notype_declarator error
                    249:                { }
                    250:        ;
                    251: 
                    252: identifier:
                    253:        IDENTIFIER
                    254:        | TYPENAME
                    255:        ;
                    256: 
                    257: unop:     '&'
                    258:                { $$ = ADDR_EXPR; }
                    259:        | '-'
                    260:                { $$ = NEGATE_EXPR; }
                    261:        | '+'
                    262:                { $$ = CONVERT_EXPR; }
                    263:        | PLUSPLUS
                    264:                { $$ = PREINCREMENT_EXPR; }
                    265:        | MINUSMINUS
                    266:                { $$ = PREDECREMENT_EXPR; }
                    267:        | '~'
                    268:                { $$ = BIT_NOT_EXPR; }
                    269:        | '!'
                    270:                { $$ = TRUTH_NOT_EXPR; }
                    271:        ;
                    272: 
                    273: expr:  nonnull_exprlist
                    274:                { $$ = build_compound_expr ($1); }
                    275:        ;
                    276: 
                    277: exprlist:
                    278:          /* empty */
                    279:                { $$ = NULL_TREE; }
                    280:        | nonnull_exprlist
                    281:        ;
                    282: 
                    283: nonnull_exprlist:
                    284:        expr_no_commas
                    285:                { $$ = build_tree_list (NULL_TREE, $1); }
                    286:        | nonnull_exprlist ',' expr_no_commas
                    287:                { chainon ($1, build_tree_list (NULL_TREE, $3)); }
                    288:        ;
                    289: 
1.1.1.8   root      290: unary_expr:
1.1       root      291:        primary
1.1.1.8   root      292:        | '*' cast_expr   %prec UNARY
1.1       root      293:                { $$ = build_indirect_ref ($2, "unary *"); }
1.1.1.8   root      294:        | unop cast_expr  %prec UNARY
1.1       root      295:                { $$ = build_unary_op ($1, $2, 0); }
1.1.1.8   root      296:        | SIZEOF unary_expr  %prec UNARY
                    297:                { if (TREE_CODE ($2) == COMPONENT_REF
                    298:                      && TREE_PACKED (TREE_OPERAND ($2, 1)))
                    299:                    error ("`sizeof' applied to a bit-field");
1.1.1.12  root      300:                  /* ANSI says arrays and functions are converted inside comma.
                    301:                     But we can't really convert them in build_compound_expr
                    302:                     because that would break commas in lvalues.
                    303:                     So do the conversion here if operand was a comma.  */
                    304:                  if (TREE_CODE ($2) == COMPOUND_EXPR
                    305:                      && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE
                    306:                          || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE))
                    307:                    $2 = default_conversion ($2);
1.1.1.8   root      308:                  $$ = c_sizeof (TREE_TYPE ($2)); }
                    309:        | SIZEOF '(' typename ')'  %prec HYPERUNARY
                    310:                { $$ = c_sizeof (groktypename ($3)); }
                    311:        | ALIGNOF unary_expr  %prec UNARY
                    312:                { if (TREE_CODE ($2) == COMPONENT_REF
                    313:                      && TREE_PACKED (TREE_OPERAND ($2, 1)))
                    314:                    error ("`__alignof' applied to a bit-field");
1.1.1.11  root      315:                  if (TREE_CODE ($2) == INDIRECT_REF)
                    316:                    {
                    317:                      tree t = TREE_OPERAND ($2, 0);
                    318:                      tree best = t;
                    319:                      int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
                    320:                      while (TREE_CODE (t) == NOP_EXPR
                    321:                             && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
                    322:                        {
                    323:                          int thisalign;
                    324:                          t = TREE_OPERAND (t, 0);
                    325:                          thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
                    326:                          if (thisalign > bestalign)
                    327:                            best = t, bestalign = thisalign;
                    328:                        }
                    329:                      $$ = c_alignof (TREE_TYPE (TREE_TYPE (best)));
                    330:                    }
                    331:                  else
1.1.1.12  root      332:                    {
                    333:                      /* ANSI says arrays and fns are converted inside comma.
                    334:                         But we can't convert them in build_compound_expr
                    335:                         because that would break commas in lvalues.
                    336:                         So do the conversion here if operand was a comma.  */
                    337:                      if (TREE_CODE ($2) == COMPOUND_EXPR
                    338:                          && (TREE_CODE (TREE_TYPE ($2)) == ARRAY_TYPE
                    339:                              || TREE_CODE (TREE_TYPE ($2)) == FUNCTION_TYPE))
                    340:                        $2 = default_conversion ($2);
                    341:                      $$ = c_alignof (TREE_TYPE ($2));
                    342:                    }
                    343:                }
1.1.1.8   root      344:        | ALIGNOF '(' typename ')'  %prec HYPERUNARY
                    345:                { $$ = c_alignof (groktypename ($3)); }
                    346:        ;
                    347: 
                    348: cast_expr:
                    349:        unary_expr
                    350:        | '(' typename ')' cast_expr  %prec UNARY
1.1       root      351:                { tree type = groktypename ($2);
                    352:                  $$ = build_c_cast (type, $4); }
                    353:        | '(' typename ')' '{' initlist maybecomma '}'  %prec UNARY
                    354:                { tree type = groktypename ($2);
                    355:                  if (pedantic)
1.1.1.8   root      356:                    warning ("ANSI C forbids constructor expressions");
1.1       root      357:                  $$ = digest_init (type, build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5)), 0);
                    358:                  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
                    359:                    {
                    360:                      int failure = complete_array_type (type, $$, 1);
                    361:                      if (failure)
                    362:                        abort ();
                    363:                    }
                    364:                }
1.1.1.8   root      365:        ;
                    366: 
                    367: expr_no_commas:
                    368:          cast_expr
1.1       root      369:        | expr_no_commas '+' expr_no_commas
                    370:                { $$ = build_binary_op ($2, $1, $3); }
                    371:        | expr_no_commas '-' expr_no_commas
                    372:                { $$ = build_binary_op ($2, $1, $3); }
                    373:        | expr_no_commas '*' expr_no_commas
                    374:                { $$ = build_binary_op ($2, $1, $3); }
                    375:        | expr_no_commas '/' expr_no_commas
                    376:                { $$ = build_binary_op ($2, $1, $3); }
                    377:        | expr_no_commas '%' expr_no_commas
                    378:                { $$ = build_binary_op ($2, $1, $3); }
                    379:        | expr_no_commas LSHIFT expr_no_commas
                    380:                { $$ = build_binary_op ($2, $1, $3); }
                    381:        | expr_no_commas RSHIFT expr_no_commas
                    382:                { $$ = build_binary_op ($2, $1, $3); }
                    383:        | expr_no_commas ARITHCOMPARE expr_no_commas
                    384:                { $$ = build_binary_op ($2, $1, $3); }
                    385:        | expr_no_commas EQCOMPARE expr_no_commas
                    386:                { $$ = build_binary_op ($2, $1, $3); }
                    387:        | expr_no_commas '&' expr_no_commas
                    388:                { $$ = build_binary_op ($2, $1, $3); }
                    389:        | expr_no_commas '|' expr_no_commas
                    390:                { $$ = build_binary_op ($2, $1, $3); }
                    391:        | expr_no_commas '^' expr_no_commas
                    392:                { $$ = build_binary_op ($2, $1, $3); }
                    393:        | expr_no_commas ANDAND expr_no_commas
                    394:                { $$ = build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }
                    395:        | expr_no_commas OROR expr_no_commas
                    396:                { $$ = build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }
                    397:        | expr_no_commas '?' xexpr ':' expr_no_commas
                    398:                { $$ = build_conditional_expr ($1, $3, $5); }
                    399:        | expr_no_commas '=' expr_no_commas
                    400:                { $$ = build_modify_expr ($1, NOP_EXPR, $3); }
                    401:        | expr_no_commas ASSIGN expr_no_commas
                    402:                { $$ = build_modify_expr ($1, $2, $3); }
                    403:        ;
                    404: 
                    405: primary:
                    406:        IDENTIFIER
                    407:                { $$ = lastiddecl;
1.1.1.8   root      408:                  if (!$$ || $$ == error_mark_node)
1.1       root      409:                    {
                    410:                      if (yychar == YYEMPTY)
                    411:                        yychar = YYLEX;
                    412:                      if (yychar == '(')
1.1.1.7   root      413:                        {
                    414:                          $$ = implicitly_declare ($1);
                    415:                          assemble_external ($$);
                    416:                          TREE_USED ($$) = 1;
                    417:                        }
1.1.1.8   root      418:                      else if (current_function_decl == 0)
                    419:                        {
                    420:                          error ("`%s' undeclared, outside of functions",
                    421:                                 IDENTIFIER_POINTER ($1));
                    422:                          $$ = error_mark_node;
                    423:                        }
1.1       root      424:                      else
                    425:                        {
1.1.1.8   root      426:                          if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node
                    427:                              || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl)
                    428:                            {
                    429:                              error ("`%s' undeclared (first use this function)",
                    430:                                     IDENTIFIER_POINTER ($1));
                    431: 
                    432:                              if (! undeclared_variable_notice)
                    433:                                {
                    434:                                  error ("(Each undeclared identifier is reported only once");
                    435:                                  error ("for each function it appears in.)");
                    436:                                  undeclared_variable_notice = 1;
                    437:                                }
                    438:                            }
1.1       root      439:                          $$ = error_mark_node;
                    440:                          /* Prevent repeated error messages.  */
                    441:                          IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node;
1.1.1.8   root      442:                          IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl;
1.1       root      443:                        }
                    444:                    }
1.1.1.7   root      445:                  else if (! TREE_USED ($$))
                    446:                    {
                    447:                      if (TREE_EXTERNAL ($$))
                    448:                        assemble_external ($$);
                    449:                      TREE_USED ($$) = 1;
                    450:                    }
1.1       root      451:                  if (TREE_CODE ($$) == CONST_DECL)
                    452:                    $$ = DECL_INITIAL ($$);
                    453:                }
                    454:        | CONSTANT
                    455:        | string
                    456:                { $$ = combine_strings ($1); }
                    457:        | '(' expr ')'
                    458:                { $$ = $2; }
                    459:        | '(' error ')'
                    460:                { $$ = error_mark_node; }
1.1.1.11  root      461:        | '('
1.1       root      462:                { if (current_function_decl == 0)
                    463:                    {
                    464:                      error ("braced-group within expression allowed only inside a function");
1.1.1.13  root      465:                      YYFAIL;
1.1       root      466:                    }
1.1.1.11  root      467:                  keep_next_level ();
1.1.1.2   root      468:                  $<ttype>$ = expand_start_stmt_expr (); }
1.1       root      469:          compstmt ')'
1.1.1.11  root      470:                { tree rtl_exp;
                    471:                  if (pedantic)
1.1       root      472:                    warning ("ANSI C forbids braced-groups within expressions");
1.1.1.11  root      473:                  rtl_exp = expand_end_stmt_expr ($<ttype>2);
                    474:                  $$ = $3;
                    475:                  TREE_USED ($$) = 0;
                    476:                  /* Since the statements have side effects,
                    477:                     consider this volatile.  */
                    478:                  TREE_VOLATILE ($$) = 1;
                    479:                  TREE_TYPE ($$) = TREE_TYPE (rtl_exp);
                    480:                  STMT_BODY ($$) = rtl_exp; }
1.1       root      481:        | primary '(' exprlist ')'   %prec '.'
                    482:                { $$ = build_function_call ($1, $3); }
                    483:        | primary '[' expr ']'   %prec '.'
                    484:                { $$ = build_array_ref ($1, $3); }
                    485:        | primary '.' identifier
                    486:                { $$ = build_component_ref ($1, $3); }
                    487:        | primary POINTSAT identifier
                    488:                { $$ = build_component_ref (build_indirect_ref ($1, "->"), $3); }
                    489:        | primary PLUSPLUS
                    490:                { $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
                    491:        | primary MINUSMINUS
                    492:                { $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
                    493:        ;
                    494: 
                    495: /* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it.  */
                    496: string:
                    497:          STRING
                    498:        | string STRING
                    499:                { $$ = chainon ($1, $2); }
                    500:        ;
                    501: 
                    502: xdecls:
                    503:        /* empty */
                    504:        | decls
                    505:        ;
                    506: 
                    507: decls:
                    508:        decl
                    509:        | errstmt
                    510:        | decls decl
                    511:        | decl errstmt
                    512:        ;
                    513: 
                    514: /* records the type and storage class specs to use for processing
1.1.1.11  root      515:    the declarators that follow.
                    516:    Maintains a stack of outer-level values of current_declspecs,
                    517:    for the sake of parm declarations nested in function declarators.  */
1.1       root      518: setspecs: /* empty */
1.1.1.11  root      519:                { $$ = suspend_momentary ();
                    520:                  declspec_stack = tree_cons (0, current_declspecs,
                    521:                                              declspec_stack);
                    522:                  current_declspecs = $<ttype>0; }
1.1       root      523:        ;
                    524: 
                    525: decl:
                    526:        typed_declspecs setspecs initdecls ';'
1.1.1.11  root      527:                { current_declspecs = TREE_VALUE (declspec_stack);
                    528:                  declspec_stack = TREE_CHAIN (declspec_stack);
                    529:                  resume_momentary ($2); }
1.1       root      530:        | declmods setspecs notype_initdecls ';'
1.1.1.11  root      531:                { current_declspecs = TREE_VALUE (declspec_stack);
                    532:                  declspec_stack = TREE_CHAIN (declspec_stack);
                    533:                  resume_momentary ($2); }
1.1       root      534:        | typed_declspecs ';'
                    535:                { shadow_tag ($1); }
                    536:        | declmods ';'
                    537:                { warning ("empty declaration"); }
                    538:        ;
                    539: 
                    540: /* Declspecs which contain at least one type specifier or typedef name.
                    541:    (Just `const' or `volatile' is not enough.)
                    542:    A typedef'd name following these is taken as a name to be declared.  */
                    543: 
                    544: typed_declspecs:
                    545:          typespec reserved_declspecs
                    546:                { $$ = tree_cons (NULL_TREE, $1, $2); }
                    547:        | declmods typespec reserved_declspecs
                    548:                { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
                    549:        ;
                    550: 
                    551: reserved_declspecs:  /* empty */
                    552:                { $$ = NULL_TREE; }
                    553:        | reserved_declspecs typespecqual_reserved
                    554:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    555:        | reserved_declspecs SCSPEC
                    556:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    557:        ;
                    558: 
                    559: /* List of just storage classes and type modifiers.
                    560:    A declaration can start with just this, but then it cannot be used
                    561:    to redeclare a typedef-name.  */
                    562: 
                    563: declmods:
                    564:          TYPE_QUAL
                    565:                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
                    566:        | SCSPEC
                    567:                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
                    568:        | declmods TYPE_QUAL
                    569:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    570:        | declmods SCSPEC
                    571:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    572:        ;
                    573: 
                    574: 
                    575: /* Used instead of declspecs where storage classes are not allowed
                    576:    (that is, for typenames and structure components).
                    577:    Don't accept a typedef-name if anything but a modifier precedes it.  */
                    578: 
                    579: typed_typespecs:
                    580:          typespec reserved_typespecquals
                    581:                { $$ = tree_cons (NULL_TREE, $1, $2); }
                    582:        | nonempty_type_quals typespec reserved_typespecquals
                    583:                { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
                    584:        ;
                    585: 
                    586: reserved_typespecquals:  /* empty */
                    587:                { $$ = NULL_TREE; }
                    588:        | reserved_typespecquals typespecqual_reserved
                    589:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    590:        ;
                    591: 
                    592: /* A typespec (but not a type qualifier).
                    593:    Once we have seen one of these in a declaration,
                    594:    if a typedef name appears then it is being redeclared.  */
                    595: 
                    596: typespec: TYPESPEC
                    597:        | structsp
                    598:        | TYPENAME
                    599:        | TYPEOF '(' expr ')'
1.1.1.15! root      600:                { $$ = TREE_TYPE ($3); }
1.1       root      601:        | TYPEOF '(' typename ')'
1.1.1.15! root      602:                { $$ = groktypename ($3); }
1.1       root      603:        ;
                    604: 
                    605: /* A typespec that is a reserved word, or a type qualifier.  */
                    606: 
                    607: typespecqual_reserved: TYPESPEC
                    608:        | TYPE_QUAL
                    609:        | structsp
                    610:        ;
                    611: 
                    612: initdecls:
                    613:        initdcl
                    614:        | initdecls ',' initdcl
                    615:        ;
                    616: 
                    617: notype_initdecls:
                    618:        notype_initdcl
                    619:        | notype_initdecls ',' initdcl
                    620:        ;
                    621: 
                    622: maybeasm:
                    623:          /* empty */
                    624:                { $$ = NULL_TREE; }
                    625:        | ASM '(' string ')'
                    626:                { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
                    627:                  $$ = $3;
                    628:                }
                    629:        ;
                    630: 
                    631: initdcl:
1.1.1.11  root      632:          declarator maybeasm maybe_attribute '='
1.1       root      633:                { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
                    634:          init
                    635: /* Note how the declaration of the variable is in effect while its init is parsed! */
1.1.1.11  root      636:                { finish_decl ($<ttype>5, $6, $2); }
                    637:        | declarator maybeasm maybe_attribute
1.1       root      638:                { tree d = start_decl ($1, current_declspecs, 0);
                    639:                  finish_decl (d, NULL_TREE, $2); }
                    640:        ;
                    641: 
                    642: notype_initdcl:
1.1.1.11  root      643:          notype_declarator maybeasm maybe_attribute '='
1.1       root      644:                { $<ttype>$ = start_decl ($1, current_declspecs, 1); }
                    645:          init
                    646: /* Note how the declaration of the variable is in effect while its init is parsed! */
1.1.1.11  root      647:                { finish_decl ($<ttype>5, $6, $2); }
                    648:        | notype_declarator maybeasm maybe_attribute
1.1       root      649:                { tree d = start_decl ($1, current_declspecs, 0);
                    650:                  finish_decl (d, NULL_TREE, $2); }
                    651:        ;
1.1.1.11  root      652: /* the * rules are dummies to accept the Apollo extended syntax
                    653:    so that the header files compile. */
                    654: maybe_attribute:
                    655:     /* empty */
1.1.1.12  root      656:        { $$ = NULL_TREE; }
1.1.1.11  root      657:     | ATTRIBUTE '(' '(' attribute_list ')' ')'
                    658:         { $$ = $4; }
                    659:     ;
                    660: 
                    661: attribute_list
                    662:     : attrib
                    663:     | attribute_list ',' attrib
                    664:     ;
                    665: 
                    666: attrib
                    667:     : IDENTIFIER
                    668:        { warning ("`%s' attribute directive ignored",
                    669:                   IDENTIFIER_POINTER ($1));
                    670:          $$ = $1; }
                    671:     | IDENTIFIER '(' CONSTANT ')'
                    672:        { /* if not "aligned(1)", then issue warning */
                    673:          if (strcmp (IDENTIFIER_POINTER ($1), "aligned") != 0
                    674:              || TREE_CODE ($3) != INTEGER_CST
                    675:              || TREE_INT_CST_LOW ($3) != 1)
                    676:            warning ("`%s' attribute directive ignored",
                    677:                     IDENTIFIER_POINTER ($1));
                    678:          $$ = $1; }
                    679:     | IDENTIFIER '(' identifiers ')'
                    680:        { warning ("`%s' attribute directive ignored",
                    681:                   IDENTIFIER_POINTER ($1));
                    682:          $$ = $1; }
                    683:     ;
1.1       root      684: 
                    685: init:
                    686:        expr_no_commas
1.1.1.2   root      687:        | '{' '}'
                    688:                { $$ = build_nt (CONSTRUCTOR, NULL_TREE, NULL_TREE);
                    689:                  if (pedantic)
                    690:                    warning ("ANSI C forbids empty initializer braces"); }
1.1       root      691:        | '{' initlist '}'
                    692:                { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
                    693:        | '{' initlist ',' '}'
                    694:                { $$ = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($2)); }
                    695:        | error
                    696:                { $$ = NULL_TREE; }
                    697:        ;
                    698: 
                    699: /* This chain is built in reverse order,
                    700:    and put in forward order where initlist is used.  */
                    701: initlist:
1.1.1.2   root      702:          init
1.1       root      703:                { $$ = build_tree_list (NULL_TREE, $1); }
                    704:        | initlist ',' init
                    705:                { $$ = tree_cons (NULL_TREE, $3, $1); }
                    706:        ;
                    707: 
                    708: /* Any kind of declarator (thus, all declarators allowed
                    709:    after an explicit typespec).  */
                    710: 
                    711: declarator:
                    712:          after_type_declarator
                    713:        | notype_declarator
                    714:        ;
                    715: 
                    716: /* A declarator that is allowed only after an explicit typespec.  */
                    717: 
                    718: after_type_declarator:
                    719:          '(' after_type_declarator ')'
                    720:                { $$ = $2; }
                    721:        | after_type_declarator '(' parmlist_or_identifiers  %prec '.'
                    722:                { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
                    723: /*     | after_type_declarator '(' error ')'  %prec '.'
                    724:                { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
                    725:                  poplevel (0, 0, 0); }  */
                    726:        | after_type_declarator '[' expr ']'  %prec '.'
                    727:                { $$ = build_nt (ARRAY_REF, $1, $3); }
                    728:        | after_type_declarator '[' ']'  %prec '.'
                    729:                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
                    730:        | '*' type_quals after_type_declarator  %prec UNARY
                    731:                { $$ = make_pointer_declarator ($2, $3); }
                    732:        | TYPENAME
                    733:        ;
                    734: 
                    735: /* Kinds of declarator that can appear in a parameter list
                    736:    in addition to notype_declarator.  This is like after_type_declarator
                    737:    but does not allow a typedef name in parentheses as an identifier
                    738:    (because it would conflict with a function with that typedef as arg).  */
                    739: 
                    740: parm_declarator:
                    741:          parm_declarator '(' parmlist_or_identifiers  %prec '.'
                    742:                { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
                    743: /*     | parm_declarator '(' error ')'  %prec '.'
                    744:                { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
                    745:                  poplevel (0, 0, 0); }  */
                    746:        | parm_declarator '[' expr ']'  %prec '.'
                    747:                { $$ = build_nt (ARRAY_REF, $1, $3); }
                    748:        | parm_declarator '[' ']'  %prec '.'
                    749:                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
                    750:        | '*' type_quals parm_declarator  %prec UNARY
                    751:                { $$ = make_pointer_declarator ($2, $3); }
                    752:        | TYPENAME
                    753:        ;
                    754: 
                    755: /* A declarator allowed whether or not there has been
                    756:    an explicit typespec.  These cannot redeclare a typedef-name.  */
                    757: 
                    758: notype_declarator:
                    759:          notype_declarator '(' parmlist_or_identifiers  %prec '.'
                    760:                { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
                    761: /*     | notype_declarator '(' error ')'  %prec '.'
                    762:                { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
                    763:                  poplevel (0, 0, 0); }  */
                    764:        | '(' notype_declarator ')'
                    765:                { $$ = $2; }
                    766:        | '*' type_quals notype_declarator  %prec UNARY
                    767:                { $$ = make_pointer_declarator ($2, $3); }
                    768:        | notype_declarator '[' expr ']'  %prec '.'
                    769:                { $$ = build_nt (ARRAY_REF, $1, $3); }
                    770:        | notype_declarator '[' ']'  %prec '.'
                    771:                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
                    772:        | IDENTIFIER
                    773:        ;
                    774: 
                    775: structsp:
                    776:          STRUCT identifier '{'
                    777:                { $$ = start_struct (RECORD_TYPE, $2);
                    778:                  /* Start scope of tag before parsing components.  */
                    779:                }
                    780:          component_decl_list '}'
                    781:                { $$ = finish_struct ($<ttype>4, $5);
                    782:                  /* Really define the structure.  */
                    783:                }
                    784:        | STRUCT '{' component_decl_list '}'
                    785:                { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
                    786:                                      $3); }
                    787:        | STRUCT identifier
                    788:                { $$ = xref_tag (RECORD_TYPE, $2); }
                    789:        | UNION identifier '{'
                    790:                { $$ = start_struct (UNION_TYPE, $2); }
                    791:          component_decl_list '}'
                    792:                { $$ = finish_struct ($<ttype>4, $5); }
                    793:        | UNION '{' component_decl_list '}'
                    794:                { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
                    795:                                      $3); }
                    796:        | UNION identifier
                    797:                { $$ = xref_tag (UNION_TYPE, $2); }
                    798:        | ENUM identifier '{'
                    799:                { $<itype>3 = suspend_momentary ();
                    800:                  $$ = start_enum ($2); }
1.1.1.5   root      801:          enumlist maybecomma_warn '}'
1.1       root      802:                { $$ = finish_enum ($<ttype>4, nreverse ($5));
                    803:                  resume_momentary ($<itype>3); }
                    804:        | ENUM '{'
                    805:                { $<itype>2 = suspend_momentary ();
                    806:                  $$ = start_enum (NULL_TREE); }
1.1.1.5   root      807:          enumlist maybecomma_warn '}'
1.1       root      808:                { $$ = finish_enum ($<ttype>3, nreverse ($4));
                    809:                  resume_momentary ($<itype>2); }
                    810:        | ENUM identifier
                    811:                { $$ = xref_tag (ENUMERAL_TYPE, $2); }
                    812:        ;
                    813: 
                    814: maybecomma:
                    815:          /* empty */
                    816:        | ','
                    817:        ;
                    818: 
1.1.1.5   root      819: maybecomma_warn:
                    820:          /* empty */
                    821:        | ','
                    822:                { if (pedantic) warning ("comma at end of enumerator list"); }
                    823:        ;
                    824: 
1.1.1.13  root      825: component_decl_list:
                    826:          component_decl_list2
                    827:                { $$ = $1; }
                    828:        | component_decl_list2 component_decl
                    829:                { $$ = chainon ($1, $2);
                    830:                  warning ("no semicolon at end of struct or union"); }
                    831:        ;
                    832: 
                    833: component_decl_list2:  /* empty */
1.1       root      834:                { $$ = NULL_TREE; }
1.1.1.13  root      835:        | component_decl_list2 component_decl ';'
1.1       root      836:                { $$ = chainon ($1, $2); }
1.1.1.13  root      837:        | component_decl_list2 ';'
1.1.1.11  root      838:                { if (pedantic)
1.1       root      839:                    warning ("extra semicolon in struct or union specified"); }
                    840:        ;
                    841: 
                    842: /* There is a shift-reduce conflict here, because `components' may
                    843:    start with a `typename'.  It happens that shifting (the default resolution)
                    844:    does the right thing, because it treats the `typename' as part of
                    845:    a `typed_typespecs'.
                    846: 
                    847:    It is possible that this same technique would allow the distinction
                    848:    between `notype_initdecls' and `initdecls' to be eliminated.
                    849:    But I am being cautious and not trying it.  */
                    850: 
                    851: component_decl:
                    852:        typed_typespecs setspecs components
                    853:                { $$ = $3;
1.1.1.11  root      854:                  current_declspecs = TREE_VALUE (declspec_stack);
                    855:                  declspec_stack = TREE_CHAIN (declspec_stack);
1.1       root      856:                  resume_momentary ($2); }
                    857:        | nonempty_type_quals setspecs components
                    858:                { $$ = $3;
1.1.1.11  root      859:                  current_declspecs = TREE_VALUE (declspec_stack);
                    860:                  declspec_stack = TREE_CHAIN (declspec_stack);
1.1       root      861:                  resume_momentary ($2); }
                    862:        | error
                    863:                { $$ = NULL_TREE; }
                    864:        ;
                    865: 
                    866: components:
                    867:          /* empty */
1.1.1.10  root      868:                { if (pedantic)
                    869:                    warning ("ANSI C forbids member declarations with no members");
                    870:                  $$ = NULL_TREE; }
1.1       root      871:        | component_declarator
                    872:        | components ',' component_declarator
                    873:                { $$ = chainon ($1, $3); }
                    874:        ;
                    875: 
                    876: component_declarator:
1.1.1.11  root      877:        declarator maybe_attribute
1.1       root      878:                { $$ = grokfield (input_filename, lineno, $1, current_declspecs, NULL_TREE); }
1.1.1.11  root      879:        | declarator ':' expr_no_commas maybe_attribute
1.1       root      880:                { $$ = grokfield (input_filename, lineno, $1, current_declspecs, $3); }
                    881:        | ':' expr_no_commas
                    882:                { $$ = grokfield (input_filename, lineno, NULL_TREE, current_declspecs, $2); }
                    883:        ;
                    884: 
                    885: /* We chain the enumerators in reverse order.
                    886:    They are put in forward order where enumlist is used.
                    887:    (The order used to be significant, but no longer is so.
                    888:    However, we still maintain the order, just to be clean.)  */
                    889: 
                    890: enumlist:
                    891:          enumerator
                    892:        | enumlist ',' enumerator
                    893:                { $$ = chainon ($3, $1); }
                    894:        ;
                    895: 
                    896: 
                    897: enumerator:
                    898:          identifier
                    899:                { $$ = build_enumerator ($1, NULL_TREE); }
                    900:        | identifier '=' expr_no_commas
                    901:                { $$ = build_enumerator ($1, $3); }
                    902:        ;
                    903: 
                    904: typename:
                    905:        typed_typespecs absdcl
                    906:                { $$ = build_tree_list ($1, $2); }
                    907:        | nonempty_type_quals absdcl
                    908:                { $$ = build_tree_list ($1, $2); }
                    909:        ;
1.1.1.11  root      910: 
1.1       root      911: absdcl:   /* an absolute declarator */
                    912:        /* empty */
                    913:                { $$ = NULL_TREE; }
                    914:        | absdcl1
                    915:        ;
                    916: 
                    917: nonempty_type_quals:
                    918:          TYPE_QUAL
                    919:                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
                    920:        | nonempty_type_quals TYPE_QUAL
                    921:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    922:        ;
                    923: 
                    924: type_quals:
                    925:          /* empty */
                    926:                { $$ = NULL_TREE; }
                    927:        | type_quals TYPE_QUAL
                    928:                { $$ = tree_cons (NULL_TREE, $2, $1); }
                    929:        ;
                    930: 
                    931: absdcl1:  /* a nonempty absolute declarator */
                    932:          '(' absdcl1 ')'
                    933:                { $$ = $2; }
                    934:          /* `(typedef)1' is `int'.  */
                    935:        | '*' type_quals absdcl1  %prec UNARY
                    936:                { $$ = make_pointer_declarator ($2, $3); }
                    937:        | '*' type_quals  %prec UNARY
                    938:                { $$ = make_pointer_declarator ($2, NULL_TREE); }
                    939:        | absdcl1 '(' parmlist  %prec '.'
                    940:                { $$ = build_nt (CALL_EXPR, $1, $3, NULL_TREE); }
                    941:        | absdcl1 '[' expr ']'  %prec '.'
                    942:                { $$ = build_nt (ARRAY_REF, $1, $3); }
                    943:        | absdcl1 '[' ']'  %prec '.'
                    944:                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
                    945:        | '(' parmlist  %prec '.'
                    946:                { $$ = build_nt (CALL_EXPR, NULL_TREE, $2, NULL_TREE); }
                    947:        | '[' expr ']'  %prec '.'
                    948:                { $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
                    949:        | '[' ']'  %prec '.'
                    950:                { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
                    951:        ;
                    952: 
                    953: /* at least one statement, the first of which parses without error.  */
                    954: /* stmts is used only after decls, so an invalid first statement
                    955:    is actually regarded as an invalid decl and part of the decls.  */
                    956: 
                    957: stmts:
                    958:        stmt
                    959:        | stmts stmt
                    960:        | stmts errstmt
                    961:        ;
                    962: 
                    963: xstmts:
                    964:        /* empty */
                    965:        | stmts
                    966:        ;
                    967: 
                    968: errstmt:  error ';'
                    969:        ;
                    970: 
                    971: pushlevel:  /* empty */
                    972:                { pushlevel (0);
                    973:                  clear_last_expr ();
                    974:                  push_momentary ();
                    975:                  expand_start_bindings (0); }
                    976:        ;
                    977: 
                    978: /* This is the body of a function definition.
                    979:    It causes syntax errors to ignore to the next openbrace.  */
                    980: compstmt_or_error:
                    981:          compstmt
1.1.1.11  root      982:                {}
1.1       root      983:        | error compstmt
                    984:        ;
                    985: 
                    986: compstmt: '{' '}'
1.1.1.11  root      987:                { $$ = 0; }
1.1       root      988:        | '{' pushlevel decls xstmts '}'
1.1.1.2   root      989:                { expand_end_bindings (getdecls (), 1, 0);
1.1.1.11  root      990:                  $$ = poplevel (1, 1, 0);
1.1       root      991:                  pop_momentary (); }
                    992:        | '{' pushlevel error '}'
1.1.1.12  root      993:                { expand_end_bindings (getdecls (), kept_level_p (), 0);
                    994:                  $$ = poplevel (kept_level_p (), 0, 0);
1.1       root      995:                  pop_momentary (); }
                    996:        | '{' pushlevel stmts '}'
1.1.1.12  root      997:                { expand_end_bindings (getdecls (), kept_level_p (), 0);
                    998:                  $$ = poplevel (kept_level_p (), 0, 0);
1.1       root      999:                  pop_momentary (); }
                   1000:        ;
                   1001: 
                   1002: simple_if:
                   1003:          IF '(' expr ')'
1.1.1.6   root     1004:                { emit_line_note (input_filename, lineno);
1.1       root     1005:                  expand_start_cond (truthvalue_conversion ($3), 0); }
                   1006:          stmt
                   1007:        ;
                   1008: 
                   1009: stmt:
1.1.1.11  root     1010:          compstmt      {}
1.1       root     1011:        | expr ';'
1.1.1.6   root     1012:                { emit_line_note (input_filename, lineno);
1.1.1.11  root     1013:                  /* Do default conversion if safe and possibly important,
                   1014:                     in case within ({...}).  */
                   1015:                  if ((TREE_CODE (TREE_TYPE ($1)) == ARRAY_TYPE
                   1016:                       && lvalue_p ($1))
                   1017:                      || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)
                   1018:                    $1 = default_conversion ($1);
1.1       root     1019:                  expand_expr_stmt ($1);
                   1020:                  clear_momentary (); }
                   1021:        | simple_if ELSE
                   1022:                { expand_start_else (); }
                   1023:          stmt
                   1024:                { expand_end_else (); }
1.1.1.10  root     1025:        | simple_if %prec IF
1.1       root     1026:                { expand_end_cond (); }
                   1027:        | WHILE
1.1.1.11  root     1028:                { emit_nop ();
                   1029:                  emit_line_note (input_filename, lineno);
1.1       root     1030:                  expand_start_loop (1); }
                   1031:          '(' expr ')'
1.1.1.6   root     1032:                { emit_line_note (input_filename, lineno);
1.1       root     1033:                  expand_exit_loop_if_false (truthvalue_conversion ($4)); }
                   1034:          stmt
                   1035:                { expand_end_loop (); }
                   1036:        | DO
1.1.1.11  root     1037:                { emit_nop ();
                   1038:                  emit_line_note (input_filename, lineno);
1.1       root     1039:                  expand_start_loop_continue_elsewhere (1); }
                   1040:          stmt WHILE
                   1041:                { expand_loop_continue_here (); }
                   1042:          '(' expr ')' ';'
1.1.1.6   root     1043:                { emit_line_note (input_filename, lineno);
1.1       root     1044:                  expand_exit_loop_if_false (truthvalue_conversion ($7));
                   1045:                  expand_end_loop ();
                   1046:                  clear_momentary (); }
1.1.1.11  root     1047:        | FOR
1.1       root     1048:          '(' xexpr ';'
1.1.1.11  root     1049:                { emit_nop ();
                   1050:                  emit_line_note (input_filename, lineno);
1.1       root     1051:                  if ($3) expand_expr_stmt ($3);
                   1052:                  expand_start_loop_continue_elsewhere (1); }
                   1053:          xexpr ';'
1.1.1.6   root     1054:                { emit_line_note (input_filename, lineno);
1.1       root     1055:                  if ($6)
                   1056:                    expand_exit_loop_if_false (truthvalue_conversion ($6)); }
                   1057:          xexpr ')'
                   1058:                /* Don't let the tree nodes for $9 be discarded
                   1059:                   by clear_momentary during the parsing of the next stmt.  */
                   1060:                { push_momentary ();
                   1061:                  $<itype>10 = lineno; }
                   1062:          stmt
1.1.1.6   root     1063:                { emit_line_note (input_filename, $<itype>10);
1.1       root     1064:                  expand_loop_continue_here ();
                   1065:                  if ($9)
                   1066:                    expand_expr_stmt ($9);
                   1067:                  pop_momentary ();
                   1068:                  expand_end_loop (); }
                   1069:        | SWITCH '(' expr ')'
1.1.1.6   root     1070:                { emit_line_note (input_filename, lineno);
1.1       root     1071:                  c_expand_start_case ($3);
                   1072:                  /* Don't let the tree nodes for $3 be discarded by
                   1073:                     clear_momentary during the parsing of the next stmt.  */
                   1074:                  push_momentary (); }
                   1075:          stmt
1.1.1.10  root     1076:                { expand_end_case ($3);
1.1       root     1077:                  pop_momentary (); }
                   1078:        | CASE expr ':'
                   1079:                { register tree value = fold ($2);
                   1080:                  register tree label
                   1081:                    = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
                   1082: 
1.1.1.9   root     1083:                  /* build_c_cast puts on a NOP_EXPR to make a non-lvalue.
                   1084:                     Strip such NOP_EXPRs.  */
                   1085:                  if (TREE_CODE (value) == NOP_EXPR
                   1086:                      && TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
                   1087:                    value = TREE_OPERAND (value, 0);
                   1088: 
1.1       root     1089:                  if (TREE_CODE (value) != INTEGER_CST
                   1090:                      && value != error_mark_node)
                   1091:                    {
                   1092:                      error ("case label does not reduce to an integer constant");
                   1093:                      value = error_mark_node;
                   1094:                    }
                   1095:                  else
                   1096:                    /* Promote char or short to int.  */
                   1097:                    value = default_conversion (value);
                   1098:                  if (value != error_mark_node)
                   1099:                    {
                   1100:                      int success = pushcase (value, label);
                   1101:                      if (success == 1)
                   1102:                        error ("case label not within a switch statement");
                   1103:                      else if (success == 2)
                   1104:                        error ("duplicate case value");
                   1105:                      else if (success == 3)
                   1106:                        warning ("case value out of range");
                   1107:                    }
                   1108:                }
                   1109:          stmt
                   1110:        | DEFAULT ':'
                   1111:                {
                   1112:                  register tree label
                   1113:                    = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
                   1114:                  int success = pushcase (NULL_TREE, label);
                   1115:                  if (success == 1)
                   1116:                    error ("default label not within a switch statement");
                   1117:                  else if (success == 2)
                   1118:                    error ("multiple default labels in one switch");
                   1119:                }
                   1120:          stmt
                   1121:        | BREAK ';'
1.1.1.6   root     1122:                { emit_line_note (input_filename, lineno);
1.1       root     1123:                  if ( ! expand_exit_something ())
                   1124:                    error ("break statement not within loop or switch"); }
1.1.1.11  root     1125:        | CONTINUE ';'
1.1.1.6   root     1126:                { emit_line_note (input_filename, lineno);
1.1       root     1127:                  if (! expand_continue_loop ())
                   1128:                    error ("continue statement not within a loop"); }
                   1129:        | RETURN ';'
1.1.1.6   root     1130:                { emit_line_note (input_filename, lineno);
1.1       root     1131:                  c_expand_return (NULL_TREE); }
                   1132:        | RETURN expr ';'
1.1.1.6   root     1133:                { emit_line_note (input_filename, lineno);
1.1       root     1134:                  c_expand_return ($2); }
                   1135:        | ASM maybe_type_qual '(' string ')' ';'
1.1.1.6   root     1136:                { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1.1.1.11  root     1137:                  emit_line_note (input_filename, lineno);
1.1       root     1138:                  expand_asm ($4); }
                   1139:        /* This is the case with just output operands.  */
                   1140:        | ASM maybe_type_qual '(' string ':' asm_operands ')' ';'
1.1.1.6   root     1141:                { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1.1.1.11  root     1142:                  emit_line_note (input_filename, lineno);
1.1.1.3   root     1143:                  c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
1.1.1.7   root     1144:                                         $2 == ridpointers[(int)RID_VOLATILE],
                   1145:                                         input_filename, lineno); }
1.1       root     1146:        /* This is the case with input operands as well.  */
                   1147:        | ASM maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';'
1.1.1.6   root     1148:                { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1.1.1.11  root     1149:                  emit_line_note (input_filename, lineno);
1.1.1.3   root     1150:                  c_expand_asm_operands ($4, $6, $8, NULL_TREE,
1.1.1.7   root     1151:                                         $2 == ridpointers[(int)RID_VOLATILE],
                   1152:                                         input_filename, lineno); }
1.1.1.3   root     1153:        /* This is the case with clobbered registers as well.  */
                   1154:        | ASM maybe_type_qual '(' string ':' asm_operands ':'
                   1155:          asm_operands ':' asm_clobbers ')' ';'
1.1.1.6   root     1156:                { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
1.1.1.11  root     1157:                  emit_line_note (input_filename, lineno);
1.1.1.3   root     1158:                  c_expand_asm_operands ($4, $6, $8, $10,
1.1.1.7   root     1159:                                         $2 == ridpointers[(int)RID_VOLATILE],
                   1160:                                         input_filename, lineno); }
1.1       root     1161:        | GOTO identifier ';'
                   1162:                { tree decl;
1.1.1.6   root     1163:                  emit_line_note (input_filename, lineno);
1.1       root     1164:                  decl = lookup_label ($2);
1.1.1.10  root     1165:                  TREE_USED (decl) = 1;
1.1       root     1166:                  expand_goto (decl); }
                   1167:        | identifier ':'
                   1168:                { tree label = define_label (input_filename, lineno, $1);
1.1.1.11  root     1169:                  emit_nop ();
1.1       root     1170:                  if (label)
                   1171:                    expand_label (label); }
                   1172:          stmt
                   1173:        | ';'
                   1174:        ;
                   1175: 
1.1.1.6   root     1176: /* Either a type-qualifier or nothing.  First thing in an `asm' statement.  */
                   1177: 
1.1       root     1178: maybe_type_qual:
                   1179:        /* empty */
1.1.1.15! root     1180:                { emit_line_note (input_filename, lineno); }
1.1       root     1181:        | TYPE_QUAL
1.1.1.15! root     1182:                { emit_line_note (input_filename, lineno); }
1.1       root     1183:        ;
                   1184: 
                   1185: xexpr:
                   1186:        /* empty */
                   1187:                { $$ = NULL_TREE; }
                   1188:        | expr
                   1189:        ;
                   1190: 
                   1191: /* These are the operands other than the first string and colon
                   1192:    in  asm ("addextend %2,%1": "=dm" (x), "0" (y), "g" (*x))  */
                   1193: asm_operands: /* empty */
                   1194:                { $$ = NULL_TREE; }
                   1195:        | nonnull_asm_operands
                   1196:        ;
                   1197: 
                   1198: nonnull_asm_operands:
                   1199:          asm_operand
                   1200:        | nonnull_asm_operands ',' asm_operand
                   1201:                { $$ = chainon ($1, $3); }
                   1202:        ;
                   1203: 
                   1204: asm_operand:
1.1.1.3   root     1205:          STRING '(' expr ')'
1.1       root     1206:                { $$ = build_tree_list ($1, $3); }
                   1207:        ;
                   1208: 
1.1.1.3   root     1209: asm_clobbers:
1.1.1.11  root     1210:          string
                   1211:                { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE); }
                   1212:        | asm_clobbers ',' string
                   1213:                { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
1.1.1.3   root     1214:        ;
                   1215: 
1.1       root     1216: /* This is what appears inside the parens in a function declarator.
                   1217:    Its value is a list of ..._TYPE nodes.  */
                   1218: parmlist:
1.1.1.11  root     1219:                { pushlevel (0);
                   1220:                  declare_parm_level (); }
1.1       root     1221:          parmlist_1
1.1.1.9   root     1222:                { $$ = $2;
                   1223:                  parmlist_tags_warning ();
                   1224:                  poplevel (0, 0, 0); }
1.1       root     1225:        ;
                   1226: 
                   1227: /* This is referred to where either a parmlist or an identifier list is ok.
                   1228:    Its value is a list of ..._TYPE nodes or a list of identifiers.  */
                   1229: parmlist_or_identifiers:
1.1.1.11  root     1230:                { pushlevel (0);
                   1231:                  declare_parm_level (); }
1.1       root     1232:          parmlist_or_identifiers_1
1.1.1.9   root     1233:                { $$ = $2;
                   1234:                  parmlist_tags_warning ();
                   1235:                  poplevel (0, 0, 0); }
1.1       root     1236:        ;
                   1237: 
                   1238: parmlist_or_identifiers_1:
                   1239:          parmlist_2 ')'
                   1240:        | identifiers ')'
                   1241:                { $$ = tree_cons (NULL_TREE, NULL_TREE, $1); }
                   1242:        | error ')'
                   1243:                { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
                   1244:        ;
                   1245: 
                   1246: parmlist_1:
                   1247:          parmlist_2 ')'
                   1248:        | error ')'
                   1249:                { $$ = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE); }
                   1250:        ;
                   1251: 
                   1252: /* This is what appears inside the parens in a function declarator.
                   1253:    Is value is represented in the format that grokdeclarator expects.  */
                   1254: parmlist_2:  /* empty */
                   1255:                { $$ = get_parm_info (0); }
                   1256:        | parms
                   1257:                { $$ = get_parm_info (1); }
                   1258:        | parms ',' ELLIPSIS
                   1259:                { $$ = get_parm_info (0); }
                   1260:        ;
                   1261: 
1.1.1.11  root     1262: parms:
1.1       root     1263:        parm
                   1264:                { push_parm_decl ($1); }
                   1265:        | parms ',' parm
                   1266:                { push_parm_decl ($3); }
                   1267:        ;
                   1268: 
                   1269: /* A single parameter declaration or parameter type name,
                   1270:    as found in a parmlist.  */
                   1271: parm:
                   1272:          typed_declspecs parm_declarator
                   1273:                { $$ = build_tree_list ($1, $2) ; }
                   1274:        | typed_declspecs notype_declarator
                   1275:                { $$ = build_tree_list ($1, $2) ; }
                   1276:        | typed_declspecs absdcl
                   1277:                { $$ = build_tree_list ($1, $2); }
                   1278:        | declmods notype_declarator
                   1279:                { $$ = build_tree_list ($1, $2) ; }
                   1280:        | declmods absdcl
                   1281:                { $$ = build_tree_list ($1, $2); }
                   1282:        ;
                   1283: 
                   1284: /* A nonempty list of identifiers.  */
1.1.1.11  root     1285: identifiers:
1.1       root     1286:        IDENTIFIER
                   1287:                { $$ = build_tree_list (NULL_TREE, $1); }
                   1288:        | identifiers ',' IDENTIFIER
                   1289:                { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
                   1290:        ;
                   1291: %%
                   1292: 
                   1293: /* Return something to represent absolute declarators containing a *.
                   1294:    TARGET is the absolute declarator that the * contains.
                   1295:    TYPE_QUALS is a list of modifiers such as const or volatile
                   1296:    to apply to the pointer type, represented as identifiers.
                   1297: 
                   1298:    We return an INDIRECT_REF whose "contents" are TARGET
                   1299:    and whose type is the modifier list.  */
1.1.1.11  root     1300: 
1.1       root     1301: static tree
                   1302: make_pointer_declarator (type_quals, target)
                   1303:      tree type_quals, target;
                   1304: {
                   1305:   return build (INDIRECT_REF, type_quals, target);
                   1306: }
                   1307: 
                   1308: /* Given a chain of STRING_CST nodes,
                   1309:    concatenate them into one STRING_CST
                   1310:    and give it a suitable array-of-chars data type.  */
                   1311: 
                   1312: static tree
                   1313: combine_strings (strings)
                   1314:      tree strings;
                   1315: {
                   1316:   register tree value, t;
                   1317:   register int length = 1;
                   1318:   int wide_length = 0;
                   1319:   int wide_flag = 0;
1.1.1.13  root     1320:   int nchars;
1.1       root     1321: 
                   1322:   if (TREE_CHAIN (strings))
                   1323:     {
                   1324:       /* More than one in the chain, so concatenate.  */
                   1325:       register char *p, *q;
                   1326: 
                   1327:       /* Don't include the \0 at the end of each substring,
                   1328:         except for the last one.
                   1329:         Count wide strings and ordinary strings separately.  */
                   1330:       for (t = strings; t; t = TREE_CHAIN (t))
                   1331:        {
                   1332:          if (TREE_TYPE (t) == int_array_type_node)
                   1333:            {
1.1.1.13  root     1334:              wide_length += (TREE_STRING_LENGTH (t) - UNITS_PER_WORD);
1.1       root     1335:              wide_flag = 1;
                   1336:            }
                   1337:          else
                   1338:            length += (TREE_STRING_LENGTH (t) - 1);
                   1339:        }
                   1340: 
                   1341:       /* If anything is wide, the non-wides will be converted,
                   1342:         which makes them take more space.  */
                   1343:       if (wide_flag)
                   1344:        length = length * UNITS_PER_WORD + wide_length;
                   1345: 
1.1.1.11  root     1346:       p = (char *) savealloc (length);
1.1       root     1347: 
                   1348:       /* Copy the individual strings into the new combined string.
                   1349:         If the combined string is wide, convert the chars to ints
                   1350:         for any individual strings that are not wide.  */
                   1351: 
                   1352:       q = p;
                   1353:       for (t = strings; t; t = TREE_CHAIN (t))
                   1354:        {
1.1.1.14  root     1355:          int len = (TREE_STRING_LENGTH (t) 
                   1356:                     - ((TREE_TYPE (t) == int_array_type_node)
                   1357:                        ? UNITS_PER_WORD : 1));
1.1       root     1358:          if ((TREE_TYPE (t) == int_array_type_node) == wide_flag)
                   1359:            {
                   1360:              bcopy (TREE_STRING_POINTER (t), q, len);
                   1361:              q += len;
                   1362:            }
                   1363:          else
                   1364:            {
                   1365:              int i;
                   1366:              for (i = 0; i < len; i++)
                   1367:                ((int *) q)[i] = TREE_STRING_POINTER (t)[i];
                   1368:              q += len * UNITS_PER_WORD;
                   1369:            }
                   1370:        }
1.1.1.14  root     1371:       if (wide_flag)
                   1372:        {
                   1373:          int i;
                   1374:          for (i = 0; i < UNITS_PER_WORD; i++)
                   1375:            *q++ = 0;
                   1376:        }
                   1377:       else
                   1378:        *q = 0;
1.1       root     1379: 
                   1380:       value = make_node (STRING_CST);
                   1381:       TREE_STRING_POINTER (value) = p;
                   1382:       TREE_STRING_LENGTH (value) = length;
                   1383:       TREE_LITERAL (value) = 1;
                   1384:     }
                   1385:   else
                   1386:     {
                   1387:       value = strings;
                   1388:       length = TREE_STRING_LENGTH (value);
                   1389:       if (TREE_TYPE (value) == int_array_type_node)
                   1390:        wide_flag = 1;
                   1391:     }
                   1392: 
1.1.1.13  root     1393:   /* Compute the number of elements, for the array type.  */ 
                   1394:   nchars = wide_flag ? length / UNITS_PER_WORD : length;
                   1395: 
1.1.1.3   root     1396:   /* Create the array type for the string constant.
                   1397:      -Wwrite-strings says make the string constant an array of const char
                   1398:      so that copying it to a non-const pointer will get a warning.  */
                   1399:   if (warn_write_strings)
                   1400:     {
                   1401:       tree elements
                   1402:        = build_type_variant (wide_flag ? integer_type_node : char_type_node,
                   1403:                              1, 0);
                   1404:       TREE_TYPE (value)
                   1405:        = build_array_type (elements,
1.1.1.13  root     1406:                            build_index_type (build_int_2 (nchars - 1, 0)));
1.1.1.3   root     1407:     }
                   1408:   else
                   1409:     TREE_TYPE (value)
                   1410:       = build_array_type (wide_flag ? integer_type_node : char_type_node,
1.1.1.13  root     1411:                          build_index_type (build_int_2 (nchars - 1, 0)));
1.1       root     1412:   TREE_LITERAL (value) = 1;
                   1413:   TREE_STATIC (value) = 1;
                   1414:   return value;
                   1415: }
                   1416: 
                   1417: FILE *finput;                  /* input file.
                   1418:                                   Normally a pipe from the preprocessor.  */
                   1419: 
                   1420: /* lexical analyzer */
                   1421: 
1.1.1.7   root     1422: static int maxtoken;           /* Current nominal length of token buffer.  */
1.1       root     1423: static char *token_buffer;     /* Pointer to token buffer.
                   1424:                                   Actual allocated length is maxtoken + 2.  */
1.1.1.7   root     1425: static int max_wide;           /* Current nominal length of wide_buffer.  */
                   1426: static int *wide_buffer;       /* Pointer to wide-string buffer.
                   1427:                                   Actual allocated length is max_wide + 1.  */
                   1428: 
                   1429: /* Nonzero if end-of-file has been seen on input.  */
1.1.1.5   root     1430: static int end_of_file;
1.1       root     1431: 
1.1.1.15! root     1432: /* Buffered character to reread.
        !          1433:    I'm not sure why ungetc is not used.  */
        !          1434: static int nextchar = -1;
        !          1435: 
1.1.1.9   root     1436: /* Data type that represents the GNU C reserved words. */
                   1437: struct resword { char *name; short token; enum rid rid; };
1.1       root     1438: 
1.1.1.9   root     1439: #define MIN_WORD_LENGTH     2      /* minimum size for C keyword */
1.1.1.11  root     1440: #define MAX_WORD_LENGTH     13     /* maximum size for C keyword */
                   1441: #define MIN_HASH_VALUE      7      /* range of the hash keys values  */
                   1442: #define MAX_HASH_VALUE      91     /* for the perfect hash generator */
1.1       root     1443: #define NORID RID_UNUSED
                   1444: 
1.1.1.4   root     1445: /* This function performs the minimum-perfect hash mapping from input
1.1.1.11  root     1446:    string to reswords table index.  It only looks at the first and
                   1447:    last characters in the string, thus assuring the O(1) lookup time
1.1.1.4   root     1448:    (this keeps our constant down to an insignificant amount!).  Compiling
                   1449:    the following 2 functions as inline removes all overhead of the
                   1450:    function calls. */
                   1451: 
                   1452: #ifdef __GNUC__
1.1.1.11  root     1453: __inline
1.1.1.4   root     1454: #endif
1.1.1.11  root     1455: static int
1.1.1.4   root     1456: hash (str, len)
1.1.1.10  root     1457:      register char *str;
                   1458:      register int len;
1.1.1.4   root     1459: {
1.1.1.9   root     1460: /* This table is used to build the hash table index that recognizes
1.1.1.11  root     1461:    reserved words in 0(1) steps.  It is larger than strictly necessary,
                   1462:    but I'm trading off the space for the time-saving luxury of avoiding
                   1463:    subtraction of an offset.  All those ``91's'' (actually just a
                   1464:    short-hand for MAX_HASH_VALUE #defined above) are used to speed up
                   1465:    the search when the string found on the input stream doesn't have a
                   1466:    first or last character that is part of the set of alphabetic
                   1467:    characters that comprise the first or last characters in C
1.1.1.9   root     1468:    reserved words. */
1.1.1.4   root     1469: 
1.1.1.11  root     1470:   static int hash_table[] =
1.1.1.9   root     1471:     {
1.1.1.11  root     1472:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1473:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1474:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1475:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1476:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1477:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1478:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1479:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1480:      91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
                   1481:      91, 91, 91, 91, 91,  1, 91,  2,  1, 32,
                   1482:       7,  5, 18, 20,  1, 17, 91,  1, 18,  1,
                   1483:      28,  1, 23, 91, 12, 20,  1, 41,  7, 15,
                   1484:      91, 91, 10, 91, 91, 91, 91, 91,
1.1.1.9   root     1485:     };
1.1.1.11  root     1486:   register int hval = len ;
1.1.1.9   root     1487: 
1.1.1.11  root     1488:   switch (hval)
                   1489:     {
                   1490:       default:
                   1491:       case 3:
                   1492:         hval += hash_table[str[2]];
                   1493:       case 2:
                   1494:       case 1:
                   1495:         return hval + hash_table[str[0]] + hash_table[str[len - 1]];
                   1496:     }
1.1.1.4   root     1497: }
                   1498: 
1.1.1.9   root     1499: /* This routine attempts to match the string found in the reswords table
1.1.1.11  root     1500:    with the one from the input stream.  If all the relevant details
1.1.1.9   root     1501:    match then an actual strcmp comparison is performed and the address of
1.1.1.11  root     1502:    correct struct resword entry is returned.  Otherwise, a NULL
1.1.1.9   root     1503:    pointer is returned. */
1.1.1.4   root     1504: 
                   1505: #ifdef __GNUC__
1.1.1.11  root     1506: __inline
1.1.1.4   root     1507: #endif
1.1.1.10  root     1508: struct resword *
1.1.1.9   root     1509: is_reserved_word (str, len)
1.1.1.10  root     1510:      register char *str;
                   1511:      register int len;
1.1.1.4   root     1512: {
1.1.1.10  root     1513:   /* This is the hash table of keywords.
                   1514:      The order of keywords has been chosen for perfect hashing.
                   1515:      Therefore, this table cannot be updated by hand.
1.1.1.11  root     1516:      Use the program ``gperf,'' available with the latest libg++
                   1517:      distribution, to generate an updated table.  A file called
                   1518:      c-parse.gperf, distributed with GNU C, contains the keyword file.  */
1.1.1.9   root     1519: 
1.1.1.11  root     1520:   static struct resword reswords[] =
1.1.1.9   root     1521:     {
1.1.1.11  root     1522:       { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, 
                   1523:       {"asm",  ASM, NORID },
                   1524:       {"auto",  SCSPEC, RID_AUTO },
                   1525:       {"__asm",  ASM, NORID },
                   1526:       {"do",  DO, NORID },
                   1527:       {"__asm__",  ASM, NORID },
                   1528:       {"break",  BREAK, NORID },
                   1529:       {"__typeof__",  TYPEOF, NORID },
                   1530:       { "", }, 
                   1531:       {"__alignof__",  ALIGNOF, NORID },
                   1532:       { "", }, 
                   1533:       {"__attribute__",  ATTRIBUTE, NORID },
                   1534:       { "", }, 
                   1535:       {"__attribute",  ATTRIBUTE, NORID },
                   1536:       { "", }, 
                   1537:       {"__volatile__",  TYPE_QUAL, RID_VOLATILE },
                   1538:       {"int",  TYPESPEC, RID_INT },
                   1539:       {"__volatile",  TYPE_QUAL, RID_VOLATILE },
                   1540:       { "", }, 
                   1541:       {"float",  TYPESPEC, RID_FLOAT },
                   1542:       {"goto",  GOTO, NORID },
                   1543:       {"short",  TYPESPEC, RID_SHORT },
                   1544:       {"__typeof",  TYPEOF, NORID },
                   1545:       {"__inline__",  SCSPEC, RID_INLINE },
                   1546:       {"__alignof",  ALIGNOF, NORID },
                   1547:       {"__inline",  SCSPEC, RID_INLINE },
                   1548:       {"__signed__",  TYPESPEC, RID_SIGNED },
                   1549:       {"default",  DEFAULT, NORID },
                   1550:       {"else",  ELSE, NORID },
                   1551:       {"void",  TYPESPEC, RID_VOID },
                   1552:       {"__signed",  TYPESPEC, RID_SIGNED },
                   1553:       {"if",  IF, NORID },
                   1554:       {"volatile",  TYPE_QUAL, RID_VOLATILE },
                   1555:       {"struct",  STRUCT, NORID },
                   1556:       {"extern",  SCSPEC, RID_EXTERN },
                   1557:       {"__const",  TYPE_QUAL, RID_CONST },
                   1558:       {"while",  WHILE, NORID },
                   1559:       {"__const__",  TYPE_QUAL, RID_CONST },
                   1560:       {"switch",  SWITCH, NORID },
                   1561:       {"for",  FOR, NORID },
                   1562:       {"inline",  SCSPEC, RID_INLINE },
                   1563:       {"return",  RETURN, NORID },
                   1564:       {"typeof",  TYPEOF, NORID },
                   1565:       {"typedef",  SCSPEC, RID_TYPEDEF },
                   1566:       {"char",  TYPESPEC, RID_CHAR },
                   1567:       {"enum",  ENUM, NORID },
                   1568:       {"register",  SCSPEC, RID_REGISTER },
                   1569:       {"signed",  TYPESPEC, RID_SIGNED },
                   1570:       {"sizeof",  SIZEOF, NORID },
                   1571:       { "", }, { "", }, { "", }, { "", }, 
                   1572:       {"double",  TYPESPEC, RID_DOUBLE },
                   1573:       {"static",  SCSPEC, RID_STATIC },
                   1574:       {"case",  CASE, NORID },
                   1575:       { "", }, { "", }, { "", }, { "", }, 
                   1576:       {"const",  TYPE_QUAL, RID_CONST },
                   1577:       { "", }, { "", }, { "", }, 
                   1578:       {"long",  TYPESPEC, RID_LONG },
                   1579:       { "", }, { "", }, 
                   1580:       {"continue",  CONTINUE, NORID },
                   1581:       { "", }, { "", }, 
                   1582:       {"unsigned",  TYPESPEC, RID_UNSIGNED },
                   1583:       { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, { "", }, 
                   1584:       { "", }, { "", }, { "", }, { "", }, { "", }, 
                   1585:       {"union",  UNION, NORID },
1.1.1.9   root     1586:     };
                   1587: 
1.1.1.11  root     1588:   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
1.1.1.4   root     1589:     {
                   1590:       register int key = hash (str, len);
                   1591: 
1.1.1.11  root     1592:       if (key <= MAX_HASH_VALUE)
1.1.1.9   root     1593:         {
                   1594:           register char *s = reswords[key].name;
                   1595: 
1.1.1.11  root     1596:           if (*s == *str && !strcmp (str + 1, s + 1))
1.1.1.9   root     1597:             return &reswords[key];
                   1598:         }
1.1.1.4   root     1599:     }
1.1.1.9   root     1600:   return 0;
1.1.1.4   root     1601: }
1.1       root     1602: 
1.1.1.9   root     1603: /* The elements of `ridpointers' are identifier nodes
                   1604:    for the reserved type names and storage classes.
                   1605:    It is indexed by a RID_... value.  */
                   1606: 
                   1607: tree ridpointers[(int) RID_MAX];
                   1608: 
                   1609: int check_newline ();
                   1610: 
1.1       root     1611: void
                   1612: init_lex ()
                   1613: {
                   1614:   /* Start it at 0, because check_newline is called at the very beginning
                   1615:      and will increment it to 1.  */
                   1616:   lineno = 0;
                   1617: 
                   1618:   maxtoken = 40;
1.1.1.7   root     1619:   token_buffer = (char *) xmalloc (maxtoken + 2);
                   1620:   max_wide = 40;
1.1.1.14  root     1621:   wide_buffer = (int *) xmalloc ((max_wide + 1) * UNITS_PER_WORD);
1.1.1.7   root     1622: 
1.1       root     1623:   ridpointers[(int) RID_INT] = get_identifier ("int");
                   1624:   ridpointers[(int) RID_CHAR] = get_identifier ("char");
                   1625:   ridpointers[(int) RID_VOID] = get_identifier ("void");
                   1626:   ridpointers[(int) RID_FLOAT] = get_identifier ("float");
                   1627:   ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
                   1628:   ridpointers[(int) RID_SHORT] = get_identifier ("short");
                   1629:   ridpointers[(int) RID_LONG] = get_identifier ("long");
                   1630:   ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
                   1631:   ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
                   1632:   ridpointers[(int) RID_INLINE] = get_identifier ("inline");
                   1633:   ridpointers[(int) RID_CONST] = get_identifier ("const");
                   1634:   ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
                   1635:   ridpointers[(int) RID_AUTO] = get_identifier ("auto");
                   1636:   ridpointers[(int) RID_STATIC] = get_identifier ("static");
                   1637:   ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
                   1638:   ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
                   1639:   ridpointers[(int) RID_REGISTER] = get_identifier ("register");
                   1640: }
                   1641: 
                   1642: static void
                   1643: reinit_parse_for_function ()
                   1644: {
                   1645: }
                   1646: 
                   1647: /* If C is not whitespace, return C.
                   1648:    Otherwise skip whitespace and return first nonwhite char read.  */
                   1649: 
                   1650: static int
                   1651: skip_white_space (c)
                   1652:      register int c;
                   1653: {
1.1.1.7   root     1654: #if 0
1.1       root     1655:   register int inside;
1.1.1.7   root     1656: #endif
1.1       root     1657: 
                   1658:   for (;;)
                   1659:     {
                   1660:       switch (c)
                   1661:        {
1.1.1.6   root     1662:          /* Don't recognize comments in cc1: all comments are removed by cpp,
                   1663:             and cpp output can include / and * consecutively as operators.  */
                   1664: #if 0
1.1       root     1665:        case '/':
                   1666:          c = getc (finput);
                   1667:          if (c != '*')
                   1668:            {
                   1669:              ungetc (c, finput);
                   1670:              return '/';
                   1671:            }
                   1672: 
                   1673:          c = getc (finput);
                   1674: 
                   1675:          inside = 1;
                   1676:          while (inside)
                   1677:            {
                   1678:              if (c == '*')
                   1679:                {
                   1680:                  while (c == '*')
                   1681:                    c = getc (finput);
                   1682: 
                   1683:                  if (c == '/')
                   1684:                    {
                   1685:                      inside = 0;
                   1686:                      c = getc (finput);
                   1687:                    }
                   1688:                }
                   1689:              else if (c == '\n')
                   1690:                {
                   1691:                  lineno++;
                   1692:                  c = getc (finput);
                   1693:                }
                   1694:              else if (c == EOF)
                   1695:                {
                   1696:                  error ("unterminated comment");
                   1697:                  break;
                   1698:                }
                   1699:              else
                   1700:                c = getc (finput);
                   1701:            }
                   1702: 
                   1703:          break;
1.1.1.6   root     1704: #endif
1.1       root     1705: 
                   1706:        case '\n':
                   1707:          c = check_newline ();
                   1708:          break;
                   1709: 
                   1710:        case ' ':
                   1711:        case '\t':
                   1712:        case '\f':
                   1713:        case '\r':
1.1.1.11  root     1714:        case '\v':
1.1       root     1715:        case '\b':
                   1716:          c = getc (finput);
                   1717:          break;
                   1718: 
                   1719:        case '\\':
                   1720:          c = getc (finput);
                   1721:          if (c == '\n')
                   1722:            lineno++;
                   1723:          else
                   1724:            error ("stray '\\' in program");
                   1725:          c = getc (finput);
                   1726:          break;
                   1727: 
                   1728:        default:
                   1729:          return (c);
                   1730:        }
                   1731:     }
                   1732: }
                   1733: 
                   1734: 
                   1735: 
                   1736: /* Make the token buffer longer, preserving the data in it.
                   1737:    P should point to just beyond the last valid character in the old buffer.
                   1738:    The value we return is a pointer to the new buffer
                   1739:    at a place corresponding to P.  */
                   1740: 
                   1741: static char *
                   1742: extend_token_buffer (p)
                   1743:      char *p;
                   1744: {
                   1745:   int offset = p - token_buffer;
                   1746: 
                   1747:   maxtoken = maxtoken * 2 + 10;
1.1.1.7   root     1748:   token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
1.1       root     1749: 
                   1750:   return token_buffer + offset;
                   1751: }
                   1752: 
                   1753: /* At the beginning of a line, increment the line number
1.1.1.8   root     1754:    and process any #-directive on this line.
                   1755:    If the line is a #-directive, read the entire line and return a newline.
                   1756:    Otherwise, return the line's first non-whitespace character.  */
1.1       root     1757: 
                   1758: int
                   1759: check_newline ()
                   1760: {
                   1761:   register int c;
                   1762:   register int token;
                   1763: 
1.1.1.8   root     1764:   lineno++;
1.1       root     1765: 
1.1.1.8   root     1766:   /* Read first nonwhite char on the line.  */
1.1       root     1767: 
1.1.1.8   root     1768:   c = getc (finput);
                   1769:   while (c == ' ' || c == '\t')
                   1770:     c = getc (finput);
1.1       root     1771: 
1.1.1.8   root     1772:   if (c != '#')
                   1773:     {
                   1774:       /* If not #, return it so caller will use it.  */
                   1775:       return c;
                   1776:     }
1.1       root     1777: 
1.1.1.8   root     1778:   /* Read first nonwhite char after the `#'.  */
1.1       root     1779: 
1.1.1.8   root     1780:   c = getc (finput);
                   1781:   while (c == ' ' || c == '\t')
                   1782:     c = getc (finput);
1.1       root     1783: 
1.1.1.8   root     1784:   /* If a letter follows, then if the word here is `line', skip
                   1785:      it and ignore it; otherwise, ignore the line, with an error
                   1786:      if the word isn't `pragma'.  */
1.1       root     1787: 
1.1.1.8   root     1788:   if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
                   1789:     {
                   1790:       if (c == 'p')
1.1       root     1791:        {
1.1.1.8   root     1792:          if (getc (finput) == 'r'
                   1793:              && getc (finput) == 'a'
                   1794:              && getc (finput) == 'g'
                   1795:              && getc (finput) == 'm'
                   1796:              && getc (finput) == 'a'
1.1.1.10  root     1797:              && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
1.1.1.8   root     1798:            goto skipline;
                   1799:        }
1.1       root     1800: 
1.1.1.8   root     1801:       else if (c == 'l')
                   1802:        {
                   1803:          if (getc (finput) == 'i'
                   1804:              && getc (finput) == 'n'
                   1805:              && getc (finput) == 'e'
                   1806:              && ((c = getc (finput)) == ' ' || c == '\t'))
                   1807:            goto linenum;
                   1808:        }
                   1809:       else if (c == 'i')
                   1810:        {
                   1811:          if (getc (finput) == 'd'
                   1812:              && getc (finput) == 'e'
                   1813:              && getc (finput) == 'n'
                   1814:              && getc (finput) == 't'
                   1815:              && ((c = getc (finput)) == ' ' || c == '\t'))
1.1       root     1816:            {
1.1.1.8   root     1817:              extern FILE *asm_out_file;
1.1       root     1818: 
1.1.1.8   root     1819:              if (pedantic)
                   1820:                error ("ANSI C does not allow #ident");
1.1       root     1821: 
1.1.1.8   root     1822:              /* Here we have just seen `#ident '.
                   1823:                 A string constant should follow.  */
1.1       root     1824: 
1.1.1.8   root     1825:              while (c == ' ' || c == '\t')
                   1826:                c = getc (finput);
1.1       root     1827: 
1.1.1.8   root     1828:              /* If no argument, ignore the line.  */
                   1829:              if (c == '\n')
                   1830:                return c;
                   1831: 
                   1832:              ungetc (c, finput);
                   1833:              token = yylex ();
1.1.1.15! root     1834:              if (nextchar >= 0)
        !          1835:                ungetc (nextchar, finput), nextchar = -1;
1.1.1.8   root     1836:              if (token != STRING
                   1837:                  || TREE_CODE (yylval.ttype) != STRING_CST)
                   1838:                {
                   1839:                  error ("invalid #ident");
                   1840:                  goto skipline;
                   1841:                }
1.1       root     1842: 
1.1.1.5   root     1843: #ifdef ASM_OUTPUT_IDENT
1.1.1.8   root     1844:              ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype));
1.1.1.5   root     1845: #endif
1.1       root     1846: 
1.1.1.8   root     1847:              /* Skip the rest of this line.  */
                   1848:              goto skipline;
1.1       root     1849:            }
1.1.1.8   root     1850:        }
1.1       root     1851: 
1.1.1.8   root     1852:       error ("undefined or invalid # directive");
                   1853:       goto skipline;
                   1854:     }
1.1       root     1855: 
1.1.1.8   root     1856: linenum:
                   1857:   /* Here we have either `#line' or `# <nonletter>'.
                   1858:      In either case, it should be a line number; a digit should follow.  */
1.1       root     1859: 
1.1.1.8   root     1860:   while (c == ' ' || c == '\t')
                   1861:     c = getc (finput);
1.1       root     1862: 
1.1.1.8   root     1863:   /* If the # is the only nonwhite char on the line,
                   1864:      just ignore it.  Check the new newline.  */
                   1865:   if (c == '\n')
                   1866:     return c;
1.1       root     1867: 
1.1.1.8   root     1868:   /* Something follows the #; read a token.  */
1.1       root     1869: 
1.1.1.8   root     1870:   ungetc (c, finput);
                   1871:   token = yylex ();
1.1.1.15! root     1872:   if (nextchar >= 0)
        !          1873:     ungetc (nextchar, finput), nextchar = -1;
1.1       root     1874: 
1.1.1.8   root     1875:   if (token == CONSTANT
                   1876:       && TREE_CODE (yylval.ttype) == INTEGER_CST)
                   1877:     {
1.1.1.11  root     1878:       int old_lineno = lineno;
1.1.1.8   root     1879:       /* subtract one, because it is the following line that
                   1880:         gets the specified number */
1.1       root     1881: 
1.1.1.8   root     1882:       int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
1.1       root     1883: 
1.1.1.8   root     1884:       /* Is this the last nonwhite stuff on the line?  */
                   1885:       c = getc (finput);
                   1886:       while (c == ' ' || c == '\t')
                   1887:        c = getc (finput);
                   1888:       if (c == '\n')
1.1       root     1889:        {
1.1.1.8   root     1890:          /* No more: store the line number and check following line.  */
1.1       root     1891:          lineno = l;
1.1.1.8   root     1892:          return c;
                   1893:        }
                   1894:       ungetc (c, finput);
                   1895: 
                   1896:       /* More follows: it must be a string constant (filename).  */
1.1       root     1897: 
1.1.1.8   root     1898:       token = yylex ();
1.1.1.15! root     1899:       if (nextchar >= 0)
        !          1900:        ungetc (nextchar, finput), nextchar = -1;
1.1.1.8   root     1901:       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
                   1902:        {
                   1903:          error ("invalid #line");
                   1904:          goto skipline;
1.1       root     1905:        }
                   1906: 
1.1.1.8   root     1907:       input_filename
                   1908:        = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
                   1909:       strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
                   1910:       lineno = l;
                   1911: 
                   1912:       if (main_input_filename == 0)
                   1913:        main_input_filename = input_filename;
1.1.1.11  root     1914: 
                   1915:       /* Is this the last nonwhite stuff on the line?  */
                   1916:       c = getc (finput);
                   1917:       while (c == ' ' || c == '\t')
                   1918:        c = getc (finput);
                   1919:       if (c == '\n')
                   1920:        return c;
                   1921:       ungetc (c, finput);
                   1922: 
                   1923:       token = yylex ();
1.1.1.15! root     1924:       if (nextchar >= 0)
        !          1925:        ungetc (nextchar, finput), nextchar = -1;
1.1.1.11  root     1926: 
                   1927:       /* `1' after file name means entering new file.
                   1928:         `2' after file name means just left a file.  */
                   1929: 
                   1930:       if (token == CONSTANT
                   1931:          && TREE_CODE (yylval.ttype) == INTEGER_CST)
                   1932:        {
                   1933:          if (TREE_INT_CST_LOW (yylval.ttype) == 1)
                   1934:            {
                   1935:              struct file_stack *p
                   1936:                = (struct file_stack *) xmalloc (sizeof (struct file_stack));
                   1937:              input_file_stack->line = old_lineno;
                   1938:              p->next = input_file_stack;
                   1939:              p->name = input_filename;
                   1940:              input_file_stack = p;
                   1941:              input_file_stack_tick++;
                   1942:            }
                   1943:          else if (input_file_stack->next)
                   1944:            {
                   1945:              struct file_stack *p = input_file_stack;
                   1946:              input_file_stack = p->next;
                   1947:              free (p);
                   1948:              input_file_stack_tick++;
                   1949:            }
                   1950:          else
                   1951:            error ("#-lines for entering and leaving files don't match");
                   1952:        }
1.1       root     1953:     }
1.1.1.8   root     1954:   else
1.1.1.11  root     1955:     error ("invalid #-line");
1.1.1.8   root     1956: 
                   1957:   /* skip the rest of this line.  */
                   1958:  skipline:
1.1.1.10  root     1959:   if (c == '\n')
                   1960:     return c;
1.1.1.9   root     1961:   while ((c = getc (finput)) != EOF && c != '\n');
1.1.1.8   root     1962:   return c;
1.1       root     1963: }
                   1964: 
                   1965: #define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9'))
                   1966: #define isdigit(char) (char >= '0' && char <= '9')
                   1967: #define ENDFILE -1  /* token that represents end-of-file */
                   1968: 
                   1969: 
                   1970: static int
                   1971: readescape ()
                   1972: {
                   1973:   register int c = getc (finput);
                   1974:   register int count, code;
1.1.1.7   root     1975:   int firstdig;
1.1       root     1976: 
                   1977:   switch (c)
                   1978:     {
                   1979:     case 'x':
                   1980:       code = 0;
                   1981:       count = 0;
                   1982:       while (1)
                   1983:        {
                   1984:          c = getc (finput);
                   1985:          if (!(c >= 'a' && c <= 'f')
                   1986:              && !(c >= 'A' && c <= 'F')
                   1987:              && !(c >= '0' && c <= '9'))
                   1988:            {
                   1989:              ungetc (c, finput);
                   1990:              break;
                   1991:            }
                   1992:          code *= 16;
                   1993:          if (c >= 'a' && c <= 'f')
                   1994:            code += c - 'a' + 10;
                   1995:          if (c >= 'A' && c <= 'F')
                   1996:            code += c - 'A' + 10;
                   1997:          if (c >= '0' && c <= '9')
                   1998:            code += c - '0';
1.1.1.7   root     1999:          if (count == 0)
                   2000:            firstdig = code;
1.1       root     2001:          count++;
                   2002:        }
                   2003:       if (count == 0)
                   2004:        error ("\\x used with no following hex digits");
1.1.1.11  root     2005:       else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
1.1.1.13  root     2006:               || (count > 1
                   2007:                   && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
                   2008:                       <= firstdig)))
1.1.1.7   root     2009:        warning ("hex escape out of range");
1.1       root     2010:       return code;
                   2011: 
                   2012:     case '0':  case '1':  case '2':  case '3':  case '4':
                   2013:     case '5':  case '6':  case '7':
                   2014:       code = 0;
                   2015:       count = 0;
                   2016:       while ((c <= '7') && (c >= '0') && (count++ < 3))
                   2017:        {
                   2018:          code = (code * 8) + (c - '0');
                   2019:          c = getc (finput);
                   2020:        }
                   2021:       ungetc (c, finput);
                   2022:       return code;
                   2023: 
                   2024:     case '\\': case '\'': case '"':
                   2025:       return c;
                   2026: 
                   2027:     case '\n':
                   2028:       lineno++;
                   2029:       return -1;
                   2030: 
                   2031:     case 'n':
                   2032:       return TARGET_NEWLINE;
                   2033: 
                   2034:     case 't':
                   2035:       return TARGET_TAB;
                   2036: 
                   2037:     case 'r':
                   2038:       return TARGET_CR;
                   2039: 
                   2040:     case 'f':
                   2041:       return TARGET_FF;
                   2042: 
                   2043:     case 'b':
                   2044:       return TARGET_BS;
                   2045: 
                   2046:     case 'a':
                   2047:       return TARGET_BELL;
                   2048: 
                   2049:     case 'v':
                   2050:       return TARGET_VT;
                   2051: 
                   2052:     case 'E':
                   2053:       return 033;
                   2054: 
                   2055:     case '?':
1.1.1.3   root     2056:       /* `\(', etc, are used at beginning of line to avoid confusing Emacs.  */
1.1.1.2   root     2057:     case '(':
1.1.1.3   root     2058:     case '{':
                   2059:     case '[':
1.1       root     2060:       return c;
                   2061:     }
                   2062:   if (c >= 040 && c <= 0177)
                   2063:     warning ("unknown escape sequence `\\%c'", c);
                   2064:   else
                   2065:     warning ("unknown escape sequence: `\\' followed by char code 0x%x", c);
                   2066:   return c;
                   2067: }
                   2068: 
                   2069: void
                   2070: yyerror (string)
                   2071:      char *string;
                   2072: {
                   2073:   char buf[200];
                   2074: 
                   2075:   strcpy (buf, string);
                   2076: 
                   2077:   /* We can't print string and character constants well
                   2078:      because the token_buffer contains the result of processing escapes.  */
1.1.1.5   root     2079:   if (end_of_file)
1.1       root     2080:     strcat (buf, " at end of input");
1.1.1.5   root     2081:   else if (token_buffer[0] == 0)
                   2082:     strcat (buf, " at null character");
1.1       root     2083:   else if (token_buffer[0] == '"')
                   2084:     strcat (buf, " before string constant");
                   2085:   else if (token_buffer[0] == '\'')
                   2086:     strcat (buf, " before character constant");
1.1.1.7   root     2087:   else if (token_buffer[0] < 040 || token_buffer[0] >= 0177)
                   2088:     sprintf (buf + strlen (buf), " before character 0%o", token_buffer[0]);
1.1       root     2089:   else
                   2090:     strcat (buf, " before `%s'");
                   2091: 
                   2092:   error (buf, token_buffer);
                   2093: }
                   2094: 
                   2095: static int
                   2096: yylex ()
                   2097: {
                   2098:   register int c;
                   2099:   register char *p;
                   2100:   register int value;
                   2101:   int wide_flag = 0;
                   2102: 
                   2103:   if (nextchar >= 0)
                   2104:     c = nextchar, nextchar = -1;
                   2105:   else
                   2106:     c = getc (finput);
                   2107: 
                   2108:   /* Effectively do c = skip_white_space (c)
                   2109:      but do it faster in the usual cases.  */
                   2110:   while (1)
                   2111:     switch (c)
                   2112:       {
                   2113:       case ' ':
                   2114:       case '\t':
                   2115:       case '\f':
                   2116:       case '\r':
1.1.1.11  root     2117:       case '\v':
1.1       root     2118:       case '\b':
                   2119:        c = getc (finput);
                   2120:        break;
                   2121: 
                   2122:       case '\n':
                   2123:       case '/':
                   2124:       case '\\':
                   2125:        c = skip_white_space (c);
                   2126:       default:
                   2127:        goto found_nonwhite;
                   2128:       }
                   2129:  found_nonwhite:
                   2130: 
                   2131:   token_buffer[0] = c;
                   2132:   token_buffer[1] = 0;
                   2133: 
                   2134: /*  yylloc.first_line = lineno; */
                   2135: 
                   2136:   switch (c)
                   2137:     {
                   2138:     case EOF:
1.1.1.5   root     2139:       end_of_file = 1;
1.1       root     2140:       token_buffer[0] = 0;
                   2141:       value = ENDFILE;
                   2142:       break;
                   2143: 
                   2144:     case '$':
                   2145:       if (dollars_in_ident)
                   2146:        goto letter;
                   2147:       return '$';
                   2148: 
                   2149:     case 'L':
                   2150:       /* Capital L may start a wide-string or wide-character constant.  */
                   2151:       {
                   2152:        register int c = getc (finput);
                   2153:        if (c == '\'')
                   2154:          {
                   2155:            wide_flag = 1;
                   2156:            goto char_constant;
                   2157:          }
                   2158:        if (c == '"')
                   2159:          {
                   2160:            wide_flag = 1;
                   2161:            goto string_constant;
                   2162:          }
                   2163:        ungetc (c, finput);
                   2164:       }
                   2165: 
                   2166:     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
                   2167:     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
                   2168:     case 'K':            case 'M':  case 'N':  case 'O':
                   2169:     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
                   2170:     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
                   2171:     case 'Z':
                   2172:     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
                   2173:     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
                   2174:     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
                   2175:     case 'p':  case 'q':  case 'r':  case 's':  case 't':
                   2176:     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
                   2177:     case 'z':
                   2178:     case '_':
                   2179:     letter:
                   2180:       p = token_buffer;
                   2181:       while (isalnum (c) || c == '_' || c == '$')
                   2182:        {
                   2183:          if (p >= token_buffer + maxtoken)
                   2184:            p = extend_token_buffer (p);
                   2185:          if (c == '$' && ! dollars_in_ident)
                   2186:            break;
                   2187: 
                   2188:          *p++ = c;
                   2189:          c = getc (finput);
                   2190:        }
                   2191: 
                   2192:       *p = 0;
                   2193:       nextchar = c;
                   2194: 
                   2195:       value = IDENTIFIER;
                   2196:       yylval.itype = 0;
                   2197: 
1.1.1.4   root     2198:       /* Try to recognize a keyword.  Uses minimum-perfect hash function */
1.1.1.11  root     2199: 
1.1.1.4   root     2200:       {
                   2201:        register struct resword *ptr;
1.1       root     2202: 
1.1.1.4   root     2203:        if (ptr = is_reserved_word (token_buffer, p - token_buffer))
                   2204:          {
                   2205:            if (ptr->rid)
                   2206:              yylval.ttype = ridpointers[(int) ptr->rid];
                   2207:            if ((! flag_no_asm
                   2208:                 /* -fno-asm means don't recognize the non-ANSI keywords.  */
                   2209:                 || ((int) ptr->token != ASM
                   2210:                     && (int) ptr->token != TYPEOF
1.1.1.10  root     2211:                     && ptr->rid != RID_INLINE)
                   2212:                 /* Recognize __asm and __inline despite -fno-asm.  */
                   2213:                 || token_buffer[0] == '_')
1.1.1.4   root     2214:                /* -ftraditional means don't recognize nontraditional keywords
                   2215:                   typeof, const, volatile, signed or inline.  */
                   2216:                && (! flag_traditional
                   2217:                    || ((int) ptr->token != TYPE_QUAL
                   2218:                        && (int) ptr->token != TYPEOF
                   2219:                        && ptr->rid != RID_SIGNED
1.1.1.10  root     2220:                        && ptr->rid != RID_INLINE)
                   2221:                    /* Recognize __inline, etc. despite -ftraditional.  */
                   2222:                    || token_buffer[0] == '_'))
1.1.1.15! root     2223:              {
        !          2224:                value = (int) ptr->token;
        !          2225:                /* Even if we decided to recognize asm, still perhaps warn.  */
        !          2226:                if (pedantic
        !          2227:                    && (value == ASM || value == TYPEOF
        !          2228:                        || ptr->rid == RID_INLINE)
        !          2229:                    && token_buffer[0] != '_')
        !          2230:                  warning ("ANSI does not permit the keyword `%s'",
        !          2231:                           token_buffer);
        !          2232:              }
1.1.1.4   root     2233:          }
                   2234:       }
1.1       root     2235: 
                   2236:       /* If we did not find a keyword, look for an identifier
                   2237:         (or a typename).  */
                   2238: 
                   2239:       if (value == IDENTIFIER)
                   2240:        {
                   2241:           yylval.ttype = get_identifier (token_buffer);
                   2242:          lastiddecl = lookup_name (yylval.ttype);
                   2243: 
                   2244:          if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL)
                   2245:            value = TYPENAME;
                   2246:        }
                   2247: 
                   2248:       break;
                   2249: 
                   2250:     case '0':  case '1':  case '2':  case '3':  case '4':
                   2251:     case '5':  case '6':  case '7':  case '8':  case '9':
                   2252:     case '.':
                   2253:       {
                   2254:        int base = 10;
                   2255:        int count = 0;
                   2256:        int largest_digit = 0;
                   2257:        int numdigits = 0;
                   2258:        /* for multi-precision arithmetic,
                   2259:           we store only 8 live bits in each short,
                   2260:           giving us 64 bits of reliable precision */
                   2261:        short shorts[8];
1.1.1.11  root     2262:        int overflow = 0;
1.1.1.3   root     2263: 
1.1.1.5   root     2264:        enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
1.1.1.3   root     2265:          = NOT_FLOAT;
1.1       root     2266: 
                   2267:        for (count = 0; count < 8; count++)
                   2268:          shorts[count] = 0;
                   2269: 
                   2270:        p = token_buffer;
                   2271:        *p++ = c;
                   2272: 
                   2273:        if (c == '0')
                   2274:          {
                   2275:            *p++ = (c = getc (finput));
                   2276:            if ((c == 'x') || (c == 'X'))
                   2277:              {
                   2278:                base = 16;
                   2279:                *p++ = (c = getc (finput));
                   2280:              }
                   2281:            else
                   2282:              {
                   2283:                base = 8;
                   2284:                numdigits++;
                   2285:              }
                   2286:          }
                   2287: 
                   2288:        /* Read all the digits-and-decimal-points.  */
                   2289: 
                   2290:        while (c == '.'
                   2291:               || (isalnum (c) && (c != 'l') && (c != 'L')
                   2292:                   && (c != 'u') && (c != 'U')
1.1.1.3   root     2293:                   && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
1.1       root     2294:          {
                   2295:            if (c == '.')
                   2296:              {
                   2297:                if (base == 16)
                   2298:                  error ("floating constant may not be in radix 16");
1.1.1.3   root     2299:                if (floatflag == AFTER_POINT)
                   2300:                  {
                   2301:                    error ("malformed floating constant");
                   2302:                    floatflag = TOO_MANY_POINTS;
                   2303:                  }
                   2304:                else
                   2305:                  floatflag = AFTER_POINT;
                   2306: 
1.1       root     2307:                base = 10;
                   2308:                *p++ = c = getc (finput);
                   2309:                /* Accept '.' as the start of a floating-point number
                   2310:                   only when it is followed by a digit.
                   2311:                   Otherwise, unread the following non-digit
                   2312:                   and use the '.' as a structural token.  */
                   2313:                if (p == token_buffer + 2 && !isdigit (c))
                   2314:                  {
                   2315:                    if (c == '.')
                   2316:                      {
                   2317:                        c = getc (finput);
                   2318:                        if (c == '.')
                   2319:                          {
                   2320:                            *p++ = c;
                   2321:                            *p = 0;
                   2322:                            return ELLIPSIS;
                   2323:                          }
                   2324:                        error ("parse error at `..'");
                   2325:                      }
                   2326:                    ungetc (c, finput);
                   2327:                    token_buffer[1] = 0;
                   2328:                    value = '.';
                   2329:                    goto done;
                   2330:                  }
                   2331:              }
                   2332:            else
                   2333:              {
                   2334:                /* It is not a decimal point.
                   2335:                   It should be a digit (perhaps a hex digit).  */
                   2336: 
                   2337:                if (isdigit (c))
                   2338:                  {
                   2339:                    c = c - '0';
                   2340:                  }
                   2341:                else if (base <= 10)
                   2342:                  {
                   2343:                    if ((c&~040) == 'E')
                   2344:                      {
                   2345:                        base = 10;
1.1.1.3   root     2346:                        floatflag = AFTER_POINT;
1.1       root     2347:                        break;   /* start of exponent */
                   2348:                      }
                   2349:                    error ("nondigits in number and not hexadecimal");
                   2350:                    c = 0;
                   2351:                  }
                   2352:                else if (c >= 'a')
                   2353:                  {
                   2354:                    c = c - 'a' + 10;
                   2355:                  }
                   2356:                else
                   2357:                  {
                   2358:                    c = c - 'A' + 10;
                   2359:                  }
                   2360:                if (c >= largest_digit)
                   2361:                  largest_digit = c;
                   2362:                numdigits++;
1.1.1.11  root     2363: 
1.1       root     2364:                for (count = 0; count < 8; count++)
                   2365:                  {
1.1.1.11  root     2366:                    shorts[count] *= base;
1.1       root     2367:                    if (count)
                   2368:                      {
                   2369:                        shorts[count] += (shorts[count-1] >> 8);
                   2370:                        shorts[count-1] &= (1<<8)-1;
                   2371:                      }
                   2372:                    else shorts[0] += c;
                   2373:                  }
1.1.1.11  root     2374: 
                   2375:                if (shorts[7] >= 1<<8
                   2376:                    || shorts[7] < - (1 << 8))
                   2377:                  overflow = TRUE;
                   2378: 
1.1       root     2379:                if (p >= token_buffer + maxtoken - 3)
                   2380:                  p = extend_token_buffer (p);
                   2381:                *p++ = (c = getc (finput));
                   2382:              }
                   2383:          }
                   2384: 
                   2385:        if (numdigits == 0)
                   2386:          error ("numeric constant with no digits");
                   2387: 
                   2388:        if (largest_digit >= base)
                   2389:          error ("numeric constant contains digits beyond the radix");
                   2390: 
                   2391:        /* Remove terminating char from the token buffer and delimit the string */
                   2392:        *--p = 0;
                   2393: 
1.1.1.3   root     2394:        if (floatflag != NOT_FLOAT)
1.1       root     2395:          {
                   2396:            tree type = double_type_node;
                   2397:            char f_seen = 0;
                   2398:            char l_seen = 0;
1.1.1.8   root     2399:            REAL_VALUE_TYPE value;
1.1       root     2400: 
                   2401:            /* Read explicit exponent if any, and put it in tokenbuf.  */
                   2402: 
                   2403:            if ((c == 'e') || (c == 'E'))
                   2404:              {
                   2405:                if (p >= token_buffer + maxtoken - 3)
                   2406:                  p = extend_token_buffer (p);
                   2407:                *p++ = c;
                   2408:                c = getc (finput);
                   2409:                if ((c == '+') || (c == '-'))
                   2410:                  {
                   2411:                    *p++ = c;
                   2412:                    c = getc (finput);
                   2413:                  }
                   2414:                if (! isdigit (c))
                   2415:                  error ("floating constant exponent has no digits");
                   2416:                while (isdigit (c))
                   2417:                  {
                   2418:                    if (p >= token_buffer + maxtoken - 3)
                   2419:                      p = extend_token_buffer (p);
                   2420:                    *p++ = c;
                   2421:                    c = getc (finput);
                   2422:                  }
                   2423:              }
                   2424: 
                   2425:            *p = 0;
                   2426:            errno = 0;
1.1.1.8   root     2427:            value = REAL_VALUE_ATOF (token_buffer);
1.1       root     2428: #ifdef ERANGE
                   2429:            if (errno == ERANGE && !flag_traditional)
1.1.1.5   root     2430:              {
                   2431:                char *p1 = token_buffer;
                   2432:                /* Check for "0.0" and variants;
                   2433:                   Sunos 4 spuriously returns ERANGE for them.  */
                   2434:                while (*p1 == '0') p1++;
1.1.1.11  root     2435:                if (*p1 == '.')
                   2436:                  {
                   2437:                    p1++;
                   2438:                    while (*p1 == '0') p1++;
                   2439:                  }
                   2440:                if (*p1 == 'e' || *p1 == 'E')
                   2441:                  {
                   2442:                    /* with significand==0, ignore the exponent */
                   2443:                    p1++;
                   2444:                    while (*p1 != 0) p1++;
                   2445:                  }
1.1.1.12  root     2446:                /* ERANGE is also reported for underflow,
                   2447:                   so test the value to distinguish overflow from that.  */
1.1.1.13  root     2448:                if (*p1 != 0 && (value > 1.0 || value < -1.0))
1.1.1.5   root     2449:                  warning ("floating point number exceeds range of `double'");
                   2450:              }
1.1       root     2451: #endif
                   2452: 
                   2453:            /* Read the suffixes to choose a data type.  */
                   2454:            while (1)
                   2455:              {
                   2456:                if (c == 'f' || c == 'F')
                   2457:                  {
1.1.1.11  root     2458:                    float floater;
1.1       root     2459:                    if (f_seen)
                   2460:                      error ("two `f's in floating constant");
                   2461:                    f_seen = 1;
                   2462:                    type = float_type_node;
1.1.1.11  root     2463:                    floater = value;
                   2464:                    value = floater;
1.1       root     2465:                  }
                   2466:                else if (c == 'l' || c == 'L')
                   2467:                  {
                   2468:                    if (l_seen)
                   2469:                      error ("two `l's in floating constant");
                   2470:                    l_seen = 1;
                   2471:                    type = long_double_type_node;
                   2472:                  }
                   2473:                else
                   2474:                  {
                   2475:                    if (isalnum (c))
                   2476:                      {
                   2477:                        error ("garbage at end of number");
                   2478:                        while (isalnum (c))
                   2479:                          {
                   2480:                            if (p >= token_buffer + maxtoken - 3)
                   2481:                              p = extend_token_buffer (p);
                   2482:                            *p++ = c;
                   2483:                            c = getc (finput);
                   2484:                          }
                   2485:                      }
                   2486:                    break;
                   2487:                  }
                   2488:                if (p >= token_buffer + maxtoken - 3)
                   2489:                  p = extend_token_buffer (p);
                   2490:                *p++ = c;
                   2491:                c = getc (finput);
                   2492:              }
                   2493: 
                   2494:            /* Create a node with determined type and value.  */
                   2495:            yylval.ttype = build_real (type, value);
                   2496: 
                   2497:            ungetc (c, finput);
                   2498:            *p = 0;
                   2499:          }
                   2500:        else
                   2501:          {
                   2502:            tree type;
                   2503:            int spec_unsigned = 0;
                   2504:            int spec_long = 0;
1.1.1.11  root     2505:            int spec_long_long = 0;
1.1       root     2506: 
                   2507:            while (1)
                   2508:              {
                   2509:                if (c == 'u' || c == 'U')
                   2510:                  {
                   2511:                    if (spec_unsigned)
                   2512:                      error ("two `u's in integer constant");
                   2513:                    spec_unsigned = 1;
                   2514:                  }
                   2515:                else if (c == 'l' || c == 'L')
                   2516:                  {
                   2517:                    if (spec_long)
1.1.1.11  root     2518:                      {
                   2519:                        if (spec_long_long)
                   2520:                          error ("three `l's in integer constant");
                   2521:                        else if (pedantic)
                   2522:                          warning ("ANSI C forbids long long integer constants");
                   2523:                        spec_long_long = 1;
                   2524:                      }
1.1       root     2525:                    spec_long = 1;
                   2526:                  }
                   2527:                else
                   2528:                  {
                   2529:                    if (isalnum (c))
                   2530:                      {
                   2531:                        error ("garbage at end of number");
                   2532:                        while (isalnum (c))
                   2533:                          {
                   2534:                            if (p >= token_buffer + maxtoken - 3)
                   2535:                              p = extend_token_buffer (p);
                   2536:                            *p++ = c;
                   2537:                            c = getc (finput);
                   2538:                          }
                   2539:                      }
                   2540:                    break;
                   2541:                  }
                   2542:                if (p >= token_buffer + maxtoken - 3)
                   2543:                  p = extend_token_buffer (p);
                   2544:                *p++ = c;
                   2545:                c = getc (finput);
                   2546:              }
                   2547: 
                   2548:            ungetc (c, finput);
                   2549: 
1.1.1.11  root     2550:            if ((overflow || shorts[7] || shorts[6] || shorts[5] || shorts[4])
                   2551:                && !spec_long_long)
1.1       root     2552:              warning ("integer constant out of range");
                   2553: 
1.1.1.11  root     2554:            /* If it won't fit in a signed long long, make it unsigned.
                   2555:               We can't distinguish based on the tree node because
                   2556:               any integer constant fits any long long type.  */
                   2557:            if (shorts[7] >= (1<<8))
                   2558:              spec_unsigned = 1;
                   2559: 
1.1       root     2560:            /* This is simplified by the fact that our constant
                   2561:               is always positive.  */
1.1.1.15! root     2562:            /* The casts in the following statement should not be
        !          2563:               needed, but they get around bugs in some C compilers.  */
1.1       root     2564:            yylval.ttype
1.1.1.11  root     2565:              = (build_int_2
1.1.1.15! root     2566:                 ((((long)shorts[3]<<24) + ((long)shorts[2]<<16)
        !          2567:                   + ((long)shorts[1]<<8) + (long)shorts[0]),
1.1.1.11  root     2568:                  (spec_long_long
1.1.1.15! root     2569:                   ? (((long)shorts[7]<<24) + ((long)shorts[6]<<16)
        !          2570:                      + ((long)shorts[5]<<8) + (long)shorts[4])
1.1.1.11  root     2571:                   : 0)));
                   2572: 
1.1       root     2573:            if (!spec_long && !spec_unsigned
                   2574:                && int_fits_type_p (yylval.ttype, integer_type_node))
                   2575:              type = integer_type_node;
                   2576: 
1.1.1.13  root     2577:            else if (!spec_long && (base != 10 || spec_unsigned)
1.1.1.11  root     2578:                     && int_fits_type_p (yylval.ttype, unsigned_type_node))
1.1       root     2579:              type = unsigned_type_node;
                   2580: 
1.1.1.11  root     2581:            else if (!spec_unsigned && !spec_long_long
                   2582:                     && int_fits_type_p (yylval.ttype, long_integer_type_node))
1.1       root     2583:              type = long_integer_type_node;
                   2584: 
1.1.1.11  root     2585:            else if (! spec_long_long
                   2586:                     && int_fits_type_p (yylval.ttype,
                   2587:                                         long_unsigned_type_node))
                   2588:              type = long_unsigned_type_node;
                   2589: 
                   2590:            else if (! spec_unsigned
                   2591:                     && int_fits_type_p (yylval.ttype,
                   2592:                                         long_long_integer_type_node))
                   2593:              type = long_long_integer_type_node;
                   2594: 
                   2595:            else if (int_fits_type_p (yylval.ttype,
                   2596:                                      long_long_unsigned_type_node))
                   2597:              type = long_long_unsigned_type_node;
                   2598: 
1.1       root     2599:            else
                   2600:              {
1.1.1.11  root     2601:                type = long_long_integer_type_node;
                   2602:                warning ("integer constant out of range");
1.1       root     2603:              }
1.1.1.11  root     2604: 
1.1       root     2605:            TREE_TYPE (yylval.ttype) = type;
1.1.1.13  root     2606:            *p = 0;
1.1       root     2607:          }
                   2608: 
                   2609:        value = CONSTANT; break;
                   2610:       }
                   2611: 
                   2612:     case '\'':
                   2613:     char_constant:
                   2614:       {
1.1.1.11  root     2615:        register int result = 0;
                   2616:        register num_chars = 0;
                   2617:        int width = TYPE_PRECISION (char_type_node);
                   2618:        int max_chars;
1.1       root     2619: 
1.1.1.11  root     2620:        if (wide_flag) width = TYPE_PRECISION (integer_type_node);
1.1       root     2621: 
1.1.1.11  root     2622:        max_chars = TYPE_PRECISION (integer_type_node) / width;
                   2623: 
                   2624:        while (1)
1.1       root     2625:          {
1.1.1.11  root     2626:          tryagain:
                   2627: 
                   2628:            c = getc (finput);
                   2629: 
                   2630:            if (c == '\'' || c == EOF)
                   2631:              break;
                   2632: 
                   2633:            if (c == '\\')
                   2634:              {
                   2635:                c = readescape ();
                   2636:                if (c < 0)
                   2637:                  goto tryagain;
                   2638:                if (width < HOST_BITS_PER_INT
                   2639:                    && (unsigned) c >= (1 << width))
                   2640:                  warning ("escape sequence out of range for character");
                   2641:              }
                   2642:            else if (c == '\n')
                   2643:              {
                   2644:                if (pedantic)
                   2645:                  warning ("ANSI C forbids newline in character constant");
                   2646:                lineno++;
                   2647:              }
                   2648: 
                   2649:            num_chars++;
                   2650:            if (num_chars > maxtoken - 4)
                   2651:              extend_token_buffer (token_buffer);
                   2652: 
                   2653:            token_buffer[num_chars] = c;
                   2654: 
                   2655:            /* Merge character into result; ignore excess chars.  */
                   2656:            if (num_chars < max_chars + 1)
                   2657:              {
                   2658:                if (width < HOST_BITS_PER_INT)
                   2659:                  result = (result << width) | (c & ((1 << width) - 1));
                   2660:                else
                   2661:                  result = c;
                   2662:              }
1.1       root     2663:          }
                   2664: 
1.1.1.11  root     2665:        token_buffer[num_chars + 1] = '\'';
                   2666:        token_buffer[num_chars + 2] = 0;
1.1       root     2667: 
                   2668:        if (c != '\'')
                   2669:          error ("malformatted character constant");
1.1.1.11  root     2670:        else if (num_chars == 0)
                   2671:          error ("empty character constant");
                   2672:        else if (num_chars > max_chars)
                   2673:          {
                   2674:            num_chars = max_chars;
                   2675:            error ("character constant too long");
                   2676:          }
                   2677:        else if (num_chars != 1 && ! flag_traditional)
                   2678:          warning ("multi-character character constant");
1.1       root     2679: 
                   2680:        /* If char type is signed, sign-extend the constant.  */
1.1.1.7   root     2681:        if (! wide_flag)
                   2682:          {
1.1.1.11  root     2683:            int num_bits = num_chars * width;
1.1.1.7   root     2684:            if (TREE_UNSIGNED (char_type_node)
1.1.1.11  root     2685:                || ((result >> (num_bits - 1)) & 1) == 0)
                   2686:              yylval.ttype
                   2687:                = build_int_2 (result & ((unsigned) ~0
                   2688:                                         >> (HOST_BITS_PER_INT - num_bits)),
                   2689:                               0);
1.1.1.7   root     2690:            else
1.1.1.11  root     2691:              yylval.ttype
                   2692:                = build_int_2 (result | ~((unsigned) ~0
                   2693:                                          >> (HOST_BITS_PER_INT - num_bits)),
                   2694:                               -1);
1.1.1.7   root     2695:          }
1.1       root     2696:        else
1.1.1.11  root     2697:          yylval.ttype = build_int_2 (result, 0);
1.1       root     2698: 
                   2699:        TREE_TYPE (yylval.ttype) = integer_type_node;
                   2700:        value = CONSTANT; break;
                   2701:       }
                   2702: 
                   2703:     case '"':
                   2704:     string_constant:
                   2705:       {
1.1.1.7   root     2706:        int *widep;
                   2707: 
1.1       root     2708:        c = getc (finput);
                   2709:        p = token_buffer + 1;
                   2710: 
1.1.1.7   root     2711:        if (wide_flag)
                   2712:          widep = wide_buffer;
                   2713: 
1.1.1.9   root     2714:        while (c != '"' && c >= 0)
1.1       root     2715:          {
                   2716:            if (c == '\\')
                   2717:              {
                   2718:                c = readescape ();
                   2719:                if (c < 0)
                   2720:                  goto skipnewline;
1.1.1.11  root     2721:                if (!wide_flag && c >= (1 << TYPE_PRECISION (char_type_node)))
1.1.1.7   root     2722:                  warning ("escape sequence out of range for character");
1.1       root     2723:              }
                   2724:            else if (c == '\n')
                   2725:              {
                   2726:                if (pedantic)
                   2727:                  warning ("ANSI C forbids newline in string constant");
                   2728:                lineno++;
                   2729:              }
                   2730: 
1.1.1.7   root     2731:            /* Store the char in C into the appropriate buffer.  */
                   2732: 
                   2733:            if (wide_flag)
                   2734:              {
                   2735:                if (widep == wide_buffer + max_wide)
                   2736:                  {
                   2737:                    int n = widep - wide_buffer;
                   2738:                    max_wide *= 2;
1.1.1.14  root     2739:                    wide_buffer
                   2740:                      = (int *) xrealloc (wide_buffer,
                   2741:                                          (max_wide + 1) * UNITS_PER_WORD);
1.1.1.7   root     2742:                    widep = wide_buffer + n;
                   2743:                  }
                   2744:                *widep++ = c;
                   2745:              }
                   2746:            else
                   2747:              {
                   2748:                if (p == token_buffer + maxtoken)
                   2749:                  p = extend_token_buffer (p);
                   2750:                *p++ = c;
                   2751:              }
1.1       root     2752: 
                   2753:          skipnewline:
                   2754:            c = getc (finput);
                   2755:          }
                   2756: 
1.1.1.7   root     2757:        /* We have read the entire constant.
                   2758:           Construct a STRING_CST for the result.  */
1.1       root     2759: 
                   2760:        if (wide_flag)
                   2761:          {
1.1.1.7   root     2762:            /* If this is a L"..." wide-string, make a vector
                   2763:               of the ints in wide_buffer.  */
                   2764:            *widep = 0;
                   2765:            /* We have not implemented the case where `int'
                   2766:               on the target and on the execution machine differ in size.  */
                   2767:            if (TYPE_PRECISION (integer_type_node)
                   2768:                != sizeof (int) * BITS_PER_UNIT)
                   2769:              abort ();
1.1.1.12  root     2770:            yylval.ttype
                   2771:              = build_string ((widep - wide_buffer + 1) * sizeof (int),
                   2772:                              wide_buffer);
1.1       root     2773:            TREE_TYPE (yylval.ttype) = int_array_type_node;
                   2774:          }
                   2775:        else
                   2776:          {
1.1.1.7   root     2777:            *p = 0;
1.1       root     2778:            yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
                   2779:            TREE_TYPE (yylval.ttype) = char_array_type_node;
                   2780:          }
                   2781: 
                   2782:        *p++ = '"';
                   2783:        *p = 0;
                   2784: 
                   2785:        value = STRING; break;
                   2786:       }
1.1.1.11  root     2787: 
1.1       root     2788:     case '+':
                   2789:     case '-':
                   2790:     case '&':
                   2791:     case '|':
                   2792:     case '<':
                   2793:     case '>':
                   2794:     case '*':
                   2795:     case '/':
                   2796:     case '%':
                   2797:     case '^':
                   2798:     case '!':
                   2799:     case '=':
                   2800:       {
                   2801:        register int c1;
                   2802: 
                   2803:       combine:
                   2804: 
                   2805:        switch (c)
                   2806:          {
                   2807:          case '+':
                   2808:            yylval.code = PLUS_EXPR; break;
                   2809:          case '-':
                   2810:            yylval.code = MINUS_EXPR; break;
                   2811:          case '&':
                   2812:            yylval.code = BIT_AND_EXPR; break;
                   2813:          case '|':
                   2814:            yylval.code = BIT_IOR_EXPR; break;
                   2815:          case '*':
                   2816:            yylval.code = MULT_EXPR; break;
                   2817:          case '/':
                   2818:            yylval.code = TRUNC_DIV_EXPR; break;
                   2819:          case '%':
                   2820:            yylval.code = TRUNC_MOD_EXPR; break;
                   2821:          case '^':
                   2822:            yylval.code = BIT_XOR_EXPR; break;
                   2823:          case LSHIFT:
                   2824:            yylval.code = LSHIFT_EXPR; break;
                   2825:          case RSHIFT:
                   2826:            yylval.code = RSHIFT_EXPR; break;
                   2827:          case '<':
                   2828:            yylval.code = LT_EXPR; break;
                   2829:          case '>':
                   2830:            yylval.code = GT_EXPR; break;
1.1.1.11  root     2831:          }
1.1       root     2832: 
                   2833:        token_buffer[1] = c1 = getc (finput);
                   2834:        token_buffer[2] = 0;
                   2835: 
                   2836:        if (c1 == '=')
                   2837:          {
                   2838:            switch (c)
                   2839:              {
                   2840:              case '<':
                   2841:                value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
                   2842:              case '>':
                   2843:                value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
                   2844:              case '!':
                   2845:                value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
                   2846:              case '=':
                   2847:                value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
1.1.1.11  root     2848:              }
1.1       root     2849:            value = ASSIGN; goto done;
                   2850:          }
                   2851:        else if (c == c1)
                   2852:          switch (c)
                   2853:            {
                   2854:            case '+':
                   2855:              value = PLUSPLUS; goto done;
                   2856:            case '-':
                   2857:              value = MINUSMINUS; goto done;
                   2858:            case '&':
                   2859:              value = ANDAND; goto done;
                   2860:            case '|':
                   2861:              value = OROR; goto done;
                   2862:            case '<':
                   2863:              c = LSHIFT;
                   2864:              goto combine;
                   2865:            case '>':
                   2866:              c = RSHIFT;
                   2867:              goto combine;
                   2868:            }
                   2869:        else if ((c == '-') && (c1 == '>'))
                   2870:          { value = POINTSAT; goto done; }
                   2871:        ungetc (c1, finput);
                   2872:        token_buffer[1] = 0;
                   2873: 
                   2874:        if ((c == '<') || (c == '>'))
                   2875:          value = ARITHCOMPARE;
                   2876:        else value = c;
                   2877:        goto done;
                   2878:       }
                   2879: 
1.1.1.5   root     2880:     case 0:
                   2881:       /* Don't make yyparse think this is eof.  */
                   2882:       value = 1;
                   2883:       break;
                   2884: 
1.1       root     2885:     default:
                   2886:       value = c;
                   2887:     }
                   2888: 
                   2889: done:
                   2890: /*  yylloc.last_line = lineno; */
                   2891: 
                   2892:   return value;
                   2893: }

unix.superglobalmegacorp.com

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