OSDN Git Service

* Makefile.in (local-distclean): Also remove fastjar.
[pf3gnuchains/gcc-fork.git] / gcc / c-parse.in
index 2a9fd01..cf010e6 100644 (file)
@@ -1,5 +1,6 @@
 /* YACC parser for C syntax and for Objective C.  -*-c-*-
-   Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
+   1997, 1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* This file defines the grammar of C and that of Objective C.
    ifobjc ... end ifobjc  conditionals contain code for Objective C only.
@@ -24,52 +26,33 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    c-parse.y and into objc-parse.y.  */
 
 /* To whomever it may concern: I have heard that such a thing was once
-written by AT&T, but I have never seen it.  */
+   written by AT&T, but I have never seen it.  */
 
 ifobjc
-%expect 35
+%expect 74
 end ifobjc
 ifc
-%expect 23
-
-/* These are the 23 conflicts you should get in parse.output;
-   the state numbers may vary if minor changes in the grammar are made.
-
-State 42 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
-State 44 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 103 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 110 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
-State 111 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 115 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 132 contains 1 shift/reduce conflict.  (See comment at component_decl.)
-State 180 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTE.)
-State 194 contains 2 shift/reduce conflict.  (Four ways to parse this.)
-State 202 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 214 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 220 contains 1 shift/reduce conflict.  (Two ways to recover from error.)
-State 304 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
-State 335 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
-State 347 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTES.)
-State 352 contains 1 shift/reduce conflict.  (Two ways to parse ATTRIBUTES.)
-State 383 contains 2 shift/reduce conflicts.  (Four ways to parse this.)
-State 434 contains 2 shift/reduce conflicts.  (Four ways to parse this.)  */
-
+%expect 53
 end ifc
 
 %{
-#include <stdio.h>
-#include <errno.h>
-#include <setjmp.h>
-
 #include "config.h"
+#include "system.h"
+#include <setjmp.h>
 #include "tree.h"
 #include "input.h"
+#include "cpplib.h"
+#include "intl.h"
+#include "timevar.h"
 #include "c-lex.h"
 #include "c-tree.h"
+#include "c-pragma.h"
 #include "flags.h"
-
+#include "output.h"
+#include "toplev.h"
+#include "ggc.h"
+  
 #ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
 #include <locale.h>
 #endif
 
@@ -80,29 +63,26 @@ end ifobjc
 /* Since parsers are distinct for each language, put the language string
    definition here.  */
 ifobjc
-char *language_string = "GNU Obj-C";
+const char * const language_string = "GNU Objective-C";
 end ifobjc
 ifc
-char *language_string = "GNU C";
+const char * const language_string = "GNU C";
 end ifc
 
-#ifndef errno
-extern int errno;
-#endif
-
-void yyerror ();
-
 /* Like YYERROR but do call yyerror.  */
 #define YYERROR1 { yyerror ("syntax error"); YYERROR; }
 
-/* Cause the `yydebug' variable to be defined.  */
+/* Cause the "yydebug" variable to be defined.  */
 #define YYDEBUG 1
+
+/* Rename the "yyparse" function so that we can override it elsewhere.  */
+#define yyparse yyparse_1
 %}
 
 %start program
 
 %union {long itype; tree ttype; enum tree_code code;
-       char *filename; int lineno; }
+       const char *filename; int lineno; }
 
 /* All identifiers that are not reserved words
    and are not declared typedefs in the current block */
@@ -121,7 +101,7 @@ void yyerror ();
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
 %token TYPESPEC
 
-/* Reserved words that qualify type: "const" or "volatile".
+/* Reserved words that qualify type: "const", "volatile", or "restrict".
    yylval contains an IDENTIFIER_NODE which indicates which one.  */
 %token TYPE_QUAL
 
@@ -141,7 +121,8 @@ void yyerror ();
 %token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
 %token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
 %token ATTRIBUTE EXTENSION LABEL
-%token REALPART IMAGPART
+%token REALPART IMAGPART VA_ARG
+%token PTR_VALUE PTR_BASE PTR_EXTENT
 
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc IF
@@ -173,26 +154,32 @@ void yyerror ();
 %token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
 
 /* Objective-C string constants in raw form.
-   yylval is an OBJC_STRING_CST node.  */
+   yylval is an STRING_CST node.  */
 %token OBJC_STRING
 
 
 %type <code> unop
+%type <ttype> ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
+%type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
 
 %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
 %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
 %type <ttype> typed_declspecs reserved_declspecs
 %type <ttype> typed_typespecs reserved_typespecquals
 %type <ttype> declmods typespec typespecqual_reserved
+%type <ttype> typed_declspecs_no_prefix_attr reserved_declspecs_no_prefix_attr
+%type <ttype> declmods_no_prefix_attr
 %type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
 %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
 %type <ttype> init maybeasm
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attributes attribute attribute_list attrib
-%type <ttype> any_word
+%type <ttype> any_word extension
 
-%type <ttype> compstmt
+%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
+%type <ttype> do_stmt_start poplevel
 
+%type <ttype> c99_block_start c99_block_end
 %type <ttype> declarator
 %type <ttype> notype_declarator after_type_declarator
 %type <ttype> parm_declarator
@@ -200,6 +187,7 @@ void yyerror ();
 %type <ttype> structsp component_decl_list component_decl_list2
 %type <ttype> component_decl components component_declarator
 %type <ttype> enumlist enumerator
+%type <ttype> struct_head union_head enum_head
 %type <ttype> typename absdcl absdcl1 type_quals
 %type <ttype> xexpr parms parm identifiers
 
@@ -221,28 +209,39 @@ ifobjc
 %type <ttype> keywordexpr keywordarglist keywordarg
 %type <ttype> myparms myparm optparmlist reservedwords objcselectorexpr
 %type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
-%type <ttype> objc_string protocolrefs identifier_list objcprotocolexpr
+%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
+
 %type <ttype> CLASSNAME OBJC_STRING OBJECTNAME
 end ifobjc
 \f
 %{
-/* Number of statements (loosely speaking) seen so far.  */
+/* Number of statements (loosely speaking) and compound statements 
+   seen so far.  */
 static int stmt_count;
-
+static int compstmt_count;
+  
 /* Input file and line number of the end of the body of last simple_if;
    used by the stmt-rule immediately after simple_if returns.  */
-static char *if_stmt_file;
+static const char *if_stmt_file;
 static int if_stmt_line;
 
 /* List of types and structure classes of the current declaration.  */
-static tree current_declspecs;
+static tree current_declspecs = NULL_TREE;
 static tree prefix_attributes = NULL_TREE;
 
 /* Stack of saved values of current_declspecs and prefix_attributes.  */
 static tree declspec_stack;
 
-/* 1 if we explained undeclared var errors.  */
-static int undeclared_variable_notice;
+/* For __extension__, save/restore the warning flags which are
+   controlled by __extension__.  */
+#define SAVE_WARN_FLAGS()      \
+       size_int (pedantic | (warn_pointer_arith << 1))
+#define RESTORE_WARN_FLAGS(tval) \
+  do {                                     \
+    int val = tree_low_cst (tval, 0);      \
+    pedantic = val & 1;                    \
+    warn_pointer_arith = (val >> 1) & 1;   \
+  } while (0)
 
 ifobjc
 /* Objective-C specific information */
@@ -261,13 +260,35 @@ end ifobjc
 /* Tell yyparse how to print a token's value, if yydebug is set.  */
 
 #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
-extern void yyprint ();
+
+static void yyprint      PARAMS ((FILE *, int, YYSTYPE));
+static void yyerror      PARAMS ((const char *));
+static inline int _yylex  PARAMS ((void));
+static int  yylex        PARAMS ((void));
+static void init_reswords PARAMS ((void));
+
+/* Add GC roots for variables local to this file.  */
+void
+c_parse_init ()
+{
+  ggc_add_tree_root (&declspec_stack, 1);
+  ggc_add_tree_root (&current_declspecs, 1);
+  ggc_add_tree_root (&prefix_attributes, 1);
+ifobjc
+  ggc_add_tree_root (&objc_interface_context, 1);
+  ggc_add_tree_root (&objc_implementation_context, 1);
+  ggc_add_tree_root (&objc_method_context, 1);
+  ggc_add_tree_root (&objc_ivar_chain, 1);
+  ggc_add_tree_root (&objc_ivar_context, 1);
+end ifobjc
+}
+
 %}
 \f
 %%
 program: /* empty */
                { if (pedantic)
-                   pedwarn ("ANSI C forbids an empty source file");
+                   pedwarn ("ISO C forbids an empty source file");
                  finish_file ();
                }
        | extdefs
@@ -286,7 +307,7 @@ program: /* empty */
 
 extdefs:
        {$<ttype>$ = NULL_TREE; } extdef
-       | extdefs {$<ttype>$ = NULL_TREE; } extdef
+       | extdefs {$<ttype>$ = NULL_TREE; ggc_collect(); } extdef
        ;
 
 extdef:
@@ -303,18 +324,28 @@ end ifobjc
                    assemble_asm ($3);
                  else
                    error ("argument of `asm' is not a constant string"); }
+       | extension extdef
+               { RESTORE_WARN_FLAGS ($1); }
        ;
 
 datadef:
          setspecs notype_initdecls ';'
                { if (pedantic)
-                   error ("ANSI C forbids data definition with no type or storage class");
+                   error ("ISO C forbids data definition with no type or storage class");
                  else if (!flag_traditional)
-                   warning ("data definition has no type or storage class"); }
+                   warning ("data definition has no type or storage class"); 
+
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
         | declmods setspecs notype_initdecls ';'
