DATA	EQU	0D000H		;LOCATION OF DATA BLOCK
CODE	EQU	0E000H		;LOCATION OF ACTUAL CODE
VDM1	EQU	0CC00H		;VDM-1 SCREEN MEMORY LOCATION
;
	ORG	CODE
ALS8:	NOP
	JMP	LE03B
;
;PART OF THE CODE TO DELETE CUSTOM COMMANDS
;
LE004:	CALL	LE50C		;SET UP ABUF, H,L FOR DELETE
	JMP	LE4B7		;USE SYMLD CODE TO DELETE COMD
;
;THIS ROUTINE FETCHES DIGITS FROM THE BUFFER ADDRESSED
;BY B,C AND CONVERTS THE ASCII DECIMAL DIGITS INTO
;BINARY.  UP TO A 16-BIT VALUE CAN BE CONVERTED.  THE
;SCAN STOPS WHEN A BINARY ZERO IS FOUND IN THE BUFFER.
;
ADEC:	LXI	H,0		;GET A 16 BIT ZERO
ADE1:	LDAX	B		;FETCH ASCII DIGIT
	ORA	A		;SET ZERO FLAG
	RZ			;RETURN IFF FINISHED
	MOV	D,H		;DUPLICATE CURRENT VALUE
	MOV	E,L		;FROM H,L INTO D,E
	DAD	H		;CURRENT VALUE TIMES TWO
	DAD	H		;AGAIN - NOW 4X ORIG. VALUE
	DAD	D		;ADD IN ORIG VALUE - NOW 5X
	DAD	H		;TIMES TWO - NOW 10X
	SUI	30H		;CONVERT FETCHED DGT TO BINARY
	CPI	10		;CHECK FOR LEGAL VALUE
	CMC			;SET UP CARRY FLAG
	RC			;RETURN W/CARRY SET IF ERROR
	MOV	E,A		;ELSE MOVE BINARY VALUE TO E
	MVI	D,0		;AND ZERO TO D
	DAD	D		;AND ADD TO 10X ORIG. NUMBER
	INX	B		;NOW POINT TO NEXT DIGIT
	JMP	ADE1		;AND PROCESS IT
;
;LOWEST LEVEL ENTRY POINT -- INITIALIZES EVERYTHING
;
INITA:	LXI	H,FILE0		;POINT TO START OF DATA AREA
	XRA	A		;GET A ZERO
	MOV	C,A		;MOVE IT TO C
INIT2:	MOV	M,A		;STASH THE ZERO
	DCR	C		;DECREMENT C
	INX	H		;POINT TO NEXT LOCATION
	JNZ	INIT2		;IF HAVEN'T DONE 256 LOCATIONS
	STA	SYSYM		;ANOTHER LOCATION TO ZERO
	STA	SMODE		;AND ANOTHER
	STA	CUCOM		;AND STILL ANOTHER
	JMP	ALS8		;NOW START UP THE SYSTEM
;
;WARM RESTART - RESTORES I/O DRIVERS AND DOES PARTIAL
;INITIALIZATION
;
LE03B:	MVI	C,(CRLF-IONME) AND 0FFH
	LXI	SP,SMODE	;SET STACK POINTER
	LXI	D,IONME		;POINT TO IO CODE SOURCE
	LXI	H,SYSIO		;POINT TO DEST IN DATA AREA
LE046:	LDAX	D		;GET A BYTE
	MOV	M,A		;PUT IT IN DATA AREA
	INX	D		;SOURCE POINTER
	INX	H		;DEST POINTER
	DCR	C		;NO OF BYTES LEFT TO BE MOVED
	JNZ	LE046		;IF NOT DONE
	LXI	H,ALS8		;POINT TO START CODE
	SHLD	SYMADD		;INITIAL SYMBOL TABLE ADDR
	MVI	A,(IBUF+81) AND 0FFH
	STA	TERMW		;INITIAL TERMINAL WIDTH
	XRA	A		;GET A ZERO
	STA	SMODE		;SAVE AS SMODE
	STA	CHRR		;AND CHRR
;
;WARM RESTART WITH NO INITIALIZATION
;PRINTS "READY" AND ENTERS MAIN PROCESSING LOOP
;
EORMS:	LXI	H,SYSIN		;POINT TO CUR DRIVER ADDRS
	CALL	LE15A		;SET I/O JUMPS TO CUR DRIVERS
	CALL	CRLF		;PRINT A CR/LF ON TERMINAL
	LXI	H,RDYMG		;POINT TO READY MESSAGE
	CALL	SCRN		;PRINT "READY"
	JMP	LE0CB		;ANOTHER CRLF & ENTER MAIN LOOP
;
;THIS IS THE MAIN ALS-8 COMMAND LOOP
;
LE072:	LXI	H,0		;GET A ZERO TO H,L
	SHLD	SWCH1		;TO SWITCH 1
LE078:	LXI	SP,SMODE	;SET STACK POINTER
	CALL	READ		;GET A COMND LINE IN IBUF
	INX	H		;POINT TO 1ST CHAR
	MOV	A,M		;GET IT
	CPI	'9'+1		;COMPARE TO 9
	JC	LINE		;NEW LINE IF 1ST CHAR NUMERIC
	CALL	VALC		;EXTRACT ASCII & BINARY ARGS
	MVI	B,4		;LENGTH OF ALS8 COMMANDS
	LXI	D,CTAB		;POINT AT COMMAND TABLE
	CALL	COMS		;SEE IF COMMAND IS IN TABLE
	PUSH	H		;SAVE H,L PNTR INTO LINE
	JZ	LE0AC		;MATCH WAS FOUND
	POP	H		;RESTORE POINTER TO LINE
	INX	D		;POINT TO 2ND PART OF TABLE
	CALL	COMS		;SEARCH 2ND PART
	JZ	LE0A5		;IF MATCH FOUND
	LXI	D,CUCOM		;NO MATCH, TRY CUSTOM TABLE
	CALL	LE240		;SEARCH CUSTOM TABLE
	JNZ	WHAT		;ERROR MSG IF NO MATCH FOUND
LE0A5:	PUSH	H		;SAVE H,L
	CALL	LE31E		;CONVERT ABUF CNTS TO BINARY
	JC	WHAT		;IF ABUF NOT LEGAL NO.
LE0AC:	LDA	IOSWC		;1 COMND DRVR SWTCH DELAY FLAG
	ORA	A		;SET FLAGS
	CNZ	LE157		;TIME TO SWITCH DRIVERS
	POP	H		;RESTORE POINTER TO COMD LINE
	CALL	LE0DD		;EXECUTE THE COMMAND
EOR:	LDA	SWCH1		;GET I/O RESTORE SWITCH
	ORA	A		;SET FLAGS
	JNZ	EORMS		;RESTORE JMPS & PRT "READY"
	LDA	SWCH2		;GET DRIVER HOLD REQ.
	ORA	A		;SET FLAGS
	JNZ	EORNS		;HOLD CURRENT DRVR, DO CRLF
	LXI	H,SYSIN		;POINT TO SYSTEM DRIVERS
	CALL	LE15A		;PUT IN JUMPS & DO CRLF
LE0CB:	CALL	CRLF		;PRINT CRLF
	JMP	LE072		;DO ANOTHER ALS8 COMMAND
;
;END OF MAIN PROCESSING LOOP
;
;FOLLOWING RETURN POINT DOES A CR/LF AND LEAVES
;ALL DRIVERS AND SWITCHES INTACT
;
EORNS:	CALL	CRLF		;PRINT A CRLF
	JMP	LE078		;RET LEAVING DRIVERS INTACT
;
;SIGN-ON AND COMMAND MODE MESSAGE
;
RDYMG:	DB	'READY',0DH
;
;HERE IS WHERE WE DISPATCH TO COMMANDS
;NOTE THAT SINCE THIS IS A CALLED ROUTINE, SO
;IN EFFECT IS THE ROUTINE TRANSFERED TO
;
LE0DD:	PCHL			;GO TO IT
;
;THE IODR COMMAND AND IT'S ZILLION FORMS
;
IODR:	MVI	C,MAXFIL	;MAX NUMBER OF DRIVER NAMES
	LXI	H,IOFLE		;POINT TO DRIVER FILE
	LDA	FBUF		;NAME IN SLASHES AFTR COMMAND ?
	ORA	A		;SET FLAGS
	JZ	LE151		;NO - PRT LIST OF DRIVERS
	XCHG			;YES - TABLE PNTR TO D,E
	CALL	LE68D		;SEARCH DIRECTORY FOR NAME
	JNZ	LE0FE		;NAME FOUND
	CALL	VCHK		;NOT FOUND - CHECK FOR PARMS
	LDA	FEF		;GET FREE ENTRY FOUND FLAG
	ORA	A		;SET FLAGS
	JZ	LE5CC		;NO ENTRIES LEFT - PRT "FULL"
	LHLD	FREAD		;GET ADDR OF FREE ENTRY
LE0FE:	SHLD	FREAD		;FREAD HAS ADDR OF ENTRY
	CALL	ROOM		;PUT FILE NAME INTO DIRECTORY
	LXI	H,NMLEN		;NAME LENGTH
	DAD	D		;H,L POINT JUST AFTER NAME
	LDA	ABUF		;SEE IF ADDR SPECIFIED
	ORA	A		;SET FLAGS
	JNZ	LE119		;IF ADDR WAS SPECIFIED
	SHLD	OPRD		;NO ADDR, SET UP FOR SWTCH
	INR	A		;MAKE ACCUM. NON-ZERO
	STA	IOSWC		;SET I/O SWITCH FLAG
	JMP	LE14C		;PRINT THE SELECTED ENTRY
LE119:	XCHG			;SAVE I/O ADDRS IN D,E	
	LHLD	BBUF		;GET 1ST ADDR SPECIFIED
	MOV	A,L		;L TO A
	ORA	H		;SEE IF ADDRS IS 0
	LDA	ABUF+7		;POINT TO 2ND ASCII PARM.
	JNZ	LE130		;IF 1ST ADDR NOT ZERO
	ORA	A		;SEE IF 2ND ADDR SPECIFIED
	JNZ	LE12D		;IF 2ND ARGUMENT NOT OMITTED
	STAX	D		;STORE 0 FOR INPUT, DELT ENTRY
	INX	D		;FOR 2ND BYTE
	STAX	D		;ZERO IT TOO
BITBKT:	RET			;DONE
;
;1ST ARG. WAS 0, 2ND WAS PRESENT
;
LE12D:	LHLD	SYSIN		;GET STD SYSIN DRIVER
LE130:	XCHG			;TO D,E
	MOV	M,E		;STORING IT AS INPUT DRIVER
	INX	H		;2ND BYTE
	MOV	M,D		;STORE IT
	INX	H		;POINT TO OUTPUT DRIVER
	XCHG			;OUTPUT DRIVER ADDR TO D,E
	ORA	A		;SET FLAGS FOR 2ND ARG OMITTED
	LXI	H,BITBKT	;POINT TO THE BIT BUCKET
	JZ	LE148		;IF 2ND ARG OMITTED
	LHLD	BBUF+2		;GET 2ND ARG
	MOV	A,L		;MOVE L TO A
	ORA	H		;SEE IF ARG = 0
	JNZ	LE148		;JMP IF NOT ZERO
	LHLD	SYSOT		;ELSE SET TO USE SYSOT
LE148:	XCHG			;OUTPUT ADDR TO D,E
	MOV	M,E		;MOVING IT TO OUTPUT TABLE
	INX	H		;2ND HALF
	MOV	M,D		;DONE
LE14C:	MVI	C,1		;SET UP TO PRINT ENTRY
	LHLD	FREAD		;GET IT'S ADDRESS
LE151:	CALL	LE62A		;PRINT IT
	JMP	EORNS		;DONE WITH IODR
