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: ()
881: {
882: fprintf(outfile,"%s",ixhdr);
883: }