1: #
   2: /* C compiler
   3:  *
   4:  *
   5:  *
   6:  * Called from cc:
   7:  *   c0 source temp1 temp2 [ profileflag ]
   8:  * temp1 contains some ascii text and the binary expression
   9:  * trees.  Each tree is introduced by the # character.
  10:  * Strings are put on temp2, which cc tacks onto
  11:  * temp1 for assembly.
  12:  */
  13: 
  14: #include "c0h.c"
  15: 
  16: int isn 1;
  17: int stflg   1;
  18: int peeksym -1;
  19: int line    1;
  20: int debug   0;
  21: int dimp    0;
  22: struct  tname   funcblk { NAME, 0, 0, REG, 0, 0 };
  23: int *treespace { osspace };
  24: 
  25: struct kwtab {
  26:     char    *kwname;
  27:     int kwval;
  28: } kwtab[]
  29: {
  30:     "int",      INT,
  31:     "char",     CHAR,
  32:     "float",    FLOAT,
  33:     "double",   DOUBLE,
  34:     "struct",   STRUCT,
  35:     "long",     LONG,
  36:     "auto",     AUTO,
  37:     "extern",   EXTERN,
  38:     "static",   STATIC,
  39:     "register", REG,
  40:     "goto",     GOTO,
  41:     "return",   RETURN,
  42:     "if",       IF,
  43:     "while",    WHILE,
  44:     "else",     ELSE,
  45:     "switch",   SWITCH,
  46:     "case",     CASE,
  47:     "break",    BREAK,
  48:     "continue", CONTIN,
  49:     "do",       DO,
  50:     "default",  DEFAULT,
  51:     "for",      FOR,
  52:     "sizeof",   SIZEOF,
  53:     0,      0,
  54: };
  55: 
  56: main(argc, argv)
  57: char *argv[];
  58: {
  59:     extern fin;
  60:     register char *sp;
  61:     register i;
  62:     register struct kwtab *ip;
  63: 
  64:     if(argc<3) {
  65:         error("Arg count");
  66:         exit(1);
  67:     }
  68:     if((fin=open(argv[1],0))<0) {
  69:         error("Can't find %s", argv[1]);
  70:         exit(1);
  71:     }
  72:     if (fcreat(argv[2], obuf)<0 || fcreat(argv[3], sbuf)<0) {
  73:         error("Can't create temp");
  74:         exit(1);
  75:     }
  76:     if (argc>4)
  77:         proflg++;
  78:     /*
  79: 	 * The hash table locations of the keywords
  80: 	 * are marked; if an identifier hashes to one of
  81: 	 * these locations, it is looked up in in the keyword
  82: 	 * table first.
  83: 	 */
  84:     for (ip=kwtab; (sp = ip->kwname); ip++) {
  85:         i = 0;
  86:         while (*sp)
  87:             i =+ *sp++;
  88:         hshtab[i%hshsiz].hflag = FKEYW;
  89:     }
  90:     while(!eof) {
  91:         extdef();
  92:         blkend();
  93:     }
  94:     outcode("B", EOF);
  95:     strflg++;
  96:     outcode("B", EOF);
  97:     fflush(obuf);
  98:     fflush(sbuf);
  99:     exit(nerror!=0);
 100: }
 101: 
 102: /*
 103:  * Look up the identifier in symbuf in the symbol table.
 104:  * If it hashes to the same spot as a keyword, try the keyword table
 105:  * first.  An initial "." is ignored in the hash.
 106:  * Return is a ptr to the symbol table entry.
 107:  */
 108: lookup()
 109: {
 110:     int ihash;
 111:     register struct hshtab *rp;
 112:     register char *sp, *np;
 113: 
 114:     ihash = 0;
 115:     sp = symbuf;
 116:     if (*sp=='.')
 117:         sp++;
 118:     while (sp<symbuf+ncps)
 119:         ihash =+ *sp++;
 120:     rp = &hshtab[ihash%hshsiz];
 121:     if (rp->hflag&FKEYW)
 122:         if (findkw())
 123:             return(KEYW);
 124:     while (*(np = rp->name)) {
 125:         for (sp=symbuf; sp<symbuf+ncps;)
 126:             if (*np++ != *sp++)
 127:                 goto no;
 128:         csym = rp;
 129:         return(NAME);
 130:     no:
 131:         if (++rp >= &hshtab[hshsiz])
 132:             rp = hshtab;
 133:     }
 134:     if(++hshused >= hshsiz) {
 135:         error("Symbol table overflow");
 136:         exit(1);
 137:     }
 138:     rp->hclass = 0;
 139:     rp->htype = 0;
 140:     rp->hoffset = 0;
 141:     rp->dimp = 0;
 142:     rp->hflag =| xdflg;
 143:     sp = symbuf;
 144:     for (np=rp->name; sp<symbuf+ncps;)
 145:         *np++ = *sp++;
 146:     csym = rp;
 147:     return(NAME);
 148: }
 149: 
 150: /*
 151:  * Search the keyword table.
 152:  * Ignore initial "." to avoid member-of-structure
 153:  * problems.
 154:  */
 155: findkw()
 156: {
 157:     register struct kwtab *kp;
 158:     register char *p1, *p2;
 159:     char *wp;
 160: 
 161:     wp = symbuf;
 162:     if (*wp=='.')
 163:         wp++;
 164:     for (kp=kwtab; (p2 = kp->kwname); kp++) {
 165:         p1 = wp;
 166:         while (*p1 == *p2++)
 167:             if (*p1++ == '\0') {
 168:                 cval = kp->kwval;
 169:                 return(1);
 170:             }
 171:     }
 172:     return(0);
 173: }
 174: 
 175: 
 176: /*
 177:  * Return the next symbol from the input.
 178:  * peeksym is a pushed-back symbol, peekc is a pushed-back
 179:  * character (after peeksym).
 180:  * mosflg means that the next symbol, if an identifier,
 181:  * is a member of structure or a structure tag, and it
 182:  * gets a "." prepended to it to distinguish
 183:  * it from other identifiers.
 184:  */
 185: symbol() {
 186:     register c;
 187:     register char *sp;
 188: 
 189:     if (peeksym>=0) {
 190:         c = peeksym;
 191:         peeksym = -1;
 192:         if (c==NAME)
 193:             mosflg = 0;
 194:         return(c);
 195:     }
 196:     if (peekc) {
 197:         c = peekc;
 198:         peekc = 0;
 199:     } else
 200:         if (eof)
 201:             return(EOF);
 202:         else
 203:             c = getchar();
 204: loop:
 205:     switch(ctab[c]) {
 206: 
 207:     case INSERT:        /* ignore newlines */
 208:         inhdr = 1;
 209:         c = getchar();
 210:         goto loop;
 211: 
 212:     case NEWLN:
 213:         if (!inhdr)
 214:             line++;
 215:         inhdr = 0;
 216: 
 217:     case SPACE:
 218:         c = getchar();
 219:         goto loop;
 220: 
 221:     case EOF:
 222:         eof++;
 223:         return(0);
 224: 
 225:     case PLUS:
 226:         return(subseq(c,PLUS,INCBEF));
 227: 
 228:     case MINUS:
 229:         return(subseq(c,subseq('>',MINUS,ARROW),DECBEF));
 230: 
 231:     case ASSIGN:
 232:         if (subseq(' ',0,1)) return(ASSIGN);
 233:         c = symbol();
 234:         if (c>=PLUS && c<=EXOR) {
 235:             if (spnextchar() != ' '
 236:              && (c==MINUS || c==AND || c==TIMES)) {
 237:                 error("Warning: assignment operator assumed");
 238:                 nerror--;
 239:             }
 240:             return(c+ASPLUS-PLUS);
 241:         }
 242:         if (c==ASSIGN)
 243:             return(EQUAL);
 244:         peeksym = c;
 245:         return(ASSIGN);
 246: 
 247:     case LESS:
 248:         if (subseq(c,0,1)) return(LSHIFT);
 249:         return(subseq('=',LESS,LESSEQ));
 250: 
 251:     case GREAT:
 252:         if (subseq(c,0,1)) return(RSHIFT);
 253:         return(subseq('=',GREAT,GREATEQ));
 254: 
 255:     case EXCLA:
 256:         return(subseq('=',EXCLA,NEQUAL));
 257: 
 258:     case DIVIDE:
 259:         if (subseq('*',1,0))
 260:             return(DIVIDE);
 261:         while ((c = spnextchar()) != EOF) {
 262:             peekc = 0;
 263:             if (c=='*') {
 264:                 if (spnextchar() == '/') {
 265:                     peekc = 0;
 266:                     c = getchar();
 267:                     goto loop;
 268:                 }
 269:             }
 270:         }
 271:         eof++;
 272:             error("Nonterminated comment");
 273:             return(0);
 274: 
 275:     case PERIOD:
 276:     case DIGIT:
 277:         peekc = c;
 278:         if ((c=getnum(c=='0'?8:10)) == FCON)
 279:             cval = isn++;
 280:         return(c);
 281: 
 282:     case DQUOTE:
 283:         return(getstr());
 284: 
 285:     case SQUOTE:
 286:         return(getcc());
 287: 
 288:     case LETTER:
 289:         sp = symbuf;
 290:         if (mosflg) {
 291:             *sp++ = '.';
 292:             mosflg = 0;
 293:         }
 294:         while(ctab[c]==LETTER || ctab[c]==DIGIT) {
 295:             if (sp<symbuf+ncps) *sp++ = c;
 296:             c = getchar();
 297:         }
 298:         while(sp<symbuf+ncps)
 299:             *sp++ = '\0';
 300:         peekc = c;
 301:         if ((c=lookup())==KEYW && cval==SIZEOF)
 302:             c = SIZEOF;
 303:         return(c);
 304: 
 305:     case AND:
 306:         return(subseq('&', AND, LOGAND));
 307: 
 308:     case OR:
 309:         return(subseq('|', OR, LOGOR));
 310: 
 311:     case UNKN:
 312:         error("Unknown character");
 313:         c = getchar();
 314:         goto loop;
 315: 
 316:     }
 317:     return(ctab[c]);
 318: }
 319: 
 320: /*
 321:  * If the next input character is c, return a and advance.
 322:  * Otherwise push back the character and return a.
 323:  */
 324: subseq(c,a,b)
 325: {
 326:     if (spnextchar() != c)
 327:         return(a);
 328:     peekc = 0;
 329:     return(b);
 330: }
 331: 
 332: /*
 333:  * Read a double-quoted string, placing it on the
 334:  * string buffer.
 335:  */
 336: getstr()
 337: {
 338:     register int c;
 339:     register char *sp;
 340: 
 341:     nchstr = 1;
 342:     sp = savstr;
 343:     while((c=mapch('"')) >= 0) {
 344:         nchstr++;
 345:         if (sp >= &savstr[STRSIZ]) {
 346:             sp = savstr;
 347:             error("String too long");
 348:         }
 349:         *sp++ = c;
 350:     }
 351:     strptr = sp;
 352:     cval = isn++;
 353:     return(STRING);
 354: }
 355: 
 356: /*
 357:  * Write out a string, either in-line
 358:  * or in the string temp file labelled by
 359:  * lab.
 360:  */
 361: putstr(lab)
 362: {
 363:     register char *sp;
 364: 
 365:     if (lab) {
 366:         strflg++;
 367:         outcode("BNB", LABEL, lab, BDATA);
 368:     } else
 369:         outcode("B", BDATA);
 370:     for (sp = savstr; sp<strptr; )
 371:         outcode("1N", *sp++ & 0377);
 372:     outcode("100");
 373:     strflg = 0;
 374: }
 375: 
 376: /*
 377:  * read a single-quoted character constant.
 378:  * The routine is sensitive to the layout of
 379:  * characters in a word.
 380:  */
 381: getcc()
 382: {
 383:     register int c, cc;
 384:     register char *ccp;
 385: 
 386:     cval = 0;
 387:     ccp = &cval;
 388:     cc = 0;
 389:     while((c=mapch('\'')) >= 0)
 390:         if(cc++ < NCPW)
 391:             *ccp++ = c;
 392:     if(cc>NCPW)
 393:         error("Long character constant");
 394:     return(CON);
 395: }
 396: 
 397: /*
 398:  * Read a character in a string or character constant,
 399:  * detecting the end of the string.
 400:  * It implements the escape sequences.
 401:  */
 402: mapch(ac)
 403: {
 404:     register int a, c, n;
 405:     static mpeek;
 406: 
 407:     c = ac;
 408:     if (a = mpeek)
 409:         mpeek = 0;
 410:     else
 411:         a = getchar();
 412: loop:
 413:     if (a==c)
 414:         return(-1);
 415:     switch(a) {
 416: 
 417:     case '\n':
 418:     case '\0':
 419:         error("Nonterminated string");
 420:         peekc = a;
 421:         return(-1);
 422: 
 423:     case '\\':
 424:         switch (a=getchar()) {
 425: 
 426:         case 't':
 427:             return('\t');
 428: 
 429:         case 'n':
 430:             return('\n');
 431: 
 432:         case 'b':
 433:             return('\b');
 434: 
 435:         case '0': case '1': case '2': case '3':
 436:         case '4': case '5': case '6': case '7':
 437:             n = 0;
 438:             c = 0;
 439:             while (++c<=3 && '0'<=a && a<='7') {
 440:                 n =<< 3;
 441:                 n =+ a-'0';
 442:                 a = getchar();
 443:             }
 444:             mpeek = a;
 445:             return(n);
 446: 
 447:         case 'r':
 448:             return('\r');
 449: 
 450:         case '\n':
 451:             if (!inhdr)
 452:                 line++;
 453:             inhdr = 0;
 454:             a = getchar();
 455:             goto loop;
 456:         }
 457:     }
 458:     return(a);
 459: }
 460: 
 461: /*
 462:  * Read an expression and return a pointer to its tree.
 463:  * It's the classical bottom-up, priority-driven scheme.
 464:  * The initflg prevents the parse from going past
 465:  * "," or ":" because those delimitesrs are special
 466:  * in initializer (and some other) expressions.
 467:  */
 468: tree()
 469: {
 470: #define SEOF    200
 471: #define SSIZE   20
 472:     int *op, opst[SSIZE], *pp, prst[SSIZE];
 473:     register int andflg, o;
 474:     register struct hshtab *cs;
 475:     int p, ps, os;
 476: 
 477:     space = treespace;
 478:     op = opst;
 479:     pp = prst;
 480:     cp = cmst;
 481:     *op = SEOF;
 482:     *pp = 06;
 483:     andflg = 0;
 484: 
 485: advanc:
 486:     switch (o=symbol()) {
 487: 
 488:     case NAME:
 489:         cs = csym;
 490:         if (cs->hclass==0 && cs->htype==0)
 491:             if(nextchar()=='(') {
 492:                 /* set function */
 493:                 cs->hclass = EXTERN;
 494:                 cs->htype = FUNC;
 495:             } else if (initflg)
 496:                 cs->hclass = EXTERN;
 497:             else {
 498:                 /* set label */
 499:                 cs->htype = ARRAY;
 500:                 if (cs->hoffset==0)
 501:                     cs->hoffset = isn++;
 502:             }
 503:         *cp++ = copname(cs);
 504:         goto tand;
 505: 
 506:     case FCON:
 507:         if (!initflg)
 508:             outcode("BBNB1N1N1N1N0B", DATA,LABEL,
 509:                 cval, WDATA, fcval, PROG);
 510: 
 511:     case CON:
 512:     case SFCON:
 513:         *cp++ = block(1,o,(o==CON?INT:DOUBLE),0,cval);
 514:         goto tand;
 515: 
 516:     /* fake a static char array */
 517:     case STRING:
 518:         putstr(cval);
 519:         *cp++ = block(3, NAME, ARRAY+CHAR,0,STATIC,0,cval);
 520: 
 521: tand:
 522:         if(cp>=cmst+cmsiz) {
 523:             error("Expression overflow");
 524:             exit(1);
 525:         }
 526:         if (andflg)
 527:             goto syntax;
 528:         andflg = 1;
 529:         goto advanc;
 530: 
 531:     case INCBEF:
 532:     case DECBEF:
 533:         if (andflg)
 534:             o =+ 2;
 535:         goto oponst;
 536: 
 537:     case COMPL:
 538:     case EXCLA:
 539:     case SIZEOF:
 540:         if (andflg)
 541:             goto syntax;
 542:         goto oponst;
 543: 
 544:     case MINUS:
 545:         if (!andflg)  {
 546:             if ((peeksym=symbol())==FCON) {
 547:                 fcval = - fcval;
 548:                 goto advanc;
 549:             }
 550:             if (peeksym==SFCON) {
 551:                 fcval = - fcval;
 552:                 cval =^ 0100000;
 553:                 goto advanc;
 554:             }
 555:             o = NEG;
 556:         }
 557:         andflg = 0;
 558:         goto oponst;
 559: 
 560:     case AND:
 561:     case TIMES:
 562:         if (andflg)
 563:             andflg = 0; else
 564:             if(o==AND)
 565:                 o = AMPER;
 566:             else
 567:                 o = STAR;
 568:         goto oponst;
 569: 
 570:     case LPARN:
 571:         if (andflg) {
 572:             o = symbol();
 573:             if (o==RPARN)
 574:                 o = MCALL;
 575:             else {
 576:                 peeksym = o;
 577:                 o = CALL;
 578:                 andflg = 0;
 579:             }
 580:         }
 581:         goto oponst;
 582: 
 583:     case RBRACK:
 584:     case RPARN:
 585:         if (!andflg)
 586:             goto syntax;
 587:         goto oponst;
 588: 
 589:     case DOT:
 590:     case ARROW:
 591:         mosflg++;
 592:         break;
 593: 
 594:     }
 595:     /* binaries */
 596:     if (!andflg)
 597:         goto syntax;
 598:     andflg = 0;
 599: 
 600: oponst:
 601:     p = (opdope[o]>>9) & 077;
 602:     if ((o==COMMA || o==COLON) && initflg)
 603:         p = 05;
 604: opon1:
 605:     ps = *pp;
 606:     if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) {
 607:         switch (o) {
 608: 
 609:         case INCAFT:
 610:         case DECAFT:
 611:             p = 37;
 612:             break;
 613:         case LPARN:
 614:         case LBRACK:
 615:         case CALL:
 616:             p = 04;
 617:         }
 618:         if (op >= &opst[SSIZE-1]) {
 619:             error("expression overflow");
 620:             exit(1);
 621:         }
 622:         *++op = o;
 623:         *++pp = p;
 624:         goto advanc;
 625:     }
 626:     --pp;
 627:     switch (os = *op--) {
 628: 
 629:     case SEOF:
 630:         peeksym = o;
 631:         build(0);       /* flush conversions */
 632:         return(*--cp);
 633: 
 634:     case CALL:
 635:         if (o!=RPARN)
 636:             goto syntax;
 637:         build(os);
 638:         goto advanc;
 639: 
 640:     case MCALL:
 641:         *cp++ = block(0,0,0,0); /* 0 arg call */
 642:         os = CALL;
 643:         break;
 644: 
 645:     case INCBEF:
 646:     case INCAFT:
 647:     case DECBEF:
 648:     case DECAFT:
 649:         *cp++ = block(1, CON, INT, 0, 1);
 650:         break;
 651: 
 652:     case LPARN:
 653:         if (o!=RPARN)
 654:             goto syntax;
 655:         goto advanc;
 656: 
 657:     case LBRACK:
 658:         if (o!=RBRACK)
 659:             goto syntax;
 660:         build(LBRACK);
 661:         goto advanc;
 662:     }
 663:     build(os);
 664:     goto opon1;
 665: 
 666: syntax:
 667:     error("Expression syntax");
 668:     errflush(o);
 669:     return(0);
 670: }
 671: 
 672: /*
 673:  * Generate a tree node for a name.
 674:  * All the relevant info from the symbol table is
 675:  * copied out, including the name if it's an external.
 676:  * This is because the symbol table is gone in the next
 677:  * pass, so a ptr isn't sufficient.
 678:  */
 679: copname(acs)
 680: struct hshtab *acs;
 681: {
 682:     register struct hshtab *cs;
 683:     register struct tname *tp;
 684:     register char *cp1;
 685:     int i;
 686:     char *cp2;
 687: 
 688:     cs = acs;
 689:     tp = gblock(sizeof(*tp)/NCPW);
 690:     tp->op = NAME;
 691:     tp->type = cs->htype;
 692:     tp->dimp = cs->hdimp;
 693:     if ((tp->class = cs->hclass)==0)
 694:         tp->class = STATIC;
 695:     tp->offset = 0;
 696:     tp->nloc = cs->hoffset;
 697:     if (cs->hclass==EXTERN) {
 698:         gblock((ncps-NCPW)/NCPW);
 699:         cp1 = tp->nname;
 700:         cp2 = cs->name;
 701:         i = ncps;
 702:         do {
 703:             *cp1++ = *cp2++;
 704:         } while (--i);
 705:     }
 706:     if (cs->hflag&FFIELD)
 707:         tp->class = FMOS;
 708:     return(tp);
 709: }

Defined functions

copname defined in line 679; used 1 times
findkw defined in line 155; used 1 times
getcc defined in line 381; used 1 times
getstr defined in line 336; used 1 times
lookup defined in line 108; used 1 times
main defined in line 56; never used
mapch defined in line 402; used 2 times
putstr defined in line 361; used 2 times
subseq defined in line 324; used 12 times
symbol defined in line 185; used 46 times
tree defined in line 468; used 10 times

Defined variables

debug defined in line 20; never used
dimp defined in line 21; used 2 times
funcblk defined in line 22; never used
isn defined in line 16; used 3 times
kwtab defined in line 28; used 2 times
line defined in line 19; used 2 times
peeksym defined in line 18; used 8 times
stflg defined in line 17; never used
treespace defined in line 23; used 1 times

Defined struct's

kwtab defined in line 25; used 4 times

Defined macros

SEOF defined in line 470; used 1 times
SSIZE defined in line 471; used 3 times
Last modified: 1975-07-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1709
Valid CSS Valid XHTML 1.0 Strict