-         {}
+               { current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs initdecls ';'
-         {}
+               { current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
         | declmods ';'
          { pedwarn ("empty declaration"); }
        | typed_declspecs ';'
@@ -323,40 +354,58 @@ datadef:
        | error '}'
        | ';'
                { if (pedantic)
-                   pedwarn ("ANSI C does not allow extra `;' outside of a function"); }
+                   pedwarn ("ISO C does not allow extra `;' outside of a function"); }
        ;
 \f
 fndef:
          typed_declspecs setspecs declarator
-               { if (! start_function ($1, $3, prefix_attributes, 0))
+               { if (! start_function (current_declspecs, $3,
+                                       prefix_attributes, NULL_TREE))
                    YYERROR1;
-                 reinit_parse_for_function (); }
-         xdecls
+               }
+         old_style_parm_decls
                { store_parm_decls (); }
          compstmt_or_error
-               { finish_function (0); }
+               { finish_function (0); 
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs declarator error
-               { }
+               { current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_declarator
-               { if (! start_function ($1, $3, prefix_attributes, 0))
+               { if (! start_function (current_declspecs, $3,
+                                       prefix_attributes, NULL_TREE))
                    YYERROR1;
-                 reinit_parse_for_function (); }
-         xdecls
+               }
+         old_style_parm_decls
                { store_parm_decls (); }
          compstmt_or_error
-               { finish_function (0); }
+               { finish_function (0); 
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_declarator error
-               { }
+               { current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | setspecs notype_declarator
-               { if (! start_function (NULL_TREE, $2, prefix_attributes, 0))
+               { if (! start_function (NULL_TREE, $2,
+                                       prefix_attributes, NULL_TREE))
                    YYERROR1;
-                 reinit_parse_for_function (); }
-         xdecls
+               }
+         old_style_parm_decls
                { store_parm_decls (); }
          compstmt_or_error
-               { finish_function (0); }
+               { finish_function (0); 
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | setspecs notype_declarator error
-               { }
+               { current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        ;
 
 identifier:
@@ -373,7 +422,12 @@ unop:     '&'
        | '-'
                { $$ = NEGATE_EXPR; }
        | '+'
-               { $$ = CONVERT_EXPR; }
+               { $$ = CONVERT_EXPR;
+ifc
+  if (warn_traditional && !in_system_header)
+    warning ("traditional C rejects the unary plus operator");
+end ifc
+               }
        | PLUSPLUS
                { $$ = PREINCREMENT_EXPR; }
        | MINUSMINUS
@@ -406,12 +460,9 @@ unary_expr:
        | '*' cast_expr   %prec UNARY
                { $$ = build_indirect_ref ($2, "unary *"); }
        /* __extension__ turns off -pedantic for following primary.  */
-       | EXTENSION
-               { $<itype>1 = pedantic;
-                 pedantic = 0; }
-         cast_expr       %prec UNARY
-               { $$ = $3;
-                 pedantic = $<itype>1; }
+       | extension cast_expr     %prec UNARY
+               { $$ = $2;
+                 RESTORE_WARN_FLAGS ($1); }
        | unop cast_expr  %prec UNARY
                { $$ = build_unary_op ($1, $2, 0);
                  overflow_warning ($$); }
@@ -419,7 +470,7 @@ unary_expr:
        | ANDAND identifier
                { tree label = lookup_label ($2);
                  if (pedantic)
-                   pedwarn ("ANSI C forbids `&&'");
+                   pedwarn ("ISO C forbids `&&'");
                  if (label == 0)
                    $$ = null_pointer_node;
                  else
@@ -439,45 +490,64 @@ unary_expr:
                  else
                    {
                      if (pedantic)
-                       pedwarn ("ANSI C forbids `&...'");
+                       pedwarn ("ISO C forbids `&...'");
                      $$ = tree_last (DECL_ARGUMENTS (current_function_decl));
                      $$ = build_unary_op (ADDR_EXPR, $$, 0);
                    } }
 */
-       | SIZEOF unary_expr  %prec UNARY
-               { if (TREE_CODE ($2) == COMPONENT_REF
-                     && DECL_BIT_FIELD (TREE_OPERAND ($2, 1)))
+       | sizeof unary_expr  %prec UNARY
+               { skip_evaluation--;
+                 if (TREE_CODE ($2) == COMPONENT_REF
+                     && DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1)))
                    error ("`sizeof' applied to a bit-field");
                  $$ = c_sizeof (TREE_TYPE ($2)); }
-       | SIZEOF '(' typename ')'  %prec HYPERUNARY
-               { $$ = c_sizeof (groktypename ($3)); }
-       | ALIGNOF unary_expr  %prec UNARY
-               { $$ = c_alignof_expr ($2); }
-       | ALIGNOF '(' typename ')'  %prec HYPERUNARY
-               { $$ = c_alignof (groktypename ($3)); }
+       | sizeof '(' typename ')'  %prec HYPERUNARY
+               { skip_evaluation--;
+                 $$ = c_sizeof (groktypename ($3)); }
+       | alignof unary_expr  %prec UNARY
+               { skip_evaluation--;
+                 $$ = c_alignof_expr ($2); }
+       | alignof '(' typename ')'  %prec HYPERUNARY
+               { skip_evaluation--;
+                 $$ = c_alignof (groktypename ($3)); }
        | REALPART cast_expr %prec UNARY
                { $$ = build_unary_op (REALPART_EXPR, $2, 0); }
        | IMAGPART cast_expr %prec UNARY
                { $$ = build_unary_op (IMAGPART_EXPR, $2, 0); }
        ;
 
+sizeof:
+       SIZEOF { skip_evaluation++; }
+       ;
+
+alignof:
+       ALIGNOF { skip_evaluation++; }
+       ;
+
 cast_expr:
        unary_expr
        | '(' typename ')' cast_expr  %prec UNARY
-               { tree type = groktypename ($2);
+               { tree type;
+                 int SAVED_warn_strict_prototypes = warn_strict_prototypes;
+                 /* This avoids warnings about unprototyped casts on
+                     integers.  E.g. "#define SIG_DFL (void(*)())0".  */
+                 if (TREE_CODE ($4) == INTEGER_CST)
+                   warn_strict_prototypes = 0;
+                 type = groktypename ($2);
+                 warn_strict_prototypes = SAVED_warn_strict_prototypes;
                  $$ = build_c_cast (type, $4); }
        | '(' typename ')' '{' 
                { start_init (NULL_TREE, NULL, 0);
                  $2 = groktypename ($2);
                  really_start_incremental_init ($2); }
          initlist_maybe_comma '}'  %prec UNARY
-               { char *name;
+               { const char *name;
                  tree result = pop_init_level (0);
                  tree type = $2;
                  finish_init ();
 
-                 if (pedantic)
-                   pedwarn ("ANSI C forbids constructor expressions");
+                 if (pedantic && ! flag_isoc99)
+                   pedwarn ("ISO C89 forbids constructor expressions");
                  if (TYPE_NAME (type) != 0)
                    {
                      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
@@ -488,7 +558,7 @@ cast_expr:
                  else
                    name = "";
                  $$ = result;
-                 if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
+                 if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
                    {
                      int failure = complete_array_type (type, $$, 1);
                      if (failure)
@@ -523,188 +593,62 @@ expr_no_commas:
                { $$ = parser_build_binary_op ($2, $1, $3); }
        | expr_no_commas '^' expr_no_commas
                { $$ = parser_build_binary_op ($2, $1, $3); }
-       | expr_no_commas ANDAND expr_no_commas
-               { $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $3); }
-       | expr_no_commas OROR expr_no_commas
-               { $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $3); }
-       | expr_no_commas '?' xexpr ':' expr_no_commas
-               { $$ = build_conditional_expr ($1, $3, $5); }
+       | expr_no_commas ANDAND
+               { $1 = truthvalue_conversion (default_conversion ($1));
+                 skip_evaluation += $1 == boolean_false_node; }
+         expr_no_commas
+               { skip_evaluation -= $1 == boolean_false_node;
+                 $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
+       | expr_no_commas OROR
+               { $1 = truthvalue_conversion (default_conversion ($1));
+                 skip_evaluation += $1 == boolean_true_node; }
+         expr_no_commas
+               { skip_evaluation -= $1 == boolean_true_node;
+                 $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
+       | expr_no_commas '?'
+               { $1 = truthvalue_conversion (default_conversion ($1));
+                 skip_evaluation += $1 == boolean_false_node; }
+          expr ':'
+               { skip_evaluation += (($1 == boolean_true_node)
+                                     - ($1 == boolean_false_node)); }
+         expr_no_commas
+               { skip_evaluation -= $1 == boolean_true_node;
+                 $$ = build_conditional_expr ($1, $4, $7); }
+       | expr_no_commas '?'
+               { if (pedantic)
+                   pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
+                 /* Make sure first operand is calculated only once.  */
+                 $<ttype>2 = save_expr ($1);
+                 $1 = truthvalue_conversion (default_conversion ($<ttype>2));
+                 skip_evaluation += $1 == boolean_true_node; }
+         ':' expr_no_commas
+               { skip_evaluation -= $1 == boolean_true_node;
+                 $$ = build_conditional_expr ($1, $<ttype>2, $5); }
        | expr_no_commas '=' expr_no_commas
-               { $$ = build_modify_expr ($1, NOP_EXPR, $3);
-                 C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
+               { char class;
+                 $$ = build_modify_expr ($1, NOP_EXPR, $3);
+                 class = TREE_CODE_CLASS (TREE_CODE ($$));
+                 if (class == 'e' || class == '1'
+                     || class == '2' || class == '<')
+                   C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
+               }
        | expr_no_commas ASSIGN expr_no_commas
-               { $$ = build_modify_expr ($1, $2, $3);
+               { char class;
+                 $$ = build_modify_expr ($1, $2, $3);
                  /* This inhibits warnings in truthvalue_conversion.  */
-                 C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
+                 class = TREE_CODE_CLASS (TREE_CODE ($$));
+                 if (class == 'e' || class == '1'
+                     || class == '2' || class == '<')
+                   C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
+               }
        ;
 
 primary:
        IDENTIFIER
                {
-                 $$ = lastiddecl;
-                 if (!$$ || $$ == error_mark_node)
-                   {
-                     if (yychar == YYEMPTY)
-                       yychar = YYLEX;
-                     if (yychar == '(')
-                       {
-ifobjc
-                         tree decl;
-
-                         if (objc_receiver_context
-                             && ! (objc_receiver_context
-                                   && strcmp (IDENTIFIER_POINTER ($1), "super")))
-                           /* we have a message to super */
-                           $$ = get_super_receiver ();
-                         else if (objc_method_context
-                                  && (decl = is_ivar (objc_ivar_chain, $1)))
-                           {
-                             if (is_private (decl))
-                               $$ = error_mark_node;
-                             else
-                               $$ = build_ivar_reference ($1);
-                           }
-                         else
-end ifobjc
-                           {
-                             /* Ordinary implicit function declaration.  */
-                             $$ = implicitly_declare ($1);
-                             assemble_external ($$);
-                             TREE_USED ($$) = 1;
-                           }
-                       }
-                     else if (current_function_decl == 0)
-                       {
-                         error ("`%s' undeclared here (not in a function)",
-                                IDENTIFIER_POINTER ($1));
-                         $$ = error_mark_node;
-                       }
-                     else
-                       {
-ifobjc
-                         tree decl;
-
-                         if (objc_receiver_context
-                             && ! strcmp (IDENTIFIER_POINTER ($1), "super"))
-                           /* we have a message to super */
-                           $$ = get_super_receiver ();
-                         else if (objc_method_context
-                                  && (decl = is_ivar (objc_ivar_chain, $1)))
-                           {
-                             if (is_private (decl))
-                               $$ = error_mark_node;
-                             else
-                               $$ = build_ivar_reference ($1);
-                           }
-                         else
-end ifobjc
-                           {
-                             if (IDENTIFIER_GLOBAL_VALUE ($1) != error_mark_node
-                                 || IDENTIFIER_ERROR_LOCUS ($1) != current_function_decl)
-                               {
-                                 error ("`%s' undeclared (first use this function)",
-                                        IDENTIFIER_POINTER ($1));
-
-                                 if (! undeclared_variable_notice)
-                                   {
-                                     error ("(Each undeclared identifier is reported only once");
-                                     error ("for each function it appears in.)");
-                                     undeclared_variable_notice = 1;
-                                   }
-                               }
-                             $$ = error_mark_node;
-                             /* Prevent repeated error messages.  */
-                             IDENTIFIER_GLOBAL_VALUE ($1) = error_mark_node;
-                             IDENTIFIER_ERROR_LOCUS ($1) = current_function_decl;
-                           }
-                       }
-                   }
-                 else if (TREE_TYPE ($$) == error_mark_node)
-                   $$ = error_mark_node;
-                 else if (C_DECL_ANTICIPATED ($$))
-                   {
-                     /* The first time we see a build-in function used,
-                        if it has not been declared.  */
-                     C_DECL_ANTICIPATED ($$) = 0;
-                     if (yychar == YYEMPTY)
-                       yychar = YYLEX;
-                     if (yychar == '(')
-                       {
-                         /* Omit the implicit declaration we
-                            would ordinarily do, so we don't lose
-                            the actual built in type.
-                            But print a diagnostic for the mismatch.  */
-ifobjc
-                         if (objc_method_context
-                             && is_ivar (objc_ivar_chain, $1))
-                           error ("Instance variable `%s' implicitly declared as function",
-                                  IDENTIFIER_POINTER (DECL_NAME ($$)));
-                         else
-end ifobjc
-                           if (TREE_CODE ($$) != FUNCTION_DECL)
-                             error ("`%s' implicitly declared as function",
-                                    IDENTIFIER_POINTER (DECL_NAME ($$)));
-                         else if ((TYPE_MODE (TREE_TYPE (TREE_TYPE ($$)))
-                                   != TYPE_MODE (integer_type_node))
-                                  && (TREE_TYPE (TREE_TYPE ($$))
-                                      != void_type_node))
-                           pedwarn ("type mismatch in implicit declaration for built-in function `%s'",
-                                    IDENTIFIER_POINTER (DECL_NAME ($$)));
-                         /* If it really returns void, change that to int.  */
-                         if (TREE_TYPE (TREE_TYPE ($$)) == void_type_node)
-                           TREE_TYPE ($$)
-                             = build_function_type (integer_type_node,
-                                                    TYPE_ARG_TYPES (TREE_TYPE ($$)));
-                       }
-                     else
-                       pedwarn ("built-in function `%s' used without declaration",
-                                IDENTIFIER_POINTER (DECL_NAME ($$)));
-
-                     /* Do what we would ordinarily do when a fn is used.  */
-                     assemble_external ($$);
-                     TREE_USED ($$) = 1;
-                   }
-                 else
-                   {
-                     assemble_external ($$);
-                     TREE_USED ($$) = 1;
-ifobjc
-                     /* we have a definition - still check if iVariable */
-
-                     if (!objc_receiver_context
-                         || (objc_receiver_context
-                             && strcmp (IDENTIFIER_POINTER ($1), "super")))
-                        {
-                         tree decl;
-
-                         if (objc_method_context
-                             && (decl = is_ivar (objc_ivar_chain, $1)))
-                            {
-                              if (IDENTIFIER_LOCAL_VALUE ($1))
-                                warning ("local declaration of `%s' hides instance variable",
-                                        IDENTIFIER_POINTER ($1));
-                              else
-                               {
-                                 if (is_private (decl))
-                                   $$ = error_mark_node;
-                                 else
-                                   $$ = build_ivar_reference ($1);
-                               }
-                            }
-                       }
-                      else /* we have a message to super */
-                       $$ = get_super_receiver ();
-end ifobjc
-                   }
-
-                 if (TREE_CODE ($$) == CONST_DECL)
-                   {
-                     $$ = DECL_INITIAL ($$);
-                     /* This is to prevent an enum whose value is 0
-                        from being considered a null pointer constant.  */
-                     $$ = build1 (NOP_EXPR, TREE_TYPE ($$), $$);
-                     TREE_CONSTANT ($$) = 1;
-                   }
+                 if (yychar == YYEMPTY)
+                   yychar = YYLEX;
+                 $$ = build_external_ref ($1, yychar == '(');
                }
        | CONSTANT
        | string
@@ -717,45 +661,33 @@ end ifobjc
                  $$ = $2; }
        | '(' error ')'
                { $$ = error_mark_node; }
-       | '('
-               { if (current_function_decl == 0)
-                   {
-                     error ("braced-group within expression allowed only inside a function");
-                     YYERROR;
-                   }
-                 /* We must force a BLOCK for this level
-                    so that, if it is not expanded later,
-                    there is a way to turn off the entire subtree of blocks
-                    that are contained in it.  */
-                 keep_next_level ();
-                 push_iterator_stack ();
-                 push_label_level ();
-                 $<ttype>$ = expand_start_stmt_expr (); }
-         compstmt ')'
-               { tree rtl_exp;
-                 if (pedantic)
-                   pedwarn ("ANSI C forbids braced-groups within expressions");
-                 pop_iterator_stack ();
+       | compstmt_primary_start compstmt_nostart ')'
+                 { tree saved_last_tree;
+
+                  if (pedantic)
+                    pedwarn ("ISO C forbids braced-groups within expressions");
                  pop_label_level ();
-                 rtl_exp = expand_end_stmt_expr ($<ttype>2);
-                 /* The statements have side effects, so the group does.  */
-                 TREE_SIDE_EFFECTS (rtl_exp) = 1;
 
-                 if (TREE_CODE ($3) == BLOCK)
-                   {
-                     /* Make a BIND_EXPR for the BLOCK already made.  */
-                     $$ = build (BIND_EXPR, TREE_TYPE (rtl_exp),
-                                 NULL_TREE, rtl_exp, $3);
-                     /* Remove the block from the tree at this point.
-                        It gets put back at the proper place
-                        when the BIND_EXPR is expanded.  */
-                     delete_block ($3);
-                   }
-                 else
-                   $$ = $3;
+                 saved_last_tree = COMPOUND_BODY ($1);
+                 RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
+                 last_tree = saved_last_tree;
+                 TREE_CHAIN (last_tree) = NULL_TREE;
+                 if (!last_expr_type)
+                   last_expr_type = void_type_node;
+                 $$ = build1 (STMT_EXPR, last_expr_type, $1);
+                 TREE_SIDE_EFFECTS ($$) = 1;
+               }
+       | compstmt_primary_start error ')'
+               {
+                 pop_label_level ();
+                 last_tree = COMPOUND_BODY ($1);
+                 TREE_CHAIN (last_tree) = NULL_TREE;
+                 $$ = error_mark_node;
                }
        | primary '(' exprlist ')'   %prec '.'
                { $$ = build_function_call ($1, $3); }
+       | VA_ARG '(' expr_no_commas ',' typename ')'
+               { $$ = build_va_arg ($3, groktypename ($5)); }
        | primary '[' expr ']'   %prec '.'
                { $$ = build_array_ref ($1, $3); }
        | primary '.' identifier
@@ -810,12 +742,28 @@ end ifobjc
 string:
          STRING
        | string STRING
-               { $$ = chainon ($1, $2); }
+               {
+ifc
+                  static int last_lineno = 0;
+                  static const char *last_input_filename = 0;
+end ifc
+                  $$ = chainon ($1, $2);
+ifc
+                 if (warn_traditional && !in_system_header
+                     && (lineno != last_lineno || !last_input_filename ||
+                         strcmp (last_input_filename, input_filename)))
+                   {
+                     warning ("traditional C rejects string concatenation");
+                     last_lineno = lineno;
+                     last_input_filename = input_filename;
+                   }
+end ifc
+               }
        ;
 
 ifobjc
-/* Produces an OBJC_STRING_CST with prehaps more OBJC_STRING_CSTs chained
-   onto it.  */
+/* Produces an STRING_CST with perhaps more STRING_CSTs chained
+   onto it, which is to be read as an ObjC string object.  */
 objc_string:
          OBJC_STRING
        | objc_string OBJC_STRING
@@ -823,14 +771,14 @@ objc_string:
        ;
 end ifobjc
 
-xdecls:
+old_style_parm_decls:
        /* empty */
        | datadecls
        | datadecls ELLIPSIS
                /* ... is used here to indicate a varargs function.  */
                { c_mark_varargs ();
                  if (pedantic)
-                   pedwarn ("ANSI C does not permit use of `varargs.h'"); }
+                   pedwarn ("ISO C does not permit use of `varargs.h'"); }
        ;
 
 /* The following are analogous to lineno_decl, decls and decl
@@ -848,21 +796,23 @@ datadecls:
        | lineno_datadecl errstmt
        ;
 
+/* We don't allow prefix attributes here because they cause reduce/reduce
+   conflicts: we can't know whether we're parsing a function decl with
+   attribute suffix, or function defn with attribute prefix on first old
+   style parm.  */
 datadecl:
-       typed_declspecs setspecs initdecls ';'
+       typed_declspecs_no_prefix_attr setspecs initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
-       | declmods setspecs notype_initdecls ';'
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | declmods_no_prefix_attr setspecs notype_initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);      
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
-       | typed_declspecs ';'
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | typed_declspecs_no_prefix_attr ';'
                { shadow_tag_warned ($1, 1);
                  pedwarn ("empty declaration"); }
-       | declmods ';'
+       | declmods_no_prefix_attr ';'
                { pedwarn ("empty declaration"); }
        ;
 
@@ -875,27 +825,20 @@ lineno_decl:
                { }
        ;
 
-decls:
-       lineno_decl
-       | errstmt
-       | decls lineno_decl
-       | lineno_decl errstmt
-       ;
-
 /* records the type and storage class specs to use for processing
    the declarators that follow.
    Maintains a stack of outer-level values of current_declspecs,
    for the sake of parm declarations nested in function declarators.  */
 setspecs: /* empty */
-               { $$ = suspend_momentary ();
-                 pending_xref_error ();
+               { pending_xref_error ();
                  declspec_stack = tree_cons (prefix_attributes,
                                              current_declspecs,
                                              declspec_stack);
-                 current_declspecs = $<ttype>0; 
-                 prefix_attributes = NULL_TREE; }
+                 split_specs_attrs ($<ttype>0,
+                                    &current_declspecs, &prefix_attributes); }
        ;
 
+/* ??? Yuck.  See after_type_declarator.  */
 setattrs: /* empty */
                { prefix_attributes = chainon (prefix_attributes, $<ttype>0); }
        ;
@@ -904,32 +847,31 @@ decl:
        typed_declspecs setspecs initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_initdecls ';'
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs setspecs nested_function
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | declmods setspecs notype_nested_function
                { current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs ';'
                { shadow_tag ($1); }
        | declmods ';'
                { pedwarn ("empty declaration"); }
+       | extension decl
+               { RESTORE_WARN_FLAGS ($1); }
        ;
 
 /* Declspecs which contain at least one type specifier or typedef name.
    (Just `const' or `volatile' is not enough.)
-   A typedef'd name following these is taken as a name to be declared.  */
+   A typedef'd name following these is taken as a name to be declared.
+   Declspecs have a non-NULL TREE_VALUE, attributes do not.  */
 
 typed_declspecs:
          typespec reserved_declspecs
@@ -947,22 +889,55 @@ reserved_declspecs:  /* empty */
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
                  $$ = tree_cons (NULL_TREE, $2, $1); }
+       | reserved_declspecs attributes
+               { $$ = tree_cons ($2, NULL_TREE, $1); }
        ;
 
-/* List of just storage classes and type modifiers.
+typed_declspecs_no_prefix_attr:
+         typespec reserved_declspecs_no_prefix_attr
+               { $$ = tree_cons (NULL_TREE, $1, $2); }
+       | declmods_no_prefix_attr typespec reserved_declspecs_no_prefix_attr
+               { $$ = chainon ($3, tree_cons (NULL_TREE, $2, $1)); }
+       ;
+
+reserved_declspecs_no_prefix_attr:
+         /* empty */
+               { $$ = NULL_TREE; }
+       | reserved_declspecs_no_prefix_attr typespecqual_reserved
+               { $$ = tree_cons (NULL_TREE, $2, $1); }
+       | reserved_declspecs_no_prefix_attr SCSPEC
+               { if (extra_warnings)
+                   warning ("`%s' is not at beginning of declaration",
+                            IDENTIFIER_POINTER ($2));
+                 $$ = tree_cons (NULL_TREE, $2, $1); }
+       ;
+
+/* List of just storage classes, type modifiers, and prefix attributes.
    A declaration can start with just this, but then it cannot be used
-   to redeclare a typedef-name.  */
+   to redeclare a typedef-name.
+   Declspecs have a non-NULL TREE_VALUE, attributes do not.  */
 
 declmods:
+         declmods_no_prefix_attr
+               { $$ = $1; }
+       | attributes
+               { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
+       | declmods declmods_no_prefix_attr
+               { $$ = chainon ($2, $1); }
+       | declmods attributes
+               { $$ = tree_cons ($2, NULL_TREE, $1); }
+       ;
+
+declmods_no_prefix_attr:
          TYPE_QUAL
                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
                  TREE_STATIC ($$) = 1; }
        | SCSPEC
                { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
-       | declmods TYPE_QUAL
+       | declmods_no_prefix_attr TYPE_QUAL
                { $$ = tree_cons (NULL_TREE, $2, $1);
                  TREE_STATIC ($$) = 1; }
-       | declmods SCSPEC
+       | declmods_no_prefix_attr SCSPEC
                { if (extra_warnings && TREE_STATIC ($1))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
@@ -1003,6 +978,11 @@ ifobjc
                { $$ = get_static_reference ($1, $2); }
        | OBJECTNAME protocolrefs
                { $$ = get_object_reference ($2); }
+
+/* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>"
+   - nisse@lysator.liu.se */
+        | non_empty_protocolrefs
+                { $$ = get_object_reference ($1); }
 end ifobjc
        | TYPEOF '(' expr ')'
                { $$ = TREE_TYPE ($3); }
@@ -1038,24 +1018,24 @@ maybeasm:
 
 initdcl:
          declarator maybeasm maybe_attribute '='
-               { $<ttype>$ = start_decl ($1, current_declspecs, 1);
-                 decl_attributes ($<ttype>$, $3, prefix_attributes);
+               { $<ttype>$ = start_decl ($1, current_declspecs, 1,
+                                         $3, prefix_attributes);
                  start_init ($<ttype>$, $2, global_bindings_p ()); }
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
                { finish_init ();
                  finish_decl ($<ttype>5, $6, $2); }
        | declarator maybeasm maybe_attribute
-               { tree d = start_decl ($1, current_declspecs, 0);
-                 decl_attributes (d, $3, prefix_attributes);
+               { tree d = start_decl ($1, current_declspecs, 0,
+                                      $3, prefix_attributes);
                  finish_decl (d, NULL_TREE, $2); 
                 }
        ;
 
 notype_initdcl:
          notype_declarator maybeasm maybe_attribute '='
-               { $<ttype>$ = start_decl ($1, current_declspecs, 1);
-                 decl_attributes ($<ttype>$, $3, prefix_attributes);
+               { $<ttype>$ = start_decl ($1, current_declspecs, 1,
+                                         $3, prefix_attributes);
                  start_init ($<ttype>$, $2, global_bindings_p ()); }
          init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
@@ -1063,8 +1043,8 @@ notype_initdcl:
                  decl_attributes ($<ttype>5, $3, prefix_attributes);
                  finish_decl ($<ttype>5, $6, $2); }
        | notype_declarator maybeasm maybe_attribute
-               { tree d = start_decl ($1, current_declspecs, 0);
-                 decl_attributes (d, $3, prefix_attributes);
+               { tree d = start_decl ($1, current_declspecs, 0,
+                                      $3, prefix_attributes);
                  finish_decl (d, NULL_TREE, $2); }
        ;
 /* the * rules are dummies to accept the Apollo extended syntax
@@ -1090,24 +1070,22 @@ attribute:
 
 attribute_list:
       attrib
-               { $$ = build_tree_list (NULL_TREE, $1); }
+               { $$ = $1; }
        | attribute_list ',' attrib
-               { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
+               { $$ = chainon ($1, $3); }
        ;
  
 attrib:
     /* empty */
                { $$ = NULL_TREE; }
        | any_word
-               { $$ = $1; }
+               { $$ = build_tree_list ($1, NULL_TREE); }
        | any_word '(' IDENTIFIER ')'
-               { $$ = tree_cons ($1, NULL_TREE,
-                                 build_tree_list (NULL_TREE, $3)); }
+               { $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); }
        | any_word '(' IDENTIFIER ',' nonnull_exprlist ')'
-               { $$ = tree_cons ($1, NULL_TREE,
-                                 tree_cons (NULL_TREE, $3, $5)); }
-       | any_word '(' nonnull_exprlist ')'
-               { $$ = tree_cons ($1, NULL_TREE, $3); }
+               { $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); }
+       | any_word '(' exprlist ')'
+               { $$ = build_tree_list ($1, $3); }
        ;
 
 /* This still leaves out most reserved keywords,
@@ -1125,18 +1103,9 @@ any_word:
 init:
        expr_no_commas
        | '{'
-               { really_start_incremental_init (NULL_TREE);
-                 /* Note that the call to clear_momentary
-                    is in process_init_element.  */
-                 push_momentary (); }
+               { really_start_incremental_init (NULL_TREE); }
          initlist_maybe_comma '}'
-               { $$ = pop_init_level (0);
-                 if ($$ == error_mark_node
-                     && ! (yychar == STRING || yychar == CONSTANT))
-                   pop_momentary ();
-                 else
-                   pop_momentary_nofree (); }
-
+               { $$ = pop_init_level (0); }
        | error
                { $$ = error_mark_node; }
        ;
@@ -1145,7 +1114,7 @@ init:
 initlist_maybe_comma:
          /* empty */
                { if (pedantic)
-                   pedwarn ("ANSI C forbids empty initializer braces"); }
+                   pedwarn ("ISO C forbids empty initializer braces"); }
        | initlist1 maybecomma
        ;
 
@@ -1157,46 +1126,66 @@ initlist1:
 /* `initelt' is a single element of an initializer.
    It may use braces.  */
 initelt:
-       expr_no_commas
-               { process_init_element ($1); }
-       | '{' 
+         designator_list '=' initval
+               { if (pedantic && ! flag_isoc99)
+                   pedwarn ("ISO C89 forbids specifying subobject to initialize"); }
+       | designator initval
+               { if (pedantic)
+                   pedwarn ("obsolete use of designated initializer without `='"); }
+       | identifier ':'
+               { set_init_label ($1);
+                 if (pedantic)
+                   pedwarn ("obsolete use of designated initializer with `:'"); }
+         initval
+       | initval
+       ;
+
+initval:
+         '{'
                { push_init_level (0); }
          initlist_maybe_comma '}'
                { process_init_element (pop_init_level (0)); }
+       | expr_no_commas
+               { process_init_element ($1); }
        | error
+       ;
+
+designator_list:
+         designator
+       | designator_list designator
+       ;
+
+designator:
+         '.' identifier
+               { set_init_label ($2); }
        /* These are for labeled elements.  The syntax for an array element
           initializer conflicts with the syntax for an Objective-C message,
-          so don't include these productions in the Objective-C grammer.  */
+          so don't include these productions in the Objective-C grammar.  */
 ifc
-       | '[' expr_no_commas ELLIPSIS expr_no_commas ']' '='
-               { set_init_index ($2, $4); }
-         initelt
-       | '[' expr_no_commas ']' '='
-               { set_init_index ($2, NULL_TREE); }
-         initelt
+       | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
+               { set_init_index ($2, $4);
+                 if (pedantic)
+                   pedwarn ("ISO C forbids specifying range of elements to initialize"); }
        | '[' expr_no_commas ']'
                { set_init_index ($2, NULL_TREE); }
-         initelt
 end ifc
-       | identifier ':'
-               { set_init_label ($1); }
-         initelt
-       | '.' identifier '='
-               { set_init_label ($2); }
-         initelt
        ;
 \f
 nested_function:
          declarator
-               { push_c_function_context ();
+               { if (pedantic)
+                   pedwarn ("ISO C forbids nested functions");
+
+                 push_function_context ();
                  if (! start_function (current_declspecs, $1,
-                                       prefix_attributes, 1))
+                                       prefix_attributes, NULL_TREE))
                    {
-                     pop_c_function_context ();
+                     pop_function_context ();
                      YYERROR1;
                    }
-                 reinit_parse_for_function ();
-                 store_parm_decls (); }
+               }
+          old_style_parm_decls
+               { store_parm_decls (); }
 /* This used to use compstmt_or_error.
    That caused a bug with input `f(g) int g {}',
    where the use of YYERROR1 above caused an error
@@ -1204,21 +1193,27 @@ nested_function:
    There followed a repeated execution of that same rule,
    which called YYERROR1 again, and so on.  */
          compstmt
-               { finish_function (1);
-                 pop_c_function_context (); }
+               { tree decl = current_function_decl;
+                 finish_function (1);
+                 pop_function_context (); 
+                 add_decl_stmt (decl); }
        ;
 
 notype_nested_function:
          notype_declarator
-               { push_c_function_context ();
+               { if (pedantic)
+                   pedwarn ("ISO C forbids nested functions");
+
+                 push_function_context ();
                  if (! start_function (current_declspecs, $1,
-                                       prefix_attributes, 1))
+                                       prefix_attributes, NULL_TREE))
                    {
-                     pop_c_function_context ();
+                     pop_function_context ();
                      YYERROR1;
                    }
-                 reinit_parse_for_function ();
-                 store_parm_decls (); }
+               }
+         old_style_parm_decls
+               { store_parm_decls (); }
 /* This used to use compstmt_or_error.
    That caused a bug with input `f(g) int g {}',
    where the use of YYERROR1 above caused an error
@@ -1226,8 +1221,10 @@ notype_nested_function:
    There followed a repeated execution of that same rule,
    which called YYERROR1 again, and so on.  */
          compstmt
-               { finish_function (1);
-                 pop_c_function_context (); }
+               { tree decl = current_function_decl;
+                 finish_function (1);
+                 pop_function_context (); 
+                 add_decl_stmt (decl); }
        ;
 
 /* Any kind of declarator (thus, all declarators allowed
@@ -1254,6 +1251,11 @@ after_type_declarator:
                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
        | '*' type_quals after_type_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
+       /* ??? Yuck.  setattrs is a quick hack.  We can't use
+          prefix_attributes because $1 only applies to this
+          declarator.  We assume setspecs has already been done.
+          setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
+          attributes could be recognized here or in `attributes').  */
        | attributes setattrs after_type_declarator
                { $$ = $3; }
        | TYPENAME
@@ -1273,12 +1275,24 @@ parm_declarator:
 /*     | parm_declarator '(' error ')'  %prec '.'
                { $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
                  poplevel (0, 0, 0); }  */
+ifc
+       | parm_declarator '[' '*' ']'  %prec '.'
+               { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+                 if (! flag_isoc99)
+                   error ("`[*]' in parameter declaration only allowed in ISO C 99");
+               }
+end ifc
        | parm_declarator '[' expr ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, $1, $3); }
        | parm_declarator '[' ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
        | '*' type_quals parm_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
+       /* ??? Yuck.  setattrs is a quick hack.  We can't use
+          prefix_attributes because $1 only applies to this
+          declarator.  We assume setspecs has already been done.
+          setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
+          attributes could be recognized here or in `attributes').  */
        | attributes setattrs parm_declarator
                { $$ = $3; }
        | TYPENAME
@@ -1297,51 +1311,82 @@ notype_declarator:
                { $$ = $2; }
        | '*' type_quals notype_declarator  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
+ifc
+       | notype_declarator '[' '*' ']'  %prec '.'
+               { $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
+                 if (! flag_isoc99)
+                   error ("`[*]' in parameter declaration only allowed in ISO C 99");
+               }
+end ifc
        | notype_declarator '[' expr ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, $1, $3); }
        | notype_declarator '[' ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, $1, NULL_TREE); }
+       /* ??? Yuck.  setattrs is a quick hack.  We can't use
+          prefix_attributes because $1 only applies to this
+          declarator.  We assume setspecs has already been done.
+          setattrs also avoids 5 reduce/reduce conflicts (otherwise multiple
+          attributes could be recognized here or in `attributes').  */
        | attributes setattrs notype_declarator
                { $$ = $3; }
        | IDENTIFIER
        ;
 
+struct_head:
+         STRUCT
+               { $$ = NULL_TREE; }
+       | STRUCT attributes
+               { $$ = $2; }
+       ;
+
+union_head:
+         UNION
+               { $$ = NULL_TREE; }
+       | UNION attributes
+               { $$ = $2; }
+       ;
+
+enum_head:
+         ENUM
+               { $$ = NULL_TREE; }
+       | ENUM attributes
+               { $$ = $2; }
+       ;
+
 structsp:
-         STRUCT identifier '{'
+         struct_head identifier '{'
                { $$ = start_struct (RECORD_TYPE, $2);
                  /* Start scope of tag before parsing components.  */
                }
-         component_decl_list '}'
-               { $$ = finish_struct ($<ttype>4, $5);
-                 /* Really define the structure.  */
-               }
-       | STRUCT '{' component_decl_list '}'
+         component_decl_list '}' maybe_attribute 
+               { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+       | struct_head '{' component_decl_list '}' maybe_attribute
                { $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
-                                     $3); }
-       | STRUCT identifier
+                                     $3, chainon ($1, $5));
+               }
+       | struct_head identifier
                { $$ = xref_tag (RECORD_TYPE, $2); }
