Annotation of 43BSD/contrib/icon/link/lcode.c, revision 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.