;
;SET UP I/O JUMPS TO I/O DRIVER SET WHOSE ADDRESSES
;ARE POINTED TO BY OPRD (SET ABOVE)
;
LE157:	LHLD	OPRD		;GET ADDRESS OF I/O ADDRESSAS
;
;STORE I/O JUMPS TO ADDRESSES POINTED TO BY CONTENTS OF
;H,L -- SYSIO, OR IF ENTERD IN LINE, ONE OF THE OTHER
;I/O DRIVERS
;
LE15A:	CALL	LODM		;GET THE 4 BYTES OF 2 ADDRESSES
	LXI	H,IN8		;POINT TO THE I/O JUMPS
	MVI	M,0C3H		;STORE JUMP INST.
	INX	H		;POINT TO NEXT BYTE
	MOV	M,B		;STORE IT
	INX	H		;2ND BYTE
	MOV	M,C		;STORE IT
	INX	H		;NOW 1ST BYTE FOR OUTPUT
	MVI	M,0C3H		;STORE JUMP INST
	INX	H		;POINT TO ADDR 1ST BYTE
	MOV	M,D		;STORE IT
	INX	H		;POINT 2ND BYTE
	MOV	M,E		;STORE IT
	XRA	A		;A ZERO
	STA	IOSWC		;RESET SWITCH TO NO-SWITCH MODE
	RET			;DONE
;
;THE FOLLOWING ROUTINE READS A COMMAND LINE FROM THE
;TERMINAL AND PUTS IT IN THE OUTPUT BUFFER
;
READ:	LXI	H,IBUF		;GET INPUT BUFFER ADDR
	SHLD	ADDS		;SAVE ADDRESS
	MVI	E,2		;INIT. CHAR COUNT
NEXT:	CALL	IN8		;READ A LINE
	CPI	'X'-40H		;CHECK FOR CNTL X
	JNZ	CR		;CHECK FOR C/R IF NOT CNTL X
	CALL	CRLF		;ELSE DO CRLF
	JMP	READ		;AND START OVER
CR:	CPI	0DH		;IS IT A C/R ?
	JNZ	DEL		;IF NOT, CHECK FOR CHAR DELETE
	MOV	A,L		;GET LOW ORDER BYTE OF ADDR
	CPI	IBUF AND 0FFH	;SEE IF CR IS ONLY CHAR ON LINE
	JZ	READ		;GET ANOTHER LINE IF SO
	MOV	M,B		;PUT CHAR IN THE LINE
	INX	H		;POINT TO NEXT POSITION
	MVI	M,1		;PUT END OF LINE INDICATOR
	INX	H		;POINT 1 AFTER THE LINE
	CALL	LF3DF		;GET TERMW+1 IN A
	INR	A		;INCREMENT IT FOR EOF MARK
	CALL	CLER		;CLEAR REST OF THE BUFFER
	LXI	H,IBUF-1	;POINT TO CHAR COUNT
	MOV	A,E		;PUT IT BEFORE THE LINE
	STA	CCNT		;AND SAVE AS CHAR COUNT
	RET			;DONE
DEL:	CPI	7FH		;IS THE CHAR A DELETE ?
	JNZ	CHAR		;IF NOT, PUT IT IN LINE
	MVI	A,IBUF AND 0FFH	;ELSE GET LOW-ORDER ADDR
	CMP	L		;MAKE SURE NOT AT IBUF
	JZ	NEXT		;IF SO, IGNORE DELETE
	DCX	H		;ELSE DCR BUFFER POINTER
	DCR	E		;AND CHAR COUNT
BSPA:	MVI	B,5FH		;GET BACKSPACE CHAR
	CALL	OUT8		;MAKE TERMINAL BKSPACE
	JMP	NEXT		;THEN GET NEXT CHAR
CHAR:	CALL	OUT8		;ECHO THE CHAR
	CPI	' '		;MAKE SURE IT'S PRINTABLE
	JC	NEXT		;SKIP IT IF IT'S CNTL CHAR
	MOV	M,A		;ELSE PUT IT IN THE BUFFER
	LDA	TERMW		;GET TERMINAL WIDTH
	CMP	L		;SEE IF WE'RE THERE
	JZ	BSPA		;BACKSPACE IF BUFFER OVERFLOW
	INX	H		;ELSE INCREMENT THE BUFFER PNTR
	INR	E		;AND THE CHAR COUNT
	JMP	NEXT		;THEN DO NEXT CHAR
;
;THIS ROUTINE IS USED TO BLANK OUT A PORTION OF MEMORY
;SINCE ONLY L IS TESTED, AREA MUST BE < 256 BYTES
;
CLER:	CMP	L		;SEE IF AT END OF AREA TO BLANK
	RZ			;DONE IF SO
	MVI	M,' '		;ELSE GET A SPACE
	INX	H		;INCREMENT THE MEMORY POINTER
	JMP	CLER		;AND TEST NEW ADDRESS
;
;HERE ARE THE BUILT IN I/O DRIVERS AND THEIR NAME
;THIS CODE IS MOVED INTO THE DATA PORTION DURING
;PROGRAM INITIALIZATION.
;PART OF THE ENTER COMMAND IS ALSO MOVED, FOR NO REASON.
;
IONME:	DB	'SYSIO'		;STANDARD DRIVER NAME
	DW	INDR		;INPUT ROUTINE ADDR
	DW	OUTDR		;OUTPUT ROUTINE ADDR
INP8:	CALL	STAT		;BECOMES INDR: AFTER THE MOVE
	JZ	INDR
	IN	UDATA
	ANI	7FH
	MOV	B,A
	RET
	IN	USTA		;THIS BECOMES STAT:
	ANI	DAV
	RET
OUTP8:	CALL	STAT
	JZ	NOCHR
	IN	UDATA		;NOTE THAT BEFORE EA. OUTPUT
	ANI	7FH
	CPI	ESC		;ALS8 TESTS FOR AN ESC. CHAR
	JZ	EORMS		;AND RETNS TO CMD MODE IF FOUND
	IN	USTA		;BECOMES NOCHR:
	ANI	TBE
	JZ	NOCHR
	MOV	A,B
	OUT	UDATA
	RET
;
;THE ENTER COMMAND.
;
ENTR:	CALL	VCHK		;MAKE SURE PARAMETERS GIVEN
	CALL	ENTS		;TO DO THE ENTER FUNCTION
	JC	WHAT		;IF ERROR FOUND
;
;CRLF UTILITY
;
CRLF:	MVI	B,0DH		;CAR. RETURN
	CALL	OUT8
LF:	MVI	B,0AH		;LINE FEED
	CALL	OUT8
	MVI	B,7FH		;NULLS FOR SLOW TERMINALS
	CALL	OUT8
	JMP	OUT8		;LET OUT8 DO THE RETURN
;
;TABLE SEARCH ROUTINE USED FOR BOTH COMMAND SEARCHES AND
;SYMBOL LOOK-UPS.  ZERO FLAG SET IF MATCH FOUND, IN WHICH
;CASE H,L HAS VALUE OF STRING (16 BIT).
;LENGTH OF STRING IS IN B, TABLE ADDRESS IS IN
;D,E, ADDS POINTS TO ITEM TO BE LOOKED UP.
;IF NO MATCH, D,E POINT TO BYTE AFTER TABLE END.
;
COMS:	LHLD	ADDS		;GET ADDR OF ITEM TO LOOK UP
	MOV	C,B		;LENGTH OF ITEM TO LOOK UP
	LDAX	D		;1ST BYTE OF NEXT TABLE ENTRY
	ORA	A		;IF ZERO, ==> END OF TABLE
	JZ	LE23E		;TO SET RET FLAG FOR NO MATCH
	CALL	SEAR		;SEE IF ENTRY MATCHES STRING
	LDAX	D		;GET 1ST BYTE OF VALUE
	MOV	H,A		;MOVING TO H,L
	INX	D		;INCREMENT POINTER
	LDAX	D		;GET 2ND BYTE OF VALUE
	MOV	L,A		;MOVE TO H,L COMPLETE
	RZ			;RET IF SEAR INDICATED MATCH
	INX	D		;ELSE POINT TO NEXT TABLE ITEM
	JMP	COMS		;AND TEST IT
LE23E:	INR	A		;MAKE NON ZERO
	RET			;INDICATING NO MATCH
;
;THE FOLLOWING ROUTINE IS THE SAME AS COMS, ABOVE, EXCEPT
;THAT IT IS USED TO SEARCH THE CUSTOM COMMAND TABLE, WHICH
;CONSISTS OF 5 CHAR NAMES WITH ONLY 1ST FOUR TESTED.
;BECAUSE OF THIS IT HAS AN EXTRA INX D INSTR.
;
LE240:	LHLD	ADDS		;GET ADDR OF ITEM TO LOOK UP
	MOV	C,B		;LENGTH OF ITEM TO LOOK UP
	LDAX	D		;1ST BYTE OF TABLE ENTRY
	ORA	A		;IF ZERO ==> END OF TABLE
	JZ	LE23E		;TO SET RET FLAG FOR NO MATCH
	CALL	SEAR		;SEE IF ENTRY MATCHES STRING
	INX	D		;SKIP 5TH CHAR OF ENTRY NAME
	LDAX	D		;GET 1ST BYTE OF VALUE
	MOV	H,A		;MOVING TO H,L
	INX	D		;POINT TO 2ND BYTE OF VALUE
	LDAX	D		;GET 2ND BYTE OF VALUE
	MOV	L,A		;MOVE TO H,L COMPLETE
	RZ			;RET IF SEAR INDICATED MATCH
	INX	D		;POINT TO NEXT ENTRY
	JMP	LE240		;TEST IT
;
;ROUTINE TO SEE IF TWO STRINGS ARE EQUAL.  STRINGS POINTED
;TO BY D,E AND H,L.  ZERO FLAG SET INDICATES MATCH.  REG C
;HAS LENGTH OF MASTER STRING.  D POINT AFTER ITS STRING
;EVEN IF NO MATCH; H,L POINTS AFTER IT'S STRING IF MATCH,
;ELSE TO 1ST NON-MATCHING CHAR.
;
SEAR:	LDAX	D		;GET A CHAR FROM 1 STRING
	CMP	M		;COMPARE TO OTHER STRING
	JNZ	INCA		;IF IT DOESN'T MATCH
	INX	H		;INCREMENT POINTER
	INX	D		;INCREMENT POINTER
	DCR	C		;COUNT OF CHARS LEFT TO CHECK
	JNZ	SEAR		;IF CHARS LEFT, TEST THEM
	RET			;ELSE DONE
INCA:	INX	D		;INCREMENT POINTER
	DCR	C		;DECREMENT COUNT
	JNZ	INCA		;KEEP INR. POINTER IF NOT DONE
	INR	C		;ELSE CLEAR ZERO FLAG
	RET			;AND RETURN
;
;ROUTINE TO ZERO OUT A BUFFER IN MEMORY
;
ZBUF:	XRA	A		;GET A ZERO
	LXI	D,ABUF+16	;POINT TO THE BUFFER
	MVI	B,16		;BUFFER LENGTH
ZBU1:	DCX	D		;DECREMENT POINTER
	STAX	D		;ZERO OUT A LOCATION
	DCR	B		;DECREMENT COUNT
	JNZ	ZBU1		;IF MORE LEFT TO ZERO
	RET			;DONE
;
;THE EXECUTE COMMAND - DOES A CALL TO A SPECIFIED ADDR.
;
EXEC:	CALL	VCHK		;CHECK FOR PROPER ARGUMENT
	CALL	CRLF		;DO CRLF
	LHLD	BBUF		;GET EXEC ADDR
	PCHL			;GO TO IT
