/************************************************************** * * DumpOBJ 2.0 * * By Phil Montoya * Translation to ORCA/C & 2.0 enhancements by Mike Westerfield. * * DumpOBJ 1.1 Copyright November 1986-88 * By the Byte Works, Inc. * * DumpOBJ 2.0 Copyright 1991 * Byte Works, Inc. * **************************************************************** * * Version 2.0.1, 7 July 94 * Mike Westerfield * * 1. Added resource fork. * **************************************************************** * * Version 2.0.2, June 96 * Mike Westerfield * * 1. Fixed hexadecimal dump bug. * ****************************************************************/ #pragma keep "DumpOBJ" #pragma optimize 9 /* GS specific declarations */ /*--------------------------*/ extern pascal void PDosInt(); int toolerror(void); #define WRITE_CONSOLE(parm) (PDosInt(0x015A,parm)) #define GetFileInfoGS(pBlockPtr) PDosInt(0x2006,pBlockPtr) #pragma lint -1 /* Standard C Libraries */ /*----------------------*/ #include #include #include #include /* Constants */ /*-----------*/ #define BOOLEAN int /* boolean variables */ #define TRUE 1 #define FALSE 0 #define FILEMAX 1024 /* max length of file name */ #define NAMEMAX 512 /* maximum size of variable len name */ #define NAMESIZE 11 /* size of label name */ #define OBJFL 177 /* minimum object file type */ #define MAXFL 190 /* maximum object file type */ #define LIBFL 178 /* library file type */ #define BLKSIZE 512 /* size of block */ #define COP 2 /* COP opcode */ #define REP 194 /* REP opcode */ #define SEP 226 /* SEP opcode */ /* Object File Opcodes */ /*---------------------*/ #define OPALIGN 224 /* align to a boundry */ #define OPORG 225 /* set code origin */ #define OPRELOC 226 /* relocation entry */ #define OPINTSEG 227 /* inserseg record */ #define OPUSING 228 /* use data area */ #define OPSTRONG 229 /* force segment inclusion */ #define OPGLOBAL 230 /* define global label */ #define OPGEQU 231 /* define global constant */ #define OPMEM 232 /* reserve absolute memory */ #define OPEXPR 235 /* computed value */ #define OPZEXPR 236 /* computed zero page value */ #define OPBEXPR 237 /* computed local bank value */ #define OPRELEXPR 238 /* computed relative ofset */ #define OPLOCAL 239 /* define local label */ #define OPEQU 240 /* define local constant */ #define OPDS 241 /* define storage */ #define OPLONG 242 /* long constant > $DF bytes */ #define OPLEXPR 243 /* outer segment expression */ #define OPENTRY 244 /* run time lib entry dictionary */ #define OPSRELOC 245 /* short relocation entry */ #define OPSINTSEG 246 /* short interseg entry */ #define OPSUPER 247 /* super compressed records */ /* Program variables */ /*-------------------*/ char fname[FILEMAX]; /* input file name buffer */ char nlist[NAMEMAX]; /* names list */ char symbol[NAMEMAX]; /* symbol name buffer */ BOOLEAN names; /* names list flag */ BOOLEAN sTable; /* found a COP symbol table? */ int act_lablen; /* actual length of label read */ int status; /* shell return status */ int namc; /* name argument counter */ int ftype; /* current file type */ long blocks; /* used to get to next segment */ long constant; /* constant byte counter and flag */ long opcode; /* opcode storage */ long segmark; /* start of segment marker */ long count; /* file counter */ long number; /* number read variable */ long pc; /* segment program counter */ long tkind; /* type of node for tree */ long *root; /* root pointer for expression tree */ FILE *input; /* input file */ /* Output Control Settings */ /*-------------------------*/ int format; /* format of output 0 opcode dump 1 dissassembly dump 2 hex dump */ BOOLEAN shorth; /* print short headers? */ BOOLEAN ireg; /* long index registers? */ BOOLEAN mreg; /* long accumulator? */ BOOLEAN longc; /* print long constants? */ BOOLEAN header; /* print segment headers? */ BOOLEAN body; /* print segment bodies? */ BOOLEAN checkf; /* check file types? */ BOOLEAN colf; /* print displacement numbers? */ /* Object Module Header */ /*----------------------*/ int kind; /* kind of segment */ long blkcnt; /* number of block in segment */ long resspc; /* reserved space at end of segment */ long length; /* length of finished segment */ int kind1; /* this is kind for version 1 */ int lablen; /* label length */ int numlen; /* number length */ int version; /* version number */ long banksize; /* banksize */ int kind2; /* this is kind for version 2 */ int unused; /* undefined field */ long pgorg; /* program org */ long align; /* alignment factor */ int numsex; /* significance of numbers */ int lang_card; /* language card */ int segnum; /* segment number */ long ent_disp; /* disp to beg of segment */ int nam_disp; /* displacment to names */ int bod_disp; /* displacment to body */ char loadname[NAMESIZE]; /* load file name */ char segname[NAMEMAX]; /* segment name */ /* Opcode arrays */ /*---------------*/ char opKind[] = {5,8,5,14,2,2,2,13,5,1,4,5,2,2,2,3, 17,6,12,15,2,9,9,7,5,10,4,5,2,9,9,11, 2,8,2,14,2,2,2,13,5,1,4,5,2,2,2,3, 17,6,12,15,9,9,9,7,5,10,4,5,9,9,9,11, 5,8,5,14,16,2,2,13,5,1,4,5,2,2,2,3, 17,6,12,15,16,9,9,7,5,10,5,5,3,9,9,11, 5,8,5,14,2,2,2,13,5,1,4,5,12,2,2,3, 17,6,12,15,9,9,9,7,5,10,5,5,8,9,9,11, 17,8,17,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,9,9,10,7,5,10,5,5,2,9,9,11, 1,8,1,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,9,9,10,7,5,10,5,5,9,9,10,11, 1,8,1,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,5,9,9,7,5,10,5,5,12,9,9,11, 1,8,1,14,2,2,2,13,5,1,5,5,2,2,2,3, 17,6,12,15,5,9,9,7,5,10,5,5,8,9,9,11}; char opLen[] = {1,1,1,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 2,1,3,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 0,1,0,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,3,2,2,3, 0,1,2,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 1,1,2,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 5,1,5,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 5,1,1,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,1,1,1,1,0,2,0,0,2,2,2,3, 5,1,1,1,1,1,1,1,0,4,0,0,2,2,2,3, 1,1,1,1,2,1,1,1,0,2,0,0,2,2,2,3}; char opName[] = "BRKORACOPORATSBORAASLORAPHPORAASLPHDTSBORAASLORA" "BPLORAORAORATRBORAASLORACLCORAINCTCSTRBORAASLORA" "JSRANDJSLANDBITANDROLANDPLPANDROLPLDBITANDROLAND" "BMIANDANDANDBITANDROLANDSECANDDECTSCBITANDROLAND" "RTIEORWDMEORMVPEORLSREORPHAEORLSRPHKJMPEORLSREOR" "BVCEOREOREORMVNEORLSREORCLIEORPHYTCDJMPEORLSREOR" "RTSADCPERADCSTZADCRORADCPLAADCRORRTLJMPADCRORADC" "BVSADCADCADCSTZADCRORADCSEIADCPLYTDCJMPADCRORADC" "BRASTABRLSTASTYSTASTXSTADEYBITTXAPHBSTYSTASTXSTA" "BCCSTASTASTASTYSTASTXSTATYASTATXSTXYSTZSTASTZSTA" "LDYLDALDXLDALDYLDALDXLDATAYLDATAXPLBLDYLDALDXLDA" "BCSLDALDALDALDYLDALDXLDACLVLDATSXTYXLDYLDALDXLDA" "CPYCMPREPCMPCPYCMPDECCMPINYCMPDEXWAICPYCMPDECCMP" "BNECMPCMPCMPPEICMPDECCMPCLDCMPPHXSTPJMLCMPDECCMP" "CPXSBCSEPSBCCPXSBCINCSBCINXSBCNOPXBACPXSBCINCSBC" "BEQSBCSBCSBCPEASBCINCSBCSEDSBCPLXXCEJSRSBCINCSBC"; /**** Utility Subroutines *****************************************/ /*************************************************************** * * fgeti - read an integer from the file * * Inputs: * f - file to read from * * Outputs: * Returns integer read * ***************************************************************/ int fgeti (FILE *f) { return fgetc(f) | (fgetc(f) << 8); } /*************************************************************** * * Error - Writes out an error * ***************************************************************/ void Error (int errnum, char *str) { status = -1; switch (errnum) { case 1: fputs("Format type not supported", stderr); break; case 2: fputs("Could not read segment header", stderr); break; case 3: fputs("Segment version not supported", stderr); break; case 4: fputs("Bad input ", stderr); break; case 5: fputs("Could not open file ", stderr); break; case 6: fputs("Not an object file ", stderr); break; case 7: fputs("Unknown Opcode", stderr); break; case 8: fputs("Illegal header entry", stderr); break; case 9: fputs("End of file encountered", stderr); default: break; } if (str[0] != ' ') fputs(str, stderr); fputc('\n', stderr); } /*************************************************************** * * CheckESC - Checks to see if 'escape' is pressed * * Notes: Returns to shell if open-apple period has been pressed. * ***************************************************************/ void CheckESC (void) { char *keyboard; char *strobe; char *flags; struct { int pcount; char ch; } parm; keyboard = (void *) 0x00C000; strobe = (void *) 0x00C010; flags = (void *) 0x00C025; if (*keyboard & 0x80) { if ((*keyboard & 0x7F) == '.') if (*flags & 0x80) { *strobe = (char) 0; exit(-1); } *strobe = (char) 0; parm.pcount = 1; parm.ch = (char) 27; WRITE_CONSOLE(&parm); parm.ch = (char) 15; WRITE_CONSOLE(&parm); parm.ch = (char) 0x43; WRITE_CONSOLE(&parm); parm.ch = (char) 24; WRITE_CONSOLE(&parm); parm.ch = (char) 14; WRITE_CONSOLE(&parm); parm.ch = (char) 8; WRITE_CONSOLE(&parm); while (! (*keyboard & 0x80)) ; parm.ch = (char) 32; WRITE_CONSOLE(&parm); parm.ch = (char) 8; WRITE_CONSOLE(&parm); if ((*keyboard & 0x7F) == '.') if (*flags & 0x80) { *strobe = (char) 0; exit(-1); } *strobe = (char) 0; } } /**** Segment I/O Subroutines *************************************/ /*************************************************************** * * Checks and updates output header information. * * Returns: * TRUE - if header OK. * FALSE - if header not OK and flags error. * ****************************************************************/ BOOLEAN CheckHead (void) { long talign; if ((version != 1) && (version != 2)) { Error(3," "); return FALSE; } if ((lablen > 256) || (numlen > 4) || (numlen < 1)) { Error(8," "); return FALSE; } if (align) { /* insure only 1 bit set in alignment */ talign = align; while (! (talign & 1)) talign = talign >> 1; if (talign != 1) { Error(8," "); return FALSE; } } return TRUE; } /*************************************************************** * * GetEOF - Returns The End of File Marker * * Returns: mark or -1 if error * ***************************************************************/ long GetEOF (FILE *f) { long mark, pos; pos = ftell(f); if (pos == -1) return -1; if (fseek(f, -1, SEEK_END)) return -1; mark = ftell(f)+1; if (pos == -1) return -1; if (fseek(f, pos, SEEK_SET)) return -1; return mark; } /*************************************************************** * * GetHead - Reads In The Segment Header * * Inputs: * f - file to read the header from * ***************************************************************/ int GetHead (FILE *f) { struct { long blkcnt, resspc, length; char kind1, lablen, numlen, version; long banksize; int kind2, unused; long pgorg, align; char numsex, lang_card; int segnum; long ent_disp; int nam_disp, bod_disp; } header; int i, disp, len; fseek(f, 0, SEEK_CUR); /* read the common parts of the header */ if (fread(&header, sizeof(header), 1, f) != 1) return -1; blkcnt = header.blkcnt; resspc = header.resspc; length = header.length; kind1 = header.kind1; lablen = header.lablen; numlen = header.numlen; version = header.version; banksize = header.banksize; kind2 = header.kind2; unused = header.unused; pgorg = header.pgorg; align = header.align; numsex = header.numsex; lang_card = header.lang_card; segnum = header.segnum; ent_disp = header.ent_disp; nam_disp = header.nam_disp; bod_disp = header.bod_disp; disp = nam_disp-sizeof(header); /* skip any extra stuff */ if (disp) for (i = 0; i < disp; ++i) fgetc(f); if (version == 0) loadname[0] = 0; else { for (i = 0; i < 10; ++i) /* read the load segment name */ loadname[i] = fgetc(f); loadname[10] = (char) 0; } len = lablen; if (!len) len = fgetc(f); /* read the code segment name */ for (i = 0; i < len; ++i) segname[i] = fgetc(f); segname[len] = (char) 0; if (version == 2) /* set the kind field */ kind = kind2; else kind = kind1; if (ftype == 0 && version == 1 && (kind & 0x001F) == 0x08) ftype = LIBFL; return 0; } /*************************************************************** * * IsInList - Checks to see if segment is in names list * ***************************************************************/ BOOLEAN IsInList (void) { int len, chpos; if (! names) return TRUE; len = chpos = 0; /* get length of segment name */ while (isalnum(segname[len]) || (segname[len] == '~') || (segname[len] == '_')) len++; while (nlist[chpos]) { /* see if name matches a list name */ while (nlist[chpos] == ' ') chpos++; if ((! strncmp(segname,nlist+chpos,len)) && ((nlist[chpos+len] == ' ') || (! nlist[chpos+len]))) return TRUE; while ((nlist[chpos]) && (nlist[chpos] != ' ')) chpos++; } return FALSE; } /*************************************************************** * * NextSeg - Returns the next segment * * Output: * positions file marker at next segment 0 if at end of file * ***************************************************************/ BOOLEAN NextSeg(void) { if ((format == 2 || format == 1) && !header && !checkf) { numsex = 0; return TRUE; } do { if ((ftype == LIBFL) || (version == 2)) { if (fseek(input, segmark + blocks, SEEK_SET)) return FALSE; } else { if (fseek(input,segmark + (blocks * BLKSIZE), SEEK_SET)) return FALSE; } segmark = ftell(input); /* set next segment marker */ if (segmark >= (GetEOF(input))) return FALSE; GetHead(input); blocks = blkcnt; if (! blocks) return FALSE; fseek(input, segmark, SEEK_SET); } while (! IsInList()); /* check to see if in names list */ return TRUE; } /*************************************************************** * * PutComment - Writes a comment line if colf is not active * ***************************************************************/ void PutComment (void) { if (! colf) printf("! "); } /*************************************************************** * * PutKind - Writes out the kind in name format * ***************************************************************/ void PutKind (int kind) { if (version == 1) { if (kind & 128) printf("dynamic "); else printf("static "); if (kind & 64) printf("private "); if (kind & 32) printf("position independent "); } else { if (kind & 32768) printf("dynamic "); else printf("static "); if (kind & 16384) printf("private "); if (kind & 8192) printf("position independent "); if (kind & 4096) printf("no special memory "); if (kind & 2048) printf("absolute bank "); if (kind & 1024) printf("reload "); } switch(kind & 31) { case 0: printf("code segment"); break; case 1: printf("data segment"); break; case 2: printf("jump table segment"); break; case 4: printf("pathname segment"); break; case 8: printf("library dictionary segment"); break; case 16: printf("initialization segment"); break; case 17: printf("absolute bank segment"); break; case 18: printf("direct page/stack segment"); break; default: printf("unknown segment: $04X", kind); } } /*************************************************************** * * PutHeader - Writes Out The Header * * Returns: FALSE if an error was found, else TRUE. * ***************************************************************/ /* debug */ BOOLEAN PutHeader (void) { long mark; int kind2; mark = ftell(input); /* save the file marker */ if (GetHead(input)) { Error(2," "); return FALSE; } if ((checkf) && ((version != 1) && (version != 2))) { Error(3," "); return FALSE; } blocks = blkcnt; /* set the new block counter */ if (! header) /* split on write/don't write header */ fseek(input,mark,SEEK_SET); else { count = ftell(input) - mark; /* set the file counter */ if (shorth) { /* split on short or long header */ PutComment(); printf("%s (", segname); PutKind(kind); printf(")\n"); return CheckHead(); } else { /* print the full header */ PutComment(); /* write block count */ if (version == 2) printf("Byte count : $%08lX%14ld\n", blkcnt, blkcnt); else printf("Block count : $%08lX%14ld\n", blkcnt, blkcnt); CheckESC(); PutComment(); /* write reserved space */ printf("Reserved space: $%08lX%14ld\n", resspc, resspc); CheckESC(); PutComment(); /* write segment length */ printf("Length : $%08lX%14ld\n", length, length); CheckESC(); PutComment(); /* write label length */ printf("Label length : $%02X%20d\n", lablen, lablen); CheckESC(); PutComment(); /* write number length */ printf("Number length : $%02X%20d\n", numlen, numlen); CheckESC(); PutComment(); /* write segment version */ printf("Version : $%02X%20d\n", version, version); CheckESC(); PutComment(); /* write bank size */ printf("Bank size : $%08lX%14ld\n", banksize, banksize); CheckESC(); PutComment(); /* write segment kind */ if (version == 2) { printf("Kind : $%04X%18d (", kind, kind); kind2 = kind; } else { printf("Kind : $%02X%20d (", kind, kind); kind2 = ((kind & 0xE0) << 8) | (kind & 0x1F); } switch (kind & 0x001F) { case 0x00: printf("code"); break; case 0x01: printf("data"); break; case 0x02: printf("jump table"); break; case 0x04: printf("pathname"); break; case 0x08: printf("library"); break; case 0x10: printf("initialization"); break; case 0x11: printf("absolute bank"); break; case 0x12: printf("direct-page/stack"); break; default: printf("unknown"); break; } if (kind & 0x8000) printf(",dynamic"); else printf(",static"); if (kind & 0x4000) printf(",private"); if (kind & 0x2000) printf(",position independent"); if (kind & 0x1000) printf(",no special memory"); if (kind & 0x0800) printf(",absolute bank"); if (kind & 0x0400) printf(",reload"); if (kind & 0x0200) printf(",skip"); if (kind & 0x0100) printf(",bank relative"); printf(")\n"); CheckESC(); PutComment(); /* write segment org */ printf("Org : $%08lX%14ld\n", pgorg, pgorg); CheckESC(); PutComment(); /* write alignment factor */ printf("Alignment : $%08lX%14ld\n", align, align); CheckESC(); PutComment(); /* write number sex */ printf("Number sex : $%02X%20d\n", numsex, numsex); CheckESC(); if (version == 1) { /* write language card */ PutComment(); printf("Language card : $%02X%20d\n", lang_card, lang_card); CheckESC(); } PutComment(); /* write segment number */ printf("Segment number: $%04X%18d\n", segnum, segnum); CheckESC(); PutComment(); /* write segment entry */ printf("Segment entry : $%08lX%14ld\n", ent_disp, ent_disp); CheckESC(); PutComment(); /* write segment names disp */ printf("Disp to names : $%04X%18d\n", nam_disp, nam_disp); CheckESC(); PutComment(); /* write segment body disp */ printf("Disp to body : $%04X%18d\n", bod_disp, bod_disp); CheckESC(); if (! CheckHead()) /* don't print labels if header error */ return FALSE; PutComment(); /* write load name */ printf("Load name : %s\n", loadname); CheckESC(); PutComment(); /* write segment name */ printf("Segment name : %s\n", segname); CheckESC(); } } return TRUE; } /**** Opcode Dump Subroutines *************************************/ void DoExpr (void); /*************************************************************** * * Reads the opcode into "opcode" * ***************************************************************/ int GetOpCode (void) { ++count; /* advance byte counter */ opcode = fgetc(input); if (opcode == -1) { /* check for end of file */ opcode = 0; Error(9," "); /* end of file encountered */ exit(status); } return opcode; } /*************************************************************** * * NewLine - Issues a Formatted New Line * ***************************************************************/ void NewLine (void) { int count; putchar('\n'); if (colf) count = 33; else count = 17; while (count--) putchar(' '); } /*************************************************************** * * ReadInt - reads an integer * * Inputs: * numsex - number sex * input - reference number of file * numlen - length of number * nPtr - pointer to place result * ***************************************************************/ void ReadInt (long *nPtr, int numlen, FILE *f, int numsex) { int i; long k,n; union { char c[4]; long l; } u; if (numlen <= 4) { u.l = 0; for (i = 0; i < numlen; ++i) u.c[i] = fgetc(f); *nPtr = u.l; if (numsex) { n = *nPtr; for (i = 0; i < 4; ++i) { k = (k << 8) | (n && 0xFF); n = n >> 8; } *nPtr = k; } } } /*************************************************************** * * ReadName - reads in a symbol name * * Inputs: * name - pointer to place the name * lablen - length of name * f - open file ref number * ***************************************************************/ void ReadName (char *name, int lablen, FILE *f) { int i; if (lablen) /* get the label length */ act_lablen = lablen; else act_lablen = fgetc(f); for (i = 0; i < act_lablen; ++i) /* read the name */ name[i] = fgetc(f); name[act_lablen] = (char) 0; /* set the null terminator */ } /*************************************************************** * * PrintW - Writes a word in a string to the console * * Inputs: * str - pointer to the string to write * ***************************************************************/ void PrintW (char *str) { int i = 0; while ((str[i]) && (! isspace(str[i]))) putchar(str[i++]); } /*************************************************************** * * PutConst - Writes the constant bytes for opcode format * * Inputs: * len - number of bytes to write * input - file to get bytes from * ***************************************************************/ void PutConst (long len, int flag) { long k; int i; if (flag) { /* see if we print out record */ i = 0; for (k = 0; k < len; ++k) { ++i; /* allow 23 numbers per line */ if (i == 24) { /* see if we need to issue a new line */ i = 1; NewLine(); } printf("%02X", (int) fgetc(input)); /* write the hex */ CheckESC(); } } else fseek(input, ftell(input)+len, SEEK_SET); } /*************************************************************** * * PutCTPC - Writes the count and program counter * ***************************************************************/ void PutCTPC(void) { putchar('\n'); if (colf) /* check to make sure you write col */ printf("%06lX %06lX | ", count, pc); } /*************************************************************** * * PutNumber - Writes a number * * Inputs: * input - input file * * Outputs: * number - contains number read * ***************************************************************/ void PutNumber (void) { ReadInt(&number,numlen,input,numsex); switch (numlen) { case 1: printf("%02X", (int) number); case 2: printf("%04X", (int) number); case 3: printf("%06lX", (long) number); case 4: printf("%08lX", (long) number); } count = count + numlen; } /*************************************************************** * * Putsymbol - Writes the symbol * * Inputs: * input - input file * * Outputs: * symbol - symbol read * ***************************************************************/ void PutSymbol (void) { ReadName(symbol,lablen,input); PrintW(symbol); if (lablen) count = count + lablen; else count = count + act_lablen + 1; } /*************************************************************** * * PutOpCode - Writes the opcode * * Inputs: * opcode - opcode to write * input - input file * * Outputs: * write opcode * pc, count = updates accordingly * ***************************************************************/ void PutOpCode (void) { long k; int p1, p2, p3; /* temp storage for calculated parms */ if (opcode < OPALIGN) { /* handle short constant opcode */ printf("CONST ($%02X) | ", (int) opcode); pc = pc + opcode; count = count + opcode; PutConst(opcode,longc); /* write the constant opcodes */ } else switch (opcode) { case OPALIGN: /* handle align opcode */ printf("ALIGN ($E0) | "); PutNumber(); pc = pc + (pc % number); break; case OPORG: /* handle org opcode */ printf("ORG ($E1) | "); PutNumber(); pc = pc + number; break; case OPRELOC: /* handle reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("RELOC ($E2) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); PutNumber(); count = count + 2; break; case OPINTSEG: /* handle interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("INTERSEG ($E3) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); PutNumber(); count = count + 6; break; case OPUSING: /* handle using opcode */ printf("USING ($E4) | "); PutSymbol(); break; case OPSTRONG: /* handle strong opcode */ printf("STRONG ($E5) | "); PutSymbol(); break; case OPGLOBAL: /* handle global opcode */ printf("GLOBAL ($E6) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X", p1, p2, p3); count = count + 4; } break; case OPGEQU: /* handle gequ opcode */ printf("GEQU ($E7) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X :", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X :", p1, p2, p3); count = count + 4; } DoExpr(); break; case OPMEM: /* handle mem opcode */ printf("MEM ($E8) | "); PutNumber(); printf(" : "); PutNumber(); break; case OPEXPR: /* handle expr opcode */ k = fgetc(input); count++; printf("EXPR ($EB) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPZEXPR: /* handle zexpr opcode */ k = fgetc(input); count++; printf("ZEXPR ($EC) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPBEXPR: /* handle bexpr opcode */ k = fgetc(input); count++; printf("BEXPR ($ED) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPRELEXPR: /* handle relexpr opcode */ k = fgetc(input); count++; printf("RELEXPR ($EE) | %02X : ", (int) k); PutNumber(); pc = pc + k; printf(" :"); DoExpr(); break; case OPLOCAL: /* handle local opcode */ printf("LOCAL ($EF) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X", p1, p2, p3); count = count + 4; } break; case OPEQU: /* handle equ opcode */ printf("EQU ($F0) | "); PutSymbol(); if (version == 1) { p1 = fgetc(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %02X : %02X : %02X :", p1, p2, p3); count = count + 3; } else { p1 = fgeti(input); p2 = fgetc(input); p3 = fgetc(input); printf(" : %04X : %02X : %02X :", p1, p2, p3); count = count + 4; } DoExpr(); break; case OPDS: /* handle ds opcode */ printf("DS ($F1) | "); PutNumber(); pc = pc + number; break; case OPLONG: /* handle long constant opcode */ printf("LCONST ($F2) | "); PutNumber(); printf(" : "); NewLine(); pc = pc + number; count = count + number; PutConst(number,longc); /* write the constant opcodes */ break; case OPLEXPR: /* handle long expression opcode */ k = fgetc(input); count++; printf("LEXPR ($F3) | %02X :", (int) k); pc = pc + k; DoExpr(); break; case OPENTRY: /* handle entry opcode */ p1 = fgeti(input); printf("ENTRY ($F4) | %02X :", (int)p1); PutNumber(); printf(" : "); PutSymbol(); break; case OPSRELOC: /* handle short reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("cRELOC ($F5) | %02X : %02X : ", p1, p2); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X", (int) number); count = count + 6; break; case OPSINTSEG: /* handle short interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("cINTRSEG ($F6) | %02X : %02X : ", p1, p2); ReadInt(&number,2,input,numsex); printf("%04X : %02X : ", (int) number, (int) fgetc(input)); ReadInt(&number,2,input,numsex); printf("%04X", (int) number); count = count + 7; break; case OPSUPER: /* handle short interseg opcode */ printf("SUPER ($F7) | "); ReadInt(&number,4,input,numsex); printf("%08lX : %02X", (long) number, (int) fgetc(input)); NewLine(); count = count + number; PutConst(number-1,1); break; default: Error(7," "); break; } } /*************************************************************** * * PutOpCodeBody - dump the body of one segment in opcode format * ***************************************************************/ void PutOpCodeBody (void) { while (GetOpCode()) { --count; /* adjust the counter */ PutCTPC(); /* write the count and pc */ count++; PutOpCode(); /* write out the opcode */ CheckESC(); } --count; /* write out the end opcode */ PutCTPC(); puts("END ($00)"); /* print end directive */ } /*************************************************************** * * DpOpCode - Dump file in opcode format * ***************************************************************/ void DpOpCode(void) { while (NextSeg()) { count = /* initialize counter and pc */ pc = 0; CheckESC(); if (! PutHeader()) /* write out the header */ return; if (body) { /* write out the body */ if ((! header) && checkf) { count = bod_disp; fseek(input, ftell(input) + bod_disp, SEEK_SET); } PutOpCodeBody(); } if ((! shorth) || body) puts("\n"); } } /**** Expression Output Subroutines *******************************/ /*************************************************************** * * DoOper - Writes an operation * * Inputs: * space - print a leading space? * ***************************************************************/ void DoOper (BOOLEAN space) { if (space) putchar(' '); switch(opcode) { case 1: /* handle addition */ putchar('+'); break; case 2: /* handle subtraction */ putchar('-'); break; case 3: /* handle multiplication */ putchar('*'); break; case 4: /* handle division */ putchar('/'); break; case 5: /* handle modulo */ putchar('%'); break; case 6: /* handle negation */ if (format != 1) printf("--"); else printf("unary -"); break; case 7: /* handle bit shift */ putchar('|'); break; case 8: /* handle logical and */ printf(".AND."); break; case 9: /* handle logical or */ printf(".OR."); break; case 10: /* handle logical xor */ printf(".EOR."); break; case 11: /* handle logical not */ printf(".NOT."); break; case 12: /* handle less or equal */ printf("<="); break; case 13: /* handle greater or equal */ printf(">="); break; case 14: /* handle not equal */ printf("<>"); break; case 15: /* handle less */ putchar('<'); break; case 16: /* handle greater */ putchar('>'); break; case 17: /* handle equal */ putchar('='); break; case 18: /* handle bit and */ printf(".BAND."); break; case 19: /* handle bit or */ printf(".BOR."); break; case 20: /* handle bit xor */ printf(".BEOR."); break; } } /*************************************************************** * * DoOpnd - Writes an operand * ***************************************************************/ void DoOpnd (void) { switch(opcode) { case 128: /* handle location counter */ printf(" (*)"); break; case 129: /* handle constant */ printf(" $"); PutNumber(); break; case 130: /* handle weak reference */ printf(" W:"); PutSymbol(); break; case 131: /* handle value of label */ putchar(' '); PutSymbol(); break; case 132: /* handle length attribute */ printf(" L:"); PutSymbol(); break; case 133: /* handle type attribute */ printf(" T:"); PutSymbol(); break; case 134: /* handle count attribute */ printf(" C:"); PutSymbol(); break; case 135: /* handle relative ofset */ printf(" ("); PrintW(segname); printf("+$"); PutNumber(); putchar(')'); break; } } /*************************************************************** * * DoExpr - Writes an expression * ***************************************************************/ void DoExpr (void) { while (GetOpCode()) { if (opcode < 128) DoOper(TRUE); else DoOpnd(); } } /**** Disassembler Subroutines ************************************/ /*************************************************************** * * ReadSym - Reads in a symbol and appends it to symbol * ***************************************************************/ void ReadSym (void) { int i,k; k = strlen(symbol); if (lablen) /* handle variable length labels */ act_lablen = lablen; else { act_lablen = fgetc(input); ++count; } for (i=0; i 4) { /* handle avariable I instruction */ if (imode) return 2; return 1; } return len; /* return a fixed length */ } /*************************************************************** * * GtOpName - Returns Pointer to Opcode Name * * Inputs: * opcode - operation code * * Outputs: * pointer to numonic string * * Notes: There is no terminating null on the string. The * caller should use exactly 3 characters. * ***************************************************************/ char *GtOpName (int opcode) { return &opName[opcode*3]; } /*************************************************************** * * IsExpr - Check to see if OPCODE is from an expression * * Inputs: * op - object module opcode * * Outputs: * true if from an expression; else false * Note: if constant != 0 then --constant, return false * if constant == 0 then * if (constant_opcode) set constant, getopcode, return false * else return true * ***************************************************************/ BOOLEAN IsExpr (int op) { if ((! checkf) && (! header)) return FALSE; if (constant) /* handle in a constant */ return FALSE; if (op < OPALIGN) { /* handle short constant */ constant = op; GetOpCode(); return FALSE; } if (op == OPLONG) { /* handle long constant */ ReadInt(&constant,numlen,input,numsex); count = count + numlen; GetOpCode(); return FALSE; } return TRUE; } /*************************************************************** * * PutLSymbol - Writes the symbol * * Inputs: * input - input file * * Outputs: * symbol - symbol read * ***************************************************************/ void PutLSymbol (void) { int i; ReadName(symbol,lablen,input); fputs(symbol, stdout); for (i=act_lablen; i<8; i++) /* fill out with spaces */ putchar(' '); putchar(' '); if (lablen) /* handle variable length labels */ count = count + lablen; else count = count + act_lablen + 1; } /*************************************************************** * * PutStreg - Writes out the registar status * * Inputs: * mreg - accumulator flag * ireg - index registar flag * ***************************************************************/ void PutStreg (void) { PutCTPC(); printf(" LONGA "); if (mreg) printf("ON"); else printf("OFF"); PutCTPC(); printf(" LONGI "); if (ireg) printf("ON"); else printf("OFF"); } /*************************************************************** * * ReadOpVal - reads an integer from a constant field * * Inputs: * numsex - number sex * input - reference number of file * numlen - length of number * nPtr - pointer to place result * * Outputs: * Returns true if successful, else false. * ***************************************************************/ BOOLEAN ReadOpVal (long *nPtr, int numlen, FILE *f, int numsex) { int i; long k,n; union { char c[4]; long l; } u; if (numlen <= 4) { u.l = 0; for (i = 0; i < numlen; ++i) { if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; else return FALSE; } else --constant; u.c[i] = fgetc(f); } *nPtr = u.l; if (numsex) { n = *nPtr; for (i = 0; i < 4; ++i) { k = (k << 8) | (n && 0xFF); n = n >> 8; } *nPtr = k; } } return TRUE; } /*************************************************************** * * PutOpnd - Writes the operand for an instruction * * Outputs: * Returns true if successful, false if an expression * was encountered in the middle of operand. * ***************************************************************/ BOOLEAN PutOpnd (int op) { BOOLEAN success; int i; long addr; i = GtOpLen(op,mreg,ireg); pc = pc + i; if (constant) { /* split on constant or expression */ count = count + i; /* update the file counter */ success = ReadOpVal(&number,i,input,numsex); /* get the value and print it */ printf("$%0*lX", (int) i*2, (long) number); if (op == REP) { /* check for REP */ if (number & 32) mreg = 1; if (number & 16) ireg = 1; PutStreg(); } if (op == SEP) { /* check for SEP */ if (number & 32) mreg = 0; if (number & 16) ireg = 0; PutStreg(); } if (op == COP) { /* special handling for debug COPs */ switch (number) { case 0: case 1: case 2: success = ReadOpVal(&number,2,input,numsex); printf(",%d", (int) number); count += 2; pc += 2; break; case 5: case 8: sTable = TRUE; break; } } } else { /* handle case where operand is an exp */ switch(GetOpCode()) { case OPEXPR: case OPZEXPR: case OPBEXPR: case OPLEXPR: fgetc(input); ++count; DoInexp(); /* write expression in infix form */ break; case OPRELEXPR: fgetc(input); ReadInt(&number,numlen,input,numsex); count = count + numlen + 1; DoInexp(); /* write expression in infix form */ break; default: /* case with unexpected input */ printf("???"); break; } } return success; } /*************************************************************** * * Dis_DC - Disassembles a DC format * * Inputs: * op - object module opcode * ***************************************************************/ void Dis_DC (int op) { int i; int p1, p2; /* temps for computed parameters */ switch(op) { case OPGEQU: case OPEQU: /* handle equates */ PutLSymbol(); if (op == OPEQU) printf("EQU "); else printf("GEQU "); fgetc(input); fgetc(input); fgetc(input); count = count+3; if (version == 2) { fgetc(input); ++count; } DoInexp(); break; case OPUSING: /* handle using directives */ printf(" USING "); PutSymbol(); break; case OPLOCAL: case OPGLOBAL: /* handle local and global labels */ PutLSymbol(); if (op == OPLOCAL) printf("ANOP"); else printf("ENTRY"); fgetc(input); fgetc(input); fgetc(input); count = count + 3; if (version == 2) { fgetc(input); ++count; } break; case OPDS: case OPALIGN: /* handle ds and align directive */ if (op == OPALIGN) printf(" ALIGN $"); else printf(" DS $"); PutNumber(); if (op == OPALIGN) pc = pc + (pc % number); else pc = pc + number; break; case OPSTRONG: /* handle strong reference */ printf(" DC R'"); PutSymbol(); putchar('\''); break; case OPORG: /* handle inter-segment org */ printf(" ORG *+$"); PutNumber(); pc = pc + number; break; case OPMEM: /* handle inter-segment mem */ printf(" MEM $"); PutNumber(); printf(",$"); PutNumber(); break; case OPEXPR: case OPZEXPR: /* handle expressions */ case OPBEXPR: case OPLEXPR: case OPRELEXPR: printf(" DC "); i = fgetc(input); if (i == 1) printf("I1'"); else if (i == 2) printf("I2'"); else if (i == 3) printf("I3'"); else printf("I4'"); ++count; pc = pc + i; if (op == OPRELEXPR) { PutNumber(); putchar('+'); } DoInexp(); /* write expression in infix form */ putchar('\''); break; case OPRELOC: /* handle reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("! RELOC ($E2) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); PutNumber(); count = count + 2; break; case OPINTSEG: /* handle interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("! INTERSEG ($E3) | %02X : %02X : ", p1, p2); PutNumber(); printf(" : "); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); PutNumber(); count = count + 6; break; case OPENTRY: /* handle entry opcode */ p1 = fgeti(input); printf("! ENTRY ($F4) | %02X :", (int)p1); PutNumber(); printf(" : "); PutSymbol(); break; case OPSRELOC: /* handle short reloc opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("! cRELOC ($F5) | %02X : %02X : ", p1, p2); ReadInt(&number,2,input,numsex); printf("%04X : ", (int) number); ReadInt(&number,2,input,numsex); printf("%04X", (int) number); count = count + 6; break; case OPSINTSEG: /* handle short interseg opcode */ p1 = fgetc(input); p2 = fgetc(input); printf("! cINTRSEG ($F6) | %02X : %02X : ", p1, p2); ReadInt(&number,2,input,numsex); printf("%04X : %02X : ", (int) number, (int) fgetc(input)); ReadInt(&number,2,input,numsex); printf("%04X", (int) number); count = count + 7; break; case OPSUPER: /* handle short interseg opcode */ printf("! SUPER ($F7) | "); ReadInt(&number,4,input,numsex); printf("%08lX : %02X", (long) number, (int) fgetc(input)); NewLine(); count = count + number; PutConst(number-1,1); break; default: Error(7," "); break; } } /*************************************************************** * * Disasm - Disassembles OPCODE * * Inputs: * op - assembly language opcode * * Outputs: * Returns true if successful, false if an expression * was hit trying to process an operand. * ***************************************************************/ BOOLEAN Disasm (int op) { BOOLEAN success; int i; char opn[4]; sTable = FALSE; /* no COP symbol table found (yet) */ success = TRUE; /* assume everything will work */ --constant; /* now this is a constant */ ++pc; /* update program counter */ strncpy(opn, GtOpName(op), 3); opn[3] = (char) 0; printf(" %s ", opn); switch(GtOpKind(op)) { /* split on type of output format */ case 1: /* handle '# operand' */ putchar('#'); success = PutOpnd(op); break; case 2: /* handle 'operand' */ success = PutOpnd(op); break; case 3: /* handle '> operand' */ putchar('>'); success = PutOpnd(op); break; case 4: /* handle 'A' */ putchar('A'); break; case 5: /* handle ' ' or 'operand' */ if (GtOpLen(op,mreg,ireg)) success = PutOpnd(op); break; case 6: /* handle '(operand),Y' */ putchar('('); success = PutOpnd(op); printf("),Y"); break; case 7: /* handle '[operand],Y' */ putchar('['); success = PutOpnd(op); printf("],Y"); break; case 8: /* handle '(operand,X)' */ putchar('('); success = PutOpnd(op); printf(",X)"); break; case 9: /* handle 'operand,X' */ success = PutOpnd(op); printf(",X"); break; case 10: /* handle 'operand,Y' */ success = PutOpnd(op); printf(",Y"); break; case 11: /* handle '>operand,X' */ putchar('>'); success = PutOpnd(op); printf(",X"); break; case 12: /* handle '(operand)' */ putchar('('); success = PutOpnd(op); putchar(')'); break; case 13: /* handle '[operand]' */ putchar('['); success = PutOpnd(op); putchar(']'); break; case 14: /* handle 'operand,S' */ success = PutOpnd(op); printf(",S"); break; case 15: /* handle '(operand,S),Y */ putchar('('); success = PutOpnd(op); printf(",S),Y"); break; case 16: /* handle 'operand,operand' */ success = PutOpnd(op); putchar(','); success = PutOpnd(op); break; case 17: /* handle relative branches */ if (constant) { i = GtOpLen(op,mreg,ireg); pc = pc + i; count = count + i; /* update the file counter */ constant = constant - i; /* set new constant number */ number = 0; ReadInt(&number,i,input,numsex); /* get the value and print it */ if (i == 1) { if (number > 127) number = number | -256; } else { if (number > 32767) number = number | -32768; } number = number + i + 1; if (number < 0) { number = -number; printf("*-$"); } else printf("*+$"); printf("%0*lX", (int) i*2, (long) number); } else success = PutOpnd(op); break; default: printf("Operand Error"); status = -1; break; } return success; } /*************************************************************** * * DisSTable - disassemble a COP 5 symbol table * ***************************************************************/ void DisSTable (void) { long tlen; int p1, p2; /* temps for computed parms */ long subscript; if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; else { PutCTPC(); Dis_DC(opcode); } } if (constant >= 2) { ReadInt(&tlen,2,input,numsex); /* get and print the table length */ PutCTPC(); printf(" DC I'%d'", (int) tlen); pc += 2; count += 2; constant -= 2; CheckESC(); while (tlen > 0) { if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; } if (constant) { ReadOpVal(&number,4,input,numsex); PutCTPC(); printf(" DC I4'%d'", (long) number); pc += 4; count += 4; } else { PutCTPC(); Dis_DC(opcode); } if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; } if (constant) { ReadOpVal(&number,4,input,numsex); PutCTPC(); printf(" DC I4'%d'", (long) number); pc += 4; count += 4; } else { PutCTPC(); Dis_DC(opcode); } if (!constant) { GetOpCode(); if (opcode && (opcode < OPALIGN)) constant = opcode; else { PutCTPC(); Dis_DC(opcode); } } subscript = 0; if (constant >= 4) { PutCTPC(); p1 = fgetc(input); p2 = fgetc(input); ReadInt(&subscript,2,input,numsex); printf(" DC H'%02X %02X'", p1, p2); /* flag, format */ count += 2; pc += 2; PutCTPC(); printf(" DC I2'%d'", (int)subscript); /* subscript */ count += 2; pc += 2; constant -= 4; // type 13 subscript is not a subscript. if ((p2 & 0x3f) == 13) subscript = 0; else subscript *= 12; } tlen -= 12; if (constant >= subscript) { long a, b, c; while (subscript) { ReadInt(&a, 4, input, numsex); ReadInt(&b, 4, input, numsex); ReadInt(&c, 4, input, numsex); PutCTPC(); printf(" DC I4'%d,%d,%d'", (int)a, (int)b, (int)c); /* subscript */ subscript -= 12; constant -= 12; count += 12; tlen -= 12; pc += 12; } } } } } /*************************************************************** * * Dis_Cns - disassemble a constant as a DC statement(s) * ***************************************************************/ void Dis_Cns (int opcode) { int i, delta; int b1,b2; while (opcode != 0) { printf(" DC H'"); i = 16; while ((i != 0) && (opcode != 0)) { if (opcode == 1) { printf("%02X", (int) fgetc(input)); delta = 1; } else { b1 = fgetc(input); b2 = fgetc(input); if (opcode == 2) printf("%02X%02X", (int) b1, (int) b2); else printf("%02X%02X ", (int) b1, (int) b2); delta = 2; } opcode -= delta; i -= delta; pc += delta; count += delta; } putchar('\''); if (opcode != 0) { CheckESC(); PutCTPC(); } } } /*************************************************************** * * DpDisasm - Dump file in disassembled format * ***************************************************************/ void DpDisasm (void) { int i; long mark; long codelen; while (NextSeg()) { count = /* initialize counter and pc */ pc = constant = 0; /* we're not in a constant */ CheckESC(); if (checkf || header) /* write out the header */ if (! PutHeader()) return; if ((! checkf) && (! header)) { /* get segment length */ mark = GetEOF(input); blocks = 30000; } else if ((ftype == LIBFL) || (version == 2)) mark = blkcnt; else mark = blkcnt*512; if (body) { /* write out the body */ if ((! header) && checkf) { count = bod_disp; fseek(input, ftell(input) + bod_disp, SEEK_SET); } PutStreg(); /* write the registar status */ PutCTPC(); fputs(segname, stdout); /* print the segment name */ for (i=strlen(segname); i<8; i++) /* fill out with spaces */ putchar(' '); if (kind & 1) /* print out segment type */ printf(" DATA"); else printf(" START"); codelen = length-resspc; while (count <= mark) { PutCTPC(); GetOpCode(); if ((checkf || header) && ((pc > codelen) || ((! opcode) && (pc == codelen)))) break; if (((kind & 0x001F) == 1) && checkf && (opcode < OPALIGN) && (opcode != 0)) Dis_Cns(opcode); else if (IsExpr(opcode)) Dis_DC(opcode); else if (!Disasm(opcode)) { PutCTPC(); Dis_DC(opcode); } else if (sTable) DisSTable(); CheckESC(); } if (resspc) { printf(" DS $%08lX", (long) resspc); count += resspc; } if (count > mark) PutCTPC(); puts(" END"); /* print out the end directive */ } if ((! shorth) || body) puts("\n"); if (!checkf && !header) break; } } /**** Hex Dump Subroutines ****************************************/ /*************************************************************** * * DpHex - Dump file in hex format * ***************************************************************/ void DpHex (void) { long mark; /* next segment mark */ long ch = 0; char chline[20]; int k, i, space; while (NextSeg()) { count = 0L; CheckESC(); if (checkf || header) /* write out the header */ if (! PutHeader()) return; /* if we don't print header and we're not doing file checking then dump the entire file and forget about segment scanning */ if ((! checkf) && (! header)) { /* get the segment length */ mark = GetEOF(input); blocks = 30000; } else if ((ftype == LIBFL) || (version == 2)) mark = blkcnt; else mark = blkcnt*512; if (body) { /* write out the body */ if ((! header) && checkf) { count = bod_disp; fseek(input, ftell(input) + bod_disp, SEEK_SET); } while (count <= mark) { putchar('\n'); if (colf) printf("%06lX | ", count); space = 0; for (k=0; k<16; k++) { ch = fgetc(input); count++; if (count > mark) { printf(" "); ch = 0; } else printf("%02X", ch); if ((ch & 127) > 31) chline[k] = ch & 127; else chline[k] = ' '; space++; if (space == 4) { putchar(' '); space = 0; } CheckESC(); } chline[16] = 0; printf(" | %s", chline); CheckESC(); } } if ((! shorth) || body) printf("\n\n"); if (!checkf && !header) break; } } /**** Command Line Input Subroutines ******************************/ /*************************************************************** * * GetFType - Return Type Of File * * Inputs: * name - file name to get the type of * * Returns: file type; 0 if not found * ***************************************************************/ int GetFType (char name[]) { struct FileInfoRecGS { int pCount; struct { int length; char name[FILEMAX]; } *fname; int access; int fileType; } parm; parm.pCount = 3; parm.fname = (void *) malloc (sizeof(int) + FILEMAX); if (parm.fname == NULL) return 0; parm.fname->length = strlen(name); strcpy(parm.fname->name, name); GetFileInfoGS(&parm); free(parm.fname); if (toolerror()) return 0; return parm.fileType; } /*************************************************************** * * CheckFile - Checks For Valid File * ***************************************************************/ BOOLEAN CheckFile (char file[]) { if (! checkf) { /* see if we have to check file type */ ftype = FALSE; /* unspecified file type */ return TRUE; } /* insure file exists and is an OMF type of file */ if (! (ftype = GetFType(file))) { Error(5,file); return FALSE; } if ((ftype < OBJFL) || (ftype > MAXFL)) { Error(6,file); return FALSE; } return TRUE; } /*************************************************************** * * ExpandDev - Expand devices and prefixes * ***************************************************************/ #define INIT_WILDCARD(parm) (PDosInt(0x0149,parm)) #define NEXT_WILDCARD(parm) (PDosInt(0x014A,parm)) void ExpandDev (char name[]) { struct { /* parameter block for Init_Wildcard */ int pcount; struct { int length; char name[FILEMAX]; } *inName; int flags; } iwRec; struct { /* parameter block for Next_Wildcard */ int pcount; struct { int buffLen; int length; char name[FILEMAX]; } *outName; } nwRec; iwRec.inName = (void *) malloc (sizeof(int) + FILEMAX); nwRec.outName = (void *) malloc (sizeof(int)*2 + FILEMAX); if ((iwRec.inName == NULL) || (nwRec.outName == NULL)) { if (iwRec.inName != NULL) free(iwRec.inName); if (nwRec.outName != NULL) free(nwRec.outName); return; } iwRec.pcount = 2; iwRec.inName->length = strlen(name); strcpy(iwRec.inName->name, name); iwRec.flags = 0x4000; nwRec.pcount = 1; nwRec.outName->buffLen = FILEMAX+4; INIT_WILDCARD(&iwRec); if (!toolerror()) { NEXT_WILDCARD(&nwRec); if (!toolerror()) { memcpy(name, nwRec.outName->name, nwRec.outName->length); name[nwRec.outName->length] = (char) 0; } } free(iwRec.inName); free(nwRec.outName); } /*************************************************************** * * SetFlag - Sets the input parameters flags * ***************************************************************/ BOOLEAN SetFlag (char *str) { char ch; if (strlen(str) != 2) { Error(4,str); return FALSE; } ch = toupper(str[1]); if ((str[0]) == '+') { /* handle + flags */ if (ch == 'X') {format = 2;} else if (ch == 'D') {format = 1;} else if (ch == 'S') {shorth = FALSE;} else if (ch == 'I') {ireg = TRUE;} else if (ch == 'L') {longc = TRUE;} else if (ch == 'M') {mreg = TRUE;} else if (ch == 'H') {header = TRUE;} else if (ch == 'O') {body = TRUE;} else if (ch == 'F') {checkf = TRUE;} else if (ch == 'A') {colf = TRUE;} else {Error(4, str); return FALSE;} } else { /* handle - flags */ if (ch == 'X') {format = 0;} else if (ch == 'D') {format = 0;} else if (ch == 'S') {shorth = TRUE;} else if (ch == 'I') {ireg = FALSE;} else if (ch == 'L') {longc = FALSE;} else if (ch == 'M') {mreg = FALSE;} else if (ch == 'H') {header = FALSE;} else if (ch == 'O') {body = FALSE;} else if (ch == 'F') {checkf = FALSE;} else if (ch == 'A') {colf = FALSE;} else {Error(4, str); return FALSE;} } return TRUE; } /*************************************************************** * * Reads the names list and sets up namelist pointers * ***************************************************************/ BOOLEAN GetList (int num, int argc, char *argv[]) { char local[NAMEMAX]; int i, k; if (num == argc) { names = FALSE; return TRUE; } for (i=num; i<=argc; i++) { strncat(nlist, argv[i], strlen(argv[i])); strncat(nlist, " ", 1); } strcpy(local, nlist); if (strlen(nlist) < 8) { Error(4,local); names = FALSE; return FALSE; } for (i=0; i<5; i++) nlist[i] = toupper(nlist[i]); if (strncmp(nlist,"NAMES=(",7) != 0) { Error(4,local); names = FALSE; return FALSE; } for (i=0; i<7; i++) nlist[i] = ' '; i = 0; while (nlist[i] && (nlist[i] != ')')) { if (nlist[i] == ',') nlist[i] = ' '; i++; } if (! nlist[i]) { Error(4,local); names = FALSE; return FALSE; } nlist[i] = 0; names = TRUE; return TRUE; } /*************************************************************** * * GetName - This is the name input routine * ***************************************************************/ void GetName (char *name) { int i, x; char ch; fputs("File name: ", stdout); /* prompt for file name */ name[0] = (char) 0; /* read the file name */ fgets(name, NAMEMAX, stdin); x = strlen(name); /* strip whitespace */ while ((x != 0) && isspace(name[x-1])) name[--x] = (char) 0; while (((x = strlen(name)) != 0) && isspace(name[0])) for (i = 0; i < x; ++i) name[i] = name[i+1]; } /*************************************************************** * * GetParms - Gets the input parameters * ***************************************************************/ BOOLEAN GetParms (int argc, char *argv[]) { char local[NAMEMAX]; int i; i = 1; while (i <= argc) { /* first set the flags */ strcpy(local,argv[i]); ++i; if ((local[0] == '+') || (local[0] == '-')) { if (! SetFlag(local)) return FALSE; } else break; } if (i <= argc) /* get file name */ strcpy(fname,argv[i-1]); else { GetName(fname); /* ask for and get file name */ i = argc; /* no names list */ } ExpandDev(fname); /* expand devices */ if (! CheckFile(fname)) return FALSE; if ((input = fopen(fname,"rb")) == NULL) { Error(5,fname); return FALSE; } return GetList(i, argc, argv); } /**************************************************************** * * Initialize - Initialize variables * ****************************************************************/ void Initialize (void) { puts("DumpOBJ 2.0.2 B1\n"); /* write the header */ format = /* dump in opcode format */ namc = /* no names in namelist */ ftype = /* no specified file type yet */ status = 0; /* assume no errors */ segmark = /* start with begining segment */ blocks = 0L; /* no block yet */ shorth = FALSE; /* don't do "scan" type output */ ireg = /* use long index registars */ mreg = /* use long accumulator */ header = /* print the header */ longc = /* print long constants */ body = /* print the body */ checkf = /* check input file type */ colf = TRUE; /* write out the numbers */ } /**** Main Programs ***********************************************/ /**************************************************************** * * Main - Begin Program * ****************************************************************/ int main (int argc, char * argv[]) { Initialize(); /* initialize variables */ if (GetParms(argc, argv)) { /* get input parameters */ switch (format) { case 0: DpOpCode(); break; /* dump file in opcode format */ case 1: DpDisasm(); break; /* dump file in disassembled format */ case 2: DpHex(); break; /* dump file in hex format */ default: Error(1," "); /* flag error if not one of these */ } } putchar('\n'); return status; }