;=================================================================
;
;                SUBGEN.ASM Version 1.2
;                  (Original - Feb/82)
;
;             Submit File Generator Program
;
;                  By Steve Pritchard
;
;               of Solutions Canada Inc.
;                  83 Cummer Ave,
;                  Willowdale, Ontario
;                  M2M 2E6   (519)-223-7549
;
;
;
;           Copyrighted(1982) by Steve Pritchard
;
; PERMISSION IS GIVEN FOR USE AND FOR DISTRIBUTION OF THESE ROUTINES
;
;          BUT THEY ARE NOT TO BE SOLD FOR PROFIT.
;
;
;=================================================================
;
; Fixes/Updates in reverse order.
;
; Feb/27/82 - Fix problem of writing to unopened file that causes
;             CP/M to go crazy. (Harvey Fishman)
;
; Feb/24/82 - Remove attribute flags from match testing, remove
;             limit on file capacity (W. Earnest)
;
; Feb/12/82 - Original. Lifted mostly from FMAP by WARD CHRISTENSEN
;
;-----------------------------------------------------------------
;
;Possible Extensions
;
;(1) -  Multiple disk files. Would need expanded sort capability and
;       probably drive substitute character.
;
;(2) -  Since the file match logic is in SUBGEN in can be expanded
;       beyond CP/Ms wildcard approach.
;
;=================================================================
;
;
;               ---  PGM Generation Options ---
;
FALSE   EQU     0
TRUE    EQU     NOT FALSE
;
RMAC    EQU     FALSE
FNFTMRK EQU     '@'             ;char used to signal fn.ft substitute point
;
DEFP    EQU     FALSE           ;default Prompt option
DEFH    EQU     FALSE           ;        header option
DEFT    EQU     FALSE           ;        trailer option
DEFNOT  EQU     FALSE           ;        not (invert) option
DEFLOG  EQU     TRUE            ;        log option
;
;=================================================================
;
;                LET WORK BEGIN ........
;
       IF      RMAC
       ASEG                    ; FOR RMAC
       ENDIF
;
;               -----     EQUATES   -------
;
;
FCB     EQU     5CH             ;SYSTEM FCB
CR      EQU     13
LF      EQU     10
ELEN    EQU     8+3             ;length of entry
;
; BDOS EQUATES
;
RDCHR   EQU     1               ;READ CHAR FROM CONSOLE
WRCHR   EQU     2               ;WRITE CHR TO CONSOLE
PRINT   EQU     9               ;PRINT CONSOLE BUFF
RCBUF   EQU     10              ;READ CONSOLE BUFFER
CONST   EQU     11              ;CHECK CONS STAT
FOPEN   EQU     15              ;0FFH=NOT FOUND
FCLOSE  EQU     16              ;   "   "
FSRCHF  EQU     17              ;   "   "
FSRCHN  EQU     18              ;   "   "
ERASE   EQU     19              ;NO RET CODE
FREAD   EQU     20              ;0=OK, 1=EOF
FWRTE   EQU     21              ;0=OK, 1=ERR, 2=?, 255=NO DIR SPC
FMAKE   EQU     22              ;255=BAD
FREN    EQU     23              ;255=BAD
FDMA    EQU     26
BDOS    EQU     5
REBOOT  EQU     0
;
;
;
;               ------  MAINLINE  --------
;
;
;               PROGRAM INITIATION
;

       ORG     100H
       JMP     START
VERSION DB            'SUBGEN - February 24/82 Version'
       DB      CR,LF,'Copyright(1982) Steve Pritchard'
       DB      CR,LF
       DB      '$'
HELP    DB      CR,LF,'Command format:SUBGEN [d:afn.ft] [options]'
       DB      CR,LF
       DB      CR,LF,'It will generate SUBGEN.SUB from d:afn.ft file match'
       DB      CR,LF,'under control of skeleton obtained from prompt'
       DB      CR,LF,'and will substitute fn.ft where ever it finds the'
       DB      CR,LF,'character '
       DB      FNFTMRK,' (Try a . suffix and prefix too)'
       DB      CR,LF
       DB      CR,LF,'Options are:-'
       DB      CR,LF,'P = prompt on each file for n, y or CR'
       DB      CR,LF,'H = generate header(s) before body'
       DB      CR,LF,'T = generate trailer(s) after body'
       DB      CR,LF,'- = invert select logic'
       DB      CR,LF,'L = invert default logging option'
       DB      CR,LF,'$'
