.TITLE MCE - CLI-Commandline-Editor .IDENT /V4.0./ .ENABLE LC ; ; ; J.H. Hamakers, BBC Brown Boveri b.v. 1-Sep-87 ; P.O.Box 301 3000 AH Rotterdam, The Netherlands ; Phone : +31 - 10 - 4078631 ; ; PLEASE CONTACT ME FOR PROBLEMS OR SUGESTIONS ; ; Merged two versions, one from decus swissbox and one from BBC Rotterdam ; Both from the same first author : ; ; +--------------------------------------------------------------------------+ ; | | ; | D. Sponza (YU) 06-OCT-81 | ; | | ; | With the following modifications : | ; | | ; | -tf- 18-Nov-81 ... Sep-82 | ; | Rolle / Paranor: | ; | VMS V4.0 compatibility introduced 20-Sep-84 | ; | | ; +--------------------------------------------------------------------------+ ; ; ; This version of mce has the folowing new features : ; ; - User friendly installation with MCEBLD.CMD ; - VT2xx functionkeys support VT2XX ; - TDV2xx functionkeys support TDV2XX ; - Alternate CLI support CLISUP ; - Named directory support NAMDIR ; - Startup and end messages optional SILENT ; - MCEINI.xxx file support FILE ; First the systemwide LB:[1,2]MCEINI.xxx is read, then ; the file SY:MCEINI.xxx ; xxx = "CMD" when no alternate CLI support is selected ; xxx = "NAME_OF_CLI" when alternate CLI support is sel. ; Aternate initfile support by starting with : ; "MCE FILE_SPEC" ; - Terminal time-out support : Logs out after no action TMO0, ; within a given time (TT0: only exits MCE) TMOTIM ; - "Execute No_Wait" with ESC/ESC or VT2xx "DO" key ; - Command definition abbrivetion (as in VMS) ; DIR*ECTORY := PIP 'P1'/LI ; - has a RECALL function: ; D will recall the latest command starting with "D" ; - VT2xx HELP key gives HELP MCE ; - Internal commands : ; "MCE PURGe" Deletes definitions ; "MCE READ FILE_SPEC" Adds definitions from file ; "MCE REPLace FILE_SPEC" Combines PURG and READ ; "MCE EXIT Exits MCE ; - Dynamic prompt ( Takes prompt from current CLI ) ; - Make MCE visible to the user by adding A "+" or "-" ; (depending on insert or overstrike mode) before the prompt ; - Holdscreen mode support (VT52) ; - CTRL-T : Detach TI: for 10 seconds ; - Split in I and D, RW and RO psects ; ; ; Removed all audit trails, but here follows the edit ; history of both versions: ; ; +-------------------------------------------------------------------------+ ; ; Swissbox version: ; ================ ; ; Rolle / Paranor: 20-Sep-84 ; "PF2" as RECALL 06-Mar-85 ; Allow translations with "*" 29-Apr-85 ; Huber/Muenchen: LB:[1,2] Instead SY:[1,2] JSH001 ; Volker C. Huck, THD: support for VT2xx terminals VCH001 ; E. Meyer (IfN) 18-Dec-85 Change prompt to CLI default IFN001 ; E. Meyer (IfN) 06-Feb-87 Use GDIR$ to set defDir IFN001 ; E. Meyer (IfN) 18-Feb-87 Merge my previous changes, IFN001 ; which where originally for CLE, into MCE. IFN001 ; Make some improvements: IFN001 ; See options SILENT,CLISUP,NAMDIR. IFN001 ; seperate R/W and R/O code for /MU task. IFN001 ; March'87 J.S.Huber/MPI Muenchen: V3.0C ; o file-type of MCEINI. according to CLI JSH002 ; o check for EXIT/BYE AFTER translation JSH003 ; General handling of MCE internal commands 'MCE ...' JSH003 ; 'EXIT' changed to 'MCE EXIT' JSH003 ; o use startup file specification in MCR command JSH004 ; o correct some mess-up between JSH005 ; startup code mentioned to be unconditional, and code JSH005 ; conditionalized on symbol FILE, JSH005 ; introduced by several previous modifications. JSH005 ; o 'MCE READ,REPL,PURG' commands implemented JSH006 ; o Correct cursur positioning for Begin of line (BS) JSH007 ; o Change IFN001's use of GDIR$/SDIR$ JSH008 ; Volker Huck, Inst. fuer Kernphysik, THD, March87, V3.0D VCH002 ; Add a blank to the prompt. This makes MCE 'visible' VCH002 ; to the user. Make RECALL also work on one line VCH002 ; instead of using a new line for each 'CURSOR UP' VCH002 ; with MCR (Make each prompt start with if VCH002 ; reverse order). Make 'Add blank to prompt' VCH002 ; optional by setting 'ADDBLK'. VCH002 ; Change BYETXT to 'MCE EXIT' instead of 'EXIT' VCH003 ; The modifications with the audit trails above are based on: ; Revision : Dave Guerlet ; Version : V3.0 ; Function : Supports MCR and DCL editing ; Date : 15-Jun-1986 ; ; +-------------------------------------------------------------------------+ ; ; BBC Rotterdam version ; ===================== ; Paul van Randwijk BBC Mannheim ; Function on other CLI 24-Jul-86 PVR01 ; Hans Hamakers BBC Rotterdam ; Added dynamic prompt and VT2xx supp 29-Jul-86 JHA01 ; Fix bug with only spaces on a line 14-Oct-86 JHA02 ; Simplify function on other CLI 14-Jan-87 JHA03 ; Enable nonsaving of short commands 14-Jan-87 JHA04 ; Add support for system wide MCESYS.MCE 21-Apr-87 JHA05 ; Paul van Randwijk BBC Mannheim ; Add Tandberg TDV2230 Support 28-Apr-87 PVR02 ; John Bovenlander Erasmus university Rotterdam ; Add lowercase command definitions 01-May-87 JHB01 ; Change HELP MCE to HELP ASV MCE 01-May-87 JHB02 ; Hans Hamakers BBC Rotterdam ; Merged two versions 19-Jun-87 JHA06 ; Fixed VT2xx bug 22-Jun-87 JHA07 ; Fixed TDV2XX bug 28-JuL-87 JHA08 ; ; +-------------------------------------------------------------------------+ ; ; Edit history since version V4.0a : ; ; .SBTTL MCE - Macros, Constants, Variables .MCALL QIO$S,EXIT$S,SPWN$S,STSE$S .MCALL MRKT$S,ASTX$S,GLUN$S .IF DF CLISUP .MCALL GCII$S .ENDC ;CLISUP .IF DF NAMDIR .MCALL SDIR$S .ENDC ;NAMDIR ; .NLIST BEX ; ; Local symbol definitions ; BUFSIZ = 76. ; (this is max for >SET /BUF=TI:80.) BELL = 7 BKSP = 10 LF = 12 CR = 15 ESC = 33 BLNK = 40 TI = 1 ; TI: LUN INI = 2 ; MCEINI.xxx LUN SS3 = 217 ; SS3 8-bit control character ; .IIF NDF MAXFIF MAXFIF = 23. .IIF NDF MINCHR MINCHR = 0 ; .IF DF FILE .MCALL CSI$ .MCALL DIR$,GMCR$ .MCALL CSI$SW,CSI$SV,CSI$ND,CSI$1,CSI$2 .MCALL FSRSZ$,FDBDF$,FDRC$A,FDOP$A,OPEN$R,GET$S,CLOSE$,NMBLK$ CSI$ ; Define CSI control block offsets FSRSZ$ 1 .PSECT IDATA,D,RW FDBIN: FDBDF$ ; FDB for initialization FDRC$A ,NEW,BUFSIZ FDOP$A INI,FDSPT,DFNB,FO.RD .ENABL LSB 10$: DEVINF: .ASCII /LB:/ ; Device Name DEVL = .-10$ 20$: .IF DF A$SV .ASCII /[2,2]/ ; Directory .IFF ;A$SV .ASCII /[1,2]/ ; Directory .ENDC ;A$SV DIRL = .-20$ .EVEN ; ; Default startup file name block ; ; Default file name (if no CLI support) is 'MCEINI.CMD' ; default device is SY: (but superimposed by the first LB: in DSPT ; SY: in the DFNB will be effective for files specified in the ; invoking MCR commandline. Specifying 'MCE XXX' thus results in ; file name 'SY0:XXX.CMD' ; Note, that the file-type in DFNB will be overwritten by the CLI name ; DFNB: NMBLK$ MCEINI,CMD,0,SY,0 DFTYP = DFNB+N.FTYP ; Define address of RAD-50 filetype FDSPT: .WORD DEVL,10$ ; File Descriptor: Device FDIRL: .WORD DIRL,20$ ; Directory string at begin .WORD 0,0 ; No File name (DFNB will be used) .DSABL LSB ; ; Dummy CSI switch tables ; SWTBL: CSI$ND .EVEN ; ; CSI$ Control block ; CSIBLK: CSI$ .BLKB C.SIZE .EVEN .ENDC ;FILE ; ; Text Formats ; .PSECT PDATA,D,RO CRET: .ASCII .EVEN STARTX: .ASCII \MCE -- CLI-Commandline-Editor V4.0a\ .IF DF A$SV .ASCII \/ASV\ .ENDC ;A$SV .IF DF VT2XX .ASCII \/VT2\ .ENDC ;VT2XX .IF DF TDV2XX .ASCII \/TDV\ .ENDC ;TDV2XX .ASCII .BYTE 0 ENDTXT: .ASCIZ \MCE -- Exit\ NOPOOL: .ASCIZ /MCE -- Pool exhausted - Install MCE with INC/ TOOLON: .ASCIZ /MCE -- Command too long/ BYETXT: .ASCIZ /Bye/ EXITXT: .ASCIZ /MCE -- Exit/ .IF DF VT2XX HLPTXT: .IF DF A$SV .ASCIZ /HELP ASV MCE/ .IFF ;A$SV .ASCIZ /HELP MCE/ .ENDC ;A$SV .EVEN .ENDC ;VT2XX ; ; internal MCE command dispatch table (see subroutine Intern) ; INTCMD: .ASCII /EXIT/ ; Task exit .WORD EXIT .ASCII /PURG/ ; Delete all command translations .WORD ICPURG .IF DF FILE .ASCII /READ/ ; Read definition file 'MCE READ filespc' .WORD ICREAD .ASCII /REPL/ ; Replace translations by new file .WORD ICREPL .ENDC ;FILE .WORD 0 ; End of table marker ; ; data ; .PSECT IDATA ; ; FIFO Buffer descriptors ; ; Entry offsets : ; ;FNXT = 0 ; Pointer to next Entry FLEN = 2 ; Length of entry FTXT = 4 ; Text, terminated by binary 0 FIFO: .WORD 0, FIFO ; Header FIFO Buffer: FIFCNT: .WORD 0 ; Number of entries in FIFO FIFPTR: .WORD 0 ; Ptr to current Entry (for UP, DOWN keys) ; ; Commandbuffer, same entries as in FIFO ; CMDB: .WORD 0, CMDB ; Header command definitions ; FREE: .WORD 0,0 ; Free memory listhead ; SFGMCB: ANI: .BYTE TC.ANI,0 ; HLD: .BYTE TC.HLD,0 ; .IF DF VT2XX!TDV2XX TTP: .BYTE TC.TTP,0 ; Get terminal type .ENDC ;VT2XX!TDV2XX SFGMCL = .-SFGMCB IOSTAT: .BLKW 2 ; PROMLF: .WORD DEFPR ; Point to default prompt PROMPT: .WORD DEFPR+1 ; ; Buffers ; .IF DF FILE ; MCR command line directive and buffer ; GMCR: GMCR$ MCRLIN=GMCR+G.MCRB .ENDC ;FILE .BLKB 15. ; Prompt buffer .ASCII '/' ; Hold screen esc seq. DEFPR: .ASCII ; Default prompt with new line .ASCII \+>\ ; without new line .EVEN NEW: .ASCII '[' ; Hold screen esc seq. .REPT BUFSIZ+4-2 ; Current Buffer, word aligned .ASCII ; Must be blanked .ENDR ; .EVEN SAVB: .BLKB BUFSIZ+4 ; Save Buffer (start on even boundary) BS: .REPT BUFSIZ+2 ; Backspace buffer for .ASCII ; Cursor positioning .ENDR .EVEN .IF DF CLISUP ; Buffer to receive CLI information: ; GCISIZ = 50. GCLI: .BLKB GCISIZ ; For GCII$S DEFTAS: .RAD50 \CLI...\ ; Current CLI TASK: .RAD50 \CLI...\ ; Current CLI .IFF ;CLISUP DEFTAS: .RAD50 \MCR...\ ; For Systems without CLI-Support TASK: .RAD50 \MCR...\ ; For Systems without CLI-Support .ENDC ;CLISUP CODE: .WORD 0 ; QIO-Functioncode ADR: .WORD 0 ; Buffer-address LEN: .WORD 0 ; Buffer-lengh (to output) CHAR: .WORD 0 ; Input-character WAITFL: .WORD 0 ; Flag ; ; Modes (NE if set) ; OVSTMO: .BYTE 0 ; If overstrike mode FILINP: .BYTE 0 ; If File Input NOLOAD: .BYTE 0 ; Skip loading of Command in Commandbuffer TTN: .BYTE 0 ; Terminal Number .IF DF TMOTIM TMOCNT: .BYTE TMO0 ; Counter for timeout .ENDC ;TMOTIM .EVEN CDSC: .WORD 0,0 ; Descriptor of whole remainder PDSC: ; Descriptor of P0 .. P8 .REPT 9. .WORD 0,0 .ENDR CFETCH: .BYTE 0 ; Flag if Paramter fetched OVMSG: .BYTE 0 ; Send Overflow Message CTSTAR: .BYTE 0 ; Find command with "*" enabled (ne 0) TMPFLG: .BYTE 0 ; Temporary Flag: "*" encountered in compare .EVEN CLL = .-CDSC ; Region to be cleared from CDSC ; .SBTTL MCE - Jumptable .PSECT PDATA ; ;JUMP TABLE ; TAB: .WORD INSERT ; SINGLE CHR. .WORD chover ; CTRL/A .WORD ctrlb ; CTRL/B .WORD loop ; CTRL/C .WORD BACKSP ; CTRL/D .WORD ENDLIN ; CTRL/E .WORD skip ; CTRL/F .WORD loop ; CTRL/G .WORD BEGLIN ; BS (CTRL/H) .WORD inser0 ; HT (CTRL/I) .WORD DELEW ; LF (CTRL/J) .WORD LOOP ; CTRL/K .WORD loop ; CTRL/L .WORD EXEC ; CR (CTRL/M) .WORD loop ; CTRL/N .WORD loop ; CTRL/O (STOP OUTPUT TO TI:) .WORD loop ; CTRL/P .WORD loop ; CTRL/Q (XON) .WORD ctrlr ; CTRL/R .WORD loop ; CTRL/S (XOFF) .WORD DELAY ; CTRL/T .WORD CTRLU ; CTRL/U .WORD loop ; CTRL/V .WORD loop ; CTRL/W .WORD loop ; CTRL/X .WORD EXIT ; CTRL/Y .WORD loop ; CTRL/Z .WORD ESCAP ; ESC .WORD loop ; CTRL/\ .WORD loop ; CTRL/] .WORD loop ; CTRL/^ .WORD DELEC ; DEL ; ; ; Register usage ; ; R0 Scratch Pointer ; R1 Cursor in NEW ; R2 First free byte in NEW (End of Text) ; R3 Result of READNR ; R4 Scratch ; R5 Scratch Counter ; .SBTTL MCE - I/O and other subroutines ; .PSECT CODE,I,RO ; ; SUBROUTINES FOR ALL DIFERENT KINDS OF I/O ; ; print CR ; IOCR: MOV #IO.CCO,CODE ; Print MOV #CRET,ADR ; MOV #1,LEN ; Go to IO ; ; QIO routine ; IO: .IF DF TMOTIM MOVB #TMO0,TMOCNT ; Set new timeout .ENDC ;TMOCNT QIO$S CODE,#TI,#5,,#IOSTAT,, STSE$S #5 RETURN ; ; Write from current Position to End of Line and reposition Cursor ; UPD1: MOV #IO.WVB,CODE MOV R1,ADR ; Cursor MOV R2,LEN SUB R1,LEN BEQ 10$ CALL IO ; Write rest of line MOV #BS,ADR CALLR IO ; Cursor back 10$: RETURN ; ; Get terminal information ; TERM: MOV #SFGMCB, ADR ; First find out what Terminal MOV #SFGMCL, LEN ; MOV #SF.GMC, CODE ; CALLR IO ; ; ; Rewrite whole Line ; DISPLY: ; Retype edit-buffer TSTB ANI+1 ; Ansii Screen ? BNE 20$ ; Y CMP ADR, PROMLF ; N- just new Line written ? BNE 10$ ; N- start new line CMP LEN,#2 ; Something written ? BLE 20$ ; N- do not start new Line 10$: MOV PROMLF, ADR ; Y- skip LF BR 30$ ; 20$: MOV PROMPT,ADR ; 30$: MOV R2,LEN ; Calculate length SUB ADR, LEN MOV R0, -(SP) ; Set up to delete to EOL MOV R2, R0 MOVB #ESC, (R0)+ ; MOVB #'[, (R0)+ MOVB #'K, (R0)+ TSTB ANI+1 ; Ansii Screen ? BEQ 50$ ; N ADD #3,LEN ; Y- make Escseq visible 50$: MOV #IO.WVB,CODE CALL IO MOVB #40, -(R0) ; Restore escseq MOVB #40, -(R0) MOVB #40, -(R0) MOV (SP)+, R0 MOV #BS,ADR MOV R2,LEN SUB R1,LEN BEQ 60$ CALLR IO ; Write same no of backspaces 60$: RETURN ; ; Load Buffer into NEW, R0 points to source ; GETBUF: MOV #NEW,R1 ; Adr. of the new->r1 MOV R1, R2 MOV #BUFSIZ,R5 ; Buf. length->R5 10$: MOVB (R0)+,(R1)+ ; NEW <-- BUF BEQ 30$ CMPB -1(R1),#BLNK ; Blank ? BEQ 20$ MOV R1,R2 ; Point behind last 20$: SOB R5,10$ ; Go back if not the end BR 40$ 30$: MOVB #BLNK,-1(R1) ; Overprint 000 (.ASCIZ) 40$: MOV R2,R1 ; Both at the end RETURN ; ; Print Message ; IOMSG: ; Print a Msg in (R0) CALL IOCR CALL GETBUF CALL DISPLY ; ; Clear Buffer NEW ; CLRNEW: MOV #NEW,R1 ; Adr. of the new->R1 MOV #BUFSIZ,R5 ; Buf. length->R5 10$: MOVB #BLNK,(R1)+ ; Reset NEW TO BLANK SOB R5, 10$ ; Go back if not the end MOV #NEW,R1 ; Adr. of the new->r1 MOV R1,R2 ; New is empty RETURN .IF DF FILE .SBTTL MCE - reading MCEINI.CMD FILOP: ; Open File CALL GETMCR ; Get MCR commandline (startup file) FILOP1: .IF DF CLISUP CALL GETCLI ; Get CLI info/filetype .ENDC ;CLISUP CALL FILO1 ; Open File LB:[1,2]xxx.CLI BCC RET0 ; Success TST FDIRL ; Was it first default file ? BEQ RET0 ; If eq no: already specific file CLR FDIRL ; No directory descriptor MOV #"SY,DEVINF ; Users system disk ; Try file 'SY:xxx.CLI' FILO1: CLRB FILINP ; Assume file can not by opened OPEN$R #FDBIN ; Open input file BCS RET0 ; DECB FILINP ; Enable File Input RET0: RETURN ; Return with CC-C FILREA: GET$S #FDBIN ; Get a record from infile BCS FILCLO ; No more records MOV F.NRBD(R0),R2 ; This length BLE FILREA ; Empty line MOV R2,LEN ; Store TST (SP)+ ; Do not return JMP EXEC0 ; but execute directly FILCLO: CLRB FILINP ; CLOSE$ #FDBIN ; Close inputfile TST FDIRL ; Already on default directory ? BEQ 10$ ; Y CLR FDIRL ; N- Open MCEINI.CMD for default dir MOV #"SY,DEVINF ; Users system disk CALL FILO1 ; If there BCC FILREA ; Read next input line from there 10$: RETURN .ENDC ;FILE .IF DF CLISUP GETCLI: GCII$S #GCLI,#GCISIZ ; Get CLI information .IF DF FILE BCS 20$ ; Error is C set ; ; choose the startup file type according to the CLI in use: ; MOV G.CICL+GCLI,DFTYP ; Use CLI name for file type 20$: .ENDC ;FILE RETURN ; .ENDC ;CLISUP .IF DF TMOTIM ; On timeout - log off (TT0: just exit) ; TIMAST: TST (SP)+ ;; Restore stack DECB TMOCNT ;; Timeout ? BLT 10$ ;; Should not have decremented BNE 20$ ;; Not yet ; ; Timed out - kill pending read ; MOV #IO.KIL,CODE ;; Kill pending read CALL IO ;; 10$: CLRB TMOCNT ;; 20$: MRKT$S ,#TMOTIM,#2,#TIMAST ;; next Marktime ASTX$S ;; .ENDC ;TMOTIM .SBTTL MCE - INIT-Code, Main-Loop ; START: CALL TERM ; Get terminal info MOV #FREE, R0 ; CALL $INIDM ; Initialize Free Memory MOV #NEW+1&^C1, R0 ; Temporary buffer, word aligned GLUN$S #5, R0 ; Get terminal number MOVB 2(R0),TTN ; And save it .IF DF TMOTIM MRKT$S ,#TMOTIM,#2,#TIMAST ; Marktime for timeout .ENDC ;TMOTIM CALL IO ; .IF NDF SILENT MOV #STARTX, R0 CALL IOMSG .ENDC ;SILENT .IIF DF FILE CALL FILOP ; ; Get next Line ; RESTAR: CALL TERM ; Get terminal info .IF DF FILE TSTB FILINP ; File Input ? BEQ 10$ ; N CALL FILREA ; Y- goto EXEC0 if something read 10$: .ENDC ;FILE MOV #IO.ATT,CODE ; Attach the terminal CALL IO ; ; .IF DF NAMDIR ; ; set our task default directory string to that of the terminal. We ; need to do that since the last command could have been a SET /DEF ; SDIR$S #SD.TI ; Set task DDS to terminal DDS .ENDC ;NAMDIR MOV #IO.CCO,CODE ; Printing of the prompt MOV PROMLF,ADR ; MOV #4,LEN ; .IF DF CLISUP CALL GETCLI ; Get CLI information BCC 20$ ; If C clear: success MOV #^RMCR,TASK ; MCR... only JMP 80$ ; Continue with default prompt 20$: MOV #GCLI,R0 30$: ; ; Transfer prompt to prompt buffer ; ADD #G.CIDP,R0 ; Default prompt (first byte = length) MOVB (R0)+,R4 ; Get length, advance to prompt string ADD R4,R0 ; Point behind CLI prompt MOV #NEW+2,R5 ; Point behind prompt buffer (ROOM for ESC[) MOVB #'[,-(R5) ; Insert '[' ( hold screen mode ) MOVB #ESC,-(R5) ; Insert ESC ( hold screen mode ) CLR -(SP) ; Reserve space 50$: MOVB -(R0),(SP) ; CMPB (SP),#CR ; ? BEQ 60$ ; CMPB (SP),#LF ; ? BEQ 60$ ; MOVB (SP),-(R5) ; 60$: SOB R4,50$ ; TST (SP)+ ; Flush space MOVB #'+,-(R5) ; Assume insert mode BITB #1,OVSTMO ; Overstrike ? BEQ 70$ ; No : => 70$ MOVB #'-,(R5) ; Overstrike 70$: MOVB #CR,-(R5) ; Insert cr MOVB #LF,-(R5) ; Insert lf MOVB #'/,-1(R5) ; Insert '/' ( hold screen mode ) MOVB #ESC,-2(R5) ; Insert ESC ( hold screen mode ) MOV #NEW,LEN ; Point behind prompt buffer SUB R5,LEN ; Length MOV R5,PROMPT ; MOV R5,PROMLF ; INC PROMPT ; MOV PROMLF,ADR ; 80$: TSTB HLD+1 ; Hold screen mode ? BEQ 90$ ; No : => 90$ ADD #4,LEN ; Adjust length for Hold screen escseq. SUB #2,ADR ; Adjust address 90$: .ENDC ;CLISUP ; CALL IO ; CALL CLRNEW ; ; ; Accept next Character for input and dispatch it ; LOOP: MOV #IO.RST!IO.RNE,CODE ; Accept one chr. MOV #CHAR,ADR ; Extrabuffer !! MOV #1,LEN ; CALL IO ; Read 1 char LOOP00: CMPB IOSTAT, #IE.ABO ; IO killed ? (time-out) BNE 20$ ; N MOV #BYETXT, R0 ; Y- get last command TSTB TTN ; Are we on TT0: ? BNE 10$ ; N- Spawn BYE MOV #EXITXT,R0 ; Y- exit 10$: CALL GETBUF ; CALL DISPLY ; JMP EXEC ; Execute BYE or EXIT command 20$: MOVB IOSTAT+1,R4 ; Test for branch table ; ; The following 2 lines test if there is a VT2xx Terminal ; in 8 Bit Ctrl-Mode, ; that sends 'P' - 'S' when pressing 'PF1' - 'PF4' ; CMPB #SS3,R4 ; 'SS3' Control-String ? BNE 30$ ; N JMP ESCAP ; Y 30$: BIC #177740,R4 ; IO.RST: all ctrl-char in iostat ASL R4 ; JMP @TAB(R4) ; <== Dispatch .SBTTL MCE - Edit-commands ; ; Insert one character ; INSER0: MOVB #40,CHAR ; Insert space (e.g. instead of tab) INSERT: CMP R2,#NEW+BUFSIZ ; Room ? BLO 10$ ; BR LOOP ; 10$: MOV #IO.WVB,CODE ; MOV #CHAR,ADR ; Echo MOV #1,LEN ; CALL IO ; BITB #1,OVSTMO ; Overstrike ? BEQ 20$ ; N MOVB CHAR,(R1)+ ; Overstrike CMP R1,R2 ; At end ? BLOS 40$ ; N MOV R1,R2 ; Y- increment end ptr BR 40$ ; 20$: INC R2 ; No overstrike - shift MOV R2,R0 ; 30$: MOVB -(R0),1(R0) ; Shift string CMP R0,R1 ; BHI 30$ ; MOVB CHAR,(R1)+ ; Insert new character CALL UPD1 ; 40$: ; LOOP1: BR LOOP ; ; Cursor right ; SKIP: CMP R1,R2 ; End of text ? BHIS LOOP1 ; MOV #IO.WVB,CODE ; Print chr. MOV R1,ADR ; Cursor position MOV #1,LEN ; CALL IO ; INC R1 ; Shift cursor BR LOOP1 ; ; ; Cursor left ; BACKS1: CMP R1,#NEW ; The begining of the buf. BLOS 10$ ; MOV #IO.WVB,CODE ; Go one chr. back MOV #BS,ADR ; MOV #1,LEN ; CALL IO ; DEC R1 ; Cursor CLC ; Indicate success RETURN ; 10$: SEC ; Indicate cursur error RETURN ; BACKSP: CALL BACKS1 ; cursor left one space BR LOOP1 ; ; ; Begin of line ; BEGLIN: CALL BACKS1 ; Back space one position BCC BEGLIN ; If CC not yet at the begin BR LOOP1 ; ; ; Delete left single char ; DELEC: CMP R1,#NEW ; Test limit BLOS 20$ ; DEC R1 ; Cursor MOV #IO.WVB,CODE ; Cursor one chr. back MOV #BS,ADR ; MOV #1,LEN ; CALL IO ; MOV R1,R0 ; 10$: MOVB 1(R0),(R0)+ ; Shift string left CMP R0,R2 ; BLOS 10$ ; CALL UPD1 ; DEC R2 ; End of text 20$: ; LOOP2: BR LOOP1 ; ; Delete left single word ; DELEW: CMP R1,#NEW ; Test limit BLOS 60$ ; MOV #IO.WVB,CODE ; MOV R1,-(SP) ; Save initial Pointer 10$: DEC R1 ; Cursor CMP R1,#NEW ; At beginning of line ? BLOS 30$ ; Y MOVB -1(R1),R0 ; N- get previous char CMPB R0,#40 ; Space BNE 20$ ; N CMPB R0,(R1) ; Y- was previous one a space ? BEQ 10$ ; Y- then delete it 20$: CMPB R0,#'0 ; Alphabetical ? BLO 30$ ; Certainly not CMPB R0,#'9 ; Really ? BLO 10$ ; Y CMPB R0,#'_ ; Special char ? BEQ 10$ ; Y- accept BIC #40,R0 ; Convert to upper CMPB R0,#'A ; Alphabetical ? BLO 30$ ; N CMPB R0,#'Z ; Maybe - check upper limt BLOS 10$ ; Ok - alphabetical 30$: MOV (SP)+,R0 ; Restore initial pointer MOV R1,-(SP) ; 40$: CMP R0,R2 ; More to shift BHIS 50$ ; N MOVB (R0),(R1)+ ; Shift down MOVB #40,(R0)+ ; Must be replaced by space BR 40$ ; 50$: MOV R1,R2 ; New end ptr MOV (SP)+,R1 ; Restore CTRLR = . CALL DISPLY ; Write buffer 60$: BR LOOP2 ; ; ; Delete from start of line to cursor ; CTRLU: CMP R1,#NEW ; BLOS 50$ ; Ready MOV #NEW,R0 ; 10$: CMP R1,R2 ; BEQ 20$ ; MOVB (R1)+,(R0)+ ; Shift string left BR 10$ ; 20$: MOV R0,R2 ; End of text 30$: CMP R0,#NEW+BUFSIZ ; BHIS 40$ ; MOVB #BLNK,(R0)+ ; Fill with blank BR 30$ ; 40$: MOV #IO.WVB,CODE ; MOV PROMPT,ADR ; MOV R1,LEN ; SUB PROMPT,LEN ; CALL IO ; MOV #NEW,LEN ; SUB PROMPT,LEN ; Reposition cursor CALL IO ; MOV #NEW,R1 ; 50$: BR LOOP2 ; ; ; Jump to end of text ; ENDLIN: MOV #IO.WVB,CODE ; MOV R1,ADR ; MOV R2,LEN ; SUB R1,LEN ; BEQ 10$ ; CALL IO ; MOV R2,R1 ; End of text 10$: BR LOOP2 ; ; ; Flip between insert and overstrike mode ; CHOVER: INCB OVSTMO ; Change overstrike mode MOV PROMLF,R4 ; CMPB 2(R4),#'+ ; BEQ 10$ ; MOVB #'+,2(R4) ; BR 20$ ; 10$: MOVB #'-,2(R4) ; 20$: CALL DISPLY ; BR LOOP2 ; .SBTTL MCE - Escape Sequences / FIFO - Commands ; .ENABL LSB ESCAP: CALL IO ; Read next char MOVB CHAR, R0 ; Get it here CMPB R0,#'[ ; VT100 or VT52 BEQ ESCAP CMPB R0,#'O ; VT100 BEQ ESCAP CMPB IOSTAT+1,#ESC ; esc/esc BNE 10$ ; JMP EXECNW ; Execute no-wait 10$: CMPB R0,#'A ; ^ BNE 40$ ; CTRLB: MOV FIFPTR, R5 ; Get Ptr of buffer BNE 20$ ; Not set - take newest buffer TST FIFO ; Any entry at all ? BEQ 70$ ; N MOV FIFO+2, FIFPTR ; Take newest entry BR 70$ ; 20$: MOV #FIFO, R5 ; N- find previous entry 30$: MOV (R5), R5 ; Next BEQ 70$ ; No more CMP (R5), FIFPTR ; Does this point to me ? BNE 30$ ; Not this MOV R5, FIFPTR ; Found - load and BR 70$ ; Display ; 40$: CMPB R0,#'B ; v - find newer command BNE 100$ 50$: MOV FIFPTR, R5 ; Get Ptr of buffer BNE 60$ ; Defined TST FIFO ; Any entry at all ? BEQ 70$ ; N BR 90$ 60$: TST (R5) ; Goto next buffer if any BEQ 80$ ; No more MOV (R5), FIFPTR ; Next 70$: CALL GEFIFO ; Load NEW from FIFO BR LOOP0 80$: MOV (R5), FIFPTR ; Next 90$: CALL CLRNEW ; CALL DISPLY ; BR LOOP0 ; ; 100$: CMPB R0,#'C ; --> BNE 110$ JMP SKIP ; Skip single char ; 110$: CMPB R0,#'D ; <-- BNE 120$ JMP BACKSP ; Backspace on char ; 120$: SUB #'P-1, R0 ; Any PFn ? BLE VT2KEY ; N CMP R0, #4 ; BHI VT2KEY ; N MOV R0, -(SP) ; Y- save 1,..,4 for ,.. MOV #"PF, SAVB ; Check if to be translated ADD #'0, R0 ; MOV R0, SAVB+2 ; MOV #3, PDSC ; Set up P0 MOV #SAVB, PDSC+2 ; MOV R2, -(SP) ; CALL FNDCMD ; Find cmd MOV (SP)+, R2 ; MOV (SP)+, R0 ; BCS 140$ ; No entry found FUNC: ; ; Exectute function key commands ; MOV R1, R0 ; Find start of text 130$: ; Execute command in (R0) CALL IOCR ; Clear current line CALL GETBUF ; Load new buffer SUB #NEW, R2 ; Calculate length MOV R2, LEN ; Save it MOV #IO.DET,CODE ; Deatt. the terminal CALL IO ; JMP EXEC1 ; And execute without display 140$: ; Execute function key MOV R2, R1 ; Point to end of buffer ASL R0 ; Word offset ADD R0, PC ; Branch NOP ; BR 150$ ; BR 160$ ; BR 170$ ; ; Print whole fifo CALL PRIFIF ; BR LOOP0 ; 150$: ; Translate CMP R2, #NEW ; Something in buffer BEQ LOOP0 ; N- ignore command DECB NOLOAD ; Disable command load SUB #NEW, R2 ; Calculate Length MOV R2, LEN ; Store CALL CMDCHK ; Command Translation MOV LEN, R2 ; Restore R2 ADD #NEW, R2 ; Point to end MOV R2, R1 ; CALL DISPLY ; CLRB NOLOAD ; Enable command load BR LOOP0 160$: ; - RECALL CALL RECCMD ; Recall Command BR LOOP0 170$: ; Print CMD Buffer CALL PRICMD ; LOOP0: JMP LOOP ; .IF DF VT2XX HELP: ; HELP MOV #HLPTXT, R0 ; Move HELP MCE into Buffer BR 130$ ; CALL PRICMD ; BR LOOP0 ; .ENDC ;VT2XX .DSABL LSB .SBTTL MCE - VT2xx part ; VT2KEY: .IF DF VT2XX!TDV2XX CMPB TTP+1,#T.V2XX ; VT2xx ? BEQ 10$ ; ; JMP TDVTST ; 10$: .ENDC ;VT2XX!TDV2XX ; ; Check if function key : ; ; [n~ n 1..6 ; or ; [nn~ nn 17..34 ; .IF NDF VT2XX JMP LOOP .IFF ;VT2XX MOVB CHAR,R0 ; CMPB R0,#'1 ; + BLO EX1 ; 1..6 ? CMPB R0,#'6 ; BHI EX1 ; - SWAB R0 ; Char in highbyte BISB #BLNK,R0 ; Lowbyte = space MOV R0,-(SP) ; Save it CALL IO ; Next char. MOVB CHAR,R0 ; Take char. CMPB R0,#'~ ; Tilde ? BEQ 20$ ; Yes: => 20$ CMPB R0,#'0 ; + BLO EX2 ; 0..9 ? CMPB R0,#'9 ; BHI EX2 ; - CLRB (SP) ; BISB R0,(SP) ; Insert in word CALL IO ; Next char. CMPB CHAR,#'~ ; Tilde ? BNE EX2 ; No: => EX2 20$: MOV (SP)+,R0 ; Retrieve word SWAB R0 ; Adjust MOV #VT2TAB,R4 ; R4 -> VT2XX table MOV #VT2LEN/6,R5 ; R5 = Table length 30$: CMP R0,(R4)+ ; Look for table entry BEQ VT2FN ; Found : => VT2FN CMP (R4)+,(R4)+ ; Next entry SOB R5,30$ ; Try next JMP LOOP ; Not found : => LOOP EX2: TST (SP)+ ; Flush word EX1: JMP LOOP00 ; ; ; VT2xx functionkey found; check if to be translated ; VT2FN: MOVB #'F, SAVB ; Check if to be translated MOVB 2(R4),SAVB+1 ; Insert MOVB 3(R4),SAVB+2 ; key ident MOV #3, PDSC ; Set up P0 CMPB SAVB+2,#BLNK ; BNE 10$ ; DEC PDSC ; Set up P0 one less 10$: MOV #SAVB, PDSC+2 ; MOV R2, -(SP) ; CALL FNDCMD ; Find cmd MOV (SP)+, R2 BCS 20$ ; No entry found JMP FUNC ; Proccess it 20$: JMP @(R4) ; .SBTTL MCE - VT2ESC ; ; Typed VT2xx F11 () key; look for a second one ; .PSECT PDATA VT2ESQ: .ASCII /[23~/ VT2ESL = .-VT2ESQ ; .PSECT CODE VT2ESC: CALL IO ; Next char CMPB IOSTAT+1,#ESC ; ? BNE 20$ ; No : => 20$ MOV #VT2ESQ,R4 ; R4 -> VT2XX ESC-SEQ. MOV #VT2ESL,R5 ; R5 = Length 10$: CALL IO ; Next char. CMPB CHAR,(R4)+ ; Macth ? BNE 20$ ; No : => 20$ SOB R5,10$ ; Next JMP EXECNW ; esc/esc 20$: JMP LOOP1 ; .SBTTL MCE - VT2TAB Key table ; ; Entry: ; ; word 1 : 2 ascii char. from esc-seq. ; word 2 : action routine address ; word 3 : 2 ascii char. from key ; .PSECT PDATA .MACRO KEYVT2,ESC,ACT,KEY .ASCII /ESC/ .IF NB ACT ACT .IFF LOOP .ENDC .ASCII /KEY/ .ENDM ; VT2TAB: KEYVT2 <1 > , ,<$F> ; Find KEYVT2 <2 > , ,<$I> ; Insert here KEYVT2 <3 > , ,<$R> ; Remove KEYVT2 <4 > , ,<$S> ; Select KEYVT2 <5 > , ,<$P> ; Prev. Screen KEYVT2 <6 > , ,<$N> ; Next Screen ; KEYVT2 <17> , ,<6 > ; F6 KEYVT2 <18> , ,<7 > ; F7 KEYVT2 <19> , ,<8 > ; F8 KEYVT2 <20> , ,<9 > ; F9 KEYVT2 <21> , ,<10> ; F10 KEYVT2 <23> ,VT2ESC ,<11> ; F11 ESC KEYVT2 <24> ,BEGLIN ,<12> ; F12 BS KEYVT2 <25> ,DELEW ,<13> ; F13 LF KEYVT2 <26> , ,<14> ; F14 KEYVT2 <28> ,HELP ,<15> ; F15 HELP KEYVT2 <29> ,EXECNW ,<16> ; F16 DO KEYVT2 <31> , ,<17> ; F17 KEYVT2 <32> , ,<18> ; F18 KEYVT2 <33> , ,<19> ; F19 KEYVT2 <34> , ,<20> ; F20 ; VT2LEN =.-VT2TAB .PSECT CODE .ENDC ;VT2XX .SBTTL MCE - TDV2230 support. ; ; O ... ; TDVTST: ; .IF NDF TDV2XX JMP LOOP ; Not available .IFF ;TDV2XX CMPB TTP+1,#200 ; TDV2XX ? BNE NEXT ; Not a TDV22 ; ; Test character is in the range of "T" - "Z" ; MOVB CHAR,R0 ; SUB #'T,R0 ; BLT NEXT ; Less then: no funktion CMPB R0,#'Z-'T ; BGT NEXT ; ; ; Function ok: convert to string ; MOVB #'F,SAVB ; ADD #'1,R0 ; Make it an ascii number MOVB R0,SAVB+1 ; ; MOV #2,PDSC ; MOV #SAVB,PDSC+2 ; ; MOV R2,-(SP) ; CALL FNDCMD ; MOV (SP)+,R2 ; BCS NEXT ; No command found JMP FUNC ; Do execute found command .ENDC ;TDV2XX ; NEXT: ; JMP LOOP .SBTTL MCE - FIFO Buffer Subroutines ; ; FIFO OPERATIONS ; ; Get FIFO Buffer, pointed to by FIFPTR ; GEFIFO: MOV FIFPTR, R0 ; Get Ptr BNE 10$ ; Defined MOV #FIFPTR, R0 ; Null String BR 20$ 10$: ADD #FTXT, R0 ; Get start of text 20$: CALL GETBUF ; Load buffer CALLR DISPLY ; ; Print FIFO / or Command buffer and put pointer to end of queue ; .ENABL LSB PRIFIF: MOV #FIFO, FIFPTR BR 10$ PRICMD: MOV #CMDB, FIFPTR 10$: MOV #IO.WVB, CODE 20$: MOV PROMLF,ADR ; Print LF MOV #1,LEN CALL IO MOV @FIFPTR, FIFPTR ; Next PTR BEQ 30$ ; All done CALL GEFIFO ; Display BR 20$ 30$: CALL CLRNEW ; Clear line, FIFPTR already cleared CALLR DISPLY .DSABL LSB ; ; Clear first entry of FIFO buffer ; CLFIF: MOV #FIFO, R0 ; This header CALL FRENT BCS 10$ DEC FIFCNT ; Adjust count 10$: RETURN ; ; Free entry from queue (Header in R0). CC-C set if it was empty ; FRENT: JSR R5, .SAVR1 ; Save Regs MOV (R0), R2 ; Get entry if any SEC BEQ 20$ ; None MOV (R2), (R0) ; Remove from head of queue BNE 10$ ; More entries MOV R0, 2(R0) ; This was last one 10$: MOV FLEN(R2), R1 ; This length MOV #FREE, R0 CALL $RLCB CLC 20$: RETURN ; ; Load NEW into FIFO Buffer ; Input: R2 - Length ; LDFIF: JSR R5, .SAVR1 ; Save Regs CLR FIFPTR ; Initialize FIFO Ptr MOV R2, R5 ; Length BEQ 40$ ; None CMP R2,#MINCHR ; Save it ? BLO 40$ ; No : => 40$ MOV R5, R1 ; Save it ADD #FTXT+2, R1 ; Increment for header CMP FIFCNT, #MAXFIF ; Maximum reached ? BLO 20$ ; N 10$: CALL CLFIF ; Release one entry BCS 40$ ; Nothing to release 20$: MOV #FREE, R0 ; CALL $RQCB ; Request core block BCS 10$ ; Nothing received yet - release more CLR (R0) ; No next entry MOV R0, @FIFO+2 ; Link to previous MOV R0, FIFO+2 ; New last entry MOV R1, FLEN(R0) ; Total length ADD #FTXT, R0 ; MOV #NEW, R1 ; Source text 30$: MOVB (R1)+, (R0)+ ; Load SOB R5, 30$ CLRB (R0) ; End of string INC FIFCNT ; Count 40$: RETURN .SBTTL MCE - Detach and delay ; DELAY: CALL IOCR ; MOV #IO.DET,CODE ; Deatt. the terminal CALL IO ; MRKT$S #1,#10.,#2 ; Wait 10 seconds STSE$S #1 ; JMP RESTAR ; ; ; .SBTTL MCE - Execute new Command ; .ENABL LSB EXECNW: CLR WAITFL ; .XDT BR EXEC00 ; EXEC: MOV #1,WAITFL ; EXEC00: CALL IOCR MOV #IO.DET,CODE ; Deatt. the terminal CALL IO SUB #NEW, R2 ; Calculate Length MOV R2, LEN ; Store BLE 40$ ; MOV R2,R1 ; R1 = counter MOV #NEW,R5 ; R5 => NEW buffer 10$: CMPB (R5)+,#BLNK ; A space ? BNE 20$ ; No : => 20$ SOB R1,10$ ; Look for non space BR 40$ ; Only spaces => 40$ 20$: CALL LDFIF ; Load into FIFO EXEC0: CALL CMDCHK ; Check for command Translation BCS 40$ ; Nothing to execute EXEC1: .IF DF TMOTIM CLRB TMOCNT ; Disable timeouts (until next IO) .ENDC ;TMOTIM CALL INTERN ; Internal command or BYE ? BCS 40$ ; If C set: no command for CLI CALL EXEC2 ; Excute command in buffer NEW TST WAITFL ; Wait ? BNE 30$ ; Yes : => 30$ INC WAITFL ; Make flag #1 MRKT$S WAITFL,#20.,#1 ; Allow task to run 30$: STSE$S WAITFL ; Stop until done 40$: JMP RESTAR .DSABL LSB ; .SBTTL MCE - Task exit ; ; Exit ; EXIT: .IF NDF SILENT MOV #ENDTXT,R0 CALL IOMSG .ENDC ;SILENT EXITS: MOV #IO.DET,CODE ; Deatt. the terminal CALL IO EXIT$S ; Exit .SBTTL MCE - Exec2 - submit command to CLI ; EXEC2: MOV LEN,R1 MOV #NEW,R0 10$: CMPB (R0),#BLNK ; Blank ? BNE 20$ ; No : => 20$ INC R0 ; Next DEC R1 ; char. BR 10$ ; Agian 20$: SPWN$S #TASK,,,,,WAITFL,,,R0,R1 ; *** EXECUTE COMMAND *** ; RETURN .SBTTL MCE - Command Substitution etc. ; .SBTTL MCE - FNDCMD - find entry in command table ; ; FNDCMD - Find entry in Command (=Translation-) Table ; FNDCMA - Find entry in Command (=Translation-) Table - accept Abbreviations ; ; Input - PDSC of P0 defined ; - CTSTAR .ne.0 to allow abreviated command if command ; definition contains "*" (a la VMS) ; Output - CC-C set - no entry found ; CC-C clr - entry found ; R0 - to entry ; R1 - to point to string after ":=" ; R2 - to previous entry (for remove and inserts) ; .ENABL LSB FNDCMA: MOVB #1, CTSTAR ; Enable abbreviations BR 10$ FNDCMD: CLRB CTSTAR ; Ignore "*" in translation buffer 10$: MOV #CMDB, R0 ; Header MOV R3, -(SP) MOV R1, -(SP) CLR -(SP) ; For previous entry 20$: MOV R0, (SP) ; Save previous entry TST (R0) ; any next entry ? BEQ 100$ ; N- end of list MOV (R0), R0 ; Y- take next entry MOV R0, R1 ; to Text ADD #FTXT, R1 MOV PDSC, R3 ; Length to be compared BLE 100$ ; ? MOV PDSC+2, R2 ; and start addr of P0 TSTB CTSTAR ; without abbreviation ? BEQ 80$ ; Y- exact match required ; ; Check for match, accepting any "*" in command defintion ; CLRB TMPFLG ; Reset Flag: "*" found in Cmd Translation 30$: CMPB (R1), #'* ; check for "*" in translation buffer BNE 40$ ; not yet found INCB TMPFLG ; Y- found, remember it INC R1 ; to next char 40$: CMPB (R1), #40 ; end of translation buffer ? BEQ 60$ ; Y- terminate compare CMPB (R2)+, (R1)+ ; check for equality BEQ 50$ ; match BGT 20$ ; NE and must come further down in list TSTB TMPFLG ; passed entry - any "*" seen ? BNE 20$ ; then continue search BR 100$ ; else we passed alphabetical order 50$: SOB R3, 30$ ; match- to next char CMPB (R1), #40 ; end of input string - translation buffer BEQ 70$ ; is also terminated CMPB (R1), #'* ; or next byte might be end ? BEQ 70$ ; Y- then accept 60$: TSTB TMPFLG ; match found- abbreviation possible ? BEQ 20$ ; N- then don't accept match- to next entry 70$: CMPB (R1)+, #40 ; goto end of string (or binary 0???) BHI 70$ ; not yet found BR 90$ ; point past key ; ; Check for match, igoring any "*" in command defintion ; 80$: CMPB (R2)+, (R1)+ ; compare BGT 20$ ; NE and must come further down in list BLT 100$ ; already passed alphabetical order SOB R3, 80$ CMPB (R1)+, #40 ; match - followed by space ? BNE 100$ ; no still continuing 90$: ADD #3, R1 ; skip ":= " CLC ; MOV (SP)+, R2 ; to previous entry TST (SP)+ ; Flush old R1 BR 110$ 100$: SEC MOV (SP)+, R2 ; to previous entry MOV (SP)+, R1 110$: MOV (SP)+, R3 RETURN .DSABL LSB ; .SBTTL MCE - CMDCHK - Check for Command definition ; ; Check for Command definition ; or replace first command word by stuff defined in command buffer ; P1..P8 may also be replaced ; ; R2 - length of buffer in NEW (also stored in LEN) ; on return: LEN updated, all Regs destroyed CMDCHK: ; all Regs destroyed MOV #CDSC, R0 ; Clear scratch buffer MOV #CLL/2, R1 10$: CLR (R0)+ SOB R1, 10$ MOV #NEW, R1 ; Source Buffer MOV #SAVB, R3 ; Destination Buffer MOV #PDSC, R5 ; to current Para Desc MOV R3, 2(R5) ; start of P0 20$: ; Store single char MOVB (R1)+, R0 ; next char - convert to upper CALL CNVUPC ; check for delimiter MOVB R0, (R3)+ ; store char BCC 40$ ; no delimiter found CMP R5, #PDSC ; on P0 ? BNE 30$ ; N MOV R3, CDSC+2 ; load starting Addr 30$: ; to next Pn CMP R5, #8.*4+PDSC ; already on P8 ? BHIS 40$ ; Y- put it all there ADD #4, R5 ; N- to next Para MOV R3, 2(R5) ; starting address BR 50$ ; do not count 40$: ; no delimiter found INC (R5) ; count char 50$: SOB R2, 20$ MOV CDSC+2, R2 ; Remainder Descriptor defined ? BEQ 60$ ; N SUB R2, R3 ; Y- then calculate length of it MOV R3, CDSC ; and store ; ; Now everything is moved into SAVB ; Check if we define a new command ":=" in P1 ; 60$: MOV #4+PDSC, R2 ; to P1 descr CMP (R2)+, #2 ; correct length ? BNE 70$ ; N MOV (R2), R2 ; Y- to string CMPB (R2)+, #': BNE 70$ CMPB (R2)+, #'= BNE 70$ JMP NEWCMD ; match found ; ; Try find an entry in the commandbuffer with key P0 ; 70$: CALL FNDCMA ; check in table BCC 80$ ; entry found if C CLC ;indicate success for RETURN 80$: ; entry found, R1 points to Text MOV #NEW, R2 ; and destination 90$: ; assemble buffer NEW MOVB (R1)+, R0 ; next char BEQ 110$ ; all done CMPB R0, #'' ; could it be 'Pn' ? BNE 100$ ; N CALL 180$ ; check it and substitute if necessary BCS 90$ ; already substituted 100$: MOVB R0, (R2)+ ; store BR 90$ ; next char from CMD Buf 110$: ; whole buffer moved to NEW TSTB CFETCH ; buffer already feched ? BLT 120$ ; Y- all done MOV #CDSC, R1 ; this descriptor to append CALL 140$ ; store 120$: ; all done, execute new command SUB #NEW, R2 ; calculate new length MOV R2, LEN ; and store TSTB OVMSG ; buffer overflow ? BEQ 130$ ; MOV #TOOLON, R0 ; Y- give Msg CALL IOMSG SEC 130$: RETURN ; CC-C only set if no command to execute 140$: ; append string with descriptor (R1) toNEW MOV (R1)+, R5 ; length BEQ 170$ ; empty MOV (R1), R1 ; source Addr 150$: CMP R2, #NEW+BUFSIZ ; in range ? BLO 160$ ; Y DECB OVMSG ; N- mark for Ovflw RETURN 160$: MOVB (R1)+, (R2)+ SOB R5, 150$ 170$: RETURN ; 180$: ; Substitute Pn's JSR R5, .SAVR1 ; save Regs CMPB (R1)+, #'P ; check next symbol BNE 190$ ; no match MOVB (R1)+, R3 ; get Parameter number SUB #'0, R3 ; decode BLE 190$ ; illegal CMP R3, #8. ; in range ? BHI 190$ ; N CMPB (R1)+, R0 ; endmark ? BEQ 200$ ; Y 190$: CLC ; tell no substit RTS PC 200$: ; substitution string found MOV R1, 2(SP) ; set up R1 after retunr ASL R3 ; Param num times 4 ASL R3 ADD #PDSC, R3 ; point to descriptor MOV R3, R1 CALL 140$ ; load it MOV R2, 2*2(SP) ; load R2 after return DECB CFETCH ; mark that parameter fetched SEC ; tell substituted RTS PC ; .SBTTL MCE - CNVUPC - Convert to uppercase ; ; Convert to upper case, CC-C set if delimiter ; CNVUPC: ; check for delimiter CMPB R0, #'A+40 ; convert to upper case BLO 10$ CMPB R0, #'Z+40 BHI 10$ BICB #40, R0 ; convert to upper 10$: CMPB R0, #40 ; delimter ? SEC BEQ 30$ ; its a delimiter 20$: CLC ; character within string 30$: RTS PC ; ; .SBTTL MCE - NEWCMD - define new command or delete command ; ; Define new command in command buffer, or delete it ; NEWCMD: TSTB NOLOAD ; skip processing ? BNE 50$ ; Y CALL FNDCMD ; check if in table BCC 60$ ; Y- release old entry TST 2*4+PDSC ; P2 defined ? BNE 10$ ; Y- must load TST 3*4+PDSC+2 ; P3 with addr ? BEQ 50$ ; N- delete only 10$: ; insert new command MOV R2, R3 ; to entry after which to insert MOV LEN, R1 ; length of string BEQ 50$ ; ?? ADD #FTXT+1, R1 ; with overhead MOV #FREE, R0 CALL $RQCB ; request core block BCC 20$ ; ok MOV #NOPOOL, R0 ; No more Pool CALL IOMSG BR 50$ 20$: MOV (R3), (R0) ; link to previous entry BNE 30$ MOV R0, CMDB+2 ; we will be last one 30$: MOV R0, (R3) ; MOV R1, FLEN(R0) ; total length ADD #FTXT, R0 ; to start of text MOV #SAVB, R1 ; source MOV LEN, R2 ; length 40$: MOVB (R1)+, (R0)+ SOB R2, 40$ CLRB (R0) ; write delimiter 50$: SEC ; nothing to execute RETURN 60$: ; release old entry MOV (R0), (R2) ; link remainder BNE 70$ ; more entries MOV R2, CMDB+2 ; this was last one 70$: MOV FLEN(R0), R1 ; this length MOV R0, R2 MOV #FREE, R0 CALL $RLCB ; release it BR NEWCMD ; find more to release ; ; .SBTTL MCE - RECCMD - recall command from FIFO ; ; Recall Command from Fifo by key ; RECCMD: CLR -(SP) ; Save any Pointer to FIFO entry MOV FIFO, R4 ; Point to oldest Entry in Fifo BEQ 50$ ; empty MOV #NEW, R1 ; Source Buffer MOV #SAVB, R3 ; Destination Buffer SUB R1, R2 ; Length MOV R2, R5 ; Save it BGT 10$ ; non zero MOV FIFO+2,(SP) ; empty string - take previous entry BR 50$ ; from FIFO 10$: ; Store single char into SAVB MOVB (R1)+, R0 ; next char - convert to upper CALL CNVUPC ; check for delimiter MOVB R0, (R3)+ ; store char SOB R2, 10$ 20$: ; Check next entry in FIFO MOV #SAVB, R1 ; Source to Compare MOV R5, R2 ; Length of source MOV R4, R3 ; to entry ADD #FTXT, R3 ; to text of entry 30$: MOVB (R3)+, R0 ; next char BEQ 40$ ; EOL - no match CALL CNVUPC ; convert to uppercase CMPB R0, (R1)+ ; compare with source BNE 40$ ; no match SOB R2, 30$ ; match - try next char MOV R4, (SP) ; source exhausted - match found 40$: MOV (R4), R4 ; to next entry BEQ 50$ ; no more CMP R4, FIFPTR ; continue search ? BNE 20$ ; Y 50$: MOV (SP)+, FIFPTR ; Pop Pointer to entry if any CALL GEFIFO ; Load from FIFO (or delete NEW buffer) ; CLR FIFPTR ; initialize FIFO Ptr RETURN .SBTTL MCE - Intern - check for internal commands (EXIT/BYE) ; Check if the command (AFTER translation) is BYE or an internal ; command starting with the verb 'MCE '. ; To check for the special commands after translation offers the ; possibility to define any other string for exit/bye. ; (E.g.: LOGOF*F := BYE) ; Intern returns C clear, if no intern command, i.e. the buffer NEW ; has to be submitted to the CLI. ; C set on return, if internal command found, no CLI submit. ; .macro cmpuc src,what,action,label ; Compare upper case char .NCHR $$$$$L, .if gt $$$$$L-1 mov src,R0 bic #" ,R0 cmp R0,#"what .iff movb src,R0 bicb #' ,R0 cmpb R0,#''what .endc action label .endm ; INTERN: ; ; To be recognised as an internal command, at least 3 characters ; must be present. ; Internal commands trapped are: ; BYE : the RSX logout command ; MCE action: MCE internal actions ; JSR R5,.SAVR1 ; Save registers CMP LEN,#3 ; Did we receive "BYE" ? BLT 30$ ; No CMPUC NEW,BY,bne 29$ ; BY ? CMPUC NEW+2,E,bne 29$ ; E ? CLR WAITFL ; Do not wait CALL EXEC2 ; Submit BYE to CLI 28$: CALLR ExitS ; Immediate task exit 29$: CMPUC NEW,MC,bne 30$ ; MC ? CMPUC NEW+2,E,beq 40$ ; E ? 30$: CLC ; No internal command trapped RETURN ; ; Internal command strings must not be less than 8 characters in length ; Ignore anything else ; 40$: CMP LEN,#8. ; "MCE action?" BLT 80$ ; N BIC #" ,NEW+4 ; 'action' verb upper case BIC #" ,NEW+6 ; 4 characters MOV #INTCMD,r1 ; Point to internal command table 50$: TST (R1) ; End of table reached ? BEQ 80$ ; Y if eq: ignore command CMP NEW+4,(r1)+ ; First 2 characters match ? BEQ 60$ ADD #4,R1 ; Point to next table entry BR 50$ ; Look ahead 60$: CMP NEW+6,(r1)+ ; Second 2 characters match ? BEQ 70$ ; If eq Yes: action verb match TST (R1)+ ; Point to next table entry BR 50$ ; Look ahead 70$: CALL @(R1) ; EXECute internal command 80$: SEC ; Indicate internal command done RETURN .IF DF FILE ICREPL: CALL ICPURG ; Delete current translation table ; Fall through to ICREAD, adjacency assumed ICREAD: ; ; read commands from file specified ; TSTB FILINP ; Is a file open ? BEQ 10$ ; If eq no: just open new ; ; Close a file currently open, i.e. 'MCE READ' issued from ; inside a definition is equivalent to a 'MCE CHAIN' command ; CALL FILCLO ; Close current file 10$: MOV #NEW+4,r1 ; Point behind 'MCE ' MOV LEN,r2 ; Length of command SUB #4.,r2 ; Remaining # characters BLE 20$ ; No more: no file name CALL GETFIL ; Get new file name 20$: CALLR FILOP1 ; Read file(s) .IFF ;FILE RETURN .ENDC ;FILE ICpurg: ; ; delete current translation table ; 10$: MOV #CMDB,R0 ; Queue header for TR table CALL FRENT ; Delete table entry BCC 10$ ; Id C clear there may be more entries RETURN .IF DF FILE ; .SBTTL MCE - GETMCR - get filespecification from MCR command ; ; This subroutine dequeues the command which invokes MCE (if any), ; and overrides the default startup file name (MCEINI.xxx) by ; file specified in the commandline. ; Command line syntax is : 'MCE file_specification' ; .ENABL LSB GETMCR: DIR$ #GMCR ; Get commandline BCS 30$ MOV #GMCR+G.MCRB,R1 ; Point to commandline MOV $DSW,R2 ; Length of line GETFIL: ; ; reset FDB file-name pointers ; MOV #"LB,DEVINF ; Reset default file volume MOV #DIRL,FDIRL ; Restore pointer to [1,2]directory MOV #FDSPT,FDBIN+F.DSPT ; Reset DSPT pointer in FDB 10$: CMPB #40,(R1)+ ; Mnemonic delimiter ? BEQ 20$ DEC R2 ; Count remaining char BNE 10$ ; If eq: empty command RETURN 20$: CSI$1 #CSIBLK,R1,R2 ; Syntax check BCS 30$ ; Syntax error: ignore it CSI$2 R0,OUTPUT,#SWTBL ; Parse line into its com ; ; now we have a file descriptor table inside the CSI parser block ; override the default DSPT pointing to MCEINI.CMD: ; MOV #CSIBLK+C.DSDS,FDBIN+F.DSPT ; New DSPT pointer CLR FDIRL ; Indicate 'no more files 30$: RETURN .DSABL LSB .ENDC ;FILE .END START