1: /*
   2:  * Routines to parse .u1 files and produce icode.
   3:  */
   4: 
   5: #include "ilink.h"
   6: #include "opcode.h"
   7: #include "datatype.h"
   8: 
   9: static int pc = 0;      /* simulated program counter */
  10: 
  11: /*
  12:  * gencode - read .u1 file, resolve variable references, and generate icode.
  13:  *  Basic process is to read each line in the file and take some action
  14:  *  as dictated by the opcode.  This action sometimes involves parsing
  15:  *  of operands and usually culminates in the call of the appropriate
  16:  *  emit* routine.
  17:  *
  18:  * Appendix C of the "tour" has a complete description of the intermediate
  19:  *  language that gencode parses.
  20:  */
  21: gencode()
  22:    {
  23:    register int op, k, lab;
  24:    int j, nargs, flags, implicit;
  25:    char *id, *name, *procname;
  26:    struct centry *cp;
  27:    struct gentry *gp;
  28:    struct fentry *fp, *flocate();
  29: 
  30:    extern long getint();
  31:    extern double getreal();
  32:    extern char *getid(), *getstrlit();
  33:    extern struct gentry *glocate();
  34: 
  35:    while ((op = getop(&name)) != EOF) {
  36:       switch (op) {
  37: 
  38:          /* Ternary operators. */
  39: 
  40:          case OP_TOBY:
  41:          case OP_SECT:
  42: 
  43:          /* Binary operators. */
  44: 
  45:          case OP_ASGN:
  46:          case OP_CAT:
  47:          case OP_DIFF:
  48:          case OP_DIV:
  49:          case OP_EQV:
  50:          case OP_INTER:
  51:          case OP_LCONCAT:
  52:          case OP_LEXEQ:
  53:          case OP_LEXGE:
  54:          case OP_LEXGT:
  55:          case OP_LEXLE:
  56:          case OP_LEXLT:
  57:          case OP_LEXNE:
  58:          case OP_MINUS:
  59:          case OP_MOD:
  60:          case OP_MULT:
  61:          case OP_NEQV:
  62:          case OP_NUMEQ:
  63:          case OP_NUMGE:
  64:          case OP_NUMGT:
  65:          case OP_NUMLE:
  66:          case OP_NUMLT:
  67:          case OP_NUMNE:
  68:          case OP_PLUS:
  69:          case OP_POWER:
  70:          case OP_RASGN:
  71:          case OP_RSWAP:
  72:          case OP_SUBSC:
  73:          case OP_SWAP:
  74:          case OP_UNIONCS:
  75: 
  76:          /* Unary operators. */
  77: 
  78:          case OP_BANG:
  79:          case OP_COMPL:
  80:          case OP_NEG:
  81:          case OP_NONNULL:
  82:          case OP_NULL:
  83:          case OP_NUMBER:
  84:          case OP_RANDOM:
  85:          case OP_REFRESH:
  86:          case OP_SIZE:
  87:          case OP_TABMAT:
  88:          case OP_VALUE:
  89: 
  90:          /* Instructions. */
  91: 
  92:          case OP_BSCAN:
  93:          case OP_CCASE:
  94:          case OP_COACT:
  95:          case OP_COFAIL:
  96:          case OP_CORET:
  97:          case OP_DUP:
  98:          case OP_EFAIL:
  99:          case OP_ERET:
 100:          case OP_ESCAN:
 101:          case OP_ESUSP:
 102:          case OP_INCRES:
 103:          case OP_LIMIT:
 104:          case OP_LSUSP:
 105:          case OP_PFAIL:
 106:          case OP_PNULL:
 107:          case OP_POP:
 108:          case OP_PRET:
 109:          case OP_PSUSP:
 110:          case OP_PUSH1:
 111:          case OP_PUSHN1:
 112:          case OP_SDUP:
 113:             newline();
 114:             emit(op, name);
 115:             break;
 116: 
 117:          case OP_CHFAIL:
 118:          case OP_CREATE:
 119:          case OP_GOTO:
 120:          case OP_INIT:
 121:             lab = getlab();
 122:             newline();
 123:             emitl(op, lab, name);
 124:             break;
 125: 
 126:          case OP_CSET:
 127:          case OP_REAL:
 128:             k = getdec();
 129:             newline();
 130:             emitr(op, ctable[k].c_pc, name);
 131:             break;
 132: 
 133:          case OP_FIELD:
 134:             id = getid();
 135:             newline();
 136:             fp = flocate(id);
 137:             if (fp == NULL) {
 138:                err(id, "invalid field name", 0);
 139:                break;
 140:                }
 141:             emitn(op, fp->f_fid-1, name);
 142:             break;
 143: 
 144:          case OP_FILE:
 145:             file = getid();
 146:             newline();
 147:             emiti(op, file - strings, name);
 148:             break;
 149: 
 150:          case OP_INT:
 151:             k = getdec();
 152:             newline();
 153:             cp = &ctable[k];
 154:             if (cp->c_flag & F_LONGLIT)
 155:                emitr(OP_CON, cp->c_pc, name);
 156:             else {
 157:                int i;
 158:                i = (int)cp->c_val.ival;
 159:                if (i >= 0 && i < 16)
 160:                   emit(OP_INTX+i, name);
 161:                else
 162:                   emitint(op, i, name);
 163:                   }
 164:             break;
 165: 
 166:          case OP_INVOKE:
 167:             k = getdec();
 168:             newline();
 169:             abbrev(op, k, name, OP_INVKX, 8);
 170:             break;
 171: 
 172:          case OP_KEYWD:
 173:          case OP_LLIST:
 174:             k = getdec();
 175:             newline();
 176:             emitn(op, k, name);
 177:             break;
 178: 
 179:          case OP_LAB:
 180:             lab = getlab();
 181:             newline();
 182:             if (Dflag)
 183:                fprintf(dbgfile, "L%d:\n", lab);
 184:             backpatch(lab);
 185:             break;
 186: 
 187:          case OP_LINE:
 188:             line = getdec();
 189:             newline();
 190:             abbrev(op, line, name, OP_LINEX, 64);
 191:             break;
 192: 
 193:          case OP_MARK:
 194:             lab = getlab();
 195:             newline();
 196:             if (lab != 0)
 197:                emitl(op, lab, name);
 198:             else
 199:                emit(OP_MARK0, "mark0");
 200:             break;
 201: 
 202:          case OP_STR:
 203:             k = getdec();
 204:             newline();
 205:             cp = &ctable[k];
 206:             id = cp->c_val.sval;
 207:             emitin(op, id-strings, cp->c_length, name);
 208:             break;
 209: 
 210:          case OP_UNMARK:
 211:             k = getdec();
 212:             newline();
 213:             abbrev(op, k, name, OP_UNMKX, 8);
 214:             break;
 215: 
 216:          case OP_VAR:
 217:             k = getdec();
 218:             newline();
 219:             flags = ltable[k].l_flag;
 220:             if (flags & F_GLOBAL)
 221:                abbrev(OP_GLOBAL, ltable[k].l_val.global-gtable, "global",
 222:                       OP_GLOBX, 16);
 223:             else if (flags & F_STATIC)
 224:                abbrev(OP_STATIC, ltable[k].l_val.staticid-1, "static",
 225:                       OP_STATX, 8);
 226:             else if (flags & F_ARGUMENT)
 227:                abbrev(OP_ARG, nargs-ltable[k].l_val.offset, "arg",
 228:                       OP_ARGX,  8);
 229:             else
 230:                abbrev(OP_LOCAL, ltable[k].l_val.offset-1, "local",
 231:                       OP_LOCX, 16);
 232:             break;
 233: 
 234:          /* Declarations. */
 235: 
 236:          case OP_PROC:
 237:             procname = getid();
 238:             newline();
 239:             locinit();
 240:             clearlab();
 241:             line = 0;
 242:             gp = glocate(procname);
 243:             implicit = gp->g_flag & F_IMPERROR;
 244:             nargs = gp->g_nargs;
 245:             emiteven();
 246:             break;
 247: 
 248:          case OP_LOCAL:
 249:             k = getdec();
 250:             flags = getoct();
 251:             id = getid();
 252:             putloc(k, id, flags, implicit, procname);
 253:             break;
 254: 
 255:          case OP_CON:
 256:             k = getdec();
 257:             flags = getoct();
 258:             if (flags & F_INTLIT)
 259:                putconst(k, flags, 0, pc, getint());
 260:             else if (flags & F_REALLIT)
 261:                putconst(k, flags, 0, pc, getreal());
 262:             else if (flags & F_STRLIT) {
 263:                j = getdec();
 264:                putconst(k, flags, j, pc, getstrlit(j));
 265:                }
 266:             else if (flags & F_CSETLIT) {
 267:                j = getdec();
 268:                putconst(k, flags, j, pc, getstrlit(j));
 269:                }
 270:             else
 271:                fprintf(stderr, "gencode: illegal constant\n");
 272:             newline();
 273:             emitcon(k);
 274:             break;
 275: 
 276:          case OP_DECLEND:
 277:             newline();
 278:             gp->g_pc = pc;
 279:             emitproc(procname, nargs, dynoff, statics-static1, static1);
 280:             break;
 281: 
 282:          case OP_END:
 283:             newline();
 284:             flushcode();
 285:             break;
 286: 
 287:          default:
 288:             fprintf(stderr, "gencode: illegal opcode(%d): %s\n", op, name);
 289:             newline();
 290:          }
 291:       }
 292:    }
 293: 
 294: /*
 295:  * abbrev - for certain opcodes with integer arguments that are small enough,
 296:  * use an abbreviated opcode that includes the integer argument in it.
 297:  */
 298: abbrev(op, n, name, altop, limit)
 299: int op, n;
 300: char *name;
 301: int altop, limit;
 302:    {
 303:    if (n >= 0 && n < limit)
 304:       emit(altop+n, name);
 305:    else
 306:       emitn(op, n, name);
 307:    }
 308: 
 309: /*
 310:  *  emit - emit opcode.
 311:  *  emitl - emit opcode with reference to program label, consult the "tour"
 312:  *	for a description of the chaining and backpatching for labels.
 313:  *  emitn - emit opcode with integer argument.
 314:  *  emitr - emit opcode with pc-relative reference.
 315:  *  emiti - emit opcode with reference to identifier table.
 316:  *  emitin - emit opcode with reference to identifier table & integer argument.
 317:  *  emitint - emit INT opcode with integer argument.
 318:  *  emiteven - emit null bytes to bring pc to word boundary.
 319:  *  emitcon - emit constant table entry.
 320:  *  emitproc - emit procedure block.
 321:  *
 322:  * The emit* routines call out* routines to effect the "outputting" of icode.
 323:  *  Note that the majority of the code for the emit* routines is for debugging
 324:  *  purposes.
 325:  */
 326: emit(op, name)
 327: int op;
 328: char *name;
 329:    {
 330:    if (Dflag)
 331:       fprintf(dbgfile, "%d:\t%d\t\t\t\t# %s\n", pc, op, name);
 332:    outop(op);
 333:    }
 334: 
 335: emitl(op, lab, name)
 336: int op, lab;
 337: char *name;
 338:    {
 339:    if (Dflag)
 340:       fprintf(dbgfile, "%d:\t%d\tL%d\t\t\t# %s\n", pc, op, lab, name);
 341:    if (lab >= maxlabels)
 342:       syserr("too many labels in ucode");
 343:    outop(op);
 344:    if (labels[lab] <= 0) {      /* forward reference */
 345:       outopnd(labels[lab]);
 346:       labels[lab] = OPNDSIZE - pc;  /* add to front of reference chain */
 347:       }
 348:    else                 /* output relative offset */
 349:       outopnd(labels[lab] - (pc + OPNDSIZE));
 350:    }
 351: 
 352: emitn(op, n, name)
 353: int op, n;
 354: char *name;
 355:    {
 356:    if (Dflag)
 357:       fprintf(dbgfile, "%d:\t%d\t%d\t\t\t# %s\n", pc, op, n, name);
 358:    outop(op);
 359:    outopnd(n);
 360:    }
 361: 
 362: emitr(op, loc, name)
 363: int op, loc;
 364: char *name;
 365:    {
 366:    loc -= pc + (OPSIZE + OPNDSIZE);
 367:    if (Dflag) {
 368:       if (loc >= 0)
 369:          fprintf(dbgfile, "%d:\t%d\t*+%d\t\t\t# %s\n", pc, op, loc, name);
 370:       else
 371:          fprintf(dbgfile, "%d:\t%d\t*-%d\t\t\t# %s\n", pc, op, -loc, name);
 372:       }
 373:    outop(op);
 374:    outopnd(loc);
 375:    }
 376: 
 377: emiti(op, offset, name)
 378: int op, offset;
 379: char *name;
 380:    {
 381:    if (Dflag)
 382:       fprintf(dbgfile, "%d:\t%d\tI+%d\t\t\t# %s\n", pc, op, offset, name);
 383:    outop(op);
 384:    outopnd(offset);
 385:    }
 386: 
 387: emitin(op, offset, n, name)
 388: int op, offset, n;
 389: char *name;
 390:    {
 391:    if (Dflag)
 392:       fprintf(dbgfile, "%d:\t%d\tI+%d,%d\t\t\t# %s\n", pc, op, offset, n, name);
 393:    outop(op);
 394:    outopnd(offset);
 395:    outopnd(n);
 396:    }
 397: /*
 398:  * emitint can have some pitfalls.  outword is used to output the
 399:  *  integer and this is picked up in the interpreter as the second
 400:  *  word of a short integer.  The integer value output must be
 401:  *  the same size as what the interpreter expects.  See op_int and op_intx
 402:  *  in interp.s
 403:  */
 404: emitint(op, i, name)
 405: int op, i;
 406: char *name;
 407:    {
 408:    if (Dflag)
 409:         fprintf(dbgfile, "%d:\t%d\t%d\t\t\t# %s\n", pc, op, i, name);
 410:    outop(op);
 411:    outword(i);
 412:    }
 413: 
 414: emiteven()
 415:    {
 416:    while ((pc % WORDSIZE) != 0) {
 417:       if (Dflag)
 418:          fprintf(dbgfile, "%d:\t0\n", pc);
 419:       outop(0);
 420:       }
 421:    }
 422: 
 423: emitcon(k)
 424: register int k;
 425:    {
 426:    register int i;
 427:    register char *s;
 428:    int csbuf[CSETSIZE];
 429:    union {
 430:       char ovly[1];  /* Array used to overlay l and f on a bytewise basis. */
 431:       long int l;
 432:       double f;
 433:       } x;
 434: 
 435:    if (ctable[k].c_flag & F_REALLIT) {
 436:       x.f = ctable[k].c_val.rval;
 437:       if (Dflag) {
 438:          fprintf(dbgfile, "%d:\t%d", pc, T_REAL);
 439:          dumpblock(x.ovly,sizeof(double));
 440:          fprintf(dbgfile, "\t\t\t( %g )\n",x.f);
 441:          }
 442:       outword(T_REAL);
 443:       outblock(x.ovly,sizeof(double));
 444:       }
 445:    else if (ctable[k].c_flag & F_LONGLIT) {
 446:       x.l = ctable[k].c_val.ival;
 447:       if (Dflag) {
 448:          fprintf(dbgfile, "%d:\t%d", pc, T_LONGINT);
 449:          dumpblock(x.ovly,sizeof(long));
 450:          fprintf(dbgfile,"\t\t\t( %ld)\n",x.l);
 451:          }
 452:       outword(T_LONGINT);
 453:       outblock(x.ovly,sizeof(long));
 454:       }
 455:    else if (ctable[k].c_flag & F_CSETLIT) {
 456:       for (i = 0; i < CSETSIZE; i++)
 457:          csbuf[i] = 0;
 458:       s = ctable[k].c_val.sval;
 459:       i = ctable[k].c_length;
 460:       while (i--) {
 461:          setb(*s, csbuf);
 462:          s++;
 463:          }
 464:       if (Dflag)
 465:          fprintf(dbgfile, "%d:\t%d", pc, T_CSET);
 466:       outword(T_CSET);
 467:       outblock(csbuf,sizeof(csbuf));
 468:       if (Dflag)
 469:          dumpblock(csbuf,CSETSIZE);
 470:       }
 471:    }
 472: 
 473: emitproc(name, nargs, ndyn, nstat, fstat)
 474: char *name;
 475: int nargs, ndyn, nstat, fstat;
 476:    {
 477:    register int i;
 478:    register char *p;
 479:    int size;
 480:    /*
 481:     * ProcBlockSize = sizeof(BasicProcBlock) +
 482:     *  sizeof(descrip)*(# of args + # of dynamics + # of statics).
 483:     */
 484:    size = (9*WORDSIZE) + (2*WORDSIZE) * (nargs+ndyn+nstat);
 485: 
 486:    if (Dflag) {
 487:       fprintf(dbgfile, "%d:\t%d", pc, T_PROC);      /* type code */
 488:       fprintf(dbgfile, "\t%d", size);           /* size of block */
 489:       fprintf(dbgfile, "\tZ+%d\n", pc+size);        /* entry point */
 490:       fprintf(dbgfile, "\t%d", nargs);          /* # of arguments */
 491:       fprintf(dbgfile, "\t%d", ndyn);           /* # of dynamic locals */
 492:       fprintf(dbgfile, "\t%d", nstat);          /* # of static locals */
 493:       fprintf(dbgfile, "\t%d\n", fstat);        /* first static */
 494:       fprintf(dbgfile, "\t%d\tI+%d\t\t\t# %s\n",    /* name of procedure */
 495:          strlen(name), name-strings, name);
 496:       }
 497:    outword(T_PROC);
 498:    outword(size);
 499:    outword(pc + size - 2*WORDSIZE); /* Have to allow for the two words
 500:                                      that we've already output. */
 501:    outword(nargs);
 502:    outword(ndyn);
 503:    outword(nstat);
 504:    outword(fstat);
 505:    outword(strlen(name));
 506:    outword(name - strings);
 507: 
 508:    /*
 509:     * Output string descriptors for argument names by looping through
 510:     *  all locals, and picking out those with F_ARGUMENT set.
 511:     */
 512:    for (i = 0; i <= nlocal; i++) {
 513:       if (ltable[i].l_flag & F_ARGUMENT) {
 514:          p = ltable[i].l_name;
 515:          if (Dflag)
 516:             fprintf(dbgfile, "\t%d\tI+%d\t\t\t# %s\n", strlen(p), p-strings, p);
 517:          outword(strlen(p));
 518:          outword(p - strings);
 519:          }
 520:       }
 521: 
 522:    /*
 523:     * Output string descriptors for local variable names.
 524:     */
 525:    for (i = 0; i <= nlocal; i++) {
 526:       if (ltable[i].l_flag & F_DYNAMIC) {
 527:          p = ltable[i].l_name;
 528:          if (Dflag)
 529:             fprintf(dbgfile, "\t%d\tI+%d\t\t\t# %s\n", strlen(p), p-strings, p);
 530:          outword(strlen(p));
 531:          outword(p - strings);
 532:          }
 533:       }
 534: 
 535:    /*
 536:     * Output string descriptors for local variable names.
 537:     */
 538:    for (i = 0; i <= nlocal; i++) {
 539:       if (ltable[i].l_flag & F_STATIC) {
 540:          p = ltable[i].l_name;
 541:          if (Dflag)
 542:             fprintf(dbgfile, "\t%d\tI+%d\t\t\t# %s\n", strlen(p), p-strings, p);
 543:          outword(strlen(p));
 544:          outword(p - strings);
 545:          }
 546:       }
 547:    }
 548: 
 549: /*
 550:  * gentables - generate interpreter code for global, static,
 551:  *  identifier, and record tables, and built-in procedure blocks.
 552:  */
 553: 
 554: gentables()
 555:    {
 556:    register int i;
 557:    register char *s;
 558:    register struct gentry *gp;
 559:    struct fentry *fp;
 560:    struct rentry *rp;
 561:    struct header hdr;
 562: 
 563:    emiteven();
 564: 
 565:    /*
 566:     * Output record constructor procedure blocks.
 567:     */
 568:    hdr.records = pc;
 569:    if (Dflag)
 570:       fprintf(dbgfile, "%d:\t%d\t\t\t\t# record blocks\n", pc, nrecords);
 571:    outword(nrecords);
 572:    for (gp = gtable; gp < gfree; gp++) {
 573:       if (gp->g_flag & (F_RECORD & ~F_GLOBAL)) {
 574:          s = gp->g_name;
 575:          gp->g_pc = pc;
 576:          if (Dflag) {
 577:             fprintf(dbgfile, "%d:", pc);
 578:             fprintf(dbgfile, "\t%d", T_PROC);
 579:             fprintf(dbgfile, "\t%d", RKBLKSIZE);
 580:             fprintf(dbgfile, "\t_mkrec+4\n");
 581:             fprintf(dbgfile, "\t%d", gp->g_nargs);
 582:             fprintf(dbgfile, "\t-2");
 583:             fprintf(dbgfile, "\t%d", gp->g_procid);
 584:             fprintf(dbgfile, "\t0\n");
 585:             fprintf(dbgfile, "\t%d\tI+%d\t\t\t# %s\n", strlen(s), s-strings, s);
 586:             }
 587:          outword(T_PROC);       /* type code */
 588:          outword(RKBLKSIZE);        /* size of block */
 589:          outword(0);            /* entry point (filled in by interp)*/
 590:          outword(gp->g_nargs);      /* number of fields */
 591:          outword(-2);           /* record constructor indicator */
 592:          outword(gp->g_procid);     /* record id */
 593:          outword(0);            /* not used */
 594:          outword(strlen(s));        /* name of record */
 595:          outword(s - strings);
 596:          }
 597:       }
 598: 
 599:    /*
 600:     * Output record/field table.
 601:     */
 602:    hdr.ftab = pc;
 603:    if (Dflag)
 604:       fprintf(dbgfile, "%d:\t\t\t\t\t# record/field table\n", pc);
 605:    for (fp = ftable; fp < ffree; fp++) {
 606:       if (Dflag)
 607:          fprintf(dbgfile, "%d:", pc);
 608:       rp = fp->f_rlist;
 609:       for (i = 1; i <= nrecords; i++) {
 610:          if (rp != NULL && rp->r_recid == i) {
 611:             if (Dflag)
 612:                fprintf(dbgfile, "\t%d", rp->r_fnum);
 613:             outword(rp->r_fnum);
 614:             rp = rp->r_link;
 615:             }
 616:          else {
 617:             if (Dflag)
 618:                fprintf(dbgfile, "\t-1");
 619:             outword(-1);
 620:             }
 621:          if (Dflag && (i == nrecords || (i & 03) == 0))
 622:             putc('\n', dbgfile);
 623:          }
 624:       }
 625: 
 626:    /*
 627:     * Output global variable descriptors.
 628:     */
 629:    hdr.globals = pc;
 630:    for (gp = gtable; gp < gfree; gp++) {
 631:       if (gp->g_flag & (F_BUILTIN & ~F_GLOBAL)) {   /* built-in procedure */
 632:          if (Dflag)
 633:             fprintf(dbgfile, "%d:\t%06o\t%d\t\t\t# %s\n",
 634:                pc, D_PROC, -gp->g_procid, gp->g_name);
 635:          outword(D_PROC);
 636:          outword(-gp->g_procid);
 637:          }
 638:       else if (gp->g_flag & (F_PROC & ~F_GLOBAL)) { /* Icon procedure */
 639:          if (Dflag)
 640:             fprintf(dbgfile, "%d:\t%06o\tZ+%d\t\t\t# %s\n",
 641:                pc, D_PROC, gp->g_pc, gp->g_name);
 642:          outword(D_PROC);
 643:          outword(gp->g_pc);
 644:          }
 645:       else if (gp->g_flag & (F_RECORD & ~F_GLOBAL)) {   /* record constructor */
 646:          if (Dflag)
 647:             fprintf(dbgfile, "%d:\t%06o\tZ+%d\t\t\t# %s\n",
 648:                pc, D_PROC, gp->g_pc, gp->g_name);
 649:          outword(D_PROC);
 650:          outword(gp->g_pc);
 651:          }
 652:       else {    /* global variable */
 653:          if (Dflag)
 654:             fprintf(dbgfile, "%d:\t0\t0\t\t\t# %s\n", pc, gp->g_name);
 655:          outword(0);
 656:          outword(0);
 657:          }
 658:       }
 659: 
 660:    /*
 661:     * Output descriptors for global variable names.
 662:     */
 663:    hdr.gnames = pc;
 664:    for (gp = gtable; gp < gfree; gp++) {
 665:       if (Dflag)
 666:          fprintf(dbgfile, "%d:\t%d\tI+%d\t\t\t# %s\n",
 667:                  pc, strlen(gp->g_name), gp->g_name-strings, gp->g_name);
 668:       outword(strlen(gp->g_name));
 669:       outword(gp->g_name - strings);
 670:       }
 671: 
 672:    /*
 673:     * Output a null descriptor for each static variable.
 674:     */
 675:    hdr.statics = pc;
 676:    for (i = statics; i > 0; i--) {
 677:       if (Dflag)
 678:          fprintf(dbgfile, "%d:\t0\t0\n", pc);
 679:       outword(0);
 680:       outword(0);
 681:       }
 682:    flushcode();
 683: 
 684:    /*
 685:     * Output the identifier table.  Note that the call to write
 686:     *  really does all the work.
 687:     */
 688:    hdr.ident = pc;
 689:    if (Dflag) {
 690:       for (s = strings; s < sfree; ) {
 691:          fprintf(dbgfile, "%d:\t%03o", pc, *s++);
 692:          for (i = 7; i > 0; i--) {
 693:             if (s >= sfree)
 694:                break;
 695:             fprintf(dbgfile, " %03o", *s++);
 696:             }
 697:          putc('\n', dbgfile);
 698:          }
 699:       }
 700:    write(fileno(outfile), strings, sfree - strings);
 701:    pc += sfree - strings;
 702: 
 703:    /*
 704:     * Output icode file header.
 705:     */
 706:    hdr.size = pc;
 707:    hdr.trace = trace;
 708:    if (Dflag) {
 709:       fprintf(dbgfile, "size:    %d\n", hdr.size);
 710:       fprintf(dbgfile, "trace:   %d\n", hdr.trace);
 711:       fprintf(dbgfile, "records: %d\n", hdr.records);
 712:       fprintf(dbgfile, "ftab:    %d\n", hdr.ftab);
 713:       fprintf(dbgfile, "globals: %d\n", hdr.globals);
 714:       fprintf(dbgfile, "gnames:  %d\n", hdr.gnames);
 715:       fprintf(dbgfile, "statics: %d\n", hdr.statics);
 716:       fprintf(dbgfile, "ident:   %d\n", hdr.ident);
 717:       }
 718:    fseek(outfile, (long)hdrloc, 0);
 719:    write(fileno(outfile), &hdr, sizeof hdr);
 720:    }
 721: 
 722: #define CodeCheck if (codep >= code + maxcode)\
 723:                      syserr("out of code buffer space")
 724: /*
 725:  * outop(i) outputs the integer i as an interpreter opcode.  This
 726:  *  assumes opcodes fit into a char.  If they don't, outop will
 727:  *  need to look like outword and outopnd.
 728:  */
 729: outop(op)
 730: int op;
 731:    {
 732:    CodeCheck;
 733:    *codep++ = op;
 734:    pc++;
 735:    }
 736: /*
 737:  * outopnd(i) outputs i as an operand for an interpreter operation.
 738:  *  OPNDSIZE bytes must be moved from &opnd[0] to &codep[0].
 739:  */
 740: outopnd(opnd)
 741: int opnd;
 742:    {
 743:    int i;
 744:    union {
 745:         char *i;
 746:         char c[OPNDSIZE];
 747:         } u;
 748: 
 749:    CodeCheck;
 750:    u.i = (char *) opnd;
 751: 
 752:    for (i = 0; i < OPNDSIZE; i++)
 753:       codep[i] = u.c[i];
 754: 
 755:    codep += OPNDSIZE;
 756:    pc += OPNDSIZE;
 757:    }
 758: /*
 759:  * outword(i) outputs i as a word that is used by the runtime system
 760:  *  WORDSIZE bytes must be moved from &word[0] to &codep[0].
 761:  */
 762: outword(word)
 763: int word;
 764:    {
 765:    int i;
 766:    union {
 767:         char *i;
 768:         char c[WORDSIZE];
 769:         } u;
 770: 
 771:    CodeCheck;
 772:    u.i = (char *) word;
 773: 
 774:    for (i = 0; i < WORDSIZE; i++)
 775:       codep[i] = u.c[i];
 776: 
 777:    codep += WORDSIZE;
 778:    pc += WORDSIZE;
 779:    }
 780: /*
 781:  * outblock(a,i) output i bytes starting at address a.
 782:  */
 783: outblock(addr,count)
 784: char *addr;
 785: int count;
 786:    {
 787:    if (codep + count > code + maxcode)
 788:       syserr("out of code buffer space");
 789:    pc += count;
 790:    while (count--)
 791:       *codep++ = *addr++;
 792:    }
 793: /*
 794:  * dumpblock(a,i) dump contents of i bytes at address a, used only
 795:  *  in conjunction with -D.
 796:  */
 797: dumpblock(addr, count)
 798: char *addr;
 799: int count;
 800:    {
 801:    int i;
 802:    for (i = 0; i < count; i++) {
 803:       if ((i & 7) == 0)
 804:          fprintf(dbgfile,"\n\t");
 805:       fprintf(dbgfile," %03o",(unsigned)addr[i]);
 806:       }
 807:    putc('\n',dbgfile);
 808:    }
 809: 
 810: /*
 811:  * flushcode - write buffered code to the output file.
 812:  */
 813: flushcode()
 814:    {
 815:    if (codep > code)
 816:       /*fwrite(code, 1, codep - code, outfile);*/
 817:       write(fileno(outfile), code, codep - code);
 818:    codep = code;
 819:    }
 820: 
 821: /*
 822:  * clearlab - clear label table to all zeroes.
 823:  */
 824: clearlab()
 825:    {
 826:    register int i;
 827: 
 828:    for (i = 0; i < maxlabels; i++)
 829:       labels[i] = 0;
 830:    }
 831: 
 832: /*
 833:  * backpatch - fill in all forward references to lab.
 834:  */
 835: backpatch(lab)
 836: int lab;
 837:    {
 838:    register int p, r;
 839: #ifdef VAX
 840:    register int *q;
 841: #endif VAX
 842: #ifdef PORT
 843:    int *q;  /* BE SURE to properly declare q - this won't always work. */
 844:    return;
 845: #endif PORT
 846: #ifdef PDP11
 847:    register char *q;
 848: #endif PDP11
 849: 
 850:    if (lab >= maxlabels)
 851:       syserr("too many labels in ucode");
 852:    p = labels[lab];
 853:    if (p > 0)
 854:       syserr("multiply defined label in ucode");
 855:    while (p < 0) {      /* follow reference chain */
 856:       r = pc - (OPNDSIZE - p);  /* compute relative offset */
 857: #ifdef VAX
 858:       q = (int *) (codep - (pc + p));   /* point to word with address */
 859:       p = *q;           /* get next address on chain */
 860:       *q = r;           /* fill in correct offset */
 861: #endif VAX
 862: 
 863: #ifdef PORT
 864: #endif PORT
 865: 
 866: #ifdef PDP11
 867:       q = codep - (pc + p); /* point to word with address */
 868:       p = *q++ & 0377;      /* get next address on chain */
 869:       p |= *q << 8;
 870:       *q = r >> 8;      /* fill in correct offset */
 871:       *--q = r;
 872: #endif PDP11
 873:       }
 874:    labels[lab] = pc;
 875:    }
 876: 
 877: /*
 878:  * genheader - output the header line to the .u1 file.
 879:  */
 880: genheader()
 881:    {
 882:    fprintf(outfile,"%s",ixhdr);
 883:    }

Defined functions

abbrev defined in line 298; used 7 times
backpatch defined in line 835; used 1 times
clearlab defined in line 824; used 1 times
dumpblock defined in line 797; used 3 times
emit defined in line 326; used 4 times
emitcon defined in line 423; used 1 times
emiteven defined in line 414; used 2 times
emiti defined in line 377; used 1 times
emitin defined in line 387; used 1 times
emitint defined in line 404; used 1 times
emitl defined in line 335; used 2 times
emitn defined in line 352; used 3 times
emitproc defined in line 473; used 1 times
emitr defined in line 362; used 2 times
flushcode defined in line 813; used 2 times
gencode defined in line 21; used 1 times
genheader defined in line 880; used 1 times
gentables defined in line 554; used 1 times
outblock defined in line 783; used 3 times
outop defined in line 729; used 8 times
outopnd defined in line 740; used 7 times
outword defined in line 762; used 43 times

Defined variables

pc defined in line 9; used 52 times

Defined macros

CodeCheck defined in line 722; used 3 times
Last modified: 1984-11-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2427
Valid CSS Valid XHTML 1.0 Strict