#include #include #include "stone.h" #include "info.h" typedef unsigned char uint8; typedef unsigned short uint16; int stone_info_omf (char *filename) { int *group = NULL; int *segment = NULL; char **name = NULL; int nname = 0; int nsegment = 0; int ngroup = 0; int c, d, ch; FILE *file; if ((file = fopen (filename, "rb")) == NULL) return 0; if (fgetc (file) != 0x80) { fclose (file); return 0; } fseek (file, -1, SEEK_CUR); out ("OMF file '%s'\n", filename); while (1) { uint8 type; uint16 length; int end; type = fgetc (file); length = fgetw (file); if (feof (file)) break; if (fseek (file, length, SEEK_CUR)) { out ("end-of-file"); break; } fseek (file, -length, SEEK_CUR); end = ftell (file) + length; if (__verbose) out ("%Xh %d", type, length); switch (type) { case 0x80: /* source filename (translator's header) */ d = fgetc (file); out ("%ssource file - '", __verbose ? " - " : ""); for (c = 0; c < length - 2; c ++) out ("%c", fgetc (file)); out ("'\n"); break; case 0x88: /* comment */ { uint8 comtype; uint8 comclass; comtype = fgetc (file); comclass = fgetc (file); out ("%scomment - ", __verbose ? " - " : ""); if (comtype & 1) out ("no-purge "); if (comtype & 2) out ("dont-display "); if (comtype) out ("- "); switch (comclass) { case 0: out ("translator"); break; default: out ("unknown class"); break; } out (" (%d/%Xh)\n", comclass, comclass); if (length > 3) out (" "); for (c = d = 0; c < length - 3; c ++) { ch = fgetc (file); if (ch >= 32 && ch < 128) { if (d + 1 >= 70) out ("\n "), d = 2; d += out ("%c", ch); } else if (ch == '\n') out ("\n "), d = 2; else { if (d + 4 >= 70) out ("\n "), d = 2; d += out ("<%02X>", ch); } } if (length > 3) out ("\n"); break; } case 0x8B: /* end */ out ("%send\n", __verbose ? " - " : ""); break; case 0x8C: /* extern */ { out ("%sextern\n", __verbose ? " - " : ""); while (1) { if (ftell (file) >= end - 1) break; d = fgetc (file); out (" "); for (c = 0; c < d; c ++) out ("%c", fgetc (file)); out (" (%d)\n", fgetc (file)); } break; } case 0x90: /* public */ { uint8 groupindex; uint8 segmentindex; groupindex = fgetc (file); segmentindex = fgetc (file); if (__verbose) out (" - "); if (groupindex != 0) out ("public (%s:%s)\n", name [group [groupindex - 1]], name [segment [segmentindex - 1]]); else out ("public (%s)\n", name [segment [segmentindex - 1]]); while (1) { char buf [256]; uint8 length; uint16 offset; uint8 type; if (ftell (file) >= end - 1) break; length = fgetc (file); for (c = 0; c < length; c ++) buf [c] = fgetc (file); offset = fgetw (file); type = fgetc (file); out (" %d/%Xh %.*s (%d)\n", offset, offset, length, buf, type); } break; } case 0x96: /* names */ { out ("%snames\n", __verbose ? " - " : ""); while (1) { if (ftell (file) >= end) break; name = realloc (name, sizeof (*name) * (nname + 1)); d = fgetc (file); name [nname] = malloc (d + 1); fread (name [nname], 1, d, file); name [nname] [d] = '\0'; nname ++; } break; } case 0x98: /* segment */ { uint8 attrib; uint16 length; uint8 nameindex; uint8 classindex; uint8 overlayindex; attrib = fgetc (file); length = fgetw (file); nameindex = fgetc (file); classindex = fgetc (file); overlayindex = fgetc (file); segment = realloc (segment, sizeof (*segment) * (nsegment + 1)); segment [nsegment ++] = nameindex; out ("%s%s segment (%d bytes)\n", __verbose ? " - " : "", name [nameindex], length); if (*name [classindex] != '\0') out (" class = '%s'\n", name [classindex]); if (*name [overlayindex] != '\0') out (" overlay = '%s'\n", name [overlayindex]); out (" attrib: "); for (c = 0; c < 8; c ++) out ("%c", attrib & (1 << c) ? '1' : '0'); out ("\n"); out (" alignment: "); switch (attrib & 7) { case 0: out ("absolute segment\n"); break; case 1: out ("relocatable, byte-aligned\n"); break; case 2: out ("relocatable, word-aligned\n"); break; case 3: out ("relocatable, paragraph (16-byte) aligned"); break; case 4: out ("relocatable, page-aligned (4096-byte?)"); break; case 5: out ("relocatable, double-word-aligned\n"); break; default: out ("reserved (%d)\n", attrib & 7); break; } out (" combination: "); switch ((attrib >> 3) & 7) { case 0: out ("private\n"); break; case 7: case 4: case 2: out ("public (%d)\n", (attrib >> 3) & 7); break; case 5: out ("stack\n"); break; case 6: out ("common\n"); break; default: out ("reserved (%d)\n", (attrib >> 3) & 7); break; } break; } case 0x9A: /* group */ { uint8 nameindex; nameindex = fgetc (file); group = realloc (group, ngroup + 1); group [ngroup ++] = nameindex; out ("%sgroup %s -", __verbose ? " - " : "", name [nameindex]); while (ftell (file) < end - 1) { uint8 index; uint8 segmentindex; index = fgetc (file); segmentindex = fgetc (file); if (index != 255) out (" %s:%Xh", name [segment [segmentindex - 1]], index); else out (" %s", name [segment [segmentindex - 1]]); } out ("\n"); break; } case 0x9D: /* relocations */ { out ("%srelocations\n", __verbose ? " - " : ""); while (ftell (file) < end - 1) { uint8 type; type = fgetc (file); if (type & 128) { uint16 locat; locat = (type << 8) | fgetc (file); /* I know, it's backwards! */ out (" %d - ", locat & 1023); switch ((locat >> 2) & 15) { case 1: out ("16-bit offset"); break; default: out ("unknown (%d)", (locat >> 2) & 15); break; } out ("\n"); break; } else break; } fseek (file, end - length, SEEK_SET); print_hex_file_file (outfile, file, length - 1, 0, 2, 16); break; } case 0xA0: /* segment data */ { uint8 segmentindex; uint16 offset; segmentindex = fgetc (file); offset = fgetw (file); out ("%s%s segment data", __verbose ? " - " : "", name [segment [segmentindex - 1]]); if (offset != 0) out (" - offset %d", offset); if (!__verbose) out (" - %d bytes", length - 4); out ("\n"); if (__verbose) print_hex_file_file (outfile, file, length - 4, 0, 2, 16); break; } case 0xA2: /* iterated data */ { uint8 segmentindex; uint16 offset; uint16 length; segmentindex = fgetc (file); offset = fgetw (file); length = fgetw (file); out ("%s%s segment iterated data", __verbose ? " - " : "", name [segment [segmentindex - 1]]); if (offset != 0) out (" - offset %d", offset); out (" - %d bytes", length); if (fgetc (file) != 0x01 || fgetc (file) != 0x00 || fgetc (file) != 0x01 || fgetc (file) != 0x00 || fgetc (file) != 0x00 || fgetc (file) != 0x00 || fgetc (file) != 0x01 || fgetc (file) != 0x00) out ("- not-zero data"); out ("\n"); break; } default: if (!__verbose) out ("%Xh %d", type, length); out ("\n"); print_hex_file_file (outfile, file, length, 0, 2, 16); break; } fseek (file, end, SEEK_SET); } for (c = 0; c < nname; c ++) free (name [c]); if (name != NULL) free (name); if (segment != NULL) free (segment); if (group != NULL) free (group); fclose (file); return 1; }