home *** CD-ROM | disk | FTP | other *** search
- TITLE 'EDIT - SUPER EDITOR FOR CP/M'
- ;
- ORG 0100H
- ;
- DFCB1 EQU 5CH ;FIRST DEFAULT FCB
- DFCB2 EQU 6CH ;SECOND DEFAULT FCB
- ;
- XRA A ;CLEAR FLAGS
- STA SWFLG
- STA EOFFLG
- LXI SP,STACK ;SET UP A STACK
- LHLD 1
- LXI B,3 ;SET UP CONSOLE VECTORS
- DAD B
- SHLD CSTS1 ;STATUS VECTOR
- INX H
- INX H
- INX H
- SHLD CONIN1 ;CONSOLE INPUT VECTOR
- LXI H,DFCB1+1 ;MAKE SURE THERE'S A FILENAME
- MOV A,M
- CPI 020H
- JNZ HAVNAM
- MVI C,9 ;OTHERWISE, DIE WITH ERROR
- LXI D,NSFMSG
- CALL 5
- RST 0
- HAVNAM:
- LXI D,IFCB ;MOVE FIRST FILENAME TO OUR INPUT FCB
- LXI H,DFCB1
- LXI B,0CH
- CALL MOVE
- LXI D,IFCB ;TRY TO OPEN IT
- CALL OPENF
- INR A
- LDA DFCB2
- JNZ OPNDST
- LXI D,NEWMSG ;OPEN FAILED - SAY 'NEW FILE'
- MVI C,9
- CALL 5
- LXI H,DFCB1 ;AND CREATE THE FILE
- LXI D,OFCB
- LXI B,0CH
- CALL MOVE
- LXI H,SWFLG
- MVI M,0FFH ;SET 'CREATE' FLAG
- INX H
- MVI M,01AH ;SET 'END OF FILE' FLAG
- LDA DFCB1
- OPNDST:
- STA OFCB ;SET DESTINATION DRIVE #
- LXI D,OFCB1 ;COPY NAME FROM FIRST FILE
- CALL MOVNAM ;TO OUR OUTPUT FCB
- LXI D,OFCB ;CREATE THE OUTPUT FILE
- CALL MAKFIL
- JMP MAIN ;NOW GO EDIT IT
- CONIN:
- CALL 0 ;CONSOLE INPUT
- CONIN1 EQU $-2 ;WHERE TO DROP IN THE ADDRESS
- ANI 07FH ;STRIP PARITY BIT
- RET
- CONOUT:
- PUSH B ;CONSOLE OUTPUT
- PUSH D ;SAVE ALL REGS
- PUSH H
- MOV E,C ;THEN CALL CP/M
- MVI C,2
- CALL 5
- POP H ;RESTORE REGS
- POP D
- POP B
- RET
- CSTS:
- JMP 0 ;CONSOLE STATUS (BREAK TEST)
- CSTS1 EQU $-2 ;WHERE TO DROP IN THE ADDRESS
- GETTOP:
- PUSH H ;DETERMINE TOP OF USEABLE RAM
- LHLD 6 ;BY LOOKING AT THE BDOS VECTOR
- DCX H ;MINUS ONE
- MOV B,H
- MOV A,L
- POP H
- RET
- GETBYT:
- LDA EOFFLG ;READ A BYTE FROM THE INPUT FILE
- ORA A ;FIRST CHECK END-OF-FILE
- MVI A,01AH
- RNZ
- PUSH B ;NOW WE KNOW WE'VE GOT SOMETHING
- PUSH D
- PUSH H
- GTBYT1:
- LXI H,INFCNT ;CHECK BYTE COUNT IN BUFFER
- INR M ;WILL SET MINUS IF AT END
- JM READF ; WHICH SAYS TO READ SOME MORE
- MOV C,M ;OTHERWISE, ADD COUNT TO BUFFER
- MVI B,0 ; ADDRESS, GIVING ADDRESS OF
- LXI H,INBUF ; NEXT BYTE
- DAD B
- MOV A,M ;FETCH THE BYTE
- CPI 01AH ;MAKE SURE IT'S NOT EOF
- JNZ L01B6
- L01B3:
- STA EOFFLG ;WE READ AN EOF, SO SET THE FLAG
- L01B6:
- ANI 07FH ;STRIP THE PARITY BIT
- POP H ;RESTORE REGS
- POP D
- POP B
- RET ;AND EXIT
- READF:
- LXI H,INFCNT ;COME HERE TO READ NEXT BUFFER
- MVI M,0FFH ;FIRST RIG THE COUNT SO NEXT INR WILL
- LXI D,INBUF ; GIVE US BYTE ZERO
- MVI C,01AH ;ISSUE 'SET DMA ADDRESS' CALL TO CP/M
- CALL 5
- LXI D,IFCB ;ISSUE 'READ' CALL TO CP/M
- MVI C,014H
- CALL 5
- DCR A ;A=1 MEANS EOF
- JNZ GTBYT1 ;OTHERWISE, PROCESS BYTE
- MVI A,01AH ;GOT EOF - SEND BACK EOF CHARACTER
- JMP L01B3
- PUTBYT:
- PUSH H ;WRITE A BYTE TO THE OUTPUT FILE
- PUSH D
- PUSH B
- LXI H,OUFCNT ;BUMP OUTPUT BUFFER COUNT
- INR M ;GOES NEGATIVE AFTER 128 BYTES
- CM WRITEF ; WHICH SAYS TO FLUSH BUFFER BEFORE CONTINUING
- MOV C,M
- MVI B,0 ;ADD BYTE COUNT TO BUFFER BASE ADDRESS
- LXI H,OUTBUF ;GIVING ADDRESS OF NEXT BYTE
- DAD B
- POP B ;CHARACTER WAS IN C AT ENTRY
- PUSH B ;SO REFRESH IT
- MOV M,C ;AND STORE IN BUFFER
- MOV A,C ;WAS IT AN EOF?
- CPI 01AH
- JNZ L0218
- MVI A,RET ;WE WROTE AN EOF, SO DISABLE WRITE ROUTINE
- STA PUTBYT ;BY MAKING FIRST INSTRUCTION 'RET'
- LXI H,OUFCNT ;NOW FLUSH LAST OUTPUT BUFFER
- CALL WRITEF
- MVI C,010H ;CLOSE THE OUTPUT FILE
- LXI D,OFCB
- CALL 5
- LXI H,IFCB1 ;MOVE INPUT NAME TO SECOND HALF OF
- LDA OFCB ;OUTPUT FCB, IN PREPARATION
- LXI D,OFCBRN ;FOR RENAME OPERATION
- STAX D
- INX D
- LXI B,0BH
- CALL MOVE
- L0218:
- POP B ;RESTORE REGISTERS AND EXIT
- POP D
- POP H
- RET
- WRITEF:
- MVI M,0 ;COME HERE TO FLUSH OUTPUT BUFFER
- MVI C,01AH ; CLEAR BYTE COUNT
- LXI D,OUTBUF ;ISSUE 'SET DMA ADDRESS' TO CP/M
- CALL 5
- LXI D,OFCB ;ISSUE 'WRITE' TO CP/M
- MVI C,015H
- CALL 5
- LXI H,OUFCNT ;POINT TO BYTE COUNT (PUTBYT NEEDS IT)
- CPI 2 ;TEST FOR 'NO SPACE' ERROR (A=2)
- RNZ ;NO ERROR - RETURN
- LXI D,NSPMSG ;SCREAM ABOUT ERROR
- MVI C,9
- CALL 5
- LXI D,OFCB ;CLOSE OUTPUT FILE (SAVE WHAT WE CAN)
- MVI C,010H
- CALL 5
- BYEBYE:
- LDA SWFLG ;EXIT FROM EDITOR - FIRST CHECK CREATE FLAG
- ORA A
- JNZ 0 ;NO CREATE
- LXI D,IFCB ;YES CREATE - WE MUST CLOSE IT
- MVI C,010H
- CALL 5
- RST 0 ;THEN EXIT
- MAKFIL: ;PERFORM ALL STEPS OF CREATING A FILE
- PUSH D ;MAKE AN OUTPUT FILE
- MVI C,013H ;FIRST DELETE OLD ONE
- CALL 5
- POP D
- PUSH D
- MVI C,016H ;THEN CREATE NEW ONE
- CALL 5
- POP D ;FALL INTO OPEN ROUTINE
- OPENF:
- MVI C,0FH ;OPEN THE FILE WITH FCB AT (DE)
- JMP 5
- MOVNAM:
- LXI H,DFCB1+1 ;COPY NAME FIELD ONLY
- LXI B,8 ;FROM FIRST DEFAULT FCB
- MOVE:
- DCX B ;MOVE M(HL) TO M(DE) UNTIL BC=0
- INR C
- INR B
- MOVELP:
- MOV A,M
- STAX D
- INX H
- INX D
- DCR C
- JNZ MOVELP
- DCR B
- JNZ MOVELP
- RET
- FILL:
- MOV M,B ;FILL M(HL) WITH (B)
- INX H
- DCR C ;UNTIL C=0
- JNZ FILL
- RET
- NEWMSG:
- DB 13,10,'NEW FILE$'
- NSPMSG:
- DB 13,10,'NO MORE DISK SPACE$'
- NSFMSG:
- DB 13,10,'NO SOURCE FILE SPECIFIED$'
- INFCNT:
- DB 7FH ;BYTE COUNT IN INPUT BUFFER
- IFCB:
- DB 0 ;INPUT FILE CONTROL BLOCK
- IFCB1:
- DS 8
- DB 'ASM'
- DB 0,0,0,0
- IFCBRN:
- DS 16
- DB 0
- INBUF:
- DS 128 ;INPUT BUFFER (1 SECTOR LONG)
- OUFCNT:
- DB 255 ;BYTE COUNT IN OUTPUT BUFFER
- OFCB:
- DB 0 ;OUTPUT FILE CONTROL BLOCK
- OFCB1:
- DS 8
- DB '$$$'
- DB 0,0,0,0
- OFCBRN:
- DS 16
- DB 0
- OUTBUF:
- DS 128 ;OUTPUT BUFFER (1 SECTOR)
- SIGNON:
- DB 13,10,'SUPER CP/M EDITOR',13,10
- ILGMSG:
- DB '" ILLEGAL IN THIS CONTEXT',13,10
- CNFMSG:
- DB 13,10,'CANNOT FIND "'
- ISFMSG:
- DB 13,10,'ITERATION STACK FAULT'
- BRKMSG:
- DB 13,10,'*BREAK*',13,10
- CRLF:
- MVI C,0DH ;PRINT CARRIAGE RETURN, LINE FEED
- CALL PCHAR
- MVI C,0AH
- PCHAR:
- PUSH D ;PRINT A CHARACTER
- PUSH H ;WITH FULL FORMATTING
- MOV A,C ;(EXPAND TABS AND CTRL CHARS)
- SUI 9
- JNZ PCHAR1 ;IF A TAB, WRITE SPACE INSTEAD
- MVI C,020H
- PCHAR1:
- SUI 1 ;GIVES FF & CARRY IF A TAB
- SBB A ;GIVES FF IF TAB, ZERO OTHERWISE
- MOV B,A ;SAVE FOR LATER
- LDA LINPOS ;CHECK CURRENT COLUMN NUMBER
- ANI 7 ;LOW 3 BITS ONLY
- CMA ;DERIVE SPACES TO NEXT TAB STOP
- ADI 8
- ANA B ;MASK WITH FLAG, (ZERO IF NO TAB)
- MOV B,A ;SAVE RESULT AS REPEAT COUNT
- MOV A,C ;LOOK AGAIN AT CHARACTER TO PRINT
- SUI 0DH ;CARRIAGE RETURN?
- JNZ PCHAR2
- STA LINPOS ;IF CARRIAGE RETURN, CLEAR COLUMN COUNT
- PCHAR2:
- PUSH B ;SAVE CHARACTER
- CALL CONOUT ;PRINT IT
- POP B ;GET IT BACK
- MOV A,C
- CPI 020H ;IF CONTROL CHARACTER, DON'T
- JC PCHAR3 ; INCREMENT COLUMN COUNTER
- LDA LINPOS
- INR A
- STA LINPOS
- PCHAR3:
- DCR B ;NOW TEST REPEAT COUNT (0 UNLESS TAB)
- JP PCHAR2 ;PRINT AGAIN IF NECESSARY
- POP H ;RESTORE REGS
- POP D
- RET ;AND EXIT
- CPHLDE:
- MOV A,H ;COMPARE (HL)::(DE)
- SUB D
- RNZ
- MOV A,L
- SUB E
- RET
- MESSBC:
- MOV H,B ;PRINT MESSAGE AT M(BC)
- MOV L,C ; FOR LENGTH (DE)
- MESSHL:
- MOV C,M
- INX H
- CALL PCHAR
- CALL BRKCHK
- MOV A,D
- ORA E
- RZ
- DCX D
- JMP MESSHL
- BRKCHK:
- CALL CSTS ;TEST FOR BREAK CHARACTER
- ORA A
- RZ
- CALL CONIN
- ORA A
- RNZ
- JMP BREAK
- INCCMD:
- LDA ITRLVL ;MOVE COMMAND POINTER TO NEXT COMMAND
- ORA A ;ONLY IF NO ITERATIONS ARE
- RNZ ;IN PROGRESS
- LHLD CMDFPT
- XCHG ;COMMAND FORWARD POINTER -> DE
- LHLD MAXMEM ;TOP OF RAM -> HL
- DCX H ;BACK OFF BY 1 BYTE
- SHLD CMDFPT ;CMDFPT WILL NOW POINT TO SECOND CHAR OF COMMAND
- PUSH H ;SAVE IT
- LXI H,CMDPTR ;GET POINTER TO END OF COMMAND
- MOV A,E ;SUBTRACT FORWARD POINTER TO
- SUB M ; GET LENGTH OF COMMAND STRING
- INX H
- MOV C,A
- MOV A,D
- SBB M
- MOV B,A
- JC INCCDN ;IF LENGTH GOES NEGATIVE, QUIT
- INX B ;NOW WE KNOW WE REALLY HAVE SOMETHING LEFT
- XCHG ;OLD FWD PNTR -> HL
- POP D ;NEW FWD PNTR -> DE
- CMDMOV:
- MOV A,M ;PACK DOWN USED-UP PARTS OF COMMAND
- STAX D ; TO MAKE MORE ROOM FOR TEXT
- DCX H
- DCX D
- DCX B
- MOV A,B
- ORA C
- JNZ CMDMOV
- PUSH D ;DE IS NOW NEW END POINTER
- INCCDN:
- POP H ;GET END POINTER
- INX H
- SHLD CMDPTR ;AND SAVE IT
- RET
- GETCMD:
- MVI C,'*' ;PROMPT FOR A COMMAND STRING
- CALL PCHAR
- LHLD MAXMEM ;STORED UPSIDE DOWN
- SHLD CMDPTR ; SO THAT COMMAND BUFFER
- DCX H ; GROWS TOWARDS TEXT BUFFER
- SHLD CMDFPT
- XRA A
- STA PRVCHR
- STA ITRLVL ;CLEAR PREVIOUS CHARACTER AND ITERATION LEVE
- GETCML:
- CALL CONIN ;LOOP, FETCHING CMD CHARS
- STA CURCHR ;SAVE AS CURRENT CHARACTER
- ORA A ;BREAK?
- JZ BREAK
- LHLD MAXMEM ;TOP OF RAM -> DE
- XCHG
- LHLD CMDPTR ;CMD STACK PTR -> HL
- CPI 012H ;CONTROL-R?
- JNZ RUBOUT
- CALL CRLF ;CONTROL-R MEANS RE-ECHO BUFFER
- CALL CPHLDE ;MAKE SURE THERE'S WHAT TO ECHO
- JZ GETCMD
- CNTLR:
- CALL CPHLDE ;DONE YET?
- JZ GETCML
- DCX D ;NO, FETCH NEXT CHARACTER
- LDAX D
- CPI 01BH ;CHANGE ESCAPE TO DOLLAR SIGN
- JNZ RNOTES
- MVI A,'$'
- RNOTES:
- MOV C,A ;PRINT CHARACTER
- CALL PCHAR
- JMP CNTLR ;AND GET SOME MORE
- RUBOUT:
- CPI 07FH ;WAS A RUBOUT TYPED?
- JNZ STCMCH
- CALL CPHLDE ;TEST FOR EMPTY BUFFER
- JZ CMDOVR
- MOV A,M ;GET LAST COMMAND CHARACTER
- CPI 01BH ;CONVERT ESCAPE TO DOLLAR SIGN
- JNZ DELNES
- MVI A,'$'
- DELNES:
- MOV C,A ;PRINT THE CHARACTER
- CALL PCHAR
- XRA A ;CLEAR 'PREVIOUS CHAR' FLAG
- STA PRVCHR
- LHLD CMDPTR ;BACK UP COMMAND POINTER
- INX H ; TO ACCOUNT FOR DELETED CHAR
- SHLD CMDPTR
- JMP GETCML ;LOOP BACK FOR NEXT INPUT
- CMDOVR:
- CALL CRLF ;DELETED PAST BEGINNING - SEND CRLF
- JMP GETCMD ;AND RE-PROMPT
- STCMCH:
- LHLD CMDPTR ;HERE TO STORE COMMAND CHAR
- LXI D,-20 ;MAKE SURE THERE'S ROOM
- DAD D
- XCHG
- LHLD TXTTOP
- CALL CPHLDE
- JC HVROOM
- MVI C,7 ;NO RAM LEFT - PRINT A BELL
- CALL PCHAR
- JMP GETCML ;AND HOPE NEXT CHAR IS RUBOUT
- HVROOM:
- LDA CURCHR ;GET CURRENT CHARACTER
- CPI 0DH ;TEST FOR CARRIAGE RETURN
- JNZ CHKALT
- LHLD CMDPTR ;STORE CARRIAGE RETURN
- DCX H
- SHLD CMDPTR
- MVI C,0DH
- MOV M,C ;IN COMMAND BUFFER
- CALL PCHAR ;ECHO IT
- MVI A,0AH ;ECHO AND STORE A LINEFEED BEHIND IT
- CHKALT:
- CPI 07DH ;CONVERT ALTMODE TO ESCAPE
- JNZ NOALT
- MVI A,01BH
- NOALT:
- STA CURCHR ;SAVE CURRENT CHAR
- CPI 01BH ;IS IT AN ESCAPE?
- MOV C,A ;IF ESCAPE, ECHO '$' INSTEAD
- JNZ ECHOCM
- MVI C,'$'
- ECHOCM:
- CALL PCHAR ;ECHO THE COMMAND CHARACTER
- LHLD CMDPTR ;BUMP COMMAND STACK POINTR
- DCX H
- SHLD CMDPTR
- LDA CURCHR ;STORE CURRENT CHAR IN COMMAND BUFFER
- MOV M,A
- CPI 01BH ;IF CURRENT IS ESCAPE, WHAT WAS PREVIOUS?
- JNZ SETPRV
- LDA PRVCHR ;IF PREV WAS ALSO ESCAPE, SEND CRLF
- CPI 01BH ;AND RETURN
- JZ CRLF
- SETPRV:
- MOV A,M ;MAKE CURRENT CHARACTER PREVIOUS CHAR
- STA PRVCHR
- JMP GETCML ;AND GO GET SOME MORE
- GETCDC:
- LHLD CMDPTR ;FETCH NEXT CHARACTER FROM COMMAND STRING
- XCHG ;END OF COMMAND -> DE
- LHLD CMDFPT ;CURRENT POINTER -> HL
- CALL CPHLDE ;COMMAND EXHAUSTED?
- CC GETCMD ;READ ANOTHER COMMAND IF NEEDED
- LXI H,CHRTYP ;INITIALIZE CHARACTER TYPE TO 'OTHER'
- MVI M,2
- LHLD CMDFPT
- MOV A,M ;GET COMMAND CHARACTER
- CPI 'A'
- JC GETCD1 ;SET FLAG FOR ALPHA OR NUMERIC
- CPI 'Z'+1 ;IF ALPHABETIC, CHRTYP=0
- JNC GETCDN
- LXI H,CHRTYP
- MVI M,0
- GETCD1:
- CPI '0' ;IF NUMERIC, CHRTYP=1
- JC GETCDN
- CPI '9'+1
- JNC GETCDN
- LXI H,CHRTYP
- MVI M,1
- GETCDN:
- LHLD CMDFPT ;ADVANCE COMMAND FORWARD PNTR
- DCX H
- SHLD CMDFPT
- RET
- GETNUM:
- LDA CURCMC ;PARSE A NUMBER FROM THE COMMAND
- CPI '-' ; STRING
- JNZ CKPLUS ;SET MINUS FLAG IF WE SEE A MINUS
- LXI H,MINUS
- MVI M,0FFH
- CALL GETCDC ;AND GET NEXT CHAR
- STA CURCMC ;INTO 'CURRENT CMD CHAR'
- JMP CNVNUM
- CKPLUS:
- CPI '+' ;SWALLOW A PLUS SIGN IF PRESENT
- JNZ CNVNUM
- CALL GETCDC
- STA CURCMC
- CNVNUM:
- LXI H,0
- CNVLUP:
- LDA CHRTYP ;TEST FOR NUMERIC
- CPI 1
- JNZ CNVDON ;QUIT IF NOT NUMERIC
- MOV D,H ;MULTIPLY HL BY 10
- MOV E,L
- DAD H
- DAD H
- DAD D
- DAD H
- LDA CURCMC ;CONVERT DIGIT TO NUMBER
- SUI '0'
- MOV E,A ;AND ADD IT TO HL
- MVI D,0
- DAD D
- PUSH H ;BUMP TO NEXT CMD CHAR
- CALL GETCDC
- POP H
- STA CURCMC ;MAKE IT CURRENT
- JMP CNVLUP ;AND GO CONVERT IT
- CNVDON:
- SHLD ITRCNT ;COMPLETED NUMBER BECOMES ITERATION COUNT
- LDA MINUS ;MINUS ZERO BECOMES MINUS ONE
- RRC
- RNC
- MOV A,H
- ORA L
- RNZ
- INX H
- SHLD ITRCNT
- RET ;DONE
- SKPLIN:
- LHLD ITRCNT ;SKIP FORWARD OR BACKWARD
- MOV B,H ; (ITRCNT) LINES
- MOV C,L ;(ITRCNT) -> BC
- LHLD TXTTOP ;END OF TEXT -> HL
- MVI A,TXTBUF AND 255 ;END=BEG? (BUFF EMPTY)
- SUB L
- MOV D,A
- MVI A,TXTBUF/256
- SBB H
- ORA D
- RZ ;IF EMPTY, QUIT
- XCHG ;END OF TEXT -> DE
- LHLD TXTPTR ;CURRENT POSN -> HL
- MOV A,B ;ITRCNT=0 MEANS BACKWARD SKIP
- ORA C
- INX B ;ANYWAY, WE ALWAYS WANT ITRCNT+1
- JZ SKPBAK ;TO ACCOUNT FOR CURRENT LINE
- LDA MINUS ;ITRCNT#0, SO CHECK SIGN FLAG
- RRC
- JNC SKPFWD ;TO DECIDE WHICH WAY TO SKIP
- SKPBAK:
- INX B ;BACKWARD SKIP - ITRCNT+2 -> BC
- CALL CPHLDE ;ARE WE AT END OF TEXT?
- JNZ SKPBA1
- LXI D,TXTBUF ;IS END ALSO BEGINNING?
- CALL CPHLDE
- JZ SKPBA1 ;IF SO, BACK OFF SO WE FIND EOF
- DCX H ; ON FIRST TEST
- SKPBA1:
- MVI D,0FFH ;SEARCH FOR EITHER FF (END OF TEXT)
- MVI E,0AH ;OR LINEFEED
- SKPBA2:
- DCX B ;DECREMENT ITERATION COUNT
- MOV A,B ;DONE YET?
- ORA C
- JZ SKPBA4 ;YUP
- SKPBA3:
- MOV A,M ;TEST NEXT CHARACTER
- CMP D ;END OF BUFFER?
- JZ SKPBDN
- CMP E ;LINEFEED?
- DCX H
- JNZ SKPBA3 ;BUMP POINTER AND TRY AGAIN
- JMP SKPBA2 ;FOUND ONE, MORE ITERATIONS?
- SKPBA4:
- INX H ;FOUND RIGHT NUMBER OF LF'S -
- SKPBDN:
- INX H ;CORRECT POINTER TO BE AFTER LAST LF
- RET
- SKPFWD:
- MVI D,0FFH ;HERE TO SKIP FORWARD - SEARCH FOR END OF BUFFER
- MVI E,0AH ;OR LINEFEED
- SKPFW1:
- DCX B ;DECREMENT ITERATION COUNT
- MOV A,B ;DONE YET?
- ORA C
- RZ
- SKPFW2:
- MOV A,M ;TEST NEXT CHARACTER
- CMP D ;END OF BUFFER?
- RZ
- CMP E ;LINEFEED
- INX H ;BUMP POINTER
- JNZ SKPFW2 ;TRY NEXT IF NO MATCH
- JMP SKPFW1 ;CHECK ITERATION COUNT IF MATCH
- SEARCH:
- LXI H,TARGLN ;SEARCH FOR A CHARACTER STRING
- MVI M,0 ;SET TARGET STRING LENGTH TO ZERO
- GTARGT:
- LXI B,TARGST ;COPY STRING FROM COMMAND BUFFER
- LHLD TARGLN ;INTO TARGET BUFFER AND UPDATE
- DAD B ; TARGET LENGTH
- PUSH H
- CALL GETCDC
- POP H
- MOV M,A
- SUI 01BH ;END COPY ON AN ESCAPE CHAR
- JZ DOSEAR ;AND GO DO THE SEARCH
- LXI H,TARGLN
- MOV A,M
- SUI 020H ;TARGET BUFFER OVERFLOW?
- JNC GTARGT ;NO
- INR M ;IF YES, IGNORE EXTRA CHARS
- JMP GTARGT
- DOSEAR:
- LHLD TXTPTR ;ACTUALLY PERFORM THE SEARCH
- XCHG ;TEXT POINTER -> DE
- DCX D ;BACK OFF ONE TO ACCOUNT FOR ALGORITHM
- SEARL1:
- LXI H,TARGST ;RESET TARGET STRING POINTER
- SEARL2:
- INX D ;FETCH CHARACTER FROM TEXT BUFFER
- LDAX D
- CPI 0FFH ;END OF BUFFER?
- JZ SEARER ;IF END, GIVE NOTICE
- CMP M ;COMPARE BUFFER TO TARGET
- JNZ SEARL2 ;NO MATCH, TRY NEXT
- MOV B,D ;MATCHED FIRST CHAR, SAVE ITS POSN
- MOV C,E
- SEARL3:
- INX H ;SEE IF REST OF STRING MATCHES
- INX D ; BUMP BOTH TARGET AND BUFFER
- LDAX D ;FETCH NEXT FROM BUFFER
- CMP M ;MATCH?
- JZ SEARL3 ;YUP, KEEP GOING
- MOV A,M ;NO MATCH, BUT MAYBE IT'S A 'DONT CARE'
- CPI 07CH ;'OR BAR' IS DONT CARE CHAR
- JZ SEARL3
- CPI 01BH ;NEITHER MATCH NOR DONT CARE, BUT WE MAY BE DONE
- MOV D,B ;PREPARE FOR RETRY BY RESTORING
- MOV E,C ;BUFFER POINTER
- RZ ;LAST TARGET WAS ESCAPE: WE'RE DONE
- LDAX D ;TEST FOR END OF BUFFER
- CPI 0FFH
- JZ SEARER ;IF END, ERROR
- JMP SEARL1 ;ELSE RESTORE TARGET PTR AND CONTINUE
- SEARER:
- STC ;NOT FOUND - SET CARRY FOR ERROR
- RET
- NOFIND:
- LXI B,CNFMSG ;SAY 'CAN NOT FIND...'
- LXI D,0EH
- CALL MESSBC
- LDA TARGLN ;ECHO TARGET STRING AS WELL
- ORA A
- JZ ENDQUO
- LXI B,TARGST
- MOV E,A
- DCR E ;DECREMENT LENGTH TO AVOID TERMINATING ESCAPE
- MVI D,0
- CALL MESSBC
- ENDQUO:
- MVI C,022H ;TERMINATING QUOTE AND CRLF
- CALL CONOUT
- CALL CRLF
- JMP BREAK
- PACK:
- LHLD SPLBEG ;PACK DOWN TEXT BUFFER AFTER
- XCHG ; A DELETE-TYPE OPERATION
- LHLD TXTPTR ;BEG. OF SPLIT -> DE; CURR POS. -> HL
- MOV A,E ;IF EQUAL, NO PACK REQUIRED
- SUB L
- MOV C,A
- MOV A,D
- SBB H
- ORA C
- RZ
- LXI H,SPLEND ;OTHERWISE, LENGTH OF SPLIT -> BC
- MOV A,M
- SUB E
- INX H
- MOV C,A
- MOV A,M
- SBB D
- MOV B,A
- JC PACKDN ;IF SPLIT LENGTH=0, QUIT
- INX B ;ADJUST LENGTH
- LHLD SPLBEG ;START OF SPLIT -> DE
- XCHG
- LHLD TXTPTR ;CURRENT POINTER -> HL
- PACKLP:
- LDAX D ;PACK A CHAR FROM SPLIT
- MOV M,A ;TOWARDS CURRENT POINTER
- INX D ;BUMP POINTERS
- INX H
- DCX B ;MORE TO PACK?
- MOV A,B
- ORA C
- JNZ PACKLP
- DCX H ;SET END OF TEXT MARKER AT NEW END OF BUFFER
- MVI M,0FFH
- SHLD TXTTOP ;STORE NEW END VALUE
- JMP INCCMD ;GO REPACK COMMAND BUFFER
- PACKDN:
- LHLD TXTTOP ;DELETE ONLY COVERED ONE CHAR
- DCX H ;SO JUST RESET END OF BUFFER
- SHLD TXTTOP
- MVI M,0FFH ;AND MARK IT
- JMP INCCMD ;AND GO PACK COMMAND BUFFER
- MAIN:
- LXI SP,STACK ;MAIN PROGRAM STARTS HERE
- LXI B,SIGNON ;PRINT SIGNON MESSAGE
- LXI D,014H
- CALL MESSBC
- CALL GETTOP ;SET TOP OF RAM
- MOV L,A
- MOV H,B
- SHLD MAXMEM
- LXI H,-1
- SHLD FENCE ;MARK ENDS OF BUFFER
- LXI H,TXTBUF
- SHLD TXTPTR ;INITIALIZE CURRENT POINTER
- SHLD TXTTOP ;AND END POINTER
- CMDLUP:
- CALL GETCMD ;GET FIRST COMMAND STRING
- FOREVR:
- CALL NXTCMD ;PROCESS COMMANDS FOREVER
- JMP FOREVR
- NXTCMD:
- LHLD TXTPTR ;MAKE SPLIT POINTERS MATCH
- SHLD SPLBEG ;ACTUAL BUFFER POINTERS
- LHLD TXTTOP
- SHLD SPLEND
- LXI H,MINUS ;CLEAR MINUS FLAG
- MVI M,0
- LXI H,1 ;DEFAULT TO ONE ITERATION
- SHLD ITRCNT
- CALL GETCDC ;GET NEXT CHAR FROM COMMAND STRING
- STA CURCMC ;SAVE IT
- CPI '-' ;IF + OR -,
- JZ CPUSH ; THEN GET A NUMBER
- CPI '+'
- JZ CPUSH
- LDA CHRTYP ;IF NUMERIC, ALSO GET A NUMBER
- CPI 1
- JNZ NOTNUM
- CPUSH:
- CALL GETNUM ;GET NUMBER INTO ITRCNT
- NOTNUM:
- LDA CURCMC ;GET CURRENT CHARACTER
- CPI '<' ;START OF ITERATION?
- LXI H,ITRLVL ;PREPARE TO STACK AN ITERATION
- MVI B,0
- JNZ CPOP
- INR M ;INCREMENT ITERATION STACK COUNT
- MOV C,M ;AND FETCH IT
- MVI A,8 ;STACK OVERFLOW? (8 LEVELS MAX.)
- CMP M
- JNC PUSHIT
- LXI B,ISFMSG ;GIVE STACK FAULT MESSAGE
- LXI D,016H
- CALL MESSBC
- JMP BREAK ;AND FAKE A BREAK
- PUSHIT:
- LHLD CMDFPT ;PUT COMMAND FORWARD POINTER ONTO ITS STACK
- XCHG
- LXI H,ITRPST
- DAD B
- DAD B
- MOV M,E
- INX H
- MOV M,D
- LHLD ITRCNT ;PUT ITERATION COUNT ONTO ITS STACK
- XCHG
- LXI H,ITRCST
- DAD B
- DAD B
- MOV M,E
- INX H
- MOV M,D
- RET ;GO BACK FOR NEXT COMMAND
- CPOP:
- CPI '>' ;END OF ITERATION?
- JNZ DISPAT
- MOV C,M ;CHECK ITERATION LEVEL
- MOV A,C
- ORA A ;IF ZERO, IGNORE
- JZ DISPAT
- LXI H,ITRCST ;POINT TO ITERATION COUNT ON
- DAD B ; CURRENT LEVEL
- DAD B
- MOV A,M
- SUI 1 ;DECREMENT IT
- MOV M,A
- INX H
- MOV A,M
- SBI 0
- MOV M,A
- DCX H ;CURRENT LEVEL'S COUNT=0?
- ORA M
- JZ DRPSTK ;IF YES, DROP ITERATION STACKS
- LXI H,ITRPST ;OTHERWISE, RESTORE COMMAND PTR
- DAD B ; FOR THIS LEVEL
- DAD B
- MOV E,M
- INX H
- MOV D,M
- XCHG
- SHLD CMDFPT
- RET
- DRPSTK:
- LXI H,ITRLVL ;DECREMENT ITERATION LEVEL
- DCR M
- RET
- DISPAT: ;****COMMAND DISPATCHER***
- LDA CHRTYP ;IF WE GET HERE WITH OTHER
- ORA A ;THAN A LETTER, IT'S AN ERROR
- JNZ CMDERR
- LDA CURCMC ;CONVERT LETTER TO DISPATCH
- SUI 'A' ; TABLE INDEX
- MOV L,A
- MVI H,0
- DAD H
- LXI D,DSPTBL ;INDEX TO RIGHT TABLE ENTRY
- DAD D
- MOV E,M
- INX H
- MOV D,M
- XCHG
- PCHL ;AND DISPATCH TO IT
- ACMD: ;*****APPEND COMMAND*****
- LHLD ITRCNT
- MOV B,H
- MOV C,L
- APPLIM:
- LHLD CMDPTR
- LXI D,-40
- DAD D
- XCHG
- LHLD TXTTOP
- APPEND:
- CALL CPHLDE
- JNC FLGEND
- ACMLUP:
- CALL GETBYT
- ORA A
- JZ ACMLUP
- CPI 07FH
- JZ ACMLUP
- CPI 01AH
- JZ FLGEND
- MOV M,A
- INX H
- CPI 0AH
- JNZ APPEND
- DCX B
- MOV A,B
- ORA C
- JNZ APPEND
- FLGEND:
- SHLD TXTTOP
- MVI M,0FFH
- RET
- BCMD:
- LXI H,TXTBUF
- SHLD TXTPTR
- RET
- CCMD:
- CALL MOVPTR
- SHLD TXTPTR
- RET
- MOVPTR:
- LDA MINUS
- RRC
- LHLD TXTPTR
- XCHG
- LHLD ITRCNT
- JNC CPLUS
- MOV A,E
- SUB L
- MOV E,A
- MOV A,D
- SBB H
- MOV D,A
- LXI H,TXTBUF
- CALL CPHLDE
- RNC
- XCHG
- RET
- CPLUS:
- DAD D
- XCHG
- LHLD TXTTOP
- CALL CPHLDE
- RC
- XCHG
- RET
- DCMD:
- CALL MOVPTR
- LDA MINUS
- RRC
- XCHG
- LXI H,TXTPTR
- JC DELSET
- LXI H,SPLBEG
- DELSET:
- MOV M,E
- INX H
- MOV M,D
- JMP PACK
- ECMD:
- LXI H,TXTBUF
- ECMLUP:
- MOV A,M
- CPI 0FFH
- JZ CPREST
- MOV C,A
- CALL PUTBYT
- INX H
- JMP ECMLUP
- CPREST:
- CALL GETBYT
- CPI 01AH
- MOV C,A
- PUSH PSW
- CALL PUTBYT
- POP PSW
- JNZ CPREST
- MVI C,01AH
- CALL PUTBYT
- LDA SWFLG
- ORA A
- JNZ 0
- LXI D,IFCB
- PUSH D
- MVI C,010H
- CALL 5
- POP H
- LXI D,IFCBRN
- PUSH D
- LXI B,9
- CALL MOVE
- XCHG
- MVI M,'B'
- INX H
- MVI M,'A'
- INX H
- MVI M,'K'
- INX H
- LXI B,015H
- CALL FILL
- POP D
- MVI C,013H
- CALL 5
- LXI D,IFCB
- MVI C,017H
- CALL 5
- LXI D,OFCB
- MVI C,017H
- CALL 5
- RST 0
- FCMD:
- CALL SEARCH
- JC NOFIND
- FCMD1:
- LHLD TARGLN
- DAD D
- SHLD TXTPTR
- RET
- ICMD:
- CALL GETCDC
- CPI 01BH
- JZ PACK
- LHLD CMDFPT
- INX H
- SHLD CMDFPT
- ICMD1:
- CALL INCCMD
- LXI B,-20
- LHLD CMDPTR
- DAD B
- XCHG
- LHLD SPLEND
- CALL CPHLDE
- JNC BREAK
- XCHG
- PUSH H
- LXI H,SPLBEG
- MOV A,E
- SUB M
- MOV C,A
- INX H
- MOV A,D
- SBB M
- MOV B,A
- POP H
- JC L09CE
- PUSH D
- PUSH H
- LHLD CMDFPT
- LXI D,0
- GTISIZ:
- MOV A,M
- CPI 01BH
- JZ GOTSIZ
- INX D
- DCX H
- JMP GTISIZ
- GOTSIZ:
- LHLD TXTPTR
- DAD D
- DAD B
- INX B
- XCHG
- POP H
- CALL CPHLDE
- JNC L09B5
- XCHG
- L09B5:
- POP H
- CALL CPHLDE
- JNC L09D1
- XCHG
- SHLD TXTTOP
- SHLD SPLEND
- L09C3:
- LDAX D
- MOV M,A
- DCX D
- DCX H
- DCX B
- MOV A,B
- ORA C
- JNZ L09C3
- INX H
- L09CE:
- SHLD SPLBEG
- L09D1:
- LHLD TXTPTR
- XCHG
- LHLD SPLBEG
- MOV A,L
- SUB E
- MOV C,A
- MOV A,H
- SBB D
- MOV B,A
- LHLD CMDFPT
- L09E1:
- MOV A,M
- CPI 01BH
- DCX H
- JZ L09F1
- STAX D
- INX D
- DCX B
- MOV A,B
- ORA C
- JNZ L09E1
- MOV A,M
- L09F1:
- SHLD CMDFPT
- XCHG
- SHLD TXTPTR
- CPI 01BH
- JNZ ICMD1
- CALL INCCMD
- JMP PACK
- KCMD:
- CALL SKPLIN
- SHLD SPLBEG
- XCHG
- LHLD TXTPTR
- CALL CPHLDE
- JC PACK
- SHLD SPLBEG
- XCHG
- SHLD TXTPTR
- JMP PACK
- LCMD:
- CALL SKPLIN
- SHLD TXTPTR
- RET
- NCMD:
- CALL SEARCH
- NCMD1:
- JNC FCMD1
- LXI D,-120
- LHLD CMDPTR
- DAD D
- XCHG
- LHLD TXTTOP
- CALL CPHLDE
- JC NAPP
- LXI H,032H
- SHLD ITRCNT
- CALL WCMD
- NAPP:
- LHLD TXTTOP
- PUSH H
- LXI B,1
- CALL APPLIM
- POP H
- CPI 01AH
- JZ NOFIND
- SHLD TXTPTR
- LHLD TXTTOP
- SHLD SPLEND
- CALL DOSEAR
- JMP NCMD1
- QCMD:
- LXI D,OFCB
- MVI C,010H
- CALL 5
- LXI D,OFCB
- MVI C,013H
- CALL 5
- JMP BYEBYE
- SCMD:
- CALL SEARCH
- JC NOFIND
- LHLD TARGLN
- DAD D
- SHLD SPLBEG
- XCHG
- SHLD TXTPTR
- JMP ICMD
- TCMD:
- CALL SKPLIN
- XCHG
- LHLD TXTPTR
- MOV A,L
- SUB E
- MOV L,A
- MOV A,H
- SBB D
- MOV H,A
- XCHG
- JNC TCMD1
- LHLD TXTPTR
- MOV A,D
- CMA
- MOV D,A
- MOV A,E
- CMA
- MOV E,A
- INX D
- TCMD1:
- MOV B,H
- MOV C,L
- MOV A,D
- ORA E
- DCX D
- JNZ MESSBC
- RET
- WCMD:
- LXI H,MINUS
- MVI M,0
- LXI H,TXTBUF
- SHLD TXTPTR
- CALL SKPLIN
- SHLD SPLBEG
- XCHG
- LXI H,TXTBUF
- WCMDL:
- CALL CPHLDE
- JNC PACK
- MOV C,M
- INX H
- CALL PUTBYT
- JMP WCMDL
- ZCMD:
- LHLD TXTTOP
- SHLD TXTPTR
- RET
- DSPTBL:
- DW ACMD
- DW BCMD
- DW CCMD
- DW DCMD
- DW ECMD
- DW FCMD
- DW CMDERR
- DW CMDERR
- DW ICMD
- DW CMDERR
- DW KCMD
- DW LCMD
- DW CMDERR
- DW NCMD
- DW CMDERR
- DW CMDERR
- DW QCMD
- DW CMDERR
- DW SCMD
- DW TCMD
- DW CMDERR
- DW CMDERR
- DW WCMD
- DW CMDERR
- DW CMDERR
- DW ZCMD
- CMDERR:
- LDA CURCMC
- CPI ' '+1
- RC
- CALL CRLF
- MVI C,'"'
- CALL CONOUT
- LXI H,CURCMC
- MOV C,M
- CALL PCHAR
- LXI B,ILGMSG
- LXI D,1AH
- BRKOUT:
- LXI SP,STACK
- CALL MESSBC
- JMP CMDLUP
- TARGLN:
- DW 0
- BREAK:
- LXI B,BRKMSG
- LXI D,0AH
- JMP BRKOUT
- DS 50
- STACK EQU $
- CMDPTR:
- DW 0
- TXTPTR:
- DW 0
- TXTTOP:
- DW 0
- SPLBEG:
- DW 0
- SPLEND:
- DW 0
- CMDFPT:
- DW 0
- MAXMEM:
- DW 0
- CURCMC:
- DB 0
- CHRTYP:
- DB 0
- ITRCNT:
- DW 0
- MINUS:
- DB 0
- LINPOS:
- DS 1
- SWFLG:
- DS 1
- EOFFLG:
- DS 1
- ITRLVL:
- DS 1
- TARGST:
- DS 31
- ITRPST:
- DS 16
- ITRCST:
- DS 16
- L0BC3:
- DS 2
- CURCHR:
- DS 1
- PRVCHR:
- DS 1
- FENCE:
- DS 1
- TXTBUF EQU $
- END
-
-