;
;ROUTINE TO EXTRACT VALUES FROM A COMMAND LINE
;AND PLACE THEM IN BUFFERS
;
ETRA:	LXI	H,0		;GET A ZERO
	SHLD	BBUF+2		;ASSUME NO 2ND OPERAND
	SHLD	FBUF		;ASSUME NO FILE NAME IN /'S
	CALL	ZBUF		;ZERO OUT ABUF
	LXI	H,IBUF-1	;SET TO SCAN COMMAND LINE
VAL1:	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET CHAR
	CPI	' '		;SPACE ?
	CMC			;SET CARRY TO INDICATE CNTL CHR
	RNC			;DONE-CR ONLY CNTL CHR ALLOWED
	JNZ	VAL1		;IF CHAR WAS NOT A SPACE
	SHLD	PNTR		;ELSE SPACE, SAVE POINTER
	CALL	SBLK		;AND SCAN TO 1ST CHAR
	CMC			;CARRY SET ==> C/R 1ST CHAR
	RNC			;DONE THEN
	CPI	'/'		;FILE NAME DELIMITER ?
	JNZ	VAL5		;NO, LOOK FOR OTHER PARAMETERS
	LXI	D,FBUF		;YES, POINT TO FILE NAME BUFFER
	MVI	C,NMLEN		;FILE NAME LENGTH
VAL2:	INX	H		;MOVING NAME TO FILE NAME BUFR
	MOV	A,M		;GET A CHAR
	CPI	'/'		;TERMINATING SLASH ?
	JZ	VAL3		;DONE MOVING NAME THEN
	DCR	C		;ELSE DCR COUNT OF CHARS LEFT
	JM	WHAT		;IF NAME > 5 CHARS
	STAX	D		;ELSE PUT LETTER IN BUFFER
	INX	D		;INCREMENT DEST. POINTER
	JMP	VAL2		;AND DO NEXT CHARACTER
VAL3:	MVI	A,' '		;GET A SPACE
VAL4:	DCR	C		;DECREMENT COUNT OF CHARS LEFT
	JM	DONE		;IF NEGATIVE, DONE
	STAX	D		;PAD REST OF BUFR WITH SPACES
	INX	D		;INCREMENT BUFFER POINTER
	JMP	VAL4		;CONTINUE TILL BUFFER FILLED
DONE:	CALL	SBL2		;SCAN TO NEXT NON-SPACE CHAR
	CMC			;CARRY MEANS CHAR. RETRN FOUND
	RNC			;AND CAR. RETRN = DONE
VAL5:	LXI	D,ABUF		;POINT TO THE ASCII BUFFER
	CALL	LE2D7		;PUT IN ABUF & CNVRT BY MODE
	RC			;IF C/R WAS TERMINATING CHAR
	CALL	SBLK		;ELSE SCAN TO 2ND ASCII PARM.
	CMC			;TEST FOR C/R FOUND
	RNC			;RET., ELSE FALL THRU TO DO 2ND
LE2D7:	CALL	ALPS		;PUT PARM. IN ABUF
	MOV	A,E		;GET ENDING ADDR LOW BYTE
	SUB	B		;SUBTRACTING PARM LENGTH
	MOV	L,A		;TO GET BACK TO START
	MOV	A,D		;NOW HIGH ORDER BYTE
	SBI	0		;IN CASE OF BORROW
	MOV	H,A		;H,L HAS START OF PARM IN ABUF
	LDA	SMODE		;GET NUMERIC MODE
	ADD	A		;MULT. BY 2
	ADI	4		;AND ADD 4
	CMP	B		;TEST FOR NO. OF DIGITS ALLOWED
	RC			;# DIGITS > 4 AND HEX MODE
	CALL	NORM		;NORMALIZE ASCII NUMBER
	XCHG			;START OF SUB-BUFFER TO D,E
	LXI	H,7		;LENGTH OF SUB-BUFFERS IN ABUF
	DAD	D		;H,L POINT TO NEXT SUB-BUFFER
	XCHG			;NEXT SUB-BUFFER IN D,E
	RET			;DONE
;
;SOME NUMERICAL CONVERSION ROUTINES FOLLOW.
;B,C POINT TO 1ST ASCII DIGIT, NUMERIC STRING ENDS WITH 
;BINARY ZERO.  ANSWER IN H,L AND CARRY SET = ERROR.
;
;EMODE CONVERTS BASED ON CURRENT MODE SETTING, SMODE
;EQUAL TO 0 FOR HEX, 1 FOR OCTAL.
;
EMODE:	LDA	SMODE		;GET MODE SETTING
	ORA	A		;SET FLAGS
	JNZ	AOCT		;OCTAL IS 1
AHEX:	LXI	H,0		;START WITH A ZERO
AHE1:	LDAX	B		;GET A DIGIT
	ORA	A		;SEE IF ZERO
	RZ			;YES - DONE
	DAD	H		;MULT H,L BY TWO
	DAD	H		;AGAIN - NOW 4X ORIG VALUE
	DAD	H		;AGAIN - NOW 8X ORIG VALUE
	DAD	H		;AGAIN - NOW 10H X ORIG VALU
	CALL	AHS1		;CONVERT DIGIT TO BINARY
	CPI	10H		;SEE IF LEGAL
	CMC			;SET CARRY FLAG
	RC			;FOR PROPER ILLEAGLE RETURN
	ADD	L		;OTHERWISE ADD IT INTO THE NO.
	MOV	L,A		;AND RESTORE TO H,L
	INX	B		;NOW POINT TO NEXT ASCII DIGIT
	JMP	AHE1		;AND PROCESS IT
;
;ROUTINE TO CONVERT ASCII HEX DIGIT INTO BINARY
;
AHS1:	SUI	30H		;CONVERT 0-9 TO BINARY
	CPI	0AH		;SEE IF > ASCII 9
	RC			;RETURN IF NOT, DONE
	SUI	7		;TO TAKE CARE OF A-F
	CPI	0AH		;COMPARE TO DECIMAL 10
	RNC			;IF > 10 OR =, RETURN DONE
	MVI	A,0FFH		;ELSE BAD CHAR, SET A > 10H
	RET			;AND RETURN
;
;HERE IS A ROUTINE TO CONVERT BOTH OF TWO POSSIBLE
;VALUES IN ABUF INTO BINARY BASED ON THE CURRENT MODE
;SETTING, AND PLACE THEM INTO BBUF AND BBUF+2
;
LE31E:	LXI	B,ABUF		;POINT TO THE 1ST OPERAND
	CALL	EMODE		;CONVERT IT
	RC			;RETURN W/CARRY SET ON ERROR
	SHLD	BBUF		;PUT VALUE IN BBUF
	LXI	B,ABUF+7	;POINT TO 2ND VALUE
	CALL	EMODE		;CONVERT IT
	RC			;RETURN W/CARRY SET ON ERROR
	SHLD	BBUF+2		;PUT IT IN THE BINARY BUFFER
	RET			;DONE
;
;OCTAL TO BINARY CONVERSION
;
AOCT:	LXI	H,0		;START W/ZERO
LE336:	LDAX	B		;GET A CHAR
	ORA	A		;ZERO ?
	RZ			;DONE THEN, RETURN
	DAD	H		;MULT H,L BY TWO
	DAD	H		;AGAIN - NOW 4X ORIG VALU
	DAD	H		;AGAIN - NOW 8X ORIG VALU
	SUI	30H		;CONVERT ASCII DIGIT TO BINARY
	CPI	8		;LEGAL VALUE ?
	CMC			;SET CARRY FOR PROPER RETURN
	RC			;RETURN IF BAD
	ADD	L		;ELSE ADD IN VALUE
	MOV	L,A		;AND PUT IT BACK
	INX	B		;POINT TO NEXT ASCII DIGIT
	JMP	LE336		;AND PROCESS IT
;
;DECIMAL OUTPUT ROUTINE FOR BINARY NO. IN REG A.
;
DOUT:	CALL	BIND		;CONVRT A TO DECIMAL IN ADDS
LE34B:	CALL	LE57A		;PRINT 1ST TWO CHARS IN ADDS
	INX	H		;POINT TO 3RD CHAR IN ADDS
	MOV	B,M		;GET IT
	JMP	OUT8		;PRINT IT AND RETURN
;
;OCTAL OUTPUT ROUTINE
;
OOUT:	CALL	BINO		;CONVERT TO OCTAL IN ADDS
	JMP	LE34B		;PUT OUT 3 OCTAL DIGITS AND RET
;
;OCTAL FOLLOWED BY SPACE
;
OOTB:	CALL	OOUT		;PUT OUT OCTAL NO.
LE35C:	MVI	B,' '		;GET A SPACE
	JMP	OUT8		;PUT IT OUT
;
;OUTPUT NUMBER OF SPACES IN REG C
;
BLKO:	CALL	LE35C		;PUT OUT A SPACE
	DCR	C		;DECREMENT COUNT
	JNZ	BLKO		;PUT OUT MORE IF NOT DONE
	RET			;ELSE RETURN
;
;COMPARE THE ADDRESSES AT BBUF AND BBUF+2
;INCREMENT THE ADDR AT BBUF AND RET CARRY SET IF SAME
;USED BY DUMP COMMAND TO TEST FOR END
;
ACHK:	LHLD	BBUF		;GET 1ST ADDRESS
	LDA	BBUF+3		;GET HIGH BYTE OF 2ND ADDR
	CMP	H		;COMPARE HIGH ORDER BYTES
	JNZ	ACH1		;BBUF LOWER, INR IT & GO HOME
	LDA	BBUF+2		;GET 2ND ADDR LOW BYTE
	CMP	L		;COMPARE TWO ADDR.
	JNZ	ACH1		;BBUF LOWER, INR IT & GO HOME
	STC			;ADDR. ARE SAME, SET CARRY
ACH1:	INX	H		;INCREMENT BBUF ADDR
	SHLD	BBUF		;PUT IT BACK
	RET			;DONE
;
;PRINT CHARACTERS UNTIL A CAR. RET. FOUND
;
SCRN:	XRA	A		;BINARY ZERO
	STA	XOUT		;LAST CHAR OUTPUT
	MOV	B,M		;GET A CHARACTER
	MVI	A,0DH		;CAR. RETRN TO A.
	CMP	B		;CHAR IN B = C/R ?
	RZ			;YES - DONE
	CALL	OUT8		;NO - OUTPUT IT & MOV TO A
	INX	H		;INCREMENT POINTER
	JMP	SCRN+1		;UPDATE XOUT AND DO NEXT CHAR
;
;CONVERT BINARY TO HEX ASCII & STORE
;
BINH:	LXI	H,ADDS		;DESTINATION FOR ASCII
	MOV	B,A		;SAVE CHAR IN B
	RAR			;MOVING HIGH ORDER NIBBLE TO
	RAR			;LOW ORDER NIBBLE
	RAR	
	RAR	
	CALL	BIN1		;CONVERT TO LETTER OR NO.
	MOV	M,A		;STORE IT
	INX	H		;INCREMENT DEST. POINTER
	MOV	A,B		;GET BACK ORIG NO.
	CALL	BIN1		;CONVERT LOW ORDER NIBBLE TO NO
	MOV	M,A		;PUT IT IN MEMORY
	RET			;DONE
;
;CONVERT LOW ORDER NIBBLE OF A TO HEX ASCII
;
BIN1:	ANI	0FH		;MASK LOW NIBBLE
	ADI	30H		;CONVERT TO NO.
	CPI	'9'+1		;SEE IF > 9
	RC			;IT WASN'T -- DONE
	ADI	7		;ADD 7 TO GET LETTER
	RET			;DONE
