--- /dev/null
+TITLE OPEN - CHANNEL OPENER FOR MUDDLE
+
+RELOCATABLE
+
+;C. REEVE MARCH 1973
+
+.INSRT MUDDLE >
+
+SYSQ
+
+FNAMS==1
+F==E+1
+G==F+1
+
+IFE ITS,[
+IF1, .INSRT STENEX >
+]
+;THIS PROGRAM HAS ENTRIES: FOPEN, FCLOSE, RENAME, READB, PRINTB, FILECOPY, READSTRING,
+; PRINTSTRING, NETSTATE, NETACC, NETS, ACCESS, AND FILE-EXISTS?
+
+;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
+; ACCESS - DOES A .ACCESS ON A CHARACTER BASIS FOR CHARACTER FILES
+
+
+; A CHANNEL OBJECT IS A VECTOR CONTAINIG THE FOLLOWING INFORMATION
+
+; CHANNO ;ITS I/O CHANNEL NUMBER. 0 MEANS NOT A REAL CHANNEL.
+; DIRECT ;DIRECTION (EITHER READ OR PRINT)
+; NAME1 ;FIRST NAME OF FILE AS OPENED.
+; NAME2 ;SECOND NAME OF FILE
+; DEVICE ;DEVICE UPON WHICH THE CHANNEL IS OPEN
+; SNAME ;DIRECTORY NAME
+; RNAME1 ;REAL FIRST NAME (AS RETURNED BY READING CHANNEL STATUS)
+; RNAME2 ;REAL SECOND NAME
+; RDEVIC ;REAL DEVICE
+; RSNAME ;SYSTEM OR DIRECTORY NAME
+; STATUS ;VARIOUS STATUS BITS
+; IOINS ;INSTRUCTION EXECUTED TO INPUT OR OUTPUT ONE CHARACTER
+; ACCESS ;ACCESS POINTER FOR RAND ACCESS (OR USED FOR DISPLAY INFO)
+; RADX ;RADIX FOR CHANNELS NUMBER CONVERSION
+
+; *** THE FOLLOWING FIELDS FOR OUTPUT ONLY ***
+; LINLN ;LENGTH OF A LINE IN CHARACTERS FOR THIS DEVICE
+; CHRPOS ;CURRENT POSITION ON CURRENT LINE
+; PAGLN ;LENGTH OF A PAGE
+; LINPOS ;CURRENT LINE BEING WRITTEN ON
+
+; *** THE FOLLOWING FILEDS FOR INPUT ONLY ***
+; EOFCND ;GETS EVALUATED ON EOF
+; LSTCH ;BACKUP CHARACTER
+; WAITNS ;FOR TTY INPUT, BECOMES A .SLEEP WHEN WAITING
+; EXBUFR ;FOR TTY INPUT, CONTAINS A WAITING BUFFER LIST
+; BUFSTR ;A CHARACTER STRING USED AS BUFFER FOR NON-TTY DEVICES
+
+; THIS DEFINES THE LENGTH OF THE NON-TTY BUFFER
+BUFLNT==100
+
+;THIS DEFINES BLOCK MODE BIT FOR OPENING
+BLOCKM==2 ;DEFINED IN THE LEFT HALF
+IMAGEM==4
+
+\f
+;THIS IRP DEFINES THE FIELDS AT ASSEMBLY TIME
+
+ CHANLNT==4 ;INITIAL CHANNEL LENGTH
+
+; BUILD A PROTOTYPE CHANNEL AND DEFINE FILEDS
+BUFRIN==-1 ;SPECIAL HACK SO LOSERS WON'T SEE TTY BUFFER
+SCRPTO==-3 ;SPECIAL HACK FOR SCRIPT CHANNELS
+PROCHN:
+
+IRP A,,[[CHANNO,FIX],[DIRECT,CHSTR]
+[NAME1,CHSTR],[NAME2,CHSTR],[DEVICE,CHSTR],[SNAME,CHSTR]
+[RNAME1,CHSTR],[RNAME2,CHSTR],[RDEVIC,CHSTR],[RSNAME,CHSTR]
+[STATUS,FIX],[IOINS,FIX],[LINLN,FIX],[CHRPOS,FIX],[PAGLN,FIX],[LINPOS,FIX]
+[ACCESS,FIX],[RADX,FIX],[BUFSTR,CHSTR]]
+
+ IRP B,C,[A]
+ B==CHANLNT-3
+ T!C,,0
+ 0
+ .ISTOP
+ TERMIN
+ CHANLNT==CHANLNT+2
+TERMIN
+
+
+; EQUIVALANCES FOR CHANNELS
+
+EOFCND==LINLN
+LSTCH==CHRPOS
+WAITNS==PAGLN
+EXBUFR==LINPOS
+DISINF==BUFSTR ;DISPLAY INFO
+INTFCN==BUFSTR ;FUNCTION (OR SUBR, OR RSUBR) TO BE APPLIED FOR INTERNAL CHNLS
+
+
+;DEFINE VARIABLES ASSOCIATED WITH TTY BUFFERS
+
+IRP A,,[IOIN2,ECHO,CHRCNT,ERASCH,KILLCH,BRKCH,ESCAP,SYSCHR,BRFCHR,BRFCH2,BYTPTR]
+A==.IRPCNT
+TERMIN
+
+EXTBFR==BYTPTR+1+<100./5> ;LENGTH OF ADD'L BUFFER
+
+
+
+
+.GLOBAL IPNAME,MOPEN,MCLOSE,MIOT,ILOOKU,6TOCHS,ICLOS,OCLOS,RGPARS,RGPRS
+.GLOBAL OPNCHN,CHMAK,READC,TYO,SYSCHR,BRFCHR,LSTCH,BRFCH2,EXTBFR
+.GLOBAL CHRWRD,STRTO6,TTYBLK,WAITNS,EXBUFR,TTICHN,TTOCHN,GETCHR,IILIST
+.GLOBAL CHANNO,STATUS,LINPOS,PAGLN,CHRPOS,LINLN,IOINS,ACCESS,ADDNUL
+.GLOBAL DIRECT,DISINF,RADX,EOFCND,BUFSTR,MODE1,MODE2,GCHACK,GMTYO,INMTYO
+.GLOBAL T.CHAN,NAME1,BFCLOS,DOIOTI,DOIOTO,DOACCS,NOTTY,DEMFLG,BYTDOP,TNXIN
+.GLOBAL DISOPN,DISROP,DISCLS,DCHAR,DISLNL,DISPGL,INSTAT,MTYO,CIREST
+.GLOBAL ECHO,ERASCH,KILLCH,BRKCH,BYTPTR,SYSCHR,CHRCNT,ESCAP,N.CHNS
+.GLOBAL REOPN,QUITTE,CHNL0,CHNL1,BUFRIN,IOIN2,IFALSE,GFALS,IDVAL,PVSTOR,SPSTOR
+.GLOBAL BADCHN,WRONGD,CHNCLS,GSNAME,GIBLOK,APLQ,NAPT,ICONS,INCONS,IBLOCK,IDVAL1
+.GLOBAL GRB,GWB,R1CHAR,W1CHAR,BFCLS1,TTYOP2,MPOPJ,COMPER,R1C,W1C,WXCT,RXCT
+.GLOBAL TMTNXS,TNXSTR,RDEVIC,CPCH1,RCYCHN,CGFALS,CISTNG,CFILLE,FRSTCH
+.GLOBAL TGFALS,ONINT
+\f
+.VECT.==40000
+
+; PAIR MOVING MACRO
+
+DEFINE PMOVEM A,B
+ MOVE 0,A
+ MOVEM 0,B
+ MOVE 0,A+1
+ MOVEM 0,B+1
+ TERMIN
+
+; DEFINITIONS OF THE OFFSETS INTO THE TP STACK FOR OPEN
+
+T.SPDL==0 ; SAVES P STACK BASE
+T.DIR==2 ; CONTAINS DIRECTION AND MODE
+T.NM1==4 ; NAME 1 OF FILE
+T.NM2==6 ; NAME 2 OF FILE
+T.DEV==10 ; DEVICE NAME
+T.SNM==12 ; SNAME
+T.XT==14 ; EXTRA CRUFT IF NECESSARY
+T.CHAN==16 ; CHANNEL AS GENERATED
+
+; OFFSETS FROM PSTACK BASE (USED FOR OPENS, .RCHST AND .FDELES)
+
+S.DIR==0 ; CODE FOR DIRECTION 0-IN, 1-OUT, 2-BIN, 3-BOUT,4-DISPLAY
+ ; S.DIR(P) = <control word>,,<direction>
+IFN ITS,[
+S.DEV==1 ; SIXBIT DEVICE RIGHT JUSTIFIED
+S.NM1==2 ; SIXBIT NAME1
+S.NM2==3 ; SIXBIT NAME2
+S.SNM==4 ; SIXBIT SNAME
+S.X1==5 ; TEMPS
+S.X2==6
+S.X3==7
+]
+
+IFE ITS,[
+S.DEV==1
+S.X1==2
+S.X2==3
+S.X3==4
+]
+
+
+; FLAGS SPECIFYING STATE OF THE WORLD AT VARIOUS TIMES
+
+NOSTOR==400000 ; ON MEANS DONT BUILD NEW STRINGS
+MSTNET==200000 ; ON MEANS ONLY THE "NET" DEVICE CAN WIN
+SNSET==100000 ; FLAG, SNAME SUPPLIED
+DVSET==040000 ; FLAG, DEV SUPPLIED
+N2SET==020000 ; FLAG, NAME2 SET
+N1SET==010000 ; FLAG, NAME1 SET
+4ARG==004000 ; FLAG, CONSIDER ARGS TO BE 4 STRINGS
+
+RMT [EXPUNGE N1SET,N2SET,DVSET,SNSET,MSTNET,NOSTOR
+]
+
+; TABLE OF LEGAL MODES
+
+MODES: IRP A,,[READ,PRINT,READB,PRINTB,PRINTO,PRINAO]
+ SIXBIT /A/
+ TERMIN
+NMODES==.-MODES
+
+MODCOD: 0?1?2?3?3?1
+; TABLE OF KNOWN DEVICES AND A POINTER TO THEIR OPENERS
+
+IFN ITS,[
+DEVSTB: IRP A,,[DSK,TTY,USR,STY,ST,NET,INT,PTP,PTR,UT,T,NUL]
+ SIXBIT /A/ ; DEVICE NAMES
+ TERMIN
+
+DEVS: IRP B,,[ODSK,OTTY,OUSR,OSTY,OSTY,ONET,OINT,OPTP,OPTP,OUTN,OTTY,ONUL]
+ SETZ B ; POINTERS
+ TERMIN
+]
+
+IFE ITS,[
+DEVSTB: IRP A,,[PS,SS,SRC,DSK,TTY,INT,NET]
+ SIXBIT /A/
+ TERMIN
+
+DEVS: IRP B,,[ODSK,ODSK,ODSK,ODSK,OTTY,OINT,ONET]
+ SETZ B
+ TERMIN
+]
+NDEVS==.-DEVS
+
+
+\f
+;SUBROUTINE TO DO OPENING BEGINS HERE
+
+MFUNCTION NFOPEN,SUBR,[OPEN-NR]
+
+ JRST FOPEN1
+
+MFUNCTION FOPEN,SUBR,[OPEN]
+
+FOPEN1: ENTRY
+ PUSHJ P,MAKCHN ;MAKE THE CHANNEL
+ PUSHJ P,OPNCH ;NOW OPEN IT
+ JUMPL B,FINIS
+ SUB D,[4,,4] ; TOP THE CHANNEL
+ MOVEM D,RCYCHN+1 ; RECYCLE DEAD CHANNEL
+ SETZM (D) ; ZAP IT
+ MOVEI C,1(D)
+ HRLI C,(D)
+ BLT C,CHANLNT-1(D)
+ JRST FINIS
+
+; SUBR TO JUST CREATE A CHANNEL
+
+IMFUNCTION CHANNEL,SUBR
+
+ ENTRY
+ PUSHJ P,MAKCHN
+ MOVSI A,TCHAN
+ JRST FINIS
+
+
+\f
+
+; THIS ROUTINE PARSES ARGUMENTS TO FOPEN ETC. AND BUILDS A CHANNEL BUT DOESN'T OPEN IT
+
+MAKCHN: PUSH TP,$TPDL
+ PUSH TP,P ; POINT AT CURRENT STACK BASE
+ PUSH TP,$TCHSTR
+ PUSH TP,CHQUOTE READ
+ MOVEI E,10 ; SLOTS OF TP NEEDED
+ PUSH TP,[0]
+ SOJG E,.-1
+ MOVEI E,0
+ EXCH E,(P) ; GET RET ADDR IN E
+IFE ITS, PUSH P,[0]
+IRP ATM,,[DEV,NM1,NM2,SNM]MDF,,[DSK,INPUT,>,[ ]]TMDF,,[DSK,INPUT,MUD,[ ]]
+ MOVE B,IMQUOTE ATM
+IFN ITS, PUSH P,E
+ PUSHJ P,IDVAL1
+ GETYP 0,A
+ CAIN 0,TCHSTR
+ JRST MAK!ATM
+
+ MOVE A,$TCHSTR
+IFN ITS, MOVE B,CHQUOTE MDF
+IFE ITS, MOVE B,CHQUOTE TMDF
+MAK!ATM:
+ MOVEM A,T.!ATM(TB)
+ MOVEM B,T.!ATM+1(TB)
+IFN ITS,[
+ POP P,E
+ PUSHJ P,STRTO6 ; RESULT LEFT ON P STACK AS DESIRED
+]
+ TERMIN
+ PUSH TP,[0] ; PUSH SLOTS
+ PUSH TP,[0]
+
+ PUSH P,[0] ; EXT SLOTS
+ PUSH P,[0]
+ PUSH P,[0]
+ PUSH P,E ; PUSH RETURN ADDRESS
+ MOVEI A,0
+
+ JUMPGE AB,MAKCH0 ; NO ARGS, ALREADY DONE
+ GETYP 0,(AB) ; 1ST ARG MUST BE A STRING
+ CAIE 0,TCHSTR
+ JRST WTYP1
+ MOVE A,(AB) ; GET ARG
+ MOVE B,1(AB)
+ PUSHJ P,CHMODE ; CHECK OUT OPEN MODE
+
+ PMOVEM (AB),T.DIR(TB) ; SAVE MODE NAME IN TEMPS
+ ADD AB,[2,,2] ; BUMP PAST DIRECTION
+ MOVEM AB,ABSAV(TB)
+ MOVEI A,0
+ JUMPGE AB,MAKCH0 ; CHECK NAME1 BASED ON JUST MODE
+
+ MOVEI 0,0 ; FLAGS PRESET
+ PUSHJ P,RGPARS ; PARSE THE STRING(S)
+ JRST TMA
+
+; ARGUMENTS PARSED, DO FINAL CHECKS AND BUILD CHANNEL
+
+MAKCH0:
+IFN ITS,[
+ MOVE C,T.SPDL+1(TB)
+ MOVE D,S.DEV(C) ; GET DEV
+]
+IFE ITS,[
+ MOVE A,T.DEV(TB)
+ MOVE B,T.DEV+1(TB)
+ PUSHJ P,STRTO6
+ POP P,D
+ HLRZS D
+ MOVE C,T.SPDL+1(TB)
+ MOVEM D,S.DEV(C)
+]
+IFE ITS, CAIE D,(SIXBIT /INT/);INTERNAL?
+IFN ITS, CAME D,[SIXBIT /INT /]
+ JRST CHNET ; NO, MAYBE NET
+ SKIPN T.XT+1(TB) ; WAS FCN SUPPLIED?
+ JRST TFA
+
+; FALLS TROUGH IF SKIP
+
+\f
+
+; NOW BUILD THE CHANNEL
+
+ARGSOK: MOVEI A,CHANLNT ; GET LENGTH
+ SKIPN B,RCYCHN+1 ; RECYCLE?
+ PUSHJ P,GIBLOK ; GET A BLOCK OF STUFF
+ SETZM RCYCHN+1
+ ADD B,[4,,4] ; HIDE THE TTY BUFFER SLOT
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ HRLI C,PROCHN ; POINT TO PROTOTYPE
+ HRRI C,(B) ; AND NEW ONE
+ BLT C,CHANLN-5(B) ; CLOBBER
+ MOVSI C,TLIST ; TO GIVE HIM A CLEAN LIST OF SCRIPT CHANS
+ HLLM C,SCRPTO-1(B)
+
+; NOW BLT IN STUFF FROM THE STACK
+
+ MOVSI C,T.DIR(TB) ; DIRECTION
+ HRRI C,DIRECT-1(B)
+ BLT C,SNAME(B)
+ MOVEI C,RNAME1-1(B) ; NOW "REAL" SLOTS
+ HRLI C,T.NM1(TB)
+ BLT C,RSNAME(B)
+ MOVE B,IMQUOTE MODE
+ PUSHJ P,IDVAL1
+ GETYP 0,A
+ CAIN 0,TFIX
+ JRST .+3
+ MOVE B,(TP)
+ POPJ P,
+
+ MOVE C,(TP)
+IFE ITS,[
+ ANDI B,403776 ; ONLY ALLOW NON-CRITICAL BITSS
+]
+ HRRM B,-4(C) ; HIDE BITS
+ MOVE B,C
+ POPJ P,
+
+; HERE TO VALIDIFY ARGUMENTS FOR A NET OPEN
+
+CHNET:
+IFN ITS,[
+ CAME D,[SIXBIT /NET /] ; IS IT NET
+ JRST MAKCH1]
+IFE ITS,[
+ CAIE D,(SIXBIT /NET/) ; IS IT NET
+ JRST ARGSOK]
+ MOVSI D,TFIX ; FOR TYPES
+ MOVEI B,T.NM1(TB) ; MAKE SURE ALL ARE FIXED
+ PUSHJ P,CHFIX
+ MOVEI B,T.NM2(TB)
+ PUSHJ P,CHFIX
+ MOVEI B,T.SNM(TB)
+ LSH A,-1 ; SKIP DEV FLAG
+ PUSHJ P,CHFIX
+ JRST ARGSOK
+
+MAKCH1: TRNN A,MSTNET ; CANT HAVE SEEN A FIX
+ JRST ARGSOK
+ JRST WRONGT
+
+IFN ITS,[
+CHFIX: TRNE A,N1SET ; SKIP IF NOT SPECIFIED
+ JRST CHFIX1
+ SETOM 1(B) ; SET TO -1
+ SETOM S.NM1(C)
+ MOVEM D,(B) ; CORRECT TYPE
+]
+IFE ITS,CHFIX:
+ GETYP 0,(B)
+ CAIE 0,TFIX
+ JRST PARSQ
+CHFIX1: ADDI C,1 ; POINT TO NEXT FIELD
+ LSH A,-1 ; AND NEXT FLAG
+ POPJ P,
+PARSQ: CAIE 0,TCHSTR
+ JRST WRONGT
+IFE ITS, POPJ P,
+IFN ITS,[
+ PUSH P,A
+ PUSH P,C
+ PUSH TP,(B)
+ PUSH TP,1(B)
+ SUBI B,(TB)
+ PUSH P,B
+ MCALL 1,PARSE
+ GETYP 0,A
+ CAIE 0,TFIX
+ JRST WRONGT
+ POP P,C
+ ADDI C,(TB)
+ MOVEM A,(C)
+ MOVEM B,1(C)
+ POP P,C
+ POP P,A
+ POPJ P,
+]
+\f
+
+; SUBROUTINE TO CHECK VALIDITY OF MODE AND SAVE A CODE
+
+CHMODE: PUSHJ P,CHMOD ; DO IT
+ MOVE C,T.SPDL+1(TB)
+ HRRZM A,S.DIR(C)
+ POPJ P,
+
+CHMOD: PUSHJ P,STRTO6 ; TO SIXBIT
+ POP P,B ; VALUE ENDSUP ON STACK, RESTORE IT
+
+ MOVSI A,-NMODES ; SCAN TO SEE IF LEGAL MODE
+ CAME B,MODES(A)
+ AOBJN A,.-1
+ JUMPGE A,WRONGD ; ILLEGAL MODE NAME
+ MOVE A,MODCOD(A)
+ POPJ P,
+\f
+
+IFN ITS,[
+; RGPARS -- PARSE THE STRINGS COMPRISING FILE NAMES INTO STANDARD ITS GOODIES
+
+RGPRS: MOVEI 0,NOSTOR ; DONT STORE STRINGS IF ENTER HERE
+
+RGPARS: CAMGE AB,[-7,,] ; MULTI-STRING CASE POSSIBLE?
+ IORI 0,4ARG ; 4 STRING CASE
+ HRLM 0,(P) ; LH IS FLAGS FOR THIS PROG
+ MOVSI E,-4 ; FIELDS TO FILL
+
+RPARGL: GETYP 0,(AB) ; GET TYPE
+ CAIE 0,TCHSTR ; STRING?
+ JRST ARGCLB ; NO, JUST CLOBBER IT IN RAW
+ JUMPGE E,CPOPJ ; DON'T DO ANY MORE
+ PUSH TP,(AB) ; GET AN ARG
+ PUSH TP,1(AB)
+
+FPARS: PUSH TP,-1(TP) ; ANOTHER COPY
+ PUSH TP,-1(TP)
+ HLRZ 0,(P)
+ TRNN 0,4ARG
+ PUSHJ P,FLSSP ; NO LEADING SPACES
+ MOVEI A,0 ; WILL HOLD SIXBIT
+ MOVEI B,6 ; CHARS PER 6BIT WORD
+ MOVE C,[440600,,A] ; BYTE POINTER INTO A
+
+FPARSL: HRRZ 0,-1(TP) ; GET COUNT
+ JUMPE 0,PARSD ; DONE
+ SOS -1(TP) ; COUNT
+ ILDB 0,(TP) ; CHAR TO 0
+
+ CAIE 0,"\11 ; FILE NAME QUOTE?
+ JRST NOCNTQ
+ HRRZ 0,-1(TP)
+ JUMPE 0,PARSD
+ SOS -1(TP)
+ ILDB 0,(TP) ; USE THIS
+ JRST GOTCNQ
+
+NOCNTQ: HLL 0,(P)
+ TLNE 0,4ARG
+ JRST GOTCNQ
+ ANDI 0,177
+ CAIG 0,40 ; SPACE?
+ JRST NDFLD ; YES, TERMINATE THIS FIELD
+ CAIN 0,": ; DEVICE ENDED?
+ JRST GOTDEV
+ CAIN 0,"; ; SNAME ENDED
+ JRST GOTSNM
+
+GOTCNQ: ANDI 0,177
+ PUSHJ P,A0TO6 ; CONVERT TO 6BIT AND CHECK
+
+ JUMPE B,FPARSL ; IGNORE IF AREADY HAVE 6
+ IDPB 0,C
+ SOJA B,FPARSL
+
+; HERE IF SPACE ENCOUNTERED
+
+NDFLD: MOVEI D,(E) ; COPY GOODIE
+ PUSHJ P,FLSSP ; FLUSH REDUNDANT SPACES
+ JUMPE 0,PARSD ; NO CHARS LEFT
+
+NFL0: PUSH P,A ; SAVE SIXBIT WORD
+ SKIPGE -1(P) ; SKIP IF STRING TO BE STORED
+ JRST NFL1
+ PUSH TP,$TAB ; PREVENT AB LOSSAGE
+ PUSH TP,AB
+ PUSHJ P,6TOCHS ; CONVERT TO STRING
+ MOVE AB,(TP)
+ SUB TP,[2,,2]
+NFL1: HRRZ 0,-1(TP) ; RESTORE CHAR COUNT
+
+NFL2: MOVEI C,(D) ; COPY REL PNTR
+ SKIPGE -1(P) ; SKIP IF STRINGS TO BE STORED
+ JRST NFL3
+ ASH D,1 ; TIMES 2
+ ADDI D,T.NM1(TB)
+ MOVEM A,(D) ; STORE
+ MOVEM B,1(D)
+NFL3: MOVSI A,N1SET ; FLAG IT
+ LSH A,(C)
+ IORM A,-1(P) ; AND CLOBBER
+ MOVE D,T.SPDL+1(TB) ; GET P BASE
+ POP P,@SIXTBL(C) ; AND STORE SIXBIT OF IT
+
+ POP TP,-2(TP) ; MAKE NEW STRING POINTER
+ POP TP,-2(TP)
+ JUMPE 0,.+3 ; SKIP IF NO MORE CHARS
+ AOBJN E,FPARS ; MORE TO PARSE?
+CPOPJ: POPJ P, ; RETURN, ALL DONE
+
+ SUB TP,[2,,2] ; FLUSH OLD STRING
+ ADD E,[1,,1]
+ ADD AB,[2,,2] ; BUMP ARG
+ MOVEM AB,ABSAV(TB)
+ JUMPL AB,RPARGL ; AND GO ON
+CPOPJ1: AOS A,(P) ; PREPARE TO WIN
+ HLRZS A
+ POPJ P,
+
+\f
+
+; HERE IF STRING HAS ENDED
+
+PARSD: PUSH P,A ; SAVE 6 BIT
+ MOVE A,-3(TP) ; CAN USE ARG STRING
+ MOVE B,-2(TP)
+ MOVEI D,(E)
+ JRST NFL2 ; AND CONTINUE
+
+; HERE IF JUST READ DEV
+
+GOTDEV: MOVEI D,2 ; CODE FOR DEVICE
+ JRST GOTFLD ; GOT A FIELD
+
+; HERE IF JUST READ SNAME
+
+GOTSNM: MOVEI D,3
+GOTFLD: PUSHJ P,FLSSP
+ SOJA E,NFL0
+
+
+; HERE FOR NON STRING ARG ENCOUNTERED
+
+ARGCLB: SKIPGE (P) ; IF NOT STORING, CONSIDER THIS THE END
+
+ POPJ P,
+ MOVE C,T.SPDL+1(TB) ; GET P-BASE
+ MOVE A,S.DEV(C) ; GET DEVICE
+ CAME A,[SIXBIT /INT /]; IS IT THE INTERNAL DEVICE
+ JRST TRYNET ; NO, COUD BE NET
+ MOVE A,0 ; OFFNEDING TYPE TO A
+ PUSHJ P,APLQ ; IS IT APPLICABLE
+ JRST NAPT ; NO, LOSE
+ PMOVEM (AB),T.XT(TB)
+ ADD AB,[2,,2] ; MUST BE LAST ARG
+ MOVEM AB,ABSAV(TB)
+ JUMPL AB,TMA
+ JRST CPOPJ1 ; ELSE SUCCESSFUL RETURN
+TRYNET: CAIE 0,TFIX ; FOR NET DEV, ARGS MUST BE FIX
+ JRST WRONGT ; TREAT AS WRONG TYPE
+ MOVSI A,MSTNET ; BETTER BE NET EVENTUALLY
+ IORM A,(P) ; STORE FLAGS
+ MOVSI A,TFIX
+ MOVE B,1(AB) ; GET NUMBER
+ MOVEI 0,(E) ; MAKE SURE NOT DEVICE
+ CAIN 0,2
+ JRST WRONGT
+ PUSH P,B ; SAVE NUMBER
+ MOVEI D,(E) ; SET FOR TABLE OFFSETS
+ MOVEI 0,0
+ ADD TP,[4,,4]
+ JRST NFL2 ; GO CLOBBER IT AWAY
+]
+\f
+
+; ROUTINE TO FLUSH LEADING SPACES FROM A FIELD
+
+FLSSP: HRRZ 0,-1(TP) ; GET CHR COUNNT
+ JUMPE 0,CPOPJ ; FINISHED STRING
+FLSS1: MOVE B,(TP) ; GET BYTR
+ ILDB C,B ; GETCHAR
+ CAIE C,^Q ; DONT FLUSH CNTL-Q
+ CAILE C,40
+ JRST FLSS2
+ MOVEM B,(TP) ; UPDATE BYTE POINTER
+ SOJN 0,FLSS1
+
+FLSS2: HRRM 0,-1(TP) ; UPDATE STRING
+ POPJ P,
+
+IFN ITS,[
+;TABLE FOR STFUFFING SIXBITS AWAY
+
+SIXTBL: SETZ S.NM1(D)
+ SETZ S.NM2(D)
+ SETZ S.DEV(D)
+ SETZ S.SNM(D)
+ SETZ S.X1(D)
+]
+
+RDTBL: SETZ RDEVIC(B)
+ SETZ RNAME1(B)
+ SETZ RNAME2(B)
+ SETZ RSNAME(B)
+
+
+\f
+IFE ITS,[
+
+; TENEX VERSION OF FILE NAME PARSER (ONLY ACCEPT ARGS IN SINGLE STRING)
+
+
+RGPRS: MOVEI 0,NOSTOR
+
+RGPARS: HRLM 0,(P) ; SAVE FOR STORE CHECKING
+ CAMGE AB,[-2,,] ; MULTI-STRING CASE POSSIBLE?
+ JRST TN.MLT ; YES, GO PROCESS
+RGPRSS: GETYP 0,(AB) ; CHECK ARG TYPE
+ CAIE 0,TCHSTR
+ JRST WRONGT ; FOR NOW ONLY STRING ARGS WIN
+ PUSH TP,(AB)
+ PUSH TP,1(AB)
+ PUSHJ P,FLSSP ; FLUSH LEADING SPACES
+ PUSHJ P,RGPRS1
+ ADD AB,[2,,2]
+ MOVEM AB,ABSAV(TB)
+CHKLST: JUMPGE AB,CPOPJ1
+ SKIPGE (P) ; IF FROM OPEN, ALLOW ONE MORE
+ POPJ P,
+ PMOVEM (AB),T.XT(TB)
+ ADD AB,[2,,2]
+ MOVEM AB,ABSAV(TB)
+ JUMPL AB,TMA
+CPOPJ1: AOS (P)
+ POPJ P,
+
+RGPRS1: PUSH P,[0] ; ALLOW A DEVICE SPEC
+TN.SNM: MOVE A,(TP)
+ HRRZ 0,-1(TP)
+ JUMPE 0,RPDONE
+ ILDB A,A
+ CAIE A,"< ; START "DIRECTORY" ?
+ JRST TN.N1 ; NO LOOK FOR NAME1
+ SETOM (P) ; DEV NOT ALLOWED
+ IBP (TP) ; SKIP CHAR
+ SOS -1(TP)
+ PUSHJ P,TN.CNT ; COUNT CHARS TO ">" OR "."
+ JUMPE B,ILLNAM ; RAN OUT
+ CAIE A,".
+ JRST TN.SN3
+ PUSH TP,0
+ PUSH TP,C
+TN.SN1: PUSHJ P,TN.CNT ; COUNT CHARS TO ">"
+ JUMPE B,ILLNAM ; RAN OUT
+ CAIE A,".
+ JRST TN.SN2
+ MOVEM 0,-1(TP)
+ MOVEM C,(TP)
+ JRST TN.SN1
+TN.SN2: HRRZ B,-3(TP)
+ SUB B,0
+ SUBI B,1
+ SUB TP,[2,,2]
+TN.SN3: CAIE A,"> ; SKIP IF WINS
+ JRST ILLNAM
+ PUSHJ P,TN.CPS ; COPY TO NEW STRING
+ HLLOS T.SPDL(TB)
+ MOVEM A,T.SNM(TB)
+ MOVEM B,T.SNM+1(TB)
+
+TN.N1: PUSHJ P,TN.CNT
+ JUMPE B,RPDONE
+ CAIE A,": ; GOT A DEVICE
+ JRST TN.N11
+ SKIPE (P)
+ JRST ILLNAM
+ SETOM (P)
+ PUSHJ P,TN.CPS
+ MOVEM A,T.DEV(TB)
+ MOVEM B,T.DEV+1(TB)
+ JRST TN.SNM ; NOW LOOK FOR SNAME
+
+TN.N11: CAIE A,">
+ CAIN A,"<
+ JRST ILLNAM
+ MOVEM A,(P) ; SAVE END CHAR
+ PUSHJ P,TN.CPS ; GEN STRING
+ MOVEM A,T.NM1(TB)
+ MOVEM B,T.NM1+1(TB)
+
+TN.N2: SKIPN A,(P) ; GET CHAR BACK
+ JRST RPDONE
+ CAIN A,"; ; START VERSION?
+ JRST .+3
+ CAIE A,". ; START NAME2?
+ JRST ILLNAM ; I GIVE UP!!!
+ HRRZ B,-1(TP) ; GET RMAINS OF STRING
+ PUSHJ P,TN.CPS ; AND COPY IT
+ MOVEM A,T.NM2(TB)
+ MOVEM B,T.NM2+1(TB)
+RPDONE: SUB P,[1,,1] ; FLUSH TEMP
+ SUB TP,[2,,2]
+CPOPJ: POPJ P,
+
+TN.CNT: HRRZ 0,-1(TP) ; CHAR COUNT
+ MOVE C,(TP) ; BPTR
+ MOVEI B,0 ; INIT COUNT TO 0
+
+TN.CN1: MOVEI A,0 ; IN CASE RUN OUT
+ SOJL 0,CPOPJ ; RUN OUT?
+ ILDB A,C ; TRY ONE
+ CAIE A,"\16 ; TNEX FILE QUOTE?
+ JRST TN.CN2
+ SOJL 0,CPOPJ
+ IBP C ; SKIP QUOTED CHAT
+ ADDI B,2
+ JRST TN.CN1
+
+TN.CN2: CAIE A,"<
+ CAIN A,">
+ POPJ P,
+
+ CAIE A,".
+ CAIN A,";
+ POPJ P,
+ CAIN A,":
+ POPJ P,
+ AOJA B,TN.CN1
+
+TN.CPS: PUSH P,B ; # OF CHARS
+ MOVEI A,4(B) ; ADD 4 TO B IN A
+ IDIVI A,5
+ PUSHJ P,IBLOCK ; GET BLOCK OF WORDS FOR STRING
+
+ POP P,C ; CHAR COUNT BACK
+ HRLI B,010700
+ SUBI B,1
+ MOVSI A,TCHSTR
+ HRRI A,(C) ; CHAR STRING
+ MOVE D,B ; COPY BYTER
+
+ JUMPE C,CPOPJ
+ ILDB 0,(TP) ; GET CHAR
+ IDPB 0,D ; AND STROE
+ SOJG C,.-2
+
+ MOVNI C,(A) ; - LENGTH TO C
+ ADDB C,-1(TP) ; DECREMENT WORDS COUNT
+ TRNN C,-1 ; SKIP IF EMPTY
+ POPJ P,
+ IBP (TP)
+ SOS -1(TP) ; ELSE FLUSH TERMINATOR
+ POPJ P,
+
+ILLNAM: ERRUUO EQUOTE ILLEGAL-TENEX-FILE-NAME
+
+TN.MLT: MOVE A,AB ; AOBJN POINTER TO ARGS IN A
+
+TN.ML1: GETYP 0,(A) ; IS THIS ARG OF RIGHT TYPE
+ CAIE 0,TFIX
+ CAIN 0,TCHSTR
+ JRST .+2
+ JRST RGPRSS ; ASSUME SINGLE STRING
+ ADD A,[2,,2]
+ JUMPL A,TN.ML1 ; TRY NEXT ARG IF ANY LEFT
+
+ MOVEI 0,T.NM1(TB) ; 1ST WORD OF DESTINATION
+ HLRO A,AB ; MINUS NUMBER OF ARGS IN A
+ MOVN A,A ; NUMBER OF ARGS IN A
+ SUBI A,1
+ CAMGE AB,[-10,,0]
+ MOVEI A,7 ; IF MORE THAN 10 ARGS, PUT 7
+ ADD A,0 ; LAST WORD OF DESTINATION
+ HRLI 0,(AB)
+ BLT 0,(A) ; BLT 'EM IN
+ ADD AB,[10,,10] ; SKIP THESE GUYS
+ MOVEM AB,ABSAV(TB)
+ JRST CHKLST
+
+]
+\f
+
+; ROUTINE TO OPEN A CHANNEL FOR ANY DEVICE. NAMES ARE ASSUMED TO ALREADY
+; BE ON BOTH TP STACK AND P STACK
+
+OPNCH: MOVE C,T.SPDL+1(TB) ; GET PDL BASE
+ HRRZ A,S.DIR(C)
+ ANDI A,1 ; JUST WANT I AND O
+IFE ITS,[
+ HRLM A,S.DEV(C)
+; .TRANS S.DEV(C) ; UNDO ANY TRANSLATIONS
+; JRST TRLOST ; COMPLAIN
+]
+IFN ITS,[
+ HRLM A,S.DIR(C)
+]
+
+IFN ITS,[
+ MOVE A,S.DEV(C) ; GET SIXBIT DEVICE CODE
+]
+
+IFE ITS,[HRLZS A,S.DEV(C)
+]
+
+ MOVSI B,-NDEVS ; AOBJN COUNTER
+DEVLP: SETO D,
+ MOVE 0,DEVSTB(B) ; GET ONE FROM TABLE
+ MOVE E,A
+DEVLP1: AND E,D ; FLUSH POSSIBLE DIGITNESS
+ CAMN 0,E
+ JRST CHDIGS ; MAKE SURE REST IS DIGITS
+ LSH D,6
+ JUMPN D,DEVLP1 ; KEEP TRUCKING UNTIL DONE
+
+; WASN'T THAT DEVICE, MOVE TO NEXT
+NXTDEV: AOBJN B,DEVLP
+ JRST ODSK ; UNKNOWN DEVICE IS ASSUMED TO BE DISK
+
+IFN ITS,[
+OUSR: HRRZ A,S.DIR(C) ; BLOCK OR UNIT?
+ TRNE A,2 ; SKIP IF UNIT
+ JRST ODSK
+ PUSHJ P,OPEN1 ; OPEN IT
+ PUSHJ P,FIXREA ; AND READCHST IT
+ MOVE B,T.CHAN+1(TB) ; RESTORE CHANNEL
+ MOVE 0,[PUSHJ P,DOIOT] ; GET AN IOINS
+ MOVEM 0,IOINS(B)
+ MOVE C,T.SPDL+1(TB)
+ HRRZ A,S.DIR(C)
+ TRNN A,1
+ JRST EOFMAK
+ MOVEI 0,80.
+ MOVEM 0,LINLN(B)
+ JRST OPNWIN
+
+OSTY: HLRZ A,S.DIR(C)
+ IORI A,10 ; THE DONT LOSE BIT (DONT HANG ON INPUT DO ON OUTPUT)
+ HRLM A,S.DIR(C)
+ JRST OUSR
+]
+
+; MAKE SURE DIGITS EXIST
+
+CHDIGS: SETCA D,
+ JUMPE D,DISPA ; NO DIGITS, WIN IMMEDIATE
+ MOVE E,A
+ AND E,D ; LEAVES ONLY DIGITS, IF WINNING
+ LSH E,6
+ LSH D,6
+ JUMPG D,.-2 ; KEEP GOING TIL DIGITS LEFT SHIFTED
+ JRST CHDIGN
+
+CHDIG1: CAIG D,'9
+ CAIGE D,'0
+ JRST NXTDEV ; NOT A DIGIT, LOSE
+ JUMPE E,DISPA ; IF THAT'S ALL THE CHARACTERS, WIN!
+CHDIGN: SETZ D,
+ ROTC D,6 ; GET NEXT CHARACTER INTO D
+ JRST CHDIG1 ; GO TEST?
+
+; HERE TO DISPATCH IF SUCCESSFUL
+
+DISPA: JRST @DEVS(B)
+
+\f
+IFN ITS,[
+
+; DISK DEVICE OPNER COME HERE
+
+ODSK: MOVE A,S.SNM(C) ; GET SNAME
+ .SUSET [.SSNAM,,A] ; CLOBBER IT
+ PUSHJ P,OPEN0 ; DO REAL LIVE OPEN
+]
+IFE ITS,[
+
+; TENEX DISK FILE OPENER
+
+ODSK: MOVE B,T.CHAN+1(TB) ; GET CHANNEL
+ PUSHJ P,STSTK ; EXPAND STRING ONTO STACK (E POINTS TO OLD P)
+ MOVE A,DIRECT-1(B)
+ MOVE B,DIRECT(B)
+ PUSHJ P,STRTO6 ; GET DIR NAME
+ MOVE C,(P)
+ MOVE D,T.SPDL+1(TB)
+ HRRZ D,S.DIR(D)
+ CAME C,[SIXBIT /PRINAO/]
+ CAMN C,[SIXBIT /PRINTO/]
+ IORI D,100 ; TURN ON BIT TO SAY USE OLD FILE
+ MOVSI A,101 ; START SETTING UP BITS EXTRA BIT FOR MSB
+ TRNE D,1 ; SKIP IF INPUT
+ TRNE D,100 ; WITE OVER?
+ TLOA A,100000 ; FORCE OLD VERSION
+ TLO A,600000 ; FORCE NEW VERSION
+ HRROI B,1(E) ; POINT TO STRING
+ GTJFN
+ TDZA 0,0 ; SAVE FACT OF NO SKIP
+ MOVEI 0,1 ; INDICATE SKIPPED
+ POP P,C ; RECOVER OPEN MODE SIXBIT
+ MOVE P,E ; RESTORE PSTACK
+ JUMPE 0,GTJLOS ; FIND OUT WHAT HAPPENED
+
+ MOVE B,T.CHAN+1(TB) ; GET CHANNEL
+ HRRZ 0,-4(B) ; FUNNY MODE BITS
+ HRRZM A,CHANNO(B) ; SAVE IT
+ ANDI A,-1 ; READ Y TO DO OPEN
+ MOVSI B,440000 ; USE 36. BIT BYES
+ HRRI B,200000 ; ASSUME READ
+; CAMN C,[SIXBIT /READB/]
+; TRO B,2000 ; TURN ON THAWED IF READB
+ IOR B,0
+ TRNE D,1 ; SKIP IF READ
+ HRRI B,300000 ; WRITE BIT
+ HRRZ 0,FSAV(TB) ; SEE IF REF DATE HACK
+ CAIN 0,NFOPEN
+ TRO B,400 ; SET DON'T MUNG REF DATE BIT
+ MOVE E,B ; SAVE BITS FOR REOPENS
+ OPENF
+ JRST OPFLOS
+ MOVE B,[2,,11] ; GET LENGTH & BYTE SIZE
+ PUSH P,[0]
+ PUSH P,[0]
+ MOVEI C,-1(P)
+ GTFDB
+ LDB 0,[300600,,-1(P)] ; GET BYTE SIZE
+ MOVE B,(P)
+ SUB P,[2,,2]
+ CAIN 0,7
+ JRST SIZASC
+ CAIN 0,36.
+ SIZEF ; USE OPENED SIZE
+ JFCL
+ IMULI B,5 ; TO BYTES
+SIZASC: MOVEI 0,C.OPN+C.READ+C.DISK
+ TRNE D,1 ; SKIP FOR READ
+ MOVEI 0,C.OPN+C.PRIN+C.DISK
+ TRNE D,2 ; SKIP IF NOT BINARY FILE
+ TRO 0,C.BIN
+ HRL 0,B
+ MOVE B,T.CHAN+1(TB)
+ TRNE D,1
+ HLRM 0,LSTCH-1(B) ; SAVE CURRENT LENGTH
+ MOVEM E,STATUS(B)
+ HRRM 0,-2(B) ; MUNG THOSE BITS
+ ASH A,1 ; POINT TO SLOT
+ ADDI A,CHNL0 ; TO REAL SLOT
+ MOVEM B,1(A) ; SAVE CHANNEL
+ PUSHJ P,TMTNXS ; GET STRING FROM TENEX
+ MOVE B,CHANNO(B) ; JFN TO A
+ HRROI A,1(E) ; BASE OF STRING
+ MOVE C,[111111,,140001] ; WEIRD CONTROL BITS
+ JFNS ; GET STRING
+ MOVEI B,1(E) ; POINT TO START OF STRING
+ SUBM P,E ; RELATIVIZE E
+ PUSHJ P,TNXSTR ; MAKE INTO A STRING
+ SUB P,E ; BACK TO NORMAL
+ PUSH TP,A
+ PUSH TP,B
+ PUSHJ P,RGPRS1 ; PARSE INTO FIELDS
+ MOVE B,T.CHAN+1(TB)
+ MOVEI C,RNAME1-1(B)
+ HRLI C,T.NM1(TB)
+ BLT C,RSNAME(B)
+ JRST OPBASC
+OPFLOS: MOVEI C,(A) ; SAVE ERROR CODE
+ MOVE B,T.CHAN+1(TB)
+ HRRZ A,CHANNO(B) ; JFN BACK TO A
+ RLJFN ; TRY TO RELEASE IT
+ JFCL
+ MOVEI A,(C) ; ERROR CODE BACK TO A
+
+GTJLOS: MOVE B,T.CHAN+1(TB)
+ PUSHJ P,TGFALS ; GET A FALSE WITH REASON
+ JRST OPNRET
+
+STSTK: PUSH TP,$TCHAN
+ PUSH TP,B
+ MOVEI A,4+5 ; COUNT CHARS NEEDED (NEED LAST 0 BYTE)
+ MOVE B,(TP)
+ ADD A,RDEVIC-1(B)
+ ADD A,RNAME1-1(B)
+ ADD A,RNAME2-1(B)
+ ADD A,RSNAME-1(B)
+ ANDI A,-1 ; TO 18 BITS
+ MOVEI 0,A(A)
+ IDIVI A,5 ; TO WORDS NEEDED
+ POP P,C ; SAVE RET ADDR
+ MOVE E,P ; SAVE POINTER
+ PUSH P,[0] ; ALOCATE SLOTS
+ SOJG A,.-1
+ PUSH P,C ; RET ADDR BACK
+ INTGO ; IN CASE OVERFLEW
+ PUSH P,0
+ MOVE B,(TP) ; IN CASE GC'D
+ MOVE D,[440700,,1(E)] ; BYTE POINTER TO IT
+ MOVEI A,RDEVIC-1(B)
+ PUSHJ P,MOVSTR ; FLUSH IT ON
+ HRRZ A,T.SPDL(TB)
+ JUMPN A,NLNMS ; USER GAVE NAME, USE IT (CAREFUL, RELIES ON
+ ; A BEING NON ZERO)
+ PUSH P,B
+ PUSH P,C
+ MOVEI A,0 ; HERE TO SEE IF THIS IS REALLY L.N.
+ HRROI B,1(E)
+ HRROI C,1(P)
+ LNMST ; LOOK UP LOGICAL NAME
+ MOVNI A,1 ; NOT A LOGICAL NAME
+ POP P,C
+ POP P,B
+NLNMS: MOVEI 0,":
+ IDPB 0,D
+ JUMPE A,ST.NM1 ; LOGICAL NAME, FLUSH SNAME
+ HRRZ A,RSNAME-1(B) ; ANY SNAME AT ALL?
+ JUMPE A,ST.NM1 ; NOPE, CANT HACK WITH IT
+ MOVEI A,"<
+ IDPB A,D
+ MOVEI A,RSNAME-1(B)
+ PUSHJ P,MOVSTR ; SNAME UP
+ MOVEI A,">
+ IDPB A,D
+ST.NM1: MOVEI A,RNAME1-1(B)
+ PUSHJ P,MOVSTR
+ MOVEI A,".
+ IDPB A,D
+ MOVEI A,RNAME2-1(B)
+ PUSHJ P,MOVSTR
+ SUB TP,[2,,2]
+ POP P,A
+ POPJ P,
+
+MOVSTR: HRRZ 0,(A) ; CHAR COUNT
+ MOVE A,1(A) ; BYTE POINTER
+ SOJL 0,CPOPJ
+ ILDB C,A ; GET CHAR
+ IDPB C,D ; MUNG IT UP
+ JRST .-3
+
+; MAKE A TENEX ERROR MESSAGE STRING
+
+TGFALS: PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH P,A ; SAVE ERROR CODE
+ PUSHJ P,TMTNXS ; STRING ON STACK
+ HRROI A,1(E) ; POINT TO SPACE
+ MOVE B,(E) ; ERROR CODE
+ HRLI B,400000 ; FOR ME
+ MOVSI C,-100. ; MAX CHARS
+ ERSTR ; GET TENEX STRING
+ JRST TGFLS1
+ JRST TGFLS1
+
+ MOVEI B,1(E) ; A AND B BOUND STRING
+ SUBM P,E ; RELATIVIZE E
+ PUSHJ P,TNXSTR ; BUILD STRING
+ SUB P,E ; P BACK TO NORMAL
+TGFLS2:
+IFE FNAMS, SUB P,[1,,1] ; FLUSH ERROR CODE SLOT
+IFN FNAMS,[
+ PUSH TP,A
+ PUSH TP,B
+ SKIPN B,-2(TP)
+ JRST TGFLS3
+ PUSHJ P,STSTK
+ MOVEI B,1(E)
+ SUBM P,E
+ MOVSI A,440700
+ HRRI A,(P)
+ MOVEI C,5
+ ILDB 0,A
+ JUMPE 0,.+2
+ SOJG C,.-2
+
+ PUSHJ P,TNXSTR
+ PUSH TP,A
+ PUSH TP,B
+ SUB P,E
+TGFLS3: POP P,A
+ PUSH TP,$TFIX
+ PUSH TP,A
+ MOVEI A,3
+ SKIPN B
+ MOVEI A,2
+]
+IFE FNAMS,[
+ MOVEI A,1
+]
+ PUSHJ P,IILIST ; BUILD LIST
+ MOVSI A,TFALSE ; MAKE IT FALSE
+ SUB TP,[2,,2]
+ POPJ P,
+
+TGFLS1: MOVE P,E ; RESET STACK
+ MOVE A,$TCHSTR
+ MOVE B,CHQUOTE UNKNOWN PROBLEM IN I/O
+ JRST TGFLS2
+
+]
+; OTHER BUFFERED DEVICES JOIN HERE
+
+OPDSK1:
+IFN ITS,[
+ PUSHJ P,FIXREA ; STORE THE "REAL" NAMES INTO THE CHANNEL
+]
+OPBASC: MOVE C,T.SPDL+1(TB) ; C WAS CLOBBERED, GET IT BACK
+ HRRZ A,S.DIR(C) ; FIND OUT IF OPEN IS ASCII OR WORD
+ TRZN A,2 ; SKIP IF BINARY
+ PUSHJ P,OPASCI ; DO IT FOR ASCII
+
+; NOW SET UP IO INSTRUCTION FOR CHANNEL
+
+MAKION: MOVE B,T.CHAN+1(TB)
+ MOVEI C,GETCHR
+ JUMPE A,MAKIO1 ; JUMP IF INPUT
+ MOVEI C,PUTCHR ; ELSE GET INPUT
+ MOVEI 0,80. ; DEFAULT LINE LNTH
+ MOVEM 0,LINLN(B)
+ MOVSI 0,TFIX
+ MOVEM 0,LINLN-1(B)
+MAKIO1:
+ HRLI C,(PUSHJ P,)
+ MOVEM C,IOINS(B) ; STORE IT
+ JUMPN A,OPNWIN ; GET AN EOF FORM FOR INPUT CHANNEL
+
+; HERE TO CONS UP <ERROR END-OF-FILE>
+
+EOFMAK: MOVSI C,TATOM
+ MOVE D,EQUOTE END-OF-FILE
+ PUSHJ P,INCONS
+ MOVEI E,(B)
+ MOVSI C,TATOM
+ MOVE D,IMQUOTE ERROR
+ PUSHJ P,ICONS
+ MOVE D,T.CHAN+1(TB) ; RESTORE CHANNEL
+ MOVSI 0,TFORM
+ MOVEM 0,EOFCND-1(D)
+ MOVEM B,EOFCND(D)
+
+OPNWIN: MOVEI 0,10. ; SET UP RADIX
+ MOVSI A,TCHAN ; OPEN SUCCEEDED, RET CHANNEL
+ MOVE B,T.CHAN+1(TB)
+ MOVEM 0,RADX(B)
+
+OPNRET: MOVE D,T.CHAN+1(TB) ; IN CASE WE RECYCLE IT
+ MOVE C,(P) ; RET ADDR
+ SUB P,[S.X3+2,,S.X3+2]
+ SUB TP,[T.CHAN+2,,T.CHAN+2]
+ JRST (C)
+\f
+
+; HERE TO CREATE CHARACTER BUFFERS FOR ASCII I/O
+
+OPASCI: PUSH P,A ; CONTAINS MODE, SAVE IT
+ MOVEI A,BUFLNT ; GET SIZE OF BUFFER
+ PUSHJ P,IBLOCK ; GET STORAGE
+ MOVSI 0,TWORD+.VECT. ; SET UTYPE
+ MOVEM 0,BUFLNT(B) ; AND STORE
+ MOVSI A,TCHSTR
+ SKIPE (P) ; SKIP IF INPUT
+ JRST OPASCO
+ MOVEI D,BUFLNT-1(B) ; REST BYTE POINTER
+OPASCA: HRLI D,010700
+ MOVE B,T.CHAN+1(TB) ; GET CHANNEL BACK
+ MOVEI 0,C.BUF
+ IORM 0,-2(B) ; TURN ON BUFFER BIT
+ MOVEM A,BUFSTR-1(B)
+ MOVEM D,BUFSTR(B) ; CLOBBER
+ POP P,A
+ POPJ P,
+
+OPASCO: HRROI C,777776
+ MOVEM C,(B) ; -1 THE BUFFER (LEAVE OFF LOW BIT)
+ MOVSI C,(B)
+ HRRI C,1(B) ; BUILD BLT POINTER
+ BLT C,BUFLNT-1(B) ; ZAP
+ MOVEI D,-1(B) ; START MAKING STRING POINTER
+ HRRI A,BUFLNT*5 ; SET UP CHAR COUNT
+ JRST OPASCA
+\f
+
+; OPEN NON FILE ORIENTED DEVICES (NUL, PTR, PTP ETC.)
+
+IFN ITS,[
+ONUL:
+OPTP:
+OPTR: PUSHJ P,OPEN0 ; SET UP MODE AND OPEN
+ SETZM S.NM1(C) ; CLOBBER UNINTERESTING FIELDS
+ SETZM S.NM2(C)
+ SETZM S.SNM(C)
+ JRST OPDSK1
+
+; OPEN DEVICES THAT IGNORE SNAME
+
+OUTN: PUSHJ P,OPEN0
+ SETZM S.SNM(C)
+ JRST OPDSK1
+
+]
+
+; INTERNAL CHANNEL OPENER
+
+OINT: HRRZ A,S.DIR(C) ; CHECK DIR
+ CAIL A,2 ; READ/PRINT?
+ JRST WRONGD ; NO, LOSE
+
+ MOVE 0,INTINS(A) ; GET INS
+ MOVE D,T.CHAN+1(TB) ; AND CHANNEL
+ MOVEM 0,IOINS(D) ; AND CLOBBER
+ MOVEI 0,C.OPN+C.READ
+ TRNE A,1
+ MOVEI 0,C.OPN+C.PRIN
+ HRRM 0,-2(D)
+ SETOM STATUS(D) ; MAKE SURE NOT AA TTY
+ PMOVEM T.XT(TB),INTFCN-1(D)
+
+; HERE TO SAVE PSEUDO CHANNELS
+
+SAVCHN: HRRZ E,CHNL0+1 ; POINT TO CURRENT LIST
+ MOVSI C,TCHAN
+ PUSHJ P,ICONS ; CONS IT ON
+ HRRZM B,CHNL0+1
+ JRST OPNWIN
+
+; INT DEVICE I/O INS
+
+INTINS: PUSHJ P,GTINTC
+ PUSHJ P,PTINTC
+\f
+
+; HERE TO OPEN THE NET DEVICE (I.E. THE ARPA NET)
+
+IFN ITS,[
+ONET: HRRZ A,S.DIR(C) ; DIRECTION CODE
+ CAILE A,1 ; ASCII ?
+ IORI A,4 ; TURN ON IMAGE BIT
+ SKIPGE S.NM1(C) ; NAME1 I.E. LOCAL HOST GIVEN
+ IORI A,10 ; NO, WE WILL LET ITS GIVE US ONE
+ SKIPGE S.NM2(C) ; NORMAL OR "LISTEN"
+ IORI A,20 ; TURN ON LISTEN BIT
+ MOVEI 0,7 ; DEFAULT BYTE SIZE
+ TRNE A,2 ; UNLESS
+ MOVEI 0,36. ; IMAGE WHICH IS 36
+ SKIPN T.XT(TB) ; BYTE SIZE GIVEN?
+ MOVEM 0,S.X1(C) ; NO, STORE DEFAULT
+ SKIPG D,S.X1(C) ; BYTE SIZE REASONABLE?
+ JRST RBYTSZ ; NO <0, COMPLAIN
+ TRNE A,2 ; SKIP TO CHECK ASCII
+ JRST ONET2 ; CHECK IMAGE
+ CAIN D,7 ; 7-BIT WINS
+ JRST ONET1
+ CAIE D,44 ; 36-BIT INDICATES BLOCK ASCII MODE
+ JRST .+3
+ IORI A,2 ; SET BLOCK FLAG
+ JRST ONET1
+ IORI A,40 ; USE 8-BIT MODE
+ CAIN D,10 ; IS IT RIGHT
+ JRST ONET1 ; YES
+]
+
+RBYTSZ: ERRUUO EQUOTE BYTE-SIZE-BAD
+
+IFN ITS,[
+ONET2: CAILE D,36. ; IMAGE SIZE REASONABLE?
+ JRST RBYTSZ ; NO
+ CAIN D,36. ; NORMAL
+ JRST ONET1 ; YES, DONT SET FIELD
+
+ ASH D,9. ; POSITION FOR FIELD
+ IORI A,40(D) ; SET IT AND ITS BIT
+
+ONET1: HRLM A,S.DIR(C) ; CLOBBER OPEN BLOCK
+ MOVE E,A ; SAVE BLOCK MODE INFO
+ PUSHJ P,OPEN1 ; DO THE OPEN
+ PUSH P,E
+
+; CLOBBER REAL SLOTS FOR THE OPEN
+
+ MOVEI A,3 ; GET STATE VECTOR
+ PUSHJ P,IBLOCK
+ MOVSI A,TUVEC
+ MOVE D,T.CHAN+1(TB)
+ HLLM A,BUFRIN-1(D)
+ MOVEM B,BUFRIN(D)
+ MOVSI A,TFIX+.VECT. ; SET U TYPE
+ MOVEM A,3(B)
+ MOVE C,T.SPDL+1(TB)
+ MOVE B,T.CHAN+1(TB)
+
+ PUSHJ P,INETST ; GET STATE
+
+ POP P,A ; IS THIS BLOCK MODE
+ MOVEI 0,80. ; POSSIBLE LINE LENGTH
+ TRNE A,1 ; SKIP IF INPUT
+ MOVEM 0,LINLN(B)
+ TRNN A,2 ; BLOCK MODE?
+ JRST .+3
+ TRNN A,4 ; ASCII MODE?
+ JRST OPBASC ; GO SETUP BLOCK ASCII
+ MOVE 0,[PUSHJ P,DOIOT]
+ MOVEM 0,IOINS(B)
+
+ JRST OPNWIN
+
+; INTERNAL ROUTINE TO GET THE CURRENT STATE OF THE NETWROK CHANNEL
+
+INETST: MOVE A,S.NM1(C)
+ MOVEM A,RNAME1(B)
+ MOVE A,S.NM2(C)
+ MOVEM A,RNAME2(B)
+ LDB A,[1100,,S.SNM(C)]
+ MOVEM A,RSNAME(B)
+
+ MOVE E,BUFRIN(B) ; GET STATE BLOCK
+INTST1: HRRE 0,S.X1(C)
+ MOVEM 0,(E)
+ ADDI C,1
+ AOBJN E,INTST1
+
+ POPJ P,
+\f
+
+; ACCEPT A CONNECTION
+
+MFUNCTION NETACC,SUBR
+
+ PUSHJ P,ARGNET ; CHECK THAT ARG IS AN OPEN NET CHANNEL
+ MOVE A,CHANNO(B) ; GET CHANNEL
+ LSH A,23. ; TO AC FIELD
+ IOR A,[.NETACC]
+ XCT A
+ JRST IFALSE ; RETURN FALSE
+NETRET: MOVE A,(AB)
+ MOVE B,1(AB)
+ JRST FINIS
+
+; FORCE SYSTEM NETWORK BUFFERS TO BE SENT
+
+MFUNCTION NETS,SUBR
+
+ PUSHJ P,ARGNET
+ CAME A,MODES+1
+ CAMN A,MODES+3
+ SKIPA A,CHANNO(B) ; GET CHANNEL
+ JRST WRONGD
+ LSH A,23.
+ IOR A,[.NETS]
+ XCT A
+ JRST NETRET
+
+; SUBR TO RETURN UPDATED NET STATE
+
+MFUNCTION NETSTATE,SUBR
+
+ PUSHJ P,ARGNET ; IS IT A NET CHANNEL
+ PUSHJ P,INSTAT
+ JRST FINIS
+
+; INTERNAL NETSTATE ROUTINE
+
+INSTAT: MOVE C,P ; GET PDL BASE
+ MOVEI 0,S.X3 ; # OF SLOTS NEEDED
+ PUSH P,[0]
+ SOJN 0,.-1
+; RESTORED FROM MUDDLE 54. IT SEEMED TO WORK THERE, AND THE STUFF
+; COMMENTED OUT HERE CERTAINLY DOESN'T.
+ MOVEI D,S.DEV(C)
+ HRL D,CHANNO(B)
+ .RCHST D,
+; HRR D,CHANNO(B) ; SETUP FOR RFNAME CALL
+; DOTCAL RFNAME,[D,[2003,,S.DEV],[2003,,S.NM1],[2003,,S.NM2],[2003,,S.SNM]]
+; .LOSE %LSFIL ; THIS MAY NOT BE DESIRABLE, BUT I ASSUME WE CARE IF
+ ; LOSSAGE
+ PUSHJ P,INETST ; INTO VECTOR
+ SUB P,[S.X3,,S.X3]
+ MOVE B,BUFRIN(B)
+ MOVSI A,TUVEC
+ POPJ P,
+]
+; INTERNAL ROUTINE TO CHECK FOR CORRECT CHANNEL TYPE
+
+ARGNET: ENTRY 1
+ GETYP 0,(AB)
+ CAIE 0,TCHAN
+ JRST WTYP1
+ MOVE B,1(AB) ; GET CHANNEL
+ SKIPN CHANNO(B) ; OPEN?
+ JRST CHNCLS
+ MOVE A,RDEVIC-1(B) ; GET DEV NAME
+ MOVE B,RDEVIC(B)
+ PUSHJ P,STRTO6
+ POP P,A
+ CAME A,[SIXBIT /NET /]
+ JRST NOTNET
+ MOVE B,1(AB)
+ MOVE A,DIRECT-1(B) ; CHECK FOR A READ SOCKET
+ MOVE B,DIRECT(B)
+ PUSHJ P,STRTO6
+ MOVE B,1(AB) ; RESTORE CHANNEL
+ POP P,A
+ POPJ P,
+\f
+IFE ITS,[
+
+; TENEX NETWRK OPENING CODE
+
+ONET: MOVE B,T.CHAN+1(TB) ; GET CHANNEL
+ MOVSI C,100700
+ HRRI C,1(P)
+ MOVE E,P
+ PUSH P,[ASCII /NET:/] ; FOR STRINGS
+ GETYP 0,RNAME1-1(B) ; CHECK TYPE
+ CAIE 0,TFIX ; SKIP IF # SUPPLIED
+ JRST ONET1
+ MOVE 0,RNAME1(B) ; GET IT
+ PUSHJ P,FIXSTK
+ JFCL
+ JRST ONET2
+ONET1: CAIE 0,TCHSTR
+ JRST WRONGT
+ HRRZ 0,RNAME1-1(B)
+ MOVE B,RNAME1(B)
+ JUMPE 0,ONET2
+ ILDB A,B
+ JSP D,ONETCH
+ SOJA 0,.-3
+ONET2: MOVEI A,".
+ JSP D,ONETCH
+ MOVE B,T.CHAN+1(TB)
+ GETYP 0,RNAME2-1(B)
+ CAIE 0,TFIX
+ JRST ONET3
+ GETYP 0,RSNAME-1(B)
+ CAIE 0,TFIX
+ JRST WRONGT
+ MOVE 0,RSNAME(B)
+ CAIG 0,377 ;NEW STYLE 32 BIT HOST NUMBER?
+ JRST ONET2A
+;CONVERT HOSTS2 HOST NUMBERS TO INTERNET (TOPS-20) HOST NUMBERS
+ MOVEI A,0
+ LDB B,[001100,,0] ;HOST NUMBER: 1.1-1.9 ->
+ DPB B,[201000,,A] ; 2.8-3.6
+ LDB B,[111100,,0] ;IMP LOW BITS: 2.1-2.9 ->
+ DPB B,[001000,,A] ; 1.1-1.8
+ LDB B,[221100,,0] ;IMP HIGH BITS: 3.1-3.9 ->
+ DPB B,[101000,,A] ; 1.9-2.7
+ LDB B,[331100,,0] ;NETWORK: 4.1-4.9 ->
+ DPB B,[301000,,A] ; 3.7-4.5
+ MOVE 0,A
+ONET2A: PUSHJ P,FIXSTK
+ JRST ONET4
+ MOVE B,T.CHAN+1(TB)
+ MOVEI A,"-
+ JSP D,ONETCH
+ MOVE 0,RNAME2(B)
+ PUSHJ P,FIXSTK
+ JRST WRONGT
+ JRST ONET4
+ONET3: CAIE 0,TCHSTR
+ JRST WRONGT
+ HRRZ 0,RNAME2-1(B)
+ MOVE B,RNAME2(B)
+ JUMPE 0,ONET4
+ ILDB A,B
+ JSP D,ONETCH
+ SOJA 0,.-3
+
+ONET4:
+ONET5: MOVE B,T.CHAN+1(TB)
+ GETYP 0,RNAME2-1(B)
+ CAIN 0,TCHSTR
+ JRST ONET6
+ MOVEI A,";
+ JSP D,ONETCH
+ MOVEI A,"T
+ JSP D,ONETCH
+ONET6: MOVSI A,1
+ HRROI B,1(E) ; STRING POINTER
+ GTJFN ; GET THE G.D JFN
+ TDZA 0,0 ; REMEMBER FAILURE
+ MOVEI 0,1
+ MOVE P,E ; RESTORE P
+ JUMPE 0,GTJLOS ; CONS UP ERROR STRING
+
+ MOVE B,T.CHAN+1(TB)
+ HRRZM A,CHANNO(B) ; SAVE THE JFN
+
+ MOVE C,T.SPDL+1(TB)
+ MOVE D,S.DIR(C)
+ MOVEI B,10
+ TRNE D,2
+ MOVEI B,36.
+ SKIPE T.XT(TB)
+ MOVE B,T.XT+1(TB)
+ JUMPL B,RBYTSZ
+ CAILE B,36.
+ JRST RBYTSZ
+ ROT B,-6
+ TLO B,3400
+ HRRI B,200000
+ TRNE D,1 ; SKIP FOR INPUT
+ HRRI B,100000
+ ANDI A,-1 ; ISOLATE JFCN
+ OPENF
+ JRST OPFLOS ; REPORT ERROR
+ MOVE B,T.CHAN+1(TB)
+ ASH A,1 ; POINT TO SLOT
+ ADDI A,CHNL0 ; TO REAL SLOT
+ MOVEM B,1(A) ; SAVE CHANNEL
+ MOVE C,T.SPDL+1(TB) ; POINT TO P BASE
+ HRRZ A,S.DIR(C) ; 0/ 0 FOR READ 0/ 1 FOR PRINT
+ MOVEI 0,C.OPN+C.READ
+ TRNE A,1
+ MOVEI 0,C.OPN+C.PRIN
+ TRNE A,2
+ TRO 0,C.BIN
+ HRRM 0,-2(B)
+ MOVE A,CHANNO(B)
+ CVSKT ; GET ABS SOCKET #
+ FATAL NETWORK BITES THE BAG!
+ MOVE D,B
+ MOVE B,T.CHAN+1(TB)
+ MOVEM D,RNAME1(B)
+ MOVSI 0,TFIX
+ MOVEM 0,RNAME1-1(B)
+
+ MOVSI 0,TFIX
+ MOVEM 0,RNAME2-1(B)
+ MOVEM 0,RSNAME-1(B)
+ MOVE C,T.SPDL+1(TB)
+ MOVE C,S.DIR(C)
+ MOVE 0,[PUSHJ P,DONETO]
+ TRNN C,1 ; SKIP FOR OUTPUT
+ MOVE 0,[PUSHJ P,DONETI]
+ MOVEM 0,IOINS(B)
+ MOVEI 0,80. ; LINELENGTH
+ TRNE C,1 ; SKIP FOR INPUT
+ MOVEM 0,LINLN(B)
+ MOVEI A,3 ; GET STATE UVECTOR
+ PUSHJ P,IBLOCK
+ MOVSI 0,TFIX+.VECT.
+ MOVEM 0,3(B)
+ MOVE C,B
+ MOVE B,T.CHAN+1(TB)
+ MOVEM C,BUFRIN(B)
+ MOVSI 0,TUVEC
+ HLLM 0,BUFRIN-1(B)
+ MOVE B,CHANNO(B) ; GET JFN
+ MOVEI A,4 ; CODE FOR GTNCP
+ MOVEI C,1(P)
+ ADJSP P,4 ; ROOM FOR DATA
+ MOVE D,[-4,,1] ; GET FHOST, LOC SOC, F SOC
+ GTNCP
+ FATAL NET LOSSAGE ; GET STATE
+ MOVE B,(P)
+ MOVE D,-1(P)
+ MOVE C,-3(P)
+ ADJSP P,-4
+ MOVE E,T.CHAN+1(TB)
+ MOVEM D,RNAME2(E)
+ MOVEM C,RSNAME(E)
+ MOVE C,BUFRIN(E)
+ MOVEM B,(C) ; INITIAL STATE STORED
+ MOVE B,E
+ JRST OPNWIN
+
+; DOIOT FOR TENEX NETWRK
+
+DONETO: PUSH P,0
+ MOVE 0,[BOUT]
+ JRST .+3
+
+DONETI: PUSH P,0
+ MOVE 0,[BIN]
+ PUSH P,0
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ MOVEI 0,(A) ; POSSIBLE OUTPUT CHAR TO 0
+ MOVE A,CHANNO(B)
+ MOVE B,0
+ ENABLE
+ XCT (P)
+ DISABLE
+ MOVEI A,(B) ; RET CHAR IN A
+ MOVE B,(TP)
+ MOVE 0,-1(P)
+ SUB P,[2,,2]
+ SUB TP,[2,,2]
+ POPJ P,
+
+NETPRS: MOVEI D,0
+ HRRZ 0,(C)
+ MOVE C,1(C)
+
+ONETL: ILDB A,C
+ CAIN A,"#
+ POPJ P,
+ SUBI A,60
+ ASH D,3
+ IORI D,(A)
+ SOJG 0,ONETL
+ AOS (P)
+ POPJ P,
+
+FIXSTK: CAMN 0,[-1]
+ POPJ P,
+ JFFO 0,FIXS3 ; PUT OCTAL DIGITS INTO STIRNG
+ MOVEI A,"0
+ POP P,D
+ AOJA D,ONETCH
+FIXS3: IDIVI A,3
+ MOVEI B,12.
+ SUBI B,(A)
+ HRLM B,(P)
+ IMULI A,3
+ LSH 0,(A)
+ POP P,B
+FIXS2: MOVEI A,0
+ ROTC 0,3 ; NEXT DIGIT
+ ADDI A,60
+ JSP D,ONETCH
+ SUB B,[1,,0]
+ TLNN B,-1
+ JRST 1(B)
+ JRST FIXS2
+
+ONETCH: IDPB A,C
+ TLNE C,760000 ; SKIP IF NEW WORD
+ JRST (D)
+ PUSH P,[0]
+ JRST (D)
+
+INSTAT: MOVE E,B
+ MOVE B,CHANNO(B) ; GET JFN
+ MOVEI A,4 ; CODE FOR GTNCP
+ MOVEI C,1(P)
+ ADJSP P,4 ; ROOM FOR DATA
+ MOVE D,[-4,,1] ; GET FHOST, LOC SOC, F SOC
+ GTNCP
+ FATAL NET LOSSAGE ; GET STATE
+ MOVE B,(P)
+ MOVE D,-1(P)
+ MOVE C,-3(P)
+ ADJSP P,-4
+ MOVEM D,RNAME2(E) ; UPDATE FOREIGN SOCHKET
+ MOVEM C,RSNAME(E) ; AND HOST
+ MOVE C,BUFRIN(E)
+ XCT ITSTRN(B) ; XLATE TO LOOK MORE LIKE ITS
+ MOVEM B,(C) ; STORE STATE
+ MOVE B,E
+ POPJ P,
+\r
+ITSTRN: MOVEI B,0\r
+ JRST NLOSS\r
+ JRST NLOSS\r
+ MOVEI B,1\r
+ MOVEI B,2\r
+ JRST NLOSS\r
+ MOVEI B,4\r
+ PUSHJ P,NOPND\r
+ MOVEI B,0\r
+ JRST NLOSS\r
+ JRST NLOSS\r
+ PUSHJ P,NCLSD\r
+ MOVEI B,0\r
+ JRST NLOSS\r
+ MOVEI B,0
+
+NLOSS: FATAL ILLEGAL NETWORK STATE
+
+NOPND: MOVE B,DIRECT(E) ; SEE IF READ OR PRINT
+ ILDB B,B ; GET 1ST CHAR
+ CAIE B,"R ; SKIP FOR READ
+ JRST NOPNDW
+ SIBE ; SEE IF INPUT EXISTS
+ JRST .+3
+ MOVEI B,5
+ POPJ P,
+ MOVEM B,2(C) ; STORE BYTES IN STATE VECTOR
+ MOVEI B,11 ; RETURN DATA PRESENT STATE
+ POPJ P,
+
+NOPNDW: SOBE ; SEE IF OUTPUT PRESENT
+ JRST .+3
+ MOVEI B,5
+ POPJ P,
+
+ MOVEI B,6
+ POPJ P,
+
+NCLSD: MOVE B,DIRECT(E)
+ ILDB B,B
+ CAIE B,"R
+ JRST RET0
+ SIBE
+ JRST .+2
+ JRST RET0
+ MOVEI B,10
+ POPJ P,
+
+RET0: MOVEI B,0
+ POPJ P,
+
+
+MFUNCTION NETSTATE,SUBR
+
+ PUSHJ P,ARGNET
+ PUSHJ P,INSTAT
+ MOVE B,BUFRIN(B)
+ MOVSI A,TUVEC
+ JRST FINIS
+
+MFUNCTION NETS,SUBR
+
+ PUSHJ P,ARGNET
+ CAME A,MODES+1 ; PRINT OR PRINTB?
+ CAMN A,MODES+3
+ SKIPA A,CHANNO(B)
+ JRST WRONGD
+ MOVEI B,21
+ MTOPR
+NETRET: MOVE B,1(AB)
+ MOVSI A,TCHAN
+ JRST FINIS
+
+MFUNCTION NETACC,SUBR
+
+ PUSHJ P,ARGNET
+ MOVE A,CHANNO(B)
+ MOVEI B,20
+ MTOPR
+ JRST NETRET
+
+]
+\f
+; HERE TO OPEN TELETYPE DEVICES
+
+OTTY: HRRZ A,S.DIR(C) ; GET DIR CODE
+ TRNE A,2 ; SKIP IF NOT READB/PRINTB
+ JRST WRONGD ; CANT DO THAT
+
+IFN ITS,[
+ MOVE A,S.NM1(C) ; CHECK FOR A DIR
+ MOVE 0,S.NM2(C)
+ CAMN A,[SIXBIT /.FILE./]
+ CAME 0,[SIXBIT /(DIR)/]
+ SKIPA E,[-15.*2,,]
+ JRST OUTN ; DO IT THAT WAY
+
+ HRRZ A,S.DIR(C) ; CHECK DIR
+ TRNE A,1
+ JRST TTYLP2
+ HRRI E,CHNL1
+ PUSH P,S.DEV(C) ; SAVE THE SIXBIT DEV NAME
+ ; HRLZS (P) ; POSTITION DEVICE NAME
+
+TTYLP: SKIPN D,1(E) ; CHANNEL OPEN?
+ JRST TTYLP1 ; NO, GO TO NEXT
+ MOVE A,RDEVIC-1(D) ; GET DEV NAME
+ MOVE B,RDEVIC(D)
+ PUSHJ P,STRTO6 ; TO 6 BIT
+ POP P,A ; GET RESULT
+ CAMN A,(P) ; SAME?
+ JRST SAMTYQ ; COULD BE THE SAME
+TTYLP1: ADD E,[2,,2]
+ JUMPL E,TTYLP
+ SUB P,[1,,1] ; THIS ONE MUST BE UNIQUE
+TTYLP2: MOVE C,T.SPDL+1(TB) ; POINT TO P BASE
+ HRRZ A,S.DIR(C) ; GET DIR OF OPEN
+ SKIPE A ; IF OUTPUT,
+ IORI A,20 ; THEN USE DISPLAY MODE
+ HRLM A,S.DIR(C) ; STORE IN OPEN BLOCK
+ PUSHJ P,OPEN2 ; OPEN THE TTY
+ MOVE A,S.DEV(C) ; GET DEVICE NAME
+ PUSHJ P,6TOCHS ; TO A STRING
+ MOVE D,T.CHAN+1(TB) ; POINT TO CHANNEL
+ MOVEM A,RDEVIC-1(D)
+ MOVEM B,RDEVIC(D)
+ MOVE C,T.SPDL+1(TB) ; RESTORE PDL BASE
+ MOVE B,D ; CHANNEL TO B
+ HRRZ 0,S.DIR(C) ; AND DIR
+ JUMPE 0,TTYSPC
+TTY1: DOTCAL TTYGET,[CHANNO(B),[2000,,0],[2000,,A],[2000,,D]]
+ .LOSE %LSSYS
+ DOTCAL TTYSET,[CHANNO(B),MODE1,MODE2,D]
+ .LOSE %LSSYS
+ MOVE A,[PUSHJ P,GMTYO]
+ MOVEM A,IOINS(B)
+ DOTCAL RSSIZE,[CHANNO(B),[2000,,A],[2000,,D]]
+ .LOSE %LSSYS
+ MOVEM D,LINLN(B)
+ MOVEM A,PAGLN(B)
+ JRST OPNWIN
+
+; MAKE AN IOT
+
+IOTMAK: HRLZ A,CHANNO(B) ; GET CHANNEL
+ ROT A,5
+ IOR A,[.IOT A] ; BUILD IOT
+ MOVEM A,IOINS(B) ; AND STORE IT
+ POPJ P,
+\f
+
+; HERE IF POSSIBLY OPENING AN ALREADY OPEN TTY
+
+SAMTYQ: MOVE D,1(E) ; RESTORE CURRENT CHANNEL
+ MOVE A,DIRECT-1(D) ; GET DIR
+ MOVE B,DIRECT(D)
+ PUSHJ P,STRTO6
+ POP P,A ; GET SIXBIT
+ MOVE C,T.SPDL+1(TB)
+ HRRZ C,S.DIR(C)
+ CAME A,MODES(C) ; SKIP IF DIFFERENT DIRECTION
+ JRST TTYLP1
+
+; HERE IF A RE-OPEN ON A TTY
+
+ HRRZ 0,FSAV(TB) ; IS IT FROM A FOPEN
+ CAIN 0,FOPEN
+ JRST RETOLD ; RET OLD CHANNEL
+
+ PUSH TP,$TCHAN
+ PUSH TP,1(E) ; PUSH OLD CHANNEL
+ PUSH TP,$TFIX
+ PUSH TP,T.CHAN+1(TB)
+ MOVE A,[PUSHJ P,CHNFIX]
+ MOVEI PVP,0 ; SAY MIGHT BE NON-ATOMS
+ PUSHJ P,GCHACK
+ SUB TP,[4,,4]
+
+RETOLD: MOVE B,1(E) ; GET CHANNEL
+ AOS CHANNO-1(B) ; AOS REF COUNT
+ MOVSI A,TCHAN
+ SUB P,[1,,1] ; CLEAN UP STACK
+ JRST OPNRET ; AND LEAVE
+
+
+; ROUTINE TO PASS TO GCHACK TO FIX UP CHANNEL POINTER
+
+CHNFIX: CAIN C,TCHAN
+ CAME D,(TP)
+ POPJ P,
+ MOVE D,-2(TP) ; GET REPLACEMENT
+ SKIPE B
+ MOVEM D,1(B) ; CLOBBER IT AWAY
+ POPJ P,
+]\f
+
+IFE ITS,[
+ MOVE C,T.SPDL+1(TB) ; POINT TO P BASE
+ HRRZ 0,S.DIR(C) ; 0/ 0 FOR READ 0/ 1 FOR PRINT
+ MOVE A,[PUSHJ P,INMTYO]
+ MOVE B,T.CHAN+1(TB)
+ MOVEM A,IOINS(B)
+ MOVEI A,100 ; PRIM INPUT JFN
+ JUMPN 0,TNXTY1
+ MOVEI E,C.OPN+C.READ+C.TTY
+ HRRM E,-2(B)
+ MOVEM B,CHNL0+2*100+1
+ JRST TNXTY2
+TNXTY1: MOVEM B,CHNL0+2*101+1
+ MOVEI A,101 ; PRIM OUTPUT JFN
+ MOVEI E,C.OPN+C.PRIN+C.TTY
+ HRRM E,-2(B)
+TNXTY2: MOVEM A,CHANNO(B)
+ JUMPN 0,OPNWIN
+]
+; SETUP FUNNY BUFFER FOR TTY INPUT DEVICES
+
+TTYSPC: MOVEI A,EXTBFR ; GET EXTRA BUFFER
+ PUSHJ P,IBLOCK ; GET BLOCK
+ MOVE D,T.CHAN+1(TB) ;RESTORE CHANNEL POINTER
+IFN ITS,[
+ MOVE A,CHANNO(D)
+ LSH A,23.
+ IOR A,[.IOT A]
+ MOVEM A,IOIN2(B)
+]
+IFE ITS,[
+ MOVE A,[PBIN]
+ MOVEM A,IOIN2(B)
+]
+ MOVSI A,TLIST
+ MOVEM A,EXBUFR-1(D) ; FOR WAITING TTY BUFFERS
+ SETZM EXBUFR(D) ; NIL LIST
+ MOVEM B,BUFRIN(D) ;STORE IN CHANNEL
+ MOVSI A,TUVEC ;MAKE SURE TYPE IS UNIFORM VECTOR
+ HLLM A,BUFRIN-1(D)
+ MOVEI A,177 ;SET ERASER TO RUBOUT
+ MOVEM A,ERASCH(B)
+IFE ITS,[
+ MOVEI A,25
+ MOVEM A,KILLCH(B)
+]
+IFN ITS,[
+ SETZM 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(E)] ;RELATIVE BYTE POINTER
+ MOVEM A,BYTPTR(B)
+ MOVEI A,14 ;BARF BACK CHARACTER FF
+ MOVEM A,BRFCHR(B)
+ MOVEI A,^D
+ MOVEM A,BRFCH2(B)
+
+; SETUP DEFAULT TTY INTERRUPT HANDLER
+
+ PUSH TP,$TATOM
+ PUSH TP,MQUOTE CHAR,CHAR,INTRUP
+ PUSH TP,$TFIX
+ PUSH TP,[10] ; PRIORITY OF CHAR INT
+ PUSH TP,$TCHAN
+ PUSH TP,D
+ MCALL 3,EVENT ; 1ST MAKE AN EVENT EXIST
+ PUSH TP,A
+ PUSH TP,B
+ PUSH TP,$TSUBR
+ PUSH TP,[QUITTER] ; DEFAULT HANDLER IS QUITTER
+ MCALL 2,HANDLER
+
+; BUILD A NULL STRING
+
+ MOVEI A,0
+ PUSHJ P,IBLOCK ; USE A BLOCK
+ MOVE D,T.CHAN+1(TB)
+ MOVEI 0,C.BUF
+ IORM 0,-2(D)
+ HRLI B,010700
+ SUBI B,1
+ MOVSI A,TCHSTR
+ MOVEM A,BUFSTR-1(D)
+ MOVEM B,BUFSTR(D)
+ MOVEI A,0
+ MOVE B,D ; CHANNEL TO B
+ JRST MAKION
+\f
+
+; ROUTINE TO OPEN ITS CHANNEL WITHOUT .RCHST
+
+IFN ITS,[
+OPEN2: MOVEI A,S.DIR(C) ; POINT TO OPEN BLOCK
+ PUSHJ P,MOPEN ; OPEN THE FILE
+ JRST OPNLOS
+ MOVE B,T.CHAN+1(TB) ; GET CHANNEL BACK
+ MOVEM A,CHANNO(B) ; SAVE THE CHANNEL
+ JRST OPEN3
+
+; FIX UP MODE AND FALL INTO OPEN
+
+OPEN0: HRRZ A,S.DIR(C) ; GET DIR
+ TRNE A,2 ; SKIP IF NOT BLOCK
+ IORI A,4 ; TURN ON IMAGE
+ IORI A,2 ; AND BLOCK
+
+ PUSH P,A
+ PUSH TP,$TPDL
+ PUSH TP,C ; SAVE CRUFT TO CHECK FOR PRINTO, HA HA
+ MOVE B,T.CHAN+1(TB)
+ MOVE A,DIRECT-1(B)
+ MOVE B,DIRECT(B) ; THIS KLUDGE THE MESS OF NDR
+ PUSHJ P,STRTO6
+ MOVE C,(TP)
+ POP P,D ; THE SIXBIT FOR KLUDGE
+ POP P,A ; GET BACK THE RANDOM BITS
+ SUB TP,[2,,2]
+ CAME D,[SIXBIT /PRINAO/]
+ CAMN D,[SIXBIT /PRINTO/]
+ IORI A,100000 ; WRITEOVER BIT
+ HRRZ 0,FSAV(TB)
+ CAIN 0,NFOPEN
+ IORI A,10 ; DON'T CHANGE REF DATE
+OPEN9: HRLM A,S.DIR(C) ; AND STORE IT
+
+; ROUTINE TO ATTEMPT TO OPEN A REAL ITS CHANNEL
+
+OPEN1: MOVEI A,S.DIR(C) ; POINT TO OPEN BLOCK
+ PUSHJ P,MOPEN
+ JRST OPNLOS
+ MOVE B,T.CHAN+1(TB) ; GET CHANNEL BACK
+ MOVEM A,CHANNO(B) ; CLOBBER INTO CHANNEL
+ DOTCAL RFNAME,[A,[2003,,S.DEV],[2003,,S.NM1],[2003,,S.NM2],[2003,,S.SNM]]
+ JFCL
+
+; NOW CLOBBER THE TVP SLOT FOR THIS CHANNEL
+
+OPEN3: MOVE A,S.DIR(C)
+ MOVEI 0,C.OPN+C.READ
+ TRNE A,1
+ MOVEI 0,C.OPN+C.PRIN
+ TRNE A,2
+ TRO 0,C.BIN
+ HRRM 0,-2(B)
+ MOVE A,CHANNO(B) ; GET CHANNEL #
+ ASH A,1
+ ADDI A,CHNL0 ; POINT TO SLOT
+ MOVEM B,1(A) ; NOT: TYPE ALREADY SETUP
+
+; NOW GET STATUS WORD
+
+DOSTAT: HRRZ A,CHANNO(B) ; NOW GET STATUS WORD
+ DOTCAL STATUS,[A,[2002,,STATUS]]
+ JFCL
+ POPJ P,
+\f
+
+; HERE IF OPEN FAILS (CHANNEL IS IN A)
+
+OPNLOS: JUMPL A,NOCHAN ; ALL CHANNELS ARE IN USE
+ LSH A,23. ; DO A .STATUS
+ IOR A,[.STATUS A]
+ XCT A ; STATUS TO A
+ MOVE B,T.CHAN+1(TB)
+ PUSHJ P,GFALS ; GET A FALSE WITH A MESSAGE
+ SUB P,[1,,1] ; EXTRA RET ADDR FLUSHED
+ JRST OPNRET ; AND RETURN
+]
+
+CGFALS: SUBM M,(P)
+ MOVEI B,0
+IFN ITS, PUSHJ P,GFALS
+IFE ITS, PUSHJ P,TGFALS
+ JRST MPOPJ
+
+; ROUTINE TO CONS UP FALSE WITH REASON
+IFN ITS,[
+GFALS: PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH P,[SIXBIT / ERR/] ; SET UP OPEN TO ERR DEV
+ PUSH P,[3] ; SAY ITS FOR CHANNEL
+ PUSH P,A
+ .OPEN 0,-2(P) ; USE CHANNEL 0 FOR THIS
+ FATAL CAN'T OPEN ERROR DEVICE
+ SUB P,[3,,3] ; DONT WANT OPEN BLOCK NOW
+IFN FNAMS, PUSH P,A
+ MOVEI A,0 ; PREPARE TO BUILD STRING ON STACK
+EL1: PUSH P,[0] ; WHERE IT WILL GO
+ MOVSI B,(<440700,,(P)>) ; BYTE POINTER TO TOP OF STACK
+EL2: .IOT 0,0 ; GET A CHAR
+ JUMPL 0,EL3 ; JUMP ON -1,,3
+ CAIN 0,3 ; EOF?
+ JRST EL3 ; YES, MAKE STRING
+ CAIN 0,14 ; IGNORE FORM FEEDS
+ JRST EL2 ; IGNORE FF
+ CAIE 0,15 ; IGNORE CR & LF
+ CAIN 0,12
+ JRST EL2
+ IDPB 0,B ; STUFF IT
+ TLNE B,760000 ; SIP IF WORD FULL
+ AOJA A,EL2
+ AOJA A,EL1 ; COUNT WORD AND GO
+
+EL3:
+IFN FNAMS,[
+ SKIPN (P)
+ SUB P,[1,,1]
+ PUSH P,A
+ .CLOSE 0,
+ PUSHJ P,CHMAK
+ PUSH TP,A
+ PUSH TP,B
+ SKIPN B,-2(TP)
+ JRST EL4
+ MOVEI A,0
+ MOVSI B,(<440700,,(P)>)
+ PUSH P,[0]
+ IRP XX,,[RDEVIC,RSNAME,RNAME1,RNAME2]YY,,[0,72,73,40]
+IFSN YY,0,[
+ MOVEI 0,YY
+ JSP E,1PUSH
+]
+ MOVE E,-2(TP)
+ MOVE C,XX(E)
+ HRRZ D,XX-1(E)
+ JSP E,PUSHIT
+ TERMIN
+]
+ SKIPN (P) ; ANY CHARS AT END?
+ SUB P,[1,,1] ; FLUSH XTRA
+ PUSH P,A ; PUT UP COUNT
+ .CLOSE 0, ; CLOSE THE ERR DEVICE
+ PUSHJ P,CHMAK ; MAKE STRING
+ PUSH TP,A
+ PUSH TP,B
+IFN FNAMS,[
+EL4: POP P,A
+ PUSH TP,$TFIX
+ PUSH TP,A]
+IFE FNAMS, MOVEI A,1
+IFN FNAMS,[
+ MOVEI A,3
+ SKIPN B
+ MOVEI A,2
+]
+ PUSHJ P,IILIST
+ MOVSI A,TFALSE ; MAKEIT A FALSE
+IFN FNAMS, SUB TP,[2,,2]
+ POPJ P,
+
+IFN FNAMS,[
+1PUSH: MOVEI D,0
+ JRST PUSHI2
+PUSHI1: PUSH P,[0]
+ MOVSI B,(<440700,,(P)>)
+PUSHIT: SOJL D,(E)
+ ILDB 0,C
+PUSHI2: IDPB 0,B
+ TLNE B,760000
+ AOJA A,PUSHIT
+ AOJA A,PUSHI1
+]
+]
+\f
+
+; ROUTINE TO FILL IN THE "REAL" SLOTS FOR THE CHANNEL
+
+FIXREA:
+IFE ITS, HRLZS S.DEV(C) ; KILL MODE BITS
+ MOVE D,[-4,,S.DEV]
+
+FIXRE1: MOVEI A,(D) ; COPY REL POINTER
+ ADD A,T.SPDL+1(TB) ; POINT TO SLOT
+ SKIPN A,(A) ; SKIP IF GOODIE THERE
+ JRST FIXRE2
+ PUSHJ P,6TOCHS ; MAKE INOT A STRING
+ MOVE C,RDTBL-S.DEV(D); GET OFFSET
+ ADD C,T.CHAN+1(TB)
+ MOVEM A,-1(C)
+ MOVEM B,(C)
+FIXRE2: AOBJN D,FIXRE1
+ POPJ P,
+
+IFN ITS,[
+DOOPN: HRLZ A,A
+ HRR A,CHANNO(B) ; GET CHANNEL
+ DOTCAL OPEN,[A,-3(P),-2(P),-1(P),(P)]
+ SKIPA
+ AOS -1(P)
+ POPJ P,
+]
+\f
+;THIS ROUTINE CONVERTS MUDDLE CHARACTER STRINGS TO SIXBIT FILE NAMES
+STRTO6: PUSH TP,A
+ PUSH TP,B
+ PUSH P,E ;SAVE USEFUL FROB
+ MOVEI E,(A) ; CHAR COUNT TO E
+ GETYP A,A
+ CAIE A,TCHSTR ; IS IT ONE WORD?
+ JRST WRONGT ;NO
+ CAILE E,6 ; SKIP IF L=? 6 CHARS
+ MOVEI E,6
+CHREAD: MOVEI A,0 ;INITIALIZE OUTPUT WORD
+ MOVE D,[440600,,A] ;AND BYTE POINTER TO IT
+NEXCHR: SOJL E,SIXDON
+ ILDB 0,B ; GET NEXT CHAR
+ CAIN 0,^Q ; CNTL-Q, QUOTES NEXT CHAR
+ JRST NEXCHR
+ JUMPE 0,SIXDON ;IF NULL, WE ARE FINISHED
+ PUSHJ P,A0TO6 ; CONVERT TO SIXBIT
+ IDPB 0,D ;DEPOSIT INTO SIX BIT
+ JRST NEXCHR ; NO, GET NEXT
+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
+ PUSH P,D
+ MOVEI B,0 ;MAX NUMBER OF CHARACTERS
+ PUSH P,[0] ;STRING WILL GO ON P SATCK
+ JUMPE A,GETATM ; EMPTY, LEAVE
+ 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
+ ADDI 0,40 ;CHANGET TOASCII
+ IDPB 0,E ;AND STORE IT
+ TLNN D,770000 ; SKIP IF NOT DONE
+ JRST 6LOOP1
+ TDNN A,MSKS(B) ; CHECK IF JUST SPACES LEFT
+ AOJA B,GETATM ; YES, DONE
+ AOJA B,6LOOP ;KEEP LOOKING
+6LOOP1: PUSH P,[6] ;IF ARRIVE HERE, STRING IS 2 WORDS
+ JRST .+2
+GETATM: MOVEM B,(P) ;SET STRING LENGTH=1
+ PUSHJ P,CHMAK ;MAKE A MUDDLE STRING
+ POP P,D
+ POP P,E
+ POPJ P,
+
+MSKS: 7777,,-1
+ 77,,-1
+ ,,-1
+ 7777
+ 77
+
+
+; CONVERT ONE CHAR
+
+A0TO6: 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
+ JUMPL 0,BAD6 ;CHECK FOR A WINNER
+ CAILE 0,77
+ JRST BAD6
+ POPJ P,
+\f
+; SUBR TO TEST THE EXISTENCE OF FILES
+
+MFUNCTION FEXIST,SUBR,[FILE-EXISTS?]
+
+ ENTRY
+
+ JUMPGE AB,TFA
+ PUSH TP,$TPDL
+ PUSH TP,P ; SAVE P-STACK BASE
+ ADD TP,[2,,2]
+ MOVSI E,-4 ; 4 THINGS TO PUSH
+EXIST:
+IFN ITS, MOVE B,@RNMTBL(E)
+IFE ITS, MOVE B,@FETBL(E)
+ PUSH P,E
+ PUSHJ P,IDVAL1
+ POP P,E
+ GETYP 0,A
+ CAIE 0,TCHSTR ; SKIP IF WINS
+ JRST EXIST1
+
+IFN ITS, PUSHJ P,STRTO6 ; CONVERT TO SIXBIT
+IFE ITS,[
+; PUSH P,E
+; PUSHJ P,ADDNUL ; NOT NEEDED, SINCE CONSED INTO ONE STRING-TAA
+; POP P,E
+ PUSH TP,A ; DEFAULT TYPE AND VALUE GIVEN BY USER
+ PUSH TP,B ; IN VALUE OF DEV, SNM, NM1, NM2
+ ]
+IFN ITS, JRST .+2
+IFE ITS, JRST .+3
+
+EXIST1:
+IFN ITS, PUSH P,EXISTS(E) ; USE DEFAULT
+IFE ITS,[
+ PUSH TP,FETYP(E) ; DEFAULT TYPE AND VALUE IF NO
+ PUSH TP,FEVAL(E) ; DEFAULT GIVEN BY USER
+ ]
+ AOBJN E,EXIST
+
+ PUSHJ P,RGPRS ; PARSE THE ARGS
+ JRST TMA ; TOO MANY ARGUMENTS
+
+IFN ITS,[
+ MOVE 0,-3(P) ; GET SIXBIT DEV NAME
+ MOVEI B,0
+ CAMN 0,[SIXBITS /DSK /]
+ MOVSI B,10 ; DONT SET REF DATE IF DISK DEV
+ .IOPUSH
+ DOTCAL OPEN,[B,[17,,-3],[17,,-2],[17,,-1],[17,,0]]
+ JRST .+3
+ .IOPOP
+ JRST FDLWON ; WON!!!
+ .STATUS 0,A ; FIND THE STATUS OF CHANNEL BEFORE POPING
+ .IOPOP
+ JRST FDLST1]
+
+IFE ITS,[
+ MOVE B,TB
+ SUBI B,10 ; GET B TO POINT CORRECTLY TO ARGS
+ PUSHJ P,STSTK ; GET FILE NAME IN A STRING
+ HRROI B,1(E) ; POINT B TO THE STRING
+ MOVSI A,100001
+ GTJFN
+ JRST TDLLOS ; FILE DOES NOT EXIST
+ RLJFN ; FILE EXIST SO RETURN JFN
+ JFCL
+ JRST FDLWON ; SUCCESS
+ ]
+
+IFN ITS,[
+EXISTS: SIXBITS /DSK INPUT > /
+ ]
+IFE ITS,[
+FETBL: SETZ IMQUOTE NM1
+ SETZ IMQUOTE NM2
+ SETZ IMQUOTE DEV
+ SETZ IMQUOTE SNM
+
+FETYP: TCHSTR,,5
+ TCHSTR,,3
+ TCHSTR,,3
+ TCHSTR,,0
+
+FEVAL: 440700,,[ASCIZ /INPUT/]
+ 440700,,[ASCIZ /MUD/]
+ 440700,,[ASCIZ /DSK/]
+ 0
+ ]
+\f
+; SUBR TO DELETE AND RENAME FILES
+
+MFUNCTION RENAME,SUBR
+
+ ENTRY
+
+ JUMPGE AB,TFA
+ PUSH TP,$TPDL
+ PUSH TP,P ; SAVE P-STACK BASE
+ GETYP 0,(AB) ; GET 1ST ARG TYPE
+IFN ITS,[
+ CAIN 0,TCHAN ; CHANNEL?
+ JRST CHNRNM ; MUST BE RENAME WHILE OPEN FOR WRITING
+]
+IFE ITS,[
+ PUSH P,[100000,,-2]
+ PUSH P,[377777,,377777]
+]
+ MOVSI E,-4 ; 4 THINGS TO PUSH
+RNMALP: MOVE B,@RNMTBL(E)
+ PUSH P,E
+ PUSHJ P,IDVAL1
+ POP P,E
+ GETYP 0,A
+ CAIE 0,TCHSTR ; SKIP IF WINS
+ JRST RNMLP1
+
+IFN ITS, PUSHJ P,STRTO6 ; CONVERT TO SIXBIT
+IFE ITS,[
+ PUSH P,E
+ PUSHJ P,ADDNUL
+ EXCH B,(P)
+ MOVE E,B
+]
+ JRST .+2
+
+RNMLP1: PUSH P,RNSTBL(E) ; USE DEFAULT
+ AOBJN E,RNMALP
+
+IFN ITS,[
+ PUSHJ P,RGPRS ; PARSE THE ARGS
+ JRST RNM1 ; COULD BE A RENAME
+
+; HERE TO DELETE A FILE
+
+DELFIL: MOVE A,(P) ; AND GET SNAME
+ .SUSET [.SSNAM,,A]
+ DOTCAL DELETE,[[17,,-3],[17,,-2],[17,,-1],[17,,0]]
+ JRST FDLST ; ANALYSE ERROR
+
+FDLWON: MOVSI A,TATOM
+ MOVE B,IMQUOTE T
+ JRST FINIS
+]
+IFE ITS,[
+ MOVE A,(AB)
+ MOVE B,1(AB)
+ PUSHJ P,ADDNUL
+ MOVE A,(TP) ; GET BASE OF PDL
+ MOVEI A,1(A) ; POINT TO CRAP
+ CAMGE AB,[-3,,] ; SKIP IF DELETE
+ HLLZS (A) ; RESET DEFAULT
+ PUSH P,[0]
+ PUSH P,[0]
+ PUSH P,[0]
+ GTJFN ; GET A JFN
+ JRST TDLLOS ; LOST
+ ADD AB,[2,,2] ; PAST ARG
+ MOVEM AB,ABSAV(TB)
+ JUMPL AB,RNM1 ; GO TRY FOR RENAME
+ MOVE P,(TP) ; RESTORE P STACK
+ MOVEI C,(A) ; FOR RELEASE
+ DELF ; ATTEMPT DELETE
+ JRST DELLOS ; LOSER
+ RLJFN ; MAKE SURE FLUSHED
+ JFCL
+
+FDLWON: MOVSI A,TATOM
+ MOVE B,IMQUOTE T
+ JRST FINIS
+
+RNMLOS: PUSH P,A
+ MOVEI A,(B)
+ RLJFN
+ JFCL
+DELLO1: MOVEI A,(C)
+ RLJFN
+ JFCL
+ POP P,A ; ERR NUMBER BACK
+TDLLOS: MOVEI B,0
+ PUSHJ P,TGFALS ; GET FALSE WITH REASON
+ JRST FINIS
+
+DELLOS: PUSH P,A ; SAVE ERROR
+ JRST DELLO1
+]
+
+;TABLE OF REANMAE DEFAULTS
+IFN ITS,[
+RNMTBL: IMQUOTE DEV
+ IMQUOTE NM1
+ IMQUOTE NM2
+ IMQUOTE SNM
+
+RNSTBL: SIXBIT /DSK _MUDS_> /
+]
+IFE ITS,[
+RNMTBL: SETZ IMQUOTE DEV
+ SETZ IMQUOTE SNM
+ SETZ IMQUOTE NM1
+ SETZ IMQUOTE NM2
+
+RNSTBL: -1,,[ASCIZ /DSK/]
+ 0
+ -1,,[ASCIZ /_MUDS_/]
+ -1,,[ASCIZ /MUD/]
+]
+; HERE TO DO A RENAME
+
+RNM1: JUMPGE AB,TMA ; IF ARGS EXHAUSTED, MUST BE TOO MUCH STRING
+ GETYP 0,(AB)
+ MOVE C,1(AB) ; GET ARG
+ CAIN 0,TATOM ; IS IT "TO"
+ CAME C,IMQUOTE TO
+ JRST WRONGT ; NO, LOSE
+ ADD AB,[2,,2] ; BUMP PAST "TO"
+ MOVEM AB,ABSAV(TB)
+ JUMPGE AB,TFA
+IFN ITS,[
+ MOVEM P,T.SPDL+1(TB) ; SAVE NEW P-BASE
+
+ MOVEI 0,4 ; FOUR DEFAULTS
+ PUSH P,-3(P) ; DEFAULT DEVICE IS CURRENT
+ SOJN 0,.-1
+
+ PUSHJ P,RGPRS ; PARSE THE NEXT STRING
+ JRST TMA
+
+ MOVE A,-7(P) ; FIX AND GET DEV1
+ MOVE B,-3(P) ; SAME FOR DEV2
+ CAME A,B ; SAME?
+ JRST DEVDIF
+
+ POP P,A ; GET SNAME 2
+ CAME A,(P)-3 ; SNAME 1
+ JRST DEVDIF
+ .SUSET [.SSNAM,,A]
+ POP P,-2(P) ; MOVE NAMES DOWN
+ POP P,-2(P)
+ DOTCAL RENAME,[[17,,-4],[17,,-3],[17,,-2],A,[17,,-1],(P)]
+ JRST FDLST
+ JRST FDLWON
+
+; HERE FOR RENAME WHILE OPEN FOR WRITING
+
+CHNRNM: ADD AB,[2,,2] ; NEXT ARG
+ MOVEM AB,ABSAV(TB)
+ JUMPGE AB,TFA
+ MOVE B,-1(AB) ; GET CHANNEL
+ SKIPN CHANNO(B) ; SKIP IF OPEN
+ JRST BADCHN
+ MOVE A,DIRECT-1(B) ; CHECK DIRECTION
+ MOVE B,DIRECT(B)
+ PUSHJ P,STRTO6 ; TO 6 BIT
+ POP P,A
+ CAME A,[SIXBIT /PRINT/]
+ CAMN A,[SIXBIT /PRINTB/]
+ JRST CHNRN1
+ CAMN A,[SIXBIT /PRINAO/]
+ JRST CHNRM1
+ CAME A,[SIXBIT /PRINTO/]
+ JRST WRONGD
+
+; SET UP .FDELE BLOCK
+
+CHNRN1: PUSH P,[0]
+ PUSH P,[0]
+ MOVEM P,T.SPDL+1(TB)
+ PUSH P,[0]
+ PUSH P,[SIXBIT /_MUDL_/]
+ PUSH P,[SIXBIT />/]
+ PUSH P,[0]
+
+ PUSHJ P,RGPRS ; PARSE THESE
+ JRST TMA
+
+ SUB P,[1,,1] ; SNAME/DEV IGNORED
+ MOVE AB,ABSAV(TB) ; GET ORIG ARG POINTER
+ MOVE B,1(AB)
+ MOVE A,CHANNO(B) ; ITS CHANNEL #
+ DOTCAL RENMWO,[A,[17,,-1],(P)]
+ JRST FDLST
+ MOVE A,CHANNO(B) ; ITS CHANNEL #
+ DOTCAL RFNAME,[A,[2017,,-4],[2017,,-3],[2017,,-2],[2017,,-1]]
+ JFCL
+ MOVE A,-3(P) ; UPDATE CHANNEL
+ PUSHJ P,6TOCHS ; GET A STRING
+ MOVE C,1(AB)
+ MOVEM A,RNAME1-1(C)
+ MOVEM B,RNAME1(C)
+ MOVE A,-2(P)
+ PUSHJ P,6TOCHS
+ MOVE C,1(AB)
+ MOVEM A,RNAME2-1(C)
+ MOVEM B,RNAME2(C)
+ MOVE B,1(AB)
+ MOVSI A,TCHAN\b
+ JRST FINIS
+]
+IFE ITS,[
+ PUSH P,A
+ MOVE A,(AB)
+ MOVE B,1(AB)
+ PUSHJ P,ADDNUL
+ MOVE A,(TP) ; PBASE BACK
+ PUSH A,[400000,,0]
+ MOVEI A,(A)
+ GTJFN
+ JRST TDLLOS
+ POP P,B
+ EXCH A,B
+ MOVEI C,(A) ; FOR RELEASE ATTEMPT
+ RNAMF
+ JRST RNMLOS
+ MOVEI A,(B)
+ RLJFN ; FLUSH JFN
+ JFCL
+ MOVEI A,(C) ; MAKE SURR OTHER IS FLUSHED
+ RLJFN
+ JFCL
+ JRST FDLWON
+
+
+ADDNUL: PUSH TP,A
+ PUSH TP,B
+ MOVEI A,(A) ; LNTH OF STRING
+ IDIVI A,5
+ JUMPN B,NONUAD ; DONT NEED TO ADD ONE
+
+ PUSH TP,$TCHRS
+ PUSH TP,[0]
+ MOVEI A,2
+ PUSHJ P,CISTNG ; COPY OF STRING
+ POPJ P,
+
+NONUAD: POP TP,B
+ POP TP,A
+ POPJ P,
+]
+; HERE FOR LOSING .FDELE
+
+IFN ITS,[
+FDLST: .STATUS 0,A ; GET STATUS
+FDLST1: MOVEI B,0
+ PUSHJ P,GFALS ; ANALYZE IT
+ JRST FINIS
+]
+
+; SOME .FDELE ERRORS
+
+DEVDIF: ERRUUO EQUOTE DEVICE-OR-SNAME-DIFFERS
+
+\f; HERE TO RESET A READ CHANNEL
+
+MFUNCTION FRESET,SUBR,RESET
+
+ ENTRY 1
+ GETYP A,(AB)
+ CAIE A,TCHAN
+ JRST WTYP1
+ MOVE B,1(AB) ;GET CHANNEL
+ SKIPN IOINS(B) ; OPEN?
+ JRST REOPE1 ; NO, IGNORE CHECKS
+IFN ITS,[
+ MOVE A,STATUS(B) ;GET STATUS
+ ANDI A,77
+ JUMPE A,REOPE1 ;IF IT CLOSED, JUST REOPEN IT, MAYBE?
+ CAILE A,2 ;SKIPS IF TTY FLAVOR
+ JRST REOPEN
+]
+IFE ITS,[
+ MOVE A,CHANNO(B)
+ CAIE A,100 ; TTY-IN
+ CAIN A,101 ; TTY-OUT
+ JRST .+2
+ JRST REOPEN
+]
+ CAME B,TTICHN+1
+ CAMN B,TTOCHN+1
+ JRST REATTY
+REATT1: MOVEI B,DIRECT-1(B) ;POINT TO DIRECTION
+ PUSHJ P,CHRWRD ;CONVERT TO A WORD
+ JFCL
+ CAME B,[ASCII /READ/]
+ JRST TTYOPN
+ MOVE B,1(AB) ;RESTORE CHANNEL
+ PUSHJ P,RRESET" ;DO REAL RESET
+ JRST TTYOPN
+
+REOPEN: PUSH TP,(AB) ;FIRST CLOSE IT
+ PUSH TP,(AB)+1
+ MCALL 1,FCLOSE
+ MOVE B,1(AB) ;RESTORE CHANNEL
+
+; SET UP TEMPS FOR OPNCH
+
+REOPE1: PUSH P,[0] ; WILL HOLD DIR CODE
+ PUSH TP,$TPDL
+ PUSH TP,P
+ IRP A,,[DIRECT,RNAME1,RNAME2,RDEVIC,RSNAME,ACCESS]
+ PUSH TP,A-1(B)
+ PUSH TP,A(B)
+ TERMIN
+
+ PUSH TP,$TCHAN
+ PUSH TP,1(AB)
+
+ MOVE A,T.DIR(TB)
+ MOVE B,T.DIR+1(TB) ; GET DIRECTION
+ PUSHJ P,CHMOD ; CHECK THE MODE
+ MOVEM A,(P) ; AND STORE IT
+
+; NOW SET UP OPEN BLOCK IN SIXBIT
+
+IFN ITS,[
+ MOVSI E,-4 ; AOBN PNTR
+FRESE2: MOVE B,T.CHAN+1(TB)
+ MOVEI A,@RDTBL(E) ; GET ITEM POINTER
+ GETYP 0,-1(A) ; GET ITS TYPE
+ CAIE 0,TCHSTR
+ JRST FRESE1
+ MOVE B,(A) ; GET STRING
+ MOVE A,-1(A)
+ PUSHJ P,STRTO6
+FRESE3: AOBJN E,FRESE2
+]
+IFE ITS,[
+ MOVE B,T.CHAN+1(TB)
+ MOVE A,RDEVIC-1(B)
+ MOVE B,RDEVIC(B)
+ PUSHJ P,STRTO6 ; RESULT ON STACK
+ HLRZS (P)
+]
+
+ PUSH P,[0] ; PUSH UP SOME DUMMIES
+ PUSH P,[0]
+ PUSH P,[0]
+ PUSHJ P,OPNCH ; ATTEMPT TO DO THEOPEN
+ GETYP 0,A
+ CAIE 0,TCHAN
+ JRST FINIS ; LEAVE IF FALSE OR WHATEVER
+
+DRESET: MOVE A,(AB)
+ MOVE B,1(AB)
+ SETZM CHRPOS(B) ;INITIALIZE THESE PARAMETERS
+ SETZM LINPOS(B)
+ SETZM ACCESS(B)
+ JRST FINIS
+
+TTYOPN:
+IFN ITS,[
+ MOVE B,1(AB)
+ CAME B,TTOCHN+1
+ CAMN B,TTICHN+1
+ PUSHJ P,TTYOP2
+ PUSHJ P,DOSTAT
+ DOTCAL RSSIZE,[CHANNO(B),[2000,,C],[2000,,D]]
+ .LOSE %LSSYS
+ MOVEM C,PAGLN(B)
+ MOVEM D,LINLN(B)
+]
+ JRST DRESET
+
+IFN ITS,[
+FRESE1: CAIE 0,TFIX
+ JRST BADCHN
+ PUSH P,(A)
+ JRST FRESE3
+]
+
+; INTERFACE TO REOPEN CLOSED CHANNELS
+
+OPNCHN: PUSH TP,$TCHAN
+ PUSH TP,B
+ MCALL 1,FRESET
+ POPJ P,
+
+REATTY: PUSHJ P,TTYOP2
+IFE ITS, SKIPN DEMFLG ; SKIP IF DEMONFLAG IS ON
+ SKIPE NOTTY
+ JRST DRESET
+ MOVE B,1(AB)
+ JRST REATT1
+\f
+; FUNCTION TO LIST ALL CHANNELS
+
+MFUNCTION CHANLIST,SUBR
+
+ ENTRY 0
+
+ MOVEI A,N.CHNS-1 ;MAX # OF REAL CHANNELS
+ MOVEI C,0
+ MOVEI B,CHNL1 ;POINT TO FIRST REAL CHANNEL
+
+CHNLP: SKIPN 1(B) ;OPEN?
+ JRST NXTCHN ;NO, SKIP
+ HRRE E,(B) ; ABOUT TO FLUSH?
+ JUMPL E,NXTCHN ; YES, FORGET IT
+ MOVE D,1(B) ; GET CHANNEL
+ HRRZ E,CHANNO-1(D) ; GET REF COUNT
+ PUSH TP,(B)
+ PUSH TP,1(B)
+ ADDI C,1 ;COUNT WINNERS
+ SOJGE E,.-3 ; COUNT THEM
+NXTCHN: ADDI B,2
+ SOJN A,CHNLP
+
+ SKIPN B,CHNL0+1 ;NOW HACK LIST OF PSUEDO CHANNELS
+ JRST MAKLST
+CHNLS: PUSH TP,(B)
+ PUSH TP,(B)+1
+ ADDI C,1
+ HRRZ B,(B)
+ JUMPN B,CHNLS
+
+MAKLST: ACALL C,LIST
+ JRST FINIS
+
+\f; ROUTINE TO RESTORE A CLOSED CHANNEL TO ITS PREVIOUS STATE
+
+
+REOPN: PUSH TP,$TCHAN
+ PUSH TP,B
+ SKIPN CHANNO(B) ; ONLY REAL CHANNELS
+ JRST PSUEDO
+
+IFN ITS,[
+ MOVSI E,-4 ; SET UP POINTER FOR NAMES
+
+GETOPB: MOVE B,(TP) ; GET CHANNEL
+ MOVEI A,@RDTBL(E) ; GET POINTER
+ MOVE B,(A) ; NOW STRING
+ MOVE A,-1(A)
+ PUSHJ P,STRTO6 ; LEAVES SIXBIT ON STACK
+ AOBJN E,GETOPB
+]
+IFE ITS,[
+ MOVE A,RDEVIC-1(B)
+ MOVE B,RDEVIC(B)
+ PUSHJ P,STRTO6 ; GET DEV NAME IN SIXBIT
+]
+ MOVE B,(TP) ; RESTORE CHANNEL
+ MOVE A,DIRECT-1(B)
+ MOVE B,DIRECT(B)
+ PUSHJ P,CHMOD ; CHECK FOR A VALID MODE
+
+IFN ITS, MOVE E,-3(P) ; GET DEVICE IN PROPER PLACE
+IFE ITS, HLRZS E,(P)
+ MOVE B,(TP) ; RESTORE CHANNEL
+IFN ITS, CAMN E,[SIXBIT /DSK /]
+IFE ITS,[
+ CAIE E,(SIXBIT /PS /)
+ CAIN E,(SIXBIT /DSK/)
+ JRST DISKH ; DISK WINS IMMEIDATELY
+ CAIE E,(SIXBIT /SS /)
+ CAIN E,(SIXBIT /SRC/)
+ JRST DISKH ; DISK WINS IMMEIDATELY
+]
+IFN ITS, CAMN E,[SIXBIT /TTY /] ; NO NEED TO RE-OPEN THE TTY
+IFE ITS, CAIN E,(SIXBIT /TTY/)
+ JRST REOPD1
+IFN ITS,[
+ AND E,[777700,,0] ; COULD BE "UTn"
+ MOVE D,CHANNO(B) ; GET CHANNEL
+ ASH D,1
+ ADDI D,CHNL0 ; DON'T SEEM TO BE OPEN
+ SETZM 1(D)
+ SETZM CHANNO(B)
+ CAMN E,[SIXBIT /UT /]
+ JRST REOPD ; CURRENTLY, CANT RESTORE UTAPE CHANNLES
+ CAMN E,[SIXBIT /AI /]
+ JRST REOPD ; CURRENTLY CANT RESTORE AI CHANNELS
+ CAMN E,[SIXBIT /ML /]
+ JRST REOPD ; CURRENTLY CANT RESTORE ML CHANNELS
+ CAMN E,[SIXBIT /DM /]
+ JRST REOPD ; CURRENTLY CANT RESTORE DM CHANNELS
+]
+ PUSH TP,$TCHAN ; TRY TO RESET IT
+ PUSH TP,B
+ MCALL 1,FRESET
+
+IFN ITS,[
+REOPD1: AOS -4(P)
+REOPD: SUB P,[4,,4]
+]
+IFE ITS,[
+REOPD1: AOS -1(P)
+REOPD: SUB P,[1,,1]
+]
+REOPD0: SUB TP,[2,,2]
+ POPJ P,
+
+IFN ITS,[
+DISKH: MOVE C,(P) ; SNAME
+ .SUSET [.SSNAM,,C]
+]
+IFE ITS,[
+DISKH: MOVEM A,(P) ; SAVE MODE WORD
+ PUSHJ P,STSTK ; STRING TO STACK
+ MOVE A,(E) ; RESTORE MODE WORD
+ PUSH TP,$TPDL
+ PUSH TP,E ; SAVE PDL BASE
+ MOVE B,-2(TP) ; CHANNEL BACK TO B
+]
+ MOVE C,ACCESS(B) ; GET CHANNELS ACCESS
+ TRNN A,2 ; SKIP IF NOT ASCII CHANNEL
+ JRST DISKH1
+ HRRZ D,ACCESS-1(B) ; IF PARTIAL WORD OUT
+ IMULI C,5 ; TO CHAR ACCESS
+ JUMPE D,DISKH1 ; NO SWEAT
+ ADDI C,(D)
+ SUBI C,5
+DISKH1: HRRZ D,BUFSTR-1(B) ; ANY CHARS IN MUDDLE BUFFER
+ JUMPE D,DISKH2
+ TRNN A,1 ; SKIP IF OUTPUT CHANNEL
+ JRST DISKH2
+ PUSH P,A
+ PUSH P,C
+ MOVEI C,BUFSTR-1(B)
+ PUSHJ P,BYTDOP ; FIND LENGTH OF WHOLE BUFFER
+ HLRZ D,(A) ; LENGTH + 2 TO D
+ SUBI D,2
+ IMULI D,5 ; TO CHARS
+ SUB D,BUFSTR-1(B)
+ POP P,C
+ POP P,A
+DISKH2: SUBI C,(D) ; UPDATE CHAR ACCESS
+ IDIVI C,5 ; BACK TO WORD ACCESS
+IFN ITS,[
+ IORI A,6 ; BLOCK IMAGE
+ TRNE A,1
+ IORI A,100000 ; WRITE OVER BIT
+ PUSHJ P,DOOPN
+ JRST REOPD
+ MOVE A,C ; ACCESS TO A
+ PUSHJ P,GETFLN ; CHECK LENGTH
+ CAIGE 0,(A) ; CHECK BOUNDS
+ JRST .+3 ; COMPLAIN
+ PUSHJ P,DOACCS ; AND ACESS
+ JRST REOPD1 ; SUCCESS
+
+ MOVE A,CHANNO(B) ; CLOSE THE G.D. CHANNEL
+ PUSHJ P,MCLOSE
+ JRST REOPD
+
+DOACCS: PUSH P,A
+ HRRZ A,CHANNO(B)
+ DOTCAL ACCESS,[A,(P)]
+ JFCL
+ POP P,A
+ POPJ P,
+
+DOIOTO:
+DOIOTI:
+DOIOT:
+ PUSH P,0
+ MOVSI 0,TCHAN
+ MOVE PVP,PVSTOR+1
+ MOVEM 0,BSTO(PVP) ; IN CASE OF INTERRUPT
+ ENABLE
+ HRRZ 0,CHANNO(B)
+ DOTCAL IOT,[0,A]
+ JFCL
+ DISABLE
+ MOVE PVP,PVSTOR+1
+ SETZM BSTO(PVP)
+ POP P,0
+ POPJ P,
+
+GETFLN: MOVE 0,CHANNO(B) ; GET CHANNEL
+ .CALL FILBLK ; READ LNTH
+ .VALUE
+ POPJ P,
+
+FILBLK: SETZ
+ SIXBIT /FILLEN/
+ 0
+ 402000,,0 ; STUFF RESULT IN 0
+]
+IFE ITS,[
+ MOVEI A,CHNL0
+ ADD A,CHANNO(B)
+ ADD A,CHANNO(B)
+ SETZM 1(A) ; MAY GET A DIFFERENT JFN
+ HRROI B,1(E) ; TENEX STRING POINTER
+ MOVSI A,400001 ; MAKE SURE
+ GTJFN ; GO GET IT
+ JRST RGTJL ; COMPLAIN
+ MOVE D,-2(TP)
+ HRRZM A,CHANNO(D) ; COULD HAVE CHANGED
+ MOVE P,(TP) ; RESTORE P
+ MOVEI B,CHNL0
+ ASH A,1 ; MUNG ITS SLOT
+ ADDI A,(B)
+ MOVEM D,1(A)
+ HLLOS (A) ; MARK CHANNEL NOT TO BE RELOOKED AT
+ MOVE A,(P) ; MODE WORD BACK
+ MOVE B,[440000,,200000] ; FLAG BITS
+ TRNE A,1 ; SKIP FOR INPUT
+ TRC B,300000 ; CHANGE TO WRITE
+ MOVE A,CHANNO(D) ; GET JFN
+ OPENF
+ JRST ROPFLS
+ MOVE E,C ; LENGTH TO E
+ SIZEF ; GET CURRENT LENGTH
+ JRST ROPFLS
+ CAMGE B,E ; STILL A WINNER
+ JRST ROPFLS
+ MOVE A,CHANNO(D) ; JFN
+ MOVE B,C
+ SFPTR
+ JRST ROPFLS
+ SUB TP,[2,,2] ; FLUSH PDL POINTER
+ JRST REOPD1
+
+ROPFLS: MOVE A,-2(TP)
+ MOVE A,CHANNO(A)
+ CLOSF ; ATTEMPT TO CLOSE
+ JFCL ; IGNORE FAILURE
+ SKIPA
+
+RGTJL: MOVE P,(TP)
+ SUB TP,[2,,2]
+ JRST REOPD
+
+DOACCS: PUSH P,B
+ EXCH A,B
+ MOVE A,CHANNO(A)
+ SFPTR
+ JRST ACCFAI
+ POP P,B
+ POPJ P,
+]
+PSUEDO: AOS (P) ; ASSUME SUCCESS FOR NOW
+ MOVEI B,RDEVIC-1(B) ; SEE WHAT DEVICE IS
+ PUSHJ P,CHRWRD
+ JFCL
+ JRST REOPD0 ; NO, RETURN HAPPY
+IFN 0,[ CAME B,[ASCII /E&S/] ; DISPLAY ?
+ CAMN B,[ASCII /DIS/]
+ SKIPA B,(TP) ; YES, REGOBBLE CHANNEL AND CONTINUE
+ JRST REOPD0 ; NO, RETURN HAPPY
+ PUSHJ P,DISROP
+ SOS (P) ; DISPLAY DID NOT REOPEN, UNDO ASSUMPTION OF SUCCESS
+ JRST REOPD0]
+
+\f;THIS PROGRAM CLOSES THE SPECIFIED CHANNEL
+
+MFUNCTION FCLOSE,SUBR,[CLOSE]
+
+ ENTRY 1 ;ONLY ONE ARG
+ GETYP A,(AB) ;CHECK ARGS
+ CAIE A,TCHAN ;IS IT A CHANNEL
+ JRST WTYP1
+ MOVE B,1(AB) ;PICK UP THE CHANNEL
+ HRRZ A,CHANNO-1(B) ; GET REF COUNT
+ SOJGE A,CFIN5 ; NOT READY TO REALLY CLOSE
+ CAME B,TTICHN+1 ; CHECK FOR TTY
+ CAMN B,TTOCHN+1
+ JRST CLSTTY
+ MOVE A,[JRST CHNCLS]
+ MOVEM A,IOINS(B) ;CLOBBER THE IO INS
+ MOVE A,RDEVIC-1(B) ;GET THE NAME OF THE DEVICE
+ MOVE B,RDEVIC(B)
+ PUSHJ P,STRTO6
+IFN ITS, MOVE A,(P)
+IFE ITS, HLRZS A,(P)
+ MOVE B,1(AB) ; RESTORE CHANNEL
+IFN 0,[
+ CAME A,[SIXBIT /E&S /]
+ CAMN A,[SIXBIT /DIS /]
+ PUSHJ P,DISCLS]
+ MOVE B,1(AB) ; IN CASE CLOBBERED BY DISCLS
+ SKIPN A,CHANNO(B) ;ANY REAL CHANNEL?
+ JRST REMOV ; NO, EITHER CLOSED OR PSEUDO CHANNEL
+
+ MOVE A,DIRECT-1(B) ; POINT TO DIRECTION
+ MOVE B,DIRECT(B)
+ PUSHJ P,STRTO6 ; CONVERT TO WORD
+ POP P,A
+IFN ITS, LDB E,[360600,,(P)] ; FIRST CHAR OD DEV NAME
+IFE ITS, LDB E,[140600,,(P)] ; FIRST CHAR OD DEV NAME
+ CAIE E,'T ; SKIP IF TTY
+ JRST CFIN4
+ CAME A,[SIXBIT /READ/] ; SKIP IF WINNER
+ JRST CFIN1
+IFN ITS,[
+ MOVE B,1(AB) ; IN ITS CHECK STATUS
+ LDB A,[600,,STATUS(B)]
+ CAILE A,2
+ JRST CFIN1
+]
+ PUSH TP,$TCHSTR
+ PUSH TP,CHQUOTE CHAR
+ PUSH TP,(AB)
+ PUSH TP,1(AB)
+ MCALL 2,OFF ; TURN OFF INTERRUPT
+CFIN1: MOVE B,1(AB)
+ MOVE A,CHANNO(B)
+IFN ITS,[
+ PUSHJ P,MCLOSE
+]
+IFE ITS,[
+ TLZ A,400000 ; FOR JFN RELEASE
+ CLOSF ; CLOSE THE FILE AND RELEASE THE JFN
+ JFCL
+ MOVE A,CHANNO(B)
+]
+CFIN: LSH A,1
+ ADDI A,CHNL0+1 ;POINT TO THIS CHANNELS LSOT
+ SETZM CHANNO(B)
+ SETZM (A) ;AND CLOBBER IT
+ HLLZS BUFSTR-1(B)
+ SETZM BUFSTR(B)
+ HLLZS ACCESS-1(B)
+CFIN2: HLLZS -2(B)
+ MOVSI A,TCHAN ;RETURN THE CHANNEL
+ JRST FINIS
+
+CLSTTY: ERRUUO EQUOTE ATTEMPT-TO-CLOSE-TTY-CHANNEL
+
+
+REMOV: MOVEI D,CHNL0+1 ;ATTEMPT TO REMOVE FROM PSUEDO CHANNEL LIST
+REMOV0: SKIPN C,D ;FOUND ON LIST ?
+ JRST CFIN2 ;NO, JUST IGNORE THIS CLOSED CHANNEL
+ HRRZ D,(C) ;GET POINTER TO NEXT
+ CAME B,(D)+1 ;FOUND ?
+ JRST REMOV0
+ HRRZ D,(D) ;YES, SPLICE IT OUT
+ HRRM D,(C)
+ JRST CFIN2
+
+
+; CLOSE UP ANY LEFTOVER BUFFERS
+
+CFIN4:
+; CAME A,[SIXBIT /PRINTO/]
+; CAMN A,[SIXBIT /PRINTB/]
+; JRST .+3
+; CAME A,[SIXBIT /PRINT/]
+; JRST CFIN1
+ MOVE B,1(AB) ; GET CHANNEL
+ HRRZ A,-2(B) ;GET MODE BITS
+ TRNN A,C.PRIN
+ JRST CFIN1
+ GETYP 0,BUFSTR-1(B) ; IS THERE AN OUTPUT BUFFER
+ SKIPN BUFSTR(B)
+ JRST CFIN1
+ CAIE 0,TCHSTR
+ JRST CFINX1
+ PUSHJ P,BFCLOS
+IFE ITS,[
+ MOVE A,CHANNO(B)
+ MOVEI B,7
+ SFBSZ
+ JFCL
+ CLOSF
+ JFCL
+]
+ HLLZS BUFSTR-1(B)
+ SETZM BUFSTR(B)
+CFINX1: HLLZS ACCESS-1(B)
+ JRST CFIN1
+
+CFIN5: HRRM A,CHANNO-1(B)
+ JRST CFIN2
+\f;SUBR TO DO .ACCESS ON A READ CHANNEL
+;FORM: <ACCESS CHANNEL FIX-NUMBER>
+;POSITIONS CHANNEL AT CHARACTER POSN FIX-NUMBER
+;H. BRODIE 7/26/72
+
+MFUNCTION MACCESS,SUBR,[ACCESS]
+ ENTRY 2 ;ARGS: CHANNEL AND FIX-NUMBER
+
+;CHECK ARGUMENT TYPES
+ GETYP A,(AB)
+ CAIE A,TCHAN ;FIRST ARG SHOULD BE CHANNEL
+ JRST WTYP1
+ GETYP A,2(AB) ;TYPE OF SECOND
+ CAIE A,TFIX ;SHOULD BE FIX
+ JRST WTYP2
+
+;CHECK DIRECTION OF CHANNEL
+ MOVE B,1(AB) ;B GETS PNTR TO CHANNEL
+; MOVEI B,DIRECT-1(B) ;GET DIRECTION OF CHANNEL
+; PUSHJ P,CHRWRD ;GRAB THE CHAR STRNG
+; JFCL
+; CAME B,[<ASCII /PRINT/>+1]
+ HRRZ A,-2(B) ; GET MODE BITS
+ TRNN A,C.PRIN
+ JRST MACCA
+ MOVE B,1(AB)
+ SKIPE C,BUFSTR(B) ;SEE IF WE MUST FLUSH PART BUFFER
+ PUSHJ P,BFCLOS
+ JRST MACC
+MACCA:
+; CAMN B,[ASCIZ /READ/]
+; JRST .+4
+; CAME B,[ASCIZ /READB/] ; READB CHANNEL?
+; JRST WRONGD
+; AOS (P) ; SET INDICATOR FOR BINARY MODE
+
+;CHECK THAT THE CHANNEL IS OPEN
+MACC: MOVE B,1(AB) ;GET BACK PTR TO CHANNEL
+ HRRZ E,-2(B)
+ TRNN E,C.OPN
+ JRST CHNCLS ;IF CHNL CLOSED => ERROR
+
+;COMPUTE ACCESS PNTR TO ACCESS WORD CHAR IS IN
+;REMAINDER IS NUMBER OF TIMES TO INCR BYTE POINTER
+ADEVOK: SKIPGE C,3(AB) ;GET CHAR POSN
+ ERRUUO EQUOTE NEGATIVE-ARGUMENT
+MACC1: MOVEI D,0
+ TRNN E,C.BIN ; SKIP FOR BINARY FILE
+ IDIVI C,5
+
+;SETUP THE .ACCESS
+ TRNN E,C.PRIN
+ JRST NLSTCH
+ HRRZ 0,LSTCH-1(B)
+ MOVE A,ACCESS(B)
+ TRNN E,C.BIN
+ JRST LSTCH1
+ IMULI A,5
+ ADD A,ACCESS-1(B)
+ ANDI A,-1
+LSTCH1: CAIG 0,(A)
+ MOVE 0,A
+ MOVE A,C
+ IMULI A,5
+ ADDI A,(D)
+ CAML A,0
+ MOVE 0,A
+ HRRM 0,LSTCH-1(B) ; UPDATE "LARGEST"
+NLSTCH: MOVE A,CHANNO(B) ;A GETS REAL CHANNEL NUMBER
+IFN ITS,[
+ DOTCAL ACCESS,[A,C]
+ .LOSE %LSFIL ;PRESUMABLY LOSSAGE MATTERS
+]
+
+IFE ITS,[
+ MOVE B,C
+ SFPTR ; DO IT IN TENEX
+ JRST ACCFAI
+ MOVE B,1(AB) ; RESTORE CHANNEL
+]
+; POP P,E ; CHECK FOR READB MODE
+ TRNN E,C.READ
+ JRST ACCOUT ; PRINT TYPE CHANNEL, GO DO IT
+ SKIPE BUFSTR(B) ; IS THERE A READ BUFFER TO FLUSH
+ JRST .+3
+ SETZM LSTCH(B) ; CLEAR OUT POSSIBLE EOF INDICATOR
+ JRST DONADV
+
+;NOW FORCE GETCHR TO DO A .IOT FIRST THING
+ MOVEI C,BUFSTR-1(B) ; FIND END OF STRING
+ PUSHJ P,BYTDOP"
+ SUBI A,2 ; LAST REAL WORD
+ HRLI A,010700
+ MOVEM A,BUFSTR(B)
+ HLLZS BUFSTR-1(B) ; CLOBBER CHAR COUNT
+ SETZM LSTCH(B) ;CLOBBER READ'S HIDDEN CHARACTER
+
+;NOW DO THE APPROPRIATE NUM OF BYTE ADVANCEMENTS
+ JUMPLE D,DONADV
+ADVPTR: PUSHJ P,GETCHR
+ MOVE B,1(AB) ;RESTORE IN CASE CLOBBERED
+ SOJG D,ADVPTR
+
+DONADV: MOVE C,3(AB) ;FIXUP ACCESS SLOT IN CHNL
+ HLLZS ACCESS-1(B)
+ MOVEM C,ACCESS(B)
+ MOVE A,$TCHAN ;TYPE OF RESULT = "CHANNEL"
+ JRST FINIS ;DONE...B CONTAINS CHANNEL
+
+IFE ITS,[
+ACCFAI: ERRUUO EQUOTE ACCESS-FAILURE
+]
+ACCOUT: SKIPN C,BUFSTR(B) ; FIXUP BUFFER?
+ JRST ACCOU1
+ HRRZ F,BUFSTR-1(B)
+ ADD F,[-BUFLNT*5-4]
+ IDIVI F,5
+ ADD F,BUFSTR(B)
+ HRLI F,010700
+ MOVEM F,BUFSTR(B)
+ MOVEI F,BUFLNT*5
+ HRRM F,BUFSTR-1(B)
+ACCOU1: TRNE E,C.BIN ; FINISHED FOR BINARY CHANNELS
+ JRST DONADV
+
+ JUMPE D,DONADV ; THIS CASE OK
+IFE ITS,[
+ MOVE A,CHANNO(B) ; GET LAST WORD
+ RFPTR
+ JFCL
+ PUSH P,B
+ MOVNI C,1
+ MOVE B,[444400,,E] ; READ THE WORD
+ SIN
+ JUMPL C,ACCFAI
+ POP P,B
+ SFPTR
+ JFCL
+ MOVE B,1(AB) ; CHANNEL BACK
+ MOVE C,[440700,,E]
+ ILDB 0,C
+ IDPB 0,BUFSTR(B)
+ SOS BUFSTR-1(B)
+ SOJG D,.-3
+ JRST DONADV
+]
+IFN ITS, ERRUUO EQUOTE CANT-ACCESS-ASCII-ON-ITS
+
+
+;WRONG TYPE OF DEVICE ERROR
+WRDEV: ERRUUO EQUOTE NON-DSK-DEVICE
+\f
+; BINARY READ AND PRINT ROUTINES
+
+MFUNCTION PRINTB,SUBR
+
+ ENTRY
+
+PBFL: PUSH P,. ; PUSH NON-ZERONESS
+ MOVEI A,-7
+ JRST BINI1
+
+MFUNCTION READB,SUBR
+
+ ENTRY
+
+ PUSH P,[0]
+ MOVEI A,-11
+BINI1: HLRZ 0,AB
+ CAILE 0,-3
+ JRST TFA
+ CAIG 0,(A)
+ JRST TMA
+
+ GETYP 0,(AB) ; SHOULD BE UVEC OR STORE
+ CAIE 0,TSTORAGE
+ CAIN 0,TUVEC
+ JRST BINI2
+ CAIE 0,TCHSTR
+ CAIN 0,TBYTE
+ JRST BYTOK
+ JRST WTYP1 ; ELSE LOSE
+BINI2: MOVE B,1(AB) ; GET IT
+ HLRE C,B
+ SUBI B,(C) ; POINT TO DOPE
+ GETYP A,(B)
+ PUSHJ P,SAT" ; GET ITS ST.ALOC.TYPE
+ CAIE A,S1WORD
+ JRST WTYP1
+BYTOK: GETYP 0,2(AB)
+ CAIE 0,TCHAN ; BETTER BE A CHANNEL
+ JRST WTYP2
+ MOVE B,3(AB) ; GET IT
+; MOVEI B,DIRECT-1(B) ; GET DIRECTION OF
+; PUSHJ P,CHRWRD ; INTO 1 WORD
+; JFCL
+; MOVNI E,1
+; CAMN B,[ASCII /READB/]
+; MOVEI E,0
+; CAMN B,[<ASCII /PRINT/>+1]
+ HRRZ A,-2(B) ; MODE BITS
+ TRNN A,C.BIN ; IF NOT BINARY
+ JRST WRONGD
+ MOVEI E,0
+ TRNE A,C.PRIN
+ MOVE E,PBFL
+; JUMPL E,WRONGD ; LOSER
+ CAME E,(P) ; CHECK WINNGE
+ JRST WRONGD
+ MOVE B,3(AB) ; GET CHANNEL BACK
+ SKIPN A,IOINS(B) ; OPEN?
+ PUSHJ P,OPENIT ; LOSE
+ CAMN A,[JRST CHNCLS]
+ JRST CHNCLS ; LOSE, CLOSED
+ JUMPN E,BUFOU1 ; JUMP FOR OUTPUT
+ MOVEI C,0
+ CAML AB,[-5,,] ; SKIP IF EOF GIVEN
+ JRST BINI5
+ MOVE 0,4(AB)
+ MOVEM 0,EOFCND-1(B)
+ MOVE 0,5(AB)
+ MOVEM 0,EOFCND(B)
+ CAML AB,[-7,,]
+ JRST BINI5
+ GETYP 0,6(AB)
+ CAIE 0,TFIX
+ JRST WTYP
+ MOVE C,7(AB)
+BINI5: SKIPE LSTCH(B) ; INDICATES IF EOF HIT
+ JRST BINEOF
+ GETYP 0,(AB) ; BRANCH BASED ON BYTE SIZE
+ CAIE 0,TCHSTR
+ CAIN 0,TBYTE
+ JRST BYTI
+ MOVE A,1(AB) ; GET VECTOR
+ PUSHJ P,PGBIOI ; READ IT
+ HLRE C,A ; GET COUNT DONE
+ HLRE D,1(AB) ; AND FULL COUNT
+ SUB C,D ; C=> TOTAL READ
+ ADDM C,ACCESS(B)
+ JUMPGE A,BINIOK ; NOT EOF YET
+ SETOM LSTCH(B)
+BINIOK: MOVE B,C
+ MOVSI A,TFIX ; RETURN AMOUNT ACTUALLY READ
+ JRST FINIS
+
+BYTI:
+IFE ITS,[
+ MOVE A,1(B)
+ RFBSZ
+ FATAL RFBSZ-LOST
+ PUSH P,B
+ LDB B,[300600,,1(AB)]
+ SFBSZ
+ FATAL SFBSZ-LOST
+ MOVE B,3(AB)
+ HRRZ A,(AB) ; GET BYTE STRING LENGTH
+ MOVNS A
+ MOVSS A ; MAKE FUNNY BYTE POINTER
+ HRR A,1(AB)
+ ADDI A,1
+ PUSH P,C
+ HLL C,1(AB) ; GET START OF BPTR
+ MOVE D,[SIN]
+ PUSHJ P,PGBIOT
+ HLRE C,A ; GET COUNT DONE
+ POP P,D
+ SKIPN D
+ HRRZ D,(AB) ; AND FULL COUNT
+ ADD D,C ; C=> TOTAL READ
+ LDB E,[300600,,1(AB)]
+ MOVEI A,36.
+ IDIVM A,E
+ IDIVM D,E
+ ADDM E,ACCESS(B)
+ SKIPGE C ; NOT EOF YET
+ SETOM LSTCH(B)
+ MOVE A,1(B)
+ POP P,B
+ SFBSZ
+ FATAL SFBSZ-LOST
+ MOVE C,D
+ JRST BINIOK
+]
+BUFOU1: SKIPE BUFSTR(B) ; ANY BUFFERS AROUND?
+ PUSHJ P,BFCLS1 ; GET RID OF SAME
+ MOVEI C,0
+ CAML AB,[-5,,]
+ JRST BINO5
+ GETYP 0,4(AB)
+ CAIE 0,TFIX
+ JRST WTYP
+ MOVE C,5(AB)
+BINO5: MOVE A,1(AB)
+ GETYP 0,(AB) ; BRANCH BASED ON BYTE SIZE
+ CAIE 0,TCHSTR
+ CAIN 0,TBYTE
+ JRST BYTO
+ PUSHJ P,PGBIOO
+ HLRE C,1(AB)
+ MOVNS C
+ ADDM C,ACCESS(B)
+BYTO1: MOVE A,(AB) ; RET VECTOR ETC.
+ MOVE B,1(AB)
+ JRST FINIS
+
+BYTO:
+IFE ITS,[
+ MOVE A,1(B)
+ RFBSZ
+ FATAL RFBSZ-FAILURE
+ PUSH P,B
+ LDB B,[300600,,1(AB)]
+ SFBSZ
+ FATAL SFBSZ-FAILURE
+ MOVE B,3(AB)
+ HRRZ A,(AB) ; GET BYTE SIZE
+ MOVNS A
+ MOVSS A ; MAKE FUNNY BYTE POINTER
+ HRR A,1(AB)
+ ADDI A,1 ; COMPENSATE FOR PGBIOT DOING THE WRONG THING
+ HLL C,1(AB) ; GET START OF BPTR
+ MOVE D,[SOUT]
+ PUSHJ P,PGBIOT
+ LDB D,[300600,,1(AB)]
+ MOVEI C,36.
+ IDIVM C,D
+ HRRZ C,(AB)
+ IDIVI C,(D)
+ ADDM C,ACCESS(B)
+ MOVE A,1(B)
+ POP P,B
+ SFBSZ
+ FATAL SFBSZ-FAILURE
+ JRST BYTO1
+]
+
+BINEOF: PUSH TP,EOFCND-1(B)
+ PUSH TP,EOFCND(B)
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ MCALL 1,FCLOSE ; CLOSE THE LOSER
+ MCALL 1,EVAL
+ JRST FINIS
+
+OPENIT: PUSH P,E
+ PUSHJ P,OPNCHN ;TRY TO OPEN THE LOSER
+ JUMPE B,CHNCLS ;FAIL
+ POP P,E
+ POPJ P,
+\f; THESE SUBROUTINES BY NDR 9/16/73 TO FACILITATE THE
+; TYPES OF IO NECESSARY TO MAKE MORE EFFICIENT USE OF
+; THE NETWORK AND DO RELATED FILE TRANSFER TYPE OF JOBS.
+
+R1CHAR: SKIPN A,LSTCH(B) ; CHAR READING ROUTINE FOR FCOPY
+ PUSHJ P,RXCT
+ TLO A,200000 ; ^@ BUG
+ MOVEM A,LSTCH(B)
+ TLZ A,200000
+ JUMPL A,.+2 ; IN CASE OF -1 ON STY
+ TRZN A,400000 ; EXCL HACKER
+ JRST .+4
+ MOVEM A,LSTCH(B) ; SAVE DE-EXCLED CHAR
+ MOVEI A,"!
+ JRST .+2
+ SETZM LSTCH(B)
+ PUSH P,C
+ HRRZ C,DIRECT-1(B)
+ CAIE C,5 ; IF DIRECTION IS 5 LONG THEN READB
+ JRST R1CH1
+ AOS C,ACCESS-1(B)
+ CAMN C,[TFIX,,1]
+ AOS ACCESS(B) ; EVERY FIFTY INCREMENT
+ CAMN C,[TFIX,,5]
+ HLLZS ACCESS-1(B)
+ JRST .+2
+R1CH1: AOS ACCESS(B)
+ POP P,C
+ POPJ P,
+
+W1CHAR: CAIE A,15 ; CHAR WRITING ROUTINE, TEST FOR CR
+ JRST .+3
+ SETOM CHRPOS(B)
+ AOSA LINPOS(B)
+ CAIE A,12 ; TEST FOR LF
+ AOS CHRPOS(B) ; IF NOT LF AOS CHARACTE5R POSITION
+ CAIE A,14 ; TEST FOR FORM FEED
+ JRST .+3
+ SETZM CHRPOS(B) ; IF FORM FEED ZERO CHARACTER POSITION
+ SETZM LINPOS(B) ; AND LINE POSITION
+ CAIE A,11 ; IS THIS A TAB?
+ JRST .+6
+ MOVE C,CHRPOS(B)
+ ADDI C,7
+ IDIVI C,8.
+ IMULI C,8. ; FIX UP CHAR POS FOR TAB
+ MOVEM C,CHRPOS(B) ; AND SAVE
+ PUSH P,C
+ HRRZ C,-2(B) ; GET BITS
+ TRNN C,C.BIN ; SIX LONG MUST BE PRINTB
+ JRST W1CH1
+ AOS C,ACCESS-1(B)
+ CAMN C,[TFIX,,1]
+ AOS ACCESS(B)
+ CAMN C,[TFIX,,5]
+ HLLZS ACCESS-1(B)
+ JRST .+2
+W1CH1: AOS ACCESS(B)
+ PUSH P,A
+ PUSHJ P,WXCT
+ POP P,A
+ POP P,C
+ POPJ P,
+
+R1C: SUBM M,(P) ;LITTLE ENTRY FOR COMPILED STUFF
+; PUSH TP,$TCHAN ;SAVE THE CHANNEL TO BLESS IT
+; PUSH TP,B
+; MOVEI B,DIRECT-1(B)
+; PUSHJ P,CHRWRD
+; JFCL
+; CAME B,[ASCIZ /READ/]
+; CAMN B,[ASCII /READB/]
+; JRST .+2
+; JRST BADCHN
+ HRRZ A,-2(B) ; GET MODE BITS
+ TRNN A,C.READ
+ JRST BADCHN
+ SKIPN IOINS(B) ; IS THE CHANNEL OPEN
+ PUSHJ P,OPENIT ; NO, GO DO IT
+ PUSHJ P,GRB ; MAKE SURE WE HAVE A READ BUFFER
+ PUSHJ P,R1CHAR ; AND GET HIM A CHARACTER
+ JRST MPOPJ ; THATS ALL FOLKS
+
+W1C: SUBM M,(P)
+ PUSHJ P,W1CI
+ JRST MPOPJ
+
+W1CI:
+; PUSH TP,$TCHAN
+; PUSH TP,B
+ PUSH P,A ; ASSEMBLER ENTRY TO OUTPUT 1 CHAR
+; MOVEI B,DIRECT-1(B)
+; PUSHJ P,CHRWRD ; INTERNAL CALL TO W1CHAR
+; JFCL
+; CAME B,[ASCII /PRINT/]
+; CAMN B,[<ASCII /PRINT/>+1]
+; JRST .+2
+; JRST BADCHN
+; POP TP,B
+; POP TP,(TP)
+ HRRZ A,-2(B)
+ TRNN A,C.PRIN
+ JRST BADCHN
+ SKIPN IOINS(B) ; MAKE SURE THAT IT IS OPEN
+ PUSHJ P,OPENIT
+ PUSHJ P,GWB
+ POP P,A ; GET THE CHAR TO DO
+ JRST W1CHAR
+
+; ROUTINES TO REPLACE XCT IOINS(B) FOR INPUT AND OUTPUT
+; THEY DO THE XCT THEN CHECK OUT POSSIBLE SCRIPTAGE--BLECH.
+
+
+WXCT:
+RXCT: XCT IOINS(B) ; READ IT
+ SKIPN SCRPTO(B)
+ POPJ P,
+
+DOSCPT: PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH P,A ; AND SAVE THE CHAR AROUND
+
+ SKIPN SCRPTO(B) ; IF ZERO FORGET IT
+ JRST SCPTDN ; THATS ALL THERE IS TO IT
+ PUSH P,C ; SAVE AN ACCUMULATOR FOR CLEANLINESS
+ GETYP C,SCRPTO-1(B) ; IS IT A LIST
+ CAIE C,TLIST
+ JRST BADCHN
+ PUSH TP,$TLIST
+ PUSH TP,[0] ; SAVE A SLOT FOR THE LIST
+ MOVE C,SCRPTO(B) ; GET THE LIST OF SCRIPT CHANNELS
+SCPT1: GETYP B,(C) ; GET THE TYPE OF THIS SCRIPT CHAN
+ CAIE B,TCHAN
+ JRST BADCHN ; IF IT ISN'T A CHANNEL, COMPLAIN
+ HRRZ B,(C) ; GET THE REST OF THE LIST IN B
+ MOVEM B,(TP) ; AND STORE ON STACK
+ MOVE B,1(C) ; GET THE CHANNEL IN B
+ MOVE A,-1(P) ; AND THE CHARACTER IN A
+ PUSHJ P,W1CI ; GO TO INTERNAL W1C, IT BLESSES GOODIES
+ SKIPE C,(TP) ; GET THE REST OF LIST OF CHANS
+ JRST SCPT1 ; AND CYCLE THROUGH
+ SUB TP,[2,,2] ; CLEAN OFF THE LIST OF CHANS
+ POP P,C ; AND RESTORE ACCUMULATOR C
+SCPTDN: POP P,A ; RESTORE THE CHARACTER
+ POP TP,B ; AND THE ORIGINAL CHANNEL
+ POP TP,(TP)
+ POPJ P, ; AND THATS ALL
+
+
+; SUBROUTINE TO COPY FROM INCHAN TO OUTCHAN UNTIL EOF HIT
+; ON THE INPUT CHANNEL
+; CALL IS <FILECOPY IN OUT> WHERE DEFAULTS ARE INCHAN AND OUTCHAN
+
+ MFUNCTION FCOPY,SUBR,[FILECOPY]
+
+ ENTRY
+ HLRE 0,AB
+ CAMGE 0,[-4]
+ JRST WNA ; TAKES FROM 0 TO 2 ARGS
+
+ JUMPE 0,.+4 ; NO FIRST ARG?
+ PUSH TP,(AB)
+ PUSH TP,1(AB) ; SAVE IN CHAN
+ JRST .+6
+ MOVE A,$TATOM
+ MOVE B,IMQUOTE INCHAN
+ PUSHJ P,IDVAL
+ PUSH TP,A
+ PUSH TP,B
+ HLRE 0,AB ; CHECK FOR SECOND ARG
+ CAML 0,[-2] ; WAS THERE MORE THAN ONE ARG?
+ JRST .+4
+ PUSH TP,2(AB) ; SAVE SECOND ARG
+ PUSH TP,3(AB)
+ JRST .+6
+ MOVE A,$TATOM ; LOOK UP OUTCHAN AS DEFAULT
+ MOVE B,IMQUOTE OUTCHAN
+ PUSHJ P,IDVAL
+ PUSH TP,A
+ PUSH TP,B ; AND SAVE IT
+
+ MOVE A,-3(TP)
+ MOVE B,-2(TP) ; INPUT CHANNEL
+ MOVEI 0,C.READ ; INDICATE INPUT
+ PUSHJ P,CHKCHN ; CHECK FOR GOOD CHANNEL
+ MOVE A,-1(TP)
+ MOVE B,(TP) ; GET OUT CHAN
+ MOVEI 0,C.PRIN ; INDICATE OUT CHAN
+ PUSHJ P,CHKCHN ; CHECK FOR GOOD OUT CHAN
+
+ PUSH P,[0] ; COUNT OF CHARS OUTPUT
+
+ MOVE B,-2(TP)
+ PUSHJ P,GRB ; MAKE SURE WE HAVE READ BUFF
+ MOVE B,(TP)
+ PUSHJ P,GWB ; MAKE SURE WE HAVE WRITE BUFF
+
+FCLOOP: INTGO
+ MOVE B,-2(TP)
+ PUSHJ P,R1CHAR ; GET A CHAR
+ JUMPL A,FCDON ; IF A NEG NUMBER WE GOT EOF
+ MOVE B,(TP) ; GET OUT CHAN
+ PUSHJ P,W1CHAR ; SPIT IT OUT
+ AOS (P) ; INCREMENT COUNT
+ JRST FCLOOP
+
+FCDON: SUB TP,[2,,2] ; POP OFF OUTCHAN
+ MCALL 1,FCLOSE ; CLOSE INCHAN
+ MOVE A,$TFIX
+ POP P,B ; GET CHAR COUNT TO RETURN
+ JRST FINIS
+
+CHKCHN: PUSH P,0 ; CHECK FOR GOOD TASTING CHANNEL
+ PUSH TP,A
+ PUSH TP,B
+ GETYP C,A
+ CAIE C,TCHAN
+ JRST CHKBDC ; GO COMPLAIN IN RIGHT WAY
+; MOVEI B,DIRECT-1(B)
+; PUSHJ P,CHRWRD
+; JRST CHKBDC
+; MOVE C,(P) ; GET CHAN DIRECT
+ HRRZ C,-2(B) ; MODE BITS
+ TDNN C,0
+ JRST CHKBDC
+; CAMN B,CHKT(C)
+; JRST .+4
+; ADDI C,2 ; TEST FOR READB OR PRINTB ALSO
+; CAME B,CHKT(C) ; TEST FOR CORRECT DIRECT
+; JRST CHKBDC
+ MOVE B,(TP)
+ SKIPN IOINS(B) ; MAKE SURE IT IS OPEN
+ PUSHJ P,OPENIT ; IF ZERO IOINS GO OPEN IT
+ SUB TP,[2,,2]
+ POP P, ; CLEAN UP STACKS
+ POPJ P,
+
+CHKT: ASCIZ /READ/
+ ASCII /PRINT/
+ ASCII /READB/
+ <ASCII /PRINT/>+1
+
+CHKBDC: POP P,E
+ MOVNI D,2
+ IMULI D,1(E)
+ HLRE 0,AB
+ CAMLE 0,D ; SEE IF THIS WAS HIS ARG OF DEFAULT
+ JRST BADCHN
+ JUMPE E,WTYP1
+ JRST WTYP2
+
+\f; FUNCTIONS READSTRING AND PRINTSTRING WORK LIKE READB AND PRINTB,
+; THAT IS THEY READ INTO AND OUT OF STRINGS. IN ADDITION BOTH ACCEPT
+; AN ADDITIONAL ARGUMENT WHICH IS THE NUMBER OF CHARS TO READ OR PRINT, IF
+; IT IS DESIRED FOR THIS TO BE DIFFERENT THAN THE LENGTH OF THE STRING.
+
+; FORMAT IS <READSTRING .STRING .INCHANNEL .EOFCOND .MAXCHARS>
+; AND BOTH SUBRS RETURN THE NUMBER OF CHARS READ OR WRITTEN
+
+; FORMAT FOR PRINTSTRING IS <PRINTSTRING .STRING .OUTCHANNEL .MAXCHARS>
+
+; THESE WERE CODED 9/16/73 BY NEAL D. RYAN
+
+ MFUNCTION RSTRNG,SUBR,READSTRING
+
+ ENTRY
+ PUSH P,[0] ; FLAG TO INDICATE READING
+ HLRE 0,AB
+ CAMG 0,[-1]
+ CAMG 0,[-9]
+ JRST WNA ; CHECK THAT IT HAS FROM 1 TO 4 ARGS
+ JRST STRIO1
+
+ MFUNCTION PSTRNG,SUBR,PRINTSTRING
+
+ ENTRY
+ PUSH P,[1] ; FLAG TO INDICATE WRITING
+ HLRE 0,AB
+ CAMG 0,[-1]
+ CAMG 0,[-7]
+ JRST WNA ; CHECK THAT IT HAS FROM 1 TO 3 ARGS
+
+STRIO1: PUSH TP,[0] ; SAVE SLOT ON STACK
+ PUSH TP,[0]
+ GETYP 0,(AB)
+ CAIE 0,TCHSTR ; MAKE SURE WE GOT STRING
+ JRST WTYP1
+ HRRZ 0,(AB) ; CHECK FOR EMPTY STRING
+ SKIPN (P)
+ JUMPE 0,MTSTRN
+ HLRE 0,AB
+ CAML 0,[-2] ; WAS A CHANNEL GIVEN
+ JRST STRIO2
+ GETYP 0,2(AB)
+ SKIPN (P) ; SKIP IF PRINT
+ JRST TESTIN
+ CAIN 0,TTP ; SEE IF FLATSIZE HACK
+ JRST STRIO9
+TESTIN: CAIE 0,TCHAN
+ JRST WTYP2 ; SECOND ARG NOT CHANNEL
+ MOVE B,3(AB)
+ HRRZ B,-2(B)
+ MOVNI E,1 ; CHECKING FOR GOOD DIRECTION
+ TRNE B,C.READ ; SKIP IF NOT READ
+ MOVEI E,0
+ TRNE B,C.PRIN ; SKIP IF NOT PRINT
+ MOVEI E,1
+ CAME E,(P)
+ JRST WRONGD ; MAKE SURE CHANNEL IS OPEN IN RIGHT MODE
+STRIO9: PUSH TP,2(AB)
+ PUSH TP,3(AB) ; PUSH ON CHANNEL
+ JRST STRIO3
+STRIO2: MOVE B,IMQUOTE INCHAN
+ MOVSI A,TCHAN
+ SKIPE (P)
+ MOVE B,IMQUOTE OUTCHAN
+ PUSHJ P,IDVAL
+ GETYP 0,A
+ SKIPN (P) ; SKIP IF PRINTSTRING
+ JRST TESTI2
+ CAIN 0,TTP ; SKIP IF NOT FLATSIZE HACK
+ JRST STRIO8
+TESTI2: CAIE 0,TCHAN
+ JRST BADCHN ; MAKE SURE WE GOT A GOOD DEFAULT CHANNEL
+STRIO8: PUSH TP,A
+ PUSH TP,B
+STRIO3: MOVE B,(TP) ; GET CHANNEL
+ SKIPN E,IOINS(B)
+ PUSHJ P,OPENIT ; IF NOT GO OPEN
+ MOVE E,IOINS(B)
+ CAMN E,[JRST CHNCLS]
+ JRST CHNCLS ; CHECK TO SEE THAT CHANNEL ISNT ALREADY CLOSED
+STRIO4: HLRE 0,AB
+ CAML 0,[-4]
+ JRST STRIO5 ; NO COUNT TO WORRY ABOUT
+ GETYP 0,4(AB)
+ MOVE E,4(AB)
+ MOVE C,5(AB)
+ CAIE 0,TCHSTR
+ CAIN 0,TFIX ; BETTER BE A FIXED NUMBER
+ JRST .+2
+ JRST WTYP3
+ HRRZ D,(AB) ; GET ACTUAL STRING LENGTH
+ CAIN 0,TFIX
+ JRST .+7
+ SKIPE (P) ; TEST FOR WRITING
+ JRST .-7 ; IF WRITING WE GOT TROUBLE
+ PUSH P,D ; ACTUAL STRING LENGTH
+ MOVEM E,(TB) ; STUFF HIS FUNNY DELIM STRING
+ MOVEM C,1(TB)
+ JRST STRIO7
+ CAML D,C ; MAKE SURE THE STRING IS LONG ENOUGH
+ JRST .+2 ; WIN
+ ERRUUO EQUOTE COUNT-GREATER-THAN-STRING-SIZE
+ PUSH P,C ; PUSH ON MAX COUNT
+ JRST STRIO7
+STRIO5:
+STRIO6: HRRZ C,(AB) ; GET CHAR COUNT
+ PUSH P,C ; AND PUSH IT ON STACK AS NO MAX COUNT GIVEN
+STRIO7: HLRE 0,AB
+ CAML 0,[-6]
+ JRST .+6
+ MOVE B,(TP) ; GET THE CHANNEL
+ MOVE 0,6(AB)
+ MOVEM 0,EOFCND-1(B) ; STUFF IN SLOT IN CHAN
+ MOVE 0,7(AB)
+ MOVEM 0,EOFCND(B)
+ PUSH TP,(AB) ; PUSH ON STRING
+ PUSH TP,1(AB)
+ PUSH P,[0] ; PUSH ON CURRENT COUNT OF CHARS DONE
+ MOVE 0,-2(P) ; GET READ OR WRITE FLAG
+ JUMPN 0,OUTLOP ; GO WRITE STUFF
+
+ MOVE B,-2(TP) ; GET CHANNEL
+ PUSHJ P,GRB ; MAKE SURE WE HAVE BUFF
+ SKIPGE A,LSTCH(B) ; CHECK FOR EOF ALREADY READ PREVIOUSLY
+ JRST SRDOEF ; GO DOES HIS EOF HACKING
+INLOP: INTGO
+ MOVE B,-2(TP) ; GET CHANNEL
+ MOVE C,-1(P) ; MAX COUNT
+ CAMG C,(P) ; COMPARE WITH COUNT DONE
+ JRST STREOF ; WE HAVE FINISHED
+ PUSHJ P,R1CHAR ; GET A CHAR
+ JUMPL A,INEOF ; EOF HIT
+ MOVE C,1(TB)
+ HRRZ E,(TB) ; DO WE HAVE A STRING TO WORRY US?
+ SOJL E,INLNT ; GO FINISH STUFFING
+ ILDB D,C
+ CAME D,A
+ JRST .-3
+ JRST INEOF
+INLNT: IDPB A,(TP) ; STUFF IN STRING
+ SOS -1(TP) ; DECREMENT STRING COUNT
+ AOS (P) ; INCREMENT CHAR COUNT
+ JRST INLOP
+
+INEOF: SKIPE C,LSTCH(B) ; IS THIS AN ! AND IS THERE A CHAR THERE
+ JRST .+3 ; YES
+ MOVEM A,LSTCH(B) ; NO SAVE THE CHAR
+ JRST .+3
+ ADDI C,400000
+ MOVEM C,LSTCH(B)
+ MOVSI C,200000
+ IORM C,LSTCH(B)
+ HRRZ C,DIRECT-1(B) ; GET THE TYPE OF CHAN
+ CAIN C,5 ; IS IT READB?
+ JRST .+3
+ SOS ACCESS(B) ; FIX UP ACCESS FOR READ CHANNEL
+ JRST STREOF ; AND THATS IT
+ HRRZ C,ACCESS-1(B) ; FOR A READB ITS WORSE
+ MOVEI D,5
+ SKIPG C
+ HRRM D,ACCESS-1(B) ; CHANGE A 0 TO A FIVE
+ SOS C,ACCESS-1(B)
+ CAMN C,[TFIX,,0]
+ SOS ACCESS(B) ; AND SOS THE WORD COUNT MAYBE
+ JRST STREOF
+
+SRDOEF: SETZM LSTCH(B) ; IN CASE OF -1, FLUSH IT
+ AOJE A,INLOP ; SKIP OVER -1 ON PTY'S
+ SUB TP,[6,,6]
+ SUB P,[3,,3] ; POP JUNK OFF STACKS
+ PUSH TP,EOFCND-1(B)
+ PUSH TP,EOFCND(B) ; WHAT WE NEED TO EVAL
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ MCALL 1,FCLOSE ; CLOSE THE LOOSING CHANNEL
+ MCALL 1,EVAL ; EVAL HIS EOF JUNK
+ JRST FINIS
+
+OUTLOP: MOVE B,-2(TP)
+OUTLP1: INTGO
+ MOVE A,-3(TP) ; GET CHANNEL
+ MOVE B,-2(TP)
+ MOVE C,-1(P) ; MAX COUNT TO DO
+ CAMG C,(P) ; HAVE WE DONE ENOUGH
+ JRST STREOF
+ ILDB D,(TP) ; GET THE CHAR
+ SOS -1(TP) ; SUBTRACT FROM STRING LENGTH
+ AOS (P) ; INC COUNT OF CHARS DONE
+ PUSHJ P,CPCH1 ; GO STUFF CHAR
+ JRST OUTLP1
+
+STREOF: MOVE A,$TFIX
+ POP P,B ; RETURN THE LOOSER A COUNT OF WHAT WAS DONE
+ SUB P,[2,,2]
+ SUB TP,[6,,6]
+ JRST FINIS
+
+
+GWB: SKIPE BUFSTR(B)
+ POPJ P,
+ PUSH TP,$TCHAN
+ PUSH TP,B ; GET US A WRITE BUFFER ON PRINTB CHAN
+ MOVEI A,BUFLNT
+ PUSHJ P,IBLOCK
+ MOVSI A,TWORD+.VECT.
+ MOVEM A,BUFLNT(B)
+ SETOM (B)
+ MOVEI C,1(B)
+ HRLI C,(B)
+ BLT C,BUFLNT-1(B)
+ MOVEI C,-1(B)
+ HRLI C,010700
+ MOVE B,(TP)
+ MOVEI 0,C.BUF
+ IORM 0,-2(B)
+ MOVEM C,BUFSTR(B)
+ MOVE C,[TCHSTR,,BUFLNT*5]
+ MOVEM C,BUFSTR-1(B)
+ SUB TP,[2,,2]
+ POPJ P,
+
+
+GRB: SKIPE BUFSTR(B)
+ POPJ P,
+ PUSH TP,$TCHAN
+ PUSH TP,B ; GET US A READ BUFFER
+ MOVEI A,BUFLNT
+ PUSHJ P,IBLOCK
+ MOVEI C,BUFLNT-1(B)
+ POP TP,B
+ MOVEI 0,C.BUF
+ IORM 0,-2(B)
+ HRLI C,010700
+ MOVEM C,BUFSTR(B)
+ MOVSI C,TCHSTR
+ MOVEM C,BUFSTR-1(B)
+ SUB TP,[1,,1]
+ POPJ P,
+
+MTSTRN: ERRUUO EQUOTE EMPTY-STRING
+
+\f; INPUT UNBUFFERING ROUTINE. THIS DOES THE CHARACTER UNBUFFERING
+; FOR INPUT. THE OPEN ROUTINE SETUPS A PUSHJ P, TO
+; THIS ROUTINE AS THE IOINS FOR A CHANNEL OPEN TO A NON-TTY DEVICE.
+
+; H. BRODIE 7/19/72
+
+; CALLING SEQ:
+; PUSHJ P,GETCHR
+; B/ AOBJN PNTR TO CHANNEL VECTOR
+; RETURNS NEXT CHARACTER IN AC A.
+; ON ENCOUNTERING EITHER ^C OR NUL(^@) IT ASSUMES EOF AND
+; TRANSMITS ONLY ^C ON SUCCESSIVE CALLS
+
+
+GETCHR:
+; FIRST GRAB THE BUFFER
+; GETYP A,BUFSTR-1(B) ; GET TYPE WORD
+; CAIN A,TCHSTR ; SKIPS IF NOT CHSTR (I.E. IF BAD BUFFER)
+; JRST GTGBUF ; IS GOOD BUFFER...SKIP ERROR RETURN
+GTGBUF: HRRZ A,BUFSTR-1(B) ; GET LENGTH OF STRING
+ SOJGE A,GTGCHR ; JUMP IF STILL MORE
+
+; HERE IF THE BUFFER WAS EXHAUSTED (BYTE PNTR POINTS INTO DOPE WDS)
+; GENERATE AN .IOT POINTER
+;FIRST SAVE C AND D AS I WILL CLOBBER THEM
+NEWBUF: PUSH P,C
+ PUSH P,D
+IFN ITS,[
+ LDB C,[600,,STATUS(B)] ; GET TYPE
+ CAIG C,2 ; SKIP IF NOT TTY
+]
+IFE ITS,[
+ SKIPE BUFRIN(B)
+]
+ JRST GETTTY ; GET A TTY BUFFER
+
+ PUSHJ P,PGBUFI ; RE-FILL BUFFER
+
+IFE ITS, MOVEI C,-1
+ JUMPGE A,BUFGOO ;SKIPS IF IOT COMPLETED...FIX UP CHANNEL
+ MOVEI C,1 ; MAKE SURE LAST EOF REALLY ENDS IT
+ ANDCAM C,-1(A)
+ MOVSI C,014000 ; GET A ^C
+ MOVEM C,(A) ;FAKE AN EOF
+
+IFE ITS,[
+ HLRE C,A ; HOW MUCH LEFT
+ ADDI C,BUFLNT ; # OF WORDS TO C
+ IMULI C,5 ; TO CHARS
+ MOVE A,-2(B) ; GET BITS
+ TRNE A,C.BIN ; CAN'T HELP A BINARY CHANNEL
+ JRST BUFGOO
+ MOVE A,CHANNO(B)
+ PUSH P,B
+ PUSH P,D
+ PUSH P,C
+ PUSH P,[0]
+ PUSH P,[0]
+ MOVEI C,-1(P)
+ MOVE B,[2,,11] ; READ WORD CONTAINING BYTE SIZE
+ GTFDB
+ LDB D,[300600,,-1(P)] ; GET BYTE SIZE
+ MOVE B,(P)
+ SUB P,[2,,2]
+ POP P,C
+ CAIE D,7 ; SEVEN BIT BYTES?
+ JRST BUFGO1 ; NO, DONT HACK
+ MOVE D,C
+ IDIVI B,5 ; C IS NUMBER IN LAST WORD IF NOT EVEN
+ SKIPN C
+ MOVEI C,5
+ ADDI C,-5(D) ; FIXUP C FOR WINNAGE
+BUFGO1: POP P,D
+ POP P,B
+]
+; RESET THE BYTE POINTER IN THE CHANNEL.
+; BUILD ONE USING THE PTR TO BEG OF BUFFER SAVED IN D
+BUFGOO: HRLI D,010700 ; GENERATE VIRGIN LH
+ SUBI D,1
+
+ MOVEM D,BUFSTR(B) ; STASH IN THE BUFFER BYTE PNTR SLOT
+IFE ITS, HRRM C,LSTCH-1(B) ; SAVE IT
+ MOVEI A,BUFLNT*5-1
+BUFROK: POP P,D ;RESTORE D
+ POP P,C ;RESTORE C
+
+
+; HERE IF THERE ARE CHARS IN BUFFER
+GTGCHR: HRRM A,BUFSTR-1(B)
+ ILDB A,BUFSTR(B) ; GET A CHAR FROM BUFFER
+
+IFN ITS,[
+ CAIE A,3 ; EOF?
+ POPJ P, ; AND RETURN
+ LDB A,[600,,STATUS(B)] ; CHECK FOR TTY
+ CAILE A,2 ; SKIP IF TTY
+]
+IFE ITS,[
+ PUSH P,0
+ HRRZ 0,LSTCH-1(B)
+ SOJL 0,.+4
+ HRRM 0,LSTCH-1(B)
+ POP P,0
+ POPJ P,
+
+ POP P,0
+ MOVSI A,-1
+ SKIPN BUFRIN(B)
+]
+ JRST .+3
+RETEO1: HRRI A,3
+ POPJ P,
+
+ HRRZ A,BUFSTR(B) ; SEE IF RSUBR START BIT IS ON
+ HRRZ A,(A)
+ TRNN A,1
+ MOVSI A,-1
+ JRST RETEO1
+
+IFN ITS,[
+PGBUFO:
+PGBUFI:
+]
+IFE ITS,[
+PGBUFO: SKIPA D,[SOUT]
+PGBUFI: MOVE D,[SIN]
+]
+ SKIPGE A,BUFSTR(B) ; POINT TO CURRENT BUFFER POSIT
+ SUBI A,1 ; FOR 440700 AND 010700 START
+ SUBI A,BUFLNT-1 ; CALCULATE PNTR TO BEG OF BUFFER
+ HRLI A,-BUFLNT ; IOT (AOBJN) PNTR IN A
+ MOVSI C,004400
+IFN ITS,[
+PGBIOO:
+PGBIOI: MOVE D,A ; COPY FOR LATER
+ MOVSI C,TUVEC ; PREPARE TO HANDDLE INTS
+ MOVE PVP,PVSTOR+1
+ MOVEM C,DSTO(PVP)
+ MOVEM C,ASTO(PVP)
+ MOVSI C,TCHAN
+ MOVEM C,BSTO(PVP)
+
+; BUILD .IOT INSTR
+ MOVE C,CHANNO(B) ; CHANNEL NUMBER IN C
+ ROT C,23. ; MOVE INTO AC FIELD
+ IOR C,[.IOT 0,A] ; IOR IN SKELETON .IOT
+
+; DO THE .IOT
+ ENABLE ; ALLOW INTS
+ XCT C ; EXECUTE THE .IOT INSTR
+ DISABLE
+ MOVE PVP,PVSTOR+1
+ SETZM BSTO(PVP)
+ SETZM ASTO(PVP)
+ SETZM DSTO(PVP)
+ POPJ P,
+]
+
+IFE ITS,[
+PGBIOT: PUSH P,D
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH P,C
+ HRRZS (P)
+ HRRI C,-1(A) ; POINT TO BUFFER
+ HLRE D,A ; XTRA POINTER
+ MOVNS D
+ HRLI D,TCHSTR
+ MOVE PVP,PVSTOR+1
+ MOVEM D,BSTO(PVP)
+ MOVE D,[PUSHJ P,FIXACS]
+ MOVEM D,ONINT
+ MOVSI D,TUVEC
+ MOVEM D,DSTO(PVP)
+ MOVE D,A
+ MOVE A,CHANNO(B) ; FILE JFN
+ MOVE B,C
+ HLRE C,D ; - COUNT TO C
+ SKIPE (P)
+ MOVN C,(P) ; REAL DESIRED COUNT
+ SUB P,[1,,1]
+ ENABLE
+ XCT (P) ; DO IT TO IT
+ DISABLE
+ MOVE PVP,PVSTOR+1
+ SETZM BSTO(PVP)
+ SETZM DSTO(PVP)
+ SETZM ONINT
+ MOVEI A,1(B)
+ MOVE B,(TP)
+ SUB TP,[2,,2]
+ SUB P,[1,,1]
+ JUMPGE C,CPOPJ ; NO EOF YET
+ HRLI A,(C) ; LOOK LIKE AN AOBJN PNTR
+ POPJ P,
+
+FIXACS: PUSH P,PVP
+ MOVE PVP,PVSTOR+1
+ MOVNS C
+ HRRM C,BSTO(PVP)
+ MOVNS C
+ POP P,PVP
+ POPJ P,
+
+PGBIOO: SKIPA D,[SOUT]
+PGBIOI: MOVE D,[SIN]
+ HRLI C,004400
+ JRST PGBIOT
+DOIOTO: PUSH P,[SOUT]
+DOIOTC: PUSH P,B
+ PUSH P,C
+ EXCH A,B
+ MOVE A,CHANNO(A)
+ HLRE C,B
+ HRLI B,444400
+ XCT -2(P)
+ HRL B,C
+ MOVE A,B
+DOIOTE: POP P,C
+ POP P,B
+ SUB P,[1,,1]
+ POPJ P,
+DOIOTI: PUSH P,[SIN]
+ JRST DOIOTC
+]
+\f
+; OUTPUT BUFFERING ROUTINES SIMILAR TO INPUT BUFFERING ROUTINES OF PREV PAGE
+
+PUTCHR: PUSH P,A
+ GETYP A,BUFSTR-1(B) ; CHECK TYPE OF ARG
+ CAIE A,TCHSTR ; MUST BE STRING
+ JRST BDCHAN
+
+ HRRZ A,BUFSTR-1(B) ; GET CHAR COUNT
+ JUMPE A,REBUFF ; PREV RESET BUFF, UNDO SAME
+
+PUTCH1: POP P,A ; RESTORE CHAR
+ CAMN A,[-1] ; SPECIAL HACK?
+ JRST PUTCH2 ; YES GO HANDLE
+ IDPB A,BUFSTR(B) ; STUFF IT
+PUTCH3: SOS A,BUFSTR-1(B) ; COUNT DOWN STRING
+ TRNE A,-1 ; SKIP IF FULL
+ POPJ P,
+
+; HERE TO FLUSH OUT A BUFFER
+
+ PUSH P,C
+ PUSH P,D
+ PUSHJ P,PGBUFO ; SETUP AND DO IOT
+ HRLI D,010700 ; POINT INTO BUFFER
+ SUBI D,1
+ MOVEM D,BUFSTR(B) ; STORE IT
+ MOVEI A,BUFLNT*5 ; RESET COUNT
+ HRRM A,BUFSTR-1(B)
+ POP P,D
+ POP P,C
+ POPJ P,
+
+;HERE TO DA ^C AND TURN ON MAGIC BIT
+
+PUTCH2: MOVEI A,3
+ IDPB A,BUFSTR(B) ; ZAP OUT THE ^C
+ MOVEI A,1 ; GET BIT
+IFE ITS,[
+ PUSH P,C
+ HRRZ C,BUFSTR(B)
+ IORM A,(C)
+ POP P,C
+]
+IFN ITS,[
+ IORM A,@BUFSTR(B) ; ON GOES THE BIT
+]
+ JRST PUTCH3
+
+; RESET A FUNNY BUF
+
+REBUFF: MOVEI A,BUFLNT*5 ; 1ST COUNT
+ HRRM A,BUFSTR-1(B)
+ HRRZ A,BUFSTR(B) ; NOW POINTER
+ SUBI A,BUFLNT+1
+ HRLI A,010700
+ MOVEM A,BUFSTR(B) ; STORE BACK
+ JRST PUTCH1
+
+
+; HERE TO FLUSH FINAL BUFFER
+
+BFCLOS: HRRZ C,-2(B) ; THIS BUFFER FLUSHER THE WORK OF NDR
+ MOVEI A,0
+ TRNE C,C.TTY
+ POPJ P,
+ TRNE C,C.DISK
+ MOVEI A,1
+ PUSH P,A ; SAVE THE RESULT OF OUR TEST
+ JUMPN A,BFCLNN ; DONT HAVE TO CHECK NET STATE
+ PUSH TP,$TCHAN
+ PUSH TP,B ; SAVE CHANNEL
+ PUSHJ P,INSTAT ; GET CURRENT NETWORK STATE
+ MOVE A,(B) ; GET FIRST ELEMENT OF STATE UVECTOR WHICH IS CUR STATE
+ POP TP,B ; RESTORE B
+ POP TP,
+ CAIE A,5 ; IS NET IN OPEN STATE?
+ CAIN A,6 ; OR ELSE IS IT IN RFNM WAIT STATE
+ JRST BFCLNN ; IF SO TO THE IOT
+ POP P, ; ELSE FLUSH CRUFT AND DONT IOT
+ POPJ P, ; RETURN DOING NO IOT
+BFCLNN: MOVEI C,BUFLNT*5 ; NEW BUFFER FLUSHER BY NDR
+ HRRZ D,BUFSTR-1(B) ; SO THAT NET ALSO WORKS RIGHT
+ SUBI C,(D) ; GET NUMBER OF CHARS
+ IDIVI C,5 ; NUMBER OF FULL WORDS AND REST
+ PUSH P,D ; SAVE NUMBER OF ODD CHARS
+ SKIPGE A,BUFSTR(B) ; GET CURRENT BUF POSITION
+ SUBI A,1 ; FIX FOR 440700 BYTE POINTER
+IFE ITS,[
+ HRRO D,A
+ PUSH P,(D)
+]
+IFN ITS,[
+ PUSH P,(A) ; SAVE THE ODD WORD OF BUFFER
+]
+ MOVEI D,BUFLNT
+ SUBI D,(C)
+ SKIPE -1(P)
+ SUBI A,1
+ ADDI D,1(A) ; FIX UP FOR POSSIBLE ODD CHARS
+ PUSH TP,$TUVEC
+ PUSH TP,D ; PUSH THE DOPE VECTOR ONTO THE STACK
+ JUMPE C,BFCLSR ; IN CASE THERE ARE NO FULL WORDS TO DO
+ HRL A,C
+ TLO A,400000
+ MOVE E,[SETZ BUFLNT(A)]
+ SUBI E,(C) ; FIX UP FOR BACKWARDS BLT
+ POP A,@E ; AMAZING GRACE
+ TLNE A,377777
+ JRST .-2
+ HRRO A,D ; SET UP AOBJN POINTER
+ SUBI A,(C)
+ TLC A,-1(C)
+ PUSHJ P,PGBIOO ; DO THE IOT OF ALL THE FULL WORDS
+BFCLSR: HRRO A,(TP) ; GET IOT PTR FOR REST OF JUNK
+ SUBI A,1 ; POINT TO WORD BEFORE DOPE WORDS
+ POP P,0 ; GET BACK ODD WORD
+ POP P,C ; GET BACK ODD CHAR COUNT
+ POP P,D ; FLAG FOR NET OR DSK
+ JUMPN D,BFCDSK ; GO FINISH OFF DSK
+ JUMPE C,BFCLSD ; IF NO ODD CHARS FINISH UP
+ MOVEI D,7
+ IMULI D,(C) ; FIND NO OF BITS TO SHIFT
+ LSH 0,-43(D) ; SHIFT BITS TO RIGHT PLACE
+ MOVEM 0,(A) ; STORE IN STRING
+ SUBI C,5 ; HOW MANY CHAR POSITIONS TO SKIP
+ MOVNI C,(C) ; MAKE C POSITIVE
+ LSH C,17
+ TLC A,(C) ; MUNG THE AOBJN POINTER TO KLUDGE
+ PUSHJ P,PGBIOO ; DO IOT OF ODD CHARS
+ MOVEI C,0
+BFCLSD: HRRZ A,(TP) ; GET PTR TO DOPE WORD
+ SUBI A,BUFLNT+1
+ JUMPLE C,.+3
+ SKIPE ACCESS(B)
+ MOVEM 0,1(A) ; LAST WORD BACK IN BFR
+ HRLI A,010700 ; AOBJN POINTER TO FIRST OF BUFFER
+ MOVEM A,BUFSTR(B)
+ MOVEI A,BUFLNT*5
+ HRRM A,BUFSTR-1(B)
+ SKIPN ACCESS(B)
+ JRST BFCLSY
+ JUMPL C,BFCLSY
+ JUMPE C,BFCLSZ
+ IBP BUFSTR(B)
+ SOS BUFSTR-1(B)
+ SOJG C,.-2
+BFCLSY: MOVE A,CHANNO(B)
+ MOVE C,B
+IFE ITS,[
+ RFPTR
+ FATAL RFPTR FAILED
+ HRRZ F,LSTCH-1(C) ; PREVIOUS HIGH
+ MOVE G,C ; SAVE CHANNEL
+ MOVE C,B
+ CAML F,B
+ MOVE C,F
+ MOVE F,B
+ HRLI A,400000
+ CLOSF
+ JFCL
+ MOVNI B,1
+ HRLI A,12
+ CHFDB
+ MOVE B,STATUS(G)
+ ANDI A,-1
+ OPENF
+ FATAL OPENF LOSES
+ MOVE C,F
+ IDIVI C,5
+ MOVE B,C
+ SFPTR
+ FATAL SFPTR FAILED
+ MOVE B,G
+]
+IFN ITS,[
+ DOTCAL RFPNTR,[A,[2000,,B]]
+ .LOSE %LSFIL ;PRESUMABLY LOSSAGE MATTERS
+ SUBI B,1
+ DOTCAL ACCESS,[A,B]
+ .LOSE %LSFIL ;PRESUMABLY LOSSAGE MATTERS
+ MOVE B,C
+]
+BFCLSZ: SUB TP,[2,,2]
+ POPJ P,
+
+BFCDSK: TRZ 0,1
+ PUSH P,C
+IFE ITS,[
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ PUSH P,0 ; WORD OF CHARS
+ MOVE A,CHANNO(B)
+ MOVEI B,7 ; MAKE BYTE SIZE 7
+ SFBSZ
+ JFCL
+ HRROI B,(P)
+ MOVNS C
+ SKIPE C
+ SOUT
+ MOVE B,(TP)
+ SUB P,[1,,1]
+ SUB TP,[2,,2]
+]
+IFN ITS,[
+ MOVE D,[440700,,A]
+ DOTCAL SIOT,[CHANNO(B),D,C]
+ .LOSE %LSFIL ;PRESUMABLY LOSSAGE MATTERS
+]
+ POP P,C
+ JUMPN C,BFCLSD
+BFCDS1: MOVNI C,1 ; INDICATE NOT TOHACK BUFFER
+ JRST BFCLSD
+
+BFCLS1: HRRZ C,DIRECT-1(B)
+ MOVSI 0,(JFCL)
+ CAIE C,6
+ MOVE 0,[AOS ACCESS(B)]
+ PUSH P,0
+ HRRZ C,BUFSTR-1(B)
+ IDIVI C,5
+ JUMPE D,BCLS11
+ MOVEI A,40 ; PAD WITH SPACES
+ PUSHJ P,PUTCHR
+ XCT (P) ; AOS ACCESS IF NECESSARY
+ SOJG D,.-3 ; TO END OF WORD\r
+BCLS11: POP P,0
+ HLLZS ACCESS-1(B)
+ HRRZ C,BUFSTR-1(B)
+ CAIE C,BUFLNT*5
+ PUSHJ P,BFCLOS
+ POPJ P,
+
+\f
+; HERE TO GET A TTY BUFFER
+
+GETTTY: SKIPN C,EXBUFR(B) ; SKIP IF BUFFERS BACKED UP
+ JRST TTYWAI
+ HRRZ D,(C) ; CDR THE LIST
+ GETYP A,(C) ; CHECK TYPE
+ CAIE A,TDEFER ; MUST BE DEFERRED
+ JRST BDCHAN
+ MOVE C,1(C) ; GET DEFERRED GOODIE
+ GETYP A,(C) ; BETTER BE CHSTR
+ CAIE A,TCHSTR
+ JRST BDCHAN
+ MOVE A,(C) ; GET FULL TYPE WORD
+ MOVE C,1(C)
+ MOVEM D,EXBUFR(B) ; STORE CDR'D LIST
+ MOVEM A,BUFSTR-1(B) ; MAKE CURRENT BUFFER
+ MOVEM C,BUFSTR(B)
+ HRRM A,LSTCH-1(B)
+ SOJA A,BUFROK
+
+TTYWAI: PUSHJ P,TTYBLK ; BLOCKED FOR TTY I/O
+ JRST GETTTY ; SHOULD ONLY RETURN HAPPILY
+
+\f;INTERNAL DEVICE READ ROUTINE.
+
+;FOR INTERNAL DEVICES THIS ROUTINE APPLIES THE GIVEN OBJECT,
+;CHECKS THAT THE RETURNED VALUE IS OF TYPE CHARACTER,
+;AND RETURNS THAT AS THE NEXT CHARACTER IN THE "FILE"
+
+;H. BRODIE 8/31/72
+
+GTINTC: PUSH TP,$TCHAN ;SAVE THE CHANNEL...WE'LL CLOBBER B
+ PUSH TP,B
+ PUSH P,C ;AND SAVE THE OTHER ACS
+ PUSH P,D
+ PUSH P,E
+ PUSH P,0
+ PUSH TP,$TCHAN
+ PUSH TP,B
+ MCALL 1,INTFCN-1(B)
+ GETYP A,A
+ CAIE A,TCHRS
+ JRST BADRET
+ MOVE A,B
+INTRET: POP P,0 ;RESTORE THE ACS
+ POP P,E
+ POP P,D
+ POP P,C
+ POP TP,B ;RESTORE THE CHANNEL
+ SUB TP,[1,,1] ;FLUSH $TCHAN...WE DON'T NEED IT
+ POPJ P,
+
+
+BADRET: ERRUUO EQUOTE INT-DEVICE-WRONG-TYPE-EVALUATION-RESULT
+
+;INTERNAL DEVICE PRINT ROUTINE.
+
+;FOR INTERNAL DEVICES THIS ROUTINE APPLIES THE GIVEN OBJECT,(FUNCTION, SUBR, OR RSUBR)
+;TO THE CURRENT CHARACTER BEING "PRINTED".
+
+PTINTC: PUSH TP,$TCHAN ;SAVE THE CHANNEL...WE'LL CLOBBER B
+ PUSH TP,B
+ PUSH P,C ;AND SAVE THE OTHER ACS
+ PUSH P,D
+ PUSH P,E
+ PUSH P,0
+ PUSH TP,$TCHRS ;PUSH THE TYPE "CHARACTER"
+ PUSH TP,A ;PUSH THE CHAR
+ PUSH TP,$TCHAN ;PUSH THE CHANNEL
+ PUSH TP,B
+ MCALL 2,INTFCN-1(B) ;APPLY THE FUNCTION TO THE CHAR
+ JRST INTRET
+
+
+\f
+; ROUTINE TO FLUSH OUT A PRINT BUFFER
+
+MFUNCTION BUFOUT,SUBR
+
+ ENTRY 1
+
+ GETYP 0,(AB)
+ CAIE 0,TCHAN
+ JRST WTYP1
+
+ MOVE B,1(AB)
+; MOVEI B,DIRECT-1(B)
+; PUSHJ P,CHRWRD ; GET DIR NAME
+; JFCL
+; CAMN B,[ASCII /PRINT/]
+; JRST .+3
+; CAME B,[<ASCII /PRINT/>+1]
+; JRST WRONGD
+; TRNE B,1 ; SKIP IF PRINT
+; PUSH P,[JFCL]
+; TRNN B,1 ; SKIP IF PRINTB
+; PUSH P,[AOS ACCESS(B)]
+ HRRZ 0,-2(B)
+ TRNN 0,C.PRIN
+ JRST WRONGD
+; TRNE 0,C.BIN ; SKIP IF PRINT
+; PUSH P,[JFCL]
+; TRNN 0,C.BIN ; SKIP IF PRINTB
+; PUSH P,[AOS ACCESS(B)]
+; MOVE B,1(AB)
+; GETYP 0,BUFSTR-1(B)
+; CAIN 0,TCHSTR
+; SKIPN A,BUFSTR(B) ; BYTE POINTER?
+; JRST BFIN1
+; HRRZ C,BUFSTR-1(B) ; CHARS LEFT
+; IDIVI C,5 ; MULTIPLE OF 5?
+; JUMPE D,BFIN2 ; YUP NO EXTRAS
+
+; MOVEI A,40 ; PAD WITH SPACES
+; PUSHJ P,PUTCHR ; OUT IT GOES
+; XCT (P) ; MAYBE BUMP ACCESS
+; SOJG D,.-3 ; FILL
+
+BFIN2: PUSHJ P,BFCLOS ; WRITE OUT BUFFER
+
+BFIN1: MOVSI A,TCHAN
+ JRST FINIS
+
+
+
+; FUNCTION TO GET THE FILE LENGTH OF A READ CHANNEL
+
+MFUNCTION FILLNT,SUBR,[FILE-LENGTH]
+ ENTRY 1
+
+ GETYP 0,(AB)
+ CAIE 0,TCHAN
+ JRST WTYP1
+ MOVE B,1(AB)
+ PUSHJ P,CFILLE
+ JRST FINIS
+
+CFILLE:
+IFN 0,[
+ MOVEI B,DIRECT-1(B) ; GET CHANNEL TYPE
+ PUSHJ P,CHRWRD
+ JFCL
+ CAME B,[ASCIZ /READ/]
+ JRST .+3
+ PUSH P,[5] ; MULTIPLICATIVE FACTOR FOR READ
+ JRST .+4
+ CAME B,[ASCII /READB/]
+ JRST WRONGD
+ PUSH P,[1] ; MULTIPLICATIVE FACTOR FOR READ
+]
+ MOVE C,-2(B) ; GET BITS
+ MOVEI D,5 ; ASSUME ASCII
+ TRNE C,C.BIN ; SKIP IF NOT BINARY
+ MOVEI D,1
+ PUSH P,D
+ MOVE C,B
+IFN ITS,[
+ .CALL FILL1
+ JRST FILLOS ; GIVE HIM A NICE FALSE
+]
+IFE ITS,[
+ MOVE A,CHANNO(C)
+ PUSH P,[0]
+ MOVEI C,(P)
+ MOVE B,[1,,11] ; READ WORD CONTAINING BYTE SIZE
+ GTFDB
+ LDB D,[300600,,(P)] ; GET BYTE SIZE
+ JUMPN D,.+2
+ MOVEI D,36. ; HANDLE "0" BYTE SIZE
+ SUB P,[1,,1]
+ SIZEF
+ JRST FILLOS
+]
+ POP P,C
+IFN ITS, IMUL B,C
+IFE ITS,[
+ CAIN C,5
+ CAIE D,7
+ JRST NOTASC
+]
+YESASC: MOVE A,$TFIX
+ POPJ P,
+
+IFE ITS,[
+NOTASC: MOVEI 0,36.
+ IDIV 0,D ; BYTES PER WORD
+ IDIVM B,0
+ IMUL C,0
+ MOVE B,C
+ JRST YESASC
+]
+
+IFN ITS,[
+FILL1: SETZ ; BLOCK FOR .CALL TO FILLEN
+ SIXBIT /FILLEN/
+ CHANNO (C)
+ SETZM B
+
+FILLOS: MOVE A,CHANNO(C)
+ MOVE B,[.STATUS A] ;MAKE A CALL TO STATUS TO FIND REASON
+ LSH A,23. ;SHIFT THE CHANNEL NUMBER INTO RIGHT PLACE
+ IOR B,A ;FIX UP .STATUS
+ XCT B
+ MOVE B,C
+ PUSHJ P,GFALS
+ POP P,
+ POPJ P,
+]
+IFE ITS,[
+FILLOS: MOVE B,C
+ PUSHJ P,TGFALS
+ POP P,
+ POPJ P,
+]
+
+
+\f; MCHAN LOW-LEVEL I/O GARBAGE (PDL)-ORIGINAL (LIM)-ADDITIONS
+
+;CALLING ROUTINE: AC-A contains pointer to block of SIXBIT data
+; DIR ? DEV ? FNM1 ? FNM2 ? SNM
+;RETURNED VALUE : AC-A = <channel #, or -1 if no channel available>
+IFN ITS,[
+MOPEN: PUSH P,B
+ PUSH P,C
+ MOVE C,FRSTCH ; skip gc and tty channels
+CNLP: DOTCAL STATUS,[C,[2000,,B]]
+ .LOSE %LSFIL
+ ANDI B,77
+ JUMPE B,CHNFND ; found unused channel ?
+ ADDI C,1 ; try another channel
+ CAIG C,17 ; are all the channels used ?
+ JRST CNLP
+ SETO C, ; all channels used so C = -1
+ JRST CHNFUL
+CHNFND: MOVEI B,(C)
+ HLL B,(A) ; M.DIR slot
+ DOTCAL OPEN,[B,1(A),2(A),3(A),4(A)]
+ SKIPA
+ AOS -2(P) ; successful skip when returning
+CHNFUL: MOVE A,C
+ POP P,C
+ POP P,B
+ POPJ P,
+
+MIOT: DOTCAL IOT,[A,B]
+ JFCL
+ POPJ P,
+
+MCLOSE: DOTCAL CLOSE,[A]
+ JFCL
+ POPJ P,
+
+IMPURE
+
+FRSTCH: 1
+
+PURE
+]
+\f;THREE GENERALLY USEFUL ERROR ROUTINES FOR I/O
+
+NOTNET:
+BADCHN: ERRUUO EQUOTE BAD-CHANNEL
+BDCHAN: ERRUUO EQUOTE BAD-INPUT-BUFFER
+
+WRONGD: ERRUUO EQUOTE WRONG-DIRECTION-CHANNEL
+
+CHNCLS: ERRUUO EQUOTE CHANNEL-CLOSED
+
+BAD6: ERRUUO EQUOTE NON-6-BIT-CHARACTER-IN-FILE-NAME
+
+DISLOS: MOVE C,$TCHSTR
+ MOVE D,CHQUOTE [DISPLAY NOT AVAILABLE]
+ PUSHJ P,INCONS
+ MOVSI A,TFALSE
+ JRST OPNRET
+
+NOCHAN: ERRUUO EQUOTE ITS-CHANNELS-EXHAUSTED
+
+MODE1: 232020,,202020
+MODE2: 232023,,330320
+
+END
+
+\f
\ No newline at end of file