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