Annotation of researchv10dc/cmd/icon/src/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 "opcode.h"
                      6: #include "ilink.h"
                      7: #include "../h/keyword.h"
                      8: #include "../h/version.h"
                      9: #include "../h/header.h"
                     10: 
                     11: #ifndef MaxHeader
                     12: #define MaxHeader MaxHdr
                     13: #endif MaxHeader
                     14: 
                     15: static word pc = 0;            /* simulated program counter */
                     16: 
                     17: #define outword(n)     wordout((word)(n))
                     18: 
                     19: /*
                     20:  * gencode - read .u1 file, resolve variable references, and generate icode.
                     21:  *  Basic process is to read each line in the file and take some action
                     22:  *  as dictated by the opcode.  This action sometimes involves parsing
                     23:  *  of operands and usually culminates in the call of the appropriate
                     24:  *  emit* routine.
                     25:  *
                     26:  * Appendix C of the "tour" has a complete description of the intermediate
                     27:  *  language that gencode parses.
                     28:  */
                     29: gencode()
                     30:    {
                     31:    register int op, k, lab;
                     32:    int j, nargs, flags, implicit;
                     33:    char *id, *name, *procname;
                     34:    struct centry *cp;
                     35:    struct gentry *gp;
                     36:    struct fentry *fp, *flocate();
                     37: 
                     38:    extern long getint();
                     39:    extern double getreal();
                     40:    union {
                     41:       long ival;
                     42:       double rval;
                     43:       char *sval;
                     44:       } gg;
                     45:    extern char *getid(), *getstrlit();
                     46:    extern struct gentry *glocate();
                     47: 
                     48:    while ((op = getop(&name)) != EOF) {
                     49:       switch (op) {
                     50: 
                     51:          /* Ternary operators. */
                     52: 
                     53:          case Op_Toby:
                     54:          case Op_Sect:
                     55: 
                     56:          /* Binary operators. */
                     57: 
                     58:          case Op_Asgn:
                     59:          case Op_Cat:
                     60:          case Op_Diff:
                     61:          case Op_Div:
                     62:          case Op_Eqv:
                     63:          case Op_Inter:
                     64:          case Op_Lconcat:
                     65:          case Op_Lexeq:
                     66:          case Op_Lexge:
                     67:          case Op_Lexgt:
                     68:          case Op_Lexle:
                     69:          case Op_Lexlt:
                     70:          case Op_Lexne:
                     71:          case Op_Minus:
                     72:          case Op_Mod:
                     73:          case Op_Mult:
                     74:          case Op_Neqv:
                     75:          case Op_Numeq:
                     76:          case Op_Numge:
                     77:          case Op_Numgt:
                     78:          case Op_Numle:
                     79:          case Op_Numlt:
                     80:          case Op_Numne:
                     81:          case Op_Plus:
                     82:          case Op_Power:
                     83:          case Op_Rasgn:
                     84:          case Op_Rswap:
                     85:          case Op_Subsc:
                     86:          case Op_Swap:
                     87:          case Op_Unions:
                     88: 
                     89:          /* Unary operators. */
                     90: 
                     91:          case Op_Bang:
                     92:          case Op_Compl:
                     93:          case Op_Neg:
                     94:          case Op_Nonnull:
                     95:          case Op_Null:
                     96:          case Op_Number:
                     97:          case Op_Random:
                     98:          case Op_Refresh:
                     99:          case Op_Size:
                    100:          case Op_Tabmat:
                    101:          case Op_Value:
                    102: 
                    103:          /* Instructions. */
                    104: 
                    105:          case Op_Bscan:
                    106:          case Op_Ccase:
                    107:          case Op_Coact:
                    108:          case Op_Cofail:
                    109:          case Op_Coret:
                    110:          case Op_Dup:
                    111:          case Op_Efail:
                    112:          case Op_Eret:
                    113:          case Op_Escan:
                    114:          case Op_Esusp:
                    115:          case Op_Limit:
                    116:          case Op_Lsusp:
                    117:          case Op_Pfail:
                    118:          case Op_Pnull:
                    119:          case Op_Pop:
                    120:          case Op_Pret:
                    121:          case Op_Psusp:
                    122:          case Op_Push1:
                    123:          case Op_Pushn1:
                    124:          case Op_Sdup:
                    125:             newline();
                    126:             emit(op, name);
                    127:             break;
                    128: 
                    129:          case Op_Chfail:
                    130:          case Op_Create:
                    131:          case Op_Goto:
                    132:          case Op_Init:
                    133:             lab = getlab();
                    134:             newline();
                    135:             emitl(op, lab, name);
                    136:             break;
                    137: 
                    138:          case Op_Cset:
                    139:          case Op_Real:
                    140:             k = getdec();
                    141:             newline();
                    142:             emitr(op, ctable[k].c_pc, name);
                    143:             break;
                    144: 
                    145:          case Op_Field:
                    146:             id = getid();
                    147:             newline();
                    148:             fp = flocate(id);
                    149:             if (fp == NULL) {
                    150:                err(id, "invalid field name", 0);
                    151:                break;
                    152:                }
                    153:             emitn(op, (word)(fp->f_fid-1), name);
                    154:             break;
                    155: 
                    156:          case Op_Int:
                    157:             k = getdec();
                    158:             newline();
                    159:             cp = &ctable[k];
                    160:             if (cp->c_flag & F_LongLit)
                    161:                emitr(Op_Long, cp->c_pc, "long");
                    162:             else {
                    163:                long int i;
                    164:                i = (long)cp->c_val.ival;
                    165:                emitint(op, i, name);
                    166:                }
                    167:             break;
                    168: 
                    169:          case Op_Invoke:
                    170:             k = getdec();
                    171:             newline();
                    172:             emitn(op, (word)k, name);
                    173:             break;
                    174: 
                    175:          case Op_Keywd:
                    176:             k = getdec();
                    177:             newline();
                    178:             switch (k) {
                    179:                case K_FAIL:
                    180:                   emit(Op_Efail,"efail");
                    181:                   break;
                    182:                case K_NULL:
                    183:                   emit(Op_Pnull,"pnull");
                    184:                   break;
                    185:                default:
                    186:                emitn(op, (word)k, name);
                    187:             }
                    188:             break;
                    189: 
                    190:          case Op_Llist:
                    191:             k = getdec();
                    192:             newline();
                    193:             emitn(op, (word)k, name);
                    194:             break;
                    195: 
                    196:          case Op_Lab:
                    197:             lab = getlab();
                    198:             newline();
                    199:             if (Dflag)
                    200:                fprintf(dbgfile, "L%d:\n", lab);
                    201:             backpatch(lab);
                    202:             break;
                    203: 
                    204:          case Op_Line:
                    205:             line = getdec();
                    206:             newline();
                    207:             emitn(op, (word)line, name);
                    208:             break;
                    209: 
                    210:          case Op_Mark:
                    211:             lab = getlab();
                    212:             newline();
                    213:             emitl(op, lab, name);
                    214:             break;
                    215: 
                    216:          case Op_Mark0:
                    217:             emit(op, name);
                    218:             break;
                    219: 
                    220:          case Op_Str:
                    221:             k = getdec();
                    222:             newline();
                    223:             cp = &ctable[k];
                    224:             id = cp->c_val.sval;
                    225:             emitin(op, (word)(id-strings), cp->c_length, name);
                    226:             break;
                    227:        
                    228:          case Op_Tally:
                    229:             k = getdec();
                    230:             newline();
                    231:             emitn(op, (word)k, name);
                    232:             break;
                    233: 
                    234:          case Op_Unmark:
                    235:             emit(Op_Unmark, name);
                    236:             break;
                    237: 
                    238:          case Op_Var:
                    239:             k = getdec();
                    240:             newline();
                    241:             flags = ltable[k].l_flag;
                    242:             if (flags & F_Global)
                    243:                emitn(Op_Global, (word)(ltable[k].l_val.global-gtable), "global");
                    244:             else if (flags & F_Static)
                    245:                emitn(Op_Static, (word)(ltable[k].l_val.staticid-1), "static");
                    246:             else if (flags & F_Argument)
                    247:                emitn(Op_Arg, (word)(ltable[k].l_val.offset-1), "arg");
                    248:             else
                    249:                emitn(Op_Local, (word)(ltable[k].l_val.offset-1), "local");
                    250:             break;
                    251: 
                    252:          /* Declarations. */
                    253: 
                    254:          case Op_Proc:
                    255:             procname = getid();
                    256:             newline();
                    257:             locinit();
                    258:             clearlab();
                    259:             line = 0;
                    260:             gp = glocate(procname);
                    261:             implicit = gp->g_flag & F_ImpError;
                    262:             nargs = gp->g_nargs;
                    263:             emiteven();
                    264:             break;
                    265: 
                    266:          case Op_Local:
                    267:             k = getdec();
                    268:             flags = getoct();
                    269:             id = getid();
                    270:             putloc(k, id, flags, implicit, procname);
                    271:             break;
                    272: 
                    273:          case Op_Con:
                    274:             k = getdec();
                    275:             flags = getoct();
                    276:             if (flags & F_IntLit) {
                    277:                gg.ival = getint();
                    278:                putconst(k, flags, 0, pc, gg);
                    279:                }
                    280:             else if (flags & F_RealLit) {
                    281:                gg.rval = getreal();
                    282:                putconst(k, flags, 0, pc, gg);
                    283:                }
                    284:             else if (flags & F_StrLit) {
                    285:                j = getdec();
                    286:                gg.sval = getstrlit(j);
                    287:                putconst(k, flags, j, pc, gg);
                    288:                }
                    289:             else if (flags & F_CsetLit) {
                    290:                j = getdec();
                    291:                gg.sval = getstrlit(j);
                    292:                putconst(k, flags, j, pc, gg);
                    293:                }
                    294:             else
                    295:                fprintf(stderr, "gencode: illegal constant\n");
                    296:             newline();
                    297:             emitcon(k);
                    298:             break;
                    299: 
                    300:          case Op_Filen:
                    301:             file = getid();
                    302:             newline();
                    303:             break;
                    304: 
                    305:          case Op_Declend:
                    306:             newline();
                    307:             gp->g_pc = pc;
                    308:             emitproc(procname, nargs, dynoff, statics-static1, static1);
                    309:             break;
                    310: 
                    311:          case Op_End:
                    312:             newline();
                    313:             flushcode();
                    314:             break;
                    315: 
                    316:          default:
                    317:             fprintf(stderr, "gencode: illegal opcode(%d): %s\n", op, name);
                    318:             newline();
                    319:          }
                    320:       }
                    321:    }
                    322: 
                    323: /*
                    324:  *  emit - emit opcode.
                    325:  *  emitl - emit opcode with reference to program label, consult the "tour"
                    326:  *     for a description of the chaining and backpatching for labels.
                    327:  *  emitn - emit opcode with integer argument.
                    328:  *  emitr - emit opcode with pc-relative reference.
                    329:  *  emiti - emit opcode with reference to identifier table.
                    330:  *  emitin - emit opcode with reference to identifier table & integer argument.
                    331:  *  emitint - emit word opcode with integer argument.
                    332:  *  emiteven - emit null bytes to bring pc to word boundary.
                    333:  *  emitcon - emit constant table entry.
                    334:  *  emitproc - emit procedure block.
                    335:  *
                    336:  * The emit* routines call out* routines to effect the "outputting" of icode.
                    337:  *  Note that the majority of the code for the emit* routines is for debugging
                    338:  *  purposes.
                    339:  */
                    340: emit(op, name)
                    341: int op;
                    342: char *name;
                    343:    {
                    344:    if (Dflag)
                    345:       fprintf(dbgfile, "%ld:\t%d\t\t\t\t# %s\n", (long)pc, op, name);
                    346:    outword(op);
                    347:    }
                    348: 
                    349: emitl(op, lab, name)
                    350: int op, lab;
                    351: char *name;
                    352:    {
                    353:    if (Dflag)
                    354:       fprintf(dbgfile, "%ld:\t%d\tL%d\t\t\t# %s\n", (long)pc, op, lab, name);
                    355:    if (lab >= maxlabels)
                    356:       syserr("too many labels in ucode");
                    357:    outword(op);
                    358:    if (labels[lab] <= 0) {             /* forward reference */
                    359:       outword(labels[lab]);
                    360:       labels[lab] = WordSize - pc;     /* add to front of reference chain */
                    361:       }
                    362:    else                                        /* output relative offset */
                    363:       outword(labels[lab] - (pc + WordSize));
                    364:    }
                    365: 
                    366: emitn(op, n, name)
                    367: int op;
                    368: word n;
                    369: char *name;
                    370:    {
                    371:    if (Dflag)
                    372:       fprintf(dbgfile, "%ld:\t%d\t%ld\t\t\t# %s\n", (long)pc, op, (long)n, name);
                    373:    outword(op);
                    374:    outword(n);
                    375:    }
                    376: 
                    377: emitr(op, loc, name)
                    378: int op;
                    379: word loc;
                    380: char *name;
                    381:    {
                    382:    loc -= pc + (WordSize * 2);
                    383:    if (Dflag) {
                    384:       if (loc >= 0)
                    385:         fprintf(dbgfile, "%ld:\t%d\t*+%ld\t\t\t# %s\n",(long) pc, op, (long)loc, name);
                    386:       else
                    387:         fprintf(dbgfile, "%ld:\t%d\t*-%ld\t\t\t# %s\n",(long) pc, op, (long)-loc, name);
                    388:       }
                    389:    outword(op);
                    390:    outword(loc);
                    391:    }
                    392: 
                    393: emiti(op, offset, name)
                    394: int op;
                    395: word offset;
                    396: char *name;
                    397:    {
                    398:    if (Dflag)
                    399:       fprintf(dbgfile, "%ld:\t%d\tI+%d\t\t\t# %s\n", (long)pc, op, offset, name);
                    400:    outword(op);
                    401:    outword(offset);
                    402:    }
                    403: 
                    404: emitin(op, offset, n, name)
                    405: int op, n;
                    406: word offset;
                    407: char *name;
                    408:    {
                    409:    if (Dflag)
                    410:       fprintf(dbgfile, "%ld:\t%d\t%d,I+%ld\t\t\t# %s\n", (long)pc, op, n, (long)offset, name);
                    411:    outword(op);
                    412:    outword(n);
                    413:    outword(offset);
                    414:    }
                    415: /*
                    416:  * emitint can have some pitfalls.  outword is used to output the
                    417:  *  integer and this is picked up in the interpreter as the second
                    418:  *  word of a short integer.  The integer value output must be
                    419:  *  the same size as what the interpreter expects.  See op_int and op_intx
                    420:  *  in interp.s
                    421:  */
                    422: emitint(op, i, name)
                    423: int op;
                    424: long int i;
                    425: char *name;
                    426:    {
                    427:    if (Dflag)
                    428:        fprintf(dbgfile, "%ld:\t%d\t%ld\t\t\t# %s\n", (long)pc, op, (long)i, name);
                    429:    outword(op);
                    430:    outword(i);
                    431:    }
                    432: 
                    433: emiteven()
                    434:    {
                    435:    while ((pc % WordSize) != 0) {
                    436:       if (Dflag)
                    437:         fprintf(dbgfile, "%ld:\t0\n",(long) pc);
                    438:       outword(0);
                    439:       }
                    440:    }
                    441: 
                    442: emitcon(k)
                    443: register int k;
                    444:    {
                    445:    register int i, j;
                    446:    register char *s;
                    447:    int csbuf[CsetSize];
                    448:    union {
                    449:       char ovly[1];  /* Array used to overlay l and f on a bytewise basis. */
                    450:       long int l;
                    451:       double f;
                    452:       } x;
                    453: 
                    454:    if (ctable[k].c_flag & F_RealLit) {
                    455: #ifdef Double
                    456: /* access real values one word at a time */
                    457:       {  int *rp, *rq;
                    458:         rp = (int *) &(x.f);
                    459:         rq = (int *) &(ctable[k].c_val.rval);
                    460:         *rp++ = *rq++;
                    461:         *rp   = *rq;
                    462:       }
                    463: #else Double
                    464:       x.f = ctable[k].c_val.rval;
                    465: #endif Double
                    466:       if (Dflag) {
                    467:         fprintf(dbgfile, "%ld:\t%d\n", (long)pc, T_Real);
                    468:         dumpblock(x.ovly,sizeof(double));
                    469:         fprintf(dbgfile, "\t\t\t( %g )\n",x.f);
                    470:         }
                    471:       outword(T_Real);
                    472: 
                    473: #ifdef Double
                    474: /* fill out real block with an empty word */
                    475:       outword(0);
                    476: #endif Double
                    477:       outblock(x.ovly,sizeof(double));
                    478:       }
                    479:    else if (ctable[k].c_flag & F_LongLit) {
                    480:       x.l = ctable[k].c_val.ival;
                    481:       if (Dflag) {
                    482:         fprintf(dbgfile, "%ld:\t%d\n",(long) pc, T_Longint);
                    483:         dumpblock(x.ovly,sizeof(long));
                    484:         fprintf(dbgfile,"\t\t\t( %ld)\n",(long)x.l);
                    485:         }
                    486:       outword(T_Longint);
                    487:       outblock(x.ovly,sizeof(long));
                    488:       }
                    489:    else if (ctable[k].c_flag & F_CsetLit) {
                    490:       for (i = 0; i < CsetSize; i++)
                    491:         csbuf[i] = 0;
                    492:       s = ctable[k].c_val.sval;
                    493:       i = ctable[k].c_length;
                    494:       while (i--) {
                    495:         Setb(*s, csbuf);
                    496:         s++;
                    497:         }
                    498:       j = 0;
                    499:       for (i = 0; i < 256; i++) {
                    500:         if (Testb(i, csbuf))
                    501:           j++;
                    502:         }
                    503:       if (Dflag) {
                    504:         fprintf(dbgfile, "%ld:\t%d\n",(long) pc, T_Cset);
                    505:         fprintf(dbgfile, "\t%d\n",j);
                    506:         fprintf(dbgfile,csbuf,sizeof(csbuf));
                    507:         }
                    508:       outword(T_Cset);
                    509:       outword(j);                 /* cset size */
                    510:       outblock(csbuf,sizeof(csbuf));
                    511:       if (Dflag)
                    512:         dumpblock(csbuf,CsetSize);
                    513:       }
                    514:    }
                    515: 
                    516: emitproc(name, nargs, ndyn, nstat, fstat)
                    517: char *name;
                    518: int nargs, ndyn, nstat, fstat;
                    519:    {
                    520:    register int i;
                    521:    register char *p;
                    522:    int size;
                    523:    /*
                    524:     * FncBlockSize = sizeof(BasicFncBlock) +
                    525:     *  sizeof(descrip)*(# of args + # of dynamics + # of statics).
                    526:     */
                    527:    size = (10*WordSize) + (2*WordSize) * (nargs+ndyn+nstat);
                    528: 
                    529:    if (Dflag) {
                    530:       fprintf(dbgfile, "%ld:\t%d\n", (long)pc, T_Proc); /* type code */
                    531:       fprintf(dbgfile, "\t%d\n", size);                 /* size of block */
                    532:       fprintf(dbgfile, "\tZ+%ld\n",(long)(pc+size));    /* entry point */
                    533:       fprintf(dbgfile, "\t%d\n", nargs);                /* # of arguments */
                    534:       fprintf(dbgfile, "\t%d\n", ndyn);                 /* # of dynamic locals */
                    535:       fprintf(dbgfile, "\t%d\n", nstat);                /* # of static locals */
                    536:       fprintf(dbgfile, "\t%d\n", fstat);                /* first static */
                    537:       fprintf(dbgfile, "\t%s\n", file);                 /* file */
                    538:       fprintf(dbgfile, "\t%d\tI+%ld\t\t\t# %s\n",        /* name of procedure */
                    539:         strlen(name), (long)(name-strings), name);
                    540:       }
                    541:    outword(T_Proc);
                    542:    outword(size);
                    543:    outword(pc + size - 2*WordSize); /* Have to allow for the two words
                    544:                                     that we've already output. */
                    545:    outword(nargs);
                    546:    outword(ndyn);
                    547:    outword(nstat);
                    548:    outword(fstat);
                    549:    outword(file - strings);
                    550:    outword(strlen(name));
                    551:    outword(name - strings);
                    552: 
                    553:    /*
                    554:     * Output string descriptors for argument names by looping through
                    555:     *  all locals, and picking out those with F_Argument set.
                    556:     */
                    557:    for (i = 0; i <= nlocal; i++) {
                    558:       if (ltable[i].l_flag & F_Argument) {
                    559:         p = ltable[i].l_name;
                    560:         if (Dflag)
                    561:            fprintf(dbgfile, "\t%d\tI+%ld\t\t\t# %s\n", strlen(p), (long)(p-strings), p);
                    562:         outword(strlen(p));
                    563:         outword(p - strings);
                    564:         }
                    565:       }
                    566: 
                    567:    /*
                    568:     * Output string descriptors for local variable names.
                    569:     */
                    570:    for (i = 0; i <= nlocal; i++) {
                    571:       if (ltable[i].l_flag & F_Dynamic) {
                    572:         p = ltable[i].l_name;
                    573:         if (Dflag)
                    574:            fprintf(dbgfile, "\t%d\tI+%ld\t\t\t# %s\n", strlen(p), (long)(p-strings), p);
                    575:         outword(strlen(p));
                    576:         outword(p - strings);
                    577:         }
                    578:       }
                    579: 
                    580:    /*
                    581:     * Output string descriptors for local variable names.
                    582:     */
                    583:    for (i = 0; i <= nlocal; i++) {
                    584:       if (ltable[i].l_flag & F_Static) {
                    585:         p = ltable[i].l_name;
                    586:         if (Dflag)
                    587:            fprintf(dbgfile, "\t%d\tI+%ld\t\t\t# %s\n", strlen(p), (long)(p-strings), p);
                    588:         outword(strlen(p));
                    589:         outword(p - strings);
                    590:         }
                    591:       }
                    592:    }
                    593: 
                    594: /*
                    595:  * gentables - generate interpreter code for global, static,
                    596:  *  identifier, and record tables, and built-in procedure blocks.
                    597:  */
                    598: 
                    599: gentables()
                    600:    {
                    601:    register int i;
                    602:    register char *s;
                    603:    register struct gentry *gp;
                    604:    struct fentry *fp;
                    605:    struct rentry *rp;
                    606:    struct header hdr;
                    607:    char *strcpy();
                    608: 
                    609:    emiteven();
                    610: 
                    611:    /*
                    612:     * Output record constructor procedure blocks.
                    613:     */
                    614:    hdr.records = pc;
                    615:    if (Dflag)
                    616:       fprintf(dbgfile, "%ld:\t%d\t\t\t\t# record blocks\n",(long)pc, nrecords);
                    617:    outword(nrecords);
                    618:    for (gp = gtable; gp < gfree; gp++) {
                    619:       if (gp->g_flag & (F_Record & ~F_Global)) {
                    620:         s = gp->g_name;
                    621:         gp->g_pc = pc;
                    622:         if (Dflag) {
                    623:            fprintf(dbgfile, "%ld:\n", pc);
                    624:            fprintf(dbgfile, "\t%d\n", T_Proc);
                    625:            fprintf(dbgfile, "\t%d\n", RkBlkSize);
                    626:            fprintf(dbgfile, "\t_mkrec\n");
                    627:            fprintf(dbgfile, "\t%d\n", gp->g_nargs);
                    628:            fprintf(dbgfile, "\t-2\n");
                    629:            fprintf(dbgfile, "\t%d\n", gp->g_procid);
                    630:            fprintf(dbgfile, "\t0\n");
                    631:            fprintf(dbgfile, "\t0\n");
                    632:            fprintf(dbgfile, "\t%d\tI+%ld\t\t\t# %s\n", strlen(s), (long)(s-strings), s);
                    633:            }
                    634:         outword(T_Proc);               /* type code */
                    635:         outword(RkBlkSize);            /* size of block */
                    636:         outword(0);                    /* entry point (filled in by interp)*/
                    637:         outword(gp->g_nargs);          /* number of fields */
                    638:         outword(-2);                   /* record constructor indicator */
                    639:         outword(gp->g_procid);         /* record id */
                    640:         outword(0);                    /* not used */
                    641:         outword(0);                    /* not used */
                    642:         outword(strlen(s));            /* name of record */
                    643:         outword(s - strings);
                    644:         }
                    645:       }
                    646: 
                    647:    /*
                    648:     * Output record/field table.
                    649:     */
                    650:    hdr.ftab = pc;
                    651:    if (Dflag)
                    652:       fprintf(dbgfile, "%ld:\t\t\t\t\t# record/field table\n", (long)pc);
                    653:    for (fp = ftable; fp < ffree; fp++) {
                    654:       if (Dflag)
                    655:         fprintf(dbgfile, "%ld:\n", (long)pc);
                    656:       rp = fp->f_rlist;
                    657:       for (i = 1; i <= nrecords; i++) {
                    658:         if (rp != NULL && rp->r_recid == i) {
                    659:            if (Dflag)
                    660:               fprintf(dbgfile, "\t%d\n", rp->r_fnum);
                    661:            outword(rp->r_fnum);
                    662:            rp = rp->r_link;
                    663:            }
                    664:         else {
                    665:            if (Dflag)
                    666:               fprintf(dbgfile, "\t-1\n");
                    667:            outword(-1);
                    668:            }
                    669:         if (Dflag && (i == nrecords || (i & 03) == 0))
                    670:            putc('\n', dbgfile);
                    671:         }
                    672:       }
                    673: 
                    674:    /*
                    675:     * Output global variable descriptors.
                    676:     */
                    677:    hdr.globals = pc;
                    678:    for (gp = gtable; gp < gfree; gp++) {
                    679:       if (gp->g_flag & (F_Builtin & ~F_Global)) {      /* built-in procedure */
                    680:         if (Dflag)
                    681:            fprintf(dbgfile, "%ld:\t%06lo\t%d\t\t\t# %s\n",
                    682:               (long)pc, (long)D_Proc, -gp->g_procid, gp->g_name);
                    683:         outword(D_Proc);
                    684:         outword(-gp->g_procid);
                    685:         }
                    686:       else if (gp->g_flag & (F_Proc & ~F_Global)) {    /* Icon procedure */
                    687:         if (Dflag)
                    688:            fprintf(dbgfile, "%ld:\t%06lo\tZ+%ld\t\t\t# %s\n",
                    689:               (long)pc,(long)D_Proc, (long)gp->g_pc, gp->g_name);
                    690:         outword(D_Proc);
                    691:         outword(gp->g_pc);
                    692:         }
                    693:       else if (gp->g_flag & (F_Record & ~F_Global)) {  /* record constructor */
                    694:         if (Dflag)
                    695:            fprintf(dbgfile, "%ld:\t%06lo\tZ+%ld\t\t\t# %s\n",
                    696:               (long)pc, (long)D_Proc, (long)gp->g_pc, gp->g_name);
                    697:         outword(D_Proc);
                    698:         outword(gp->g_pc);
                    699:         }
                    700:       else {   /* global variable */
                    701:         if (Dflag)
                    702:            fprintf(dbgfile, "%ld:\t%06lo\t0\t\t\t# %s\n",(long)pc,(long)D_Null, gp->g_name);
                    703:         outword(D_Null);
                    704:         outword(0);
                    705:         }
                    706:       }
                    707: 
                    708:    /*
                    709:     * Output descriptors for global variable names.
                    710:     */
                    711:    hdr.gnames = pc;
                    712:    for (gp = gtable; gp < gfree; gp++) {
                    713:       if (Dflag)
                    714:         fprintf(dbgfile, "%ld:\t%d\tI+%ld\t\t\t# %s\n",
                    715:                 (long)pc, strlen(gp->g_name), (long)(gp->g_name-strings), gp->g_name);
                    716:       outword(strlen(gp->g_name));
                    717:       outword(gp->g_name - strings);
                    718:       }
                    719: 
                    720:    /*
                    721:     * Output a null descriptor for each static variable.
                    722:     */
                    723:    hdr.statics = pc;
                    724:    for (i = statics; i > 0; i--) {
                    725:       if (Dflag)
                    726:         fprintf(dbgfile, "%ld:\t0\t0\n", (long)pc);
                    727:       outword(D_Null);
                    728:       outword(0);
                    729:       }
                    730:    flushcode();
                    731: 
                    732:    /*
                    733:     * Output the identifier table.  Note that the call to write
                    734:     *  really does all the work.
                    735:     */
                    736:    hdr.ident = pc;
                    737:    if (Dflag) {
                    738:       for (s = strings; s < strfree; ) {
                    739:         fprintf(dbgfile, "%ld:\t%03o\n", (long)pc, *s++);
                    740:         for (i = 7; i > 0; i--) {
                    741:            if (s >= strfree)
                    742:               break;
                    743:            fprintf(dbgfile, " %03o\n", *s++);
                    744:            }
                    745:         putc('\n', dbgfile);
                    746:         }
                    747:       }
                    748: #ifndef MSDOS
                    749:    write(fileno(outfile), strings, strfree - strings);
                    750: #else MSDOS
                    751: #ifdef SPTR
                    752:    write(fileno(outfile), strings, strfree - strings);
                    753: #else  /* Handle the case where strfree-strings will create a long int */
                    754:    longwrite(fileno(outfile), strings, (long)(strfree - strings));
                    755: #endif
                    756: #endif MSDOS
                    757:    pc += strfree - strings;
                    758: 
                    759:    /*
                    760:     * Output icode file header.
                    761:     */
                    762:    hdr.hsize = pc;
                    763:    strcpy((char *)hdr.config,IVersion);
                    764:    hdr.trace = trace;
                    765:    if (Dflag) {
                    766:       fprintf(dbgfile, "size:    %ld\n", (long)hdr.hsize);
                    767:       fprintf(dbgfile, "trace:   %ld\n", (long)hdr.trace);
                    768:       fprintf(dbgfile, "records: %ld\n", (long)hdr.records);
                    769:       fprintf(dbgfile, "ftab:    %ld\n", (long)hdr.ftab);
                    770:       fprintf(dbgfile, "globals: %ld\n", (long)hdr.globals);
                    771:       fprintf(dbgfile, "gnames:  %ld\n", (long)hdr.gnames);
                    772:       fprintf(dbgfile, "statics: %ld\n", (long)hdr.statics);
                    773:       fprintf(dbgfile, "ident:   %ld\n", (long)hdr.ident);
                    774:       fprintf(dbgfile, "config:   %s\n", hdr.config);
                    775:       }
                    776: #ifndef NoHeader
                    777:    fseek(outfile, (long)MaxHeader, 0);
                    778: #else NoHeader
                    779:    fseek(outfile, 0L, 0);
                    780: #endif NoHeader
                    781:    write(fileno(outfile), &hdr, sizeof hdr);
                    782:    }
                    783: 
                    784: #define CodeCheck if (codep >= code + maxcode)\
                    785:                     syserr("out of code buffer space")
                    786: /*
                    787:  * outword(i) outputs i as a word that is used by the runtime system
                    788:  *  WordSize bytes must be moved from &word[0] to &codep[0].
                    789:  */
                    790: wordout(oword)
                    791: word oword;
                    792:    {
                    793:    int i;
                    794:    union {
                    795:        word i;
                    796:        char c[WordSize];
                    797:        } u;
                    798: 
                    799:    CodeCheck;
                    800:    u.i = oword;
                    801: 
                    802:    for (i = 0; i < WordSize; i++)
                    803:       codep[i] = u.c[i];
                    804: 
                    805:    codep += WordSize;
                    806:    pc += WordSize;
                    807:    }
                    808: /*
                    809:  * outblock(a,i) output i bytes starting at address a.
                    810:  */
                    811: outblock(addr,count)
                    812: char *addr;
                    813: int count;
                    814:    {
                    815:    if (codep + count > code + maxcode)
                    816:       syserr("out of code buffer space");
                    817:    pc += count;
                    818:    while (count--)
                    819:       *codep++ = *addr++;
                    820:    }
                    821: /*
                    822:  * dumpblock(a,i) dump contents of i bytes at address a, used only
                    823:  *  in conjunction with -D.
                    824:  */
                    825: dumpblock(addr, count)
                    826: char *addr;
                    827: int count;
                    828:    {
                    829:    int i;
                    830:    for (i = 0; i < count; i++) {
                    831:       if ((i & 7) == 0)
                    832:         fprintf(dbgfile,"\n\t");
                    833:       fprintf(dbgfile," %03o\n",(unsigned)addr[i]);
                    834:       }
                    835:    putc('\n',dbgfile);
                    836:    }
                    837: 
                    838: /*
                    839:  * flushcode - write buffered code to the output file.
                    840:  */
                    841: flushcode()
                    842:    {
                    843:    if (codep > code)
                    844:       write(fileno(outfile), code, codep - code);
                    845:    codep = code;
                    846:    }
                    847: 
                    848: /*
                    849:  * clearlab - clear label table to all zeroes.
                    850:  */
                    851: clearlab()
                    852:    {
                    853:    register int i;
                    854: 
                    855:    for (i = 0; i < maxlabels; i++)
                    856:       labels[i] = 0;
                    857:    }
                    858: 
                    859: /*
                    860:  * backpatch - fill in all forward references to lab.
                    861:  */
                    862: backpatch(lab)
                    863: int lab;
                    864:    {
                    865:    word p, r;
                    866:    register char *q;
                    867:    register char *cp, *cr;
                    868:    register int j;
                    869: 
                    870:    if (lab >= maxlabels)
                    871:       syserr("too many labels in ucode");
                    872: 
                    873:    p = labels[lab];
                    874:    if (p > 0)
                    875:       syserr("multiply defined label in ucode");
                    876:    while (p < 0) {             /* follow reference chain */
                    877:       r = pc - (WordSize - p); /* compute relative offset */
                    878:       q = codep - (pc + p);    /* point to word with address */
                    879:       cp = (char *) &p;        /* address of integer p       */
                    880:       cr = (char *) &r;        /* address of integer r       */
                    881:       for (j = 0; j < WordSize; j++) {   /* move bytes from int pointed to */
                    882:         *cp++ = *q;                      /* by q to p, and move bytes from */
                    883:         *q++ = *cr++;                    /* r to int pointed to by q */
                    884:         }                      /* moves integers at arbitrary addresses */
                    885:       }
                    886:    labels[lab] = pc;
                    887:    }
                    888: #ifdef MSDOS
                    889: #ifdef LPTR
                    890: /* Write a long string in 32k chunks */
                    891: static longwrite(file,s,len)
                    892: int file;
                    893: char *s;
                    894: long int len;
                    895: {
                    896:    long int loopnum;
                    897:    unsigned int leftover;
                    898:    char *p;
                    899: 
                    900:    loopnum = len / 32768;
                    901:    leftover = len % 32768;
                    902:    for(p = s, loopnum = len/32768;loopnum;loopnum--) {
                    903:        write(file,p,32768);
                    904:        p += 32768;
                    905:    }
                    906:    if(leftover) write(file,p,leftover);
                    907: }
                    908: #endif LPTR
                    909: #endif MSDOS

unix.superglobalmegacorp.com

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