; JUMPING TO THIS LOCATION IS LIKE RETSKP.  IT ASSUMES THE INSTRUCTION
;   AFTER THE CALL IS A JMP ADDR.
RSKP:	POP    HL		; GET THE RETURN ADDRESS.
	INC    HL		; INCREMENT BY THREE.
	INC    HL
	INC    HL
	JP   (HL)
; THIS ROUTINE PRINTS THE NUMBER IN HL ON THE SCREEN IN DECIMAL.
; SAVES ALL ACS.
NOUT:	PUSH   AF	; SAVE OUR ACS.
	PUSH   BC
	PUSH   DE
	PUSH   HL
	LD     BC,-10	; GET SOME USEFUL CONSTANTS.
	LD     DE,-1
NOUT2:	ADD    HL,BC		; SUBTRACT AS MANY 10S AS POSSIBLE.
	INC    DE		; COUNT THEM.
	JP     C,NOUT2	; IF SOME LEFT KEEP GOING.
	LD     BC,10	; RESTORE THE LAST 10 WE TOOK AWAY.
	ADD    HL,BC
	EX   DE,HL   			; SWAP THE REMAINDER AND THE QUOTIENT.
	LD     A,H		; GET THE NUMBER OF 10S FOUND.
	OR     L		;* I THINK THIS CHECKS IF H EQUALS ZERO.  IF
	CALL   NZ,NOUT	; IF NON ZERO, RECURSE.
	LD     A,E		; GET THE REMAINDER.
	ADD    A,30H		; MAKE THE NUMBER PRINTABLE.
	CALL	CONOUT
	POP    HL		; RESTORE THE ACS.
	POP    DE
	POP    BC
	POP    AF
	RET
;	THIS SET OF ROUTINES PROVIDES A USER ORIENTED WAY OF PARSING
;	COMMANDS.  IT IS SIMILAR TO THAT OF THE COMND JSYS IN TOPS-20.
;	THIS ROUTINE PRINTS THE PROMPT IN DE AND SPECIFIES THE REPARSE
;	ADDRESS.
PROMPT:	POP    HL		; GET THE RETURN ADDRESS.
	PUSH   HL		; PUT IT ON THE STACK AGAIN.
	LD     (CMRPRS),HL	; SAVE IT AS THE ADDRESS TO GO TO ON REPARSE.
	LD     (CMOSTP),SP	; SAVE FOR LATER RESTORAL.
	LD     (CMPRMP),DE	;save the prompt location
	LD     HL,CMDBUF
	LD     (CMCPTR),HL	; INITIALIZE THE COMMAND POINTER.
	LD     (CMDPTR),HL
	XOR    A
	LD     (CMAFLG),A	; ZERO THE FLAGS.
	LD     (CMCCNT),A
	LD     A,0FFH	; TRY IT THIS WAY (DAPHNE.)
	LD     (CMSFLG),A
	LD     DE,CMCRLF
	CALL   PRTSTR
	LD     DE,(CMPRMP)	; PRINT THE PROMPT.
	CALL   PRTSTR
	RET
;	THIS ADDRESS IS JUMPED TO ON REPARSE.
REPARS:	LD     SP,(CMOSTP)	; GET THE OLD STACK POINTER.
	LD     HL,CMDBUF
	LD     (CMDPTR),HL
	LD     A,0FFH	; TRY IT THIS WAY (DAPHNE.)
	LD     (CMSFLG),A
	LD     HL,(CMRPRS)	; GET THE REPARSE ADDRESS.
	JP   (HL)  			; GO THERE.
;	THIS ADDRESS CAN BE JUMPED TO ON A PARSING ERROR.
PRSERR:	LD     SP,(CMOSTP)	; GET THE OLD STACK POINTER.
	LD     HL,CMDBUF
	LD     (CMCPTR),HL	; INITIALIZE THE COMMAND POINTER.
	LD     (CMDPTR),HL
	XOR    A
	LD     (CMAFLG),A	; ZERO THE FLAGS.
	LD     (CMCCNT),A
	LD     A,0FFH	; TRY IT THIS WAY (DAPHNE.)
	LD     (CMSFLG),A
	LD     DE,CMCRLF
	CALL   PRTSTR
	LD     DE,(CMPRMP)	; GET THE PROMPT.
	CALL   PRTSTR