;
;BINARY TO DECIMAL
;
BIND:	LXI	H,ADDS		;POINT TO DESTINATION
	MVI	B,100		;DOING SUCCESSIVE SUBTRACTIONS
	CALL	BID1		;SUBTRACT & KEEP COUNT
	MVI	B,10		;NOW WORK WITH TENS
	CALL	BID1		;MORE SUBTRACTIONS
	ADI	30H		;CONVERT UNITS TO DECIMAL ASCII
	MOV	M,A		;STORE UNITS DIGIT IN MEMORY
	RET			;DONE
BID1:	MVI	M,'0'-1
	INR	M		;INCR COUNT OF SUBTRACTIONS
	SUB	B		;DO A SUBTRACTION
	JNC	BID1+2		;DO IT AGAIN IF ANS > 0
	ADD	B		;IF ANS < 0, UN-SUBTRACT
	INX	H		;INCREMENT DEST. POINTER
	RET			;DIGIT STORED
;
;BINARY TO OCTAL
;
;NOTE THAT THE CARRY IS USED, SO THE MAX SINGLE BYTE OCTAL
;VALUE THAT CAN BE HANDLED IS 777 NOT 377.  THIS FEATURE IS
;USED IN THE DUMP ROUTINE.
;
BINO:	LXI	H,ADDS		;GET DEST. POINTER
	MOV	B,A		;SAVE ORIG NO. IN B
	RAL			;HIGH ORDER BITS & CARRY
	RAL			;MOVING TO LOW ORDER 3 BITS
	RAL			;
	ANI	7		;MASK TO 3 BITS
	ADI	30H		;CONVERT TO ASCII
	MOV	M,A		;STORE IN MEMORY
	MOV	A,B		;GET ORIG. NO.
	RAR			;MOVE MIDDLE 3 BITS
	RAR			;TO LOW ORDER 3 BITS
	RAR	
	ANI	7		;AND MASK THEM OUT
	ADI	30H		;CONVERT TO ASCII
	INX	H		;INCREMENT MEMORY POINTER
	MOV	M,A		;AND PUT DIGIT IN MEMORY
	MOV	A,B		;GET ORIGINAL DIGIT AGAIN
	ANI	7		;MASK TO LOW ORDER 3 BITS
	ADI	30H		;CONVERT TO ASCII
	INX	H		;INCREMENT MEMORY POINTER
	MOV	M,A		;AND STORE IN MEMORY
	RET			;DONE
;
;HERE IS THE ALS-8 COMMAND TABLE
;
CTAB:	DB	'LIST'
	DB	(LIST SHR 8) AND 0FFH, LIST AND 0FFH
	DB	'TEXT'
	DB	(TEXT SHR 8) AND 0FFH, TEXT AND 0FFH
	DB	'DELT'
	DB	(DELT SHR 8) AND 0FFH, DELT AND 0FFH
	DB	'MODE'
	DB	(MODE SHR 8) AND 0FFH, MODE AND 0FFH
	DB	'FCHK'
	DB	(FCHK SHR 8) AND 0FFH, FCHK AND 0FFH
	DB	'FORM'
	DB	(FORM SHR 8) AND 0FFH, FORM AND 0FFH
	DB	'NFOR'
	DB	(NFOR SHR 8) AND 0FFH, NFOR AND 0FFH
	DB	'SWCH'
	DB	(EORNS SHR 8) AND 0FFH, EORNS AND 0FFH
	DB	'SIMU'
	DB	(SIMU SHR 8) AND 0FFH, SIMU AND 0FFH
	DB	0
	DB	'DUMP'
	DB	(DUMP SHR 8) AND 0FFH, DUMP AND 0FFH
	DB	'EXEC'
	DB	(EXEC SHR 8) AND 0FFH, EXEC AND 0FFH
	DB	'ENTR'
	DB	(ENTR SHR 8) AND 0FFH, ENTR AND 0FFH
	DB	'FILE'
	DB	(FILE SHR 8) AND 0FFH, FILE AND 0FFH
	DB	'ASSM'
	DB	(ASSM SHR 8) AND 0FFH, ASSM AND 0FFH
	DB	'ASSI'
	DB	(ASSM SHR 8) AND 0FFH, ASSM AND 0FFH
	DB	'IODR'
	DB	(IODR SHR 8) AND 0FFH, IODR AND 0FFH
	DB	'STAB'
	DB	(STAB SHR 8) AND 0FFH, STAB AND 0FFH
	DB	'SYML'
	DB	(SYML SHR 8) AND 0FFH, SYML AND 0FFH
	DB	'CUST'
	DB	(CUST SHR 8) AND 0FFH, CUST AND 0FFH
	DB	'RNUM'
	DB	(RNUM SHR 8) AND 0FFH, RNUM AND 0FFH
	DB	'FMOV'
	DB	(FMOV SHR 8) AND 0FFH, FMOV AND 0FFH
	DB	'EDIT'
	DB	(TXT2 SHR 8) AND 0FFH, TXT2 AND 0FFH
	DB	'AUTO'
	DB	(AUTO SHR 8) AND 0FFH, AUTO AND 0FFH
	DB	'FIND'
	DB	(FIND2 SHR 8) AND 0FFH, FIND2 AND 0FFH
	DB	'TERM'
	DB	(TERM SHR 8) AND 0FFH, TERM AND 0FFH
	DB	0
;
;SYSTEM SYMBOL TABLE ROUTINES
;
SYML:	LXI	H,IBUF+4	;POINT TO FIFTH CHAR
	MOV	A,M		;GET IT
	CPI	'E'		;SYMLE - ENTER INTO TABLE ?
	JZ	LE4AB		;YES - MAKE AN ENTRY
	CPI	'D'		;SYMLD - DELETE FROM TABLE ?
	JZ	LE4B4		;YES - DELETE IT THEN
;
;PRINT CONTENTS OF SYSTEM SYMBOL TABLE
;
	LXI	H,SYSYM		;POINT TO SYSTEM SYMBOL TABLE
LE48F:	MVI	A,4		;PRINT 4 ACROSS
	STA	CCNT		;SAVE AS COUNT
	CALL	CRLF		;START ON NEW LINE
LE497:	MOV	A,M		;GET 1ST CHAR
	ORA	A		;END OF TABLE ?
	JZ	LE4EE		;THEN PRINT END ADDRESS
	CALL	LEEA8		;PRINT 1 SYMBOL & VALUE
	INX	D		;POINT TO NEXT SYMBOL
	LXI	H,CCNT		;POINT AT COUNT
	DCR	M		;DCR NO LEFT THIS LINE
	XCHG			;TABLE POINTER TO H,L
	JNZ	LE497		;PRINT MORE THIS LINE
	JMP	LE48F		;OR START NEW LINE
;
;ENTER NEW SYMBOL INTO TABLE
;
LE4AB:	CALL	VCHK		;CHECK FOR VALID VALUE & NAME
LE4AE:	CALL	LE4CE		;VALIDATE NAME & MOVE TO ABUF
	JMP	LECE2		;PUT SYMBOL INTO TABLE
;
;DELETE SYMBOL
;
LE4B4:	CALL	LE4AE		;H,L POINTS TO VALUE ON RET
LE4B7:	INX	H		;POINT TO 2ND CHAR OF VALUE
	INX	H		;POINT TO NEXT SYMBOL
	XCHG			;D,E POINT AT SYM. AFTR DELETED
	LXI	H,-(NMLEN+2)	;SYMBOL TABLE ENTRY LENGTH
	DAD	D		;H,L POINTS AT BEG. OF ENTRY
	LDAX	D		;GET CHAR FROM TABLE ENTRY
LE4BF:	ORA	A		;SET FLAGS
	MVI	B,(NMLEN+2)	;ENTRY LENGTH
LE4C2:	MOV	M,A		;MOVE CHAR UP IN TABLE
	RZ			;IF END OF TABLE MOVED
	INX	H		;INR DEST. POINTER
	INX	D		;INR SOURCE POINTER
	LDAX	D		;GET NEXT CHAR FROM SYMBOL
	DCR	B		;COUNT OF CHRS THIS SYMBOL
	JNZ	LE4C2		;IF NOT DONE THIS SYMBOL
	JMP	LE4BF		;TO MOVE NEXT SYMBOL UP
;
;ROUTINE TO VALIDATE A SYMBOL NAME & MOVE IT TO ABUF
;
LE4CE:	CALL	ZBUF		;BLANK OUT ABUF
	XCHG			;H,L POINT TO START OF ABUF
	SHLD	ADDS		;SAVE ADDRESS
	LXI	D,FBUF		;POINT AT FILE-NAME BUFFER
	XCHG			;H,L=FBUF & D,E=ABUF
	XRA	A		;GET A ZERO
	STA	FREAD		;SAVE AS 1ST FREE ADDRESS
	MOV	A,M		;GET 1ST CHAR OF NAME
	ORA	A		;ZERO ?
	JZ	WHAT		;ERROR IF NO NAME GIVEN
	CALL	LF154		;MOVE THE NAME IF IT'S VALID
	CPI	21H		;MAKE SURE SPACE FOLLOWS NAME
	JNC	WHAT		;ERROR IF SPACE DOESN'T FOLLOW
	LHLD	BBUF		;GET VALUE
	RET			;RETURN W/VALUE IN H,L
;
;DO A CR/LF AND PRINT ASCII CONTENTS OF ADDR POINTED TO BY H,L
;
LE4EE:	XCHG			;POINTER FROM D,E TO H,L
	CALL	CRLF		;START ON NEW LINE
	JMP	ADOUT		;PRINT ADDR POINTED TO BY H,L
;
;CUSTOM COMMAND TABLE MANAGEMENT
;
CUST:	LXI	H,IBUF+4	;POINT AT 5TH CHAR
	MOV	A,M		;GET IT
	CPI	'E'		;ENTER NEW CUST. COMMAND ?
	JZ	LE509		;YES - DO IT
	CPI	'D'		;DELETE CUSTOM COMMAND ?
	JZ	LE004		;YES - DO IT
	LXI	H,CUCOM		;POINT AT CUSTOM COMMAND TABLE
	JMP	LE48F		;PRINT USING SYML ROUTINES
;
;ENTER AND DELETE MOSTLY USE SYMLE & SYMLD CODE
;
LE509:	CALL	VCHK		;MAKE SURE VALUE GIVEN
LE50C:	CALL	LE4CE		;VALIDATE NAME & MOVE TO ABUF
	LXI	D,CUCOM		;D,E POINT AT CUST. TABLE
	JMP	LECE5		;PUT VALUE INTO TABLE
;
;ROUTINE TO EXTRACT VALUES FROM COMMAND LINE & REPORT AN ERROR
;
VALC:	CALL	ETRA		;ETRA DOES THE REAL WORK
	JC	WHAT		;IF AN ERROR OCCURED
	RET			;DONE, NO ERROR
;
;ROUTINE TO VERIFY THAT REQUIRED PARAMETERS WERE ENTERED
;
VCHK:	LDA	ABUF		;GET 1ST CHAR OF ABUF
	ORA	A		;ZERO ?
	JZ	WHAT		;ERROR - REQD. PARM. OMITTED
	RET			;DONE
;
;THE DUMP COMMAND
;
DUMP:	CALL	VCHK		;MAKE SURE ADDRESS GIVEN
	MVI	A,16		;16 VALUES PER LINE
	STA	CCNT		;SAVE AS COUNT
LE52C:	CALL	CRLF		;START NEW LINE
	LHLD	BBUF		;GET ADDRESS
	XCHG			;DO D,E
	CALL	ADOUT		;PRINT ADDRESS ON LEFT OF LINE
	MVI	B,':'		;FOLLOW ADDRESS WITH COLON
	CALL	OUT8		;PRINT IT
	CALL	LE35C		;PUT OUT A SPACE
	LDA	CCNT		;GET COUNT OF ADDRS/LINE
