1: # 2: /* C compiler 3: * 4: * 5: */ 6: 7: #include "c0h.c" 8: 9: /* 10: * Process a single external definition 11: */ 12: extdef() 13: { 14: register o, elsize; 15: int type, sclass; 16: register struct hshtab *ds; 17: 18: if(((o=symbol())==EOF) || o==SEMI) 19: return; 20: peeksym = o; 21: type = INT; 22: sclass = EXTERN; 23: xdflg = FNDEL; 24: if ((elsize = getkeywords(&sclass, &type)) == -1 && peeksym!=NAME) 25: goto syntax; 26: if (type==STRUCT) 27: blkhed(); 28: do { 29: defsym = 0; 30: decl1(EXTERN, type, 0, elsize); 31: if ((ds=defsym)==0) 32: return; 33: funcsym = ds; 34: ds->hflag =| FNDEL; 35: outcode("BS", SYMDEF, ds->name); 36: xdflg = 0; 37: if ((ds->type&XTYPE)==FUNC) { 38: if ((peeksym=symbol())==LBRACE || peeksym==KEYW) { 39: funcblk.type = decref(ds->type); 40: cfunc(ds->name); 41: return; 42: } 43: } else 44: cinit(ds); 45: } while ((o=symbol())==COMMA); 46: if (o==SEMI) 47: return; 48: syntax: 49: if (o==RBRACE) { 50: error("Too many }'s"); 51: peeksym = 0; 52: return; 53: } 54: error("External definition syntax"); 55: errflush(o); 56: statement(0); 57: } 58: 59: /* 60: * Process a function definition. 61: */ 62: cfunc(cs) 63: char *cs; 64: { 65: register savdimp; 66: 67: savdimp = dimp; 68: outcode("BBS", PROG, RLABEL, cs); 69: declist(ARG); 70: regvar = 5; 71: retlab = isn++; 72: if ((peeksym = symbol()) != LBRACE) 73: error("Compound statement required"); 74: statement(1); 75: outcode("BNB", LABEL, retlab, RETRN); 76: dimp = savdimp; 77: } 78: 79: /* 80: * Process the initializers for an external definition. 81: */ 82: cinit(ds) 83: struct hshtab *ds; 84: { 85: register basetype, nel, ninit; 86: int o, width, realwidth; 87: 88: nel = 1; 89: basetype = ds->type; 90: /* 91: * If it's an array, find the number of elements. 92: * "basetype" is the type of thing it's an array of. 93: */ 94: while ((basetype&XTYPE)==ARRAY) { 95: if ((nel = dimtab[ds->ssp&0377])==0) 96: nel = 1; 97: basetype = decref(basetype); 98: } 99: realwidth = width = length(ds) / nel; 100: /* 101: * Pretend a structure is kind of an array of integers. 102: * This is a kludge. 103: */ 104: if (basetype==STRUCT) { 105: nel =* realwidth/2; 106: width = 2; 107: } 108: if ((peeksym=symbol())==COMMA || peeksym==SEMI) { 109: outcode("BSN",CSPACE,ds->name,(nel*width+ALIGN)&~ALIGN); 110: return; 111: } 112: ninit = 0; 113: outcode("BBS", DATA, NLABEL, ds->name); 114: if ((o=symbol())==LBRACE) { 115: do 116: ninit = cinit1(ds, basetype, width, ninit, nel); 117: while ((o=symbol())==COMMA); 118: if (o!=RBRACE) 119: peeksym = o; 120: } else { 121: peeksym = o; 122: ninit = cinit1(ds, basetype, width, 0, nel); 123: } 124: /* 125: * Above we pretended that a structure was a bunch of integers. 126: * Readjust in accordance with reality. 127: * First round up partial initializations. 128: */ 129: if (basetype==STRUCT) { 130: if (o = 2*ninit % realwidth) 131: outcode("BN", SSPACE, realwidth-o); 132: ninit = (2*ninit+realwidth-2) / realwidth; 133: nel =/ realwidth/2; 134: } 135: /* 136: * If there are too few initializers, allocate 137: * more storage. 138: * If there are too many initializers, extend 139: * the declared size for benefit of "sizeof" 140: */ 141: if (ninit<nel) 142: outcode("BN", SSPACE, (nel-ninit)*realwidth); 143: else if (ninit>nel) { 144: if ((ds->type&XTYPE)==ARRAY) 145: dimtab[ds->ssp&0377] = ninit; 146: nel = ninit; 147: } 148: /* 149: * If it's not an array, only one initializer is allowed. 150: */ 151: if (ninit>1 && (ds->type&XTYPE)!=ARRAY) 152: error("Too many initializers"); 153: if (((nel&width)&ALIGN)) 154: outcode("B", EVEN); 155: } 156: 157: /* 158: * Process a single expression in a sequence of initializers 159: * for an external. Mainly, it's for checking 160: * type compatibility. 161: */ 162: cinit1(ds, type, awidth, aninit, nel) 163: struct hshtab *ds; 164: { 165: float sf; 166: register struct tnode *s; 167: register width, ninit; 168: 169: width = awidth; 170: ninit = aninit; 171: if ((peeksym=symbol())==STRING && type==CHAR) { 172: peeksym = -1; 173: if (ninit) 174: bxdec(); 175: putstr(0); 176: if (nel>nchstr) { 177: strflg++; 178: outcode("BN", SSPACE, nel-nchstr); 179: strflg = 0; 180: nchstr = nel; 181: } 182: return(nchstr); 183: } 184: if (peeksym==RBRACE) 185: return(ninit); 186: initflg++; 187: s = tree(); 188: initflg = 0; 189: switch(width) { 190: 191: case 1: 192: if (s->op != CON) 193: goto bad; 194: outcode("B1N0", BDATA, s->value); 195: break; 196: 197: case 2: 198: if (s->op==CON) { 199: outcode("B1N0", WDATA, s->value); 200: break; 201: } 202: if (s->op==FCON || s->op==SFCON) { 203: if (type==STRUCT) { 204: ninit =+ 3; 205: goto prflt; 206: } 207: goto bad; 208: } 209: rcexpr(block(1,INIT,0,0,s)); 210: break; 211: 212: case 4: 213: sf = fcval; 214: outcode("B1N1N0", WDATA, sf); 215: goto flt; 216: 217: case 8: 218: prflt: 219: outcode("B1N1N1N1N0", WDATA, fcval); 220: flt: 221: if (s->op==FCON || s->op==SFCON) 222: break; 223: 224: default: 225: bad: 226: bxdec(); 227: 228: } 229: return(++ninit); 230: } 231: 232: bxdec() 233: { 234: error("Inconsistent external initialization"); 235: } 236: 237: /* 238: * Process one statement in a function. 239: */ 240: statement(d) 241: { 242: register o, o1, o2; 243: int o3, o4; 244: struct tnode *np; 245: 246: stmt: 247: switch(o=symbol()) { 248: 249: case EOF: 250: error("Unexpected EOF"); 251: case SEMI: 252: return; 253: 254: case LBRACE: 255: if (d) { 256: if (proflg) 257: outcode("BN", PROFIL, isn++); 258: outcode("BN", SAVE, blkhed()); 259: } 260: while (!eof) { 261: if ((o=symbol())==RBRACE) 262: return; 263: peeksym = o; 264: statement(0); 265: } 266: error("Missing '}'"); 267: return; 268: 269: case KEYW: 270: switch(cval) { 271: 272: case GOTO: 273: if (o1 = simplegoto()) 274: branch(o1); 275: else 276: dogoto(); 277: goto semi; 278: 279: case RETURN: 280: doret(); 281: goto semi; 282: 283: case IF: 284: np = pexpr(); 285: o2 = 0; 286: if ((o1=symbol())==KEYW) switch (cval) { 287: case GOTO: 288: if (o2=simplegoto()) 289: goto simpif; 290: cbranch(np, o2=isn++, 0); 291: dogoto(); 292: label(o2); 293: goto hardif; 294: 295: case RETURN: 296: if (nextchar()==';') { 297: o2 = retlab; 298: goto simpif; 299: } 300: cbranch(np, o1=isn++, 0); 301: doret(); 302: label(o1); 303: o2++; 304: goto hardif; 305: 306: case BREAK: 307: o2 = brklab; 308: goto simpif; 309: 310: case CONTIN: 311: o2 = contlab; 312: simpif: 313: chconbrk(o2); 314: cbranch(np, o2, 1); 315: hardif: 316: if ((o=symbol())!=SEMI) 317: goto syntax; 318: if ((o1=symbol())==KEYW && cval==ELSE) 319: goto stmt; 320: peeksym = o1; 321: return; 322: } 323: peeksym = o1; 324: cbranch(np, o1=isn++, 0); 325: statement(0); 326: if ((o=symbol())==KEYW && cval==ELSE) { 327: o2 = isn++; 328: branch(o2); 329: label(o1); 330: statement(0); 331: label(o2); 332: return; 333: } 334: peeksym = o; 335: label(o1); 336: return; 337: 338: case WHILE: 339: o1 = contlab; 340: o2 = brklab; 341: label(contlab = isn++); 342: cbranch(pexpr(), brklab=isn++, 0); 343: statement(0); 344: branch(contlab); 345: label(brklab); 346: contlab = o1; 347: brklab = o2; 348: return; 349: 350: case BREAK: 351: chconbrk(brklab); 352: branch(brklab); 353: goto semi; 354: 355: case CONTIN: 356: chconbrk(contlab); 357: branch(contlab); 358: goto semi; 359: 360: case DO: 361: o1 = contlab; 362: o2 = brklab; 363: contlab = isn++; 364: brklab = isn++; 365: label(o3 = isn++); 366: statement(0); 367: label(contlab); 368: contlab = o1; 369: if ((o=symbol())==KEYW && cval==WHILE) { 370: cbranch(tree(), o3, 1); 371: label(brklab); 372: brklab = o2; 373: goto semi; 374: } 375: goto syntax; 376: 377: case CASE: 378: o1 = conexp(); 379: if ((o=symbol())!=COLON) 380: goto syntax; 381: if (swp==0) { 382: error("Case not in switch"); 383: goto stmt; 384: } 385: if(swp>=swtab+swsiz) { 386: error("Switch table overflow"); 387: } else { 388: swp->swlab = isn; 389: (swp++)->swval = o1; 390: label(isn++); 391: } 392: goto stmt; 393: 394: case SWITCH: 395: o1 = brklab; 396: brklab = isn++; 397: np = pexpr(); 398: chkw(np, -1); 399: rcexpr(block(1,RFORCE,0,0,np)); 400: pswitch(); 401: brklab = o1; 402: return; 403: 404: case DEFAULT: 405: if (swp==0) 406: error("Default not in switch"); 407: if ((o=symbol())!=COLON) 408: goto syntax; 409: label(deflab = isn++); 410: goto stmt; 411: 412: case FOR: 413: o1 = contlab; 414: o2 = brklab; 415: contlab = isn++; 416: brklab = isn++; 417: if (o=forstmt()) 418: goto syntax; 419: label(brklab); 420: contlab = o1; 421: brklab = o2; 422: return; 423: } 424: 425: error("Unknown keyword"); 426: goto syntax; 427: 428: case NAME: 429: if (nextchar()==':') { 430: peekc = 0; 431: o1 = csym; 432: if (o1->hclass>0) { 433: error("Redefinition"); 434: goto stmt; 435: } 436: o1->hclass = STATIC; 437: o1->htype = ARRAY; 438: if (o1->hoffset==0) 439: o1->hoffset = isn++; 440: label(o1->hoffset); 441: goto stmt; 442: } 443: } 444: peeksym = o; 445: rcexpr(tree()); 446: 447: semi: 448: if ((o=symbol())==SEMI) 449: return; 450: syntax: 451: error("Statement syntax"); 452: errflush(o); 453: } 454: 455: /* 456: * Process a for statement. 457: */ 458: forstmt() 459: { 460: register int l, o, sline; 461: int sline1, *ss; 462: struct tnode *st; 463: 464: if ((o=symbol()) != LPARN) 465: return(o); 466: if ((o=symbol()) != SEMI) { /* init part */ 467: peeksym = o; 468: rcexpr(tree()); 469: if ((o=symbol()) != SEMI) 470: return(o); 471: } 472: label(contlab); 473: if ((o=symbol()) != SEMI) { /* test part */ 474: peeksym = o; 475: rcexpr(block(1,CBRANCH,tree(),brklab,0)); 476: if ((o=symbol()) != SEMI) 477: return(o); 478: } 479: if ((peeksym=symbol()) == RPARN) { /* incr part */ 480: peeksym = -1; 481: statement(0); 482: branch(contlab); 483: return(0); 484: } 485: l = contlab; 486: contlab = isn++; 487: st = tree(); 488: sline = line; 489: if ((o=symbol()) != RPARN) 490: return(o); 491: ss = treespace; 492: treespace = space; 493: statement(0); 494: sline1 = line; 495: line = sline; 496: label(contlab); 497: rcexpr(st); 498: line = sline1; 499: treespace = ss; 500: branch(l); 501: return(0); 502: } 503: 504: /* 505: * A parenthesized expression, 506: * as after "if". 507: */ 508: pexpr() 509: { 510: register o, t; 511: 512: if ((o=symbol())!=LPARN) 513: goto syntax; 514: t = tree(); 515: if ((o=symbol())!=RPARN) 516: goto syntax; 517: return(t); 518: syntax: 519: error("Statement syntax"); 520: errflush(o); 521: return(0); 522: } 523: 524: /* 525: * The switch stateent, which involves collecting the 526: * constants and labels for the cases. 527: */ 528: pswitch() 529: { 530: register struct swtab *cswp, *sswp; 531: int dl, swlab; 532: 533: cswp = sswp = swp; 534: if (swp==0) 535: cswp = swp = swtab; 536: branch(swlab=isn++); 537: dl = deflab; 538: deflab = 0; 539: statement(0); 540: branch(brklab); 541: label(swlab); 542: if (deflab==0) 543: deflab = brklab; 544: outcode("BNN", SWIT, deflab, line); 545: for (; cswp < swp; cswp++) 546: outcode("NN", cswp->swlab, cswp->swval); 547: outcode("0"); 548: label(brklab); 549: deflab = dl; 550: swp = sswp; 551: } 552: 553: /* 554: * blkhed is called at the start of each function. 555: * It reads the declarations at the start; 556: * then assigns storage locations for the 557: * parameters (which have been linked into a list, 558: * in order of appearance). 559: * This list is necessary because in 560: * f(a, b) float b; int a; ... 561: * the names are seen before the types. 562: * Also, the routine adjusts structures involved 563: * in some kind of forward-referencing. 564: */ 565: blkhed() 566: { 567: register pl; 568: register struct hshtab *cs; 569: 570: autolen = 6; 571: declist(0); 572: pl = 4; 573: while(paraml) { 574: parame->hoffset = 0; 575: cs = paraml; 576: paraml = paraml->hoffset; 577: if (cs->htype==FLOAT) 578: cs->htype = DOUBLE; 579: cs->hoffset = pl; 580: cs->hclass = AUTO; 581: if ((cs->htype&XTYPE) == ARRAY) { 582: cs->htype =- (ARRAY-PTR); /* set ptr */ 583: cs->ssp++; /* pop dims */ 584: } 585: pl =+ rlength(cs); 586: } 587: for (cs=hshtab; cs<hshtab+hshsiz; cs++) { 588: if (cs->name[0] == '\0') 589: continue; 590: /* check tagged structure */ 591: if (cs->hclass>KEYWC && (cs->htype&TYPE)==RSTRUCT) { 592: cs->lenp = dimtab[cs->lenp&0377]->lenp; 593: cs->htype = cs->htype&~TYPE | STRUCT; 594: } 595: if (cs->hclass == STRTAG && dimtab[cs->lenp&0377]==0) 596: error("Undefined structure: %.8s", cs->name); 597: if (cs->hclass == ARG) 598: error("Not an argument: %.8s", cs->name); 599: if (stflg) 600: prste(cs); 601: } 602: space = treespace; 603: outcode("BN", SETREG, regvar); 604: return(autolen); 605: } 606: 607: /* 608: * After a function definition, delete local 609: * symbols. 610: * Also complain about undefineds. 611: */ 612: blkend() { 613: register struct hshtab *cs; 614: 615: for (cs=hshtab; cs<hshtab+hshsiz; cs++) { 616: if (cs->name[0]) { 617: if (cs->hclass==0 && (cs->hflag&FNUND)==0) { 618: error("%.8s undefined", cs->name); 619: cs->hflag =| FNUND; 620: } 621: if((cs->hflag&FNDEL)==0) { 622: cs->name[0] = '\0'; 623: hshused--; 624: cs->hflag =& ~(FNUND|FFIELD); 625: } 626: } 627: } 628: } 629: 630: /* 631: * write out special definitions of local symbols for 632: * benefit of the debugger. None of these are used 633: * by the assembler except to save them. 634: */ 635: prste(acs) 636: { 637: register struct hshtab *cs; 638: register nkind; 639: 640: cs = acs; 641: switch (cs->hclass) { 642: case REG: 643: nkind = RNAME; 644: break; 645: 646: case AUTO: 647: nkind = ANAME; 648: break; 649: 650: case STATIC: 651: nkind = SNAME; 652: break; 653: 654: default: 655: return; 656: 657: } 658: outcode("BSN", nkind, cs->name, cs->hoffset); 659: } 660: 661: /* 662: * In case of error, skip to the next 663: * statement delimiter. 664: */ 665: errflush(ao) 666: { 667: register o; 668: 669: o = ao; 670: while(o>RBRACE) /* ; { } */ 671: o = symbol(); 672: peeksym = o; 673: }