;=================================================================
;
;  		 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

