#include #include #include #include #include #include #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 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 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>", "<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>", }; #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 { 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 != 2) { fprintf(stderr, "syntax: idec basename\n"); exit(1); } sprintf(icode_filename, "%s.icode", 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); } sprintf(source_filename, "%s.i", 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 < d/*+1*/) { 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); }