START   LXI     H,0
       DAD     SP
       SHLD    STACK
       LXI     SP,STACK
;
;               MAIN PROGRAM FLOW
;
       CALL    INIT            ;initialize
       CALL    DIRLOAD         ;load directory into memory
       CALL    OPENFILE        ;open output file
       CALL    TYPEHIT         ;type number of hits
       LHLD    COUNT           ;check number found
       MOV     A,H
       ORA     L
       JZ      EXIT            ;return no work
       CALL    SORTDIR         ;sort dir entries
       CALL    FORMBUF         ;form pretty buffer
       CALL    WHEADER         ;write file header(s) if reqd
       CALL    SKELIN          ;read standard format line(s)
       CALL    WFILE           ;write body of file
       CALL    WTRAIL          ;write file trailer(s) if reqd
EXIT    CALL    CLSEFILE        ;close output file
       NOP     ! NOP ! NOP     ;JMP 0 FOR DDT
       LHLD    STACK
       SPHL
       RET
;============================================================
;                       1ST LEVEL ROUTINES
;============================================================
;
;               INITIALIZE
;
INIT    LXI     D,VERSION       ;T/ON help if ? in FCB1 pos 1
       LDA     FCB+1
       CPI     '?'
       JNZ     INIT03
       LDA     FCB+2           ;check if just ?
       CPI     ' '
       JNZ     INIT03          ;must be CP/M *.*
       LXI     D,HELP          ;yes - so print and quit
       CALL    WRCON
       JMP     EXIT            ;out in a hurry
INIT03  CALL    WRCON
       CALL    SAVEOPT         ;save options
       LXI     H,FCB+1         ;format FCB to ????????.???
       MVI     B,ELEN          ;FN+FT count
QLOOP   MVI     M,'?'           ;store '?' in FCB
       INX     H
       DCR     B
       JNZ     QLOOP
       RET
;
;               LOAD THE DIRECTORY (SELECTED) INTO MEMORY
;
DIRLOAD MVI     C,FSRCHF        ;search first
DIRL10  LXI     D,FCB
       CALL    BDOS            ;read first
       INR     A               ;some?
       RZ                      ;jmp no to done
       CALL    SELENT          ;select entry
       MVI     C,FSRCHN        ;search next
       JMP     DIRL10          ;repeat
;
;               OPEN OUTPUT FILE
;
OPENFILE
       LXI     D,MYFCB         ;open file
       MVI     C,ERASE
       CALL    BDOS
       LXI     D,MYFCB
       MVI     C,FMAKE
       CALL    BDOS
       INR     A
       JZ      OPEN1           ;if error
       STA     OPENFLAG        ;else show file is open
       RET
OPEN1   CALL    ERXIT           ;abort type error
       DB      '>> File MAKE error'
       DB      CR,LF,'$'

;
;               SORT THE SAVED ENTRIES
;
SORTDIR LHLD    COUNT           ;init the order table
       PUSH    H               ;file count on stack
       XCHG
       LHLD    NEXTT
       SHLD    AORDER          ;pointer table start
       PUSH    H
       DAD     D               ;2 bytes per file
       DAD     D
       SHLD    NEXTT           ;new table limit
       POP     H
       LXI     D,TABLE
       LXI     B,ELEN          ;entry length
;
BLDORD  MOV     M,E             ;save lo ord addr
       INX     H
       MOV     M,D             ;save hi ord addr
       INX     H
       XCHG                    ;table addr in HL
       DAD     B               ;point to next entry
       XCHG
       XTHL                    ;count from stack
       DCX     H
       MOV     A,H
       ORA     L               ;test cpunt
       XTHL                    ;back to stack
       JNZ     BLDORD          ;..yes
       POP     H               ;clean up stack of count
       LHLD    COUNT           ;get count
       SHLD    SCOUNT          ;save as # to sort
       DCX     H               ;only 1 entry?
       MOV     A,H
       ORA     L
       JZ      SORTDONE        ;..yes, so skip sort
