mirror of
https://github.com/open-simh/simtools.git
synced 2026-01-13 15:27:18 +00:00
792 lines
19 KiB
C
792 lines
19 KiB
C
/* Dump and interpret an object file. */
|
|
|
|
/*
|
|
Copyright (c) 2001, Richard Krehbiel
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are
|
|
met:
|
|
|
|
o Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
o Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
o Neither the name of the copyright holder nor the names of its
|
|
contributors may be used to endorse or promote products derived from
|
|
this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
|
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
DAMAGE.
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <assert.h>
|
|
|
|
#include "rad50.h"
|
|
|
|
#include "util.h"
|
|
|
|
#define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8))
|
|
|
|
#define NPSECTS 256
|
|
|
|
#ifndef DEFAULT_OBJECTFORMAT_RT11
|
|
#define DEFAULT_OBJECTFORMAT_RT11 0
|
|
#endif
|
|
|
|
int psectid = 0;
|
|
char *psects[NPSECTS];
|
|
FILE *bin = NULL;
|
|
int badbin = 0;
|
|
int xferad = 1;
|
|
|
|
/* memcheck - crash out if a pointer (returned from malloc) is NULL. */
|
|
|
|
void *memcheck(
|
|
void *ptr)
|
|
{
|
|
if (ptr == NULL) {
|
|
fprintf(stderr, "Out of memory.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
char *readrec(
|
|
FILE *fp,
|
|
int *len,
|
|
int rt11)
|
|
{
|
|
int c,
|
|
i;
|
|
int chksum;
|
|
char *buf;
|
|
|
|
chksum = 0;
|
|
|
|
if (rt11) {
|
|
while (c = fgetc(fp), c != EOF && c == 0) ;
|
|
|
|
if (c == EOF)
|
|
return NULL;
|
|
|
|
if (c != 1) {
|
|
fprintf(stderr, "Improperly formatted OBJ file (1)\n");
|
|
return NULL; /* Not a properly formatted file. */
|
|
}
|
|
|
|
chksum -= c;
|
|
|
|
c = fgetc(fp);
|
|
if (c != 0) {
|
|
fprintf(stderr, "Improperly formatted OBJ file (2)\n");
|
|
return NULL; /* Not properly formatted */
|
|
}
|
|
|
|
chksum -= c; /* even though for 0 the checksum isn't changed... */
|
|
}
|
|
|
|
c = fgetc(fp);
|
|
if (c == EOF) {
|
|
if (rt11) {
|
|
fprintf(stderr, "Improperly formatted OBJ file (3)\n");
|
|
}
|
|
return NULL;
|
|
}
|
|
*len = c;
|
|
|
|
chksum -= c;
|
|
|
|
c = fgetc(fp);
|
|
if (c == EOF) {
|
|
fprintf(stderr, "Improperly formatted OBJ file (4)\n");
|
|
return NULL;
|
|
}
|
|
|
|
*len += (c << 8);
|
|
|
|
chksum -= c;
|
|
|
|
if (rt11) {
|
|
*len -= 4; /* Subtract header and length bytes from length */
|
|
}
|
|
|
|
if (*len < 0) {
|
|
fprintf(stderr, "Improperly formatted OBJ file (5)\n");
|
|
return NULL;
|
|
}
|
|
|
|
buf = malloc(*len);
|
|
if (buf == NULL) {
|
|
fprintf(stderr, "Out of memory allocating %d bytes\n", *len);
|
|
return NULL; /* Bad alloc */
|
|
}
|
|
|
|
i = fread(buf, 1, *len, fp);
|
|
if (i < *len) {
|
|
free(buf);
|
|
fprintf(stderr, "Improperly formatted OBJ file (6)\n");
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < *len; i++)
|
|
chksum -= (buf[i] & 0xff);
|
|
|
|
if (rt11) {
|
|
c = fgetc(fp);
|
|
c &= 0xff;
|
|
chksum &= 0xff;
|
|
|
|
if (c != chksum) {
|
|
free(buf);
|
|
fprintf(stderr, "Bad record checksum, " "calculated=$%04x, recorded=$%04x\n", chksum, c);
|
|
return NULL;
|
|
}
|
|
} else {
|
|
if (*len & 1) {
|
|
/* skip 1 byte of padding */
|
|
c = fgetc(fp);
|
|
if (c == EOF) {
|
|
free(buf);
|
|
fprintf(stderr, "EOF where padding byte should be\n");
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
void dump_bytes(
|
|
char *buf,
|
|
int len)
|
|
{
|
|
int i,
|
|
j;
|
|
|
|
for (i = 0; i < len; i += 8) {
|
|
printf("\t%3.3o: ", i);
|
|
for (j = i; j < len && j < i + 8; j++)
|
|
printf("%3.3o ", buf[j] & 0xff);
|
|
|
|
printf("%*s", (i + 8 - j) * 4, "");
|
|
|
|
for (j = i; j < len && j < i + 8; j++) {
|
|
int c = buf[j] & 0xff;
|
|
|
|
if (!isprint(c))
|
|
c = '.';
|
|
putchar(c);
|
|
}
|
|
|
|
putchar('\n');
|
|
}
|
|
}
|
|
|
|
void dump_words(
|
|
unsigned addr,
|
|
char *buf,
|
|
int len)
|
|
{
|
|
int i,
|
|
j;
|
|
|
|
for (i = 0; i < len; i += 8) {
|
|
printf("\t%6.6o: ", addr);
|
|
|
|
for (j = i; j < len && j < i + 8; j += 2)
|
|
if (len - j >= 2) {
|
|
unsigned word = WORD(buf + j);
|
|
|
|
printf("%6.6o ", word);
|
|
} else
|
|
printf("%3.3o ", buf[j] & 0xff);
|
|
|
|
printf("%*s", (i + 8 - j) * 7 / 2, "");
|
|
|
|
for (j = i; j < len && j < i + 8; j++) {
|
|
int c = buf[j] & 0xff;
|
|
|
|
if (!isprint(c))
|
|
c = '.';
|
|
putchar(c);
|
|
}
|
|
|
|
putchar('\n');
|
|
addr += 8;
|
|
}
|
|
}
|
|
|
|
void dump_bin(
|
|
unsigned addr,
|
|
char *buf,
|
|
int len)
|
|
{
|
|
int chksum; /* Checksum is negative sum of all
|
|
bytes including header and length */
|
|
int FBR_LEAD1 = 1,
|
|
FBR_LEAD2 = 0;
|
|
int i;
|
|
unsigned hdrlen = len + 6;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
fputc(0, bin);
|
|
chksum = 0;
|
|
if (fputc(FBR_LEAD1, bin) == EOF)
|
|
return; /* All recs begin with 1,0 */
|
|
chksum -= FBR_LEAD1;
|
|
if (fputc(FBR_LEAD2, bin) == EOF)
|
|
return;
|
|
chksum -= FBR_LEAD2;
|
|
|
|
i = hdrlen & 0xff; /* length, lsb */
|
|
chksum -= i;
|
|
if (fputc(i, bin) == EOF)
|
|
return;
|
|
|
|
i = (hdrlen >> 8) & 0xff; /* length, msb */
|
|
chksum -= i;
|
|
if (fputc(i, bin) == EOF)
|
|
return;
|
|
|
|
i = addr & 0xff; /* origin, msb */
|
|
chksum -= i;
|
|
if (fputc(i, bin) == EOF)
|
|
return;
|
|
|
|
i = (addr >> 8) & 0xff; /* origin, lsb */
|
|
chksum -= i;
|
|
if (fputc(i, bin) == EOF)
|
|
return;
|
|
|
|
if ((len == 0) || (buf == NULL))
|
|
return; /* end of tape block */
|
|
|
|
i = fwrite(buf, 1, len, bin);
|
|
if (i < len)
|
|
return;
|
|
|
|
while (len > 0) { /* All the data bytes */
|
|
chksum -= *buf++ & 0xff;
|
|
len--;
|
|
}
|
|
|
|
chksum &= 0xff;
|
|
|
|
fputc(chksum, bin); /* Followed by the checksum byte */
|
|
|
|
return; /* Worked okay. */
|
|
}
|
|
|
|
void trim(
|
|
char *buf)
|
|
{
|
|
char *cp;
|
|
|
|
for (cp = buf + strlen(buf); cp > buf; cp--)
|
|
if (cp[-1] != ' ')
|
|
break;
|
|
*cp = 0;
|
|
}
|
|
|
|
char **all_gsds = NULL;
|
|
int nr_gsds = 0;
|
|
int gsdsize = 0;
|
|
|
|
void add_gsdline(
|
|
char *line)
|
|
{
|
|
if (nr_gsds >= gsdsize || all_gsds == NULL) {
|
|
gsdsize += 128;
|
|
all_gsds = memcheck(realloc(all_gsds, gsdsize * sizeof(char *)));
|
|
}
|
|
|
|
all_gsds[nr_gsds++] = line;
|
|
}
|
|
|
|
void got_gsd(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
int i;
|
|
char *gsdline;
|
|
|
|
for (i = 2; i < len; i += 8) {
|
|
char name[8];
|
|
unsigned value;
|
|
unsigned flags;
|
|
|
|
gsdline = memcheck(malloc(256));
|
|
|
|
unrad50(WORD(cp + i), name);
|
|
unrad50(WORD(cp + i + 2), name + 3);
|
|
name[6] = 0;
|
|
|
|
value = WORD(cp + i + 6);
|
|
flags = cp[i + 4] & 0xff;
|
|
|
|
switch (cp[i + 5] & 0xff) {
|
|
case 0:
|
|
sprintf(gsdline, "\tMODNAME %s=%o flags=%o\n", name, value, flags);
|
|
break;
|
|
case 1:
|
|
sprintf(gsdline, "\tCSECT %s=%o flags=%o\n", name, value, flags);
|
|
break;
|
|
case 2:
|
|
sprintf(gsdline, "\tISD %s=%o flags=%o\n", name, value, flags);
|
|
break;
|
|
case 3:
|
|
sprintf(gsdline, "\tXFER %s=%o flags=%o\n", name, value, flags);
|
|
xferad = value;
|
|
break;
|
|
case 4:
|
|
sprintf(gsdline, "\tGLOBAL %s=%o %s%s%s %s flags=%o\n", name, value,
|
|
flags & 01 ? "WEAK " : "",
|
|
flags & 04 ? "LIB " : "",
|
|
flags & 010 ? "DEF" : "REF",
|
|
flags & 040 ? "REL" : "ABS",
|
|
flags);
|
|
break;
|
|
case 5:
|
|
sprintf(gsdline, "\tPSECT %s=%o %s%s %s %s %s %s %s flags=%o\n", name, value,
|
|
flags & 01 ? "SAV " : "",
|
|
flags & 02 ? "LIB " : "",
|
|
flags & 04 ? "OVR" : "CON",
|
|
flags & 020 ? "RO" : "RW",
|
|
flags & 040 ? "REL" : "ABS",
|
|
flags & 0100 ? "GBL" : "LCL",
|
|
flags & 0200 ? "D" : "I",
|
|
flags);
|
|
psects[psectid] = memcheck(strdup(name));
|
|
trim(psects[psectid++]);
|
|
psectid %= NPSECTS;
|
|
break;
|
|
case 6:
|
|
sprintf(gsdline, "\tIDENT %s=%o flags=%o\n", name, value, flags);
|
|
break;
|
|
case 7:
|
|
sprintf(gsdline, "\tVSECT %s=%o flags=%o\n", name, value, flags);
|
|
break;
|
|
case 010:
|
|
sprintf(gsdline, "\tCompletion Routine Name %s=%o flags=%o\n", name, value, flags);
|
|
break;
|
|
default:
|
|
sprintf(gsdline, "\t***Unknown GSD entry type %d flags=%o\n", cp[i + 5] & 0xff, flags);
|
|
break;
|
|
}
|
|
|
|
gsdline = memcheck(realloc(gsdline, strlen(gsdline) + 1));
|
|
add_gsdline(gsdline);
|
|
}
|
|
}
|
|
|
|
int compare_gsdlines(
|
|
const void *p1,
|
|
const void *p2)
|
|
{
|
|
const char *const *l1 = p1,
|
|
*const *l2 = p2;
|
|
|
|
return strcmp(*l1, *l2);
|
|
}
|
|
|
|
void got_endgsd(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
int i;
|
|
|
|
(void)cp;
|
|
(void)len;
|
|
|
|
if (nr_gsds == 0) {
|
|
return;
|
|
}
|
|
|
|
qsort(all_gsds, nr_gsds, sizeof(char *), compare_gsdlines);
|
|
|
|
printf("GSD:\n");
|
|
|
|
for (i = 0; i < nr_gsds; i++) {
|
|
fputs(all_gsds[i], stdout);
|
|
free(all_gsds[i]);
|
|
}
|
|
|
|
printf("ENDGSD\n");
|
|
|
|
free(all_gsds);
|
|
all_gsds = NULL;
|
|
nr_gsds = 0;
|
|
gsdsize = 0;
|
|
}
|
|
|
|
unsigned last_text_addr = 0;
|
|
|
|
void got_text(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
unsigned addr = WORD(cp + 2);
|
|
|
|
last_text_addr = addr;
|
|
|
|
printf("TEXT ADDR=%o LEN=%o\n", last_text_addr, len - 4);
|
|
|
|
dump_words(last_text_addr, cp + 4, len - 4);
|
|
|
|
if (bin)
|
|
dump_bin(last_text_addr, cp + 4, len - 4);
|
|
}
|
|
|
|
void rad50name(
|
|
char *cp,
|
|
char *name)
|
|
{
|
|
unrad50(WORD(cp), name);
|
|
unrad50(WORD(cp + 2), name + 3);
|
|
name[6] = 0;
|
|
trim(name);
|
|
}
|
|
|
|
void got_rld(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
int i;
|
|
|
|
printf("RLD\n");
|
|
|
|
for (i = 2; i < len;) {
|
|
unsigned addr;
|
|
unsigned word;
|
|
unsigned disp = cp[i + 1] & 0xff;
|
|
char name[8];
|
|
char *byte;
|
|
|
|
addr = last_text_addr + disp - 4;
|
|
|
|
byte = "";
|
|
if (cp[i] & 0200)
|
|
byte = " byte";
|
|
|
|
switch (cp[i] & 0x7f) {
|
|
case 01:
|
|
printf("\tInternal%s %o=%o\n", byte, addr, WORD(cp + i + 2));
|
|
i += 4;
|
|
break;
|
|
case 02:
|
|
rad50name(cp + i + 2, name);
|
|
printf("\tGlobal%s %o=%s\n", byte, addr, name);
|
|
i += 6;
|
|
break;
|
|
case 03:
|
|
printf("\tInternal displaced%s %o=%o\n", byte, addr, WORD(cp + i + 2));
|
|
i += 4;
|
|
badbin = 1;
|
|
break;
|
|
case 04:
|
|
rad50name(cp + i + 2, name);
|
|
printf("\tGlobal displaced%s %o=%s\n", byte, addr, name);
|
|
i += 6;
|
|
badbin = 1;
|
|
break;
|
|
case 05:
|
|
rad50name(cp + i + 2, name);
|
|
word = WORD(cp + i + 6);
|
|
printf("\tGlobal plus offset%s %o=%s+%o\n", byte, addr, name, word);
|
|
i += 8;
|
|
badbin = 1;
|
|
break;
|
|
case 06:
|
|
rad50name(cp + i + 2, name);
|
|
word = WORD(cp + i + 6);
|
|
printf("\tGlobal plus offset displaced%s %o=%s+%o\n", byte, addr, name, word);
|
|
i += 8;
|
|
badbin = 1;
|
|
break;
|
|
case 07:
|
|
rad50name(cp + i + 2, name);
|
|
word = WORD(cp + i + 6);
|
|
printf("\tLocation counter definition %s+%o\n", name, word);
|
|
i += 8;
|
|
|
|
last_text_addr = word;
|
|
break;
|
|
case 010:
|
|
word = WORD(cp + i + 2);
|
|
printf("\tLocation counter modification %o\n", word);
|
|
i += 4;
|
|
|
|
last_text_addr = word;
|
|
break;
|
|
case 011:
|
|
printf("\t.LIMIT %o\n", addr);
|
|
i += 2;
|
|
break;
|
|
|
|
case 012:
|
|
rad50name(cp + i + 2, name);
|
|
printf("\tPSECT%s %o=%s\n", byte, addr, name);
|
|
i += 6;
|
|
badbin = 1;
|
|
break;
|
|
case 014:
|
|
rad50name(cp + i + 2, name);
|
|
|
|
printf("\tPSECT displaced%s %o=%s\n", byte, addr, name);
|
|
i += 6;
|
|
badbin = 1;
|
|
break;
|
|
case 015:
|
|
rad50name(cp + i + 2, name);
|
|
word = WORD(cp + i + 6);
|
|
printf("\tPSECT plus offset%s %o=%s+%o\n", byte, addr, name, word);
|
|
i += 8;
|
|
badbin = 1;
|
|
break;
|
|
case 016:
|
|
rad50name(cp + i + 2, name);
|
|
word = WORD(cp + i + 6);
|
|
printf("\tPSECT plus offset displaced%s %o=%s+%o\n", byte, addr, name, word);
|
|
i += 8;
|
|
badbin = 1;
|
|
break;
|
|
|
|
case 017:
|
|
badbin = 1;
|
|
printf("\tComplex%s %o=", byte, addr);
|
|
i += 2; {
|
|
char *xp = cp + i;
|
|
int size;
|
|
|
|
for (;;) {
|
|
size = 1;
|
|
switch (*xp) {
|
|
case 000:
|
|
fputs("nop ", stdout);
|
|
break;
|
|
case 001:
|
|
fputs("+ ", stdout);
|
|
break;
|
|
case 002:
|
|
fputs("- ", stdout);
|
|
break;
|
|
case 003:
|
|
fputs("* ", stdout);
|
|
break;
|
|
case 004:
|
|
fputs("/ ", stdout);
|
|
break;
|
|
case 005:
|
|
fputs("& ", stdout);
|
|
break;
|
|
case 006:
|
|
fputs("! ", stdout);
|
|
break;
|
|
case 010:
|
|
fputs("neg ", stdout);
|
|
break;
|
|
case 011:
|
|
fputs("^C ", stdout);
|
|
break;
|
|
case 012:
|
|
fputs("store ", stdout);
|
|
break;
|
|
case 013:
|
|
fputs("store{disp} ", stdout);
|
|
break;
|
|
|
|
case 016:
|
|
rad50name(xp + 1, name);
|
|
printf("%s ", name);
|
|
size = 5;
|
|
break;
|
|
|
|
case 017:
|
|
assert((xp[1] & 0377) < psectid);
|
|
printf("%s:%o ", psects[xp[1] & 0377], WORD(xp + 2));
|
|
size = 4;
|
|
break;
|
|
|
|
case 020:
|
|
printf("%o ", WORD(xp + 1));
|
|
size = 3;
|
|
break;
|
|
default:
|
|
printf("**UNKNOWN COMPLEX CODE** %o\n", *xp & 0377);
|
|
return;
|
|
}
|
|
i += size;
|
|
if (*xp == 012 || *xp == 013)
|
|
break;
|
|
xp += size;
|
|
}
|
|
fputc('\n', stdout);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
printf("\t***Unknown RLD code %o\n", cp[i] & 0xff);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void got_isd(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
(void)cp;
|
|
printf("ISD len=%o\n", len);
|
|
}
|
|
|
|
void got_endmod(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
(void)cp;
|
|
(void)len;
|
|
printf("ENDMOD\n");
|
|
}
|
|
|
|
void got_libhdr(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
(void)cp;
|
|
(void)len;
|
|
printf("LIBHDR\n");
|
|
}
|
|
|
|
void got_libend(
|
|
char *cp,
|
|
int len)
|
|
{
|
|
(void)cp;
|
|
(void)len;
|
|
printf("LIBEND\n");
|
|
}
|
|
|
|
int main(
|
|
int argc,
|
|
char *argv[])
|
|
{
|
|
int len;
|
|
FILE *fp;
|
|
int arg;
|
|
int rt11 = DEFAULT_OBJECTFORMAT_RT11;
|
|
char *infile = 0;
|
|
char *outfile = 0;
|
|
|
|
for (arg = 1; arg < argc; arg++) {
|
|
if (*argv[arg] == '-') {
|
|
char *cp;
|
|
|
|
cp = argv[arg] + 1;
|
|
if (!strcasecmp(cp, "rt11")) {
|
|
rt11 = 1;
|
|
} else if (!strcasecmp(cp, "rsx")) {
|
|
rt11 = 0;
|
|
} else {
|
|
fprintf(stderr, "Unknown option %s\n", argv[arg]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
else if (infile == 0) {
|
|
infile = argv[arg];
|
|
}
|
|
else if (outfile == 0) {
|
|
outfile = argv[arg];
|
|
}
|
|
else {
|
|
fprintf(stderr, "Extra parameter %s\n", argv[arg]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if (infile == 0) {
|
|
fprintf(stderr, "Usage: dumpobj [ -rt11 ] [ -rsx ] input.obj [ output.obj ]\n");
|
|
exit(1);
|
|
}
|
|
|
|
fp = fopen(infile, "rb");
|
|
if (fp == NULL) {
|
|
fprintf(stderr, "Unable to open %s\n", infile);
|
|
return EXIT_FAILURE;
|
|
}
|
|
if (outfile != 0) {
|
|
bin = fopen(outfile, "wb");
|
|
if (bin == NULL) {
|
|
fprintf(stderr, "Unable to open %s\n", outfile);
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
char *cp;
|
|
|
|
while ((cp = readrec(fp, &len, rt11)) != NULL) {
|
|
switch (cp[0] & 0xff) {
|
|
case 1:
|
|
got_gsd(cp, len);
|
|
break;
|
|
case 2:
|
|
got_endgsd(cp, len);
|
|
break;
|
|
case 3:
|
|
got_text(cp, len);
|
|
break;
|
|
case 4:
|
|
got_rld(cp, len);
|
|
break;
|
|
case 5:
|
|
got_isd(cp, len);
|
|
break;
|
|
case 6:
|
|
got_endmod(cp, len);
|
|
break;
|
|
case 7:
|
|
got_libhdr(cp, len);
|
|
break;
|
|
case 8:
|
|
got_libend(cp, len);
|
|
break;
|
|
default:
|
|
printf("Unknown record type %o\n", cp[0] & 0xff);
|
|
break;
|
|
}
|
|
|
|
free(cp);
|
|
}
|
|
|
|
if (bin) {
|
|
dump_bin(xferad, NULL, 0);
|
|
fclose(bin);
|
|
if (badbin)
|
|
fprintf(stderr, "Probable errors in binary file\n");
|
|
}
|
|
|
|
fclose(fp);
|
|
return EXIT_SUCCESS;
|
|
}
|