112099Sjoerg%{
2281168Spfg/* $NetBSD: cgram.y,v 1.40 2008/04/25 17:18:24 christos Exp $ */
312099Sjoerg
412099Sjoerg/*
591592Smarkm * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
612099Sjoerg * Copyright (c) 1994, 1995 Jochen Pohl
712099Sjoerg * All Rights Reserved.
812099Sjoerg *
912099Sjoerg * Redistribution and use in source and binary forms, with or without
1012099Sjoerg * modification, are permitted provided that the following conditions
1112099Sjoerg * are met:
1212099Sjoerg * 1. Redistributions of source code must retain the above copyright
1312099Sjoerg *    notice, this list of conditions and the following disclaimer.
1412099Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1512099Sjoerg *    notice, this list of conditions and the following disclaimer in the
1612099Sjoerg *    documentation and/or other materials provided with the distribution.
1712099Sjoerg * 3. All advertising materials mentioning features or use of this software
1812099Sjoerg *    must display the following acknowledgement:
1912099Sjoerg *      This product includes software developed by Jochen Pohl for
2012099Sjoerg *	The NetBSD Project.
2112099Sjoerg * 4. The name of the author may not be used to endorse or promote products
2212099Sjoerg *    derived from this software without specific prior written permission.
2312099Sjoerg *
2412099Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2512099Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2612099Sjoerg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2712099Sjoerg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2812099Sjoerg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2912099Sjoerg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3012099Sjoerg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3112099Sjoerg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3212099Sjoerg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3312099Sjoerg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3412099Sjoerg */
3512099Sjoerg
3691592Smarkm#include <sys/cdefs.h>
3791592Smarkm#if defined(__RCSID) && !defined(lint)
38281168Spfg__RCSID("$NetBSD: cgram.y,v 1.40 2008/04/25 17:18:24 christos Exp $");
3912099Sjoerg#endif
4091592Smarkm__FBSDID("$FreeBSD: releng/10.2/usr.bin/xlint/lint1/cgram.y 281168 2015-04-06 19:56:27Z pfg $");
4112099Sjoerg
4212099Sjoerg#include <stdlib.h>
4391592Smarkm#include <string.h>
4412099Sjoerg#include <limits.h>
4512099Sjoerg
4612099Sjoerg#include "lint1.h"
4712099Sjoerg
4812099Sjoerg/*
4912099Sjoerg * Contains the level of current declaration. 0 is extern.
5012099Sjoerg * Used for symbol table entries.
5112099Sjoerg */
5212099Sjoergint	blklev;
5312099Sjoerg
5412099Sjoerg/*
5512099Sjoerg * level for memory allocation. Normaly the same as blklev.
5612099Sjoerg * An exeption is the declaration of arguments in prototypes. Memory
5712099Sjoerg * for these can't be freed after the declaration, but symbols must
5812099Sjoerg * be removed from the symbol table after the declaration.
5912099Sjoerg */
6012099Sjoergint	mblklev;
6112099Sjoerg
6291592Smarkm/*
6391592Smarkm * Save the no-warns state and restore it to avoid the problem where
6491592Smarkm * if (expr) { stmt } / * NOLINT * / stmt;
6591592Smarkm */
6691592Smarkmstatic int onowarn = -1;
6712099Sjoerg
68281168Spfgstatic	int	toicon(tnode_t *, int);
6991592Smarkmstatic	void	idecl(sym_t *, int, sbuf_t *);
7091592Smarkmstatic	void	ignuptorp(void);
7191592Smarkm
7291592Smarkm#ifdef DEBUG
73281168Spfgstatic inline void CLRWFLGS(void);
74281168Spfgstatic inline void CLRWFLGS(void)
7591592Smarkm{
7691592Smarkm	printf("%s, %d: clear flags %s %d\n", curr_pos.p_file,
7791592Smarkm	    curr_pos.p_line, __FILE__, __LINE__);
7891592Smarkm	clrwflgs();
7991592Smarkm	onowarn = -1;
8091592Smarkm}
8191592Smarkm
82281168Spfgstatic inline void SAVE(void);
83281168Spfgstatic inline void SAVE(void)
8491592Smarkm{
8591592Smarkm	if (onowarn != -1)
8691592Smarkm		abort();
8791592Smarkm	printf("%s, %d: save flags %s %d = %d\n", curr_pos.p_file,
8891592Smarkm	    curr_pos.p_line, __FILE__, __LINE__, nowarn);
8991592Smarkm	onowarn = nowarn;
9091592Smarkm}
9191592Smarkm
92281168Spfgstatic inline void RESTORE(void);
93281168Spfgstatic inline void RESTORE(void)
9491592Smarkm{
9591592Smarkm	if (onowarn != -1) {
9691592Smarkm		nowarn = onowarn;
9791592Smarkm		printf("%s, %d: restore flags %s %d = %d\n", curr_pos.p_file,
9891592Smarkm		    curr_pos.p_line, __FILE__, __LINE__, nowarn);
9991592Smarkm		onowarn = -1;
10091592Smarkm	} else
10191592Smarkm		CLRWFLGS();
10291592Smarkm}
10391592Smarkm#else
10491592Smarkm#define CLRWFLGS() clrwflgs(), onowarn = -1
10591592Smarkm#define SAVE()	onowarn = nowarn
10691592Smarkm#define RESTORE() (void)(onowarn == -1 ? (clrwflgs(), 0) : (nowarn = onowarn))
10791592Smarkm#endif
10812099Sjoerg%}
10912099Sjoerg
110281168Spfg%expect 1
111281168Spfg
11212099Sjoerg%union {
11312099Sjoerg	int	y_int;
11412099Sjoerg	val_t	*y_val;
11512099Sjoerg	sbuf_t	*y_sb;
11612099Sjoerg	sym_t	*y_sym;
11712099Sjoerg	op_t	y_op;
11812099Sjoerg	scl_t	y_scl;
11912099Sjoerg	tspec_t	y_tspec;
12012099Sjoerg	tqual_t	y_tqual;
12112099Sjoerg	type_t	*y_type;
12212099Sjoerg	tnode_t	*y_tnode;
123281168Spfg	range_t	y_range;
12412099Sjoerg	strg_t	*y_strg;
12512099Sjoerg	pqinf_t	*y_pqinf;
12612099Sjoerg};
12712099Sjoerg
12812099Sjoerg%token			T_LBRACE T_RBRACE T_LBRACK T_RBRACK T_LPARN T_RPARN
12912099Sjoerg%token	<y_op>		T_STROP
13012099Sjoerg%token	<y_op>		T_UNOP
13112099Sjoerg%token	<y_op>		T_INCDEC
13212099Sjoerg%token			T_SIZEOF
13312099Sjoerg%token	<y_op>		T_MULT
13412099Sjoerg%token	<y_op>		T_DIVOP
13512099Sjoerg%token	<y_op>		T_ADDOP
13612099Sjoerg%token	<y_op>		T_SHFTOP
13712099Sjoerg%token	<y_op>		T_RELOP
13812099Sjoerg%token	<y_op>		T_EQOP
13912099Sjoerg%token	<y_op>		T_AND
14012099Sjoerg%token	<y_op>		T_XOR
14112099Sjoerg%token	<y_op>		T_OR
14212099Sjoerg%token	<y_op>		T_LOGAND
14312099Sjoerg%token	<y_op>		T_LOGOR
14412099Sjoerg%token			T_QUEST
14512099Sjoerg%token			T_COLON
14612099Sjoerg%token	<y_op>		T_ASSIGN
14712099Sjoerg%token	<y_op>		T_OPASS
14812099Sjoerg%token			T_COMMA
14912099Sjoerg%token			T_SEMI
15012099Sjoerg%token			T_ELLIPSE
15112099Sjoerg
15212099Sjoerg/* storage classes (extern, static, auto, register and typedef) */
15312099Sjoerg%token	<y_scl>		T_SCLASS
15412099Sjoerg
15512099Sjoerg/* types (char, int, short, long, unsigned, signed, float, double, void) */
15612099Sjoerg%token	<y_tspec>	T_TYPE
15712099Sjoerg
15812099Sjoerg/* qualifiers (const, volatile) */
15912099Sjoerg%token	<y_tqual>	T_QUAL
16012099Sjoerg
16112099Sjoerg/* struct or union */
16212099Sjoerg%token	<y_tspec>	T_SOU
16312099Sjoerg
16412099Sjoerg/* enum */
16512099Sjoerg%token			T_ENUM
16612099Sjoerg
16712099Sjoerg/* remaining keywords */
16812099Sjoerg%token			T_CASE
16912099Sjoerg%token			T_DEFAULT
17012099Sjoerg%token			T_IF
17112099Sjoerg%token			T_ELSE
17212099Sjoerg%token			T_SWITCH
17312099Sjoerg%token			T_DO
17412099Sjoerg%token			T_WHILE
17512099Sjoerg%token			T_FOR
17612099Sjoerg%token			T_GOTO
17712099Sjoerg%token			T_CONTINUE
17812099Sjoerg%token			T_BREAK
17912099Sjoerg%token			T_RETURN
18012099Sjoerg%token			T_ASM
18191592Smarkm%token			T_SYMBOLRENAME
18212099Sjoerg
18312099Sjoerg%left	T_COMMA
18412099Sjoerg%right	T_ASSIGN T_OPASS
18512099Sjoerg%right	T_QUEST T_COLON
18612099Sjoerg%left	T_LOGOR
18712099Sjoerg%left	T_LOGAND
18812099Sjoerg%left	T_OR
18912099Sjoerg%left	T_XOR
19012099Sjoerg%left	T_AND
19112099Sjoerg%left	T_EQOP
19212099Sjoerg%left	T_RELOP
19312099Sjoerg%left	T_SHFTOP
19412099Sjoerg%left	T_ADDOP
19512099Sjoerg%left	T_MULT T_DIVOP
19612099Sjoerg%right	T_UNOP T_INCDEC T_SIZEOF
19712099Sjoerg%left	T_LPARN T_LBRACK T_STROP
19812099Sjoerg
19912099Sjoerg%token	<y_sb>		T_NAME
20012099Sjoerg%token	<y_sb>		T_TYPENAME
20112099Sjoerg%token	<y_val>		T_CON
20212099Sjoerg%token	<y_strg>	T_STRING
20312099Sjoerg
20412099Sjoerg%type	<y_sym>		func_decl
20512099Sjoerg%type	<y_sym>		notype_decl
20612099Sjoerg%type	<y_sym>		type_decl
20712099Sjoerg%type	<y_type>	typespec
20812099Sjoerg%type	<y_type>	clrtyp_typespec
20912099Sjoerg%type	<y_type>	notype_typespec
21012099Sjoerg%type	<y_type>	struct_spec
21112099Sjoerg%type	<y_type>	enum_spec
21212099Sjoerg%type	<y_sym>		struct_tag
21312099Sjoerg%type	<y_sym>		enum_tag
21412099Sjoerg%type	<y_tspec>	struct
21512099Sjoerg%type	<y_sym>		struct_declaration
21612099Sjoerg%type	<y_sb>		identifier
21712099Sjoerg%type	<y_sym>		member_declaration_list_with_rbrace
21812099Sjoerg%type	<y_sym>		member_declaration_list
21912099Sjoerg%type	<y_sym>		member_declaration
22012099Sjoerg%type	<y_sym>		notype_member_decls
22112099Sjoerg%type	<y_sym>		type_member_decls
22212099Sjoerg%type	<y_sym>		notype_member_decl
22312099Sjoerg%type	<y_sym>		type_member_decl
22412099Sjoerg%type	<y_tnode>	constant
22512099Sjoerg%type	<y_sym>		enum_declaration
22612099Sjoerg%type	<y_sym>		enums_with_opt_comma
22712099Sjoerg%type	<y_sym>		enums
22812099Sjoerg%type	<y_sym>		enumerator
22912099Sjoerg%type	<y_sym>		ename
23012099Sjoerg%type	<y_sym>		notype_direct_decl
23112099Sjoerg%type	<y_sym>		type_direct_decl
23212099Sjoerg%type	<y_pqinf>	pointer
23312099Sjoerg%type	<y_pqinf>	asterisk
23412099Sjoerg%type	<y_sym>		param_decl
23512099Sjoerg%type	<y_sym>		param_list
23612099Sjoerg%type	<y_sym>		abs_decl_param_list
23712099Sjoerg%type	<y_sym>		direct_param_decl
23812099Sjoerg%type	<y_sym>		notype_param_decl
23912099Sjoerg%type	<y_sym>		direct_notype_param_decl
24012099Sjoerg%type	<y_pqinf>	type_qualifier_list
24112099Sjoerg%type	<y_pqinf>	type_qualifier
24212099Sjoerg%type	<y_sym>		identifier_list
24312099Sjoerg%type	<y_sym>		abs_decl
24412099Sjoerg%type	<y_sym>		direct_abs_decl
24512099Sjoerg%type	<y_sym>		vararg_parameter_type_list
24612099Sjoerg%type	<y_sym>		parameter_type_list
24712099Sjoerg%type	<y_sym>		parameter_declaration
24812099Sjoerg%type	<y_tnode>	expr
249281168Spfg%type	<y_tnode>	expr_stmnt_val
250281168Spfg%type	<y_tnode>	expr_stmnt_list
25112099Sjoerg%type	<y_tnode>	term
25212099Sjoerg%type	<y_tnode>	func_arg_list
25312099Sjoerg%type	<y_op>		point_or_arrow
25412099Sjoerg%type	<y_type>	type_name
25512099Sjoerg%type	<y_sym>		abstract_declaration
25612099Sjoerg%type	<y_tnode>	do_while_expr
25712099Sjoerg%type	<y_tnode>	opt_expr
25812099Sjoerg%type	<y_strg>	string
25912099Sjoerg%type	<y_strg>	string2
26091592Smarkm%type	<y_sb>		opt_asm_or_symbolrename
261281168Spfg%type	<y_range>	range
262281168Spfg%type	<y_range>	lorange
26312099Sjoerg
26412099Sjoerg
26512099Sjoerg%%
26612099Sjoerg
26712099Sjoergprogram:
26812099Sjoerg	  /* empty */ {
26912099Sjoerg		if (sflag) {
27012099Sjoerg			/* empty translation unit */
27112099Sjoerg			error(272);
27212099Sjoerg		} else if (!tflag) {
27312099Sjoerg			/* empty translation unit */
27412099Sjoerg			warning(272);
27512099Sjoerg		}
27612099Sjoerg	  }
27712099Sjoerg	| translation_unit
27812099Sjoerg	;
27912099Sjoerg
28012099Sjoergtranslation_unit:
28112099Sjoerg	  ext_decl
28212099Sjoerg	| translation_unit ext_decl
28312099Sjoerg	;
28412099Sjoerg
28512099Sjoergext_decl:
28691592Smarkm	  asm_stmnt
28791592Smarkm	| func_def {
28812099Sjoerg		glclup(0);
28991592Smarkm		CLRWFLGS();
29012099Sjoerg	  }
29112099Sjoerg	| data_def {
29212099Sjoerg		glclup(0);
29391592Smarkm		CLRWFLGS();
29412099Sjoerg	  }
29512099Sjoerg	;
29612099Sjoerg
29712099Sjoergdata_def:
29812099Sjoerg	  T_SEMI {
29912099Sjoerg		if (sflag) {
30012099Sjoerg			/* syntax error: empty declaration */
30112099Sjoerg			error(0);
30212099Sjoerg		} else if (!tflag) {
30312099Sjoerg			/* syntax error: empty declaration */
30412099Sjoerg			warning(0);
30512099Sjoerg		}
30612099Sjoerg	  }
30712099Sjoerg	| clrtyp deftyp notype_init_decls T_SEMI {
30812099Sjoerg		if (sflag) {
30912099Sjoerg			/* old style declaration; add "int" */
31012099Sjoerg			error(1);
31112099Sjoerg		} else if (!tflag) {
31212099Sjoerg			/* old style declaration; add "int" */
31312099Sjoerg			warning(1);
31412099Sjoerg		}
31512099Sjoerg	  }
31612099Sjoerg	| declmods deftyp T_SEMI {
31712099Sjoerg		if (dcs->d_scl == TYPEDEF) {
31812099Sjoerg			/* typedef declares no type name */
31912099Sjoerg			warning(72);
32012099Sjoerg		} else {
32112099Sjoerg			/* empty declaration */
32212099Sjoerg			warning(2);
32312099Sjoerg		}
32412099Sjoerg	  }
32512099Sjoerg	| declmods deftyp notype_init_decls T_SEMI
32612099Sjoerg	| declspecs deftyp T_SEMI {
32712099Sjoerg		if (dcs->d_scl == TYPEDEF) {
32812099Sjoerg			/* typedef declares no type name */
32912099Sjoerg			warning(72);
33012099Sjoerg		} else if (!dcs->d_nedecl) {
33112099Sjoerg			/* empty declaration */
33212099Sjoerg			warning(2);
33312099Sjoerg		}
33412099Sjoerg	  }
33512099Sjoerg	| declspecs deftyp type_init_decls T_SEMI
33612099Sjoerg	| error T_SEMI {
33791592Smarkm		globclup();
33812099Sjoerg	  }
33912099Sjoerg	| error T_RBRACE {
34012099Sjoerg		globclup();
34112099Sjoerg	  }
34212099Sjoerg	;
34312099Sjoerg
34412099Sjoergfunc_def:
34512099Sjoerg	  func_decl {
34612099Sjoerg		if ($1->s_type->t_tspec != FUNC) {
34712099Sjoerg			/* syntax error */
34812099Sjoerg			error(249);
34912099Sjoerg			YYERROR;
35012099Sjoerg		}
35112099Sjoerg		if ($1->s_type->t_typedef) {
35212099Sjoerg			/* ()-less function definition */
35312099Sjoerg			error(64);
35412099Sjoerg			YYERROR;
35512099Sjoerg		}
35612099Sjoerg		funcdef($1);
35712099Sjoerg		blklev++;
35812099Sjoerg		pushdecl(ARG);
35912099Sjoerg	  } opt_arg_declaration_list {
36012099Sjoerg		popdecl();
36112099Sjoerg		blklev--;
36212099Sjoerg		cluparg();
36312099Sjoerg		pushctrl(0);
36412099Sjoerg	  } comp_stmnt {
36512099Sjoerg		funcend();
36612099Sjoerg		popctrl(0);
36712099Sjoerg	  }
36812099Sjoerg	;
36912099Sjoerg
37012099Sjoergfunc_decl:
37112099Sjoerg	  clrtyp deftyp notype_decl {
37212099Sjoerg		$$ = $3;
37312099Sjoerg	  }
37412099Sjoerg	| declmods deftyp notype_decl {
37512099Sjoerg		$$ = $3;
37612099Sjoerg	  }
37712099Sjoerg	| declspecs deftyp type_decl {
37812099Sjoerg		$$ = $3;
37912099Sjoerg	  }
38012099Sjoerg	;
38112099Sjoerg
38212099Sjoergopt_arg_declaration_list:
38312099Sjoerg	  /* empty */
38412099Sjoerg	| arg_declaration_list
38512099Sjoerg	;
38612099Sjoerg
38712099Sjoergarg_declaration_list:
38812099Sjoerg	  arg_declaration
38912099Sjoerg	| arg_declaration_list arg_declaration
39012099Sjoerg	/* XXX or better "arg_declaration error" ? */
39112099Sjoerg	| error
39212099Sjoerg	;
39312099Sjoerg
39412099Sjoerg/*
39512099Sjoerg * "arg_declaration" is separated from "declaration" because it
39612099Sjoerg * needs other error handling.
39712099Sjoerg */
39812099Sjoerg
39912099Sjoergarg_declaration:
40012099Sjoerg	  declmods deftyp T_SEMI {
40112099Sjoerg		/* empty declaration */
40212099Sjoerg		warning(2);
40312099Sjoerg	  }
40412099Sjoerg	| declmods deftyp notype_init_decls T_SEMI
40512099Sjoerg	| declspecs deftyp T_SEMI {
40612099Sjoerg		if (!dcs->d_nedecl) {
40712099Sjoerg			/* empty declaration */
40812099Sjoerg			warning(2);
40912099Sjoerg		} else {
41012099Sjoerg			tspec_t	ts = dcs->d_type->t_tspec;
41112099Sjoerg			/* %s declared in argument declaration list */
41212099Sjoerg			warning(3, ts == STRUCT ? "struct" :
41312099Sjoerg				(ts == UNION ? "union" : "enum"));
41412099Sjoerg		}
41512099Sjoerg	  }
41612099Sjoerg	| declspecs deftyp type_init_decls T_SEMI {
41712099Sjoerg		if (dcs->d_nedecl) {
41812099Sjoerg			tspec_t	ts = dcs->d_type->t_tspec;
41912099Sjoerg			/* %s declared in argument declaration list */
42012099Sjoerg			warning(3, ts == STRUCT ? "struct" :
42112099Sjoerg				(ts == UNION ? "union" : "enum"));
42212099Sjoerg		}
42312099Sjoerg	  }
42412099Sjoerg	| declmods error
42512099Sjoerg	| declspecs error
42612099Sjoerg	;
42712099Sjoerg
42812099Sjoergdeclaration:
42912099Sjoerg	  declmods deftyp T_SEMI {
43012099Sjoerg		if (dcs->d_scl == TYPEDEF) {
43112099Sjoerg			/* typedef declares no type name */
43212099Sjoerg			warning(72);
43312099Sjoerg		} else {
43412099Sjoerg			/* empty declaration */
43512099Sjoerg			warning(2);
43612099Sjoerg		}
43712099Sjoerg	  }
43812099Sjoerg	| declmods deftyp notype_init_decls T_SEMI
43912099Sjoerg	| declspecs deftyp T_SEMI {
44012099Sjoerg		if (dcs->d_scl == TYPEDEF) {
44112099Sjoerg			/* typedef declares no type name */
44212099Sjoerg			warning(72);
44312099Sjoerg		} else if (!dcs->d_nedecl) {
44412099Sjoerg			/* empty declaration */
44512099Sjoerg			warning(2);
44612099Sjoerg		}
44712099Sjoerg	  }
44812099Sjoerg	| declspecs deftyp type_init_decls T_SEMI
44912099Sjoerg	| error T_SEMI
45012099Sjoerg	;
45112099Sjoerg
45212099Sjoergclrtyp:
45312099Sjoerg	  {
45412099Sjoerg		clrtyp();
45512099Sjoerg	  }
45612099Sjoerg	;
45712099Sjoerg
45812099Sjoergdeftyp:
45912099Sjoerg	  /* empty */ {
46012099Sjoerg		deftyp();
46112099Sjoerg	  }
46212099Sjoerg	;
46312099Sjoerg
46412099Sjoergdeclspecs:
46512099Sjoerg	  clrtyp_typespec {
46612099Sjoerg		addtype($1);
46712099Sjoerg	  }
46812099Sjoerg	| declmods typespec {
46912099Sjoerg		addtype($2);
47012099Sjoerg	  }
47112099Sjoerg	| declspecs declmod
47212099Sjoerg	| declspecs notype_typespec {
47312099Sjoerg		addtype($2);
47412099Sjoerg	  }
47512099Sjoerg	;
47612099Sjoerg
47712099Sjoergdeclmods:
47812099Sjoerg	  clrtyp T_QUAL {
47912099Sjoerg		addqual($2);
48012099Sjoerg	  }
48112099Sjoerg	| clrtyp T_SCLASS {
48212099Sjoerg		addscl($2);
48312099Sjoerg	  }
48412099Sjoerg	| declmods declmod
48512099Sjoerg	;
48612099Sjoerg
48712099Sjoergdeclmod:
48812099Sjoerg	  T_QUAL {
48912099Sjoerg		addqual($1);
49012099Sjoerg	  }
49112099Sjoerg	| T_SCLASS {
49212099Sjoerg		addscl($1);
49312099Sjoerg	  }
49412099Sjoerg	;
49512099Sjoerg
49612099Sjoergclrtyp_typespec:
49712099Sjoerg	  clrtyp notype_typespec {
49812099Sjoerg		$$ = $2;
49912099Sjoerg	  }
50012099Sjoerg	| T_TYPENAME clrtyp {
50112099Sjoerg		$$ = getsym($1)->s_type;
50212099Sjoerg	  }
50312099Sjoerg	;
50412099Sjoerg
50512099Sjoergtypespec:
50612099Sjoerg	  notype_typespec {
50712099Sjoerg		$$ = $1;
50812099Sjoerg	  }
50912099Sjoerg	| T_TYPENAME {
51012099Sjoerg		$$ = getsym($1)->s_type;
51112099Sjoerg	  }
51212099Sjoerg	;
51312099Sjoerg
51412099Sjoergnotype_typespec:
51512099Sjoerg	  T_TYPE {
51612099Sjoerg		$$ = gettyp($1);
51712099Sjoerg	  }
51812099Sjoerg	| struct_spec {
51912099Sjoerg		popdecl();
52012099Sjoerg		$$ = $1;
52112099Sjoerg	  }
52212099Sjoerg	| enum_spec {
52312099Sjoerg		popdecl();
52412099Sjoerg		$$ = $1;
52512099Sjoerg	  }
52612099Sjoerg	;
52712099Sjoerg
52812099Sjoergstruct_spec:
52912099Sjoerg	  struct struct_tag {
53012099Sjoerg		/*
53112099Sjoerg		 * STDC requires that "struct a;" always introduces
53212099Sjoerg		 * a new tag if "a" is not declared at current level
53312099Sjoerg		 *
53412099Sjoerg		 * yychar is valid because otherwise the parser would
53512099Sjoerg		 * not been able to deceide if he must shift or reduce
53612099Sjoerg		 */
53712099Sjoerg		$$ = mktag($2, $1, 0, yychar == T_SEMI);
53812099Sjoerg	  }
53912099Sjoerg	| struct struct_tag {
54012099Sjoerg		dcs->d_tagtyp = mktag($2, $1, 1, 0);
54112099Sjoerg	  } struct_declaration {
54212099Sjoerg		$$ = compltag(dcs->d_tagtyp, $4);
54312099Sjoerg	  }
54412099Sjoerg	| struct {
54512099Sjoerg		dcs->d_tagtyp = mktag(NULL, $1, 1, 0);
54612099Sjoerg	  } struct_declaration {
54712099Sjoerg		$$ = compltag(dcs->d_tagtyp, $3);
54812099Sjoerg	  }
54912099Sjoerg	| struct error {
55012099Sjoerg		symtyp = FVFT;
55112099Sjoerg		$$ = gettyp(INT);
55212099Sjoerg	  }
55312099Sjoerg	;
55412099Sjoerg
55512099Sjoergstruct:
55612099Sjoerg	  T_SOU {
55712099Sjoerg		symtyp = FTAG;
55812099Sjoerg		pushdecl($1 == STRUCT ? MOS : MOU);
55912099Sjoerg		dcs->d_offset = 0;
56012099Sjoerg		dcs->d_stralign = CHAR_BIT;
56112099Sjoerg		$$ = $1;
56212099Sjoerg	  }
56312099Sjoerg	;
56412099Sjoerg
56512099Sjoergstruct_tag:
56612099Sjoerg	  identifier {
56712099Sjoerg		$$ = getsym($1);
56812099Sjoerg	  }
56912099Sjoerg	;
57012099Sjoerg
57112099Sjoergstruct_declaration:
57212099Sjoerg	  struct_decl_lbrace member_declaration_list_with_rbrace {
57312099Sjoerg		$$ = $2;
57412099Sjoerg	  }
57512099Sjoerg	;
57612099Sjoerg
57712099Sjoergstruct_decl_lbrace:
57812099Sjoerg	  T_LBRACE {
57912099Sjoerg		symtyp = FVFT;
58012099Sjoerg	  }
58112099Sjoerg	;
58212099Sjoerg
58312099Sjoergmember_declaration_list_with_rbrace:
58412099Sjoerg	  member_declaration_list T_SEMI T_RBRACE {
58512099Sjoerg		$$ = $1;
58612099Sjoerg	  }
58712099Sjoerg	| member_declaration_list T_RBRACE {
58812099Sjoerg		if (sflag) {
58912099Sjoerg			/* syntax req. ";" after last struct/union member */
59012099Sjoerg			error(66);
59112099Sjoerg		} else {
59212099Sjoerg			/* syntax req. ";" after last struct/union member */
59312099Sjoerg			warning(66);
59412099Sjoerg		}
59512099Sjoerg		$$ = $1;
59612099Sjoerg	  }
59712099Sjoerg	| T_RBRACE {
59812099Sjoerg		$$ = NULL;
59912099Sjoerg	  }
60012099Sjoerg	;
60112099Sjoerg
60212099Sjoergmember_declaration_list:
60312099Sjoerg	  member_declaration {
60412099Sjoerg		$$ = $1;
60512099Sjoerg	  }
60612099Sjoerg	| member_declaration_list T_SEMI member_declaration {
60712099Sjoerg		$$ = lnklst($1, $3);
60812099Sjoerg	  }
60912099Sjoerg	;
61012099Sjoerg
61112099Sjoergmember_declaration:
61212099Sjoerg	  noclass_declmods deftyp {
61312099Sjoerg		/* too late, i know, but getsym() compensates it */
61412099Sjoerg		symtyp = FMOS;
61512099Sjoerg	  } notype_member_decls {
61612099Sjoerg		symtyp = FVFT;
61712099Sjoerg		$$ = $4;
61812099Sjoerg	  }
61912099Sjoerg	| noclass_declspecs deftyp {
62012099Sjoerg		symtyp = FMOS;
62112099Sjoerg	  } type_member_decls {
62212099Sjoerg		symtyp = FVFT;
62312099Sjoerg		$$ = $4;
62412099Sjoerg	  }
62512099Sjoerg	| noclass_declmods deftyp {
62612099Sjoerg		/* struct or union member must be named */
62712099Sjoerg		warning(49);
62812099Sjoerg		$$ = NULL;
62912099Sjoerg	  }
63012099Sjoerg	| noclass_declspecs deftyp {
63112099Sjoerg		/* struct or union member must be named */
63212099Sjoerg		warning(49);
63312099Sjoerg		$$ = NULL;
63412099Sjoerg	  }
63512099Sjoerg	| error {
63612099Sjoerg		symtyp = FVFT;
63712099Sjoerg		$$ = NULL;
63812099Sjoerg	  }
63912099Sjoerg	;
64012099Sjoerg
64112099Sjoergnoclass_declspecs:
64212099Sjoerg	  clrtyp_typespec {
64312099Sjoerg		addtype($1);
64412099Sjoerg	  }
64512099Sjoerg	| noclass_declmods typespec {
64612099Sjoerg		addtype($2);
64712099Sjoerg	  }
64812099Sjoerg	| noclass_declspecs T_QUAL {
64912099Sjoerg		addqual($2);
65012099Sjoerg	  }
65112099Sjoerg	| noclass_declspecs notype_typespec {
65212099Sjoerg		addtype($2);
65312099Sjoerg	  }
65412099Sjoerg	;
65512099Sjoerg
65612099Sjoergnoclass_declmods:
65712099Sjoerg	  clrtyp T_QUAL {
65812099Sjoerg		addqual($2);
65912099Sjoerg	  }
66012099Sjoerg	| noclass_declmods T_QUAL {
66112099Sjoerg		addqual($2);
66212099Sjoerg	  }
66312099Sjoerg	;
66412099Sjoerg
66512099Sjoergnotype_member_decls:
66612099Sjoerg	  notype_member_decl {
66712099Sjoerg		$$ = decl1str($1);
66812099Sjoerg	  }
66912099Sjoerg	| notype_member_decls {
67012099Sjoerg		symtyp = FMOS;
67112099Sjoerg	  } T_COMMA type_member_decl {
67212099Sjoerg		$$ = lnklst($1, decl1str($4));
67312099Sjoerg	  }
67412099Sjoerg	;
67512099Sjoerg
67612099Sjoergtype_member_decls:
67712099Sjoerg	  type_member_decl {
67812099Sjoerg		$$ = decl1str($1);
67912099Sjoerg	  }
68012099Sjoerg	| type_member_decls {
68112099Sjoerg		symtyp = FMOS;
68212099Sjoerg	  } T_COMMA type_member_decl {
68312099Sjoerg		$$ = lnklst($1, decl1str($4));
68412099Sjoerg	  }
68512099Sjoerg	;
68612099Sjoerg
68712099Sjoergnotype_member_decl:
68812099Sjoerg	  notype_decl {
68912099Sjoerg		$$ = $1;
69012099Sjoerg	  }
69112099Sjoerg	| notype_decl T_COLON constant {
692281168Spfg		$$ = bitfield($1, toicon($3, 1));
69312099Sjoerg	  }
69412099Sjoerg	| {
69512099Sjoerg		symtyp = FVFT;
69612099Sjoerg	  } T_COLON constant {
697281168Spfg		$$ = bitfield(NULL, toicon($3, 1));
69812099Sjoerg	  }
69912099Sjoerg	;
70012099Sjoerg
70112099Sjoergtype_member_decl:
70212099Sjoerg	  type_decl {
70312099Sjoerg		$$ = $1;
70412099Sjoerg	  }
70512099Sjoerg	| type_decl T_COLON constant {
706281168Spfg		$$ = bitfield($1, toicon($3, 1));
70712099Sjoerg	  }
70812099Sjoerg	| {
70912099Sjoerg		symtyp = FVFT;
71012099Sjoerg	  } T_COLON constant {
711281168Spfg		$$ = bitfield(NULL, toicon($3, 1));
71212099Sjoerg	  }
71312099Sjoerg	;
71412099Sjoerg
71512099Sjoergenum_spec:
71612099Sjoerg	  enum enum_tag {
71712099Sjoerg		$$ = mktag($2, ENUM, 0, 0);
71812099Sjoerg	  }
71912099Sjoerg	| enum enum_tag {
72012099Sjoerg		dcs->d_tagtyp = mktag($2, ENUM, 1, 0);
72112099Sjoerg	  } enum_declaration {
72212099Sjoerg		$$ = compltag(dcs->d_tagtyp, $4);
72312099Sjoerg	  }
72412099Sjoerg	| enum {
72512099Sjoerg		dcs->d_tagtyp = mktag(NULL, ENUM, 1, 0);
72612099Sjoerg	  } enum_declaration {
72712099Sjoerg		$$ = compltag(dcs->d_tagtyp, $3);
72812099Sjoerg	  }
72912099Sjoerg	| enum error {
73012099Sjoerg		symtyp = FVFT;
73112099Sjoerg		$$ = gettyp(INT);
73212099Sjoerg	  }
73312099Sjoerg	;
73412099Sjoerg
73512099Sjoergenum:
73612099Sjoerg	  T_ENUM {
73712099Sjoerg		symtyp = FTAG;
73812099Sjoerg		pushdecl(ENUMCON);
73912099Sjoerg	  }
74012099Sjoerg	;
74112099Sjoerg
74212099Sjoergenum_tag:
74312099Sjoerg	  identifier {
74412099Sjoerg		$$ = getsym($1);
74512099Sjoerg	  }
74612099Sjoerg	;
74712099Sjoerg
74812099Sjoergenum_declaration:
74912099Sjoerg	  enum_decl_lbrace enums_with_opt_comma T_RBRACE {
75012099Sjoerg		$$ = $2;
75112099Sjoerg	  }
75212099Sjoerg	;
75312099Sjoerg
75412099Sjoergenum_decl_lbrace:
75512099Sjoerg	  T_LBRACE {
75612099Sjoerg		symtyp = FVFT;
75712099Sjoerg		enumval = 0;
75812099Sjoerg	  }
75912099Sjoerg	;
76012099Sjoerg
76112099Sjoergenums_with_opt_comma:
76212099Sjoerg	  enums {
76312099Sjoerg		$$ = $1;
76412099Sjoerg	  }
76512099Sjoerg	| enums T_COMMA {
76612099Sjoerg		if (sflag) {
76712099Sjoerg			/* trailing "," prohibited in enum declaration */
76812099Sjoerg			error(54);
76912099Sjoerg		} else {
77012099Sjoerg			/* trailing "," prohibited in enum declaration */
77191592Smarkm			(void)gnuism(54);
77212099Sjoerg		}
77312099Sjoerg		$$ = $1;
77412099Sjoerg	  }
77512099Sjoerg	;
77612099Sjoerg
77712099Sjoergenums:
77812099Sjoerg	  enumerator {
77912099Sjoerg		$$ = $1;
78012099Sjoerg	  }
78112099Sjoerg	| enums T_COMMA enumerator {
78212099Sjoerg		$$ = lnklst($1, $3);
78312099Sjoerg	  }
78412099Sjoerg	| error {
78512099Sjoerg		$$ = NULL;
78612099Sjoerg	  }
78712099Sjoerg	;
78812099Sjoerg
78912099Sjoergenumerator:
79012099Sjoerg	  ename {
79112099Sjoerg		$$ = ename($1, enumval, 1);
79212099Sjoerg	  }
79312099Sjoerg	| ename T_ASSIGN constant {
794281168Spfg		$$ = ename($1, toicon($3, 1), 0);
79512099Sjoerg	  }
79612099Sjoerg	;
79712099Sjoerg
79812099Sjoergename:
79912099Sjoerg	  identifier {
80012099Sjoerg		$$ = getsym($1);
80112099Sjoerg	  }
80212099Sjoerg	;
80312099Sjoerg
80412099Sjoerg
80512099Sjoergnotype_init_decls:
80612099Sjoerg	  notype_init_decl
80712099Sjoerg	| notype_init_decls T_COMMA type_init_decl
80812099Sjoerg	;
80912099Sjoerg
81012099Sjoergtype_init_decls:
81112099Sjoerg	  type_init_decl
81212099Sjoerg	| type_init_decls T_COMMA type_init_decl
81312099Sjoerg	;
81412099Sjoerg
81512099Sjoergnotype_init_decl:
81691592Smarkm	  notype_decl opt_asm_or_symbolrename {
81791592Smarkm		idecl($1, 0, $2);
81812099Sjoerg		chksz($1);
81912099Sjoerg	  }
82091592Smarkm	| notype_decl opt_asm_or_symbolrename {
82191592Smarkm		idecl($1, 1, $2);
82212099Sjoerg	  } T_ASSIGN initializer {
82312099Sjoerg		chksz($1);
82412099Sjoerg	  }
82512099Sjoerg	;
82612099Sjoerg
82712099Sjoergtype_init_decl:
82891592Smarkm	  type_decl opt_asm_or_symbolrename {
82991592Smarkm		idecl($1, 0, $2);
83012099Sjoerg		chksz($1);
83112099Sjoerg	  }
83291592Smarkm	| type_decl opt_asm_or_symbolrename {
83391592Smarkm		idecl($1, 1, $2);
83412099Sjoerg	  } T_ASSIGN initializer {
83512099Sjoerg		chksz($1);
83612099Sjoerg	  }
83712099Sjoerg	;
83812099Sjoerg
83912099Sjoergnotype_decl:
84012099Sjoerg	  notype_direct_decl {
84112099Sjoerg		$$ = $1;
84212099Sjoerg	  }
84312099Sjoerg	| pointer notype_direct_decl {
84412099Sjoerg		$$ = addptr($2, $1);
84512099Sjoerg	  }
84612099Sjoerg	;
84712099Sjoerg
84812099Sjoergnotype_direct_decl:
84912099Sjoerg	  T_NAME {
85012099Sjoerg		$$ = dname(getsym($1));
85112099Sjoerg	  }
85212099Sjoerg	| T_LPARN type_decl T_RPARN {
85312099Sjoerg		$$ = $2;
85412099Sjoerg	  }
85512099Sjoerg	| notype_direct_decl T_LBRACK T_RBRACK {
85612099Sjoerg		$$ = addarray($1, 0, 0);
85712099Sjoerg	  }
85812099Sjoerg	| notype_direct_decl T_LBRACK constant T_RBRACK {
859281168Spfg		$$ = addarray($1, 1, toicon($3, 0));
86012099Sjoerg	  }
86112099Sjoerg	| notype_direct_decl param_list {
86212099Sjoerg		$$ = addfunc($1, $2);
86312099Sjoerg		popdecl();
86412099Sjoerg		blklev--;
86512099Sjoerg	  }
86612099Sjoerg	;
86712099Sjoerg
86812099Sjoergtype_decl:
86912099Sjoerg	  type_direct_decl {
87012099Sjoerg		$$ = $1;
87112099Sjoerg	  }
87212099Sjoerg	| pointer type_direct_decl {
87312099Sjoerg		$$ = addptr($2, $1);
87412099Sjoerg	  }
87512099Sjoerg	;
87612099Sjoerg
87712099Sjoergtype_direct_decl:
87812099Sjoerg	  identifier {
87912099Sjoerg		$$ = dname(getsym($1));
88012099Sjoerg	  }
88112099Sjoerg	| T_LPARN type_decl T_RPARN {
88212099Sjoerg		$$ = $2;
88312099Sjoerg	  }
88412099Sjoerg	| type_direct_decl T_LBRACK T_RBRACK {
88512099Sjoerg		$$ = addarray($1, 0, 0);
88612099Sjoerg	  }
88712099Sjoerg	| type_direct_decl T_LBRACK constant T_RBRACK {
888281168Spfg		$$ = addarray($1, 1, toicon($3, 0));
88912099Sjoerg	  }
89012099Sjoerg	| type_direct_decl param_list {
89112099Sjoerg		$$ = addfunc($1, $2);
89212099Sjoerg		popdecl();
89312099Sjoerg		blklev--;
89412099Sjoerg	  }
89512099Sjoerg	;
89612099Sjoerg
89712099Sjoerg/*
89812099Sjoerg * param_decl and notype_param_decl exist to avoid a conflict in
89912099Sjoerg * argument lists. A typename enclosed in parens should always be
90012099Sjoerg * treated as a typename, not an argument.
90112099Sjoerg * "typedef int a; f(int (a));" is  "typedef int a; f(int foo(a));"
90212099Sjoerg *				not "typedef int a; f(int a);"
90312099Sjoerg */
90412099Sjoergparam_decl:
90512099Sjoerg	  direct_param_decl {
90612099Sjoerg		$$ = $1;
90712099Sjoerg	  }
90812099Sjoerg	| pointer direct_param_decl {
90912099Sjoerg		$$ = addptr($2, $1);
91012099Sjoerg	  }
91112099Sjoerg	;
91212099Sjoerg
91312099Sjoergdirect_param_decl:
91412099Sjoerg	  identifier {
91512099Sjoerg		$$ = dname(getsym($1));
91612099Sjoerg	  }
91712099Sjoerg	| T_LPARN notype_param_decl T_RPARN {
91812099Sjoerg		$$ = $2;
91912099Sjoerg	  }
92012099Sjoerg	| direct_param_decl T_LBRACK T_RBRACK {
92112099Sjoerg		$$ = addarray($1, 0, 0);
92212099Sjoerg	  }
92312099Sjoerg	| direct_param_decl T_LBRACK constant T_RBRACK {
924281168Spfg		$$ = addarray($1, 1, toicon($3, 0));
92512099Sjoerg	  }
92612099Sjoerg	| direct_param_decl param_list {
92712099Sjoerg		$$ = addfunc($1, $2);
92812099Sjoerg		popdecl();
92912099Sjoerg		blklev--;
93012099Sjoerg	  }
93112099Sjoerg	;
93212099Sjoerg
93312099Sjoergnotype_param_decl:
93412099Sjoerg	  direct_notype_param_decl {
93512099Sjoerg		$$ = $1;
93612099Sjoerg	  }
93712099Sjoerg	| pointer direct_notype_param_decl {
93812099Sjoerg		$$ = addptr($2, $1);
93912099Sjoerg	  }
94012099Sjoerg	;
94112099Sjoerg
94212099Sjoergdirect_notype_param_decl:
94312099Sjoerg	  T_NAME {
94412099Sjoerg		$$ = dname(getsym($1));
94512099Sjoerg	  }
94612099Sjoerg	| T_LPARN notype_param_decl T_RPARN {
94712099Sjoerg		$$ = $2;
94812099Sjoerg	  }
94912099Sjoerg	| direct_notype_param_decl T_LBRACK T_RBRACK {
95012099Sjoerg		$$ = addarray($1, 0, 0);
95112099Sjoerg	  }
95212099Sjoerg	| direct_notype_param_decl T_LBRACK constant T_RBRACK {
953281168Spfg		$$ = addarray($1, 1, toicon($3, 0));
95412099Sjoerg	  }
95512099Sjoerg	| direct_notype_param_decl param_list {
95612099Sjoerg		$$ = addfunc($1, $2);
95712099Sjoerg		popdecl();
95812099Sjoerg		blklev--;
95912099Sjoerg	  }
96012099Sjoerg	;
96112099Sjoerg
96212099Sjoergpointer:
96312099Sjoerg	  asterisk {
96412099Sjoerg		$$ = $1;
96512099Sjoerg	  }
96612099Sjoerg	| asterisk type_qualifier_list {
96712099Sjoerg		$$ = mergepq($1, $2);
96812099Sjoerg	  }
96912099Sjoerg	| asterisk pointer {
97012099Sjoerg		$$ = mergepq($1, $2);
97112099Sjoerg	  }
97212099Sjoerg	| asterisk type_qualifier_list pointer {
97312099Sjoerg		$$ = mergepq(mergepq($1, $2), $3);
97412099Sjoerg	  }
97512099Sjoerg	;
97612099Sjoerg
97712099Sjoergasterisk:
97812099Sjoerg	  T_MULT {
97991592Smarkm		$$ = xcalloc(1, sizeof (pqinf_t));
98012099Sjoerg		$$->p_pcnt = 1;
98112099Sjoerg	  }
98212099Sjoerg	;
98312099Sjoerg
98412099Sjoergtype_qualifier_list:
98512099Sjoerg	  type_qualifier {
98612099Sjoerg		$$ = $1;
98712099Sjoerg	  }
98812099Sjoerg	| type_qualifier_list type_qualifier {
98912099Sjoerg		$$ = mergepq($1, $2);
99012099Sjoerg	  }
99112099Sjoerg	;
99212099Sjoerg
99312099Sjoergtype_qualifier:
99412099Sjoerg	  T_QUAL {
99591592Smarkm		$$ = xcalloc(1, sizeof (pqinf_t));
99612099Sjoerg		if ($1 == CONST) {
99712099Sjoerg			$$->p_const = 1;
99812099Sjoerg		} else {
99912099Sjoerg			$$->p_volatile = 1;
100012099Sjoerg		}
100112099Sjoerg	  }
100212099Sjoerg	;
100312099Sjoerg
100412099Sjoergparam_list:
100512099Sjoerg	  id_list_lparn identifier_list T_RPARN {
100612099Sjoerg		$$ = $2;
100712099Sjoerg	  }
100812099Sjoerg	| abs_decl_param_list {
100912099Sjoerg		$$ = $1;
101012099Sjoerg	  }
101112099Sjoerg	;
101212099Sjoerg
101312099Sjoergid_list_lparn:
101412099Sjoerg	  T_LPARN {
101512099Sjoerg		blklev++;
101612099Sjoerg		pushdecl(PARG);
101712099Sjoerg	  }
101812099Sjoerg	;
101912099Sjoerg
102012099Sjoergidentifier_list:
102112099Sjoerg	  T_NAME {
102212099Sjoerg		$$ = iname(getsym($1));
102312099Sjoerg	  }
102412099Sjoerg	| identifier_list T_COMMA T_NAME {
102512099Sjoerg		$$ = lnklst($1, iname(getsym($3)));
102612099Sjoerg	  }
102712099Sjoerg	| identifier_list error {
102812099Sjoerg		$$ = $1;
102912099Sjoerg	  }
103012099Sjoerg	;
103112099Sjoerg
103212099Sjoergabs_decl_param_list:
103312099Sjoerg	  abs_decl_lparn T_RPARN {
103412099Sjoerg		$$ = NULL;
103512099Sjoerg	  }
103612099Sjoerg	| abs_decl_lparn vararg_parameter_type_list T_RPARN {
103712099Sjoerg		dcs->d_proto = 1;
103812099Sjoerg		$$ = $2;
103912099Sjoerg	  }
104012099Sjoerg	| abs_decl_lparn error T_RPARN {
104112099Sjoerg		$$ = NULL;
104212099Sjoerg	  }
104312099Sjoerg	;
104412099Sjoerg
104512099Sjoergabs_decl_lparn:
104612099Sjoerg	  T_LPARN {
104712099Sjoerg		blklev++;
104812099Sjoerg		pushdecl(PARG);
104912099Sjoerg	  }
105012099Sjoerg	;
105112099Sjoerg
105212099Sjoergvararg_parameter_type_list:
105312099Sjoerg	  parameter_type_list {
105412099Sjoerg		$$ = $1;
105512099Sjoerg	  }
105612099Sjoerg	| parameter_type_list T_COMMA T_ELLIPSE {
105712099Sjoerg		dcs->d_vararg = 1;
105812099Sjoerg		$$ = $1;
105912099Sjoerg	  }
106012099Sjoerg	| T_ELLIPSE {
106112099Sjoerg		if (sflag) {
106212099Sjoerg			/* ANSI C requires formal parameter before "..." */
106312099Sjoerg			error(84);
106412099Sjoerg		} else if (!tflag) {
106512099Sjoerg			/* ANSI C requires formal parameter before "..." */
106612099Sjoerg			warning(84);
106712099Sjoerg		}
106812099Sjoerg		dcs->d_vararg = 1;
106912099Sjoerg		$$ = NULL;
107012099Sjoerg	  }
107112099Sjoerg	;
107212099Sjoerg
107312099Sjoergparameter_type_list:
107491592Smarkm	  parameter_declaration {
107512099Sjoerg		$$ = $1;
107612099Sjoerg	  }
107791592Smarkm	| parameter_type_list T_COMMA parameter_declaration {
107812099Sjoerg		$$ = lnklst($1, $3);
107912099Sjoerg	  }
108012099Sjoerg	;
108112099Sjoerg
108212099Sjoergparameter_declaration:
108312099Sjoerg	  declmods deftyp {
108412099Sjoerg		$$ = decl1arg(aname(), 0);
108512099Sjoerg	  }
108612099Sjoerg	| declspecs deftyp {
108712099Sjoerg		$$ = decl1arg(aname(), 0);
108812099Sjoerg	  }
108912099Sjoerg	| declmods deftyp notype_param_decl {
109012099Sjoerg		$$ = decl1arg($3, 0);
109112099Sjoerg	  }
109212099Sjoerg	/*
109312099Sjoerg	 * param_decl is needed because of following conflict:
109412099Sjoerg	 * "typedef int a; f(int (a));" could be parsed as
109512099Sjoerg	 * "function with argument a of type int", or
109612099Sjoerg	 * "function with an abstract argument of type function".
109712099Sjoerg	 * This grammar realizes the second case.
109812099Sjoerg	 */
109912099Sjoerg	| declspecs deftyp param_decl {
110012099Sjoerg		$$ = decl1arg($3, 0);
110112099Sjoerg	  }
110212099Sjoerg	| declmods deftyp abs_decl {
110312099Sjoerg		$$ = decl1arg($3, 0);
110412099Sjoerg	  }
110512099Sjoerg	| declspecs deftyp abs_decl {
110612099Sjoerg		$$ = decl1arg($3, 0);
110712099Sjoerg	  }
110812099Sjoerg	;
110912099Sjoerg
111091592Smarkmopt_asm_or_symbolrename:		/* expect only one */
111191592Smarkm	  /* empty */ {
111291592Smarkm		$$ = NULL;
111391592Smarkm	  }
111412099Sjoerg	| T_ASM T_LPARN T_STRING T_RPARN {
111512099Sjoerg		freeyyv(&$3, T_STRING);
111691592Smarkm		$$ = NULL;
111712099Sjoerg	  }
111891592Smarkm	| T_SYMBOLRENAME T_LPARN T_NAME T_RPARN {
111991592Smarkm		$$ = $3;
112091592Smarkm	  }
112112099Sjoerg	;
112212099Sjoerg
112312099Sjoerginitializer:
112412099Sjoerg	  init_expr
112512099Sjoerg	;
112612099Sjoerg
112712099Sjoerginit_expr:
112812099Sjoerg	  expr				%prec T_COMMA {
112912099Sjoerg		mkinit($1);
113012099Sjoerg	  }
1131281168Spfg	| init_by_name init_expr	%prec T_COMMA
113212099Sjoerg	| init_lbrace init_expr_list init_rbrace
113312099Sjoerg	| init_lbrace init_expr_list T_COMMA init_rbrace
113412099Sjoerg	| error
113512099Sjoerg	;
113612099Sjoerg
113712099Sjoerginit_expr_list:
113812099Sjoerg	  init_expr			%prec T_COMMA
113912099Sjoerg	| init_expr_list T_COMMA init_expr
114012099Sjoerg	;
114112099Sjoerg
1142281168Spfglorange:
1143281168Spfg	  constant T_ELLIPSE {
1144281168Spfg		$$.lo = toicon($1, 1);
1145281168Spfg	  }
1146281168Spfg	;
1147281168Spfgrange:
1148281168Spfg	constant {
1149281168Spfg		$$.lo = toicon($1, 1);
1150281168Spfg		$$.hi = $$.lo + 1;
1151281168Spfg	  }
1152281168Spfg	| lorange constant {
1153281168Spfg		$$.lo = $1.lo;
1154281168Spfg		$$.hi = toicon($2, 1);
1155281168Spfg	  }
1156281168Spfg	;
1157281168Spfg
1158281168Spfginit_by_name:
1159281168Spfg	  T_LBRACK range T_RBRACK T_ASSIGN {
1160281168Spfg		if (!Sflag)
1161281168Spfg			warning(321);
1162281168Spfg	  }
1163281168Spfg	| point identifier T_ASSIGN {
1164281168Spfg		if (!Sflag)
1165281168Spfg			warning(313);
1166281168Spfg		memberpush($2);
1167281168Spfg	  }
1168281168Spfg	| identifier T_COLON {
1169281168Spfg		gnuism(315);
1170281168Spfg		memberpush($1);
1171281168Spfg	  }
1172281168Spfg	;
1173281168Spfg
117412099Sjoerginit_lbrace:
117512099Sjoerg	  T_LBRACE {
117612099Sjoerg		initlbr();
117712099Sjoerg	  }
117812099Sjoerg	;
117912099Sjoerg
118012099Sjoerginit_rbrace:
118112099Sjoerg	  T_RBRACE {
118212099Sjoerg		initrbr();
118312099Sjoerg	  }
118412099Sjoerg	;
118512099Sjoerg
118612099Sjoergtype_name:
118712099Sjoerg	  {
118812099Sjoerg		pushdecl(ABSTRACT);
118912099Sjoerg	  } abstract_declaration {
119012099Sjoerg		popdecl();
119112099Sjoerg		$$ = $2->s_type;
119212099Sjoerg	  }
119312099Sjoerg	;
119412099Sjoerg
119512099Sjoergabstract_declaration:
119612099Sjoerg	  noclass_declmods deftyp {
119712099Sjoerg		$$ = decl1abs(aname());
119812099Sjoerg	  }
119912099Sjoerg	| noclass_declspecs deftyp {
120012099Sjoerg		$$ = decl1abs(aname());
120112099Sjoerg	  }
120212099Sjoerg	| noclass_declmods deftyp abs_decl {
120312099Sjoerg		$$ = decl1abs($3);
120412099Sjoerg	  }
120512099Sjoerg	| noclass_declspecs deftyp abs_decl {
120612099Sjoerg		$$ = decl1abs($3);
120712099Sjoerg	  }
120812099Sjoerg	;
120912099Sjoerg
121012099Sjoergabs_decl:
121112099Sjoerg	  pointer {
121212099Sjoerg		$$ = addptr(aname(), $1);
121312099Sjoerg	  }
121412099Sjoerg	| direct_abs_decl {
121512099Sjoerg		$$ = $1;
121612099Sjoerg	  }
121712099Sjoerg	| pointer direct_abs_decl {
121812099Sjoerg		$$ = addptr($2, $1);
121912099Sjoerg	  }
122012099Sjoerg	;
122112099Sjoerg
122212099Sjoergdirect_abs_decl:
122312099Sjoerg	  T_LPARN abs_decl T_RPARN {
122412099Sjoerg		$$ = $2;
122512099Sjoerg	  }
122612099Sjoerg	| T_LBRACK T_RBRACK {
122712099Sjoerg		$$ = addarray(aname(), 0, 0);
122812099Sjoerg	  }
122912099Sjoerg	| T_LBRACK constant T_RBRACK {
1230281168Spfg		$$ = addarray(aname(), 1, toicon($2, 0));
123112099Sjoerg	  }
123212099Sjoerg	| direct_abs_decl T_LBRACK T_RBRACK {
123312099Sjoerg		$$ = addarray($1, 0, 0);
123412099Sjoerg	  }
123512099Sjoerg	| direct_abs_decl T_LBRACK constant T_RBRACK {
1236281168Spfg		$$ = addarray($1, 1, toicon($3, 0));
123712099Sjoerg	  }
123812099Sjoerg	| abs_decl_param_list {
123912099Sjoerg		$$ = addfunc(aname(), $1);
124012099Sjoerg		popdecl();
124112099Sjoerg		blklev--;
124212099Sjoerg	  }
124312099Sjoerg	| direct_abs_decl abs_decl_param_list {
124412099Sjoerg		$$ = addfunc($1, $2);
124512099Sjoerg		popdecl();
124612099Sjoerg		blklev--;
124712099Sjoerg	  }
124812099Sjoerg	;
124912099Sjoerg
1250281168Spfgnon_expr_stmnt:
125112099Sjoerg	  labeled_stmnt
125212099Sjoerg	| comp_stmnt
125312099Sjoerg	| selection_stmnt
125412099Sjoerg	| iteration_stmnt
125512099Sjoerg	| jump_stmnt {
125612099Sjoerg		ftflg = 0;
125712099Sjoerg	  }
125812099Sjoerg	| asm_stmnt
1259281168Spfg
1260281168Spfgstmnt:
1261281168Spfg	  expr_stmnt
1262281168Spfg	| non_expr_stmnt
126312099Sjoerg	;
126412099Sjoerg
126512099Sjoerglabeled_stmnt:
126612099Sjoerg	  label stmnt
126712099Sjoerg	;
126812099Sjoerg
126912099Sjoerglabel:
127012099Sjoerg	  identifier T_COLON {
127112099Sjoerg		symtyp = FLAB;
127212099Sjoerg		label(T_NAME, getsym($1), NULL);
127312099Sjoerg	  }
127412099Sjoerg	| T_CASE constant T_COLON {
127512099Sjoerg		label(T_CASE, NULL, $2);
127612099Sjoerg		ftflg = 1;
1277281168Spfg	}
1278281168Spfg	| T_CASE constant T_ELLIPSE constant T_COLON {
1279281168Spfg		/* XXX: We don't fill all cases */
1280281168Spfg		label(T_CASE, NULL, $2);
1281281168Spfg		ftflg = 1;
1282281168Spfg	}
128312099Sjoerg	| T_DEFAULT T_COLON {
128412099Sjoerg		label(T_DEFAULT, NULL, NULL);
128512099Sjoerg		ftflg = 1;
128612099Sjoerg	  }
128712099Sjoerg	;
128812099Sjoerg
128912099Sjoergcomp_stmnt:
1290281168Spfg	  comp_stmnt_lbrace declaration_list opt_stmnt_list comp_stmnt_rbrace
1291281168Spfg	| comp_stmnt_lbrace opt_stmnt_list comp_stmnt_rbrace
129212099Sjoerg	;
129312099Sjoerg
1294281168Spfgcomp_stmnt_lbrace:
129512099Sjoerg	  T_LBRACE {
129612099Sjoerg		blklev++;
129712099Sjoerg		mblklev++;
129812099Sjoerg		pushdecl(AUTO);
129912099Sjoerg	  }
130012099Sjoerg	;
130112099Sjoerg
1302281168Spfgcomp_stmnt_rbrace:
130312099Sjoerg	  T_RBRACE {
130412099Sjoerg		popdecl();
130512099Sjoerg		freeblk();
130612099Sjoerg		mblklev--;
130712099Sjoerg		blklev--;
130812099Sjoerg		ftflg = 0;
130912099Sjoerg	  }
131012099Sjoerg	;
131112099Sjoerg
131212099Sjoergopt_stmnt_list:
131312099Sjoerg	  /* empty */
131412099Sjoerg	| stmnt_list
131512099Sjoerg	;
131612099Sjoerg
131712099Sjoergstmnt_list:
131891592Smarkm	  stmnt
131912099Sjoerg	| stmnt_list stmnt {
132091592Smarkm		RESTORE();
132112099Sjoerg	  }
132291592Smarkm	| stmnt_list error T_SEMI
132312099Sjoerg	;
132412099Sjoerg
132512099Sjoergexpr_stmnt:
132612099Sjoerg	  expr T_SEMI {
1327281168Spfg		expr($1, 0, 0, 1);
132812099Sjoerg		ftflg = 0;
132912099Sjoerg	  }
133012099Sjoerg	| T_SEMI {
133112099Sjoerg		ftflg = 0;
133212099Sjoerg	  }
133312099Sjoerg	;
133412099Sjoerg
1335281168Spfg/*
1336281168Spfg * The following two productions are used to implement
1337281168Spfg * ({ [[decl-list] stmt-list] }).
1338281168Spfg * XXX: This is not well tested.
1339281168Spfg */
1340281168Spfgexpr_stmnt_val:
1341281168Spfg	  expr T_SEMI {
1342281168Spfg		/* XXX: We should really do that only on the last name */
1343281168Spfg		if ($1->tn_op == NAME)
1344281168Spfg			$1->tn_sym->s_used = 1;
1345281168Spfg		$$ = $1;
1346281168Spfg		expr($1, 0, 0, 0);
1347281168Spfg		ftflg = 0;
1348281168Spfg	  }
1349281168Spfg	| non_expr_stmnt {
1350281168Spfg	$$ = getnode();
1351281168Spfg	$$->tn_type = gettyp(VOID);
1352281168Spfg	}
1353281168Spfg	;
1354281168Spfg
1355281168Spfgexpr_stmnt_list:
1356281168Spfg	  expr_stmnt_val
1357281168Spfg	| expr_stmnt_list expr_stmnt_val {
1358281168Spfg		$$ = $2;
1359281168Spfg	}
1360281168Spfg	| expr_stmnt_list expr_stmnt_val
1361281168Spfg	;
1362281168Spfg
136312099Sjoergselection_stmnt:
136412099Sjoerg	  if_without_else {
136591592Smarkm		SAVE();
136612099Sjoerg		if2();
136712099Sjoerg		if3(0);
136812099Sjoerg	  }
136912099Sjoerg	| if_without_else T_ELSE {
137091592Smarkm		SAVE();
137112099Sjoerg		if2();
137212099Sjoerg	  } stmnt {
137391592Smarkm		CLRWFLGS();
137412099Sjoerg		if3(1);
137512099Sjoerg	  }
137612099Sjoerg	| if_without_else T_ELSE error {
137791592Smarkm		CLRWFLGS();
137812099Sjoerg		if3(0);
137912099Sjoerg	  }
138012099Sjoerg	| switch_expr stmnt {
138191592Smarkm		CLRWFLGS();
138212099Sjoerg		switch2();
138312099Sjoerg	  }
138412099Sjoerg	| switch_expr error {
138591592Smarkm		CLRWFLGS();
138612099Sjoerg		switch2();
138712099Sjoerg	  }
138812099Sjoerg	;
138912099Sjoerg
139012099Sjoergif_without_else:
139112099Sjoerg	  if_expr stmnt
139212099Sjoerg	| if_expr error
139312099Sjoerg	;
139412099Sjoerg
139512099Sjoergif_expr:
139612099Sjoerg	  T_IF T_LPARN expr T_RPARN {
139712099Sjoerg		if1($3);
139891592Smarkm		CLRWFLGS();
139912099Sjoerg	  }
140012099Sjoerg	;
140112099Sjoerg
140212099Sjoergswitch_expr:
140312099Sjoerg	  T_SWITCH T_LPARN expr T_RPARN {
140412099Sjoerg		switch1($3);
140591592Smarkm		CLRWFLGS();
140612099Sjoerg	  }
140712099Sjoerg	;
140812099Sjoerg
140991592Smarkmdo_stmnt:
141091592Smarkm	  do stmnt {
141191592Smarkm		CLRWFLGS();
141291592Smarkm	  }
141391592Smarkm	;
141491592Smarkm
141512099Sjoergiteration_stmnt:
141612099Sjoerg	  while_expr stmnt {
141791592Smarkm		CLRWFLGS();
141812099Sjoerg		while2();
141912099Sjoerg	  }
142012099Sjoerg	| while_expr error {
142191592Smarkm		CLRWFLGS();
142212099Sjoerg		while2();
142312099Sjoerg	  }
142491592Smarkm	| do_stmnt do_while_expr {
142591592Smarkm		do2($2);
142612099Sjoerg		ftflg = 0;
142712099Sjoerg	  }
142812099Sjoerg	| do error {
142991592Smarkm		CLRWFLGS();
143012099Sjoerg		do2(NULL);
143112099Sjoerg	  }
143212099Sjoerg	| for_exprs stmnt {
143391592Smarkm		CLRWFLGS();
143412099Sjoerg		for2();
143512099Sjoerg	  }
143612099Sjoerg	| for_exprs error {
143791592Smarkm		CLRWFLGS();
143812099Sjoerg		for2();
143912099Sjoerg	  }
144012099Sjoerg	;
144112099Sjoerg
144212099Sjoergwhile_expr:
144312099Sjoerg	  T_WHILE T_LPARN expr T_RPARN {
144412099Sjoerg		while1($3);
144591592Smarkm		CLRWFLGS();
144612099Sjoerg	  }
144712099Sjoerg	;
144812099Sjoerg
144912099Sjoergdo:
145012099Sjoerg	  T_DO {
145112099Sjoerg		do1();
145212099Sjoerg	  }
145312099Sjoerg	;
145412099Sjoerg
145512099Sjoergdo_while_expr:
145612099Sjoerg	  T_WHILE T_LPARN expr T_RPARN T_SEMI {
145712099Sjoerg		$$ = $3;
145812099Sjoerg	  }
145912099Sjoerg	;
146012099Sjoerg
146112099Sjoergfor_exprs:
146212099Sjoerg	  T_FOR T_LPARN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPARN {
146312099Sjoerg		for1($3, $5, $7);
146491592Smarkm		CLRWFLGS();
146512099Sjoerg	  }
146612099Sjoerg	;
146712099Sjoerg
146812099Sjoergopt_expr:
146912099Sjoerg	  /* empty */ {
147012099Sjoerg		$$ = NULL;
147112099Sjoerg	  }
147212099Sjoerg	| expr {
147312099Sjoerg		$$ = $1;
147412099Sjoerg	  }
147512099Sjoerg	;
147612099Sjoerg
147712099Sjoergjump_stmnt:
147812099Sjoerg	  goto identifier T_SEMI {
147912099Sjoerg		dogoto(getsym($2));
148012099Sjoerg	  }
148112099Sjoerg	| goto error T_SEMI {
148212099Sjoerg		symtyp = FVFT;
148312099Sjoerg	  }
148412099Sjoerg	| T_CONTINUE T_SEMI {
148512099Sjoerg		docont();
148612099Sjoerg	  }
148712099Sjoerg	| T_BREAK T_SEMI {
148812099Sjoerg		dobreak();
148912099Sjoerg	  }
149012099Sjoerg	| T_RETURN T_SEMI {
149112099Sjoerg		doreturn(NULL);
149212099Sjoerg	  }
149312099Sjoerg	| T_RETURN expr T_SEMI {
149412099Sjoerg		doreturn($2);
149512099Sjoerg	  }
149612099Sjoerg	;
149712099Sjoerg
149812099Sjoerggoto:
149912099Sjoerg	  T_GOTO {
150012099Sjoerg		symtyp = FLAB;
150112099Sjoerg	  }
150212099Sjoerg	;
150312099Sjoerg
150412099Sjoergasm_stmnt:
150512099Sjoerg	  T_ASM T_LPARN read_until_rparn T_SEMI {
150612099Sjoerg		setasm();
150712099Sjoerg	  }
150812099Sjoerg	| T_ASM T_QUAL T_LPARN read_until_rparn T_SEMI {
150912099Sjoerg		setasm();
151012099Sjoerg	  }
151112099Sjoerg	| T_ASM error
151212099Sjoerg	;
151312099Sjoerg
151412099Sjoergread_until_rparn:
151512099Sjoerg	  /* empty */ {
151612099Sjoerg		ignuptorp();
151712099Sjoerg	  }
151812099Sjoerg	;
151912099Sjoerg
152012099Sjoergdeclaration_list:
152112099Sjoerg	  declaration {
152291592Smarkm		CLRWFLGS();
152312099Sjoerg	  }
152412099Sjoerg	| declaration_list declaration {
152591592Smarkm		CLRWFLGS();
152612099Sjoerg	  }
152712099Sjoerg	;
152812099Sjoerg
152912099Sjoergconstant:
153012099Sjoerg	  expr				%prec T_COMMA {
153112099Sjoerg		  $$ = $1;
153212099Sjoerg	  }
153312099Sjoerg	;
153412099Sjoerg
153512099Sjoergexpr:
153612099Sjoerg	  expr T_MULT expr {
153712099Sjoerg		$$ = build(MULT, $1, $3);
153812099Sjoerg	  }
153912099Sjoerg	| expr T_DIVOP expr {
154012099Sjoerg		$$ = build($2, $1, $3);
154112099Sjoerg	  }
154212099Sjoerg	| expr T_ADDOP expr {
154312099Sjoerg		$$ = build($2, $1, $3);
154412099Sjoerg	  }
154512099Sjoerg	| expr T_SHFTOP expr {
154612099Sjoerg		$$ = build($2, $1, $3);
154712099Sjoerg	  }
154812099Sjoerg	| expr T_RELOP expr {
154912099Sjoerg		$$ = build($2, $1, $3);
155012099Sjoerg	  }
155112099Sjoerg	| expr T_EQOP expr {
155212099Sjoerg		$$ = build($2, $1, $3);
155312099Sjoerg	  }
155412099Sjoerg	| expr T_AND expr {
155512099Sjoerg		$$ = build(AND, $1, $3);
155612099Sjoerg	  }
155712099Sjoerg	| expr T_XOR expr {
155812099Sjoerg		$$ = build(XOR, $1, $3);
155912099Sjoerg	  }
156012099Sjoerg	| expr T_OR expr {
156112099Sjoerg		$$ = build(OR, $1, $3);
156212099Sjoerg	  }
156312099Sjoerg	| expr T_LOGAND expr {
156412099Sjoerg		$$ = build(LOGAND, $1, $3);
156512099Sjoerg	  }
156612099Sjoerg	| expr T_LOGOR expr {
156712099Sjoerg		$$ = build(LOGOR, $1, $3);
156812099Sjoerg	  }
156912099Sjoerg	| expr T_QUEST expr T_COLON expr {
157012099Sjoerg		$$ = build(QUEST, $1, build(COLON, $3, $5));
157112099Sjoerg	  }
157212099Sjoerg	| expr T_ASSIGN expr {
157312099Sjoerg		$$ = build(ASSIGN, $1, $3);
157412099Sjoerg	  }
157512099Sjoerg	| expr T_OPASS expr {
157612099Sjoerg		$$ = build($2, $1, $3);
157712099Sjoerg	  }
157812099Sjoerg	| expr T_COMMA expr {
157912099Sjoerg		$$ = build(COMMA, $1, $3);
158012099Sjoerg	  }
158112099Sjoerg	| term {
158212099Sjoerg		$$ = $1;
158312099Sjoerg	  }
158412099Sjoerg	;
158512099Sjoerg
158612099Sjoergterm:
158712099Sjoerg	  T_NAME {
158891592Smarkm		/* XXX really necessary? */
158912099Sjoerg		if (yychar < 0)
159012099Sjoerg			yychar = yylex();
159112099Sjoerg		$$ = getnnode(getsym($1), yychar);
159212099Sjoerg	  }
159312099Sjoerg	| string {
159412099Sjoerg		$$ = getsnode($1);
159512099Sjoerg	  }
159612099Sjoerg	| T_CON {
159712099Sjoerg		$$ = getcnode(gettyp($1->v_tspec), $1);
159812099Sjoerg	  }
159912099Sjoerg	| T_LPARN expr T_RPARN {
160012099Sjoerg		if ($2 != NULL)
160112099Sjoerg			$2->tn_parn = 1;
160212099Sjoerg		$$ = $2;
160312099Sjoerg	  }
1604281168Spfg	| T_LPARN comp_stmnt_lbrace declaration_list expr_stmnt_list {
1605281168Spfg		blklev--;
1606281168Spfg		mblklev--;
1607281168Spfg		initsym = mktempsym(duptyp($4->tn_type));
1608281168Spfg		mblklev++;
1609281168Spfg		blklev++;
1610281168Spfg		gnuism(320);
1611281168Spfg	} comp_stmnt_rbrace T_RPARN {
1612281168Spfg		$$ = getnnode(initsym, 0);
1613281168Spfg	}
1614281168Spfg	| T_LPARN comp_stmnt_lbrace expr_stmnt_list {
1615281168Spfg		blklev--;
1616281168Spfg		mblklev--;
1617281168Spfg		initsym = mktempsym($3->tn_type);
1618281168Spfg		mblklev++;
1619281168Spfg		blklev++;
1620281168Spfg		gnuism(320);
1621281168Spfg	} comp_stmnt_rbrace T_RPARN {
1622281168Spfg		$$ = getnnode(initsym, 0);
1623281168Spfg	}
162412099Sjoerg	| term T_INCDEC {
162512099Sjoerg		$$ = build($2 == INC ? INCAFT : DECAFT, $1, NULL);
162612099Sjoerg	  }
162712099Sjoerg	| T_INCDEC term {
162812099Sjoerg		$$ = build($1 == INC ? INCBEF : DECBEF, $2, NULL);
162912099Sjoerg	  }
163012099Sjoerg	| T_MULT term {
163112099Sjoerg		$$ = build(STAR, $2, NULL);
163212099Sjoerg	  }
163312099Sjoerg	| T_AND term {
163412099Sjoerg		$$ = build(AMPER, $2, NULL);
163512099Sjoerg	  }
163612099Sjoerg	| T_UNOP term {
163712099Sjoerg		$$ = build($1, $2, NULL);
163812099Sjoerg	  }
163912099Sjoerg	| T_ADDOP term {
164012099Sjoerg		if (tflag && $1 == PLUS) {
164112099Sjoerg			/* unary + is illegal in traditional C */
164212099Sjoerg			warning(100);
164312099Sjoerg		}
164412099Sjoerg		$$ = build($1 == PLUS ? UPLUS : UMINUS, $2, NULL);
164512099Sjoerg	  }
164612099Sjoerg	| term T_LBRACK expr T_RBRACK {
164712099Sjoerg		$$ = build(STAR, build(PLUS, $1, $3), NULL);
164812099Sjoerg	  }
164912099Sjoerg	| term T_LPARN T_RPARN {
165012099Sjoerg		$$ = funccall($1, NULL);
165112099Sjoerg	  }
165212099Sjoerg	| term T_LPARN func_arg_list T_RPARN {
165312099Sjoerg		$$ = funccall($1, $3);
165412099Sjoerg	  }
165512099Sjoerg	| term point_or_arrow T_NAME {
165612099Sjoerg		if ($1 != NULL) {
165712099Sjoerg			sym_t	*msym;
165812099Sjoerg			/* XXX strmemb should be integrated in build() */
165912099Sjoerg			if ($2 == ARROW) {
166012099Sjoerg				/* must to this before strmemb is called */
166112099Sjoerg				$1 = cconv($1);
166212099Sjoerg			}
166312099Sjoerg			msym = strmemb($1, $2, getsym($3));
166412099Sjoerg			$$ = build($2, $1, getnnode(msym, 0));
166512099Sjoerg		} else {
166612099Sjoerg			$$ = NULL;
166712099Sjoerg		}
166812099Sjoerg	  }
166912099Sjoerg	| T_SIZEOF term					%prec T_SIZEOF {
167012099Sjoerg		if (($$ = $2 == NULL ? NULL : bldszof($2->tn_type)) != NULL)
167112099Sjoerg			chkmisc($2, 0, 0, 0, 0, 0, 1);
167212099Sjoerg	  }
167312099Sjoerg	| T_SIZEOF T_LPARN type_name T_RPARN		%prec T_SIZEOF {
167412099Sjoerg		$$ = bldszof($3);
167512099Sjoerg	  }
167612099Sjoerg	| T_LPARN type_name T_RPARN term		%prec T_UNOP {
167712099Sjoerg		$$ = cast($4, $2);
167812099Sjoerg	  }
1679281168Spfg	| T_LPARN type_name T_RPARN 			%prec T_UNOP {
1680281168Spfg		sym_t *tmp = mktempsym($2);
1681281168Spfg		idecl(tmp, 1, NULL);
1682281168Spfg	  } init_lbrace init_expr_list init_rbrace {
1683281168Spfg		if (!Sflag)
1684281168Spfg			gnuism(319);
1685281168Spfg		$$ = getnnode(initsym, 0);
1686281168Spfg	  }
168712099Sjoerg	;
168812099Sjoerg
168912099Sjoergstring:
169012099Sjoerg	  T_STRING {
169112099Sjoerg		$$ = $1;
169212099Sjoerg	  }
169312099Sjoerg	| T_STRING string2 {
169412099Sjoerg		$$ = catstrg($1, $2);
169512099Sjoerg	  }
169612099Sjoerg	;
169712099Sjoerg
169812099Sjoergstring2:
169912099Sjoerg	 T_STRING {
170012099Sjoerg		if (tflag) {
170112099Sjoerg			/* concatenated strings are illegal in traditional C */
170212099Sjoerg			warning(219);
170312099Sjoerg		}
170412099Sjoerg		$$ = $1;
170512099Sjoerg	  }
170612099Sjoerg	| string2 T_STRING {
170712099Sjoerg		$$ = catstrg($1, $2);
170812099Sjoerg	  }
170912099Sjoerg	;
171012099Sjoerg
171112099Sjoergfunc_arg_list:
171212099Sjoerg	  expr						%prec T_COMMA {
171312099Sjoerg		$$ = funcarg(NULL, $1);
171412099Sjoerg	  }
171512099Sjoerg	| func_arg_list T_COMMA expr {
171612099Sjoerg		$$ = funcarg($1, $3);
171712099Sjoerg	  }
171812099Sjoerg	;
171912099Sjoerg
172012099Sjoergpoint_or_arrow:
172112099Sjoerg	  T_STROP {
172212099Sjoerg		symtyp = FMOS;
172312099Sjoerg		$$ = $1;
172412099Sjoerg	  }
172512099Sjoerg	;
172612099Sjoerg
1727281168Spfgpoint:
1728281168Spfg	  T_STROP {
1729281168Spfg		if ($1 != POINT)
1730281168Spfg			error(249);
1731281168Spfg	  }
1732281168Spfg	;
1733281168Spfg
173412099Sjoergidentifier:
173512099Sjoerg	  T_NAME {
173612099Sjoerg		$$ = $1;
173712099Sjoerg	  }
173812099Sjoerg	| T_TYPENAME {
173912099Sjoerg		$$ = $1;
174012099Sjoerg	  }
174112099Sjoerg	;
174212099Sjoerg
174312099Sjoerg%%
174412099Sjoerg
174512099Sjoerg/* ARGSUSED */
174612099Sjoergint
174791592Smarkmyyerror(char *msg)
174812099Sjoerg{
174912099Sjoerg	error(249);
175012099Sjoerg	if (++sytxerr >= 5)
175112099Sjoerg		norecover();
175212099Sjoerg	return (0);
175312099Sjoerg}
175412099Sjoerg
1755115967Sobrienstatic __inline int uq_gt(uint64_t, uint64_t);
1756115967Sobrienstatic __inline int
175791592Smarkmuq_gt(uint64_t a, uint64_t b)
175891592Smarkm{
175991592Smarkm
176091592Smarkm	return (a > b);
176191592Smarkm}
176291592Smarkm
1763115967Sobrienstatic __inline int q_gt(int64_t, int64_t);
1764115967Sobrienstatic __inline int
176591592Smarkmq_gt(int64_t a, int64_t b)
176691592Smarkm{
176791592Smarkm
176891592Smarkm	return (a > b);
176991592Smarkm}
177091592Smarkm
177191592Smarkm#define	q_lt(a, b)	q_gt(b, a)
177291592Smarkm
177312099Sjoerg/*
177412099Sjoerg * Gets a node for a constant and returns the value of this constant
177512099Sjoerg * as integer.
177612099Sjoerg * Is the node not constant or too large for int or of type float,
177712099Sjoerg * a warning will be printed.
177812099Sjoerg *
177912099Sjoerg * toicon() should be used only inside declarations. If it is used in
178012099Sjoerg * expressions, it frees the memory used for the expression.
178112099Sjoerg */
178212099Sjoergstatic int
1783281168Spfgtoicon(tnode_t *tn, int required)
178412099Sjoerg{
178512099Sjoerg	int	i;
178612099Sjoerg	tspec_t	t;
178712099Sjoerg	val_t	*v;
178812099Sjoerg
1789281168Spfg	v = constant(tn, required);
179012099Sjoerg
179112099Sjoerg	/*
179212099Sjoerg	 * Abstract declarations are used inside expression. To free
179312099Sjoerg	 * the memory would be a fatal error.
179412099Sjoerg	 */
179512099Sjoerg	if (dcs->d_ctx != ABSTRACT)
179612099Sjoerg		tfreeblk();
179712099Sjoerg
179812099Sjoerg	if ((t = v->v_tspec) == FLOAT || t == DOUBLE || t == LDOUBLE) {
179912099Sjoerg		i = (int)v->v_ldbl;
180012099Sjoerg		/* integral constant expression expected */
180112099Sjoerg		error(55);
180212099Sjoerg	} else {
180312099Sjoerg		i = (int)v->v_quad;
180412099Sjoerg		if (isutyp(t)) {
180591592Smarkm			if (uq_gt((uint64_t)v->v_quad,
180691592Smarkm				  (uint64_t)INT_MAX)) {
180712099Sjoerg				/* integral constant too large */
180812099Sjoerg				warning(56);
180912099Sjoerg			}
181012099Sjoerg		} else {
181191592Smarkm			if (q_gt(v->v_quad, (int64_t)INT_MAX) ||
181291592Smarkm			    q_lt(v->v_quad, (int64_t)INT_MIN)) {
181326582Stegge				/* integral constant too large */
181426582Stegge				warning(56);
181526582Stegge			}
181612099Sjoerg		}
181712099Sjoerg	}
181812099Sjoerg	free(v);
181912099Sjoerg	return (i);
182012099Sjoerg}
182112099Sjoerg
182212099Sjoergstatic void
182391592Smarkmidecl(sym_t *decl, int initflg, sbuf_t *rename)
182412099Sjoerg{
182591592Smarkm	char *s;
182691592Smarkm
182712099Sjoerg	initerr = 0;
182812099Sjoerg	initsym = decl;
182912099Sjoerg
183012099Sjoerg	switch (dcs->d_ctx) {
183112099Sjoerg	case EXTERN:
183291592Smarkm		if (rename != NULL) {
183391592Smarkm			if (decl->s_rename != NULL)
1834281168Spfg				LERROR("idecl()");
183591592Smarkm
183691592Smarkm			s = getlblk(1, rename->sb_len + 1);
183791592Smarkm	                (void)memcpy(s, rename->sb_name, rename->sb_len + 1);
183891592Smarkm			decl->s_rename = s;
183991592Smarkm			freeyyv(&rename, T_NAME);
184091592Smarkm		}
184112099Sjoerg		decl1ext(decl, initflg);
184212099Sjoerg		break;
184312099Sjoerg	case ARG:
184491592Smarkm		if (rename != NULL) {
184591592Smarkm			/* symbol renaming can't be used on function arguments */
184691592Smarkm			error(310);
184791592Smarkm			freeyyv(&rename, T_NAME);
184891592Smarkm			break;
184991592Smarkm		}
185012099Sjoerg		(void)decl1arg(decl, initflg);
185112099Sjoerg		break;
185212099Sjoerg	case AUTO:
185391592Smarkm		if (rename != NULL) {
185491592Smarkm			/* symbol renaming can't be used on automatic variables */
185591592Smarkm			error(311);
185691592Smarkm			freeyyv(&rename, T_NAME);
185791592Smarkm			break;
185891592Smarkm		}
185912099Sjoerg		decl1loc(decl, initflg);
186012099Sjoerg		break;
186112099Sjoerg	default:
1862281168Spfg		LERROR("idecl()");
186312099Sjoerg	}
186412099Sjoerg
186512099Sjoerg	if (initflg && !initerr)
186612099Sjoerg		prepinit();
186712099Sjoerg}
186812099Sjoerg
186912099Sjoerg/*
187012099Sjoerg * Discard all input tokens up to and including the next
187112099Sjoerg * unmatched right paren
187212099Sjoerg */
187391592Smarkmstatic void
187491592Smarkmignuptorp(void)
187512099Sjoerg{
187612099Sjoerg	int	level;
187712099Sjoerg
187812099Sjoerg	if (yychar < 0)
187912099Sjoerg		yychar = yylex();
188012099Sjoerg	freeyyv(&yylval, yychar);
188112099Sjoerg
188212099Sjoerg	level = 1;
188312099Sjoerg	while (yychar != T_RPARN || --level > 0) {
188412099Sjoerg		if (yychar == T_LPARN) {
188512099Sjoerg			level++;
188612099Sjoerg		} else if (yychar <= 0) {
188712099Sjoerg			break;
188812099Sjoerg		}
188912099Sjoerg		freeyyv(&yylval, yychar = yylex());
189012099Sjoerg	}
189112099Sjoerg
189212099Sjoerg	yyclearin;
189312099Sjoerg}
1894