;* INSTEAD RETURN TO BEFORE THE PROMPT CALL.
	LD     HL,(CMRPRS)
	JP   (HL)
;	THIS ROUTINE PARSES THE SPECIFIED FUNCTION IN A.  ANY ADDITIONAL
;	INFORMATION IS IN DE AND HL.
;	RETURNS +1 ON SUCCESS
;		+4 ON FAILURE (ASSUMES A JMP FOLLOWS THE CALL)
COMND:	LD     (CMSTAT),A	; SAVE WHAT WE ARE PRESENTLY PARSING.
	CALL   CMINBF	; GET CHARS UNTIL AN ACTION OR A ERASE CHAR.
	CP     CMCFM	; PARSE A CONFIRM?
	JP     Z,CMCFRM	; GO GET ONE.
	CP     CMKEY	; PARSE A KEYWORD?
	JP     Z,CMKEYW	; TRY AND GET ONE.
	CP     CMIFI	; PARSE AN INPUT FILE SPEC?
	JP     Z,CMIFIL	; GO GET ONE.
	CP     CMIFIN	; INPUT FILE-SPEC SILENT?
	JP     Z,CMIFIL	; DO AS HE WISHES
	CP     CMOFI	; OUTPUT FILE SPEC?
	JP     Z,CMOFIL	; GO GET ONE.
	CP     CMTXT	; PARSE ARBITRARY TEXT?
	JP     Z,CMTEXT	; GO DO IT.
	LD     DE,CMER00	; "?UNRECOGNIZED COMND CALL"
	CALL   PRTSTR
	RET
;	THIS ROUTINE PARSES ARBITRARY TEXT UP TO A CR.
;	ACCEPTS DE:	ADDRESS TO PUT TEXT
;	RETURNS IN A:	NUMBER OF CHARS IN TEXT (MAY BE 0)
;		  DE:	UPDATED POINTER
CMTEXT:	EX   DE,HL   			; PUT THE POINTER TO THE DEST IN HL.
	LD     (CMPTAB),HL	; SAVE THE POINTER.
	LD     B,0		; INIT THE CHAR COUNT
CMTXT1:	CALL   CMGTCH	; GET A CHAR.
	OR     A		; TERMINATOR?
	JP     P,CMTXT5	; NO, PUT IN USER SPACE.
	AND    7FH		; TURN OFF MINUS BIT.
	CP     ESC		; AN ESCAPE?
	JR     NZ,CMTXT2	; NO.
	LD     A,BELL	; GET A BELL.
	CALL   CONOUT
	XOR    A
	LD     (CMAFLG),A	; TURN OFF THE ACTION FLAG.
	LD     HL,(CMCPTR)	; MOVE THE POINTER TO BEFORE THE ESCAPE.
	DEC    HL
	LD     (CMCPTR),HL
	LD     (CMDPTR),HL
	LD     HL,CMCCNT	; GET THE CHAR COUNT.
	DEC    (HL)		; DECREMENT IT BY ONE.
	JP     CMTXT1		; TRY AGAIN.
CMTXT2:	CP     '?'		; IS IT A QUESTION MARK?
	JR     Z,CMTXT3		; IF SO PUT IT IN THE TEXT.
	CP	' '	 	;blank?
	JR	Z,CMTXT3	;if so put in the text
	CP     FF		; IS IT A FORMFEED?
	CALL   Z,CMBLNK		; IF SO BLANK THE SCREEN.
	LD     A,B		; RETURN THE COUNT.
	LD     HL,(CMPTAB)	; RETURN UPDATED POINTER IN HL.
	EX   DE,HL
	JP     RSKP		; RETURN SUCCESS.
CMTXT3:	LD     HL,CMAFLG	; POINT TO THE ACTION FLAG.
	LD     (HL),0		; SET IT TO ZERO.