LE541:	STA	DCNT		;SAVE AS DUMP COUNT
	LHLD	BBUF		;GET ADDR TO DUMP
	MOV	A,M		;GET DATA AT THAT ADDR
	CALL	DUMO		;PRINT ITS VALUE
	CALL	LE35C		;PUT A SPACE OUT
	CALL	ACHK		;COMPARE BBUF & BBUF+2
	RC			;REACHED END ADDRS. - DONE
	LDA	DCNT		;ELSE GET DUMP COUNT
	DCR	A		;DCR COUNT BYTES LEFT THIS LINE
	JNZ	LE541		;DO MORE BYTES ON THIS LINE
	JMP	LE52C		;DO ANOTHER LINE
;
;ROUTINE TO PUT OUT AN ADDRESS
;
;NOTE THAT THIS ROUTINE TAKES ADVANTAGE (?) OF THE FACT THAT
;BINO USES THE CARRY BIT TO OUTPUT A SINGLE BYTE IN A AS
;XXX WHERE XXX MAY BE 777 (INCLUDING CARRY) AND IS NOT
;LIMITED TO 377.  ADDRESSES THUS COME OUT AS A SINGLE 16 BIT
;NUMBER RATHER THAN IN THE MORE COMMON "SPLIT OCTAL" CONSISTING
;OF TWO SEPERATE 8 BIT QUANTITIES WITH A MAX VALUE OF 377 EACH.
;
ADOUT:	LDA	SMODE		;GET CURRENT MODE
	ORA	A		;CLEAR CARRY & SET ZERO FLAG
	MOV	A,D		;HIGH ORDER BYTE TO A
	JZ	LE565		;SKIP NEXT PART IF BASE HEX
	RAR			;LOW ORDER BIT TO CARRY FOR OCT
LE565:	MOV	D,A		;RESTORE HIGH ORDER BYTE
	RAL			;SHIFT LEFT 1 BIT THRU ACCUM.
	MOV	C,A		;LOW BIT/CARRY IN C FOR OCTAL
	MOV	A,D		;GET HIGH ORDER BYTE
	CALL	DUMO		;OUTPUT USING CURRENT MODE
	MOV	A,C		;FOR OCTAL, GET ORIG HIGH BYTE
	RAR			;SET CARRY BIT
	MOV	A,E		;GET LOW ORDER BYTE
DUMO:	LXI	H,SMODE		;POINT TO MODE
	MOV	B,M		;GET IT
	DCR	B		;DECR (OCTAL MODE = 1)
	JZ	OOUT		;FOR OCTAL
HOUT:	CALL	BINH		;CONVERT BIN TO HEX IN ADDS
LE57A:	LXI	H,ADDS		;BUFFER WHERE CHARS STORED
	MOV	B,M		;GET CHAR IN B
	CALL	OUT8		;PRINT A HEX ASCII CHAR
	INX	H		;INX POINTER
	MOV	B,M		;GET NEXT CHAR
	JMP	OUT8		;PRINT IT & GO HOME
HOTB:	CALL	HOUT		;PUT OUT HEX
	JMP	LE35C		;PUT OUT SPACE & GO HOME
;
;MODE - USED TO SET THE OUTPUT MODE
;
MODE:	CALL	VCHK		;VERIFY PARAMETER GIVEN
	LXI	B,ABUF		;POINT TO PARAMETER
	CALL	AHEX		;CONVERT TO BINARY
	JC	WHAT		;IF PARAMETER INVALID
	MOV	A,H		;GET HIGH ORDER BYTE
	ORA	A		;SET FLAGS
	JNZ	WHAT		;PARM. MUST BE < 256
	MVI	B,0		;ASSUME HEX SPECIFIED
	MOV	A,L		;GET LOW ORDER PARMATER
	CPI	16H		;IS PARAMETER 16 ?
	JZ	LE5AB		;YES - STORE 0 AS MODE
	INR	B		;MAKE B = MODE = 1
	CPI	8		;IS PARAMETER 8 ?
	JNZ	WHAT		;MUST BE EITHER 8 OR 16
LE5AB:	MOV	A,B		;GET MODE (REG B)
	STA	SMODE		;MAKE IT THE MODE
	RET			;WE ARE DONE
;
;PROCESS THE FILE COMMANDS
;
FILE:	LDA	FBUF		;GET 1ST CHAR OF FILE NAME
	ORA	A		;SET FLAGS
	JZ	FOUT		;NO NAME GIVEN - DO A LISTING
	CALL	FSEA		;LOOK UP FILE
	XCHG			;D,E HAS ADDR OF DIR. ENTRY
	JNZ	TEST		;IF DIR. ENTRY FOUND
;
;ENTRY MATCHING FBUF NOT FOUND
;
	LDA	ABUF		;CHECK FOR PARAMETER GIVEN
	ORA	A		;SET FLAGS
	JZ	WHAT		;ADDR. REQUIRED FOR NEW FILE
;
;CHECK FOR ROOM TO ADD A NEW FILE
;
	LDA	FEF		;GET FREE ENTRY FOUND FLAG
	ORA	A		;SET FLAGS
	JNZ	ROOM1		;TO ADD THE NEW FILE
LE5CC:	LXI	H,EMES1		;POINT TO ERROR MESSAGE
	JMP	MESS		;PRINT IT
;
;ENTRY MATCHING FBUF FOUND
;
TEST:	LDA	ABUF		;SEE IF PARAMETER GIVEN
	ORA	A		;SET FLAGS
	JZ	SWAPS		;NO PARMS - MAKE IT CUR FILE
	LHLD	BBUF		;GET BINARY VALU OF PARM
	MOV	A,H		;HIGH ORDER BYTE
	ORA	L		;SEE IF PARM IS ZERO
	JZ	SWAPS		;TO DELETE THE FILE
LE5E1:	LXI	H,EMES2		;CAN'T RESPECIFY EXISTING FILE
	JMP	MESS		;TELL IT TO THE OPERATOR
;
;CREATE NEW FILE - NAME IS IN FBUF
;FREAD POINTS TO A FREE DIRECTORY ENTRY
;
ROOM1:	CALL	ROOM		;MOVE NAME IN FBUF TO DIRECTORY
;
;MAKE FILE POINTED TO BY D,E CURRENT
;
SWAPS:	LXI	H,FILE0		;POINT H,L TO CUR FILE
	MVI	C,FELEN		;BYTE COUNT
SWAP:	LDAX	D		;GET A BYTE FROM NEW CUR FILE
	MOV	B,M		;GET BYTE FROM CUR CUR FILE
	MOV	M,A		;NEW CUR FILE BYTE TO FILE 0
	MOV	A,B		;EXCHANGE
	STAX	D		;CUR CUR FILE BYTE TO FREAD
	INX	D		;INR NON-CURRENT FILE POINTER
	INX	H		;INR FILE 0 POINTER
	DCR	C		;COUNT OF BYTES TO MOVE
	JNZ	SWAP		;IF NOT DONE SWAPPING ENTRIES
;
;CHECK FOR 2ND PARAMETER (ADDRESS)
;
	LDA	ABUF		;GET 2ND PARAMETER 1ST CHAR
	ORA	A		;SET FLAGS
	JZ	FOUT		;NONE GIVEN
;
;PROCESS 2ND PARAMETER
;
	LHLD	BBUF		;GET 2ND PARAMETER ADDRESS
	SHLD	BOFP		;MAKE IT BEG OF FILE POINTER
	SHLD	EOFP		;AND END OF FILE POINTER
	MOV	A,L		;TEST FOR ADDR = 0
	ORA	H		;
	JZ	FIL35		;YES - DELETE IT
	MVI	M,1		;NO - PUT EOF MARK AT BOFP
FIL35:	XRA	A		;BINARY ZERO
	STA	MAXL		;AT MAX. LINE NO.
	JMP	FOOT		;OUTPUT PARAMETERS
;
;LIST 1 OR MORE FILES & THEIR PARAMETERS
;
FOUT:	CALL	CRLF		;DO A CR/LF
	LDA	IBUF+4		;GET OPT. 5TH CHAR
	CPI	'S'		;WAS COMMAND FILES ?
	MVI	C,MAXFIL	;MAX NO OF FILES
	JZ	FOUL		;YES - LIST ALL FILES
FOOT:	MVI	C,1		;ELSE LIST ONLY 1 FILE
;
;LIST PARMS. FOR NO OF FILES IN REG C.
;
FOUL:	LXI	H,FILE0		;POINT TO DIRECTORY
LE62A:	MOV	A,C		;GET NO FILES LEFT TO LIST
FINE:	STA	FOCNT		;SAVE AS FILE OUTPUT COUNT
	PUSH	H		;SAVE DIRECTORY POINTER
	LXI	D,NMLEN		;NAME LENGTH
	DAD	D		;POINT AT FILES BOFP
	MOV	A,M		;GET 1ST BYTE OF BOFP
	ORA	A		;ZERO ?
	JNZ	FOOD		;NO - LIST IT
	INX	H		;POINT AT 2ND BYTE OF BOFP
	ADD	M		;ADD TO 1ST BYTE
	INX	H		;POINT TO EOFP 1ST BYTE
	JNZ	FOOD		;BOFP NON ZERO - LIST IT
	INX	SP		;TO "UN-PUSH" H,L
	INX	SP		;
	INX	H		;POINT TO 2ND BYTE OF EOFP
	INX	H		;POINT TO MAXL
	JMP	FEET		;TO GO TO NEXT ENTRY
;
;HAVE A VALID ENTRY TO OUTPUT
;
FOOD:	POP	H		;GET POINTER TO FILES NAME
	CALL	CRLF		;START IT ON A FRESH LINE
	MVI	C,NMLEN		;LENGTH
FAST:	MOV	B,M		;GET A CHAR OF NAME
	CALL	OUT8		;PRINT IT
	DCR	C		;DECREMENT COUNT
	INX	H		;POINT TO NEXT CHAR
	JNZ	FAST		;PRINT REMAINING CHARS IF ANY
	CALL	LE666		;PRINT SPACE, BOFP, SPACE
	CALL	LE666		;PRINT SPACE, EOFP, SPACE
FEET:	LXI	D,FELEN-NMLEN-4	;LENGTH OF MAXL
	DAD	D		;POINT AT NEXT FILE ENTRY
	LDA	FOCNT		;PRINTING 1 OR ALL ?
	DCR	A		;DECR. COUNT
	JNZ	FINE		;TO PRINT MORE
	RET			;DONE
;
;ROUTINE TO PRINT AN ADDRESS
;
LE666:	CALL	LE35C		;PRINT SPACE
	MOV	E,M		;GET BYTE OF BOFP OR EOFP
	INX	H		;POINT TO 2ND BYTE
	MOV	D,M		;GET IT
	PUSH	H		;SAVE POINTER INTO FILE DIR.
	CALL	ADOUT		;PRINT ADDRESS
	CALL	LE35C		;AND TRAILING SPACE
	POP	H		;RESTORE POINTER
	INX	H		;POINT TO MAXL
	RET			;DONE
;
;MOVE FILE NAME TO BLOCK POINTED TO BY FREAD
;
ROOM:	LHLD	FREAD		;GET ADDR OF FREE ENTRY
	XCHG			;TO D,E
	LXI	H,FBUF		;ADDR OF NAME IN COMMAND
	PUSH	D		;SAVE DIRECTORY ADDR
	MVI	C,NMLEN		;NO CHARS TO MOVE
MOV23:	MOV	A,M		;GET CHAR FROM COMMAND
	STAX	D		;PUT INTO DIRECTORY
	INX	D		;INCR. DIR. POINTER
	DCR	C		;DCR CHAR COUNT
	INX	H		;INCR. FBUF POINTER
	JNZ	MOV23		;MOVE REMAINING CHARS
	POP	D		;RESTORE DIR. POINTER
	RET			;DONE