-       | UNION identifier '{'
+       | union_head identifier '{'
                { $$ = start_struct (UNION_TYPE, $2); }
-         component_decl_list '}'
-               { $$ = finish_struct ($<ttype>4, $5); }
-       | UNION '{' component_decl_list '}'
+         component_decl_list '}' maybe_attribute
+               { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+       | union_head '{' component_decl_list '}' maybe_attribute
                { $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
-                                     $3); }
-       | UNION identifier
+                                     $3, chainon ($1, $5));
+               }
+       | union_head identifier
                { $$ = xref_tag (UNION_TYPE, $2); }
-       | ENUM identifier '{'
-               { $<itype>3 = suspend_momentary ();
-                 $$ = start_enum ($2); }
-         enumlist maybecomma_warn '}'
-               { $$ = finish_enum ($<ttype>4, nreverse ($5));
-                 resume_momentary ($<itype>3); }
-       | ENUM '{'
-               { $<itype>2 = suspend_momentary ();
-                 $$ = start_enum (NULL_TREE); }
-         enumlist maybecomma_warn '}'
-               { $$ = finish_enum ($<ttype>3, nreverse ($4));
-                 resume_momentary ($<itype>2); }
-       | ENUM identifier
+       | enum_head identifier '{'
+               { $$ = start_enum ($2); }
+         enumlist maybecomma_warn '}' maybe_attribute
+               { $$ = finish_enum ($<ttype>4, nreverse ($5),
+                                   chainon ($1, $8)); }
+       | enum_head '{'
+               { $$ = start_enum (NULL_TREE); }
+         enumlist maybecomma_warn '}' maybe_attribute
+               { $$ = finish_enum ($<ttype>3, nreverse ($4),
+                                   chainon ($1, $7)); }
+       | enum_head identifier
                { $$ = xref_tag (ENUMERAL_TYPE, $2); }
        ;
 