CMTXT5:	INC    B		; INCREMENT THE COUNT.
	CP	'a'
	JR	C,CMTXT6	;lower than 'a'
	CP	'z'
	JR	NC,CMTXT6	;greater than 'z'
	AND	5FH		;capitalize it
CMTXT6	LD     HL,(CMPTAB)	; GET THE POINTER.
	LD     (HL),A		; PUT THE CHAR IN THE ARRAY.
	INC    HL
	LD     (CMPTAB),HL	; SAVE THE UPDATED POINTER.
	JP     CMTXT1		; GET ANOTHER CHAR.
; THIS ROUTINE GETS A CONFIRM.
CMCFRM:	LD     DE,CMIN00	; PRINT SOMETHING USEFUL.
	CALL   PRTSTR
	LD     DE,CMCRLF	; PRINT A CRLF.
	CALL   PRTSTR
	LD     DE,(CMPRMP)	; REPRINT THE PROMPT.
	CALL   PRTSTR
	LD     HL,(CMDPTR)	; GET THE POINTER INTO THE BUFFER.
	LD     A,'$'		; PUT A $ THERE FOR PRINTING.
	LD     (HL),A
	LD     HL,(CMCPTR)
	DEC    HL		; DECREMENT AND SAVE THE BUFFER POINTER.
	LD     (CMCPTR),HL
	LD     DE,CMDBUF
	CALL   PRTSTR
	XOR    A		; TURN OFF THE ACTION FLAG.
	LD     (CMAFLG),A
	CALL	@KEY		;get a key from the keyboard
	CP	CR
	JR	Z,CMCFR3
	CP	FF
	JR	Z,CMCFR3
	CP	4
	RET	M
	LD	HL,(CMCPTR)
	INC	HL
	LD	(HL),A
	INC	HL
	LD	(CMCPTR),HL
	CALL	CONOUT
	JP     REPARS	; REPARSE EVERYTHING.
CMCFR3:	CP     FF		; IS IT A FORM FEED?
	CALL   Z,CMBLNK	; IF SO BLANK THE SCREEN.
	JP     RSKP
;	THIS ROUTINE PARSES A KEYWORD FROM THE TABLE POINTED
;	TO IN DE.  THE FORMAT OF THE TABLE IS AS FOLLOWS:
;
;	ADDR:	DB	N	; WHERE N IS THE # OF ENTRIES IN THE TABLE.
;		DB	M	; M IS THE SIZE OF THE KEYWORD.
;		DB	'STRING$' ; WHERE STRING IS THE KEYWORD.
;		DB	A,B	; WHERE A & B ARE PIECES OF DATA
;				;  TO BE RETURNED.  (MUST BE TWO OF THEM.)
;
;	THE KEYWORDS MUST BE IN ALPHABETICAL ORDER.
;**** NOTE:  THE DATA VALUE A IS RETURNED IN REGISTERS A AND E.  THE
;****	DATA VALUE B IS RETURNED IN REGISTER D.  THIS ALLOWS THE TWO DATA
;	BYTES TO BE STORED AS:
;		DW	XXX
;	AND RESULT IN A CORRECTLY FORMATTED 16-BIT VALUE IN REGISTER PAIR
;	DE.
CMKEYW:	LD     (CMHLP),HL	; SAVE THE HELP.
	LD     (CMPTAB),DE	; SAVE THE BEGINNING OF KEYWORD TAB FOR '?'.
	LD     A,(DE)		; GET THE NUMBER OF ENTRIES IN THE TABLE.
	LD	B,A		;save in B
	INC    DE
	LD     (CMKPTR),DE
	LD     HL,(CMDPTR)	; SAVE THE COMMAND POINTER.
	LD     (CMSPTR),HL
CMKEY2:	LD	A,B
	OR     A		; ANY LEFT?
	RET   Z			; IF NOT WE FAILED.
	LD     HL,(CMKPTR)
	LD     E,(HL)		; GET THE LENGTH OF THE KEYWORD.
	INC    HL