;
SORT    XRA     A               ;get a zero
       STA     SWITCH          ;show none switched
       LHLD    SCOUNT          ;get count
       DCX     H               ;use 1 less
       SHLD    TEMP            ;save # to compare
       SHLD    SCOUNT          ;save highest entry
       MOV     A,H
       ORA     L
       JZ      SORTDONE        ;exit if no more
       LHLD    AORDER  ;point to order table
;
SORTLP  MVI     A,ELEN          ;length of compare
       CALL    COMPR           ;compare 2 entries
       CM      SWAP            ;swap if not in order
       INX     H               ;bump order
       INX     H               ;..table pointer
       PUSH    H
       LHLD    TEMP            ;get count
       DCX     H
       SHLD    TEMP
       MOV     A,H
       ORA     L
       POP     H
       JNZ     SORTLP          ;continue
;
;ONE PASS OF SORT DONE
       LDA     SWITCH          ;any swaps done?
       ORA     A
       JNZ     SORT            ;jmp yes to repeat another pass
;
SORTDONE
       RET
;
;               TYPE NUMBER OF HITS
;
TYPEHIT LHLD    COUNT
       MOV     A,H
       ORA     A
       JNZ     THIT02
       MOV     A,L
       CPI     1
       JZ      THIT10
THIT02  LXI     D,HITM1
       CALL    WRCON
       LHLD    COUNT
       CALL    DECPRT
       LXI     D,HITM3
THIT05  CALL    WRCON
       RET
THIT10  LXI     D,HITM2
       LXI     H,HITM4-1
       MVI     M,' '
       JMP     THIT05
HITM1   DB      'There are $'
HITM2   DB      'There is 1'
HITM3   DB      ' selected files'
HITM4   DB      CR,LF,'$'
;
;               WRITE HEADER RECORDS IF REQD
;
WHEADER LDA     OPTH            ;see if requested
       ORA     A
       RZ                      ;return not
       LXI     H,PRHDR         ;Header prompt
       CALL    CONCOPY         ;copy console input to file
       RET
;
;               INPUT SKELETON LINES
;
SKELIN  LHLD    NEXTT           ;skel lines start where
       SHLD    FSKEL           ;dir entries stop
       SHLD    LSKEL
SKEL10  LXI     D,PRSKEL        ;skeleton prompt
       CALL    WRCON
       LXI     D,TBUF          ;input a line from console
       MVI     C,RCBUF
       CALL    BDOS
       CALL    TYPECR
       LDA     TBUF+1          ;check for data
       ORA     A
       JZ      SKEL50          ;jmp no
;
       MOV     B,A             ;move entry to save area
       LXI     D,TBUF+2        ;input data
       LHLD    LSKEL           ;output location
SKEL30  LDAX    D               ;pick up byte
       MOV     M,A             ;move it
       INX     D
       INX     H
       DCR     B
       JNZ     SKEL30          ;until done
       MVI     M,CR            ;add crlf
       INX     H
       MVI     M,LF
       INX     H
       SHLD    LSKEL           ;remember where we are
       JMP     SKEL10          ;try again
;
SKEL50  LHLD    FSKEL           ;see if any entries
       CALL    FLEND           ; .by doing a compare
       JNZ     SKEL60          ;jmp there are some
       LHLD    LSKEL           ;else default to FMAP output
       MVI     M,FNFTMRK
       INX     H
       MVI     M,CR            ;and trailer
       INX     H
       MVI     M,LF
       INX     H
       SHLD    LSKEL           ;and save
SKEL60  RET                     ;return
;
;               WRITE OUTPUT FILE
;
WFILE   LHLD    COUNT           ;number of entries to write
       MOV     C,L
       MOV     B,H
       LHLD    AORDER          ;first entry
WFILE10 MOV     E,M             ;indirect adr
       INX     H
       MOV     D,M
       INX     H
       PUSH    H               ;save where we are
       XCHG                    ;now HL has entry adr
       CALL    WENTRY          ;write entry
       POP     H               ;ready for next
       DCX     B
       MOV     A,B
       ORA     C
       JNZ     WFILE10         ;until done
       RET
;
;               WRITE TRAILERS IF REQD
;
WTRAIL  LDA     OPTT            ;see if requested
       ORA     A
       RZ                      ;return not
       LXI     H,PRTRLR        ;trailr prompt
       CALL    CONCOPY         ;copy console input to file
       RET