@@ -1353,7 +1398,8 @@ maybecomma:
 maybecomma_warn:
          /* empty */
        | ','
-               { if (pedantic) pedwarn ("comma at end of enumerator list"); }
+               { if (pedantic && ! flag_isoc99)
+                   pedwarn ("comma at end of enumerator list"); }
        ;
 
 component_decl_list:
@@ -1403,26 +1449,35 @@ component_decl:
                { $$ = $3;
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | typed_typespecs setspecs save_filename save_lineno maybe_attribute
+               {
+                 /* Support for unnamed structs or unions as members of 
+                    structs or unions (which is [a] useful and [b] supports 
+                    MS P-SDK).  */
+                 if (pedantic)
+                   pedwarn ("ISO C doesn't support unnamed structs/unions");
+
+                 $$ = grokfield($3, $4, NULL, current_declspecs, NULL_TREE);
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
                  declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
-       | typed_typespecs
-               { if (pedantic)
-                   pedwarn ("ANSI C forbids member declarations with no members");
-                 shadow_tag($1);
-                 $$ = NULL_TREE; }
-       | nonempty_type_quals setspecs components
+               }
+    | nonempty_type_quals setspecs components
                { $$ = $3;
                  current_declspecs = TREE_VALUE (declspec_stack);
                  prefix_attributes = TREE_PURPOSE (declspec_stack);
-                 declspec_stack = TREE_CHAIN (declspec_stack);
-                 resume_momentary ($2); }
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | nonempty_type_quals
                { if (pedantic)
-                   pedwarn ("ANSI C forbids member declarations with no members");
+                   pedwarn ("ISO C forbids member declarations with no members");
                  shadow_tag($1);
                  $$ = NULL_TREE; }
        | error
                { $$ = NULL_TREE; }
+       | extension component_decl
+               { $$ = $2;
+                 RESTORE_WARN_FLAGS ($1); }
        ;
 
 components:
@@ -1452,7 +1507,10 @@ component_declarator:
 enumlist:
          enumerator
        | enumlist ',' enumerator
-               { $$ = chainon ($3, $1); }
+               { if ($1 == error_mark_node)
+                   $$ = $1;
+                 else
+                   $$ = chainon ($3, $1); }
        | error
                { $$ = error_mark_node; }
        ;
@@ -1512,34 +1570,72 @@ absdcl1:  /* a nonempty absolute declarator */
                { $$ = build_nt (ARRAY_REF, NULL_TREE, $2); }
        | '[' ']'  %prec '.'
                { $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
+       /* ??? It appears we have to support attributes here, however
+          using prefix_attributes is wrong.  */
        | attributes setattrs absdcl1
                { $$ = $3; }
        ;
 
-/* at least one statement, the first of which parses without error.  */
-/* stmts is used only after decls, so an invalid first statement
-   is actually regarded as an invalid decl and part of the decls.  */
+/* A nonempty series of declarations and statements (possibly followed by
+   some labels) that can form the body of a compound statement.
+   NOTE: we don't allow labels on declarations; this might seem like a
+   natural extension, but there would be a conflict between attributes
+   on the label and prefix attributes on the declaration.  */
+
+stmts_and_decls:
+         lineno_stmt_decl_or_labels_ending_stmt
+       | lineno_stmt_decl_or_labels_ending_decl
+       | lineno_stmt_decl_or_labels_ending_label
+               {
+                 pedwarn ("deprecated use of label at end of compound statement");
+               }
+       | lineno_stmt_decl_or_labels_ending_error
+       ;
+
+lineno_stmt_decl_or_labels_ending_stmt:
+         lineno_stmt
+       | lineno_stmt_decl_or_labels_ending_stmt lineno_stmt
+       | lineno_stmt_decl_or_labels_ending_decl lineno_stmt
+       | lineno_stmt_decl_or_labels_ending_label lineno_stmt
+       | lineno_stmt_decl_or_labels_ending_error lineno_stmt
+       ;
 
-stmts:
-         lineno_stmt_or_label
-       | stmts lineno_stmt_or_label
-       | stmts errstmt
+lineno_stmt_decl_or_labels_ending_decl:
+         lineno_decl
+       | lineno_stmt_decl_or_labels_ending_stmt lineno_decl
+               { if (pedantic && !flag_isoc99)
+                   pedwarn ("ISO C89 forbids mixed declarations and code"); }
+       | lineno_stmt_decl_or_labels_ending_decl lineno_decl
+       | lineno_stmt_decl_or_labels_ending_error lineno_decl
        ;
 
-xstmts:
-       /* empty */
-       | stmts
+lineno_stmt_decl_or_labels_ending_label:
+         lineno_label
+       | lineno_stmt_decl_or_labels_ending_stmt lineno_label
+       | lineno_stmt_decl_or_labels_ending_decl lineno_label
+       | lineno_stmt_decl_or_labels_ending_label lineno_label
+       | lineno_stmt_decl_or_labels_ending_error lineno_label
+       ;
+
+lineno_stmt_decl_or_labels_ending_error:
+       errstmt
+       | lineno_stmt_decl_or_labels errstmt
+       ;
+
+lineno_stmt_decl_or_labels:
+         lineno_stmt_decl_or_labels_ending_stmt
+       | lineno_stmt_decl_or_labels_ending_decl
+       | lineno_stmt_decl_or_labels_ending_label
+       | lineno_stmt_decl_or_labels_ending_error
        ;
 
 errstmt:  error ';'
        ;
 
 pushlevel:  /* empty */
-               { emit_line_note (input_filename, lineno);
-                 pushlevel (0);
+               { pushlevel (0);
                  clear_last_expr ();
-                 push_momentary ();
-                 expand_start_bindings (0);
+                 add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
 ifobjc
                  if (objc_method_context)
                    add_objc_decls ();
@@ -1547,13 +1643,50 @@ end ifobjc
                }
        ;
 
+poplevel:  /* empty */
+                { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
+
+/* Start and end blocks created for the new scopes of C99.  */
+c99_block_start: /* empty */
+               { if (flag_isoc99)
+                   {
+                     $$ = c_begin_compound_stmt ();
+                     pushlevel (0);
+                     clear_last_expr ();
+                     add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
+ifobjc
+                     if (objc_method_context)
+                       add_objc_decls ();
+end ifobjc
+                   }
+                 else
+                   $$ = NULL_TREE;
+               }
+       ;
+
+/* Productions using c99_block_start and c99_block_end will need to do what's
+   in compstmt: RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); $$ = $2; where
+   $1 is the value of c99_block_start and $2 of c99_block_end.  */
+c99_block_end: /* empty */
+                { if (flag_isoc99)
+                   {
+                     tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
+                     $$ = poplevel (kept_level_p (), 0, 0); 
+                     SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt)) 
+                       = SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
+                       = $$;
+                   }
+                 else
+                   $$ = NULL_TREE; }
+       ;
+
 /* Read zero or more forward-declarations for labels
    that nested functions can jump to.  */
 maybe_label_decls:
          /* empty */
        | label_decls
                { if (pedantic)
-                   pedwarn ("ANSI C forbids label declarations"); }
+                   pedwarn ("ISO C forbids label declarations"); }
        ;
 
 label_decls:
@@ -1568,7 +1701,7 @@ label_decl:
                    {
                      tree label = shadow_label (TREE_VALUE (link));
                      C_DECLARED_LABEL_FLAG (label) = 1;
-                     declare_nonlocal_label (label);
+                     add_decl_stmt (label);
                    }
                }
        ;