CMKEY3:	DEC    E		; DECREMENT THE NUMBER OF CHARS LEFT.
	LD     A,E
	CP     0FFH	; HAVE WE PASSED THE END?
	JP     M,CMKEY5	; IF SO GO TO THE NEXT.
	CALL   CMGTCH	; GET A CHAR.
	OR     A		; IS IT A TERMINATER?
	JP     P,CMKEY4	; IF POSITIVE, IT IS NOT.
	AND    7FH		; TURN OFF THE MINUS BIT.
	CP     '?'
	JP     NZ,CMKY31
	XOR    A
	LD     (CMAFLG),A	; TURN OFF THE ACTION FLAG.
	LD     HL,CMCCNT	; DECREMENT THE CHAR COUNT.
	DEC    (HL)
;* MUST GO THROUGH THE KEYWORD TABLE AND PRINT THEM.
	LD     DE,(CMHLP)	; FOR NOW PRINT THE HELP TEXT.
	CALL   PRTSTR
	LD     DE,CMCRLF	; PRINT A CRLF.
	CALL   PRTSTR
	LD     DE,(CMPRMP)	; REPRINT THE PROMPT.
	CALL   PRTSTR
	LD     HL,(CMDPTR)	; GET THE POINTER INTO THE BUFFER.
	LD     A,'$'	; PUT A $ THERE FOR PRINTING.
	LD     (HL),A
	LD     HL,(CMCPTR)
	DEC    HL		; DECREMENT AND SAVE THE BUFFER POINTER.
	LD     (CMCPTR),HL
	LD     DE,CMDBUF
	CALL   PRTSTR
	JP     REPARS	; REPARSE EVERYTHING.
CMKY31:	CP     ESC		; IS IT AN ESCAPE?
	JP     NZ,CMKY35
	XOR    A
	LD     (CMAFLG),A	; TURN OFF THE ACTION FLAG.
	PUSH   DE
	PUSH   BC
	PUSH   HL
	CALL   CMAMBG
	JP	CMKY32
	LD     A,BELL
	CALL	CONOUT
	LD     HL,(CMCPTR)	; MOVE THE POINTER TO BEFORE THE ESCAPE.
	DEC    HL
	LD     (CMCPTR),HL
	LD     (CMDPTR),HL
	LD     HL,CMCCNT	; GET THE CHAR COUNT.
	DEC    (HL)		; DECREMENT IT BY ONE.
	POP    HL
	POP    BC
	POP    DE
	INC    E		; INCREMENT THE LEFT TO PARSE CHAR COUNT.
	JP     CMKEY3
CMKY32:	LD     HL,(CMCPTR)	; POINTER INTO BUFFER.
	DEC    HL		; BACKUP TO THE ESCAPE.
	EX   DE,HL
	POP    HL
	PUSH   HL
CMKY33:	LD     A,(HL)		; GET THE NEXT CHAR.
	CP     '$'		; FINISHED?
	JP     Z,CMKY34
	INC    HL
	EX   DE,HL
	LD     (HL),A		; MOVE IT INTO THE BUFFER.
	INC    HL
	EX   DE,HL
	LD     A,(CMCCNT)	; INCREMENT THE CHAR COUNT.
	INC    A
	LD     (CMCCNT),A
	JP     CMKY33
CMKY34:	LD     A,(CMCCNT)	; GET THE CHARACTER COUNT.
	INC    A		; INCREMENT AND SAVE IT.
	LD     (CMCCNT),A
	EX   DE,HL   			; PUT THE COMMAND BUFFER POINTER IN HL.
	LD     A,' '		; GET A BLANK.
	LD     (HL),A		; PUT IT IN THE COMMAND BUFFER.
	INC    HL		; INCREMENT THE POINTER
	LD     (CMCPTR),HL	; SAVE THE UPDATED POINTER.
	LD     (CMDPTR),HL
	POP    HL
	PUSH   HL
	EX   DE,HL
	CALL   PRTSTR	; PRINT THE REST OF THE KEYWORD.
	LD     A,' '
	CALL	CONOUT
	POP    HL
	POP    BC
	POP    DE
	JP     CMKY37
