! FILE 'BTT7S'
!**************
!* BTT7S *
!*DA:24.FEB.81*
!**************
CONTROL K'100001'; ! 'SYSTEM' PROGRAM (FAST ROUTINE ENTRY/EXIT)
PERMROUTINESPEC SVC(INTEGER EP, P1, P2)
BEGIN
SYSTEMINTEGERFNSPEC MAP VIRT(INTEGER ID, FROM SEG, TO SEG)
SYSTEMROUTINESPEC MAPHWR(INTEGER SEGS)
SYSTEMROUTINESPEC LINKIN(INTEGER SER)
RECORDFORMAT PF(BYTEINTEGER SERVICE, REPLY, C
INTEGER A1, A2, A3)
RECORDFORMAT TTF(INTEGER KBS, KBD, TTS, TTD)
RECORDFORMAT BUFF(INTEGER PT, LAST, BYTEINTEGERARRAYNAME B)
RECORDFORMAT BUFFX(INTEGER PT, LAST, ARRAYPT)
CONSTRECORD (BUFFX) NAME NULL = 0
CONSTINTEGER RUBOUT=K'177'
CONSTINTEGER CAN=24
CONSTINTEGER CR=13
CONSTINTEGER BELL=7
CONSTINTEGER ESC=K'33'
CONSTINTEGER SI=K'17'; ! SHIFT INTO LOWER MODE (CTRL O)
CONSTINTEGER SO=K'16'; ! SHIFT OUT (CTRL N)
CONSTINTEGER DLE=K'20'; ! (CTRL P)
CONSTINTEGER EOT = K'04'; ! EOF (CTRL D)
CONSTINTEGER DC1=K'21'; ! CANCEL OUTPUT (CTRL Q)
CONSTINTEGER TAB = 9; ! TAB (IMPLEMENTED AS 3 SPACES)
OWNRECORD (TTF) NAME TT=K'137560'
OWNINTEGER KBINT=-2
OWNINTEGER TTINT=-1
OWNINTEGER TTSER=1; ! ???
OWNINTEGER CLIID=2
OWNINTEGER TT STATUS=0, UPPER=32, TT IDLE=0, E PT=0, EFPT=0
RECORD (PF) P2
OWNRECORD (PF) NAME P
CONSTINTEGER NO OF SPECS = 6
OWNBYTEINTEGERARRAY SPECS(0:NO OF SPECS) =
RUBOUT, CAN, ESC, CR, SI, SO, TAB
CONSTINTEGER ECHO OFF = 10; ! COMMAND TO PUT ECHO OFF
INTEGER CHAR, I, IN MODE, E LAST, ECHOFL
INTEGER OUTID, SEG, CLI FLAG, CID, CADR
OWNRECORD (BUFF) OUT, INH
RECORD (BUFFX) NAME BUFX, INX
RECORDFORMAT HF(RECORD (HF) NAME H, RECORD (PF) P)
RECORDFORMAT QF(RECORD (HF) NAME H)
OWNRECORD (HF) ARRAY HA(0:15)
OWNRECORD (HF) NAME H
OWNRECORD (QF) HI, HO
OWNRECORD (QF) FREE
OWNINTEGER FIRST, LAST, CURR
OWNBYTEINTEGERARRAY BUFFER(0:255)
OWNBYTEINTEGERARRAY ECHOB(1:40)
SWITCH INS(0:NO OF SPECS), STATE(0:7)
ROUTINESPEC DRIVE TT(INTEGER CHAR)
ROUTINESPEC ECHO(INTEGER X)
ROUTINESPEC ECHO BELL
ROUTINESPEC TRANSFER INPUT
ROUTINESPEC OUTPUT REPLY
ROUTINESPEC PLANT(INTEGER N)
!! %CONSTBYTEINTEGERARRAY CANM(0:3)= 3, '#', CR, NL
!! %CONSTBYTEINTEGERARRAY CLIM(0:3)= 3, '<', 8, '>'
CONSTINTEGER MYSEG=4, MSA=K'100000'
CONSTINTEGER MYISEG=3, MISA=K'060000'
MAPHWR(5); ! MAP REGS TO SEG 5
LINKIN(TTSER); LINKIN(KBINT); LINKIN(TTINT)
TT_KBS=K'100'
BUFX==OUT
INX==INH
CYCLE I = 15, -1, 0
PUSH(FREE, HA(I))
REPEAT
CYCLE
IF OUTID=0 AND NOT HO_H == NULL START
H == POP(HO); PUSH(FREE, H)
P == H_P
ELSE
P == P2
P_SERVICE = 0
POFF(P)
FINISH
IF P_SERVICE=KBINT&X'FF' START
CHAR=TT_KBD&127; ! STRIP PARITY BIT
CYCLE I=NO OF SPECS, -1, 0
->INS(I) IF CHAR=SPECS(I)
REPEAT
!! NORMAL CHAR
IF CHAR>='A'+K'40' AND CHAR<='Z'+K'40' THENC
CHAR=CHAR-UPPER; ! TURN TO UPPER
PLANT(CHAR)
CONTINUE
INS(0): ! RUBOUT
IF LAST#CURR START
LAST = (LAST-1)&255
ECHO('¬')
ELSE ECHO BELL
CONTINUE
INS(1): ! CANCEL
IF LAST#CURR START
LAST = CURR
ECHO('#'); ECHO(CR); ECHO(NL); E LAST=E PT
ELSE ECHO BELL
CONTINUE
INS(2): ! ESCAPE - GO TO CLI
CLI FLAG = 1
LAST = 0; CURR = 0; FIRST = 0
INS2: ECHO('<'); ECHO(13); ECHO('>')
CONTINUE
INS(4): ! SHIFT IN
UPPER = 0; CONTINUE
INS(5): ! SHIFT OUT
UPPER = 32; CONTINUE
INS(6): ! TAB
PLANT(' '); PLANT(' '); PLANT(' '); CONTINUE
INS(3): ! CR
ECHOFL = 0; ! ECHO TURNED ON AT NL
PLANT(NL); CURR = LAST
TRANSFER INPUT
E LAST=E PT; ! ALLOW IT TO DO OUTPUT NOW
ELSE IF P_SERVICE=TT INT&X'FF' START
->STATE(TT STATUS)
DO OUT:
STATE(5): ! GOING IDLE
TT STATUS=0
IF E PT>0 THEN TT STATUS=2 ELSESTART
IF OUT_LAST#0 THEN TT STATUS=1
FINISH
->STATE(TT STATUS)
STATE(1): ! NORMAL OP
CHAR=OUT_B(OUT_PT); OUT_PT=OUT_PT+1
IF OUT_PT>=OUT_LAST THEN TT STATUS=5 AND OUTPUT REPLY
DRIVE TT(CHAR)
STATE(0): CONTINUE
STATE(2): ! ECHO OP
IF EFPT<E PT START
EFPT=EFPT+1
CHAR=ECHOB(EFPT)
IF EFPT=E LAST THEN TT STATUS=5 AND E LAST=-1
DRIVE TT (CHAR)
ELSE
TT STATUS = 6
IF EFPT=E LAST START
E LAST=-1; E PT=0; EFPT=0
->DO OUT
FINISH
FINISH
IF EFPT=E PT THEN E PT=0 AND EFPT=0
CONTINUE
STATE(3): ! NORMAL CR
STATE(4): ! ECHO CR
STATE(7): ! END OF LINE - NEWLINE
TT STATUS=5
DRIVE TT(NL+128)
CONTINUE
STATE(6): ! IN ECHO LINE
CYCLE ; REPEAT
ELSE IF P_SERVICE=TT SER START ; ! USER REQUEST
IF P_A1=1 START ; ! OUTPUT REQUEST
IF OUTID#0 START
H == POP(FREE)
IF H == NULL START
REJ: P_SERVICE= P_REPLY; P_REPLY = TT SER
P_A1 = 1; PON(P)
CONTINUE
FINISH
H_P = P; ! COPY P INTO SAFE PLACE
PUSH(HO, H); ! AND QUEUE IT
CONTINUE
FINISH
OUTID=P_REPLY
SEG=P_A2>>13; ! SEG NO OF BUFFER
I = MAP VIRT(OUTID, SEG, MY SEG)
CONTINUE IF I = 0
BUFX_ARRAYPT=MSA+(P_A2&K'17777')
OUT_PT=0; OUT_LAST=P_A3; ! LENGTH
IF OUT_LAST=0 THEN OUTPUT REPLY ELSESTART
->DO OUT IF TT STATUS=0; ! TT IDLE
FINISH
ELSE
!! INPUT REQUEST
IF P_A1 = ECHO OFF THEN ECHO FL = ECHO FL+1 ANDCONTINUE
IF P_A1 # 0 START
CID = P_REPLY; CADR = P_A2
CONTINUE IF P_A3 # 0; ! JUST READ FROM CLI
FINISH
H == POP(FREE)
-> REJ IF H == NULL
H_P = P; ! COPY P INTO A SAFE PLACE
PUSH(HI, H); ! AND Q IT
IF P_A1#0 AND FIRST=LAST THEN -> INS2
IF FIRST#CURR START ; ! NON EMPTY LINE
TRANSFER INPUT
FINISH
FINISH
FINISH
REPEAT
ROUTINE DRIVE TT(INTEGER CHAR)
IF CHAR=NL START
TT STATUS=TT STATUS+2
CHAR=CR
FINISH
TT_TTD=CHAR
TT_TTS=TT_TTS!K'100'; ! INTS ON
END
ROUTINE ECHO(INTEGER X)
RETURN IF E PT>40 OR ECHO FL # 0
E PT=E PT+1; ECHOB(E PT)=X
IF TT STATUS=0 OR TT STATUS=6 START
TT STATUS=2
DRIVE TT(X)
EFPT=1
FINISH
END
ROUTINE ECHO BELL
ECHO(BELL); E LAST=E PT
END
ROUTINE PLANT(INTEGER CHAR)
BUFFER(LAST) = CHAR
LAST = (LAST+1)&255
ECHO(CHAR)
END
ROUTINE TRANSFER INPUT
INTEGER SEG, I, ID, ADR, N
RETRY:
IF CLI FLAG # 0 START ; ! PREEMPTED BY CLI
ID = CID; ADR = C ADR; CLI FLAG = 0
ELSE
IF HI_H == NULL THEN RETURN
H == POP(HI); PUSH(FREE, H)
ID = H_P_REPLY; ADR = H_P_A2
FINISH
IF ID#0 START
SEG=ADR>>13
I = MAP VIRT(ID, SEG, MYISEG)
-> RETRY IF I = 0; ! TASK HAS GONE AWAY/ILLEGAL ADDR
INX_ARRAY PT=MISA+(ADR&K'17777')
CYCLE I = 0, 1, 80
N = BUFFER(FIRST)
INH_B(I) = N
FIRST = (FIRST+1)&255
EXIT IF N = NL
REPEAT
P_SERVICE=ID; P_REPLY=TTSER
P_A1=I+1
PON(P)
I =MAP VIRT(0, -1, MYISEG)
FINISH
END
ROUTINE OUTPUT REPLY
INTEGER I
I = MAP VIRT(0, -1, MYSEG)
P_SERVICE=OUTID; P_REPLY=TTSER
P_A1=0
PON(P)
OUTID=0; OUT_LAST = 0
END
ENDOFPROGRAM