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