@@ -1581,51 +1714,62 @@ compstmt_or_error:
        | error compstmt
        ;
 
-compstmt: '{' '}'
+compstmt_start: '{' { compstmt_count++;
+                      $$ = c_begin_compound_stmt (); } 
+
+compstmt_nostart: '}'
                { $$ = convert (void_type_node, integer_zero_node); }
-       | '{' pushlevel maybe_label_decls decls xstmts '}'
-               { emit_line_note (input_filename, lineno);
-                 expand_end_bindings (getdecls (), 1, 0);
-                 $$ = poplevel (1, 1, 0);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
-       | '{' pushlevel maybe_label_decls error '}'
-               { emit_line_note (input_filename, lineno);
-                 expand_end_bindings (getdecls (), kept_level_p (), 0);
-                 $$ = poplevel (kept_level_p (), 0, 0);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
-       | '{' pushlevel maybe_label_decls stmts '}'
-               { emit_line_note (input_filename, lineno);
-                 expand_end_bindings (getdecls (), kept_level_p (), 0);
-                 $$ = poplevel (kept_level_p (), 0, 0);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
+       | pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
+               { $$ = poplevel (kept_level_p (), 1, 0); 
+                 SCOPE_STMT_BLOCK (TREE_PURPOSE ($5)) 
+                   = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
+                   = $$; }
+       ;
+
+compstmt_contents_nonempty:
+         stmts_and_decls
+       | error
+       ;
+
+compstmt_primary_start:
+       '(' '{'
+               { if (current_function_decl == 0)
+                   {
+                     error ("braced-group within expression allowed only inside a function");
+                     YYERROR;
+                   }
+                 /* We must force a BLOCK for this level
+                    so that, if it is not expanded later,
+                    there is a way to turn off the entire subtree of blocks
+                    that are contained in it.  */
+                 keep_next_level ();
+                 push_label_level ();
+                 compstmt_count++;
+                 $$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
+               }
+
+compstmt: compstmt_start compstmt_nostart
+               { RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); 
+                  $$ = $2; }
        ;
 
 /* Value is number of statements counted as of the closeparen.  */
 simple_if:
-         if_prefix lineno_labeled_stmt
-/* Make sure expand_end_cond is run once
-   for each call to expand_start_cond.
+         if_prefix c99_block_lineno_labeled_stmt
+                { c_finish_then (); }
+/* Make sure c_expand_end_cond is run once
+   for each call to c_expand_start_cond.
    Otherwise a crash is likely.  */
        | if_prefix error
        ;
 
 if_prefix:
          IF '(' expr ')'
-               { emit_line_note ($<filename>-1, $<lineno>0);
-                 expand_start_cond (truthvalue_conversion ($3), 0);
+               { c_expand_start_cond (truthvalue_conversion ($3), 
+                                      compstmt_count);
                  $<itype>$ = stmt_count;
-                 if_stmt_file = $<filename>-1;
-                 if_stmt_line = $<lineno>0;
-                 position_after_white_space (); }
+                 if_stmt_file = $<filename>-2;
+                 if_stmt_line = $<lineno>-1; }
        ;
 
 /* This is a subroutine of stmt.
@@ -1634,21 +1778,33 @@ if_prefix:
 do_stmt_start:
          DO
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 /* See comment in `while' alternative, above.  */
-                 emit_nop ();
-                 expand_start_loop_continue_elsewhere (1);
-                 position_after_white_space (); }
-         lineno_labeled_stmt WHILE
-               { expand_loop_continue_here (); }
-       ;
-
+                 compstmt_count++;
+                 $<ttype>$ 
+                   = add_stmt (build_stmt (DO_STMT, NULL_TREE,
+                                           NULL_TREE));
+                 /* In the event that a parse error prevents
+                    parsing the complete do-statement, set the
+                    condition now.  Otherwise, we can get crashes at
+                    RTL-generation time.  */
+                 DO_COND ($<ttype>$) = error_mark_node; }
+         c99_block_lineno_labeled_stmt WHILE
+               { $$ = $<ttype>2;
+                 RECHAIN_STMTS ($$, DO_BODY ($$)); }
+       ;
+
+/* The forced readahead in here is because we might be at the end of a
+   line, and the line and file won't be bumped until yylex absorbs the
+   first token on the next line.  */
 save_filename:
-               { $$ = input_filename; }
+               { if (yychar == YYEMPTY)
+                   yychar = YYLEX;
+                 $$ = input_filename; }
        ;
 
 save_lineno:
-               { $$ = lineno; }
+               { if (yychar == YYEMPTY)
+                   yychar = YYLEX;
+                 $$ = lineno; }
        ;
 
 lineno_labeled_stmt:
@@ -1661,55 +1817,34 @@ lineno_labeled_stmt:
                { }
        ;
 
-lineno_stmt_or_label:
-         save_filename save_lineno stmt_or_label
+/* Like lineno_labeled_stmt, but a block in C99.  */
+c99_block_lineno_labeled_stmt:
+         c99_block_start lineno_labeled_stmt c99_block_end
+               { if (flag_isoc99)
+                   RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
+       ;
+
+lineno_stmt:
+         save_filename save_lineno stmt
                { }
        ;
 
-stmt_or_label:
-         stmt
-       | label
-               { int next;
-                 position_after_white_space ();
-                 next = getc (finput);
-                 ungetc (next, finput);
-                 if (pedantic && next == '}')
-                   pedwarn ("ANSI C forbids label at end of compound statement");
-               }
+lineno_label:
+         save_filename save_lineno label
+               { }
        ;
 
-/* Parse a single real statement, not including any labels.  */
-stmt:
-         compstmt
-               { stmt_count++; }
-        | all_iter_stmt 
-       | expr ';'
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-/* It appears that this should not be done--that a non-lvalue array
-   shouldn't get an error if the value isn't used.
-   Section 3.2.2.1 says that an array lvalue gets converted to a pointer
-   if it appears as a top-level expression,
-   but says nothing about non-lvalue arrays.  */
-#if 0
-                 /* Call default_conversion to get an error
-                    on referring to a register array if pedantic.  */
-                 if (TREE_CODE (TREE_TYPE ($1)) == ARRAY_TYPE
-                     || TREE_CODE (TREE_TYPE ($1)) == FUNCTION_TYPE)
-                   $1 = default_conversion ($1);
-#endif
-                 iterator_expand ($1);
-                 clear_momentary (); }
-       | simple_if ELSE
-               { expand_start_else ();
-                 $<itype>1 = stmt_count;
-                 position_after_white_space (); }
-         lineno_labeled_stmt
-               { expand_end_cond ();
+select_or_iter_stmt:
+         simple_if ELSE
+               { c_expand_start_else ();
+                 $<itype>1 = stmt_count; }
+         c99_block_lineno_labeled_stmt
+                { c_finish_else ();
+                 c_expand_end_cond ();
                  if (extra_warnings && stmt_count == $<itype>1)
                    warning ("empty body in an else-statement"); }
        | simple_if %prec IF
-               { expand_end_cond ();
+               { c_expand_end_cond ();
                  /* This warning is here instead of in simple_if, because we
                     do not want a warning if an empty if is followed by an
                     else statement.  Increment stmt_count so we don't
@@ -1717,139 +1852,98 @@ stmt:
                  if (extra_warnings && stmt_count++ == $<itype>1)
                    warning_with_file_and_line (if_stmt_file, if_stmt_line,
                                                "empty body in an if-statement"); }
-/* Make sure expand_end_cond is run once
-   for each call to expand_start_cond.
+/* Make sure c_expand_end_cond is run once
+   for each call to c_expand_start_cond.
    Otherwise a crash is likely.  */
        | simple_if ELSE error
-               { expand_end_cond (); }
+               { c_expand_end_cond (); }
        | WHILE
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 /* The emit_nop used to come before emit_line_note,
-                    but that made the nop seem like part of the preceding line.
-                    And that was confusing when the preceding line was
-                    inside of an if statement and was not really executed.
-                    I think it ought to work to put the nop after the line number.
-                    We will see.  --rms, July 15, 1991.  */
-                 emit_nop (); }
+                { stmt_count++; }
          '(' expr ')'
-               { /* Don't start the loop till we have succeeded
-                    in parsing the end test.  This is to make sure
-                    that we end every loop we start.  */
-                 expand_start_loop (1);
-                 emit_line_note (input_filename, lineno);
-                 expand_exit_loop_if_false (NULL_PTR,
-                                            truthvalue_conversion ($4));
-                 position_after_white_space (); }
-         lineno_labeled_stmt
-               { expand_end_loop (); }
+                { $4 = truthvalue_conversion ($4);
+                 $<ttype>$ 
+                   = add_stmt (build_stmt (WHILE_STMT, $4, NULL_TREE)); }
+         c99_block_lineno_labeled_stmt
+               { RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
        | do_stmt_start
          '(' expr ')' ';'
-               { emit_line_note (input_filename, lineno);
-                 expand_exit_loop_if_false (NULL_PTR,
-                                            truthvalue_conversion ($3));
-                 expand_end_loop ();
-                 clear_momentary (); }
-/* This rule is needed to make sure we end every loop we start.  */
+                { DO_COND ($1) = truthvalue_conversion ($3); }
        | do_stmt_start error
-               { expand_end_loop ();
-                 clear_momentary (); }
+               { }
        | FOR
-         '(' xexpr ';'
+               { $<ttype>$ = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
+                                         NULL_TREE, NULL_TREE);
+                 add_stmt ($<ttype>$); } 
+         '(' for_init_stmt
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 /* See comment in `while' alternative, above.  */
-                 emit_nop ();
-                 if ($3) c_expand_expr_stmt ($3);
-                 /* Next step is to call expand_start_loop_continue_elsewhere,
-                    but wait till after we parse the entire for (...).
-                    Otherwise, invalid input might cause us to call that
-                    fn without calling expand_end_loop.  */
-               }
+                 RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
          xexpr ';'
-               /* Can't emit now; wait till after expand_start_loop...  */
-               { $<lineno>7 = lineno;
-                 $<filename>$ = input_filename; }
+                { FOR_COND ($<ttype>2) = $6; }
          xexpr ')'
-               { 
-                 /* Start the loop.  Doing this after parsing
-                    all the expressions ensures we will end the loop.  */
-                 expand_start_loop_continue_elsewhere (1);
-                 /* Emit the end-test, with a line number.  */
-                 emit_line_note ($<filename>8, $<lineno>7);
-                 if ($6)
-                   expand_exit_loop_if_false (NULL_PTR,
-                                              truthvalue_conversion ($6));
-                 /* Don't let the tree nodes for $9 be discarded by
-                    clear_momentary during the parsing of the next stmt.  */
-                 push_momentary ();
-                 $<lineno>7 = lineno;
-                 $<filename>8 = input_filename;
-                 position_after_white_space (); }
-         lineno_labeled_stmt
-               { /* Emit the increment expression, with a line number.  */
-                 emit_line_note ($<filename>8, $<lineno>7);
-                 expand_loop_continue_here ();
-                 if ($9)
-                   c_expand_expr_stmt ($9);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary ();
-                 expand_end_loop (); }
+               { FOR_EXPR ($<ttype>2) = $9; }
+         c99_block_lineno_labeled_stmt
+                { RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2)); }
        | SWITCH '(' expr ')'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 c_expand_start_case ($3);
