Annotation of 43BSD/contrib/icon/link/lcode.c, revision 1.1.1.1

1.1       root        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:    }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.