;
;               CLOSE OUTPUT FILE
;
CLSEFILE
       LDA     OPENFLAG        ;get flag
       ORA     A               ;is file open?
       RZ                      ;return if not
       MVI     A,'Z'-40H       ;write eof mark
       CALL    FILCHR
       CALL    WRSEC           ;and then the sector
       LXI     D,MYFCB         ;close file
       MVI     C,FCLOSE        ;function
       CALL    BDOS
       RET
;
;==========================================================
;               LEVEL 2 OR MORE ROUTINES
;==========================================================
;
;               SAVE OPTIONS AND INPUT FILE NAME
;
SAVEOPT LXI     D,FCB+1         ;move file name to FNFTMAT
       LXI     H,FNFTMAT
       MVI     B,8             ;FN portion
       MVI     C,0             ;first loop sw
       LDA     FCB+1           ;format to *.* if reqd
       CPI     ' '
       JNZ     SOPT20
       MVI     A,'*'           ;yes - do it
       STA     FCB+1
       STA     FCB+1+8
SOPT20  LDAX    D               ;pick up next byte
       CPI     '*'             ;need expanding?
       JNZ     SOPT30          ;no
SOPT25  MVI     M,'?'           ;so do it
       INX     H
       INX     D
       DCR     B
       JNZ     SOPT25          ;until
       JMP     SOPT40
SOPT30  MOV     M,A             ;copy byte across
       INX     H
       INX     D
       DCR     B
       JNZ     SOPT20          ;until
SOPT40  MOV     A,C             ;FT portion
       ORA     A
       MVI     B,3
       MVI     C,1             ;2nd time sw
       JZ      SOPT20          ;jmp only once so far
;
       LXI     D,FCB+17-1      ;Pick up options section
SOPT50  INX     D               ;next byte
       LDAX    D               ;next option byte
       CPI     ' '             ;test for end
       JZ      SOPT60          ; .yes
       CPI     00H             ;DDT support
       JZ      SOPT60
       MVI     B,(OPTTABE-OPTTAB)/2
       LXI     H,OPTTAB+1
SOPT53  CMP     M               ;hit
       JZ      SOPT55          ;jmp yes
       INX     H               ;no - try next
       INX     H
       DCR     B
       JNZ     SOPT53
       STA     SOPTMSG-1
       CALL    ERXIT           ;quit
       DB      CR,LF
       DB      '>> Invalid option=x'
SOPTMSG DB      '$'
SOPT55  DCX     H               ;have a hit
       MOV     A,M             ;invert hit flag
       XRI     TRUE            ;from default selected at sysgen
       MOV     M,A             ;and store back
       JMP     SOPT50
SOPT60  RET                     ;return all options set
;
;               COMPARE HL TO LSKEL. NZ=NOT EQUAL
;
FLEND   XCHG                    ;do a subtract
       LHLD    LSKEL
       MOV     A,E
       SUB     L
       MOV     A,D
       SBB     H
       RET                     ;return with carry set
