From 58f6e7d2dbb1ed20eea2058bfd21d73ae03c45f8 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 8 May 2017 09:28:50 -0700 Subject: [PATCH] IBM1130: Pickup the latest utils from ibm1130software.zip from ibm1130.org - ibm1130software.zip was contained within ibm1130.zip from ibm1130.org - Tabs converted to spaces --- Ibm1130/utils/asm1130.c | 2532 +++++++++++++++++++----------------- Ibm1130/utils/bindump.c | 312 +++-- Ibm1130/utils/disklist.c | 1547 ++++++++++++++++++++++ Ibm1130/utils/disklist.mak | 178 +++ Ibm1130/utils/makefile | 8 +- Ibm1130/utils/punches.c | 337 +++++ Ibm1130/utils/punches.mak | 176 +++ Ibm1130/utils/util_io.c | 155 +++ Ibm1130/utils/util_io.h | 10 + 9 files changed, 3936 insertions(+), 1319 deletions(-) create mode 100644 Ibm1130/utils/disklist.c create mode 100644 Ibm1130/utils/disklist.mak create mode 100644 Ibm1130/utils/punches.c create mode 100644 Ibm1130/utils/punches.mak create mode 100644 Ibm1130/utils/util_io.c create mode 100644 Ibm1130/utils/util_io.h diff --git a/Ibm1130/utils/asm1130.c b/Ibm1130/utils/asm1130.c index 1f1166be..03e806ea 100644 --- a/Ibm1130/utils/asm1130.c +++ b/Ibm1130/utils/asm1130.c @@ -9,119 +9,135 @@ * Mail to sim@ibm1130.org */ -#define VERSION "ASM1130 CROSS ASSEMBLER V1.14" +#define VERSION "ASM1130 CROSS ASSEMBLER V1.22" -// --------------------------------------------------------------------------------- -// ASM1130 - IBM 1130 Cross Assembler -// -// Version -// 1.14 - 2004Oct22 - Fixed problem with BSS complaining about negative -// sizes. This may be a fundamental problem with my using -// 32-bit expressions, but for now, it appears that just -// truncating the BSS size to 16 bits is sufficient to build DMS. -// 1.13 - 2004Jun05 - Fixed sign extension of constants in expressions. Statements -// like LD /FFFF were being assembled incorrectly. -// 1.12 - 2004Jun04 - Made WAIT instruction take a displacement value. -// Doesn't affect operation, but these are used as indicators -// in the IBM one-card diagnostic programs. -// Also -- should mention that the .IPL directive was -// removed some time ago. To create bootable cards, -// use -b flag to create binary output, and post-process the -// binary output with program "mkboot" -// 1.11 - 2004May22 - Added CMP, DCM, and DECS instructions for 1800, -// thanks to Kevin Everets. -// 1.10 - 2003Dec08 - Fixed opcode value for XCH instruction, thanks to -// Roger Simpson. -// 1.09 - 2003Aug03 - Added fxwrite so asm will write little-endian files -// on all CPUs. -// 1.08 - 2003Mar18 - Fixed bug that complained about valid MDX displacement of +127 -// 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case -// 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte) -// First stab at adding ISS level # info, this is iffy -// 1.05 - 2002Apr24 - Made negative BSS size a warning not an error, as it -// it's looking like it happens twice in PTMASMBL. -// This version still doesn't do fixed point numbers and -// negative floats may be wrong. -// 1.04 - 2002Apr18 - Added binary (card loader format) output, removed -// interim IPL output formats and moved that to MKBOOT. -// Enhanced relocatable code handling. Added floating -// point constants, but don't know how to make fixed point -// constants yet. Made amenable to syntax variations found -// in the DMS sources. Doesn't properly handle ILS -// modules yet and ISS is probably wrong. -// 1.03 - 2002Apr10 - numerous fixes, began to add relative/absolute support -// 1.02 - 2002Feb26 - replaced "strupr" with "upcase" for compatibility -// 1.01 - 2002Feb25 - minor compiler compatibility changes -// 1.00 - 2002Feb01 - first release. Tested only under Win32. -// --------------------------------------------------------------------------------- -// -// Usage: -// asm1130 [-bvsx] [-o[file]] [-l[file]] [-rN.M] file... -// -// Description: -// -b binary output (.bin, relocatable absolute format) -// -v verbose -// -s print symbol table -// -x print cross references -// -o output file (default is name of first source file + extension .out or .bin) -// -l listing file (default is name of first source file + extension .lst) -// -y preload system symbol table SYMBOLS.SYS (from the current directory) -// -w write the system symbol table SYMBOLS.SYS in the current directory -// -W same as -w but don't prompt to confirm overwriting existing file -// -r set DMS release to release N version M, for sbrk cards -// -// Listing and symbol table output can be turned on by *LIST directives in the source, too -// Listing file default extension is .LST -// -// Input files can use strict IBM 1130 Assembler column format, or loose formatting -// with tabs, or any mix on a line-by-line basis. Input files default extension is .ASM. -// -// Strict specification is: -// -// label columns 1 - 5 -// opcode 7 - 10 -// tag 12 -// index 13 -// arguments 15 - 51 -// -// Loose, indicated by presence of ascii tab character(s): -// -// labelopcodeindex and format indicatorsarguments -// -// In both cases, the IBM convention that the arguments section ends with the -// first nonblank applies. This means that ".DC 1, 2, 3" assembles only the 1! -// -// Output file format is that used by the LOAD command in my 1130 -// simulator. Lines are any of the following. All values are in hex: -// -// @addr load address for subsequent words is addr -// Znwords Zero the next "nwords" and increment load address by nwords. -// =addr set IAR register to address addr (a convenience) -// value load value at load address and increment load address -// -// Output file default extension is .OUT or .BIN for binary assemblies -// -// Note: this version does not handle relative assembly, and so doesn't carry -// absolute/relative indication through expression calculation. -// -// Seems to work. Was able to assemble the resident monitor OK. -// >>> Look for "bug here" though, for things to check out. -// -// Notes: -// We assume that the computer on which the assembler runs uses ANSI floating point. -// Also, the assembly of floating point values may be incorrect on non-Intel -// architectures, this needs to be investigated. -// -// org_advanced tells whether * in an expression refers to the address AFTER the -// instruction (1 or 2 words, depending on length). This is the case for opcodes -// but not all directives. -// -// Revision History -// 16Apr02 1.03 Added sector break, relocation flag output -// 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction. -// Added directives for 1130 and 1800 IPL output formats -// Added conditional assembly directives -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * ASM1130 - IBM 1130 Cross Assembler + * + * Version + * 1.22 - 2012Nov26 - When the -d argument is specified on the command line, % and < in sources + * act like ( and ), since in the DMS sources these characters need to be interpreted + * this way. + * 1.21 - 2012Oct25 - Fixed bug in XFLC. With no argument, it should spit out a zero + * value, thus reserving core for a variable. It was not, so separate + * variables ended up sharing the same core address. + * 1.20 - 2011Mar25 - Made hex output in listings uppercase + * 1.19 - 2008Nov25 - Set binout[4] in SBRK cards (probably irrelevant) + * 1.18 - 2006Sep09 - Fixed opcode for BOD instruction, error found by Luiz Carlos Orsoni + * 1.17 - 2004Dec14 - Made DEC, DECS output 0 if no argument is given + * 1.16 - 2004Nov12 - Output WAIT instruction for LIBF if output mode is not binary + * 1.15 - 2004Nov03 - Added -f option to offset displayed assembly address in listing + * This is useful when viewing listings of code that is assembled to + * one address but actually loaded to another (e.g. some APL\1130 modules) + * 1.14 - 2004Oct22 - Fixed problem with BSS complaining about negative + * sizes. This may be a fundamental problem with my using + * 32-bit expressions, but for now, it appears that just + * truncating the BSS size to 16 bits is sufficient to build DMS. + * 1.13 - 2004Jun05 - Fixed sign extension of constants in expressions. Statements + * like LD /FFFF were being assembled incorrectly. + * 1.12 - 2004Jun04 - Made WAIT instruction take a displacement value. + * Doesn't affect operation, but these are used as indicators + * in the IBM one-card diagnostic programs. + * Also -- should mention that the .IPL directive was + * removed some time ago. To create bootable cards, + * use -b flag to create binary output, and post-process the + * binary output with program "mkboot" + * 1.11 - 2004May22 - Added CMP, DCM, and DECS instructions for 1800, + * thanks to Kevin Everets. + * 1.10 - 2003Dec08 - Fixed opcode value for XCH instruction, thanks to + * Roger Simpson. + * 1.09 - 2003Aug03 - Added fxwrite so asm will write little-endian files + * on all CPUs. + * 1.08 - 2003Mar18 - Fixed bug that complained about valid MDX displacement of +127 + * 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case + * 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte) + * First stab at adding ISS level # info, this is iffy + * 1.05 - 2002Apr24 - Made negative BSS size a warning not an error, as it + * it's looking like it happens twice in PTMASMBL. + * This version still doesn't do fixed point numbers and + * negative floats may be wrong. + * 1.04 - 2002Apr18 - Added binary (card loader format) output, removed + * interim IPL output formats and moved that to MKBOOT. + * Enhanced relocatable code handling. Added floating + * point constants, but don't know how to make fixed point + * constants yet. Made amenable to syntax variations found + * in the DMS sources. Doesn't properly handle ILS + * modules yet and ISS is probably wrong. + * 1.03 - 2002Apr10 - numerous fixes, began to add relative/absolute support + * 1.02 - 2002Feb26 - replaced "strupr" with "upcase" for compatibility + * 1.01 - 2002Feb25 - minor compiler compatibility changes + * 1.00 - 2002Feb01 - first release. Tested only under Win32. + * --------------------------------------------------------------------------------- + * + * Usage: + * asm1130 [-bdvsx] [-o[file]] [-l[file] [-fXXXX]] [-rN.M] file... + * + * Description: + * -b binary output (.bin, relocatable absolute format) + * -d compile with DMS source character adjustments: % is interpreted as ( and < is intrepreted as ). + * -v verbose + * -s print symbol table + * -x print cross references + * -o output file (default is name of first source file + extension .out or .bin) + * -l listing file (default is name of first source file + extension .lst) + * -y preload system symbol table SYMBOLS.SYS (from the current directory) + * -w write the system symbol table SYMBOLS.SYS in the current directory + * -W same as -w but don't prompt to confirm overwriting existing file + * -r set DMS release to release N version M, for sbrk cards + * -f Apply offset XXXX (hex) to APPARENT assembly address in leftmost column of listing + * + * Listing and symbol table output can be turned on by *LIST directives in the source, too + * Listing file default extension is .LST + * + * Input files can use strict IBM 1130 Assembler column format, or loose formatting + * with tabs, or any mix on a line-by-line basis. Input files default extension is .ASM. + * + * Strict specification is: + * + * label columns 1 - 5 + * opcode 7 - 10 + * tag 12 + * index 13 + * arguments 15 - 51 + * + * Loose, indicated by presence of ascii tab character(s): + * + * labelopcodeindex and format indicatorsarguments + * + * In both cases, the IBM convention that the arguments section ends with the + * first nonblank applies. This means that ".DC 1, 2, 3" assembles only the 1! + * + * Output file format is that used by the LOAD command in my 1130 + * simulator. Lines are any of the following. All values are in hex: + * + * @addr load address for subsequent words is addr + * Znwords Zero the next "nwords" and increment load address by nwords. + * =addr set IAR register to address addr (a convenience) + * value load value at load address and increment load address + * + * Output file default extension is .OUT or .BIN for binary assemblies + * + * Note: this version does not handle relative assembly, and so doesn't carry + * absolute/relative indication through expression calculation. + * + * Seems to work. Was able to assemble the resident monitor OK. + * >>> Look for "bug here" though, for things to check out. + * + * Notes: + * We assume that the computer on which the assembler runs uses ANSI floating point. + * Also, the assembly of floating point values may be incorrect on non-Intel + * architectures, this needs to be investigated. + * + * org_advanced tells whether * in an expression refers to the address AFTER the + * instruction (1 or 2 words, depending on length). This is the case for opcodes + * but not all directives. + * + * Revision History + * 16Apr02 1.03 Added sector break, relocation flag output + * 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction. + * Added directives for 1130 and 1800 IPL output formats + * Added conditional assembly directives + ********************************************************************************************/ #include #include @@ -132,13 +148,14 @@ #include #include "util_io.h" -// ---------------------------------------------------------------1------------------ -// DEFINITIONS -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * DEFINITIONS + ********************************************************************************************/ -// I have found some IBM source code where @ and ' seem interchangable (likely due to the -// use of 026 keypunches). -// Comment out this define to make @ and ' different in symbol names, keep to make equivalent +/* I have found some IBM source code where @ and ' seem interchangable (likely due to the + * use of 026 keypunches). + * Comment out this define to make @ and ' different in symbol names, keep to make equivalent + */ #if defined(VMS) # include /* to pick up 'unlink' */ @@ -155,9 +172,9 @@ #define FIX_ATS -#define DMSVERSION "V2M12" /* required 5 characters on sector break card col 67-71 */ +#define DMSVERSION "V2M12" /* required 5 characters on sector break card col 67-71 */ -#define DOLLAREXIT "/38" // hmmm, are these really fixed absolutely in all versions? +#define DOLLAREXIT "/38" /* hmmm, are these really fixed absolutely in all versions? */ #define DOLLARDUMP "/3F" #define SYSTEM_TABLE "SYMBOLS.SYS" @@ -166,42 +183,42 @@ #define TRUE 1 #define FALSE 0 -#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV +#define ISTV 0x33 /* magic number from DMS R2V12 monitorm symbol @ISTV */ #define MAXLITERALS 300 #define MAXENTRIES 14 #define LINEFORMAT " %4ld | %s" #define LEFT_MARGIN " |" - // XXXX XXXX XXXX XXXX XXXX XXXX - // org w1 w2 w3 w4 w5 - // XXXX 1111 2222 3333 4444 LLLL | - // 12345678901234567890123456789012 + /* XXXX XXXX XXXX XXXX XXXX XXXX */ + /* org w1 w2 w3 w4 w5 */ + /* XXXX 1111 2222 3333 4444 LLLL | */ + /* 12345678901234567890123456789012 */ typedef enum {ABSOLUTE = 0, RELATIVE = 1, LIBF = 2, CALL = 3} RELOC; -typedef struct tag_symbol { // symbol table entry: - char *name; // name of symbol - int value; // value (absolute) - int pass; // defined during pass # - int defined; // definition state, see #defines below - RELOC relative; // ABSOLUTE = absolute, RELATIVE = relative - struct tag_symbol *next; // next symbol in list - struct tag_xref *xrefs; // cross references +typedef struct tag_symbol { /* symbol table entry: */ + char *name; /* name of symbol */ + int value; /* value (absolute) */ + int pass; /* defined during pass # */ + int defined; /* definition state, see #defines below */ + RELOC relative; /* ABSOLUTE = absolute, RELATIVE = relative */ + struct tag_symbol *next; /* next symbol in list */ + struct tag_xref *xrefs; /* cross references */ } SYMBOL, *PSYMBOL; -#define S_UNDEFINED 0 // values of 'defined' -#define S_PROVISIONAL 1 // usually an expression with forward references -#define S_DEFINED 2 // ordering must be undef < prov < def +#define S_UNDEFINED 0 /* values of 'defined' */ +#define S_PROVISIONAL 1 /* usually an expression with forward references */ +#define S_DEFINED 2 /* ordering must be undef < prov < def */ -typedef struct tag_xref { // cross reference entry - char *fname; // filename - int lno; // line number - BOOL definition; // true = definition, false = reference - struct tag_xref *next; // next reference +typedef struct tag_xref { /* cross reference entry */ + char *fname; /* filename */ + int lno; /* line number */ + BOOL definition; /* true = definition, false = reference */ + struct tag_xref *next; /* next reference */ } XREF, *PXREF; -typedef struct tag_expr { // expression result: absolute or relative +typedef struct tag_expr { /* expression result: absolute or relative */ int value; RELOC relative; } EXPR; @@ -215,28 +232,29 @@ typedef enum {SUBTYPE_INCORE = 0, SUBTYPE_FORDISK = 1, SUBTYPE_ARITH = 2, typedef enum {INTMODE_UNSPECIFIED = 0, INTMODE_MATCHREAL = 0x0080, INTMODE_ONEWORD = 0x0090} INTMODE; typedef enum {REALMODE_UNSPECIFIED = 0, REALMODE_STANDARD = 0x0001, REALMODE_EXTENDED = 0x0002} REALMODE; -#define OP_INDEXED 0x0300 // 1130 opcode modifier bits +#define OP_INDEXED 0x0300 /* 1130 opcode modifier bits */ #define OP_LONG 0x0400 #define OP_INDIRECT 0x0080 -typedef enum {OUTMODE_LOAD, OUTMODE_1130, OUTMODE_1800, OUTMODE_BINARY} OUTMODE; +typedef enum {OUTMODE_LOAD, OUTMODE_BINARY} OUTMODE; #ifdef _WIN32 -# define OUTWRITEMODE "wb" // write outfile in binary mode -# define ENDLINE "\r\n" // explictly write CR/LF +# define OUTWRITEMODE "wb" /* write outfile in binary mode */ +# define ENDLINE "\r\n" /* explictly write CR/LF */ #else -# define OUTWRITEMODE "w" // use native mode +# define OUTWRITEMODE "w" /* use native mode */ # define ENDLINE "\n" #endif -// --------------------------------------------------------------------------------- -// GLOBALS -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * GLOBALS + ********************************************************************************************/ -// command line syntax +/* command line syntax */ char *usestr = -"Usage: asm1130 [-bpsvwxy8] [-o[file]] [-l[file]] [-rN.M] file...\n\n" +"Usage: asm1130 [-bdpsvwxy8] [-o[file]] [-l[file] [-fXXXX]] [-rN.M] file...\n\n" "-b binary (relocatable format) output; default is simulator LOAD format\n" +"-d interpret % and < as ( and ), for assembling DMS sources\n" "-p count passes required; no assembly output is created with this flag" "-s add symbol table to listing\n" "-v verbose mode\n" @@ -244,95 +262,102 @@ char *usestr = "-W same as -w but do not confirm overwriting previous file\n" "-x add cross reference table to listing\n" "-y preload system symbol table SYMBOLS.SYS\n" +"-8 enable IBM 1800 instructions\n" /* (alternately, rename or link executable to asm1800.exe) */ "-o set output file; default is first input file + .out or .bin\n" "-l create listing file; default is first input file + .lst\n" "-r set dms version to VN RM for system SBRK cards\n" -"-8 enable IBM 1800 instructions"; // (alternately, rename or link executable to asm1800.exe) +"-f apply offset XXXX (hex) to APPARENT assembly address listing\n"; -BOOL verbose = FALSE; // verbose mode flag -BOOL tabformat = FALSE; // TRUE if tabs were seen in the file -BOOL enable_1800 = FALSE; // TRUE if 1800 mode is enabled by flag or executable name -int pass; // current assembler pass (1 or 2) -char curfn[256]; // current input file name -char progname[8]; // base name of primary input file -char *outfn = NULL; // output file name -int lno; // current input file line number -BOOL preload = FALSE; // preload system symbol table -BOOL savetable = FALSE; // write system symbol table -BOOL saveprompt = TRUE; // prompt before overwriting -int nerrors = 0; // count of errors -int nwarnings = 0; // count of warnings -FILE *fin = NULL; // current input file -FILE *fout = NULL; // output file stream -OUTMODE outmode = OUTMODE_LOAD; // output file mode -int outcols = 0; // columns written in using card output +BOOL verbose = FALSE; /* verbose mode flag */ +BOOL tabformat = FALSE; /* TRUE if tabs were seen in the file */ +BOOL enable_1800 = FALSE; /* TRUE if 1800 mode is enabled by flag or executable name */ +int listoffset = 0; /* offset to use for listing assembly address column */ +int pass; /* current assembler pass (1 or 2) */ +char curfn[256]; /* current input file name */ +char progname[8]; /* base name of primary input file */ +char *outfn = NULL; /* output file name */ +int lno; /* current input file line number */ +BOOL preload = FALSE; /* preload system symbol table */ +BOOL savetable = FALSE; /* write system symbol table */ +BOOL saveprompt = TRUE; /* prompt before overwriting */ +int nerrors = 0; /* count of errors */ +int nwarnings = 0; /* count of warnings */ +FILE *fin = NULL; /* current input file */ +FILE *fout = NULL; /* output file stream */ +OUTMODE outmode = OUTMODE_LOAD; /* output file mode */ +int outcols = 0; /* columns written in using card output */ int maxiplcols = 80; -char cardid[9]; // characters used for IPL card ID -FILE *flist = NULL; // listing file stream -char *listfn = NULL; // listing filename -BOOL do_list = FALSE; // flag: create listing -BOOL passcount = FALSE; // flag: count passes only -BOOL list_on = TRUE; // listing is currently enabled -BOOL do_xref = FALSE; // cross reference listing -BOOL do_syms = FALSE; // symbol table listing -BOOL ended = FALSE; // end of current file -BOOL hasforward = FALSE; // true if there are any forward references -char listline[350]; // output listing line -BOOL line_error; // already saw an error on current line -RELOC relocate = RELATIVE; // relocatable assembly mode -BOOL assembled = FALSE; // true if any output has been generated -int nwout; // number of words written on current line -int org = 0; // output address (origin) -int org_advanced; // if TRUE, * means instruction addr+(value) during evaluation -int pta = -1; // program transfer address -BOOL cexpr = FALSE; // "C" expression syntax -PSYMBOL symbols = NULL; // the symbol table (linear search) -BOOL check_control = TRUE; // check for control cards -PROGTYPE progtype = PROGTYPE_RELOCATABLE; // program type -INTMODE intmode = INTMODE_UNSPECIFIED; // integer mode -REALMODE realmode = REALMODE_UNSPECIFIED; // real mode -int nintlevels = 0; // # of interrupt levels for ISS -int intlevel_primary = 0; // primary level for ISS and level for ILS -int intlevel_secondary = 0; // secondary level for ISS -int iss_number = 0; // ISS number -PSYMBOL entry[MAXENTRIES]; // entries for subroutines +char cardid[9]; /* characters used for IPL card ID */ +FILE *flist = NULL; /* listing file stream */ +char *listfn = NULL; /* listing filename */ +BOOL do_list = FALSE; /* flag: create listing */ +BOOL passcount = FALSE; /* flag: count passes only */ +BOOL list_on = TRUE; /* listing is currently enabled */ +BOOL do_xref = FALSE; /* cross reference listing */ +BOOL do_syms = FALSE; /* symbol table listing */ +BOOL ended = FALSE; /* end of current file */ +BOOL hasforward = FALSE; /* true if there are any forward references */ +char listline[350]; /* output listing line */ +BOOL line_error; /* already saw an error on current line */ +RELOC relocate = RELATIVE; /* relocatable assembly mode */ +BOOL assembled = FALSE; /* true if any output has been generated */ +int nwout; /* number of words written on current line */ +int org = 0; /* output address (origin) */ +int org_advanced; /* if nonzero, value of * is (instruction address + org_advanced) during evaluation */ +int pta = -1; /* program transfer address */ +BOOL cexpr = FALSE; /* "C" expression syntax (nonstandard, not enabled by default) */ +PSYMBOL symbols = NULL; /* the symbol table (linear search) */ +BOOL check_control = TRUE; /* check for control cards */ +PROGTYPE progtype = PROGTYPE_RELOCATABLE; /* program type */ +INTMODE intmode = INTMODE_UNSPECIFIED; /* integer mode */ +REALMODE realmode = REALMODE_UNSPECIFIED; /* real mode */ +int nintlevels = 0; /* # of interrupt levels for ISS */ +int intlevel_primary = 0; /* primary level for ISS and level for ILS */ +int intlevel_secondary = 0; /* secondary level for ISS */ +int iss_number = 0; /* ISS number */ +PSYMBOL entry[MAXENTRIES]; /* entries for subroutines */ int nentries = 0; int ndefined_files = 0; - -struct lit { // accumulated literals waiting to be output - int value; // constant value - int tagno; // constant symbol tag number (e.g. _L001) - BOOL hex; // constant was expressed in hex - BOOL even; // constant was operand of a double-width instruction (e.g. AD) +struct lit { /* accumulated literals waiting to be output */ + int value; /* constant value */ + int tagno; /* constant symbol tag number (e.g. _L001) */ + BOOL hex; /* constant was expressed in hex */ + BOOL even; /* constant was operand of a double-width instruction (e.g. AD) */ } literal[MAXLITERALS]; int n_literals = 0, lit_tag = 0; -BOOL requires_even_address; // target of current instruction -BOOL dmes_saved; // odd character left over from dmes ending in ' +BOOL requires_even_address; /* target of current instruction */ +BOOL dmes_saved; /* odd character left over from dmes ending in ' */ int dmes_savew; -char opfield[256]; // extracted operand field from source line -char dmsversion[12] = DMSVERSION; // version number for SBRK cards -const char whitespace[] = " \t"; // whitespace +char opfield[256]; /* extracted operand field from source line */ +char dmsversion[12] = DMSVERSION; /* version number for SBRK cards */ +const char whitespace[] = " \t"; /* whitespace */ int ascii_to_ebcdic_table[128] = { -// +/* */ 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, -// +/* */ 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, -// spac ! " # $ % & ' ( ) * + , - . / +/* spac ! " # $ % & ' ( ) * + , - . / */ 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, -// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? +/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, -// @ A B C D E F G H I J K L M N O +/* @ A B C D E F G H I J K L M N O */ 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, -// P Q R S T U V W X Y Z [ \ ] & _ +/* P Q R S T U V W X Y Z [ \ ] & _ */ 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, -// a b c d e f g h i j k l m n o +/* a b c d e f g h i j k l m n o */ 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, -// p q r s t u v w x y z { | } ~ +/* p q r s t u v w x y z { | } ~ */ 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, }; + + /* note that by default, ascii_to_ebcdic_table maps % and < to the EBCDIC codes for these characters. + * If the -d command line switch is used to enable DMS mode, these characters map to ( and ) + * Another way to look at the -d switch is that it interprets % and < as if they had been typed + * on an 026 Commercial keypunch. + */ int ascii_to_1403_table[128] = { /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f */ @@ -349,9 +374,9 @@ int ascii_to_1403_table[128] = #include "../ibm1130_conout.h" /* conout_to_ascii_table */ #include "../ibm1130_prtwheel.h" /* 1132 printer printwheel data */ -// --------------------------------------------------------------------------------- -// PROTOTYPES -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * PROTOTYPES + ********************************************************************************************/ void init (int argc, char **argv); void bail (char *msg); @@ -394,23 +419,23 @@ void bincard_typecard (void); void namecode (unsigned short *words, char *tok); int signextend (int v); -// --------------------------------------------------------------------------------- -// main routine -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * main routine + ********************************************************************************************/ int main (int argc, char **argv) { int i, sawfile = FALSE; - init(argc, argv); // initialize, process flags + init(argc, argv); /* initialize, process flags */ - startpass(1); // first pass, process files + startpass(1); /* first pass, process files */ for (i = 1; i < argc; i++) if (*argv[i] != '-') proc(argv[i]), sawfile = TRUE; - if (! sawfile) // should have seen at least one file + if (! sawfile) /* should have seen at least one file */ bail(usestr); if (passcount) { @@ -418,21 +443,21 @@ int main (int argc, char **argv) return 0; } - startpass(2); // second pass, process files again + startpass(2); /* second pass, process files again */ for (i = 1; i < argc; i++) if (*argv[i] != '-') proc(argv[i]); if (outmode == OUTMODE_LOAD) { - if (pta >= 0) // write start address to the load file - fprintf(fout, "=%04x" ENDLINE, pta & 0xFFFF); + if (pta >= 0) /* write start address to the load file */ + fprintf(fout, "=%04X" ENDLINE, pta & 0xFFFF); } else bincard_endcard(); if (flist) { - if (nerrors || nwarnings) { // summarize (or summarise) + if (nerrors || nwarnings) { /* summarize (or summarise) */ if (nerrors == 0) fprintf(flist, "There %s ", (nwarnings == 1) ? "was" : "were"); else @@ -448,9 +473,9 @@ int main (int argc, char **argv) fprintf(flist, "\nThere were no errors in this assembly\n"); } - if (flist) { // finish the listing + if (flist) { /* finish the listing */ if (pta >= 0) - fprintf(flist, "\nProgram transfer address = %04x\n", pta); + fprintf(flist, "\nProgram transfer address = %04X\n", pta); if (do_xref) xref_list(); @@ -461,27 +486,27 @@ int main (int argc, char **argv) if (savetable) save_symbols(); - return 0; // all done + return 0; /* all done */ } -// --------------------------------------------------------------------------------- -// init - initialize assembler, process command line flags -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * init - initialize assembler, process command line flags + ********************************************************************************************/ void init (int argc, char **argv) { int i; - enable_1800 = strstr(argv[0], "1800") != NULL; // if "1800" appears in the executable name, enable 1800 extensions + enable_1800 = strstr(argv[0], "1800") != NULL; /* if "1800" appears in the executable name, enable 1800 extensions */ - for (i = 1; i < argc; i++) // process command line switches + for (i = 1; i < argc; i++) /* process command line switches */ if (*argv[i] == '-') flag(argv[i]+1); } -// --------------------------------------------------------------------------------- -// flag - process one command line switch -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * flag - process one command line switch + ********************************************************************************************/ void flag (char *arg) { @@ -489,7 +514,7 @@ void flag (char *arg) while (*arg) { switch (*arg++) { - case 'o': // output (load) file name + case 'o': /* output (load) file name */ if (! *arg) bail(usestr); outfn = arg; @@ -499,26 +524,26 @@ void flag (char *arg) passcount = TRUE; break; - case 'v': // mumble while running + case 'v': /* mumble while running */ verbose = TRUE; break; - case 'x': // print cross reference table + case 'x': /* print cross reference table */ do_xref = TRUE; break; - case 's': // print symbol table + case 's': /* print symbol table */ do_syms = TRUE; break; - case 'l': // listing file name + case 'l': /* listing file name */ listfn = (* arg) ? arg : NULL; do_list = TRUE; return; case 'W': saveprompt = FALSE; - // fall through + /* fall through */ case 'w': savetable = TRUE; break; @@ -541,6 +566,20 @@ void flag (char *arg) sprintf(dmsversion, "V%01.1dM%02.2d", major, minor); return; + case 'f': + if (sscanf(arg, "%x", &listoffset) != 1) + bail(usestr); + + if (listoffset & 0x8000) /* sign extend from 16 to (int) bits */ + listoffset |= ~0x7FFF; + + return; + + case 'd': /* DMS source code mode: treat % and < as ( and ) */ + ascii_to_ebcdic_table['%'] = ascii_to_ebcdic_table['(']; /* an alternate intpretation of -d is that it interprets */ + ascii_to_ebcdic_table['<'] = ascii_to_ebcdic_table[')']; /* % and < as if from an 026 Commercial keypunch */ + break; + default: bail(usestr); break; @@ -548,9 +587,9 @@ void flag (char *arg) } } -// --------------------------------------------------------------------------------- -// bail - print error message on stderr (only) and exit -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * bail - print error message on stderr (only) and exit + ********************************************************************************************/ void bail (char *msg) { @@ -558,36 +597,36 @@ void bail (char *msg) exit(1); } -// --------------------------------------------------------------------------------- -// errprintf - print error message to stderr -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * errprintf - print error message to stderr + ********************************************************************************************/ void errprintf (char *fmt, ...) { va_list args; - va_start(args, fmt); // get pointer to argument list + va_start(args, fmt); /* get pointer to argument list */ - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) + vfprintf(stderr, fmt, args); /* write errors to terminal (stderr) */ va_end(args); } -// --------------------------------------------------------------------------------- -// asm_error - report an error to listing file and to user's console -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * asm_error - report an error to listing file and to user's console + ********************************************************************************************/ void asm_error (char *fmt, ...) { va_list args; - if (pass == 1) // only print on pass 2 + if (pass == 1) /* only print on pass 2 */ return; - va_start(args, fmt); // get pointer to argument list + va_start(args, fmt); /* get pointer to argument list */ fprintf(stderr, "E: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) + vfprintf(stderr, fmt, args); /* write errors to terminal (stderr) */ putc('\n', stderr); if (flist != NULL && list_on) { @@ -595,7 +634,7 @@ void asm_error (char *fmt, ...) line_error = TRUE; fprintf(flist, "**** Error: "); - vfprintf(flist, fmt, args); // write errors to listing file + vfprintf(flist, fmt, args); /* write errors to listing file */ putc('\n', flist); } @@ -603,21 +642,21 @@ void asm_error (char *fmt, ...) va_end(args); } -// --------------------------------------------------------------------------------- -// asm_warning - same but warnings are not counted -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * asm_warning - same but warnings are not counted + ********************************************************************************************/ void asm_warning (char *fmt, ...) { va_list args; - if (pass == 1) // only print on pass 2 + if (pass == 1) /* only print on pass 2 */ return; - va_start(args, fmt); // get pointer to argument list + va_start(args, fmt); /* get pointer to argument list */ fprintf(stderr, "W: %s (%d): ", curfn, lno); - vfprintf(stderr, fmt, args); // write errors to terminal (stderr) + vfprintf(stderr, fmt, args); /* write errors to terminal (stderr) */ putc('\n', stderr); if (flist != NULL && list_on) { @@ -625,16 +664,16 @@ void asm_warning (char *fmt, ...) line_error = TRUE; fprintf(flist, "**** Warning: "); - vfprintf(flist, fmt, args); // write errors to listing file + vfprintf(flist, fmt, args); /* write errors to listing file */ putc('\n', flist); } nwarnings++; } -// --------------------------------------------------------------------------------- -// sym_list - print the symbol table -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * sym_list - print the symbol table + ********************************************************************************************/ void sym_list (void) { @@ -656,7 +695,7 @@ void sym_list (void) fprintf(flist, "%-6s ", s->name); if (s->defined == S_DEFINED) - fprintf(flist, "%04x%s", s->value & 0xFFFF, s->relative ? "R" : " "); + fprintf(flist, "%04X%s", s->value & 0xFFFF, s->relative ? "R" : " "); else fprintf(flist, "UUUU "); @@ -665,9 +704,9 @@ void sym_list (void) fprintf(flist, "\n"); } -// --------------------------------------------------------------------------------- -// passreport - report # of passes required for assembly on the 1130 -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * passreport - report # of passes required for assembly on the 1130 + ********************************************************************************************/ void passreport (void) { @@ -686,9 +725,9 @@ void passreport (void) printf("There are no forward references. Only one pass is required.\n"); } -// --------------------------------------------------------------------------------- -// xref_list - print the cross-reference table -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * xref_list - print the cross-reference table + ********************************************************************************************/ void xref_list (void) { @@ -704,10 +743,10 @@ void xref_list (void) if (symbols == NULL || flist == NULL) return; - fprintf(flist, "Name Val Defd Referenced\n"); + fprintf(flist, "Name Val Defd Referenced\n"); for (s = symbols; s != NULL; s = s->next) { - fprintf(flist, "%-5s %04x%s", s->name, s->value & 0xFFFF, s->relative ? "R" : " "); + fprintf(flist, "%-5s %04X%s", s->name, s->value & 0xFFFF, s->relative ? "R" : " "); for (x = s->xrefs; x != NULL; x = x->next) if (x->definition) @@ -733,30 +772,35 @@ void xref_list (void) } } -// --------------------------------------------------------------------------------- -// listhdr - print a banner header in the listing file. Since it's not paginated -// at this time, this is not used often. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * listhdr - print a banner header in the listing file. Since it's not paginated + * at this time, this is not used often. + ********************************************************************************************/ void listhdr (void) { time_t t; time(&t); - fprintf(flist, "%s -- %s -- %s\n", VERSION, dmsversion, ctime(&t)); + fprintf(flist, "%s -- %s -- ", VERSION, dmsversion); + + if (listoffset != 0) /* be sure to note difference in the listing */ + fprintf(flist, "LIST OFFSET %04X -- ", listoffset & 0xFFFF); + + fprintf(flist, "%s\n", ctime(&t)); } -// --------------------------------------------------------------------------------- -// astring - allocate a copy of a string -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * astring - allocate a copy of a string + ********************************************************************************************/ char *astring (char *str) { static char *s = NULL; if (s != NULL) - if (strcmp(s, str) == 0) // if same as immediately previous allocation - return s; // return same pointer (why did I do this?) + if (strcmp(s, str) == 0) /* if same as immediately previous allocation */ + return s; /* return same pointer (why did I do this?) */ if ((s = malloc(strlen(str)+1)) == NULL) bail("out of memory"); @@ -765,10 +809,10 @@ char *astring (char *str) return s; } -// --------------------------------------------------------------------------------- -// lookup_symbol - get pointer to a symbol. -// If define is TRUE, creates and marks 'undefined' if not previously defined. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * lookup_symbol - get pointer to a symbol. + * If define is TRUE, creates and marks 'undefined' if not previously defined. + ********************************************************************************************/ PSYMBOL lookup_symbol (char *name, BOOL define) { @@ -776,7 +820,7 @@ PSYMBOL lookup_symbol (char *name, BOOL define) int c; char *at; - if (strlen(name) > 5) { // (sigh) + if (strlen(name) > 5) { /* (sigh) */ asm_error("Symbol '%s' is longer than 5 letters", name); name[5] = '\0'; } @@ -785,7 +829,7 @@ PSYMBOL lookup_symbol (char *name, BOOL define) while ((at = strchr(name, '@')) != NULL) *at = '\''; #endif - // search sorted list of symbols + /* search sorted list of symbols */ for (s = symbols; s != NULL; prv = s, s = s->next) { c = strcmpi(s->name, name); if (c == 0) @@ -795,41 +839,41 @@ PSYMBOL lookup_symbol (char *name, BOOL define) } if (! define) - return NULL; // not found + return NULL; /* not found */ if ((n = malloc(sizeof(SYMBOL))) == NULL) bail("out of memory"); - n->name = astring(name); // symbol was undefined -- add it now + n->name = astring(name); /* symbol was undefined -- add it now */ n->value = 0; n->defined = FALSE; n->xrefs = NULL; n->defined = FALSE; - n->next = s; // link in alpha order + n->next = s; /* link in alpha order */ - if (prv == NULL) // we stopped before first item in list + if (prv == NULL) /* we stopped before first item in list */ symbols = n; else - prv->next = n; // insert after item before place we stopped + prv->next = n; /* insert after item before place we stopped */ return n; } -// --------------------------------------------------------------------------------- -// add_xref - add a cross reference entry to a symbol -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * add_xref - add a cross reference entry to a symbol + ********************************************************************************************/ void add_xref (PSYMBOL s, BOOL definition) { PXREF x, prv = NULL, n; - if (pass == 1 || ! do_xref) // define only during 2nd pass and only if listing was requested + if (pass == 1 || ! do_xref) /* define only during 2nd pass and only if listing was requested */ return; for (x = s->xrefs; x != NULL; prv = x, x = x->next) if (strcmpi(x->fname, curfn) == 0 && x->lno == lno) - return; // ignore multiple refs on same line + return; /* ignore multiple refs on same line */ if ((n = malloc(sizeof(XREF))) == NULL) bail("out of memory"); @@ -838,7 +882,7 @@ void add_xref (PSYMBOL s, BOOL definition) n->lno = lno; n->definition = definition; - n->next = x; // link at end of existing list + n->next = x; /* link at end of existing list */ if (prv == NULL) s->xrefs = n; @@ -846,30 +890,30 @@ void add_xref (PSYMBOL s, BOOL definition) prv->next = n; } -// --------------------------------------------------------------------------------- -// get_symbol - get a symbol value, defining if necessary -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * get_symbol - get a symbol value, defining if necessary + ********************************************************************************************/ int get_symbol (char *name) { PSYMBOL s; - s = lookup_symbol(name, TRUE); // lookup, define if necessary + s = lookup_symbol(name, TRUE); /* lookup, define if necessary */ - if (pass == 2) // should be defined by now + if (pass == 2) /* should be defined by now */ if (! s->defined) asm_error("Symbol '%s' is undefined", name); - add_xref(s, FALSE); // note the reference + add_xref(s, FALSE); /* note the reference */ return s->value; } -// --------------------------------------------------------------------------------- -// set_symbol - set a symbol value. Known = TRUE means we really know the value; -// FALSE means we're calculating it with forward referenced values or something like -// that. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * set_symbol - set a symbol value. Known = TRUE means we really know the value; + * FALSE means we're calculating it with forward referenced values or something like + * that. + ********************************************************************************************/ void set_symbol (char *name, int value, int known, RELOC relative) { @@ -888,7 +932,7 @@ void set_symbol (char *name, int value, int known, RELOC relative) s = lookup_symbol(name, TRUE); - if (s->defined == S_DEFINED) // once defined, it should not change + if (s->defined == S_DEFINED) /* once defined, it should not change */ if (s->value != value) asm_error("Symbol '%s' %s", name, (s->pass == pass) ? "is multiply defined" : "changed between passes"); @@ -900,12 +944,12 @@ void set_symbol (char *name, int value, int known, RELOC relative) if (! known) hasforward = TRUE; - add_xref(s, TRUE); // record the place of definition + add_xref(s, TRUE); /* record the place of definition */ } -// --------------------------------------------------------------------------------- -// skipbl - return pointer to first nonblank character in string s -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * skipbl - return pointer to first nonblank character in string s + ********************************************************************************************/ char *skipbl (char *s) { @@ -915,45 +959,46 @@ char *skipbl (char *s) return s; } -// --------------------------------------------------------------------------------- -// gtok - extracts a whitespace-delimited token from the string pointed to by *pc; -// stores the token into the buffer tok and returns pointer to same. Returns NULL -// when there are no tokens. Best to call repeatedly with a pointer to the source -// buffer, e.g. -// char *pbuf = buf; -// while (gtok(&pbuf, token) != NULL) ... -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * gtok - extracts a whitespace-delimited token from the string pointed to by *pc; + * stores the token into the buffer tok and returns pointer to same. Returns NULL + * when there are no tokens. Best to call repeatedly with a pointer to the source + * buffer, e.g. + * char *pbuf = buf; + * while (gtok(&pbuf, token) != NULL) ... + ********************************************************************************************/ char * gtok (char **pc, char *tok) { char *s = *pc, *otok = tok; - while (*s && *s <= ' ') // skip blanks + while (*s && *s <= ' ') /* skip blanks */ s++; - if (! *s) { // no tokens to be found + if (! *s) { /* no tokens to be found */ *tok = '\0'; *pc = s; return NULL; } - while (*s > ' ') // save nonblanks into 'tok' + while (*s > ' ') /* save nonblanks into 'tok' */ *tok++ = *s++; - *tok = '\0'; // terminate - *pc = s; // adjust caller's pointer + *tok = '\0'; /* terminate */ + *pc = s; /* adjust caller's pointer */ - return otok; // return pointer to token + return otok; /* return pointer to token */ } -// listing format: -// -// ADDR CODE SOURCE -// 0000 0000 0000 0000 0000 | XXXXXXXXXXXXXXXXX +/* listing format: + * + * ADDR CODE SOURCE + * 0000 0000 0000 0000 0000 | XXXXXXXXXXXXXXXXX + */ -// --------------------------------------------------------------------------------- -// trim - remove trailing whitespace from string s -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * trim - remove trailing whitespace from string s + ********************************************************************************************/ char *trim (char *s) { @@ -967,11 +1012,11 @@ char *trim (char *s) return os; } -// --------------------------------------------------------------------------------- -// listout - emit current constructed output listing line held in "listline" and -// if "reset" is true, prepare listline for second and subsequent listing lines -// for a given input statement. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * listout - emit current constructed output listing line held in "listline" and + * if "reset" is true, prepare listline for second and subsequent listing lines + * for a given input statement. + ********************************************************************************************/ void listout (BOOL reset) { @@ -984,21 +1029,21 @@ void listout (BOOL reset) } } -// --------------------------------------------------------------------------------- -// storew - store a word in the output medium (hex or binary file). Most of the time -// writew is used. Advances the origin! -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * storew - store a word in the output medium (hex or binary file). Most of the time + * writew is used. Advances the origin! + ********************************************************************************************/ void storew (int word, RELOC relative) { - if (pass == 2) { // save in output (load) file. + if (pass == 2) { /* save in output (load) file. */ switch (outmode) { case OUTMODE_BINARY: bincard_writew(word, relative); break; case OUTMODE_LOAD: - fprintf(fout, " %04x%s" ENDLINE, word & 0xFFFF, + fprintf(fout, " %04X%s" ENDLINE, word & 0xFFFF, (relative == ABSOLUTE) ? "" : (relative == RELATIVE) ? "R" : (relative == LIBF) ? "L" : (relative == CALL) ? "$" : "?"); break; @@ -1011,12 +1056,12 @@ void storew (int word, RELOC relative) if (relative != LIBF) org++; - assembled = TRUE; // remember that we wrote something + assembled = TRUE; /* remember that we wrote something */ } -// --------------------------------------------------------------------------------- -// setw - store a word value in the current listing output line in position 'pos'. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * setw - store a word value in the current listing output line in position 'pos'. + ********************************************************************************************/ void setw (int pos, int word, RELOC relative) { @@ -1026,7 +1071,7 @@ void setw (int pos, int word, RELOC relative) if (flist == NULL || ! list_on) return; - sprintf(tok, "%04x", word & 0xFFFF); + sprintf(tok, "%04X", word & 0xFFFF); for (i = 0, p = listline + 5*pos; i < 4; i++) p[i] = tok[i]; @@ -1037,38 +1082,38 @@ void setw (int pos, int word, RELOC relative) p[i] = '*'; } -// --------------------------------------------------------------------------------- -// writew - emit an assembled word value. Words are also displayed in the listing file. -// if relative is true, a relocation entry should be recorded. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * writew - emit an assembled word value. Words are also displayed in the listing file. + * if relative is true, a relocation entry should be recorded. + ********************************************************************************************/ void writew (int word, RELOC relative) -{ // first, the listing stuff... - if (nwout == 0) { // on first output word, display address in column 0 - setw(0, org, FALSE); +{ /* first, the listing stuff... */ + if (nwout == 0) { /* on first output word, display address in column 0 */ + setw(0, org+listoffset, FALSE); } - else if (nwout >= 4) { // if 4 words have already been written, start new line + else if (nwout >= 4) { /* if 4 words have already been written, start new line */ listout(TRUE); nwout = 0; } nwout++; - setw(nwout, word, relative); // display word in the listing line + setw(nwout, word, relative); /* display word in the listing line */ - storew(word, relative); // write it to the output medium + storew(word, relative); /* write it to the output medium */ } -// --------------------------------------------------------------------------------- -// setorg - take note of new load address -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * setorg - take note of new load address + ********************************************************************************************/ void setorg (int neworg) { if (pass == 2) { - setw(0, neworg, FALSE); // display in listing file in column 0 + setw(0, neworg+listoffset, FALSE); /* display in listing file in column 0 */ - if (outmode == OUTMODE_LOAD) { // write new load address to the output file - fprintf(fout, "@%04x%s" ENDLINE, neworg & 0xFFFF, relocate ? "R" : ""); + if (outmode == OUTMODE_LOAD) { /* write new load address to the output file */ + fprintf(fout, "@%04X%s" ENDLINE, neworg & 0xFFFF, relocate ? "R" : ""); } else { bincard_setorg(neworg); @@ -1078,9 +1123,9 @@ void setorg (int neworg) org = neworg; } -// --------------------------------------------------------------------------------- -// org_even - force load address to an even address -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * org_even - force load address to an even address + ********************************************************************************************/ void org_even (void) { @@ -1088,38 +1133,38 @@ void org_even (void) setorg(org+1); } -// --------------------------------------------------------------------------------- -// tabtok - get the token in tab-delimited column number i, from source string c, -// saving in string 'tok'. If save is nonnull, we copy the entire remainder of -// the input string in buffer 'save' (in contrast to 'tok' which gets only the -// first whitespace delimited token). -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * tabtok - get the token in tab-delimited column number i, from source string c, + * saving in string 'tok'. If save is nonnull, we copy the entire remainder of + * the input string in buffer 'save' (in contrast to 'tok' which gets only the + * first whitespace delimited token). + ********************************************************************************************/ void tabtok (char *c, char *tok, int i, char *save) { *tok = '\0'; - while (--i >= 0) { // skip to i'th tab-delimited field + while (--i >= 0) { /* skip to i'th tab-delimited field */ if ((c = strchr(c, '\t')) == NULL) { - if (save) // was none + if (save) /* was none */ *save = '\0'; return; } c++; } - while (*c == ' ') // skip leading blanks + while (*c == ' ') /* skip leading blanks */ c++; - if (save != NULL) // save copy of entire remainder + if (save != NULL) /* save copy of entire remainder */ strcpy(save, c); - while (*c > ' ') { // take up to any whitespace - if (*c == '(') { // if we start with a paren, take all up to closing paren including spaces + while (*c > ' ') { /* take up to any whitespace */ + if (*c == '(') { /* if we start with a paren, take all up to closing paren including spaces */ while (*c && *c != ')') *tok++ = *c++; } - else if (*c == '.') { // period means literal character following + else if (*c == '.') { /* period means literal character following */ *tok++ = *c++; if (*c) *tok++ = *c++; @@ -1131,18 +1176,18 @@ void tabtok (char *c, char *tok, int i, char *save) *tok = '\0'; } -// --------------------------------------------------------------------------------- -// coltok - extract a token from string c, saving to buffer tok, by examining -// columns ifrom through ito only. If save is nonnull, the entire remainder -// of the input from ifrom to the end is saved there. In this routine -// if condense is true, we save all nonwhite characters in the column range; -// not the usual thing. This helps us coalesce the format, tag, & index things -// nto one string for the simple minded parser. If condense is FALSE, we terminate -// on the first nonblank, except that if we start with a (, we take up to ) and -// then terminate on a space. -// -// ifrom and ito on entry are column numbers, not indices; we change that right away -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * coltok - extract a token from string c, saving to buffer tok, by examining + * columns ifrom through ito only. If save is nonnull, the entire remainder + * of the input from ifrom to the end is saved there. In this routine + * if condense is true, we save all nonwhite characters in the column range; + * not the usual thing. This helps us coalesce the format, tag, & index things + * nto one string for the simple minded parser. If condense is FALSE, we terminate + * on the first nonblank, except that if we start with a (, we take up to ) and + * then terminate on a space. + * + * ifrom and ito on entry are column numbers, not indices; we change that right away + ********************************************************************************************/ void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) { @@ -1153,7 +1198,7 @@ void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) ito--; for (i = 0; i < ifrom; i++) { - if (c[i] == '\0') { // line ended before this column + if (c[i] == '\0') { /* line ended before this column */ *tok = '\0'; if (save) *save = '\0'; @@ -1161,29 +1206,29 @@ void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) } } - if (save) // save from ifrom on + if (save) /* save from ifrom on */ strcpy(save, c+i); if (condense) { - for (; i <= ito; i++) { // save only nonwhite characters + for (; i <= ito; i++) { /* save only nonwhite characters */ if (c[i] > ' ') *tok++ = c[i]; } } else { - if (c[i] == ' ' && save != NULL)// if it starts with a space, it's empty + if (c[i] == ' ' && save != NULL)/* if it starts with a space, it's empty */ *save = '\0'; - while (i <= ito) { // take up to any whitespace + while (i <= ito) { /* take up to any whitespace */ if (c[i] <= ' ') break; - else if (c[i] == '(') { // starts with paren? take to close paren + else if (c[i] == '(') { /* starts with paren? take to close paren */ while (i <= ito && c[i]) { if ((*tok++ = c[i++]) == ')') break; } } - else if (c[i] == '.') { // period means literal character following + else if (c[i] == '.') { /* period means literal character following */ *tok++ = c[i++]; if (i <= ito && c[i]) *tok++ = c[i++]; @@ -1197,30 +1242,30 @@ void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save) trim(otok); } -// --------------------------------------------------------------------------------- -// opcode table -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * opcode table + ********************************************************************************************/ -// modifiers for the opcode definition table: +/* modifiers for the opcode definition table: */ -#define L "L" // long -#define X "X" // absolute displacement -#define I "I" // indirect -#define IDX "0123" // indexed (some LDX commands in the DMS source say LDX L0, so accept 0 -#define E "E" // even address +#define L "L" /* long */ +#define X "X" /* absolute displacement */ +#define I "I" /* indirect */ +#define IDX "0123" /* indexed (some LDX commands in the DMS source say LDX L0, so accept 0 */ +#define E "E" /* even address */ #define NONE "" -#define ALL L X I IDX // hope non-Microsoft C accepts and concatenates strings like this +#define ALL L X I IDX /* hope non-Microsoft C accepts and concatenates strings like this */ #define ANY "\xFF" #define NUMS "0123456789" -#define IS_DBL 0x0001 // double word operand implies even address -#define IS_ABS 0x0002 // always uses absolute addressing mode (implied X) -#define NO_IDX 0x0004 // even with 1 or 2 modifier, this is not really indexed (for STX/LDX) -#define NO_ARGS 0x0008 // statement takes no arguments -#define IS_1800 0x0010 // 1800-only directive or instruction, flagged if 1800 mode is not enabled -#define TRAP 0x1000 // debug this instruction +#define IS_DBL 0x0001 /* double word operand implies even address */ +#define IS_ABS 0x0002 /* always uses absolute addressing mode (implied X) */ +#define NO_IDX 0x0004 /* even with 1 or 2 modifier, this is not really indexed (for STX/LDX) */ +#define NO_ARGS 0x0008 /* statement takes no arguments */ +#define IS_1800 0x0010 /* 1800-only directive or instruction, flagged if 1800 mode is not enabled */ +#define TRAP 0x1000 /* debug this instruction */ -struct tag_op { // OPCODE TABLE +struct tag_op { /* OPCODE TABLE */ char *mnem; int opcode; void (*handler)(struct tag_op *op, char *label, char *mods, char *arg); @@ -1228,7 +1273,7 @@ struct tag_op { // OPCODE TABLE char *mods_implied; int flags; }; - // special opcode handlers + /* special opcode handlers */ void std_op (struct tag_op *op, char *label, char *mods, char *arg); void b_op (struct tag_op *op, char *label, char *mods, char *arg); void bsc_op (struct tag_op *op, char *label, char *mods, char *arg); @@ -1278,16 +1323,16 @@ void x_trap (struct tag_op *op, char *label, char *mods, char *arg); void x_xflc (struct tag_op *op, char *label, char *mods, char *arg); struct tag_op ops[] = { - ".OPT", 0, x_opt, NONE, NONE, 0, // non-IBM extensions - "TRAP", 0, x_trap, NONE, NONE, 0, // assembler breakpoint trap - ".CES", 0, x_ces, NONE, NONE, 0, // lets us specify simulated console entry switch values for startup + ".OPT", 0, x_opt, NONE, NONE, 0, /* non-IBM extensions */ + "TRAP", 0, x_trap, NONE, NONE, 0, /* assembler breakpoint trap */ + ".CES", 0, x_ces, NONE, NONE, 0, /* lets us specify simulated console entry switch values for startup */ "ABS", 0, x_abs, NONE, NONE, 0, - "BES", 0, x_bes, E, NONE, 0, // standard pseudo-ops + "BES", 0, x_bes, E, NONE, 0, /* standard pseudo-ops */ "BSS", 0, x_bss, E, NONE, 0, "DC", 0, x_dc, NONE, NONE, 0, "DEC", 0, x_dec, E, E, IS_DBL, - "DECS", 0, x_decs, E, E, IS_DBL, // this is an IBM 1800 directive + "DECS", 0, x_decs, E, E, IS_DBL, /* this is an IBM 1800 directive */ "DMES", 0, x_dmes, ANY, NONE, 0, "DN", 0, x_dn, NONE, NONE, 0, "DSA", 0, x_dsa, NONE, NONE, 0, @@ -1298,7 +1343,7 @@ struct tag_op ops[] = { "ENT", 0, x_ent, NONE, NONE, 0, "EPR", 0, x_epr, NONE, NONE, 0, "EQU", 0, x_equ, NONE, NONE, 0, - "EXIT", 0, x_exit, NONE, NONE, 0, // alias for call $exit since we don't have macros yet + "EXIT", 0, x_exit, NONE, NONE, 0, /* alias for call $exit since we don't have macros yet */ "FILE", 0, x_file, NONE, NONE, 0, "HDNG", 0, x_hdng, ANY, NONE, 0, "ILS", 0, x_ils, NUMS, NONE, 0, @@ -1314,13 +1359,13 @@ struct tag_op ops[] = { "SPR", 0, x_spr, NONE, NONE, 0, "XFLC", 0, x_xflc, NONE, NONE, 0, - "A", 0x8000, std_op, ALL, NONE, 0, // standard addressing ops + "A", 0x8000, std_op, ALL, NONE, 0, /* standard addressing ops */ "AD", 0x8800, std_op, ALL, NONE, IS_DBL, "AND", 0xE000, std_op, ALL, NONE, 0, "BSI", 0x4000, bsi_op, ALL, NONE, 0, - "CALL", 0x4000, x_call, ALL, L, 0, // alias for BSI L, or external call - "CMP", 0xB000, std_op, ALL, NONE, IS_1800, // this is an IBM 1800-only instruction - "DCM", 0xB800, std_op, ALL, NONE, IS_1800, // this is an IBM 1800-only instruction + "CALL", 0x4000, x_call, ALL, L, 0, /* alias for BSI L, or external call */ + "CMP", 0xB000, std_op, ALL, NONE, IS_1800, /* this is an IBM 1800-only instruction */ + "DCM", 0xB800, std_op, ALL, NONE, IS_1800, /* this is an IBM 1800-only instruction */ "D" , 0xA800, std_op, ALL, NONE, 0, "EOR", 0xF000, std_op, ALL, NONE, 0, "LD", 0xC000, std_op, ALL, NONE, 0, @@ -1329,7 +1374,7 @@ struct tag_op ops[] = { "LDX", 0x6000, std_op, ALL, NONE, IS_ABS|NO_IDX, "M", 0xA000, std_op, ALL, NONE, 0, "MDX", 0x7000, mdx_op, ALL, NONE, 0, - "MDM", 0x7000, mdx_op, L, L, 0, // like MDX L + "MDM", 0x7000, mdx_op, L, L, 0, /* like MDX L */ "NOP", 0x1000, std_op, NONE, NONE, NO_ARGS, "OR", 0xE800, std_op, ALL, NONE, 0, "S", 0x9000, std_op, ALL, NONE, 0, @@ -1339,25 +1384,25 @@ struct tag_op ops[] = { "STS", 0x2800, std_op, ALL, NONE, 0, "STX", 0x6800, std_op, ALL, NONE, NO_IDX, "WAIT", 0x3000, std_op, NONE, NONE, IS_ABS, - "XCH", 0x18D0, std_op, NONE, NONE, 0, // same as RTE 16, 18C0 + 10 + "XCH", 0x18D0, std_op, NONE, NONE, 0, /* same as RTE 16, 18C0 + 10 */ "XIO", 0x0800, std_op, ALL, NONE, IS_DBL, - "BSC", 0x4800, bsc_op, ALL, NONE, 0, // branch family - "BOSC", 0x4840, bsc_op, ALL, NONE, 0, // is BOSC always long form? No. - "SKP", 0x4800, bsc_op, NONE, NONE, 0, // alias for BSC one word version + "BSC", 0x4800, bsc_op, ALL, NONE, 0, /* branch family */ + "BOSC", 0x4840, bsc_op, ALL, NONE, 0, /* is BOSC always long form? No. */ + "SKP", 0x4800, bsc_op, NONE, NONE, 0, /* alias for BSC one word version */ - "B", 0x4800, b_op, ALL, NONE, 0, // alias for MDX or BSC L - "BC", 0x4802, std_op, ALL, L, 0, // alias for BSC L - "BN", 0x4828, std_op, ALL, L, 0, // alias for BSC L - "BNN", 0x4810, std_op, ALL, L, 0, // alias for BSC L - "BNP", 0x4808, std_op, ALL, L, 0, // alias for BSC L - "BNZ", 0x4820, std_op, ALL, L, 0, // alias for BSC L - "BO", 0x4801, std_op, ALL, L, 0, // alias for BSC L - "BOD", 0x4840, std_op, ALL, L, 0, // alias for BSC L - "BP", 0x4830, std_op, ALL, L, 0, // alias for BSC L - "BZ", 0x4818, std_op, ALL, L, 0, // alias for BSC L + "B", 0x4800, b_op, ALL, NONE, 0, /* alias for MDX or BSC L */ + "BC", 0x4802, std_op, ALL, L, 0, /* alias for BSC L */ + "BN", 0x4828, std_op, ALL, L, 0, /* alias for BSC L */ + "BNN", 0x4810, std_op, ALL, L, 0, /* alias for BSC L */ + "BNP", 0x4808, std_op, ALL, L, 0, /* alias for BSC L */ + "BNZ", 0x4820, std_op, ALL, L, 0, /* alias for BSC L */ + "BO", 0x4801, std_op, ALL, L, 0, /* alias for BSC L */ + "BOD", 0x4804, std_op, ALL, L, 0, /* alias for BSC L */ + "BP", 0x4830, std_op, ALL, L, 0, /* alias for BSC L */ + "BZ", 0x4818, std_op, ALL, L, 0, /* alias for BSC L */ - "RTE", 0x18C0, shf_op, IDX X, X, 0, // shift family + "RTE", 0x18C0, shf_op, IDX X, X, 0, /* shift family */ "SLA", 0x1000, shf_op, IDX X, X, 0, "SLC", 0x10C0, shf_op, IDX X, X, 0, "SLCA", 0x1040, shf_op, IDX X, X, 0, @@ -1365,19 +1410,19 @@ struct tag_op ops[] = { "SRA", 0x1800, shf_op, IDX X, X, 0, "SRT", 0x1880, shf_op, IDX X, X, 0, - "AIF", 0, x_aif, NONE, NONE, 0, // assemble if - "AIFB", 0, x_aifb, NONE, NONE, 0, // assemble if - "AGO", 0, x_ago, NONE, NONE, 0, // assemble goto - "AGOB", 0, x_agob, NONE, NONE, 0, // assemble goto - "ANOP", 0, x_anop, NONE, NONE, 0, // assemble target + "AIF", 0, x_aif, NONE, NONE, 0, /* assemble if */ + "AIFB", 0, x_aifb, NONE, NONE, 0, /* assemble if */ + "AGO", 0, x_ago, NONE, NONE, 0, /* assemble goto */ + "AGOB", 0, x_agob, NONE, NONE, 0, /* assemble goto */ + "ANOP", 0, x_anop, NONE, NONE, 0, /* assemble target */ - NULL // end of table + NULL /* end of table */ }; -// --------------------------------------------------------------------------------- -// addextn - apply file extension 'extn' to filename 'fname' and put result in 'outbuf' -// if outbuf is NULL, we allocate a buffer -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * addextn - apply file extension 'extn' to filename 'fname' and put result in 'outbuf' + * if outbuf is NULL, we allocate a buffer + ********************************************************************************************/ char *addextn (char *fname, char *extn, char *outbuf) { @@ -1385,7 +1430,7 @@ char *addextn (char *fname, char *extn, char *outbuf) buf = (outbuf == NULL) ? line : outbuf; - strcpy(buf, fname); // create listfn from first source filename (e.g. xxx.lst); + strcpy(buf, fname); /* create listfn from first source filename (e.g. xxx.lst); */ if ((c = strrchr(buf, '\\')) == NULL) if ((c = strrchr(buf, '/')) == NULL) if ((c = strrchr(buf, ':')) == NULL) @@ -1399,13 +1444,13 @@ char *addextn (char *fname, char *extn, char *outbuf) return (outbuf == NULL) ? astring(line) : outbuf; } -// --------------------------------------------------------------------------------- -// controlcard - examine an assembler control card (* in column 1) -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * controlcard - examine an assembler control card (* in column 1) + ********************************************************************************************/ BOOL controlcard (char *line) { - if (strnicmp(line, "*LIST", 5) == 0) { // turn on listing file even if not specified on command line + if (strnicmp(line, "*LIST", 5) == 0) { /* turn on listing file even if not specified on command line */ do_list = list_on = TRUE; return TRUE; } @@ -1434,9 +1479,9 @@ BOOL controlcard (char *line) return FALSE; } -// --------------------------------------------------------------------------------- -// stuff - insert characters into a line -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * stuff - insert characters into a line + ********************************************************************************************/ void stuff (char *buf, char *tok, int maxchars) { @@ -1449,9 +1494,9 @@ void stuff (char *buf, char *tok, int maxchars) } } -// --------------------------------------------------------------------------------- -// format_line - construct a source code input line from components -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * format_line - construct a source code input line from components + ********************************************************************************************/ void format_line (char *buf, char *label, char *op, char *mods, char *args, char *remarks) { @@ -1472,9 +1517,9 @@ void format_line (char *buf, char *label, char *op, char *mods, char *args, char } } -// --------------------------------------------------------------------------------- -// lookup_op - find an opcode -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * lookup_op - find an opcode + ********************************************************************************************/ struct tag_op * lookup_op (char *mnem) { @@ -1491,44 +1536,48 @@ struct tag_op * lookup_op (char *mnem) return NULL; } -// --------------------------------------------------------------------------------- -// bincard - routines to write IBM 1130 Card object format -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * bincard - routines to write IBM 1130 Card object format + ********************************************************************************************/ -unsigned short bincard[54]; // the 54 data words that can fit on a binary format card -char binflag[45]; // the relocation flags of the 45 buffered object words (0, 1, 2, 3) -int bincard_n = 0; // number of object words stored in bincard (0-45) -int bincard_seq = 0; // card output sequence number -int bincard_org = 0; // origin of current card-full +unsigned short bincard[54]; /* the 54 data words that can fit on a binary format card */ +char binflag[45]; /* the relocation flags of the 45 buffered object words (0, 1, 2, 3) */ +int bincard_n = 0; /* number of object words stored in bincard (0-45) */ +int bincard_seq = 0; /* card output sequence number */ +int bincard_org = 0; /* origin of current card-full */ int bincard_maxaddr = 0; -BOOL bincard_first = TRUE; // TRUE when we're to write the program type card +BOOL bincard_first = TRUE; /* TRUE when we're to write the program type card */ -// bincard_init - prepare a new object data output card +/******************************************************************************************** + * bincard_init - prepare a new object data output card + ********************************************************************************************/ void bincard_init (void) { - memset(bincard, 0, sizeof(bincard)); // clear card data - memset(binflag, 0, sizeof(binflag)); // clear relocation data - bincard_n = 0; // no data - bincard[0] = bincard_org; // store load address - bincard_maxaddr = MAX(bincard_maxaddr, bincard_org-1); // save highest address written-to (this may be a BSS) + memset(bincard, 0, sizeof(bincard)); /* clear card data */ + memset(binflag, 0, sizeof(binflag)); /* clear relocation data */ + bincard_n = 0; /* no data */ + bincard[0] = bincard_org; /* store load address */ + bincard_maxaddr = MAX(bincard_maxaddr, bincard_org-1); /* save highest address written-to (this may be a BSS) */ } -// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card -// note: sbrk_text if not NULL MUST be a writeable buffer of at LEAST 71 characters +/******************************************************************************************** + * binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card + * note: sbrk_text if not NULL MUST be a writeable buffer of at LEAST 71 characters + ********************************************************************************************/ void bincard_writecard (char *sbrk_text) { unsigned short binout[80]; char ident[12]; int i, j; - - if (sbrk_text != NULL) { // sbrk card has 4 binary words followed by comment text - for (j = 66; j < 71; j++) // be sure input columns 67..71 are nonblank (have version number) + /* this is an SBRK record */ + if (sbrk_text != NULL) { /* sbrk card has 4 binary words followed by comment text */ + for (j = 66; j < 71; j++) /* be sure input columns 67..71 are nonblank (have version number) */ if (sbrk_text[j] <= ' ') break; - if (j < 71) // sbrk card didn't have the info, stuff in current release + if (j < 71) /* sbrk card didn't have the info, stuff in current release */ for (j = 0; j < 5; j++) sbrk_text[66+j] = dmsversion[j]; @@ -1536,13 +1585,15 @@ void bincard_writecard (char *sbrk_text) binout[1] = 0; binout[2] = 0; binout[3] = 0x1000; + // V1.19 - in previous versions of asm1130, binout[4] was left unset, random + binout[4] = 0; - sbrk_text += 5; // start at the real column 6 (after *SBRK + sbrk_text += 5; /* start at the real column 6 (after *SBRK */ for (j = 5; j < 72; j++) binout[j] = (*sbrk_text) ? ascii_to_hollerith(*sbrk_text++) : 0; } - else { // binary card format packs 54 words into 72 columns + else { /* binary card format packs 54 words into 72 columns */ for (i = j = 0; i < 54; i += 3, j += 4) { binout[j ] = ( bincard[i] & 0xFFF0); binout[j+1] = ((bincard[i] << 12) & 0xF000) | ((bincard[i+1] >> 4) & 0x0FF0); @@ -1551,26 +1602,28 @@ void bincard_writecard (char *sbrk_text) } } - sprintf(ident, "%08ld", ++bincard_seq); // append sequence text + sprintf(ident, "%08ld", ++bincard_seq); /* append sequence text */ memmove(ident, progname, MIN(strlen(progname), 4)); for (i = 0; i < 8; i++) binout[j++] = ascii_to_hollerith(ident[i]); - fxwrite(binout, sizeof(binout[0]), 80, fout); // write card image + fxwrite(binout, sizeof(binout[0]), 80, fout); /* write card image */ } -// binard_writedata - emit an object data card +/******************************************************************************************** + * binard_writedata - emit an object data card + ********************************************************************************************/ void bincard_writedata (void) { unsigned short rflag = 0; int i, j, nflag = 0; - bincard[1] = 0; // checksum - bincard[2] = 0x0A00 | bincard_n; // data card type + word count + bincard[1] = 0; /* checksum */ + bincard[2] = 0x0A00 | bincard_n; /* data card type + word count */ - for (i = 0, j = 3; i < bincard_n; i++) { // construct relocation indicator bitmap + for (i = 0, j = 3; i < bincard_n; i++) { /* construct relocation indicator bitmap */ if (nflag == 8) { bincard[j++] = rflag; rflag = 0; @@ -1583,10 +1636,12 @@ void bincard_writedata (void) if (nflag > 0) bincard[j] = rflag << (16 - 2*nflag); - bincard_writecard(FALSE); // emit the card + bincard_writecard(FALSE); /* emit the card */ } -// bincard_flush - flush any pending binary data +/******************************************************************************************** + * bincard_flush - flush any pending binary data + ********************************************************************************************/ void bincard_flush (void) { @@ -1596,7 +1651,9 @@ void bincard_flush (void) bincard_init(); } -// bincard_sbrk - emit an SBRK card +/******************************************************************************************** + * bincard_sbrk - emit an SBRK card + ********************************************************************************************/ void bincard_sbrk (char *line) { @@ -1608,21 +1665,25 @@ void bincard_sbrk (char *line) bincard_writecard(line); } -// bincard_setorg - set the origin +/******************************************************************************************** + * bincard_setorg - set the origin + ********************************************************************************************/ void bincard_setorg (int neworg) { - bincard_org = neworg; // set origin for next card - bincard_flush(); // flush any current data & store origin + bincard_org = neworg; /* set origin for next card */ + bincard_flush(); /* flush any current data & store origin */ } -// bincard_endcard - write end of program card +/******************************************************************************************** + * bincard_endcard - write end of program card + ********************************************************************************************/ void bincard_endcard (void) { bincard_flush(); - bincard[0] = (bincard_maxaddr + 2) & ~1; // effective length: add 1 to max origin, then 1 more to round up + bincard[0] = (bincard_maxaddr + 2) & ~1; /* effective length: add 1 to max origin, then 1 more to round up */ bincard[1] = 0; bincard[2] = 0x0F00; bincard[3] = pta & 0xFFFF; @@ -1630,7 +1691,9 @@ void bincard_endcard (void) bincard_writecard(NULL); } -// bincard_typecard - write the program type +/******************************************************************************************** + * bincard_typecard - write the program type + ********************************************************************************************/ void bincard_typecard (void) { @@ -1645,14 +1708,14 @@ void bincard_typecard (void) bincard[2] = (unsigned short) ((progtype << 8) | intmode | realmode); -// all indices not listed are documented as 'reserved' +/* all indices not listed are documented as 'reserved' */ switch (progtype) { case PROGTYPE_ABSOLUTE: case PROGTYPE_RELOCATABLE: -// bincard[ 4] = 0; // length of common (fortran only) +/* bincard[ 4] = 0; // length of common (fortran only) */ bincard[ 5] = 0x0003; -// bincard[ 6] = 0; // length of work area (fortran only) +/* bincard[ 6] = 0; // length of work area (fortran only) */ bincard[ 8] = ndefined_files; namecode(&bincard[9], progname); bincard[11] = (pta < 0) ? 0 : pta; @@ -1672,7 +1735,7 @@ void bincard_typecard (void) bincard[ 5] = 6+nintlevels; namecode(&bincard[9], entry[0]->name); bincard[11] = entry[0]->value; - bincard[12] = iss_number + ISTV; // magic number ISTV is 0x33 in DMS R2V12 + bincard[12] = iss_number + ISTV; /* magic number ISTV is 0x33 in DMS R2V12 */ bincard[13] = iss_number; bincard[14] = nintlevels; bincard[15] = intlevel_primary; @@ -1690,14 +1753,16 @@ void bincard_typecard (void) bail("in bincard_typecard, can't happen"); } - bincard[1] = 0; // checksum + bincard[1] = 0; /* checksum */ bincard_writecard(NULL); bincard_init(); } -// bincard_writew - write a word to the current output card. +/******************************************************************************************** + * bincard_writew - write a word to the current output card. + ********************************************************************************************/ void bincard_writew (int word, RELOC relative) { @@ -1706,10 +1771,10 @@ void bincard_writew (int word, RELOC relative) if (bincard_first) bincard_typecard(); - else if (bincard_n >= 45) // flush full card buffer + else if (bincard_n >= 45) /* flush full card buffer */ bincard_flush(); - binflag[bincard_n] = relative & 3; // store relocation bits and data word + binflag[bincard_n] = relative & 3; /* store relocation bits and data word */ bincard[9+bincard_n++] = word; if (relative != LIBF) { @@ -1718,7 +1783,9 @@ void bincard_writew (int word, RELOC relative) } } -// writetwo - notification that we are about to write two words which must stay together +/******************************************************************************************** + * writetwo - notification that we are about to write two words which must stay together + ********************************************************************************************/ void writetwo (void) { @@ -1726,8 +1793,10 @@ void writetwo (void) bincard_flush(); } -// handle_sbrk - handle an SBRK directive. -// This was not part of the 1130 assembler; they assembled DMS on a 360 +/******************************************************************************************** + * handle_sbrk - handle an SBRK directive. + * This was not part of the 1130 assembler; they must have assembled DMS on a 360 using a cross assembler + ********************************************************************************************/ void handle_sbrk (char *line) { @@ -1736,7 +1805,7 @@ void handle_sbrk (char *line) if (pass != 2) return; - strncpy(rline, line, 81); // get a copy and pad it if necessary to 80 characters + strncpy(rline, line, 81); /* get a copy and pad it if necessary to 80 characters */ rline[80] = '\0'; while (strlen(rline) < 80) strcat(rline, " "); @@ -1754,16 +1823,16 @@ void handle_sbrk (char *line) } } -// --------------------------------------------------------------------------------- -// namecode - turn a string into a two-word packed name -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * namecode - turn a string into a two-word packed name + ********************************************************************************************/ void namecode (unsigned short *words, char *tok) { long val = 0; int i, ch; - for (i = 0; i < 5; i++) { // pick up bits + for (i = 0; i < 5; i++) { /* pick up bits */ if (*tok) ch = *tok++; else @@ -1776,22 +1845,22 @@ void namecode (unsigned short *words, char *tok) words[1] = (unsigned short) val; } -// --------------------------------------------------------------------------------- -// parse_line - parse one input line. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * parse_line - parse one input line. + ********************************************************************************************/ void parse_line (char *line) { char label[100], mnem[100], arg[200], mods[20], *c; struct tag_op *op; - if (line[0] == '/' && line[1] == '/') // job control card? probably best to ignore it + if (line[0] == '/' && line[1] == '/') /* job control card? probably best to ignore it */ return; - if (line[0] == '*') { // control card comment or comment in tab-format file - if (check_control) // pay attention to control cards only at top of file + if (line[0] == '*') { /* control card comment or comment in tab-format file */ + if (check_control) /* pay attention to control cards only at top of file */ if (! controlcard(line)) - check_control = FALSE; // first non-control card shuts off sensitivity to them + check_control = FALSE; /* first non-control card shuts off sensitivity to them */ if (strnicmp(line+1, "SBRK", 4) == 0) handle_sbrk(line); @@ -1799,20 +1868,20 @@ void parse_line (char *line) return; } - check_control = FALSE; // non-control card, consider them no more + check_control = FALSE; /* non-control card, consider them no more */ - label[0] = '\0'; // prepare to extract fields + label[0] = '\0'; /* prepare to extract fields */ mods[0] = '\0'; mnem[0] = '\0'; arg[0] = '\0'; - if (tabformat || strchr(line, '\t') != NULL) { // if input line has tabs, parse loosely - tabformat = TRUE; // this is a tab-formatted file + if (tabformat || strchr(line, '\t') != NULL) { /* if input line has tabs, parse loosely */ + tabformat = TRUE; /* this is a tab-formatted file */ - for (c = line; *c && *c <= ' '; c++) // find first nonblank + for (c = line; *c && *c <= ' '; c++) /* find first nonblank */ ; - if (*c == '*' || ! *c) // ignore as a comment + if (*c == '*' || ! *c) /* ignore as a comment */ return; tabtok(line, label, 0, NULL); @@ -1820,11 +1889,11 @@ void parse_line (char *line) tabtok(line, mods, 2, NULL); tabtok(line, arg, 3, opfield); } - else { // if no tabs, use strict card-column format - if (line[20] == '*') // comment + else { /* if no tabs, use strict card-column format */ + if (line[20] == '*') /* comment */ return; - line[72] = '\0'; // clip off sequence + line[72] = '\0'; /* clip off sequence */ coltok(line, label, 21, 25, TRUE, NULL); coltok(line, mnem, 27, 30, TRUE, NULL); @@ -1832,124 +1901,118 @@ void parse_line (char *line) coltok(line, arg, 35, 72, FALSE, opfield); } -// I don't know where I got this idea, but it's wrong... -// if (strchr(mods, '1') || strchr(mods, '2') || strchr(mods, '3')) { // index + X means ignore X -// if ((c = strchr(mods, 'X')) != NULL) -// strcpy(c, c+1); // remove the X -// } + if (*label) /* display org in any line with a label */ + setw(0, org+listoffset, FALSE); - if (*label) // display org in any line with a label - setw(0, org, FALSE); - - if (! *mnem) { // label w/o mnemonic, just define the symbol + if (! *mnem) { /* label w/o mnemonic, just define the symbol */ if (*label) set_symbol(label, org, TRUE, relocate); return; } - if ((op = lookup_op(mnem)) == NULL) { // look up mnemonic + if ((op = lookup_op(mnem)) == NULL) { /* look up mnemonic */ if (*label) - set_symbol(label, org, TRUE, relocate);// at least define the label + set_symbol(label, org, TRUE, relocate);/* at least define the label */ asm_error("Unknown opcode '%s'", mnem); return; } - if (op->flags & TRAP) // assembler debugging breakpoint + if (op->flags & TRAP) /* assembler debugging breakpoint */ x_trap(op, label, mods, arg); - if (*op->mods_allowed != '\xFF') { // validate modifiers against list of allowed characters + if (*op->mods_allowed != '\xFF') { /* validate modifiers against list of allowed characters */ for (c = mods; *c; ) { if (strchr(op->mods_allowed, *c) == NULL) { asm_warning("Modifier '%c' not permitted", *c); - strcpy(c, c+1); // remove it and keep parsing + strcpy(c, c+1); /* remove it and keep parsing */ } else c++; } } - strcat(mods, op->mods_implied); // tack on implied modifiers + strcat(mods, op->mods_implied); /* tack on implied modifiers */ - if (strchr(mods, 'I')) // indirect implies long + if (strchr(mods, 'I')) /* indirect implies long */ strcat(mods, "L"); requires_even_address = op->flags & IS_DBL; - org_advanced = strchr(mods, 'L') ? 2 : 1; // by default, * means address + 1 or 2. Sometimes it doesn't + org_advanced = strchr(mods, 'L') ? 2 : 1; /* by default, * means address + 1 or 2. Sometimes it doesn't */ (op->handler)(op, label, mods, arg); if ((op->flags & IS_1800) && ! enable_1800) asm_warning("%s is IBM 1800-specific; use the -8 command line option", op->mnem); } -// --------------------------------------------------------------------------------- -// get one input line from current file or macro -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * get one input line from current file or macro + ********************************************************************************************/ BOOL get_line (char *buf, int nbuf, BOOL onelevel) { char *retval; - if (ended) // we hit the END command + if (ended) /* we hit the END command */ return FALSE; - // if macro active, return line from macro buffer, otherwise read from file - // do not pop end-of-macro if onelevel is TRUE + /* if macro active, return line from macro buffer, otherwise read from file */ + /* do not pop end-of-macro if onelevel is TRUE */ if ((retval = fgets(buf, nbuf, fin)) == NULL) return FALSE; - lno++; // count the line + lno++; /* count the line */ return TRUE; } -// --------------------------------------------------------------------------------- -// proc - process one pass of one source file -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * proc - process one pass of one source file + ********************************************************************************************/ void proc (char *fname) { char line[256], *c; int i; - if (strchr(fname, '.') == NULL) // if input file has no extension, - addextn(fname, ".asm", curfn); // set appropriate file extension + if (strchr(fname, '.') == NULL) /* if input file has no extension, */ + addextn(fname, ".asm", curfn); /* set appropriate file extension */ else - strcpy(curfn, fname); // otherwise use extension specified + strcpy(curfn, fname); /* otherwise use extension specified */ -// let's leave filename case alone even if it doesn't matter -//#if (defined(_WIN32) || defined(VMS)) -// upcase(curfn); // only force uppercase of name on Windows and VMS -//#endif +/* let's leave filename case alone even if it doesn't matter */ +/*#if (defined(_WIN32) || defined(VMS)) */ +/* upcase(curfn); // only force uppercase of name on Windows and VMS */ +/*#endif */ - if (progname[0] == '\0') { // pick up primary filename + if (progname[0] == '\0') { /* pick up primary filename */ if ((c = strrchr(curfn, '\\')) == NULL) if ((c = strrchr(curfn, '/')) == NULL) if ((c = strrchr(curfn, ':')) == NULL) c = curfn; - strncpy(progname, c, sizeof(progname)); // take name after path + strncpy(progname, c, sizeof(progname)); /* take name after path */ progname[sizeof(progname)-1] = '\0'; - if ((c = strchr(progname, '.')) != NULL)// remove extension + if ((c = strchr(progname, '.')) != NULL)/* remove extension */ *c = '\0'; } - lno = 0; // reset global input line number - ended = FALSE; // have not seen END statement + lno = 0; /* reset global input line number */ + ended = FALSE; /* have not seen END statement */ - if (listfn == NULL) // if list file name is undefined, - listfn = addextn(fname, ".lst", NULL); // create from first filename + if (listfn == NULL) /* if list file name is undefined, */ + listfn = addextn(fname, ".lst", NULL); /* create from first filename */ if (verbose) fprintf(stderr, "--- Starting file %s pass %d\n", curfn, pass); if ((fin = fopen(curfn, "r")) == NULL) { - perror(curfn); // oops + perror(curfn); /* oops */ exit(1); } - if (flist) { // put banner in listing file + if (flist) { /* put banner in listing file */ strcpy(listline,"=== FILE ======================================================================"); for (i = 9, c = curfn; *c;) listline[i++] = *c++; @@ -1958,67 +2021,67 @@ void proc (char *fname) putc('\n', flist); list_on = TRUE; } - // read all lines till EOF or END statement + /* read all lines till EOF or END statement */ while (get_line(line, sizeof(line), FALSE)) { - prep_line(line); // preform standard line prep - parse_line(line); // parse - listout(FALSE); // complete the listing + prep_line(line); /* preform standard line prep */ + parse_line(line); /* parse */ + listout(FALSE); /* complete the listing */ } fclose(fin); - if (n_literals > 0) { // force out any pending literal constants at end of file + if (n_literals > 0) { /* force out any pending literal constants at end of file */ output_literals(TRUE); listout(FALSE); } } -// --------------------------------------------------------------------------------- -// prep_line - prepare input line for parsing -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * prep_line - prepare input line for parsing + ********************************************************************************************/ void prep_line (char *line) { char *c; - upcase(line); // uppercase it - nwout = 0; // number of words output so far - line_error = FALSE; // no errors on this line so far + upcase(line); /* uppercase it */ + nwout = 0; /* number of words output so far */ + line_error = FALSE; /* no errors on this line so far */ - for (c = line; *c; c++) { // truncate at newline + for (c = line; *c; c++) { /* truncate at newline */ if (*c == '\r' || *c == '\n') { *c = '\0'; break; } } - if (flist && list_on) { // construct beginning of listing line + if (flist && list_on) { /* construct beginning of listing line */ if (tabformat) sprintf(listline, LINEFORMAT, lno, detab(line)); else { - if (strlen(line) > 20) // get the part where the commands start + if (strlen(line) > 20) /* get the part where the commands start */ c = line+20; else c = ""; sprintf(listline, LINEFORMAT, lno, c); - stuff(listline, line, 20); // stuff the left margin in to the left side + stuff(listline, line, 20); /* stuff the left margin in to the left side */ } } } -// --------------------------------------------------------------------------------- -// opcmp - operand name comparison routine for qsort -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * opcmp - operand name comparison routine for qsort + ********************************************************************************************/ int opcmp (const void *a, const void *b) { return strcmp(((struct tag_op *) a)->mnem, ((struct tag_op *) b)->mnem); } -// --------------------------------------------------------------------------------- -// preload_symbols - load a saved symbol table -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * preload_symbols - load a saved symbol table + ********************************************************************************************/ void preload_symbols (void) { @@ -2032,7 +2095,7 @@ void preload_symbols (void) preloaded_already = TRUE; - if ((fd = fopen(SYSTEM_TABLE, "r")) == NULL) // read the system symbol tabl + if ((fd = fopen(SYSTEM_TABLE, "r")) == NULL) /* read the system symbol tabl */ perror(SYSTEM_TABLE); else { while (fgets(str, sizeof(str), fd) != NULL) { @@ -2043,9 +2106,9 @@ void preload_symbols (void) } } -// --------------------------------------------------------------------------------- -// save_symbols - save a symbol table -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * save_symbols - save a symbol table + ********************************************************************************************/ void save_symbols (void) { @@ -2075,100 +2138,92 @@ void save_symbols (void) } for (s = symbols; s != NULL; s = s->next) - fprintf(fd, "%-5s %04x\n", s->name, s->value); + fprintf(fd, "%-5s %04X\n", s->name, s->value); fclose(fd); } -// --------------------------------------------------------------------------------- -// startpass - initialize data structures, prepare to start a pass -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * startpass - initialize data structures, prepare to start a pass + ********************************************************************************************/ void startpass (int n) { int nops; struct tag_op *p; - pass = n; // reset globals: pass number - nerrors = 0; // error count - org = 0; // load address (origin) - lno = 0; // input line number - relocate = TRUE; // relocatable assembly mode - assembled = FALSE; // true if any output has been generated - list_on = do_list; // listing enable - dmes_saved = FALSE; // partial character strings output + pass = n; /* reset globals: pass number */ + nerrors = 0; /* error count */ + org = 0; /* load address (origin) */ + lno = 0; /* input line number */ + relocate = TRUE; /* relocatable assembly mode */ + assembled = FALSE; /* true if any output has been generated */ + list_on = do_list; /* listing enable */ + dmes_saved = FALSE; /* partial character strings output */ - n_literals = 0; // literal values pending output + n_literals = 0; /* literal values pending output */ lit_tag = 0; - if (pass == 1) { // first pass only - for (nops = 0, p = ops; p->mnem != NULL; p++, nops++) // count opcodes + if (pass == 1) { /* first pass only */ + for (nops = 0, p = ops; p->mnem != NULL; p++, nops++) /* count opcodes */ ; - qsort(ops, nops, sizeof(*p), opcmp); // sort the opcode table + qsort(ops, nops, sizeof(*p), opcmp); /* sort the opcode table */ if (preload) preload_symbols(); } - else { // second pass only + else { /* second pass only */ if (outfn == NULL) outfn = addextn(curfn, (outmode == OUTMODE_LOAD) ? ".out" : ".bin" , NULL); - if ((fout = fopen(outfn, OUTWRITEMODE)) == NULL) { // open output file + if ((fout = fopen(outfn, OUTWRITEMODE)) == NULL) { /* open output file */ perror(outfn); exit(1); } - if (do_list) { // open listing file + if (do_list) { /* open listing file */ if ((flist = fopen(listfn, "w")) == NULL) { perror(listfn); exit(1); } - listhdr(); // print banner + listhdr(); /* print banner */ } } } -// --------------------------------------------------------------------------------- -// x_dc - DC define constant directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_dc - DC define constant directive + ********************************************************************************************/ void x_dc (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; -// char *tok; +/* char *tok; */ - org_advanced = 1; // assume * means this address+1 -// doesn't make sense, but I think I found DMS listings to support it + org_advanced = 1; /* assume * means this address+1 */ +/* doesn't make sense, but I think I found DMS listings to support it */ - if (strchr(mods, 'E') != NULL) // force even address + if (strchr(mods, 'E') != NULL) /* force even address */ org_even(); - setw(0, org, FALSE); // display org in listing line + setw(0, org+listoffset, FALSE); /* display org in listing line */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); -// just one!? getexpr(arg, FALSE, &expr); - writew(expr.value, expr.relative); // store value - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getexpr(tok, FALSE, &expr); -// writew(expr.value, expr.relative); // store value -// } + writew(expr.value, expr.relative); /* store value */ } -// --------------------------------------------------------------------------------- -// x_dec - DEC define double word constant directive. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_dec - DEC define double word constant directive. + ********************************************************************************************/ -// wd[0]: 8 unused bits | characteristic (= exponent+128) -// wd[1]: sign + 15 msb of mantissa in 2's complement -// wd[2]: 16 lsb of mantissa - -// NOTE: these are wrong with Fixed point numbers +/* wd[0]: 8 unused bits | characteristic (= exponent+128) + * wd[1]: sign + 15 msb of mantissa in 2's complement + * wd[2]: 16 lsb of mantissa + * NOTE: these are wrong with Fixed point numbers */ void convert_double_to_extended (double d, unsigned short *wd) { @@ -2180,37 +2235,38 @@ void convert_double_to_extended (double d, unsigned short *wd) wd[0] = wd[1] = wd[2] = 0; return; } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM + /* 7 6 5 4 0 */ + /* d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM */ neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias + exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); /* extract exponent */ + exp -= 1023; /* remove bias */ - exp++; // shift to account for implied 1 we added + exp++; /* shift to account for implied 1 we added */ - // get 32 bits worth of mantissa. add the implied point + /* get 32 bits worth of mantissa. add the implied point */ mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - if (mantissa & (0x80000000L >> 31)) // keep 31 bits, round if necessary + if (mantissa & (0x80000000L >> 31)) /* keep 31 bits, round if necessary */ mantissa += (0x80000000L >> 31); - mantissa >>= (32-31); // get into low 31 bits + mantissa >>= (32-31); /* get into low 31 bits */ - // now turn into IBM 1130 extended precision + /* now turn into IBM 1130 extended precision */ exp += 128; if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement + mantissa = (unsigned long) (- (long) mantissa); /* two's complement */ wd[0] = (unsigned short) (exp & 0xFF); wd[1] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (31-15)) & 0x7FFF)); wd[2] = (unsigned short) (mantissa & 0xFFFF); } -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * convert_double_to_standard - + ********************************************************************************************/ void convert_double_to_standard (double d, unsigned short *wd) { @@ -2222,42 +2278,43 @@ void convert_double_to_standard (double d, unsigned short *wd) wd[0] = wd[1] = 0; return; } - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM + /* 7 6 5 4 0 */ + /* d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM */ neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias + exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); /* extract exponent */ + exp -= 1023; /* remove bias */ - exp++; // shift to account for implied 1 we added + exp++; /* shift to account for implied 1 we added */ - // get 32 bits worth of mantissa. add the implied point + /* get 32 bits worth of mantissa. add the implied point */ mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); -// if (mantissa & (0x80000000L >> 23)) // keep 23 bits, round if necessary -// mantissa += (0x80000000L >> 23); +/* if (mantissa & (0x80000000L >> 23)) // keep 23 bits, round if necessary */ +/* mantissa += (0x80000000L >> 23); */ -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); +/* DEBUG */ +/* printf("%8.4lf: %08lX %d\n", d, mantissa, exp); */ - mantissa >>= (32-23); // get into low 23 bits + mantissa >>= (32-23); /* get into low 23 bits */ - // now turn into IBM 1130 standard precision + /* now turn into IBM 1130 standard precision */ exp += 128; if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement + mantissa = (unsigned long) (- (long) mantissa); /* two's complement */ wd[0] = (unsigned short) ((neg ? 0x8000 : 0) | ((mantissa >> (23-15)) & 0x7FFF)); wd[1] = (unsigned short) ((mantissa & 0x00FF) << 8) | (exp & 0xFF); -// DEBUG -// printf(" D %04x%04x\n", wd[0], wd[1]); +/* DEBUG */ +/* printf(" D %04x%04X\n", wd[0], wd[1]); */ } -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * convert_double_to_fixed - + ********************************************************************************************/ void convert_double_to_fixed (double d, unsigned short *wd, int bexp) { @@ -2270,24 +2327,24 @@ void convert_double_to_fixed (double d, unsigned short *wd, int bexp) return; } - // note: we assume that this computer uses ANSI floating point + /* note: we assume that this computer uses ANSI floating point */ - // 7 6 5 4 0 - // d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM + /* 7 6 5 4 0 */ + /* d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM */ neg = byte[7] & 0x80; - exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); // extract exponent - exp -= 1023; // remove bias + exp = ((byte[7] & 0x7F) << 4) | ((byte[6] & 0xF0) >> 4); /* extract exponent */ + exp -= 1023; /* remove bias */ - exp++; // shift to account for implied 1 we added + exp++; /* shift to account for implied 1 we added */ - // get 32 bits worth of mantissa. add the implied point + /* get 32 bits worth of mantissa. add the implied point */ mantissa = 0x80000000L | ((byte[6] & 0x0F) << 27) | (byte[5] << 19) | (byte[4] << 11) | (byte[3] << 3) | ((byte[2] & 0xE0) >> 5); - mantissa >>= 1; // shift it out of the sign bit + mantissa >>= 1; /* shift it out of the sign bit */ -// DEBUG -// printf("%8.4lf: %08lx %d\n", d, mantissa, exp); +/* DEBUG */ +/* printf("%8.4lf: %08lX %d\n", d, mantissa, exp); */ rshift = bexp - exp; @@ -2300,114 +2357,110 @@ void convert_double_to_fixed (double d, unsigned short *wd, int bexp) } if (neg) - mantissa = (unsigned long) (- (long) mantissa); // two's complement + mantissa = (unsigned long) (- (long) mantissa); /* two's complement */ -// DEBUG -// printf(" B %08lx\n", mantissa); +/* DEBUG */ +/* printf(" B %08lX\n", mantissa); */ - wd[0] = (unsigned short) ((mantissa >> 16) & 0xFFFF); // return all of the bits; no exponent here + wd[0] = (unsigned short) ((mantissa >> 16) & 0xFFFF); /* return all of the bits; no exponent here */ wd[1] = (unsigned short) (mantissa & 0xFFFF); } -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * getDconstant - + ********************************************************************************************/ void getDconstant (char *tok, unsigned short *wd) { unsigned long l; char *b, *fmt; double d; - int bexp, fixed; + int bexp; + BOOL fixed = FALSE; wd[0] = 0; wd[1] = 0; + tok = skipbl(tok); + if (! *tok) + return; /* no argument is the same as 0 */ + if (strchr(tok, '.') == NULL && strchr(tok, 'B') == NULL && strchr(tok, 'E') == NULL) { - fmt = "%ld"; - if (*tok == '/') { // I don't see that this is legal but can't hurt to allow it + fmt = "%ld"; /* not a floating point number -- parse as a 32-bit integer */ + if (*tok == '/') { /* I don't see that this is legal but can't hurt to allow it */ fmt = "%lx"; tok++; } - if (sscanf(tok, fmt, &l) != 1) { // no decimal means it's an integer? + + if (sscanf(tok, fmt, &l) != 1) asm_error("Syntax error in constant"); - } else { - wd[0] = (unsigned short) ((l >> 16) & 0xFFFF); // high word - wd[1] = (unsigned short) (l & 0xFFFF); // low word + wd[0] = (unsigned short) ((l >> 16) & 0xFFFF); /* high word */ + wd[1] = (unsigned short) (l & 0xFFFF); /* low word */ } - return; } + else { + if ((b = strchr(tok, 'B')) != NULL) { + fixed = TRUE; + bexp = atoi(b+1); /* get binary exponent, after the B */ + *b = '\0'; /* truncate at the B */ + } - fixed = 0; - if ((b = strchr(tok, 'B')) != NULL) { - fixed = 1; - bexp = atoi(b+1); - *b = '\0'; // truncate at the b + if (sscanf(tok, "%lg", &d) != 1) + asm_error("Syntax error in constant"); + else if (fixed) + convert_double_to_fixed(d, wd, bexp); + else + convert_double_to_standard(d, wd); } - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - return; - } - - if (fixed) - convert_double_to_fixed(d, wd, bexp); - else - convert_double_to_standard(d, wd); } -// --------------------------------------------------------------------------------- -// If the input value is an integer with no decimal point and no B or E, -// DEC generates a double INTEGER value. -// IBM documentation ranges from ambiguous to wrong on this point, but -// examination of the DMS microfiche supports this. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_dec - If the input value is an integer with no decimal point and no B or E, + * DEC generates a double INTEGER value. + * IBM documentation ranges from ambiguous to wrong on this point, but + * examination of the DMS microfiche supports this. + ********************************************************************************************/ void x_dec (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short wd[2]; - org_advanced = 2; // assume * means address after this location, since it's +1 for dc? + org_advanced = 2; /* assume * means address after this location, since it's +1 for dc? */ - org_even(); // even address is implied - setw(0, org, FALSE); // display the origin + org_even(); /* even address is implied */ + setw(0, org+listoffset, FALSE); /* display the origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); -// just one!? getDconstant(arg, wd); - writew(wd[0], FALSE); // write hiword, then loword + writew(wd[0], FALSE); /* write hiword, then loword */ writew(wd[1], FALSE); - - // pick up values, comma delimited -// for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { -// getDconstant(tok, wd); -// -// writew(wd[0], FALSE); // write hiword, then loword -// writew(wd[1], FALSE); } -// --------------------------------------------------------------------------------- -// DECS directive. Writes just the high word of a DEC value -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * DECS directive. Writes just the high word of a DEC value + ********************************************************************************************/ void x_decs (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short wd[2]; - org_advanced = 1; // assume * means address after this location + org_advanced = 1; /* assume * means address after this location */ - setw(0, org, FALSE); // display the origin + setw(0, org+listoffset, FALSE); /* display the origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); getDconstant(arg, wd); - writew(wd[0], FALSE); // write hiword ONLY + writew(wd[0], FALSE); /* write hiword ONLY */ } -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_xflc - extended precision constant. (Note: if there is no argument, we must write a zero value) + ********************************************************************************************/ void x_xflc (struct tag_op *op, char *label, char *mods, char *arg) { @@ -2416,68 +2469,71 @@ void x_xflc (struct tag_op *op, char *label, char *mods, char *arg) int bexp, fixed; unsigned short wd[3]; - org_advanced = 2; // who knows? + org_advanced = 2; /* who knows? */ - setw(0, org, FALSE); // display the origin + setw(0, org+listoffset, FALSE); /* display the origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - // pick up values, comma delimited - for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { - bexp = 0; - if ((b = strchr(tok, 'B')) != NULL) { - bexp = atoi(b+1); - fixed = TRUE; - *b = '\0'; // truncate at the b - asm_warning("Fixed point extended floating constant?"); - } - if (sscanf(tok, "%lg", &d) != 1) { - asm_error("Syntax error in constant"); - d = 0.; - } - - convert_double_to_extended(d, wd); - - writew(wd[0], ABSOLUTE); - writew(wd[1], ABSOLUTE); - writew(wd[2], ABSOLUTE); + if ((tok = strtok(arg, ",")) == NULL) { /* pick up value */ + tok = "0"; /* if there is no argument at all, spit out a zero */ +/* fprintf(stderr, ">>> ENCOUNTERED XFLC WITH NO ARGUMENT IN %s -- THIS WAS BUGGY BEFORE\n", curfn); */ } + + bexp = 0; /* parse the value */ + if ((b = strchr(tok, 'B')) != NULL) { + bexp = atoi(b+1); + fixed = TRUE; + *b = '\0'; /* truncate at the b */ + asm_warning("Fixed point extended floating constant?"); + } + + if (sscanf(tok, "%lg", &d) != 1) { + asm_error("Syntax error in constant"); + d = 0.; + } + + convert_double_to_extended(d, wd); + + writew(wd[0], ABSOLUTE); + writew(wd[1], ABSOLUTE); + writew(wd[2], ABSOLUTE); } -// --------------------------------------------------------------------------------- -// x_equ - EQU directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_equ - EQU directive + ********************************************************************************************/ void x_equ (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - org_advanced = FALSE; // * means this address, not incremented + org_advanced = 0; /* * means this address, not incremented */ getexpr(arg, FALSE, &expr); - setw(0, expr.value, expr.relative); // show this as address + setw(0, expr.value, expr.relative); /* show this as address */ - if (*label) // EQU is all about defining labels, better have one + if (*label) /* EQU is all about defining labels, better have one */ set_symbol(label, expr.value, TRUE, expr.relative); -// else // IBM assembler doesn't complain about this -// asm_error("EQU without label?"); +/* else // IBM assembler doesn't complain about this */ +/* asm_error("EQU without label?"); */ } -// --------------------------------------------------------------------------------- -// x_lorg - LORG directive -- output queued literal values -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_lorg - LORG directive -- output queued literal values + ********************************************************************************************/ void x_lorg (struct tag_op *op, char *label, char *mods, char *arg) { - org_advanced = FALSE; // * means this address (not used, though) - output_literals(FALSE); // generate .DC's for queued literal values + org_advanced = 0; /* * means this address (not used, though) */ + output_literals(FALSE); /* generate .DC's for queued literal values */ } -// --------------------------------------------------------------------------------- -// x_abs - ABS directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_abs - ABS directive + ********************************************************************************************/ void x_abs (struct tag_op *op, char *label, char *mods, char *arg) { @@ -2489,7 +2545,7 @@ void x_abs (struct tag_op *op, char *label, char *mods, char *arg) switch (progtype) { case PROGTYPE_ABSOLUTE: case PROGTYPE_RELOCATABLE: - progtype = PROGTYPE_ABSOLUTE; // change program type, still assumed to be mainline + progtype = PROGTYPE_ABSOLUTE; /* change program type, still assumed to be mainline */ break; case PROGTYPE_LIBF: @@ -2505,16 +2561,16 @@ void x_abs (struct tag_op *op, char *label, char *mods, char *arg) } } -// --------------------------------------------------------------------------------- -// x_call - ORG pseudo-op -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_call - ORG pseudo-op + ********************************************************************************************/ void x_call (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short words[2]; static struct tag_op *bsi = NULL; - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); if (! *arg) { @@ -2522,88 +2578,93 @@ void x_call (struct tag_op *op, char *label, char *mods, char *arg) return; } - if (pass == 1) { // it will take two words in any case + if (pass == 1) { /* it will take two words in any case */ org += 2; return; } - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - if (lookup_symbol(arg, FALSE) != NULL) { // it's a defined symbol? + if (lookup_symbol(arg, FALSE) != NULL) {/* it's a defined symbol? */ if (bsi == NULL) if ((bsi = lookup_op("BSI")) == NULL) bail("Can't find BSI op"); (bsi->handler)(bsi, "", "L", arg); } - else { - namecode(words, arg); // emit namecode for loader + else if (outmode == OUTMODE_BINARY) { + namecode(words, arg); /* emit namecode for loader */ writetwo(); writew(words[0], CALL); writew(words[1], ABSOLUTE); } + else { + writew(0x3000, 0); /* write two WAIT commands */ + writew(0x3000, 0); + asm_warning("CALL is not valid for simulator load output format, emitting WAIT"); + } } -// --------------------------------------------------------------------------------- -// x_org - ORG directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_org - ORG directive + ********************************************************************************************/ void x_org (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - org_advanced = FALSE; // * means this address + org_advanced = 0; /* * means this address */ - if (*label) // label is defined BEFORE the new origin is set!!! + if (*label) /* label is defined BEFORE the new origin is set!!! */ set_symbol(label, org, TRUE, relocate); if (getexpr(arg, FALSE, &expr) != S_DEFINED) return; - setorg(expr.value); // set origin to this value + setorg(expr.value); /* set origin to this value */ } -// --------------------------------------------------------------------------------- -// x_end - END directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_end - END directive + ********************************************************************************************/ void x_end (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - org_advanced = FALSE; // * means this address + org_advanced = 0; /* * means this address */ - if (*arg) { // they're specifing the program start address + if (*arg) { /* they're specifing the program start address */ if (getexpr(arg, FALSE, &expr) == S_DEFINED) pta = expr.value; } - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - ended = TRUE; // assembly is done, stop reading file + ended = TRUE; /* assembly is done, stop reading file */ } -// --------------------------------------------------------------------------------- -// x_ent - ENT op -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_ent - ENT op + ********************************************************************************************/ void x_ent (struct tag_op *op, char *label, char *mods, char *arg) { PSYMBOL s; - org_advanced = FALSE; // * means this address + org_advanced = 0; /* * means this address */ if (pass < 2) return; -// if (*label) // define label -// set_symbol(label, org, TRUE, relocate); -// -// setw(0, org, FALSE); // display origin +/* if (*label) // define label */ +/* set_symbol(label, org, TRUE, relocate); */ +/* */ +/* setw(0, org+listoffset, FALSE); // display origin */ if (! *arg) asm_error("No entry label specified"); @@ -2615,7 +2676,7 @@ void x_ent (struct tag_op *op, char *label, char *mods, char *arg) asm_error("Too many entries, limit is %d", MAXENTRIES); else - entry[nentries++] = s; // save symbol pointer + entry[nentries++] = s; /* save symbol pointer */ switch (progtype) { case PROGTYPE_ABSOLUTE: @@ -2637,9 +2698,9 @@ void x_ent (struct tag_op *op, char *label, char *mods, char *arg) } } -// --------------------------------------------------------------------------------- -// declare a libf-type subprogram -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * declare a libf-type subprogram + ********************************************************************************************/ void x_libr (struct tag_op *op, char *label, char *mods, char *arg) { @@ -2664,9 +2725,9 @@ void x_libr (struct tag_op *op, char *label, char *mods, char *arg) } } -// --------------------------------------------------------------------------------- -// x_ils - ILS directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_ils - ILS directive + ********************************************************************************************/ void x_ils (struct tag_op *op, char *label, char *mods, char *arg) { @@ -2692,9 +2753,9 @@ void x_ils (struct tag_op *op, char *label, char *mods, char *arg) intlevel_primary = atoi(mods); } -// --------------------------------------------------------------------------------- -// x_iss - ISS directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_iss - ISS directive + ********************************************************************************************/ void x_iss (struct tag_op *op, char *label, char *mods, char *arg) { @@ -2719,20 +2780,20 @@ void x_iss (struct tag_op *op, char *label, char *mods, char *arg) bail("in x_libr, can't happen"); } - iss_number = atoi(mods); // get ISS number + iss_number = atoi(mods); /* get ISS number */ - opfield[16] = '\0'; // be sure not to look too far into this + opfield[16] = '\0'; /* be sure not to look too far into this */ - nintlevels = 0; // # of interrupt levels for ISS - intlevel_primary = 0; // primary level for ISS and level for ILS - intlevel_secondary = 0; // secondary level for ISS + nintlevels = 0; /* # of interrupt levels for ISS */ + intlevel_primary = 0; /* primary level for ISS and level for ILS */ + intlevel_secondary = 0; /* secondary level for ISS */ if ((tok = strtok(opfield, " ")) == NULL) asm_error("ISS missing entry label"); else - x_ent(NULL, label, "", arg); // process as an ENT + x_ent(NULL, label, "", arg); /* process as an ENT */ - if ((tok = strtok(NULL, " ")) != NULL) { // get associated levels + if ((tok = strtok(NULL, " ")) != NULL) { /* get associated levels */ nintlevels++; intlevel_primary = atoi(tok); } @@ -2743,44 +2804,65 @@ void x_iss (struct tag_op *op, char *label, char *mods, char *arg) } } +/******************************************************************************************** + * x_spr - + ********************************************************************************************/ + void x_spr (struct tag_op *op, char *label, char *mods, char *arg) { realmode = REALMODE_STANDARD; } +/******************************************************************************************** + * x_epr - + ********************************************************************************************/ + void x_epr (struct tag_op *op, char *label, char *mods, char *arg) { realmode = REALMODE_EXTENDED; } +/******************************************************************************************** + * x_dsa - + ********************************************************************************************/ + void x_dsa (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short words[2]; - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); if (! *arg) { asm_error("DSA missing filename"); } - else { + else if (outmode == OUTMODE_BINARY) { namecode(words, arg); writetwo(); - writew(words[0], CALL); // special relocation bits here 3 and 1 + writew(words[0], CALL); /* special relocation bits here 3 and 1 */ writew(words[1], RELATIVE); } + else { + writew(0, 0); /* write two zeroes */ + writew(0, 0); + asm_warning("DSA is not valid for simulator load output format, emitting 0's"); + } } +/******************************************************************************************** + * x_link - + ********************************************************************************************/ + void x_link (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short words[2]; char nline[128]; - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); if (! *arg) { @@ -2790,17 +2872,28 @@ void x_link (struct tag_op *op, char *label, char *mods, char *arg) format_line(nline, label, "CALL", "", "$LINK", ""); parse_line(nline); - namecode(words, arg); - writew(words[0], ABSOLUTE); // special relocation bits here 3 and 1 - writew(words[1], ABSOLUTE); + if (outmode == OUTMODE_BINARY) { + namecode(words, arg); + writew(words[0], ABSOLUTE); /* special relocation bits here 3 and 1 */ + writew(words[1], ABSOLUTE); + } + else { + writew(0x3000, 0); /* write two WAIT commands */ + writew(0x3000, 0); + asm_warning("LINK is not valid for simulator load output format, emitting WAIT"); + } } } +/******************************************************************************************** + * x_libf - + ********************************************************************************************/ + void x_libf (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short words[2]; - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); if (! *arg) { @@ -2808,20 +2901,30 @@ void x_libf (struct tag_op *op, char *label, char *mods, char *arg) return; } - if (pass == 1) { // it will take one words in any case + if (pass == 1) { /* it will take one word in any case */ org++; return; } - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - namecode(words, arg); // emit namecode for loader + if (outmode == OUTMODE_BINARY) { + namecode(words, arg); /* emit namecode for loader */ - writetwo(); - writew(words[0], LIBF); // this one does NOT advance org! - writew(words[1], ABSOLUTE); + writetwo(); + writew(words[0], LIBF); /* this one does NOT advance org! */ + writew(words[1], ABSOLUTE); + } + else { + writew(0x3000, 0); /* write a WAIT command */ + asm_warning("LIBF is not valid for simulator load output format, emitting WAIT"); + } } +/******************************************************************************************** + * x_file - + ********************************************************************************************/ + void x_file (struct tag_op *op, char *label, char *mods, char *arg) { int i, n, r; @@ -2833,7 +2936,7 @@ void x_file (struct tag_op *op, char *label, char *mods, char *arg) asm_error("FILE has insufficient arguments"); return; } - arg = NULL; // for next strtok call + arg = NULL; /* for next strtok call */ if (i == 3) { if (strcmpi(tok, "U") != 0) @@ -2862,45 +2965,45 @@ void x_file (struct tag_op *op, char *label, char *mods, char *arg) ndefined_files++; } -// --------------------------------------------------------------------------------- -// x_trap - place to set a breakpoint -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_trap - place to set a breakpoint + ********************************************************************************************/ void x_trap (struct tag_op *op, char *label, char *mods, char *arg) { - // debugging breakpoint + /* debugging breakpoint */ } -// --------------------------------------------------------------------------------- -// x_ces - .CES directive (nonstandard). Specify a value for the console entry -// switches. When this program is loaded into the simulator, the switches will -// be set accordingly. Handy for bootstraps and other programs that read -// the switches. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_ces - .CES directive (nonstandard). Specify a value for the console entry + * switches. When this program is loaded into the simulator, the switches will + * be set accordingly. Handy for bootstraps and other programs that read + * the switches. + ********************************************************************************************/ void x_ces (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - if (outmode != OUTMODE_LOAD) // this works only in our loader format + if (outmode != OUTMODE_LOAD) /* this works only in our loader format */ return; if (getexpr(arg, FALSE, &expr) != S_DEFINED) return; if (pass == 2) - fprintf(fout, "S%04x" ENDLINE, expr.value & 0xFFFF); + fprintf(fout, "S%04X" ENDLINE, expr.value & 0xFFFF); } -// --------------------------------------------------------------------------------- -// x_bss - BSS directive - reserve space in core -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_bss - BSS directive - reserve space in core + ********************************************************************************************/ void x_bss (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - org_advanced = FALSE; // * means this address + org_advanced = 0; /* * means this address */ if (! *arg) { expr.value = 0; @@ -2909,46 +3012,47 @@ void x_bss (struct tag_op *op, char *label, char *mods, char *arg) else if (getexpr(arg, FALSE, &expr) != S_DEFINED) return; - if (strchr(mods, 'E') != NULL) // force even address + if (strchr(mods, 'E') != NULL) /* force even address */ org_even(); if (expr.relative) asm_error("BSS size must be an absolute value"); - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - expr.value &= 0xFFFF; // truncate to 16 bits + expr.value &= 0xFFFF; /* truncate to 16 bits */ - if (expr.value & 0x8000) - asm_warning("Negative BSS size"); + if (expr.value & 0x8000) { + asm_warning("Negative BSS size (%ld, /%04X)", (long)(short)expr.value, expr.value); + } else if (expr.value > 0) { if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin by appropriate number of words - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); + org += expr.value; /* advance the origin by appropriate number of words */ + if (pass == 2) /* emit new load address in output file */ + fprintf(fout, "@%04X%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); } else { - org += expr.value; // advance the origin by appropriate number of words + org += expr.value; /* advance the origin by appropriate number of words */ if (pass == 2) bincard_setorg(org); } } } -// --------------------------------------------------------------------------------- -// x_bes - Block Ended by Symbol directive. Like BSS but label gets address AFTER the space, instead of first address -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_bes - Block Ended by Symbol directive. Like BSS but label gets address AFTER the space, instead of first address + ********************************************************************************************/ void x_bes (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - org_advanced = FALSE; // * means this address + org_advanced = 0; /* * means this address */ - if (! *arg) { // arg field = space + if (! *arg) { /* arg field = space */ expr.value = 0; expr.relative = ABSOLUTE; } @@ -2956,7 +3060,7 @@ void x_bes (struct tag_op *op, char *label, char *mods, char *arg) return; if (strchr(mods, 'E') != NULL && (org & 1) != 0) - org_even(); // force even address + org_even(); /* force even address */ if (expr.relative) asm_error("BES size must be an absolute value"); @@ -2965,26 +3069,26 @@ void x_bes (struct tag_op *op, char *label, char *mods, char *arg) asm_warning("Negative BES size"); else if (expr.value > 0) { - setw(0, org+expr.value, FALSE); // display NEW origin + setw(0, org+expr.value+listoffset, FALSE); /* display NEW origin */ if (outmode == OUTMODE_LOAD) { - org += expr.value; // advance the origin - if (pass == 2) // emit new load address in output file - fprintf(fout, "@%04x%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); + org += expr.value; /* advance the origin */ + if (pass == 2) /* emit new load address in output file */ + fprintf(fout, "@%04X%s" ENDLINE, org & 0xFFFF, relocate ? "R" : ""); } else { - org += expr.value; // advance the origin + org += expr.value; /* advance the origin */ bincard_setorg(org); } } - if (*label) // NOW define the label + if (*label) /* NOW define the label */ set_symbol(label, org, TRUE, relocate); } -// --------------------------------------------------------------------------------- -// x_dmes - DMES define message directive. Various encodings, none pretty. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_dmes - DMES define message directive. Various encodings, none pretty. + ********************************************************************************************/ int dmes_wd; int dmes_nc; @@ -2997,20 +3101,20 @@ void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) char *c = opfield; BOOL cont = FALSE; - if (dmes_saved) { // previous DMES had an odd character saved + if (dmes_saved) { /* previous DMES had an odd character saved */ dmes_wd = dmes_savew; - dmes_nc = 1; // stick it into the outbut buffer + dmes_nc = 1; /* stick it into the outbut buffer */ } else - dmes_nc = dmes_wd = 0; // clear output buffer + dmes_nc = dmes_wd = 0; /* clear output buffer */ - trim(opfield); // remove trailing blanks from rest of input line (use whole thing) - setw(0, org, FALSE); // display origin + trim(opfield); /* remove trailing blanks from rest of input line (use whole thing) */ + setw(0, org+listoffset, FALSE); /* display origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - if (strchr(mods, '1') != NULL) // determine the encoding scheme + if (strchr(mods, '1') != NULL) /* determine the encoding scheme */ dmes_cs = CODESET_1403; else if (strchr(mods, '2') != NULL) dmes_cs = CODESET_1132; @@ -3021,24 +3125,24 @@ void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) dmes_cs = CODESET_EBCDIC; } - while (*c) { // pick up characters - if (*c == '\'') { // quote (') is the escape character + while (*c) { /* pick up characters */ + if (*c == '\'') { /* quote (') is the escape character */ c++; - rpt = 0; // get repeat count + rpt = 0; /* get repeat count */ while (BETWEEN(*c, '0', '9')) { rpt = rpt*10 + *c++ - '0'; } - if (rpt <= 0) // no count = insert one copy + if (rpt <= 0) /* no count = insert one copy */ rpt = 1; - switch (*c) { // handle escape codes + switch (*c) { /* handle escape codes */ case '\'': stuff_dmes(*c, 1); break; case 'E': - *c = '\0'; // end + *c = '\0'; /* end */ break; case 'X': @@ -3047,13 +3151,13 @@ void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) break; case 'F': - stuff_dmes(*++c, rpt); // repeat character + stuff_dmes(*++c, rpt); /* repeat character */ break; case ' ': case '\0': cont = TRUE; - *c = '\0'; // end + *c = '\0'; /* end */ break; case 'T': @@ -3061,32 +3165,32 @@ void x_dmes (struct tag_op *op, char *label, char *mods, char *arg) badcode: asm_error("Invalid ' escape for selected printer"); break; } - stuff_dmes(0x41, -rpt); // tab + stuff_dmes(0x41, -rpt); /* tab */ break; case 'D': if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x11, -rpt); // backspace + stuff_dmes(0x11, -rpt); /* backspace */ break; case 'B': if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x05, -rpt); // black + stuff_dmes(0x05, -rpt); /* black */ break; case 'A': if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x09, -rpt); // red + stuff_dmes(0x09, -rpt); /* red */ break; case 'R': if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x81, -rpt); // return + stuff_dmes(0x81, -rpt); /* return */ break; case 'L': if (dmes_cs != CODESET_CONSOLE) goto badcode; - stuff_dmes(0x03, -rpt); // line feed + stuff_dmes(0x03, -rpt); /* line feed */ break; default: @@ -3095,7 +3199,7 @@ badcode: asm_error("Invalid ' escape for selected printer"); break; } } - else // just copy literal character + else /* just copy literal character */ stuff_dmes(*c, 1); if (*c) @@ -3104,25 +3208,25 @@ badcode: asm_error("Invalid ' escape for selected printer"); dmes_saved = FALSE; - if (dmes_nc) { // odd number of characters + if (dmes_nc) { /* odd number of characters */ if (cont) { dmes_saved = TRUE; - dmes_savew = dmes_wd; // save for next time + dmes_savew = dmes_wd; /* save for next time */ } else - stuff_dmes(' ', 1); // pad with a space to force out even # of characters + stuff_dmes(' ', 1); /* pad with a space to force out even # of characters */ } } -// --------------------------------------------------------------------------------- -// stuff_dmes - insert 'rpt' copies of character 'ch' into output words -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * stuff_dmes - insert 'rpt' copies of character 'ch' into output words + ********************************************************************************************/ void stuff_dmes (int ch, int rpt) { - int nch, i; // nch is translated output value + int nch, i; /* nch is translated output value */ - if (rpt < 0) { // negative repeat means no translation needed + if (rpt < 0) { /* negative repeat means no translation needed */ rpt = -rpt; nch = ch; } @@ -3166,7 +3270,7 @@ void stuff_dmes (int ch, int rpt) } } - while (--rpt >= 0) { // pack them into words, output when we have two + while (--rpt >= 0) { /* pack them into words, output when we have two */ if (dmes_nc == 0) { dmes_wd = (nch & 0xFF) << 8; dmes_nc = 1; @@ -3179,51 +3283,51 @@ void stuff_dmes (int ch, int rpt) } } -// --------------------------------------------------------------------------------- -// x_ebc - handle EBCDIC string definition (delimited with periods) -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_ebc - handle EBCDIC string definition (delimited with periods) + ********************************************************************************************/ void x_ebc (struct tag_op *op, char *label, char *mods, char *arg) { char *p; -// setw(0, org, FALSE); +/* setw(0, org+listoffset, FALSE); */ if (*label) set_symbol(label, org, TRUE, relocate); - p = trim(opfield); // remove trailing blanks from rest of input line (use whole thing) + p = trim(opfield); /* remove trailing blanks from rest of input line (use whole thing) */ if (*p != '.') { asm_error("EBC data must start with ."); return; } - p++; // skip leading period + p++; /* skip leading period */ - dmes_nc = dmes_wd = 0; // clear output buffer (we're borrowing the DMES packer) + dmes_nc = dmes_wd = 0; /* clear output buffer (we're borrowing the DMES packer) */ dmes_cs = CODESET_EBCDIC; - while (*p && *p != '.') // store packed ebcdic + while (*p && *p != '.') /* store packed ebcdic */ stuff_dmes(*p++, 1); - if (dmes_nc) // odd number of characters - stuff_dmes(' ', 1); // pad with a space to force out even # of characters + if (dmes_nc) /* odd number of characters */ + stuff_dmes(' ', 1); /* pad with a space to force out even # of characters */ if (*p != '.') asm_error("EBC missing closing ."); } -// --------------------------------------------------------------------------------- -// x_dn - define name DN directive. Pack 5 characters into two words. This by the -// way is the reason the language Forth is not Fourth. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_dn - define name DN directive. Pack 5 characters into two words. This by the + * way is the reason the language Forth is not Fourth. + ********************************************************************************************/ void x_dn (struct tag_op *op, char *label, char *mods, char *arg) { unsigned short words[2]; - setw(0, org, FALSE); // display origin + setw(0, org+listoffset, FALSE); /* display origin */ - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); namecode(words, arg); @@ -3232,19 +3336,19 @@ void x_dn (struct tag_op *op, char *label, char *mods, char *arg) writew(words[1], ABSOLUTE); } -// --------------------------------------------------------------------------------- -// x_dump - DUMP directive - pretend we saw "call $dump, call $exit" -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_dump - DUMP directive - pretend we saw "call $dump, call $exit" + ********************************************************************************************/ void x_dump (struct tag_op *op, char *label, char *mods, char *arg) { x_pdmp(op, label, mods, arg); - x_exit(NULL, "", "", ""); // compile "call $exit" + x_exit(NULL, "", "", ""); /* compile "call $exit" */ } -// --------------------------------------------------------------------------------- -// x_pdmp - PDMP directive - like DUMP but without the call $exit -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_pdmp - PDMP directive - like DUMP but without the call $exit + ********************************************************************************************/ void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3259,49 +3363,49 @@ void x_pdmp (struct tag_op *op, char *label, char *mods, char *arg) } } - org_advanced = FALSE; // * means this address+1 + org_advanced = 0; /* * means this address+1 */ format_line(nline, label, "BSI", "L", DOLLARDUMP, ""); - parse_line(nline); // compile "call $dump" + parse_line(nline); /* compile "call $dump" */ - writew(addr[2].value, ABSOLUTE); // append arguments (0, start, end address) + writew(addr[2].value, ABSOLUTE); /* append arguments (0, start, end address) */ writew(addr[0].value, addr[0].relative); writew(addr[1].value, addr[1].relative); } -// --------------------------------------------------------------------------------- -// x_hdng - HDNG directive -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_hdng - HDNG directive + ********************************************************************************************/ void x_hdng (struct tag_op *op, char *label, char *mods, char *arg) { char *c; - // label is not entered into the symbol table + /* label is not entered into the symbol table */ if (flist == NULL || ! list_on) { - line_error = TRUE; // inhibit listing: don't print the HDNG statement + line_error = TRUE; /* inhibit listing: don't print the HDNG statement */ return; } - line_error = TRUE; // don't print the statement + line_error = TRUE; /* don't print the statement */ c = skipbl(opfield); trim(c); - fprintf(flist, "\f%s\n\n", c); // print page header + fprintf(flist, "\f%s\n\n", c); /* print page header */ } -// --------------------------------------------------------------------------------- -// x_list - LIST directive. enable or disable listing -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_list - LIST directive. enable or disable listing + ********************************************************************************************/ void x_list (struct tag_op *op, char *label, char *mods, char *arg) { BOOL on; - // label is not entered into the symbol table + /* label is not entered into the symbol table */ - line_error = TRUE; // don't print the LIST statement + line_error = TRUE; /* don't print the LIST statement */ if (flist == NULL || ! list_on) { return; @@ -3317,75 +3421,75 @@ void x_list (struct tag_op *op, char *label, char *mods, char *arg) list_on = on; } -// --------------------------------------------------------------------------------- -// x_spac - SPAC directive. Put blank lines in listing -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_spac - SPAC directive. Put blank lines in listing + ********************************************************************************************/ void x_spac (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; - // label is not entered into the symbol table + /* label is not entered into the symbol table */ if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the SPAC statement + line_error = TRUE; /* don't print the SPAC statement */ return; } if (getexpr(arg, FALSE, &expr) != S_DEFINED) return; - line_error = TRUE; // don't print the statement + line_error = TRUE; /* don't print the statement */ while (--expr.value >= 0) putc('\n', flist); } -// --------------------------------------------------------------------------------- -// x_ejct - EJCT directive - put formfeed in listing -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_ejct - EJCT directive - put formfeed in listing + ********************************************************************************************/ void x_ejct (struct tag_op *op, char *label, char *mods, char *arg) { - // label is not entered into the symbol table + /* label is not entered into the symbol table */ if (flist == NULL || ! list_on) { - line_error = TRUE; // don't print the EJCT statement + line_error = TRUE; /* don't print the EJCT statement */ return; } - line_error = TRUE; // don't print the statement + line_error = TRUE; /* don't print the statement */ putc('\f', flist); } -// --------------------------------------------------------------------------------- -// basic_opcode - construct a standard opcode value from op table entry and modifier chars -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * basic_opcode - construct a standard opcode value from op table entry and modifier chars + ********************************************************************************************/ int basic_opcode (struct tag_op *op, char *mods) { - int opcode = op->opcode; // basic code value + int opcode = op->opcode; /* basic code value */ - if (strchr(mods, '1') != 0) // indexing + if (strchr(mods, '1') != 0) /* indexing */ opcode |= 0x0100; else if (strchr(mods, '2') != 0) opcode |= 0x0200; else if (strchr(mods, '3') != 0) opcode |= 0x0300; - if (strchr(mods, 'L')) { // two-word format + if (strchr(mods, 'L')) { /* two-word format */ opcode |= OP_LONG; - if (strchr(mods, 'I') != 0) // and indirect to boot + if (strchr(mods, 'I') != 0) /* and indirect to boot */ opcode |= OP_INDIRECT; } return opcode; } -// --------------------------------------------------------------------------------- -// std_op - assemble a vanilla opcode -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * std_op - assemble a vanilla opcode + ********************************************************************************************/ void std_op (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3393,10 +3497,10 @@ void std_op (struct tag_op *op, char *label, char *mods, char *arg) int opcode = basic_opcode(op, mods); BOOL val_ok = FALSE; - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - if (*arg && ! (op->flags & NO_ARGS)) { // get value argument + if (*arg && ! (op->flags & NO_ARGS)) { /* get value argument */ if (getexpr(arg, FALSE, &expr) == S_DEFINED) val_ok = TRUE; } @@ -3405,29 +3509,29 @@ void std_op (struct tag_op *op, char *label, char *mods, char *arg) expr.relative = FALSE; } - if (opcode & OP_LONG) { // two-word format, just write code and value + if (opcode & OP_LONG) { /* two-word format, just write code and value */ writew(opcode, FALSE); writew(expr.value, expr.relative); } - else { // one-word format + else { /* one-word format */ if (strchr(mods, 'I') != 0) asm_error("Indirect mode not permitted on one-word instructions"); if (val_ok && ! (strchr(mods, 'X') || (op->flags & IS_ABS) || ((opcode & OP_INDEXED) && ! (op->flags & NO_IDX)))) - expr.value -= (org+1); // compute displacement + expr.value -= (org+1); /* compute displacement */ - if (expr.value < -128 || expr.value > 127) {// check range + if (expr.value < -128 || expr.value > 127) {/* check range */ asm_error("Offset of %d is too large", expr.value); expr.value = 0; } - writew(opcode | (expr.value & 0x00FF), FALSE);// that's the code + writew(opcode | (expr.value & 0x00FF), FALSE);/* that's the code */ } } -// --------------------------------------------------------------------------------- -// mdx_op - assemble a MDX family instruction -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * mdx_op - assemble a MDX family instruction + ********************************************************************************************/ void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3435,37 +3539,37 @@ void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) int opcode = basic_opcode(op, mods); char *tok; - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - if ((tok = strtok(arg, ",")) == NULL) { // argument format is dest[,increment] -// asm_error("Destination not specified"); // seems not to be an error, IBM omits it sometimes + if ((tok = strtok(arg, ",")) == NULL) { /* argument format is dest[,increment] */ +/* asm_error("Destination not specified"); // seems not to be an error, IBM omits it sometimes */ dest.value = 0; dest.relative = ABSOLUTE; } else - getexpr(tok, FALSE, &dest); // parse the address + getexpr(tok, FALSE, &dest); /* parse the address */ - tok = strtok(NULL, ","); // look for second argument + tok = strtok(NULL, ","); /* look for second argument */ - if (opcode & OP_LONG) { // two word format - if (opcode & OP_INDEXED) { // format: MDX 2 dest + if (opcode & OP_LONG) { /* two word format */ + if (opcode & OP_INDEXED) { /* format: MDX 2 dest */ if (tok != NULL) asm_error("This format takes only one argument"); } - else { // format: MDX dest,increment + else { /* format: MDX dest,increment */ if (opcode & OP_INDIRECT) asm_error("Indirect can't be used without indexing"); if (tok == NULL) { -// asm_error("This format takes two arguments"); +/* asm_error("This format takes two arguments"); */ incr.value = 0; incr.relative = ABSOLUTE; } else getexpr(tok, FALSE, &incr); - if (incr.value < -128 || incr.value > 127) // displacement style (fixed in ver 1.08) + if (incr.value < -128 || incr.value > 127) /* displacement style (fixed in ver 1.08) */ asm_error("Invalid increment value (8 bits signed)"); opcode |= (incr.value & 0xFF); @@ -3474,12 +3578,12 @@ void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) writew(opcode, ABSOLUTE); writew(dest.value, dest.relative); } - else { // one word format MDX val + else { /* one word format MDX val */ if (tok != NULL) asm_error("This format takes only one argument"); if (! (strchr(mods, 'X') || (opcode & OP_INDEXED))) - dest.value -= (org+1); // compute displacement + dest.value -= (org+1); /* compute displacement */ if (dest.value < -128 || dest.value > 127) asm_error("Offset/Increment of %d is too large", dest.value); @@ -3488,9 +3592,9 @@ void mdx_op (struct tag_op *op, char *label, char *mods, char *arg) } } -// --------------------------------------------------------------------------------- -// bsi_op - BSI long instruction is like a BSC L, short is standard -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * bsi_op - BSI long instruction is like a BSC L, short is standard + ********************************************************************************************/ void bsi_op (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3500,9 +3604,9 @@ void bsi_op (struct tag_op *op, char *label, char *mods, char *arg) std_op(op, label, mods, arg); } -// --------------------------------------------------------------------------------- -// b_op - branch; use short or long version -// -------------------------------------------------------------------------------- +/******************************************************************************************** + * b_op - branch; use short or long version + ********************************************************************************************/ void b_op (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3520,9 +3624,9 @@ void b_op (struct tag_op *op, char *label, char *mods, char *arg) (mdx->handler)(mdx, label, mods, arg); } -// --------------------------------------------------------------------------------- -// bsc_op - compute a BSC family instruction -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * bsc_op - compute a BSC family instruction + ********************************************************************************************/ void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3530,11 +3634,11 @@ void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) int opcode = basic_opcode(op, mods); char *tok, *tests; - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - if (opcode & OP_LONG) { // two word format - if ((tok = strtok(arg, ",")) == NULL) { // format is BSC dest[,tests] + if (opcode & OP_LONG) { /* two word format */ + if ((tok = strtok(arg, ",")) == NULL) { /* format is BSC dest[,tests] */ asm_error("Destination not specified"); dest.value = 0; dest.relative = ABSOLUTE; @@ -3542,15 +3646,15 @@ void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) else getexpr(tok, FALSE, &dest); - tests = strtok(NULL, ","); // get test characters + tests = strtok(NULL, ","); /* get test characters */ } else - tests = arg; // short format is BSC tests + tests = arg; /* short format is BSC tests */ - if (tests != NULL) { // stick in the testing bits + if (tests != NULL) { /* stick in the testing bits */ for (; *tests; tests++) { switch (*tests) { - // bit 0x40 is the BOSC bit + /* bit 0x40 is the BOSC bit */ case 'Z': opcode |= 0x20; break; case '-': opcode |= 0x10; break; case '+': @@ -3564,24 +3668,24 @@ void bsc_op (struct tag_op *op, char *label, char *mods, char *arg) } } - writew(opcode, ABSOLUTE); // emit code + writew(opcode, ABSOLUTE); /* emit code */ if (opcode & OP_LONG) writew(dest.value, dest.relative); } -// --------------------------------------------------------------------------------- -// shf_op - assemble a shift instruction -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * shf_op - assemble a shift instruction + ********************************************************************************************/ void shf_op (struct tag_op *op, char *label, char *mods, char *arg) { EXPR expr; int opcode = basic_opcode(op, mods); - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - if (opcode & OP_INDEXED) { // shift value comes from index register + if (opcode & OP_INDEXED) { /* shift value comes from index register */ expr.value = 0; expr.relative = ABSOLUTE; } @@ -3593,32 +3697,32 @@ void shf_op (struct tag_op *op, char *label, char *mods, char *arg) expr.relative = ABSOLUTE; } - if (expr.value < 0 || expr.value > 32) { // check range + if (expr.value < 0 || expr.value > 32) { /* check range */ asm_error("Shift count of %d is invalid", expr.value); expr.value = 0; } - writew(opcode | (expr.value & 0x3F), FALSE); // put shift count into displacement field + writew(opcode | (expr.value & 0x3F), FALSE); /* put shift count into displacement field */ } -// --------------------------------------------------------------------------------- -// x_mdm - MDM instruction -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_mdm - MDM instruction + ********************************************************************************************/ void x_mdm (struct tag_op *op, char *label, char *mods, char *arg) { int opcode = basic_opcode(op, mods); - if (*label) // define label + if (*label) /* define label */ set_symbol(label, org, TRUE, relocate); - // oh dear: bug here + /* oh dear: bug here */ asm_error("'%s' is not yet supported", op->mnem); } -// --------------------------------------------------------------------------------- -// x_exit - EXIT directive. Assembler manual says it treats like CALL $EXIT, but -// object code reveals the truth: jump to $EXIT, which is a small value, so we can use LDX. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_exit - EXIT directive. Assembler manual says it treats like CALL $EXIT, but + * object code reveals the truth: jump to $EXIT, which is a small value, so we can use LDX. + ********************************************************************************************/ void x_exit (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3628,54 +3732,56 @@ void x_exit (struct tag_op *op, char *label, char *mods, char *arg) parse_line(nline); } -// --------------------------------------------------------------------------------- -// x_opt - .OPT directive. Nonstandard. Possible values: -// -// .OPT CEXPR - use C precedence in evaluating expressions rather than strict left-right -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_opt - .OPT directive. Nonstandard. Possible values: + * + * .OPT CEXPR - use C precedence in evaluating expressions rather than strict left-right. The real + * 1130 assembler was left-to-right. Enabling CEXPR enables precedence and makes the + * assembler NON STANDARD. + ********************************************************************************************/ void x_opt (struct tag_op *op, char *label, char *mods, char *arg) { char *tok; - org_advanced = FALSE; // * means this address + org_advanced = 0; /* * means this address */ if (*label) { asm_error("Label not permitted on .OPT statement"); return; } - // look for OPT arguments + /* look for OPT arguments */ for (tok = strtok(arg, ","); tok != NULL; tok = strtok(NULL, ",")) { if (strcmp(tok, "CEXPR") == 0) { - cexpr = TRUE; // use C expression precedence (untested) + cexpr = TRUE; /* use C expression precedence (untested) */ } else asm_error("Unknown .OPT: '%s'", tok); } } -// --------------------------------------------------------------------------------- -// askip - skip input lines until a line with the target label appears -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * askip - skip input lines until a line with the target label appears + ********************************************************************************************/ void askip (char *target) { char nline[200], cur_label[20], *c; - while (get_line(nline, sizeof(nline), TRUE)) { // read next line (but don't exit a macro) - listout(FALSE); // end listing of previous input line + while (get_line(nline, sizeof(nline), TRUE)) { /* read next line (but don't exit a macro) */ + listout(FALSE); /* end listing of previous input line */ - prep_line(nline); // preform standard line prep + prep_line(nline); /* preform standard line prep */ - strncpy(cur_label, nline, 6); // get first 5 characters + strncpy(cur_label, nline, 6); /* get first 5 characters */ cur_label[5] = '\0'; - for (c = cur_label; *c > ' '; c++) // truncate at first whitespace + for (c = cur_label; *c > ' '; c++) /* truncate at first whitespace */ ; *c = '\0'; - // stop if there's a match + /* stop if there's a match */ if ((target == NULL) ? (cur_label[0] == '\0') : strcmp(target, cur_label) == 0) { - parse_line(nline); // process this line + parse_line(nline); /* process this line */ return; } } @@ -3684,9 +3790,9 @@ void askip (char *target) asm_error("Label %s not found", target); } -// --------------------------------------------------------------------------------- -// x_aif - process conditional assembly jump -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_aif - process conditional assembly jump + ********************************************************************************************/ void x_aif (struct tag_op *op, char *label, char *mods, char *arg) { @@ -3695,7 +3801,7 @@ void x_aif (struct tag_op *op, char *label, char *mods, char *arg) BOOL istrue; enum {OP_EQ, OP_LT, OP_GT, OP_NE, OP_LE, OP_GE} cmp_op; - // label is not entered into the symbol table + /* label is not entered into the symbol table */ arg = skipbl(arg); if (*arg != '(') { @@ -3703,10 +3809,10 @@ void x_aif (struct tag_op *op, char *label, char *mods, char *arg) return; } - arg++; // skip the paren + arg++; /* skip the paren */ - // normally whitespace is never found in the arg string (see tabtok and coltok). - // However, spaces inside parens are permitted. + /* normally whitespace is never found in the arg string (see tabtok and coltok). */ + /* However, spaces inside parens are permitted. */ if ((tok = strtok(arg, whitespace)) == NULL) { asm_error("AIF missing first expression"); @@ -3744,7 +3850,7 @@ void x_aif (struct tag_op *op, char *label, char *mods, char *arg) getexpr(tok, FALSE, &expr2); - switch (cmp_op) { // test the condition + switch (cmp_op) { /* test the condition */ case OP_EQ: istrue = expr1.value == expr2.value; break; case OP_LT: istrue = expr1.value < expr2.value; break; case OP_GT: istrue = expr1.value > expr2.value; break; @@ -3754,62 +3860,64 @@ void x_aif (struct tag_op *op, char *label, char *mods, char *arg) default: bail("in aif, can't happen"); } - // After the closing paren coltok and tabtok guarantee we will have no whitespace + /* After the closing paren coltok and tabtok guarantee we will have no whitespace */ - if ((target = strtok(arg, ",")) == NULL) // get target label + if ((target = strtok(arg, ",")) == NULL) /* get target label */ asm_warning("Missing target label"); if (istrue) - askip(target); // skip to the target + askip(target); /* skip to the target */ } -// --------------------------------------------------------------------------------- -// x_aifb - conditional assembly jump back (macro only) -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_aifb - conditional assembly jump back (macro only) + ********************************************************************************************/ void x_aifb (struct tag_op *op, char *label, char *mods, char *arg) { asm_error("aifb valid in macros only and not implemented in any case"); } -// --------------------------------------------------------------------------------- -// x_ago -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_ago + ********************************************************************************************/ void x_ago (struct tag_op *op, char *label, char *mods, char *arg) { char *target; - // label is not entered into the symbol table + /* label is not entered into the symbol table */ - // handle differently in a macro + /* handle differently in a macro */ - if ((target = strtok(arg, ",")) == NULL) // get target label + if ((target = strtok(arg, ",")) == NULL) /* get target label */ asm_warning("Missing target label"); - askip(target); // skip to the target + askip(target); /* skip to the target */ } -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_agob - + ********************************************************************************************/ void x_agob (struct tag_op *op, char *label, char *mods, char *arg) { asm_error("agob valid in macros only and not implemented in any case"); } -// --------------------------------------------------------------------------------- -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * x_anop - + ********************************************************************************************/ void x_anop (struct tag_op *op, char *label, char *mods, char *arg) { - // label is not entered into the symbol table - // do nothing else + /* label is not entered into the symbol table */ + /* do nothing else */ } -// --------------------------------------------------------------------------------- -// expression parser, borrowed from older code, no comments, sorry -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * expression parser, borrowed from older code, no comments, sorry + ********************************************************************************************/ char *exprptr, *oexprptr; @@ -3838,7 +3946,7 @@ void exprerr (int n); void a1130_expr (EXPR *ap); void a1130_term (EXPR *ap); -char ctype[128] = { // character types +char ctype[128] = { /* character types */ /*^0ABCDEFG */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, /*^HIJKLMNO */ ILL, SPACE, SPACE, ILL, SPACE, SPACE, ILL, ILL, /*^PQRSTUVW */ ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, @@ -3858,27 +3966,27 @@ char ctype[128] = { // character types }; char *errstr[] = { - "Missing exponent", // 0 - "Undefined symbol", // 1 - "Division by zero", // 2 - "Illegal operator", // 3 - ") expected", // 4 - "Char expected after '", // 5 - "Char expected after .", // 6 - "Number expected after =", // 7 - "Syntax error", // 8 - "Number syntax", // 9 - "Char expected after \\", // 10 - "Relocation error" // 11 + "Missing exponent", /* 0 */ + "Undefined symbol", /* 1 */ + "Division by zero", /* 2 */ + "Illegal operator", /* 3 */ + ") expected", /* 4 */ + "Char expected after '", /* 5 */ + "Char expected after .", /* 6 */ + "Number expected after =", /* 7 */ + "Syntax error", /* 8 */ + "Number syntax", /* 9 */ + "Char expected after \\", /* 10 */ + "Relocation error" /* 11 */ }; int getnb () { int c; - if (cexpr) { // in C mode, handle normally + if (cexpr) { /* in C mode, handle normally */ while (ctype[(c = GETNEXT)] == SPACE) ; - } // in 1130 mode, a space terminates the expression. Here, eat the rest + } /* in 1130 mode, a space terminates the expression. Here, eat the rest */ else if ((c = GETNEXT) == ' ') { while ((c = GETNEXT) != '\0') ; @@ -3890,37 +3998,37 @@ int getnb () { int symbest, exprerrno; jmp_buf exprjmp; -// --------------------------------------------------------------------------------- -// getexpr -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * getexpr + ********************************************************************************************/ int getexpr (char *pc, BOOL undefined_ok, EXPR *pval) { - symbest = S_DEFINED; // assume no questionable symbols + symbest = S_DEFINED; /* assume no questionable symbols */ pval->value = 0; pval->relative = ABSOLUTE; - if (! *pc) // blank expression is same as zero, ok? + if (! *pc) /* blank expression is same as zero, ok? */ return S_DEFINED; - if (setjmp(exprjmp) != 0) { // encountered a syntax error & bailed + if (setjmp(exprjmp) != 0) { /* encountered a syntax error & bailed */ pval->value = 0; pval->relative = ABSOLUTE; return S_UNDEFINED; } - exprptr = oexprptr = pc; // make global the buffer pointer + exprptr = oexprptr = pc; /* make global the buffer pointer */ c_expr(pval); - if (GETNEXT) // expression should have been entirely eaten - exprerr(8); // if characters are left, it's an error + if (GETNEXT) /* expression should have been entirely eaten */ + exprerr(8); /* if characters are left, it's an error */ if (pval->relative < 0 || pval->relative > 1) - exprerr(11); // has to work out to an absolute or a single relative term + exprerr(11); /* has to work out to an absolute or a single relative term */ - if (symbest == S_DEFINED) // tell how it came out + if (symbest == S_DEFINED) /* tell how it came out */ return S_DEFINED; pval->value = 0; @@ -3928,23 +4036,23 @@ int getexpr (char *pc, BOOL undefined_ok, EXPR *pval) return (pass == 1 && undefined_ok) ? S_PROVISIONAL : S_UNDEFINED; } -// --------------------------------------------------------------------------------- -// output_literals - construct .DC assembler lines to assemble pending literal -// constant values that have accumulated. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * output_literals - construct .DC assembler lines to assemble pending literal + * constant values that have accumulated. + ********************************************************************************************/ void output_literals (BOOL eof) { char line[120], label[12], num[20]; int i; - for (i = 0; i < n_literals; i++) { // generate DC statements for any pending literal constants - if (literal[i].even && literal[i].hex) // create the value string - sprintf(num, "/%08lx", literal[i].value); + for (i = 0; i < n_literals; i++) { /* generate DC statements for any pending literal constants */ + if (literal[i].even && literal[i].hex) /* create the value string */ + sprintf(num, "/%08lX", literal[i].value); else if (literal[i].even) sprintf(num, "%ld", literal[i].value); else if (literal[i].hex) - sprintf(num, "/%04x", literal[i].value & 0xFFFF); + sprintf(num, "/%04X", literal[i].value & 0xFFFF); else sprintf(num, "%d", literal[i].value); @@ -3952,26 +4060,26 @@ void output_literals (BOOL eof) format_line(line, label, literal[i].even ? "DEC" : "DC", "", num, "GENERATED LITERAL CONSTANT"); if (eof) { - eof = FALSE; // at end of file, for first literal, only prepare blank line + eof = FALSE; /* at end of file, for first literal, only prepare blank line */ sprintf(listline, LEFT_MARGIN, org); } else - listout(TRUE); // push out any pending line(s) + listout(TRUE); /* push out any pending line(s) */ - if (flist && list_on) // this makes stuff appear in the listing + if (flist && list_on) /* this makes stuff appear in the listing */ sprintf(listline, LEFT_MARGIN " %s", detab(line)); nwout = 0; - parse_line(line); // assemble the constant definition + parse_line(line); /* assemble the constant definition */ } - n_literals = 0; // clear list + n_literals = 0; /* clear list */ } -// --------------------------------------------------------------------------------- -// a1130_term - extract one term of an expression -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * a1130_term - extract one term of an expression using 1130 assembler syntax (no precedence!) + ********************************************************************************************/ void a1130_term (EXPR *ap) { @@ -3979,7 +4087,7 @@ void a1130_term (EXPR *ap) char token[80], *t; int c; - if (cexpr) { // use C syntax + if (cexpr) { /* use C syntax and operator precedence */ c_term(ap); return; } @@ -4002,7 +4110,7 @@ void a1130_term (EXPR *ap) ap->relative = ABSOLUTE; } else if (c == '*') { /* asterisk alone = org */ - ap->value = org + org_advanced; // here is where that offset matters! + ap->value = org + org_advanced; /* here is where that offset matters! */ ap->relative = relocate; } else if (c == '.') { /* EBCDIC constant */ @@ -4012,7 +4120,7 @@ void a1130_term (EXPR *ap) c = ' '; } c = ascii_to_ebcdic_table[c]; - ap->value = c; // VALUE IS IN LOW BYTE!!! + ap->value = c; /* VALUE IS IN LOW BYTE!!! */ ap->relative = ABSOLUTE; } else if (ctype[c] == LETTER) { /* symbol */ @@ -4029,7 +4137,7 @@ void a1130_term (EXPR *ap) ap->value = s->value; ap->relative = s->relative; - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) + symbest = MIN(symbest, s->defined); /* this goes to lowest value (undefined < provisional < defined) */ if (pass == 2 && s->defined != S_DEFINED) exprerr(1); } @@ -4037,36 +4145,36 @@ void a1130_term (EXPR *ap) exprerr(8); } -// --------------------------------------------------------------------------------- -// signextend - sign-extend a 16-bit constant value to whatever "int" is. -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * signextend - sign-extend a 16-bit constant value to whatever "int" is. + ********************************************************************************************/ int signextend (int v) { - v &= 0xFFFF; // clip to 16 bits (this may not be necessary, but best to be safe?) + v &= 0xFFFF; /* clip to 16 bits (this may not be necessary, but best to be safe?) */ - if (v & 0x8000) // if sign bit is set - v |= ~0xFFFF; // sign extend + if (v & 0x8000) /* if sign bit is set */ + v |= ~0xFFFF; /* sign extend */ return v; } -// --------------------------------------------------------------------------------- -// c_expr - evalate an expression -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_expr - evalate an expression using C syntax + ********************************************************************************************/ void c_expr (EXPR *ap) { int c; EXPR rop; - c_expr_m(ap); // get combined multiplicative terms - for (;;) { // handle +/- precedence operators + c_expr_m(ap); /* get combined multiplicative terms */ + for (;;) { /* handle +/- precedence operators */ if (ctype[c=getnb()] != ADDOP) { UNGET; break; } - c_expr_m(&rop); // right hand operand + c_expr_m(&rop); /* right hand operand */ switch (c) { case '+': ap->value += rop.value; @@ -4090,26 +4198,26 @@ void c_expr (EXPR *ap) } } -// --------------------------------------------------------------------------------- -// c_expr_m - get multiplicative precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_expr_m - get multiplicative precedence terms. Again, this is not usually used + ********************************************************************************************/ void c_expr_m (EXPR *ap) { int c; EXPR rop; - c_expr_e(ap); // get exponential precedence term - for (;;) { // get operator + c_expr_e(ap); /* get exponential precedence term */ + for (;;) { /* get operator */ c = getnb(); if ((c=='<') || (c=='>')) - if (c != getnb()) // << or >> + if (c != getnb()) /* << or >> */ exprerr(3); if (ctype[c] != MULOP) { UNGET; break; } - c_expr_e(&rop); // right hand operand + c_expr_e(&rop); /* right hand operand */ switch(c) { case '*': @@ -4165,9 +4273,9 @@ void c_expr_m (EXPR *ap) } } -// --------------------------------------------------------------------------------- -// c_expr_e - get exponential precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_expr_e - get exponential precedence terms. Again, this is not usually used + ********************************************************************************************/ void c_expr_e (EXPR *ap) { @@ -4200,9 +4308,9 @@ void c_expr_e (EXPR *ap) } } -// --------------------------------------------------------------------------------- -// c_expr_u - get unary precedence terms. Again, this is not usually used -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_expr_u - get unary precedence terms. Again, this is not usually used + ********************************************************************************************/ void c_expr_u (EXPR *ap) { @@ -4226,9 +4334,9 @@ void c_expr_u (EXPR *ap) } } -// --------------------------------------------------------------------------------- -// c_term - get basic operand or parenthesized expression. Again, this is not usually used -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_term - get basic operand or parenthesized expression. Again, this is not usually used + ********************************************************************************************/ void c_term (EXPR *ap) { @@ -4277,7 +4385,7 @@ void c_term (EXPR *ap) ap->value = s->value; ap->relative = s->relative; add_xref(s, FALSE); - symbest = MIN(symbest, s->defined); // this goes to lowest value (undefined < provisional < defined) + symbest = MIN(symbest, s->defined); /* this goes to lowest value (undefined < provisional < defined) */ if (pass == 2 && s->defined != S_DEFINED) exprerr(1); @@ -4286,9 +4394,9 @@ void c_term (EXPR *ap) exprerr(8); } -// --------------------------------------------------------------------------------- -// c_number - get a C format constant value. Again, this is not usually used -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_number - get a C format constant value. Again, this is not usually used + ********************************************************************************************/ int c_number (int c, int r, int nchar) { @@ -4321,7 +4429,7 @@ int c_number (int c, int r, int nchar) n = r*n + v; c = GETNEXT; - if (c == '.') { // maybe make it decimal? + if (c == '.') { /* maybe make it decimal? */ c = GETNEXT; break; } @@ -4331,9 +4439,9 @@ int c_number (int c, int r, int nchar) return (n); } -// --------------------------------------------------------------------------------- -// digit - get digit value of character c in radix r -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * digit - get digit value of character c in radix r + ********************************************************************************************/ int digit (int c, int r) { @@ -4348,9 +4456,9 @@ int digit (int c, int r) return (-1); } -// --------------------------------------------------------------------------------- -// c_esc - handle C character escape -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * c_esc - handle C character escape + ********************************************************************************************/ int c_esc (int c) { @@ -4377,16 +4485,16 @@ int c_esc (int c) return c; } -// --------------------------------------------------------------------------------- -// exprerr - note an expression syntax error. Longjumps back to caller with failure code -// --------------------------------------------------------------------------------- +/******************************************************************************************** + * exprerr - note an expression syntax error. Longjumps back to caller with failure code + ********************************************************************************************/ void exprerr (int n) { char msg[256]; int nex = exprptr-oexprptr; - strncpy(msg, oexprptr, nex); // show where the problem was + strncpy(msg, oexprptr, nex); /* show where the problem was */ msg[nex] = '\0'; strcat(msg, " << "); strcat(msg, errstr[n]); @@ -4397,9 +4505,9 @@ void exprerr (int n) longjmp(exprjmp, 1); } -/* ------------------------------------------------------------------------ +/******************************************************************************************** * upcase - force a string to uppercase (ASCII) - * ------------------------------------------------------------------------ */ + ********************************************************************************************/ char *upcase (char *str) { @@ -4413,9 +4521,9 @@ char *upcase (char *str) return str; } -/* ------------------------------------------------------------------------ +/******************************************************************************************** * hollerith table for IPL card ident field - * ------------------------------------------------------------------------ */ + ********************************************************************************************/ typedef struct { int hollerith; @@ -4425,7 +4533,7 @@ typedef struct { static CPCODE cardcode_029[] = { 0x0000, ' ', - 0x8000, '&', // + in 026 Fortran + 0x8000, '&', /* + in 026 Fortran */ 0x4000, '-', 0x2000, '0', 0x1000, '1', @@ -4465,14 +4573,14 @@ static CPCODE cardcode_029[] = 0x2020, 'Y', 0x2010, 'Z', 0x0820, ':', - 0x0420, '#', // = in 026 Fortran - 0x0220, '@', // ' in 026 Fortran + 0x0420, '#', /* = in 026 Fortran */ + 0x0220, '@', /* ' in 026 Fortran */ 0x0120, '\'', 0x00A0, '=', 0x0060, '"', - 0x8820, 'c', // cent + 0x8820, 'c', /* cent */ 0x8420, '.', - 0x8220, '<', // ) in 026 Fortran + 0x8220, '<', /* ) in 026 Fortran */ 0x8120, '(', 0x80A0, '+', 0x8060, '|', @@ -4481,15 +4589,19 @@ static CPCODE cardcode_029[] = 0x4220, '*', 0x4120, ')', 0x40A0, ';', - 0x4060, 'n', // not - 0x2820, 'x', // what? + 0x4060, 'n', /* not */ + 0x2820, 'x', /* what? */ 0x2420, ',', - 0x2220, '%', // ( in 026 Fortran + 0x2220, '%', /* ( in 026 Fortran */ 0x2120, '_', 0x20A0, '>', 0x2060, '>', }; +/******************************************************************************************** + * ascii_to_hollerith - + ********************************************************************************************/ + int ascii_to_hollerith (int ch) { int i; @@ -4501,9 +4613,9 @@ int ascii_to_hollerith (int ch) return 0; } -/* ------------------------------------------------------------------------ +/******************************************************************************************** * detab - replace tabs with spaces for listing files - * ------------------------------------------------------------------------ */ + ********************************************************************************************/ char *detab (char *instr) { @@ -4534,25 +4646,29 @@ char *detab (char *instr) #ifndef _WIN32 +/******************************************************************************************** + * routines provided by Microsoft C but not others + ********************************************************************************************/ + int strnicmp (char *a, char *b, int n) { int ca, cb; for (;;) { - if (--n < 0) // still equal after n characters? quit now + if (--n < 0) /* still equal after n characters? quit now */ return 0; - if ((ca = *a) == 0) // get character, stop on null terminator + if ((ca = *a) == 0) /* get character, stop on null terminator */ return *b ? -1 : 0; - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase + if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */ ca -= 32; cb = *b; if (cb >= 'a' && cb <= 'z') cb -= 32; - if ((ca -= cb) != 0) // if different, return comparison + if ((ca -= cb) != 0) /* if different, return comparison */ return ca; a++, b++; @@ -4564,17 +4680,17 @@ int strcmpi (char *a, char *b) int ca, cb; for (;;) { - if ((ca = *a) == 0) // get character, stop on null terminator + if ((ca = *a) == 0) /* get character, stop on null terminator */ return *b ? -1 : 0; - if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase + if (ca >= 'a' && ca <= 'z') /* fold lowercase to uppercase */ ca -= 32; cb = *b; if (cb >= 'a' && cb <= 'z') cb -= 32; - if ((ca -= cb) != 0) // if different, return comparison + if ((ca -= cb) != 0) /* if different, return comparison */ return ca; a++, b++; diff --git a/Ibm1130/utils/bindump.c b/Ibm1130/utils/bindump.c index 8efa8ccf..8865edf3 100644 --- a/Ibm1130/utils/bindump.c +++ b/Ibm1130/utils/bindump.c @@ -36,35 +36,53 @@ typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC; +typedef enum {PACKED, UNPACKED} PACKMODE; + +#define CARDTYPE_COREIMAGE 0x00 +#define CARDTYPE_ABS 0x01 +#define CARDTYPE_REL 0x02 +#define CARDTYPE_LIB 0x03 +#define CARDTYPE_SUB 0x04 +#define CARDTYPE_ISSL 0x05 +#define CARDTYPE_ISSC 0x06 +#define CARDTYPE_ILS 0x07 +#define CARDTYPE_END 0x0F +#define CARDTYPE_ENDC 0x80 +#define CARDTYPE_81 0x81 +#define CARDTYPE_DATA 0x0A + BOOL verbose = FALSE; BOOL phid = FALSE; BOOL sort = FALSE; -unsigned short card[80], buf[54], cardtype; +unsigned short card[80], buf[54]; // bindump - dump a binary (card format) deck to verify sbrks, etc -void bail (char *msg); -void dump (char *fname); -void dump_data (char *fname); -void dump_phids (char *fname); -char *getname (unsigned short *ptr); -char *getseq (void); -int hollerith_to_ascii (unsigned short h); -void process (char *fname); -void show_raw (char *name); -void show_data (void); -void show_core (void); -void show_endc (void); -void show_81 (void); -void show_main (void); -void show_sub (void); -void show_ils (void); -void show_iss (void); -void show_end (void); -void sort_phases (char *fname); -void trim (char *s); -void unpack (unsigned short *card, unsigned short *buf); -void verify_checksum(unsigned short *buf); +void bail (char *msg); +void dump (char *fname); +void dump_data (char *fname); +void dump_phids (char *fname); +char *getname (unsigned short *ptr); +char *getseq (void); +int hollerith_to_ascii (unsigned short h); +void process (char *fname); +void show_raw (char *name); +void show_data (void); +void show_core (void); +void show_endc (void); +void show_81 (void); +void show_main (void); +void show_sub (void); +void show_ils (void); +void show_iss (void); +void show_end (void); +void sort_phases (char *fname); +void trim (char *s); +void unpack (unsigned short *icard, unsigned short *obuf, int nwords); +void pack (unsigned short *ocard, unsigned short *ibuf); +void verify_checksum(unsigned short *buf); +int type_of_card(unsigned short *buf, PACKMODE packed); +char *card_type_name (unsigned short cardtype); int main (int argc, char **argv) { @@ -99,6 +117,7 @@ int main (int argc, char **argv) if (*arg != '-') process(arg); } + return 0; } @@ -188,6 +207,12 @@ void sort_phases (char *fname) ncards = len / 160; + if (ncards <= 0) { + fprintf(stderr, "%s: can't sort, empty deck\n"); + fclose(fd); + return; + } + if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) { fprintf(stderr, "%s: can't sort, insufficient memory\n"); fclose(fd); @@ -203,31 +228,39 @@ void sort_phases (char *fname) return; } - unpack(deck[i].card, buf); - deck[i].seq = seq++; - deck[i].phid = phid; + deck[i].seq = seq++; // store current sequence + deck[i].phid = phid; // store current phase ID - verify_checksum(buf); + cardtype = type_of_card(deck[i].card, PACKED); - cardtype = (buf[2] >> 8) & 0xFF; + switch (cardtype) { + case CARDTYPE_ABS: // start of deck is same as sector break + saw_sbrk = TRUE; // (though I don't ever expect to get a REL deck) + break; - if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break - saw_sbrk = TRUE; - } - else if (cardtype == 0) { - fprintf(stderr, "%s is a core image deck\n"); - free(deck); - fclose(fd); - return; - } - else if (cardtype == 0x0A && saw_sbrk) { - phid = (int) (signed short) buf[10]; - if (phid < 0) - phid = -phid; + case CARDTYPE_DATA: + if (saw_sbrk) { + unpack(deck[i].card, buf, 0); + verify_checksum(buf); - deck[i].phid = phid; // this belongs to the new phase - deck[i-1].phid = phid; // as does previous card - saw_sbrk = FALSE; + phid = (int) (signed short) buf[10]; + if (phid < 0) + phid = -phid; + + deck[i].phid = phid; // this belongs to the new phase + deck[i-1].phid = phid; // as does previous card (START or SBRK card) + saw_sbrk = FALSE; + } + break; + + case CARDTYPE_END: + break; + + default: + fprintf(stderr, "%s is a %s deck, can't sort\n", card_type_name(cardtype)); + free(deck); + fclose(fd); + return; } } fclose(fd); @@ -235,11 +268,21 @@ void sort_phases (char *fname) qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck #ifdef _WIN32 - _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode + _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode #endif - for (i = 0; i < ncards; i++) // write to stdout - fxwrite(deck[i].card, sizeof(card[0]), 80, stdout); + for (i = 0; i < ncards; i++) { // write to stdout + cardtype = type_of_card(deck[i].card, PACKED); + if (cardtype != CARDTYPE_END || (i == (ncards-1))) // don't write embedded END cards + fxwrite(deck[i].card, sizeof(deck[i].card[0]), 80, stdout); + } + + if (cardtype != CARDTYPE_END) { // fudge an end card + memset(buf, 0, sizeof(buf)); + buf[2] = CARDTYPE_END; + pack(card, buf); + fxwrite(card, sizeof(card[0]), 80, stdout); + } free(deck); } @@ -247,8 +290,8 @@ void sort_phases (char *fname) void dump_phids (char *fname) { FILE *fp; - BOOL first = TRUE; - BOOL saw_sbrk = TRUE, neg; + BOOL saw_sbrk = FALSE, neg; + unsigned short cardtype; short id; if ((fp = fopen(fname, "rb")) == NULL) { @@ -259,49 +302,46 @@ void dump_phids (char *fname) printf("\n%s:\n", fname); while (fxread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); - verify_checksum(buf); + cardtype = type_of_card(card, PACKED); - cardtype = (buf[2] >> 8) & 0xFF; - - if (cardtype == 1 && ! first) { // sector break - saw_sbrk = TRUE; - continue; + if (saw_sbrk && cardtype != CARDTYPE_DATA) { + printf("DECK STRUCTURE ERROR: ABS/SBRK card was followed by %s, not DATA", card_type_name(cardtype)); } - else { - switch (cardtype) { - case 0x00: - printf(" This is a core image deck\n"); - goto done; - break; - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x0F: - break; - case 0x0A: - if (saw_sbrk) { - id = buf[10]; - if (id < 0) - id = -id, neg = TRUE; - else - neg = FALSE; - printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : ""); - saw_sbrk = FALSE; - } - break; + switch (cardtype) { + case CARDTYPE_ABS: // beginning of absolute deck, or SBRK card (which spoofs an ABS start card) + saw_sbrk = TRUE; + break; - default: - show_raw("??? "); - } + case CARDTYPE_END: + break; + + case CARDTYPE_DATA: + if (saw_sbrk) { // first data card after a SBRK or new deck has the phase ID + unpack(card, buf, 11); + id = buf[10]; + if (id < 0) + id = -id, neg = TRUE; + else + neg = FALSE; + printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : ""); + saw_sbrk = FALSE; + } + break; + + case CARDTYPE_COREIMAGE: + case CARDTYPE_REL: + case CARDTYPE_LIB: + case CARDTYPE_SUB: + case CARDTYPE_ISSL: + case CARDTYPE_ISSC: + case CARDTYPE_ILS: + printf("%s module not expected in a system load deck\n", card_type_name(cardtype)); + break; + + default: + show_raw("??? "); } -done: - first = FALSE; } fclose(fp); @@ -311,6 +351,7 @@ void dump_data (char *fname) { FILE *fp; BOOL first = TRUE; + unsigned short cardtype; char str[80]; int i; @@ -322,10 +363,10 @@ void dump_data (char *fname) printf("\n%s:\n", fname); while (fxread(card, sizeof(card[0]), 80, fp) > 0) { - unpack(card, buf); + unpack(card, buf, 0); verify_checksum(buf); - cardtype = (buf[2] >> 8) & 0xFF; + cardtype = type_of_card(buf, UNPACKED); if (cardtype == 1 && ! first) { // sector break for (i = 4; i < 72; i++) @@ -338,54 +379,54 @@ void dump_data (char *fname) } else { switch (cardtype) { - case 0x00: + case CARDTYPE_COREIMAGE: if (first) show_raw("CORE"); if (verbose) show_core(); break; - case 0x01: + case CARDTYPE_ABS: show_raw("ABS "); show_main(); break; - case 0x02: + case CARDTYPE_REL: show_raw("REL "); show_main(); break; - case 0x03: + case CARDTYPE_LIB: show_raw("LIB "); show_sub(); break; - case 0x04: + case CARDTYPE_SUB: show_raw("SUB "); show_sub(); break; - case 0x05: + case CARDTYPE_ISSL: show_raw("ISSL"); show_iss(); break; - case 0x06: + case CARDTYPE_ISSC: show_raw("ISSC"); show_iss(); break; - case 0x07: + case CARDTYPE_ILS: show_raw("ILS "); show_ils(); break; - case 0x0F: + case CARDTYPE_END: show_raw("END "); show_end(); break; - case 0x80: + case CARDTYPE_ENDC: show_raw("ENDC"); show_endc(); break; - case 0x81: + case CARDTYPE_81: show_raw("81 "); show_81(); break; - case 0x0A: + case CARDTYPE_DATA: if (verbose) show_data(); break; @@ -584,20 +625,40 @@ void bail (char *msg) exit(1); } -void unpack (unsigned short *icard, unsigned short *obuf) +// unpack nwords of data from card image icard into buffer obuf + +void unpack (unsigned short *icard, unsigned short *obuf, int nwords) { int i, j; unsigned short wd1, wd2, wd3, wd4; - for (i = j = 0; i < 54; i += 3, j += 4) { - wd1 = icard[j]; - wd2 = icard[j+1]; - wd3 = icard[j+2]; - wd4 = icard[j+3]; + if (nwords <= 0 || nwords > 54) nwords = 54; // the default is to unpack all 54 words - obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); - obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); - obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); + for (i = j = 0; i < nwords; i++) { + wd1 = icard[j++]; + wd2 = icard[j++]; + wd3 = icard[j++]; + wd4 = icard[j++]; + + obuf[i] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F); + if (++i >= nwords) break; + obuf[i] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF); + if (++i >= nwords) break; + obuf[i] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF); + } +} + +// pack - pack 54 words of data in ibuf into card image icard + +void pack (unsigned short *ocard, unsigned short *ibuf) +{ + int i, j; + + for (i = j = 0; i < 54; i += 3, j += 4) { + ocard[j ] = ( ibuf[i] & 0xFFF0); + ocard[j+1] = ((ibuf[i] << 12) & 0xF000) | ((ibuf[i+1] >> 4) & 0x0FF0); + ocard[j+2] = ((ibuf[i+1] << 8) & 0xFF00) | ((ibuf[i+2] >> 8) & 0x00F0); + ocard[j+3] = ((ibuf[i+2] << 4) & 0xFFF0); } } @@ -752,4 +813,35 @@ char *getname (unsigned short *ptr) return str; } +int type_of_card (unsigned short *buf, PACKMODE packed) +{ + unsigned short unp[3]; + // card type is the 3rd unpacked word on the card + + if (packed == PACKED) { + unpack(buf, unp, 3); // unpack the first 3 words only + buf = unp; + } + + return (buf[2] >> 8) & 0xFF; +} + +char * card_type_name (unsigned short cardtype) +{ + switch (cardtype) { + case CARDTYPE_COREIMAGE: return "core image"; + case CARDTYPE_ABS: return "absolute"; + case CARDTYPE_REL: return "relative"; + case CARDTYPE_LIB: return "LIB"; + case CARDTYPE_SUB: return "SUB"; + case CARDTYPE_ISSL: return "ISSL"; + case CARDTYPE_ISSC: return "ISSC"; + case CARDTYPE_ILS: return "ILS"; + case CARDTYPE_END: return "END"; + case CARDTYPE_ENDC: return "ENDC"; + case CARDTYPE_81: return "81"; + case CARDTYPE_DATA: return "data"; + } + return "unknown"; +} diff --git a/Ibm1130/utils/disklist.c b/Ibm1130/utils/disklist.c new file mode 100644 index 00000000..406f367a --- /dev/null +++ b/Ibm1130/utils/disklist.c @@ -0,0 +1,1547 @@ +// ------------------------------------------------------------------------------------------- +// DISKLIST - print directory listing of DMS2 disk image +// ------------------------------------------------------------------------------------------- + +/* + * (C) Copyright 2004, Brian Knittel. + * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN + * RISK basis, there is no warranty of fitness for any purpose, and the rest of the + * usual yada-yada. Please keep this notice and the copyright in any distributions + * or modifications. + */ + +// ------------------------------------------------------------------------------------------- +// HISTORY +// ------------------------------------------------------------------------------------------- +// 24-Nov-2004 Written. It would be nice to make this distinguish a DMS disk from +// other potential disk formats (e.g. APL\1130). +// +// 03-Dec-2004 Split get_let and print_let so we could get listings for specific files. +// 06-Dec-2004 Added printout of detailed file info (print_xxx_info) and dump, and listing of calls +// 21-Dec-2006 Added file type column in standard output mode +// ------------------------------------------------------------------------------------------- + +#include +#include +#include +#include "util_io.h" + +// ------------------------------------------------------------------------------------------- +// DEFINITIONS +// ------------------------------------------------------------------------------------------- + +typedef int BOOL; // boolean +typedef unsigned short uint16; // unsigned 16-bit integer +typedef short int16; // signed 16-bit integer + +#define TRUE 1 // BOOL values +#define FALSE 0 + +#define ALLOCATE(obj) ((obj *) calloc(1, sizeof(obj))) // macro to allocate an object and return pointer to it + +#define SEC_WORDS 320 // useful words per sector +#define SEC_BYTES 640 // bytes per sector +#define PHY_WORDS 321 // physical words per sector +#define SLET_LENGTH 160 // size of SLET (2 sectors of 4 words per entry) +#define SEC_BLOCKS 16 // disk blocks per sector +#define BLK_WORDS 20 // size of a "disk block", a sub-sector +#define BLK_BYTES 40 + +#define THOUSANDS_SEP ',' // thousands separator (eg. 9,999,999) + // (in Europe, define as '.', or comment out definition) + +typedef struct tag_letentry { // linked list node for directory entry + struct tag_letentry *next; + char name[6]; // file name (1-5 chars) + uint16 filetype; // file image type + uint16 dbcount; // length in DMS "disk blocks" (20 words per block) + uint16 dbaddr; // disk block address + struct tag_letentry *master; // master entry, if this is an alternate name entry + BOOL dummy; // TRUE if this is a 1DUMY entry +} LETENTRY; + +typedef struct tag_filearg { // node in linked list of filename arguments + struct tag_filearg *next; + char *name; +} FILEARG; + +static char *progtype_nm[16] = { // DMS2 program types for DSF format files + "Undefined", "Mainline, absolute", "Mainline, relocatable", "LIBF Subprogram", + "CALL Subprogram", "LIBF Interrupt Service Subroutine (ISS)", + "CALL Interrupt Service Subroutine (ISS)", "Interrupt Level Subroutine (ILS)", + "Undefined", "Undefined", "Undefined", "Undefined", + "Undefined", "Undefined", "Undefined", "Undefined" +}; + +struct { // DMS2 program subtypes for DSF format files + unsigned progtype; + unsigned subtype; + char *descr; +} subtype_nm[] = { + 3, 0, "In-core subprogram", + 3, 1, "FORTRAN Disk IO subroutine", + 3, 2, "Arithmetic subroutine", + 3, 3, "FORTRAN non-disk IO and \"Z\" conversion subroutine", + 5, 3, "\"Z\" device suboutine", + 5, 0, NULL, // NULL suppresses printing of subtype + 4, 0, "In-core subprogram", + 4, 8, "Function subprogram", + 7, 1, "Dummy ILS02 or ILS04", +}; +#define N_SUBTYPE_NMS (sizeof(subtype_nm) / sizeof(subtype_nm[0])) + +#pragma pack(1) + +typedef struct tag_dsf_program_header { // header block of a DSF format file, disk layout + uint16 zero1; + uint16 checksum; + uint16 type; + uint16 proglen; // effective length, terminal address + uint16 commonlen; // length of common + uint16 hdr_len9; // length of this header - 9 + uint16 zero2; + uint16 dblen; // length of program including header in disk blocks (20 wds) + uint16 fortran_info; + union { + struct { // normal programs: entry point information. 1-15. Actual number is hdr_len9/3 + uint16 name[2]; + uint16 addr; + } entry[15]; + struct { // ISS (types 5 and 6) + uint16 name[2]; + uint16 addr; + uint16 iss_50; // ISS number + 50 + uint16 issnumber; // ISS number + uint16 nlevels; // # of levels required (1 or 2) + uint16 level[2]; // interrupt level associated with interrupt (nlevels entries used) + } iss; + struct { // ILS (type 7) + uint16 name[2]; + uint16 addr; + uint16 level; // interrupt level + } ils; + } x; +} DSF_PROGRAM_HEADER; + +typedef struct tag_dci_program_header { // header of a DCI (core image) format file, disk layout + uint16 xeqa; // execute address + uint16 cmon; // length of COMMON + uint16 dreq; // disk IO indicator, /FFFF for DISKZ, 0000 for DISK1, 0001 for DISKN + uint16 file; // number of files defined + uint16 hwct; // length of core image header in words + uint16 lsct; // sector count of files in system WS + uint16 ldad; // loading address of core load + uint16 xctl; // exit control address for DISK1/N + uint16 tvwc; // length of transfer vector in words + uint16 wcnt; // length, in words of the core load, core image header and transfer vector + uint16 xr3x; // setting for index register 3 during execution of core load + uint16 itv[6]; // ITV (values of words 8-13 during execution) + uint16 reserved1; + uint16 ibt[8]; // IBT for ILS04. interrupt entry for ISS of 1231 (3 words), 1403, 2501, 1442, keyboard/prt, 1134/1055 respectively + uint16 ovsw; // sector count of LOCALs/SOCALs + uint16 core; // core size of system on which core load was built + uint16 reserved2[2]; + uint16 hend; // last word of header +} DCI_PROGRAM_HEADER; + +#pragma pack() + +// ------------------------------------------------------------------------------------------- +// GLOBALS +// ------------------------------------------------------------------------------------------- + +#define FILETYPE_DSF 0 // DMS2 filetypes. Type 1 is undefined +#define FILETYPE_1 1 +#define FILETYPE_DCI 2 +#define FILETYPE_DDF 3 + +uint16 defective[3] = {0xFFFF, 0xFFFF, 0xFFFF}; // defective cylinder table, number is 1st sector number of bad cylinder +FILE *fd; // stream for open disk image file +BOOL verbose = FALSE; // verbose switch +BOOL show_all = FALSE; // switch to display alternate file entries +BOOL dumpslet = FALSE; // dump SLET switch +BOOL do_dump = FALSE; +char *ftname[4] = {"DSF", "???", "DCI", "DDF"}; // DMS2 filetype names + +LETENTRY *flet = NULL, *let = NULL; // pointers to contents of FLET and LET + +#pragma pack(1) // (don't pad struct elements) + +struct { // buffer for one sector + uint16 secno; + uint16 data[SEC_WORDS]; +} sector; + +struct { // structure of the SLET on disk + uint16 id; + uint16 addr; + uint16 size; + uint16 secno; +} slet[SLET_LENGTH]; + +struct { // DCOM sector + uint16 _dummy0; + uint16 _dummy1; + uint16 _dummy2; + uint16 _dummy3; + uint16 name[2]; // 4 name of program + uint16 dbct; // 6 disk block count of program + uint16 fcnt; // 7 files indicator + uint16 sysc; // 8 system cartridge indicator switch + uint16 jbsw; // 9 temporary job switch (nonzero = JOB T) + uint16 cbsw; // 10 clb switch (nonzero = storeci) + uint16 lcnt; // 11 local indicator (# of locals) + uint16 mpsw; // 12 core map desired switch + uint16 mdf1; // 13 no. of dup ctrl rcds (modif) + uint16 mdf2; // 14 addr of modif buffer + uint16 ncnt; // 15 nocal indicator + uint16 enty; // 16 rel entry addr of program + uint16 rp67; // 17 1442-5 switch (nonzero = mod 6 or 7) + uint16 todr; // 18 -to- wk stg drive code + uint16 frdr; // 19 -from- wk stg drive code + uint16 fhol; // 20 addr of largest hole in fxa + uint16 fsze; // 21 blk cnt largest hole in fxa + uint16 uhol; // 22 addr of largest hole in ua + uint16 usze; // 23 blk cnt largest hole in ua + uint16 dcsw; // 24 dup call switch + uint16 piod; // 25 principal IO device indicator + uint16 pptr; // 26 print print device indicator + uint16 ciad; // 27 sctr 0 loc of cil sctr addr + uint16 cain; // 28 avail cartridge indicator + uint16 grph; // 29 2250 indicator + uint16 gcnt; // 30 g2260 count + uint16 locw; // 31 local call locals sw + uint16 x3sw; // 32 special ils sw + uint16 ecnt; // 33 equat count + uint16 _dummy34; // 34 + uint16 andu[5]; // 35 end of UA address (adj) + uint16 bndu[5]; // 40 end of UA address (base) + uint16 fpad[5]; // 45 file protected address + uint16 pcid[5]; // 50 available cartridge IDs (physical drvs 0..4) + uint16 cidn[5]; // 55 cartridge ID (logical drvs 0..4) + uint16 ciba[5]; // 60 sector address of CIB + uint16 scra[5]; // 65 sector address of SCRA + uint16 fmat[5]; // 70 format of program in WS + uint16 flet[5]; // 75 FLET sector address + uint16 ulet[5]; // 80 LET sector address + uint16 wsct[5]; // 85 BLK count of program in WS + uint16 cshn[5]; // 90 1+sctr addr of end of cusn. +} dcom; + +#pragma pack() + +BOOL is_system = FALSE; // TRUE if this is a system disk + +// NOTE: in DMS, disk blocks are 1/16 of a sector (20 words) -- DMS suballocates sectors for files. Some +// files have to start on a sector boundary, and there are 1DUMY entries for the little lost bits. The last +// 1DUMY entry in the LET is the size of Working Storage. + +// ------------------------------------------------------------------------------------------- +// PROTOTYPES +// ------------------------------------------------------------------------------------------- + +void getsec (uint16 secno); // read sector by number +void getdata (void *buf, uint16 dbaddr, uint16 offset, uint16 nwords); // read data from file relative to its disk block address +void bail (char *msg); // print error message and exit +void print_slet (void); // print contents of SLET +void get_let (LETENTRY **listhead, uint16 secno); // read FLET or LET, building linked list +void print_let (char *title, LETENTRY *listhead); // print contents of FLET or LET +void list_named_files (char *name, char *image) ; // print info for specified file(s) +void print_onefile (LETENTRY *entry, BOOL in_flet); // print detailed info about one particular file +int ebcdic_to_ascii (int ch); // convert EBCDIC character to ASCII +void convert_namecode (uint16 *namecode, char *name); // convert DMS name code words into ASCII filename +char *upcase (char *str); // convert string to upper case +void commas (int n, int width); // print number n with commas +char *astring (char *str); // allocate memory for and return copy of string +void print_dsf_info (LETENTRY *entry); // print information about a Disk System Format file +void print_dci_info (LETENTRY *entry); // print information about a Disk Core Image file +void print_ddf_info (LETENTRY *entry); // print information about a Disk Data Format file +char * file_progtype (LETENTRY *entry); // description of module type + +// ------------------------------------------------------------------------------------------- +// main - main routine +// ------------------------------------------------------------------------------------------- + +int main (int argc, char **argv) +{ + int i; + char *arg, cartid[10]; + char *image = NULL; + FILEARG *fileargs = NULL, *filearg, *filearg_tail = NULL; + char *usestr = "Usage: disklist [-sadv] diskfile [filename ...]\n" + "\n" + "Lists contents of fixed and user area directories in IBM 1130 DMS 2\n" + "disk image file \"diskfile\". With the optional filename argument(s)\n" + "(1-5 letters), prints detailed information about the named file(s).\n" + "Wildcard characters ? and * may be specfied in the filename." + "\n" + " -s dump SLET in addition to fixed and user areas\n" + " -a dump additional information including alternate entries and addresses\n" + " For named file(s), prints information about entry points and calls\n" + " -d dumps contents of named file(s) in hex\n" + " -v verbose mode, prints internal information\n"; + + for (i = 1; i < argc; i++) { // scan command line arguments + arg = argv[i]; + if (*arg == '-') { // command line switch + arg++; // skip over the - + while (*arg) { // process all flags + switch (*arg++) { + case 'v': + verbose = TRUE; // -v turns on verbose mode + break; + case 'a': + show_all = TRUE; // -a turns on listing of alternate file entries & pad spaces + break; + case 's': // -s turns on dump slet + dumpslet = TRUE; + break; + case 'd': + do_dump = TRUE; + break; + default: + bail(usestr); // unrecognized flag + } + } + } + else if (image == NULL) + image = arg; // first name is the name of disk image file + else { + filearg = ALLOCATE(FILEARG); // subsequent names are filename arguments, + filearg->name = upcase(astring(arg)); // copy to a FILEARG object (as uppercase) + filearg->next = NULL; + + if (fileargs == NULL) // add to end of linked list + fileargs = filearg; + else + filearg_tail->next = filearg; + + filearg_tail = filearg; + } + } + + if (image == NULL) // filename was not specified + bail(usestr); + + if ((fd = fopen(image, "rb")) == NULL) { // open file in binary mode + perror(image); // print reason for open failure and exit + return 1; + } + + getsec(0); // get sector 0, which has defective cylinder table + + defective[0] = sector.data[0]; // load defective cylinder table + defective[1] = sector.data[1]; + defective[2] = sector.data[2]; + + if (verbose) + printf("Defective cylinder table: %04x %04x %04x\n", defective[0], defective[1], defective[2]); + + printf("Filename: %s", image); + + sprintf(cartid, "%04x", sector.data[3]); // display cartridge ID in upper case + printf(" Cartridge ID: %s", upcase(cartid)); + if (show_all) + printf(" Copy: number %d", sector.data[4]); + + printf("\n\n"); + + getsec(1); // get sector 1, save to DCOM + memcpy(&dcom, sector.data, min(sizeof(dcom), SEC_BYTES)); + + is_system = dcom.sysc != 0; // is this a system cartridge? + + if (dumpslet) { // display SLET + if (is_system) { + getsec(3); + memcpy(slet+0, sector.data, SEC_BYTES); + getsec(4); + memcpy(slet+80, sector.data, SEC_BYTES); + + print_slet(); + } + else + printf("(Not a system cartridge, no SLET)\n\n"); + } + + if (dcom.flet[0] != 0) // do we have a FLET? + get_let(&flet, dcom.flet[0]); // read it + + get_let(&let, dcom.ulet[0]); // read LET + + if (fileargs == NULL) { // if there are no filename arguments + if (flet != NULL) // print FLET and LET + print_let("FIXED AREA", flet); + + print_let("USER AREA", let); + } + else { // print information for specified file(s) + for (filearg = fileargs; filearg != NULL; filearg = filearg->next) + list_named_files(filearg->name, image); + } + + return 0; +} + +// ------------------------------------------------------------------------------------------- +// upcase - force a string to uppercase (ASCII) +// ------------------------------------------------------------------------------------------- + +char *upcase (char *str) +{ + char *s; + + for (s = str; *s; s++) { + if (*s >= 'a' && *s <= 'z') + *s -= 32; + } + + return str; +} + +// ------------------------------------------------------------------------------------------- +// commas - print n as a decimal number with commas; width is minimum width +// ------------------------------------------------------------------------------------------- + +void commas (int n, int width) +{ + char fmt[20]; +#ifdef THOUSANDS_SEP + int nchar; + char tmp[20], *cin, *cout; + + sprintf(tmp, "%d", n); // format number n into string + nchar = strlen(tmp); // get length of string + + for (cin = tmp, cout = fmt; *cin; ) { // scan through the formatted number + *cout++ = *cin++; // output digit + --nchar; // get number of digits left + if (nchar > 0 && (nchar % 3) == 0) + *cout++ = THOUSANDS_SEP; // if there is a multiple of three digits left, emit a comma + } + *cout = '\0'; // terminate string + +#else // THOUSANDS_SEP is undefined, output number w/o commas + + sprintf(fmt, "%d", n); + +#endif + + width -= strlen(fmt); // get width shortage + while (--width >= 0) // output spaces if necessary + putchar(' '); + + fputs(fmt, stdout); // print formatted number +} + +// ------------------------------------------------------------------------------------------- +// bail - print fatal error message and exit +// ------------------------------------------------------------------------------------------- + +void bail (char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +// ------------------------------------------------------------------------------------------- +// getsec - read desired sector +// ------------------------------------------------------------------------------------------- + +void getsec (uint16 secno) +{ + int i, phys_sec; + static uint16 cur_sec = 0xFFFF; + + if (secno == cur_sec) // see if we already have the sector. Presumes + return; // we haven't modified its contents! + + cur_sec = secno; // remember current sector + + phys_sec = secno; // physical sector + + for (i = 0; i < 3; i++) { // bump cylinder if it's past any in the defective cylinder list + if (secno >= defective[i]) // (use logical secno for comparisons, not physical secno) + phys_sec += 8; + else + break; + } + + fseek(fd, phys_sec*PHY_WORDS*2, SEEK_SET); // jump to translated sector + + if (fxread(§or, 2, PHY_WORDS, fd) != PHY_WORDS) // fxread handles flipping data on little-endian machines + bail("error reading disk image"); + + if (sector.secno != secno) { // verify that 1st word in sector is sector number + fprintf(stderr, "* expected sector number /%04x, got /%04x\n", secno, sector.secno); + bail("disk image is corrupt"); + } +} + +// ------------------------------------------------------------------------------------------- +// getdata -- read data from file relative to its disk block address +// ------------------------------------------------------------------------------------------- + +void getdata (void *buf, uint16 dbaddr, uint16 offset, uint16 nwords) +{ + uint16 secno, nsec, nw; + + if (nwords == 0) + return; + + secno = dbaddr / SEC_BLOCKS; // desired sector number from dbaddr + dbaddr -= SEC_BLOCKS*secno; // # of blocks offset within that sector + offset += dbaddr*BLK_WORDS; // add offset in words + + nsec = offset / SEC_WORDS; // turn offset into integer sectors + secno += nsec; // bump sector number + offset -= nsec*SEC_WORDS; // ultimate offset within sector + + for (;;) { + getsec(secno); // read desired sector + nw = min(SEC_WORDS-offset, nwords); // number of words to copy from this sector + memcpy(buf, §or.data[offset], nw*2); // copy the data + + if ((nwords -= nw) <= 0) // decrement remaining word count + break; + + secno++; // bump sector + offset = 0; // no offset in subsequent sector(s) + ((uint16 *) buf) += nw; // bump buffer pointer + } +} + +// ------------------------------------------------------------------------------------------- +// print_slet - list the contents of the SLET +// ------------------------------------------------------------------------------------------- + +struct { + unsigned int id; + char *name; +} slet_phase[] = { + 0x01, "@DDUP DUPCO *** DUP", // DMS R1V12 phase ID's and names + 0x02, "@DCTL DUP CONTROL - PART 1", + 0x03, "@STOR STORE", + 0x04, "@FILQ FILE EQUATE", + 0x05, "@DUMP DUMP", + 0x06, "@DL/F DUMP LET/FLET", + 0x07, "@DLTE DELETE", + 0x08, "@DFNE DEFINE", + 0x09, "@EXIT DEXIT", + 0x0A, "@CFCE CARD INTERFACE", + 0x0B, "@DU11 KEYBOARD INTERFACE", + 0x0C, "@DU12 PAPER TAPE INTERFACE", + 0x0D, "@DU13 DUP UPCOR", + 0x0E, "@DU14 DUP PRINCIPAL I/O", + 0x0F, "@DU15 DUP PRINCIPAL I/O SANS KB", + 0x10, "@DU16 DUP PAPER TAPE I/O", + 0x11, "@PRCI PRE CORE IMAGE", + 0x12, "@DU18 DUP RESERVED", + 0x1F, "@FR01 INPUT *** FORTRAN COMPILER", + 0x20, "@FR02 CLASSIFIER", + 0x21, "@FR03 CHECK ORDER/STMNT NUMBER", + 0x22, "@FR04 COMMON/SUBROUTINE OR FUNC", + 0x23, "@FR05 DIM/REAL, INTEGER, EXTERNAL", + 0x24, "@FR06 REAL CONSTANTS", + 0x25, "@FR07 DEFN FILE, CALL LINK/EXIT", + 0x26, "@FR08 VARIABLES AND STMNT FUNC", + 0x27, "@FR09 DATA STATEMENT", + 0x28, "@FR10 FORMAT", + 0x29, "@FR11 SUBSCRIPT DECOMPOSITION", + 0x2A, "@FR12 ASCAN I", + 0x2B, "@FR13 ASCAN II", + 0x2C, "@FR14 DO, CONTINUE, ETC", + 0x2D, "@FR15 SUBSCRIPT OPTIMIZE", + 0x2E, "@FR16 SCAN", + 0x2F, "@FR17 EXPANDER I", + 0x30, "@FR18 EXPANDER II", + 0x31, "@FR19 DATA ALLOCATION", + 0x32, "@FR20 COMPILATION ERRORS", + 0x33, "@FR21 STATEMENT ALLOCATION", + 0x34, "@FR22 LIST STATEMENT ALLOCATION", + 0x35, "@FR23 LIST SYMBOLS", + 0x36, "@FR24 LIST CONSTANTS", + 0x37, "@FR25 OUTPUT I", + 0x38, "@FR26 OUTPUT II", + 0x39, "@FR27 RECOVERY", + 0x3A, "DUMMY DUMMY NAME", + 0x3B, "DUMMY DUMMY NAME", + 0x3C, "DUMMY DUMMY NAME", + 0x51, "@QCTL PROCESS CTL CDS *** COBOL COMPILER ", + 0x52, "@QTXT SOURCE TEXT REDUCTION", + 0x53, "@QLIT LITERAL ALLOCATION", + 0x54, "@QDTA DATA DIVISION PROCESSING", + 0x55, "@QPRO PROCEDURE DIV SCAN", + 0x56, "@QGEN GENERATE INST STRINGS", + 0x57, "@QOBJ PRODUCE DSF-MODULE", + 0x58, "@QERR MAP/DIAGNOSTIC OUTPUT", + 0x59, "@QEND COMPILE TERMINATION", + 0x5A, "@QSER PRODUCE SERVICEABILITY", + 0x5B, "@QXR1", + 0x5C, "@QXR2", + 0x6E, "@SUP1 MONITOR CTRL RCD ANALYZER *** SUPERVISOR", + 0x6F, "@SUP2 JOB RECORD PROCESSING", + 0x70, "@SUP3 DELETE TEMPOTARY LET", + 0x71, "@SUP4 XEQ RECORD PROCESSING", + 0x72, "@SUP5 SCR PROCESSING", + 0x73, "@SUP6 SYSTEM DUMP PROGRAM", + 0x74, "@SUP7 AUXILIARY SUPERVISOR", + 0x78, "@CLB1 PHASE 1 *** CORE LOAD BUILDER", + 0x79, "@CLB2 PHASE 2", + 0x7A, "@CLB3 PHASE 3", + 0x7B, "@CLB4 PHASE 4", + 0x7C, "@CLB5 PHASE 5", + 0x7D, "@CLB6 PHASE 6", + 0x7E, "@CLB7 PHASE 7", + 0x7F, "@CLB8 PHASE 8", + 0x80, "@CLB9 PHASE 9", + 0x81, "@CLBA PHASE 10", + 0x82, "@CLBB PHASE 11", + 0x83, "@CLBC PHASE 12", + 0x84, "@CLBD PHASE 13 (GRAPHICS)", + 0x8C, "@1403 1403 SUBR *** SYSTEM DEVICE DRIVERS", + 0x8D, "@1132 1132 SUBR", + 0x8E, "@CPTR CONSOLE PRINTER SUBR", + 0x8F, "@2501 2501 SUBR", + 0x90, "@1442 1442 SUBR", + 0x91, "@1134 1134 SUBR", + 0x92, "@KBCP KB/CONSOLE PRINTER SUBR", + 0x93, "@CDCV 2501/1442 CONVERSION SUBR", + 0x94, "@PTCV 1134 CONVERSION SUBR", + 0x95, "@KBCV KB/CP CONVERSION SUBR", + 0x96, "@DZID DISKZ", + 0x97, "@D1ID DISK1", + 0x98, "@DNID DISKN", + 0x99, "@PPRT PRINCIPAL PRINT SUBROUTINE", + 0x9A, "@PIWK PRINCIPAL INPUT SUBROUTINE", + 0x9B, "@PIXK PRINCIPAL INPUT W/O KB", + 0x9C, "@PCWK PRINCIPAL CONV W/ KEYBOARD", + 0x9D, "@PCXK PRINCIPAL CONV W/O KEYBOARD", + 0xA0, "@CIL1 PHASE 1 *** CORE IMAGE LOADER", + 0xA1, "@CIL2 PHASE 2", + 0xB0, "@RG00 PHASE 0 *** RPG COMPILER", + 0xB1, "@RG02 PHASE 2", + 0xB2, "@RG04 PHASE 4", + 0xB3, "@RG06 PHASE 6", + 0xB4, "@RG08 PHASE 8", + 0xB5, "@RG10 PHASE 10", + 0xB6, "@RG12 PHASE 12", + 0xB7, "@RG14 PHASE 14", + 0xB8, "@RG16 PHASE 16", + 0xB9, "@RG17 PHASE 17", + 0xBA, "@RG19 PHASE 19", + 0xBB, "@RG20 PHASE 20", + 0xBC, "@RG21 PHASE 21", + 0xBD, "@RG22 PHASE 22", + 0xBE, "@RG24 PHASE 24", + 0xBF, "@RG26 PHASE 26", + 0xC0, "@RG28 PHASE 28", + 0xC1, "@RG32 PHASE 32", + 0xC2, "@RG34 PHASE 34", + 0xC3, "@RG36 PHASE 36", + 0xC4, "@RG38 PHASE 38", + 0xC5, "@RG40 PHASE 40", + 0xC6, "@RG42 PHASE 42", + 0xC7, "@RG44 PHASE 44", + 0xC8, "@RG46 PHASE 46", + 0xC9, "@RG52 PHASE 52", + 0xCA, "@RG54 PHASE 54", + 0xCB, "@RG58 PHASE 58", + 0xCC, "@RG60 PHASE 60", + 0xCD, "@DCL2 *** DUP CONTROL - PART 2", + 0xCE, "@DMUP MACRO UPDATE PROGRAM", + 0xCF, "@AS00 PHASE 0 *** ASSEMBLER", + 0xD0, "@ACNV CARD CONVERSION", + 0xD1, "@AS10 PHASE 10", + 0xD2, "@AS11 PHASE 11", + 0xD3, "@AS12 PHASE 12", + 0xD4, "@AERM ERROR MESSAGES", + 0xD5, "@AS01 PHASE 1", + 0xD6, "@AS1A PHASE 1A", + 0xD7, "@ASYM SYSTEM SYMBOL TABLE", + 0xD8, "@AS03 PHASE 3", + 0xD9, "@AS04 PHASE 4", + 0xDA, "@AS02 PHASE 2", + 0xDB, "@AS2A PHASE 2A", + 0xDC, "@AS09 PHASE 9", + 0xDD, "@AS05 PHASE 5", + 0xDE, "@AS06 PHASE 6", + 0xDF, "@AS07 PHASE 7", + 0xE0, "@AS7A PHASE 7A", + 0xE1, "@AS08 PHASE 8", + 0xE2, "@AS8A PHASE 8A", + 0xE3, "@APCV CARD PUNCH CONVERSION", + 0xE4, "@AINT INTERMEDIATE DISK OUTPT", + 0xE5, "@ASAA PHASE 10A", + 0xE6, "@ASGR PHASE 13 GRAPHICS", + 0xE7, "@ADIV DIVISION OPERATOR", + 0xE8, "@AMCC MACRO CONTROL CARDS III", + 0xE9, "@AM01 MACRO PHASE 1", + 0xEA, "@AM1A MACRO PHASE 1A", + 0xEB, "@AM1B MACRO PHASE 1B", + 0xEC, "@AM02 MACRO PHASE 2", + 0xED, "@AM2A MACRO PHASE 2A", + 0xEE, "@AM2B MACRO PHASE 2B", + 0xEF, "@AM03 MACRO PHASE 3", + 0xF0, "@AM3A MACRO PHASE 3A", + 0xF1, "@AM3B MACRO PHASE 3B", + 0xF2, "@AX01 CROSS REF - PART 1", + 0xF3, "@AX2A CROSS REF - PART 2A", + 0xF4, "@AX2B CROSS REF - PART 2B", + 0xF5, "@AX2C CROSS REF - PART 2C", + 0xF6, "@AX03 CROSS REF - PART 3", + 0x100, "@AS00 *** MSP7 ASSEMBLER", + 0x101, "@ACNV", + 0x102, "@AS10", + 0x103, "@AS11", + 0x104, "@AS12", + 0x105, "@AERM", + 0x106, "@AS01", + 0x107, "@AS1A", + 0x108, "@ASYM", + 0x109, "@AS03", + 0x10A, "@AS04", + 0x10B, "@AS02", + 0x10C, "@AS2A", + 0x10D, "@AS09", + 0x10E, "@AS05", + 0x10F, "@AS06", + 0x110, "@AS07", + 0x111, "@AS7A", + 0x112, "@AS08", + 0x113, "@AS8A", + 0x114, "@APCV", + 0x115, "@AINT", + 0x116, "@ASAA", + 0x117, "@ASGR", + 0x118, "@ADIV", + 0x119, "@AMCC", + 0x11A, "@AM01", + 0x11B, "@AM1A", + 0x11C, "@AM1B", + 0x11D, "@AM02", + 0x11E, "@AM2A", + 0x11F, "@AM2B", + 0x120, "@AM03", + 0x121, "@AM3A", + 0x122, "@AM3B", + 0x123, "@AX01", + 0x124, "@AX2A", + 0x125, "@AX2B", + 0x126, "@AX2C", + 0x127, "@AX03", + 0x128, "@ASP7", + 0xFFFF, "" +}; +#define N_SLET_PHASES (sizeof(slet_phase)/sizeof(slet_phase[0]) - 1) + +void print_slet (void) +{ + int i, j = 0; + + printf("SLET (System Logical Equivalence Table)\n\n"); // dump SLET + printf("ID Addr Size Sect Description\n"); + printf("---- ---- ---- ---- -----------------------\n"); + + for (i = 0; i < SLET_LENGTH; i++) { + if (slet[i].id == 0 && slet[i].secno == 0) + break; + + printf("%04x %04x %04x %04x ", slet[i].id, slet[i].addr, slet[i].size, slet[i].secno); + + while (j < N_SLET_PHASES && slet_phase[j].id < slet[i].id) + j++; // skip to entry in slet_phase name table + + printf("%s\n", (slet_phase[j].id == slet[i].id) ? slet_phase[j].name : "?"); + } + + putchar('\n'); +} + +// ------------------------------------------------------------------------------------------- +// ebcdic_to_ascii - convert EBCDIC character to ASCII (ignores controls) +// ------------------------------------------------------------------------------------------- + +int ebcdic_to_ascii (int ch) +{ + int j; + static int ascii_to_ebcdic_table[128] = { + // + 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, + // + 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f, + // spac ! " # $ % & ' ( ) * + , - . / + 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, + // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, + // @ A B C D E F G H I J K L M N O + 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, + // P Q R S T U V W X Y Z [ \ ] & _ + 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, + // a b c d e f g h i j k l m n o + 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, + // p q r s t u v w x y z { | } ~ + 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, + }; + + for (j = 32; j < 128; j++) // look it up in table. (Of course if we constructed + if (ascii_to_ebcdic_table[j] == ch) // an ebcdic_to_ascii table we could just get the result directly) + return j; + + return '?'; +} + +// ------------------------------------------------------------------------------------------- +// convert_namecode - convert two-word name code into 5 character ASCII name +// ------------------------------------------------------------------------------------------- + +void convert_namecode (uint16 *namecode, char *name) +{ + unsigned long val; + int i, ch; + + val = (namecode[0] << 16) | namecode[1]; // reconstruct the 30-bit code + + for (i = 0; i < 5; i++) { // scan for 5 letters + ch = ((val >> 24) & 0x3F); // pick up 6 bits at leftmost character position + if (ch == 0) + ch = ' '; // zero is a space + else + ch = ebcdic_to_ascii(ch | 0xC0); // add assumed high bits and convert to ASCII + + name[i] = ch; // save it + val <<= 6; // shift next character into position + } + + while (--i >= 0) // back up to last nonblank character + if (name[i] != ' ') + break; + + name[i+1] = '\0'; // terminate string +} + +// ------------------------------------------------------------------------------------------- +// get_let - get FLET or LET, build into linked list +// ------------------------------------------------------------------------------------------- + +void get_let (LETENTRY **listhead, uint16 secno) +{ + uint16 seq, sec_addr, avail, chain, namecode[2], dbcount, addr; + int i, nwords, filetype; + char name[6]; + LETENTRY *head = NULL, *tail, *entry, *master = NULL; + + for (; secno != 0; secno = chain) { // scan through linked sectors + getsec(secno); + + seq = sector.data[0]; // relative sector number + sec_addr = sector.data[1]; // sector address of FA or UA + avail = sector.data[3]; // available words in this sector + chain = sector.data[4]; // next sector number, 0 if this is the last + + if (seq == 0) // first time through, get starting address of FA or UA + addr = sec_addr*16; // (convert sector to "disk block") + + if (verbose) + printf(" (sector %d, addr /%04x, next %04x)\n", seq, secno, chain); + + nwords = SEC_WORDS - 5 - avail; // number of words used by F/LET entries in this sector + + for (i = 5; nwords >= 3; ) { // scan through entries + filetype = (sector.data[i] >> 14) & 0x03; // get file type: 0=DSF, 2=DCI, 3=data + + namecode[0] = sector.data[i] & 0x3FFF; // get name + namecode[1] = sector.data[i+1]; + convert_namecode(namecode, name); + + dbcount = sector.data[i+2]; // get disk block count + + i += 3; // advance index, decrement words-left count + nwords -= 3; + + entry = ALLOCATE(LETENTRY); + strcpy(entry->name, name); + entry->next = NULL; + entry->filetype = filetype; + entry->dbaddr = addr; + entry->dbcount = dbcount; + entry->dummy = strcmp(entry->name, "1DUMY") == 0; + + if (dbcount == 0) + entry->master = master; // this is an alternate entry for previous master entry + else { + entry->master = NULL; // this is a master entry + master = entry; + } + + if (head == NULL) + head = entry; // first entry is head of linked list + else + tail->next = entry; // add to end of linked list + + tail = entry; + + addr += dbcount; // skip to next file + } + } + + *listhead = head; +} + +// ------------------------------------------------------------------------------------------- +// print_let - list FLET or LET +// ------------------------------------------------------------------------------------------- + +void print_let (char *title, LETENTRY *entry) +{ + int nblocks, nfiles, nalternates, nfree; // used to get total files, blocks in a directory + static char *ftname[4] = {"DSF", "???", "DCI", "DDF"}; // filetype names + + nfiles = 0; // reset total counts + nblocks = 0; + nalternates = 0; + nfree = 0; + + printf("%s\n\n", title); + printf("Name Type Blocks%s\n", show_all ? " Addr Type" : ""); + printf("----- ---- ------%s\n", show_all ? " ---- --------------------------------------" : ""); + + for (; entry != NULL; entry = entry->next) { + if (entry->dummy) { // this is an unused LET/FLET slot + if (entry->next == NULL) { + nfree = entry->dbcount; // last 1DUMY gives amount of free space + } + else { + nblocks += entry-> dbcount; // in middle, it's a bit of space lost due to sector-padding + + if (show_all) { // display padding entries in show_all mode + printf("%-5s %-3s ", "(pad)", ""); + commas(entry->dbcount, 8); + printf(" %04x\n", entry->dbaddr); + } + } + } + else if (entry->dbcount > 0) { // if disk block count is nonzero, it's a file + printf("%-5s %-3s", entry->name, ftname[entry->filetype]); + commas(entry->dbcount, 8); + if (show_all) + printf(" %04x %s", entry->dbaddr, file_progtype(entry)); + putchar('\n'); + + nblocks += entry->dbcount; // add to cumulative totals + nfiles++; + } + else { // 0 blocks means it's an alternate entry for previous file + if (show_all) + printf("%-5s\n", entry->name); + + nalternates++; + } + } + + putchar('\n'); // double space after table + + printf("\nTotal: "); // print summary + commas(nfiles, 0); + printf(" file%s", (nfiles == 1) ? "" : "s"); + if (show_all) { + printf(", "); + commas(nalternates, 0); + printf(" entr%s", (nalternates == 1) ? "y" : "ies"); + } + putchar('\n'); + + printf("Space Used: "); + commas(nblocks, 0); + printf(" block%s, ", (nblocks == 1) ? "" : "s"); + commas(nblocks*BLK_WORDS, 0); + printf(" words\n"); + + printf("Space Free: "); + commas(nfree, 0); + printf(" block%s, ", (nfree == 1) ? "" : "s"); + commas(nfree*BLK_WORDS, 0); + printf(" words\n\n"); +} + +// ------------------------------------------------------------------------------------------- +// astring - allocate memory for an return copy of a string +// ------------------------------------------------------------------------------------------- + +char *astring (char *str) +{ + char *cpy; + + cpy = malloc(strlen(str)+1); + strcpy(cpy, str); + + return cpy; +} + +// ------------------------------------------------------------------------------------------- +// matchname - see if filename matches (wildcard) file specification. We assume that both +// name and spec are uppercase. +// ------------------------------------------------------------------------------------------- + +BOOL matchname (char *name, char *spec) +{ + while (*name) { // scan through the filename + if (*name == *spec || *spec == '?') { // if exact match, or single-char ? match, + name++; // so far so good; skip to next character + spec++; + } + else if (*spec == '*') { // we are at a * in the pattern. We need to try all possible + while (*spec == '*') // see if there are any more literal characters + spec++; + + if (*spec == '\0') // no more literal pattern characters; this qualifies as a match + return TRUE; + + // if we get here, we need to start matching the remaining part of the pattern against + // some reduction of the name; we can skip 0 or more characters looking for a hit. + // For example, if called with matchname("ABCDEF", "AB*F"), when we get here, + // name = "CDEF" and spec = "F". What we need to do is start eating away at name to see + // if it can be made to match the final F. + + while (*name) { + if (matchname(name, spec)) // if the remaining part of the pattern matches the name, + return TRUE; // it's a hit + + name++; // skip one character in name (the part matched by our *) and try again + } + + return FALSE; // we skipped everything and still couldn't match the residual pattern + } + else + return FALSE; // this is a definite mismatch + } + // we've hit the end of the actual filename + while (*spec == '*') + spec++; // skip over any trailing * wildcards + + return *spec == '\0'; // match is true if we're now at end of the pattern +} + +typedef struct tag_namelist { + struct tag_namelist *next; + char name[6]; +} NAMENODE, *NAMELIST; + +NAMELIST free_nodes = NULL; + +#define INDENT " " // indent for information lines +#define INDENT2 " " // indent for debugging lines + +// ------------------------------------------------------------------------------------------- +// add_list - add a name to a linked list of names, in alphabetical order +// ------------------------------------------------------------------------------------------- + +void add_list (char *name, NAMELIST *plisthead) +{ + NAMELIST n, prev; + int cmp; + + for (n = *plisthead, prev = NULL; n != NULL; prev = n, n = n->next) { // scan list. 'Prev' is trailing pointer + if ((cmp = strcmp(n->name, name)) == 0) + return; // name is already in the list + + if (cmp > 0) // new entry goes before this entry + break; + } + + if (free_nodes == NULL) // get a NAMELIST node from freelist or + n = ALLOCATE(NAMENODE); // by allocating more memory + else { + n = free_nodes; + free_nodes = n->next; + } + + strcpy(n->name, name); // save the name + + if (prev == NULL) { // add to head of list + n->next = *plisthead; + *plisthead = n; + } + else { // add to middle of list, after entry 'prev' + n->next = prev->next; + prev->next = n; + } +} + +// ------------------------------------------------------------------------------------------- +// print_list - print list of names +// ------------------------------------------------------------------------------------------- + +void print_list (NAMELIST list, char *title) +{ + int i; + + printf(INDENT "%-14s", title); // print title string + + for (i = 0; list != NULL; list = list->next, i++) { // print up to 8 names per line + if (i == 8) { + printf("\n" INDENT "%-14s", ""); // (start a new line) + i = 0; + } + printf("%s%s", (i == 0) ? "" : ", ", list->name); // print names, separated by commas + } + + putchar('\n'); // terminate last line +} + +// ------------------------------------------------------------------------------------------- +// free_list - put list of names into the freelist for possible reuse +// ------------------------------------------------------------------------------------------- + +void free_list (NAMELIST list) +{ + NAMELIST n; + + if (free_nodes == NULL) // freelist is empty, this list becomes the freelist + free_nodes = list; + else { + for (n = free_nodes; n->next != NULL; n = n->next) // find last node in freelist + ; + + n->next = list; // tack this list onto the end + } +} + +// ------------------------------------------------------------------------------------------- +// init_dsf_stream - like "fopen", prepares to read data out of a DSF file. A DSFSTREAM structure +// hold necessary state information like file offset, current data module and current data block +// ------------------------------------------------------------------------------------------- + +typedef struct { + uint16 dbaddr; // dbaddr of current file + uint16 offset; // current offset in file + uint16 nwords; // number of words left in current data module + uint16 addr; // load address of next word + uint16 nw; // number of words in current data block (2-9) + uint16 ind; // index of next word to extract from current data block (1-8) + uint16 relflag; // relocation flags; next word's flags are left adjusted + uint16 datablock[9]; // current data block; datablock[ind] is next word +} DSFSTREAM; + +void init_dsf_stream (DSFSTREAM *dsf_stream, LETENTRY *entry, DSF_PROGRAM_HEADER *hdr) +{ + dsf_stream->dbaddr = entry->dbaddr; // set up dbaddr and offset for data in chosen file + dsf_stream->offset = hdr->hdr_len9 + 9; // point just past the file header (hdr_len9 is the length - 9) + + dsf_stream->ind = 999; // set state so we have to read the first data module + dsf_stream->nw = 0; + dsf_stream->nwords = 0; +} + +// ------------------------------------------------------------------------------------------- +// get_dsf_word - read next data word and associated relocation flag bits from DSF data stream +// ------------------------------------------------------------------------------------------- + +BOOL get_dsf_word (DSFSTREAM *dsf_stream, uint16 *word, uint16 *addr, uint16 *relflag) +{ + uint16 dataheader[2]; + int i; + + if (dsf_stream->ind >= dsf_stream->nw) { // we've exhausted the current data block, get next one + if (dsf_stream->nwords == 0) { // we've exhausted the current module, get next one + getdata(dataheader, dsf_stream->dbaddr, dsf_stream->offset, 2); // get two-word data block header + dsf_stream->offset += 2; + + dsf_stream->addr = dataheader[0]; // save address and module size + dsf_stream->nwords = dataheader[1]; + + if (dsf_stream->nwords == 0) // end of file + return FALSE; + + if (verbose) // in verbose mode, show module header + printf(INDENT2 "%04x %04x %d\n", dsf_stream->addr, dsf_stream->nwords, dsf_stream->nwords-2); + + dsf_stream->nwords -= 2; // deduct 2 dataheader words we just read + } + + dsf_stream->nw = min(dsf_stream->nwords, 9); // size of next data block + getdata(dsf_stream->datablock, dsf_stream->dbaddr, dsf_stream->offset, dsf_stream->nw); + dsf_stream->offset += dsf_stream->nw; // bump file offset + dsf_stream->nwords -= dsf_stream->nw; // and number of words left in current module + dsf_stream->relflag = dsf_stream->datablock[0]; // get relocation flag word + dsf_stream->ind = 1; // initialize index + + if (verbose) { // in verbose mode, show data block including relocation bits + static char flagchar[4] = {'.', 'r', 'L', 'C'}; // (show . r L or C for abs, rel, LIBF or CALL) + char flagstr[10]; + + for (i = 1; i < dsf_stream->nw; i++) // construct string showing meaning of relocation bits + flagstr[i-1] = flagchar[(dsf_stream->relflag >> (16-2*i)) & 3]; + flagstr[i-1] = '\0'; + // display address, relocation info, data words + printf(INDENT2 " %04x [%04x %-8s]", dsf_stream->addr, dsf_stream->relflag, flagstr); + for (i = 1; i < dsf_stream->nw; i++) + printf(" %04x", dsf_stream->datablock[i]); + putchar('\n'); + } + } + // ready to extract the next word... + *word = dsf_stream->datablock[dsf_stream->ind++]; // give caller the word, and increment index + *relflag = (dsf_stream->relflag >> 14) & 3; // give caller the top two bits of the relocation flag word + dsf_stream->relflag <<= 2; // and slide next two bits into place + + *addr = dsf_stream->addr; // give caller the word's address, and increment address + if (*relflag != 2) // unless relflag was 2 (LIBF), which occupies only 1 word + dsf_stream->addr++; // in core. We'll increment addr when we fetch the 2nd name word +} + +// ------------------------------------------------------------------------------------------- +// print_dsf_info - print information about a Disk System Format file +// ------------------------------------------------------------------------------------------- + +void print_dsf_info (LETENTRY *entry) +{ + DSF_PROGRAM_HEADER hdr; + char name[6], *nm, label[4]; + int i, nentries; + unsigned subtype, progtype, int_precis, real_precis, n_defined_files, fortran_indicator; + uint16 namewords[2], word, addr, relflag; + NAMELIST call_list, dsn_list; + DSFSTREAM dsf_stream; + + getdata(&hdr, entry->dbaddr, 0, sizeof(DSF_PROGRAM_HEADER)/2); // read file header (assume maximum size) + + subtype = (hdr.type >> 12) & 0x0F; // extract file type and subtype + progtype = (hdr.type >> 8) & 0x0F; + int_precis = (hdr.type >> 4) & 0x0F; // get precision specification + real_precis = hdr.type & 0x0F; + fortran_indicator = (hdr.fortran_info >> 8) & 0xFF; // get fortran specifications + n_defined_files = hdr.fortran_info & 0xFF; + + if (hdr.zero1 != 0) // this word is supposed to be zero + printf(INDENT "CORRUPT: hdr word 1 should be 0, is %d\n", hdr.zero1); +// if (hdr.zero2 != 0) // so is this word, but it turns out not to be reliably zero +// printf(INDENT "CORRUPT: hdr word 7 should be 0, is %d\n", hdr.zero2); + + printf(INDENT "Program type: %d=%s\n", progtype, progtype_nm[progtype]); + if (progtype == 3 || progtype == 4 || progtype == 5 || progtype == 7) { + nm = "Undefined"; // types 3, 4, 5 and 7 should have a subtype + for (i = 0; i < N_SUBTYPE_NMS; i++) { + if (subtype_nm[i].progtype == progtype && subtype_nm[i].subtype == subtype) { + nm = subtype_nm[i].descr; + break; + } + } + if (nm != NULL) // print subtype unless name was defined as NULL + printf(INDENT "Subtype: %d=%s\n", subtype, nm); + } + // print fortran information + printf(INDENT "Precision: Real=%s Integer=%s\n", + (real_precis == 0) ? "Unspecified" : (real_precis == 1) ? "Standard" : (real_precis == 2) ? "Extended" : "invalid", + (int_precis == 0) ? "Unspecified" : (int_precis == 8) ? "Matches Real" : (int_precis == 9) ? "One word" : "invalid"); + printf(INDENT "Prog length: %d wd\n", hdr.proglen); + printf(INDENT "COMMON: %d wd\n", hdr.commonlen); + printf(INDENT "Fortran ind: 0x%02x, %d defined file%s\n", + fortran_indicator, n_defined_files, (n_defined_files == 1) ? "" : "s"); + + switch (progtype) { // print entry information for... + default: // ... mainline or subprogram + if ((hdr.hdr_len9 % 3) != 0) { + printf(INDENT "CORRUPT: header length-9 is %d, should be multiple of 3\n", hdr.hdr_len9); + break; + } + nentries = hdr.hdr_len9 / 3; // get number of entry points (assuming not an ILS or ISS) + if (nentries > 15) + printf(INDENT "CORRUPT: # of entries is %d, max is 15\n", nentries); + + for (i = 0; i < nentries; i++) { // list entry point names and addresses + convert_namecode(hdr.x.entry[i].name, name); + sprintf(label, (i < 9) ? "%d: " : "%d:", i+1); // print, e.g. "2: " or "12:" + printf(INDENT "Entry %s %-5s addr /%04x\n", label, name, hdr.x.entry[i].addr); + } + break; + + case 5: // ... ISS (device interrupt service routine) + case 6: + if (hdr.hdr_len9 != 7 && hdr.hdr_len9 != 8) + printf(INDENT "CORRUPT: header length-9 is %d, should be 7 or 8\n", hdr.hdr_len9); + + convert_namecode(hdr.x.iss.name, name); // has just one entry point name + printf(INDENT "Entry: %-5s addr /%04x\n", name, hdr.x.iss.addr); + printf(INDENT "ISS number: %d\n", hdr.x.iss.issnumber); + + if (hdr.x.iss.nlevels != 1 && hdr.x.iss.nlevels != 2) { // should have 1 or 2 associated interrupt levels + printf(INDENT "CORRUPT: # of levels is %d, should be 1 or 2\n", hdr.x.iss.nlevels); + hdr.x.iss.nlevels = 1; + } + + for (i = 0; i < hdr.x.iss.nlevels; i++) + printf(INDENT "Int level %d: %d\n", i+1, hdr.x.iss.level[i]); + break; + + case 7: // ... ILS (interrupt handler) + if (hdr.hdr_len9 != 4) + printf(INDENT "CORRUPT: header length-9 is %d, should be 4\n", hdr.hdr_len9); + + convert_namecode(hdr.x.ils.name, name); + printf(INDENT "Entry: %-5s addr /%04x\n", name, hdr.x.ils.addr); + printf(INDENT "ILS level: %d\n", hdr.x.ils.level); + break; + } + + call_list = dsn_list = NULL; // clear list of external references + + init_dsf_stream(&dsf_stream, entry, &hdr); // prepare to read data from the file + + while (get_dsf_word(&dsf_stream, &word, &addr, &relflag)) { + switch (relflag) { + case 0: // 00 - absolute data + case 1: // 01 - relocatable data + break; + + case 2: // 10 - LIBF + namewords[0] = word; // save first name word and get the second + get_dsf_word(&dsf_stream, &namewords[1], &addr, &relflag); + convert_namecode(namewords, name); // convert to ASCII + add_list(name, &call_list); // add name to list of external references + break; + + case 3: // 11 - CALL or DSN + namewords[0] = word; // save first name word and get the second + get_dsf_word(&dsf_stream, &namewords[1], &addr, &relflag); + convert_namecode(namewords, name); // convert to ASCII + if (relflag == 0) // 1100 - CALL + add_list(name, &call_list); // add name to list of external references + else if (relflag == 1) // 1101 - DSN + add_list(name, &dsn_list); // add name to list of data source names + else // 1110 or 1111 - invalid + printf(INDENT, "CORRUPT: object data contains invalid relocation bits 111%d\n", relflag & 1); + break; + } + } + + if (call_list != NULL) { // print list(s) of external references + print_list(call_list, "Calls:"); + free_list(call_list); + } + + if (dsn_list != NULL) { + print_list(dsn_list, "DSN's referenced:"); + free_list(dsn_list); + } + + putchar('\n'); +} + +// ------------------------------------------------------------------------------------------- +// print_dci_info - print information about a Disk Core Image file +// ------------------------------------------------------------------------------------------- + +void print_dci_info (LETENTRY *entry) +{ + DCI_PROGRAM_HEADER hdr; + char *diskprog; + int i; + + getdata(&hdr, entry->dbaddr, 0, sizeof(DCI_PROGRAM_HEADER)/2); // read file header + + diskprog = (hdr.dreq == 0xFFFF) ? "DISKZ" : (hdr.dreq == 0x0000) ? "DISK1" : (hdr.dreq == 0x0001) ? "DISKN" : "Unknown"; + + printf(INDENT "Execute addr: /%04x\n", hdr.xeqa); // interpret and print it + printf(INDENT "COMMON: %d wd\n", hdr.cmon); + printf(INDENT "Disk IO: /%04x (%s)\n", hdr.dreq, diskprog); + printf(INDENT "# files defd: %d\n", hdr.file); + printf(INDENT "Hdr length: %d wd\n", hdr.hwct); + printf(INDENT "Sector cnt: %d files in WS\n", hdr.lsct); + printf(INDENT "Load address: /%04x\n", hdr.ldad); + printf(INDENT "Exit addr: /%04x\n", hdr.xctl); + printf(INDENT "TV length: %d wd\n", hdr.tvwc); + printf(INDENT "Load size: %d wd including TV\n", hdr.wcnt-hdr.hwct); + printf(INDENT "XR3: /%04x\n", hdr.xr3x); + +#define NO_VECTOR 0x0091 // appears to be DMS default handler for unrecognized interrupt + + for (i = 0; i < 6; i++) { + if (hdr.itv[i] != NO_VECTOR) + printf(INDENT "Lvl %d vector: /%04x\n", i, hdr.itv[i]); + } + + if (hdr.ibt[0] != NO_VECTOR || hdr.ibt[1] != NO_VECTOR || hdr.ibt[2] != NO_VECTOR) + printf(INDENT "ISS of 1231: /%04x /%04x /%04x\n", hdr.ibt[0], hdr.ibt[1], hdr.ibt[2]); + if (hdr.ibt[3] != NO_VECTOR) + printf(INDENT "ISS of 1403: /%04x\n", hdr.ibt[3]); + if (hdr.ibt[4] != NO_VECTOR) + printf(INDENT "ISS of 2501: /%04x\n", hdr.ibt[4]); + if (hdr.ibt[5] != NO_VECTOR) + printf(INDENT "ISS of 1442: /%04x\n", hdr.ibt[5]); + if (hdr.ibt[6] != NO_VECTOR) + printf(INDENT "ISS of kb/pr: /%04x\n", hdr.ibt[6]); + if (hdr.ibt[7] != NO_VECTOR) + printf(INDENT "ISS of ptr/p: /%04x\n", hdr.ibt[7]); + printf(INDENT "LOCAL/SOCALs: %d sectors\n", hdr.ovsw); + printf(INDENT "Built for: %d wds core\n", hdr.core); + + putchar('\n'); +} + +// ------------------------------------------------------------------------------------------- +// print_ddf_info - print information about a Disk Data Format file +// ------------------------------------------------------------------------------------------- + +void print_ddf_info (LETENTRY *entry) +{ + // there's nothing to say, really -- these are user-defined files +} + +// ------------------------------------------------------------------------------------------- +// dumpfile - print file contents in hex +// ------------------------------------------------------------------------------------------- + +void dumpfile (LETENTRY *entry) +{ + uint16 offset = 0, nw, nwords, buf[8], i; + + nwords = entry->dbcount*BLK_WORDS; // number of words to dump + + while (nwords > 0) { + printf(" %04x |", offset); // print current offset + + nw = min(nwords, 8); // fetch (up to) 8 words of data + getdata(buf, entry->dbaddr, offset, nw); + offset += nw; // bump offset and count + nwords -= nw; + + for (i = 0; i < nw; i++) // print values in hex + printf(" %04x", buf[i]); + + putchar('\n'); + } + + putchar('\n'); +} + +// ------------------------------------------------------------------------------------------- +// print_onefile - print detailed info about one particular file +// ------------------------------------------------------------------------------------------- + +void print_onefile (LETENTRY *entry, BOOL in_flet) +{ + static BOOL first = TRUE; + LETENTRY *mst; + + if (first) { // print column headings + first = FALSE; + printf("Name Type Blocks Addr Remarks\n"); + printf("----- ---- ------ ---- ---------------------------------------------------\n"); + } + + mst = (entry->master != NULL) ? entry->master : entry; // pointer to main (primary) entry + + printf("%-5s %-3s ", entry->name, ftname[mst->filetype]); // print file name and size info + commas(mst->dbcount, 8); + printf(" %04x", mst->dbaddr); + if (entry->master != NULL) // this is an alternate entry since it points to a master + printf(" (alternate entry point in %s)", mst->name); + printf("%s\n", in_flet ? " (in FLET)" : ""); + + if (do_dump) // if -d specified, dump contents + dumpfile(mst); + + if (show_all) { // if -a specified, print detailed info for particular file type + switch (mst->filetype) { + case FILETYPE_DSF: print_dsf_info(mst); break; + case FILETYPE_1: /* unknown format */ break; + case FILETYPE_DCI: print_dci_info(mst); break; + case FILETYPE_DDF: print_ddf_info(mst); break; + default: bail("in print_onefile, can't happen"); + } + } +} + +// ------------------------------------------------------------------------------------------- +// list_named_files - print info for file(s) matching a filename specified on the command line +// ------------------------------------------------------------------------------------------- + +void list_named_files (char *name, char *image) +{ + BOOL has_wild = strchr(name, '?') != NULL || strchr(name, '*') != NULL; + BOOL in_flet, matched; + LETENTRY *entry; + + if (flet != NULL) { // start at head of FLET if we have one, otherwise LET + in_flet = TRUE; + entry = flet; + } + else { + in_flet = FALSE; + entry = let; + } + + matched = FALSE; + + while (entry != NULL) { // scan through flet/let lists + if (! entry->dummy) { + if (matchname(entry->name, name)) { // does this file match the specified name? + print_onefile(entry, in_flet); // print it + matched = TRUE; + if (! has_wild) // if there were no wildcard characters in the name, stop scanning + break; + } + } + // try next file... + if (entry->next == NULL) { // if at end of current list + if (in_flet) { + entry = let; // move from flet to let + in_flet = FALSE; + } + else + break; // done with both lists + } + else + entry = entry->next; // go to next entry in list + } + + if (! matched) + printf("%s: no such file in %s", name, image); +} + +char * file_progtype (LETENTRY *entry) // description of module type +{ + static char buf[100]; + DSF_PROGRAM_HEADER hdr; + char *nm; + unsigned subtype, progtype; + int i; + + *buf = '\0'; + + switch (entry->filetype) { + case FILETYPE_DSF: + getdata(&hdr, entry->dbaddr, 0, sizeof(DSF_PROGRAM_HEADER)/2); // read file header (assume maximum size) + subtype = (hdr.type >> 12) & 0x0F; // extract file type and subtype + progtype = (hdr.type >> 8) & 0x0F; + + strcpy(buf, progtype_nm[progtype]); + if (progtype == 3 || progtype == 4 || progtype == 5 || progtype == 7) { + nm = NULL; + for (i = 0; i < N_SUBTYPE_NMS; i++) { + if (subtype_nm[i].progtype == progtype && subtype_nm[i].subtype == subtype) { + nm = subtype_nm[i].descr; + break; + } + } + if (nm != NULL) { + strcat(buf, "; "); + strcat(buf, nm); + } + } + break; + + case FILETYPE_DCI: + return "Mainline, core image"; + + case FILETYPE_DDF: + return "Data"; + + default: + return "unknown"; + } + + return buf; +} + diff --git a/Ibm1130/utils/disklist.mak b/Ibm1130/utils/disklist.mak new file mode 100644 index 00000000..a67d48ec --- /dev/null +++ b/Ibm1130/utils/disklist.mak @@ -0,0 +1,178 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "disklist.mak" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Win32 Debug" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : $(OUTDIR)/disklist.exe $(OUTDIR)/disklist.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c +# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c +CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /FR$(INTDIR)/ /Fp$(OUTDIR)/"disklist.pch" /Fo$(INTDIR)/ /c +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"disklist.bsc" +BSC32_SBRS= \ + $(INTDIR)/disklist.sbr \ + $(INTDIR)/util_io.sbr + +$(OUTDIR)/disklist.bsc : $(OUTDIR) $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ + /PDB:$(OUTDIR)/"disklist.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"disklist.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/disklist.obj \ + $(INTDIR)/util_io.obj + +$(OUTDIR)/disklist.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : $(OUTDIR)/disklist.exe $(OUTDIR)/disklist.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c +# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c +CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /FR$(INTDIR)/ /Fp$(OUTDIR)/"disklist.pch" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"disklist.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"disklist.bsc" +BSC32_SBRS= \ + $(INTDIR)/disklist.sbr \ + $(INTDIR)/util_io.sbr + +$(OUTDIR)/disklist.bsc : $(OUTDIR) $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ + /PDB:$(OUTDIR)/"disklist.pdb" /DEBUG /MACHINE:I386\ + /OUT:$(OUTDIR)/"disklist.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/disklist.obj \ + $(INTDIR)/util_io.obj + +$(OUTDIR)/disklist.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\disklist.c + +$(INTDIR)/disklist.obj : $(SOURCE) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\util_io.c +DEP_UTIL_=\ + .\util_io.h + +$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/Ibm1130/utils/makefile b/Ibm1130/utils/makefile index 612b3c67..c83feedf 100644 --- a/Ibm1130/utils/makefile +++ b/Ibm1130/utils/makefile @@ -21,7 +21,8 @@ IOLIB_SRC = util_io.c # all : ${BIN}asm1130 ${BIN}bindump ${BIN}checkdisk \ - ${BIN}diskview ${BIN}mkboot ${BIN}viewdeck + ${BIN}diskview ${BIN}mkboot ${BIN}viewdeck \ + ${BIN}disklist ${BIN}punches # # Individual builds @@ -36,6 +37,9 @@ ${BIN}bindump : bindump.c ${IOLIB_DEP} ${BIN}checkdisk : checkdisk.c ${IOLIB_DEP} ${CC} checkdisk.c ${IOLIB_SRC} -o $@ +${BIN}disklist : disklist.c ${IOLIB_DEP} + ${CC} disklist.c ${IOLIB_SRC} -o $@ + ${BIN}diskview : diskview.c ${IOLIB_DEP} ${CC} diskview.c ${IOLIB_SRC} -o $@ @@ -45,3 +49,5 @@ ${BIN}mkboot : mkboot.c ${IOLIB_DEP} ${BIN}viewdeck : viewdeck.c ${IOLIB_DEP} ${CC} viewdeck.c ${IOLIB_SRC} -o $@ +${BIN}punches : punches.c ${IOLIB_DEP} + ${CC} punches.c ${IOLIB_SRC} -o $@ diff --git a/Ibm1130/utils/punches.c b/Ibm1130/utils/punches.c new file mode 100644 index 00000000..bc094364 --- /dev/null +++ b/Ibm1130/utils/punches.c @@ -0,0 +1,337 @@ +/* + * punches - convert beteen IBM1130 simulator binary card image format and ascii text lists of punch numbers + * + * Usage: + * punches -b [infile [outfile]] + * Converts from ascii to binary. Reads stdin/writes stdout if infile/outfile not specified + * + * punches -a [infile [outfile]] + * Converts from binary to ascii. + * + * The ASCII format consists of an arbitrary number of card images. Each card image consists of + * a line with the word "start", followed by 80 lines each containing the punch data for one card + * column, followe by a line with the word "end". + * + * A column specification line consists of the word "blank", for a column with no punches, + * or an arbitrary number of integer row names separated by hyphens. The row names are 12, 11, 0, 1, 2, ..., 9. + * + * The character #, * or ; terminates an input line and the remainder of the line is ignored as a comment. + * Blank lines are ignored and may occur at any place in the input file. + * + * A typical card specification might look like this: + + start + * This is a comment line + 12-1-2 + blank + 5 # this is a comment after the data for column 3 + 4 + 2 + blank + blank + 11-5 + 2-6-3 +. \ +. | not all lines shown. Exactly 80 data lines are required +. / +blank +12-0-2-6-7-8 +end + + */ + +#include +#include +#include +#include "util_io.h" +#ifdef WIN32 // for Windows binary file mode setting +# include +# include +#endif + +#define TRUE 1 +#define FALSE 0 +typedef int BOOL; + +#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b))) + +BOOL failed = FALSE; +int ncards = 0; + +void tobinary (char *fnin, char *fnout); +void toascii (char *fnin, char *fnout); +void bail (char *msg); + +int main (int argc, char **argv) +{ + enum {MODE_UNKNOWN, MODE_TOBINARY, MODE_TOASCII} mode = MODE_UNKNOWN; + int i; + char *arg, *fnin = NULL, *fnout = NULL; + static char usestr[] = "Usage: punches -b|-a [infile [outfile]]"; + + for (i = 1; i < argc; i++) { + arg = argv[i]; + if (*arg == '-') { + arg++; + while (*arg) { + switch (*arg++) { + case 'b': + mode = MODE_TOBINARY; + break; + + case 'a': + mode = MODE_TOASCII; + break; + + default: + bail(usestr); + } + } + } + else if (fnin == NULL) + fnin = arg; + else if (fnout == NULL) + fnout = arg; + else + bail(usestr); + } + + util_io_init(); // check CPU for big/little endianness + + if (mode == MODE_TOBINARY) + tobinary(fnin, fnout); + else if (mode == MODE_TOASCII) + toascii(fnin, fnout); + else + bail(usestr); + + if (failed) { + if (fnin != NULL) { // if there was an error, delete output file if possible + unlink(fnout); + fprintf(stderr, "Output file \"%s\" deleted\n", fnout); + exit(1); + } + else + bail("Output file is incorrect"); + } + else // if no error, tell how many cards we converted + fprintf(stderr, "* %d card%s converted\n", ncards, (ncards == 1) ? "" : "s"); + + return 0; +} + +// alltrim - remove string's leading and trailing whitespace + +char *alltrim (char *str) +{ + char *c, *e; + + for (c = str; *c && *c <= ' '; c++) // skip over leading whitespace + ; + + if (c > str) // if there was some, copy string down over it + strcpy(str, c); + + for (e = str-1, c = str; *c; c++) // find last non-white character + if (*c > ' ') + e = c; + + e[1] = '\0'; // terminate string immediately after last nonwhite character + return str; // return pointer to string +} + +void tobinary (char *fnin, char *fnout) +{ + FILE *fin, *fout; + BOOL gotnum; + int col, v, lineno = 0; + char str[256], *c; + unsigned short buf[80], punches; + static unsigned short punchval[13] = { + 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, // 0, 1, 2, 3, 4 + 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, // 5, 6, 7, 8, 9 + 0x0000, // there is no 10 punch + 0x4000, 0x8000}; // 11 and 12. + + if (fnin == NULL) { + fin = stdin; + } + else if ((fin = fopen(fnin, "r")) == NULL) { + perror(fnin); + exit(1); + } + + if (fnout == NULL) { + fout = stdout; +#ifdef WIN32 + _setmode(_fileno(stdout), _O_BINARY); +#endif + } + else if ((fout = fopen(fnout, "wb")) == NULL) { + perror(fnout); + exit(1); + } + + col = 0; // we are starting between cards, expect start as first data line + + while (fgets(str, sizeof(str), fin) != NULL && ! failed) { + alltrim(str); // trim leading/trailing blanks (including newline) + lineno++; // count input line + + if (*str == ';' || *str == '#'|| *str == '*' || ! *str) + continue; // ignore comment or blank line + + if (strnicmp(str, "start", 5) == 0) { // start marks new card, proceed to column 1 (strnicmp so trailing comment is ignored) + if (col == 0) + col = 1; + else { + fprintf(stderr, "\"start\" encountered where column %d was expected, at line %d\n", lineno); + failed = TRUE; + } + } + else if (strnicmp(str, "end", 3) == 0) { // end is expected as 81'st data line + if (col == 81) { + fxwrite(buf, 2, 80, fout); // write binary card image to output file + ncards++; // increment card count + col = 0; // reset, expect start next + } + else { + fprintf(stderr, "\"end\" encountered where "); + + if (col == 0) + fprintf(stderr, "\"start\""); + else + fprintf(stderr, "column %d", col); + + fprintf(stderr, " was expected, at line %d\n", lineno); + failed = TRUE; + } + } + else if (BETWEEN(col, 1, 80)) { // for column 1 to 80, we expect a data line + if (strnicmp(str, "blank", 5) == 0) { // blank indicates an unpunched column + buf[col-1] = 0; + col++; + } + else { + punches = 0; // prepare to parse a data line. Punches is output binary value for column + + v = 0; // v is current punch number + gotnum = FALSE; // gotnum indicates we've seen a punch number + + for (c = str; ! failed; c++) { + if (BETWEEN(*c, '0', '9')) { // this is a digit, accumulate into current punch number + v = v*10 + *c - '0'; + gotnum = TRUE; // note that we've seen a value + } + else if (*c == '-' || *c == '\0') { // at - separator or at end of string + if (gotnum && BETWEEN(v, 0, 12) && v != 10) + punches |= punchval[v]; // add correct bit to column binary value + else { // error if number not seen or punch number not 0..9, 11, or 12 + fprintf(stderr, "Invalid punch value %d at line %d\n", v, lineno); + failed = TRUE; + break; + } + + if (*c == '\0') { // at end of string store value and advance column count + buf[col-1] = punches; + col++; + break; + } + else { + v = 0; // at separator, reset for next punch value + gotnum = FALSE; + } + } + else if (*c == '#' || *c == ';' || *c == '*') { + break; // terminate line parsing at comment character + } + else { // invalid character + fprintf(stderr, "Unexpected character '%c' at line %d\n", *c, lineno); + failed = TRUE; + break; + } + } + } + } + else { // we expected start or end when not expecting column data + fprintf(stderr, "\"%s\" encountered where \"%s\" was expected, at line %d\n", str, + (col == 0) ? "start" : "end", lineno); + failed = TRUE; + } + } + + fclose(fin); + fclose(fout); +} + +void toascii (char *fnin, char *fnout) +{ + FILE *fin, *fout; + unsigned short buf[80], mask; + int nread, col, row; + BOOL first; + static char *punchname[] = {"12", "11", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + + if (fnin == NULL) { + fin = stdin; // no input file named, read from stdin +#ifdef WIN32 + _setmode(_fileno(stdin), _O_BINARY); // (on Windows, must set binary mode) +#endif + } + else if ((fin = fopen(fnin, "rb")) == NULL) { // open named input file + perror(fnin); + exit(1); + } + + if (fnout == NULL) { // no output file named, write to stdout + fout = stdout; + } + else if ((fout = fopen(fnout, "wb")) == NULL) { // open named output file + perror(fnout); + exit(1); + } + // write comment with input file name + fprintf(fout, "* converted from %s\n", (fnin == NULL) ? "" : fnin); + + while ((nread = fxread(buf, 2, 80, fin)) == 80) { // pull cards from binary file + ncards++; // increment card count + fprintf(fout, "**** card %d\nstart\n", ncards); // write comment with card number and start statement + + for (col = 0; col < 80; col++) { // dump 80 columns + if (buf[col] == 0) { + fprintf(fout, "blank\n"); // no punches this column + } + else if (buf[col] & 0x000F) { // if low bits are set it is not a valid IBM1130 card image + fprintf(stderr, "Input file is not an IBM 1130 card image, low bits set found at card image %d\n", ncards); + failed = TRUE; + break; + } + else { + first = TRUE; // scan the 12 punch bits + for (mask = 0x8000, row = 0; row < 12; row++, mask >>= 1) { + if (buf[col] & mask) { // output name of punch row for each bit set (12, 10, 0, ..., 9) + fprintf(fout, "%s%s", first ? "" : "-", punchname[row]); + first = FALSE; // next punch will need a hyphen + } + } + putc('\n', fout); + } + } + + fprintf(fout, "end\n"); + } + + if (nread != 0) { // oops, file wasn't a multiple of 160 bytes in length + fprintf(stderr, "Input file invalid or contained a partial card image\n"); + failed = TRUE; + } + + fclose(fin); + fclose(fout); +} + +void bail (char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} diff --git a/Ibm1130/utils/punches.mak b/Ibm1130/utils/punches.mak new file mode 100644 index 00000000..dc099f22 --- /dev/null +++ b/Ibm1130/utils/punches.mak @@ -0,0 +1,176 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "punches.mak" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : $(OUTDIR)/punches.exe $(OUTDIR)/punches.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c +# ADD CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c +CPP_PROJ=/nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /FR$(INTDIR)/ /Fp$(OUTDIR)/"punches.pch" /Fo$(INTDIR)/ /c +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"punches.bsc" +BSC32_SBRS= \ + $(INTDIR)/punches.sbr \ + $(INTDIR)/util_io.sbr + +$(OUTDIR)/punches.bsc : $(OUTDIR) $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ + /PDB:$(OUTDIR)/"punches.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"punches.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/punches.obj \ + $(INTDIR)/util_io.obj + +$(OUTDIR)/punches.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : $(OUTDIR)/punches.exe $(OUTDIR)/punches.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c +# ADD CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c +CPP_PROJ=/nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /FR$(INTDIR)/ /Fp$(OUTDIR)/"punches.pch" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"punches.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"punches.bsc" +BSC32_SBRS= \ + $(INTDIR)/punches.sbr \ + $(INTDIR)/util_io.sbr + +$(OUTDIR)/punches.bsc : $(OUTDIR) $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ + /PDB:$(OUTDIR)/"punches.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"punches.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/punches.obj \ + $(INTDIR)/util_io.obj + +$(OUTDIR)/punches.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\punches.c + +$(INTDIR)/punches.obj : $(SOURCE) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\util_io.c +DEP_UTIL_=\ + .\util_io.h + +$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR) + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/Ibm1130/utils/util_io.c b/Ibm1130/utils/util_io.c new file mode 100644 index 00000000..4578f6d6 --- /dev/null +++ b/Ibm1130/utils/util_io.c @@ -0,0 +1,155 @@ +// util_io - I/O routines from simh package -- "endian-independent" +// borrowed from scp.c, with this copyright notice: + +// use fxread and fxwrite instead of fread and fwrite + +/* + Copyright (c) 1993-2002, Robert M Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not + be used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. +*/ + +/* Endian independent binary I/O package + + For consistency, all binary data read and written by the simulator + is stored in little endian data order. That is, in a multi-byte + data item, the bytes are written out right to left, low order byte + to high order byte. On a big endian host, data is read and written + from high byte to low byte. Consequently, data written on a little + endian system must be byte reversed to be usable on a big endian + system, and vice versa. + + These routines are analogs of the standard C runtime routines + fread and fwrite. If the host is little endian, or the data items + are size char, then the calls are passed directly to fread or + fwrite. Otherwise, these routines perform the necessary byte swaps + using an intermediate buffer. +*/ + +#include +#include "util_io.h" + +#define int32 int +#define FLIP_SIZE 1024 /* make the flip buffer smaller for these utilities */ + +static int sim_end = 1; /* 1 = little-endian */ +static unsigned char sim_flip[FLIP_SIZE]; +static int end_tested = 0; + +void util_io_init (void) +{ + union {int32 i; char c[sizeof (int32)]; } end_test; + + end_test.i = 1; /* test endian-ness */ + sim_end = end_test.c[0]; + end_tested = 1; +} + +size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr) +{ + size_t c, j, nelem, nbuf, lcnt, total; + int32 i, k; + unsigned char *sptr, *dptr; + + if (! end_tested) + util_io_init(); + + if (sim_end || (size == sizeof(char))) + return fread(bptr, size, count, fptr); + + if ((size == 0) || (count == 0)) + return 0; + + nelem = FLIP_SIZE / size; /* elements in buffer */ + nbuf = count / nelem; /* number buffers */ + lcnt = count % nelem; /* count in last buf */ + + if (lcnt) + ++nbuf; + else + lcnt = nelem; + + total = 0; + dptr = bptr; /* init output ptr */ + + for (i = nbuf; i > 0; i--) { + if ((c = fread(sim_flip, size, (i == 1) ? lcnt : nelem, fptr)) == 0) + return total; + + total += c; + + for (j = 0, sptr = sim_flip; j < c; j++) { + for (k = size - 1; k >= 0; k--) + *(dptr + k) = *sptr++; + + dptr += size; + } + } + + return total; +} + +size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr) +{ + size_t c, j, nelem, nbuf, lcnt, total; + int32 i, k; + unsigned char *sptr, *dptr; + + if (! end_tested) + util_io_init(); + + if (sim_end || (size == sizeof(char))) + return fwrite(bptr, size, count, fptr); + + if ((size == 0) || (count == 0)) + return 0; + + nelem = FLIP_SIZE / size; /* elements in buffer */ + nbuf = count / nelem; /* number buffers */ + lcnt = count % nelem; /* count in last buf */ + + if (lcnt) + ++nbuf; + else + lcnt = nelem; + + total = 0; + sptr = bptr; /* init input ptr */ + + for (i = nbuf; i > 0; i--) { + c = (i == 1) ? lcnt : nelem; + + for (j = 0, dptr = sim_flip; j < c; j++) { + for (k = size - 1; k >= 0; k--) + *(dptr + k) = *sptr++; + + dptr += size; + } + + if ((c = fwrite(sim_flip, size, c, fptr)) == 0) + return total; + + total += c; + } + + return total; +} diff --git a/Ibm1130/utils/util_io.h b/Ibm1130/utils/util_io.h new file mode 100644 index 00000000..a3cc7bf6 --- /dev/null +++ b/Ibm1130/utils/util_io.h @@ -0,0 +1,10 @@ +// util_io.h - definitions for simulator io routines + +#ifndef FILE +# include +#endif + +void util_io_init(void); +size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr); +size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr); +