diff --git a/README b/README index 8d70c6b..f4be345 100644 --- a/README +++ b/README @@ -110,6 +110,10 @@ Options: -m macname Gives a macro library name. Up to 32 macro libraries may be specified, one per -m option. + The current object file format (default, or from + -rt11 or -rsx before this option) is used first to + read the file; if this fails, the other format is + tried. Note: unlike MACRO.SAV, SYSMAC.SML is not automatically included; you must name it. diff --git a/macro11.c b/macro11.c index 4debd12..5444bb9 100644 --- a/macro11.c +++ b/macro11.c @@ -1,6 +1,3 @@ -#define MACRO11__C - - /* Assembler compatible with MACRO-11. @@ -132,7 +129,7 @@ static void print_help( printf(" -l - enables listing to stdout.\n"); printf("-m load RSX-11 or RT-11 compatible macro library from which\n"); printf(" .MCALLed macros can be found.\n"); - printf(" Multiple allowed.\n"); + printf(" Multiple allowed. Affected by any -rsx or -rt11 which come before.\n"); printf("-o gives the object file name (.OBJ)\n"); printf("-p gives the name of a directory in which .MCALLed macros may be found.\n"); printf(" Sets environment variable \"MCALL\".\n"); diff --git a/mlb-rsx.c b/mlb-rsx.c index c86bc62..a545130 100644 --- a/mlb-rsx.c +++ b/mlb-rsx.c @@ -156,6 +156,9 @@ DAMAGE. #include "mlb.h" #include "util.h" +#define MLBDEBUG_OPEN 0 +#define MLBDEBUG_ENTRY 0 + static MLB *mlb_rsx_open( char *name, int allow_object_library); @@ -168,10 +171,11 @@ static void mlb_rsx_extract( MLB *mlb); struct mlb_vtbl mlb_rsx_vtbl = { - mlb_rsx_open, - mlb_rsx_entry, - mlb_rsx_extract, - mlb_rsx_close, + .mlb_open = mlb_rsx_open, + .mlb_entry = mlb_rsx_entry, + .mlb_extract = mlb_rsx_extract, + .mlb_close = mlb_rsx_close, + .mlb_is_rt11 = 0, }; #define BLOCKSIZE 512 @@ -201,7 +205,7 @@ MLB *mlb_rsx_open( int allow_objlib) { MLB *mlb = memcheck(malloc(sizeof(MLB))); - char *buff; + char *buff = NULL; unsigned entsize; unsigned nr_entries; unsigned start_block; @@ -210,6 +214,9 @@ MLB *mlb_rsx_open( mlb->vtbl = &mlb_rsx_vtbl; mlb->directory = NULL; +#if MLBDEBUG_OPEN + fprintf(stderr, "mlb_rsx_open('%s', %d)\n", name, allow_objlib); +#endif mlb->fp = fopen(name, "rb"); if (mlb->fp == NULL) { mlb_rsx_close(mlb); @@ -219,20 +226,16 @@ MLB *mlb_rsx_open( buff = memcheck(malloc(060)); /* Size of MLB library header */ if (fread(buff, 1, 060, mlb->fp) < 060) { - fprintf(stderr, "error: can't read full header\n"); - mlb_rsx_close(mlb); - free(buff); - return NULL; + fprintf(stderr, "mlb_rsx_open error: can't read full header\n"); + goto error; } mlb->is_objlib = 0; if (allow_objlib && WORD(buff) == 01000) { /* Is it an object library? */ mlb->is_objlib = 1; } else if (WORD(buff) != 01001) { /* Is this really a macro library? */ - /* fprintf(stderr, "error: first word not correct value\n"); */ - mlb_rsx_close(mlb); /* Nope. */ - free(buff); - return NULL; + /* fprintf(stderr, "mlb_rsx_open error: first word not correct value\n"); */ + goto error; } entsize = buff[032]; /* The size of each macro directory @@ -242,24 +245,33 @@ MLB *mlb_rsx_open( directory */ if (entsize < 8) { /* Is this really a macro library? */ - mlb_rsx_close(mlb); /* Nope. */ - fprintf(stderr, "error: entsize too small: %d\n", entsize); - return NULL; + fprintf(stderr, "mlb_rsx_open error: entsize too small: %d\n", entsize); + goto error; } -// fprintf(stderr, "entsize=%d, nr_entries=%d, start_block=%d\n", -// entsize, nr_entries, start_block); + if (start_block < 1) { /* Is this really a macro library? */ + fprintf(stderr, "mlb_rsx_open error: start_block too small: %d\n", start_block); + goto error; + } + +#if MLBDEBUG_OPEN + fprintf(stderr, "entsize=%d, nr_entries=%d, start_block=%d\n", + entsize, nr_entries, start_block); +#endif free(buff); /* Done with that header. */ /* Allocate a buffer for the disk directory */ buff = memcheck(malloc(nr_entries * entsize)); - fseek(mlb->fp, start_block * BLOCKSIZE, SEEK_SET); /* Go to the directory */ + /* Go to the directory */ + if (fseek(mlb->fp, start_block * BLOCKSIZE, SEEK_SET) == -1) { + fprintf(stderr, "mlb_rsx_open error: seek error: %d\n", start_block * BLOCKSIZE); + goto error; + } /* Read the disk directory */ if (fread(buff, entsize, nr_entries, mlb->fp) < nr_entries) { - mlb_rsx_close(mlb); /* Sorry, read error. */ - free(buff); - return NULL; + fprintf(stderr, "mlb_rsx_open error: fread: not enough entries\n"); + goto error; } /* Shift occupied directory entries to the front of the array */ @@ -269,11 +281,15 @@ MLB *mlb_rsx_open( for (i = 0, j = nr_entries; i < j; i++) { char *ent1, *ent2; + int w1, w2; ent1 = buff + (i * entsize); /* Unused entries have 0177777 0177777 for the RAD50 name, which is not legal RAD50. */ - if (WORD(ent1) == 0177777 && WORD(ent1 + 2) == 0177777) { + w1 = WORD(ent1); + w2 = WORD(ent1 + 2); + + if (w1 == 0177777 && w2 == 0177777) { while (--j > i && (ent2 = buff + (j * entsize), WORD(ent2) == 0177777 && WORD(ent2 + 2) == 0177777)) ; if (j <= i) @@ -283,15 +299,31 @@ MLB *mlb_rsx_open( space */ memset(ent2, 0377, entsize); /* Mark entry unused */ } else { -// fprintf(stderr, "entry %d: %02x%02x.%02x%02x\n", -// i, ent1[5] & 0xFF, ent1[4] & 0xFF, ent1[7] & 0xFF, ent1[6] & 0xFF); +#if MLBDEBUG_OPEN + fprintf(stderr, "entry %d: %02x%02x.%02x%02x\n", + i, ent1[5] & 0xFF, ent1[4] & 0xFF, ent1[7] & 0xFF, ent1[6] & 0xFF); +#endif + /* + * 00 00 rad50-decodes to spaces, which are not a + * valid name for a macro or object file. + */ + if (w1 == 0000000 && w2 == 0000000) { + fprintf(stderr, "mlb_rsx_open error: bad file, null name\n"); + goto error; + } } } /* Now i contains the actual number of entries. */ mlb->nentries = i; -// fprintf(stderr, " mlb->nentries=%d\n", mlb->nentries); +#if MLBDEBUG_OPEN + fprintf(stderr, "mlb->nentries=%d\n", mlb->nentries); +#endif + if (mlb->nentries == 0) { + fprintf(stderr, "mlb_rsx_open error: no entries\n"); + goto error; + } /* Now, allocate my in-memory directory */ mlb->directory = memcheck(malloc(sizeof(MLBENT) * mlb->nentries)); @@ -308,15 +340,28 @@ MLB *mlb_rsx_open( unrad50(WORD(ent + 2), radname + 3); radname[6] = 0; -// fprintf(stderr, "entry %d: \"%s\" %02x%02x.%02x%02x\n", -// j, radname, -// ent[5] & 0xFF, ent[4] & 0xFF, ent[7] & 0xFF, ent[6] & 0xFF); +#if MLBDEBUG_OPEN + fprintf(stderr, "entry %d: \"%s\" %02x%02x.%02x%02x\n", + j, radname, + ent[5] & 0xFF, ent[4] & 0xFF, ent[7] & 0xFF, ent[6] & 0xFF); +#endif trim(radname); + if (radname[0] == '\0' || strchr(radname, ' ')) { + fprintf(stderr, "mlb_rsx_open error: entry with space in name\n"); + goto error; + } mlb->directory[j].label = memcheck(strdup(radname)); mlb->directory[j].position = BYTEPOS(ent); -// fprintf(stderr, "entry %d: \"%s\" bytepos=%d\n", j, mlb->directory[j].label, mlb->directory[j].position); +#if MLBDEBUG_OPEN + fprintf(stderr, "entry %d: \"%s\" bytepos=%ld\n", j, mlb->directory[j].label, mlb->directory[j].position); +#endif mlb->directory[j].length = -1; + + if (mlb->directory[j].position < BLOCKSIZE) { + fprintf(stderr, "mlb_rsx_open error: bad entry: position\n"); + goto error; + } } free(buff); @@ -324,6 +369,14 @@ MLB *mlb_rsx_open( /* Done. Return the struct that represents the opened MLB. */ return mlb; + +error: +#if MLBDEBUG_OPEN + fprintf(stderr, "(mlb_rsx_open closing '%s' due to errors)\n", name); +#endif + mlb_rsx_close(mlb); /* Sorry, bad file. */ + free(buff); + return NULL; } /* mlb_rsx_close discards MLB and closes the file. */ @@ -367,28 +420,38 @@ BUFFER *mlb_rsx_entry( } if (i >= mlb->nentries) { -// fprintf(stderr, "mlb_rsx_entry: %s not found\n", name); +#if MLBDEBUG_ENTRY + fprintf(stderr, "mlb_rsx_entry: %s not found\n", name); +#endif return NULL; } fseek(mlb->fp, ent->position, SEEK_SET); -// fprintf(stderr, "mlb_rsx_entry: %s at position %ld\n", name, (long)ent->position); +#if MLBDEBUG_ENTRY + fprintf(stderr, "mlb_rsx_entry: %s at position %ld\n", name, (long)ent->position); +#endif #define MODULE_HEADER_SIZE 022 if (fread(module_header, MODULE_HEADER_SIZE, 1, mlb->fp) < 1) { -// fprintf(stderr, "mlb_rsx_entry: %s at position %lx can't read 022 bytes\n", name, (long)ent->position); +#if MLBDEBUG_ENTRY + fprintf(stderr, "mlb_rsx_entry: %s at position %lx can't read 022 bytes\n", name, (long)ent->position); +#endif return NULL; } -// for (i = 0; i < MODULE_HEADER_SIZE; i++) { -// fprintf(stderr, "%02x ", module_header[i]); -// } -// fprintf(stderr, "\n"); +#if MLBDEBUG_ENTRY + for (i = 0; i < MODULE_HEADER_SIZE; i++) { + fprintf(stderr, "%02x ", module_header[i]); + } + fprintf(stderr, "\n"); +#endif ent->length = (WORD(module_header + 04) << 16) + WORD(module_header + 06); ent->length -= MODULE_HEADER_SIZE; /* length is including this header */ -// fprintf(stderr, "mlb_rsx_entry: %s at position %lx length = %d\n", name, (long)ent->position, ent->length); +#if MLBDEBUG_ENTRY + fprintf(stderr, "mlb_rsx_entry: %s at position %lx length = %d\n", name, (long)ent->position, ent->length); +#endif if (module_header[02] == 1) { fprintf(stderr, "mlb_rsx_entry: %s at position %lx deleted entry\n", name, (long)ent->position); @@ -418,19 +481,25 @@ BUFFER *mlb_rsx_entry( i = fread(bp, 1, ent->length, mlb->fp); bp += i; } else if (module_header[0] & 0x10) { -// fprintf(stderr, "mlb_rsx_entry: %s at position %lx variable length records\n", name, (long)ent->position); +#if MLBDEBUG_ENTRY + fprintf(stderr, "mlb_rsx_entry: %s at position %lx variable length records\n", name, (long)ent->position); +#endif /* Variable length records with size before them */ i = ent->length; while (i > 0) { int length; -// fprintf(stderr, "file offset:$%lx\n", (long)ftell(mlb->fp)); +#if MLBDEBUG_ENTRY + fprintf(stderr, "file offset:$%lx\n", (long)ftell(mlb->fp)); +#endif c = fgetc(mlb->fp); /* Get low byte of length */ length = c & 0xFF; c = fgetc(mlb->fp); /* Get high byte */ length += (c & 0xFF) << 8; i -= 2; -// fprintf(stderr, "line length: %d $%x\n", length, length); +#if MLBDEBUG_ENTRY + fprintf(stderr, "line length: %d $%x\n", length, length); +#endif /* Odd lengths are padded with an extra 0 byte */ int padded = length & 1; @@ -441,7 +510,9 @@ BUFFER *mlb_rsx_entry( while (length > 0) { c = fgetc(mlb->fp); /* Get macro byte */ - //fprintf(stderr, "%02x %c length=%d\n", c, c, length); +#if MLBDEBUG_ENTRY + fprintf(stderr, "%02x %c length=%d\n", c, c, length); +#endif i--; length--; if (c == '\r' || c == 0) /* If it's a carriage return or 0, @@ -452,12 +523,16 @@ BUFFER *mlb_rsx_entry( *bp++ = '\n'; if (padded) { c = fgetc(mlb->fp); /* Get pad byte; need not be 0. */ - //fprintf(stderr, "pad byte %02x %c length=%d\n", c, c, length); +#if MLBDEBUG_ENTRY + fprintf(stderr, "pad byte %02x %c length=%d\n", c, c, length); +#endif i--; } } } else { -// fprintf(stderr, "mlb_rsx_entry: %s at position %lx byte stream records\n", name, (long)ent->position); +#if MLBDEBUG_ENTRY + fprintf(stderr, "mlb_rsx_entry: %s at position %lx byte stream records\n", name, (long)ent->position); +#endif for (i = 0; i < ent->length; i++) { c = fgetc(mlb->fp); /* Get macro byte */ if (c == '\r' || c == 0) /* If it's a carriage return or 0, diff --git a/mlb-rt11.c b/mlb-rt11.c index 2e10f88..dfd79d1 100644 --- a/mlb-rt11.c +++ b/mlb-rt11.c @@ -59,12 +59,20 @@ static void mlb_rt11_extract( MLB *mlb); struct mlb_vtbl mlb_rt11_vtbl = { - mlb_rt11_open, - mlb_rt11_entry, - mlb_rt11_extract, - mlb_rt11_close, + .mlb_open = mlb_rt11_open, + .mlb_entry = mlb_rt11_entry, + .mlb_extract = mlb_rt11_extract, + .mlb_close = mlb_rt11_close, + .mlb_is_rt11 = 1, }; +/* + * Format description: + * http://www.bitsavers.org/pdf/dec/pdp11/rt11/v5.6_Aug91/AA-PD6PA-TC_RT-11_Volume_and_File_Formats_Manual_Aug91.pdf + * pages 2-27 ff. + * + * A MLB Macro Library Header differs a lot from an Object Library Header. + */ #define WORD(cp) ((*(cp) & 0xff) + ((*((cp)+1) & 0xff) << 8)) /* BYTEPOS calculates the byte position within the macro libray file. diff --git a/mlb.h b/mlb.h index e9db913..2631a77 100644 --- a/mlb.h +++ b/mlb.h @@ -62,6 +62,7 @@ typedef struct mlb_vtbl { BUFFER *(*mlb_entry)(MLB *mlb, char *name); void (*mlb_extract)(MLB *mlb); void (*mlb_close)(MLB *mlb); + int mlb_is_rt11; } MLB_VTBL; extern MLB *mlb_open( diff --git a/mlb2.c b/mlb2.c index 9d58953..a60d5c5 100644 --- a/mlb2.c +++ b/mlb2.c @@ -35,6 +35,7 @@ DAMAGE. #include #include "util.h" #include "mlb.h" +#include "object.h" MLB_VTBL *mlb_vtbls[] = { &mlb_rsx_vtbl, @@ -42,25 +43,46 @@ MLB_VTBL *mlb_vtbls[] = { NULL }; -MLB *mlb_open( +static MLB *mlb_open_fmt( char *name, - int allow_object_library) + int allow_object_library, + int object_format) { MLB_VTBL *vtbl; MLB *mlb = NULL; int i; for (i = 0; (vtbl = mlb_vtbls[i]); i++) { - mlb = vtbl->mlb_open(name, allow_object_library); - if (mlb != NULL) { - mlb->name = memcheck(strdup(name)); - break; + if (vtbl->mlb_is_rt11 == object_format) { + mlb = vtbl->mlb_open(name, allow_object_library); + if (mlb != NULL) { + mlb->name = memcheck(strdup(name)); + break; + } } } return mlb; } +MLB *mlb_open( + char *name, + int allow_object_library) +{ + MLB *mlb = NULL; + + /* + * First try the open function for the currently set object format. + * If that fails, try the other one. + */ + mlb = mlb_open_fmt(name, allow_object_library, rt11); + if (mlb == NULL) { + mlb = mlb_open_fmt(name, allow_object_library, !rt11); + } + + return mlb; +} + BUFFER *mlb_entry( MLB *mlb, char *name)