Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20121020200836

Diff

Diff from 1.5 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cxxcom/cgram.y

Annotated File View

plunky
1.5
1 /*      $Id: cgram.y,v 1.5 2012/10/20 20:08:37 plunky Exp $     */
ragge
1.1
2
3 /*
4  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*
29  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  *
35  * Redistributions of source code and documentation must retain the above
36  * copyright notice, this list of conditions and the following disclaimer.
37  * Redistributions in binary form must reproduce the above copyright
38  * notice, this list of conditions and the following disclaimer in the
39  * documentation and/or other materials provided with the distribution.
40  * All advertising materials mentioning features or use of this software
41  * must display the following acknowledgement:
42  *      This product includes software developed or owned by Caldera
43  *      International, Inc.
44  * Neither the name of Caldera International, Inc. nor the names of other
45  * contributors may be used to endorse or promote products derived from
46  * this software without specific prior written permission.
47  *
48  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
49  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
50  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
51  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
53  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
57  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
58  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
59  * POSSIBILITY OF SUCH DAMAGE.
60  */
61
62 /*
63  * Comments for this grammar file. Ragge 021123
64  *
65  * ANSI support required rewrite of the function header and declaration
66  * rules almost totally.
67  *
68  * The lex/yacc shared keywords are now split from the keywords used
69  * in the rest of the compiler, to simplify use of other frontends.
70  */
71
72 /*
73  * At last count, there were 5 shift/reduce and no reduce/reduce conflicts
74  * Four are accounted for;
75  * One is "dangling else"
76  * Two is in attribute parsing
77  * One is in ({ }) parsing
78  */
79
80 /*
81  * Token used in C lex/yacc communications.
82  */
83 %token  C_STRING        /* a string constant */
84 %token  C_ICON          /* an integer constant */
85 %token  C_FCON          /* a floating point constant */
86 %token  C_NAME          /* an identifier */
87 %token  C_TYPENAME      /* a typedef'd name */
88 %token  C_ANDAND        /* && */
89 %token  C_OROR          /* || */
90 %token  C_GOTO          /* unconditional goto */
91 %token  C_RETURN        /* return from function */
92 %token  C_TYPE          /* a type */
93 %token  C_CLASS         /* a storage class */
94 %token  C_ASOP          /* assignment ops */
95 %token  C_RELOP         /* <=, <, >=, > */
96 %token  C_EQUOP         /* ==, != */
97 %token  C_DIVOP         /* /, % */
98 %token  C_SHIFTOP       /* <<, >> */
99 %token  C_INCOP         /* ++, -- */
100 %token  C_UNOP          /* !, ~ */
101 %token  C_STROP         /* ., -> */
102 %token  C_STRUCT
103 %token  C_IF
104 %token  C_ELSE
105 %token  C_SWITCH
106 %token  C_BREAK
107 %token  C_CONTINUE
108 %token  C_WHILE 
109 %token  C_DO
110 %token  C_FOR
111 %token  C_DEFAULT
112 %token  C_CASE
113 %token  C_SIZEOF
114 %token  C_ALIGNOF
115 %token  C_ENUM
116 %token  C_ELLIPSIS
117 %token  C_QUALIFIER
118 %token  C_FUNSPEC
119 %token  C_ASM
120 %token  NOMATCH
121 %token  C_TYPEOF        /* COMPAT_GCC */
122 %token  C_ATTRIBUTE     /* COMPAT_GCC */
123 %token  PCC_OFFSETOF
124 %token  GCC_DESIG
125 %token  CXX_NAMESPACE
126 %token  CXX_DUALCC
127 %token  CXX_TEMPLATE
128 %token  CXX_USING
129 %token  CXX_TYPENAME
130 %token  CXX_CASTS
131 %token  CXX_THROW
132 %token  CXX_MORENM
133 %token  CXX_NEW
134 %token  CXX_DELETE
135 %token  CXX_CLASS
136
137 /*
138  * Precedence
139  */
140 %left ','
141 %right '=' C_ASOP
142 %right '?' ':'
143 %left C_OROR
144 %left C_ANDAND
145 %left '|'
146 %left '^'
147 %left '&'
148 %left C_EQUOP
149 %left C_RELOP
150 %left C_SHIFTOP
151 %left '+' '-'
152 %left '*' C_DIVOP
153 %right C_UNOP
154 %right C_INCOP C_SIZEOF
155 %left '[' '(' C_STROP
156 %{
157 # include "pass1.h"
158 # include <stdarg.h>
159 # include <string.h>
160 # include <stdlib.h>
161
162 int fun_inline; /* Reading an inline function */
163 int oldstyle;   /* Current function being defined */
164 static struct symtab *xnf;
165 extern int enummer, tvaloff, inattr;
166 extern struct rstack *rpole;
167 static int widestr, alwinl;
168 NODE *cftnod;
169 static int attrwarn = 1;
170
171 #define NORETYP SNOCREAT /* no return type, save in unused field in symtab */
172
173        NODE *bdty(int op, ...);
174 static void fend(struct symtab *);
175 static struct symtab *fundef(NODE *tp, NODE *p);
176 static void olddecl(NODE *p, NODE *a);
177 static struct symtab *init_declarator(NODE *tn, NODE *p, int assign, NODE *a);
178 static void resetbc(int mask);
179 static void swend(void);
180 static void addcase(NODE *p);
181 #ifdef GCC_COMPAT
182 static void gcccase(NODE *p, NODE *);
183 #endif
184 static void adddef(void);
185 static void savebc(void);
186 static void swstart(int, TWORD);
187 static void genswitch(int, TWORD, struct swents **, int);
188 static char *mkpstr(char *str);
189 static struct symtab *clbrace(NODE *);
190 static NODE *cmop(NODE *l, NODE *r);
191 static NODE *xcmop(NODE *out, NODE *in, NODE *str);
192 static void mkxasm(char *str, NODE *p);
193 static NODE *xasmop(char *str, NODE *p);
194 static int maxstlen(char *str);
195 static char *stradd(char *old, char *new);
196 static NODE *biop(int op, NODE *l, NODE *r);
197 static void flend(void);
198 static char * simname(char *s);
199 #ifdef GCC_COMPAT
200 static NODE *tyof(NODE *);      /* COMPAT_GCC */
201 static NODE *voidcon(void);     /* COMPAT_GCC */
202 #endif
203 static NODE *funargs(NODE *p);
204 static void oldargs(NODE *p);
205 static void uawarn(NODE *p, char *s);
206 static int con_e(NODE *p);
207 static void dainit(NODE *d, NODE *a);
208 static NODE *tymfix(NODE *p);
209 static NODE *namekill(NODE *p, int clr);
210 static NODE *aryfix(NODE *p);
211
212 #define TYMFIX(inp) { \
213         NODE *pp = inp; \
214         inp = tymerge(pp->n_left, pp->n_right); \
215         nfree(pp->n_left); nfree(pp); }
216 /*
217  * State for saving current switch state (when nested switches).
218  */
219 struct savbc {
220         struct savbc *next;
221         int brklab;
222         int contlab;
223         int flostat;
224         int swx;
225 } *savbc, *savctx;
226
227 %}
228
229 %union {
230         int intval;
231         NODE *nodep;
232         struct symtab *symp;
233         struct rstack *rp;
234         char *strp;
235 }
236
237         /* define types */
238 %start edf
239
240 %type <intval> ifelprefix ifprefix whprefix forprefix doprefix switchpart
241                 xbegin
242 %type <nodep> e .e term enum_dcl struct_dcl cast_type declarator
243                 elist type_sq cf_spec merge_attribs
244                 parameter_declaration abstract_declarator initializer
245                 parameter_type_list parameter_list addrlbl
246                 declaration_specifiers designation
247                 specifier_qualifier_list merge_specifiers
248                 identifier_list arg_param_list type_qualifier_list
249                 designator_list designator xasm oplist oper cnstr 
250                 typeof attribute attribute_specifier /* COMPAT_GCC */
251                 attribute_list attr_spec_list attr_var /* COMPAT_GCC */
252                 new_ma new_type_sq new_ds nmrec
253 %type <strp>    string C_STRING GCC_DESIG nsname CXX_MORENM
254 %type <rp>      str_head
255 %type <symp>    xnfdeclarator clbrace enum_head funtype
256
257 %type <intval>  C_STRUCT C_RELOP C_DIVOP C_SHIFTOP
258                 C_ANDAND C_OROR C_STROP C_INCOP C_UNOP C_ASOP C_EQUOP
259
260 %type <nodep>   C_TYPE C_QUALIFIER C_ICON C_FCON C_CLASS
261 %type <strp>    C_NAME C_TYPENAME
262 %%
263
264 edf:              ext_def_list
265                 | { ftnend(); }
266                 ;
267
268 ext_def_list:     ext_def_list external_def
269                 | external_def
270                 ;
271
272 external_def:      funtype kr_args compoundstmt { fend($1); }
273                 |  declaration  { blevel = 0; symclear(0); }
274                 | namespace
275                 | extlink
276                 | blockdcl
277                 |  ';'
278                 |  error { blevel = 0; }
279                 ;
280
281 funtype:          /* no type given */ declarator {
282                     $$ = fundef(mkty(INT, 0, 0), $1);
283                     cftnsp->sflags |= NORETYP;
284                 }
285                 | declaration_specifiers declarator { $$ = fundef($1,$2); }
286                 ;
287
288 kr_args:          /* empty */
289                 | arg_dcl_list
290                 ;
291
292 blockdcl:         simple_decl
293                 | asmstatement
294                 | ns_alias
295                 | using_x
296                 ;
297
298 using_x:          CXX_USING tnopt ccopt nested_name_sp ';' { werror("using"); }
299                 | CXX_USING CXX_NAMESPACE ccopt nested_name_sp ';' { werror("using2"); }
300                 ;
301
302 tnopt:            CXX_TYPENAME { }
303                 | { }
304                 ;
305
306 ns_alias:         CXX_NAMESPACE C_NAME '=' qual_ns_sp ';' { werror("ns_alias");}
307                 ;
308
309 qual_ns_sp:       ccopt nested_name_sp
310                 ;
311
312 nested_name_sp:   nmtnm
313                 | nmtnm CXX_DUALCC nested_name_sp
314                 | nmtnm CXX_DUALCC CXX_TEMPLATE nested_name_sp
315                 ;
316
317 nmtnm:            C_NAME
318                 | C_TYPENAME
319                 ;
320
321 ccopt:            CXX_DUALCC
322                 | { }
323                 ;
324
325 simple_decl:      ')' NOMATCH { uerror("simple-declaration"); }
326                 ;
327
328 namespace:        CXX_NAMESPACE nsname attr_var nsbeg ns_body '}' { POPSYM(); }
329                 ;
330
331 nsname:           C_NAME
332                 | { $$ = NULL; }
333                 ;
334  
335 ns_body:          ext_def_list
336                 | { }
337                 ;
338
339 nsbeg:            '{' { dclns($<nodep>0, $<strp>-1); }
340                 ;
341
342 extlink:          C_CLASS C_STRING eb '{' ext_def_list '}' { elnk = LINK_DEF; }
343                 | C_CLASS C_STRING eb '{' '}' { elnk = LINK_DEF; }
344                 | C_CLASS C_STRING eb declaration { elnk = LINK_DEF; }
345                 ;
346
347 eb:               {
348                         NODE *p = $<nodep>-1;
349                         char *s = $<strp>0;
350                         if (p->n_type != EXTERN)
351                                 uerror("'extern' expected");
352                         if (strcmp(s, "\"C\"") != 0 && strcmp(s, "\"c\""))
353                                 uerror("unknown linkage %s", s);
354                         nfree(p);
355                         elnk = LINK_C;
356                 }
357                 ;
358 /*
359  * Returns a node pointer or NULL, if no types at all given.
360  * Type trees are checked for correctness and merged into one
361  * type node in typenode().
362  */
363 declaration_specifiers:
364                    merge_attribs { $$ = typenode($1); }
365                 ;
366
367 merge_attribs:     type_sq { $$ = $1; }
368                 |  type_sq merge_attribs { $$ = cmop($2, $1); }
369                 |  cf_spec { $$ = $1; }
370                 |  cf_spec merge_attribs { $$ = cmop($2, $1); }
371                 ;
372
373 type_sq:           C_TYPE { $$ = $1; }
374                 |  C_TYPENAME { 
375                         struct symtab *sp = lookup($1, 0);
376                         if (sp->stype == ENUMTY) {
377                                 sp->stype = strmemb(sp->sap)->stype;
378                         }
379                         $$ = mkty(sp->stype, sp->sdf, sp->sap);
380                         $$->n_sp = sp;
381                 }
382                 |  struct_dcl { $$ = $1; }
383                 |  enum_dcl { $$ = $1; }
384                 |  C_QUALIFIER { $$ = $1; }
385                 |  attribute_specifier { $$ = biop(ATTRIB, $1, 0); }
386                 |  typeof { $$ = $1; }
387                 ;
388
389 cf_spec:           C_CLASS { $$ = $1; }
390                 |  C_FUNSPEC { fun_inline = 1;  /* XXX - hack */
391                         $$ = block(QUALIFIER, NIL, NIL, 0, 0, 0); }
392                 ;
393
394 typeof:            C_TYPEOF '(' e ')' { $$ = tyof(eve($3)); }
395                 |  C_TYPEOF '(' cast_type ')' { TYMFIX($3); $$ = tyof($3); }
396                 ;
397
398 new_ma:            new_type_sq
399                 |  new_type_sq new_ma { $$ = cmop($2, $1); }
400                 |  cf_spec { $$ = $1; }
401                 |  cf_spec new_ma { $$ = cmop($2, $1); }
402                 ;
403
404 new_ds:            new_ma { $$ = typenode($1); }
405                 ;
406
407 new_type_sq:       C_TYPE { $$ = $1; }
408                 |  C_TYPENAME { 
409                         struct symtab *sp = lookup($1, 0);
410                         if (sp->stype == ENUMTY) {
411                                 sp->stype = strmemb(sp->sap)->stype;
412                         }
413                         $$ = mkty(sp->stype, sp->sdf, sp->sap);
414                         $$->n_sp = sp;
415                 }
416                 |  struct_dcl { $$ = $1; }
417                 |  enum_dcl { $$ = $1; }
418                 |  C_QUALIFIER { $$ = $1; }
419                 ;
420
421 attribute_specifier :
422                    C_ATTRIBUTE '(' '(' attribute_list ')' ')' { $$ = $4; }
423  /*COMPAT_GCC*/ ;
424
425 attribute_list:    attribute
426                 |  attribute ',' attribute_list { $$ = cmop($3, $1); }
427                 ;
428
429 attribute:         {
430 #ifdef GCC_COMPAT
431                          $$ = voidcon();
432 #endif
433                 }
434                 |  C_NAME { $$ = bdty(NAME, $1); }
435                 |  C_NAME '(' elist ')' {
436                         $$ = bdty($3 == NIL ? UCALL : CALL, bdty(NAME, $1), $3);
437                 }
438                 ;
439
440 /*
441  * Adds a pointer list to front of the declarators.
442  */
443 declarator:        '*' declarator { $$ = bdty(UMUL, $2); }
444                 |  '*' type_qualifier_list declarator {
445                         $$ = $2;
446                         $$->n_left = $3;
447                 }
448                 |  nmrec C_NAME { $$ = biop(NMLIST, $1, bdty(NAME, $2)); }
449                 |  C_NAME { $$ = bdty(NAME, $1); }
450                 |  '(' attr_spec_list declarator ')' {
451                         $$ = $3;
452                         $$->n_ap = attr_add($$->n_ap, gcc_attr_parse($2));
453                 }
454                 |  '(' declarator ')' { $$ = $2; }
455                 |  declarator '[' e ']' { $$ = biop(LB, $1, $3); }
456                 |  declarator '[' C_CLASS e ']' {
457                         if ($3->n_type != STATIC)
458                                 uerror("bad class keyword");
459                         tfree($3); /* XXX - handle */
460                         $$ = biop(LB, $1, $4);
461                 }
462                 |  declarator '[' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); }
463                 |  declarator '[' '*' ']' { $$ = biop(LB, $1, bcon(NOOFFSET)); }
464                 |  declarator '(' parameter_type_list ')' {
465                         $$ = bdty(CALL, $1, $3);
466                 }
467                 |  declarator '(' identifier_list ')' {
468                         $$ = bdty(CALL, $1, $3);
469                         oldstyle = 1;
470                 }
471                 |  declarator '(' ')' { $$ = bdty(UCALL, $1); }
472                 ;
473
474 type_qualifier_list:
475                    C_QUALIFIER { $$ = $1; $$->n_op = UMUL; }
476                 |  type_qualifier_list C_QUALIFIER {
477                         $$ = $1;
478                         $$->n_qual |= $2->n_qual;
479                         nfree($2);
480                 }
481                 |  attribute_specifier {
482                         $$ = block(UMUL, NIL, NIL, 0, 0, gcc_attr_parse($1));
483                 }
484                 |  type_qualifier_list attribute_specifier {
485                         $1->n_ap = attr_add($1->n_ap, gcc_attr_parse($2));
486                 }
487                 ;
488
489 identifier_list:   C_NAME { $$ = bdty(NAME, $1); oldargs($$); }
490                 |  identifier_list ',' C_NAME {
491                         $$ = cmop($1, bdty(NAME, $3));
492                         oldargs($$->n_right);
493                 }
494                 ;
495
496 /*
497  * Returns as parameter_list, but can add an additional ELLIPSIS node.
498  */
499 parameter_type_list:
500                    parameter_list { $$ = $1; }
501                 |  parameter_list ',' C_ELLIPSIS {
502                         $$ = cmop($1, biop(ELLIPSIS, NIL, NIL));
503                 }
504                 ;
505
506 /*
507  * Returns a linked lists of nodes of op CM with parameters on
508  * its right and additional CM nodes of its left pointer.
509  * No CM nodes if only one parameter.
510  */
511 parameter_list:    parameter_declaration { $$ = $1; }
512                 |  parameter_declaration '&' { $$ = $1; }
513                 |  parameter_list ',' parameter_declaration {
514                         $$ = cmop($1, $3);
515                 }
516                 ;
517
518 /*
519  * Returns a node pointer to the declaration.
520  */
521 parameter_declaration:
522                    declaration_specifiers declarator attr_var {
523                         if ($1->n_lval != SNULL && $1->n_lval != REGISTER)
524                                 uerror("illegal parameter class");
525                         $$ = block(TYMERGE, $1, $2, INT, 0, gcc_attr_parse($3));
526                 }
527                 |  declaration_specifiers abstract_declarator { 
528                         $$ = block(TYMERGE, $1, $2, INT, 0, 0);
529                 }
530                 |  declaration_specifiers {
531                         $$ = block(TYMERGE, $1, bdty(NAME, NULL), INT, 0, 0);
532                 }
533                 ;
534
535 abstract_declarator:
536                    '*' { $$ = bdty(UMUL, bdty(NAME, NULL)); }
537                 |  '*' type_qualifier_list {
538                         $$ = $2;
539                         $$->n_left = bdty(NAME, NULL);
540                 }
541                 |  '*' abstract_declarator { $$ = bdty(UMUL, $2); }
542                 |  '*' type_qualifier_list abstract_declarator {
543                         $$ = $2;
544                         $$->n_left = $3;
545                 }
546                 |  '(' abstract_declarator ')' { $$ = $2; }
547                 |  '[' ']' attr_var {
548                         $$ = block(LB, bdty(NAME, NULL), bcon(NOOFFSET),
549                             INT, 0, gcc_attr_parse($3));
550                 }
551                 |  '[' e ']' attr_var {
552                         $$ = block(LB, bdty(NAME, NULL), $2,
553                             INT, 0, gcc_attr_parse($4));
554                 }
555                 |  abstract_declarator '[' ']' attr_var {
556                         $$ = block(LB, $1, bcon(NOOFFSET),
557                             INT, 0, gcc_attr_parse($4));
558                 }
559                 |  abstract_declarator '[' e ']' attr_var {
560                         $$ = block(LB, $1, $3, INT, 0, gcc_attr_parse($5));
561                 }
562                 |  '(' ')' { $$ = bdty(UCALL, bdty(NAME, NULL)); }
563                 |  '(' ib2 parameter_type_list ')' {
564                         $$ = bdty(CALL, bdty(NAME, NULL), $3);
565                 }
566                 |  abstract_declarator '(' ')' {
567                         $$ = bdty(UCALL, $1);
568                 }
569                 |  abstract_declarator '(' ib2 parameter_type_list ')' {
570                         $$ = bdty(CALL, $1, $4);
571                 }
572                 ;
573
574 ib2:              { }
575                 ;
576 /*
577  * K&R arg declaration, between ) and {
578  */
579 arg_dcl_list:      arg_declaration
580                 |  arg_dcl_list arg_declaration
581                 ;
582
583
584 arg_declaration:   declaration_specifiers arg_param_list ';' {
585                         nfree($1);
586                 }
587                 ;
588
589 arg_param_list:    declarator attr_var {
590                         olddecl(block(TYMERGE, ccopy($<nodep>0), $1,
591                             INT, 0, 0), $2);
592                 }
593                 |  arg_param_list ',' declarator attr_var {
594                         olddecl(block(TYMERGE, ccopy($<nodep>0), $3,
595                             INT, 0, 0), $4);
596                 }
597                 ;
598
599 /*
600  * Declarations in beginning of blocks.
601  */
602 block_item_list:   block_item
603                 |  block_item_list block_item
604                 ;
605
606 block_item:        declaration
607                 |  statement
608                 ;
609
610 /*
611  * Here starts the old YACC code.
612  */
613
614 /*
615  * Variables are declared in init_declarator.
616  */
617 declaration:       declaration_specifiers ';' { tfree($1); fun_inline = 0; }
618                 |  declaration_specifiers init_declarator_list ';' {
619                         tfree($1);
620                         fun_inline = 0;
621                 }
622                 ;
623
624 /*
625  * Normal declaration of variables. curtype contains the current type node.
626  * Returns nothing, variables are declared in init_declarator.
627  */
628 init_declarator_list:
629                    init_declarator { symclear(blevel); }
630                 |  init_declarator_list ',' attr_var { $<nodep>$ = $<nodep>0; } init_declarator {
631                         uawarn($3, "init_declarator");
632                         symclear(blevel);
633                 }
634                 ;
635
636 enum_dcl:          enum_head '{' moe_list optcomma '}' { $$ = enumdcl($1); }
637                 |  C_ENUM C_NAME {  $$ = enumref($2); }
638                 ;
639
640 enum_head:         C_ENUM { $$ = enumhd(NULL); }
641                 |  C_ENUM C_NAME {  $$ = enumhd($2); }
642                 ;
643
644 moe_list:          moe
645                 |  moe_list ',' moe
646                 ;
647
648 moe:               C_NAME {  moedef($1); }
649                 |  C_TYPENAME {  moedef($1); }
650                 |  C_NAME '=' e { enummer = con_e($3); moedef($1); }
651                 |  C_TYPENAME '=' e { enummer = con_e($3); moedef($1); }
652                 ;
653
654 struct_dcl:        str_head '{' struct_dcl_list '}' {
655                         NODE *p;
656
657                         $$ = dclstruct($1);
658                         if (pragma_allpacked) {
659                                 p = bdty(CALL, bdty(NAME, "packed"),
660                                     bcon(pragma_allpacked));
661                                 $$->n_ap = attr_add($$->n_ap,gcc_attr_parse(p)); }
662                 }
663                 |  C_STRUCT attr_var C_NAME { 
664                         $$ = rstruct($3,$1);
665                         uawarn($2, "struct_dcl");
666                 }
667                 |  C_STRUCT attr_var nmrec C_NAME { 
668                         $$ = cxxrstruct($1,$2,$3,$4);
669                         uawarn($2, "struct_dcl");
670                 }
671  /*COMPAT_GCC*/ |  str_head '{' '}' { $$ = dclstruct($1); }
672                 ;
673
674 attr_var:          {    
675                         NODE *q, *p;
676
677                         p = pragma_aligned ? bdty(CALL, bdty(NAME, "aligned"),
678                             bcon(pragma_aligned)) : NIL;
679                         if (pragma_packed) {
680                                 q = bdty(NAME, "packed");
681                                 p = (p == NIL ? q : cmop(p, q));
682                         }
683                         pragma_aligned = pragma_packed = 0;
684                         $$ = p;
685                 }
686  /*COMPAT_GCC*/ |  attr_spec_list
687                 ;
688
689 attr_spec_list:    attribute_specifier 
690                 |  attr_spec_list attribute_specifier { $$ = cmop($1, $2); }
691                 ;
692
693 str_head:          C_STRUCT attr_var {  $$ = bstruct(NULL, $1, $2);  }
694                 |  C_STRUCT attr_var C_NAME {  $$ = bstruct($3, $1, $2);  }
695                 ;
696
697 struct_dcl_list:   struct_declaration
698                 |  struct_dcl_list struct_declaration
699                 ;
700
701 struct_declaration:
702                    declaration_specifiers struct_declarator_list optsemi {
703                         tfree($1);
704                 }
705                 |  C_NAME ':' { /* cxxaccess($1); */ }
706                 ;
707
708 optsemi:           ';' { }
709                 |  optsemi ';' { werror("extra ; in struct"); }
710                 ;
711
712 specifier_qualifier_list:
713                    merge_specifiers { $$ = typenode($1); }
714                 ;
715
716 merge_specifiers:  type_sq merge_specifiers { $$ = cmop($2, $1); }
717                 |  type_sq { $$ = $1; }
718                 ;
719
720 struct_declarator_list:
721                    struct_declarator { symclear(blevel); }
722                 |  struct_declarator_list ',' { $<nodep>$=$<nodep>0; } 
723                         struct_declarator { symclear(blevel); }
724                 ;
725
726 struct_declarator: declarator attr_var {
727                         NODE *p;
728
729                         $1 = aryfix($1);
730                         p = tymerge($<nodep>0, tymfix($1));
731                         if ($2)
732                                 p->n_ap = attr_add(p->n_ap, gcc_attr_parse($2));
733                         soumemb(p, (char *)$1->n_sp, $<nodep>0->n_lval);
734                         tfree(p);
735                 }
736                 |  ':' e {
737                         int ie = con_e($2);
738                         if (fldchk(ie))
739                                 ie = 1;
740                         falloc(NULL, ie, $<nodep>0);
741                 }
742                 |  declarator ':' e {
743                         int ie = con_e($3);
744                         if (fldchk(ie))
745                                 ie = 1;
746                         if ($1->n_op == NAME) {
747                                 /* XXX - tymfix() may alter $1 */
748                                 tymerge($<nodep>0, tymfix($1));
749                                 soumemb($1, (char *)$1->n_sp, FIELD | ie);
750                                 nfree($1);
751                         } else
752                                 uerror("illegal declarator");
753                 }
754                 |  declarator ':' e attr_spec_list {
755                         int ie = con_e($3);
756                         if (fldchk(ie))
757                                 ie = 1;
758                         if ($1->n_op == NAME) {
759                                 /* XXX - tymfix() may alter $1 */
760                                 tymerge($<nodep>0, tymfix($1));
761                                 if ($4)
762                                         $1->n_ap = attr_add($1->n_ap,
763                                             gcc_attr_parse($4));
764                                 soumemb($1, (char *)$1->n_sp, FIELD | ie);
765                                 nfree($1);
766                         } else
767                                 uerror("illegal declarator");
768                 }
769                 | /* unnamed member */ {
770                         NODE *p = $<nodep>0;
771                         char *c = permalloc(10);
772
773                         if (p->n_type != STRTY && p->n_type != UNIONTY)
774                                 uerror("bad unnamed member type");
775                         snprintf(c, 10, "*%dFAKE", getlab());
776                         soumemb(p, c, 0);
777                 }
778                 ;
779
780                 /* always preceeded by attributes */
781 xnfdeclarator:     declarator attr_var {
782                         $$ = xnf = init_declarator($<nodep>0, $1, 1, $2);
783                 }
784                 |  declarator C_ASM '(' string ')' {
785                         pragma_renamed = newstring($4, strlen($4));
786                         $$ = xnf = init_declarator($<nodep>0, $1, 1, NULL);
787                 }
788                 ;
789
790 /*
791  * Handles declarations and assignments.
792  * Returns nothing.
793  */
794 init_declarator:   declarator attr_var { init_declarator($<nodep>0, $1, 0, $2);}
795                 |  declarator C_ASM '(' string ')' attr_var {
796 #ifdef GCC_COMPAT
797                         pragma_renamed = newstring($4, strlen($4));
798                         init_declarator($<nodep>0, $1, 0, $6);
799 #else
800                         werror("gcc extension");
801                         init_declarator($<nodep>0, $1, 0, $6);
802 #endif
803                 }
804                 |  xnfdeclarator '=' e { 
805                         if ($1->sclass == STATIC || $1->sclass == EXTDEF)
806                                 statinit++;
807                         simpleinit($1, eve($3));
808                         if ($1->sclass == STATIC || $1->sclass == EXTDEF)
809                                 statinit--;
810                         xnf = NULL;
811                 }
812                 |  xnfdeclarator '=' begbr init_list optcomma '}' {
813                         endinit(0);
814                         xnf = NULL;
815                 }
816  /*COMPAT_GCC*/ |  xnfdeclarator '=' begbr '}' { endinit(0); xnf = NULL; }
817                 |  xnfdeclarator '=' addrlbl { simpleinit($1, $3); xnf = NULL; }
818                 ;
819
820 begbr:             '{' { beginit($<symp>-1); }
821                 ;
822
823 initializer:       e %prec ',' {  $$ = eve($1); }
824                 |  addrlbl {  $$ = $1; }
825                 |  ibrace init_list optcomma '}' { $$ = NULL; }
826                 |  ibrace '}' { asginit(bcon(0)); $$ = NULL; }
827                 ;
828
829 init_list:         designation initializer { dainit($1, $2); }
830                 |  init_list ','  designation initializer { dainit($3, $4); }
831                 ;
832
833 designation:       designator_list '=' { desinit($1); $$ = NIL; }
834                 |  GCC_DESIG { desinit(bdty(NAME, $1)); $$ = NIL; }
835                 |  '[' e C_ELLIPSIS e ']' '=' { $$ = biop(CM, $2, $4); }
836                 |  { $$ = NIL; }
837                 ;
838
839 designator_list:   designator { $$ = $1; }
840                 |  designator_list designator { $$ = $2; $$->n_left = $1; }
841                 ;
842
843 designator:        '[' e ']' {
844                         int ie = con_e($2);
845                         if (ie < 0) {
846                                 uerror("designator must be non-negative");
847                                 ie = 0;
848                         }
849                         $$ = biop(LB, NIL, bcon(ie));
850                 }
851                 |  C_STROP C_TYPENAME {
852                         if ($1 != DOT)
853                                 uerror("invalid designator");
854                         $$ = bdty(NAME, $2);
855                 }
856                 |  C_STROP C_NAME {
857                         if ($1 != DOT)
858                                 uerror("invalid designator");
859                         $$ = bdty(NAME, $2);
860                 }
861                 ;
862
863 optcomma        :       /* VOID */
864                 |  ','
865                 ;
866
867 ibrace:            '{' {  ilbrace(); }
868                 ;
869
870 /*      STATEMENTS      */
871
872 compoundstmt:      begin block_item_list '}' { flend(); }
873                 |  begin '}' { flend(); }
874                 ;
875
876 begin:            '{' {
877                         struct savbc *bc = tmpalloc(sizeof(struct savbc));
878                         if (blevel == 1) {
879 #ifdef STABS
880                                 if (gflag)
881                                         stabs_line(lineno);
882 #endif
883                                 dclargs();
884                         }
885 #ifdef STABS
886                         if (gflag && blevel > 1)
887                                 stabs_lbrac(blevel+1);
888 #endif
889                         ++blevel;
890                         oldstyle = 0;
891                         bc->contlab = autooff;
892                         bc->next = savctx;
893                         savctx = bc;
894                         if (!isinlining && sspflag && blevel == 2)
895                                 sspstart();
896                 }
897                 ;
898
899 statement:         e ';' { /* fwalk($1, eprint, 0); */ ecomp(eve($1)); symclear(blevel); }
900                 |  compoundstmt
901                 |  ifprefix statement { plabel($1); reached = 1; }
902                 |  ifelprefix statement {
903                         if ($1 != NOLAB) {
904                                 plabel( $1);
905                                 reached = 1;
906                         }
907                 }
908                 |  whprefix statement {
909                         branch(contlab);
910                         plabel( brklab );
911                         if( (flostat&FBRK) || !(flostat&FLOOP))
912                                 reached = 1;
913                         else
914                                 reached = 0;
915                         resetbc(0);
916                 }
917                 |  doprefix statement C_WHILE '(' e ')' ';' {
918                         plabel(contlab);
919                         if (flostat & FCONT)
920                                 reached = 1;
921                         if (reached)
922                                 cbranch(buildtree(NE, eve($5), bcon(0)),
923                                     bcon($1));
924                         else
925                                 tfree(eve($5));
926                         plabel( brklab);
927                         reached = 1;
928                         resetbc(0);
929                 }
930                 |  forprefix .e ')' statement
931                         {  plabel( contlab );
932                             if( flostat&FCONT ) reached = 1;
933                             if( $2 ) ecomp( $2 );
934                             branch($1);
935                             plabel( brklab );
936                             if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
937                             else reached = 0;
938                             resetbc(0);
939                             symclear(blevel); /* if declaration inside for() */
940                             }
941                 | switchpart statement
942                         { if( reached ) branch( brklab );
943                             plabel( $1 );
944                             swend();
945                             plabel( brklab);
946                             if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
947                             resetbc(FCONT);
948                             }
949                 |  C_BREAK  ';' {
950                         if (brklab == NOLAB)
951                                 uerror("illegal break");
952                         else if (reached)
953                                 branch(brklab);
954                         flostat |= FBRK;
955                         reached = 0;
956                 }
957                 |  C_CONTINUE  ';' {
958                         if (contlab == NOLAB)
959                                 uerror("illegal continue");
960                         else
961                                 branch(contlab);
962                         flostat |= FCONT;
963                         goto rch;
964                 }
965                 |  C_RETURN  ';' {
966                         branch(retlab);
967                         if (cftnsp->stype != VOID && 
968                             (cftnsp->sflags & NORETYP) == 0 &&
969                             cftnsp->stype != VOID+FTN)
970                                 uerror("return value required");
971                         rch:
972                         if (!reached)
973                                 warner(Wunreachable_code, NULL);
974                         reached = 0;
975                 }
976                 |  C_RETURN e  ';' {
977                         NODE *p, *q;
978
979                         p = nametree(cftnsp);
980                         p->n_type = DECREF(p->n_type);
981                         q = eve($2);
982 #ifndef NO_COMPLEX
983                         if (ANYCX(q) || ANYCX(p))
984                                 q = cxret(q, p);
985 #endif
986                         p = buildtree(RETURN, p, q);
987                         if (p->n_type == VOID) {
988                                 ecomp(p->n_right);
989                         } else {
990                                 if (cftnod == NIL)
991                                         cftnod = tempnode(0, p->n_type,
992                                             p->n_df, p->n_ap);
993                                 ecomp(buildtree(ASSIGN,
994                                     ccopy(cftnod), p->n_right));
995                         }
996                         tfree(p->n_left);
997                         nfree(p);
998                         branch(retlab);
999                         reached = 0;
1000                 }
1001                 |  C_GOTO C_NAME ';' { gotolabel($2); goto rch; }
1002                 |  C_GOTO '*' e ';' { ecomp(biop(GOTO, eve($3), NIL)); }
1003                 |  asmstatement ';'
1004                 |   ';'
1005                 |  error  ';'
1006                 |  error '}'
1007                 |  label statement
1008                 ;
1009
1010 asmstatement:      C_ASM mvol '(' string ')' { send_passt(IP_ASM, mkpstr($4)); }
1011                 |  C_ASM mvol '(' string xasm ')' { mkxasm($4, $5); }
1012                 ;
1013
1014 mvol:              /* empty */
1015                 |  C_QUALIFIER { nfree($1); }
1016                 ;
1017
1018 xasm:              ':' oplist { $$ = xcmop($2, NIL, NIL); }
1019                 |  ':' oplist ':' oplist { $$ = xcmop($2, $4, NIL); }
1020                 |  ':' oplist ':' oplist ':' cnstr { $$ = xcmop($2, $4, $6); }
1021                 ;
1022
1023 oplist:            /* nothing */ { $$ = NIL; }
1024                 |  oper { $$ = $1; }
1025                 ;
1026
1027 oper:              string '(' e ')' { $$ = xasmop($1, eve($3)); }
1028                 |  oper ',' string '(' e ')' {
1029                         $$ = cmop($1, xasmop($3, eve($5)));
1030                 }
1031                 ;
1032
1033 cnstr:             string { $$ = xasmop($1, bcon(0)); }
1034                 |  cnstr ',' string { $$ = cmop($1, xasmop($3, bcon(0))); }
1035                 ;
1036
1037 label:             C_NAME ':' attr_var { deflabel($1, $3); reached = 1; }
1038                 |  C_TYPENAME ':' attr_var { deflabel($1, $3); reached = 1; }
1039                 |  C_CASE e ':' { addcase(eve($2)); reached = 1; }
1040 /* COMPAT_GCC */|  C_CASE e C_ELLIPSIS e ':' {
1041 #ifdef GCC_COMPAT
1042                         gcccase(eve($2), eve($4)); reached = 1;
1043 #endif
1044                 }
1045                 |  C_DEFAULT ':' { reached = 1; adddef(); flostat |= FDEF; }
1046                 ;
1047
1048 doprefix:       C_DO {
1049                         savebc();
1050                         brklab = getlab();
1051                         contlab = getlab();
1052                         plabel(  $$ = getlab());
1053                         reached = 1;
1054                 }
1055                 ;
1056 ifprefix:       C_IF '(' e ')' {
1057                         cbranch(buildtree(NOT, eve($3), NIL), bcon($$ = getlab()));
1058                         reached = 1;
1059                 }
1060                 ;
1061 ifelprefix:       ifprefix statement C_ELSE {
1062                         if (reached)
1063                                 branch($$ = getlab());
1064                         else
1065                                 $$ = NOLAB;
1066                         plabel( $1);
1067                         reached = 1;
1068                 }
1069                 ;
1070
1071 whprefix:         C_WHILE  '('  e  ')' {
1072                         savebc();
1073                         $3 = eve($3);
1074                         if ($3->n_op == ICON && $3->n_lval != 0)
1075                                 flostat = FLOOP;
1076                         plabel( contlab = getlab());
1077                         reached = 1;
1078                         brklab = getlab();
1079                         if (flostat == FLOOP)
1080                                 tfree($3);
1081                         else
1082                                 cbranch(buildtree(NOT, $3, NIL), bcon(brklab));
1083                 }
1084                 ;
1085 forprefix:        C_FOR  '('  .e  ';' .e  ';' {
1086                         if ($3)
1087                                 ecomp($3);
1088                         savebc();
1089                         contlab = getlab();
1090                         brklab = getlab();
1091                         plabel( $$ = getlab());
1092                         reached = 1;
1093                         if ($5)
1094                                 cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
1095                         else
1096                                 flostat |= FLOOP;
1097                 }
1098                 |  C_FOR '(' { ++blevel; } declaration .e ';' {
1099                         blevel--;
1100                         savebc();
1101                         contlab = getlab();
1102                         brklab = getlab();
1103                         plabel( $$ = getlab());
1104                         reached = 1;
1105                         if ($5)
1106                                 cbranch(buildtree(NOT, $5, NIL), bcon(brklab));
1107                         else
1108                                 flostat |= FLOOP;
1109                 }
1110                 ;
1111
1112 switchpart:        C_SWITCH  '('  e ')' {
1113                         NODE *p;
1114                         int num;
1115                         TWORD t;
1116
1117                         savebc();
1118                         brklab = getlab();
1119                         $3 = eve($3);
1120                         if (!ISINTEGER($3->n_type)) {
1121                                 uerror("switch expression must have integer "
1122                                        "type");
1123                                 t = INT;
1124                         } else {
1125                                 $3 = intprom($3);
1126                                 t = $3->n_type;
1127                         }
1128                         p = tempnode(0, t, 0, 0);
1129                         num = regno(p);
1130                         ecomp(buildtree(ASSIGN, p, $3));
1131                         branch( $$ = getlab());
1132                         swstart(num, t);
1133                         reached = 0;
1134                 }
1135                 ;
1136 /*      EXPRESSIONS     */
1137 .e:                e { $$ = eve($1); }
1138                 |       { $$=0; }
1139                 ;
1140
1141 elist:             { $$ = NIL; }
1142                 |  e %prec ','
1143                 |  elist  ','  e { $$ = biop(CM, $1, $3); }
1144                 |  elist  ','  cast_type { /* hack for stdarg */
1145                         TYMFIX($3);
1146                         $3->n_op = TYPE;
1147                         $$ = biop(CM, $1, $3);
1148                 }
1149                 ;
1150
1151 /*
1152  * Precedence order of operators.
1153  */
1154 e:                 e ',' e { $$ = biop(COMOP, $1, $3); }
1155                 |  e '=' e { $$ = biop(ASSIGN, $1, $3); }
1156                 |  e C_ASOP e { $$ = biop($2, $1, $3); }
1157                 |  e '?' e ':' e {
1158                         $$=biop(QUEST, $1, biop(COLON, $3, $5));
1159                 }
1160                 |  e '?' ':' e { 
1161                         NODE *p = tempnode(0, $1->n_type, $1->n_df, $1->n_ap);
1162                         $$ = biop(COLON, ccopy(p), $4);
1163                         $$=biop(QUEST, biop(ASSIGN, p, $1), $$);
1164                 }
1165                 |  e C_OROR e { $$ = biop($2, $1, $3); }
1166                 |  e C_ANDAND e { $$ = biop($2, $1, $3); }
1167                 |  e '|' e { $$ = biop(OR, $1, $3); }
1168                 |  e '^' e { $$ = biop(ER, $1, $3); }
1169                 |  e '&' e { $$ = biop(AND, $1, $3); }
1170                 |  e C_EQUOP  e { $$ = biop($2, $1, $3); }
1171                 |  e C_RELOP e { $$ = biop($2, $1, $3); }
1172                 |  e C_SHIFTOP e { $$ = biop($2, $1, $3); }
1173                 |  e '+' e { $$ = biop(PLUS, $1, $3); }
1174                 |  e '-' e { $$ = biop(MINUS, $1, $3); }
1175                 |  e C_DIVOP e { $$ = biop($2, $1, $3); }
1176                 |  e '*' e { $$ = biop(MUL, $1, $3); }
1177                 |  e '=' addrlbl { $$ = biop(ASSIGN, $1, $3); }
1178                 |  term
1179                 ;
1180
1181 xbegin:            begin {
1182                         $$ = getlab(); getlab(); getlab();
1183                         branch($$); plabel(($$)+1); }
1184                 ;
1185
1186 addrlbl:          C_ANDAND C_NAME {
1187 #ifdef GCC_COMPAT
1188                         struct symtab *s = lookup($2, SLBLNAME);
1189                         if (s->soffset == 0)
1190                                 s->soffset = -getlab();
1191                         $$ = buildtree(ADDROF, nametree(s), NIL);
1192 #else
1193                         uerror("gcc extension");
1194 #endif
1195                 }
1196                 ;
1197
1198 term:              term C_INCOP {  $$ = biop($2, $1, bcon(1)); }
1199                 |  '*' term { $$ = biop(UMUL, $2, NIL); }
1200                 |  '&' term { $$ = biop(ADDROF, $2, NIL); }
1201                 |  '-' term { $$ = biop(UMINUS, $2, NIL ); }
1202                 |  '+' term { $$ = biop(PLUS, $2, bcon(0)); }
1203                 |  CXX_CASTS C_RELOP cast_type C_RELOP '(' e ')' {
1204                         tfree($6);
1205                         tfree($3);
1206                         $$ = bcon(0);
1207                         werror("CXX_CASTS unhandled");
1208                 }
1209                 |  C_UNOP term { $$ = biop($1, $2, NIL); }
1210                 |  C_INCOP term {
1211                         $$ = biop($1 == INCR ? PLUSEQ : MINUSEQ, $2, bcon(1));
1212                 }
1213                 |  C_SIZEOF xa term { $$ = biop(SZOF, $3, bcon(0)); inattr = $<intval>2; }
1214                 |  '(' cast_type ')' term  %prec C_INCOP {
1215                         TYMFIX($2);
1216                         $$ = biop(CAST, $2, $4);
1217                 }
1218                 |  C_SIZEOF xa '(' cast_type ')'  %prec C_SIZEOF {
1219                         $$ = biop(SZOF, $4, bcon(1));
1220                         inattr = $<intval>2;
1221                 }
1222                 |  C_ALIGNOF xa '(' cast_type ')' {
1223                         int al;
1224                         TYMFIX($4);
1225                         al = talign($4->n_type, $4->n_ap);
1226                         $$ = bcon(al/SZCHAR);
1227                         inattr = $<intval>2;
1228                         tfree($4);
1229                 }
1230                 | '(' cast_type ')' clbrace init_list optcomma '}' {
1231                         endinit(0);
1232                         $$ = bdty(NAME, $4);
1233                         $$->n_op = CLOP;
1234                 }
1235                 | '(' cast_type ')' clbrace '}' {
1236                         endinit(0);
1237                         $$ = bdty(NAME, $4);
1238                         $$->n_op = CLOP;
1239                 }
1240                 |  term '[' e ']' {
1241                         if ($1->n_op == NEWKW) {
1242                                 $1->n_left = biop(LB, $1->n_left, $3);
1243                         } else
1244                                 $$ = biop(LB, $1, $3);
1245                 }
1246                 |  C_NAME  '(' elist ')' {
1247 #if 0
1248                         if ($3) tfree($3);
1249                         $$ = bcon(0);
1250 #else
1251                         $$ = biop($3 ? CALL : UCALL, bdty(NAME, $1), $3);
1252 #endif
1253                 }
1254                 |  term  '(' elist ')' { $$ = biop($3 ? CALL : UCALL, $1, $3); }
1255                 |  term C_STROP C_NAME { $$ = biop($2, $1, bdty(NAME, $3)); }
1256                 |  term C_STROP C_TYPENAME { $$ = biop($2, $1, bdty(NAME, $3));}
1257                 |  C_NAME %prec C_SIZEOF /* below ( */{ $$ = bdty(NAME, $1); }
1258                 |  nmrec C_NAME %prec C_SIZEOF {
1259                         $$ = biop(NMLIST, $1, bdty(NAME, $2));
1260                 }
1261                 |  PCC_OFFSETOF  '(' cast_type ',' term ')' {
1262                         TYMFIX($3);
1263                         $3->n_type = INCREF($3->n_type);
1264                         $3 = biop(CAST, $3, bcon(0));
1265                         if ($5->n_op == NAME) {
1266                                 $$ = biop(STREF, $3, $5);
1267                         } else {
1268                                 NODE *p = $5;
1269                                 while (p->n_left->n_op != NAME)
1270                                         p = p->n_left;
1271                                 p->n_left = biop(STREF, $3, p->n_left);
1272                                 $$ = $5;
1273                         }
1274                         $$ = biop(ADDROF, $$, NIL);
1275                         $3 = block(NAME, NIL, NIL, ENUNSIGN(INTPTR), 0, 0);
1276                         $$ = biop(CAST, $3, $$);
1277                 }
1278                 |  C_ICON { $$ = $1; }
1279                 |  C_FCON { $$ = $1; }
1280                 |  string { $$ = bdty(STRING, $1, widestr); }
1281                 |   '('  e  ')' { $$=$2; }
1282                 |  '(' xbegin block_item_list e ';' '}' ')' {
1283                         /* XXX - check recursive ({ }) statements */
1284                         branch(($2)+2);
1285                         plabel($2);
1286                         $$ = buildtree(COMOP,
1287                             biop(GOTO, bcon(($2)+1), NIL), eve($4));
1288                         flend();
1289                 }
1290                 |  '(' xbegin block_item_list '}' ')' { 
1291                         /* XXX - check recursive ({ }) statements */
1292                         branch(($2)+2);
1293                         plabel($2);
1294                         $$ = buildtree(COMOP,
1295                             biop(GOTO, bcon(($2)+1), NIL), voidcon());
1296                         flend();
1297                 }
1298                 |  CXX_NEW new_ds { $$ = biop(NEWKW, $2, bcon(0)); }
1299                 |  CXX_NEW '(' cast_type ')' { $$ = 0; uerror("new cast"); }
1300                 |  CXX_DELETE term %prec '-' {
1301                         $$ = biop(DELETE, $2, bcon(NM_DEL));
1302                 }
1303                 |  CXX_DELETE '[' ']' term %prec '-' {
1304                         $$ = biop(DELETE, $4, bcon(NM_DLA));
1305                 }
1306                 ;
1307
1308 nmrec:            CXX_MORENM { $$ = bdty(NAME, $1); }
1309                 | CXX_MORENM nmrec { $$ = biop(NMLIST, $2, bdty(NAME, $1)); }
1310                 ;
1311
1312 xa:               { $<intval>$ = inattr; inattr = 0; }
1313                 ;
1314
1315 clbrace:           '{'  { NODE *q = $<nodep>-1; TYMFIX(q); $$ = clbrace(q); }
1316                 ;
1317
1318 string:            C_STRING { widestr = 0; $$ = stradd("", $1); }
1319                 |  string C_STRING { $$ = stradd($1, $2); }
1320                 ;
1321
1322 cast_type:         specifier_qualifier_list {
1323                         $$ = biop(TYMERGE, $1, bdty(NAME, NULL));
1324                 }
1325                 |  specifier_qualifier_list abstract_declarator {
1326                         $$ = biop(TYMERGE, $1, aryfix($2));
1327                 }
1328                 ;
1329
1330 %%
1331
1332 NODE *
1333 mkty(TWORD t, union dimfun *d, struct attr *sue)
1334 {
1335    &n