|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.