;
;FILE DIRECTORY SEARCH ROUTINE
;LOOK FOR ENTRY W/NAME IN FBUF - ZERO SET ==> NOT FOUND
;ELSE H,L POINT TO THE ENTRY
;ALSO, IF ENTRY FOUND W/BOFP ADDR = 0, SET FEF FLAG > 0
;AND FREAD TO THE ADDR OF THAT ENTRY
;
FSEA:	LXI	D,FILE0		;POINT TO DIRECTORY
LE68D:	XRA	A		;GET ZERO
	STA	FEF		;ASSUME NO FREE ENTRIES
	MVI	B,MAXFIL	;NO OF ENTRIES IN DIR.
FSE10:	LXI	H,FBUF		;ADDR OF NAME TO LOOK UP
	MVI	C,NMLEN		;NO CHARS PER NAME
	CALL	SEAR		;COMPARE CURRENT ENTRY TO FBUF
	PUSH	PSW		;SAVE RESULTS FLAG
	PUSH	D		;SAVE DIR POINTER
	LDAX	D		;GET BYTE OF BOFP ADDR
	ORA	A		;EMPTY ?
	JNZ	FSE20		;NO
	INX	D		;2ND BYTE
	LDAX	D		;GET IT
	ORA	A		;SET FLAGS
	JNZ	FSE20		;NOT ZERO
	XCHG			;DIR POINTER TO H,L
	LXI	D,-NMLEN-1	;
	DAD	D		;POINT BACK TO EMPTY ENTRY
	SHLD	FREAD		;AND SAVE IT'S ADDRESS
	MOV	A,D		;D HAPPENS TO BE NON-ZERO
	STA	FEF		;AND SO NOW IS FEF
	POP	H		;RESTORE DIR POINTER TO H,L
	POP	PSW		;RESTORE SEAR RESULTS FLAG
;
;MOVE TO NEXT ENTRY
;
FSE15:	LXI	D,FELEN-NMLEN
	DAD	D		;H,L POINTS TO NEXT ENTRY
	XCHG			;ENTRY ADDR TO D,E
	DCR	B		;COUNT OF FILES IN DIR
	RZ			;NO FILES LEFT TO SEARCH
	JMP	FSE10		;SEARCH REMAINING FILES
;
;ENTRY WASN'T FREE, LOOK AT SEAR RESULTS
;
FSE20:	POP	H		;RESTORE DIRECTORY POINTER
	POP	PSW		;SEAR RESULTS IN FLAG
	JNZ	FSE15		;IT DIDN'T MATCH ANYWAY
;
;MATCHING ENTRY FOUND WHICH WASN'T FREE
;
	LXI	D,-NMLEN
	DAD	D		;H,L POINT AT THE DIR. ENTRY
	MOV	A,D		;D IS NON-ZERO
	ORA	A		;SET FLAGS TO CLEAR ZERO FLAG
	RET			;DONE
;
;FORM COMMAND TO SET OUTPUT MODE
;
FORM:	CMA			;ALL COMNDS ARE EXEC WITH A=0
NFOR:	STA	LFMT		;
	JMP	EORMS		;IT'S THAT SIMPLE, FOLKS
;
;FCHK
;
FCHK:	LHLD	BOFP		;GET BEG. OF FILE PTR
	MOV	A,H		;SEE IF BOFP IS ZERO
	ORA	L		;WOULD IMPLY NO FILES
	JZ	LE5E1		;PRINT ERROR MESSAGE
	LXI	B,4		;LENGTH OF LINE NO.
	DAD	B		;H,L POINTS JUST PAST LINE NO
	INR	C		;C = 5 = LINE LEN TO THIS PT.
LE6E0:	INX	H		;POINT TO NEXT CHAR
	INR	C		;LINE LENGTH TO THIS POINT
	CALL	LE72B		;GET TERM WIDTH IN A
	CMP	C		;LINE > TERMINAL WIDTH ?
	JC	LE718		;YES - ERROR
	MOV	A,M		;GET LINE CHAR
	CPI	0DH		;END OF LINE ?
	JNZ	LE6E0		;KEEP TESTING THIS LINE
	LHLD	BOFP		;GET BEG. OF FILE PTR
	MOV	M,C		;MAKE LENGTH BYTE OK 1ST LINE
LE6F3:	MOV	A,M		;GET LENGTH BYTE
	CPI	1		;END OF FILE ?
	JZ	LE725		;TO RESET MAXL
	CPI	6		;MIN LINE LEN (NO. + LEN + CR)
	JC	LE718		;REPORT ERROR IF LINE TOO SHORT
	CALL	LE72B		;GET TERMINAL WIDTH IN A
	CMP	M		;COMPARE WITH LENGTH BYTE
	MOV	C,M		;LENGTH BYTE TO C
	DCR	C		;GOING TO COUNT CHARS IN LINE
LE704:	DCR	C		;COUNT OF ACUTAL CHARS LEFT
	INX	H		;POINT TO NEXT CHAR
	MOV	A,M		;GET IT
	JZ	LE712		;COUNT TO 0 - MUST BE C/R
	CPI	20H		;IS CHAR CNTL CHAR ?
	JC	LE718		;CNTL CHARS NOT ALLOWED
	JMP	LE704		;TEST NEXT CHAR IN LINE
LE712:	CPI	0DH		;IS CHAR C/R ?
	INX	H		;POINT TO NEXT CHAR
	JZ	LE6F3		;YES - GO ON, CHECK FOR EOF
;
;ERROR
;
LE718:	XCHG			;BAD ADDRESS TO D,E
	CALL	LE35C		;PRINT A SPACE
	CALL	ADOUT		;FOLLOWED BY THE BAD ADDRESS
	LXI	H,FERR		;POINT TO FILE ERROR MESSAGE
	JMP	MESS		;PRINT THE ERROR MESSAGE
LE725:	CALL	LEA50		;UPDATE MAXL
	JMP	FOUT		;PRINT FILE PARMS & RETURN
LE72B:	LDA	TERMW		;GET TERM WIDTH
	ADI	-(IBUF+1) AND 0FFH
	RET			;BINARY TERM WIDTH IN A
;
;FILE MOVE COMMANDS
;
FMOV:	CALL	VCHK		;CHECK FOR REQD PARMS
	LHLD	BOFP		;GET BEG OF FILE PTR
	XCHG			;BOFP TO D,E
	LHLD	BBUF		;GET DEST ADDR
	SHLD	BOFP		;NEW BEG OF FILE
	MOV	A,L		;LOW ORDER DEST TO A
	SUB	E		;SUBRACTING CUR BOF FROM NEW
	MOV	A,H		;TO SEE WHICH WAY TO MOVE
	SBB	D		;ANSWER NOW IN CARRY FLAG
	JC	LE760		;IF MOVING TO LOWER ADDR
;
;MOVING TO HIGHER ADDR
;
	LHLD	EOFP		;MOVING TO HIGHER ADDR
	MOV	A,L		;GOING TO SUBTRACT CUR (OLD)
	SUB	E		;BOFP FROM CUR EOFP & PUT
	MOV	C,A		;RESULT (FILE LENGTH) IN
	MOV	A,H		;REG B,C
	SBB	D		;
	MOV	B,A		;
	LHLD	BOFP		;GET DEST BEG OF FILE
	DAD	B		;ADD LENGTH = NEW END
	XCHG			;NEW END IN D,E
	MVI	M,2		;PUT 02H AT CUR BEG OF FILE
	MOV	C,M		;AND IN REG C
	LHLD	EOFP		;GET CUR END OF FILE TO H,L
	XCHG			;CUR EOF=D,E & NEW END H,L
	CALL 	RMOV		;DO THE MOVE
	JMP	LE765		;PUT 02H AT BOF AND FCHK
;
;MOVING LOWER IN MEMORY
;
LE760:	MVI	C,1		;LMOV WILL USE 01H AS END MARK
	CALL	LMOV		;DO THE MOVE
LE765:	MOV	M,C		;PUT TERMINATOR MARK IN FILE
	JMP	FCHK		;FCHK TO UPDATE 1ST L.B. & EOF
;
;RENUMBER COMMAND
;
RNUM:	CALL	VCHK		;CHECK FOR REQD. PARAMETERS
	LDA	ABUF+7		;SEE IF INCREMENT SPECIFIED
	MVI	B,5		;DEFAULT INCREMENT
	ORA	A		;SET FLAGS
	JZ	LE785		;NO INCREMENT GIVEN, USE 5
	LXI	B,ABUF+7	;POINT AT GIVEN INCREMENT
	CALL	ADEC		;CONVERT TO DECIMAL
	JC	WHAT		;IF ERROR
	MOV	A,L		;GET INCREMENT
	CPI	26		;MAXIMUM INCREMENT + 1
	JNC	WHAT		;IF INCREMENT > 25
	MOV	B,A		;INCREMENT IN B
LE785:	LHLD	BOFP		;GET BOF POINTER
	SHLD	APNT		;SAVE
LE78B:	MOV	A,M		;GET LENGTH BYTE
	CPI	1		;END OF FILE ?
	JZ	FCHK		;YES, DONE, DO FCHK
	INX	H		;POINT 1ST DIGIT
	LXI	D,ABUF		;STARTING LINE NO. SOURCE
	MVI	C,4		;LENGTH OF LINE NO.
LE797:	LDAX	D		;GET A DIGIT
	MOV	M,A		;PUT IT IN THE LINE
	INX	H		;POINT TO NEXT DIGIT
	INX	D		;IN SOURCE, TOO
	DCR	C		;COUNT OF DIGITS LEFT
	JNZ	LE797		;DO NEXT DIGITS
	LHLD	APNT		;GET POINTER TO LINE
	MOV	A,M		;GET LENGTH BYTE
	CALL	ADR		;POINT TO NEXT LINE
	SHLD	APNT		;UPDATE LINE POINTER
	DCX	H		;POINT TO LAST CHR OF PREV LINE
	MOV	A,M		;GET IT
	CPI	0DH		;IS IT A CARRIAGE RET ?
	JNZ	LE718		;DOING A LITTLE FCHKING HERE
	LXI	H,ABUF+3	;POINT TO LSB OF LINE NO.
	MOV	A,M		;GET IT
	ADD	B		;ADD INCREMENT
LE7B5:	CPI	'9'+1		;CARRY ?
	JNC	LE7CC		;NO - CONTINUE
	MOV	M,A		;PUT UPDATED DIGIT BACK
	LDA	ABUF		;GET MSB
	CPI	'9'		;EQUAL 9 ?
	CNC	LE7C9		;IF SO, CHANGE INCREMENT TO 1
	LHLD	APNT		;GET POINTER TO NEXT LINE
	JMP	LE78B		;AND DO IT
;
;CHANGE INCREMENT TO 1 IF NOS. GET TO 9000
;
LE7C9:	MVI	B,1		;NEW INCREMENT
	RET
;
;GET HERE IF ADDITION GAVE CARRY
;
LE7CC:	MVI	C,0		;C WILL BECOME DECIMAL CARRY
LE7CE:	INR	C		;INR FOR EA SUBTR. OF 10
	SUI	10		;SUB 10 FROM ADDITION RESULT
	CPI	'9'+1		;RESULT STILL > 9 ?
	JNC	LE7CE		;SUB AGAIN & KEEP CNT OF SUBTR
	MOV	M,A		;LESS THAN 10 - PUT DIGIT BACK
	DCX	H		;POINT TO NEXT MSB
	MOV	A,M		;GET IT
	ADD	C		;ADD CARRY FROM PREV. DIGIT
	JMP	LE7B5		;AND REPEAT THE PROCESS
