xref: /netbsd/external/bsd/pcc/dist/pcc/cc/ccom/cgram.y (revision a301e773)
1*a301e773Splunky /*	Id: cgram.y,v 1.340 2011/08/03 19:25:32 ragge Exp 	*/
2*a301e773Splunky /*	$NetBSD: cgram.y,v 1.1.1.4 2011/09/01 12:46:58 plunky Exp $	*/
36e0bca22Sgmcgarry 
46e0bca22Sgmcgarry /*
56e0bca22Sgmcgarry  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
66e0bca22Sgmcgarry  * All rights reserved.
76e0bca22Sgmcgarry  *
86e0bca22Sgmcgarry  * Redistribution and use in source and binary forms, with or without
96e0bca22Sgmcgarry  * modification, are permitted provided that the following conditions
106e0bca22Sgmcgarry  * are met:
116e0bca22Sgmcgarry  * 1. Redistributions of source code must retain the above copyright
126e0bca22Sgmcgarry  *    notice, this list of conditions and the following disclaimer.
136e0bca22Sgmcgarry  * 2. Redistributions in binary form must reproduce the above copyright
146e0bca22Sgmcgarry  *    notice, this list of conditions and the following disclaimer in the
156e0bca22Sgmcgarry  *    documentation and/or other materials provided with the distribution.
166e0bca22Sgmcgarry  *
176e0bca22Sgmcgarry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
186e0bca22Sgmcgarry  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
196e0bca22Sgmcgarry  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
206e0bca22Sgmcgarry  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
216e0bca22Sgmcgarry  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
226e0bca22Sgmcgarry  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236e0bca22Sgmcgarry  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246e0bca22Sgmcgarry  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256e0bca22Sgmcgarry  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
266e0bca22Sgmcgarry  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276e0bca22Sgmcgarry  */
286e0bca22Sgmcgarry 
296e0bca22Sgmcgarry /*
306e0bca22Sgmcgarry  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
316e0bca22Sgmcgarry  *
326e0bca22Sgmcgarry  * Redistribution and use in source and binary forms, with or without
336e0bca22Sgmcgarry  * modification, are permitted provided that the following conditions
346e0bca22Sgmcgarry  * are met:
356e0bca22Sgmcgarry  *
366e0bca22Sgmcgarry  * Redistributions of source code and documentation must retain the above
376e0bca22Sgmcgarry  * copyright notice, this list of conditions and the following disclaimer.
386e0bca22Sgmcgarry  * Redistributions in binary form must reproduce the above copyright
396e0bca22Sgmcgarry  * notice, this list of conditions and the following disclaimer in the
406e0bca22Sgmcgarry  * documentation and/or other materials provided with the distribution.
416e0bca22Sgmcgarry  * All advertising materials mentioning features or use of this software
426e0bca22Sgmcgarry  * must display the following acknowledgement:
436e0bca22Sgmcgarry  * 	This product includes software developed or owned by Caldera
446e0bca22Sgmcgarry  *	International, Inc.
456e0bca22Sgmcgarry  * Neither the name of Caldera International, Inc. nor the names of other
466e0bca22Sgmcgarry  * contributors may be used to endorse or promote products derived from
476e0bca22Sgmcgarry  * this software without specific prior written permission.
486e0bca22Sgmcgarry  *
496e0bca22Sgmcgarry  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
506e0bca22Sgmcgarry  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
516e0bca22Sgmcgarry  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
526e0bca22Sgmcgarry  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
536e0bca22Sgmcgarry  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
546e0bca22Sgmcgarry  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
556e0bca22Sgmcgarry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
566e0bca22Sgmcgarry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
576e0bca22Sgmcgarry  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
586e0bca22Sgmcgarry  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
596e0bca22Sgmcgarry  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
606e0bca22Sgmcgarry  * POSSIBILITY OF SUCH DAMAGE.
616e0bca22Sgmcgarry  */
626e0bca22Sgmcgarry 
636e0bca22Sgmcgarry /*
646e0bca22Sgmcgarry  * Comments for this grammar file. Ragge 021123
656e0bca22Sgmcgarry  *
666e0bca22Sgmcgarry  * ANSI support required rewrite of the function header and declaration
676e0bca22Sgmcgarry  * rules almost totally.
686e0bca22Sgmcgarry  *
696e0bca22Sgmcgarry  * The lex/yacc shared keywords are now split from the keywords used
706e0bca22Sgmcgarry  * in the rest of the compiler, to simplify use of other frontends.
716e0bca22Sgmcgarry  */
726e0bca22Sgmcgarry 
736e0bca22Sgmcgarry /*
74*a301e773Splunky  * At last count, there were 5 shift/reduce and no reduce/reduce conflicts
75*a301e773Splunky  * Four are accounted for;
76*a301e773Splunky  * One is "dangling else"
77*a301e773Splunky  * Two is in attribute parsing
78*a301e773Splunky  * One is in ({ }) parsing
796e0bca22Sgmcgarry  */
806e0bca22Sgmcgarry 
816e0bca22Sgmcgarry /*
826e0bca22Sgmcgarry  * Token used in C lex/yacc communications.
836e0bca22Sgmcgarry  */
846e0bca22Sgmcgarry %token	C_STRING	/* a string constant */
856e0bca22Sgmcgarry %token	C_ICON		/* an integer constant */
866e0bca22Sgmcgarry %token	C_FCON		/* a floating point constant */
876e0bca22Sgmcgarry %token	C_NAME		/* an identifier */
886e0bca22Sgmcgarry %token	C_TYPENAME	/* a typedef'd name */
896e0bca22Sgmcgarry %token	C_ANDAND	/* && */
906e0bca22Sgmcgarry %token	C_OROR		/* || */
916e0bca22Sgmcgarry %token	C_GOTO		/* unconditional goto */
926e0bca22Sgmcgarry %token	C_RETURN	/* return from function */
936e0bca22Sgmcgarry %token	C_TYPE		/* a type */
946e0bca22Sgmcgarry %token	C_CLASS		/* a storage class */
956e0bca22Sgmcgarry %token	C_ASOP		/* assignment ops */
966e0bca22Sgmcgarry %token	C_RELOP		/* <=, <, >=, > */
976e0bca22Sgmcgarry %token	C_EQUOP		/* ==, != */
986e0bca22Sgmcgarry %token	C_DIVOP		/* /, % */
996e0bca22Sgmcgarry %token	C_SHIFTOP	/* <<, >> */
1006e0bca22Sgmcgarry %token	C_INCOP		/* ++, -- */
1016e0bca22Sgmcgarry %token	C_UNOP		/* !, ~ */
1026e0bca22Sgmcgarry %token	C_STROP		/* ., -> */
1036e0bca22Sgmcgarry %token	C_STRUCT
1046e0bca22Sgmcgarry %token	C_IF
1056e0bca22Sgmcgarry %token	C_ELSE
1066e0bca22Sgmcgarry %token	C_SWITCH
1076e0bca22Sgmcgarry %token	C_BREAK
1086e0bca22Sgmcgarry %token	C_CONTINUE
1096e0bca22Sgmcgarry %token	C_WHILE
1106e0bca22Sgmcgarry %token	C_DO
1116e0bca22Sgmcgarry %token	C_FOR
1126e0bca22Sgmcgarry %token	C_DEFAULT
1136e0bca22Sgmcgarry %token	C_CASE
1146e0bca22Sgmcgarry %token	C_SIZEOF
115*a301e773Splunky %token	C_ALIGNOF
1166e0bca22Sgmcgarry %token	C_ENUM
1176e0bca22Sgmcgarry %token	C_ELLIPSIS
1186e0bca22Sgmcgarry %token	C_QUALIFIER
1196e0bca22Sgmcgarry %token	C_FUNSPEC
1206e0bca22Sgmcgarry %token	C_ASM
1216e0bca22Sgmcgarry %token	NOMATCH
122c4627bc7Sgmcgarry %token	C_TYPEOF	/* COMPAT_GCC */
123c4627bc7Sgmcgarry %token	C_ATTRIBUTE	/* COMPAT_GCC */
1243eb51a41Splunky %token	PCC_OFFSETOF
125*a301e773Splunky %token	GCC_DESIG
1266e0bca22Sgmcgarry 
1276e0bca22Sgmcgarry /*
1286e0bca22Sgmcgarry  * Precedence
1296e0bca22Sgmcgarry  */
1306e0bca22Sgmcgarry %left ','
1316e0bca22Sgmcgarry %right '=' C_ASOP
1326e0bca22Sgmcgarry %right '?' ':'
1336e0bca22Sgmcgarry %left C_OROR
1346e0bca22Sgmcgarry %left C_ANDAND
1356e0bca22Sgmcgarry %left '|'
1366e0bca22Sgmcgarry %left '^'
1376e0bca22Sgmcgarry %left '&'
1386e0bca22Sgmcgarry %left C_EQUOP
1396e0bca22Sgmcgarry %left C_RELOP
1406e0bca22Sgmcgarry %left C_SHIFTOP
1416e0bca22Sgmcgarry %left '+' '-'
1426e0bca22Sgmcgarry %left '*' C_DIVOP
1436e0bca22Sgmcgarry %right C_UNOP
1446e0bca22Sgmcgarry %right C_INCOP C_SIZEOF
1456e0bca22Sgmcgarry %left '[' '(' C_STROP
1466e0bca22Sgmcgarry %{
1476e0bca22Sgmcgarry # include "pass1.h"
1486e0bca22Sgmcgarry # include <stdarg.h>
1496e0bca22Sgmcgarry # include <string.h>
1506e0bca22Sgmcgarry # include <stdlib.h>
1516e0bca22Sgmcgarry 
1526e0bca22Sgmcgarry int fun_inline;	/* Reading an inline function */
1536e0bca22Sgmcgarry int oldstyle;	/* Current function being defined */
1546e0bca22Sgmcgarry static struct symtab *xnf;
155c4627bc7Sgmcgarry extern int enummer, tvaloff, inattr;
1566e0bca22Sgmcgarry extern struct rstack *rpole;
157*a301e773Splunky static int widestr, alwinl;
158c4627bc7Sgmcgarry NODE *cftnod;
159*a301e773Splunky static int attrwarn = 1;
1606e0bca22Sgmcgarry 
1616e0bca22Sgmcgarry #define	NORETYP	SNOCREAT /* no return type, save in unused field in symtab */
1626e0bca22Sgmcgarry 
163c4627bc7Sgmcgarry        NODE *bdty(int op, ...);
1646e0bca22Sgmcgarry static void fend(void);
1656e0bca22Sgmcgarry static void fundef(NODE *tp, NODE *p);
166c4627bc7Sgmcgarry static void olddecl(NODE *p, NODE *a);
167c4627bc7Sgmcgarry static struct symtab *init_declarator(NODE *tn, NODE *p, int assign, NODE *a);
1686e0bca22Sgmcgarry static void resetbc(int mask);
1696e0bca22Sgmcgarry static void swend(void);
1706e0bca22Sgmcgarry static void addcase(NODE *p);
171c4627bc7Sgmcgarry #ifdef GCC_COMPAT
172c4627bc7Sgmcgarry static void gcccase(NODE *p, NODE *);
173c4627bc7Sgmcgarry #endif
1746e0bca22Sgmcgarry static void adddef(void);
1756e0bca22Sgmcgarry static void savebc(void);
1766e0bca22Sgmcgarry static void swstart(int, TWORD);
1776e0bca22Sgmcgarry static void genswitch(int, TWORD, struct swents **, int);
1786e0bca22Sgmcgarry static char *mkpstr(char *str);
1796e0bca22Sgmcgarry static struct symtab *clbrace(NODE *);
1806e0bca22Sgmcgarry static NODE *cmop(NODE *l, NODE *r);
1816e0bca22Sgmcgarry static NODE *xcmop(NODE *out, NODE *in, NODE *str);
1826e0bca22Sgmcgarry static void mkxasm(char *str, NODE *p);
1836e0bca22Sgmcgarry static NODE *xasmop(char *str, NODE *p);
1846e0bca22Sgmcgarry static int maxstlen(char *str);
1856e0bca22Sgmcgarry static char *stradd(char *old, char *new);
1866e0bca22Sgmcgarry static NODE *biop(int op, NODE *l, NODE *r);
1876e0bca22Sgmcgarry static void flend(void);
188c4627bc7Sgmcgarry static char * simname(char *s);
189c4627bc7Sgmcgarry #ifdef GCC_COMPAT
190c4627bc7Sgmcgarry static NODE *tyof(NODE *);	/* COMPAT_GCC */
191c4627bc7Sgmcgarry static NODE *voidcon(void);	/* COMPAT_GCC */
192c4627bc7Sgmcgarry #endif
193*a301e773Splunky static NODE *funargs(NODE *p);
194c4627bc7Sgmcgarry static void oldargs(NODE *p);
1953eb51a41Splunky static void uawarn(NODE *p, char *s);
1963eb51a41Splunky static int con_e(NODE *p);
1973eb51a41Splunky static void dainit(NODE *d, NODE *a);
198*a301e773Splunky static NODE *tymfix(NODE *p);
199*a301e773Splunky static NODE *namekill(NODE *p, int clr);
200*a301e773Splunky static NODE *aryfix(NODE *p);
2013eb51a41Splunky 
202*a301e773Splunky #define	TYMFIX(inp) { \
203*a301e773Splunky 	NODE *pp = inp; \
204*a301e773Splunky 	inp = tymerge(pp->n_left, pp->n_right); \
205*a301e773Splunky 	nfree(pp->n_left); nfree(pp); }
2066e0bca22Sgmcgarry /*
2076e0bca22Sgmcgarry  * State for saving current switch state (when nested switches).
2086e0bca22Sgmcgarry  */
2096e0bca22Sgmcgarry struct savbc {
2106e0bca22Sgmcgarry 	struct savbc *next;
2116e0bca22Sgmcgarry 	int brklab;
2126e0bca22Sgmcgarry 	int contlab;
2136e0bca22Sgmcgarry 	int flostat;
2146e0bca22Sgmcgarry 	int swx;
2156e0bca22Sgmcgarry } *savbc, *savctx;
2166e0bca22Sgmcgarry 
2176e0bca22Sgmcgarry %}
2186e0bca22Sgmcgarry 
2196e0bca22Sgmcgarry %union {
2206e0bca22Sgmcgarry 	int intval;
2216e0bca22Sgmcgarry 	NODE *nodep;
2226e0bca22Sgmcgarry 	struct symtab *symp;
2236e0bca22Sgmcgarry 	struct rstack *rp;
2246e0bca22Sgmcgarry 	char *strp;
2256e0bca22Sgmcgarry }
2266e0bca22Sgmcgarry 
2276e0bca22Sgmcgarry 	/* define types */
2286e0bca22Sgmcgarry %start ext_def_list
2296e0bca22Sgmcgarry 
2303eb51a41Splunky %type <intval> ifelprefix ifprefix whprefix forprefix doprefix switchpart
231*a301e773Splunky 		xbegin
232*a301e773Splunky %type <nodep> e .e term enum_dcl struct_dcl cast_type declarator
233c4627bc7Sgmcgarry 		elist type_sq cf_spec merge_attribs
2346e0bca22Sgmcgarry 		parameter_declaration abstract_declarator initializer
2356e0bca22Sgmcgarry 		parameter_type_list parameter_list addrlbl
2363eb51a41Splunky 		declaration_specifiers designation
2373eb51a41Splunky 		specifier_qualifier_list merge_specifiers
238c4627bc7Sgmcgarry 		identifier_list arg_param_list type_qualifier_list
2396e0bca22Sgmcgarry 		designator_list designator xasm oplist oper cnstr funtype
240c4627bc7Sgmcgarry 		typeof attribute attribute_specifier /* COMPAT_GCC */
241c4627bc7Sgmcgarry 		attribute_list attr_spec_list attr_var /* COMPAT_GCC */
242*a301e773Splunky %type <strp>	string C_STRING GCC_DESIG
2436e0bca22Sgmcgarry %type <rp>	str_head
2446e0bca22Sgmcgarry %type <symp>	xnfdeclarator clbrace enum_head
2456e0bca22Sgmcgarry 
246c4627bc7Sgmcgarry %type <intval>  C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
2476e0bca22Sgmcgarry 		C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
2486e0bca22Sgmcgarry 
249c4627bc7Sgmcgarry %type <nodep>   C_TYPE C_QUALIFIER C_ICON C_FCON C_CLASS
2506e0bca22Sgmcgarry %type <strp>	C_NAME C_TYPENAME
2516e0bca22Sgmcgarry %%
2526e0bca22Sgmcgarry 
2536e0bca22Sgmcgarry ext_def_list:	   ext_def_list external_def
2546e0bca22Sgmcgarry 		| { ftnend(); }
2556e0bca22Sgmcgarry 		;
2566e0bca22Sgmcgarry 
2576e0bca22Sgmcgarry external_def:	   funtype kr_args compoundstmt { fend(); }
2586e0bca22Sgmcgarry 		|  declaration  { blevel = 0; symclear(0); }
2596e0bca22Sgmcgarry 		|  asmstatement ';'
2606e0bca22Sgmcgarry 		|  ';'
2616e0bca22Sgmcgarry 		|  error { blevel = 0; }
2626e0bca22Sgmcgarry 		;
2636e0bca22Sgmcgarry 
2646e0bca22Sgmcgarry funtype:	  /* no type given */ declarator {
265*a301e773Splunky 		    fundef(mkty(INT, 0, 0), $1);
2666e0bca22Sgmcgarry 		    cftnsp->sflags |= NORETYP;
2676e0bca22Sgmcgarry 		}
2686e0bca22Sgmcgarry 		| declaration_specifiers declarator { fundef($1,$2); }
2696e0bca22Sgmcgarry 		;
2706e0bca22Sgmcgarry 
2716e0bca22Sgmcgarry kr_args:	  /* empty */
2726e0bca22Sgmcgarry 		| arg_dcl_list
2736e0bca22Sgmcgarry 		;
2746e0bca22Sgmcgarry 
2756e0bca22Sgmcgarry /*
2766e0bca22Sgmcgarry  * Returns a node pointer or NULL, if no types at all given.
2776e0bca22Sgmcgarry  * Type trees are checked for correctness and merged into one
2786e0bca22Sgmcgarry  * type node in typenode().
2796e0bca22Sgmcgarry  */
2806e0bca22Sgmcgarry declaration_specifiers:
2816e0bca22Sgmcgarry 		   merge_attribs { $$ = typenode($1); }
2826e0bca22Sgmcgarry 		;
2836e0bca22Sgmcgarry 
284c4627bc7Sgmcgarry merge_attribs:	   type_sq { $$ = $1; }
285c4627bc7Sgmcgarry 		|  type_sq merge_attribs { $$ = cmop($2, $1); }
286c4627bc7Sgmcgarry 		|  cf_spec { $$ = $1; }
287c4627bc7Sgmcgarry 		|  cf_spec merge_attribs { $$ = cmop($2, $1); }
2886e0bca22Sgmcgarry 		;
2896e0bca22Sgmcgarry 
290c4627bc7Sgmcgarry type_sq:	   C_TYPE { $$ = $1; }
2916e0bca22Sgmcgarry 		|  C_TYPENAME {
2926e0bca22Sgmcgarry 			struct symtab *sp = lookup($1, 0);
293*a301e773Splunky 			if (sp->stype == ENUMTY) {
294*a301e773Splunky 				sp->stype = strmemb(sp->sap)->stype;
295*a301e773Splunky 			}
296*a301e773Splunky 			$$ = mkty(sp->stype, sp->sdf, sp->sap);
2976e0bca22Sgmcgarry 			$$->n_sp = sp;
2986e0bca22Sgmcgarry 		}
2996e0bca22Sgmcgarry 		|  struct_dcl { $$ = $1; }
3006e0bca22Sgmcgarry 		|  enum_dcl { $$ = $1; }
301c4627bc7Sgmcgarry 		|  C_QUALIFIER { $$ = $1; }
302c4627bc7Sgmcgarry 		|  attribute_specifier { $$ = biop(ATTRIB, $1, 0); }
303c4627bc7Sgmcgarry 		|  typeof { $$ = $1; }
304c4627bc7Sgmcgarry 		;
305c4627bc7Sgmcgarry 
306c4627bc7Sgmcgarry cf_spec:	   C_CLASS { $$ = $1; }
307c4627bc7Sgmcgarry 		|  C_FUNSPEC { fun_inline = 1;  /* XXX - hack */
308c4627bc7Sgmcgarry 			$$ = block(QUALIFIER, NIL, NIL, 0, 0, 0); }
309c4627bc7Sgmcgarry 		;
310c4627bc7Sgmcgarry 
311*a301e773Splunky typeof:		   C_TYPEOF '(' e ')' { $$ = tyof(eve($3)); }
312*a301e773Splunky 		|  C_TYPEOF '(' cast_type ')' { TYMFIX($3); $$ = tyof($3); }
313*a301e773Splunky 		;
314c4627bc7Sgmcgarry 
315c4627bc7Sgmcgarry attribute_specifier :
316c4627bc7Sgmcgarry 		   C_ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; }
317c4627bc7Sgmcgarry  /*COMPAT_GCC*/	;
318c4627bc7Sgmcgarry 
319c4627bc7Sgmcgarry attribute_list:	   attribute
320c4627bc7Sgmcgarry 		|  attribute ',' attribute_list { $$ = cmop($3, $1); }
321c4627bc7Sgmcgarry 		;
322c4627bc7Sgmcgarry 
323c4627bc7Sgmcgarry attribute:	   {
324c4627bc7Sgmcgarry #ifdef GCC_COMPAT
325c4627bc7Sgmcgarry 			 $$ = voidcon();
326c4627bc7Sgmcgarry #endif
327c4627bc7Sgmcgarry 		}
328c4627bc7Sgmcgarry 		|  C_NAME { $$ = bdty(NAME, $1); }
329c4627bc7Sgmcgarry 		|  C_NAME '(' elist ')' {
330c4627bc7Sgmcgarry 			$$ = bdty($3 == NIL ? UCALL : CALL, bdty(NAME, $1), $3);
331c4627bc7Sgmcgarry 		}
3326e0bca22Sgmcgarry 		;
3336e0bca22Sgmcgarry 
3346e0bca22Sgmcgarry /*
3356e0bca22Sgmcgarry  * Adds a pointer list to front of the declarators.
3366e0bca22Sgmcgarry  */
337c4627bc7Sgmcgarry declarator:	   '*' declarator { $$ = bdty(UMUL, $2); }
338c4627bc7Sgmcgarry 		|  '*' type_qualifier_list declarator {
339*a301e773Splunky 			$$ = $2;
340*a301e773Splunky 			$$->n_left = $3;
3416e0bca22Sgmcgarry 		}
342c4627bc7Sgmcgarry 		|  C_NAME { $$ = bdty(NAME, $1); }
3433eb51a41Splunky 		|  '(' attr_spec_list declarator ')' {
3443eb51a41Splunky 			$$ = $3;
345*a301e773Splunky 			$$->n_ap = attr_add($$->n_ap, gcc_attr_parse($2));
3463eb51a41Splunky 		}
3476e0bca22Sgmcgarry 		|  '(' declarator ')' { $$ = $2; }
348*a301e773Splunky 		|  declarator '[' e ']' { $$ = biop(LB, $1, $3); }
349*a301e773Splunky 		|  declarator '[' C_CLASS e ']' {
350*a301e773Splunky 			if ($3->n_type != STATIC)
351*a301e773Splunky 				uerror("bad class keyword");
352*a301e773Splunky 			tfree($3); /* XXX - handle */
353*a301e773Splunky 			$$ = biop(LB, $1, $4);
3546e0bca22Sgmcgarry 		}
3553eb51a41Splunky 		|  declarator '[' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); }
3563eb51a41Splunky 		|  declarator '[' '*' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); }
357*a301e773Splunky 		|  declarator '(' parameter_type_list ')' {
358*a301e773Splunky 			$$ = bdty(CALL, $1, $3);
3596e0bca22Sgmcgarry 		}
360*a301e773Splunky 		|  declarator '(' identifier_list ')' {
361*a301e773Splunky 			$$ = bdty(CALL, $1, $3);
3626e0bca22Sgmcgarry 			oldstyle = 1;
3636e0bca22Sgmcgarry 		}
364*a301e773Splunky 		|  declarator '(' ')' { $$ = bdty(UCALL, $1); }
365c4627bc7Sgmcgarry 		;
366c4627bc7Sgmcgarry 
367c4627bc7Sgmcgarry type_qualifier_list:
368*a301e773Splunky 		   C_QUALIFIER { $$ = $1; $$->n_op = UMUL; }
369c4627bc7Sgmcgarry 		|  type_qualifier_list C_QUALIFIER {
370c4627bc7Sgmcgarry 			$$ = $1;
371*a301e773Splunky 			$$->n_qual |= $2->n_qual;
372c4627bc7Sgmcgarry 			nfree($2);
373c4627bc7Sgmcgarry 		}
374*a301e773Splunky 		|  attribute_specifier {
375*a301e773Splunky 			$$ = block(UMUL, NIL, NIL, 0, 0, gcc_attr_parse($1));
376c4627bc7Sgmcgarry 		}
377*a301e773Splunky 		|  type_qualifier_list attribute_specifier {
378*a301e773Splunky 			$1->n_ap = attr_add($1->n_ap, gcc_attr_parse($2));
379c4627bc7Sgmcgarry 		}
380c4627bc7Sgmcgarry 		;
381c4627bc7Sgmcgarry 
382c4627bc7Sgmcgarry identifier_list:   C_NAME { $$ = bdty(NAME, $1); oldargs($$); }
383*a301e773Splunky 		|  identifier_list ',' C_NAME {
384*a301e773Splunky 			$$ = cmop($1, bdty(NAME, $3));
385*a301e773Splunky 			oldargs($$->n_right);
386*a301e773Splunky 		}
3876e0bca22Sgmcgarry 		;
3886e0bca22Sgmcgarry 
3896e0bca22Sgmcgarry /*
3906e0bca22Sgmcgarry  * Returns as parameter_list, but can add an additional ELLIPSIS node.
3916e0bca22Sgmcgarry  */
3926e0bca22Sgmcgarry parameter_type_list:
3936e0bca22Sgmcgarry 		   parameter_list { $$ = $1; }
3946e0bca22Sgmcgarry 		|  parameter_list ',' C_ELLIPSIS {
3956e0bca22Sgmcgarry 			$$ = cmop($1, biop(ELLIPSIS, NIL, NIL));
3966e0bca22Sgmcgarry 		}
3976e0bca22Sgmcgarry 		;
3986e0bca22Sgmcgarry 
3996e0bca22Sgmcgarry /*
4006e0bca22Sgmcgarry  * Returns a linked lists of nodes of op CM with parameters on
4016e0bca22Sgmcgarry  * its right and additional CM nodes of its left pointer.
4026e0bca22Sgmcgarry  * No CM nodes if only one parameter.
4036e0bca22Sgmcgarry  */
4046e0bca22Sgmcgarry parameter_list:	   parameter_declaration { $$ = $1; }
4056e0bca22Sgmcgarry 		|  parameter_list ',' parameter_declaration {
4066e0bca22Sgmcgarry 			$$ = cmop($1, $3);
4076e0bca22Sgmcgarry 		}
4086e0bca22Sgmcgarry 		;
4096e0bca22Sgmcgarry 
4106e0bca22Sgmcgarry /*
4116e0bca22Sgmcgarry  * Returns a node pointer to the declaration.
4126e0bca22Sgmcgarry  */
4136e0bca22Sgmcgarry parameter_declaration:
414c4627bc7Sgmcgarry 		   declaration_specifiers declarator attr_var {
4156e0bca22Sgmcgarry 			if ($1->n_lval != SNULL && $1->n_lval != REGISTER)
4166e0bca22Sgmcgarry 				uerror("illegal parameter class");
417*a301e773Splunky 			$$ = block(TYMERGE, $1, $2, INT, 0, gcc_attr_parse($3));
4186e0bca22Sgmcgarry 		}
4196e0bca22Sgmcgarry 		|  declaration_specifiers abstract_declarator {
420*a301e773Splunky 			$$ = block(TYMERGE, $1, $2, INT, 0, 0);
4216e0bca22Sgmcgarry 		}
4226e0bca22Sgmcgarry 		|  declaration_specifiers {
423*a301e773Splunky 			$$ = block(TYMERGE, $1, bdty(NAME, NULL), INT, 0, 0);
4246e0bca22Sgmcgarry 		}
4256e0bca22Sgmcgarry 		;
4266e0bca22Sgmcgarry 
4276e0bca22Sgmcgarry abstract_declarator:
428c4627bc7Sgmcgarry 		   '*' { $$ = bdty(UMUL, bdty(NAME, NULL)); }
429c4627bc7Sgmcgarry 		|  '*' type_qualifier_list {
430*a301e773Splunky 			$$ = $2;
431*a301e773Splunky 			$$->n_left = bdty(NAME, NULL);
4326e0bca22Sgmcgarry 		}
433c4627bc7Sgmcgarry 		|  '*' abstract_declarator { $$ = bdty(UMUL, $2); }
434c4627bc7Sgmcgarry 		|  '*' type_qualifier_list abstract_declarator {
435*a301e773Splunky 			$$ = $2;
436*a301e773Splunky 			$$->n_left = $3;
437c4627bc7Sgmcgarry 		}
438c4627bc7Sgmcgarry 		|  '(' abstract_declarator ')' { $$ = $2; }
439c4627bc7Sgmcgarry 		|  '[' ']' attr_var {
440*a301e773Splunky 			$$ = block(LB, bdty(NAME, NULL), bcon(NOOFFSET),
441*a301e773Splunky 			    INT, 0, gcc_attr_parse($3));
442c4627bc7Sgmcgarry 		}
4433eb51a41Splunky 		|  '[' e ']' attr_var {
444*a301e773Splunky 			$$ = block(LB, bdty(NAME, NULL), $2,
445*a301e773Splunky 			    INT, 0, gcc_attr_parse($4));
446c4627bc7Sgmcgarry 		}
447c4627bc7Sgmcgarry 		|  abstract_declarator '[' ']' attr_var {
448*a301e773Splunky 			$$ = block(LB, $1, bcon(NOOFFSET),
449*a301e773Splunky 			    INT, 0, gcc_attr_parse($4));
4506e0bca22Sgmcgarry 		}
4513eb51a41Splunky 		|  abstract_declarator '[' e ']' attr_var {
452*a301e773Splunky 			$$ = block(LB, $1, $3, INT, 0, gcc_attr_parse($5));
4536e0bca22Sgmcgarry 		}
4546e0bca22Sgmcgarry 		|  '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
455c4627bc7Sgmcgarry 		|  '(' ib2 parameter_type_list ')' {
456c4627bc7Sgmcgarry 			$$ = bdty(CALL, bdty(NAME, NULL), $3);
4576e0bca22Sgmcgarry 		}
458c4627bc7Sgmcgarry 		|  abstract_declarator '(' ')' {
4596e0bca22Sgmcgarry 			$$ = bdty(UCALL, $1);
4606e0bca22Sgmcgarry 		}
461c4627bc7Sgmcgarry 		|  abstract_declarator '(' ib2 parameter_type_list ')' {
462c4627bc7Sgmcgarry 			$$ = bdty(CALL, $1, $4);
4636e0bca22Sgmcgarry 		}
4646e0bca22Sgmcgarry 		;
4656e0bca22Sgmcgarry 
466*a301e773Splunky ib2:		  { }
467c4627bc7Sgmcgarry 		;
4686e0bca22Sgmcgarry /*
4696e0bca22Sgmcgarry  * K&R arg declaration, between ) and {
4706e0bca22Sgmcgarry  */
4716e0bca22Sgmcgarry arg_dcl_list:	   arg_declaration
4726e0bca22Sgmcgarry 		|  arg_dcl_list arg_declaration
4736e0bca22Sgmcgarry 		;
4746e0bca22Sgmcgarry 
4756e0bca22Sgmcgarry 
4766e0bca22Sgmcgarry arg_declaration:   declaration_specifiers arg_param_list ';' {
4776e0bca22Sgmcgarry 			nfree($1);
4786e0bca22Sgmcgarry 		}
4796e0bca22Sgmcgarry 		;
4806e0bca22Sgmcgarry 
481*a301e773Splunky arg_param_list:	   declarator attr_var {
482*a301e773Splunky 			olddecl(block(TYMERGE, ccopy($<nodep>0), $1,
483*a301e773Splunky 			    INT, 0, 0), $2);
484*a301e773Splunky 		}
485c4627bc7Sgmcgarry 		|  arg_param_list ',' declarator attr_var {
486*a301e773Splunky 			olddecl(block(TYMERGE, ccopy($<nodep>0), $3,
487*a301e773Splunky 			    INT, 0, 0), $4);
4886e0bca22Sgmcgarry 		}
4896e0bca22Sgmcgarry 		;
4906e0bca22Sgmcgarry 
4916e0bca22Sgmcgarry /*
4926e0bca22Sgmcgarry  * Declarations in beginning of blocks.
4936e0bca22Sgmcgarry  */
4946e0bca22Sgmcgarry block_item_list:   block_item
4956e0bca22Sgmcgarry 		|  block_item_list block_item
4966e0bca22Sgmcgarry 		;
4976e0bca22Sgmcgarry 
4986e0bca22Sgmcgarry block_item:	   declaration
4996e0bca22Sgmcgarry 		|  statement
5006e0bca22Sgmcgarry 		;
5016e0bca22Sgmcgarry 
5026e0bca22Sgmcgarry /*
5036e0bca22Sgmcgarry  * Here starts the old YACC code.
5046e0bca22Sgmcgarry  */
5056e0bca22Sgmcgarry 
5066e0bca22Sgmcgarry /*
5076e0bca22Sgmcgarry  * Variables are declared in init_declarator.
5086e0bca22Sgmcgarry  */
509c4627bc7Sgmcgarry declaration:	   declaration_specifiers ';' { tfree($1); fun_inline = 0; }
5106e0bca22Sgmcgarry 		|  declaration_specifiers init_declarator_list ';' {
511c4627bc7Sgmcgarry 			tfree($1);
5126e0bca22Sgmcgarry 			fun_inline = 0;
5136e0bca22Sgmcgarry 		}
5146e0bca22Sgmcgarry 		;
5156e0bca22Sgmcgarry 
5166e0bca22Sgmcgarry /*
5176e0bca22Sgmcgarry  * Normal declaration of variables. curtype contains the current type node.
5186e0bca22Sgmcgarry  * Returns nothing, variables are declared in init_declarator.
5196e0bca22Sgmcgarry  */
5206e0bca22Sgmcgarry init_declarator_list:
521*a301e773Splunky 		   init_declarator { symclear(blevel); }
522c4627bc7Sgmcgarry 		|  init_declarator_list ',' attr_var { $<nodep>$ = $<nodep>0; } init_declarator {
523*a301e773Splunky 			uawarn($3, "init_declarator");
524*a301e773Splunky 			symclear(blevel);
525c4627bc7Sgmcgarry 		}
5266e0bca22Sgmcgarry 		;
5276e0bca22Sgmcgarry 
5286e0bca22Sgmcgarry enum_dcl:	   enum_head '{' moe_list optcomma '}' { $$ = enumdcl($1); }
5296e0bca22Sgmcgarry 		|  C_ENUM C_NAME {  $$ = enumref($2); }
5306e0bca22Sgmcgarry 		;
5316e0bca22Sgmcgarry 
5326e0bca22Sgmcgarry enum_head:	   C_ENUM { $$ = enumhd(NULL); }
5336e0bca22Sgmcgarry 		|  C_ENUM C_NAME {  $$ = enumhd($2); }
5346e0bca22Sgmcgarry 		;
5356e0bca22Sgmcgarry 
5366e0bca22Sgmcgarry moe_list:	   moe
5376e0bca22Sgmcgarry 		|  moe_list ',' moe
5386e0bca22Sgmcgarry 		;
5396e0bca22Sgmcgarry 
5406e0bca22Sgmcgarry moe:		   C_NAME {  moedef($1); }
5416e0bca22Sgmcgarry 		|  C_TYPENAME {  moedef($1); }
5423eb51a41Splunky 		|  C_NAME '=' e { enummer = con_e($3); moedef($1); }
5433eb51a41Splunky 		|  C_TYPENAME '=' e { enummer = con_e($3); moedef($1); }
5446e0bca22Sgmcgarry 		;
5456e0bca22Sgmcgarry 
546*a301e773Splunky struct_dcl:	   str_head '{' struct_dcl_list '}' {
547*a301e773Splunky 			NODE *p;
548*a301e773Splunky 
549*a301e773Splunky 			$$ = dclstruct($1);
550*a301e773Splunky 			if (pragma_allpacked) {
551*a301e773Splunky 				p = bdty(CALL, bdty(NAME, "packed"),
552*a301e773Splunky 				    bcon(pragma_allpacked));
553*a301e773Splunky 				$$->n_ap = attr_add($$->n_ap,gcc_attr_parse(p)); }
5546e0bca22Sgmcgarry 		}
555*a301e773Splunky 		|  C_STRUCT attr_var C_NAME {
556*a301e773Splunky 			$$ = rstruct($3,$1);
557*a301e773Splunky 			uawarn($2, "struct_dcl");
5586e0bca22Sgmcgarry 		}
559c4627bc7Sgmcgarry  /*COMPAT_GCC*/	|  str_head '{' '}' { $$ = dclstruct($1); }
5606e0bca22Sgmcgarry 		;
5616e0bca22Sgmcgarry 
562c4627bc7Sgmcgarry attr_var:	   {
563c4627bc7Sgmcgarry 			NODE *q, *p;
564c4627bc7Sgmcgarry 
565c4627bc7Sgmcgarry 			p = pragma_aligned ? bdty(CALL, bdty(NAME, "aligned"),
566c4627bc7Sgmcgarry 			    bcon(pragma_aligned)) : NIL;
567c4627bc7Sgmcgarry 			if (pragma_packed) {
568c4627bc7Sgmcgarry 				q = bdty(NAME, "packed");
569c4627bc7Sgmcgarry 				p = (p == NIL ? q : cmop(p, q));
570c4627bc7Sgmcgarry 			}
571c4627bc7Sgmcgarry 			pragma_aligned = pragma_packed = 0;
572c4627bc7Sgmcgarry 			$$ = p;
573c4627bc7Sgmcgarry 		}
574c4627bc7Sgmcgarry  /*COMPAT_GCC*/	|  attr_spec_list
5756e0bca22Sgmcgarry 		;
5766e0bca22Sgmcgarry 
577c4627bc7Sgmcgarry attr_spec_list:	   attribute_specifier
578c4627bc7Sgmcgarry 		|  attr_spec_list attribute_specifier { $$ = cmop($1, $2); }
579c4627bc7Sgmcgarry 		;
580c4627bc7Sgmcgarry 
581c4627bc7Sgmcgarry str_head:	   C_STRUCT attr_var {  $$ = bstruct(NULL, $1, $2);  }
582c4627bc7Sgmcgarry 		|  C_STRUCT attr_var C_NAME {  $$ = bstruct($3, $1, $2);  }
5836e0bca22Sgmcgarry 		;
5846e0bca22Sgmcgarry 
5856e0bca22Sgmcgarry struct_dcl_list:   struct_declaration
5866e0bca22Sgmcgarry 		|  struct_dcl_list struct_declaration
5876e0bca22Sgmcgarry 		;
5886e0bca22Sgmcgarry 
5896e0bca22Sgmcgarry struct_declaration:
590c4627bc7Sgmcgarry 		   specifier_qualifier_list struct_declarator_list optsemi {
591*a301e773Splunky 			tfree($1);
5926e0bca22Sgmcgarry 		}
5936e0bca22Sgmcgarry 		;
5946e0bca22Sgmcgarry 
595c4627bc7Sgmcgarry optsemi:	   ';' { }
596c4627bc7Sgmcgarry 		|  optsemi ';' { werror("extra ; in struct"); }
597c4627bc7Sgmcgarry 		;
598c4627bc7Sgmcgarry 
5996e0bca22Sgmcgarry specifier_qualifier_list:
6006e0bca22Sgmcgarry 		   merge_specifiers { $$ = typenode($1); }
6016e0bca22Sgmcgarry 		;
6026e0bca22Sgmcgarry 
603c4627bc7Sgmcgarry merge_specifiers:  type_sq merge_specifiers { $$ = cmop($2, $1); }
604c4627bc7Sgmcgarry 		|  type_sq { $$ = $1; }
6056e0bca22Sgmcgarry 		;
6066e0bca22Sgmcgarry 
6076e0bca22Sgmcgarry struct_declarator_list:
608*a301e773Splunky 		   struct_declarator { symclear(blevel); }
6096e0bca22Sgmcgarry 		|  struct_declarator_list ',' { $<nodep>$=$<nodep>0; }
610*a301e773Splunky 			struct_declarator { symclear(blevel); }
6116e0bca22Sgmcgarry 		;
6126e0bca22Sgmcgarry 
613c4627bc7Sgmcgarry struct_declarator: declarator attr_var {
614*a301e773Splunky 			NODE *p;
615*a301e773Splunky 
616*a301e773Splunky 			$1 = aryfix($1);
617*a301e773Splunky 			p = tymerge($<nodep>0, tymfix($1));
618*a301e773Splunky 			if ($2)
619*a301e773Splunky 				p->n_ap = attr_add(p->n_ap, gcc_attr_parse($2));
620*a301e773Splunky 			soumemb(p, (char *)$1->n_sp, 0);
621*a301e773Splunky 			tfree(p);
6226e0bca22Sgmcgarry 		}
6233eb51a41Splunky 		|  ':' e {
6243eb51a41Splunky 			int ie = con_e($2);
6253eb51a41Splunky 			if (fldchk(ie))
6263eb51a41Splunky 				ie = 1;
6273eb51a41Splunky 			falloc(NULL, ie, $<nodep>0);
6286e0bca22Sgmcgarry 		}
6293eb51a41Splunky 		|  declarator ':' e {
6303eb51a41Splunky 			int ie = con_e($3);
6313eb51a41Splunky 			if (fldchk(ie))
6323eb51a41Splunky 				ie = 1;
6336e0bca22Sgmcgarry 			if ($1->n_op == NAME) {
634*a301e773Splunky 				/* XXX - tymfix() may alter $1 */
635*a301e773Splunky 				tymerge($<nodep>0, tymfix($1));
636*a301e773Splunky 				soumemb($1, (char *)$1->n_sp, FIELD | ie);
637*a301e773Splunky 				nfree($1);
638*a301e773Splunky 			} else
639*a301e773Splunky 				uerror("illegal declarator");
640*a301e773Splunky 		}
641*a301e773Splunky 		|  declarator ':' e attr_spec_list {
642*a301e773Splunky 			int ie = con_e($3);
643*a301e773Splunky 			if (fldchk(ie))
644*a301e773Splunky 				ie = 1;
645*a301e773Splunky 			if ($1->n_op == NAME) {
646*a301e773Splunky 				/* XXX - tymfix() may alter $1 */
647*a301e773Splunky 				tymerge($<nodep>0, tymfix($1));
648*a301e773Splunky 				if ($4)
649*a301e773Splunky 					$1->n_ap = attr_add($1->n_ap,
650*a301e773Splunky 					    gcc_attr_parse($4));
6513eb51a41Splunky 				soumemb($1, (char *)$1->n_sp, FIELD | ie);
6526e0bca22Sgmcgarry 				nfree($1);
6536e0bca22Sgmcgarry 			} else
6546e0bca22Sgmcgarry 				uerror("illegal declarator");
6556e0bca22Sgmcgarry 		}
656c4627bc7Sgmcgarry 		| /* unnamed member */ {
657c4627bc7Sgmcgarry 			NODE *p = $<nodep>0;
658c4627bc7Sgmcgarry 			char *c = permalloc(10);
659c4627bc7Sgmcgarry 
660c4627bc7Sgmcgarry 			if (p->n_type != STRTY && p->n_type != UNIONTY)
661c4627bc7Sgmcgarry 				uerror("bad unnamed member type");
662c4627bc7Sgmcgarry 			snprintf(c, 10, "*%dFAKE", getlab());
663c4627bc7Sgmcgarry 			soumemb(p, c, 0);
664c4627bc7Sgmcgarry 		}
6656e0bca22Sgmcgarry 		;
6666e0bca22Sgmcgarry 
6676e0bca22Sgmcgarry 		/* always preceeded by attributes */
668c4627bc7Sgmcgarry xnfdeclarator:	   declarator attr_var {
669c4627bc7Sgmcgarry 			$$ = xnf = init_declarator($<nodep>0, $1, 1, $2);
670c4627bc7Sgmcgarry 		}
6713eb51a41Splunky 		|  declarator C_ASM '(' string ')' {
6723eb51a41Splunky 			pragma_renamed = newstring($4, strlen($4));
6733eb51a41Splunky 			$$ = xnf = init_declarator($<nodep>0, $1, 1, NULL);
6743eb51a41Splunky 		}
6756e0bca22Sgmcgarry 		;
6766e0bca22Sgmcgarry 
6776e0bca22Sgmcgarry /*
6786e0bca22Sgmcgarry  * Handles declarations and assignments.
6796e0bca22Sgmcgarry  * Returns nothing.
6806e0bca22Sgmcgarry  */
681c4627bc7Sgmcgarry init_declarator:   declarator attr_var { init_declarator($<nodep>0, $1, 0, $2);}
6823eb51a41Splunky 		|  declarator C_ASM '(' string ')' attr_var {
6836e0bca22Sgmcgarry #ifdef GCC_COMPAT
6846e0bca22Sgmcgarry 			pragma_renamed = newstring($4, strlen($4));
6853eb51a41Splunky 			init_declarator($<nodep>0, $1, 0, $6);
6866e0bca22Sgmcgarry #else
6876e0bca22Sgmcgarry 			werror("gcc extension");
6883eb51a41Splunky 			init_declarator($<nodep>0, $1, 0, $6);
6896e0bca22Sgmcgarry #endif
6906e0bca22Sgmcgarry 		}
691*a301e773Splunky 		|  xnfdeclarator '=' e {
692*a301e773Splunky 			if ($1->sclass == STATIC || $1->sclass == EXTDEF)
693*a301e773Splunky 				statinit++;
694*a301e773Splunky 			simpleinit($1, eve($3));
695*a301e773Splunky 			if ($1->sclass == STATIC || $1->sclass == EXTDEF)
696*a301e773Splunky 				statinit--;
6976e0bca22Sgmcgarry 			xnf = NULL;
6986e0bca22Sgmcgarry 		}
699*a301e773Splunky 		|  xnfdeclarator '=' begbr init_list optcomma '}' {
700*a301e773Splunky 			endinit(0);
701*a301e773Splunky 			xnf = NULL;
702*a301e773Splunky 		}
703*a301e773Splunky  /*COMPAT_GCC*/	|  xnfdeclarator '=' begbr '}' { endinit(0); xnf = NULL; }
7046e0bca22Sgmcgarry 		|  xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
7056e0bca22Sgmcgarry 		;
7066e0bca22Sgmcgarry 
7076e0bca22Sgmcgarry begbr:		   '{' { beginit($<symp>-1); }
7086e0bca22Sgmcgarry 		;
7096e0bca22Sgmcgarry 
710c4627bc7Sgmcgarry initializer:	   e %prec ',' {  $$ = eve($1); }
7116e0bca22Sgmcgarry 		|  addrlbl {  $$ = $1; }
7126e0bca22Sgmcgarry 		|  ibrace init_list optcomma '}' { $$ = NULL; }
713c4627bc7Sgmcgarry 		|  ibrace '}' { asginit(bcon(0)); $$ = NULL; }
7146e0bca22Sgmcgarry 		;
7156e0bca22Sgmcgarry 
7163eb51a41Splunky init_list:	   designation initializer { dainit($1, $2); }
7173eb51a41Splunky 		|  init_list ','  designation initializer { dainit($3, $4); }
7186e0bca22Sgmcgarry 		;
7196e0bca22Sgmcgarry 
7203eb51a41Splunky designation:	   designator_list '=' { desinit($1); $$ = NIL; }
721*a301e773Splunky 		|  GCC_DESIG { desinit(bdty(NAME, $1)); $$ = NIL; }
7223eb51a41Splunky 		|  '[' e C_ELLIPSIS e ']' '=' { $$ = biop(CM, $2, $4); }
7233eb51a41Splunky 		|  { $$ = NIL; }
7246e0bca22Sgmcgarry 		;
7256e0bca22Sgmcgarry 
7266e0bca22Sgmcgarry designator_list:   designator { $$ = $1; }
7276e0bca22Sgmcgarry 		|  designator_list designator { $$ = $2; $$->n_left = $1; }
7286e0bca22Sgmcgarry 		;
7296e0bca22Sgmcgarry 
7303eb51a41Splunky designator:	   '[' e ']' {
7313eb51a41Splunky 			int ie = con_e($2);
7323eb51a41Splunky 			if (ie < 0) {
7336e0bca22Sgmcgarry 				uerror("designator must be non-negative");
7343eb51a41Splunky 				ie = 0;
7356e0bca22Sgmcgarry 			}
7363eb51a41Splunky 			$$ = biop(LB, NIL, bcon(ie));
7376e0bca22Sgmcgarry 		}
738*a301e773Splunky 		|  C_STROP C_TYPENAME {
739*a301e773Splunky 			if ($1 != DOT)
740*a301e773Splunky 				uerror("invalid designator");
741*a301e773Splunky 			$$ = bdty(NAME, $2);
742*a301e773Splunky 		}
7436e0bca22Sgmcgarry 		|  C_STROP C_NAME {
7446e0bca22Sgmcgarry 			if ($1 != DOT)
7456e0bca22Sgmcgarry 				uerror("invalid designator");
7466e0bca22Sgmcgarry 			$$ = bdty(NAME, $2);
7476e0bca22Sgmcgarry 		}
7486e0bca22Sgmcgarry 		;
7496e0bca22Sgmcgarry 
7506e0bca22Sgmcgarry optcomma	:	/* VOID */
7516e0bca22Sgmcgarry 		|  ','
7526e0bca22Sgmcgarry 		;
7536e0bca22Sgmcgarry 
7546e0bca22Sgmcgarry ibrace:		   '{' {  ilbrace(); }
7556e0bca22Sgmcgarry 		;
7566e0bca22Sgmcgarry 
7576e0bca22Sgmcgarry /*	STATEMENTS	*/
7586e0bca22Sgmcgarry 
7596e0bca22Sgmcgarry compoundstmt:	   begin block_item_list '}' { flend(); }
7606e0bca22Sgmcgarry 		|  begin '}' { flend(); }
7616e0bca22Sgmcgarry 		;
7626e0bca22Sgmcgarry 
7636e0bca22Sgmcgarry begin:		  '{' {
7646e0bca22Sgmcgarry 			struct savbc *bc = tmpalloc(sizeof(struct savbc));
7656e0bca22Sgmcgarry 			if (blevel == 1) {
7666e0bca22Sgmcgarry #ifdef STABS
7676e0bca22Sgmcgarry 				if (gflag)
7686e0bca22Sgmcgarry 					stabs_line(lineno);
7696e0bca22Sgmcgarry #endif
7706e0bca22Sgmcgarry 				dclargs();
7716e0bca22Sgmcgarry 			}
7726e0bca22Sgmcgarry #ifdef STABS
7736e0bca22Sgmcgarry 			if (gflag && blevel > 1)
7746e0bca22Sgmcgarry 				stabs_lbrac(blevel+1);
7756e0bca22Sgmcgarry #endif
7766e0bca22Sgmcgarry 			++blevel;
7776e0bca22Sgmcgarry 			oldstyle = 0;
7786e0bca22Sgmcgarry 			bc->contlab = autooff;
7796e0bca22Sgmcgarry 			bc->next = savctx;
7806e0bca22Sgmcgarry 			savctx = bc;
781*a301e773Splunky 			if (!isinlining && sspflag && blevel == 2)
7826e0bca22Sgmcgarry 				sspstart();
7836e0bca22Sgmcgarry 		}
7846e0bca22Sgmcgarry 		;
7856e0bca22Sgmcgarry 
786c4627bc7Sgmcgarry statement:	   e ';' { ecomp(eve($1)); symclear(blevel); }
7876e0bca22Sgmcgarry 		|  compoundstmt
7886e0bca22Sgmcgarry 		|  ifprefix statement { plabel($1); reached = 1; }
7896e0bca22Sgmcgarry 		|  ifelprefix statement {
7906e0bca22Sgmcgarry 			if ($1 != NOLAB) {
7916e0bca22Sgmcgarry 				plabel( $1);
7926e0bca22Sgmcgarry 				reached = 1;
7936e0bca22Sgmcgarry 			}
7946e0bca22Sgmcgarry 		}
7956e0bca22Sgmcgarry 		|  whprefix statement {
7966e0bca22Sgmcgarry 			branch(contlab);
7976e0bca22Sgmcgarry 			plabel( brklab );
7986e0bca22Sgmcgarry 			if( (flostat&FBRK) || !(flostat&FLOOP))
7996e0bca22Sgmcgarry 				reached = 1;
8006e0bca22Sgmcgarry 			else
8016e0bca22Sgmcgarry 				reached = 0;
8026e0bca22Sgmcgarry 			resetbc(0);
8036e0bca22Sgmcgarry 		}
8046e0bca22Sgmcgarry 		|  doprefix statement C_WHILE '(' e ')' ';' {
8056e0bca22Sgmcgarry 			plabel(contlab);
8066e0bca22Sgmcgarry 			if (flostat & FCONT)
8076e0bca22Sgmcgarry 				reached = 1;
8086e0bca22Sgmcgarry 			if (reached)
809*a301e773Splunky 				cbranch(buildtree(NE, eve($5), bcon(0)),
810*a301e773Splunky 				    bcon($1));
8116e0bca22Sgmcgarry 			else
812c4627bc7Sgmcgarry 				tfree(eve($5));
8136e0bca22Sgmcgarry 			plabel( brklab);
8146e0bca22Sgmcgarry 			reached = 1;
8156e0bca22Sgmcgarry 			resetbc(0);
8166e0bca22Sgmcgarry 		}
8176e0bca22Sgmcgarry 		|  forprefix .e ')' statement
8186e0bca22Sgmcgarry 			{  plabel( contlab );
8196e0bca22Sgmcgarry 			    if( flostat&FCONT ) reached = 1;
8206e0bca22Sgmcgarry 			    if( $2 ) ecomp( $2 );
8216e0bca22Sgmcgarry 			    branch($1);
8226e0bca22Sgmcgarry 			    plabel( brklab );
8236e0bca22Sgmcgarry 			    if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
8246e0bca22Sgmcgarry 			    else reached = 0;
8256e0bca22Sgmcgarry 			    resetbc(0);
826*a301e773Splunky 			    symclear(blevel); /* if declaration inside for() */
8276e0bca22Sgmcgarry 			    }
8286e0bca22Sgmcgarry 		| switchpart statement
8296e0bca22Sgmcgarry 			{ if( reached ) branch( brklab );
8306e0bca22Sgmcgarry 			    plabel( $1 );
8316e0bca22Sgmcgarry 			    swend();
8326e0bca22Sgmcgarry 			    plabel( brklab);
8336e0bca22Sgmcgarry 			    if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
8346e0bca22Sgmcgarry 			    resetbc(FCONT);
8356e0bca22Sgmcgarry 			    }
8366e0bca22Sgmcgarry 		|  C_BREAK  ';' {
8376e0bca22Sgmcgarry 			if (brklab == NOLAB)
8386e0bca22Sgmcgarry 				uerror("illegal break");
8396e0bca22Sgmcgarry 			else if (reached)
8406e0bca22Sgmcgarry 				branch(brklab);
8416e0bca22Sgmcgarry 			flostat |= FBRK;
8426e0bca22Sgmcgarry 			reached = 0;
8436e0bca22Sgmcgarry 		}
8446e0bca22Sgmcgarry 		|  C_CONTINUE  ';' {
8456e0bca22Sgmcgarry 			if (contlab == NOLAB)
8466e0bca22Sgmcgarry 				uerror("illegal continue");
8476e0bca22Sgmcgarry 			else
8486e0bca22Sgmcgarry 				branch(contlab);
8496e0bca22Sgmcgarry 			flostat |= FCONT;
8506e0bca22Sgmcgarry 			goto rch;
8516e0bca22Sgmcgarry 		}
8526e0bca22Sgmcgarry 		|  C_RETURN  ';' {
8536e0bca22Sgmcgarry 			branch(retlab);
8546e0bca22Sgmcgarry 			if (cftnsp->stype != VOID &&
8556e0bca22Sgmcgarry 			    (cftnsp->sflags & NORETYP) == 0 &&
8566e0bca22Sgmcgarry 			    cftnsp->stype != VOID+FTN)
8576e0bca22Sgmcgarry 				uerror("return value required");
8586e0bca22Sgmcgarry 			rch:
859*a301e773Splunky 			if (!reached)
860*a301e773Splunky 				warner(Wunreachable_code, NULL);
8616e0bca22Sgmcgarry 			reached = 0;
8626e0bca22Sgmcgarry 		}
8636e0bca22Sgmcgarry 		|  C_RETURN e  ';' {
864c4627bc7Sgmcgarry 			NODE *p, *q;
8656e0bca22Sgmcgarry 
866c4627bc7Sgmcgarry 			p = nametree(cftnsp);
867c4627bc7Sgmcgarry 			p->n_type = DECREF(p->n_type);
868c4627bc7Sgmcgarry 			q = eve($2);
869c4627bc7Sgmcgarry #ifndef NO_COMPLEX
870c4627bc7Sgmcgarry 			if (ANYCX(q) || ANYCX(p))
871c4627bc7Sgmcgarry 				q = cxret(q, p);
872c4627bc7Sgmcgarry #endif
873c4627bc7Sgmcgarry 			p = buildtree(RETURN, p, q);
874c4627bc7Sgmcgarry 			if (p->n_type == VOID) {
875c4627bc7Sgmcgarry 				ecomp(p->n_right);
876c4627bc7Sgmcgarry 			} else {
877c4627bc7Sgmcgarry 				if (cftnod == NIL)
878c4627bc7Sgmcgarry 					cftnod = tempnode(0, p->n_type,
879*a301e773Splunky 					    p->n_df, p->n_ap);
880c4627bc7Sgmcgarry 				ecomp(buildtree(ASSIGN,
881c4627bc7Sgmcgarry 				    ccopy(cftnod), p->n_right));
882c4627bc7Sgmcgarry 			}
883c4627bc7Sgmcgarry 			tfree(p->n_left);
884c4627bc7Sgmcgarry 			nfree(p);
8856e0bca22Sgmcgarry 			branch(retlab);
8866e0bca22Sgmcgarry 			reached = 0;
8876e0bca22Sgmcgarry 		}
8886e0bca22Sgmcgarry 		|  C_GOTO C_NAME ';' { gotolabel($2); goto rch; }
889c4627bc7Sgmcgarry 		|  C_GOTO '*' e ';' { ecomp(biop(GOTO, eve($3), NIL)); }
8906e0bca22Sgmcgarry 		|  asmstatement ';'
8916e0bca22Sgmcgarry 		|   ';'
8926e0bca22Sgmcgarry 		|  error  ';'
8936e0bca22Sgmcgarry 		|  error '}'
8946e0bca22Sgmcgarry 		|  label statement
8956e0bca22Sgmcgarry 		;
8966e0bca22Sgmcgarry 
8976e0bca22Sgmcgarry asmstatement:	   C_ASM mvol '(' string ')' { send_passt(IP_ASM, mkpstr($4)); }
8986e0bca22Sgmcgarry 		|  C_ASM mvol '(' string xasm ')' { mkxasm($4, $5); }
8996e0bca22Sgmcgarry 		;
9006e0bca22Sgmcgarry 
9016e0bca22Sgmcgarry mvol:		   /* empty */
9026e0bca22Sgmcgarry 		|  C_QUALIFIER { nfree($1); }
9036e0bca22Sgmcgarry 		;
9046e0bca22Sgmcgarry 
9056e0bca22Sgmcgarry xasm:		   ':' oplist { $$ = xcmop($2, NIL, NIL); }
9066e0bca22Sgmcgarry 		|  ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); }
9076e0bca22Sgmcgarry 		|  ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); }
9086e0bca22Sgmcgarry 		;
9096e0bca22Sgmcgarry 
9106e0bca22Sgmcgarry oplist:		   /* nothing */ { $$ = NIL; }
9116e0bca22Sgmcgarry 		|  oper { $$ = $1; }
9126e0bca22Sgmcgarry 		;
9136e0bca22Sgmcgarry 
914c4627bc7Sgmcgarry oper:		   string '(' e ')' { $$ = xasmop($1, eve($3)); }
915c4627bc7Sgmcgarry 		|  oper ',' string '(' e ')' {
916c4627bc7Sgmcgarry 			$$ = cmop($1, xasmop($3, eve($5)));
917c4627bc7Sgmcgarry 		}
9186e0bca22Sgmcgarry 		;
9196e0bca22Sgmcgarry 
9206e0bca22Sgmcgarry cnstr:		   string { $$ = xasmop($1, bcon(0)); }
9216e0bca22Sgmcgarry 		|  cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); }
9226e0bca22Sgmcgarry                 ;
9236e0bca22Sgmcgarry 
924*a301e773Splunky label:		   C_NAME ':' attr_var { deflabel($1, $3); reached = 1; }
925*a301e773Splunky 		|  C_TYPENAME ':' attr_var { deflabel($1, $3); reached = 1; }
926c4627bc7Sgmcgarry 		|  C_CASE e ':' { addcase(eve($2)); reached = 1; }
927c4627bc7Sgmcgarry /* COMPAT_GCC */|  C_CASE e C_ELLIPSIS e ':' {
928c4627bc7Sgmcgarry #ifdef GCC_COMPAT
929c4627bc7Sgmcgarry 			gcccase(eve($2), eve($4)); reached = 1;
930c4627bc7Sgmcgarry #endif
931c4627bc7Sgmcgarry 		}
9326e0bca22Sgmcgarry 		|  C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
9336e0bca22Sgmcgarry 		;
9346e0bca22Sgmcgarry 
9356e0bca22Sgmcgarry doprefix:	C_DO {
9366e0bca22Sgmcgarry 			savebc();
9376e0bca22Sgmcgarry 			brklab = getlab();
9386e0bca22Sgmcgarry 			contlab = getlab();
9396e0bca22Sgmcgarry 			plabel(  $$ = getlab());
9406e0bca22Sgmcgarry 			reached = 1;
9416e0bca22Sgmcgarry 		}
9426e0bca22Sgmcgarry 		;
9436e0bca22Sgmcgarry ifprefix:	C_IF '(' e ')' {
944c4627bc7Sgmcgarry 			cbranch(buildtree(NOT, eve($3), NIL), bcon($$ = getlab()));
9456e0bca22Sgmcgarry 			reached = 1;
9466e0bca22Sgmcgarry 		}
9476e0bca22Sgmcgarry 		;
9486e0bca22Sgmcgarry ifelprefix:	  ifprefix statement C_ELSE {
9496e0bca22Sgmcgarry 			if (reached)
9506e0bca22Sgmcgarry 				branch($$ = getlab());
9516e0bca22Sgmcgarry 			else
9526e0bca22Sgmcgarry 				$$ = NOLAB;
9536e0bca22Sgmcgarry 			plabel( $1);
9546e0bca22Sgmcgarry 			reached = 1;
9556e0bca22Sgmcgarry 		}
9566e0bca22Sgmcgarry 		;
9576e0bca22Sgmcgarry 
9586e0bca22Sgmcgarry whprefix:	  C_WHILE  '('  e  ')' {
9596e0bca22Sgmcgarry 			savebc();
960c4627bc7Sgmcgarry 			$3 = eve($3);
9616e0bca22Sgmcgarry 			if ($3->n_op == ICON && $3->n_lval != 0)
9626e0bca22Sgmcgarry 				flostat = FLOOP;
9636e0bca22Sgmcgarry 			plabel( contlab = getlab());
9646e0bca22Sgmcgarry 			reached = 1;
9656e0bca22Sgmcgarry 			brklab = getlab();
9666e0bca22Sgmcgarry 			if (flostat == FLOOP)
9676e0bca22Sgmcgarry 				tfree($3);
9686e0bca22Sgmcgarry 			else
9696e0bca22Sgmcgarry 				cbranch(buildtree(NOT, $3, NIL), bcon(brklab));
9706e0bca22Sgmcgarry 		}
9716e0bca22Sgmcgarry 		;
9726e0bca22Sgmcgarry forprefix:	  C_FOR  '('  .e  ';' .e  ';' {
9736e0bca22Sgmcgarry 			if ($3)
9746e0bca22Sgmcgarry 				ecomp($3);
9756e0bca22Sgmcgarry 			savebc();
9766e0bca22Sgmcgarry 			contlab = getlab();
9776e0bca22Sgmcgarry 			brklab = getlab();
9786e0bca22Sgmcgarry 			plabel( $$ = getlab());
9796e0bca22Sgmcgarry 			reached = 1;
9806e0bca22Sgmcgarry 			if ($5)
9816e0bca22Sgmcgarry 				cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
9826e0bca22Sgmcgarry 			else
9836e0bca22Sgmcgarry 				flostat |= FLOOP;
9846e0bca22Sgmcgarry 		}
985c4627bc7Sgmcgarry 		|  C_FOR '(' { ++blevel; } declaration .e ';' {
9866e0bca22Sgmcgarry 			blevel--;
9876e0bca22Sgmcgarry 			savebc();
9886e0bca22Sgmcgarry 			contlab = getlab();
9896e0bca22Sgmcgarry 			brklab = getlab();
9906e0bca22Sgmcgarry 			plabel( $$ = getlab());
9916e0bca22Sgmcgarry 			reached = 1;
9926e0bca22Sgmcgarry 			if ($5)
9936e0bca22Sgmcgarry 				cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
9946e0bca22Sgmcgarry 			else
9956e0bca22Sgmcgarry 				flostat |= FLOOP;
9966e0bca22Sgmcgarry 		}
9976e0bca22Sgmcgarry 		;
9986e0bca22Sgmcgarry 
9996e0bca22Sgmcgarry switchpart:	   C_SWITCH  '('  e ')' {
10006e0bca22Sgmcgarry 			NODE *p;
10016e0bca22Sgmcgarry 			int num;
10026e0bca22Sgmcgarry 			TWORD t;
10036e0bca22Sgmcgarry 
10046e0bca22Sgmcgarry 			savebc();
10056e0bca22Sgmcgarry 			brklab = getlab();
1006c4627bc7Sgmcgarry 			$3 = eve($3);
1007*a301e773Splunky 			if (!ISINTEGER($3->n_type)) {
10086e0bca22Sgmcgarry 				uerror("switch expression must have integer "
10096e0bca22Sgmcgarry 				       "type");
10106e0bca22Sgmcgarry 				t = INT;
10116e0bca22Sgmcgarry 			} else {
10126e0bca22Sgmcgarry 				$3 = intprom($3);
10136e0bca22Sgmcgarry 				t = $3->n_type;
10146e0bca22Sgmcgarry 			}
1015*a301e773Splunky 			p = tempnode(0, t, 0, 0);
10166e0bca22Sgmcgarry 			num = regno(p);
10176e0bca22Sgmcgarry 			ecomp(buildtree(ASSIGN, p, $3));
10186e0bca22Sgmcgarry 			branch( $$ = getlab());
10196e0bca22Sgmcgarry 			swstart(num, t);
10206e0bca22Sgmcgarry 			reached = 0;
10216e0bca22Sgmcgarry 		}
10226e0bca22Sgmcgarry 		;
10236e0bca22Sgmcgarry /*	EXPRESSIONS	*/
1024c4627bc7Sgmcgarry .e:		   e { $$ = eve($1); }
10256e0bca22Sgmcgarry 		| 	{ $$=0; }
10266e0bca22Sgmcgarry 		;
10276e0bca22Sgmcgarry 
1028c4627bc7Sgmcgarry elist:		   { $$ = NIL; }
1029c4627bc7Sgmcgarry 		|  e %prec ','
1030c4627bc7Sgmcgarry 		|  elist  ','  e { $$ = biop(CM, $1, $3); }
10316e0bca22Sgmcgarry 		|  elist  ','  cast_type { /* hack for stdarg */
1032*a301e773Splunky 			TYMFIX($3);
10336e0bca22Sgmcgarry 			$3->n_op = TYPE;
1034c4627bc7Sgmcgarry 			$$ = biop(CM, $1, $3);
10356e0bca22Sgmcgarry 		}
10366e0bca22Sgmcgarry 		;
10376e0bca22Sgmcgarry 
10386e0bca22Sgmcgarry /*
10396e0bca22Sgmcgarry  * Precedence order of operators.
10406e0bca22Sgmcgarry  */
1041c4627bc7Sgmcgarry e:		   e ',' e { $$ = biop(COMOP, $1, $3); }
1042c4627bc7Sgmcgarry 		|  e '=' e {  $$ = biop(ASSIGN, $1, $3); }
1043c4627bc7Sgmcgarry 		|  e C_ASOP e {  $$ = biop($2, $1, $3); }
10446e0bca22Sgmcgarry 		|  e '?' e ':' e {
1045c4627bc7Sgmcgarry 			$$=biop(QUEST, $1, biop(COLON, $3, $5));
10466e0bca22Sgmcgarry 		}
10473eb51a41Splunky 		|  e '?' ':' e {
1048*a301e773Splunky 			NODE *p = tempnode(0, $1->n_type, $1->n_df, $1->n_ap);
10493eb51a41Splunky 			$$ = biop(COLON, ccopy(p), $4);
10503eb51a41Splunky 			$$=biop(QUEST, biop(ASSIGN, p, $1), $$);
10513eb51a41Splunky 		}
1052c4627bc7Sgmcgarry 		|  e C_OROR e { $$ = biop($2, $1, $3); }
1053c4627bc7Sgmcgarry 		|  e C_ANDAND e { $$ = biop($2, $1, $3); }
1054c4627bc7Sgmcgarry 		|  e '|' e { $$ = biop(OR, $1, $3); }
1055c4627bc7Sgmcgarry 		|  e '^' e { $$ = biop(ER, $1, $3); }
1056c4627bc7Sgmcgarry 		|  e '&' e { $$ = biop(AND, $1, $3); }
1057c4627bc7Sgmcgarry 		|  e C_EQUOP  e { $$ = biop($2, $1, $3); }
1058c4627bc7Sgmcgarry 		|  e C_RELOP e { $$ = biop($2, $1, $3); }
1059c4627bc7Sgmcgarry 		|  e C_SHIFTOP e { $$ = biop($2, $1, $3); }
1060c4627bc7Sgmcgarry 		|  e '+' e { $$ = biop(PLUS, $1, $3); }
1061c4627bc7Sgmcgarry 		|  e '-' e { $$ = biop(MINUS, $1, $3); }
1062c4627bc7Sgmcgarry 		|  e C_DIVOP e { $$ = biop($2, $1, $3); }
1063c4627bc7Sgmcgarry 		|  e '*' e { $$ = biop(MUL, $1, $3); }
1064c4627bc7Sgmcgarry 		|  e '=' addrlbl { $$ = biop(ASSIGN, $1, $3); }
10656e0bca22Sgmcgarry 		|  term
10666e0bca22Sgmcgarry 		;
10676e0bca22Sgmcgarry 
1068c4627bc7Sgmcgarry xbegin:		   begin {
1069c4627bc7Sgmcgarry 			$$ = getlab(); getlab(); getlab();
1070c4627bc7Sgmcgarry 			branch($$); plabel(($$)+1); }
1071c4627bc7Sgmcgarry 		;
1072c4627bc7Sgmcgarry 
10736e0bca22Sgmcgarry addrlbl:	  C_ANDAND C_NAME {
10746e0bca22Sgmcgarry #ifdef GCC_COMPAT
10756e0bca22Sgmcgarry 			struct symtab *s = lookup($2, SLBLNAME);
10766e0bca22Sgmcgarry 			if (s->soffset == 0)
10776e0bca22Sgmcgarry 				s->soffset = -getlab();
10786e0bca22Sgmcgarry 			$$ = buildtree(ADDROF, nametree(s), NIL);
10796e0bca22Sgmcgarry #else
10806e0bca22Sgmcgarry 			uerror("gcc extension");
10816e0bca22Sgmcgarry #endif
10826e0bca22Sgmcgarry 		}
10836e0bca22Sgmcgarry 		;
10846e0bca22Sgmcgarry 
1085c4627bc7Sgmcgarry term:		   term C_INCOP {  $$ = biop($2, $1, bcon(1)); }
1086c4627bc7Sgmcgarry 		|  '*' term { $$ = biop(UMUL, $2, NIL); }
1087c4627bc7Sgmcgarry 		|  '&' term { $$ = biop(ADDROF, $2, NIL); }
1088c4627bc7Sgmcgarry 		|  '-' term { $$ = biop(UMINUS, $2, NIL ); }
1089*a301e773Splunky 		|  '+' term { $$ = biop(PLUS, $2, bcon(0)); }
1090c4627bc7Sgmcgarry 		|  C_UNOP term { $$ = biop($1, $2, NIL); }
10916e0bca22Sgmcgarry 		|  C_INCOP term {
1092c4627bc7Sgmcgarry 			$$ = biop($1 == INCR ? PLUSEQ : MINUSEQ, $2, bcon(1));
10936e0bca22Sgmcgarry 		}
1094c4627bc7Sgmcgarry 		|  C_SIZEOF xa term { $$ = biop(SZOF, $3, bcon(0)); inattr = $<intval>2; }
10956e0bca22Sgmcgarry 		|  '(' cast_type ')' term  %prec C_INCOP {
1096*a301e773Splunky 			TYMFIX($2);
1097c4627bc7Sgmcgarry 			$$ = biop(CAST, $2, $4);
10986e0bca22Sgmcgarry 		}
1099c4627bc7Sgmcgarry 		|  C_SIZEOF xa '(' cast_type ')'  %prec C_SIZEOF {
1100c4627bc7Sgmcgarry 			$$ = biop(SZOF, $4, bcon(1));
1101c4627bc7Sgmcgarry 			inattr = $<intval>2;
11026e0bca22Sgmcgarry 		}
1103*a301e773Splunky 		|  C_ALIGNOF xa '(' cast_type ')' {
1104*a301e773Splunky 			int al;
1105*a301e773Splunky 			TYMFIX($4);
1106*a301e773Splunky 			al = talign($4->n_type, $4->n_ap);
1107*a301e773Splunky 			$$ = bcon(al/SZCHAR);
1108*a301e773Splunky 			inattr = $<intval>2;
1109*a301e773Splunky 			tfree($4);
1110*a301e773Splunky 		}
11116e0bca22Sgmcgarry 		| '(' cast_type ')' clbrace init_list optcomma '}' {
1112*a301e773Splunky 			endinit(0);
1113*a301e773Splunky 			$$ = bdty(NAME, $4);
1114*a301e773Splunky 			$$->n_op = CLOP;
1115*a301e773Splunky 		}
1116*a301e773Splunky 		| '(' cast_type ')' clbrace '}' {
1117*a301e773Splunky 			endinit(0);
1118c4627bc7Sgmcgarry 			$$ = bdty(NAME, $4);
1119c4627bc7Sgmcgarry 			$$->n_op = CLOP;
11206e0bca22Sgmcgarry 		}
1121c4627bc7Sgmcgarry 		|  term '[' e ']' { $$ = biop(LB, $1, $3); }
1122c4627bc7Sgmcgarry 		|  C_NAME  '(' elist ')' {
1123c4627bc7Sgmcgarry 			$$ = biop($3 ? CALL : UCALL, bdty(NAME, $1), $3);
11246e0bca22Sgmcgarry 		}
1125c4627bc7Sgmcgarry 		|  term  '(' elist ')' { $$ = biop($3 ? CALL : UCALL, $1, $3); }
1126c4627bc7Sgmcgarry 		|  term C_STROP C_NAME { $$ = biop($2, $1, bdty(NAME, $3)); }
1127c4627bc7Sgmcgarry 		|  term C_STROP C_TYPENAME { $$ = biop($2, $1, bdty(NAME, $3));}
1128c4627bc7Sgmcgarry 		|  C_NAME %prec C_SIZEOF /* below ( */{ $$ = bdty(NAME, $1); }
11293eb51a41Splunky 		|  PCC_OFFSETOF  '(' cast_type ',' term ')' {
1130*a301e773Splunky 			TYMFIX($3);
11313eb51a41Splunky 			$3->n_type = INCREF($3->n_type);
11323eb51a41Splunky 			$3 = biop(CAST, $3, bcon(0));
11333eb51a41Splunky 			if ($5->n_op == NAME) {
11343eb51a41Splunky 				$$ = biop(STREF, $3, $5);
11353eb51a41Splunky 			} else {
11363eb51a41Splunky 				NODE *p = $5;
11373eb51a41Splunky 				while (p->n_left->n_op != NAME)
11383eb51a41Splunky 					p = p->n_left;
11393eb51a41Splunky 				p->n_left = biop(STREF, $3, p->n_left);
11403eb51a41Splunky 				$$ = $5;
11413eb51a41Splunky 			}
11423eb51a41Splunky 			$$ = biop(ADDROF, $$, NIL);
1143*a301e773Splunky 			$3 = block(NAME, NIL, NIL, ENUNSIGN(INTPTR), 0, 0);
11443eb51a41Splunky 			$$ = biop(CAST, $3, $$);
11453eb51a41Splunky 		}
11466e0bca22Sgmcgarry 		|  C_ICON { $$ = $1; }
11476e0bca22Sgmcgarry 		|  C_FCON { $$ = $1; }
1148c4627bc7Sgmcgarry 		|  string { $$ = bdty(STRING, $1, widestr); }
11496e0bca22Sgmcgarry 		|   '('  e  ')' { $$=$2; }
1150c4627bc7Sgmcgarry 		|  '(' xbegin block_item_list e ';' '}' ')' {
1151c4627bc7Sgmcgarry 			/* XXX - check recursive ({ }) statements */
1152c4627bc7Sgmcgarry 			branch(($2)+2);
1153c4627bc7Sgmcgarry 			plabel($2);
1154c4627bc7Sgmcgarry 			$$ = buildtree(COMOP,
1155c4627bc7Sgmcgarry 			    biop(GOTO, bcon(($2)+1), NIL), eve($4));
1156c4627bc7Sgmcgarry 			flend();
1157c4627bc7Sgmcgarry 		}
1158*a301e773Splunky 		|  '(' xbegin block_item_list '}' ')' {
1159*a301e773Splunky 			/* XXX - check recursive ({ }) statements */
1160*a301e773Splunky 			branch(($2)+2);
1161*a301e773Splunky 			plabel($2);
1162*a301e773Splunky 			$$ = buildtree(COMOP,
1163*a301e773Splunky 			    biop(GOTO, bcon(($2)+1), NIL), voidcon());
1164*a301e773Splunky 			flend();
1165*a301e773Splunky 		}
1166c4627bc7Sgmcgarry 		;
1167c4627bc7Sgmcgarry 
1168c4627bc7Sgmcgarry xa:		  { $<intval>$ = inattr; inattr = 0; }
11696e0bca22Sgmcgarry 		;
11706e0bca22Sgmcgarry 
1171*a301e773Splunky clbrace:	   '{'	{ NODE *q = $<nodep>-1; TYMFIX(q); $$ = clbrace(q); }
11726e0bca22Sgmcgarry 		;
11736e0bca22Sgmcgarry 
11743eb51a41Splunky string:		   C_STRING { widestr = 0; $$ = stradd("", $1); }
11756e0bca22Sgmcgarry 		|  string C_STRING { $$ = stradd($1, $2); }
11766e0bca22Sgmcgarry 		;
11776e0bca22Sgmcgarry 
11786e0bca22Sgmcgarry cast_type:	   specifier_qualifier_list {
1179*a301e773Splunky 			$$ = biop(TYMERGE, $1, bdty(NAME, NULL));
11806e0bca22Sgmcgarry 		}
11816e0bca22Sgmcgarry 		|  specifier_qualifier_list abstract_declarator {
1182*a301e773Splunky 			$$ = biop(TYMERGE, $1, aryfix($2));
11836e0bca22Sgmcgarry 		}
11846e0bca22Sgmcgarry 		;
11856e0bca22Sgmcgarry 
11866e0bca22Sgmcgarry %%
11876e0bca22Sgmcgarry 
11886e0bca22Sgmcgarry NODE *
1189*a301e773Splunky mkty(TWORD t, union dimfun *d, struct attr *sue)
11906e0bca22Sgmcgarry {
11916e0bca22Sgmcgarry 	return block(TYPE, NIL, NIL, t, d, sue);
11926e0bca22Sgmcgarry }
11936e0bca22Sgmcgarry 
1194c4627bc7Sgmcgarry NODE *
11956e0bca22Sgmcgarry bdty(int op, ...)
11966e0bca22Sgmcgarry {
11976e0bca22Sgmcgarry 	va_list ap;
11986e0bca22Sgmcgarry 	int val;
11996e0bca22Sgmcgarry 	register NODE *q;
12006e0bca22Sgmcgarry 
12016e0bca22Sgmcgarry 	va_start(ap, op);
12026e0bca22Sgmcgarry 	q = biop(op, NIL, NIL);
12036e0bca22Sgmcgarry 
12046e0bca22Sgmcgarry 	switch (op) {
12056e0bca22Sgmcgarry 	case UMUL:
12066e0bca22Sgmcgarry 	case UCALL:
12076e0bca22Sgmcgarry 		q->n_left = va_arg(ap, NODE *);
12086e0bca22Sgmcgarry 		q->n_rval = 0;
12096e0bca22Sgmcgarry 		break;
12106e0bca22Sgmcgarry 
12116e0bca22Sgmcgarry 	case CALL:
12126e0bca22Sgmcgarry 		q->n_left = va_arg(ap, NODE *);
12136e0bca22Sgmcgarry 		q->n_right = va_arg(ap, NODE *);
12146e0bca22Sgmcgarry 		break;
12156e0bca22Sgmcgarry 
12166e0bca22Sgmcgarry 	case LB:
12176e0bca22Sgmcgarry 		q->n_left = va_arg(ap, NODE *);
12186e0bca22Sgmcgarry 		if ((val = va_arg(ap, int)) <= 0) {
12196e0bca22Sgmcgarry 			uerror("array size must be positive");
12206e0bca22Sgmcgarry 			val = 1;
12216e0bca22Sgmcgarry 		}
12226e0bca22Sgmcgarry 		q->n_right = bcon(val);
12236e0bca22Sgmcgarry 		break;
12246e0bca22Sgmcgarry 
12256e0bca22Sgmcgarry 	case NAME:
12266e0bca22Sgmcgarry 		q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */
12276e0bca22Sgmcgarry 		break;
12286e0bca22Sgmcgarry 
1229c4627bc7Sgmcgarry 	case STRING:
1230c4627bc7Sgmcgarry 		q->n_name = va_arg(ap, char *);
1231c4627bc7Sgmcgarry 		q->n_lval = va_arg(ap, int);
1232c4627bc7Sgmcgarry 		break;
1233c4627bc7Sgmcgarry 
12346e0bca22Sgmcgarry 	default:
12356e0bca22Sgmcgarry 		cerror("bad bdty");
12366e0bca22Sgmcgarry 	}
12376e0bca22Sgmcgarry 	va_end(ap);
12386e0bca22Sgmcgarry 
12396e0bca22Sgmcgarry 	return q;
12406e0bca22Sgmcgarry }
12416e0bca22Sgmcgarry 
12426e0bca22Sgmcgarry static void
12436e0bca22Sgmcgarry flend(void)
12446e0bca22Sgmcgarry {
1245*a301e773Splunky 	if (!isinlining && sspflag && blevel == 2)
12466e0bca22Sgmcgarry 		sspend();
12476e0bca22Sgmcgarry #ifdef STABS
12486e0bca22Sgmcgarry 	if (gflag && blevel > 2)
12496e0bca22Sgmcgarry 		stabs_rbrac(blevel);
12506e0bca22Sgmcgarry #endif
12516e0bca22Sgmcgarry 	--blevel;
12526e0bca22Sgmcgarry 	if( blevel == 1 )
12536e0bca22Sgmcgarry 		blevel = 0;
12546e0bca22Sgmcgarry 	symclear(blevel); /* Clean ut the symbol table */
12556e0bca22Sgmcgarry 	if (autooff > maxautooff)
12566e0bca22Sgmcgarry 		maxautooff = autooff;
12576e0bca22Sgmcgarry 	autooff = savctx->contlab;
12586e0bca22Sgmcgarry 	savctx = savctx->next;
12596e0bca22Sgmcgarry }
12606e0bca22Sgmcgarry 
12616e0bca22Sgmcgarry static void
12626e0bca22Sgmcgarry savebc(void)
12636e0bca22Sgmcgarry {
12646e0bca22Sgmcgarry 	struct savbc *bc = tmpalloc(sizeof(struct savbc));
12656e0bca22Sgmcgarry 
12666e0bca22Sgmcgarry 	bc->brklab = brklab;
12676e0bca22Sgmcgarry 	bc->contlab = contlab;
12686e0bca22Sgmcgarry 	bc->flostat = flostat;
12696e0bca22Sgmcgarry 	bc->next = savbc;
12706e0bca22Sgmcgarry 	savbc = bc;
12716e0bca22Sgmcgarry 	flostat = 0;
12726e0bca22Sgmcgarry }
12736e0bca22Sgmcgarry 
12746e0bca22Sgmcgarry static void
12756e0bca22Sgmcgarry resetbc(int mask)
12766e0bca22Sgmcgarry {
12776e0bca22Sgmcgarry 	flostat = savbc->flostat | (flostat&mask);
12786e0bca22Sgmcgarry 	contlab = savbc->contlab;
12796e0bca22Sgmcgarry 	brklab = savbc->brklab;
12806e0bca22Sgmcgarry 	savbc = savbc->next;
12816e0bca22Sgmcgarry }
12826e0bca22Sgmcgarry 
12836e0bca22Sgmcgarry struct swdef {
12846e0bca22Sgmcgarry 	struct swdef *next;	/* Next in list */
12856e0bca22Sgmcgarry 	int deflbl;		/* Label for "default" */
12866e0bca22Sgmcgarry 	struct swents *ents;	/* Linked sorted list of case entries */
12876e0bca22Sgmcgarry 	int nents;		/* # of entries in list */
12886e0bca22Sgmcgarry 	int num;		/* Node value will end up in */
12896e0bca22Sgmcgarry 	TWORD type;		/* Type of switch expression */
12906e0bca22Sgmcgarry } *swpole;
12916e0bca22Sgmcgarry 
12926e0bca22Sgmcgarry /*
12936e0bca22Sgmcgarry  * add case to switch
12946e0bca22Sgmcgarry  */
12956e0bca22Sgmcgarry static void
12966e0bca22Sgmcgarry addcase(NODE *p)
12976e0bca22Sgmcgarry {
12986e0bca22Sgmcgarry 	struct swents **put, *w, *sw = tmpalloc(sizeof(struct swents));
12996e0bca22Sgmcgarry 	CONSZ val;
13006e0bca22Sgmcgarry 
1301*a301e773Splunky 	p = optim(rmpconv(p));  /* change enum to ints */
13026e0bca22Sgmcgarry 	if (p->n_op != ICON || p->n_sp != NULL) {
13036e0bca22Sgmcgarry 		uerror( "non-constant case expression");
13046e0bca22Sgmcgarry 		return;
13056e0bca22Sgmcgarry 	}
13066e0bca22Sgmcgarry 	if (swpole == NULL) {
13076e0bca22Sgmcgarry 		uerror("case not in switch");
13086e0bca22Sgmcgarry 		return;
13096e0bca22Sgmcgarry 	}
13106e0bca22Sgmcgarry 
13116e0bca22Sgmcgarry 	if (DEUNSIGN(swpole->type) != DEUNSIGN(p->n_type)) {
13126e0bca22Sgmcgarry 		val = p->n_lval;
1313*a301e773Splunky 		p = makety(p, swpole->type, 0, 0, 0);
13146e0bca22Sgmcgarry 		if (p->n_op != ICON)
13156e0bca22Sgmcgarry 			cerror("could not cast case value to type of switch "
13166e0bca22Sgmcgarry 			       "expression");
13176e0bca22Sgmcgarry 		if (p->n_lval != val)
13186e0bca22Sgmcgarry 			werror("case expression truncated");
13196e0bca22Sgmcgarry 	}
13206e0bca22Sgmcgarry 	sw->sval = p->n_lval;
13216e0bca22Sgmcgarry 	tfree(p);
13226e0bca22Sgmcgarry 	put = &swpole->ents;
13236e0bca22Sgmcgarry 	if (ISUNSIGNED(swpole->type)) {
13246e0bca22Sgmcgarry 		for (w = swpole->ents;
13256e0bca22Sgmcgarry 		     w != NULL && (U_CONSZ)w->sval < (U_CONSZ)sw->sval;
13266e0bca22Sgmcgarry 		     w = w->next)
13276e0bca22Sgmcgarry 			put = &w->next;
13286e0bca22Sgmcgarry 	} else {
13296e0bca22Sgmcgarry 		for (w = swpole->ents; w != NULL && w->sval < sw->sval;
13306e0bca22Sgmcgarry 		     w = w->next)
13316e0bca22Sgmcgarry 			put = &w->next;
13326e0bca22Sgmcgarry 	}
13336e0bca22Sgmcgarry 	if (w != NULL && w->sval == sw->sval) {
13346e0bca22Sgmcgarry 		uerror("duplicate case in switch");
13356e0bca22Sgmcgarry 		return;
13366e0bca22Sgmcgarry 	}
13376e0bca22Sgmcgarry 	plabel(sw->slab = getlab());
13386e0bca22Sgmcgarry 	*put = sw;
13396e0bca22Sgmcgarry 	sw->next = w;
13406e0bca22Sgmcgarry 	swpole->nents++;
13416e0bca22Sgmcgarry }
13426e0bca22Sgmcgarry 
1343c4627bc7Sgmcgarry #ifdef GCC_COMPAT
1344c4627bc7Sgmcgarry void
1345c4627bc7Sgmcgarry gcccase(NODE *ln, NODE *hn)
1346c4627bc7Sgmcgarry {
1347c4627bc7Sgmcgarry 	CONSZ i, l, h;
1348c4627bc7Sgmcgarry 
1349c4627bc7Sgmcgarry 	l = icons(optim(ln));
1350c4627bc7Sgmcgarry 	h = icons(optim(hn));
1351c4627bc7Sgmcgarry 
1352c4627bc7Sgmcgarry 	if (h < l)
1353c4627bc7Sgmcgarry 		i = l, l = h, h = i;
1354c4627bc7Sgmcgarry 
1355c4627bc7Sgmcgarry 	for (i = l; i <= h; i++)
1356c4627bc7Sgmcgarry 		addcase(xbcon(i, NULL, hn->n_type));
1357c4627bc7Sgmcgarry }
1358c4627bc7Sgmcgarry #endif
1359c4627bc7Sgmcgarry 
13606e0bca22Sgmcgarry /*
13616e0bca22Sgmcgarry  * add default case to switch
13626e0bca22Sgmcgarry  */
13636e0bca22Sgmcgarry static void
13646e0bca22Sgmcgarry adddef(void)
13656e0bca22Sgmcgarry {
13666e0bca22Sgmcgarry 	if (swpole == NULL)
13676e0bca22Sgmcgarry 		uerror("default not inside switch");
13686e0bca22Sgmcgarry 	else if (swpole->deflbl != 0)
13696e0bca22Sgmcgarry 		uerror("duplicate default in switch");
13706e0bca22Sgmcgarry 	else
13716e0bca22Sgmcgarry 		plabel( swpole->deflbl = getlab());
13726e0bca22Sgmcgarry }
13736e0bca22Sgmcgarry 
13746e0bca22Sgmcgarry static void
13756e0bca22Sgmcgarry swstart(int num, TWORD type)
13766e0bca22Sgmcgarry {
13776e0bca22Sgmcgarry 	struct swdef *sw = tmpalloc(sizeof(struct swdef));
13786e0bca22Sgmcgarry 
13796e0bca22Sgmcgarry 	sw->deflbl = sw->nents = 0;
13806e0bca22Sgmcgarry 	sw->ents = NULL;
13816e0bca22Sgmcgarry 	sw->next = swpole;
13826e0bca22Sgmcgarry 	sw->num = num;
13836e0bca22Sgmcgarry 	sw->type = type;
13846e0bca22Sgmcgarry 	swpole = sw;
13856e0bca22Sgmcgarry }
13866e0bca22Sgmcgarry 
13876e0bca22Sgmcgarry /*
13886e0bca22Sgmcgarry  * end a switch block
13896e0bca22Sgmcgarry  */
13906e0bca22Sgmcgarry static void
13916e0bca22Sgmcgarry swend(void)
13926e0bca22Sgmcgarry {
13936e0bca22Sgmcgarry 	struct swents *sw, **swp;
13946e0bca22Sgmcgarry 	int i;
13956e0bca22Sgmcgarry 
13966e0bca22Sgmcgarry 	sw = tmpalloc(sizeof(struct swents));
13976e0bca22Sgmcgarry 	swp = tmpalloc(sizeof(struct swents *) * (swpole->nents+1));
13986e0bca22Sgmcgarry 
13996e0bca22Sgmcgarry 	sw->slab = swpole->deflbl;
14006e0bca22Sgmcgarry 	swp[0] = sw;
14016e0bca22Sgmcgarry 
14026e0bca22Sgmcgarry 	for (i = 1; i <= swpole->nents; i++) {
14036e0bca22Sgmcgarry 		swp[i] = swpole->ents;
14046e0bca22Sgmcgarry 		swpole->ents = swpole->ents->next;
14056e0bca22Sgmcgarry 	}
14066e0bca22Sgmcgarry 	genswitch(swpole->num, swpole->type, swp, swpole->nents);
14076e0bca22Sgmcgarry 
14086e0bca22Sgmcgarry 	swpole = swpole->next;
14096e0bca22Sgmcgarry }
14106e0bca22Sgmcgarry 
14116e0bca22Sgmcgarry /*
14126e0bca22Sgmcgarry  * num: tempnode the value of the switch expression is in
14136e0bca22Sgmcgarry  * type: type of the switch expression
14146e0bca22Sgmcgarry  *
14156e0bca22Sgmcgarry  * p points to an array of structures, each consisting
14166e0bca22Sgmcgarry  * of a constant value and a label.
14176e0bca22Sgmcgarry  * The first is >=0 if there is a default label;
14186e0bca22Sgmcgarry  * its value is the label number
14196e0bca22Sgmcgarry  * The entries p[1] to p[n] are the nontrivial cases
14206e0bca22Sgmcgarry  * n is the number of case statements (length of list)
14216e0bca22Sgmcgarry  */
14226e0bca22Sgmcgarry static void
14236e0bca22Sgmcgarry genswitch(int num, TWORD type, struct swents **p, int n)
14246e0bca22Sgmcgarry {
14256e0bca22Sgmcgarry 	NODE *r, *q;
14266e0bca22Sgmcgarry 	int i;
14276e0bca22Sgmcgarry 
14286e0bca22Sgmcgarry 	if (mygenswitch(num, type, p, n))
14296e0bca22Sgmcgarry 		return;
14306e0bca22Sgmcgarry 
14316e0bca22Sgmcgarry 	/* simple switch code */
14326e0bca22Sgmcgarry 	for (i = 1; i <= n; ++i) {
14336e0bca22Sgmcgarry 		/* already in 1 */
1434*a301e773Splunky 		r = tempnode(num, type, 0, 0);
14356e0bca22Sgmcgarry 		q = xbcon(p[i]->sval, NULL, type);
14366e0bca22Sgmcgarry 		r = buildtree(NE, r, clocal(q));
14376e0bca22Sgmcgarry 		cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
14386e0bca22Sgmcgarry 	}
14396e0bca22Sgmcgarry 	if (p[0]->slab > 0)
14406e0bca22Sgmcgarry 		branch(p[0]->slab);
14416e0bca22Sgmcgarry }
14426e0bca22Sgmcgarry 
14436e0bca22Sgmcgarry /*
14446e0bca22Sgmcgarry  * Declare a variable or prototype.
14456e0bca22Sgmcgarry  */
14466e0bca22Sgmcgarry static struct symtab *
1447c4627bc7Sgmcgarry init_declarator(NODE *tn, NODE *p, int assign, NODE *a)
14486e0bca22Sgmcgarry {
14496e0bca22Sgmcgarry 	int class = tn->n_lval;
1450*a301e773Splunky 	struct symtab *sp;
14516e0bca22Sgmcgarry 
1452*a301e773Splunky 	p = aryfix(p);
1453*a301e773Splunky 	p = tymerge(tn, p);
1454*a301e773Splunky 	if (a) {
1455*a301e773Splunky 		struct attr *ap = gcc_attr_parse(a);
1456*a301e773Splunky 		p->n_ap = attr_add(p->n_ap, ap);
1457*a301e773Splunky 	}
1458c4627bc7Sgmcgarry 
1459*a301e773Splunky 	p->n_sp = sp = lookup((char *)p->n_sp, 0); /* XXX */
1460c4627bc7Sgmcgarry 
1461*a301e773Splunky 	if (fun_inline && ISFTN(p->n_type))
1462*a301e773Splunky 		sp->sflags |= SINLINE;
14636e0bca22Sgmcgarry 
1464*a301e773Splunky 	if (ISFTN(p->n_type) == 0) {
14656e0bca22Sgmcgarry 		if (assign) {
1466c4627bc7Sgmcgarry 			defid(p, class);
1467*a301e773Splunky 			sp = p->n_sp;
1468*a301e773Splunky 			sp->sflags |= SASG;
1469*a301e773Splunky 			if (sp->sflags & SDYNARRAY)
14706e0bca22Sgmcgarry 				uerror("can't initialize dynamic arrays");
1471*a301e773Splunky 			lcommdel(sp);
1472c4627bc7Sgmcgarry 		} else
1473c4627bc7Sgmcgarry 			nidcl(p, class);
14746e0bca22Sgmcgarry 	} else {
14753eb51a41Splunky 		extern NODE *parlink;
14766e0bca22Sgmcgarry 		if (assign)
14776e0bca22Sgmcgarry 			uerror("cannot initialise function");
1478c4627bc7Sgmcgarry 		defid(p, uclass(class));
1479*a301e773Splunky 		sp = p->n_sp;
14803eb51a41Splunky 		if (parlink) {
14813eb51a41Splunky 			/* dynamic sized arrays in prototypes */
14823eb51a41Splunky 			tfree(parlink); /* Free delayed tree */
14833eb51a41Splunky 			parlink = NIL;
14843eb51a41Splunky 		}
14856e0bca22Sgmcgarry 	}
1486c4627bc7Sgmcgarry 	tfree(p);
1487*a301e773Splunky 	return sp;
14886e0bca22Sgmcgarry }
14896e0bca22Sgmcgarry 
14906e0bca22Sgmcgarry /*
1491c4627bc7Sgmcgarry  * Declare old-stype function arguments.
1492c4627bc7Sgmcgarry  */
1493c4627bc7Sgmcgarry static void
1494c4627bc7Sgmcgarry oldargs(NODE *p)
1495c4627bc7Sgmcgarry {
1496*a301e773Splunky 	blevel++;
1497c4627bc7Sgmcgarry 	p->n_op = TYPE;
1498c4627bc7Sgmcgarry 	p->n_type = FARG;
1499c4627bc7Sgmcgarry 	p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */
1500c4627bc7Sgmcgarry 	defid(p, PARAM);
1501*a301e773Splunky 	blevel--;
1502c4627bc7Sgmcgarry }
1503c4627bc7Sgmcgarry 
1504c4627bc7Sgmcgarry /*
1505*a301e773Splunky  * Set NAME nodes to a null name and index of LB nodes to NOOFFSET
1506*a301e773Splunky  * unless clr is one, in that case preserve variable name.
1507*a301e773Splunky  */
1508*a301e773Splunky static NODE *
1509*a301e773Splunky namekill(NODE *p, int clr)
1510*a301e773Splunky {
1511*a301e773Splunky 	NODE *q;
1512*a301e773Splunky 	int o = p->n_op;
1513*a301e773Splunky 
1514*a301e773Splunky 	switch (coptype(o)) {
1515*a301e773Splunky 	case LTYPE:
1516*a301e773Splunky 		if (o == NAME) {
1517*a301e773Splunky 			if (clr)
1518*a301e773Splunky 				p->n_sp = NULL;
1519*a301e773Splunky 			else
1520*a301e773Splunky 				p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */
1521*a301e773Splunky 		}
1522*a301e773Splunky 		break;
1523*a301e773Splunky 
1524*a301e773Splunky 	case UTYPE:
1525*a301e773Splunky 		p->n_left = namekill(p->n_left, clr);
1526*a301e773Splunky 		break;
1527*a301e773Splunky 
1528*a301e773Splunky         case BITYPE:
1529*a301e773Splunky                 p->n_left = namekill(p->n_left, clr);
1530*a301e773Splunky 		if (o == LB) {
1531*a301e773Splunky 			if (clr) {
1532*a301e773Splunky 				tfree(p->n_right);
1533*a301e773Splunky 				p->n_right = bcon(NOOFFSET);
1534*a301e773Splunky 			} else
1535*a301e773Splunky 				p->n_right = eve(p->n_right);
1536*a301e773Splunky 		} else if (o == CALL)
1537*a301e773Splunky 			p->n_right = namekill(p->n_right, 1);
1538*a301e773Splunky 		else
1539*a301e773Splunky 			p->n_right = namekill(p->n_right, clr);
1540*a301e773Splunky 		if (o == TYMERGE) {
1541*a301e773Splunky 			q = tymerge(p->n_left, p->n_right);
1542*a301e773Splunky 			q->n_ap = attr_add(q->n_ap, p->n_ap);
1543*a301e773Splunky 			tfree(p->n_left);
1544*a301e773Splunky 			nfree(p);
1545*a301e773Splunky 			p = q;
1546*a301e773Splunky 		}
1547*a301e773Splunky 		break;
1548*a301e773Splunky 	}
1549*a301e773Splunky 	return p;
1550*a301e773Splunky }
1551*a301e773Splunky 
1552*a301e773Splunky /*
1553*a301e773Splunky  * Declare function arguments.
1554*a301e773Splunky  */
1555*a301e773Splunky static NODE *
1556*a301e773Splunky funargs(NODE *p)
1557*a301e773Splunky {
1558*a301e773Splunky 	extern NODE *arrstk[10];
1559*a301e773Splunky 
1560*a301e773Splunky 	if (p->n_op == ELLIPSIS)
1561*a301e773Splunky 		return p;
1562*a301e773Splunky 
1563*a301e773Splunky 	p = namekill(p, 0);
1564*a301e773Splunky 	if (ISFTN(p->n_type))
1565*a301e773Splunky 		p->n_type = INCREF(p->n_type);
1566*a301e773Splunky 	if (ISARY(p->n_type)) {
1567*a301e773Splunky 		p->n_type += (PTR-ARY);
1568*a301e773Splunky 		if (p->n_df->ddim == -1)
1569*a301e773Splunky 			tfree(arrstk[0]), arrstk[0] = NIL;
1570*a301e773Splunky 		p->n_df++;
1571*a301e773Splunky 	}
1572*a301e773Splunky 	if (p->n_type == VOID && p->n_sp->sname == NULL)
1573*a301e773Splunky 		return p; /* sanitycheck later */
1574*a301e773Splunky 	else if (p->n_sp->sname == NULL)
1575*a301e773Splunky 		uerror("argument missing");
1576*a301e773Splunky 	else
1577*a301e773Splunky 		defid(p, PARAM);
1578*a301e773Splunky 	return p;
1579*a301e773Splunky }
1580*a301e773Splunky 
1581*a301e773Splunky static NODE *
1582*a301e773Splunky listfw(NODE *p, NODE * (*f)(NODE *))
1583*a301e773Splunky {
1584*a301e773Splunky         if (p->n_op == CM) {
1585*a301e773Splunky                 p->n_left = listfw(p->n_left, f);
1586*a301e773Splunky                 p->n_right = (*f)(p->n_right);
1587*a301e773Splunky         } else
1588*a301e773Splunky                 p = (*f)(p);
1589*a301e773Splunky 	return p;
1590*a301e773Splunky }
1591*a301e773Splunky 
1592*a301e773Splunky 
1593*a301e773Splunky /*
15946e0bca22Sgmcgarry  * Declare a function.
15956e0bca22Sgmcgarry  */
15966e0bca22Sgmcgarry static void
15976e0bca22Sgmcgarry fundef(NODE *tp, NODE *p)
15986e0bca22Sgmcgarry {
15996e0bca22Sgmcgarry 	extern int prolab;
16006e0bca22Sgmcgarry 	struct symtab *s;
1601*a301e773Splunky 	NODE *q, *typ;
1602*a301e773Splunky 	int class = tp->n_lval, oclass, ctval;
16036e0bca22Sgmcgarry 	char *c;
16046e0bca22Sgmcgarry 
1605*a301e773Splunky 	/*
1606*a301e773Splunky 	 * We discard all names except for those needed for
1607*a301e773Splunky 	 * parameter declaration. While doing that, also change
1608*a301e773Splunky 	 * non-constant array sizes to unknown.
1609*a301e773Splunky 	 */
1610*a301e773Splunky 	ctval = tvaloff;
1611*a301e773Splunky 	for (q = p; coptype(q->n_op) != LTYPE &&
1612*a301e773Splunky 	    q->n_left->n_op != NAME; q = q->n_left) {
1613*a301e773Splunky 		if (q->n_op == CALL)
1614*a301e773Splunky 			q->n_right = namekill(q->n_right, 1);
1615*a301e773Splunky 	}
16166e0bca22Sgmcgarry 	if (q->n_op != CALL && q->n_op != UCALL) {
16176e0bca22Sgmcgarry 		uerror("invalid function definition");
16186e0bca22Sgmcgarry 		p = bdty(UCALL, p);
1619*a301e773Splunky 	} else if (q->n_op == CALL) {
1620*a301e773Splunky 		blevel = 1;
1621*a301e773Splunky 		argoff = ARGINIT;
1622*a301e773Splunky 		if (oldstyle == 0)
1623*a301e773Splunky 			q->n_right = listfw(q->n_right, funargs);
16246e0bca22Sgmcgarry 		ftnarg(q);
1625*a301e773Splunky 		blevel = 0;
16266e0bca22Sgmcgarry 	}
16276e0bca22Sgmcgarry 
1628c4627bc7Sgmcgarry 	p = typ = tymerge(tp, p);
1629c4627bc7Sgmcgarry #ifdef GCC_COMPAT
1630*a301e773Splunky 	/* gcc seems to discard __builtin_ when declaring functions */
1631*a301e773Splunky 	if (strncmp("__builtin_", (char *)typ->n_sp, 10) == 0)
1632*a301e773Splunky 		typ->n_sp = (struct symtab *)((char *)typ->n_sp + 10);
1633c4627bc7Sgmcgarry #endif
1634c4627bc7Sgmcgarry 	s = typ->n_sp = lookup((char *)typ->n_sp, 0); /* XXX */
16356e0bca22Sgmcgarry 
16366e0bca22Sgmcgarry 	oclass = s->sclass;
16376e0bca22Sgmcgarry 	if (class == STATIC && oclass == EXTERN)
16386e0bca22Sgmcgarry 		werror("%s was first declared extern, then static", s->sname);
16396e0bca22Sgmcgarry 
16406e0bca22Sgmcgarry 	if (fun_inline) {
16416e0bca22Sgmcgarry 		/* special syntax for inline functions */
1642*a301e773Splunky 		if (! strcmp(s->sname,"main"))
1643*a301e773Splunky 			uerror("cannot inline main()");
1644*a301e773Splunky 
16456e0bca22Sgmcgarry 		s->sflags |= SINLINE;
16466e0bca22Sgmcgarry 		inline_start(s);
1647c4627bc7Sgmcgarry 		if (class == EXTERN)
16486e0bca22Sgmcgarry 			class = EXTDEF;
16496e0bca22Sgmcgarry 	} else if (class == EXTERN)
16506e0bca22Sgmcgarry 		class = SNULL; /* same result */
16516e0bca22Sgmcgarry 
16526e0bca22Sgmcgarry 	cftnsp = s;
16536e0bca22Sgmcgarry 	defid(p, class);
1654*a301e773Splunky #ifdef GCC_COMPAT
1655*a301e773Splunky 	if (attr_find(p->n_ap, GCC_ATYP_ALW_INL)) {
1656*a301e773Splunky 		/* Temporary turn on temps to make always_inline work */
1657*a301e773Splunky 		alwinl = 1;
1658*a301e773Splunky 		if (xtemps == 0) alwinl |= 2;
1659*a301e773Splunky 		xtemps = 1;
1660*a301e773Splunky 	}
1661*a301e773Splunky #endif
16626e0bca22Sgmcgarry 	prolab = getlab();
1663c4627bc7Sgmcgarry 	if ((c = cftnsp->soname) == NULL)
1664c4627bc7Sgmcgarry 		c = addname(exname(cftnsp->sname));
1665c4627bc7Sgmcgarry 	send_passt(IP_PROLOG, -1, c, cftnsp->stype,
16666e0bca22Sgmcgarry 	    cftnsp->sclass == EXTDEF, prolab, ctval);
16676e0bca22Sgmcgarry 	blevel++;
16686e0bca22Sgmcgarry #ifdef STABS
16696e0bca22Sgmcgarry 	if (gflag)
16706e0bca22Sgmcgarry 		stabs_func(s);
16716e0bca22Sgmcgarry #endif
1672c4627bc7Sgmcgarry 	tfree(tp);
1673c4627bc7Sgmcgarry 	tfree(p);
16746e0bca22Sgmcgarry 
16756e0bca22Sgmcgarry }
16766e0bca22Sgmcgarry 
16776e0bca22Sgmcgarry static void
16786e0bca22Sgmcgarry fend(void)
16796e0bca22Sgmcgarry {
16806e0bca22Sgmcgarry 	if (blevel)
16816e0bca22Sgmcgarry 		cerror("function level error");
16826e0bca22Sgmcgarry 	ftnend();
16836e0bca22Sgmcgarry 	fun_inline = 0;
1684*a301e773Splunky 	if (alwinl & 2) xtemps = 0;
1685*a301e773Splunky 	alwinl = 0;
16866e0bca22Sgmcgarry 	cftnsp = NULL;
16876e0bca22Sgmcgarry }
16886e0bca22Sgmcgarry 
1689c4627bc7Sgmcgarry NODE *
16906e0bca22Sgmcgarry structref(NODE *p, int f, char *name)
16916e0bca22Sgmcgarry {
16926e0bca22Sgmcgarry 	NODE *r;
16936e0bca22Sgmcgarry 
16946e0bca22Sgmcgarry 	if (f == DOT)
16956e0bca22Sgmcgarry 		p = buildtree(ADDROF, p, NIL);
16966e0bca22Sgmcgarry 	r = biop(NAME, NIL, NIL);
16976e0bca22Sgmcgarry 	r->n_name = name;
16986e0bca22Sgmcgarry 	r = buildtree(STREF, p, r);
16996e0bca22Sgmcgarry 	return r;
17006e0bca22Sgmcgarry }
17016e0bca22Sgmcgarry 
17026e0bca22Sgmcgarry static void
1703c4627bc7Sgmcgarry olddecl(NODE *p, NODE *a)
17046e0bca22Sgmcgarry {
17056e0bca22Sgmcgarry 	struct symtab *s;
17066e0bca22Sgmcgarry 
1707*a301e773Splunky 	p = namekill(p, 0);
1708*a301e773Splunky 	s = p->n_sp;
17096e0bca22Sgmcgarry 	if (s->slevel != 1 || s->stype == UNDEF)
17106e0bca22Sgmcgarry 		uerror("parameter '%s' not defined", s->sname);
17116e0bca22Sgmcgarry 	else if (s->stype != FARG)
17126e0bca22Sgmcgarry 		uerror("parameter '%s' redefined", s->sname);
1713*a301e773Splunky 
17146e0bca22Sgmcgarry 	s->stype = p->n_type;
17156e0bca22Sgmcgarry 	s->sdf = p->n_df;
1716*a301e773Splunky 	s->sap = p->n_ap;
1717*a301e773Splunky 	if (ISARY(s->stype)) {
1718*a301e773Splunky 		s->stype += (PTR-ARY);
1719*a301e773Splunky 		s->sdf++;
1720*a301e773Splunky 	} else if (s->stype == FLOAT)
1721*a301e773Splunky 		s->stype = DOUBLE;
1722*a301e773Splunky 	if (a)
1723*a301e773Splunky 		attr_add(s->sap, gcc_attr_parse(a));
17246e0bca22Sgmcgarry 	nfree(p);
17256e0bca22Sgmcgarry }
17266e0bca22Sgmcgarry 
17276e0bca22Sgmcgarry void
17286e0bca22Sgmcgarry branch(int lbl)
17296e0bca22Sgmcgarry {
17306e0bca22Sgmcgarry 	int r = reached++;
17316e0bca22Sgmcgarry 	ecomp(biop(GOTO, bcon(lbl), NIL));
17326e0bca22Sgmcgarry 	reached = r;
17336e0bca22Sgmcgarry }
17346e0bca22Sgmcgarry 
17356e0bca22Sgmcgarry /*
17366e0bca22Sgmcgarry  * Create a printable string based on an encoded string.
17376e0bca22Sgmcgarry  */
17386e0bca22Sgmcgarry static char *
17396e0bca22Sgmcgarry mkpstr(char *str)
17406e0bca22Sgmcgarry {
17416e0bca22Sgmcgarry 	char *s, *os;
17426e0bca22Sgmcgarry 	int v, l = strlen(str)+3; /* \t + \n + \0 */
17436e0bca22Sgmcgarry 
17446e0bca22Sgmcgarry 	os = s = inlalloc(l);
17456e0bca22Sgmcgarry 	*s++ = '\t';
17466e0bca22Sgmcgarry 	for (; *str; ) {
17476e0bca22Sgmcgarry 		if (*str++ == '\\')
17486e0bca22Sgmcgarry 			v = esccon(&str);
17496e0bca22Sgmcgarry 		else
17506e0bca22Sgmcgarry 			v = str[-1];
17516e0bca22Sgmcgarry 		*s++ = v;
17526e0bca22Sgmcgarry 	}
17536e0bca22Sgmcgarry 	*s++ = '\n';
17546e0bca22Sgmcgarry 	*s = 0;
17556e0bca22Sgmcgarry 	return os;
17566e0bca22Sgmcgarry }
17576e0bca22Sgmcgarry 
17586e0bca22Sgmcgarry /*
17596e0bca22Sgmcgarry  * Estimate the max length a string will have in its internal
17606e0bca22Sgmcgarry  * representation based on number of \ characters.
17616e0bca22Sgmcgarry  */
17626e0bca22Sgmcgarry static int
17636e0bca22Sgmcgarry maxstlen(char *str)
17646e0bca22Sgmcgarry {
17656e0bca22Sgmcgarry 	int i;
17666e0bca22Sgmcgarry 
17676e0bca22Sgmcgarry 	for (i = 0; *str; str++, i++)
17686e0bca22Sgmcgarry 		if (*str == '\\' || *str < 32 || *str > 0176)
17696e0bca22Sgmcgarry 			i += 3;
17706e0bca22Sgmcgarry 	return i;
17716e0bca22Sgmcgarry }
17726e0bca22Sgmcgarry 
17736e0bca22Sgmcgarry static char *
17746e0bca22Sgmcgarry voct(char *d, unsigned int v)
17756e0bca22Sgmcgarry {
17766e0bca22Sgmcgarry 	v &= (1 << SZCHAR) - 1;
17776e0bca22Sgmcgarry 	*d++ = '\\';
17786e0bca22Sgmcgarry 	*d++ = v/64 + '0'; v &= 077;
17796e0bca22Sgmcgarry 	*d++ = v/8 + '0'; v &= 7;
17806e0bca22Sgmcgarry 	*d++ = v + '0';
17816e0bca22Sgmcgarry 	return d;
17826e0bca22Sgmcgarry }
17836e0bca22Sgmcgarry 
17846e0bca22Sgmcgarry 
17856e0bca22Sgmcgarry /*
17866e0bca22Sgmcgarry  * Convert a string to internal format.  The resulting string may be no
17876e0bca22Sgmcgarry  * more than len characters long.
17886e0bca22Sgmcgarry  */
17896e0bca22Sgmcgarry static void
17906e0bca22Sgmcgarry fixstr(char *d, char *s, int len)
17916e0bca22Sgmcgarry {
17926e0bca22Sgmcgarry 	unsigned int v;
17936e0bca22Sgmcgarry 
17946e0bca22Sgmcgarry 	while (*s) {
17956e0bca22Sgmcgarry 		if (len <= 0)
17966e0bca22Sgmcgarry 			cerror("fixstr");
17976e0bca22Sgmcgarry 		if (*s == '\\') {
17986e0bca22Sgmcgarry 			s++;
17996e0bca22Sgmcgarry 			v = esccon(&s);
18006e0bca22Sgmcgarry 			d = voct(d, v);
18016e0bca22Sgmcgarry 			len -= 4;
18026e0bca22Sgmcgarry 		} else if (*s < ' ' || *s > 0176) {
18036e0bca22Sgmcgarry 			d = voct(d, *s++);
18046e0bca22Sgmcgarry 			len -= 4;
18056e0bca22Sgmcgarry 		} else
18066e0bca22Sgmcgarry 			*d++ = *s++, len--;
18076e0bca22Sgmcgarry 	}
18086e0bca22Sgmcgarry 	*d = 0;
18096e0bca22Sgmcgarry }
18106e0bca22Sgmcgarry 
18116e0bca22Sgmcgarry /*
18126e0bca22Sgmcgarry  * Add "raw" string new to cleaned string old.
18136e0bca22Sgmcgarry  */
18146e0bca22Sgmcgarry static char *
18156e0bca22Sgmcgarry stradd(char *old, char *new)
18166e0bca22Sgmcgarry {
18176e0bca22Sgmcgarry 	char *rv;
18186e0bca22Sgmcgarry 	int len;
18196e0bca22Sgmcgarry 
18206e0bca22Sgmcgarry 	if (*new == 'L' && new[1] == '\"')
18216e0bca22Sgmcgarry 		widestr = 1, new++;
18226e0bca22Sgmcgarry 	if (*new == '\"') {
18236e0bca22Sgmcgarry 		new++;			 /* remove first " */
18246e0bca22Sgmcgarry 		new[strlen(new) - 1] = 0;/* remove last " */
18256e0bca22Sgmcgarry 	}
18266e0bca22Sgmcgarry 	len = strlen(old) + maxstlen(new) + 1;
18276e0bca22Sgmcgarry 	rv = tmpalloc(len);
18286e0bca22Sgmcgarry 	strlcpy(rv, old, len);
18296e0bca22Sgmcgarry 	fixstr(rv + strlen(old), new, maxstlen(new) + 1);
18306e0bca22Sgmcgarry 	return rv;
18316e0bca22Sgmcgarry }
18326e0bca22Sgmcgarry 
1833c4627bc7Sgmcgarry /*
1834c4627bc7Sgmcgarry  * Fake a symtab entry for compound literals.
1835c4627bc7Sgmcgarry  */
18366e0bca22Sgmcgarry static struct symtab *
18376e0bca22Sgmcgarry clbrace(NODE *p)
18386e0bca22Sgmcgarry {
18396e0bca22Sgmcgarry 	struct symtab *sp;
18406e0bca22Sgmcgarry 
1841c4627bc7Sgmcgarry 	sp = getsymtab(simname("cl"), STEMP);
18426e0bca22Sgmcgarry 	sp->stype = p->n_type;
18436e0bca22Sgmcgarry 	sp->squal = p->n_qual;
18446e0bca22Sgmcgarry 	sp->sdf = p->n_df;
1845*a301e773Splunky 	sp->sap = p->n_ap;
1846c4627bc7Sgmcgarry 	tfree(p);
1847c4627bc7Sgmcgarry 	if (blevel == 0 && xnf != NULL) {
1848c4627bc7Sgmcgarry 		sp->sclass = STATIC;
1849c4627bc7Sgmcgarry 		sp->slevel = 2;
1850c4627bc7Sgmcgarry 		sp->soffset = getlab();
1851c4627bc7Sgmcgarry 	} else {
18526e0bca22Sgmcgarry 		sp->sclass = blevel ? AUTO : STATIC;
18536e0bca22Sgmcgarry 		if (!ISARY(sp->stype) || sp->sdf->ddim != NOOFFSET) {
18546e0bca22Sgmcgarry 			sp->soffset = NOOFFSET;
18556e0bca22Sgmcgarry 			oalloc(sp, &autooff);
18566e0bca22Sgmcgarry 		}
1857c4627bc7Sgmcgarry 	}
18586e0bca22Sgmcgarry 	beginit(sp);
18596e0bca22Sgmcgarry 	return sp;
18606e0bca22Sgmcgarry }
18616e0bca22Sgmcgarry 
1862c4627bc7Sgmcgarry char *
1863c4627bc7Sgmcgarry simname(char *s)
1864c4627bc7Sgmcgarry {
1865c4627bc7Sgmcgarry 	int len = strlen(s) + 10 + 1;
1866c4627bc7Sgmcgarry 	char *w = tmpalloc(len);
1867c4627bc7Sgmcgarry 
1868c4627bc7Sgmcgarry 	snprintf(w, len, "%s%d", s, getlab());
1869c4627bc7Sgmcgarry 	return w;
1870c4627bc7Sgmcgarry }
1871c4627bc7Sgmcgarry 
18726e0bca22Sgmcgarry NODE *
18736e0bca22Sgmcgarry biop(int op, NODE *l, NODE *r)
18746e0bca22Sgmcgarry {
1875*a301e773Splunky 	return block(op, l, r, INT, 0, 0);
18766e0bca22Sgmcgarry }
18776e0bca22Sgmcgarry 
18786e0bca22Sgmcgarry static NODE *
18796e0bca22Sgmcgarry cmop(NODE *l, NODE *r)
18806e0bca22Sgmcgarry {
18816e0bca22Sgmcgarry 	return biop(CM, l, r);
18826e0bca22Sgmcgarry }
18836e0bca22Sgmcgarry 
18846e0bca22Sgmcgarry static NODE *
18856e0bca22Sgmcgarry voidcon(void)
18866e0bca22Sgmcgarry {
1887*a301e773Splunky 	return block(ICON, NIL, NIL, STRTY, 0, 0);
18886e0bca22Sgmcgarry }
18896e0bca22Sgmcgarry 
18906e0bca22Sgmcgarry /* Support for extended assembler a' la' gcc style follows below */
18916e0bca22Sgmcgarry 
18926e0bca22Sgmcgarry static NODE *
18936e0bca22Sgmcgarry xmrg(NODE *out, NODE *in)
18946e0bca22Sgmcgarry {
18956e0bca22Sgmcgarry 	NODE *p = in;
18966e0bca22Sgmcgarry 
18976e0bca22Sgmcgarry 	if (p->n_op == XARG) {
18986e0bca22Sgmcgarry 		in = cmop(out, p);
18996e0bca22Sgmcgarry 	} else {
19006e0bca22Sgmcgarry 		while (p->n_left->n_op == CM)
19016e0bca22Sgmcgarry 			p = p->n_left;
19026e0bca22Sgmcgarry 		p->n_left = cmop(out, p->n_left);
19036e0bca22Sgmcgarry 	}
19046e0bca22Sgmcgarry 	return in;
19056e0bca22Sgmcgarry }
19066e0bca22Sgmcgarry 
19076e0bca22Sgmcgarry /*
19086e0bca22Sgmcgarry  * Put together in and out node lists in one list, and balance it with
19096e0bca22Sgmcgarry  * the constraints on the right side of a CM node.
19106e0bca22Sgmcgarry  */
19116e0bca22Sgmcgarry static NODE *
19126e0bca22Sgmcgarry xcmop(NODE *out, NODE *in, NODE *str)
19136e0bca22Sgmcgarry {
19146e0bca22Sgmcgarry 	NODE *p, *q;
19156e0bca22Sgmcgarry 
19166e0bca22Sgmcgarry 	if (out) {
19176e0bca22Sgmcgarry 		/* D out-list sanity check */
19186e0bca22Sgmcgarry 		for (p = out; p->n_op == CM; p = p->n_left) {
19196e0bca22Sgmcgarry 			q = p->n_right;
19206e0bca22Sgmcgarry 			if (q->n_name[0] != '=' && q->n_name[0] != '+')
19216e0bca22Sgmcgarry 				uerror("output missing =");
19226e0bca22Sgmcgarry 		}
19236e0bca22Sgmcgarry 		if (p->n_name[0] != '=' && p->n_name[0] != '+')
19246e0bca22Sgmcgarry 			uerror("output missing =");
19256e0bca22Sgmcgarry 		if (in == NIL)
19266e0bca22Sgmcgarry 			p = out;
19276e0bca22Sgmcgarry 		else
19286e0bca22Sgmcgarry 			p = xmrg(out, in);
19296e0bca22Sgmcgarry 	} else if (in) {
19306e0bca22Sgmcgarry 		p = in;
19316e0bca22Sgmcgarry 	} else
19326e0bca22Sgmcgarry 		p = voidcon();
19336e0bca22Sgmcgarry 
19346e0bca22Sgmcgarry 	if (str == NIL)
19356e0bca22Sgmcgarry 		str = voidcon();
19366e0bca22Sgmcgarry 	return cmop(p, str);
19376e0bca22Sgmcgarry }
19386e0bca22Sgmcgarry 
19396e0bca22Sgmcgarry /*
19406e0bca22Sgmcgarry  * Generate a XARG node based on a string and an expression.
19416e0bca22Sgmcgarry  */
19426e0bca22Sgmcgarry static NODE *
19436e0bca22Sgmcgarry xasmop(char *str, NODE *p)
19446e0bca22Sgmcgarry {
19456e0bca22Sgmcgarry 
19466e0bca22Sgmcgarry 	p = biop(XARG, p, NIL);
19476e0bca22Sgmcgarry 	p->n_name = isinlining ? newstring(str, strlen(str)+1) : str;
19486e0bca22Sgmcgarry 	return p;
19496e0bca22Sgmcgarry }
19506e0bca22Sgmcgarry 
19516e0bca22Sgmcgarry /*
19526e0bca22Sgmcgarry  * Generate a XASM node based on a string and an expression.
19536e0bca22Sgmcgarry  */
19546e0bca22Sgmcgarry static void
19556e0bca22Sgmcgarry mkxasm(char *str, NODE *p)
19566e0bca22Sgmcgarry {
19576e0bca22Sgmcgarry 	NODE *q;
19586e0bca22Sgmcgarry 
19596e0bca22Sgmcgarry 	q = biop(XASM, p->n_left, p->n_right);
19606e0bca22Sgmcgarry 	q->n_name = isinlining ? newstring(str, strlen(str)+1) : str;
19616e0bca22Sgmcgarry 	nfree(p);
19626e0bca22Sgmcgarry 	ecomp(q);
19636e0bca22Sgmcgarry }
1964c4627bc7Sgmcgarry 
1965c4627bc7Sgmcgarry #ifdef GCC_COMPAT
1966c4627bc7Sgmcgarry static NODE *
1967c4627bc7Sgmcgarry tyof(NODE *p)
1968c4627bc7Sgmcgarry {
1969c4627bc7Sgmcgarry 	static struct symtab spp;
1970*a301e773Splunky 	NODE *q = block(TYPE, NIL, NIL, p->n_type, p->n_df, p->n_ap);
1971c4627bc7Sgmcgarry 	q->n_qual = p->n_qual;
1972c4627bc7Sgmcgarry 	q->n_sp = &spp; /* for typenode */
1973c4627bc7Sgmcgarry 	tfree(p);
1974c4627bc7Sgmcgarry 	return q;
1975c4627bc7Sgmcgarry }
1976c4627bc7Sgmcgarry #endif
1977c4627bc7Sgmcgarry 
1978c4627bc7Sgmcgarry /*
1979*a301e773Splunky  * Rewrite ++/-- to (t=p, p++, t) ops on types that do not act act as usual.
1980*a301e773Splunky  */
1981*a301e773Splunky static NODE *
1982*a301e773Splunky rewincop(NODE *p1, NODE *p2, int op)
1983*a301e773Splunky {
1984*a301e773Splunky 	NODE *t, *r;
1985*a301e773Splunky 
1986*a301e773Splunky 	t = cstknode(p1->n_type, 0, 0);
1987*a301e773Splunky 	r = buildtree(ASSIGN, ccopy(t), ccopy(p1));
1988*a301e773Splunky 	r = buildtree(COMOP, r, buildtree(op, p1, eve(p2)));
1989*a301e773Splunky 	return buildtree(COMOP, r, t);
1990*a301e773Splunky }
1991*a301e773Splunky 
1992*a301e773Splunky /*
1993c4627bc7Sgmcgarry  * Traverse an unhandled expression tree bottom-up and call buildtree()
1994c4627bc7Sgmcgarry  * or equivalent as needed.
1995c4627bc7Sgmcgarry  */
1996c4627bc7Sgmcgarry NODE *
1997c4627bc7Sgmcgarry eve(NODE *p)
1998c4627bc7Sgmcgarry {
1999c4627bc7Sgmcgarry 	struct symtab *sp;
2000c4627bc7Sgmcgarry 	NODE *r, *p1, *p2;
2001c4627bc7Sgmcgarry 	int x;
2002c4627bc7Sgmcgarry 
2003c4627bc7Sgmcgarry 	p1 = p->n_left;
2004c4627bc7Sgmcgarry 	p2 = p->n_right;
2005c4627bc7Sgmcgarry 	switch (p->n_op) {
2006c4627bc7Sgmcgarry 	case NAME:
2007c4627bc7Sgmcgarry 		sp = lookup((char *)p->n_sp, 0);
2008c4627bc7Sgmcgarry 		if (sp->sflags & SINLINE)
2009c4627bc7Sgmcgarry 			inline_ref(sp);
2010c4627bc7Sgmcgarry 		r = nametree(sp);
2011c4627bc7Sgmcgarry 		if (sp->sflags & SDYNARRAY)
2012c4627bc7Sgmcgarry 			r = buildtree(UMUL, r, NIL);
2013*a301e773Splunky #ifdef GCC_COMPAT
2014*a301e773Splunky 		if (attr_find(sp->sap, GCC_ATYP_DEPRECATED))
2015*a301e773Splunky 			werror("`%s' is deprecated", sp->sname);
2016*a301e773Splunky #endif
2017c4627bc7Sgmcgarry 		break;
2018c4627bc7Sgmcgarry 
2019c4627bc7Sgmcgarry 	case DOT:
2020c4627bc7Sgmcgarry 	case STREF:
2021c4627bc7Sgmcgarry 		r = structref(eve(p1), p->n_op, (char *)p2->n_sp);
2022c4627bc7Sgmcgarry 		nfree(p2);
2023c4627bc7Sgmcgarry 		break;
2024c4627bc7Sgmcgarry 
2025c4627bc7Sgmcgarry 	case CAST:
2026c4627bc7Sgmcgarry 		p1 = buildtree(CAST, p1, eve(p2));
2027c4627bc7Sgmcgarry 		nfree(p1->n_left);
2028c4627bc7Sgmcgarry 		r = p1->n_right;
2029c4627bc7Sgmcgarry 		nfree(p1);
2030c4627bc7Sgmcgarry 		break;
2031c4627bc7Sgmcgarry 
2032c4627bc7Sgmcgarry 
2033c4627bc7Sgmcgarry 	case SZOF:
2034c4627bc7Sgmcgarry 		x = xinline; xinline = 0; /* XXX hack */
2035c4627bc7Sgmcgarry 		if (p2->n_lval == 0)
2036c4627bc7Sgmcgarry 			p1 = eve(p1);
2037*a301e773Splunky 		else
2038*a301e773Splunky 			TYMFIX(p1);
2039c4627bc7Sgmcgarry 		nfree(p2);
2040c4627bc7Sgmcgarry 		r = doszof(p1);
2041c4627bc7Sgmcgarry 		xinline = x;
2042c4627bc7Sgmcgarry 		break;
2043c4627bc7Sgmcgarry 
2044c4627bc7Sgmcgarry 	case LB:
2045c4627bc7Sgmcgarry 		p1 = eve(p->n_left);
2046c4627bc7Sgmcgarry 		r = buildtree(UMUL, buildtree(PLUS, p1, eve(p2)), NIL);
2047c4627bc7Sgmcgarry 		break;
2048c4627bc7Sgmcgarry 
2049c4627bc7Sgmcgarry 	case COMPL:
2050c4627bc7Sgmcgarry #ifndef NO_COMPLEX
2051c4627bc7Sgmcgarry 		p1 = eve(p1);
2052c4627bc7Sgmcgarry 		if (ANYCX(p1))
2053c4627bc7Sgmcgarry 			r = cxconj(p1);
2054c4627bc7Sgmcgarry 		else
2055c4627bc7Sgmcgarry 			r = buildtree(COMPL, p1, NIL);
2056c4627bc7Sgmcgarry 		break;
2057c4627bc7Sgmcgarry #endif
2058c4627bc7Sgmcgarry 	case UMINUS:
2059c4627bc7Sgmcgarry 	case NOT:
2060c4627bc7Sgmcgarry 	case UMUL:
2061c4627bc7Sgmcgarry 		r = buildtree(p->n_op, eve(p->n_left), NIL);
2062c4627bc7Sgmcgarry 		break;
2063c4627bc7Sgmcgarry 
2064c4627bc7Sgmcgarry 	case ADDROF:
2065c4627bc7Sgmcgarry 		r = eve(p1);
2066c4627bc7Sgmcgarry 		if (ISFTN(p->n_type)/* || ISARY(p->n_type) */){
2067c4627bc7Sgmcgarry #ifdef notdef
2068c4627bc7Sgmcgarry 			werror( "& before array or function: ignored" );
2069c4627bc7Sgmcgarry #endif
2070c4627bc7Sgmcgarry 		} else
2071c4627bc7Sgmcgarry 			r = buildtree(ADDROF, r, NIL);
2072c4627bc7Sgmcgarry 		break;
2073c4627bc7Sgmcgarry 
2074c4627bc7Sgmcgarry 	case CALL:
2075c4627bc7Sgmcgarry 		p2 = eve(p2);
2076c4627bc7Sgmcgarry 		/* FALLTHROUGH */
2077c4627bc7Sgmcgarry 	case UCALL:
2078c4627bc7Sgmcgarry 		if (p1->n_op == NAME) {
2079c4627bc7Sgmcgarry 			sp = lookup((char *)p1->n_sp, 0);
2080c4627bc7Sgmcgarry 			if (sp->stype == UNDEF) {
2081c4627bc7Sgmcgarry 				p1->n_type = FTN|INT;
2082c4627bc7Sgmcgarry 				p1->n_sp = sp;
2083*a301e773Splunky 				p1->n_ap = NULL;
2084c4627bc7Sgmcgarry 				defid(p1, EXTERN);
2085c4627bc7Sgmcgarry 			}
2086c4627bc7Sgmcgarry 			nfree(p1);
2087*a301e773Splunky #ifdef GCC_COMPAT
2088*a301e773Splunky 			if (attr_find(sp->sap, GCC_ATYP_DEPRECATED))
2089*a301e773Splunky 				werror("`%s' is deprecated", sp->sname);
2090*a301e773Splunky #endif
2091c4627bc7Sgmcgarry 			r = doacall(sp, nametree(sp), p2);
2092c4627bc7Sgmcgarry 		} else
2093c4627bc7Sgmcgarry 			r = doacall(NULL, eve(p1), p2);
2094c4627bc7Sgmcgarry 		break;
2095c4627bc7Sgmcgarry 
2096c4627bc7Sgmcgarry #ifndef NO_COMPLEX
2097c4627bc7Sgmcgarry 	case XREAL:
2098c4627bc7Sgmcgarry 	case XIMAG:
2099c4627bc7Sgmcgarry 		p1 = eve(p1);
2100c4627bc7Sgmcgarry 		r = cxelem(p->n_op, p1);
2101c4627bc7Sgmcgarry 		break;
2102c4627bc7Sgmcgarry #endif
2103c4627bc7Sgmcgarry 
2104c4627bc7Sgmcgarry 	case MUL:
2105c4627bc7Sgmcgarry 	case DIV:
2106c4627bc7Sgmcgarry 	case PLUS:
2107c4627bc7Sgmcgarry 	case MINUS:
2108c4627bc7Sgmcgarry 	case ASSIGN:
2109*a301e773Splunky 	case EQ:
2110*a301e773Splunky 	case NE:
2111c4627bc7Sgmcgarry #ifndef NO_COMPLEX
2112c4627bc7Sgmcgarry 		p1 = eve(p1);
2113c4627bc7Sgmcgarry 		p2 = eve(p2);
2114c4627bc7Sgmcgarry 		if (ANYCX(p1) || ANYCX(p2)) {
2115c4627bc7Sgmcgarry 			r = cxop(p->n_op, p1, p2);
2116c4627bc7Sgmcgarry 		} else if (ISITY(p1->n_type) || ISITY(p2->n_type)) {
2117c4627bc7Sgmcgarry 			r = imop(p->n_op, p1, p2);
2118c4627bc7Sgmcgarry 		} else
2119c4627bc7Sgmcgarry 			r = buildtree(p->n_op, p1, p2);
2120c4627bc7Sgmcgarry 		break;
2121c4627bc7Sgmcgarry #endif
2122c4627bc7Sgmcgarry 	case MOD:
2123c4627bc7Sgmcgarry 	case CM:
2124c4627bc7Sgmcgarry 	case GT:
2125c4627bc7Sgmcgarry 	case GE:
2126c4627bc7Sgmcgarry 	case LT:
2127c4627bc7Sgmcgarry 	case LE:
2128c4627bc7Sgmcgarry 	case RS:
2129c4627bc7Sgmcgarry 	case LS:
2130c4627bc7Sgmcgarry 	case RSEQ:
2131c4627bc7Sgmcgarry 	case LSEQ:
2132c4627bc7Sgmcgarry 	case AND:
2133c4627bc7Sgmcgarry 	case OR:
2134c4627bc7Sgmcgarry 	case ER:
2135c4627bc7Sgmcgarry 	case OROR:
2136c4627bc7Sgmcgarry 	case ANDAND:
2137c4627bc7Sgmcgarry 	case EREQ:
2138c4627bc7Sgmcgarry 	case OREQ:
2139c4627bc7Sgmcgarry 	case ANDEQ:
2140*a301e773Splunky 	case QUEST:
2141*a301e773Splunky 	case COLON:
2142*a301e773Splunky 		p1 = eve(p1);
2143*a301e773Splunky eve2:		r = buildtree(p->n_op, p1, eve(p2));
2144*a301e773Splunky 		break;
2145*a301e773Splunky 
2146*a301e773Splunky 	case INCR:
2147*a301e773Splunky 	case DECR:
2148*a301e773Splunky 		p1 = eve(p1);
2149*a301e773Splunky 		if (p1->n_type >= FLOAT && p1->n_type <= LDOUBLE) {
2150*a301e773Splunky 			/* ++/-- on floats isn't ((d+=1)-1) */
2151*a301e773Splunky 			/* rewrite to (t=d,d++,t) */
2152*a301e773Splunky 			/* XXX - side effects */
2153*a301e773Splunky 			r = rewincop(p1, p2, p->n_op);
2154*a301e773Splunky 			break;
2155*a301e773Splunky 		}
2156*a301e773Splunky 		if (p1->n_type != BOOL)
2157*a301e773Splunky 			goto eve2;
2158*a301e773Splunky 		/* Hey, fun.  ++ will always be 1, and -- will toggle result */
2159*a301e773Splunky 		if (p->n_op == INCR) {
2160*a301e773Splunky 			/* (t=d,d=1,t) */
2161*a301e773Splunky 			r = rewincop(p1, p2, ASSIGN);
2162*a301e773Splunky 		} else {
2163*a301e773Splunky 			/* (t=d,d^=1,t) */
2164*a301e773Splunky 			r = rewincop(p1, p2, EREQ);
2165*a301e773Splunky 		}
2166*a301e773Splunky 		break;
2167*a301e773Splunky 
2168*a301e773Splunky 	case MODEQ:
2169c4627bc7Sgmcgarry 	case MINUSEQ:
2170c4627bc7Sgmcgarry 	case PLUSEQ:
2171c4627bc7Sgmcgarry 	case MULEQ:
2172c4627bc7Sgmcgarry 	case DIVEQ:
2173c4627bc7Sgmcgarry 		p1 = eve(p1);
2174*a301e773Splunky 		p2 = eve(p2);
2175*a301e773Splunky #ifndef NO_COMPLEX
2176*a301e773Splunky 		if (ANYCX(p1) || ANYCX(p2)) {
2177*a301e773Splunky 			r = cxop(UNASG p->n_op, ccopy(p1), p2);
2178*a301e773Splunky 			r = cxop(ASSIGN, p1, r);
2179*a301e773Splunky 			break;
2180*a301e773Splunky 		} else if (ISITY(p1->n_type) || ISITY(p2->n_type)) {
2181*a301e773Splunky 			r = imop(UNASG p->n_op, ccopy(p1), p2);
2182*a301e773Splunky 			r = cxop(ASSIGN, p1, r);
2183*a301e773Splunky 			break;
2184*a301e773Splunky 		}
2185*a301e773Splunky 		/* FALLTHROUGH */
2186*a301e773Splunky #endif
2187*a301e773Splunky 		if (p1->n_type == BOOL) {
2188*a301e773Splunky 			r = buildtree(UNASG p->n_op, ccopy(p1), p2);
2189*a301e773Splunky 			r = buildtree(ASSIGN, p1, r);
2190*a301e773Splunky 		} else {
2191*a301e773Splunky 			r = buildtree(p->n_op, p1, p2);
2192*a301e773Splunky 		}
2193c4627bc7Sgmcgarry 		break;
2194c4627bc7Sgmcgarry 
2195c4627bc7Sgmcgarry 	case STRING:
2196c4627bc7Sgmcgarry 		r = strend(p->n_lval, p->n_name);
2197c4627bc7Sgmcgarry 		break;
2198c4627bc7Sgmcgarry 
2199c4627bc7Sgmcgarry 	case COMOP:
2200c4627bc7Sgmcgarry 		if (p1->n_op == GOTO) {
2201c4627bc7Sgmcgarry 			/* inside ({ }), eve already called */
2202c4627bc7Sgmcgarry 			r = buildtree(p->n_op, p1, p2);
2203c4627bc7Sgmcgarry 		} else {
2204c4627bc7Sgmcgarry 			p1 = eve(p1);
2205c4627bc7Sgmcgarry 			r = buildtree(p->n_op, p1, eve(p2));
2206c4627bc7Sgmcgarry 		}
2207c4627bc7Sgmcgarry 		break;
2208c4627bc7Sgmcgarry 
2209c4627bc7Sgmcgarry 	case TYPE:
2210c4627bc7Sgmcgarry 	case ICON:
2211c4627bc7Sgmcgarry 	case FCON:
22123eb51a41Splunky 	case TEMP:
2213c4627bc7Sgmcgarry 		return p;
2214c4627bc7Sgmcgarry 
2215c4627bc7Sgmcgarry 	case CLOP:
2216c4627bc7Sgmcgarry 		r = nametree(p->n_sp);
2217c4627bc7Sgmcgarry 		break;
2218c4627bc7Sgmcgarry 
2219c4627bc7Sgmcgarry 	default:
2220c4627bc7Sgmcgarry #ifdef PCC_DEBUG
2221c4627bc7Sgmcgarry 		fwalk(p, eprint, 0);
2222c4627bc7Sgmcgarry #endif
2223c4627bc7Sgmcgarry 		cerror("eve");
22243eb51a41Splunky 		r = NIL;
2225c4627bc7Sgmcgarry 	}
2226c4627bc7Sgmcgarry 	nfree(p);
2227c4627bc7Sgmcgarry 	return r;
2228c4627bc7Sgmcgarry }
2229c4627bc7Sgmcgarry 
22303eb51a41Splunky int
22313eb51a41Splunky con_e(NODE *p)
22323eb51a41Splunky {
2233*a301e773Splunky 	return icons(optim(eve(p)));
22343eb51a41Splunky }
22353eb51a41Splunky 
22363eb51a41Splunky void
22373eb51a41Splunky uawarn(NODE *p, char *s)
22383eb51a41Splunky {
22393eb51a41Splunky 	if (p == 0)
22403eb51a41Splunky 		return;
22413eb51a41Splunky 	if (attrwarn)
22423eb51a41Splunky 		werror("unhandled %s attribute", s);
22433eb51a41Splunky 	tfree(p);
22443eb51a41Splunky }
22453eb51a41Splunky 
22463eb51a41Splunky static void
22473eb51a41Splunky dainit(NODE *d, NODE *a)
22483eb51a41Splunky {
22493eb51a41Splunky 	if (d == NULL) {
22503eb51a41Splunky 		asginit(a);
22513eb51a41Splunky 	} else if (d->n_op == CM) {
22523eb51a41Splunky 		int is = con_e(d->n_left);
22533eb51a41Splunky 		int ie = con_e(d->n_right);
22543eb51a41Splunky 		int i;
22553eb51a41Splunky 
22563eb51a41Splunky 		nfree(d);
22573eb51a41Splunky 		if (ie < is)
22583eb51a41Splunky 			uerror("negative initializer range");
22593eb51a41Splunky 		desinit(biop(LB, NIL, bcon(is)));
22603eb51a41Splunky 		for (i = is; i < ie; i++)
22613eb51a41Splunky 			asginit(ccopy(a));
22623eb51a41Splunky 		asginit(a);
22633eb51a41Splunky 	} else {
22643eb51a41Splunky 		cerror("dainit");
22653eb51a41Splunky 	}
22663eb51a41Splunky }
2267*a301e773Splunky 
2268*a301e773Splunky /*
2269*a301e773Splunky  * Traverse down and tymerge() where appropriate.
2270*a301e773Splunky  */
2271*a301e773Splunky static NODE *
2272*a301e773Splunky tymfix(NODE *p)
2273*a301e773Splunky {
2274*a301e773Splunky 	NODE *q;
2275*a301e773Splunky 	int o = coptype(p->n_op);
2276*a301e773Splunky 
2277*a301e773Splunky 	switch (o) {
2278*a301e773Splunky 	case LTYPE:
2279*a301e773Splunky 		break;
2280*a301e773Splunky 	case UTYPE:
2281*a301e773Splunky 		p->n_left = tymfix(p->n_left);
2282*a301e773Splunky 		break;
2283*a301e773Splunky 	case BITYPE:
2284*a301e773Splunky 		p->n_left = tymfix(p->n_left);
2285*a301e773Splunky 		p->n_right = tymfix(p->n_right);
2286*a301e773Splunky 		if (p->n_op == TYMERGE) {
2287*a301e773Splunky 			q = tymerge(p->n_left, p->n_right);
2288*a301e773Splunky 			q->n_ap = attr_add(q->n_ap, p->n_ap);
2289*a301e773Splunky 			tfree(p->n_left);
2290*a301e773Splunky 			nfree(p);
2291*a301e773Splunky 			p = q;
2292*a301e773Splunky 		}
2293*a301e773Splunky 		break;
2294*a301e773Splunky 	}
2295*a301e773Splunky 	return p;
2296*a301e773Splunky }
2297*a301e773Splunky 
2298*a301e773Splunky static NODE *
2299*a301e773Splunky aryfix(NODE *p)
2300*a301e773Splunky {
2301*a301e773Splunky 	NODE *q;
2302*a301e773Splunky 
2303*a301e773Splunky 	for (q = p; q->n_op != NAME; q = q->n_left) {
2304*a301e773Splunky 		if (q->n_op == LB) {
2305*a301e773Splunky 			q->n_right = optim(rmpconv(eve(q->n_right)));
2306*a301e773Splunky 			if ((blevel == 0 || rpole != NULL) &&
2307*a301e773Splunky 			    !nncon(q->n_right))
2308*a301e773Splunky 				uerror("array size not constant");
2309*a301e773Splunky 			/*
2310*a301e773Splunky 			 * Checks according to 6.7.5.2 clause 1:
2311*a301e773Splunky 			 * "...the expression shall have an integer type."
2312*a301e773Splunky 			 * "If the expression is a constant expression,
2313*a301e773Splunky 			 * it shall have a value greater than zero."
2314*a301e773Splunky 			 */
2315*a301e773Splunky 			if (!ISINTEGER(q->n_right->n_type))
2316*a301e773Splunky 				werror("array size is not an integer");
2317*a301e773Splunky 			else if (q->n_right->n_op == ICON &&
2318*a301e773Splunky 			    q->n_right->n_lval < 0 &&
2319*a301e773Splunky 			    q->n_right->n_lval != NOOFFSET) {
2320*a301e773Splunky 					uerror("array size cannot be negative");
2321*a301e773Splunky 					q->n_right->n_lval = 1;
2322*a301e773Splunky 			}
2323*a301e773Splunky 		} else if (q->n_op == CALL)
2324*a301e773Splunky 			q->n_right = namekill(q->n_right, 1);
2325*a301e773Splunky 	}
2326*a301e773Splunky 	return p;
2327*a301e773Splunky }
2328