#include <stdio.h> #include <string.h> #include <assert.h> #include <stdlib.h> #include <ctype.h> #include <errno.h> #define OLD_ICODE 1 #ifndef FALSE #define TRUE (0==0) #define FALSE (0!=0) #endif static int debug_input = FALSE; static char *indent = " "; FILE *icode_file; FILE *source_file; int source_line = 0; #define MAX_LINE 1024 char line[MAX_LINE+1]; /* This is primarily for the old-style (as described in the thesis) icode, with any 'unused' opcodes plugged in with the newer description from https://web.archive.org/web/20041216161503/http://www.gtoal.com/athome/edinburgh/imp77/gtoal/icode.html ( http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html ) Lower case text in the array below means 'new style'. There are also all the new opcodes >= 128 which I have not yet incorporated - the coding can be found by grepping for ^c\( in file https://history.dcs.ed.ac.uk/archive/languages/imp77-acorn-tmp/3l/COMPILERS/bend/imp/pass2 ( http://www.gtoal.com/athome/edinburgh/acorn/3l/COMPILERS/bend/imp/pass2 ) I think some of the old-style opcodes were redefined in an incompatible way for the new style. So be careful. For now this is really just old-style only, which I hope is all that is ever generated by the Mouses Imp77 V8.4 compiler which ABD is porting. */ #ifdef OLD_ICODE static char *icode_name[256] = { "<0>", "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>", "<10>", "<11>", "<12>", "<13>", "<14>", "<15>", "<16>", "<17>", "<18>", "<19>", "<20>", "<21>", "<22>", "<23>", "<24>", "<25>", "<26>", "<27>", "<28>", "<29>", "<30>", "<31>", /* SP ! " # $ % & ' ( ) * + , - . / */ "<32>", "OR", "JUMPIFD", "BNE", "DEF", "XOR", "AND", "PUSHS", "<'('>", "<')'>", "MUL", "ADD", "+ ", "SUB", "CONCAT", "QUOT", /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ "<'0'>", "<'1'>", "<'2'>", "<'3'>", "<'4'>", "<'5'>", "<'6'>", "<'7'>", "<'8'>", "<'9'>", "LOCATE", "END", "<'<'>", "<'='>", "<'>'>", "JUMPIF", /* @ A B C D E F G H I J K L M N O */ "PUSH", "INIT", "REPEAT", "JUMPIFA", "PUSHR", "CALL", "GOTO", "ALIAS", "BEGIN", "<'I'>", "JUMP", "FALSE", "LABEL", "MAP", "PUSHI", "LINE", /* P Q R S T U V W X Y Z [ \ ] ^ _ */ "PLANT", "DIVIDE", "RETURN", "ASSVAL", "TRUE", "NEGATE", "RESULT", "SJUMP", "IEXP", "DEFAULT", "ASSREF", "LSH", "NOT", "RSH", "PROC", "SLABEL", /* ` a b c d e f g h i j k l m n o */ "<'`'>", "ACCESS", "BOUNDS", "MCODE", "DIM", "EVENT", "FOR", "<'g'>", "ALTBEG", "INDEX", "JAM", "BF", "LANG", "MONITOR", "SELECT", "ON", /* p q r s t u v w x y z { | } ~ DEL */ "ASSPAR", "ALTEND", "RESOLVE", "STOP", "BT", "ADDA", "MOD", "SUBA", "REXP", "DIAG", "CONTROL", "START", "ALT", "FINISH", "pending", "<127>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", }; #else /* New Icode */ static char *icode_name[256] = { "<0>", "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>", "<10>", "<11>", "<12>", "<13>", "<14>", "<15>", "<16>", "<17>", "<18>", "<19>", "<20>", "<21>", "<22>", "<23>", "<24>", "<25>", "<26>", "<27>", "<28>", "<29>", "<30>", "<31>", /* SP ! " # $ % & ' ( ) * + , - . / */ "<32>", "OR", "JUMPIFD/compare-double?", "BNE", "DEF", "XOR", "AND", "PUSHS", "ble", "bge", "MUL", "ADD", "+ ", "SUB", "CONCAT", "QUOT", /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ "<'0'>", "<'1'>", "<'2'>", "<'3'>", "<'4'>", "<'5'>", "<'6'>", "<'7'>", "<'8'>", "<'9'>", "LOCATE", "END", "blt", "beq", "bgt", "JUMPIF/compare-values?", /* @ A B C D E F G H I J K L M N O */ "PUSH", "INIT", "REPEAT", "JUMPIFA/compare-addresses", "PUSHR", "CALL", "GOTO", "ALIAS", "BEGIN", "select-input-2", "JUMP", "FALSE", "LABEL", "MAP", "PUSHI", "LINE", /* P Q R S T U V W X Y Z [ \ ] ^ _ */ "PLANT", "DIVIDE", "RETURN", "ASSVAL", "TRUE", "NEGATE", "RESULT", "SJUMP", "IEXP", "DEFAULT", "ASSREF", "LSH", "NOT", "RSH", "PROC", "SLABEL", /* ` a b c d e f g h i j k l m n o */ "<'`'>", "ACCESS", "BOUNDS", "MCODE", "DIM", "EVENT", "FOR", "<'g'>", "ALTBEG", "INDEX", "JAM", "bf", "LANG", "MONITOR", "SELECT", "ON", /* p q r s t u v w x y z { | } ~ DEL */ "ASSPAR", "ALTEND", "RESOLVE", "STOP", "bt", "ADDA", "MOD", "SUBA", "REXP", "DIAG", "CONTROL", "START", "ALT", "FINISH", "pending", "<127>", /* c('!'): Operation(ORx); %continue c('"'): Compare Double; %continue c('#'): Jump Forward(Tag, NE); %continue c('$'): Define Var; %continue c('%'): Operation(XORx); %continue c('&'): Operation(ANDx); %continue c(''''): Input String Value; %continue c('('): Jump Forward(Tag, LE); %continue c(')'): Jump Forward(Tag, GE); %continue c('*'): Operation(MULx); %continue c('+'): Operation(ADDx); %continue c('-'): Operation(SUBx); %continue c('.'): Operation(CONCx); %continue c('/'): Operation(DIVx); %continue c(':'): Define Compiler Label(Tag); %continue c(';'): End of Block; %exit c('<'): Jump Forward(Tag, LT); %continue c('='): Jump Forward(Tag, EQ); %continue c('>'): Jump Forward(Tag, GT); %continue c('?'): Compare Values; %continue c('@'): Stack Var(Tag); %continue c('A'): Init(Tag); %continue c('B'): Jump Backward(Tag); %continue c('C'): Compare Addresses; %continue c('D'): Input Real Value; %continue c('E'): Call(0); %continue c('F'): Jump Forward(Tag, Always); %continue c('G'): Get String(Alias); %continue c('H'): Compile Begin; %continue c('I'): Select Input(Icode In2); Readsymbol(Pending); %continue c('J'): User Jump(Tag); %continue c('K'): Return(False); %continue c('L'): Define User Label(Tag); %continue c('M'): Return(Map); %continue c('N'): Input Integer Value(0); %continue c('O'): Update Line(Tag); %continue c('P'): Dump Byte(Popped Value&255); %continue c('Q'): Operation(RDIVx); %continue c('R'): Return(Routine); %continue c('S'): Assign(Equals); %continue c('T'): Return(True); %continue c('U'): Operate(NEGx, Stack, Nil); %continue c('V'): Return(Fn); %continue c('W'): Switch Jump(Tag); %continue c('X'): Operation(EXPx); %continue c('Z'): Assign(EqualsEquals); %continue c('['): Operation(LSHx); %continue c('\'): Operate(NOTx, Stack, Nil); %continue c(']'): Operation(RSHx); %continue c('^'): Stack_Format = -Tag; %continue c('_'): Switch Label(Tag); %continue c('a'): Array Access; %continue c('b'): Constant Bounds; %continue c('c'): Section = 1; Get String(Section Id); %exit c('d'): D = Tag; N = Tag; Dimension(D, N); %continue c('e'): Signal Event(Tag); %continue c('f'): Compile For(Tag); %continue c('g'): Test for NIL; %continue c('h'): Special Call(Tag); %continue c('i'): Array Index; %continue c('j'): Assign(Jam); %continue c('k'): Jump Forward(Tag, FF); %continue c('l'): Language Flags = Tag; %continue c('m'): Do(Monitor Id, Monitor Ep, 0); %continue c('n'): Select(Tag); %continue c('o'): Event Trap(Tag); %continue c('p'): AssignParameter; %continue c('q'): Process Include File; %continue c('r'): Resolve(Tag); %continue c('s'): To Store(Tag); %continue c('t'): Jump Forward(Tag, TT); %continue c('u'): Aop; %continue c('v'): Operate(ABSx, Stack, Nil); %continue c('w'): Machine Code; Forget Everything; %continue c('x'): Operation(REXPx); %continue c('y'): Set CD(Tag, Diag); %continue c('z'): Set CD(Tag, Control); %continue c('{'): Assemble(DefV, Blocktype, Vars, Local+1, Parameter Mode, Attributes) %continue c('}'): %exit %if Finish Params Do("3L___stack_check", Stack Check, 0) %if Interface_Options&LL Stack # 0 %continue c('~'): N = Pending; Readsymbol(Pending) %exit %if Alternate Format(N); %continue */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", /* SP ! " # $ % & ' ( ) * + , - . / */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", /* @ A B C D E F G H I J K L M N O */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", /* P Q R S T U V W X Y Z [ \ ] ^ _ */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", /* ` a b c d e f g h i j k l m n o */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", /* p q r s t u v w x y z { | } ~ DEL */ "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", "<128-255>", }; /* Details of codes >= 128 can be found in https://history.dcs.ed.ac.uk/archive/languages/imp77-acorn-tmp/3l/COMPILERS/bend/imp/pass2 {************ Extra Items **************} c(128+'"'): Unsigned = 10; Stack Condition; %continue c(128+'?'): Unsigned = 10; Compare Values; %continue c(128+','): Max Frame = Frame %if Frame > Max Frame Frame = Frame Base; %continue c(128+'0'): N = Tag; {but no operation} %continue c(128+'1'): Add Member(0); %continue c(128+'2'): Add Member(1); %continue c(128+'3'): Set Variant Count(Tag); %continue c(128+'4'): Test Variant Count(Tag); %continue c(128+'5'): Check not long NEW; %continue c(128+'6'): Check Dynamic Bounds; %continue c(128+'/'): Operation(UDIVx); %continue c(128+'|'): Operation(UREMx); %continue c(128+'@'): Decode(0, -1) %if Diag&Mon Code # 0 Current Line = Tag; %continue c(128+'A'): Amap(Stack); %continue c(128+'B'): %if Pending = 't' %then Pending = '#' - %else Pending = '=' Test Zero(Stack); Pop Release and Drop; %continue c(128+'C'): Unsigned = 0; Stack Condition; %continue c(128+'D'): Duplicate; %continue c(128+'E'): Loadup(Stack) %unless Stack_Form = Address - %and Locked(Stack_Base) - %and Stack_Record == Nil - %and Stack_Index == Nil; %continue c(128+'F'): Stack_Format = -Tag; %continue c(128+'I'): Compile In(1); %continue c(128+'L'): Localise; %continue c(128+'M'): Operation(MODx); %continue c(128+'N'): Operation(REMx); %continue C(128+'O'): Apply Round(Stack); %continue c(128+'P'): Pop Release and Drop; %continue c(128+'R'): Define Range; %continue c(128+'S'): Swop; %continue c(128+'T'): Apply Trunc(Stack); %continue c(128+'U'): Use With(Tag); %continue c(128+'V'): Vmap(Stack, Tag); %continue c(128+'W'): Stack Work Variable; %continue C(128+'X'): Loadup(Stack) %unless Stack_Type = Lreals; %continue c(128+'Z'): Stack Integer(0); Stack_Type = Sets Stack_Flags = Null Set; %continue c(128+'['): Claim With(Tag); %continue c(128+']'): Release With(Tag); %continue c(128+'b'): Input Integer Value(1); %continue c(128+'c'): General Compare; %continue c(128+'e'): N = Stack_Type ; Amap(Stack) Loadup(Stack) %unless Stack_Form = Address - %and Locked(Stack_Base) - %and Stack_Index == Nil - %and Stack_Record == Nil Vmap(Stack, N); %continue c(128+'f'): For Range == Var(Tag); %continue c(128+'g'): Call(1); %continue c(128+'i'): Compile In(0); %continue C(128+'n'): Apply Int(Stack); %continue c(128+'m'): General Move; %continue c(128+'o'): Owntype = Tag; %continue c(128+'p'): Fmap(Tag); %continue c(128+'r'): Test Range(Stack, Var(Tag)); %continue c(128+'s'): Set Size or Type(1, Stack); %continue c(128+'t'): Set Size or Type(2, Stack); %continue c(128+'v'): Compare Values; Prim(Test Variant); %continue c(128+'w'): Apply Intpt(Stack); %continue c(128+'z'): Stack Data Size; %continue c(128+'{'): Nn = 0 Assemble(AltV, -2, Vars, Local, -1, Nn) Alt Align = Alt Align&Falign; %continue c(128+'}'): Frame = Max Frame %if Max Frame > Frame Falign = Alt Align; %exit */ #endif int get_icode(FILE *f) { int c = fgetc(f); if (c != EOF) { if (debug_input) { if ('!' <= c && c <= '~') { fprintf(stdout, "'%c':\n", c); } else if ((('!'|128) <= (c|128)) && ((c|128) <= ('~'|128))) { fprintf(stdout, "128+'%c':\n", c&127); } else { fprintf(stdout, "%d:\n", c); } } } return(c); } static char *getname(void) /* A Hack */ { static char local[256]; int c; char *s = local; for (;;) { c = get_icode(icode_file); assert(c != EOF); if ((isalpha(c) && isupper(c)) || isdigit(c)) { } else break; *s++ = c; } *s = '\0'; ungetc(c, icode_file); return(local); } static char *getwordconst(void) { static char local[12]; int i, c; int word = 0; for (i = 0; i < 4; i++) { word = word << 8 | (c = get_icode(icode_file)); assert(c != EOF); } sprintf(local, "#0x%08x", word); return(local); } static char *getbyte(void) { static char local[4]; int c; c = get_icode(icode_file); assert(c != EOF); sprintf(local, "%02x", c&255); return(local); } static char *getcond(void) { static char local[3]; int c; c = get_icode(icode_file); assert(c != EOF); c &= 255; if (c == '(') { sprintf(local, "<="); } else if (c == ')') { sprintf(local, ">="); } else { sprintf(local, "%c", c&255); } return(local); } static char *getimpstring(void) { static char local[256*2+3]; int i, c, len; char *s = local; len = get_icode(icode_file); assert(c != EOF); *s++ = '"'; for (i = 0; i < len; i++) { c = get_icode(icode_file); assert(c != EOF); if (c == '"') { *s++ = '\\'; *s++ = c; } else if (c == '\n') { *s++ = '\\'; *s++ = 'n'; } else *s++ = c; } *s++ = '"'; *s++ = '\0'; return(local); } static char *getmcstring(int *cp) { static char local[256*2+3]; int i, c, len; char *s = local; for (;;) { c = get_icode(icode_file); assert(c != EOF); if ((c == ' ') || (c == ';')) { *s++ = '\0'; *cp = c; return(local); } *s++ = c; } } static char *getshort(void) { static char local[5]; int i, c; int word = 0; for (i = 0; i < 2; i++) { word = word << 8 | (c = get_icode(icode_file)); assert(c != EOF); } sprintf(local, "%04x", word); return(local); } static char *getshortdecimal(int *d) { static char local[7]; int i, c; int word = 0; for (i = 0; i < 2; i++) { word = word << 8 | (c = get_icode(icode_file)); assert(c != EOF); } if (d != NULL) *d = word; sprintf(local, "%0d", word); return(local); } static char *getlab(void) { static char local[7]; int i, c; int word = 0; for (i = 0; i < 2; i++) { word = word << 8 | (c = get_icode(icode_file)); assert(c != EOF); } sprintf(local, "L_%04x", word); return(local); } static char *getvar(void) { static char local[7]; int i, c; int word = 0; for (i = 0; i < 2; i++) { word = word << 8 | (c = get_icode(icode_file)); assert(c != EOF); } sprintf(local, "V_%04x", word); return(local); } int main(int argc, char **argv) { char *p1, *p2, *p3; int opcode, d; char icode_filename[256], source_filename[256]; if (argc >= 2 && strcmp(argv[1], "-d") == 0) { debug_input = TRUE; argc -= 1; argv += 1; } if (argc == 1 || argc > 3) { fprintf(stderr, "syntax: idec file.icd {file.imp}? *or* idec basename (looks for .icd and .imp extensions)\n"); exit(1); } if (argc == 3) { sprintf(icode_filename, "%s", argv[1]); } else { sprintf(icode_filename, "%s.icd", argv[1]); } icode_file = fopen(icode_filename, "rb"); if (icode_file == NULL) { fprintf(stderr, "idec: cannot open '%s' - %s\n", icode_filename, strerror(errno)); exit(2); } if (argc == 3) { sprintf(source_filename, "%s", argv[2]); } else { sprintf(source_filename, "%s.imp", argv[1]); } source_file = fopen(source_filename, "r"); if (source_file != NULL) { fprintf(stdout, "\n %s\n\n\n", "Edinburgh IMP77 Compiler - Version 8.4"); } for (;;) { opcode = get_icode(icode_file); if (opcode == EOF) break; switch(opcode) { case '\n': break; case '$': /* DEF TAG TEXT TYPE FORM SIZE SPEC PREFIX */ p1 = getvar(); p2 = getname(); fprintf(stdout, "%s%s %s %s\n", indent, icode_name[opcode], p1, p2); break; case ',': fprintf(stdout, "%s%s 0x%s\n", /* TEMP HACK */ indent, icode_name[opcode], getshort()); break; case '"': /* JUMPIFD cond label */ case 'C': /* JUMPIFA cond label */ case '?': /* JUMPIF cond label */ p1 = getcond(); p2 = getlab(); fprintf(stdout, "%s%s %s %s\n", indent, icode_name[opcode], p1, p2); break; case 'k': /* BF label */ case 't': /* BT label */ p1 = getlab(); fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], p1); break; case '\'': /* PUSHS sconst */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getimpstring()); break; case 'D': /* PUSHR rconst */ fprintf(stdout, "%s/* TODO */ %s %s\n", indent, icode_name[opcode], getwordconst()); break; case 'N': /* PUSHI iconst */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getwordconst()); break; case ':': /* LOCATE label */ case 'B': /* REPEAT label */ case 'F': /* GOTO label */ case 'J': /* JUMP label */ case 'L': /* LABEL label */ case 'f': /* FOR label (label was missing from thesis description) */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getlab()); break; case 'O': /* LINE decimal */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getshortdecimal(&d)); /* output source file up to line %d */ if (source_file != NULL) { while (source_line < /*+1*/d) { if (fgets(line, MAX_LINE, source_file) == NULL) break; source_line += 1; fprintf(stdout, "%6d ", source_line); line[MAX_LINE] = '\0'; fputs(line, stdout); } } break; case '@': /* PUSH tag */ case '^': /* PROC tag */ case 'n': /* SELECT tag */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getvar()); break; case 'W': /* SJUMP sd */ case '_': /* SLABEL sd */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getshortdecimal(NULL)); break; break; case 'd': /* DIM short,short */ p1 = strdup(getshort()); assert(get_icode(icode_file) == ','); p2 = getshort(); fprintf(stdout, "%s%s %s %s\n", indent, icode_name[opcode], p1, p2); free(p1); break; case 'Y': /* DEFAULT short */ case 'A': /* INIT short */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getshortdecimal(NULL)); break; case 'y': /* DIAG short */ case 'z': /* CONTROL short */ case 'e': /* EVENT short */ case 'l': /* LANG short */ fprintf(stdout, "%s%s %s\n", indent, icode_name[opcode], getshort()); break; case 'o': /* ON byte short label */ /* BUG! wrong data */ p1 = strdup(getshort()); assert(get_icode(icode_file) == ','); p2 = getlab(); fprintf(stdout, "%s%s MASK=%s %s\n", indent, icode_name[opcode], p1, p2); break; case 'r': /* RESOLVE m */ fprintf(stdout, "%s/* TODO */ %s %s\n", indent, icode_name[opcode], getbyte()); break; break; case 'w': /* SUBA - documentation failure??? file uses 'w' */ opcode = 'c'; case 'c': /* MCODE */ { int i1; short int h1; printf("%s%s ", indent, icode_name[opcode]); for (;;) { p1 = getmcstring(&i1); printf(" %s", p1); if (i1 == ';') break; p2 = getshort(); printf(" tag_%s", p2); } printf("\n"); } break; case '!': /* OR */ case '#': /* BNE */ case '%': /* XOR */ case '&': /* AND */ case '*': /* MUL */ case '+': /* ADD */ case '-': /* SUB */ case '.': /* CONCAT */ case '/': /* QUOT */ case ';': /* END */ case 'E': /* CALL */ case 'G': /* ALIAS */ case 'H': /* BEGIN */ case 'K': /* FALSE */ case 'M': /* MAP */ case 'P': /* PLANT */ case 'Q': /* DIVIDE */ case 'R': /* RETURN */ case 'S': /* ASSVAL */ case 'T': /* TRUE */ case 'U': /* NEGATE */ case 'V': /* RESULT */ case 'X': /* IEXP */ case 'Z': /* ASSREF */ case '[': /* LSH */ case '\\': /* NOT */ case ']': /* RSH */ case 'a': /* ACCESS */ case 'b': /* BOUNDS */ case 'h': /* ALTBEG */ case 'i': /* INDEX */ case 'j': /* JAM */ case 'm': /* MONITOR */ case 'p': /* ASSPAR */ case 'q': /* ALTEND */ case 's': /* STOP */ case 'u': /* ADDA */ case 'v': /* MOD */ case 'x': /* REXP */ case '{': /* START */ case '|': /* ALT */ case '}': /* FINISH */ fprintf(stdout, "%s%s\n", indent, icode_name[opcode]); break; default: fprintf(stdout, "?%s%s\n", indent, icode_name[opcode]); break; } } exit(0); return(0); }