.title k11edi Command line editing .ident /3.52/ ; 18-Jul-86 12:00:29 Brian Nelson ; ; This code is used (currently) for the RSTS/E Command Line ; Editor (CLE.RTS) written by the above author, and for 5.1 ; of MINITAB. The encryption calls are for the RSTS/E CLE. .iif ndf, $MINITAB, $MINITAB = 0 .if eq ,$Minitab .if ndf, K11INC .ift .include /IN:K11MAC.MAC/ .endc .endc .enabl gbl .psect rwdata ,rw,d,lcl,rel,con .psect CLECTX ,rw,d,gbl,rel,con curpos: .word edipos curlen: .word edilen curcmd: .word edicmd maxsiz: .word edisiz clests: .word edists enckey: .word $enckey deckey: .word $deckey .if ne ,$Minitab .ift .macro dump v mov v ,-(sp) call o$dump .globl o$dump .endm dump CR = 15 LF = 12 LN$MAX = 80. LN$CNT = 3 ER$EOF == -1 $lastl: .blkb <*LN$CNT>+2 lastli: .word $lastl ,$lastl+<1*>,$lastl+<2*>,0 lastcn: .word LN$CNT edipos: .word 0 edilen: .word 0 edicmd: .word -1 edists: .word 0 edikey: .word 0 edisiz: .word LN$MAX $enckey: $deckey: TTY = 0 .endc ; If NE, $Minitab .psect $pdata ,ro,d,lcl,rel,con .psect $code ,i,ro,i,lcl,rel FALSE = 0 TRUE = 1 IN$MODE = 1 SET$VT1 = 2 $DEBUG = 0 .iif ndf, $DEBUG, $DEBUG = 0 .sbttl Define macros .if ne ,$MINITAB .ift .MACRO ENCRYPT txt,key .ENDM ENCRYPT .MACRO DECRYPT txt,key .ENDM DECRYPT .MACRO DEBUG a,b,c .ENDM DEBUG .MACRO STRCPY dst,src mov src ,-(sp) mov dst ,-(sp) jsr pc ,strcpy .ENDM STRCPY .MACRO STRLEN src mov src ,-(sp) call strlen .ENDM STRLEN .MACRO SCAN ch,str mov str ,-(sp) clr -(sp) bisb ch ,@sp call scanch .ENDM SCAN .MACRO SAVE list .if b , .ift SAVE .iff .irp x, mov x,-(sp) .endr .endc .ENDM SAVE .MACRO UNSAVE list .if b , .ift UNSAVE .iff .irp x, mov (sp)+,x .endr .endc .ENDM UNSAVE .MACRO GLOBAL LIST .GLOBL LIST .ENDM GLOBAL .iff ; Kermit or CLE .MACRO ENCRYPT txt,key mov key ,-(sp) mov txt ,-(sp) call ENCRYPT .endm ENCRYPT .MACRO DECRYPT txt,key mov key ,-(sp) mov txt ,-(sp) call DECRYPT .endm DECRYPT .MACRO DEBUG txt,sts=1,docr=1 .if ne ,$DEBUG .if ne ,sts .save .psect $pdata $$ = . .if b , .ift .byte 15,12,0 .iff .asciz @txt@ .endc .even .restore mov #$$ ,-(sp) ; dump the text next please CALL mout ; to the terminal .globl mout ; perhaps .if nb , .ift .iif nb,docr, message .endc .endc .endc .endm DEBUG .endc ; if NE, $Minitab .macro WRTALL arg ; IO.WAL for an .asciz string mov arg ,-(sp) ; Pass the address call wrtall ; Do it GLOBAL ; Insure globalized .endm WRTALL ; Done .enabl lsb Kbredi::.iif ne, $MINITAB, mov r1,-(sp); .iif ne, $MINITAB, mov r5,-(sp); SAVE ; Save cmpb vttype ,#TTY ; Not a VT100 or VT2xx? bne 10$ ; No, try editing .if ne ,$MINITAB ; Minitab today? .ift ; Yes sec ; Just set carry and exit .iff ; Kermit or CLE WRTALL @r5 ; Prompt CALLS kbread ,<2(r5)> ; Hardcopy, use vanilla reads .endc ; All done br 100$ ; Exit 10$: WRTALL #$cr ; WRTALL @r5 ; bit #SET$VT1,@clests ; Insure terminal in VT100 mode bne 15$ ; Already did it WRTALL #$setvt1 ; Not done, do so bis #SET$VT1,@clests ; Flag as having been done 15$: clr @curpos ; Assume at start of the line. clr @curlen ; No length mov 2(r5) ,r4 ; Buffer address clrb @r4 ; Insure starting with .ASCIZ 20$: CALL read1ch ; Read one character now mov r0 ,r3 ; Any data persent? beq 90$ ; Yes, treat as a control Z SCAN r3 ,#scanlst ; Look for a match asl r0 ; And dispatch jsr pc ,@scandsp(r0) ; Do it bcs 20$ ; Not done .iif ne, $MINITAB, mov r1,r0 ; br 100$ ; Done ; 90$: mov #ER$EOF ,r0 ; Error, return END_OF_FILE clr r1 ; And no data 100$: UNSAVE ; Exit .iif ne, $MINITAB, mov (sp)+,r5; .iif ne, $MINITAB, mov (sp)+,r1; return .dsabl lsb .save .psect $pdata scanlst:.byte 'H&37 ,'E&37 ,'B&37 ,'U&37 ,'Z&37 ,CR ,LF .byte 'I&37 ,177 ,33 ,233 ,'R&37 ,'X&37 ,'C&37 .byte 'A&37 .byte 0 .even scandsp:.word INSCH .word SOL ,EOL ,PREV ,CTRLU ,EOF ,NOOP ,DONE .word NOOP ,DORUB ,DOESC ,DO220 ,RETYPE ,CANTYP ,CTRLC .word TOGGLE esclst: .byte 'A&137 ,'B&137 ,'C&137 ,'D&137 ,0 .even escdsp: .word NOOP .word PREV ,NEXT ,RIGHT ,LEFT $cc: .asciz /^C/ $cz: .asciz /^Z/ $bs: .byte 'H&37,0 $cr: .byte 15,0 $right: .asciz <33>/[C/ $left: .asciz <33>/[D/ $save: .asciz <33>/7/ $resto: .asciz <33>/8/ $ceol: .asciz <33>/[K/ $crlf: .byte CR,LF,0 $rrub: .byte 10,40,10,0 $setvt: .byte 33,'< .even .restore Doesc: DEBUG ; ... CALL read1ch ; Get next in esc seq Do220: DEBUG ; You know CALL read1ch ; Ditto mov r0 ,r3 ; Get the data beq 90$ ; Error Exit SCAN r3 ,#esclst ; Process the character asl r0 ; Convert to word offset jsr pc ,@escdsp(r0) ; Do it br 100$ ; Ok 90$: sec ; Failure on the READ 100$: return ; And Exit Noop: DEBUG ; ... sec ; Ignore return ; And Exit Insch: DEBUG ,FALSE ; ... sub #200 ,sp ; A temp buffer mov sp ,r2 ; A pointer to it tst r3 ; Null? beq 100$ ; Ignore cmp @curlen ,@maxsiz ; Too many chars? blo 10$ ; No CALL done ; Yes, exit br 100$ ; Bye 10$: inc @curlen ; Save this mov @curpos ,r1 ; Get the offset into line add r4 ,r1 ; Where to stuff the data tstb @r1 ; Already at end of line? beq 20$ ; Yes, we have the stop to stuff it bit #IN$MODE,@clests ; Insert or overstrike? bne 15$ ; Insert movb r3 ,(r1)+ ; Overstrike br 30$ ; Exit 15$: STRCPY r2 ,r1 ; No, so save the data now movb r3 ,(r1)+ ; And insert the new character STRCPY r1 ,r2 ; And put the trailing data back in. br 30$ ; Now for the echoing 20$: movb r3 ,(r1)+ ; Already at eol, insert clrb @r1 ; And insure .ASCIZ dec r1 ; ... WRTALL r1 ; Echo br 90$ ; Exit 30$: WRTALL #$save ; Save cursor pos dec r1 ; Back to to the new character WRTALL r1 ; Dump the data WRTALL #$restore ; Put the cursor back now WRTALL #$right ; Move over on the display 90$: inc @curpos ; Move over one 100$: add #200 ,sp ; Pop buffer sec ; Not done return ; Exit .sbttl More line editing routines ; SOL Move to start of line (Control H) Sol: DEBUG ; ... tst @curpos ; Stop when at position 0 ble 100$ ; Done WRTALL #$bs ; Move dec @curpos ; Fix position br sol ; Next please 100$: clr @curpos ; Insure correct sec ; Not done return ; Exit ; EOL Move to End of Line, Control E Eol: DEBUG ; ... STRLEN r4 ; Find string length 10$: cmp @curpos ,r0 ; End yet? bhis 100$ ; Yes WRTALL #$right ; No inc @curpos ; Fix this br 10$ ; Next 100$: sec ; Not done return ; Exit Gotoeol:STRLEN r4 ; Find string length 10$: cmp @curpos ,r0 ; End yet? bhis 100$ ; Yes inc @curpos ; Fix this br 10$ ; Next 100$: return ; Exit ; EOF Control Z on input .enabl lsb ; Temp Ctrlc: DEBUG ; ... WRTALL #$cc ; Echo a control C br 100$ ; Common exit now Eof: DEBUG ; ... WRTALL #$cz ; Echo a control Z .if ne ,$MINITAB ; WRTALL #$crlf ; .endc ; 100$: mov #ER$EOF ,r0 ; Control Z clr r1 ; And return byte count of zero clc ; All done return ; Exit .dsabl lsb ; Done .enabl lsb .sbttl Carriage return (actually LF) processing ; Done. CR on input, store new line and bubble previous ones back Done: mov r5 ,-(sp) ; A scratch register we need DEBUG ; ... WRTALL #$crlf ; STRLEN r4 ; Get byte count (we have CR or LF) mov r0 ,r1 ; Return it beq 90$ ; Nothing there, don't copy it. clr r2 ; The index mov lastcnt ,r3 ; Number of lines to do 10$: mov lastli(r2),r0 ; Look to find a free spot. tstb @r0 ; Empty? beq 60$ ; Yes add #2 ,r2 ; No, keep looking sob r3 ,10$ ; .... ; No room for command line. clr r2 ; The index mov r4 ,-(sp) ; Save it mov lastcnt ,r3 ; Number of lines to do dec r3 ; ... asl r3 ; See if this is same as last mov lastli(r3),r5 ; Current address inc r5 ; Skip the length mov r5 ,-(sp) ; Save DECRYPT r5,deckey ; Undo the old line STRLEN r4 ; Length cmpb -1(r5) ,r0 ; Same length bne 20$ ; No 15$: cmpb (r4)+ ,(r5)+ ; Check for string equality bne 20$ ; Not the same sob r0 ,15$ ; Same, check next 20$: mov (sp)+ ,r5 ; Restore old text pointer mov (sp)+ ,r4 ; Restore the current pointer ENCRYPT r5,enckey ; Restore the data asr r3 ; Restore r3 tst r0 ; Same ? bne 30$ ; No mov r3 ,@curcmd ; Yes, save index br 100$ ; Exit 30$: 40$: mov lastli(r2),r0 ; Counted string format mov lastli+2(r2),r1 ; Again movb (r1) ,(r0)+ ; Copy the string length beq 55$ ; Can't happen, but may as well check clr r5 ; Counter for the copy operation bisb (r1)+ ,r5 ; Copy the byte count 50$: movb (r1)+ ,(r0)+ ; Copy the string now sob r5 ,50$ ; Next 55$: add #2 ,r2 ; Move up sob r3 ,40$ ; Next please ; 60$: mov lastli(r2),r1 ; Copy the line at last STRLEN r4 ; Get the line length mov @maxsiz ,r3 ; For padding with spaces movb r0 ,(r1)+ ; Copy the length beq 80$ ; Nothing mov r4 ,r5 ; Source string mov r1 ,-(sp) ; Save text address 70$: movb (r5)+ ,(r1)+ ; Copy the data now dec r3 ; Keep track of remaining space beq 75$ ; No room left sob r0 ,70$ ; Next please 74$: movb #40 ,(r1)+ ; Now space fill the line sob r3 ,74$ ; Next please 75$: mov (sp)+ ,r1 ; Restore text address ENCRYPT r1,enckey ; Encode it 80$: asr r2 ; Set 'Current' Command index mov r2 ,@curcmd ; And save it br 100$ ; Exit 90$: movb #CR ,@r4 ; Return only a carriage return clrb 1(r4) ; .ASCIZ 100$: STRLEN r4 ; Get line length mov r0 ,r1 ; Where to return it. clr r0 ; No errors mov (sp)+ ,r5 ; Restore r5 clc ; All done return ; Exit .dsabl lsb ; PREV: Recall previous command line, UP-Arrow Key. Prev: DEBUG ; ... mov r5 ,-(sp) ; Save it 10$: mov @curcmd ,r2 ; Current command number blt 100$ ; Never been here. CALL sol ; Back up WRTALL #$cr ; Start of line WRTALL #$ceol ; Clear WRTALL @r5 ; Prompt asl r2 ; We want addresses today mov lastli(r2),r2 ; At last tstb @r2 ; Anything to copy? bne 20$ ; Yes dec @curcmd ; No, back up again bge 10$ ; Ok clr @curcmd ; Reached the end br 100$ ; And exit 20$: clrb @r4 ; TO be safe clr r3 ; Get length next bisb (r2)+ ,r3 ; Do it beq 50$ ; Nothing? mov @maxsiz ,r0 ; Copy all for DES types mov r4 ,r5 ; A copy of the destination 30$: movb (r2)+ ,(r5)+ ; Copy it sob r0 ,30$ ; Next please DECRYPT r4,deckey ; Decode the data add r4 ,r3 ; Point to the real end of data clrb @r3 ; Insure .asciz WRTALL r4 ; Echo it 50$: CALL gotoeol ; Move to end of the line STRLEN r4 ; Get length mov r0 ,@curlen ; And save it tst @curcmd ; Check for underflow ble 100$ ; Yes, exit dec @curcmd ; No, backup now. br 100$ ; Exit 90$: clrb @r4 ; Nothing, kill the buffer 100$: sec ; Not done yet mov (sp)+ ,r5 ; Restore this return ; Exit ; Control U: Erase entire line Ctrlu: DEBUG ; ... CALL sol ; Move to start of the line WRTALL #$ceol ; Erase to the end of the line clrb @r4 ; No data left over clr @curlen ; No length sec ; Not done return ; Exit Right: DEBUG ; ... STRLEN r4 ; Get current length of the line cmp @curpos ,r0 ; Already at EOL? bhis 100$ ; Yes inc @curpos ; No, move over WRTALL #$right ; Simple to do. 100$: sec ; Not done return ; Exit .sbttl Rubouts and move left ; DORUB: Erase character Dorub: DEBUG ,FALSE ; ... sub #200 ,sp ; Allocate a buffer again mov sp ,r3 ; And a pointer to such. tstb @r4 ; Is there ANYTHING in the line? beq 100$ ; No, it's a NO-OP tst @curpos ; Already at SOL (start of line)? bgt 10$ ; No clr @curpos ; Insure correct position clr @curlen ; Save this br 20$ ; Off to common code 10$: mov r4 ,r2 ; See if at eoln add @curpos ,r2 ; Compute address dec @curpos ; Correct offset now dec @curlen ; Fix this up movb @r2 ,-(sp) ; Get current beq 20$ ; Nothing to do WRTALL #$LEFT ; Go back one please 20$: mov r4 ,r2 ; And move down add @curpos ,r2 ; Point to CURRENT character mov r2 ,r1 ; Again inc r1 ; Next position please STRCPY r3 ,r1 ; Make a temporary copy of the data STRCPY r2 ,r3 ; Move it down tstb (sp)+ ; Were we already at EOL? bne 30$ ; No WRTALL #$rrub ; Use simple style BS SP BS if EOL br 100$ ; Exit 30$: WRTALL #$save ; Save cursor position WRTALL #$ceol ; Erase to EOL WRTALL r2 ; Dump buffer WRTALL #$restore ; And go back 100$: add #200 ,sp ; Pop local buffer and Exit sec ; Not done return ; Exit ; Left: Move left one character Left: DEBUG ; ... tst @curpos ; Can we back up ? ble 100$ ; No dec @curpos ; Yes, backup a bit WRTALL #$left ; And do so. 100$: sec ; Not done return ; Exit .sbttl Command recall and control R processing Next: DEBUG ; ... mov r5 ,-(sp) ; Save mov curcmd ,r2 ; Point to CURCMD tst @r2 ; Current command number blt 100$ ; Never been here. mov lastcnt ,-(sp) ; Get the recall buffer count dec (sp) ; ... cmp @r2 ,(sp)+ ; Can we move up? bge 100$ ; No inc @r2 ; Yes, move up. CALL sol ; Back up WRTALL #$cr ; Start of line WRTALL #$ceol ; Clear WRTALL @r5 ; Prompt mov @r2 ,r2 ; Copy it. asl r2 ; We want addresses today mov lastli(r2),r2 ; At last tstb @r2 ; Anything to copy? beq 90$ ; No ; clrb @r4 ; TO be safe clr r3 ; Get length next bisb (r2)+ ,r3 ; Do it mov @maxsiz ,r0 ; Copy ALL for DES type routines mov r4 ,r5 ; A copy of the destination 30$: movb (r2)+ ,(r5)+ ; Copy it sob r0 ,30$ ; Next please DECRYPT r4,deckey ; Decode the data add r4 ,r3 ; Point to the real end of data clrb @r3 ; And force to .ASCIZ WRTALL r4 ; Dump the data call gotoeol ; Fix internal pointers STRLEN r4 ; Get last line length mov r0 ,@curlen ; And save it mov lastcnt ,-(sp) ; Get the recall buffer count dec (sp) ; ... cmp @curcmd ,(sp)+ ; Poised at the last command? bne 100$ ; No dec @curcmd ; Fix so PREV works correctly. br 100$ ; Exit 90$: clrb @r4 ; Nothing, kill the buffer 100$: sec ; Not done yet mov (sp)+ ,r5 ; Restore return ; Exit Retype: DEBUG ; ... WRTALL #$cr ; Start of line WRTALL #$ceol ; Clear WRTALL @r5 ; Prompt WRTALL r4 ; Dump the buffer WRTALL #$cr ; Back up again STRLEN @r5 ; Get a new poistion now add @curpos ,r0 ; Get to correct position beq 100$ ; Nothing (?) 10$: WRTALL #$right ; Move over sob r0 ,10$ ; Simple 100$: sec ; Not yet done return ; Exit Cantyp: call clrcns ; Eat up console data sec ; Not done return ; Exit Toggle: mov #IN$MODE,r0 ; Toggle modes xor r0 ,@clests ; Do it sec ; Not done return ; Exit .sbttl Utilities .if ne ,$MINITAB .ift Strlen: mov 2(sp) ,r0 ; Get string length 10$: tstb (r0)+ ; Look for end bne 10$ ; Not yet sub 2(sp) ,r0 ; Compute length dec r0 ; Fix mov (sp)+ ,(sp) ; Pop stack return ; Exit ; Strcpy ; ; input: ; 0(sp) return address ; 2(sp) dst address ; 4(sp) src address ; output: r0 dest address Strcpy: save ; save temp registers please mov 2+2(sp) ,r0 ; destination address mov 2+4(sp) ,r1 ; source .asciz address 10$: movb (r1)+ ,(r0)+ ; copy until a null bne 10$ ; not done mov 2+2(sp) ,r0 ; return the dst address unsave ; pop r1 and exit mov (sp) ,4(sp) ; move return address up now cmp (sp)+ ,(sp)+ ; pop junk and exit return ; S C A N C H ; ; input: 4(sp) the string address ; 2(sp) the character to look for ; output: r0 position of ch in string Scanch: save ; save temps mov 6(sp) ,r2 ; get address of the string clr r0 ; initial found position 10$: tstb @r2 ; end of the string yet ? beq 90$ ; yes inc r0 ; no, pos := succ(pos) cmpb 4(sp) ,(r2)+ ; does the ch match the next one? bne 10$ ; no, try again br 100$ ; yes, exit loop 90$: clr r0 ; failure, return postion = 0 100$: unsave ; pop r2 mov @sp ,4(sp) ; move return address up cmp (sp)+ ,(sp)+ ; pop stack return ; and exit .endc ; If NE, $Minitab .end