X-Git-Url: https://jxself.org/git/?p=pdp10-muddle.git;a=blobdiff_plain;f=MUDDLE%2Ffopen.63;fp=MUDDLE%2Ffopen.63;h=f1ae706bae1ee5b304dee98a2c0b9766ed1bb536;hp=0000000000000000000000000000000000000000;hb=39c5769144e7f2a58076bdb973d2c80fa603345c;hpb=bab072f950a643ac109660a223b57e635492ac25 diff --git a/MUDDLE/fopen.63 b/MUDDLE/fopen.63 new file mode 100644 index 0000000..f1ae706 --- /dev/null +++ b/MUDDLE/fopen.63 @@ -0,0 +1,545 @@ +TITLE OPEN - CHANNEL OPENER FOR MUDDLE + +RELOCATABLE + +;C. REEVE JAN 1971 + +.INSRT MUDDLE > + +;THIS PROGRAM HAS TWO ENTRIES. FOPEN,FCLOSE AND FDELETE. +;THESE SUBROUTINES HANDLE I/O STREAMS FOR THE MUDDLE SYSTEM. + +; FOPEN - OPENS A FILE FOR EITHER READING OR WRITING. IT TAKES +; FIVE OPTINAL ARGUMENTS AS FOLLOWS: + +; FOPEN (,,,,) +; +; - DIRECTION EITHER READ (INPUT) OR PRINT (OUPUT). DEFAULT IS READ + +; - FIRST FILE NAME. DEFAULT INPUT OR OUTPUT. + +; - SECOND FILE NAME. DEFAULT MUDDLE. + +; - DEVICE FROM WHICH TO OPEN. DEFAULT IS DSK. + +; - SYSTEM (DIRECTORY) NAME. DEFAULT UNAME. + +; FOPEN RETURNS AN OBJECT OF TYPE CHANNEL IF IT SUCCEEDS OTHERWISE NIL + + +; FCLOSE - CLOSES A FILE. TAKES A CHANNEL OBJECT AS ITS ARGUMENT. IT ALSO TAKES + + +;A CHANNEL OBJECT IS A VECTOR CONTAINIG THE FOLLOWING INFORMATION + +; CHANNO==1 ;ITS I/O CHANNEL NUMBER. 0 MEANS NOT A REAL CHANNEL. +; DIRECT==3 ;DIRECTION (EITHER READ OR PRINT) +; DEVICE==5 ;DEVICE UPON WHICH THE CHANNEL IS OPEN +; NAME1==7 ;FIRST NAME OF FILE AS OPENED. +; NAME2==11 ;SECOND NAME OF FILE +; SNAME==13 ;DIRECTORY NAME +; RDEVIC==15 ;REAL DEVICE +; RNAME1=17 ;REAL FIRST NAME (AS RETURNED BY READING CHANNEL STATUS) +; RNAME2==21 ;REAL SECOND NAME +; RSNAME==23 ;SYSTEM OR DIRECTORY NAME +; STATUS==25 ;VARIOUS STATUS BITS +; IOINS==27 ;INSTRUCTION EXECUTED TO INPUT OR OUTPUT ONE CHARACTER +; ACCESS==31 ;ACCESS POINTER FOR RAND ACCESS +; RADX==33 ;RADIX FOR CHANNELS NUMBER CONVERSION +; *** THE FOLLOWING FIELDS FOR OUTPUT ONLY *** + +; LINLN==35 ;LENGTH OF A LINE IN CHARACTERS FOR THIS DEVICE +; CHRPOS==37 ;CURRENT POSITION ON CURRENT LINE +; PAGLN==41 ;LENGTH OF A PAGE +; LINPOS==43 ;CURRENT LINE BEING WRITTEN ON +; *** THE FOLLOWING FILEDS FOR INPUT ONLY *** + +; EOFCND==35 ;GETS EVALUATED ON EOF +; LSTCHR==37 ;BACKUP CHARACTER +; BUFRIN==41 ;POINTER TO BUFFER FOR TTY FLAVOR DEVICES + + +;CHANLNT==42 ;LENGTH OF A CHANNEL OBJECT + +;THIS IRP DEFINES THE FIELDS AT ASSEMBLY TIME + + CHANLNT==1 ;INITIAL CHANNEL LENGTH + +; BUILD A PROTOTYPE CHANNEL AND DEFINE FILEDS + +PROCHN: + +IRP A,,[[CHANNO,FIX],[DIRECT,CHSTR],[DEVICE,CHSTR],[NAME1,CHSTR],[NAME2,CHSTR] +[SNAME,CHSTR],[RDEVIC,CHSTR],[RNAME1,CHSTR],[RNAME2,CHSTR],[RSNAME,CHSTR] +[STATUS,FIX],[IOINS,FIX],[LINLN,FIX],[CHRPOS,FIX],[PAGLN,FIX],[LINPOS,FIX] +[ACCESS,FIX],[RADX,FIX]] + + IRP B,C,[A] + B==CHANLNT + T!C,,0 + 0 + .ISTOP + TERMIN + CHANLNT==CHANLNT+2 +TERMIN + + +; EQUIVALANCES FOR INPUT CHANNELS + +EOFCND==LINLN +LSTCH==CHRPOS +BUFRIN==PAGLN + +;PRESET LINE LENGTH AND PAGE LENGTH + +ZZZ==. ;SAVE CURRENT LOCATION + +LOC PROCHN+RADX +10. + +LOC PROCHN+LINLN +TTYLNL ;USE TTY LINE LENGTH + +LOC PROCHN+PAGLN +TTYPGL ;USE TTY PAGE LENGTH + +LOC ZZZ ;RESET LOCATIN +CHANLNT==CHANLNT-1 + + +INBIT==0 ;LH BITS FOR INPUT +OUTBIT==1 ;AND FOR OUTPUT + +;PAGE AND LINE LENGTH FOR TTY + +TTYLNL==80. +TTYPGL==60. + +;DEFINE VARIABLES ASSOCIATED WITH TTY BUFFERS + +IRP A,,[IOIN2,ECHO,CHRCNT,ERASCH,KILLCH,BRKCH,ESCAP,SYSCHR,BRFCHR,BYTPTR] +A==.IRPCNT +TERMIN + +EXTBFR==BYTPTR+1+<100./5> ;LENGTH OF ADD'L BUFFER + + + + +.GLOBAL IPNAME,OPEN,CLOSE,IOT,ILOOKU,6TOCHS,ICLOS,OCLOS +.GLOBAL OPNCHN,CHMAK,READC,TYO,RADX,SYSCHR,BRFCHR,LSTCH +.GLOBAL CHRWRD + +.GLOBAL DISOPN,DISCLS,DCHAR,DISLNL,DISPGL,CHANL0,BUFRIN,IOIN2 +.GLOBAL ECHO,ERASCH,KILLCH,BRKCH,BYTPTR,SYSCHR,CHRCNT,ESCAP + + ;SUBROUTINE TO DO OPENING BEGINS HERE + +MFUNCTION FOPEN,SUBR,[OPEN] + + ENTRY + PUSHJ P,MAKCHN ;MAKE THE CHANNEL + PUSHJ P,OPNCHN ;NOW OPEN IT + JRST FINIS + +; SUBROUTINE TO JUST CREATE A CHANNEL + +MFUNCTION CHANNEL,SUBR + + ENTRY + PUSHJ P,MAKCHN + JRST FINIS +;INTERNAL CHANNEL CREATOR + + +MAKCHN: + +; CYCLE THROUGH THE GIVEN ARGUMENTS + + MOVSI A,-5 ;NUMBER OF ARGUMENTS INTO A +ARGLP: JUMPGE AB,ARGDON ;IF AB>=0, NO MORE ARGS + HLRZ C,(AB) ;CHECK THE TYPE + CAIN C,TCHRS ;MUST BE AN CHRS + JRST ARGWIN + CAIE C,TCHSTR + JRST WRONGT +ARGWIN: PUSH TP,(AB) ;NOW TO TEMPS + PUSH TP,1(AB) + ADD AB,[2,,2] ;BUMP ARGG POINTER + AOBJN A,ARGLP ;CYCLE + +;NOW PUSH ANY MORE GOODIES FOR DEFAULTS + +ARGDON: + MOVEI A,(A) ;GET NUMBER DONE + CAIN A,5 ;FINISHED? + JRST GETCHN ;YES + LSH A,1 + CAIE A,2 ;WASONLY DIRECTION GIVEN? + JRST DFLTAB(A) ;NO + MOVEI B,-1(TP) ;PICK UP DIRECTION + PUSHJ P,CHRWRD ;GET WORD + JRST WRONGT + CAMN B,CHQUOTE READ + JRST DFLTB1 ;YES,GO PUSH 'INPUT' + PUSH TP,$TCHSTR + PUSH TP,CHQUOTE OUTPUT + JRST DFLTB2 + +DFLTAB: PUSH TP,$TCHSTR ;DEFAULT DIRECTION + PUSH TP,CHQUOTE READ +DFLTB1: PUSH TP,$TCHSTR ;DEFAULT NAME1 + PUSH TP,CHQUOTE INPUT +DFLTB2: PUSH TP,$TCHSTR ;DEFAULT NAME2 + PUSH TP,CHQUOTE MUDDLE + PUSH TP,$TCHSTR ;DEFAULT DEVICE + PUSH TP,CHQUOTE DSK + .SUSET [.RSNAM,,A] + PUSHJ P,6TOCHS + PUSH TP,A + PUSH TP,B ;AND DEFAULT SYS NAME + +GETCHN: PUSH TP,$TFIX ;SETUP CALL TO VECTOR + PUSH TP,[CHANLN_-1] + MCALL 1,VECTOR ;GO GET STORAGE + HRLI C,PROCHN ;SETUP FOR BLT + HRRI C,(B) + BLT C,CHANLNT-1(B) ;BLT IN THE TYPES + MOVE A,(TB) ;GET TYPE + MOVEM A,DIRECT-1(B) ;AND CLOBBER + MOVE A,1(TB) ;GET THE DIRECTION + MOVEM A,DIRECT(B) ;STORE IT + MOVE A,2(TB) ;TYPE FIRST + MOVEM A,NAME1-1(B) + MOVEM A,RNAME1-1(B) + MOVE A,3(TB) ;GET NAME1 + MOVEM A,NAME1(B) + MOVEM A,RNAME1(B) ;ALSO REAL NAME 1 + MOVE A,4(TB) ;TYPE + MOVEM A,NAME2-1(B) + MOVEM A,RNAME2-1(B) + MOVE A,5(TB) ;MAME 2 + MOVEM A,NAME2(B) + MOVEM A,RNAME2(B) ;ALSO REAL NAME 2 + MOVE A,6(TB) + MOVEM A,DEVICE-1(B) + MOVEM A,RDEVICE-1(B) + MOVE A,7(TB) ;GET DEVICE NAME + MOVEM A,DEVICE(B) + MOVEM A,RDEVIC(B) + MOVE A,10(TB) + MOVEM A,SNAME-1(B) + MOVEM A,RSNAME-1(B) + MOVE A,11(TB) ;FINALLY UNAME + MOVEM A,SNAME(B) + MOVEM A,RSNAME(B) + SUB TP,[10.,,10.] ;GARBAGE COLLECT TP + MOVSI A,TCHAN ;MAKE TYPE INTO CHANNEL + POPJ P, ;RETURN + + ;OPEN THE CHANNEL POINTED TO BY B + +OPNCHN: PUSH TP,$TCHAN ;SAVE THE CHANNEL + PUSH TP,B + MOVEI B,DIRECT-1(B) ;POINT TO DIRECTION + PUSHJ P,CHRWRD ;PUT INTO A WORD + JFCL + MOVE E,B ;TO E + MOVE B,(TP) + MOVE A,DEVICE-1(B) ;GET DEVICE + MOVE B,DEVICE(B) + PUSHJ P,STRTO6 ;CONVERT TO 6-BIT + HLRZS A,(P) ;DEVICE TO RH + CAIN A,(SIXBIT /E&S/) ;DISPLAY HACK? + JRST DISCHK ;YES, GO HACK + MOVE B,(TP) ;RESTORE B + MOVE A,NAME1-1(B) ;TYPE OF NAME1 + MOVE B,NAME1(B) ;GET THE FIRST NAME + PUSHJ P,STRTO6 ;TO 6-BIT + MOVE B,(TP) ;RESTORE B + MOVE A,NAME2-1(B) + MOVE B,NAME2(B) ;SECOND NAME + PUSHJ P,STRTO6 ;ALSO TO 6 BIT + MOVE B,(TP) + MOVSI A,INBIT ;GET BIT FOR INPUT OPEN + CAME E,[ASCII /READ/] ;REALLY INPUT? + MOVSI A,OUTBIT ;NO GET OUTPUT BIT + IORM A,-2(P) ;INTO OPEN STUFF + MOVE A,SNAME-1(B) + MOVE B,SNAME(B) ;GOBBLE SNAME + PUSHJ P,STRTO6 ;6 BIT + POP P,A ;RESTORE RESULT + .SUSET [.SSNAM,,A] ;SET THE SYSTEM NAME + MOVEI A,-2(P) ;POINT TO OPEN BLOCK + PUSHJ P,OPEN ;DO THE OPEN + JRST OPNFAI ;OPEN FAILED, LOSE + MOVE B,(TP) ;RESTORE B + PUSHJ P,DOSTAT ;GOBBLE THE STATUS + LDB C,[600,,STATUS(B)] ;GOBBLE STATUS + CAMN E,[ASCII /PRINT/] + CAIE C,2 ;SKIP IF DATAPOINT CROCK + JRST OPNCH2 ;NOT SAME FOR OUTPUT + + PUSHJ P,CLOSE ;CLOSE THE FILE + MOVSI A,OUTBIT+20 ;AND RE-OPEN IN DISPLAY MODE + HLLM A,-2(P) + MOVEI A,-2(P) ;POINT TO OPEN BLOCK + PUSHJ P,OPEN ;NOW OPEN THE DEVICE + JRST OPNFAI ;CANT OPEN + +OPNCH2: SUB P,[3,,3] ;REMOVE OPEN BLOCK + MOVEM A,CHANNO(B) ;RESTORE CHANNEL NUMBER + MOVEI D,(A) ;COPY CHANNEL NO. + LSH D,1 + ADDI D,CHANL0+1(TVP) ;POINT TO THIS CHANNELS TV ENTRY + MOVEM B,(D) + HRLZS A ;CHANNEL NO. TO LH + MOVE C,A ;COPY TO C + ROT C,5 ;INTO C'S AC FILED + IOR C,[.IOT 0,A] ;AND AN I/O INSTRUCTION + MOVEM C,IOINS(B) ;SAVE IN CHANNEL +; THIS CODES SETS THE 'REAL' NAMES, DEVICES AND SNAMES + + HRRI A,1(P) ;POINT INTO P + MOVEI C,(A) ;C ALSO POINTS + ADD P,[5,,5] ;ALLOCATE SOME P + JUMPGE P,[.VALUE [ASCIZ 'P/']] ;DIE ON PDL LOSSAGE + .RCHST A, ;READ THE STATUS + HRLZS (C) ;FOR NOW KILL LH OF DEVICE + HRLI C,-5 ;5 GOODIES + PUSH P,C + PUSH P,[0] ;USED AS A COUNTER +NXTREL: MOVEM C,-1(P) ;SAVE C + SKIPN A,(C) ;WAS THIS ONE GIVEN? + JRST NXTLOK ;NO, SKIP CHANGE + PUSHJ P,6TOCHS ;YES, MAKE INTO ATOM + MOVEI C,RDTBL ;FIND OUT WHERE + ADD C,(P) ;FOR THIS ONE + MOVE C,(C) ;NOW HAVE TH OFFSET TO USE + ADD C,(TP) ;ADD TO POINTER + MOVEM A,-1(C) + MOVEM B,(C) ;CLOBBER THE NEW ATOM IN + MOVE C,-1(P) ;RESTORE C +NXTLOK: AOS (P) ;COUNT THE GOODIES + AOBJN C,NXTREL + + SUB P,[7,,7] ;GC ON P + +; DETERMIN EIF THIS IS A TTY FLAVOR DEVICE + + MOVE B,(TP) ;RESTORE CHANEL POINTER + MOVE A,STATUS(B) ;GET STATUS + ANDI A,77 ;ISOLATE DEVICE SPEC + CAMN E,[ASCIZ /READ/] + CAILE A,2 ;NOT A TTY, NO FURTHER ACTION + JRST OPNRET + + PUSH TP,$TFIX ;CALL UVECTOR FOR BUFFER + PUSH TP,[EXTBFR] + MCALL 1,UVECTOR ;GET VECTOR + MOVE C,[PUSHJ P,READC] ;GET NEW IOINS + MOVE D,(TP) ;RESTORE CHANNEL POINTER + EXCH C,IOINS(D) ;STORE NEW ONE AND GE OLD + MOVEM C,IOIN2(B) ;STORE + MOVEM B,BUFRIN(D) ;STORE IN CHANNEL + MOVSI A,TUVEC ;MAKE SURE TYPE IS UNIFORM VECTOR + MOVEM A,BUFRIN-1(D) + MOVEI A,177 ;SET ERASER TO RUBOUT + MOVEM A,ERASCH(B) + SETOM KILLCH(B) ;NO KILL CHARACTER NEEDED + MOVEI A,33 ;BREAKCHR TO C.R. + MOVEM A,BRKCH(B) + MOVEI A,"\ ;ESCAPER TO \ + MOVEM A,ESCAP(B) + MOVE A,[010700,,BYTPTR(B)] ;RELATIVE BYTE POINTER + MOVEM A,BYTPTR(B) + MOVEI A,14 ;BARF BACK CHARACTER FF + MOVEM A,BRFCHR(B) + +OPNRET: POP TP,B ;GET CHANNEL POINTER BACK + + POP TP,A ;RESTORE TYPE OF CHANNEL + POPJ P, + + +;TABLE USED TO DO THE 'REAL GOODIES' + +RDTBL: RDEVIC + RNAME1 + RNAME2 + RSNAME + ACCESS + + +;HERE TO DO STATUS FOR OPEN LOSSAGE ETC. + +DOSTAT: PUSH P,A ;SAVE CHANNEL + ROT A,23. ;INTO AC FILED + IOR A,[.STATUS STATUS(B)] ;GOBBLE THE STATUS + XCT A ;DO IT + POP P,A + POPJ P, + + +;MAKE THE DISPLAY DEVICE A PSEUDO DEVICE HANDLED BY "DCHAR" ROUTINE +DISCHK: SUB P,[1,,1] ;POP OFF JUNK + MOVE B,(TP) ;GET POINTER TO CHANNEL + SETZM CHANNO(B) ;A PSEUDO CHANNEL NUMBER + MOVE C,[PUSHJ P,DCHAR] + MOVEM C,IOINS(B) ;GO TO THIS ROUTINE TO HANDLE I/O + MOVEI C,DISLNL + MOVEM C,LINLN(B) + MOVEI C,DISPGL + MOVEM C,PAGLN(B) + PUSHJ P,DISOPN ;GO INITIALIZE THE DISPLAY + JRST OPNFAI + JRST OPNRET + +;ARRIVE HERE IF FOPEN CALLED WITH WRONG TYPES OF ARGUMENTS + +WRONGT: PUSH TP,$TATOM ;SET UP CALL TO ERROR + PUSH TP,MQUOTE WRONG-TYPE + JRST CALER1 + + +;THIS ROTINE CONVERTS MUDDLE CHARACTER STRINGS TO SIXBIT FILE NAMES +STRTO6: PUSH TP,A + PUSH TP,B + PUSH P,E ;SAVE USEFUL FROB + MOVEI E,-1(A) ;GET END+1 OF TCHSTR + HLRZS A ;CHECK THE TYPE(ONE WORD OR VECTOR) + CAIE A,TCHRS ; IS IT ONE WORD? + JRST CHREAD ;NO + MOVEI B,(TP) ;YES, CREATE DUMMY VECTOR POINTER + HRLI B,350700 + MOVEI E,1(TP) ;AND DUMMY VECTOR END+1 +CHREAD: MOVEI A,0 ;INITIALIZE OUTPUT WORD + MOVE D,[440600,,A] ;AND BYTE POINTER TO IT + LDB 0,B ;PICK UP FIRST CHARACTER +NEXCHR: + JUMPE 0,SIXDON ;IF NULL, WE ARE FINISHED + CAIL 0,141 ;IF IT IS GREATER OR EQUAL TO LOWER A + CAILE 0,172 ;BUT LESS THAN OR EQUAL TO LOWER Z + JRST .+2 ;THEN + SUBI 0,40 ;CONVERT TO UPPER CASE + SUBI 0,40 ;NOW TO SIX BIT + JUMPLE 0,BAD6 ;CHECK FOR A WINNER + CAILE 0,77 + JRST BAD6 + IDPB 0,D ;DEPOSIT INTO SIX BIT + TRNE A,77 ;IS OUTPUT FULL + JRST SIXDON ;YES, LEAVE + ILDB 0,B ;GET NEXT CHAR AND INC POINTER + HRRZ C,B ;GET ADDRESS PART OF BYTE POINTER + CAME C,E ;HAS POINTER REACHED LIMIT? + JRST NEXCHR ;NO, GOBBLE NEXT CHARACTER +SIXDON: SUB TP,[2,,2] ;FIX UP TP + POP P,E + EXCH A,(P) ;LEAVE RESULT ON P-STACK + JRST (A) ;NOW RETURN + + +;SUBROUTINE TO CONVERT SIXBIT TO ATOM + +6TOCHS: PUSH P,E + MOVEI B,6 ;MAX NUMBER OF CHARACTERS + PUSH P,[0] ;STRING WILL GO ON P SATCK + MOVEI E,-1(P) ;WILL BE BYTE POINTER + HRLI E,10700 ;SET IT UP + PUSH P,[0] ;SECOND POSSIBLE WORD + MOVE D,[440600,,A] ;INPUT BYTE POINTER +6LOOP: ILDB 0,D ;START CHAR GOBBLING + JUMPE 0,GETATM ;IF ZERO, FINISHED + ADDI 0,40 ;CHANGET TOASCII + IDPB 0,E ;AND STORE IT + SOJG B,6LOOP ;KEEP LOOKING + PUSH P,[2] ;IF ARRIVE HERE, STRING IS 2 WORDS + JRST .+2 +GETATM: AOS (P) ;SET STRING LENGTH=1 + PUSHJ P,CHMAK ;MAKE A MUDDLE STRING + POP P,E + POPJ P, + + +;HERE IF OPEN FAILS + +OPNFAI: MOVE B,(TP) ;RESTORE CHANNEL POINTER + SETOM STATUS(B) ;SET TO -1 + JUMPL A,.+2 ;A<0 MEANS NO CHANNELS + PUSHJ P,DOSTAT ;GOBBLE STATUS + SUB TP,[2,,2] ;PATCH UP TP + SUB P,[3,,3] ;REMOVE CRAP +RETNIL: MOVSI A,TFALSE ;RETURN A FALSE + MOVEI B,0 + POPJ P, + +;ERROR FOR BAD CHARACTER IN SIX BIT STRING + +BAD6: PUSH TP,$TATOM ;SETUP ERROR CALL + PUSH TP,MQUOTE FILE-NAME-NOT-6-BIT + JRST CALER1 + + +; FUNCTION TO LIST ALL CHANNELS + +MFUNCTION CHANLIST,SUBR + + ENTRY 0 + + MOVEI A,16. ;MAX # OF CHANNELS + MOVEI C,0 + MOVEI B,CHANL0(TVP) ;POINT TO FIRST + +CHNLP: SKIPN 1(B) ;OPEN? + JRST NXTCHN ;NO, SKIP + PUSH TP,(B) + PUSH TP,1(B) + ADDI C,1 ;COUNT WINNERS +NXTCHN: ADDI B,2 + SOJN A,CHNLP + + ACALL C,LIST + JRST FINIS + + +;THIS PROGRAM CLOSES THE SPECIFIED CHANNEL + +MFUNCTION FCLOSE,SUBR,[CLOSE] + + ENTRY 1 ;ONLY ONE ARG + HLRZ A,(AB) ;CHECK ARGS + CAIE A,TCHAN ;IS IT A CHANNEL + JRST WRONGT + MOVE B,1(AB) ;PICK UP THE CHANNEL + CLEARM IOINS(B) ;CLOBBER THE IO INS + MOVEI B,DEVICE-1(B) ;GE THE NAME OF THE DEVICE + PUSHJ P,CHRWRD + JFCL + MOVE A,B + MOVE B,1(AB) + CAMN A,[ASCIZ /TTY/] ;IS IT THE TTY? + JRST TTYCLS ;YES, DO SPECIAL HACK + CAMN A,[ASCIZ /DIS/] + PUSHJ P,DISCLS ;GO RELEASE THE DISPLAY SPACE + SKIPE A,CHANNO(B) ;IS THERE A CHANNEL NO.? + PUSHJ P,CLOSE ;YES, CLOSE IT +CFIN: SKIPN A,CHANNO(B) ;ANY CHANNEL? + JRST CFIN2 + LSH A,1 + ADDI A,CHANL0+1(TVP) ;POINT TO THIS CHANNELS LSOT + SETZM CHANNO(B) + SETZM (A) ;AND CLOBBER IT +CFIN2: MOVSI A,TCHAN ;RETURN THE CHANNEL + JRST FINIS + +TTYCLS: MOVE A,DIRECT(B) ;GET THE DIRECTION OF THE CHANNEL + CAMN A,CHQUOTE READ, ;IS IT READ + PUSHJ P,ICLOS ;YES, CLOSE THAT + CAMN A,CHQUOTE PRINT, ;IS IT PEINT + PUSHJ P,OCLOS ;YES CLOSE TTY OUT CHANNEL + JRST CFIN + + +END + +  \ No newline at end of file