ITS Muddle.
[pdp10-muddle.git] / MUDDLE / fopen.63
diff --git a/MUDDLE/fopen.63 b/MUDDLE/fopen.63
new file mode 100644 (file)
index 0000000..f1ae706
--- /dev/null
@@ -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 (<DIR>,<FILE NAME1>,<FILE NAME2>,<DEVICE>,<SYSTEM NAME>)
+;
+;              <DIR> - DIRECTION EITHER READ (INPUT) OR PRINT (OUPUT). DEFAULT IS READ
+
+;              <FILE NAME1> - FIRST FILE NAME.  DEFAULT INPUT OR OUTPUT.
+
+;              <FILE NAME2> - SECOND FILE NAME.  DEFAULT MUDDLE.
+
+;              <DEVICE> - DEVICE FROM WHICH TO OPEN.  DEFAULT IS DSK.
+
+;              <SNAME> - 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
+
+\f;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
+
+\f;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
+\f
+;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,
+
+\f
+;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
+
+\f
+;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
+
+\f\ 3\f
\ No newline at end of file