1: /* 2: * C compiler 3: */ 4: 5: #include "c0.h" 6: 7: /* 8: * Process a single external definition 9: */ 10: extdef() 11: { 12: register o; 13: int sclass, scflag; 14: struct nmlist typer; 15: register struct nmlist *ds; 16: 17: if(((o=symbol())==EOFC) || o==SEMI) 18: return; 19: peeksym = o; 20: sclass = 0; 21: blklev = 0; 22: if (getkeywords(&sclass, &typer)==0) { 23: sclass = EXTERN; 24: if (peeksym!=NAME) 25: goto syntax; 26: } 27: scflag = 0; 28: if (sclass==DEFXTRN) { 29: scflag++; 30: sclass = EXTERN; 31: } 32: if (sclass!=EXTERN && sclass!=STATIC && sclass!=TYPEDEF) 33: error("Illegal storage class"); 34: do { 35: defsym = 0; 36: paraml = NULL; 37: parame = NULL; 38: if (sclass==TYPEDEF) { 39: decl1(TYPEDEF, &typer, 0, (struct nmlist *)NULL); 40: continue; 41: } 42: decl1(EXTERN, &typer, 0, (struct nmlist *)NULL); 43: if ((ds=defsym)==0) 44: return; 45: funcsym = ds; 46: if ((ds->htype&XTYPE)==FUNC) { 47: if ((peeksym=symbol())==LBRACE || peeksym==KEYW 48: || (peeksym==NAME && csym->hclass==TYPEDEF)) { 49: funcblk.type = decref(ds->htype); 50: funcblk.strp = ds->hstrp; 51: setinit(ds); 52: outcode("BS", SYMDEF, sclass==EXTERN?ds->name:""); 53: cfunc(); 54: return; 55: } 56: if (paraml) 57: error("Inappropriate parameters"); 58: } else if ((o=symbol())==COMMA || o==SEMI) { 59: peeksym = o; 60: o = (length((union tree *)ds)+ALIGN) & ~ALIGN; 61: if (sclass==STATIC) { 62: setinit(ds); 63: outcode("BSBBSBN", SYMDEF, "", BSS, NLABEL, ds->name, SSPACE, o); 64: } else if (scflag) 65: outcode("BSN", CSPACE, ds->name, o); 66: } else { 67: if (o!=ASSIGN) { 68: error("Declaration syntax"); 69: peeksym = o; 70: } 71: setinit(ds); 72: if (sclass==EXTERN) 73: outcode("BS", SYMDEF, ds->name); 74: outcode("BBS", DATA, NLABEL, ds->name); 75: if (cinit(ds, 1, sclass) & ALIGN) 76: outcode("B", EVEN); 77: } 78: } while ((o=symbol())==COMMA); 79: if (o==SEMI) 80: return; 81: syntax: 82: if (o==RBRACE) { 83: error("Too many }'s"); 84: peeksym = 0; 85: return; 86: } 87: error("External definition syntax"); 88: errflush(o); 89: statement(); 90: } 91: 92: /* 93: * Process a function definition. 94: */ 95: cfunc() 96: { 97: register char *cb; 98: register sloc; 99: 100: sloc = isn; 101: isn += 2; 102: outcode("BBS", PROG, RLABEL, funcsym->name); 103: regvar = 5; 104: autolen = STAUTO; 105: maxauto = STAUTO; 106: blklev = 1; 107: cb = locbase; 108: declist(ARG); 109: outcode("B", SAVE); 110: if (proflg) 111: outcode("BNS", PROFIL, isn++, funcsym->name); 112: funchead(); 113: branch(sloc); 114: label(sloc+1); 115: retlab = isn++; 116: blklev = 0; 117: if ((peeksym = symbol()) != LBRACE) 118: error("Compound statement required"); 119: statement(); 120: outcode("BNB", LABEL, retlab, RETRN); 121: label(sloc); 122: /* add STAUTO; overlay bug fix, coupled with section in c11.c */ 123: outcode("BN", SETSTK, -maxauto+STAUTO); 124: branch(sloc+1); 125: locbase = cb; 126: } 127: 128: /* 129: * Process the initializers for an external definition. 130: */ 131: cinit(anp, flex, sclass) 132: struct nmlist *anp; 133: { 134: struct nmlist np; 135: register nel, ninit; 136: int width, isarray, o, brace, realtype; 137: union tree *s; 138: 139: np = *anp; 140: realtype = np.htype; 141: isarray = 0; 142: if ((realtype&XTYPE) == ARRAY) 143: isarray++; 144: else 145: flex = 0; 146: width = length((union tree *)&np); 147: nel = 1; 148: /* 149: * If it's an array, find the number of elements. 150: * temporarily modify to look like kind of thing it's 151: * an array of. 152: */ 153: if (sclass==AUTO) 154: if (isarray || realtype==STRUCT) 155: error("No auto. aggregate initialization"); 156: if (isarray) { 157: np.htype = decref(realtype); 158: np.hsubsp++; 159: if (width==0 && flex==0) 160: error("0-length row: %s", anp->name); 161: o = length((union tree *)&np); 162: nel = (unsigned)width/o; 163: width = o; 164: } 165: brace = 0; 166: if ((peeksym=symbol())==LBRACE && (isarray || np.htype!=STRUCT)) { 167: peeksym = -1; 168: brace++; 169: } 170: ninit = 0; 171: do { 172: if ((o=symbol())==RBRACE) 173: break; 174: peeksym = o; 175: if (o==STRING && (realtype==ARRAY+CHAR || realtype==ARRAY+UNCHAR)) { 176: if (sclass==AUTO) 177: error("No strings in automatic"); 178: peeksym = -1; 179: putstr(0, flex?10000:nel); 180: ninit += nchstr; 181: o = symbol(); 182: break; 183: } else if (np.htype==STRUCT) { 184: strinit(&np, sclass); 185: } else if ((np.htype&ARRAY)==ARRAY || peeksym==LBRACE) 186: cinit(&np, 0, sclass); 187: else { 188: char *st; 189: initflg++; 190: st = starttree(); 191: s = tree(0); 192: initflg = 0; 193: if (np.hflag&FFIELD) 194: error("No field initialization"); 195: *cp++ = nblock(&np); 196: *cp++ = s; 197: build(ASSIGN); 198: if (sclass==AUTO||sclass==REG) 199: rcexpr(*--cp); 200: else if (sclass==ENUMCON) { 201: if (s->t.op!=CON) 202: error("Illegal enum constant for %s", anp->name); 203: anp->hoffset = s->c.value; 204: } else 205: rcexpr(block(INIT,np.htype,(int *)NULL, 206: (union str *)NULL, (*--cp)->t.tr2, TNULL)); 207: endtree(st); 208: } 209: ninit++; 210: if ((ninit&077)==0 && sclass==EXTERN) 211: outcode("BS", SYMDEF, ""); 212: } while ((o=symbol())==COMMA && (ninit<nel || brace || flex)); 213: if (brace==0 || o!=RBRACE) 214: peeksym = o; 215: /* 216: * If there are too few initializers, allocate 217: * more storage. 218: * If there are too many initializers, extend 219: * the declared size for benefit of "sizeof" 220: */ 221: if (ninit<nel && sclass!=AUTO) 222: outcode("BN", SSPACE, (nel-ninit)*width); 223: else if (ninit>nel) { 224: if (flex && nel==0) { 225: np.hsubsp[-1] = ninit; 226: } else 227: error("Too many initializers: %s", anp->name); 228: nel = ninit; 229: } 230: return(nel*width); 231: } 232: 233: /* 234: * Initialize a structure 235: */ 236: strinit(np, sclass) 237: struct nmlist *np; 238: { 239: static struct nmlist junk; 240: register struct nmlist **mlp; 241: static struct nmlist *zerloc = NULL; 242: register int o, brace; 243: 244: if ((mlp = np->hstrp->S.memlist)==NULL) { 245: mlp = &zerloc; 246: error("Undefined structure initialization"); 247: } 248: brace = 0; 249: if ((o = symbol()) == LBRACE) 250: brace++; 251: else 252: peeksym = o; 253: do { 254: if ((o=symbol()) == RBRACE) 255: break; 256: peeksym = o; 257: if (*mlp==0) { 258: error("Too many structure initializers"); 259: cinit(&junk, 0, sclass); 260: } else 261: cinit(*mlp++, 0, sclass); 262: if (*mlp == &structhole) { 263: outcode("B", EVEN); 264: mlp++; 265: } 266: /* DAG -- union initialization bug fix */ 267: if (*mlp && mlp[-1]->hoffset == (*mlp)->hoffset) { 268: werror("union initialization non-portable"); 269: while (*mlp) /* will NOT be &structhole */ 270: mlp++; /* skip other members of union */ 271: } 272: } while ((o=symbol())==COMMA && (*mlp || brace)); 273: if (sclass!=AUTO && sclass!=REG) { 274: if (*mlp) 275: outcode("BN", SSPACE, np->hstrp->S.ssize - (*mlp)->hoffset); 276: outcode("B", EVEN); 277: } 278: if (o!=RBRACE || brace==0) 279: peeksym = o; 280: } 281: 282: /* 283: * Mark already initialized 284: */ 285: setinit(np) 286: register struct nmlist *np; 287: { 288: 289: if (np->hflag&FINIT) 290: error("%s multiply defined", np->name); 291: np->hflag |= FINIT; 292: } 293: 294: /* 295: * Process one statement in a function. 296: */ 297: statement() 298: { 299: register o, o1; 300: int sauto, sreg; 301: 302: stmt: 303: switch(o=symbol()) { 304: 305: case EOFC: 306: error("Unexpected EOF"); 307: case SEMI: 308: return; 309: 310: case LBRACE: 311: sauto = autolen; 312: sreg = regvar; 313: blockhead(); 314: while (!eof) { 315: if ((o=symbol())==RBRACE) { 316: autolen = sauto; 317: if (sreg!=regvar) 318: outcode("BN", SETREG, sreg); 319: regvar = sreg; 320: blkend(); 321: return; 322: } 323: peeksym = o; 324: statement(); 325: } 326: error("Missing '}'"); 327: return; 328: 329: case KEYW: 330: switch(cval) { 331: 332: case GOTO: 333: if (o1 = simplegoto()) 334: branch(o1); 335: else 336: dogoto(); 337: goto semi; 338: 339: case RETURN: 340: doret(); 341: goto semi; 342: 343: case ASM: 344: { 345: char tmp[80], /* tmp for line buffer */ 346: *p; 347: 348: if (symbol() != LPARN || (o1 = symbol()) != STRING) 349: goto syntax; 350: for (p = tmp; (o1 = mapch('"')) >= 0; ) 351: *p++ = o1&0177; 352: *p = '\0'; 353: if (symbol() != RPARN) 354: goto syntax; 355: outcode("BF", ASSEM, tmp); 356: goto semi; 357: } 358: 359: case IF: { 360: register o2; 361: register union tree *np; 362: 363: np = pexpr(1); 364: o2 = 0; 365: if ((o1=symbol())==KEYW) switch (cval) { 366: case GOTO: 367: if (o2=simplegoto()) 368: goto simpif; 369: cbranch(np, o2=isn++, 0); 370: dogoto(); 371: label(o2); 372: goto hardif; 373: 374: case RETURN: 375: if (nextchar()==';') { 376: o2 = retlab; 377: goto simpif; 378: } 379: cbranch(np, o1=isn++, 0); 380: doret(); 381: label(o1); 382: o2++; 383: goto hardif; 384: 385: case BREAK: 386: o2 = brklab; 387: goto simpif; 388: 389: case CONTIN: 390: o2 = contlab; 391: simpif: 392: chconbrk(o2); 393: cbranch(np, o2, 1); 394: hardif: 395: if ((o=symbol())!=SEMI) 396: goto syntax; 397: if ((o1=symbol())==KEYW && cval==ELSE) 398: goto stmt; 399: peeksym = o1; 400: return; 401: } 402: peeksym = o1; 403: cbranch(np, o1=isn++, 0); 404: statement(); 405: if ((o=symbol())==KEYW && cval==ELSE) { 406: o2 = isn++; 407: branch(o2); 408: label(o1); 409: statement(); 410: label(o2); 411: return; 412: } 413: peeksym = o; 414: label(o1); 415: return; 416: } 417: 418: case WHILE: { 419: register o2; 420: o1 = contlab; 421: o2 = brklab; 422: label(contlab = isn++); 423: cbranch(pexpr(1), brklab=isn++, 0); 424: statement(); 425: branch(contlab); 426: label(brklab); 427: contlab = o1; 428: brklab = o2; 429: return; 430: } 431: 432: case BREAK: 433: chconbrk(brklab); 434: branch(brklab); 435: goto semi; 436: 437: case CONTIN: 438: chconbrk(contlab); 439: branch(contlab); 440: goto semi; 441: 442: case DO: { 443: register int o2, o3; 444: o1 = contlab; 445: o2 = brklab; 446: contlab = isn++; 447: brklab = isn++; 448: label(o3 = isn++); 449: statement(); 450: label(contlab); 451: contlab = o1; 452: if ((o=symbol())==KEYW && cval==WHILE) { 453: cbranch(tree(1), o3, 1); 454: label(brklab); 455: brklab = o2; 456: goto semi; 457: } 458: goto syntax; 459: } 460: 461: case CASE: 462: o1 = conexp(); 463: if ((o=symbol())!=COLON) 464: goto syntax; 465: if (swp==0) { 466: error("Case not in switch"); 467: goto stmt; 468: } 469: if(swp>=swtab+SWSIZ) { 470: error("Switch table overflow"); 471: } else { 472: swp->swlab = isn; 473: (swp++)->swval = o1; 474: label(isn++); 475: } 476: goto stmt; 477: 478: case SWITCH: { 479: register union tree *np; 480: register char *st; 481: 482: o1 = brklab; 483: brklab = isn++; 484: st = starttree(); 485: np = pexpr(0); 486: chkw(np, -1); 487: rcexpr(block(RFORCE,0,(int *)NULL,(union str *)NULL,np,TNULL)); 488: endtree(st); 489: pswitch(); 490: brklab = o1; 491: return; 492: } 493: 494: case DEFAULT: 495: if (swp==0) 496: error("Default not in switch"); 497: if (deflab) 498: error("More than 1 'default'"); 499: if ((o=symbol())!=COLON) 500: goto syntax; 501: label(deflab = isn++); 502: goto stmt; 503: 504: case FOR: { 505: register int o2; 506: o1 = contlab; 507: o2 = brklab; 508: contlab = isn++; 509: brklab = isn++; 510: if (o=forstmt()) 511: goto syntax; 512: contlab = o1; 513: brklab = o2; 514: return; 515: } 516: 517: case ELSE: 518: error("Inappropriate 'else'"); 519: statement(); 520: return; 521: } 522: error("Unknown keyword"); 523: goto syntax; 524: 525: case NAME: { 526: register struct nmlist *np; 527: if (nextchar()==':') { 528: peekc = 0; 529: np = csym; 530: if (np->hclass>0) { 531: if (np->hblklev==0) { 532: np = pushdecl(np); 533: np->hoffset = 0; 534: } else { 535: defsym = np; 536: redec(); 537: goto stmt; 538: } 539: } 540: np->hclass = STATIC; 541: np->htype = ARRAY; 542: np->hflag |= FLABL; 543: if (np->hoffset==0) 544: np->hoffset = isn++; 545: label(np->hoffset); 546: goto stmt; 547: } 548: } 549: } 550: peeksym = o; 551: rcexpr(tree(1)); 552: 553: semi: 554: if ((o=symbol())==SEMI) 555: return; 556: syntax: 557: error("Statement syntax"); 558: errflush(o); 559: } 560: 561: /* 562: * Process a for statement. 563: */ 564: forstmt() 565: { 566: register int o; 567: register union tree *st; 568: register l; 569: char *ss; 570: 571: if ((o=symbol()) != LPARN) 572: return(o); 573: if ((o=symbol()) != SEMI) { /* init part */ 574: peeksym = o; 575: rcexpr(tree(1)); 576: if ((o=symbol()) != SEMI) 577: return(o); 578: } 579: l = isn; 580: isn += 3; 581: branch(l+0); 582: label(l+1); 583: branch(l+2); 584: label(contlab); 585: st = NULL; 586: if ((o=symbol()) != SEMI) { /* test part */ 587: peeksym = o; 588: ss = starttree(); 589: st = tree(0); 590: if ((o=symbol()) != SEMI) { 591: endtree(ss); 592: return(o); 593: } 594: } 595: if ((o=symbol()) != RPARN) { /* incr part */ 596: peeksym = o; 597: rcexpr(tree(1)); 598: if ((o=symbol()) != RPARN) { 599: if (st) 600: endtree(ss); 601: return(o); 602: } 603: } 604: label(l+0); 605: if (st) { 606: cbranch(st, l+1, 1); 607: endtree(ss); 608: } else 609: branch(l+1); 610: branch(brklab); 611: label(l+2); 612: statement(); 613: branch(contlab); 614: label(brklab); 615: return(0); 616: } 617: 618: /* 619: * A parenthesized expression, 620: * as after "if". 621: */ 622: union tree * 623: pexpr(eflag) 624: { 625: register o; 626: register union tree *t; 627: 628: if ((o=symbol())!=LPARN) 629: goto syntax; 630: t = tree(eflag); 631: if ((o=symbol())!=RPARN) 632: goto syntax; 633: if (t->t.type==VOID) 634: error("Illegal use of void"); 635: return(t); 636: syntax: 637: error("Statement syntax"); 638: errflush(o); 639: return(0); 640: } 641: 642: /* 643: * The switch statement, which involves collecting the 644: * constants and labels for the cases. 645: */ 646: pswitch() 647: { 648: register struct swtab *cswp, *sswp; 649: int dl, swlab; 650: 651: cswp = sswp = swp; 652: if (swp==0) 653: cswp = swp = swtab; 654: branch(swlab=isn++); 655: dl = deflab; 656: deflab = 0; 657: statement(); 658: branch(brklab); 659: label(swlab); 660: if (deflab==0) 661: deflab = brklab; 662: outcode("BNN", SWIT, deflab, line); 663: for (; cswp < swp; cswp++) 664: outcode("NN", cswp->swlab, cswp->swval); 665: outcode("0"); 666: label(brklab); 667: deflab = dl; 668: swp = sswp; 669: } 670: 671: /* 672: * funchead is called at the start of each function 673: * to process the arguments, which have been linked in a list. 674: * This list is necessary because in 675: * f(a, b) float b; int a; ... 676: * the names are seen before the types. 677: */ 678: /* 679: * Structure resembling a block for a register variable. 680: */ 681: struct nmlist hreg = { REG, 0, 0, NULL, NULL, 0 }; 682: struct tnode areg = { NAME, 0, NULL, NULL, (union tree *)&hreg}; 683: funchead() 684: { 685: register pl; 686: register struct nmlist *cs; 687: register char *st; 688: 689: pl = STARG; 690: while(paraml) { 691: parame->sparent = NULL; 692: cs = paraml; 693: paraml = ¶ml->sparent->P; 694: if (cs->htype==FLOAT) 695: cs->htype = DOUBLE; 696: cs->hoffset = pl; 697: if ((cs->htype&XTYPE) == ARRAY) { 698: cs->htype -= (ARRAY-PTR); /* set ptr */ 699: cs->hsubsp++; /* pop dims */ 700: } 701: pl += rlength((union tree *)cs); 702: if (cs->hclass==AREG && (hreg.hoffset=goodreg(cs))>=0) { 703: st = starttree(); 704: *cp++ = (union tree *)&areg; 705: *cp++ = nblock(cs); 706: areg.type = cs->htype; 707: areg.strp = cs->hstrp; 708: cs->hclass = AUTO; 709: build(ASSIGN); 710: rcexpr(*--cp); 711: cs->hoffset = hreg.hoffset; 712: cs->hclass = REG; 713: endtree(st); 714: } else 715: cs->hclass = AUTO; 716: prste(cs); 717: } 718: for (pl=0; pl<HSHSIZ; pl++) { 719: for (cs = hshtab[pl]; cs!=NULL; cs = cs->nextnm) { 720: if (cs->hclass == ARG || cs->hclass==AREG) 721: error("Not an argument: %s", cs->name); 722: } 723: } 724: outcode("BN", SETREG, regvar); 725: } 726: 727: blockhead() 728: { 729: register r; 730: 731: r = regvar; 732: blklev++; 733: declist(0); 734: if (r != regvar) 735: outcode("BN", SETREG, regvar); 736: } 737: 738: /* 739: * After the end of a block, delete local 740: * symbols; 741: * Also complain about undefined labels. 742: */ 743: blkend() 744: { 745: register struct nmlist *cs, **lcs; 746: register i; 747: 748: blklev--; 749: for (i = 0; i < HSHSIZ; i++) { 750: lcs = &hshtab[i]; 751: cs = *lcs; 752: while (cs) { 753: if (cs->hblklev > blklev 754: && (((cs->hflag&FLABL)==0 && cs->hclass!=EXTERN) || blklev<=0)) { 755: if (cs->hclass==0) 756: error("%s undefined", cs->name); 757: if (cs->hclass==EXTERN) 758: nameconflict(hshtab[i], cs); 759: *lcs = cs->nextnm; 760: } else 761: lcs = &cs->nextnm; 762: cs = cs->nextnm; 763: } 764: } 765: } 766: 767: nameconflict(ocs, cs) 768: register struct nmlist *ocs, *cs; 769: { 770: 771: for (; ocs!=NULL; ocs = ocs->nextnm) 772: if (ocs!=cs && ocs->hclass==EXTERN && 773: strncmp(cs->name, ocs->name, MAXCPS-1) == 0) 774: error("names %s and %s conflict", cs->name, ocs->name); 775: } 776: 777: /* 778: * write out special definitions of local symbols for 779: * benefit of the debugger. None of these are used 780: * by the assembler except to save them. 781: */ 782: prste(cs) 783: struct nmlist *cs; 784: { 785: register nkind; 786: 787: switch (cs->hclass) { 788: case REG: 789: nkind = RNAME; 790: break; 791: 792: case AUTO: 793: nkind = ANAME; 794: break; 795: 796: case STATIC: 797: nkind = SNAME; 798: break; 799: 800: default: 801: return; 802: 803: } 804: outcode("BSN", nkind, cs->name, cs->hoffset); 805: } 806: 807: /* 808: * In case of error, skip to the next 809: * statement delimiter. 810: */ 811: errflush(ao) 812: { 813: register o; 814: 815: o = ao; 816: while(o>RBRACE) { /* ; { } */ 817: if (o==STRING) 818: putstr(0, 0); 819: o = symbol(); 820: } 821: peeksym = o; 822: }