;
;GENERAL ERROR MESSAGE ROUTINES
;
WHAT:	LXI	H,EMES
MESS:	CALL	CRLF		;DO CR/LF
	PUSH	H		;SAVE H,L
	LXI	H,SYSIN		;RESTORE STD I/O DRIVERS
	CALL	LE15A		;DO IT
	POP	H		;RESTORE H,L
	CALL	SCRN		;PRINT THE MSG POINTED TO BY H,L
	JMP	LE0CB		;GO BACK TO ALS-8 COMND MODE
;
;MESSAGES
;
EMES:	DB	'WHAT?', 0DH
EMES1:	DB	'FULL', 0DH
EMES2:	DB	'FCON', 0DH
FERR:	DB	' FILE ERR', 0DH
;
;THIS IS THE PROCESSING PORTION OF THE ENTER COMMAND
;
ENTS:	CALL	CRLF		;START ON A NEW LINE
	CALL	READ		;GET A LINE OF INPUT
	LXI	H,IBUF		;POINT TO IT'S START
	SHLD	PNTR		;SAVE POINTER
ENT1:	CALL	ZBUF		;CLEAR ASCII BUFFER
	CALL	SBLK		;SCAN TO CHARACTERS IN IBUF
	JC	ENTS		;C/R FOUND, GET ANOTHER LINE
	CPI	'/'		;ENTER TERMINATION CHAR ?
	RZ			;YES - DONE THEN
	CALL	ALPS		;LOAD ABUF FROM IBUF
	XCHG			;
	LXI	B,ABUF		;POINT TO THE LOADED BUFR
	LDA	SMODE		;GET THE CURRENT MODE
	ORA	A		;SET FLAGS
	JNZ	LE837		;JUMP IF OCTAL
	CALL	AHEX		;CONVERT ASCII HEX TO BINARY
	JMP	LE83A		;TO CONTINUE
LE837:	CALL	AOCT		;CONVERT OCTAL TO BINARY
LE83A:	RC			;RETURN IF ERROR
	LDAX	D		;GET CHAR FROM INPUT LINE
	CPI	':'		;NEW ADDRESS OR DATA ?
	JZ	LE84C		;NEW ADDRESS
	MOV	A,L		;DATA TO A
	LHLD	BBUF		;GET ENTER POINTER
	MOV	M,A		;PUT DATA IN MEMORY
	CALL	ACH1		;INCREMENT ENTER POINTER
	JMP	ENT1		;DO NEXT BYTE
LE84C:	SHLD	BBUF		;SAVE AS NEW ENTER ADDR
	XCHG			;IBUF POINTER TO H,L
	INX	H		;INCREMENT IT
	SHLD	PNTR		;SAVE IT
	JMP	ENT1		;DO MORE BYTES
;
;HERE ARE THE ROUTINES THAT ADD OR REPLACE LINES IN FILES
;BASED ON THEIR LINE NUMBERS.  DELETE IS HANDLED BY A
;SEPARATE ROUTINE
;
LINE:	CPI	'0'		;MAKE SURE 1ST CHAR IS NUMERIC
	JC	WHAT		;IF IT'S NOT
	LXI	H,3030H		;TWO ASCII ZEROES
	SHLD	IBUF-4		;PUT TWO BEFORE THE LINE
	SHLD	IBUF-2		;TWO MORE MAKES FOUR
	LXI	H,IBUF-1	;POINT TO SPACE BEFORE LINE
	MVI	C,4		;MAX NO DIGITS IN LINE NO
LE86A:	INX	H		;POINT TO 1ST CHAR
	MOV	A,M		;GET IT
	CPI	'0'		;NUMERIC ?
	JC	LE87C		;NO
	CPI	'9'+1		;NUMERIC ?
	JNC	LE87C		;NO
	DCR	C		;YES, NUMERIC
	JNZ	LE86A		;COUNT NUMERIC CHRS IN LINE NO.
;
;IF WE GET HERE THE LINE HAD A FULL 4-DIGIT NO. TO BEGIN WITH
;NOW MAKE SURE LINE NO. IS FOLLOWED BY AT LEAST ONE SPACE
;PUT ONE IN IF IT'S NOT
;
	INX	H		;POINT AFTER THE LINE NO
	MOV	A,M		;GET CHAR
LE87C:	CPI	' '		;IS CHAR AFTER LINE NO. SPACE ?
	MOV	B,C		;COUNT OF LEADING 0'S TO ADD
	DCX	H		;POINT TO LAST DIGIT OF LINE NO
	JZ	LE893		;IF LINE NO FOLLOWED BY SPACE
	INR	C		;INR COUNT OF TOTAL CHRS TO ADD
	MOV	B,C		;SAVE IN B
	MVI	C,4		;NEED TO MOVE 4 DIGIT LINE NO.
	MVI	A,' '		;TO INSERT A SPACE
LE889:	MOV	D,M		;GET CHAR
	MOV	M,A		;PUT CHAR IN A INTO LINE
	MOV	A,D		;CHAR REMOVED FROM LINE TO A
	DCX	H		;DECREMENT LINE POINTER
	DCR	C		;AND COUNT OF CHRS LEFT TO MOVE
	JNZ	LE889		;IF NOT DONE
	MOV	M,A		;REPLACE LAST CHARACTER
	MOV	C,B		;COUNT OF 0'S TO INSERT
LE893:	LXI	H,IBUF		;POINT TO IBUFFER
LE896:	DCX	H		;DECREMENT LINE POINTER
	DCR	C		;DCR COUNT OF 0'S TO INSERT
	JP	LE896		;LOOP TILL IT GOES NEGATIVE
	SHLD	SAVL		;H,L IS NEW START OF LINE
	LDA	CCNT		;GET OLD LINE LENGTH COUNT
	ADD	B		;ADD COUNT OF CHARACTERS ADDED
	STA	CCNT		;UPDATED COUNT
	CPI	7		;7 ==> ORIG LINE WAS BLANK
	JZ	LE92B		;TO DELETE THE LINE
	MOV	M,A		;PUT LEN BYTE AT HEAD OF LINE
	LXI	D,4		;LENGTH OF LINE NO.
	DAD	D		;H,L POINTS LAST CHR OF LINE NO
	SHLD	ADDS		;SAVE ADDR.
	LXI	D,MAXL+3	;END OF HIGHEST LIN # IN FILE
	CALL	COM0		;COMPARE LINE NO. TO MAXL
	JNC	INSRT		;LINE GOES INTO MIDDLE OF FILE
;
;LINE GOES AT END OF FILE
;
	INX	H		;POINT TO LINE NO.
	CALL	LODM		;GET IT IN BCDE
	LXI	H,MAXL+3	;POINT TO END OF MAXL
	CALL	STOM		;THIS LINE BECOMES NEW MAXL
	LHLD	SAVL		;GET ADDR OF LINE
	XCHG			;D,E IS LINE POINTER
	LHLD	EOFP		;H,L IS CURRENT END OF FILE
	MVI	C,1		;1 IS THE MOVE TERMINATOR CHAR
	CALL	LMOV		;MOVE LINE TO END OF FILE
	MOV	M,C		;PUT EOF MARK IN FILE
	SHLD	EOFP		;UPDATE END OF FILE
	JMP	EORNS		;DONE
;
;GET HERE TO INSERT A LINE INTO FILE
;
INSRT:	CALL	LE947		;FIND LINE NO IN FILE
	MVI	C,2		;FLAG INITIALIZATION
	JZ	EQUL		;LINE IN FILE HAS SAME NO.
	DCR	C		;C=1 ==> NO. NOT NOW IN FILE
EQUL:	MOV	B,M		;GET LENGTH OF LINE IN FILE
	DCX	H		;ADDR TO INSERT LINE AFTER
	MVI	M,2		;PUT MARKER THERE
	SHLD	APNT		;AND SAVE AS POINTER
	LDA	CCNT		;LENGTH OF LINE TO ADD
	DCR	C		;THE FLAG - 2 = REPLACEMENT
	JZ	LT		;IF NEW LINE # NOT = OLD LINE #
	SUB	B		;COMPUTE DIFF IN LINE LENGTHS
	JZ	ZERO		;IF LINES ARE SAME LENGTH
	JC	GT		;IF NEW LINE > OLD LINE
;
;GET HERE IF OLD LINE > NEW LINE OR DOING
;ADDITION RATHER THAN REPLACEMENT
;
LT:	LHLD	EOFP		;GET OLD END OF FILE
	MOV	D,H		;DUPLICATE IN D,E
	MOV	E,L		;
	CALL	ADR		;ADD DIFF. TO OLD EOFP
	SHLD	EOFP		;OLD + ADDED = NEW
	MVI	C,2		;MOVE TERMINATION MARK IN FILE
	CALL	RMOV		;DO THE MOVE
	JMP	ZERO		;INSERT LINE INTO GAP CREATED
;
;GET HERE IF OLD LINE < NEW LINE
;
GT:	CMA			;MAKE DIFFERENCE NEGATIVE
	INR	A		;TWO'S COMPLEMENT
	MOV	D,H		;DUPLICATE H,L IN D,E
	MOV	E,L		;
	CALL	ADR		;SUB. DIFF FROM OLD EOFP
	XCHG			;
	CALL	LMOV		;DELETE EXCESS CHAR IN FILE
	MVI	M,1		;E-O-F INDICATOR
	SHLD	EOFP		;E-O-F ADDRESS
;
;GET HERE TO INSERT CURRENT LINE INTO FILE AREA
;
ZERO:	LHLD	SAVL		;LINE ADDRESS
	XCHG			;TO D,E
	LHLD	APNT		;INSERT ADDRESS
	MVI	M,0DH		;REPLACE MOVE TERM. MARK W/CR
	INX	H		;POINT TO WHERE NEW LINE GOES
	MVI	C,1		;MOVE TERMINATION MARK
	CALL	LMOV		;PUT LINE INTO FILE
	JMP	EORNS		;DONE
;
;DELETE LINE IF LINE NO. ENTERED WITH NO TEXT
;
LE92B:	INX	H		;POINT TO LINE NO TO DELETE
	CALL	LODM		;GET IT IN B,C,D,E
	LXI	H,ABUF+3	;DESTINATION ADDRESS
	CALL	STOM		;STORE DELETE ADDRESS
	LXI	H,ABUF+10	;ADDRESS OF END OF 2ND PARM
	CALL	STOM		;STORE LINE NO. AGAIN
	CALL	LEA2F		;MAKE LIKE A DELT N,N COMMAND
	JMP	EORNS		;LINE DELETED, DONE
;
;FIND - SEARCH FILE FOR SPECIFIED LINE
;
FIND:	LXI	H,ABUF+3	;ADDRS. OF TEMP BUFFER
FIND1:	SHLD	ADDS		;ADDR OF NO. TO LOOK UP
LE947:	LHLD	BOFP		;START OF FILE TO SEARCH
FI1:	CALL	E01		;SEE IF AT END OF FILE
	XCHG			;FILE ADR TO D,E
	LHLD	ADDS		;GET ADDR OF NO TO LOOK UP
	XCHG			;SET UP
	MVI	A,4		;LENGTH OF LINE NO.
	CALL	ADR		;POINT TO END OF LINE NO.
	CALL	COM0		;SEE IF LINE NOS. ARE SAME
	RC			;NO IN FILE > SUBJECT
	RZ			;NOS. ARE THE SAME
FI2:	MOV	A,M		;GET LENGTH BYTE
	CALL	ADR		;POINT TO NEXT LINE
	JMP	FI1		;TEST NEXT LINE
;
;ROUTINE TO CHECK FOR END OF FILE
;
EOF:	INX	H		;
E01:	MVI	A,1		;EOF INDICATOR
	CMP	M		;SAME AS CHAR POINTED TO ?
	RNZ			;NO - RETURN
	JMP	EORNS		;YES - ABORT COMMAND
