/* @(#)put.c 2.3 SCCS id keyword */ /* Copyright (c) 1979 Regents of the University of California */ # /* * pi - Pascal interpreter code translator * * Charles Haley, Bill Joy UCB * Version 1.2 November 1978 */ #include "whoami" #include "opcode.h" #include "0.h" short *obufp = obuf; /* * If DEBUG is defined, include the table * of the printing opcode names. */ #ifdef DEBUG char *otext[] = { #include "OPnames.h" }; #endif /* * Put is responsible for the interpreter equivalent of code * generation. Since the interpreter is specifically designed * for Pascal, little work is required here. */ put(a) { register int *p, i; register char *cp; int n, subop, suboppr, op, oldlc, w; char *string; static int casewrd; /* * It would be nice to do some more * optimizations here. The work * done to collapse offsets in lval * should be done here, the IFEQ etc * relational operators could be used * etc. */ oldlc = lc; if (cgenflg) /* * code disabled - do nothing */ return (oldlc); p = &a; n = *p++; suboppr = subop = (*p>>8) & 0377; op = *p & 0377; string = 0; #ifdef DEBUG if ((cp = otext[op]) == NIL) { printf("op= %o\n", op); panic("put"); } #endif switch (op) { /***** case O_LINO: if (line == codeline) return (oldlc); codeline = line; *****/ case O_PUSH: case O_POP: if (p[1] == 0) return (oldlc); case O_NEW: case O_DISPOSE: case O_AS: case O_IND: case O_OFF: case O_INX2: case O_INX4: case O_CARD: case O_ADDT: case O_SUBT: case O_MULT: case O_IN: case O_CASE1OP: case O_CASE2OP: case O_CASE4OP: case O_PACK: case O_UNPACK: case O_RANG2: case O_RSNG2: case O_RANG42: case O_RSNG42: if (p[1] == 0) break; case O_CON2: if (p[1] < 128 && p[1] >= -128) { suboppr = subop = p[1]; p++; n--; if (op == O_CON2) op = O_CON1; } break; case O_CON8: { short *sp = &p[1]; #ifdef DEBUG if ( opt( 'c' ) ) printf ( "%5d\tCON8\t%10.3f\n" , lc , * ( ( double * ) &p[1] ) ); #endif word ( op ); for ( i = 1 ; i <= 4 ; i ++ ) word ( *sp ++ ); return ( oldlc ); } default: if (op >= O_REL2 && op <= O_REL84) { if ((i = (subop >> 1) * 5 ) >= 30) i -= 30; else i += 2; #ifdef DEBUG string = &"IFEQ\0IFNE\0IFLT\0IFGT\0IFLE\0IFGE"[i]; #endif suboppr = 0; } break; case O_IF: case O_TRA: /***** codeline = 0; *****/ case O_CALL: case O_FOR1U: case O_FOR2U: case O_FOR4U: case O_FOR1D: case O_FOR2D: case O_FOR4D: p[1] -= (unsigned) lc + 2; break; case O_WRIT82: #ifdef DEBUG string = &"22\024\042\044"[subop*3]; #endif suboppr = 0; break; case O_CONG: i = p[1]; cp = * ( ( char ** ) &p[2] ) ; #ifdef DEBUG if (opt('c')) printf("%5d\tCONG:%d\t%s\n", lc, i, cp); #endif if (i <= 127) word(O_CON | i << 8); else { word(O_CON); word(i); } while (i > 0) { w = *cp ? *cp++ : ' '; w |= (*cp ? *cp++ : ' ') << 8; word(w); i -= 2; } return (oldlc); case O_CONC: #ifdef DEBUG (string = "'x'")[1] = p[1]; #endif suboppr = 0; op = O_CON1; subop = p[1]; goto around; case O_CON1: suboppr = subop = p[1]; around: n--; break; case O_CASEBEG: casewrd = 0; return (oldlc); case O_CASEEND: if ((unsigned) lc & 1) { lc--; word(casewrd); } return (oldlc); case O_CASE1: #ifdef DEBUG if (opt('c')) printf("%5d\tCASE1\t%d\n" , lc , ( int ) *( ( long * ) &p[1] ) ); #endif /* * this to build a byte size case table * saving bytes across calls in casewrd * so they can be put out by word() */ lc++; if ((unsigned) lc & 1) { casewrd = *( ( long * ) &p[1] ) & 0377; } else { lc -= 2; word ( casewrd | ( ( int ) *( ( long * ) &p[1] ) << 8 ) ); } return (oldlc); case O_CASE2: #ifdef DEBUG if (opt('c')) printf("%5d\tCASE2\t%d\n" , lc , ( int ) *( ( long * ) &p[1] ) ); #endif word( ( short ) *( ( long * ) &p[1] ) ); return (oldlc); case O_CON4: case O_CASE4: case O_RANG4: case O_RANG4 + 1: /* O_RANG24 */ case O_RSNG4: case O_RSNG4 + 1: /* O_RSNG24 */ { short *sp = &p[1]; long *lp = &p[1]; #ifdef DEBUG if (opt('c')) { printf ( "%5d\t%s\t" , lc , cp ); for ( i = 1 ; i < n ; i += sizeof ( long )/sizeof ( short ) ) printf ( "%D " , *lp ++ ); pchr ( '\n' ); } #endif if ( op != O_CASE4 ) word ( op ); for ( i = 1 ; i < n ; i ++ ) word ( *sp ++ ); return ( oldlc ); } } #ifdef DEBUG if (opt('c')) { printf("%5d\t%s", lc, cp); if (suboppr) printf(":%d", suboppr); if (string) printf("\t%s",string); if (n > 1) pchr('\t'); for (i=1; i 0; i -= 2) word(0); } /* * Patch repairs the branch * at location loc to come * to the current location. */ patch(loc) { patchfil(loc, lc-loc-2); } /* * Patchfil makes loc+2 have value * as its contents. */ patchfil(loc, value) char *loc; int value; { register i; if (cgenflg < 0) return; if (loc > lc) panic("patchfil"); #ifdef DEBUG if (opt('c')) printf("\tpatch %u %d\n", loc, value); #endif i = ((unsigned) loc + 2 - ((unsigned) lc & ~0777))/2; if (i >= 0 && i < 512) obuf[i] = value; else { lseek(ofil, (long) loc+2, 0); write(ofil, &value, 2); lseek(ofil, (long) 0, 2); } } /* * Put the word o into the code */ word(o) int o; { *obufp = o; obufp++; lc += 2; if (obufp >= obuf+256) pflush(); } extern char *obj; /* * Flush the code buffer */ pflush() { register i; i = (obufp - ( ( short * ) obuf ) ) * 2; if (i != 0 && write(ofil, obuf, i) != i) perror(obj), pexit(DIED); obufp = obuf; } /* * Getlab - returns the location counter. * included here for the eventual code generator. */ getlab() { return (lc); } /* * Putlab - lay down a label. */ putlab(l) int l; { return (l); }