.TITLE LISTEN - TTY SERVICE FOR TECOIO .IDENT "X0225" ; ; COPYRIGHT (C) 1976 BY DIGITAL EQUIPMENT CORPORATION, ; MAYNARD, MASSACHUSETTS ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A ; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH THE IN- ; CLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE, OR ; ANY OTHER COPIES THEREOF, MAY NOT BE PROVIDED OR OTHERWISE ; MADE AVAILABLE TO ANY OTHER PERSON EXCEPT FOR USE ON SUCH ; SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE ; TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN ; IN DIGITAL. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITH- ; OUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ; DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL EQUIPMENT CORPORATION ASSUMES NO RESPONSIBILITY FOR ; THE USE OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT WHICH IS ; NOT SUPPLIED BY DIGITAL. ; ; ANDREW C. GOLDSTEIN 10-APR-79 11:04 ; MARK H. BRAMHALL 29-MAR-79 13:34 .MCALL GET$,QIO$S,QIOW$S,QIOW$C,WSIG$S,DIR$ ;+ ; ; *** - LISTEN TTY INPUT ; ; THIS ROUTINE ACCEPTS INPUT FROM THE CONSOLE TTY AND RETURNS IT ; TO THE CALLER ONE CHARACTER AT A TIME. ; ; INPUTS: ; ; R0 = 0 DELIMITERS ARE ALTMODE, RUBOUT, CTRL/U, CTRL/G ; R0 >< 0 ALL CHARACTERS ARE DELIMITERS. ; ; OUTPUTS: ; ; R0 = CHARACTER (TRIMMED TO 7 BITS, NULLS SUPPRESSED) ; ; ALL OTHER REGISTERS ARE PRESERVED. ; ; ; *** - TLISTN TTY INPUT FOR CONTROL T ; ; THIS ENTRY IS IDENTICAL TO LISTEN, EXCEPT THAT THE CONTROL T ; CONTROL FLAGS IN ETYPE ARE INTERPRETED. ; ;- .PSECT CODE,RO,I .ENABLE LSB TLISTN:: MOV SP,R0 ; SET SINGLE CHAR MODE SAVE CLR R1 BIT #ET.NCH,ETYPE(R5) ; CHECK NO ECHO MODE BEQ 10$ ; BRANCH IF NO DEC R1 ; SET CTRL T NO ECHO MODE (R1 < 0) 10$: DECB R1 ; OR JUST CTRL T MODE (R1 LOW BYTE <> 0) BR GETNXT LISTEN:: SAVE CLR R1 ; SET NORMAL MODE (R1 = 0) GETNXT: DEC CMDFDB+F.NRBD ; BUMP DOWN RECORD CHARACTER COUNT BLT GETLIN ; BUFFER IS EMPTY BGT 20$ ; BRANCH IF THIS IS NOT THE LAST CHAR TST CMDFDB+F.BDB ; SEE IF A FILE IS REALLY OPEN BNE 20$ ; BRANCH IF YES TST CCLFLG ; NO - SEE IF COMMAND LINE IS WAITING BNE 20$ ; BRANCH IF YES CLR INDIR(R5) ; THIS IS LAST CHAR OF THE CCL COMMAND ; LINE. CLEAR THE FLAG NOW SO THAT THE ; NEXT REQUEST FOR INPUT WILL GIVE A PROMPT. 20$: CLR R0 BISB @CMDFDB+F.NRBD+2,R0 ; GET A CHARACTER INC CMDFDB+F.NRBD+2 ; BUMP RECORD POINTER BIC #^C177,R0 ; MASK GARBAGE OFF CHARACTER BEQ GETNXT ; FLUSH NULLS TST INDIR(R5) ; IF INPUT IS COMING FROM A FILE BNE RETCHR ; SKIP CHARACTER FILTERING .IF NE,TECTTY BIT #ET.LOC,ETYPE(R5) ; CHECK FOR LOWER CASE TYPE IN BNE 40$ ; IF SO, SKIP FILTERING CMP R0,#177 ; CHECK FOR RUBOUT BEQ 40$ ; YES - NO CONVERSION CMP R0,#175 ; CHECK FOR OLD ALT MODES BLO 30$ MOV #AM,R0 ; CONVERT 175, 176 TO STANDARD CODE 30$: CMP R0,#'A+40 ; CHECK FOR LOWER CASE BLO 40$ ; IS NOT CMP R0,#'Z+40 ; REALLY? BHI 40$ ; NOPE BIC #40,R0 ; CONVERT TO UPPER CASE .ENDC 40$: TSTB R1 ; SEE IF CONTROL T MODE BEQ RETCHR ; BRANCH IF NOT CMP R0,#CTRLC ; SEE IF CONTROL C WAS TYPED BNE RETCHR ; BRANCH IF NOT TSTB CTCFLG ; SEE IF JUST PROCESSED BY AST BNE RETCHR ; BRANCH IF YES BIT #ET.CC,ETYPE(R5) ; CHECK USER CTRL C INTERCEPT BNE 50$ ; BRANCH IF SET DECB TFLG+1(R5) ; SET ABORT BIT 50$: BIC #ET.CC,ETYPE(R5) ; CLEAR USER CTRL C INTERCEPT RETCHR: MOV R0,SR0(SP) ; PUT CHAR IN RETURNED R0 CLRB CTCXIT ; AND SAY NOT INTO CTRL C SEQUENCE RETURN ; ; LINE BUFFER IS EMPTY - GET A NEW ONE ; GETLIN: CLR CMDFDB+F.NRBD ; RESET RECORD BYTE COUNT MOV INDIR(R5),R0 ; CHECK IF INDIRECT FILE IS OPEN BEQ 110$ ; BRANCH IF NO TST F.BDB(R0) ; SEE IF ITS A REAL OPEN FILE BEQ 100$ ; BRANCH IF NOT ; ; WE GET HERE IF AN INDIRECT FILE IS OPEN ; GET$ R0 ; READ A RECORD BCC 60$ CALL INDER1 ; CHECK UP ON THE ERROR BR GETNXT ; AND RETRY 60$: MOV F.NRBD+2(R0),R2 ; POINT TO START OF RECORD ADD F.NRBD(R0),R2 ; POINT TO END OF RECORD CMP @F.BDB(R0),#IS.ESC ; SEE IF I/O TERMINATED WITH ALT MODE BNE 70$ ; BRANCH IF NO MOVB #AM,(R2)+ ; PUT ALT MODE IN RECORD INC F.NRBD(R0) ; AND COUNT IT BR GETNXT 70$: BITB #FD.CR!FD.FTN,F.RATT(R0) ; SEE IF INPUT NEEDS CRLF BEQ GETNXT ; BRANCH IF NO TST F.NRBD(R0) ; NULL RECORD? BEQ 80$ ; YES, ALWAYS ADD CRLF CMPB -(R2),#AM ; END WITH ESACPE? BEQ GETNXT ; YEP, NO CRLF CMPB (R2)+,#FF ; END WITH HIGHER THAN FORM FEED? BHI 80$ ; YES, GO ADD CRLF CMPB -1(R2),#LF ; END WITH LF, VT, OR FF ? BHIS GETNXT ; YEP, NO CRLF 80$: MOVB #CR,(R2)+ ; YES - APPEND CR MOVB #LF,(R2)+ ; AND LF ADD #2,F.NRBD(R0) ; AND COUNT THEM 90$: BR GETNXT ; GET CHAR FROM BUFFER 100$: CLR INDIR(R5) ; END OF FAKED COMMAND LINE 110$: TSTB CCLFLG ; SEE IF COMMAND LINE IS PENDING BEQ REDLIN ; BRANCH IF ALREADY USED MOV #CCLPRL,CMDFDB+F.NRBD ; GET BYTE COUNT OF COMMAND TO PROCESS MOV #CCLPRC,CMDFDB+F.NRBD+2 ; GET ADDRESS OF COMMAND CLRB CCLFLG ; MARK AS USED - ONCE ONLY MOV #CMDFDB,INDIR(R5) ; TURN ON INDIRECT MODE BR 90$ ; ; TO HERE IF INPUT MUST BE READ FROM THE TERMINAL ; REDLIN: MOV CMDFDB+F.URBD+2,R4 ; GET ADDR OF RECORD BUFFER MOV R4,CMDFDB+F.NRBD+2 ; AND RESTORE FOR READING .IF NE,TECTTY MOV CMDFDB+F.URBD,R3 ; GET BUFFER LENGTH MOV #IO.RST,R2 ; ASSUME NORMAL TECO MODE READ TST SR0(SP) ; CHECK TYPE IN MODE BEQ 120$ ; BRANCH IF NORMAL MOV #1,R3 ; SINGLE CHAR TYPE IN TST R1 ; SEE IF CTRL T NO ECHO BGE 120$ ; BRANCH IF NO MOV #IO.RAL!IO.RNE,R2 ; SET READ NO ECHO MODE 120$: .IFF MOV #IO.RAL!IO.RNE,R2 ; SET READ NO ECHO, PASS ALL MOV #1,R3 ; AND BUFFER LENGTH OF ONE .ENDC TSTB R1 ; SEE IF CTRL T MODE BEQ 160$ ; BRANCH IF NOT BIT #ET.CKE,ETYPE(R5) ; SEE IF CONDITIONAL TYPE IN BEQ 160$ ; BRANCH IF NOT CMPB OPSYS,#5 ; ARE WE RUNNING ON VMS? BEQ 130$ ; BRANCH IF YES ; DUE TO APPARENT RACE CONDITION PROBLEMS IN ; THE 11D/IAS TERMINAL DRIVER, PUNT THE ; CONDITIONAL TYPE-IN IN THESE SYSTEMS CMPB OPSYS,#0 ; HOW ABOUT 11D? BEQ 150$ CMPB OPSYS,#3 ; IAS, MAYBE? BEQ 150$ ; YES CLRB TYPAHD+1 ; ELSE MUST BE 11M - READ TYPE AHEAD COUNT QIOW$C SF.GMC,TTYLUN,TTYEFN,,IOSTAT,,,CODE BCS 150$ ; BRANCH ON FAILURE - ASSUME EMPTY TSTB IOSTAT ; ALSO CHECK I/O STATUS BMI 150$ TSTB TYPAHD+1 ; SEE IF TYPE AHEAD IS NON-EMPTY BEQ 150$ ; BRANCH IF NOT BR 160$ ; ELSE GO DO READ 130$: QIO$S R2,#TTYLUN,,,#IOSTAT,, ; ATTEMPT ASYNCHRONOUS READ BCS 170$ ; NO NODE FAILURE?? TSTB IOSTAT ; SEE IF IT COMPLETED IMMEDIATELY BNE 180$ ; BRANCH IF YES 140$: QIOW$S #IO.KIL,#TTYLUN,#KILEFN ; ELSE CANCEL THE I/O BCS 140$ ; UNTIL REALLY DONE... CALL TTDET ; I/O KILL DETACHES THE TERMINAL CALL TTATT ; BUT NOT SO THE VAX CME NOTICES MOVB IOSTAT,R0 ; GET THE I/O STATUS CODE BEQ 140$ ; STILL PENDING? BGT 180$ ; IT COMPLETED - GO HANDLE COMPLETION CMPB R0,#IE.EOF ; EOF *****VAX BUG?***** BEQ 180$ ; YEP... 150$: MOV #-1,R0 ; KILLED JMP RETCHR ; SO RETURN NO INPUT STATUS (-1) 160$: QIOW$S R2,#TTYLUN,#TTYEFN,,#IOSTAT,, ; DO STALLING READ BCC 180$ ; O.K... 170$: WSIG$S ; WAIT FOR NODES BR REDLIN ; AND TRY AGAIN 180$: TSTB CTCFLG ; WAS CONTROL C TYPED DURING READ? BEQ 190$ ; BRANCH IF NOT MOV #1,IOSTAT ; FAKE NORMAL COMPLETION MOV #1,IOSTAT+2 ; WITH 1 BYTE READ (ALREADY ECHOED) MOVB #CTRLC,(R4) ; WHICH IS, IN FACT, CONTROL C 190$: MOV IOSTAT+2,R3 ; GET BYTE COUNT OF READ .IF NE,TECTTY CMP R2,#IO.RST ; CHECK IF READ ECHOED BNE 220$ ; BRANCH IF NOT BIS #2,OUTDNE(R5) ; FLAG CHARACTERS ECHOED (+2) ADD R3,TABCNT ; ADJUST CURSOR FOR ECHOED CHARACTERS 210$: CMP TABCNT,TTLNSZ ; SEE IF A LINE WRAP OCCURRED BLE 230$ ; BRANCH IF NO SUB TTLNSZ,TABCNT ; TRACK IT BR 210$ ; AND CONTINUE 220$: MOVB (R4),R0 ; ALWAYS TREAT CHAR AS TERMINATOR FOR FILTERING DEC R3 ; COUNT IS EITHER 0 OR 1 BEQ 240$ ; BRANCH IF WAS 1 CLR R3 ; ELSE CHAR IS IN TERMINATOR 230$: ADD R3,R4 ; POINT TO END OF BUFFER .ENDC MOVB IOSTAT+1,R0 ; GET TERMINATOR, IF ANY 240$: TSTB IOSTAT ; CHECK I/O STATUS BPL 260$ ; BRANCH IF OK CMPB IOSTAT,#IE.EOF ; CHECK FOR EOF, WHICH IS CTRL Z BEQ 250$ ; BRANCH IF YES BR 170$ ; RETRY ON ANY ERROR 250$: MOVB #CTRLZ,R0 ; CONVERT EOF TO CONTROL Z 260$: BIC #^C177,R0 ; SEE IF THERE WAS A TERMINATOR .IF NE,TECTTY BEQ 320$ ; BRANCH IF NOT MOVB R0,(R4)+ ; STORE THE TERMINATOR IN THE BUFFER INC R3 ; AND COUNT IT .IFF BEQ 270$ ; BRANCH IF NOT MOVB R0,(R4) ; STORE THE TERMINATOR IN THE BUFFER INC R3 ; AND COUNT IT 270$: BICB #^C177,(R4) ; MAKE SURE CHAR IS CLEAN BIT #ET.LOC,ETYPE(R5) ; CHECK FOR LOWER CASE TYPE IN BNE 290$ ; IF SO, SKIP FILTERING CMPB (R4),#177 ; CHECK FOR RUBOUT BEQ 290$ ; YES - NO CONVERSION CMPB (R4),#175 ; CHECK FOR OLD ALT MODES BLO 280$ MOVB #AM,(R4) ; CONVERT 175, 176 TO STANDARD CODE 280$: CMPB (R4),#'A+40 ; CHECK FOR LOWER CASE BLO 290$ ; IS NOT CMPB (R4),#'Z+40 ; REALLY? BHI 290$ ; NOPE BICB #40,(R4) ; CONVERT TO UPPER CASE 290$: MOVB (R4)+,R0 ; GET CHAR IN R0, REGARDLESS, FOR ECHO .ENDC CMPB R0,#RUB ; CHECK IF IT WAS RUBOUT BEQ 320$ ; IF SO, DON'T ECHO TST R1 ; SEE IF CONTROL T NO ECHO BLT 300$ ; BRANCH IF ECHO SUPPRESSED ;MOV ??,R4 ; R4 IS <> 0 MOV R0,-(SP) ; SAVE CHAR CALL TYPEC ; ELSE ECHO IT CMPB (SP)+,#CTRLC ; WAS CONTROL-C TYPED IN? BNE 300$ ; BRANCH IF NOT CALL CRLF ; THEN ECHO WITH CRLF 300$: CMPB -1(R4),#CR ; SEE IF TERMINATOR WAS CR BNE 310$ ; BRANCH IF NOT MOVB #LF,R0 ; YES - APPEND LF MOVB R0,(R4)+ ; INTO THE BUFFER INC R3 ; COUNT IT TST R1 ; CHECK IF ECHO SUPPRESSED BLT 320$ ; BRANCH IF YES ;MOV ??,R4 ; R4 IS <> 0 CALL TYPEC ; ELSE ECHO IT 310$: CALL TYPENC ; FLUSH THE ECHO(ES) 320$: CMPB -(R4),#CTRLC ; WAS CONTROL-C TYPED? BNE 330$ ; BRANCH IF NOT TSTB R1 ; SEE IF CONTROL T MODE BNE 330$ ; BRANCH IF SO COMB CTCXIT ; YEP, 2ND CTRL C IN A ROW? BEQ 340$ ; 2ND CTRL C EXITS TECO JMP TECO ; 1ST CTRL C JUST RESTARTS TECO 330$: CMPB (R4),#CTRLZ ; WAS CONTROL-Z TYPED? BNE 350$ ; BRANCH IF NOT CMP R3,#1 ; WAS IT THE ONLY THING TYPED? BEQ 335$ ; BRANCH IF YES CLRB CTZCNT ; ELSE CLEAR THE CONTROL Z COUNT 335$: INCB CTZCNT ; BUMP THE CONTROL Z COUNT CMPB CTZCNT,#3 ; SEE IF 3 CONTROL-Z'S IN A ROW BLO 360$ ; BRANCH IF NOT 340$: JMP TEXIT ; YES - WE ARE STUCK ON EOF - GET OUT 350$: CLRB CTZCNT ; NOT CONTROL Z - CLEAR THE COUNT 360$: MOV R3,CMDFDB+F.NRBD ; STORE THE RECORD BYTE COUNT JMP GETNXT ; AND FINALLY GO GET A CHARACTER FOR TECO .DSABL LSB .END