-                 /* Don't let the tree nodes for $3 be discarded by
-                    clear_momentary during the parsing of the next stmt.  */
-                 push_momentary ();
-                 position_after_white_space (); }
-         lineno_labeled_stmt
-               { expand_end_case ($3);
-                 if (yychar == CONSTANT || yychar == STRING)
-                   pop_momentary_nofree ();
-                 else
-                   pop_momentary (); }
-       | BREAK ';'
+                 $<ttype>$ = c_start_case ($3); }
+         c99_block_lineno_labeled_stmt
+                { c_finish_case (); }
+       ;
+
+for_init_stmt:
+         xexpr ';'
+               { add_stmt (build_stmt (EXPR_STMT, $1)); } 
+       | decl
+               { check_for_loop_decls (); }
+       ;
+
+/* Parse a single real statement, not including any labels.  */
+stmt:
+         compstmt
+               { stmt_count++; }
+       | expr ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 if ( ! expand_exit_something ())
-                   error ("break statement not within loop or switch"); }
+                 c_expand_expr_stmt ($1); }
+       | c99_block_start select_or_iter_stmt c99_block_end
+               { if (flag_isoc99)
+                   RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
+       | BREAK ';'
+               { stmt_count++;
+                 add_stmt (build_break_stmt ()); }
        | CONTINUE ';'
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 if (! expand_continue_loop (NULL_PTR))
-                   error ("continue statement not within a loop"); }
+                { stmt_count++;
+                 add_stmt (build_continue_stmt ()); }
        | RETURN ';'
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
+                { stmt_count++;
                  c_expand_return (NULL_TREE); }
        | RETURN expr ';'
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
+                { stmt_count++;
                  c_expand_return ($2); }
        | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  STRIP_NOPS ($4);
                  if ((TREE_CODE ($4) == ADDR_EXPR
                       && TREE_CODE (TREE_OPERAND ($4, 0)) == STRING_CST)
                      || TREE_CODE ($4) == STRING_CST)
-                   expand_asm ($4);
+                   {
+                     if (TREE_CODE ($4) == ADDR_EXPR)
+                       $4 = TREE_OPERAND ($4, 0);
+                     if (TREE_CHAIN ($4))
+                       $4 = combine_strings ($4);
+                     add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4,
+                                           NULL_TREE, NULL_TREE, NULL_TREE));
+                   }
                  else
                    error ("argument of `asm' is not a constant string"); }
        /* This is the case with just output operands.  */
        | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
                                         $2 == ridpointers[(int)RID_VOLATILE],
                                         input_filename, lineno); }
        /* This is the case with input operands as well.  */
        | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' asm_operands ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_asm_operands ($4, $6, $8, NULL_TREE,
                                         $2 == ridpointers[(int)RID_VOLATILE],
                                         input_filename, lineno); }
@@ -1857,166 +1951,50 @@ stmt:
        | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
          asm_operands ':' asm_clobbers ')' ';'
                { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  c_expand_asm_operands ($4, $6, $8, $10,
                                         $2 == ridpointers[(int)RID_VOLATILE],
                                         input_filename, lineno); }
        | GOTO identifier ';'
                { tree decl;
                  stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
                  decl = lookup_label ($2);
                  if (decl != 0)
                    {
                      TREE_USED (decl) = 1;
-                     expand_goto (decl);
+                     add_stmt (build_stmt (GOTO_STMT, decl));
                    }
                }
        | GOTO '*' expr ';'
-               { stmt_count++;
-                 emit_line_note ($<filename>-1, $<lineno>0);
-                 expand_computed_goto (convert (ptr_type_node, $3)); }
+               { if (pedantic)
+                   pedwarn ("ISO C forbids `goto *expr;'");
+                 stmt_count++;
+                 $3 = convert (ptr_type_node, $3);
+                 add_stmt (build_stmt (GOTO_STMT, $3)); }
        | ';'
        ;
 
-all_iter_stmt:
-         all_iter_stmt_simple
-/*     | all_iter_stmt_with_decl */
-       ;
-
-all_iter_stmt_simple:
-         FOR '(' primary ')' 
-         {
-           /* The value returned by this action is  */
-           /*      1 if everything is OK */ 
-           /*      0 in case of error or already bound iterator */
-
-           $<itype>$ = 0;
-           if (TREE_CODE ($3) != VAR_DECL)
-             error ("invalid `for (ITERATOR)' syntax");
-           else if (! ITERATOR_P ($3))
-             error ("`%s' is not an iterator",
-                    IDENTIFIER_POINTER (DECL_NAME ($3)));
-           else if (ITERATOR_BOUND_P ($3))
-             error ("`for (%s)' inside expansion of same iterator",
-                    IDENTIFIER_POINTER (DECL_NAME ($3)));
-           else
-             {
-               $<itype>$ = 1;
-               iterator_for_loop_start ($3);
-             }
-         }
-         lineno_labeled_stmt
-         {
-           if ($<itype>5)
-             iterator_for_loop_end ($3);
-         }
-
-/*  This really should allow any kind of declaration,
-    for generality.  Fix it before turning it back on.
-
-all_iter_stmt_with_decl:
-         FOR '(' ITERATOR pushlevel setspecs iterator_spec ')' 
-         {
-*/         /* The value returned by this action is  */
-           /*      1 if everything is OK */ 
-           /*      0 in case of error or already bound iterator */
-/*
-           iterator_for_loop_start ($6);
-         }
-         lineno_labeled_stmt
-         {
-           iterator_for_loop_end ($6);
-           emit_line_note (input_filename, lineno);
-           expand_end_bindings (getdecls (), 1, 0);
-           $<ttype>$ = poplevel (1, 1, 0);
-           if (yychar == CONSTANT || yychar == STRING)
-             pop_momentary_nofree ();
-           else
-             pop_momentary ();     
-         }
-*/
-
 /* Any kind of label, including jump labels and case labels.
    ANSI C accepts labels only before statements, but we allow them
    also at the end of a compound statement.  */
 
 label:   CASE expr_no_commas ':'
-               { register tree value = check_case_value ($2);
-                 register tree label
-                   = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-                 stmt_count++;
-
-                 if (value != error_mark_node)
-                   {
-                     tree duplicate;
-                     int success = pushcase (value, convert_and_check,
-                                             label, &duplicate);
-                     if (success == 1)
-                       error ("case label not within a switch statement");
-                     else if (success == 2)
-                       {
-                         error ("duplicate case value");
-                         error_with_decl (duplicate, "this is the first entry for that value");
-                       }
-                     else if (success == 3)
-                       warning ("case value out of range");
-                     else if (success == 5)
-                       error ("case label within scope of cleanup or variable array");
-                   }
-                 position_after_white_space (); }
+                { stmt_count++;
+                 do_case ($2, NULL_TREE); }
        | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
-               { register tree value1 = check_case_value ($2);
-                 register tree value2 = check_case_value ($4);
-                 register tree label
-                   = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-                 stmt_count++;
-
-                 if (value1 != error_mark_node && value2 != error_mark_node)
-                   {
-                     tree duplicate;
-                     int success = pushcase_range (value1, value2,
-                                                   convert_and_check, label,
-                                                   &duplicate);
-                     if (success == 1)
-                       error ("case label not within a switch statement");
-                     else if (success == 2)
-                       {
-                         error ("duplicate case value");
-                         error_with_decl (duplicate, "this is the first entry for that value");
-                       }
-                     else if (success == 3)
-                       warning ("case value out of range");
-                     else if (success == 4)
-                       warning ("empty case range");
-                     else if (success == 5)
-                       error ("case label within scope of cleanup or variable array");
-                   }
-                 position_after_white_space (); }
+                { stmt_count++;
+                 do_case ($2, $4); }
        | DEFAULT ':'
-               {
-                 tree duplicate;
-                 register tree label
-                   = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-                 int success = pushcase (NULL_TREE, 0, label, &duplicate);
+                { stmt_count++;
+                 do_case (NULL_TREE, NULL_TREE); }
+       | identifier save_filename save_lineno ':' maybe_attribute
+               { tree label = define_label ($2, $3, $1);
                  stmt_count++;
-                 if (success == 1)
-                   error ("default label not within a switch statement");
-                 else if (success == 2)
+                 if (label)
                    {
-                     error ("multiple default labels in one switch");
-                     error_with_decl (duplicate, "this is the first default label");
+                     decl_attributes (label, $5, NULL_TREE);
+                     add_stmt (build_stmt (LABEL_STMT, label));
                    }
-                 position_after_white_space (); }
-       | identifier ':'
-               { tree label = define_label (input_filename, lineno, $1);
-                 stmt_count++;
-                 emit_nop ();
-                 if (label)
-                   expand_label (label);
-                 position_after_white_space (); }
+               }
        ;
 
 /* Either a type-qualifier or nothing.  First thing in an `asm' statement.  */
@@ -2077,7 +2055,7 @@ parmlist_1:
        | parms ';'
                { tree parm;
                  if (pedantic)
-                   pedwarn ("ANSI C forbids forward parameter declarations");
+                   pedwarn ("ISO C forbids forward parameter declarations");
                  /* Mark the forward decls as such.  */
                  for (parm = getdecls (); parm; parm = TREE_CHAIN (parm))
                    TREE_ASM_WRITTEN (parm) = 1;
@@ -2100,7 +2078,7 @@ parmlist_2:  /* empty */
                     it caused problems with the code in expand_builtin which
                     tries to verify that BUILT_IN_NEXT_ARG is being used
                     correctly.  */
-                 error ("ANSI C requires a named argument before `...'");
+                 error ("ISO C requires a named argument before `...'");
                }
        | parms
                { $$ = get_parm_info (1); }
@@ -2118,16 +2096,47 @@ parms:
 /* A single parameter declaration or parameter type name,
    as found in a parmlist.  */
 parm:
-         typed_declspecs parm_declarator
-               { $$ = build_tree_list ($1, $2) ; }
-       | typed_declspecs notype_declarator
-               { $$ = build_tree_list ($1, $2) ; }
-       | typed_declspecs absdcl
-               { $$ = build_tree_list ($1, $2); }
-       | declmods notype_declarator
-               { $$ = build_tree_list ($1, $2) ; }
-       | declmods absdcl
-               { $$ = build_tree_list ($1, $2); }
+         typed_declspecs setspecs parm_declarator maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $3),
+                                       build_tree_list (prefix_attributes,
+                                                        $4));
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | typed_declspecs setspecs notype_declarator maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $3),
+                                       build_tree_list (prefix_attributes,
+                                                        $4)); 
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | typed_declspecs setspecs absdcl maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $3),
+                                       build_tree_list (prefix_attributes,
+                                                        $4));
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+       | declmods setspecs notype_declarator maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $3),
+                                       build_tree_list (prefix_attributes,
+                                                        $4));
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
+
+       | declmods setspecs absdcl maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $3),
+                                       build_tree_list (prefix_attributes,
+                                                        $4));
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        ;
 
 /* This is used in a function definition
@@ -2168,6 +2177,13 @@ identifiers_or_typenames:
        | identifiers_or_typenames ',' identifier
                { $$ = chainon ($1, build_tree_list (NULL_TREE, $3)); }
        ;
+
+extension:
+       EXTENSION
+               { $$ = SAVE_WARN_FLAGS();
+                 pedantic = 0;
+                 warn_pointer_arith = 0; }
+       ;
 \f
 ifobjc
 /* Objective-C productions.  */
@@ -2354,7 +2370,11 @@ protocolrefs:
                {
                  $$ = NULL_TREE;
                }
-       | ARITHCOMPARE identifier_list ARITHCOMPARE
+       | non_empty_protocolrefs
+       ;
+
+non_empty_protocolrefs:
+         ARITHCOMPARE identifier_list ARITHCOMPARE
                {
                  if ($1 == LT_EXPR && $3 == GT_EXPR)
                    $$ = $2;
@@ -2399,15 +2419,15 @@ ivar_decls:
 
 ivar_decl:
        typed_typespecs setspecs ivars
-               {
-                  $$ = $3;
-                 resume_momentary ($2);
-                }
+               { $$ = $3;
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | nonempty_type_quals setspecs ivars
-               {
-                  $$ = $3;
-                 resume_momentary ($2);
-                }
+               { $$ = $3;
+                 current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | error
                { $$ = NULL_TREE; }
        ;
@@ -2518,20 +2538,28 @@ semi_or_error:
 methodproto:
          '+'
                {
+                 /* Remember protocol qualifiers in prototypes.  */
+                 remember_protocol_qualifiers ();
                  objc_inherit_code = CLASS_METHOD_DECL;
                }
          methoddecl
                {
+                 /* Forget protocol qualifiers here.  */
+                 forget_protocol_qualifiers ();
                  add_class_method (objc_interface_context, $3);
                }
          semi_or_error
 
        | '-'
                {
+                 /* Remember protocol qualifiers in prototypes.  */
+                 remember_protocol_qualifiers ();
                  objc_inherit_code = INSTANCE_METHOD_DECL;
                }
          methoddecl
                {
+                 /* Forget protocol qualifiers here.  */
+                 forget_protocol_qualifiers ();
                  add_instance_method (objc_interface_context, $3);
                }
          semi_or_error
@@ -2584,7 +2612,9 @@ mydecls:
 
 mydecl:
        typed_declspecs setspecs myparms ';'
-               { resume_momentary ($2); }
+               { current_declspecs = TREE_VALUE (declspec_stack);
+                 prefix_attributes = TREE_PURPOSE (declspec_stack);
+                 declspec_stack = TREE_CHAIN (declspec_stack); }
        | typed_declspecs ';'
                { shadow_tag ($1); }
        | declmods ';'
@@ -2602,12 +2632,21 @@ myparms:
    as found in a parmlist. DOES NOT ALLOW AN INITIALIZER OR ASMSPEC */
 
 myparm:
-         parm_declarator
-               { $$ = build_tree_list (current_declspecs, $1)  ; }
-       | notype_declarator
-               { $$ = build_tree_list (current_declspecs, $1)  ; }
-       | absdcl
-               { $$ = build_tree_list (current_declspecs, $1)  ; }
+         parm_declarator maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $1),
+                                       build_tree_list (prefix_attributes,
+                                                        $2)); }
+       | notype_declarator maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $1),
+                                       build_tree_list (prefix_attributes,
+                                                        $2)); }
+       | absdcl maybe_attribute
+               { $$ = build_tree_list (build_tree_list (current_declspecs,
+                                                        $1),
+                                       build_tree_list (prefix_attributes,
+                                                        $2)); }
        ;
 
 optparmlist:
