#include #define HDRLEN 512 void printvar(FILE *fp, char* s); int bcd2int(char *bcd); int bcd3int(char *bcd); void printstring(FILE *fp,char* s); void printchar(unsigned char c); void printlno(FILE *fp, char *s); void printfn (FILE *fp, char *s); void printvarname(FILE *fp); main (int argc, char* argv[]) { FILE *fp; unsigned short int lineno,sitmp; unsigned char linelen; int linestart,lineend,linect; int headerlen = HDRLEN; unsigned char opcode; char stmp[256]; /* temporary string */ unsigned char ctmp; /* temporary value */ int itmp; float ftmp; unsigned char slen; /* string length */ int i; if ((fp = fopen(argv[1],"r")) == NULL) { fprintf(stderr,"error opening file\n"); exit(1); } fseek(fp,512+24,SEEK_CUR); /* skip LIF headers + file header */ linect = 0; while (fread(&lineno,2,1,fp)) { lineno = bcd2int((char *) &lineno); fread(&linelen,1,1,fp); printf("line: %04d length: %03d filepos: %05d\n", lineno,linelen,ftell(fp)-3-headerlen); lineend = ftell(fp) + linelen; while (ftell(fp) < lineend) { opcode = fgetc(fp); switch (opcode) { case 0001: printvar(fp,"<\\001 fetch scalar variable>"); break; case 0002: printvar(fp,"<\\002 fetch array variable>"); break; case 0003: printvar(fp,"<\\003 fetch string variable>"); break; case 0004: /* 8 byte real number */ printf("<\\004 real>"); fseek(fp,7,SEEK_CUR); /* jump to last byte */ ctmp = fgetc(fp); printf(" %1d.",(ctmp >> 4) & 0x0f); /* first sig digit */ printf("%1d",ctmp & 0x0f); for (itmp = 1; itmp <= 5; itmp++) { fseek(fp,-2,SEEK_CUR); ctmp = fgetc(fp); printf("%1d",(ctmp >> 4) & 0x0f); printf("%1d",ctmp & 0x0f); } printf("E "); fseek(fp,-2,SEEK_CUR); ctmp = fgetc(fp); itmp = (ctmp >> 4) & 0x0f; printf("%1d",ctmp & 0x0f); fseek(fp,-2,SEEK_CUR); ctmp = fgetc(fp); printf("%1d",(ctmp >> 4) & 0x0f); printf("%1d",ctmp & 0x0f); printf(" *** sign bits ignored: 0x%1x\n",itmp); fseek(fp,7,SEEK_CUR); /* skip to end of number */ break; case 0005: printstring(fp,"<\\005 string>"); break; case 0006: printstring(fp,"<\\006 string>"); break; case 0007: printf("<\\007 store string variable?>\n"); break; case 0010: printf("<\\010 store numeric variable>\n"); break; case 0011: printf("<\\011 1d integer? array subscript>\n"); break; case 0012: printf("<\\012 2d integer? array subscript>\n"); break; case 0013: printf("<\\013 1d real? array subscript>\n"); break; case 0014: printf("<\\014 2d real? array subscript>\n"); break; case 0016: printf("<\\016 end line>\n"); linect++; break; case 0021: printvar(fp,"<\\021 fetch scalar variable address>"); break; case 0022: printvar(fp,"<\\022 fetch array variable address>"); break; case 0023: printvar(fp,"<\\023 fetch string variable address>"); break; case 0024: printf("<\\024 store numeric, multiple assignment?>\n"); break; case 0026: printvar(fp,"<\\026 FN call>"); printf("(number of arguments: %03d)\n",fgetc(fp)); break; case 0030: printlno(fp,"<\\030 IF .. GOTO (arithmetic?)>"); break; case 0031: printf("<\\031 END>\n"); break; case 0032: printf("<\\032 integer>"); fread(&itmp,3,1,fp); itmp = bcd3int((char *) &itmp); printf("%d\n",itmp); break; case 0033: printf("<\\033 THEN>"); fread(&itmp,2,1,fp); itmp = bcd2int((char *) &itmp); printf("%d\n",itmp); break; case 0034: printf("<\\034 ELSE>"); fread(&itmp,2,1,fp); itmp = bcd2int((char *) &itmp); printf("%d\n",itmp); break; case 0052: printf("<\\052 * >\n"); break; case 0053: printf("<\\052 + >\n"); break; case 0055: printf("<\\055 - >\n"); break; case 0057: printf("<\\057 / >\n"); break; case 0060: printf("< ^ >\n"); break; case 0065: printf("<\\065 = (string)>\n"); break; case 0070: printf("<\\070 change sign>\n"); break; case 0072: printf("<\\072 <= >\n"); break; case 0073: printf("<\\073 >= >\n"); break; case 0074: printf("<\\074 < >\n"); break; case 0075: printf("<\\075 = (numeric)>\n"); break; case 0076: printf("<\\076 > >\n"); break; case 0100: printf("<\\100 @ (statement separator)>\n"); break; case 0103: printf("<\\103 ON KEY#>\n"); break; case 0107: printf("<\\107 CLEAR>\n"); break; case 0125: printf("<\\125 DEG>\n"); break; case 0126: printf("<\\126 DISP>\n"); break; case 0132: printlno(fp,"<\\132 GOTO>"); break; case 0133: printlno(fp,"<\\133 GOSUB>"); break; case 0137: printf("<\\137 INPUT>\n"); break; case 0142: printf("<\\142 LET>\n"); break; case 0146: printf("<\\146 ON>\n"); break; case 0153: printf("<\\153 PRINT>\n"); break; //case 0213: //printlno(fp,"<\\213 USING>"); //break; case 0154: printf("<\\0154 RAD>\n"); break; case 0161: printf("<\\161 RETURN>\n"); break; //case 0200: //printf("<\\200 FN dereference>\n"); //break; case 0207: printvar(fp,"<\\207 DEF FN>"); printlno(fp,""); printf("\\%03o function return type code?\n",fgetc(fp)); printf("function argument: "); printvarname(fp); printf("*** DEF FN: skipping 8 bytes\n"); fseek(fp,8,SEEK_CUR); break; case 0214: printf("<\\214 FOR>\n"); break; case 0216: printf("<\\216 PRINT USING>\n"); break; case 0217: printf("<\\217 NEXT>\n"); break; case 0244: printf("<\\244 TO>\n"); break; case 0245: printf("<\\245 OR>\n"); break; case 0256: printf("<\\256 ATN2>\n"); break; case 0260: printf("<\\260 SQR>\n"); break; case 0274: printf("<\\274 EXP>\n"); break; case 0277: printf("<\\277 LOG>\n"); break; case 0311: printf("<\\311 PI>\n"); break; case 0312: printf("<\\312 UPC$>\n"); break; case 0315: printf("\\%03o ",opcode); opcode = fgetc(fp); printf("\\%03o ",opcode); opcode = fgetc(fp); printf("\\%03o ",opcode); printf(" unknown opcode followed by two bytes\n"); break; case 0316: printf("<\\316 STEP>\n"); break; case 0330: printf("<\\330 SIN>\n"); break; case 0331: printf("<\\331 COS>\n"); break; case 0347: printlno(fp,"<\\347 USING>"); //printf("<\\347 USING>"); //fread(&itmp,3,1,fp); //itmp = bcd3int((char *) &itmp); //printf("%d\n",itmp); break; case 0350: printf("<\\350 input numeric from keyboard>\n"); break; case 0351: printf("<\\351 input string from keyboard>\n"); break; case 0352: printvar(fp,"<\\352 single line function assignment?>"); break; case 0354: printf("<\\354 terminate output?>\n"); case 0355: printf("<\\355 format and output numeric w/o CRLF?>\n"); break; case 0356: printf("<\\356 format and output numeric w/ CRLF?>\n"); break; case 0357: printf("<\\357 format and output string w/o CRLF?>\n"); break; case 0360: printf("<\\360 format and output string w/ CRLF?>\n"); break; case 0370: /* fallthrough */ case 0371: printf("\\%03o ",opcode); printf("\\%03o ",fgetc(fp)); printf("\\%03o\n",fgetc(fp)); break; default: printf("\\%03o\n",opcode); //printchar(opcode); break; } } fseek(fp,lineend,SEEK_SET); /* recover from parse error */ printf("\n"); if (lineno == 10999) { break; } } printf("linect: %d\n",linect); } void printchar(unsigned char c) { if ((c > 32) && (c < 127)) { printf("%c ",c); } else { printf("\\%03o ",c); } } int bcd1int(unsigned char *bcd) { return (((bcd[0] & 0xf0) >> 4) * 10 + (bcd[0] & 0x0f)); } int bcd2int(char *bcd) { return (((bcd[0] & 0xf0) >> 4) * 10 + (bcd[0] & 0x0f) + ((bcd[1] & 0xf0) >> 4) * 1000 + (bcd[1] & 0x0f) * 100); } int bcd3int(char *bcd) { return (((bcd[0] & 0xf0) >> 4) * 10 + (bcd[0] & 0x0f) + ((bcd[1] & 0xf0) >> 4) * 1000 + (bcd[1] & 0x0f) * 100 + //((bcd[2] & 0xf0) >> 4) * 100000 + (bcd[2] & 0x0f) * 10000); } void printlno(FILE *fp, char *s) { unsigned short ustmp; long cpos; fread(&ustmp,2,1,fp); printf("%s",s); //printf("relative: %04d ",ustmp); cpos = ftell(fp); /* current position */ fseek(fp,ustmp+HDRLEN,SEEK_SET); /* seek to memory location */ fread(&ustmp,2,1,fp); fseek(fp,cpos,SEEK_SET); /* back to original spot */ printf("%04d\n",bcd2int((char *) &ustmp)); } void printfn (FILE *fp, char *s) { unsigned char name[2]; unsigned int subidx[2]; unsigned int nameextra; fread(name,2,1,fp); printf("%s",s); printf("`%c",(name[0] & 0x1f)+64); /* convert 5 lower to ASCII */ nameextra = (name[0] >> 5) & 0x07; subidx[1] = name[1] & 0x0f; /* get BCD subscript */ if (subidx[1] < 10) { printf("%1d",subidx[1]); } if (subidx[1] > 10) { printf("error: unknown BCD subscript on function: %02d\n",subidx[1]); exit(1); } printf("'"); subidx[0] = (name[1] >> 4) & 0x0f; if ((subidx[0] != 0) || (nameextra != 0)) { printf(" (nameextra: %1d, BCD high bits: %02d)", nameextra,subidx[0]); } printf("\n"); } void printvar(FILE *fp, char *s) { unsigned short ustmp; long cpos; printf("%s",s); fread(&ustmp,2,1,fp); /* get pointer into memory */ cpos = ftell(fp); /* store current position */ fseek(fp,ustmp+HDRLEN,SEEK_SET); /* seek to memory location */ printvarname(fp); fseek(fp,cpos,SEEK_SET); /* back to original spot */ } void printvarname(FILE *fp) { unsigned char name[2]; unsigned int subidx[2]; unsigned int nameextra; fread(name,2,1,fp); printf("`%c",(name[1] & 0x1f)+64); /* convert to ASCII */ nameextra = (name[1] >> 5) & 0x07; subidx[1] = name[0] & 0x0f; /* get BCD subscript */ if (subidx[1] < 10) { printf("%1d",subidx[1]); } if (subidx[1] > 10) { printf("error: unknown BCD subscript on variable: %02d\n",subidx[1]); exit(1); } printf("'"); subidx[0] = (name[0] >> 4) & 0x0f; if ((subidx[0] != 0) || (nameextra != 0)) { printf(" (nameextra: %1d, BCD high bits: %02d)", nameextra,subidx[0]); } // printf(" (%05d + 512 = %05d)",ustmp,ustmp+512); printf("\n"); } void printstring(FILE *fp,char* s) { int slen; char stmp[256]; slen = fgetc(fp); fread(stmp,slen,1,fp); stmp[slen] = '\0'; printf("%s`%s'\n",s,stmp); }