CMKY35:	PUSH   HL
	PUSH   DE
	CALL   CMAMBG
	JP	CMKY36
	LD	DE,CMER01
	CALL   PRTSTR	; SAY ITS AMBIGUOUS.
	JP     PRSERR	; GIVE UP.
CMKY36:	POP    DE
	POP    HL
CMKY37:	INC    E		; ADD ONE INCASE IT IS NEGATIVE.
	LD     D,0
	ADD    HL,DE		; INCREMENT PAST THE KEYWORD.
	INC    HL		; PAST THE $.
	LD     E,(HL)		; GET THE DATA.
	INC    HL
	LD     D,(HL)
	LD     A,E
	JP     RSKP
CMKEY4:	CP     'a'		; IS IT LESS THAN A?
	JR     C,CMKY41	; IF SO DON'T CAPITALIZE IT.
	CP     'z'	; IS IT MORE THAN Z?
	JR     NC,CMKY41	; IF SO DON'T CAPITALIZE IT.
	AND    137O	; CAPITALIZE IT.
CMKY41:	LD     D,(HL)		; GET THE NEXT CHAR OF THE KEYWORD.
	INC    HL
	CP     D		; MATCH?
	JP     Z,CMKEY3	; IF SO GET THE NEXT LETTER.
CMKEY5:	LD     D,0
	LD     A,E		; GET THE NUMBER OF CHARS LEFT.
	OR     A		; IS IT NEGATIVE?
	JP     P,CMKY51
	LD     D,0FFH	; IF SO, SIGN EXTEND.
CMKY51:	ADD    HL,DE		; INCREMENT PAST THE KEYWORD.
	LD     DE,0003H	; PLUS THE $ AND DATA.
	ADD    HL,DE
	LD     (CMKPTR),HL
	DEC    B		; DECREMENT THE NUMBER OF ENTRIES LEFT.
	LD     HL,(CMSPTR)	; GET THE OLD CMDPTR.
	LD     (CMDPTR),HL	; RESTORE IT.
;* CHECK SO WE DON'T PASS IT.
	JP     CMKEY2	; GO CHECK THE NEXT KEYWORD.
CMAMBG:	DEC    B		; DECREMENT THE NUMBER OF ENTRIES LEFT.
	RET   M			; IF NONE LEFT THEN IT IS NOT AMBIGUOUS.
	INC    E		; THIS IS OFF BY ONE; ADJUST.
	LD     C,E		; SAVE THE CHAR COUNT.
	LD     A,E
	OR     A		; ANY CHARS LEFT?
	RET   Z			; NO, IT CAN'T BE AMBIGUOUS.
	LD     D,0
	ADD    HL,DE		; INCREMENT PAST THE KEYWORD.
	LD     E,3		; PLUS THE $ AND DATA.
	ADD    HL,DE
	LD     B,(HL)		; GET THE LENGTH OF THE KEYWORD.
	INC    HL
	EX   DE,HL
	LD     HL,(CMKPTR)	; GET POINTER TO KEYWORD ENTRY.
	LD     A,(HL)		; GET THE LENGTH OF THE KEYWORD.
	SUB    C		; SUBTRACT HOW MANY LEFT.
	LD     C,A		; SAVE THE COUNT.
	CP     B
	JP     Z,CMAMB0
	RET   P			; IF LARGER THAN THE NEW WORD THEN NOT AMB.
CMAMB0:	LD     HL,(CMSPTR)	; GET THE POINTER TO WHAT PARSED.
CMAMB1:	DEC    C		; DECREMENT THE COUNT.
	JP     M,RSKP		; IF WE ARE DONE THEN IT IS AMBIGUOUS.
	EX   DE,HL   			; EXCHANGE THE POINTERS.
	LD     B,(HL)		; GET THE NEXT CHAR OF THE KEYWORD
	INC    HL
	EX   DE,HL   			; EXCHANGE THE POINTERS.
	LD     A,(HL)		; GET THE NEXT PARSED CHAR.
	INC    HL
	CP     'a'		; IS IT LESS THAN A?
	JR     C,CMAMB2	; IF SO DON'T CAPITALIZE IT.
	CP     'z'	; IS IT MORE THAN Z?
	JR     NC,CMAMB2	; IF SO DON'T CAPITALIZE IT.
	AND    137O