@@ -2618,7 +2657,7 @@ optparmlist:
        | ',' ELLIPSIS
                {
                  /* oh what a kludge! */
-                 $$ = (tree)1;
+                 $$ = objc_ellipsis_node;
                }
        | ','
                {
@@ -2653,25 +2692,9 @@ selector:
        ;
 
 reservedwords:
-         ENUM { $$ = get_identifier (token_buffer); }
-       | STRUCT { $$ = get_identifier (token_buffer); }
-       | UNION { $$ = get_identifier (token_buffer); }
-       | IF { $$ = get_identifier (token_buffer); }
-       | ELSE { $$ = get_identifier (token_buffer); }
-       | WHILE { $$ = get_identifier (token_buffer); }
-       | DO { $$ = get_identifier (token_buffer); }
-       | FOR { $$ = get_identifier (token_buffer); }
-       | SWITCH { $$ = get_identifier (token_buffer); }
-       | CASE { $$ = get_identifier (token_buffer); }
-       | DEFAULT { $$ = get_identifier (token_buffer); }
-       | BREAK { $$ = get_identifier (token_buffer); }
-       | CONTINUE { $$ = get_identifier (token_buffer); }
-       | RETURN  { $$ = get_identifier (token_buffer); }
-       | GOTO { $$ = get_identifier (token_buffer); }
-       | ASM_KEYWORD { $$ = get_identifier (token_buffer); }
-        | SIZEOF { $$ = get_identifier (token_buffer); }
-       | TYPEOF { $$ = get_identifier (token_buffer); }
-       | ALIGNOF { $$ = get_identifier (token_buffer); }
+         ENUM | STRUCT | UNION | IF | ELSE | WHILE | DO | FOR
+       | SWITCH | CASE | DEFAULT | BREAK | CONTINUE | RETURN
+       | GOTO | ASM_KEYWORD | SIZEOF | TYPEOF | ALIGNOF
        | TYPESPEC | TYPE_QUAL
        ;
 
@@ -2802,3 +2825,598 @@ objcencodeexpr:
 
 end ifobjc
 %%
+
+/* yylex() is a thin wrapper around c_lex(), all it does is translate
+   cpplib.h's token codes into yacc's token codes.  */
+
+static enum cpp_ttype last_token;
+
+/* The reserved keyword table.  */
+struct resword
+{
+  const char *word;
+  ENUM_BITFIELD(rid) rid : 16;
+  unsigned int disable   : 16;
+};
+
+/* Disable mask.  Keywords are disabled if (reswords[i].disable & mask) is
+   _true_.  */
+#define D_TRAD 0x01    /* not in traditional C */
+#define D_C89  0x02    /* not in C89 */
+#define D_EXT  0x04    /* GCC extension */
+#define D_EXT89        0x08    /* GCC extension incorporated in C99 */
+#define D_OBJC 0x10    /* Objective C only */
+#define D_YES  0x20    /* always starts disabled */
+
+static const struct resword reswords[] =
+{
+  { "_Bool",           RID_BOOL,       0 },
+  { "_Complex",                RID_COMPLEX,    0 },
+  { "__alignof",       RID_ALIGNOF,    0 },
+  { "__alignof__",     RID_ALIGNOF,    0 },
+  { "__asm",           RID_ASM,        0 },
+  { "__asm__",         RID_ASM,        0 },
+  { "__attribute",     RID_ATTRIBUTE,  0 },
+  { "__attribute__",   RID_ATTRIBUTE,  0 },
+  { "__bounded",       RID_BOUNDED,    0 },
+  { "__bounded__",     RID_BOUNDED,    0 },
+  { "__builtin_va_arg",        RID_VA_ARG,     0 },
+  { "__complex",       RID_COMPLEX,    0 },
+  { "__complex__",     RID_COMPLEX,    0 },
+  { "__const",         RID_CONST,      0 },
+  { "__const__",       RID_CONST,      0 },
+  { "__extension__",   RID_EXTENSION,  0 },
+  { "__imag",          RID_IMAGPART,   0 },
+  { "__imag__",                RID_IMAGPART,   0 },
+  { "__inline",                RID_INLINE,     0 },
+  { "__inline__",      RID_INLINE,     0 },
+  { "__label__",       RID_LABEL,      0 },
+  { "__ptrbase",       RID_PTRBASE,    0 },
+  { "__ptrbase__",     RID_PTRBASE,    0 },
+  { "__ptrextent",     RID_PTREXTENT,  0 },
+  { "__ptrextent__",   RID_PTREXTENT,  0 },
+  { "__ptrvalue",      RID_PTRVALUE,   0 },
+  { "__ptrvalue__",    RID_PTRVALUE,   0 },
+  { "__real",          RID_REALPART,   0 },
+  { "__real__",                RID_REALPART,   0 },
+  { "__restrict",      RID_RESTRICT,   0 },
+  { "__restrict__",    RID_RESTRICT,   0 },
+  { "__signed",                RID_SIGNED,     0 },
+  { "__signed__",      RID_SIGNED,     0 },
+  { "__typeof",                RID_TYPEOF,     0 },
+  { "__typeof__",      RID_TYPEOF,     0 },
+  { "__unbounded",     RID_UNBOUNDED,  0 },
+  { "__unbounded__",   RID_UNBOUNDED,  0 },
+  { "__volatile",      RID_VOLATILE,   0 },
+  { "__volatile__",    RID_VOLATILE,   0 },
+  { "asm",             RID_ASM,        D_EXT },
+  { "auto",            RID_AUTO,       0 },
+  { "break",           RID_BREAK,      0 },
+  { "case",            RID_CASE,       0 },
+  { "char",            RID_CHAR,       0 },
+  { "const",           RID_CONST,      D_TRAD },
+  { "continue",                RID_CONTINUE,   0 },
+  { "default",         RID_DEFAULT,    0 },
+  { "do",              RID_DO,         0 },
+  { "double",          RID_DOUBLE,     0 },
+  { "else",            RID_ELSE,       0 },
+  { "enum",            RID_ENUM,       0 },
+  { "extern",          RID_EXTERN,     0 },
+  { "float",           RID_FLOAT,      0 },
+  { "for",             RID_FOR,        0 },
+  { "goto",            RID_GOTO,       0 },
+  { "if",              RID_IF,         0 },
+  { "inline",          RID_INLINE,     D_TRAD|D_EXT89 },
+  { "int",             RID_INT,        0 },
+  { "long",            RID_LONG,       0 },
+  { "register",                RID_REGISTER,   0 },
+  { "restrict",                RID_RESTRICT,   D_TRAD|D_C89 },
+  { "return",          RID_RETURN,     0 },
+  { "short",           RID_SHORT,      0 },
+  { "signed",          RID_SIGNED,     D_TRAD },
+  { "sizeof",          RID_SIZEOF,     0 },
+  { "static",          RID_STATIC,     0 },
+  { "struct",          RID_STRUCT,     0 },
+  { "switch",          RID_SWITCH,     0 },
+  { "typedef",         RID_TYPEDEF,    0 },
+  { "typeof",          RID_TYPEOF,     D_TRAD|D_EXT },
+  { "union",           RID_UNION,      0 },
+  { "unsigned",                RID_UNSIGNED,   0 },
+  { "void",            RID_VOID,       0 },
+  { "volatile",                RID_VOLATILE,   D_TRAD },
+  { "while",           RID_WHILE,      0 },
+ifobjc
+  { "@class",          RID_AT_CLASS,           D_OBJC },
+  { "@compatibility_alias", RID_AT_ALIAS,      D_OBJC },
+  { "@defs",           RID_AT_DEFS,            D_OBJC },
+  { "@encode",         RID_AT_ENCODE,          D_OBJC },
+  { "@end",            RID_AT_END,             D_OBJC },
+  { "@implementation", RID_AT_IMPLEMENTATION,  D_OBJC },
+  { "@interface",      RID_AT_INTERFACE,       D_OBJC },
+  { "@private",                RID_AT_PRIVATE,         D_OBJC },
+  { "@protected",      RID_AT_PROTECTED,       D_OBJC },
+  { "@protocol",       RID_AT_PROTOCOL,        D_OBJC },
+  { "@public",         RID_AT_PUBLIC,          D_OBJC },
+  { "@selector",       RID_AT_SELECTOR,        D_OBJC },
+  { "id",              RID_ID,                 D_OBJC },
+  { "bycopy",          RID_BYCOPY,             D_OBJC|D_YES },
+  { "byref",           RID_BYREF,              D_OBJC|D_YES },
+  { "in",              RID_IN,                 D_OBJC|D_YES },
+  { "inout",           RID_INOUT,              D_OBJC|D_YES },
+  { "oneway",          RID_ONEWAY,             D_OBJC|D_YES },
+  { "out",             RID_OUT,                D_OBJC|D_YES },
+end ifobjc
+};
+#define N_reswords (sizeof reswords / sizeof (struct resword))
+
+/* Table mapping from RID_* constants to yacc token numbers.
+   Unfortunately we have to have entries for all the keywords in all
+   three languages.  */
+static const short rid_to_yy[RID_MAX] =
+{
+  /* RID_STATIC */     SCSPEC,
+  /* RID_UNSIGNED */   TYPESPEC,
+  /* RID_LONG */       TYPESPEC,
+  /* RID_CONST */      TYPE_QUAL,
+  /* RID_EXTERN */     SCSPEC,
+  /* RID_REGISTER */   SCSPEC,
+  /* RID_TYPEDEF */    SCSPEC,
+  /* RID_SHORT */      TYPESPEC,
+  /* RID_INLINE */     SCSPEC,
+  /* RID_VOLATILE */   TYPE_QUAL,
+  /* RID_SIGNED */     TYPESPEC,
+  /* RID_AUTO */       SCSPEC,
+  /* RID_RESTRICT */   TYPE_QUAL,
+
+  /* C extensions */
+  /* RID_BOUNDED */    TYPE_QUAL,
+  /* RID_UNBOUNDED */  TYPE_QUAL,
+  /* RID_COMPLEX */    TYPESPEC,
+
+  /* C++ */
+  /* RID_FRIEND */     0,
+  /* RID_VIRTUAL */    0,
+  /* RID_EXPLICIT */   0,
+  /* RID_EXPORT */     0,
+  /* RID_MUTABLE */    0,
+
+  /* ObjC */
+  /* RID_IN */         TYPE_QUAL,
+  /* RID_OUT */                TYPE_QUAL,
+  /* RID_INOUT */      TYPE_QUAL,
+  /* RID_BYCOPY */     TYPE_QUAL,
+  /* RID_BYREF */      TYPE_QUAL,
+  /* RID_ONEWAY */     TYPE_QUAL,
+  
+  /* C */
+  /* RID_INT */                TYPESPEC,
+  /* RID_CHAR */       TYPESPEC,
+  /* RID_FLOAT */      TYPESPEC,
+  /* RID_DOUBLE */     TYPESPEC,
+  /* RID_VOID */       TYPESPEC,
+  /* RID_ENUM */       ENUM,
+  /* RID_STRUCT */     STRUCT,
+  /* RID_UNION */      UNION,
+  /* RID_IF */         IF,
+  /* RID_ELSE */       ELSE,
+  /* RID_WHILE */      WHILE,
+  /* RID_DO */         DO,
+  /* RID_FOR */                FOR,
+  /* RID_SWITCH */     SWITCH,
+  /* RID_CASE */       CASE,
+  /* RID_DEFAULT */    DEFAULT,
+  /* RID_BREAK */      BREAK,
+  /* RID_CONTINUE */   CONTINUE,
+  /* RID_RETURN */     RETURN,
+  /* RID_GOTO */       GOTO,
+  /* RID_SIZEOF */     SIZEOF,
+
+  /* C extensions */
+  /* RID_ASM */                ASM_KEYWORD,
+  /* RID_TYPEOF */     TYPEOF,
+  /* RID_ALIGNOF */    ALIGNOF,
+  /* RID_ATTRIBUTE */  ATTRIBUTE,
+  /* RID_VA_ARG */     VA_ARG,
+  /* RID_EXTENSION */  EXTENSION,
+  /* RID_IMAGPART */   IMAGPART,
+  /* RID_REALPART */   REALPART,
+  /* RID_LABEL */      LABEL,
+  /* RID_PTRBASE */    PTR_BASE,
+  /* RID_PTREXTENT */  PTR_EXTENT,
+  /* RID_PTRVALUE */   PTR_VALUE,
+
+  /* C++ */
+  /* RID_BOOL */       TYPESPEC,
+  /* RID_WCHAR */      0,
+  /* RID_CLASS */      0,
+  /* RID_PUBLIC */     0,
+  /* RID_PRIVATE */    0,
+  /* RID_PROTECTED */  0,
+  /* RID_TEMPLATE */   0,
+  /* RID_NULL */       0,
+  /* RID_CATCH */      0,
+  /* RID_DELETE */     0,
+  /* RID_FALSE */      0,
+  /* RID_NAMESPACE */  0,
+  /* RID_NEW */                0,
+  /* RID_OPERATOR */   0,
+  /* RID_THIS */       0,
+  /* RID_THROW */      0,
+  /* RID_TRUE */       0,
+  /* RID_TRY */                0,
+  /* RID_TYPENAME */   0,
+  /* RID_TYPEID */     0,
+  /* RID_USING */      0,
+
+  /* casts */
+  /* RID_CONSTCAST */  0,
+  /* RID_DYNCAST */    0,
+  /* RID_REINTCAST */  0,
+  /* RID_STATCAST */   0,
+
+  /* alternate spellings */
+  /* RID_AND */                0,
+  /* RID_AND_EQ */     0,
+  /* RID_NOT */                0,
+  /* RID_NOT_EQ */     0,
+  /* RID_OR */         0,
+  /* RID_OR_EQ */      0,
+  /* RID_XOR */                0,
+  /* RID_XOR_EQ */     0,
+  /* RID_BITAND */     0,
+  /* RID_BITOR */      0,
+  /* RID_COMPL */      0,
+
+  /* Objective C */
+  /* RID_ID */                 OBJECTNAME,
+  /* RID_AT_ENCODE */          ENCODE,
+  /* RID_AT_END */             END,
+  /* RID_AT_CLASS */           CLASS,
+  /* RID_AT_ALIAS */           ALIAS,
+  /* RID_AT_DEFS */            DEFS,
+  /* RID_AT_PRIVATE */         PRIVATE,
+  /* RID_AT_PROTECTED */       PROTECTED,
+  /* RID_AT_PUBLIC */          PUBLIC,
+  /* RID_AT_PROTOCOL */                PROTOCOL,
+  /* RID_AT_SELECTOR */                SELECTOR,
+  /* RID_AT_INTERFACE */       INTERFACE,
+  /* RID_AT_IMPLEMENTATION */  IMPLEMENTATION
+};
+
+static void
+init_reswords ()
+{
+  unsigned int i;
+  tree id;
+  int mask = ((doing_objc_thang ? 0 : D_OBJC)
+             | (flag_isoc99 ? 0 : D_C89)
+             | (flag_traditional ? D_TRAD : 0)
+             | (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0));
+
+  /* It is not necessary to register ridpointers as a GC root, because
+     all the trees it points to are permanently interned in the
+     get_identifier hash anyway.  */
+  ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
+  for (i = 0; i < N_reswords; i++)
+    {
+      /* If a keyword is disabled, do not enter it into the table
+        and so create a canonical spelling that isn't a keyword.  */
+      if (reswords[i].disable & mask)
+       continue;
+
+      id = get_identifier (reswords[i].word);
+      C_RID_CODE (id) = reswords[i].rid;
+      ridpointers [(int) reswords[i].rid] = id;
+
+      /* Objective C does tricky things with enabling and disabling 
+        keywords.  So these we must not elide in the test above, but
+        wait and not mark them reserved now.  */
+      if (! (reswords[i].disable & D_YES))
+       C_IS_RESERVED_WORD (id) = 1;
+    }
+}
+
+const char *
+init_parse (filename)
+     const char *filename;
+{
+  add_c_tree_codes ();
+
+  /* Make identifier nodes long enough for the language-specific slots.  */
+  set_identifier_size (sizeof (struct lang_identifier));
+
+  init_reswords ();
+  init_pragma ();
+
+  return init_c_lex (filename);
+}
+
+void
+finish_parse ()
+{
+  cpp_finish (parse_in);
+  errorcount += parse_in->errors;
+}
+
+#define NAME(type) cpp_type2name (type)
+
+static void
+yyerror (msgid)
+     const char *msgid;
+{
+  const char *string = _(msgid);
+
+  if (last_token == CPP_EOF)
+    error ("%s at end of input", string);
+  else if (last_token == CPP_CHAR || last_token == CPP_WCHAR)
+    {
+      unsigned int val = TREE_INT_CST_LOW (yylval.ttype);
+      const char *ell = (last_token == CPP_CHAR) ? "" : "L";
+      if (val <= UCHAR_MAX && ISGRAPH (val))
+       error ("%s before %s'%c'", string, ell, val);
+      else
+       error ("%s before %s'\\x%x'", string, ell, val);
+    }
+  else if (last_token == CPP_STRING
+          || last_token == CPP_WSTRING
+          || last_token == CPP_OSTRING)
+    error ("%s before string constant", string);
+  else if (last_token == CPP_NUMBER
+          || last_token == CPP_INT
+          || last_token == CPP_FLOAT)
+    error ("%s before numeric constant", string);
+  else if (last_token == CPP_NAME)
+    error ("%s before \"%s\"", string, IDENTIFIER_POINTER (yylval.ttype));
+  else
+    error ("%s before '%s' token", string, NAME(last_token));
+}
+
+static inline int
+_yylex ()
+{
+ retry:
+  last_token = c_lex (&yylval.ttype);
+
+  switch (last_token)
+    {
+    case CPP_EQ:                                       return '=';
+    case CPP_NOT:                                      return '!';
+    case CPP_GREATER:  yylval.code = GT_EXPR;          return ARITHCOMPARE;
+    case CPP_LESS:     yylval.code = LT_EXPR;          return ARITHCOMPARE;
+    case CPP_PLUS:     yylval.code = PLUS_EXPR;        return '+';
+    case CPP_MINUS:    yylval.code = MINUS_EXPR;       return '-';
+    case CPP_MULT:     yylval.code = MULT_EXPR;        return '*';
+    case CPP_DIV:      yylval.code = TRUNC_DIV_EXPR;   return '/';
+    case CPP_MOD:      yylval.code = TRUNC_MOD_EXPR;   return '%';
+    case CPP_AND:      yylval.code = BIT_AND_EXPR;     return '&';
+    case CPP_OR:       yylval.code = BIT_IOR_EXPR;     return '|';
+    case CPP_XOR:      yylval.code = BIT_XOR_EXPR;     return '^';
+    case CPP_RSHIFT:   yylval.code = RSHIFT_EXPR;      return RSHIFT;
+    case CPP_LSHIFT:   yylval.code = LSHIFT_EXPR;      return LSHIFT;
+
+    case CPP_COMPL:                                    return '~';
+    case CPP_AND_AND:                                  return ANDAND;
+    case CPP_OR_OR:                                    return OROR;
+    case CPP_QUERY:                                    return '?';
+    case CPP_COLON:                                    return ':';
+    case CPP_COMMA:                                    return ',';
+    case CPP_OPEN_PAREN:                               return '(';
+    case CPP_CLOSE_PAREN:                              return ')';
+    case CPP_EQ_EQ:    yylval.code = EQ_EXPR;          return EQCOMPARE;
+    case CPP_NOT_EQ:   yylval.code = NE_EXPR;          return EQCOMPARE;
+    case CPP_GREATER_EQ:yylval.code = GE_EXPR;         return ARITHCOMPARE;
+    case CPP_LESS_EQ:  yylval.code = LE_EXPR;          return ARITHCOMPARE;
+
+    case CPP_PLUS_EQ:  yylval.code = PLUS_EXPR;        return ASSIGN;
+    case CPP_MINUS_EQ: yylval.code = MINUS_EXPR;       return ASSIGN;
+    case CPP_MULT_EQ:  yylval.code = MULT_EXPR;        return ASSIGN;
+    case CPP_DIV_EQ:   yylval.code = TRUNC_DIV_EXPR;   return ASSIGN;
+    case CPP_MOD_EQ:   yylval.code = TRUNC_MOD_EXPR;   return ASSIGN;
+    case CPP_AND_EQ:   yylval.code = BIT_AND_EXPR;     return ASSIGN;
+    case CPP_OR_EQ:    yylval.code = BIT_IOR_EXPR;     return ASSIGN;
+    case CPP_XOR_EQ:   yylval.code = BIT_XOR_EXPR;     return ASSIGN;
+    case CPP_RSHIFT_EQ:        yylval.code = RSHIFT_EXPR;      return ASSIGN;
+    case CPP_LSHIFT_EQ:        yylval.code = LSHIFT_EXPR;      return ASSIGN;
+
+    case CPP_OPEN_SQUARE:                              return '[';
+    case CPP_CLOSE_SQUARE:                             return ']';
+    case CPP_OPEN_BRACE:                               return '{';
+    case CPP_CLOSE_BRACE:                              return '}';
+    case CPP_SEMICOLON:                                        return ';';
+    case CPP_ELLIPSIS:                                 return ELLIPSIS;
+
+    case CPP_PLUS_PLUS:                                        return PLUSPLUS;
+    case CPP_MINUS_MINUS:                              return MINUSMINUS;
+    case CPP_DEREF:                                    return POINTSAT;
+    case CPP_DOT:                                      return '.';
+
+    case CPP_EOF:
+      cpp_pop_buffer (parse_in);
+      if (! CPP_BUFFER (parse_in))
+       return 0;
+      goto retry;
+
+    case CPP_NAME:
+      if (C_IS_RESERVED_WORD (yylval.ttype))
+       {
+         enum rid rid_code = C_RID_CODE (yylval.ttype);
+         /* Return the canonical spelling for this keyword.  */
+         yylval.ttype = ridpointers[(int) rid_code];
+         return rid_to_yy[(int) rid_code];
+       }
+
+      if (IDENTIFIER_POINTER (yylval.ttype)[0] == '@')
+       {
+         error ("invalid identifier `%s'", IDENTIFIER_POINTER (yylval.ttype));
+         return IDENTIFIER;
+       }
+
+      {
+       tree decl;
+
+       decl = lookup_name (yylval.ttype);
+
+       if (decl)
+         {
+           if (TREE_CODE (decl) == TYPE_DECL)
+             return TYPENAME;
+           /* A user-invisible read-only initialized variable
+              should be replaced by its value.
+              We handle only strings since that's the only case used in C.  */
+           else if (TREE_CODE (decl) == VAR_DECL
+                    && DECL_IGNORED_P (decl)
+                    && TREE_READONLY (decl)
+                    && DECL_INITIAL (decl) != 0
+                    && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+             {
+               tree stringval = DECL_INITIAL (decl);
+
+               /* Copy the string value so that we won't clobber anything
+                  if we put something in the TREE_CHAIN of this one.  */
+               yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
+                                            TREE_STRING_POINTER (stringval));
+               return STRING;
+             }
+         }
+       else if (doing_objc_thang)
+         {
+           tree objc_interface_decl = is_class_name (yylval.ttype);
+
+           if (objc_interface_decl)
+             {
+               yylval.ttype = objc_interface_decl;
+               return CLASSNAME;
+             }
+         }
+
+       return IDENTIFIER;
+      }
+
+    case CPP_INT:
+    case CPP_FLOAT:
+    case CPP_NUMBER:
+    case CPP_CHAR:
+    case CPP_WCHAR:
+      return CONSTANT;
+
+    case CPP_STRING:
+    case CPP_WSTRING:
+      return STRING;
+      
+    case CPP_OSTRING:
+      return OBJC_STRING;
+
+      /* These tokens are C++ specific (and will not be generated
+         in C mode, but let's be cautious).  */
+    case CPP_SCOPE:
+    case CPP_DEREF_STAR:
+    case CPP_DOT_STAR:
+    case CPP_MIN_EQ:
+    case CPP_MAX_EQ:
+    case CPP_MIN:
+    case CPP_MAX:
+      /* These tokens should not survive translation phase 4.  */
+    case CPP_HASH:
+    case CPP_PASTE:
+      error ("syntax error before '%s' token", NAME(last_token));
+      goto retry;
+
+    default:
+      abort ();
+    }
+
+  /* NOTREACHED */
+}
+
+static int
+yylex()
+{
+  int r;
+  timevar_push (TV_LEX);
+  r = _yylex();
+  timevar_pop (TV_LEX);
+  return r;
+}
+
+/* Sets the value of the 'yydebug' variable to VALUE.
+   This is a function so we don't have to have YYDEBUG defined
+   in order to build the compiler.  */
+
+void
+set_yydebug (value)
+     int value;
+{
+#if YYDEBUG != 0
+  yydebug = value;
+#else
+  warning ("YYDEBUG not defined.");
+#endif
+}
+
+/* Function used when yydebug is set, to print a token in more detail.  */
+
+static void
+yyprint (file, yychar, yyl)
+     FILE *file;
+     int yychar;
+     YYSTYPE yyl;
+{
+  tree t = yyl.ttype;
+
+  fprintf (file, " [%s]", NAME(last_token));
+  
+  switch (yychar)
+    {
+    case IDENTIFIER:
+    case TYPENAME:
+    case OBJECTNAME:
+    case TYPESPEC:
+    case TYPE_QUAL:
+    case SCSPEC:
+      if (IDENTIFIER_POINTER (t))
+       fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
+      break;
+
+    case CONSTANT:
+      fprintf (file, " %s", GET_MODE_NAME (TYPE_MODE (TREE_TYPE (t))));
+      if (TREE_CODE (t) == INTEGER_CST)
+       fprintf (file,
+#if HOST_BITS_PER_WIDE_INT == 64
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+                " 0x%x%016x",
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+                " 0x%lx%016lx",
+#else
+                " 0x%llx%016llx",
+#endif
+#endif
+#else
+#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
+                " 0x%lx%08lx",
+#else
+                " 0x%x%08x",
+#endif
+#endif
+                TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
+      break;
+    }
+}
+\f
+/* This is not the ideal place to put these, but we have to get them out
+   of c-lex.c because cp/lex.c has its own versions.  */
+
+/* Return something to represent absolute declarators containing a *.
+   TARGET is the absolute declarator that the * contains.
+   TYPE_QUALS is a list of modifiers such as const or volatile
+   to apply to the pointer type, represented as identifiers.
+
+   We return an INDIRECT_REF whose "contents" are TARGET
+   and whose type is the modifier list.  */
+
+tree
+make_pointer_declarator (type_quals, target)
+     tree type_quals, target;
+{
+  return build1 (INDIRECT_REF, type_quals, target);
+}