diff --git a/util/misc/Makefile b/util/misc/Makefile new file mode 100644 index 000000000..10db0cbc4 --- /dev/null +++ b/util/misc/Makefile @@ -0,0 +1,36 @@ +d=../.. +h=$d/h +l=$d/lib + +DEC_PATH=decode +ENC_PATH=encode +DATA_PATH=$l/em_data.a + +CFLAGS=-O -I$h + +all: $(DEC_PATH) $(ENC_PATH) + +$(DEC_PATH): decode.o $(DATA_PATH) + cc -n -o $(DEC_PATH) decode.o $(DATA_PATH) + +$(ENC_PATH): encode.o $(DATA_PATH) + cc -n -o $(ENC_PATH) encode.o $(DATA_PATH) + +encode.o: $h/em_spec.h $h/em_pseu.h $h/em_flag.h $h/em_ptyp.h $h/em_mes.h + +decode.o: $h/em_spec.h $h/em_pseu.h $h/em_flag.h $h/em_ptyp.h $h/em_mes.h + +clean: + rm -f $(DEC_PATH) $(ENC_PATH) *.o *.old +install : all + cp $(DEC_PATH) $l/em_$(DEC_PATH) + cp $(ENC_PATH) $l/em_$(ENC_PATH) + +cmp : all + cmp $(DEC_PATH) $l/$(DEC_PATH) + cmp $(ENC_PATH) $l/$(ENC_PATH) + +opr: + make pr ^ opr +pr: + @pr -n Makefile decode.c encode.c diff --git a/util/misc/decode.c b/util/misc/decode.c new file mode 100644 index 000000000..b239d9257 --- /dev/null +++ b/util/misc/decode.c @@ -0,0 +1,495 @@ +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* + * Decode compact EM assembly language + * + * Author: Johan Stevenson, Vrije Universiteit, Amsterdam + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define get8() ((unsigned)getchar()) + +#define check(x) if (!(x)) fail_check() + +#define MAXSTR 256 + +/* + * global variables + */ + +int opcode; +int offtyp; +long argval; +int dlbval; +char string[MAXSTR]; +int strsiz; + +int wsize; +int psize; +int lineno; +int argnum; +int errors; +char *progname; +char *filename; + +long wordmask[] = { /* allowed bits in a word */ + 0x00000000, + 0x000000FF, + 0x0000FFFF, + 0x00000000, + 0xFFFFFFFF +}; + +long sizemask[] = { /* allowed bits in multiples of 'wsize' */ + 0x00000000, + 0x7FFFFFFF, + 0x7FFFFFFE, + 0x00000000, + 0x7FFFFFFC +}; + +/* + * external tables + */ + +extern char em_flag[]; +extern short em_ptyp[]; +extern char em_mnem[][4]; +extern char em_pseu[][4]; + +/* + * routines + */ + +int get16(); +long get32(); + +main(argc,argv) char **argv; { + + progname = argv[0]; + if (argc >= 2) { + filename = argv[1]; + if (freopen(argv[1],"r",stdin) == NULL) + fatal("can't open %s",argv[1]); + } + if (argc >= 3) + if (freopen(argv[2],"w",stdout) == NULL) + fatal("can't create %s",argv[2]); + if (get16() != sp_magic) + fatal("bad magic word"); + /* In System III the array is called _ctype[] without the trailing '_' */ + (_ctype_+1)['_'] = (_ctype_+1)['a']; + while (nextline()) + ; + return(errors ? -1 : 0); +} + +/* ----- copy ----- */ + +int nextline() { + register t; + + lineno++; + argnum = 1; + switch (t = table1()) { + case EOF: + return(0); + case sp_fmnem: + instr(); + break; + case sp_fpseu: + pseudo(); + break; + case sp_ilb1: + case sp_ilb2: + argnum = 0; + putarg(sp_cst2); + break; + case sp_dlb1: + case sp_dlb2: + case sp_dnam: + argnum = 0; + putarg(t); + break; + default: + error("unknown opcode %d",t); + } + putchar('\n'); + return(1); +} + +instr() { + register i,j,t; + register long l; + + i = opcode - sp_fmnem; + printf(" %s",em_mnem[i]); + j = em_flag[i] & EM_PAR; + if (j == PAR_NO) + return; + t = em_ptyp[j]; + t = getarg(t); + /* + * range checking + */ + switch (j) { + case PAR_N: + check(argval >= 0); + break; + case PAR_G: + if (t != sp_cst2 && t != sp_cst4) + break; + check(argval >= 0); + /* fall through */ + case PAR_L: + l = argval >= 0 ? argval : -argval; + check((l & ~wordmask[psize]) == 0); + break; + case PAR_W: + if (t == sp_cend) + break; + check((argval & ~wordmask[wsize]) == 0); + /* fall through */ + case PAR_S: + check(argval != 0); + /* fall through */ + case PAR_Z: + check((argval & ~sizemask[wsize]) == 0); + break; + case PAR_O: + check(argval != 0); + check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0); + break; + case PAR_B: + t = sp_ilb2; + break; + case PAR_R: + check(argval >= 0 && argval <= 2); + break; + } + putarg(t); +} + +pseudo() { + register i,t; + + i = opcode; + printf(" %s",em_pseu[i - sp_fpseu]); + switch (i) { + case ps_bss: + case ps_hol: + putarg(getarg(cst_ptyp)); + putarg(getarg(val_ptyp)); + putarg(getarg(ptyp(sp_cst2))); + check(argval==0 || argval==1); + break; + case ps_rom: + case ps_con: + putarg(getarg(val_ptyp)); + while ((t = getarg(any_ptyp)) != sp_cend) + putarg(t); + break; + case ps_mes: + putarg(getarg(ptyp(sp_cst2))); + if (argval == ms_emx) { + putarg(getarg(ptyp(sp_cst2))); + check(argval > 0 && argval <= 4); + wsize = (int) argval; + putarg(getarg(ptyp(sp_cst2))); + check(argval > 0 && argval <= 4); + psize = (int) argval; + } + while ((t = getarg(any_ptyp)) != sp_cend) + putarg(t); + break; + case ps_exa: + case ps_ina: + putarg(getarg(sym_ptyp)); + break; + case ps_exp: + case ps_inp: + putarg(getarg(ptyp(sp_pnam))); + break; + case ps_exc: + putarg(getarg(ptyp(sp_cst2))); + putarg(getarg(ptyp(sp_cst2))); + break; + case ps_pro: + putarg(getarg(ptyp(sp_pnam))); + putarg(getarg(cst_ptyp|ptyp(sp_cend))); + break; + case ps_end: + putarg(getarg(cst_ptyp|ptyp(sp_cend))); + break; + default: + error("bad pseudo %d",i); + } +} + +/* ----- input ----- */ + +int getarg(typset) { + register t,argtyp; + + argtyp = t = table2(); + if (t == EOF) + fatal("unexpected EOF"); + t -= sp_fspec; + assert(t >= 0 && t < 16); + t = 1 << t; + if ((typset & t) == 0) + error("bad argument type %d",argtyp); + return(argtyp); +} + +int table1() { + register i; + + i = get8(); + if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) { + opcode = i; + return(sp_fmnem); + } + if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) { + opcode = i; + return(sp_fpseu); + } + if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) { + argval = i - sp_filb0; + return(sp_ilb2); + } + return(table3(i)); +} + +int table2() { + register i; + + i = get8(); + if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) { + argval = i - sp_zcst0; + return(sp_cst2); + } + return(table3(i)); +} + +int table3(i) { + long consiz; + + switch(i) { + case sp_ilb1: + argval = get8(); + break; + case sp_dlb1: + dlbval = get8(); + break; + case sp_dlb2: + dlbval = get16(); + if ( dlbval<0 ) { + error("illegal data label .%d",dlbval); + dlbval=0 ; + } + break; + case sp_cst2: + argval = get16(); + break; + case sp_ilb2: + argval = get16(); + if ( argval<0 ) { + error("illegal instruction label %D",argval); + argval=0 ; + } + break; + case sp_cst4: + argval = get32(); + break; + case sp_dnam: + case sp_pnam: + getstring(1); + break; + case sp_scon: + getstring(0); + break; + case sp_doff: + offtyp = getarg(sym_ptyp); + getarg(cst_ptyp); + break; + case sp_icon: + case sp_ucon: + case sp_fcon: + getarg(cst_ptyp); + consiz = (long) argval; + getstring(0); + argval = consiz; + break; + } + return(i); +} + +int get16() { + register int l_byte, h_byte; + + l_byte = get8(); + h_byte = get8(); + if ( h_byte>=128 ) h_byte -= 256 ; + return l_byte | (h_byte*256) ; +} + +long get32() { + register long l; + register int h_byte; + + l = get8(); l |= (unsigned)get8()*256 ; l |= get8()*256L*256L ; + h_byte = get8() ; + if ( h_byte>=128 ) h_byte -= 256 ; + return l | (h_byte*256L*256*256L) ; +} + +getstring(ident) { + register char *p; + register n; + + getarg(cst_ptyp); + if (argval < 0 || argval > MAXSTR) + fatal("string/identifier too long"); + strsiz = n = argval; + p = string; + while (--n >= 0) + *p++ = get8(); + if (ident) { + if (!isascii(string[0]) || !isalpha(string[0])) { + identerror(); + return; + } + for (n=strsiz,p=string+1;--n>0;p++) + if (!isascii(*p) || !isalnum(*p)) { + identerror(); + return; + } + } +} + +/* ----- output ----- */ + +putarg(t) { + + if (argnum != 0) + putchar(argnum == 1 ? ' ' : ','); + argnum++; + puttyp(t); +} + +puttyp(t) { + + switch (t) { + case sp_ilb1: + case sp_ilb2: + printf("*%d",(int) argval); + break; + case sp_dlb1: + case sp_dlb2: + printf(".%d",dlbval); + break; + case sp_dnam: + putstr(0,0); + break; + case sp_cst2: + case sp_cst4: + printf("%D",argval); + break; + case sp_doff: + puttyp(offtyp); + if (argval >= 0) putchar('+'); + printf("%D",argval); + break; + case sp_pnam: + putstr('$',0); + break; + case sp_scon: + putstr('\'','\''); + break; + case sp_icon: + putstr(0,'I'); + printf("%D",argval); + break; + case sp_ucon: + putstr(0,'U'); + printf("%D",argval); + break; + case sp_fcon: + putstr(0,'F'); + printf("%D",argval); + break; + case sp_cend: + putchar('?'); + break; + } +} + +putstr(c,c2) register c; { + register char *p; + + if (c) + putchar(c); + p = string; + while (--strsiz >= 0) { + c = *p++ & 0377; + if (c >= 040 && c < 0177) { + if (c == '\'' || c == '\\') + putchar('\\'); + putchar(c); + } else + printf("\\%03o",c); + } + if (c2) + putchar(c2); +} + +/* ----- error handling ----- */ + +fail_check() { + error("argument range error"); +} + +identerror() { + error("'%s' is not a correct identifier",string); +} + +/* VARARGS */ +error(s,a1,a2,a3,a4) char *s; { + fprintf(stderr, + "%s: line %d: ", + filename ? filename : progname, + lineno); + fprintf(stderr,s,a1,a2,a3,a4); + fprintf(stderr,"\n"); + errors++; +} + +/* VARARGS */ +fatal(s,a1,a2,a3,a4) char *s; { + error(s,a1,a2,a3,a4); + exit(-1); +} diff --git a/util/misc/encode.c b/util/misc/encode.c new file mode 100644 index 000000000..86e76acd7 --- /dev/null +++ b/util/misc/encode.c @@ -0,0 +1,757 @@ +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* + * Encode to compact EM assembly language + * + * Author: Johan Stevenson, Vrije Universiteit, Amsterdam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define put8(x) putchar(x) + +#define check(x) if (!(x)) fail_check() + +#define fit16i(x) ((x) >= 0xFFFF8000 && (x) <= 0x00007FFF) +#define fit8u(x) ((x) >= 0 && (x) <= 0xFF) + +#define MAXSTR 256 +#define HSIZE 256 +#define EMPTY (EOF-1) + +/* + * global variables + */ + +int opcode; +int offtyp; +long argval; +int dlbval; +char string[MAXSTR]; +int strsiz; + +int wsize; +int psize; +int lineno; +int argnum; +int errors; +char *progname; +char *filename = "INPUT"; + +long wordmask[] = { /* allowed bits in a word */ + 0x00000000, + 0x000000FF, + 0x0000FFFF, + 0x00000000, + 0xFFFFFFFF +}; + +long sizemask[] = { /* allowed bits in multiples of 'wsize' */ + 0x00000000, + 0x7FFFFFFF, + 0x7FFFFFFE, + 0x00000000, + 0x7FFFFFFC +}; + +int peekc = EMPTY; +int hashtab[HSIZE]; +jmp_buf recover; + +/* + * external tables + */ + +extern char em_flag[]; +extern short em_ptyp[]; +extern char em_mnem[][4]; +extern char em_pseu[][4]; + +int main(argc,argv) char **argv; { + + progname = argv[0]; + if (argc >= 2) { + filename = argv[1]; + if (freopen(filename,"r",stdin) == NULL) + fatal("can't open %s",filename); + } + if (argc >= 3) + if (freopen(argv[2],"w",stdout) == NULL) + fatal("can't create %s",argv[2]); + init(); + put16(sp_magic); + setjmp(recover); + while (nextline()) + ; + return(errors ? -1 : 0); +} + +/* ----- copy ----- */ + +int nextline() { + register c,i; + + lineno++; + argnum = 1; + c = nextchar(); + if (c == EOF) + return(0); + if (isspace(c) && c != '\n') { + c = nospace(); + if (isalpha(c)) { + inmnem(c); + if (opcode <= sp_lmnem) + instr(); + else + pseudo(); + } else + peekc = c; + } else if (c == '#') { + line_line(); + } else { + peekc = c; + i = gettyp(sym_ptyp | ptyp(sp_cst2) | ptyp(sp_cend)); + switch (i) { + case sp_cst2: + i = (int) argval; + if (i >= 0 && i < sp_nilb0) + put8(i + sp_filb0); + else + putarg(sp_ilb2); + break; + case sp_dlb2: + case sp_dnam: + putarg(i); + break; + case sp_cend: + break; + } + } + if (nospace() != '\n') + syntax("end of line expected"); + return(1); +} + +instr() { + register i,j,t; + register long l; + + i = opcode; + put8(i); + i -= sp_fmnem; + j = em_flag[i] & EM_PAR; + if (j == PAR_NO) + return; + t = em_ptyp[j]; + if (j == PAR_B) + t = ptyp(sp_ilb2); + t = getarg(t); + /* + * range checking + */ + switch (j) { + case PAR_N: + check(argval >= 0); + break; + case PAR_G: + if (t != sp_cst2 && t != sp_cst4) + break; + check(argval >= 0); + /* fall through */ + case PAR_L: + l = argval >= 0 ? argval : -argval; + check((l & ~wordmask[psize]) == 0); + break; + case PAR_W: + if (t == sp_cend) + break; + check((argval & ~wordmask[wsize]) == 0); + /* fall through */ + case PAR_S: + check(argval != 0); + /* fall through */ + case PAR_Z: + check((argval & ~sizemask[wsize]) == 0); + break; + case PAR_O: + check(argval != 0); + check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0); + break; + case PAR_B: + t = sp_cst2; + break; + case PAR_R: + check(argval >= 0 && argval <= 2); + break; + } + putarg(t); +} + +pseudo() { + register i,t; + + i = opcode; + put8(i); + switch (i) { + case ps_bss: + case ps_hol: + putarg(getarg(cst_ptyp)); + putarg(getarg(val_ptyp)); + putarg(getarg(ptyp(sp_cst2))); + check(argval==0 || argval==1); + break; + case ps_rom: + case ps_con: + putarg(getarg(val_ptyp)); + do + putarg(t = getarg(any_ptyp)); + while (t != sp_cend); + break; + case ps_mes: + putarg(getarg(ptyp(sp_cst2))); + if (argval == ms_emx) { + putarg(getarg(ptyp(sp_cst2))); + check(argval > 0 && argval <= 4); + wsize = (int) argval; + putarg(getarg(ptyp(sp_cst2))); + check(argval > 0 && argval <= 4); + psize = (int) argval; + } + do + putarg(t = getarg(any_ptyp)); + while (t != sp_cend); + break; + case ps_exa: + case ps_ina: + putarg(getarg(sym_ptyp)); + break; + case ps_exp: + case ps_inp: + putarg(getarg(ptyp(sp_pnam))); + break; + case ps_exc: + putarg(getarg(ptyp(sp_cst2))); + putarg(getarg(ptyp(sp_cst2))); + break; + case ps_pro: + putarg(getarg(ptyp(sp_pnam))); + putarg(getarg(cst_ptyp|ptyp(sp_cend))); + break; + case ps_end: + putarg(getarg(cst_ptyp|ptyp(sp_cend))); + break; + default: + syntax("bad pseudo %d",i); + } +} + +/* ----- input ----- */ + +int getarg(typset) { + register c; + + if (argnum != 1) { + c = nospace(); + if (c != ',') { + if (c != '\n') + syntax("comma expected"); + peekc = c; + } + } + argnum++; + return(gettyp(typset)); +} + +int gettyp(typset) { + register c,t,sp; + + c = nospace(); + if (c == '\n') { + peekc = c; + sp = sp_cend; + } else if (isdigit(c) || c == '+' || c == '-' || c == '(') { + sp = inexpr1(c); + if (sp == sp_cst4 && fit16i(argval)) + sp = sp_cst2; + } else if (isalpha(c)) { + inname(c); + sp = offsetted(sp_dnam); + } else if (c == '.') { + in15u(); + dlbval = (int) argval; + sp = offsetted(sp_dlb2); + } else if (c == '*') { + in15u(); + sp = sp_ilb2; + } else if (c == '$') { + inname(nextchar()); + sp = sp_pnam; + } else if (c == '"' || c == '\'') { + sp = instring(c); + } else if (c == '?') { + sp = sp_cend; + } else + syntax("operand expected"); + t = sp - sp_fspec; + assert(t >= 0 && t < 16); + t = 1 << t; + if ((typset & t) == 0) + error("bad argument type %d",sp); + return(sp); +} + +int offsetted(sp) { + register c; + + c = nospace(); + if (c == '+' || c == '-') { + gettyp(cst_ptyp); + if (c == '-') + argval = -argval; + offtyp = sp; + return(sp_doff); + } + peekc = c; + return(sp); +} + +inname(c) register c; { + register char *p; + + if (isalpha(c) == 0) + syntax("letter expected"); + p = string; + do { + if (p < &string[MAXSTR-1]) + *p++ = c; + c = nextchar(); + } while (isalnum(c)); + peekc = c; + *p = '\0'; + strsiz = p - string; +} + +int inmnem(c) register c; { + register unsigned h; + register i; + + inname(c); + h = hash(string); + for (;;) { + h++; + h %= HSIZE; + i = hashtab[h]; + if (i == 0) + syntax("bad mnemonic"); + if (i <= sp_lmnem) { + assert(i >= sp_fmnem); + if (strcmp(string,em_mnem[i - sp_fmnem]) != 0) + continue; + return(opcode = i); + } + assert(i <= sp_lpseu && i >= sp_fpseu); + if (strcmp(string,em_pseu[i - sp_fpseu]) != 0) + continue; + return(opcode = i); + } +} + +int inexpr1(c) register c; { + long left; + + if ((c = inexpr2(c)) != sp_cst4) + return(c); + for (;;) { + c = nospace(); + if (c != '+' && c != '-') { + peekc = c; + break; + } + left = argval; + if (inexpr2(nospace()) != sp_cst4) + syntax("term expected"); + if (c == '+') + argval += left; + else + argval = left - argval; + } + return(sp_cst4); +} + +int inexpr2(c) register c; { + long left; + + if ((c = inexpr3(c)) != sp_cst4) + return(c); + for (;;) { + c = nospace(); + if (c != '*' && c != '/' && c != '%') { + peekc = c; + break; + } + left = argval; + if (inexpr3(nospace()) != sp_cst4) + syntax("factor expected"); + if (c == '*') + argval *= left; + else if (c == '/') + argval = left / argval; + else + argval = left % argval; + } + return(sp_cst4); +} + +inexpr3(c) register c; { + + if (c == '(') { + if (inexpr1(nospace()) != sp_cst4) + syntax("expression expected"); + if (nospace() != ')') + syntax("')' expected"); + return(sp_cst4); + } + return(innumber(c)); +} + +int innumber(c) register c; { + register char *p; + register n; + int expsign; + static char numstr[MAXSTR]; + long atol(); + + p = numstr; + expsign = 0; + if (c == '+' || c == '-') { + if (c == '-') + *p++ = c; + c = nextchar(); + } + if (isdigit(c) == 0) + syntax("digit expected"); + n = sp_cst4; + for (;;) { + if (p >= &numstr[MAXSTR-1]) + fatal("number too long"); + *p++ = c; + c = nextchar(); + if (c == '.' || c == 'e' || c == 'E') { + expsign = c != '.'; + n = sp_fcon; + continue; + } + if (expsign) { + expsign = 0; + if (c == '+' || c == '-') + continue; + } + if (isdigit(c) == 0) + break; + } + peekc = c; + *p = '\0'; + c = nospace(); + if (n == sp_fcon && c != 'F') + syntax("'F' expected"); + if (c == 'I' || c == 'U' || c == 'F') + return(incon(numstr,c)); + peekc = c; + argval = atol(numstr); + return(sp_cst4); +} + +in15u() { + + if (innumber(nextchar()) != sp_cst4) + syntax("integer expected"); + check((argval & ~077777) == 0); +} + +int incon(p,c) register char *p; { + register char *q; + + q = string; + while (*q++ = *p++) + ; + strsiz = q - string - 1; + gettyp(cst_ptyp); + return(c == 'I' ? sp_icon : (c == 'U' ? sp_ucon : sp_fcon)); +} + +int instring(termc) { + register char *p; + register c; + + p = string; + for (;;) { + c = nextchar(); + if (c == '\n' || c == EOF) { + peekc = c; + syntax("non-terminated string"); + } + if (c == termc) { + if (termc == '"') + *p++ = '\0'; + break; + } + if (c == '\\') + c = inescape(); + if (p >= &string[MAXSTR-1]) + fatal("string too long"); + *p++ = c; + } + strsiz = p - string; + return(sp_scon); +} + +int inescape() { + register c,j,r; + + c = nextchar(); + if (c >= '0' && c <= '7') { + r = c - '0'; + for (j = 0; j < 2; j++) { + c = nextchar(); + if (c < '0' || c > '7') { + peekc = c; + return(r); + } + r <<= 3; + r += (c - '0'); + } + return(r); + } + switch (c) { + case 'b': return('\b'); + case 'f': return('\f'); + case 'n': return('\n'); + case 'r': return('\r'); + case 't': return('\t'); + } + return(c); +} + +int nospace() { + register c; + + do + c = nextchar(); + while (isspace(c) && c != '\n'); + if (c == ';') + do + c = nextchar(); + while (c != '\n' && c != EOF); + return(c); +} + +int nextchar() { + register c; + + if (peekc != EMPTY) { + c = peekc; + peekc = EMPTY; + return(c); + } + c = getchar(); + if (isascii(c) == 0 && c != EOF) + fatal("non-ascii char"); + return(c); +} + +line_line() { + register char *p,*q; + static char filebuff[MAXSTR+1]; + + gettyp(ptyp(sp_cst2)); + lineno = (int) (argval-1); + gettyp(ptyp(sp_scon)); + p = string; + q = filebuff; + while (--strsiz >= 0) + *q++ = *p++; + *q = '\0'; + filename = filebuff; +} + +init() { + register i; + + for (i = sp_fmnem; i <= sp_lmnem; i++) + pre_hash(i,em_mnem[i - sp_fmnem]); + for (i = sp_fpseu; i <= sp_lpseu; i++) + pre_hash(i,em_pseu[i - sp_fpseu]); + /* treat '_' as letter */ + /* In System III the array is called _ctype[] without the trailing '_' */ + (_ctype_+1)['_'] = (_ctype_+1)['a']; +} + +pre_hash(i,s) char *s; { + register unsigned h; + + assert(i != 0); + h = hash(s); + for (;;) { + h++; + h %= HSIZE; + if (hashtab[h] == 0) { + hashtab[h] = i; + return; + } + } +} + +int hash(s) register char *s; { + register h; + + h = 0; + while (*s) { + h <<= 1; + h += *s++; + } + return(h); +} + +/* ----- output ----- */ + +putarg(sp) register sp; { + register i; + + switch (sp) { + case sp_ilb2: + i = (int) argval; + if (fit8u(i)) { + put8(sp_ilb1); + put8(i); + break; + } + put8(sp); + put16(i); + break; + case sp_dlb2: + i = dlbval; + if (fit8u(i)) { + put8(sp_dlb1); + put8(i); + break; + } + put8(sp); + put16(i); + break; + case sp_cst2: + case sp_cst4: + if (fit16i(argval) == 0) { + put8(sp_cst4); + put32(argval); + break; + } + i = (int) argval; + if (i >= -sp_zcst0 && i < sp_ncst0 - sp_zcst0) { + put8(i + sp_zcst0 + sp_fcst0); + break; + } + put8(sp_cst2); + put16(i); + break; + case sp_doff: + put8(sp); + putarg(offtyp); + putarg(sp_cst4); + break; + case sp_dnam: + case sp_pnam: + case sp_scon: + put8(sp); + putstr(); + break; + case sp_icon: + case sp_ucon: + case sp_fcon: + put8(sp); + putarg(sp_cst4); + putstr(); + break; + case sp_cend: + put8(sp); + break; + } +} + +putstr() { + register char *p; + long consiz; + + consiz = argval; + argval = strsiz; + putarg(sp_cst4); + argval = consiz; + p = string; + while (--strsiz >= 0) + put8(*p++); +} + +put16(w) int w; { + + put8(w); + put8(w >> 8); +} + +put32(f) long f; { + + put16((int) f); + put16((int)(f >> 16)); +} + +/* ----- error handling ----- */ + +fail_check() { + error("argument range error"); +} + +/* VARARGS */ +error(s,a1,a2,a3,a4) char *s; { + fprintf(stderr,"%s: line %d: ", filename, lineno); + fprintf(stderr,s,a1,a2,a3,a4); + fprintf(stderr,"\n"); + errors++; +} + +/* VARARGS */ +fatal(s,a1,a2,a3,a4) char *s; { + error(s,a1,a2,a3,a4); + exit(-1); +} + +/* VARARGS */ +syntax(s,a1,a2,a3,a4) char *s; { + register c; + + error(s,a1,a2,a3,a4); + do + c = nextchar(); + while (c != '\n' && c != EOF); + longjmp(recover); +}