1/*	Id: cgram.y,v 1.2 2012/01/04 19:04:08 ragge Exp 	*/
2/*	$NetBSD: cgram.y,v 1.1.1.1 2012/01/11 20:33:17 plunky Exp $	*/
3
4/*
5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 *
36 * Redistributions of source code and documentation must retain the above
37 * copyright notice, this list of conditions and the following disclaimer.
38 * Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * 	This product includes software developed or owned by Caldera
44 *	International, Inc.
45 * Neither the name of Caldera International, Inc. nor the names of other
46 * contributors may be used to endorse or promote products derived from
47 * this software without specific prior written permission.
48 *
49 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
50 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53 * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
54 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
61 */
62
63/*
64 * Comments for this grammar file. Ragge 021123
65 *
66 * ANSI support required rewrite of the function header and declaration
67 * rules almost totally.
68 *
69 * The lex/yacc shared keywords are now split from the keywords used
70 * in the rest of the compiler, to simplify use of other frontends.
71 */
72
73/*
74 * At last count, there were 5 shift/reduce and no reduce/reduce conflicts
75 * Four are accounted for;
76 * One is "dangling else"
77 * Two is in attribute parsing
78 * One is in ({ }) parsing
79 */
80
81/*
82 * Token used in C lex/yacc communications.
83 */
84%token	C_STRING	/* a string constant */
85%token	C_ICON		/* an integer constant */
86%token	C_FCON		/* a floating point constant */
87%token	C_NAME		/* an identifier */
88%token	C_TYPENAME	/* a typedef'd name */
89%token	C_ANDAND	/* && */
90%token	C_OROR		/* || */
91%token	C_GOTO		/* unconditional goto */
92%token	C_RETURN	/* return from function */
93%token	C_TYPE		/* a type */
94%token	C_CLASS		/* a storage class */
95%token	C_ASOP		/* assignment ops */
96%token	C_RELOP		/* <=, <, >=, > */
97%token	C_EQUOP		/* ==, != */
98%token	C_DIVOP		/* /, % */
99%token	C_SHIFTOP	/* <<, >> */
100%token	C_INCOP		/* ++, -- */
101%token	C_UNOP		/* !, ~ */
102%token	C_STROP		/* ., -> */
103%token	C_STRUCT
104%token	C_IF
105%token	C_ELSE
106%token	C_SWITCH
107%token	C_BREAK
108%token	C_CONTINUE
109%token	C_WHILE
110%token	C_DO
111%token	C_FOR
112%token	C_DEFAULT
113%token	C_CASE
114%token	C_SIZEOF
115%token	C_ALIGNOF
116%token	C_ENUM
117%token	C_ELLIPSIS
118%token	C_QUALIFIER
119%token	C_FUNSPEC
120%token	C_ASM
121%token	NOMATCH
122%token	C_TYPEOF	/* COMPAT_GCC */
123%token	C_ATTRIBUTE	/* COMPAT_GCC */
124%token	PCC_OFFSETOF
125%token	GCC_DESIG
126%token	CXX_NAMESPACE
127%token	CXX_DUALCC
128%token	CXX_TEMPLATE
129%token	CXX_USING
130%token	CXX_TYPENAME
131%token	CXX_CASTS
132%token	CXX_THROW
133%token	CXX_MORENM
134%token	CXX_NEW
135%token	CXX_DELETE
136%token	CXX_CLASS
137
138/*
139 * Precedence
140 */
141%left ','
142%right '=' C_ASOP
143%right '?' ':'
144%left C_OROR
145%left C_ANDAND
146%left '|'
147%left '^'
148%left '&'
149%left C_EQUOP
150%left C_RELOP
151%left C_SHIFTOP
152%left '+' '-'
153%left '*' C_DIVOP
154%right C_UNOP
155%right C_INCOP C_SIZEOF
156%left '[' '(' C_STROP
157%{
158# include "pass1.h"
159# include <stdarg.h>
160# include <string.h>
161# include <stdlib.h>
162
163int fun_inline;	/* Reading an inline function */
164int oldstyle;	/* Current function being defined */
165static struct symtab *xnf;
166extern int enummer, tvaloff, inattr;
167extern struct rstack *rpole;
168static int widestr, alwinl;
169NODE *cftnod;
170static int attrwarn = 1;
171
172#define	NORETYP	SNOCREAT /* no return type, save in unused field in symtab */
173
174       NODE *bdty(int op, ...);
175static void fend(struct symtab *);
176static struct symtab *fundef(NODE *tp, NODE *p);
177static void olddecl(NODE *p, NODE *a);
178static struct symtab *init_declarator(NODE *tn, NODE *p, int assign, NODE *a);
179static void resetbc(int mask);
180static void swend(void);
181static void addcase(NODE *p);
182#ifdef GCC_COMPAT
183static void gcccase(NODE *p, NODE *);
184#endif
185static void adddef(void);
186static void savebc(void);
187static void swstart(int, TWORD);
188static void genswitch(int, TWORD, struct swents **, int);
189static char *mkpstr(char *str);
190static struct symtab *clbrace(NODE *);
191static NODE *cmop(NODE *l, NODE *r);
192static NODE *xcmop(NODE *out, NODE *in, NODE *str);
193static void mkxasm(char *str, NODE *p);
194static NODE *xasmop(char *str, NODE *p);
195static int maxstlen(char *str);
196static char *stradd(char *old, char *new);
197static NODE *biop(int op, NODE *l, NODE *r);
198static void flend(void);
199static char * simname(char *s);
200#ifdef GCC_COMPAT
201static NODE *tyof(NODE *);	/* COMPAT_GCC */
202static NODE *voidcon(void);	/* COMPAT_GCC */
203#endif
204static NODE *funargs(NODE *p);
205static void oldargs(NODE *p);
206static void uawarn(NODE *p, char *s);
207static int con_e(NODE *p);
208static void dainit(NODE *d, NODE *a);
209static NODE *tymfix(NODE *p);
210static NODE *namekill(NODE *p, int clr);
211static NODE *aryfix(NODE *p);
212
213#define	TYMFIX(inp) { \
214	NODE *pp = inp; \
215	inp = tymerge(pp->n_left, pp->n_right); \
216	nfree(pp->n_left); nfree(pp); }
217/*
218 * State for saving current switch state (when nested switches).
219 */
220struct savbc {
221	struct savbc *next;
222	int brklab;
223	int contlab;
224	int flostat;
225	int swx;
226} *savbc, *savctx;
227
228%}
229
230%union {
231	int intval;
232	NODE *nodep;
233	struct symtab *symp;
234	struct rstack *rp;
235	char *strp;
236}
237
238	/* define types */
239%start edf
240
241%type <intval> ifelprefix ifprefix whprefix forprefix doprefix switchpart
242		xbegin
243%type <nodep> e .e term enum_dcl struct_dcl cast_type declarator
244		elist type_sq cf_spec merge_attribs
245		parameter_declaration abstract_declarator initializer
246		parameter_type_list parameter_list addrlbl
247		declaration_specifiers designation
248		specifier_qualifier_list merge_specifiers
249		identifier_list arg_param_list type_qualifier_list
250		designator_list designator xasm oplist oper cnstr
251		typeof attribute attribute_specifier /* COMPAT_GCC */
252		attribute_list attr_spec_list attr_var /* COMPAT_GCC */
253		new_ma new_type_sq new_ds nmrec
254%type <strp>	string C_STRING GCC_DESIG nsname CXX_MORENM
255%type <rp>	str_head
256%type <symp>	xnfdeclarator clbrace enum_head funtype
257
258%type <intval>  C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
259		C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
260
261%type <nodep>   C_TYPE C_QUALIFIER C_ICON C_FCON C_CLASS
262%type <strp>	C_NAME C_TYPENAME
263%%
264
265edf:		  ext_def_list
266		| { ftnend(); }
267		;
268
269ext_def_list:	  ext_def_list external_def
270		| external_def
271		;
272
273external_def:	   funtype kr_args compoundstmt { fend($1); }
274		|  declaration  { blevel = 0; symclear(0); }
275		| namespace
276		| extlink
277		| blockdcl
278		|  ';'
279		|  error { blevel = 0; }
280		;
281
282funtype:	  /* no type given */ declarator {
283		    $$ = fundef(mkty(INT, 0, 0), $1);
284		    cftnsp->sflags |= NORETYP;
285		}
286		| declaration_specifiers declarator { $$ = fundef($1,$2); }
287		;
288
289kr_args:	  /* empty */
290		| arg_dcl_list
291		;
292
293blockdcl:	  simple_decl
294		| asmstatement
295		| ns_alias
296		| using_x
297		;
298
299using_x:	  CXX_USING tnopt ccopt nested_name_sp ';' { werror("using"); }
300		| CXX_USING CXX_NAMESPACE ccopt nested_name_sp ';' { werror("using2"); }
301		;
302
303tnopt:		  CXX_TYPENAME { }
304		| { }
305		;
306
307ns_alias:	  CXX_NAMESPACE C_NAME '=' qual_ns_sp ';' { werror("ns_alias");}
308		;
309
310qual_ns_sp:	  ccopt nested_name_sp
311		;
312
313nested_name_sp:   nmtnm
314		| nmtnm CXX_DUALCC nested_name_sp
315		| nmtnm CXX_DUALCC CXX_TEMPLATE nested_name_sp
316		;
317
318nmtnm:		  C_NAME
319		| C_TYPENAME
320		;
321
322ccopt:		  CXX_DUALCC
323		| { }
324		;
325
326simple_decl:	  ')' NOMATCH { uerror("simple-declaration"); }
327		;
328
329namespace:	  CXX_NAMESPACE nsname attr_var nsbeg ns_body '}' { POPSYM(); }
330		;
331
332nsname:		  C_NAME
333		| { $$ = NULL; }
334		;
335
336ns_body:	  ext_def_list
337		| { }
338		;
339
340nsbeg:		  '{' { dclns($<nodep>0, $<strp>-1); }
341		;
342
343extlink:	  C_CLASS C_STRING eb '{' ext_def_list '}' { elnk = LINK_DEF; }
344		| C_CLASS C_STRING eb '{' '}' { elnk = LINK_DEF; }
345		| C_CLASS C_STRING eb declaration { elnk = LINK_DEF; }
346		;
347
348eb:		  {
349			NODE *p = $<nodep>-1;
350			char *s = $<strp>0;
351			if (p->n_type != EXTERN)
352				uerror("'extern' expected");
353			if (strcmp(s, "\"C\"") != 0 && strcmp(s, "\"c\""))
354				uerror("unknown linkage %s", s);
355			nfree(p);
356			elnk = LINK_C;
357		}
358		;
359/*
360 * Returns a node pointer or NULL, if no types at all given.
361 * Type trees are checked for correctness and merged into one
362 * type node in typenode().
363 */
364declaration_specifiers:
365		   merge_attribs { $$ = typenode($1); }
366		;
367
368merge_attribs:	   type_sq { $$ = $1; }
369		|  type_sq merge_attribs { $$ = cmop($2, $1); }
370		|  cf_spec { $$ = $1; }
371		|  cf_spec merge_attribs { $$ = cmop($2, $1); }
372		;
373
374type_sq:	   C_TYPE { $$ = $1; }
375		|  C_TYPENAME {
376			struct symtab *sp = lookup($1, 0);
377			if (sp->stype == ENUMTY) {
378				sp->stype = strmemb(sp->sap)->stype;
379			}
380			$$ = mkty(sp->stype, sp->sdf, sp->sap);
381			$$->n_sp = sp;
382		}
383		|  struct_dcl { $$ = $1; }
384		|  enum_dcl { $$ = $1; }
385		|  C_QUALIFIER { $$ = $1; }
386		|  attribute_specifier { $$ = biop(ATTRIB, $1, 0); }
387		|  typeof { $$ = $1; }
388		;
389
390cf_spec:	   C_CLASS { $$ = $1; }
391		|  C_FUNSPEC { fun_inline = 1;  /* XXX - hack */
392			$$ = block(QUALIFIER, NIL, NIL, 0, 0, 0); }
393		;
394
395typeof:		   C_TYPEOF '(' e ')' { $$ = tyof(eve($3)); }
396		|  C_TYPEOF '(' cast_type ')' { TYMFIX($3); $$ = tyof($3); }
397		;
398
399new_ma:		   new_type_sq
400		|  new_type_sq new_ma { $$ = cmop($2, $1); }
401		|  cf_spec { $$ = $1; }
402		|  cf_spec new_ma { $$ = cmop($2, $1); }
403		;
404
405new_ds:		   new_ma { $$ = typenode($1); }
406		;
407
408new_type_sq:	   C_TYPE { $$ = $1; }
409		|  C_TYPENAME {
410			struct symtab *sp = lookup($1, 0);
411			if (sp->stype == ENUMTY) {
412				sp->stype = strmemb(sp->sap)->stype;
413			}
414			$$ = mkty(sp->stype, sp->sdf, sp->sap);
415			$$->n_sp = sp;
416		}
417		|  struct_dcl { $$ = $1; }
418		|  enum_dcl { $$ = $1; }
419		|  C_QUALIFIER { $$ = $1; }
420		;
421
422attribute_specifier :
423		   C_ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; }
424 /*COMPAT_GCC*/	;
425
426attribute_list:	   attribute
427		|  attribute ',' attribute_list { $$ = cmop($3, $1); }
428		;
429
430attribute:	   {
431#ifdef GCC_COMPAT
432			 $$ = voidcon();
433#endif
434		}
435		|  C_NAME { $$ = bdty(NAME, $1); }
436		|  C_NAME '(' elist ')' {
437			$$ = bdty($3 == NIL ? UCALL : CALL, bdty(NAME, $1), $3);
438		}
439		;
440
441/*
442 * Adds a pointer list to front of the declarators.
443 */
444declarator:	   '*' declarator { $$ = bdty(UMUL, $2); }
445		|  '*' type_qualifier_list declarator {
446			$$ = $2;
447			$$->n_left = $3;
448		}
449		|  nmrec C_NAME { $$ = biop(NMLIST, $1, bdty(NAME, $2)); }
450		|  C_NAME { $$ = bdty(NAME, $1); }
451		|  '(' attr_spec_list declarator ')' {
452			$$ = $3;
453			$$->n_ap = attr_add($$->n_ap, gcc_attr_parse($2));
454		}
455		|  '(' declarator ')' { $$ = $2; }
456		|  declarator '[' e ']' { $$ = biop(LB, $1, $3); }
457		|  declarator '[' C_CLASS e ']' {
458			if ($3->n_type != STATIC)
459				uerror("bad class keyword");
460			tfree($3); /* XXX - handle */
461			$$ = biop(LB, $1, $4);
462		}
463		|  declarator '[' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); }
464		|  declarator '[' '*' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); }
465		|  declarator '(' parameter_type_list ')' {
466			$$ = bdty(CALL, $1, $3);
467		}
468		|  declarator '(' identifier_list ')' {
469			$$ = bdty(CALL, $1, $3);
470			oldstyle = 1;
471		}
472		|  declarator '(' ')' { $$ = bdty(UCALL, $1); }
473		;
474
475type_qualifier_list:
476		   C_QUALIFIER { $$ = $1; $$->n_op = UMUL; }
477		|  type_qualifier_list C_QUALIFIER {
478			$$ = $1;
479			$$->n_qual |= $2->n_qual;
480			nfree($2);
481		}
482		|  attribute_specifier {
483			$$ = block(UMUL, NIL, NIL, 0, 0, gcc_attr_parse($1));
484		}
485		|  type_qualifier_list attribute_specifier {
486			$1->n_ap = attr_add($1->n_ap, gcc_attr_parse($2));
487		}
488		;
489
490identifier_list:   C_NAME { $$ = bdty(NAME, $1); oldargs($$); }
491		|  identifier_list ',' C_NAME {
492			$$ = cmop($1, bdty(NAME, $3));
493			oldargs($$->n_right);
494		}
495		;
496
497/*
498 * Returns as parameter_list, but can add an additional ELLIPSIS node.
499 */
500parameter_type_list:
501		   parameter_list { $$ = $1; }
502		|  parameter_list ',' C_ELLIPSIS {
503			$$ = cmop($1, biop(ELLIPSIS, NIL, NIL));
504		}
505		;
506
507/*
508 * Returns a linked lists of nodes of op CM with parameters on
509 * its right and additional CM nodes of its left pointer.
510 * No CM nodes if only one parameter.
511 */
512parameter_list:	   parameter_declaration { $$ = $1; }
513		|  parameter_declaration '&' { $$ = $1; }
514		|  parameter_list ',' parameter_declaration {
515			$$ = cmop($1, $3);
516		}
517		;
518
519/*
520 * Returns a node pointer to the declaration.
521 */
522parameter_declaration:
523		   declaration_specifiers declarator attr_var {
524			if ($1->n_lval != SNULL && $1->n_lval != REGISTER)
525				uerror("illegal parameter class");
526			$$ = block(TYMERGE, $1, $2, INT, 0, gcc_attr_parse($3));
527		}
528		|  declaration_specifiers abstract_declarator {
529			$$ = block(TYMERGE, $1, $2, INT, 0, 0);
530		}
531		|  declaration_specifiers {
532			$$ = block(TYMERGE, $1, bdty(NAME, NULL), INT, 0, 0);
533		}
534		;
535
536abstract_declarator:
537		   '*' { $$ = bdty(UMUL, bdty(NAME, NULL)); }
538		|  '*' type_qualifier_list {
539			$$ = $2;
540			$$->n_left = bdty(NAME, NULL);
541		}
542		|  '*' abstract_declarator { $$ = bdty(UMUL, $2); }
543		|  '*' type_qualifier_list abstract_declarator {
544			$$ = $2;
545			$$->n_left = $3;
546		}
547		|  '(' abstract_declarator ')' { $$ = $2; }
548		|  '[' ']' attr_var {
549			$$ = block(LB, bdty(NAME, NULL), bcon(NOOFFSET),
550			    INT, 0, gcc_attr_parse($3));
551		}
552		|  '[' e ']' attr_var {
553			$$ = block(LB, bdty(NAME, NULL), $2,
554			    INT, 0, gcc_attr_parse($4));
555		}
556		|  abstract_declarator '[' ']' attr_var {
557			$$ = block(LB, $1, bcon(NOOFFSET),
558			    INT, 0, gcc_attr_parse($4));
559		}
560		|  abstract_declarator '[' e ']' attr_var {
561			$$ = block(LB, $1, $3, INT, 0, gcc_attr_parse($5));
562		}
563		|  '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
564		|  '(' ib2 parameter_type_list ')' {
565			$$ = bdty(CALL, bdty(NAME, NULL), $3);
566		}
567		|  abstract_declarator '(' ')' {
568			$$ = bdty(UCALL, $1);
569		}
570		|  abstract_declarator '(' ib2 parameter_type_list ')' {
571			$$ = bdty(CALL, $1, $4);
572		}
573		;
574
575ib2:		  { }
576		;
577/*
578 * K&R arg declaration, between ) and {
579 */
580arg_dcl_list:	   arg_declaration
581		|  arg_dcl_list arg_declaration
582		;
583
584
585arg_declaration:   declaration_specifiers arg_param_list ';' {
586			nfree($1);
587		}
588		;
589
590arg_param_list:	   declarator attr_var {
591			olddecl(block(TYMERGE, ccopy($<nodep>0), $1,
592			    INT, 0, 0), $2);
593		}
594		|  arg_param_list ',' declarator attr_var {
595			olddecl(block(TYMERGE, ccopy($<nodep>0), $3,
596			    INT, 0, 0), $4);
597		}
598		;
599
600/*
601 * Declarations in beginning of blocks.
602 */
603block_item_list:   block_item
604		|  block_item_list block_item
605		;
606
607block_item:	   declaration
608		|  statement
609		;
610
611/*
612 * Here starts the old YACC code.
613 */
614
615/*
616 * Variables are declared in init_declarator.
617 */
618declaration:	   declaration_specifiers ';' { tfree($1); fun_inline = 0; }
619		|  declaration_specifiers init_declarator_list ';' {
620			tfree($1);
621			fun_inline = 0;
622		}
623		;
624
625/*
626 * Normal declaration of variables. curtype contains the current type node.
627 * Returns nothing, variables are declared in init_declarator.
628 */
629init_declarator_list:
630		   init_declarator { symclear(blevel); }
631		|  init_declarator_list ',' attr_var { $<nodep>$ = $<nodep>0; } init_declarator {
632			uawarn($3, "init_declarator");
633			symclear(blevel);
634		}
635		;
636
637enum_dcl:	   enum_head '{' moe_list optcomma '}' { $$ = enumdcl($1); }
638		|  C_ENUM C_NAME {  $$ = enumref($2); }
639		;
640
641enum_head:	   C_ENUM { $$ = enumhd(NULL); }
642		|  C_ENUM C_NAME {  $$ = enumhd($2); }
643		;
644
645moe_list:	   moe
646		|  moe_list ',' moe
647		;
648
649moe:		   C_NAME {  moedef($1); }
650		|  C_TYPENAME {  moedef($1); }
651		|  C_NAME '=' e { enummer = con_e($3); moedef($1); }
652		|  C_TYPENAME '=' e { enummer = con_e($3); moedef($1); }
653		;
654
655struct_dcl:	   str_head '{' struct_dcl_list '}' {
656			NODE *p;
657
658			$$ = dclstruct($1);
659			if (pragma_allpacked) {
660				p = bdty(CALL, bdty(NAME, "packed"),
661				    bcon(pragma_allpacked));
662				$$->n_ap = attr_add($$->n_ap,gcc_attr_parse(p)); }
663		}
664		|  C_STRUCT attr_var C_NAME {
665			$$ = rstruct($3,$1);
666			uawarn($2, "struct_dcl");
667		}
668		|  C_STRUCT attr_var nmrec C_NAME {
669			$$ = cxxrstruct($1,$2,$3,$4);
670			uawarn($2, "struct_dcl");
671		}
672 /*COMPAT_GCC*/	|  str_head '{' '}' { $$ = dclstruct($1); }
673		;
674
675attr_var:	   {
676			NODE *q, *p;
677
678			p = pragma_aligned ? bdty(CALL, bdty(NAME, "aligned"),
679			    bcon(pragma_aligned)) : NIL;
680			if (pragma_packed) {
681				q = bdty(NAME, "packed");
682				p = (p == NIL ? q : cmop(p, q));
683			}
684			pragma_aligned = pragma_packed = 0;
685			$$ = p;
686		}
687 /*COMPAT_GCC*/	|  attr_spec_list
688		;
689
690attr_spec_list:	   attribute_specifier
691		|  attr_spec_list attribute_specifier { $$ = cmop($1, $2); }
692		;
693
694str_head:	   C_STRUCT attr_var {  $$ = bstruct(NULL, $1, $2);  }
695		|  C_STRUCT attr_var C_NAME {  $$ = bstruct($3, $1, $2);  }
696		;
697
698struct_dcl_list:   struct_declaration
699		|  struct_dcl_list struct_declaration
700		;
701
702struct_declaration:
703		   declaration_specifiers struct_declarator_list optsemi {
704			tfree($1);
705		}
706		|  C_NAME ':' { /* cxxaccess($1); */ }
707		;
708
709optsemi:	   ';' { }
710		|  optsemi ';' { werror("extra ; in struct"); }
711		;
712
713specifier_qualifier_list:
714		   merge_specifiers { $$ = typenode($1); }
715		;
716
717merge_specifiers:  type_sq merge_specifiers { $$ = cmop($2, $1); }
718		|  type_sq { $$ = $1; }
719		;
720
721struct_declarator_list:
722		   struct_declarator { symclear(blevel); }
723		|  struct_declarator_list ',' { $<nodep>$=$<nodep>0; }
724			struct_declarator { symclear(blevel); }
725		;
726
727struct_declarator: declarator attr_var {
728			NODE *p;
729
730			$1 = aryfix($1);
731			p = tymerge($<nodep>0, tymfix($1));
732			if ($2)
733				p->n_ap = attr_add(p->n_ap, gcc_attr_parse($2));
734			soumemb(p, (char *)$1->n_sp, $<nodep>0->n_lval);
735			tfree(p);
736		}
737		|  ':' e {
738			int ie = con_e($2);
739			if (fldchk(ie))
740				ie = 1;
741			falloc(NULL, ie, $<nodep>0);
742		}
743		|  declarator ':' e {
744			int ie = con_e($3);
745			if (fldchk(ie))
746				ie = 1;
747			if ($1->n_op == NAME) {
748				/* XXX - tymfix() may alter $1 */
749				tymerge($<nodep>0, tymfix($1));
750				soumemb($1, (char *)$1->n_sp, FIELD | ie);
751				nfree($1);
752			} else
753				uerror("illegal declarator");
754		}
755		|  declarator ':' e attr_spec_list {
756			int ie = con_e($3);
757			if (fldchk(ie))
758				ie = 1;
759			if ($1->n_op == NAME) {
760				/* XXX - tymfix() may alter $1 */
761				tymerge($<nodep>0, tymfix($1));
762				if ($4)
763					$1->n_ap = attr_add($1->n_ap,
764					    gcc_attr_parse($4));
765				soumemb($1, (char *)$1->n_sp, FIELD | ie);
766				nfree($1);
767			} else
768				uerror("illegal declarator");
769		}
770		| /* unnamed member */ {
771			NODE *p = $<nodep>0;
772			char *c = permalloc(10);
773
774			if (p->n_type != STRTY && p->n_type != UNIONTY)
775				uerror("bad unnamed member type");
776			snprintf(c, 10, "*%dFAKE", getlab());
777			soumemb(p, c, 0);
778		}
779		;
780
781		/* always preceeded by attributes */
782xnfdeclarator:	   declarator attr_var {
783			$$ = xnf = init_declarator($<nodep>0, $1, 1, $2);
784		}
785		|  declarator C_ASM '(' string ')' {
786			pragma_renamed = newstring($4, strlen($4));
787			$$ = xnf = init_declarator($<nodep>0, $1, 1, NULL);
788		}
789		;
790
791/*
792 * Handles declarations and assignments.
793 * Returns nothing.
794 */
795init_declarator:   declarator attr_var { init_declarator($<nodep>0, $1, 0, $2);}
796		|  declarator C_ASM '(' string ')' attr_var {
797#ifdef GCC_COMPAT
798			pragma_renamed = newstring($4, strlen($4));
799			init_declarator($<nodep>0, $1, 0, $6);
800#else
801			werror("gcc extension");
802			init_declarator($<nodep>0, $1, 0, $6);
803#endif
804		}
805		|  xnfdeclarator '=' e {
806			if ($1->sclass == STATIC || $1->sclass == EXTDEF)
807				statinit++;
808			simpleinit($1, eve($3));
809			if ($1->sclass == STATIC || $1->sclass == EXTDEF)
810				statinit--;
811			xnf = NULL;
812		}
813		|  xnfdeclarator '=' begbr init_list optcomma '}' {
814			endinit(0);
815			xnf = NULL;
816		}
817 /*COMPAT_GCC*/	|  xnfdeclarator '=' begbr '}' { endinit(0); xnf = NULL; }
818		|  xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
819		;
820
821begbr:		   '{' { beginit($<symp>-1); }
822		;
823
824initializer:	   e %prec ',' {  $$ = eve($1); }
825		|  addrlbl {  $$ = $1; }
826		|  ibrace init_list optcomma '}' { $$ = NULL; }
827		|  ibrace '}' { asginit(bcon(0)); $$ = NULL; }
828		;
829
830init_list:	   designation initializer { dainit($1, $2); }
831		|  init_list ','  designation initializer { dainit($3, $4); }
832		;
833
834designation:	   designator_list '=' { desinit($1); $$ = NIL; }
835		|  GCC_DESIG { desinit(bdty(NAME, $1)); $$ = NIL; }
836		|  '[' e C_ELLIPSIS e ']' '=' { $$ = biop(CM, $2, $4); }
837		|  { $$ = NIL; }
838		;
839
840designator_list:   designator { $$ = $1; }
841		|  designator_list designator { $$ = $2; $$->n_left = $1; }
842		;
843
844designator:	   '[' e ']' {
845			int ie = con_e($2);
846			if (ie < 0) {
847				uerror("designator must be non-negative");
848				ie = 0;
849			}
850			$$ = biop(LB, NIL, bcon(ie));
851		}
852		|  C_STROP C_TYPENAME {
853			if ($1 != DOT)
854				uerror("invalid designator");
855			$$ = bdty(NAME, $2);
856		}
857		|  C_STROP C_NAME {
858			if ($1 != DOT)
859				uerror("invalid designator");
860			$$ = bdty(NAME, $2);
861		}
862		;
863
864optcomma	:	/* VOID */
865		|  ','
866		;
867
868ibrace:		   '{' {  ilbrace(); }
869		;
870
871/*	STATEMENTS	*/
872
873compoundstmt:	   begin block_item_list '}' { flend(); }
874		|  begin '}' { flend(); }
875		;
876
877begin:		  '{' {
878			struct savbc *bc = tmpalloc(sizeof(struct savbc));
879			if (blevel == 1) {
880#ifdef STABS
881				if (gflag)
882					stabs_line(lineno);
883#endif
884				dclargs();
885			}
886#ifdef STABS
887			if (gflag && blevel > 1)
888				stabs_lbrac(blevel+1);
889#endif
890			++blevel;
891			oldstyle = 0;
892			bc->contlab = autooff;
893			bc->next = savctx;
894			savctx = bc;
895			if (!isinlining && sspflag && blevel == 2)
896				sspstart();
897		}
898		;
899
900statement:	   e ';' { /* fwalk($1, eprint, 0); */ ecomp(eve($1)); symclear(blevel); }
901		|  compoundstmt
902		|  ifprefix statement { plabel($1); reached = 1; }
903		|  ifelprefix statement {
904			if ($1 != NOLAB) {
905				plabel( $1);
906				reached = 1;
907			}
908		}
909		|  whprefix statement {
910			branch(contlab);
911			plabel( brklab );
912			if( (flostat&FBRK) || !(flostat&FLOOP))
913				reached = 1;
914			else
915				reached = 0;
916			resetbc(0);
917		}
918		|  doprefix statement C_WHILE '(' e ')' ';' {
919			plabel(contlab);
920			if (flostat & FCONT)
921				reached = 1;
922			if (reached)
923				cbranch(buildtree(NE, eve($5), bcon(0)),
924				    bcon($1));
925			else
926				tfree(eve($5));
927			plabel( brklab);
928			reached = 1;
929			resetbc(0);
930		}
931		|  forprefix .e ')' statement
932			{  plabel( contlab );
933			    if( flostat&FCONT ) reached = 1;
934			    if( $2 ) ecomp( $2 );
935			    branch($1);
936			    plabel( brklab );
937			    if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
938			    else reached = 0;
939			    resetbc(0);
940			    symclear(blevel); /* if declaration inside for() */
941			    }
942		| switchpart statement
943			{ if( reached ) branch( brklab );
944			    plabel( $1 );
945			    swend();
946			    plabel( brklab);
947			    if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
948			    resetbc(FCONT);
949			    }
950		|  C_BREAK  ';' {
951			if (brklab == NOLAB)
952				uerror("illegal break");
953			else if (reached)
954				branch(brklab);
955			flostat |= FBRK;
956			reached = 0;
957		}
958		|  C_CONTINUE  ';' {
959			if (contlab == NOLAB)
960				uerror("illegal continue");
961			else
962				branch(contlab);
963			flostat |= FCONT;
964			goto rch;
965		}
966		|  C_RETURN  ';' {
967			branch(retlab);
968			if (cftnsp->stype != VOID &&
969			    (cftnsp->sflags & NORETYP) == 0 &&
970			    cftnsp->stype != VOID+FTN)
971				uerror("return value required");
972			rch:
973			if (!reached)
974				warner(Wunreachable_code, NULL);
975			reached = 0;
976		}
977		|  C_RETURN e  ';' {
978			NODE *p, *q;
979
980			p = nametree(cftnsp);
981			p->n_type = DECREF(p->n_type);
982			q = eve($2);
983#ifndef NO_COMPLEX
984			if (ANYCX(q) || ANYCX(p))
985				q = cxret(q, p);
986#endif
987			p = buildtree(RETURN, p, q);
988			if (p->n_type == VOID) {
989				ecomp(p->n_right);
990			} else {
991				if (cftnod == NIL)
992					cftnod = tempnode(0, p->n_type,
993					    p->n_df, p->n_ap);
994				ecomp(buildtree(ASSIGN,
995				    ccopy(cftnod), p->n_right));
996			}
997			tfree(p->n_left);
998			nfree(p);
999			branch(retlab);
1000			reached = 0;
1001		}
1002		|  C_GOTO C_NAME ';' { gotolabel($2); goto rch; }
1003		|  C_GOTO '*' e ';' { ecomp(biop(GOTO, eve($3), NIL)); }
1004		|  asmstatement ';'
1005		|   ';'
1006		|  error  ';'
1007		|  error '}'
1008		|  label statement
1009		;
1010
1011asmstatement:	   C_ASM mvol '(' string ')' { send_passt(IP_ASM, mkpstr($4)); }
1012		|  C_ASM mvol '(' string xasm ')' { mkxasm($4, $5); }
1013		;
1014
1015mvol:		   /* empty */
1016		|  C_QUALIFIER { nfree($1); }
1017		;
1018
1019xasm:		   ':' oplist { $$ = xcmop($2, NIL, NIL); }
1020		|  ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); }
1021		|  ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); }
1022		;
1023
1024oplist:		   /* nothing */ { $$ = NIL; }
1025		|  oper { $$ = $1; }
1026		;
1027
1028oper:		   string '(' e ')' { $$ = xasmop($1, eve($3)); }
1029		|  oper ',' string '(' e ')' {
1030			$$ = cmop($1, xasmop($3, eve($5)));
1031		}
1032		;
1033
1034cnstr:		   string { $$ = xasmop($1, bcon(0)); }
1035		|  cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); }
1036                ;
1037
1038label:		   C_NAME ':' attr_var { deflabel($1, $3); reached = 1; }
1039		|  C_TYPENAME ':' attr_var { deflabel($1, $3); reached = 1; }
1040		|  C_CASE e ':' { addcase(eve($2)); reached = 1; }
1041/* COMPAT_GCC */|  C_CASE e C_ELLIPSIS e ':' {
1042#ifdef GCC_COMPAT
1043			gcccase(eve($2), eve($4)); reached = 1;
1044#endif
1045		}
1046		|  C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
1047		;
1048
1049doprefix:	C_DO {
1050			savebc();
1051			brklab = getlab();
1052			contlab = getlab();
1053			plabel(  $$ = getlab());
1054			reached = 1;
1055		}
1056		;
1057ifprefix:	C_IF '(' e ')' {
1058			cbranch(buildtree(NOT, eve($3), NIL), bcon($$ = getlab()));
1059			reached = 1;
1060		}
1061		;
1062ifelprefix:	  ifprefix statement C_ELSE {
1063			if (reached)
1064				branch($$ = getlab());
1065			else
1066				$$ = NOLAB;
1067			plabel( $1);
1068			reached = 1;
1069		}
1070		;
1071
1072whprefix:	  C_WHILE  '('  e  ')' {
1073			savebc();
1074			$3 = eve($3);
1075			if ($3->n_op == ICON && $3->n_lval != 0)
1076				flostat = FLOOP;
1077			plabel( contlab = getlab());
1078			reached = 1;
1079			brklab = getlab();
1080			if (flostat == FLOOP)
1081				tfree($3);
1082			else
1083				cbranch(buildtree(NOT, $3, NIL), bcon(brklab));
1084		}
1085		;
1086forprefix:	  C_FOR  '('  .e  ';' .e  ';' {
1087			if ($3)
1088				ecomp($3);
1089			savebc();
1090			contlab = getlab();
1091			brklab = getlab();
1092			plabel( $$ = getlab());
1093			reached = 1;
1094			if ($5)
1095				cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
1096			else
1097				flostat |= FLOOP;
1098		}
1099		|  C_FOR '(' { ++blevel; } declaration .e ';' {
1100			blevel--;
1101			savebc();
1102			contlab = getlab();
1103			brklab = getlab();
1104			plabel( $$ = getlab());
1105			reached = 1;
1106			if ($5)
1107				cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
1108			else
1109				flostat |= FLOOP;
1110		}
1111		;
1112
1113switchpart:	   C_SWITCH  '('  e ')' {
1114			NODE *p;
1115			int num;
1116			TWORD t;
1117
1118			savebc();
1119			brklab = getlab();
1120			$3 = eve($3);
1121			if (!ISINTEGER($3->n_type)) {
1122				uerror("switch expression must have integer "
1123				       "type");
1124				t = INT;
1125			} else {
1126				$3 = intprom($3);
1127				t = $3->n_type;
1128			}
1129			p = tempnode(0, t, 0, 0);
1130			num = regno(p);
1131			ecomp(buildtree(ASSIGN, p, $3));
1132			branch( $$ = getlab());
1133			swstart(num, t);
1134			reached = 0;
1135		}
1136		;
1137/*	EXPRESSIONS	*/
1138.e:		   e { $$ = eve($1); }
1139		| 	{ $$=0; }
1140		;
1141
1142elist:		   { $$ = NIL; }
1143		|  e %prec ','
1144		|  elist  ','  e { $$ = biop(CM, $1, $3); }
1145		|  elist  ','  cast_type { /* hack for stdarg */
1146			TYMFIX($3);
1147			$3->n_op = TYPE;
1148			$$ = biop(CM, $1, $3);
1149		}
1150		;
1151
1152/*
1153 * Precedence order of operators.
1154 */
1155e:		   e ',' e { $$ = biop(COMOP, $1, $3); }
1156		|  e '=' e { $$ = biop(ASSIGN, $1, $3); }
1157		|  e C_ASOP e { $$ = biop($2, $1, $3); }
1158		|  e '?' e ':' e {
1159			$$=biop(QUEST, $1, biop(COLON, $3, $5));
1160		}
1161		|  e '?' ':' e {
1162			NODE *p = tempnode(0, $1->n_type, $1->n_df, $1->n_ap);
1163			$$ = biop(COLON, ccopy(p), $4);
1164			$$=biop(QUEST, biop(ASSIGN, p, $1), $$);
1165		}
1166		|  e C_OROR e { $$ = biop($2, $1, $3); }
1167		|  e C_ANDAND e { $$ = biop($2, $1, $3); }
1168		|  e '|' e { $$ = biop(OR, $1, $3); }
1169		|  e '^' e { $$ = biop(ER, $1, $3); }
1170		|  e '&' e { $$ = biop(AND, $1, $3); }
1171		|  e C_EQUOP  e { $$ = biop($2, $1, $3); }
1172		|  e C_RELOP e { $$ = biop($2, $1, $3); }
1173		|  e C_SHIFTOP e { $$ = biop($2, $1, $3); }
1174		|  e '+' e { $$ = biop(PLUS, $1, $3); }
1175		|  e '-' e { $$ = biop(MINUS, $1, $3); }
1176		|  e C_DIVOP e { $$ = biop($2, $1, $3); }
1177		|  e '*' e { $$ = biop(MUL, $1, $3); }
1178		|  e '=' addrlbl { $$ = biop(ASSIGN, $1, $3); }
1179		|  term
1180		;
1181
1182xbegin:		   begin {
1183			$$ = getlab(); getlab(); getlab();
1184			branch($$); plabel(($$)+1); }
1185		;
1186
1187addrlbl:	  C_ANDAND C_NAME {
1188#ifdef GCC_COMPAT
1189			struct symtab *s = lookup($2, SLBLNAME);
1190			if (s->soffset == 0)
1191				s->soffset = -getlab();
1192			$$ = buildtree(ADDROF, nametree(s), NIL);
1193#else
1194			uerror("gcc extension");
1195#endif
1196		}
1197		;
1198
1199term:		   term C_INCOP {  $$ = biop($2, $1, bcon(1)); }
1200		|  '*' term { $$ = biop(UMUL, $2, NIL); }
1201		|  '&' term { $$ = biop(ADDROF, $2, NIL); }
1202		|  '-' term { $$ = biop(UMINUS, $2, NIL ); }
1203		|  '+' term { $$ = biop(PLUS, $2, bcon(0)); }
1204		|  CXX_CASTS C_RELOP cast_type C_RELOP '(' e ')' {
1205			tfree($6);
1206			tfree($3);
1207			$$ = bcon(0);
1208			werror("CXX_CASTS unhandled");
1209		}
1210		|  C_UNOP term { $$ = biop($1, $2, NIL); }
1211		|  C_INCOP term {
1212			$$ = biop($1 == INCR ? PLUSEQ : MINUSEQ, $2, bcon(1));
1213		}
1214		|  C_SIZEOF xa term { $$ = biop(SZOF, $3, bcon(0)); inattr = $<intval>2; }
1215		|  '(' cast_type ')' term  %prec C_INCOP {
1216			TYMFIX($2);
1217			$$ = biop(CAST, $2, $4);
1218		}
1219		|  C_SIZEOF xa '(' cast_type ')'  %prec C_SIZEOF {
1220			$$ = biop(SZOF, $4, bcon(1));
1221			inattr = $<intval>2;
1222		}
1223		|  C_ALIGNOF xa '(' cast_type ')' {
1224			int al;
1225			TYMFIX($4);
1226			al = talign($4->n_type, $4->n_ap);
1227			$$ = bcon(al/SZCHAR);
1228			inattr = $<intval>2;
1229			tfree($4);
1230		}
1231		| '(' cast_type ')' clbrace init_list optcomma '}' {
1232			endinit(0);
1233			$$ = bdty(NAME, $4);
1234			$$->n_op = CLOP;
1235		}
1236		| '(' cast_type ')' clbrace '}' {
1237			endinit(0);
1238			$$ = bdty(NAME, $4);
1239			$$->n_op = CLOP;
1240		}
1241		|  term '[' e ']' {
1242			if ($1->n_op == NEWKW) {
1243				$1->n_left = biop(LB, $1->n_left, $3);
1244			} else
1245				$$ = biop(LB, $1, $3);
1246		}
1247		|  C_NAME  '(' elist ')' {
1248#if 0
1249			if ($3) tfree($3);
1250			$$ = bcon(0);
1251#else
1252			$$ = biop($3 ? CALL : UCALL, bdty(NAME, $1), $3);
1253#endif
1254		}
1255		|  term  '(' elist ')' { $$ = biop($3 ? CALL : UCALL, $1, $3); }
1256		|  term C_STROP C_NAME { $$ = biop($2, $1, bdty(NAME, $3)); }
1257		|  term C_STROP C_TYPENAME { $$ = biop($2, $1, bdty(NAME, $3));}
1258		|  C_NAME %prec C_SIZEOF /* below ( */{ $$ = bdty(NAME, $1); }
1259		|  nmrec C_NAME %prec C_SIZEOF {
1260			$$ = biop(NMLIST, $1, bdty(NAME, $2));
1261		}
1262		|  PCC_OFFSETOF  '(' cast_type ',' term ')' {
1263			TYMFIX($3);
1264			$3->n_type = INCREF($3->n_type);
1265			$3 = biop(CAST, $3, bcon(0));
1266			if ($5->n_op == NAME) {
1267				$$ = biop(STREF, $3, $5);
1268			} else {
1269				NODE *p = $5;
1270				while (p->n_left->n_op != NAME)
1271					p = p->n_left;
1272				p->n_left = biop(STREF, $3, p->n_left);
1273				$$ = $5;
1274			}
1275			$$ = biop(ADDROF, $$, NIL);
1276			$3 = block(NAME, NIL, NIL, ENUNSIGN(INTPTR), 0, 0);
1277			$$ = biop(CAST, $3, $$);
1278		}
1279		|  C_ICON { $$ = $1; }
1280		|  C_FCON { $$ = $1; }
1281		|  string { $$ = bdty(STRING, $1, widestr); }
1282		|   '('  e  ')' { $$=$2; }
1283		|  '(' xbegin block_item_list e ';' '}' ')' {
1284			/* XXX - check recursive ({ }) statements */
1285			branch(($2)+2);
1286			plabel($2);
1287			$$ = buildtree(COMOP,
1288			    biop(GOTO, bcon(($2)+1), NIL), eve($4));
1289			flend();
1290		}
1291		|  '(' xbegin block_item_list '}' ')' {
1292			/* XXX - check recursive ({ }) statements */
1293			branch(($2)+2);
1294			plabel($2);
1295			$$ = buildtree(COMOP,
1296			    biop(GOTO, bcon(($2)+1), NIL), voidcon());
1297			flend();
1298		}
1299		|  CXX_NEW new_ds { $$ = biop(NEWKW, $2, bcon(0)); }
1300		|  CXX_NEW '(' cast_type ')' { $$ = 0; uerror("new cast"); }
1301		|  CXX_DELETE term %prec '-' {
1302			$$ = biop(DELETE, $2, bcon(NM_DEL));
1303		}
1304		|  CXX_DELETE '[' ']' term %prec '-' {
1305			$$ = biop(DELETE, $4, bcon(NM_DLA));
1306		}
1307		;
1308
1309nmrec:		  CXX_MORENM { $$ = bdty(NAME, $1); }
1310		| CXX_MORENM nmrec { $$ = biop(NMLIST, $2, bdty(NAME, $1)); }
1311		;
1312
1313xa:		  { $<intval>$ = inattr; inattr = 0; }
1314		;
1315
1316clbrace:	   '{'	{ NODE *q = $<nodep>-1; TYMFIX(q); $$ = clbrace(q); }
1317		;
1318
1319string:		   C_STRING { widestr = 0; $$ = stradd("", $1); }
1320		|  string C_STRING { $$ = stradd($1, $2); }
1321		;
1322
1323cast_type:	   specifier_qualifier_list {
1324			$$ = biop(TYMERGE, $1, bdty(NAME, NULL));
1325		}
1326		|  specifier_qualifier_list abstract_declarator {
1327			$$ = biop(TYMERGE, $1, aryfix($2));
1328		}
1329		;
1330
1331%%
1332
1333NODE *
1334mkty(TWORD t, union dimfun *d, struct attr *sue)
1335{
1336	return block(TYPE, NIL, NIL, t, d, sue);
1337}
1338
1339NODE *
1340bdty(int op, ...)
1341{
1342	va_list ap;
1343	int val;
1344	register NODE *q;
1345
1346	va_start(ap, op);
1347	q = biop(op, NIL, NIL);
1348
1349	switch (op) {
1350	case UMUL:
1351	case UCALL:
1352		q->n_left = va_arg(ap, NODE *);
1353		q->n_rval = 0;
1354		break;
1355
1356	case CALL:
1357		q->n_left = va_arg(ap, NODE *);
1358		q->n_right = va_arg(ap, NODE *);
1359		break;
1360
1361	case LB:
1362		q->n_left = va_arg(ap, NODE *);
1363		if ((val = va_arg(ap, int)) <= 0) {
1364			uerror("array size must be positive");
1365			val = 1;
1366		}
1367		q->n_right = bcon(val);
1368		break;
1369
1370	case NAME:
1371		q->n_sp = va_arg(ap, struct symtab *); /* XXX survive tymerge */
1372		break;
1373
1374	case STRING:
1375		q->n_name = va_arg(ap, char *);
1376		q->n_lval = va_arg(ap, int);
1377		break;
1378
1379	default:
1380		cerror("bad bdty");
1381	}
1382	va_end(ap);
1383
1384	return q;
1385}
1386
1387static void
1388flend(void)
1389{
1390	if (!isinlining && sspflag && blevel == 2)
1391		sspend();
1392#ifdef STABS
1393	if (gflag && blevel > 2)
1394		stabs_rbrac(blevel);
1395#endif
1396	--blevel;
1397	if( blevel == 1 )
1398		blevel = 0;
1399	symclear(blevel); /* Clean ut the symbol table */
1400	if (autooff > maxautooff)
1401		maxautooff = autooff;
1402	autooff = savctx->contlab;
1403	savctx = savctx->next;
1404}
1405
1406static void
1407savebc(void)
1408{
1409	struct savbc *bc = tmpalloc(sizeof(struct savbc));
1410
1411	bc->brklab = brklab;
1412	bc->contlab = contlab;
1413	bc->flostat = flostat;
1414	bc->next = savbc;
1415	savbc = bc;
1416	flostat = 0;
1417}
1418
1419static void
1420resetbc(int mask)
1421{
1422	flostat = savbc->flostat | (flostat&mask);
1423	contlab = savbc->contlab;
1424	brklab = savbc->brklab;
1425	savbc = savbc->next;
1426}
1427
1428struct swdef {
1429	struct swdef *next;	/* Next in list */
1430	int deflbl;		/* Label for "default" */
1431	struct swents *ents;	/* Linked sorted list of case entries */
1432	int nents;		/* # of entries in list */
1433	int num;		/* Node value will end up in */
1434	TWORD type;		/* Type of switch expression */
1435} *swpole;
1436
1437/*
1438 * add case to switch
1439 */
1440static void
1441addcase(NODE *p)
1442{
1443	struct swents **put, *w, *sw = tmpalloc(sizeof(struct swents));
1444	CONSZ val;
1445
1446	p = optim(rmpconv(p));  /* change enum to ints */
1447	if (p->n_op != ICON || p->n_sp != NULL) {
1448		uerror( "non-constant case expression");
1449		return;
1450	}
1451	if (swpole == NULL) {
1452		uerror("case not in switch");
1453		return;
1454	}
1455
1456	if (DEUNSIGN(swpole->type) != DEUNSIGN(p->n_type)) {
1457		val = p->n_lval;
1458		p = makety(p, swpole->type, 0, 0, 0);
1459		if (p->n_op != ICON)
1460			cerror("could not cast case value to type of switch "
1461			       "expression");
1462		if (p->n_lval != val)
1463			werror("case expression truncated");
1464	}
1465	sw->sval = p->n_lval;
1466	tfree(p);
1467	put = &swpole->ents;
1468	if (ISUNSIGNED(swpole->type)) {
1469		for (w = swpole->ents;
1470		     w != NULL && (U_CONSZ)w->sval < (U_CONSZ)sw->sval;
1471		     w = w->next)
1472			put = &w->next;
1473	} else {
1474		for (w = swpole->ents; w != NULL && w->sval < sw->sval;
1475		     w = w->next)
1476			put = &w->next;
1477	}
1478	if (w != NULL && w->sval == sw->sval) {
1479		uerror("duplicate case in switch");
1480		return;
1481	}
1482	plabel(sw->slab = getlab());
1483	*put = sw;
1484	sw->next = w;
1485	swpole->nents++;
1486}
1487
1488#ifdef GCC_COMPAT
1489void
1490gcccase(NODE *ln, NODE *hn)
1491{
1492	CONSZ i, l, h;
1493
1494	l = icons(optim(ln));
1495	h = icons(optim(hn));
1496
1497	if (h < l)
1498		i = l, l = h, h = i;
1499
1500	for (i = l; i <= h; i++)
1501		addcase(xbcon(i, NULL, hn->n_type));
1502}
1503#endif
1504
1505/*
1506 * add default case to switch
1507 */
1508static void
1509adddef(void)
1510{
1511	if (swpole == NULL)
1512		uerror("default not inside switch");
1513	else if (swpole->deflbl != 0)
1514		uerror("duplicate default in switch");
1515	else
1516		plabel( swpole->deflbl = getlab());
1517}
1518
1519static void
1520swstart(int num, TWORD type)
1521{
1522	struct swdef *sw = tmpalloc(sizeof(struct swdef));
1523
1524	sw->deflbl = sw->nents = 0;
1525	sw->ents = NULL;
1526	sw->next = swpole;
1527	sw->num = num;
1528	sw->type = type;
1529	swpole = sw;
1530}
1531
1532/*
1533 * end a switch block
1534 */
1535static void
1536swend(void)
1537{
1538	struct swents *sw, **swp;
1539	int i;
1540
1541	sw = tmpalloc(sizeof(struct swents));
1542	swp = tmpalloc(sizeof(struct swents *) * (swpole->nents+1));
1543
1544	sw->slab = swpole->deflbl;
1545	swp[0] = sw;
1546
1547	for (i = 1; i <= swpole->nents; i++) {
1548		swp[i] = swpole->ents;
1549		swpole->ents = swpole->ents->next;
1550	}
1551	genswitch(swpole->num, swpole->type, swp, swpole->nents);
1552
1553	swpole = swpole->next;
1554}
1555
1556/*
1557 * num: tempnode the value of the switch expression is in
1558 * type: type of the switch expression
1559 *
1560 * p points to an array of structures, each consisting
1561 * of a constant value and a label.
1562 * The first is >=0 if there is a default label;
1563 * its value is the label number
1564 * The entries p[1] to p[n] are the nontrivial cases
1565 * n is the number of case statements (length of list)
1566 */
1567static void
1568genswitch(int num, TWORD type, struct swents **p, int n)
1569{
1570	NODE *r, *q;
1571	int i;
1572
1573	if (mygenswitch(num, type, p, n))
1574		return;
1575
1576	/* simple switch code */
1577	for (i = 1; i <= n; ++i) {
1578		/* already in 1 */
1579		r = tempnode(num, type, 0, 0);
1580		q = xbcon(p[i]->sval, NULL, type);
1581		r = buildtree(NE, r, clocal(q));
1582		cbranch(buildtree(NOT, r, NIL), bcon(p[i]->slab));
1583	}
1584	if (p[0]->slab > 0)
1585		branch(p[0]->slab);
1586}
1587
1588/*
1589 * Declare a variable or prototype.
1590 */
1591static struct symtab *
1592init_declarator(NODE *tn, NODE *p, int assign, NODE *a)
1593{
1594	int class = tn->n_lval;
1595	struct symtab *sp;
1596
1597	p = aryfix(p);
1598	if (p->n_op == NMLIST) {
1599		tymerge(tn, p->n_right);
1600	} else
1601		p = tymerge(tn, p);
1602	if (a) {
1603		struct attr *ap = gcc_attr_parse(a);
1604		p->n_ap = attr_add(p->n_ap, ap);
1605	}
1606
1607	sp = cxxdeclvar(p);
1608
1609	if (fun_inline && ISFTN(p->n_type))
1610		sp->sflags |= SINLINE;
1611
1612	if (ISFTN(p->n_type) == 0) {
1613		if (assign) {
1614			defid(p, class);
1615			sp = p->n_sp;
1616			sp->sflags |= SASG;
1617			if (sp->sflags & SDYNARRAY)
1618				uerror("can't initialize dynamic arrays");
1619			lcommdel(sp);
1620		} else
1621			nidcl(p, class);
1622	} else {
1623		extern NODE *parlink;
1624		if (assign)
1625			uerror("cannot initialise function");
1626		defid(p, uclass(class));
1627		sp = p->n_sp;
1628		if (parlink) {
1629			/* dynamic sized arrays in prototypes */
1630			tfree(parlink); /* Free delayed tree */
1631			parlink = NIL;
1632		}
1633	}
1634	tfree(p);
1635	return sp;
1636}
1637
1638/*
1639 * Declare old-stype function arguments.
1640 */
1641static void
1642oldargs(NODE *p)
1643{
1644	blevel++;
1645	p->n_op = TYPE;
1646	p->n_type = FARG;
1647	p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */
1648	defid(p, PARAM);
1649	blevel--;
1650}
1651
1652/*
1653 * Set NAME nodes to a null name and index of LB nodes to NOOFFSET
1654 * unless clr is one, in that case preserve variable name.
1655 */
1656static NODE *
1657namekill(NODE *p, int clr)
1658{
1659	NODE *q;
1660	int o = p->n_op;
1661
1662	switch (coptype(o)) {
1663	case LTYPE:
1664		if (o == NAME) {
1665			if (clr)
1666				p->n_sp = NULL;
1667			else
1668				p->n_sp = lookup((char *)p->n_sp, 0);/* XXX */
1669		}
1670		break;
1671
1672	case UTYPE:
1673		p->n_left = namekill(p->n_left, clr);
1674		break;
1675
1676        case BITYPE:
1677                p->n_left = namekill(p->n_left, clr);
1678		if (o == LB) {
1679			if (clr) {
1680				tfree(p->n_right);
1681				p->n_right = bcon(NOOFFSET);
1682			} else
1683				p->n_right = eve(p->n_right);
1684		} else if (o == CALL)
1685			p->n_right = namekill(p->n_right, 1);
1686		else
1687			p->n_right = namekill(p->n_right, clr);
1688		if (o == TYMERGE) {
1689			q = tymerge(p->n_left, p->n_right);
1690			q->n_ap = attr_add(q->n_ap, p->n_ap);
1691			tfree(p->n_left);
1692			nfree(p);
1693			p = q;
1694		}
1695		break;
1696	}
1697	return p;
1698}
1699
1700/*
1701 * Declare function arguments.
1702 */
1703static NODE *
1704funargs(NODE *p)
1705{
1706	extern NODE *arrstk[10];
1707
1708	if (p->n_op == ELLIPSIS)
1709		return p;
1710
1711	p = namekill(p, 0);
1712	if (ISFTN(p->n_type))
1713		p->n_type = INCREF(p->n_type);
1714	if (ISARY(p->n_type)) {
1715		p->n_type += (PTR-ARY);
1716		if (p->n_df->ddim == -1)
1717			tfree(arrstk[0]), arrstk[0] = NIL;
1718		p->n_df++;
1719	}
1720	if (p->n_type == VOID && p->n_sp->sname == NULL)
1721		return p; /* sanitycheck later */
1722	else if (p->n_sp->sname == NULL)
1723		; /* uerror("argument missing"); */
1724	else
1725		defid(p, PARAM);
1726	return p;
1727}
1728
1729static NODE *
1730listfw(NODE *p, NODE * (*f)(NODE *))
1731{
1732        if (p->n_op == CM) {
1733                p->n_left = listfw(p->n_left, f);
1734                p->n_right = (*f)(p->n_right);
1735        } else
1736                p = (*f)(p);
1737	return p;
1738}
1739
1740
1741/*
1742 * Declare a function.
1743 */
1744static struct symtab *
1745fundef(NODE *tp, NODE *p)
1746{
1747	extern int prolab;
1748	struct symtab *s, *nsthis;
1749	NODE *q, *typ;
1750	int class = tp->n_lval, oclass, ctval;
1751	char *c;
1752
1753	/*
1754	 * We discard all names except for those needed for
1755	 * parameter declaration. While doing that, also change
1756	 * non-constant array sizes to unknown.
1757	 */
1758	ctval = tvaloff;
1759	for (q = p; coptype(q->n_op) != LTYPE &&
1760	    q->n_left->n_op != NAME &&
1761	    q->n_left->n_op != NMLIST; q = q->n_left) {
1762		if (q->n_op == CALL)
1763			q->n_right = namekill(q->n_right, 1);
1764	}
1765	if (q->n_op != CALL && q->n_op != UCALL) {
1766		uerror("invalid function definition");
1767		p = bdty(UCALL, p);
1768	} else if (q->n_op == CALL) {
1769		blevel = 1;
1770		argoff = ARGINIT;
1771		if (oldstyle == 0)
1772			q->n_right = listfw(q->n_right, funargs);
1773		ftnarg(q);
1774		blevel = 0;
1775	}
1776
1777	if (p->n_op == CALL && p->n_left->n_op == NMLIST) {
1778		NODE *r = p->n_left;
1779		p->n_left = r->n_right;
1780		r->n_right = typ = tymerge(tp, p);
1781		p = r;
1782	} else
1783		typ = tymerge(tp, p);
1784
1785#ifdef GCC_COMPAT
1786	/* gcc seems to discard __builtin_ when declaring functions */
1787	if (strncmp("__builtin_", (char *)typ->n_sp, 10) == 0)
1788		typ->n_sp = (struct symtab *)((char *)typ->n_sp + 10);
1789#endif
1790
1791	s = cxxftnfind(p, SNORMAL);
1792	nsthis = nscur;
1793	nscur = s->sdown; /* XXX fun in fun? */
1794
1795	oclass = s->sclass;
1796	if (class == STATIC && oclass == EXTERN)
1797		werror("%s was first declared extern, then static", s->sname);
1798
1799	if (fun_inline) {
1800		/* special syntax for inline functions */
1801		if (! strcmp(s->sname,"main"))
1802			uerror("cannot inline main()");
1803
1804		s->sflags |= SINLINE;
1805		inline_start(s);
1806		if (class == EXTERN)
1807			class = EXTDEF;
1808	} else if (class == EXTERN)
1809		class = SNULL; /* same result */
1810
1811	cftnsp = s;
1812#if 0
1813	defid(p, class);
1814#endif
1815
1816#ifdef GCC_COMPAT
1817	if (attr_find(p->n_ap, GCC_ATYP_ALW_INL)) {
1818		/* Temporary turn on temps to make always_inline work */
1819		alwinl = 1;
1820		if (xtemps == 0) alwinl |= 2;
1821		xtemps = 1;
1822	}
1823#endif
1824	prolab = getlab();
1825	if ((c = cftnsp->soname) == NULL)
1826		c = addname(exname(cftnsp->sname));
1827	send_passt(IP_PROLOG, -1, c, cftnsp->stype,
1828	    cftnsp->sclass == EXTDEF, prolab, ctval);
1829	blevel++;
1830#ifdef STABS
1831	if (gflag)
1832		stabs_func(s);
1833#endif
1834	tfree(tp);
1835	tfree(p);
1836	return nsthis;
1837}
1838
1839static void
1840fend(struct symtab *ns)
1841{
1842	if (blevel)
1843		cerror("function level error");
1844	ftnend();
1845	fun_inline = 0;
1846	if (alwinl & 2) xtemps = 0;
1847	alwinl = 0;
1848	cftnsp = NULL;
1849	nscur = ns;
1850}
1851
1852NODE *
1853structref(NODE *p, int f, char *name)
1854{
1855	NODE *r;
1856
1857	if (f == DOT)
1858		p = buildtree(ADDROF, p, NIL);
1859	r = biop(NAME, NIL, NIL);
1860	r->n_name = name;
1861	r = buildtree(STREF, p, r);
1862	return r;
1863}
1864
1865static void
1866olddecl(NODE *p, NODE *a)
1867{
1868	struct symtab *s;
1869
1870	p = namekill(p, 0);
1871	s = p->n_sp;
1872	if (s->slevel != 1 || s->stype == UNDEF)
1873		uerror("parameter '%s' not defined", s->sname);
1874	else if (s->stype != FARG)
1875		uerror("parameter '%s' redefined", s->sname);
1876
1877	s->stype = p->n_type;
1878	s->sdf = p->n_df;
1879	s->sap = p->n_ap;
1880	if (ISARY(s->stype)) {
1881		s->stype += (PTR-ARY);
1882		s->sdf++;
1883	} else if (s->stype == FLOAT)
1884		s->stype = DOUBLE;
1885	if (a)
1886		attr_add(s->sap, gcc_attr_parse(a));
1887	nfree(p);
1888}
1889
1890void
1891branch(int lbl)
1892{
1893	int r = reached++;
1894	ecomp(biop(GOTO, bcon(lbl), NIL));
1895	reached = r;
1896}
1897
1898/*
1899 * Create a printable string based on an encoded string.
1900 */
1901static char *
1902mkpstr(char *str)
1903{
1904	char *s, *os;
1905	int v, l = strlen(str)+3; /* \t + \n + \0 */
1906
1907	os = s = inlalloc(l);
1908	*s++ = '\t';
1909	for (; *str; ) {
1910		if (*str++ == '\\')
1911			v = esccon(&str);
1912		else
1913			v = str[-1];
1914		*s++ = v;
1915	}
1916	*s++ = '\n';
1917	*s = 0;
1918	return os;
1919}
1920
1921/*
1922 * Estimate the max length a string will have in its internal
1923 * representation based on number of \ characters.
1924 */
1925static int
1926maxstlen(char *str)
1927{
1928	int i;
1929
1930	for (i = 0; *str; str++, i++)
1931		if (*str == '\\' || *str < 32 || *str > 0176)
1932			i += 3;
1933	return i;
1934}
1935
1936static char *
1937voct(char *d, unsigned int v)
1938{
1939	v &= (1 << SZCHAR) - 1;
1940	*d++ = '\\';
1941	*d++ = v/64 + '0'; v &= 077;
1942	*d++ = v/8 + '0'; v &= 7;
1943	*d++ = v + '0';
1944	return d;
1945}
1946
1947
1948/*
1949 * Convert a string to internal format.  The resulting string may be no
1950 * more than len characters long.
1951 */
1952static void
1953fixstr(char *d, char *s, int len)
1954{
1955	unsigned int v;
1956
1957	while (*s) {
1958		if (len <= 0)
1959			cerror("fixstr");
1960		if (*s == '\\') {
1961			s++;
1962			v = esccon(&s);
1963			d = voct(d, v);
1964			len -= 4;
1965		} else if (*s < ' ' || *s > 0176) {
1966			d = voct(d, *s++);
1967			len -= 4;
1968		} else
1969			*d++ = *s++, len--;
1970	}
1971	*d = 0;
1972}
1973
1974/*
1975 * Add "raw" string new to cleaned string old.
1976 */
1977static char *
1978stradd(char *old, char *new)
1979{
1980	char *rv;
1981	int len;
1982
1983	if (*new == 'L' && new[1] == '\"')
1984		widestr = 1, new++;
1985	if (*new == '\"') {
1986		new++;			 /* remove first " */
1987		new[strlen(new) - 1] = 0;/* remove last " */
1988	}
1989	len = strlen(old) + maxstlen(new) + 1;
1990	rv = tmpalloc(len);
1991	strlcpy(rv, old, len);
1992	fixstr(rv + strlen(old), new, maxstlen(new) + 1);
1993	return rv;
1994}
1995
1996/*
1997 * Fake a symtab entry for compound literals.
1998 */
1999static struct symtab *
2000clbrace(NODE *p)
2001{
2002	struct symtab *sp;
2003
2004	sp = getsymtab(simname("cl"), STEMP);
2005	sp->stype = p->n_type;
2006	sp->squal = p->n_qual;
2007	sp->sdf = p->n_df;
2008	sp->sap = p->n_ap;
2009	tfree(p);
2010	if (blevel == 0 && xnf != NULL) {
2011		sp->sclass = STATIC;
2012		sp->slevel = 2;
2013		sp->soffset = getlab();
2014	} else {
2015		sp->sclass = blevel ? AUTO : STATIC;
2016		if (!ISARY(sp->stype) || sp->sdf->ddim != NOOFFSET) {
2017			sp->soffset = NOOFFSET;
2018			oalloc(sp, &autooff);
2019		}
2020	}
2021	beginit(sp);
2022	return sp;
2023}
2024
2025char *
2026simname(char *s)
2027{
2028	int len = strlen(s) + 10 + 1;
2029	char *w = tmpalloc(len);
2030
2031	snprintf(w, len, "%s%d", s, getlab());
2032	return w;
2033}
2034
2035NODE *
2036biop(int op, NODE *l, NODE *r)
2037{
2038	return block(op, l, r, INT, 0, 0);
2039}
2040
2041static NODE *
2042cmop(NODE *l, NODE *r)
2043{
2044	return biop(CM, l, r);
2045}
2046
2047static NODE *
2048voidcon(void)
2049{
2050	return block(ICON, NIL, NIL, STRTY, 0, 0);
2051}
2052
2053/* Support for extended assembler a' la' gcc style follows below */
2054
2055static NODE *
2056xmrg(NODE *out, NODE *in)
2057{
2058	NODE *p = in;
2059
2060	if (p->n_op == XARG) {
2061		in = cmop(out, p);
2062	} else {
2063		while (p->n_left->n_op == CM)
2064			p = p->n_left;
2065		p->n_left = cmop(out, p->n_left);
2066	}
2067	return in;
2068}
2069
2070/*
2071 * Put together in and out node lists in one list, and balance it with
2072 * the constraints on the right side of a CM node.
2073 */
2074static NODE *
2075xcmop(NODE *out, NODE *in, NODE *str)
2076{
2077	NODE *p, *q;
2078
2079	if (out) {
2080		/* D out-list sanity check */
2081		for (p = out; p->n_op == CM; p = p->n_left) {
2082			q = p->n_right;
2083			if (q->n_name[0] != '=' && q->n_name[0] != '+')
2084				uerror("output missing =");
2085		}
2086		if (p->n_name[0] != '=' && p->n_name[0] != '+')
2087			uerror("output missing =");
2088		if (in == NIL)
2089			p = out;
2090		else
2091			p = xmrg(out, in);
2092	} else if (in) {
2093		p = in;
2094	} else
2095		p = voidcon();
2096
2097	if (str == NIL)
2098		str = voidcon();
2099	return cmop(p, str);
2100}
2101
2102/*
2103 * Generate a XARG node based on a string and an expression.
2104 */
2105static NODE *
2106xasmop(char *str, NODE *p)
2107{
2108
2109	p = biop(XARG, p, NIL);
2110	p->n_name = isinlining ? newstring(str, strlen(str)+1) : str;
2111	return p;
2112}
2113
2114/*
2115 * Generate a XASM node based on a string and an expression.
2116 */
2117static void
2118mkxasm(char *str, NODE *p)
2119{
2120	NODE *q;
2121
2122	q = biop(XASM, p->n_left, p->n_right);
2123	q->n_name = isinlining ? newstring(str, strlen(str)+1) : str;
2124	nfree(p);
2125	ecomp(q);
2126}
2127
2128#ifdef GCC_COMPAT
2129static NODE *
2130tyof(NODE *p)
2131{
2132	static struct symtab spp;
2133	NODE *q = block(TYPE, NIL, NIL, p->n_type, p->n_df, p->n_ap);
2134	q->n_qual = p->n_qual;
2135	q->n_sp = &spp; /* for typenode */
2136	tfree(p);
2137	return q;
2138}
2139#endif
2140
2141/*
2142 * Rewrite ++/-- to (t=p, p++, t) ops on types that do not act act as usual.
2143 */
2144static NODE *
2145rewincop(NODE *p1, NODE *p2, int op)
2146{
2147	NODE *t, *r;
2148
2149	t = cstknode(p1->n_type, 0, 0);
2150	r = buildtree(ASSIGN, ccopy(t), ccopy(p1));
2151	r = buildtree(COMOP, r, buildtree(op, p1, eve(p2)));
2152	return buildtree(COMOP, r, t);
2153}
2154
2155/*
2156 * Traverse an unhandled expression tree bottom-up and call buildtree()
2157 * or equivalent as needed.
2158 */
2159NODE *
2160eve(NODE *p)
2161{
2162	struct symtab *sp;
2163	NODE *r, *p1, *p2;
2164	int x;
2165
2166	p1 = p->n_left;
2167	p2 = p->n_right;
2168	switch (p->n_op) {
2169	case NMLIST:
2170	case NAME:
2171		sp = cxxlookup(p, SNORMAL|SNOCREAT);
2172		if (sp->sflags & SINLINE)
2173			inline_ref(sp);
2174		r = nametree(sp);
2175		if (sp->sflags & SDYNARRAY)
2176			r = buildtree(UMUL, r, NIL);
2177#ifdef GCC_COMPAT
2178		if (attr_find(sp->sap, GCC_ATYP_DEPRECATED))
2179			werror("`%s' is deprecated", sp->sname);
2180#endif
2181		break;
2182
2183	case DOT:
2184	case STREF:
2185		r = cxxstructref(eve(p1), p->n_op, (char *)p2->n_sp);
2186		nfree(p2);
2187		break;
2188
2189	case CAST:
2190		p1 = buildtree(CAST, p1, eve(p2));
2191		nfree(p1->n_left);
2192		r = p1->n_right;
2193		nfree(p1);
2194		break;
2195
2196
2197	case SZOF:
2198		x = xinline; xinline = 0; /* XXX hack */
2199		if (p2->n_lval == 0)
2200			p1 = eve(p1);
2201		else
2202			TYMFIX(p1);
2203		nfree(p2);
2204		r = doszof(p1);
2205		xinline = x;
2206		break;
2207
2208	case LB:
2209		p1 = eve(p->n_left);
2210		r = buildtree(UMUL, buildtree(PLUS, p1, eve(p2)), NIL);
2211		break;
2212
2213	case COMPL:
2214#ifndef NO_COMPLEX
2215		p1 = eve(p1);
2216		if (ANYCX(p1))
2217			r = cxconj(p1);
2218		else
2219			r = buildtree(COMPL, p1, NIL);
2220		break;
2221#endif
2222	case UMINUS:
2223	case NOT:
2224	case UMUL:
2225		r = buildtree(p->n_op, eve(p->n_left), NIL);
2226		break;
2227
2228	case ADDROF:
2229		r = eve(p1);
2230		if (ISFTN(p->n_type)/* || ISARY(p->n_type) */){
2231#ifdef notdef
2232			werror( "& before array or function: ignored" );
2233#endif
2234		} else
2235			r = buildtree(ADDROF, r, NIL);
2236		break;
2237
2238	case CALL:
2239		p2 = eve(p2);
2240		/* FALLTHROUGH */
2241	case UCALL:
2242		if (p1->n_op == NAME || p1->n_op == NMLIST) {
2243			sp = cxxlookup(p1, SNORMAL);
2244			if (sp->stype == UNDEF) {
2245				if (!isbuiltin(sp->sname))
2246					uerror("'%s' undefined", sp->sname);
2247				p1->n_type = FTN|INT;
2248				p1->n_sp = sp;
2249				p1->n_ap = NULL;
2250				defid(p1, EXTERN);
2251			}
2252			nfree(p1);
2253#ifdef GCC_COMPAT
2254			if (attr_find(sp->sap, GCC_ATYP_DEPRECATED))
2255				werror("`%s' is deprecated", sp->sname);
2256#endif
2257			r = doacall(sp, nametree(sp), p2, 0);
2258		} else if (p1->n_op == DOT || p1->n_op == STREF) {
2259			/*
2260			 * function as member of a struct.
2261			 * - check args for correct overloaded function
2262			 * - add hidden arg0 as pointer to this struct
2263			 */
2264
2265			p1->n_left = eve(p1->n_left); /* eval rest */
2266			if (p->n_op == UCALL)
2267				p2 = NULL;
2268			r = cxxmatchftn(p1, p2);
2269			if (p1->n_op == DOT)
2270				p1->n_left = buildtree(ADDROF, p1->n_left, NIL);
2271			nfree(p1->n_right);
2272			p1 = nfree(p1);
2273			p2 = cxxaddhidden(p2, p1);
2274			r = doacall(NULL, r, p2, 1);
2275		} else
2276			r = doacall(NULL, eve(p1), p2, 0);
2277		break;
2278
2279#ifndef NO_COMPLEX
2280	case XREAL:
2281	case XIMAG:
2282		p1 = eve(p1);
2283		r = cxelem(p->n_op, p1);
2284		break;
2285#endif
2286
2287	case MUL:
2288	case DIV:
2289	case PLUS:
2290	case MINUS:
2291	case ASSIGN:
2292	case EQ:
2293	case NE:
2294#ifndef NO_COMPLEX
2295		p1 = eve(p1);
2296		p2 = eve(p2);
2297		if (ANYCX(p1) || ANYCX(p2)) {
2298			r = cxop(p->n_op, p1, p2);
2299		} else if (ISITY(p1->n_type) || ISITY(p2->n_type)) {
2300			r = imop(p->n_op, p1, p2);
2301		} else
2302			r = buildtree(p->n_op, p1, p2);
2303		break;
2304#endif
2305	case MOD:
2306	case CM:
2307	case GT:
2308	case GE:
2309	case LT:
2310	case LE:
2311	case RS:
2312	case LS:
2313	case RSEQ:
2314	case LSEQ:
2315	case AND:
2316	case OR:
2317	case ER:
2318	case OROR:
2319	case ANDAND:
2320	case EREQ:
2321	case OREQ:
2322	case ANDEQ:
2323	case QUEST:
2324	case COLON:
2325		p1 = eve(p1);
2326eve2:		r = buildtree(p->n_op, p1, eve(p2));
2327		break;
2328
2329	case INCR:
2330	case DECR:
2331		p1 = eve(p1);
2332		if (p1->n_type >= FLOAT && p1->n_type <= LDOUBLE) {
2333			/* ++/-- on floats isn't ((d+=1)-1) */
2334			/* rewrite to (t=d,d++,t) */
2335			/* XXX - side effects */
2336			r = rewincop(p1, p2, p->n_op);
2337			break;
2338		}
2339		if (p1->n_type != BOOL)
2340			goto eve2;
2341		/* Hey, fun.  ++ will always be 1, and -- will toggle result */
2342		if (p->n_op == INCR) {
2343			/* (t=d,d=1,t) */
2344			r = rewincop(p1, p2, ASSIGN);
2345		} else {
2346			/* (t=d,d^=1,t) */
2347			r = rewincop(p1, p2, EREQ);
2348		}
2349		break;
2350
2351	case MODEQ:
2352	case MINUSEQ:
2353	case PLUSEQ:
2354	case MULEQ:
2355	case DIVEQ:
2356		p1 = eve(p1);
2357		p2 = eve(p2);
2358#ifndef NO_COMPLEX
2359		if (ANYCX(p1) || ANYCX(p2)) {
2360			r = cxop(UNASG p->n_op, ccopy(p1), p2);
2361			r = cxop(ASSIGN, p1, r);
2362			break;
2363		} else if (ISITY(p1->n_type) || ISITY(p2->n_type)) {
2364			r = imop(UNASG p->n_op, ccopy(p1), p2);
2365			r = cxop(ASSIGN, p1, r);
2366			break;
2367		}
2368		/* FALLTHROUGH */
2369#endif
2370		if (p1->n_type == BOOL) {
2371			r = buildtree(UNASG p->n_op, ccopy(p1), p2);
2372			r = buildtree(ASSIGN, p1, r);
2373		} else {
2374			r = buildtree(p->n_op, p1, p2);
2375		}
2376		break;
2377
2378	case STRING:
2379		r = strend(p->n_lval, p->n_name);
2380		break;
2381
2382	case COMOP:
2383		if (p1->n_op == GOTO) {
2384			/* inside ({ }), eve already called */
2385			r = buildtree(p->n_op, p1, p2);
2386		} else {
2387			p1 = eve(p1);
2388			r = buildtree(p->n_op, p1, eve(p2));
2389		}
2390		break;
2391
2392	case TYPE:
2393	case ICON:
2394	case FCON:
2395	case TEMP:
2396		return p;
2397
2398	case CLOP:
2399		r = nametree(p->n_sp);
2400		break;
2401
2402	case DELETE:
2403		p1 = eve(p1);
2404		r = cxx_delete(p1, p2->n_lval);
2405		nfree(p2);
2406		break;
2407
2408	case NEWKW:
2409		r = cxx_new(p1);
2410		nfree(p2);
2411		break;
2412
2413	default:
2414#ifdef PCC_DEBUG
2415		fwalk(p, eprint, 0);
2416#endif
2417		cerror("eve");
2418		r = NIL;
2419	}
2420	nfree(p);
2421	return r;
2422}
2423
2424int
2425con_e(NODE *p)
2426{
2427#ifdef WORD_ADDRESSED
2428	return icons(optim(eve(p)));
2429#else
2430	return icons(optim(rmpconv(eve(p))));
2431#endif
2432}
2433
2434void
2435uawarn(NODE *p, char *s)
2436{
2437	if (p == 0)
2438		return;
2439	if (attrwarn)
2440		werror("unhandled %s attribute", s);
2441	tfree(p);
2442}
2443
2444static void
2445dainit(NODE *d, NODE *a)
2446{
2447	if (d == NULL) {
2448		asginit(a);
2449	} else if (d->n_op == CM) {
2450		int is = con_e(d->n_left);
2451		int ie = con_e(d->n_right);
2452		int i;
2453
2454		nfree(d);
2455		if (ie < is)
2456			uerror("negative initializer range");
2457		desinit(biop(LB, NIL, bcon(is)));
2458		for (i = is; i < ie; i++)
2459			asginit(ccopy(a));
2460		asginit(a);
2461	} else {
2462		cerror("dainit");
2463	}
2464}
2465
2466/*
2467 * Traverse down and tymerge() where appropriate.
2468 */
2469static NODE *
2470tymfix(NODE *p)
2471{
2472	NODE *q;
2473	int o = coptype(p->n_op);
2474
2475	switch (o) {
2476	case LTYPE:
2477		break;
2478	case UTYPE:
2479		p->n_left = tymfix(p->n_left);
2480		break;
2481	case BITYPE:
2482		p->n_left = tymfix(p->n_left);
2483		p->n_right = tymfix(p->n_right);
2484		if (p->n_op == TYMERGE) {
2485			q = tymerge(p->n_left, p->n_right);
2486			q->n_ap = attr_add(q->n_ap, p->n_ap);
2487			tfree(p->n_left);
2488			nfree(p);
2489			p = q;
2490		}
2491		break;
2492	}
2493	return p;
2494}
2495
2496static NODE *
2497aryfix(NODE *p)
2498{
2499	NODE *q;
2500
2501	for (q = p; q->n_op != NAME; q = q->n_left) {
2502		if (q->n_op == LB) {
2503			q->n_right = optim(rmpconv(eve(q->n_right)));
2504			if ((blevel == 0 || rpole != NULL) &&
2505			    !nncon(q->n_right))
2506				uerror("array size not constant");
2507			/*
2508			 * Checks according to 6.7.5.2 clause 1:
2509			 * "...the expression shall have an integer type."
2510			 * "If the expression is a constant expression,
2511			 * it shall have a value greater than zero."
2512			 */
2513			if (!ISINTEGER(q->n_right->n_type))
2514				werror("array size is not an integer");
2515			else if (q->n_right->n_op == ICON &&
2516			    q->n_right->n_lval < 0 &&
2517			    q->n_right->n_lval != NOOFFSET) {
2518					uerror("array size cannot be negative");
2519					q->n_right->n_lval = 1;
2520			}
2521		} else if (q->n_op == CALL)
2522			q->n_right = namekill(q->n_right, 1);
2523	}
2524	return p;
2525}
2526