--- /dev/null
+/*
+ * (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 <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+#include <em_spec.h>
+#include <em_pseu.h>
+#include <em_flag.h>
+#include <em_ptyp.h>
+#include <em_mes.h>
+
+#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);
+}
--- /dev/null
+/*
+ * (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 <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <em_spec.h>
+#include <em_pseu.h>
+#include <em_flag.h>
+#include <em_ptyp.h>
+#include <em_mes.h>
+
+#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);
+}