CMAMB2:	CP     B		; ARE THEY EQUAL?
	RET   NZ 			; IF NOT THEN ITS NOT AMBIGUOUS.
	JP     CMAMB1	; CHECK THE NEXT CHAR.
CMIFIL	EX	DE,HL
	LD	(CMFCB),HL
	EX	DE,HL
	LD	HL,(CMFCB)
	LD	B,50		;number to blank
CMIFI0:	LD     (HL),' '			; BLANK THE FCB.
	INC    HL
	DJNZ	CMIFI0
CMIFI1:	LD	HL,(CMDPTR)	;GET COMMAND FCB
	CALL	@FSPEC
	JR	Z,CMIFI2
	LD     DE,CMER02
	CALL   PRTSTR
	JP	PRSERR
CMIFI2:	LD	(CMDPTR),HL
	JP	RSKP
CMOFIL:	JP	CMIFIL
CMINBF:	PUSH   AF
	PUSH   DE
	PUSH   HL
	LD     A,(CMAFLG)	; IS THE ACTION CHAR FLAG SET?
	OR     A
	JP     NZ,CMINB9	; IF SO GET NO MORE CHARS.
	LD	HL,(CMCPTR)
	LD	DE,CMFCB	;END OF BUFFER
	XOR	A
	SBC	HL,DE
	LD	B,L		;size of cmdbuf
	LD	HL,(CMCPTR)
	CALL	@KEYIN		;rom lineinput routine
	JP	C,PRSERR	;action if <BREAK> typed
	LD	A,B
	LD	(CMCCNT),A
	OR	A
	JP      Z,PRSERR	; IF NOT, JUST START OVER.
	LD	HL,(CMCPTR)
	LD	E,B
	LD	D,0
	ADD	HL,DE
	LD	(CMCPTR),HL	;update pointer
CMINB6:	LD     A,0FFH	; SET THE ACTION FLAG.
	LD     (CMAFLG),A
CMINB9:	POP    HL
	POP    DE
	POP    AF
	RET
CMGTCH:	PUSH   HL
	PUSH   BC
CMGTC1:	LD     A,(CMAFLG)
	OR     A		; IS IT SET.
	CALL   Z,CMINBF	; IF THE ACTION CHAR FLAG IS NOT SET GET MORE.
	LD     HL,(CMDPTR)	; GET A POINTER INTO THE BUFFER.
	LD     A,(HL)		; GET THE NEXT CHAR.
	INC    HL
	LD     (CMDPTR),HL
	CP     ' '			; IS IT A SPACE?
	JP     Z,CMGTC2
	CP     TAB		; OR A TAB?
	JP     NZ,CMGTC3
CMGTC2:	LD     A,(CMSFLG)	; GET THE SPACE FLAG.
	OR     A		; WAS THE LAST CHAR A SPACE?
	JP     NZ,CMGTC1	; YES, GET ANOTHER CHAR.
	LD     A,0FFH	; SET THE SPACE FLAG.
	LD     (CMSFLG),A
	LD     A,' '
	POP    BC
	POP    HL
	JP     CMGTC5
CMGTC3:	PUSH   AF
	XOR    A
	LD     (CMSFLG),A	; ZERO THE SPACE FLAG.
	POP    AF
	POP    BC
	POP    HL
	CP     ESC
	JP     Z,CMGTC5
	CP     '?'		; IS THE USER CURIOUS?
	JP     Z,CMGTC4
	CP     CR
	JP     Z,CMGTC4
	CP     LF
	JP     Z,CMGTC4
	CP     FF
	RET   NZ 			; NOT AN ACTION CHAR, JUST RETURN.
CMGTC4:	PUSH   HL
	LD     HL,(CMDPTR)
	DEC    HL
	LD     (CMDPTR),HL
	POP    HL
CMGTC5:	OR     80H		; MAKE THE CHAR NEGATIVE TO INDICATE IT IS
	RET    			;  A TERMINATOR.
