.TITLE AUXIO - AUX I/O Routines .IDENT /1.1/ .ENABL LC ;+ ; ; Free software BY ; Project Software & Development, Inc. ; ; This software is furnished for free and may be used and copied as ; desired. This software or any other copies thereof may be provided or ; otherwise made available to any other person. No title to and ; ownership of the software is hereby transferred or allowed. ; ; The information in this software is subject to change without notice ; and should not be construed as a commitment by PROJECT SOFTWARE ; AND DEVELOPMENT, INC. ; ; PROJECT SOFTWARE assumes no responsibility for the use or reliability ; of this software on any equipment whatsoever. ; ; Project Software & Development, Inc. ; 14 Story St. ; Cambridge, Ma. 02138 ; 617-661-1444 ; ; ; Title: AUXIO.MAC ; Author: Robin Miller ; Date: July 23, 1985 ; ; Description: ; ; This module contains the routines for the terminal I/O. ; ; Modification History: ; ; November 26, 1985 by Robin Miller. Edit (01), Version 1.1 ; Properly check for an escape sequence being typed. Previously, ; another character had to be typed following an escape character. ; ;- .ENABL AMA .NLIST BEX .MCALL DIR$, QIOW$S, GET$, mrkt$s, clef$s, cmkt$s .psect rwdata,rw,d,lcl,rel,con ; Local definitions: ESCDLY = 15. ; Escape clock ticks delay. ; ; The Read-with-termination table function (IO.RTT) allows control ; characters and space to terminate the read. ; TTABLE: .WORD -1 ; Terminate on all (00-15) .WORD -1 ; control characters (16-31) .WORD 1 ; (32-47) .WORD 0 ; (48-63) .WORD 0 ; (64-79) .WORD 0 ; (80-95) .WORD 0 ; (96-111) .WORD 100000 ; and the delete key. (112-127) .BLKW 8. ; Remaining table zero. BUFSAV::.WORD 0 ; The starting buffer address. BUFCNT::.WORD 0 ; The remaining buffer byte count. BUFSIZ::.WORD 0 ; The maximum input buffer size. .psect code,ro,i,lcl,rel,con .ENABL LC .ENABL AMA .SBTTL GETCMD - Get a command from the user. ;+ ; ; GETCMD - Gets a command from the user. ; ; This routine is used to read a command from the user. ; ; Inputs: ; R0 = The buffer address. ; R1 = The buffer size. ; ; Implicit Inputs: ; CMDEND = The command line length (0=new command). ; ; Outputs: ; C bit ; ; R0 = The buffer address (string terminated by NULL). ; R1 = The input byte count. ; Does not include escape sequence size (if any). ; ; All other registers are preserved. ; ;- GETCMD::JSR R5,$SAVRG ; Save R3 - R5. MOV R0,BUFSAV ; Save starting buffer address. MOV R1,BUFSIZ ; Save the original buffer size. MOV R1,BUFCNT ; Init. remaining buffer count. BIC #B.ESQ,STATUS ; Init escape sequence seen flag. ; Check for editing of an existing command. 10$: TST CMDEND ; Is there an existing command ? BEQ 40$ ; If EQ, no. MOV CMDEND,R1 ; Copy end of command line. SUB R1,BUFCNT ; Adjust remaining buffer size. CMP CMDPTR,R1 ; Pointing at end of command ? BEQ 30$ ; If EQ, yes (do normal read). 20$: CALL DOREAD ; Do single character reads. ; BCS 120$ ; If CS, we've had an error. ; BR 50$ ; Else, use common code ... bcc 50$ ; if ok, use common code jmp 120$ ; else do error thing 30$: ADD CMDPTR,R0 ; Point to end of command line. 40$:; mov r5,-(sp) ;save reg ; mov .crtsk,r5 ;get my ti PUD ; mov a.ti(r5),r5 ; cmp u.dn(r5),#"HT ;running on network ? ; beq 411$ ;if so, must not do read with timeout ; cmp r0,bufsav ; is this a full line read ? ; beq 41$ ; if so, do read with timeout 411$: QIOW$S #IO.RTT,#TOLUN,#TOEFN,,#TIOSB,, ; br 42$ ; else do normal read ;41$: QIOW$S #IO.RTT!tf.tmo,#TOLUN,#TOEFN,,#TIOSB,, 42$: CALL CHKERR ; Check/report any errors. BCC 43$ ; br if went ; mov (sp)+,r5 ; else restore r5 jmp 120$ ; If CS, treat this as fatal. 43$:; mov (sp)+,r5 ; restore used reg ; cmpb tiosb,#2 ; did we time out on read ? ; bne 45$ ; no, treat normally ; call getmes ; yes, go for messages ; mov #1,clrflg ; show that 3 top lines are cleared ; br 40$ ; go again, (losing anything typed) 45$: MOV BUFSAV,R0 ; Set the starting buffer address. ADD TIOSB+2,CMDEND ; Accumulate the line length. SUB TIOSB+2,BUFCNT ; Calculate remaining byte count. MOV CMDEND,R1 ; Copy the current byte count. MOV R1,CMDPTR ; Set the command line pointer. ; ; On VMS, the terminator is stored in the buffer. On RSX, it isn't. ; MOV R0,R5 ; Copy the input buffer address. ADD R1,R5 ; Point to end of input buffer. MOVB TIOSB+1,(R5) ; Store terminator in buffer. ; Check for the various control keys. 50$: TST BUFCNT ; Terminated by buffer full ? BEQ 100$ ; If EQ, yes (we're done). MOVB (R5),R3 ; Copy the terminating byte. ; Check for start of an escape sequence. CMPB #ESC,R3 ; Is this an escape character ? BNE 60$ ; If NE, no (continue ...) CALL CHKESQ ; Check for an escape sequence. BCC 70$ ; If CC, we found one. ; A carriage return always terminates the command line. 60$: CMPB #CR,R3 ; Carriage return the terminator ? BEQ 100$ ; If EQ, yes (this terminates input). 70$: CALL GETKEY ; Get the control key definition. BCC 90$ ; If CC, the key is defined. 80$: CALL VALCTR ; Validate the control character. ;*** BCS 40$ ; If CS, disgard this character. 90$: BIT #B.EXIT,STATUS ; Does the user want to exit ? BNE 110$ ; If NE, yes. MOV CMDEND,R1 ; Copy the command line size. BIT #S.TERM,KEYSTA ; Terminate the command line ? BNE 110$ ; If NE, yes. CMP R1,BUFSIZ ; Terminated by buffer full ? BGE 110$ ; If GE, yes (end of this read). MOV BUFSIZ,BUFCNT ; Copy the input buffer size. SUB R1,BUFCNT ; Calculate remaining byte count. TST CMDEND ; Is there a command line ? BEQ 40$ ; If EQ, no (normal read). CMP CMDPTR,R1 ; In middle of a command line ? ; BNE 20$ ; If NE, yes. beq 91$ ; br if not jmp 20$ 91$: ADD R1,R0 ; Set next input buffer address. ; BR 40$ ; And go read some more input. jmp 40$ ; And go read some more input. ; Terminate the command line with a NULL. 100$: CLRB (R5) ; Terminate input with a null. 110$: CLC ; Show successful input. BR 130$ ; And use common return ... ; ; We come here on directive or I/O errors. ; 120$: MOV #EX$SEV,R0 ; Set severe status code. JMP EXST ; And exit with the status. 130$: RETURN .SBTTL DOREAD - Do a single character read. ;+ ; ; DOREAD - Do a single character read. ; ; This routine is called when the command pointer is somewhere in the ; middle of a command line. In this case, we must read into a different ; buffer and later determine if we are overprinting or inserting the new ; string into the command line. ; ; Inputs: ; R0 = The starting buffer address. ; R1 = The current command line size. ; ; Implicit Inputs: ; CMDPTR = The command line pointer (index). ; ; Outputs: ; C bit clear/set = success/failure on read. ; ; R1 = The command line size. ; R3 = The terminating character. ; R5 = Points to end of command line. ; ;- DOREAD:: MOV CMDPTR,R2 ; Copy the starting byte count. ADD R2,R0 ; Index into the command line. 10$: QIOW$S #IO.RAL!TF.RNE,#TOLUN,#TOEFN,,#TIOSB,,<#TMPBUF,#1> CALL CHKERR ; Check/report any errors. BCS 100$ ; If CS, we've had an error. MOVB TMPBUF,R3 ; Copy the character input. CMP R3,#SPACE ; Is this a control key ? BLT 20$ ; If LT, yes CMP R3,#DEL ; Is this a delete character ? BEQ 20$ ; If EQ, yes. ; Check for insert or overprint mode. BIT #B.IMOD,SWMASK ; Are we in insertion mode ? BEQ 15$ ; If EQ, no (overprint). CALL INSCHR ; Insert character in command. BR 17$ ; And use common code ... 15$: CALL TYPCHR ; Display this character. MOVB R3,(R0)+ ; Overprint character for now. 17$: INC R2 ; Increment the buffer pointer. DEC BUFCNT ; Adjust remaining buffer count. BGT 10$ ; If GT, get another character. ; Check for new line longer than the previous. 20$: MOV R2,CMDPTR ; Set the new command pointer. CMP R2,CMDEND ; Past end of previous line end ? BLE 30$ ; If LE, no. MOV R2,CMDEND ; Yes, set new ending address. ; Setup the registers for use by the mainline. 30$: MOV BUFSAV,R0 ; Set starting buffer address. MOV CMDEND,R1 ; Copy the command line length. MOV R0,R5 ; Copy the starting buffer addr. ADD R1,R5 ; Point to end of command line. MOVB R3,(R5) ; Put terminating byte in buffer. CLC ; Show successful read. 100$: RETURN .SBTTL CHKESQ - Check for an escape sequence. ;+ ; ; CHKESQ - Check for an escape sequence. ; ; This routine is called after an escape character is detected. The ; routine calls the wait-a-bit routine to wait for additional characters ; to indicate whether this is an escape sequence. If there are, we read ; the next two characters and set the status code to indicate an escape ; sequence was read. This method appears to work on RSX-11M/M+ & VMS. ; ; Inputs: ; R5 = The ending buffer address. ; ; Outputs: ; C bit clear/set = escape sequence/no escape sequence. ; ; TIOSB = Filled with IS.ESQ for escape sequence. ; B.ESQ in STATUS flag is set true. ; ;- CHKESQ::CALL $SAVAL ; Save all registers. ; Sit in a delay loop waiting for escape sequence. MOV #ESCDLY,R2 ; Retry up to this limit. 10$: MOV #1,R0 ; Wait for 1 MOV #TICKS,R1 ; clock tick. CALL DELAY ; Do the delay. CALL GTYPAH ; Get the typeahead count --> R1. BCS 20$ ; If CS, nothing in typeahead. (01) CMP R1,#2 ; Do we have remaining bytes ? BHIS 30$ ; If HIS, yes. (01) 20$: SOB R2,10$ ; Loop until limit reached. SEC ; Show no escape sequence read. BR 100$ ; Use common return ... 30$: MOV #2,R1 ; Only read one escape sequence. CLRB (R5)+ ; Clear the escape character. QIOW$S #IO.RNE,#TOLUN,#TOEFN,,#TIOSB,, ; Read escape seq. CALL CHKERR ; Check/report any errors. BCS 100$ ; If CS, we've had an error. MOV #IS.ESQ,TIOSB ; Show escape sequence read. BIS #B.ESQ,STATUS ; Show an escape sequence found. 100$: RETURN .SBTTL GETONE - Read one character. ;+ ; ; GETONE - Read one character. ; ; This routine is used to read a single character from the user. ; ; Inputs: ; R0 = The input buffer address. ; ; Outputs: ; C bit clear/set = success/failure. ; ;- GETONE::JSR R5,$SAVRG ; Save R3 - R5. QIOW$S #IO.RAL!TF.RNE,#TOLUN,#TOEFN,,#TIOSB,, CALL CHKERR ; Check/report any errors. BCS 100$ ; If CS, we've had an error. ; If character entered is an escape, check for escape sequence. CMPB #ESC,(R0) ; Is this an escape character ? BNE 100$ ; If NE, no. MOV R0,R5 ; Setup input to the routine. CALL CHKESQ ; Check for an escape sequence. 100$: RETURN .SBTTL TYPCHR - Display a control character. ;+ ; ; TYPCHR - Display a control character. ; ; Inputs: ; R3 = The control character to display. ; ; Outputs: ; All registers are preserved. ; ;- TYPCHR::CALL $SAVAL ; Save all registers. MOV #FMTBUF,R0 ; Set the output buffer address. CALL DOCHAR ; Copy/format this character. JMP VTYPE ; And display at the terminal. .SBTTL WABIT - Wait for a little while. ;+ ; ; WABIT - Wait for a little while. ; ; This routine is called after an invalid or partial escape sequence is ; detected to wait for additional characters arriving from the escape ; sequence. If we don't wait for a short while on VT102 terminals, the ; clearing of the typeahead buffer doesn't discard the extra characters. ; It appears the VT102 terminals send the escape sequence at a slower ; rate than a normal VT100 terminal. ; ; Inputs: ; None. ; ; Outputs: ; All registers are preserved. ; ;- WABIT:: JSR R2,$SAVVR ; Save R0 - R2. MOV #ESCDLY,R0 ; Wait a few MOV #TICKS,R1 ; clock ticks. JMP DELAY ; Do delay and return. .SBTTL WRITE - Write a message to the terminal. ;+ ; ; WRITE - Write a message to the terminal. ; ; This routine is used to write a message terminated by null to the ; terminal. It also makes sure that writes do not exceed 512 bytes ; in length. This is done becuase one of the VMS sysgen parameters ; prevents us from writing the entire message all at once. RSX-11M ; allows us to write up to 8128 bytes in length with one QIO. ; ; Inputs: ; R4 = Message address terminated by NULL. ; ; Outputs: ; All registers are preserved. ; ;- WRITE:: CALL $SAVAL ; Save all registers. MOV R4,R0 ; Copy the buffer address. CALL GETLEN ; Calculate the length --> R1. MOV #8128.,R3 ; Setup the maximum write size. CLR R2 ; Presume a single write. 10$: CMP R1,R3 ; Is the length too large ? BLE 20$ ; If LE, no (write it). ; The length is too big, adjust into smaller length. MOV R1,R2 ; Save the message length. MOV R3,R1 ; Set the maximum message length. 20$: CALL WRITIT ; Write the message. BCS 100$ ; If CS, we had an error. TST R2 ; Is there any more to write ? BEQ 100$ ; If EQ, no (we're all done). ; Adjust the buffer address and the message length. ADD R1,R0 ; Yes, adjust the buffer address SUB R1,R2 ; and the message length. MOV R2,R1 ; Set the new message length. BR 10$ ; And continue ... 100$: RETURN .SBTTL WRITIT - Write a message to the terminal. ;+ ; ; WRITIT - Write a message to the terminal. ; ; Inputs: ; R0 = The buffer address. ; R1 = The buffer byte count. ; ; Outputs: ; Carry clear/set = success/failure. ; ; All registers are preserved. ; ;- WRITIT::QIOW$S #IO.WAL!TF.CCO,#TOLUN,#TOEFN,,#TIOSB,, CALL CHKERR ; Check/report any errors. RETURN .SBTTL GET - Get record from the input file. ;+ ; ; GET - Get next record from the input file. ; ; This routine gets the next record from the input file. ; ; Inputs: ; R5 = The file entry address. ; ; Outputs: ; C bit clear/set = success/failure. ; R1 = The record buffer address. ; R2 = The record byte count. ; ; All other registers are preserved. ; ;- GET:: MOV R0,-(SP) ; Save R0. MOV O.FDB(R5),R0 ; Copy the FDB address. GET$ R0 ; Get the next record. BCS 90$ ; If CS, we've has an error. ; Record read, copy the record address and byte count. MOV F.NRBD+2(R0),R1 ; Copy the record buffer address MOV F.NRBD(R0),R2 ; and the record byte count. BR 100$ ; Use common return ... ; Report the error message unless error is end of file. 90$: CMPB F.ERR(R0),#IE.EOF ; Was the error end of file ? BEQ 95$ ; If EQ, yes (expected error). CALL FCSERR ; Report the error message. 95$: SEC ; Show failure ... 100$: MOV (SP)+,R0 ; Restore R0. RETURN .END