;
;ROUTINE TO ADD ONE BYTE NO IN A TO ADDR IN H,L
;
ADR:	ADD	L		;ADD A TO L
	MOV	L,A		;RESULT REPLACES L
	RNC			;DONE IF NO CARRY
	INR	H		;ELSE INCREMENT H
	RET			;DONE NOW
;
;CHARACTER MOVEMENT ROUTINE TO MOVE FROM D,E TO H,L
;INCREMENTING D,E (START AT LOW ADDRESS END OF BLOCK TO MOVE)
;MOVE ENDS WHEN CHAR IN REG C IS ENCOUNTERED.
;
LMOV:	LDAX	D		;GET SOURCE CHAR
	INX	D		;INR SOURCE POINTER
	CMP	C		;TERMINATION CHAR ?
	RZ			;YES - DONE THEN
	MOV	M,A		;NO - MOVE TO DEST.
	INX	H		;INR DESTINATION POINTER
	JMP	LMOV		;DO NEXT CHAR
;
;CHARACTER MOVEMENT ROUTINE TO MOVE FROM D,E TO H,L
;DECREMENTING POINTERS (START AT HIGH END OF BLOCK)
;MOVE ENDS WHEN CHAR IN REG C IS ENCOUNTERED
;
RMOV:	LDAX	D		;GET SOURCE CHAR
	DCX	D		;DECR SOURCE POINTER
	CMP	C		;TERMINATION CHAR ?
	RZ			;YES - DONE
	MOV	M,A		;NO - STORE CHAR AT DEST.
	DCX	H		;DECREMENT DEST. POINTER
	JMP	RMOV		;DO NEXT CHARACTER
;
;LOAD FOUR CHARS FROM MEMORY INTO REGS B,C,D,E
;
LODM:	MOV	B,M
	INX	H
	MOV	C,M
	INX	H
	MOV	D,M
	INX	H
	MOV	E,M
	RET
;
;STORE FOUR CHARS FROM REGS B,C,D,E INTO MEMORY
;
STOM:	MOV	M,E
	DCX	H
	MOV	M,D
	DCX	H
	MOV	M,C
	DCX	H
	MOV	M,B
	RET
;
;ROUTINE TO COMPARE TWO CHAR STRINGS OF LENGTH 4.
;ZERO FLAG SET ==> STRINGS EQUAL. CARRY ==> STRING
;ADDRESSED BY D,E GREATER THAN OR = STRING ADDR BY
;H,L
;
COM0:	MVI	C,4		;LENGTH OF COMPARISON
COM1:	MVI	B,1		;ASSUME EQUAL
	ORA	A		;CLEAR CARRY
C01:	LDAX	D		;FETCH CHARACTER
	SBB	M		;SET FLAGS & COMPARE
	JZ	C02		;THESE BYTES ARE THE SAME
	INR	B		;MAKE EQUAL FLAG = 2
C02:	DCX	D		;DECREMENT 1 STR. POINTER
	DCX	H		;DECR. OTHER POINTER
	DCR	C		;DECR. CNT OF BYTES TO COMPARE
	JNZ	C01		;DO NEXT BYTE
	DCR	B		;DECREMENT ZERO FLAG
	RET			;DONE W/ZERO SET
;
;ROUTINE TO TAKE ASCII CHARS AND ADD LEADING ASCII
;ZEROS TO YIELD A 4 CHARACTER ASCII VALUE
;
NORM:	CALL	LODM		;GET 4 DIGITS
	XRA	A		;GET A BINARY ZERO
	CMP	B		;ARE ALL DIGITS ZERO ?
	RZ			;YES - NOTHING TO NORMALIZE
NOR1:	CMP	E		;NORMALIZED ?
	CNZ	STOM		;YES, PUT DIGITS BACK
	RNZ			;AND RETURN
	MOV	E,D		;ELSE MOVE DIGITS UP
	MOV	D,C
	MOV	C,B
	MVI	B,'0'		;AND ADD A ZERO
	JMP	NOR1		;THEN TEST FOR NORMALIZATION
;
;ROUTINE TO MOVE A LINE FROM THE FILE BUFFER INTO 
;THE ASSEMBLERS LINE BUFFER
;
MOVEL:	LHLD	APNT		;GET ASSEMBLER POINTER
	MOV	A,M		;GET 1ST CHAR OF LINE
	CPI	1		;END OF FILE ?
	RZ			;YES, RETURN
	XCHG			;LINE ADDR TO D,E
	MOV	L,A		;GET LENGTH AS 16 BITS IN H,L
	MVI	H,0		;LENGTH < 128
	DAD	D		;ADD LENGTH TO START ADDR
	DCX	H		;POINT TO LAST CHAR OF LINE
	MOV	A,M		;GET IT
	CPI	0DH		;C/R ?
	JNZ	LE718		;REPORT FCHK ERROR
	INX	D		;POINT TO 1ST ACTUAL CHAR
	LXI	H,IBUF-5	;ASSEMBLERS BUFFER
	MVI	C,0DH		;TERMINATION CHAR
	CALL	LMOV		;MOVE THE LINE
	MOV	M,C		;PUT C/R AT END OF LINE
	XCHG			;1ST CHAR OF NEXT LINE TO H,L
	SHLD	APNT		;SAVE UPDATED ASSEM. POINTER
	ORA	A		;CLEAR FLAGS
	RET			;DONE
;
;LIST AND TEXT (LIST W/O LINE NUMBERS) COMMANDS
;
LIST:	CMA			;MAKE A NON-ZERO
TEXT:	STA	NOLIN		;SAVE AS FORMAT FLAG
	CALL	CRLF		;START ON FRESH LINE
	LXI	H,ABUF		;GET STARTING LINE NO.
	CALL	LODM		;
	XRA	A		;ZERO FLAGS & ACCUM.
	CMP	B		;LINE NO. GIVEN ?
	JNZ	LE9EF		;JUMP IF LINE NO. GIVEN
	MVI	B,0FFH		;MAKE LINE NO. > 9999
LE9EF:	LXI	H,ABUF+10
	CMP	M		;ENDING LINE NO. GIVEN ?
	JNZ	LE9F9		;IF ENDING NO. GIVEN
	CALL	STOM		;STORE ENDING LINE NO > 9999
LE9F9:	CALL	FIND		;FIND STARTING LINE NO.
	SHLD	APNT		;SAVE AS POINTER
LE9FF:	CALL	MOVEL		;MOVE LINE TO OUTPUT BUFFER
	JZ	EOR		;IF END OF FILE FOUND
	LXI	H,IBUF-2	;POINT TO LAST DIGIT OF LINE NO
	LXI	D,ABUF+10	;D POINTS TO ENDING LINE NO.
	CALL	COM0		;COMPARE LINE NO. & END LIN NO.
	RC			;RETURN IF > ENDING LINE NO
	LDA	LFMT		;GET FORMAT FLAG
	ORA	A		;SET FLAGS
	CNZ	LF361		;TO FORMAT LINE
	LXI	H,IBUF-5	;POINT TO START OF LINE
	LDA	NOLIN		;GET LINE NO. FLAG
	ORA	A		;SET FLAGS
	JNZ	LEA23		;PRINT WITH LINE NO.
	LXI	H,IBUF		;POINT PAST LIN NO.
LEA23:	CALL	SCRN		;PRINT LINE FROM H,L POINTER
	CALL	CRLF		;PUT CR/LF AFTER LINE
	JMP	LE9FF		;TO DO NEXT LINE
;
;DELT - THE DELETE LINE COMMAND
;
DELT:	CALL	VCHK		;CHECK FOR REQD PARAMETERS
LEA2F:	CALL	FIND		;GET STARTING DELT ADDR
	SHLD	DELP		;SAVE IT
	LXI	H,ABUF+10	;SEE IF 2ND PARM GIVEN
	MOV	A,M		;GET CHAR
	ORA	A		;SET FLAGS
	JNZ	LEA40		;IF 2ND PARM GIVEN
	LXI	H,ABUF+3	;FIRST & LAST LINE ARE SAME
LEA40:	SHLD	ADDS		;SAVE 1ST LINE FIND ADDR
	XCHG
	LXI	H,MAXL+3	;HIGHEST LINE NO.
	CALL	COM0		;COMPARE TO ENDING DELT LINE
	LHLD	DELP		;GET DELT POSITION TO H,L
	JC	NOVR		;DELETE DOES NOT INVOLVE END
;
;GET HERE IF DELETE INVOLVES END OF FILE
;
;THIS GETS COMPLICATED BECAUSE:
;  A) THE LAST LINE'S C/R IS NOT FOLLOWED BY ANY LINE NO.
;                      AND
;  B) IN GENERAL, A 0DH MIGHT BE EITHER A LENGTH BYTE OR C/R
;
LEA50:	SHLD	EOFP		;DELT POS. ==> NEW EOF
	MVI	M,1		;PUT NEW EOF MARK IN FILE
	MOV	B,M		;FLAG WHICH ISN'T REALLY USED
	XCHG			;D,E = EOF
	LHLD	BOFP		;H,L = BOF
	XCHG			;D,E = BOF & H,L = EOF
	DCX	H		;SO WE MISS LAST LINE'S C/R
DEL2:	MOV	A,L		;SUBTRACT BOF FROM EOF
	SUB	E		;
	MOV	A,H		;
	SBB	D		;
	MVI	A,0DH		;SETTING UP FOR COMPARE
	JC	DEL4		;NO 0DH IN FILE==> MAXL=0
	DCX	H		;MOVE UP 1 CHAR
	CMP	M		;0DH ?
	JNZ	DEL2		;NO, THEN TRY NEXT CHAR
	DCX	H		;YES - SEE IF TWO IN A ROW
	MOV	A,L		;SUBTRACTING BOF FROM POINTER
	SUB	E
	MOV	A,H		;
	SBB	D		;
	JC	DEL4		;0DH WAS 1ST CHAR==>LENGTH BYTE
	MVI	A,0DH		;COMPARE THIS CHAR TO 0DH
	CMP	M		;
	INX	H		;POINT TO NEXT CHAR
	INX	H		;POINT TO NEXT CHAR
	JZ	DEL3		;WERE TWO 0DH'S, AT LINE # NOW
LEA7A:	INX	H		;ONLY 1 0DH, 1 MORE==>AT LINE #
DEL3:	CALL	LODM		;GET LINE NO IN REGS
	LXI	H,MAXL+3	;WHERE IT GOES
	CALL	STOM		;PUT IT THERE
	RET			;MAXL IS UPDATED
DEL4:	XCHG			;FOR PROPER RETURN
	DCR	B		;ALWAYS 1 ==> 0
	JNZ	LEA7A		;NEVER TAKE JUMP
	STA	MAXL		;MAKES MAXL VERY SMALL ALWAYS
	RET			;DONE, EDITOR THINKS FILE EMPTY
;
;GET HERE IF DELETE IS IN THE MIDDLE OF THE FILE
;
NOVR:	CALL	FI1		;FIND END OF DELETE AREA
	CZ	FI2		;NEXT LINE IF LINE NOS. EQUL
	XCHG			;
	LHLD	DELP		;DEST = START OF DELT AREA
	MVI	C,1		;TERM ON EOF MARK
	CALL	LMOV		;DO THE MOVE TO DELETE
	SHLD	EOFP		;UPDATE EOF ADDRESS
	MVI	M,1		;PUT EOF MARK IN FILE
	RET			;DONE
;
;STAB COMMAND - SET SYMBOL TABLE ADDRESS
;
STAB:	CALL	VCHK		;CHECK FOR REQD PARM
	LHLD	BBUF		;GET IT
	SHLD	SYMADD		;SAVE AS SYMBOL TABLE ADDRESS
	JMP	EORMS		;DONE