;
;               SELECT ENTRY IF REQUIRED
;
;point to dir entry
SELENT  DCR     A               ;undo prev 'INR A'
       ANI     3               ;make mod4
       ADD     A               ;multiply...
       ADD     A               ;..by 32 because
       ADD     A               ;..each dir
       ADD     A               ;..entry is 32
       ADD     A               ;..bytes long
       LXI     H,81H           ;point to buffer (first FN.FT entry)
       ADD     L               ;point to entry
       MOV     L,A             ;save (CAN'T CARRY TO H)
       SHLD    SVEPOS          ;save position
       CALL    FNFTMTC         ;match to FNFT wanted and NOT sw invert
       RNZ                     ;return unwanted
       LDA     OPTP            ;user want ultimate overide
       CPI     TRUE
       JNZ     SELE30          ;no - so accept into table
       CALL    CONFIRM
       RNZ                     ;user does not want it
SELE30
;move entry to table
       LHLD    SVEPOS          ;entry to save
       XCHG                    ;entry to DE
       LHLD    NEXTT           ;next table entry to HL
       MVI     B,ELEN          ;name entry length
TMOVE   LDAX    D               ;get entry char
       ANI     7FH             ;less attributes
       MOV     M,A             ;store in table
       INX     D
       INX     H
       DCR     B               ;more?
       JNZ     TMOVE
       SHLD    NEXTT           ;save updated table addr
       LHLD    COUNT           ;get prev count
       INX     H
       SHLD    COUNT
       RET
;
;               COPY CONSOLE TO DISK FILE FOR HEADER/TRAILER
;
CONCOPY PUSH    H               ;save prompt location
COPC10  POP     D               ;write prompt
       PUSH    D
       CALL    WRCON
       LXI     D,TBUF          ;read reply
       MVI     C,RCBUF
       CALL    BDOS
       CALL    TYPECR
       LDA     TBUF+1          ;length of reply
       ORA     A               ;test length
       JZ      COPC99          ;return null line
       LXI     H,TBUF+2        ;not so write entry to file
       MOV     B,A
COPC20  MOV     A,M             ;this one
       CALL    FILCHR          ;write it
       INX     H               ;next
       DCR     B               ;until
       JNZ     COPC20
       MVI     A,CR            ;write CRLF to file
       CALL    FILCHR
       MVI     A,LF
       CALL    FILCHR
       JMP     COPC10          ;repeat
COPC99  POP     H               ;clean up stack
       RET
;
;               MATCH DIR ENTRY TO FN.FT SPECIFIED
;
;                   AND POSSIBLY INVERT MATCH
FNFTMTC LHLD    SVEPOS          ;entry to check
       LXI     D,FNFTMAT       ;master entry
       MVI     B,ELEN          ;number bytes to compare
FNFT10  MOV     A,M
       ANI     7FH             ;remove flag bit
       MOV     C,A             ;for compare
       LDAX    D               ;next byte from master
       CMP     C               ;to dir entry
       JZ      FNFT30          ;jmp ok
       CPI     '?'             ;master = ?
       JNZ     FNFT40          ;no - match not equal
FNFT30  INX     H               ;repeat for next byte
       INX     D
       DCR     B               ;until
       JNZ     FNFT10
;                               ;nz=no match, z=match
FNFT40  LDA     OPTNOT          ;invert option flag
       PUSH    PSW             ;save compare results
       ORA     A               ;nz = invert
       JZ      FNFT50          ;not so leave intact
       POP     PSW             ;get back result
       JNZ     FNFT45          ;was zero so make it NZ
       ORI     1               ;by ORI
       RET                     ;and leave
FNFT45  XRA     A               ;was NZ so make it Z
       RET                     ;and leave
FNFT50  POP     PSW             ;no invert so restore
       RET                     ;return nz=no, z = yes
;
;               CONFIRM ENTRY REQUIRED OR NOT
;
CONFIRM LHLD    SVEPOS
       MVI     B,8
       CALL    TYPENB
       MVI     A,'.'
       CALL    TYPE
       MVI     B,3
       CALL    TYPENB
       MVI     A,'?'
       CALL    TYPE
       MVI     C,RDCHR         ;read reply
       CALL    BDOS
       PUSH    A
       CALL    TYPECR          ;get to newline
       POP     A
       CPI     CR              ;look for ans
       JNZ     CONF10
       MVI     A,'Y'           ;CR=YES
CONF10  ORI     020H            ;make lower case
       CPI     'y'             ;affirmative
       RZ                      ;return yes=z
       CPI     'n'             ;must be n
       JNZ     CONFIRM         ;not so try again
       ORI     1               ;set nz = no
       RET
;
;               WRITES ENTRY MAKING FN.FT SUBSTITUTION
;
WENTRY  SHLD    SVEPOS          ;save position
       PUSH    B
       PUSH    D
       PUSH    H               ;and caller regs
       LHLD    FSKEL           ;first pos of skeleton
WENT10  MOV     A,M             ;process next char
       CPI     FNFTMRK         ;special marker for FN.FT substitute
       JZ      WENT20          ;yes - do that
       CALL    FILCHR          ;no -write character to file
WENT15  INX     H               ;next byte
       PUSH    H               ;save status
       CALL    FLEND           ;test end of skeleton
       POP     H               ;and back again
       JNZ     WENT10          ;there is more
       JMP     WENT99          ;done
WENT20  PUSH    H               ;save where we are
       MVI     C,0             ;type of subst sw. 0=FN.FT, 1=FN, 2=FT
       INX     H               ;see if nxt byte is .
       MVI     A,'.'
       CMP     M
       JNZ     WENT22
       MVI     C,1             ;it is so only do FN substitute
       JMP     WENT25
WENT22  DCX     H
       DCX     H               ;try previous
       CMP     M
       JNZ     WENT25
       MVI     C,2             ;FT only
WENT25  POP     H               ;reload ptr to skeleton
       PUSH    H
       MOV     A,C             ;sw
       CPI     2
       JZ      WENT30          ;do FN
       LHLD    SVEPOS
       MVI     B,8
       CALL    FILCHRNB        ;write FN but no blanks
WENT30  MOV     A,C             ;sw again
       ORA     A               ;see if need period
       JNZ     WENT35          ;jmp no
       MVI     A,'.'
       CALL    FILCHR          ;write period
WENT35  MOV     A,C             ;see if need FN.FT
       CPI     1
       JZ      WENT40          ;no
       MVI     B,3
       LHLD    SVEPOS
       LXI     D,8
       DAD     D
       CALL    FILCHRNB        ;write filetype
WENT40  POP     H               ;reload current ptr &
       JMP     WENT15          ;return to mainline
WENT99  POP     H               ;exit
       POP     D
       POP     B
       RET
;
;               TYPE CHAR IN A
;
TYPE    PUSH    B
       PUSH    D
       PUSH    H
       MOV     E,A
       MVI     C,WRCHR
       CALL    BDOS
       POP     H
       POP     D
       POP     B
       RET
;
;               WRITE MESSAGE ON CONSOLE
;                 (D->msg $)
;
WRCON   MVI     C,PRINT
       JMP     BDOS
;
;               TYPE MSG HL POINTS TO, B HAS LENGTH
;

TYPEIT  MOV     A,M
       CALL    TYPE
       INX     H
       DCR     B
       JNZ     TYPEIT
       RET
;
;               ERROR EXIT
;
ERXIT   POP     D       ;GET MSG
       MVI     C,PRINT
       CALL    BDOS
       JMP     EXIT
;
;               WRITE CHAR IN A TO FILE
;               (SAVES ALL REGS INCLUDING A)
FILCHR  PUSH    PSW
       PUSH    H
       LHLD    BUFAD           ;current buffer adr
       MOV     M,A
       INX     H
       SHLD    BUFAD
       MOV     A,H             ;see if full buffer
       DCR     A
       CZ      WRSEC           ;yes so write sector
       POP     H
       LDA     OPTLOG          ;test if log chosen
       ORA     A
       JZ      FILC80          ;not so do not type
       POP     PSW
       PUSH    PSW             ;get char and type
       CALL    TYPE
FILC80  POP     PSW             ;restore char
       RET
;
;               WRITE A SECTOR
;
WRSEC   PUSH    B
       PUSH    D
       LXI     D,MYFCB
       MVI     C,FWRTE
       CALL    BDOS
       ORA     A
       JZ      WROK
       CALL    ERXIT
       DB      CR,LF
       DB      '>> WRITE ERROR$'
WROK    CALL    FORMBUF         ;clean up buffer
       POP     D
       POP     B
       RET
;
;               TYPE ALL BUT SPACES
;               (HL -> msg, B has length)
;
TYPENB  MOV     A,M             ;ignore spaces
       CPI     ' '
       JZ      TPNB10
       CALL    TYPE
TPNB10  INX     H
       DCR     B
       JNZ     TYPENB
       RET
;
;               TYPE CRLF
;
TYPECR  PUSH    A
       MVI     A,CR
       CALL    TYPE
       MVI     A,LF
       CALL    TYPE
       POP     A
       RET
;
;               WRITE ALL BUT SPACES TO FILE
;               (HL -> msg, B has length)
;
FILCHRNB
       MOV     A,M             ;ignore spaces
       CPI     ' '
       JZ      FILB10
       CALL    FILCHR
FILB10  INX     H
       DCR     B
       JNZ     FILCHRNB
       RET
;
;               FORMAT A BUFFER AND SET UP CONTROL WORDS
;
FORMBUF PUSH    H
       PUSH    A
       LXI     H,080H          ;address of buffer
       SHLD    BUFAD           ;save it
       MVI     A,128
FBUF10  MVI     M,'Z'-040H      ;set to EOF
       INX     H
       DCR     A
       JNZ     FBUF10
       POP     A
       POP     H
       RET
;
;               COMPARE ROUTINE FOR SORT
;               (A has number bytes to compare)
;
COMPR   PUSH    H               ;save table addr
       MOV     E,M             ;load lo
       INX     H
       MOV     D,M             ;load hi
       INX     H
       MOV     C,M
       INX     H
       MOV     B,M
;BC, DE now point to entries to be compared
       XCHG
       MOV     E,A             ;better reg
CMPLP   LDAX    B
       CMP     M
       INX     H
       INX     B
       JNZ     CMPL80          ;out with not equal status
       DCR     E
       JNZ     CMPLP
       XRA     A               ;ensure zero cc
CMPL80  POP     H
       RET                     ;cond code
tells all
;
;               SWAP ENTRIES IN THE ORDER TABLE
SWAP    MVI     A,1
       STA     SWITCH          ;show a swap was made
       MOV     C,M
       INX     H
       PUSH    H               ;save table addr+1
       MOV     B,M
       INX     H
       MOV     E,M
       MOV     M,C
       INX     H
       MOV     D,M
       MOV     M,B
       POP     H
       MOV     M,D
       DCX     H               ;back pointer to correct position
       MOV     M,E
       RET
;
;                Print  HL in decimal with leading zero suppression
;
DECPRT: SUB     A               ;Clear leading zero flag
       STA     LZFLG
       LXI     D,-1000         ;Print 1000's digit
       CALL    DIGIT
       LXI     D,-100          ;Etc.
       CALL    DIGIT
       LXI     D,-10
       CALL    DIGIT
       MVI     A,'0'           ;Get 1's digit
       ADD     L
       JMP     TYPE
DIGIT:  MVI     B,'0'           ;Start off with ASCII 0
DIGLP:  PUSH    H               ;Save current remainder
       DAD     D               ;Subtract
       JNC     DIGEX           ;Quit on overflow
       POP     PSW             ;Throw away remainder
       INR     B               ;Bump digit
       JMP     DIGLP           ;Loop back
DIGEX:  POP     H               ;Restore pointer
       MOV     A,B
       CPI     '0'             ;Zero digit?
       JNZ     DIGNZ           ;No, type it
       LDA     LZFLG           ;Leading zero?
       ORA     A
       MVI     A,'0'
       JNZ     TYPE            ;Print digit
       RET                     ;no leading spaces for 0s
DIGNZ:  STA     LZFLG           ;Set leading zero flag so next zero prints
       JMP     TYPE            ;And print digit
LZFLG   DB      0
;===================================================================
;               VARIABLES  AND   CONSTANTS
;===================================================================
;
NEXTT   DW      TABLE           ;NEXT TABLE ENTRY
COUNT   DW      0               ;ENTRY COUNT
BUFAD   DW      80H             ;OUTPUT ADDR
OPTTAB  EQU     $               ;OPTIONS-nonzero mean selected
OPTP    DB      DEFP,'P'        ;prompt for selection yae/nae
OPTH    DB      DEFH,'H'        ;ask for header
OPTT    DB      DEFT,'T'        ;ask for trailer
OPTNOT  DB      DEFNOT,'-'      ;invert selection criteria
OPTLOG  DB      DEFLOG,'L'      ;log results to console
OPTTABE EQU     $
;
PRSKEL  DB      'Skeleton? $'
PRHDR   DB      'Header? $'
PRTRLR  DB      'Trailer? $'
;
OPENFLAG
       DB      0               ;Flag to show file opened
FSKEL   DW      0               ;Position of first skel rec byte
LSKEL   DW      0               ; last byte+1
MYFCB   DB      0,'SUBGEN  SUB',0
       DS      19
       DB      0
TBUF    DB      127     ;CONSOLE INPUT BUFFER
       DS      127
FNFTMAT DS      11              ;match mask
SCOUNT  DS      2               ;# TO SORT
SVEPOS  DS      2               ;save position
AORDER  DS      2               ;ORDER TABLE ADDRESS
TEMP    DS      2       ;SAVE DIR ENTRY
SWITCH  DS      1               ;SWAP SWITCH FOR SORT
       DS      80      ;STACK AREA
STACK   DS      2       ;SAVE OLD STACK HERE
TABLE   EQU     $       ;READ ENTRIES IN HERE
       END     100H