home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / GCC 1.37.1r14 / usr / gcc-1.37.1r14 / (gcc-1.37.π) / c-parse.y < prev    next >
Encoding:
Text File  |  1993-07-01  |  82.8 KB  |  3,191 lines  |  [TEXT/KAHL]

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