perm filename IO2.TNX[TNX,AIL] blob
sn#123326 filedate 1974-10-09 generic text, type T, neo UTF8
COMMENT ⊗ VALID 00092 PAGES
RECORD PAGE DESCRIPTION
00001 00001
00011 00002 TENX<THE ENTIRE FILE IS FOR TENEX ONLY
00016 00003 COMPIL(PAT,<OPEN,LOOKUP,ENTER,USETI,USETO,MTAPE,TENXFI,RELEASE,CLOSE,CLOSIN,CLOSO,GETCHAN,CVJFN,RENAME>
00024 00004 DSCR PROCEDURE LOOKUP(INTEGER CHNL STRING FILE REFERENCE INTEGER FLAG)
00028 00005 HERE(ENTER)
00031 00006 DSCR
00034 00007 DSCR PROCEDURE USETI,USETO(INTEGER CHANNEL,BLOCK)
00036 00008 DSCR PROCEDURE CLOSE(INTEGER CHANNEL)
00037 00009 HERE(RELEASE)
00038 00010 DSCR
00039 00011 DSCR STRING PROCEDURE TENXFI(STRING DECFILE)
00043 00012 DSCR
00045 00013 COMPIL(JOBINF,<ODTIM,IDTIM,RUNTM,GTAD,GJINF>,<ZSETST,ZADJST,X22,X33,X44,.SKIP.,CATCHR>
00046 00014
00047 00015 DSCR INTEGER SIMPLE PROCEDURE RUNTM(INTEGER FORK REFERENCE INTEGER CONSOLE)
00048 00016 DSCR INTEGER SIMPLE PROCEDURE GTAD
00049 00017 DSCR INTEGER SIMPLE PROCEDURE GJINF(REFERENCE INTEGER LOGDIR,CONDIR,TTYNO)
00050 00018 ENDCOM(JOBINF)
00051 00019 COMPIL(DIRECT,<STDIR,DIRST>,<X22,X33,CATCHR,ZSETST,ZADJST.SKIP.>
00053 00020 DSCR STRING SIMPLE PROCEDURE DIRST(INTEGER I)
00054 00021 COMPIL(RUNPRG,<RUNPRG>,<X22,X33,CATCHR>,<RUNPRG -- RUN A PROGRAM>)
00059 00022 COMPIL(OPF,<OPENFILE,SETINPUT,SETPL,INDEXFILE>,<.SKIP.>,<OPENFILE -- OPEN A FILE>)
00067 00023 DSCR PROCEDURE SETINPUT(INTEGER CHAN REFERENCE INTEGER COUNT,BR,EOF)
00068 00024 DSCR
00070 00025 DSCR
00072 00026 COMPIL(GTJFN,<GTJFN,GTJFNL>,<.SKIP.,SETCHN,CATCHR,X11,X22,X44>,<GTJFN -- GET A JFN>)
00074 00027 DSCR INTEGER PROCEDURE GTJFNL(STRING ORIG INTEGER FLAGS, XWDJFN!JFN
00077 00028 COMPIL(FILINF,<GNJFN,DELF,UNDELETE,SIZEF,JFNS,OPENF,CFILE,CLOSF,RLJFN,GTSTS,STSTS,RNAMF>
00079 00029 DSCR PROCEDURE DELF(INTEGER CHAN)
00080 00030 DSCR PROCEDURE UNDELETE(INTEGER CHAN)
00081 00031 DSCR INTEGER PROCEDURE SIZEF(INTEGER JFN)
00082 00032
00083 00033 DSCR SIMPLE PROCEDURE OPENF(INTEGER JFN,FLAGS)
00085 00034
00089 00035 DSCR SIMPLE PROCEDURE CLOSF(INTEGER JFN)
00091 00036 DSCR SIMPLE PROCEDURE RLJFN(INTEGER JFN)
00092 00037 DSCR INTEGER SIMPLE PROCEDURE GTSTS(INTEGER JFN)
00093 00038 DSCR BOOLEAN SIMPLE PROCEDURE STSTS(INTEGER JFN,STATUS)
00094 00039 DSCR BOOLEAN SIMPLE PROCEDURE RNAMF(INTEGER EXISTINGJFN,NEWJFN)
00095 00040 COMPIL(DEVINF,<CNDIR,ASND,RELD,GDSTS,SDSTS,STDEV,DEVST>
00097 00041 DSCR BOOLEAN PROCEDURE ASND(INTEGER DEVICE)
00098 00042 DSCR BOOLEAN PROCEDURE RELD(INTEGER DEVICE)
00099 00043 DSCR INTEGER SIMPLE PROCEDURE GDSTS(INTEGER CHAN REFERENCE INTEGER WORDCNT)
00100 00044 DSCR PROCEDURE SDSTS(INTEGER JFN,NEWSTATUS)
00101 00045 DSCR INTEGER PROCEDURE STDEV(STRING S)
00102 00046
00103 00047
00104 00048 COMPIL(FIO,<OUT,CHAROUT,LINOUT,GTFDB>
00107 00049 DSCR PROCEDURE LINOUT(INTEGER JFN,VALUE)
00109 00050 DSCR STRSND,STRSN0
00114 00051 DSCR SIMPLE PROCEDURE GTFDB(INTEGER JFN REFERENCE INTEGER ARRAY BUF)
00115 00052 COMPIL(BINROU,<WORDIN,WORDOUT,ARRYIN,ARRYOUT,MTOPR,SFPTR,RFPTR,BKJFN,RFBSZ>
00117 00053 DSCR SIMPLE PROCEDURE WORDOUT(INTEGER JFN,BYTE)
00118 00054 DSCR SIMPLE PROCEDURE ARRYIN(INTEGER JFN REFERENCE INTEGER LOC INTEGER COUNT)
00121 00055 DSCR SIMPLE PROCEDURE ARRYOUT(INTEGER JFN REFERENCE INTEGER LOC INTEGER COUNT)
00123 00056 DSCR SIMPLE PROCEDURE MTOPR(INTEGER JFN,FUNCTION,VALUE)
00124 00057 DSCR SIMPLE PROCEDURE SFPTR(INTEGER JFN,POINTER)
00125 00058 DSCR INTEGER SIMPLE PROCEDURE RFPTR(INTEGER JFN)
00126 00059 DSCR SIMPLE PROCEDURE BKJFN(INTEGER JFN)
00127 00060 DSCR INTEGER SIMPLE PROCEDURE RFBSZ(INTEGER JFN)
00128 00061 IMSSS,<
00130 00062 DSCR SIMPLE PROCEDURE
00131 00063 COMPIL(DEVS,<DEVTYPE,DVCHR,ERSTR>
00132 00064 DSCR INTEGER SIMPLE PROCEDURE DVCHR(INTEGER JFN REFERENCE INTEGER AC1,AC3)
00133 00065 DSCR SIMPLE PROCEDURE ERSTR(INTEGER ERRNO,FORK)
00135 00066 COMPIL(UTILITY,<SETCHN,ZSETST,ZADJST,.RESET>
00140 00067 DSCR STRING SIMPLE PROCEDURE ZADJST(INTEGER CNTEST,BP)
00143 00068 DSCR
00147 00069 COMPIL(TTM,<RFMOD,SFMOD,RFCOC,SFCOC>
00149 00070 COMPIL(PAGES,<PMAP>,<SAVE,RESTR,X44>
00150 00071 IMSSS,<
00151 00072 DSCR STRING SIMPLE PROCEDURE INTTY
00153 00073 NOIMSSS<NON-IMSSS VERSION OF INTTY FOR THOSE WHO SUFFER
00157 00074 TTY FUNCTIONS
00160 00075 HERE(PBIN)
00170 00076 Filnam
00173 00077 Flscan
00175 00078 COMPIL(INP,<INPUT,CHARIN,SINI>
00178 00079 DSCR STRING SIMPLE PROCEDURE SINI(INTEGER JFN,MAXLENGTH,BRKCHAR)
00182 00080 Input
00188 00081 BACKUP, DOINP TO BACKUP JFN, DO INPUT.
00199 00082 Realin, Realscan
00201 00083 Intin, Intscan
00203 00084 DSCR NUMIN
00206 00085 NUMIN -- CONTD.
00210 00086 SCAN (CALLED BY NUMIN AND STRIN)
00214 00087 Character table for SCAN (Realscan,Intscan,Realin,Intin)
00216 00088 DSCR DATA TABLES FOR REALIN, INTSCAN, ETC.
00217 00089 COMPIL(CAS,<CSERR,LPRYER>,<GOGTAB>
00218 00090
00219 00091
00220 00092
00221 ENDMK
⊗;
TENX<;THE ENTIRE FILE IS FOR TENEX ONLY
COMMENT ⊗ TENEX-IOSER -- R. SMITH ⊗
LSTON (IOSER)
IFN ALWAYS, <BEGIN IOSER>
COMMENT ⊗ INDICES, BITS FOR TENEX VERSION OF IOSER ⊗
;WORDS IN CDB BLOCK FOR EACH CHANNEL
?GFL←←0 ;FLAGS FOR GTJFN
?OFL←←1 ;FLAGS FOR OPENF
?BRCHAR←←2 ;BRCHAR ADDRESS
?ICOUNT←←3 ;COUNT ADDRESS
?ENDFL←←4 ;EOF ADDRESS
?ICOWNT←←5 ;INPUT COUNT
?IBP←←6 ;INPUT BYTE-POINTER
?OCNT←←7 ;OUTPUT COUNT
?OBP←←10 ;OUTPUT BYTE-POINTER
?DVTYP←←11 ;DEVICE TYPE
?DVDSG←←12 ;DEVICE DESIGNATOR
?OPNDUN←←13 ;TRUE IF OPENED WITH THE OPEN STATEMENT
?DVCH←←14 ;DEVICE CHARACTERISTICS
?DMPED←←15 ;TRUE IF DUMP MODE OUTPUT SEEN
;IN PARTICULAR USED TO NOTE IF A MAGTAPE
;HAS BEEN WRITTEN BUT NOT YET CLOSED,
;SINCE EOF'S ARE WRITTEN AT THE CLOSE
;BY CLOSF,CFILE,CLOSE,ETC.
?LINNUM←←16 ;LINE NO (FOR INPUT FUNCTION)
?PAGNUM←←17 ;PAGE NO (FOR INPUT FUNCTION)
?SOSNUM←←20 ;SOS LINE NO (FOR INPUT FUNCTION)
?DECCLZ←←21 ;TRUE IF DEC-STYLE CLOSE JUST SEEN
?IOTLEN←←22 ;CURRENT LENGTH OF CDB BLOCK
IFNDEF JFNSIZE, <?JFNSIZE←←20> ;NUMBER OF CHANNELS ALLOWED
?DMOCNT←←200 ;(DEFAULT) COUNT FOR DUMP MODE OUTPUT
IFNDEF STARTPAGE,<?STARTPAGE←←610 ;STARTING PAGE FOR BUFFERS>
;BITS FOR SCAN FLAGS FOR OPENFILE ROUTINE
;THE BITS OF THE FLAGS WORD ARE THE SAME AS THE BITS OF GTJFN AND OPENF
;HOPEFULLY (WHERE APPLICABLE)
?STARBIT←←1B11 ;B11 OF GTJFN FOR INDEXED FILES
?TEMBIT←←1B5 ;B5 OF GTJFN FOR TEMPORARY FILE
?DELBIT←←1B8 ;GTJFN -- IGNORE DELETED BIT
?RDBIT←←1B19 ;B19 OF OPENF FOR READING
?WRBIT←←1B20 ;B20 OF OPENF FOR WRITING
?APPBIT←←1B22 ;B22 OF OPENF FOR APPEND
?CONFB1←←1B3 ;GTJFN BIT TO PRINT [CONFIRM] ETC
?CONFB2←←1B4 ;GTJFN BIT TO REQUIRE CONFIRMATION FROM USER
;ODDLY ENOUGH 3 AND 4 ARE ILLEGAL
?OUTBIT←←1B0 ;GTJFN -- FILE FOR OUTPUT USE
?OLDBIT←←1B2 ;GTJFN -- OLD FILE
?NEWBIT←←1B1 ;GTJFN -- NEW FILE
?ERTNBIT←←1B27 ;ERROR RETURN BIT -- INTERNAL
?BINBIT←←1B26 ;BINARY BIT -- INTERNAL
?THAWBIT←←1B25 ;THAWBIT GTJFN
?ERSNBIT←←1B28 ;ERROR SEEN -- INTERNAL
?CONFBIT←←1B29 ;CONFIRMATION -- INTERNAL
;MACROS FOR BIT TESTING
DEFINE .ZZZ $ (X,Y,Z)<
IFN Z&777777000000, <TL$X Y,Z⊗-=18> ;Z LSH -=18
IFN Z&777777, <TR$X Y,Z>
>
DEFINE TESTE (Y,Z) <.ZZZ NE,Y,Z> ;TDNE Y,[Z]
DEFINE TESTN (Y,Z) <.ZZZ NN,Y,Z> ;TDNN Y,[Z]
DEFINE TESTO (Y,Z) <.ZZZ O,Y,Z> ;TDO Y,[Z]
DEFINE TESTZ (Y,W) <.ZZZ Z,Y,W> ;TDZ Y,[Z]
;MACRO TO GET THE JFN NUMBER IN X FROM Y. IF INVALID, JUMP TO LABEL Z
;LOADS CDB (I.E., 11) WITH THE CDB ADDRESS
;LOADS CHNL WITH THE CHANNEL NUMBER
DEFINE VALCHN(X,Y,Z) <
SKIPL CHNL,Y
CAIL CHNL,JFNSIZE
JRST Z
MOVE CDB,CDBTBL(CHNL)
HRRZ X,JFNTBL(CHNL)
JUMPE X,Z
>
;ONLY USES AC X
DEFINE VALCH1(X,Y,Z) <
SKIPL X,Y
CAIL X,JFNSIZE
JRST Z
HRRZ X,JFNTBL(X)
JUMPE X,Z
>
;TTY STUFF
;CHAR FOR LINE DELETION (DELLINE) AND CHARACTER DELETION (RUBCHAR)
IFNDEF DELLINE,<?DELLINE←←"U"-100> ;CTRL-U
IFNDEF RUBCHAR,<?RUBCHAR←←177> ;RUBOUT
?ALTMODE←←175 ;ONE OF MANY VERSIONS OF ALTMODE
COMPIL(PAT,<OPEN,LOOKUP,ENTER,USETI,USETO,MTAPE,TENXFI,RELEASE,CLOSE,CLOSIN,CLOSO,GETCHAN,CVJFN,RENAME>
,<SAVE,RESTR,RELEASE,CORGET,INSET>
,<PAT -- TENEX ROUTINES EMULATING DEC CALLS>)
BEGIN PAT
DSCR PROCEDURE OPEN(INTEGER CHAN; STRING DEV; INTEGER MODE,IBUF,OBUF;
REFERENCE INTEGER COUNT,BR,EOF)
⊗
HERE(OPEN)
BEGIN OPEN
GTFLAGS←←4
OPFLAGS←←5
PUSH P,-7(P)
PUSH P,[0] ;CLOSE INHIBIT
PUSHJ P,RELEASE ;RELEASE IF ALREADY OPEN
;SEE WHAT KIND OF DEVICE WE HAVE
PUSH SP,-1(SP)
PUSH SP,-1(SP)
PUSH P,[0]
PUSHJ P,CATCHR ;PUT ON A NULL CHAR
PUSHJ P,MAKUP ;MAKE UPPER CASE (DAMMIT)
PUSH SP,-3(SP)
PUSH SP,-3(SP)
PUSH SP,[3]
PUSH SP,[POINT 7,[ASCIZ/:
/]]
PUSHJ P,CAT ;PUT ON A STRING
POP SP,-4(SP)
POP SP,-4(SP) ;SAVE ABOVE
PUSHJ P,SAVE ;NOW SAVE ACS
SETZ LPSA, ;NO PARAMETERS TO REMOVE
MOVE CHNL,-7(P) ;USER CHANNEL NUMBER
MOVE 1,(SP) ;STRING FOR DEVICE
SUB SP,X22 ;ADJUST STACK
JSYS STDEV
JRST BADOPN ;NOT A PLAUSIBLE DEVICE
PUSH P,2 ;SAVE DEVICE DESIGNATOR
;ITS A PLAUSIBLE DEVICE
MOVEI C,IOTLEN
PUSHJ P,CORGET
ERR <OPEN: CANNOT GET CORE>
MOVE CDB,B ;IO BLOCK ADDRESS
MOVEM CDB,CDBTBL(CHNL) ;SAVE
;ZERO OUT CORE (SINCE CORGET DOESNT!!!)
HRL B,B
ADDI B,1
SETZM (CDB)
BLT B,IOTLEN-1(CDB)
POP P,1 ;GET DEVICE DESIGNATOR
MOVEM 1,DVDSG(CDB) ;AND SAVE IT
JSYS DVCHR
MOVEM 2,DVCH(CDB) ;SAVE DEVICE CHARACTERISTICS
HLRZ 1,2
ANDI 1,777 ;DEVICE TYPE
MOVEM 1,DVTYP(CDB) ;SAVE IT
TLNN 2,100000 ;IS DEVICE A DIRECTORY DEVICE
JRST GTNOW ;NOPE, DO GTJFN AND OPENF NO
HASDIR:
;GET THE MODE IN 4
MOVE 4,-6(P) ;MODE
ANDI 4,17 ;FORGET OTHER JUNK
;IF DEVICE IS A DECTAPE IN DUMP MODE THEN DO IT NOW ALSO
CAIE 1,3 ;IS IT A DECTAPE?
JRST HASDI1 ;NO
CAIN 4,17 ;IN DUMP MODE?
JRST DOMNT ;YES MOUNT AND THEN OPEN
;SO DONT DO GTJFN NOW, BUT WAIT
HASDI1: SETZM JFNTBL(CHNL) ;BE SURE
MOVEM 4,GFL(CDB) ;SAVE THE MODE AS THE GTJFN FLAGS
HRL 4,-5(P) ;INPUT BUFFERS
HRR 4,-4(P) ;OUTPUT BUFFERS
MOVEM 4,OFL(CDB) ;SAVE AS THE OPENF FLAGS
JRST GUDRET ;AND RETURN
;MOUNT AND OPEN DECTAPE IN DUMP MODE
DOMNT: MOVE A,DVDSG(CDB) ;GET DEVICE DESIGNATOR
TLO A,(1B3) ;DONT READ DIRECTORY FOR DUMP MODE
JSYS MOUNT
JRST BADOPN ;CANNOT MOUNT
MOVSI GTFLAGS,100001
MOVE 1,GTFLAGS
MOVE 2,(SP)
JSYS GTJFN
JRST BADOPN
MOVEM 1,JFNTBL(CHNL)
MOVEM GTFLAGS,GFL(CDB)
MOVE OPFLAGS,[447400000000!RDBIT!WRBIT]
MOVE 2,OPFLAGS
JSYS OPENF
JRST CNTOPN
JRST OPOK
GTNOW:
MOVSI GTFLAGS,100001
MOVE 1,GTFLAGS
MOVE 2,(SP) ;DEVICE STRING
JSYS GTJFN
JRST BADOPN ;NOPE CANNOT GET
MOVEM 1,JFNTBL(CHNL) ;SAVE JFN
MOVEM GTFLAGS,GFL(CDB) ;AND SAVE THEM
;COMPUTE OPENF FLAGS
SETZ OPFLAGS,
MOVE 2,DVCH(CDB) ;DEVICE CHARACTERISTICS
TESTE 2,<1B1> ;CAN DO INPUT?
TESTO OPFLAGS,RDBIT
TESTE 2,<1B0> ;CAN DO OUTPUT?
TESTO OPFLAGS,WRBIT
MOVE 1,DVTYP(CDB) ;CHECK DEVICE TYPE
CAIN 1,12 ;IS IT A TTY?
JRST OP7BT ;USE 7 BIT BYTES
;NOW TRY VARIOUS THINGS, LOOKING FOR SOMETHING THAT WORKS
HRRZ 1,JFNTBL(CHNL)
HRLI OPFLAGS,440000
MOVE 2,OPFLAGS ;36-BIT, MODE 0
JSYS OPENF
SKIPA
JRST OPOK
HRRZ 1,JFNTBL(CHNL)
HRLI OPFLAGS,447400 ;36-BIT, MODE 17
MOVE 2,OPFLAGS
JSYS OPENF
SKIPA
JRST OPOK
OP7BT: HRRZ 1,JFNTBL(CHNL)
HRLI OPFLAGS,70000 ;7-BIT, MODE 0
MOVE 2,OPFLAGS
JSYS OPENF
JRST NOOPN
OPOK: MOVEM OPFLAGS,OFL(CDB) ;SAVE OP FLAGS
GUDRET:
;SAVE FLAGS
SETOM OPNDUN(CDB) ;INDICATE OPENED WITH OPEN
POP P,TEMP ;RETURN ADDRESS
POP P,ENDFL(CDB) ;SAVE GOOD THINGS
POP P,BRCHAR(CDB)
POP P,ICOUNT(CDB)
SETZM @ENDFL(CDB) ;INDICATE GOOD OPENING
SUB SP,X22 ;CLEAN UP STACKS
SUB P,X44
JRST RESTR ;AND RETURN
NOOPN:
CNTOPN: SKIPN 1,JFNTBL(CHNL) ;RELEASE JFN
JSYS RLJFN
JFCL
BADOPN:
SKIPE B,CDBTBL(CHNL) ;CORE ALLOCATED?
PUSHJ P,CORREL ;RELEASE CORE
SETZM JFNTBL(CHNL)
SETZM CDBTBL(CHNL)
SKIPN @-1(P) ;USER WANTS ERROR?
ERR <OPEN: IO ERROR OR ILLEGAL SPECIFICATIONS>,1
SETOM @-1(P)
POP P,TEMP
SUB P,[XWD 7,7]
SUB SP,X22
JRST RESTR
BEND OPEN
;MAKE UPPER CASE LETTERS
MAKUP: PUSHJ P,SAVE
SKIPE SGLIGN(USER)
PUSHJ P,INSET
HRRZ A,-1(SP) ;LENGTH OF STRING
ADDM A,REMCHR(USER)
SKIPLE REMCHR(USER) ;OK?
PUSHJ P,STRNGC ;NO, COLLECT
MOVE B,A
HRRO A,A
PUSH SP,A
PUSH SP,TOPBYTE(USER)
UPPER1: JUMPLE B,UPPER2 ;DONE YET?
ILDB C,-2(SP) ;NEXT CHAR
CAIL C,141
CAILE C,172
SKIPA
SUBI C,40 ;CONVERT TO UPPER CASE
IDPB C,TOPBYTE(USER)
SOJA B,UPPER1
UPPER2: POP SP,-2(SP)
POP SP,-2(SP)
SETZ LPSA,
POP P,TEMP ;RETURN ADDR
JRST RESTR ;RETURN
DSCR PROCEDURE LOOKUP(INTEGER CHNL; STRING FILE; REFERENCE INTEGER FLAG)
⊗
HERE(LOOKUP)
BEGIN LOOKUP
PUSHJ P,TENXFI ;MAKE THE FILE SPEC TENEX
PUSH P,1
PUSH P,2
PUSH P,3
PUSH P,CHNL
PUSH P,CDB
DEFINE CHNARG <-7(P)>
DEFINE FLGARG <-6(P)>
SKIPL CHNL,CHNARG
CAIL CHNL,JFNSIZE
JRST BADLU1
MOVE CDB,CDBTBL(CHNL)
SKIPN OPNDUN(CDB) ;ERROR IF NOT OPENED
JRST BADLU1
MOVE 2,DVCH(CDB) ;GET DEVICE CHARACTERISTICS
TLNN 2,100000 ;DOES DEVICE HAVE A DIRECTORY?
JRST LUKRET ;NO, NO LOOKUP
SKIPE JFNTBL(CHNL) ;JFN ALREADY ASSIGNED?
PUSHJ P,RELNOW ;YES, RELEASE IT
PUSHJ P,DEVCAT
MOVSI 1,100001 ;OLD FILE
MOVE 2,(SP)
JSYS GTJFN
JRST BADLUK
MOVEM 1,JFNTBL(CHNL)
MOVSI 3,100001
MOVEM 3,GFL(CDB)
MOVE 2,[XWD 440000,200000] ;36-BIT
JSYS OPENF
SKIPA
JRST GUDLUK
MOVE 1,JFNTBL(CHNL)
MOVE 2,[XWD 447400,200000] ;36-BIT, DUMP
JSYS OPENF
SKIPA
JRST GUDLUK
MOVE 1,JFNTBL(CHNL)
MOVE 2,[XWD 70000,200000] ;7-BIT
JSYS OPENF
JRST BADLUK
GUDLUK: MOVEM 2,OFL(CDB)
SETZM @FLGARG
LUKRET: POP P,CDB
POP P,CHNL
POP P,3
POP P,2
POP P,1
SUB SP,X22
SUB P,X33
JRST @3(P)
BADLUK: MOVEM 1,@FLGARG
JRST LUKRET
BADLU1: SETOM @FLGARG
JRST LUKRET
BEND LOOKUP
DEVCAT:
;HERE WITH CDB LOADED, FILENAME ON THE SP STACK
;RETURN WITH "DEV:FILE" & 0 ON THE SP STACK
;MUST NOT HAVE CALLED SAVE WHEN THIS IS CALLED
PUSH P,1
PUSH P,2
PUSH P,[=100]
PUSHJ P,ZSETST ;BP IN 1
MOVE 2,DVDSG(CDB) ;DEVICE DESIGNATOR
JSYS DEVST
ERR <LOOKUP, ENTER, OR RENAME: CANNOT DO DEVST>
PUSH P,[=100]
PUSH P,1 ;UPDATED BP
PUSHJ P,ZADJST
PUSH P,[":"]
PUSHJ P,CATCHR
PUSHJ P,CAT.RV
PUSH P,[0]
PUSHJ P,CATCHR
POP P,2
POP P,1
POPJ P,
;RELEASE JFN ALREADY THERE
RELNOW:
PUSH P,CHNL ;CHANNEL
PUSHJ P,CLOSF ;CLOSE DANCE
PUSH P,1
MOVE 1,JFNTBL(CHNL) ;GET JFN
JSYS RLJFN ;RELEASE
ERR <CANNOT RELEASE JFN>,1
SETZM JFNTBL(CHNL) ;AND ZERO OUT
SETZM DECCLZ(CDB) ;NO CLOSE DONE
POP P,1
POPJ P,
HERE(ENTER)
BEGIN ENTER
PUSHJ P,TENXFI
PUSH P,1
PUSH P,2
PUSH P,3
PUSH P,CHNL
PUSH P,CDB
DEFINE CHNARG <-7(P)>
DEFINE FLGARG <-6(P)>
SKIPL CHNL,CHNARG
CAIL CHNL,JFNSIZE
JRST BADEN1
MOVE CDB,CDBTBL(CHNL)
SKIPN OPNDUN(CDB)
JRST BADEN1 ;WAS AN OPEN PERFORMED HERE?
SKIPN 1,JFNTBL(CHNL)
JRST NOTOPN
MOVE 2,DVCH(CDB) ;GET DEVICE CHARACTERISTICS
TLNN 2,100000 ;DOES DEVICE HAVE DIRECTORY?
JRST ENTRET ;NO
SKIPE DECCLZ(CDB) ;A DEC-STYLE CLOSE DONE?
JRST [PUSHJ P,RELNOW ;RELEASE JFN
JRST NOTOPN ;AND PROCEED
]
PUSH P,1 ;SAVE JFN
TLO 1,400000 ;DO NOT RELEASE THE JFN
JSYS CLOSF
JFCL ;IGNORE
POP P,1
MOVE 2,OFL(CDB)
TESTO 2,WRBIT ;TURN ON WRITE BIT
MOVEM 2,OFL(CDB) ;AND SAVE NEW FLAGS
JSYS OPENF
JRST BADENT ;ERROR IN 1
JRST ENTRET ;RETURN
NOTOPN:
PUSHJ P,DEVCAT
MOVSI 1,600001 ;NEW FILE
MOVE 2,(SP)
JSYS GTJFN
JRST BADENT ;CANNOT GTJFN
MOVEM 1,JFNTBL(CHNL)
MOVSI 2,600001 ;THE
MOVEM 2,GFL(CDB) ;SAVE THE GTJFN FLAGS
B36: HRRZ 1,JFNTBL(CHNL)
MOVE 2,[XWD 440000,100000] ;36-BIT
JSYS OPENF
SKIPA
JRST ENT1
HRRZ 1,JFNTBL(CHNL)
MOVE 2,[XWD 447400,100000] ;36-BIT, DUMP
JSYS OPENF
SKIPA
JRST ENT1
HRRZ 1,JFNTBL(CHNL)
MOVE 2,[XWD 70000,100000]
JSYS OPENF
JRST BADENT
ENT1: MOVEM 2,OFL(CDB)
ENTRET: SETZM @FLGARG
ENTPOP: POP P,CDB
POP P,CHNL
POP P,3
POP P,2
POP P,1
SUB SP,X22
SUB P,X33
JRST @3(P)
BADENT: MOVEM 1,@FLGARG
JRST ENTPOP
BADEN1: SETOM @FLGARG
JRST ENTPOP
BEND ENTER
DSCR
RENAME(CHNL,"STR",PROT,@FLAG)
Since protection is not implemented in TENEX,
the feature will be ignored.
⊗
HERE(RENAME)
BEGIN RENAME
PUSH P,1
PUSH P,2
PUSH P,3
PUSH P,CHNL
PUSH P,CDB
DEFINE CHNARG <-10(p)>
DEFINE FLGARG <-6(P)>
VALCHN 1,CHNARG,RENBAD
PUSHJ P,OPNCHK ;MAKE SURE OPEN (SOMEWHAT REDUNDANT)
MOVE 2,DVCH(CDB) ;DEVICE CHARS
TLNN 2,100000 ;DIRECTORY DEVICE?
JRST RENRET ;NO, NOP
PUSHJ P,TENXFI ;MAKE A TENEX FILE NAME
;PERHAPS ONLY A DELETE?
HRRZ 2,-1(SP) ;NULL FILE SPEC?
JUMPE 2,RENDEL ;YES, DELETE
;ACTUALLY RENAME (ON THE SAME DEVICE)
PUSH P,CHNARG
PUSHJ P,CLOSF ;FIRST CLOSE THE FILE
PUSHJ P,DEVCAT
MOVE 3,1 ;SAVE FIRST JFN
MOVE 1,GFL(CDB) ;USE SAME FLAGS
TESTZ 1,OLDBIT ;EXCEPT NOT OLD
TESTO 1,NEWBIT ;BUT DO WANT NEW
TESTO 1,OUTBIT ;AND VERSION DEFAULTING
MOVEM 1,GFL(CDB) ;SAVE FLAGS
MOVE 2,(SP)
JSYS GTJFN
JRST RENERR ;ERROR BITS IN 1
MOVE 2,1 ;NEW JFN
MOVE 1,3 ;OLD JFN
JSYS RNAMF
JRST RENERR ;ERROR BITS IN 1
MOVE 1,2 ;NEW JFN
MOVE 2,OFL(CDB) ;OPENF FLAGS
JSYS OPENF
JRST RENERR ;ERROR BITS IN 1
MOVEM 1,JFNTBL(CHNL) ;SAVE THE NEW JFN
RENRET: SETZM @FLGARG ;INDICATE A GOOD RETURN
RENRE1: POP P,CDB
POP P,CHNL
POP P,3
POP P,2
POP P,1
SUB SP,X22
SUB P,X44
JRST @4(P)
RENERR: MOVEM 1,@FLGARG
JRST RENRE1
RENBAD: SETOM @FLGARG
JRST RENRE1
RENDEL: JSYS DELF ;JFN IN 1
JRST RENERR
JRST RENRET
BEND RENAME
DSCR PROCEDURE USETI,USETO(INTEGER CHANNEL,BLOCK)
⊗
HERE(USETI)
HERE(USETO)
PUSHJ P,SAVE
MOVE LPSA,X33
VALCHN 1,-2(P),USETER
PUSHJ P,OPNCHK ;MAKE SURE OPEN
MOVE 2,DVTYP(CDB)
CAIN 2,3 ;IS IT A DECTAPE?
JRST USEDTA ;YES
DOSFPT: MOVE 2,-1(P)
SUBI 2,1
IMULI 2,200 ;BLOCK NUMBER
JSYS SFPTR
ERR <USETI OR USETO: CANNOT DO SFPTR>,1
JRST RESTR
USEDTA:
;SFPTR DOES NOT SEEM TO WORK TO THE DECTAPE IN TENEX
;;; LDB 2,[POINT 4,OFL(CDB),9] ;MODE
;;; CAIE 2,17 ;DUMP?
;;; JRST DOSFPT ;NO
MOVEI 2,30 ;OPERATION 30 FOR DECTAPES
HRRZ 3,-1(P) ;TAPE BLOCK
JSYS MTOPR ;SET DIRECTLY
JRST RESTR ;AND RETURN
USETER: ERR<Illegal JFN>,1
JRST RESTR ;AND RETURN
DSCR PROCEDURE CLOSE(INTEGER CHANNEL)
PROCEDURE CLOSO(INTEGER CHANNEL)
PROCEDURE CLOSIN(INTEGER CHANNEL)
⊗
BEGIN CLOSES
HERE(CLOSIN)
HERE(CLOSO)
HERE(CLOSE)
DOOPN: PUSH P,-1(P)
PUSHJ P,CLOSF ;FORCE BUFFERS OUT, WRITE MAGT EOFS, CLOSF
PUSHJ P,SAVE
VALCHN 1,-1(P),CLORET
SETOM DECCLZ(CDB) ;INDICATE DEC CLOSE PERFORMED
CLORET: MOVE LPSA,X22
JRST RESTR
BEND CLOSES
HERE(RELEASE)
DSCR
Ignores the close inhibit bits that are available in
the STANFORD SAIL, until we decide what to do with them.
⊗
PUSH P,1
PUSH P,-3(P) ;CHANNEL
PUSHJ P,CFILE
POP P,1 ;RESTORE 1
SUB P,X33
JRST @3(P) ;RETURN
DSCR
PROCEDURE MTAPE(INTEGER CHAN,OPERATION)
(the operation is a character e.g., "U" to unload)
as in the SAIL manual.
⊗
HERE(MTAPE)
BEGIN MTAPE
PUSHJ P,SAVE
MOVE LPSA,X33
LDB C,[POINT 5,-1(P),35]
MOVE A,OPTAB
MOVE B,OPTAB+1
TRZE C,30 ;COMPRESS TABLE
ADDI C,5
LSH C,2
ROTC A,(C)
ANDI B,17
VALCHN 1,-2(P),MTAERR
PUSHJ P,OPNCHK ;MAKE SURE OPEN
JSYS MTOPR
JRST RESTR
MTAERR: ERR <Illegal JFN>,1
JRST RESTR
OPTAB: BYTE (4) 16,17,0,0,3,6,7,13,10 ;A,B,E,F,R,S,T
BYTE (4) 11,0,1 ;U,W
BEND MTAPE
DSCR STRING PROCEDURE TENXFI(STRING DECFILE)
Converts the string to a TENEX file specification.
A la Alex Cannara.
⊗
HERE(TENXFI)
BEGIN TENXFI
CTRLV←←"V"-100
FIND←←2
PUSH P,1
PUSH P,2
PUSH P,3
SETZM FIND
PUSH SP,[0] ;DEVICE TEMPORARY
PUSH SP,[0]
PUSH SP,[0] ;DIR TEMPORARY
PUSH SP,[0]
PUSH SP,[0] ;NAM TEMPORARY
PUSH SP,[0]
DEFINE ORIG <-7(SP)>
DEFINE ORIG1 <-6(SP)>
DEFINE DEV <-5(SP)>
DEFINE DEV1 <-4(SP)>
DEFINE DIR <-3(SP)>
DEFINE DIR1 <-2(SP)>
DEFINE NAM <-1(SP)>
DEFINE NAM1 <0(SP)>
;SIMPLE SINCE NAME IS AT THE TOP OF SP
DEFINE CATNAM (X) <
PUSH P,X
PUSHJ P,CATCHR
>
DEFINE CATDIR (X) <
PUSH P,X
PUSH SP,DIR
PUSH SP,DIR
PUSHJ P,CATCHR
POP SP,-4(SP)
POP SP,-4(SP)
>
DEFINE GCH <
HRRZ 1,ORIG
JUMPE 1,TENDUN
ILDB 3,ORIG1
SOS ORIG
>
TENX1: GCH
CAIE 3,CTRLV
JRST NOQUOTE
SKIPE FIND
JRST QUODIR
PUSHJ P,CATNA3
GCH
PUSHJ P,CATNA3 ;AND THE CHAR FOLLOWING THE CTRLV
JRST TENX1
QUODIR: PUSHJ P,CATDI3
GCH
PUSHJ P,CATDI3
JRST TENX1 ;AND CONTINUE
NOQUOTE:
CAIN 3,":" ;COLON -- DEVICE
JRST ISDEV ;ITS BEEN A DEVICE ALL ALONG!!
CAIN 3,","
JRST TENX1 ;IGNORE COMMA
CAIE 3,40 ;SPACE
CAIN 3,11 ;OR TAB
JRST TENX1
CAIE 3,"<" ;THESE START THE DIRECTORY NAME
CAIN 3,"["
JRST STDIR
CAIE 3,">" ;THESE FINISH THE DIR. NAME
CAIN 3,"]"
JRST ENDDIR
SKIPE FIND ;DOING DIRECTORY?
JRST .+3 ;YES
PUSHJ P,CATNA3
JRST TENX1
PUSHJ P,CATDI3
JRST TENX1
STDIR: SETOM FIND
SKIPE DIR ;ANYTHING THERE?
JRST TENX1 ;YES, IGNORE
CATDIR <[74]>
JRST TENX1
ENDDIR: SETZM FIND
JRST TENX1
ISDEV: PUSHJ P,CATNA3 ;PUT THE COLON ON THE NAME
MOVE 3,NAM ;THE "NAME" HAS REALLY BEEN A DEV
MOVEM 3,DEV
MOVE 3,NAM1
MOVEM 3,DEV1
SETZM NAM ;SO CLEAR THE NAME -- START OVER
SETZM NAM1
JRST TENX1
TENDUN:
;CHECK TO SEE WHAT LAST CHAR OF DIR IS
SKIPN DIR
JRST GOTDIR ;NO DIRECTORY THERE
CATDIR <[76]> ;PUT ON A ">"
;NOW STACK HAS ORIG,DEV,DIR,NAM
GOTDIR:
PUSHJ P,CAT
;NOW STACK HAS ORIG,DEV,<DIR>NAM
PUSHJ P,CAT
;NOW STACK HAS ORIG,DEV:<DIR>NAM
GOTDI1: POP SP,-2(SP)
POP SP,-2(SP)
TXFRET:
POP P,3
POP P,2
POP P,1
POPJ P,
;CALL CAT MACROS WITH AC 3 AS THE ARG
CATNA3: CATNAM 3
POPJ P,
CATDI3: CATDIR 3
POPJ P,
BEND TENXFI
DSCR
INTEGER PROCEDURE GETCHAN(INTEGER I)
RETURNS AN UNUSED CHANNEL NUMBER, AND MARKS IT
FOR USE, SO THAT NO ONE WILL TRY TO USE IT.
⊗
HERE(GETCHAN)
MOVE A,[XWD -JFNSIZE+1,1] ;START AT CHANNEL 1
GETCH1: SKIPN CDBTBL(A) ;ALLOCATED YET?
JRST GETCH2 ;NO, TAKE IT
AOBJN A,GETCH1 ;YES
SETOM A ;INDICATE ERROR
POPJ P,
GETCH2: HRRZ A,A
PUSH P,B ;NOW ALLOCATE A TABLE
PUSH P,C
MOVEI C,IOTLEN
PUSHJ P,CORGET
ERR <GETCHAN: CANNOT GET CORE>
MOVEM B,CDBTBL(A)
HRL C,B ;ZERO OUT BLOCK
HRRI C,1(B)
SETZM (B)
BLT C,IOTLEN-1(B)
SETZM JFNTBL(A) ;BUT NO JFN (YET)
POP P,C
POP P,B
POPJ P,
DSCR
INTEGER PROCEDURE CVJFN(INTEGER CHAN)
Returns the JFN (XWD flags,jfn) associated
with a logical channel, -1 if no jfn assigned.
Hereby, the user of these routines can access
the system directly if the need arises.
⊗
HERE(CVJFN)
SKIPL 1,-1(P)
CAIL 1,JFNSIZE
JRST CVJFER
SKIPN 1,JFNTBL(1)
JRST CVJFER
CVJFR: SUB P,X22
JRST @2(P)
CVJFER: SETO 1,
JRST CVJFR
BEND PAT
ENDCOM(PAT)
COMPIL(JOBINF,<ODTIM,IDTIM,RUNTM,GTAD,GJINF>,<ZSETST,ZADJST,X22,X33,X44,.SKIP.,CATCHR>
,<JOBINF -- JOB UTILITY ROUTINES>)
DSCR STRING SIMPLE PROCEDURE ODTIM(INTEGER DT,FORMAT)
Returns the string representation of DT
(which is in internal TENEX representation). If DT
is -1 the current date and time are used. If format
is -1, the standard format is used.
⊗
HERE(ODTIM)
PUSH P,[=100] ; 100 CHARS
PUSHJ P,ZSETST ;GET BP IN 1
MOVE 2,-2(P) ;TIME
MOVE 3,-1(P) ;FORMAT
JSYS ODTIM
PUSH P,[=100]
PUSH P,1 ;UPDATED BP
PUSHJ P,ZADJST ;GET STRING
SUB P,X33 ;ADJUST STACK
JRST @3(P) ;RETURN
DSCR INTEGER SIMPLE PROCEDURE IDTIM(STRING S)
Returns the internal TENEX representation of S, which
is assumed to be the date and time in some reasonable format.
If the format cannot be scanned, the error is returned in .SKIP.
⊗
HERE(IDTIM)
PUSH P,[0]
PUSHJ P,CATCHR
MOVE 1,(SP) ;BYTE-POINTER
SETZB 2,.SKIP. ;NO SPECIAL FORMAT, ASSUME NO ERROR
JSYS IDTIM
MOVEM 2,.SKIP. ;ERROR TO USER
MOVE 1,2 ;ANSWER
SUB SP,X22 ;ADJUST SP STACK
POPJ P, ;RETURN
DSCR INTEGER SIMPLE PROCEDURE RUNTM(INTEGER FORK; REFERENCE INTEGER CONSOLE);
Returns the runtime of a fork. If FORK=-5, then then
whole job. Time is returned as milliseconds for you. Console time,
similarly converted, is returned in CONSOLE.
⊗
HERE(RUNTM)
MOVE 1,-2(P)
JSYS RUNTM
MOVEM 3,@-1(P)
SUB P,X33
JRST @3(P)
DSCR INTEGER SIMPLE PROCEDURE GTAD;
Returns the current date and time. See Jsys manual,
3-3.
⊗
HERE(GTAD)
JSYS GTAD
POPJ P,
DSCR INTEGER SIMPLE PROCEDURE GJINF(REFERENCE INTEGER LOGDIR,CONDIR,TTYNO);
Returns the TENEX jobnumber. LOGDIR is the directory
no. logged in, CONDIR is the connected directory number. TTYNO is the
TENEX teletype number, which is -1 if the job is detached.
See the DIRST routine for converting directory numbers to
directory strings.
⊗
HERE(GJINF)
JSYS GJINF
MOVEM 1,@-3(P)
MOVEM 2,@-2(P)
MOVEM 4,@-1(P)
MOVE 1,3;
SUB P,X44
JRST @4(P)
ENDCOM(JOBINF)
COMPIL(DIRECT,<STDIR,DIRST>,<X22,X33,CATCHR,ZSETST,ZADJST.SKIP.>
,<DIRECT -- TENEX DIRECTORY SPECS>)
DSCR INTEGER SIMPLE PROCEDURE STDIR(STRING S; BOOLEAN DORECOGNITION)
DESR
Returns the directory number associated with a string.
Any problems are returned in .SKIP. with the code:
1 string does not match
2 string is ambiguous.
⊗
HERE(STDIR)
PUSH P,[0]
PUSHJ P,CATCHR ;TACK ON 0
SETZ 3, ;
MOVEI 1,1 ; ASSUME NO RECOGNITION
SKIPE -1(P) ; DO WE WANT IT?
SETO 1, ; YES AFTER ALL
MOVE 2,(SP) ;BYTE-POINTER
JSYS STDIR
MOVEI 3,1 ; NO MATCH;
MOVEI 3,2 ; AMBIGUOUS
MOVEM 3,.SKIP. ; SAVE IT FOR USER
HRRZ 1,1 ; SAVE DIR NO. (ONLY)
SUB SP,X22 ;ADJUST STRING STACK
SUB P,X22
JRST @2(P) ;RETURN
DSCR STRING SIMPLE PROCEDURE DIRST(INTEGER I)
Returns the string name for directory I. Any problems
cause .SKIP. to be set TRUE.
⊗
HERE(DIRST)
PUSH P,[=100]
PUSHJ P,ZSETST
SETZM .SKIP.
MOVE 2,-1(P) ;DIRECTORY NO.
JSYS DIRST
SETOM .SKIP.
PUSH P,[=100]
PUSH P,1 ;UPDATED BP
PUSHJ P,ZADJST ;GET STRING ON STACK
SUB P,X22
JRST @2(P)
ENDCOM(DIRECT)
COMPIL(RUNPRG,<RUNPRG>,<X22,X33,CATCHR>,<RUNPRG -- RUN A PROGRAM>)
DSCR INTEGER SIMPLE PROCEDURE RUNPRG(STRING PROGRAM; INTEGER INCREM; BOOLEAN NEWFORK)
This does two entirely different things depending on whether
NEWFORK is true or not.
If NEWFORK then a new fork is created, capabilities transmitted,
and PROGRAM is run there. INCREM is added to the entry vector. Any problems
cause the routine to return FALSE, otherwise it returns TRUE.
If not NEWFORK then the current job is destroyed and replaced
with PROGRAM, with INCREM added to the entry vector location. This is
like the DEC RUN uuo, and hence if the increment is 1, the program is
started at the CCL address. If the routine returns at all, there was a problem
with the file.
Remember to say .SAV as the PROGRAM extension.
⊗
HERE(RUNPRG)
BEGIN
JFN←←0
FORK←←14
PUSH P,[0]
PUSHJ P,CATCHR
MOVSI 1,100001 ; OLD FILE, PTR IN 2
MOVE 2,(SP) ; STRING POINTER
JSYS GTJFN ; TRY FOR JFN
JRST RUNERR ; ERROR
MOVEM 1,JFN ; SAVE JFN
SKIPN -1(P) ; USER WANTS FORK?
JRST SWP ; NO, REPLACE CURRENT PRG
MOVSI 1,100000 ; XMIT CAPABILITIES
JSYS CFORK
JRST RUNERR ; CANNOT CREATE FORK
MOVEM 1,FORK ; SAVE HANDLE
SETOB 2,3 ; INDICATE ALL PRIVILEDGES
JSYS EPCAP
HRLZ 1,1 ; FORK HANDLE
HRR 1,JFN ; THE JFN
JSYS GET ; JSYS GET THE FILE
MOVEI 1,400000 ; CURRENT FORK
JSYS GPJFN ;PRIMARY JFNS IN 2
MOVE 1,FORK ; SET PRIMARY IO
JSYS SPJFN ;FOR NEW FORK
MOVE 1,FORK ; FORK
MOVE 2,-2(P) ; USER VALUE FOR ENTRY VECTOR
JSYS SFRKV ;START THE FORK
MOVE 1,FORK ;
JSYS WFORK
SKIPE 1,FORK ; SET TO KILL
JSYS KFORK ;KILL THE FORK
HRRZ 1,JFN ;
JSYS RLJFN ; RELEASE
JFCL ; IGNORE
JRST RUNRET ; AND RETURN SAFELY
SWP:
IMSSS,< ;DESTROY EMULATOR INFO AT IMSSS
SETO 1,
MOVE 2,[XWD 400000,711] ;PAGE 711
JSYS PMAP ;DESTROY
>;IMSSS
PUSH P,JFN ;SAVE THE JFN
HRLI A1 ; BLT INTO ACS
HRRI 1 ;
BLT 15 ; THE INSTRUCTIONS -- NOTE THAT RF IS NOW CLOBBERED
POP P,0 ; RESTORE JFN TO AC0
HRLI 0,400000 ; XWD FORK, JFN
MOVE 16,-2(P) ; THE INCREMENT -- NOTE THAT SP IS NOW CLOBBERED
MOVE 17,[254000400010] ; FOR COMPARISON -- NOTE THAT THE P STACK IS GONE
JRST 4 ; AND GO
A1: -1 ; FOR PMAP
A2: 400000000677 ; THIS FORK, START AT 677 (LEAVING EMULATOR)
A3: 0 ;
A4: JSYS PMAP
A5: SOJL 2,4 ; LOOP THROUGH PAGES
A6: MOVE 1,0 ; XWD 400000,JFN
A7: JSYS GET ;
A10: MOVEI 1,400000 ; THIS FORK
A11: JSYS GEVEC ; JSYS GET ENTRY VECTOR
A12: CAMN 2,17 ; DEC STYLE??
A13: HRRZ 2,120 ; YES
A14: ADD 2,16 ; ADD THE INCREMREMENT
A15: JRST (2) ; AND START THE JOB
RUNERR: TDZA 1,[-1] ;ZERO 1 AND SKIP
RUNRET: SETO 1, ;INDICATE SUCCESS
SUB SP,X22
SUB P,X33
JRST @3(P)
BEND;RUNPRG
ENDCOM(RUNPRG)
COMPIL(OPF,<OPENFILE,SETINPUT,SETPL,INDEXFILE>,<.SKIP.>,<OPENFILE -- OPEN A FILE>)
DSCR INTEGER SIMPLE PROCEDURE OPENFILE(STRING NAME,OPTIONS)
Name is the name of the file to be opened. If it is null, then
OPENFILE goes to the user's console for the filname (with recognition).
The value of the call is the jfn returned to the user.
OPTIONS is a string of options available to the user. Legal
characters are:
One of these:
R read
W write
A append
Version numbering
O old file
N new file
T temporary file
* index with INDEXFILE routine
Independent:
C require confirmation
D ignore deleted bit
H "thawed" access
Error handling
E return errors to user in the external
integer !skip!. TENEX error codes are used.
(JFN will be released in this case.)
OPENFILE does a GTJFN followed by a OPENF. If GTJFN fails, a new
attempt is made, from the user's console.
⊗
BEGIN OPENFILE
JFN←3 ;WHERE TO PUT THINGS
FLAGS←4
GTFLAGS←5
OPFLAGS←6
DEFINE EQ $ (X,Y) <
CAIE A,"$X$"
JRST .+3
TESTO FLAGS,Y
JRST OPCONT
>
DEFINE JTRUE $ (X) <
TESTN FLAGS,X
>
DEFINE JFALSE (X) <
TESTE FLAGS,X
>
DEFINE SGT (X) <
TESTO GTFLAGS,X
>
DEFINE SOF (X) <
TESTO OPFLAGS,X
>
DEFINE TGT (X) <
TESTE FLAGS,X
TESTO GTFLAGS,X
>
DEFINE TOP (X) <
TESTE FLAGS,X
TESTO OPFLAGS,X
>
HERE(OPENFILE)
SETZB FLAGS,.SKIP.
SETZB GTFLAGS,OPFLAGS
HRRZ B,-1(SP) ;COUNT OF OPTIONS WORD
WHIOPT: JUMPE B,OPTDUN
ILDB A,(SP) ;GET AN OPTION
CAIGE A,141
JRST .+3
CAIG A,172
SUBI A,40 ;CONVERT TO UPPER CASE
;ANY NON-ALPHABETIC CHARS GO HERE
EQ *,STARBIT
;NOW ALLOW ONLY ALPHABETIC CHARS
CAIL A,101 ;MUST BE
CAILE A,132
JRST OPTERR
SKIPN BITTBL-"A"(A) ;SOMETHING THERE?
JRST OPTERR ;NOPE, ERROR
TDO FLAGS,BITTBL-"A"(A) ;RIGHT SPOT IN TABLE
SOJGE B,WHIOPT
JRST OPTDUN
;HERE ON ERROR
OPTERR: ERR <OPENFILE: ILLEGAL OPTION >,1
TESTO FLAGS,ERSNBIT
OPCONT:
SOJGE B,WHIOPT
;NOW SET UP GTFLAGS ACCORDING TO THE SCANNED INFORMATION
OPTDUN:
TGT OLDBIT ;INSIST ON OLD?
TGT NEWBIT ;INSIST ON NEW?
JTRUE OLDBIT
JFALSE NEWBIT ;IF NEITHER
JRST OPTDU1 ;WELL, ONE
JTRUE WRBIT ;IF WRITING
JRST OPTDU1
JFALSE RDBIT ;AND READING
JTRUE APPBIT ;BUT NOT APPENDING
SGT OUTBIT ;THEN SET OUTPUT BIT
OPTDU1:
JFALSE RDBIT ;IF READING
JFALSE WRBIT ;AND NOT WRITING
JRST OPTDU2
JTRUE APPBIT ;AND NOT APPENDING
SGT OLDBIT ;THEN INSIST ON OLD
OPTDU2:
;NOW TEST FOR INDEPENDANT THINGS
TESTE FLAGS,APPBIT ;IF APPENDING
TESTO OPFLAGS,WRBIT ;THEN BE SURE WE ARE READING TOO
TOP RDBIT
TOP WRBIT
TOP APPBIT
TGT TEMBIT
TGT STARBIT
TGT DELBIT
TOP THAWBIT
JFALSE CONFBIT
JRST [SGT CONFB1
SGT CONFB2
JRST .+1]
TLO GTFLAGS,1 ;SHORT CALL OF GTJFN
GTAGAIN:
HRRZ A,-3(SP) ;LENGTH OF NAME
JUMPE A,[TRYAGN:
TLO GTFLAGS,2
MOVE 2,[XWD 100,101]
JRST GT]
AND GTFLAGS,[717777777777]
PUSH SP,-3(SP)
PUSH SP,-3(SP)
PUSH P,[0]
PUSHJ P,CATCHR ;CONCATENATE A NULL CHAR
MOVE 2,(SP) ;BYTE-POINTER
SUB SP,X22 ;ADJUST STACK
GT: MOVE 1,GTFLAGS
JSYS GTJFN
JRST GTERR
MOVEM 1,JFN ;REMEMBER JFN
PUSHJ P,SETCHN ;SET A CHANNEL, ALLOCATE, GET CDB, SET DVTYP, RETURN CHANNEL
MOVEM 1,CHNL ;REMEMBER CHANNEL
MOVEM GTFLAGS,GFL(CDB)
COMMENT ⊗ Do the open.
⊗
MOVE 1,DVTYP(CDB) ;CHECK THE DEVICE TYPE
CAIN 1,12 ;IS IT A TTY?
JRST B7 ;YES, USE 7 BIT
B36: HRRZ 1,JFN ;JFN
HRRZ 2,OPFLAGS
HRLI 2,440000 ;36-BIT, MODE 0
JSYS OPENF
JRST B36DMP ;TRY 36-BIT, DUMP MODE
JRST OPNOK
B36DMP: HRRZ 1,JFN
HRRZ 2,OPFLAGS
HRLI 2,447400 ;36 BITS, DUMP MODE
JSYS OPENF
JRST B7
JRST OPNOK
B7: HRRZ 1,JFN
HRRZ 2,OPFLAGS
HRLI 2,70000 ;7 BIT
JSYS OPENF
JRST OPERR ;NOPE
OPNOK: MOVEM 2,OFL(CDB) ;SAVE
MOVE 1,CHNL ;RETURN CHANNEL NO
OPFRET: SUB SP,X44 ;ADJUST
POPJ P, ;AND RETURN
GTERR:
;HERE WITH ERROR ON GTJFN
JTRUE ERTNBIT ;USER WANT'S ERRORS?
JRST GTER1 ;NO
ERRRET: MOVEM 1,.SKIP. ;STORE FOR USER
SETO 1, ;SOMETHING SUSPICIOUS
JRST OPFRET ;AND RETURN
GTER1: PUSHJ P,SERSTR ;SHOW ERSTR
HRROI 1,[ASCIZ/
Cannot GTJFN file /]
JSYS PSOUT
PUSH SP,-3(SP)
PUSH SP,-3(SP)
PUSHJ P,OUTSTR
HRROI 1,[ASCIZ/, try again */]
JSYS PSOUT
JRST TRYAGN
OPERR: JTRUE ERTNBIT
JRST OPER1
PUSH P,1 ;SAVE ERROR BITS
PUSH P,CHNL
PUSHJ P,CFILE
POP P,1 ;RESTORE ERROR BITS
JRST ERRRET
OPER1: PUSHJ P,SERSTR ;SHOW ERSTR
HRROI 1,[ASCIZ/
Cannot OPENF file /]
JSYS PSOUT
PUSH SP,-3(SP)
PUSH SP,-3(SP)
PUSHJ P,OUTSTR
HRROI 1,[ASCIZ/, try again */]
JSYS PSOUT
PUSH P,CHNL ;CLOSE AND RELEASE FILE AND CDB BLOCK
PUSHJ P,CFILE
JRST TRYAGN
;HERE WITH THE TENEX ERROR CODE IN 1 -- 1 MAY BE CLOBBERED
SERSTR:
HRROI 1,[ASCIZ/
/]
JSYS PSOUT
PUSH P,2 ;SAVE ACS
PUSH P,3
HRRZ 2,1
HRLI 2,400000 ;THIS FORK
MOVEI 1,101 ;PRIMARY OUTPUT
SETZ 3, ;FLAGS
JSYS ERSTR
JFCL
JFCL
POP P,3
POP P,2
POPJ P,
BITTBL: APPBIT ;A
BINBIT ;B
CONFBIT ;C
DELBIT ;D
ERTNBIT ;E
0 ;F
0 ;G
THAWBIT ;H
0 ;I
0 ;J
0 ;K
0 ;L
0 ;M
NEWBIT ;N
OLDBIT ;O
0 ;P
0 ;Q
RDBIT ;R
0 ;S
TEMBIT ;T
0 ;U
0 ;V
WRBIT ;W
0 ;X
0 ;Y
0 ;Z
BEND OPENFILE
DSCR PROCEDURE SETINPUT(INTEGER CHAN; REFERENCE INTEGER COUNT,BR,EOF)
Sets up the variables associated with input (as in the DEC
open statement.)
⊗
HERE(SETINPUT)
PUSHJ P,SAVE
VALCHN 1,-4(P),SETERR
POP P,TEMP
POP P,ENDFL(CDB)
SKIPE ENDFL(CDB)
SETZM @ENDFL(CDB) ;ASSUME NOT EOF
POP P,BRCHAR(CDB)
SKIPE BRCHAR(CDB)
SETZM @BRCHAR(CDB) ;ASSUME NO BRCHAR
POP P,ICOUNT(CDB)
SETZ LPSA, ;NO PARAMETERS
SUB P,X11
JRST RESTR
SETERR: ERR <Illegal JFN>,1
MOVE LPSA,[XWD 5,5]
JRST RESTR
DSCR
SETPL(CHAN,@LINNUM,@PAGNUM,@SOSNUM)
Names the variables to be used by the INPUT
function for counting the line-feeds (12), formfeeds (14)
seen by INPUT, as well as keeping the current SOS line
number, if any. Useful when scanning a file, and
you want to know what page,line you are on.
Initializes all three variables to 0.
⊗
HERE(SETPL)
PUSHJ P,SAVE
VALCHN 1,-4(P),SETPER
POP P,TEMP ;RET ADR
POP P,SOSNUM(CDB)
SETZM @SOSNUM(CDB)
POP P,PAGNUM(CDB)
SETZM @PAGNUM(CDB)
POP P,LINNUM(CDB)
SETZM @LINNUM(CDB)
SUB P,X11 ;REMOVE CHANNEL NO.
SETRET: SETZ LPSA,
JRST RESTR
SETPER: ERR <Illegal JFN>,1
MOVE LPSA,[XWD 5,5]
JRST RESTR
DSCR
BOOLEAN PROCEDURE INDEXFILE(INTEGER JFN)
RETURNS TRUE AS LONG AS WE CAN GNJFN ANOTHER FILE
⊗
HERE(INDEXFILE)
PUSH P,-1(P)
PUSHJ P,CLOSF
PUSH P,-1(P)
PUSHJ P,GNJFN
JUMPE 1,INDRET ;RETURN FALSE IF NO OTHER FILES
PUSH P,2
PUSH P,CDB
PUSH P,CHNL
;CHANNEL ALREADY VALID
MOVE CHNL,-4(P) ;CHANNEL NUMBER
MOVE CDB,CDBTBL(CHNL) ;CDB LOC
HRRZ 1,JFNTBL(CHNL) ;JFN
MOVE 2,OFL(CDB) ;GET OPENFLAGS
JSYS OPENF ;TRY OPENING
JRST NOIND
SKIPE ENDFL(CDB) ;ZERO SETINPUT (or OPEN) VARIABLES IF HERE
SETZM @ENDFL(CDB)
SKIPE BRCHAR(CDB)
SETZM @BRCHAR(CDB)
SKIPE LINNUM(CDB) ;ZERO SETPL VARS
SETZM @LINNUM(CDB)
SKIPE PAGNUM(CDB)
SETZM @PAGNUM(CDB)
SKIPE SOSNUM(CDB)
SETZM @SOSNUM(CDB)
SETO 1,
INDPOP: POP P,CHNL
POP P,CDB
POP P,2
INDRET: SUB P,X22
JRST @2(P)
NOIND: ERR <INDEXFILE: CANNOT OPENF>,1
SETZ 1,
JRST INDPOP
ENDCOM(OPF)
COMPIL(GTJFN,<GTJFN,GTJFNL>,<.SKIP.,SETCHN,CATCHR,X11,X22,X44>,<GTJFN -- GET A JFN>)
DSCR INTEGER SIMPLE PROCEDURE GTJFN(STRING S; INTEGER FLAGS)
Does a GTJFN. If S is non-null, it is the filename, otherwise
the routine goes to the user's console for a file. FLAGS are used for
accumulator 1, and any error code is returned in .SKIP. The value
of the call is the JFN, if obtained.
Defaults for FLAGS: 0 means ordinary input, 1 means ordinary
output. Ordinarily the user will use the OPENFI routine.
⊗
HERE(GTJFN)
SKIPN 1,-1(P)
MOVSI 1,100001
CAIN 1,1
MOVSI 1,600001
TLO 1,1 ;MARK FOR SHORT CALL
HRRZ 2,-1(SP)
JUMPE 2,[MOVE 2,[100000101]
TLO 1,2 ;INDICATE XWD JFN,JFN IN 2
JRST GOTDEST]
TLZ 1,2 ;INDICATE BYTE-POINTER IN 2
PUSH P,[0]
PUSHJ P,CATCHR ;PUT ON A NULL
MOVE 2,(SP)
GOTDEST: SETZM .SKIP. ;ASSUME NO ERROR
PUSH P,1 ;SAVE FLAGS
JSYS GTJFN
JRST GTBAD ; SOMETHING IS WRONG
PUSHJ P,SETCHN ;SETUP A CHANNEL, AND ALLOCATE, GET STATUS, SET CDB
POP P,GFL(CDB) ;SAVE FLAGS
GTRET: SUB SP,X22
SUB P,X22
JRST @2(P)
GTBAD:
MOVEM 1,.SKIP. ; REMEMBER
POP P,1 ;ADJUST STACK
SETO 1, ; SOMETHING SUSPICIOUS TO RETURN TO USER
JRST GTRET
DSCR INTEGER PROCEDURE GTJFNL(STRING ORIG; INTEGER FLAGS, XWDJFN!JFN;
STRING DEV,DIR,NAM,EXT,PROT,ACCOUNT; INTEGER DESIRED!JFN)
Does the long form of GTJFN.
⊗
HERE(GTJFNL)
BEGIN GTJFNL
DEFINE STRPUT(X)<
PUSHJ P,.STPUT
MOVEM A,X
>
DEFINE FLG <-14(P)>
DEFINE IOJFN <-13(P)>
DEFINE DESJFN <-12(P)>
ADD P,[XWD 11,11] ;ROOM FOR LONG-FORM TABLE
TLNN P,400000 ;OVERFLOW?
ERR <GTJFNL: P-stack overflow>
MOVE A,DESJFN
MOVEM A,0(P) ;THE DESIRED JFN
STRPUT -1(P) ;ACCOUNT
STRPUT -2(P) ;PROTECTION
STRPUT -3(P) ;EXTENSION
STRPUT -4(P) ;NAME
STRPUT -5(P) ;DIRECTORY
STRPUT -6(P) ;DEVICE
MOVE A,IOJFN ;XWD INPUT JFN, OUTPUT JFN
MOVEM A,-7(P)
MOVE A,FLG
MOVEM A,-10(P)
STRPUT B ;MAIN STRING POINTER
MOVEI A,-10(P) ;ADDRESS OF BLOCK (ON STACK)
SETZM .SKIP. ;ASSUME NO ERROR
JSYS GTJFN ;LONG FORM
JRST GTLBAD ;NOPE
PUSHJ P,SETCHN ;SET UP CHANNEL TABLE, ALLOCATE, GET STATUS, SET CDB
MOVE B,-10(P) ;GTJFN FLAGS
MOVEM B,GFL(CDB) ;SAVE
GTLRET: SUB P,[XWD 11+4,11+4] ;ADJUST STACK FOR LONG-FORM TABLE, AND ARGUMENTS
JRST @4(P) ;AND RETURN
GTLBAD: MOVEM A,.SKIP. ;RETURN ERROR CODE TO USER
SETO A, ;SOMETHING SUSPICIOUS
JRST GTLRET ;AND RETURN
.STPUT: HRRZ A,-1(SP) ;GET THE COUNT
JUMPE A,[SUB SP,X22 ;ADJUST AND RETURN
POPJ P,]
PUSH P,[0]
PUSHJ P,CATCHR
POP SP,A
SUB SP,X11
POPJ P,
BEND GTJFNL
ENDCOM(GTJFN)
COMPIL(FILINF,<GNJFN,DELF,UNDELETE,SIZEF,JFNS,OPENF,CFILE,CLOSF,RLJFN,GTSTS,STSTS,RNAMF>
,<JFNTBL,CDBTBL,STRSND,X11,X22,X33,CORREL,.SKIP.,ZSETST,ZADJST>
,<FILINF -- UTILITY FILE ROUTINES>)
DSCR INTEGER SIMPLE PROCEDURE GNJFN(INTEGER JFN)
Does the GNJFN jsys.
⊗
HERE(GNJFN)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,<-1(P)>,GNERR
MOVE 1,JFNTBL(CHNL) ;GET THE WHOLE JFN
SETO 2,; ;ASSUME GOOD
JSYS GNJFN
SETZ 2, ;NOPE, BAD
MOVEM 2,RACS+A(USER)
JUMPE 2,GNRLZ ;RELEASE IF NO OTHER FILE
GNRET: JRST RESTR
GNERR: ERR <Illegal JFN>,1
SETZM RACS+A(USER)
JRST RESTR
GNRLZ: PUSH P,-1(P)
PUSHJ P,CFILE
JRST RESTR
DSCR PROCEDURE DELF(INTEGER CHAN)
Deletes file open on CHAN. Errors to .SKIP.
⊗
HERE(DELF)
PUSH P,1
VALCH1 1,-2(P),DELF1
JSYS DELF
JRST DELF2
SETZM .SKIP. ;NO ERROR
DELFRE: POP P,1
SUB P,X22
JRST @2(P)
DELF1: SETO 1,
DELF2: MOVEM 1,.SKIP.
JRST DELFRE
DSCR PROCEDURE UNDELETE(INTEGER CHAN)
Undeletes file open on CHAN. Errors to .SKIP.
⊗
HERE(UNDELETE)
PUSHJ P,SAVE
VALCH1 1,-1(P),UNDEL1
HRLI 1,1 ;XWD 1,JFN
MOVSI 2,(1B3) ;DELETED BIT
SETZ 3, ;TURN IT OFF
JSYS CHFDB ;CHANGE THE FDB
JRST RESTR
UNDEL1: SETOM .SKIP.
JRST RESTR
DSCR INTEGER PROCEDURE SIZEF(INTEGER JFN)
Gets the size in pages of the file open on JFN, with error code to
.SKIP.
⊗
HERE(SIZEF)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,<-1(P)>,SIZERR
SETZM .SKIP.
JSYS SIZEF
JRST [MOVEM 1,.SKIP.
SETZM RACS+A(USER)
JRST SIZRET]
MOVEM 3,RACS+A(USER) ;ANSWER IN AC 3
SIZRET: JRST RESTR
SIZERR: ERR <Illegal JFN>
SETOM .SKIP.
JRST SIZRET
DSCR STRING SIMPLE PROCEDURE JFNS(INTEGER JFN,FLAGS)
Returns the name of the file associated with JFN.
FLAGS are for ac 3 as described in the jsys manual, with
0 the reasonable default.
⊗
HERE(JFNS)
VALCHN 2,<-2(P)>,JFNSER ;GET JFN IN AC2
PUSH P,[=400]
PUSHJ P,ZSETST ;GET BP IN AC 1
MOVE 3,-1(P)
JSYS JFNS
PUSH P,[=400]
PUSH P,1
PUSHJ P,ZADJST
JFNSRE: SUB P,X33
JRST @3(P)
JFNSER: ERR <Illegal JFN>,1
PUSH SP,[0] ;RETURN NULL STRING
PUSH SP,[0]
JRST JFNSRE
DSCR SIMPLE PROCEDURE OPENF(INTEGER JFN,FLAGS)
Does an OPENF.
PARAMETERS:
JFN the JFN
FLAGS for accumulator 2.
.SKIP. the error code (if pertinent)
Some defaults:
FLAGS ACTION
-----------------------
0 INPUT CHARACTERS
1 OUTPUT CHARACTERS
2 INPUT 36-BIT WORDS
3 OUTPUT 36-BIT WORDS
4 DUMP MODE INPUT (USE DUMPI FUNCTION)
5 DUMP MODE OUTPUT (USE DUMPO FUNCTION)
VALUES 6-10 ARE RESERVED FOR EXPANSION
Other values of FLAGS are interpreted literally.
Ordinarily the user will use the OPENFI routine.
⊗
HERE(OPENF)
PUSHJ P,SAVE
MOVE LPSA,X33
VALCHN 1,-2(P),OPNERR
SKIPL 2,-1(P) ;GET THE FLAGS
CAILE 2,5 ;CHECK IN RANGE 0-5
JRST GOTFLAGS
MOVE 2,OPNTBL(2) ;GET CORRECT WORD
GOTFLAGS:
SETZM .SKIP.
PUSH P,2 ;SAVE FLAGS
JSYS OPENF
JRST NOOPN
POP P,OFL(CDB) ;AND SAVE FLAGS
OPNRET: JRST RESTR
OPNERR: ERR <Illegal JFN>,1
SETOM .SKIP.
JRST OPNRET
NOOPN: MOVEM 1,.SKIP.
SUB P,X11 ;ADJUST STACK
JRST OPNRET
OPNTBL: 070000200000 ;7-BIT READ
070000100000 ;7-BIT WRITE
440000200000 ;36-BIT READ
440000100000 ;36-BIT WRITE
447400200000 ;36-BIT DUMP READ
447400100000 ;36-BIT DUMP WRITE
DSCR SIMPLE INTEGER PROCEDURE CFILE(INTEGER JFN)
Closes the file (CLOSF) and releases (RLFJN)
the jfn. This is the ordinary way the user will use
to dispense with a file.
Returns TRUE if JFN legal and released, FALSE o.w.
Always returns.
⊗
HERE(CFILE)
PUSH P,2
PUSH P,3
PUSH P,CHNL
PUSH P,CDB
SKIPL CHNL,-5(P)
CAIL CHNL,JFNSIZE
JRST CFBAD
MOVE CDB,CDBTBL(CHNL) ;GET CDB
SKIPN 1,JFNTBL(CHNL) ;JFN ASSIGNED?
JRST CFBA1 ;NO, JUST RELEASE CORE
HRRZ 1,1 ;JFN ONLY
LDB 2,[POINT 6,OFL(CDB),5] ;GET BYTE SIZE
CAIE 2,=36 ;36-BIT?
JRST RLCOR ;NO
;FILE IN 36-BIT BYTES
SKIPE OBP(CDB) ; A BYTE-POINTER?
PUSHJ P,STRSND ;SEND OUT THE BUFFER
PUSHJ P,CUNMAP ;UNMAP THE PAGE
SKIPN DMPED(CDB) ;DUMP-MODE OUTPUT SEEN?
JRST RLCOR ;NO
PUSHJ P,MTCHK ;CHECK FOR MAGTAPE OUTPUT
SETZM DMPED(CDB) ;AND INDICATE ALL DONE
RLCOR: SKIPE B,CDBTBL(CHNL) ; ANY CORE TO RELEASE?
PUSHJ P,CORREL ; RELEASE THE BLOCK
TLZ 1,400000 ; BE SURE TO RELEASE
JSYS CLOSF ; CLOSE (AND RELEASE)
JFCL ; ERROR RETURN
HRRZ 1,JFNTBL(CHNL) ; GET JFN AGAIN
JSYS RLJFN ; RELEASE (FOR GOOD MEASURE IF FILE NOT OPEN)
JFCL ; ERROR RETURN
SETO 1, ; RETURN TRUE FOR GOOD RELEASE
SETZM CDBTBL(CHNL)
SETZM JFNTBL(CHNL)
CFRET: POP P,CDB
POP P,CHNL
POP P,3
POP P,2
SUB P,X22 ; ADJUST
JRST @2(P) ; RETURN
CFBAD: SETZ 1, ; RETURN FALSE
JRST CFRET ;
CFBA1: SKIPE B,CDB
PUSHJ P,CORREL ;RELEASE CORE BLOCK
SETZM CDBTBL(CHNL) ;REMOVE ALL TRACE
SETZM JFNTBL(CHNL)
SETZ 1, ; RETURN FALSE
JRST CFRET
;HERE WITH 1,CHNL,CDB LOADED
;IF DEVICE IS MAGTAPE, THEN WRITE TWO EOF'S AND BACKSPACE
MTCHK:
PUSH P,2 ;SAVE 2
MOVE 2,DVTYP(CDB) ;GET DEVICE TYPE
CAIE 2,2 ;IS IT A MAGTAPE?
JRST MTRET ;NO
MOVEI 2,3 ;WRITE EOF
JSYS MTOPR
JSYS MTOPR
MOVEI 2,17 ;NOW BACKSPACE
JSYS MTOPR
MTRET: POP P,2 ;RESTORE
POPJ P,
;HERE WITH 1,CHNL,CDB LOADED
;UNMAP PAGE ASSOCIATED WITH JFN
;CLOBBERS 2,3
CUNMAP:
PUSH P,1 ;SAVE JFN
MOVEI 2,STARTPAGE(1)
HRLI 2,400000 ;XWD THIS FORK, PAGE NO.
SETO 1,
SETZ 3,
JSYS PMAP
POP P,1 ;GET JFN BACK
POPJ P,
DSCR SIMPLE PROCEDURE CLOSF(INTEGER JFN)
Does a CLOSF on the JFN. Ordinarily the user
will want to use the CFILE routine, which handles errors
internally. The CLOSF is accomplished in such a way that
the JFN is actually not released.
If the device is a magtape open for output, then
2 eof's are written, followed by a backspace. This writes
a standard end-of-file on the tape.
⊗
HERE(CLOSF)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,<-1(P)>,CLOERR
LDB 2,[POINT 6,OFL(CDB),5] ;BYTE-SIZE
CAIE 2,=36 ;36-BIT BYTES?
JRST DOCLO
;RELEASE BUFFER IN CORE (IF THERE IS ONE)
SKIPE OBP(CDB) ;A BYTE POINTER?
PUSHJ P,STRSND ;CLEAN UP BUFFER IN CORE
PUSHJ P,CUNMAP ;UNMAP THE PAGE
SKIPE DMPED(CDB) ;DUMP-MODE IO SEEN?
PUSHJ P,MTCHK ;CHECK IF MAGT-TAPE (AND MARK EOF,EOF)
SETZM DMPED(CDB) ;AND INDICATE ALL DONE
SETZM ICOWNT(CDB)
SETZM IBP(CDB)
SETZM OCNT(CDB)
SETZM OBP(CDB)
SETZM DECCLZ(CDB)
DOCLO: SETZM .SKIP. ;ASSUME NO ERROR
TLO 1,400000 ; DO NOT RELEASE THE JFN
JSYS CLOSF
MOVEM 1,.SKIP. ;ERROR
CLORET: JRST RESTR
CLOERR:
SETOM .SKIP.
JRST CLORET
DSCR SIMPLE PROCEDURE RLJFN(INTEGER JFN)
Does the RLJFN jsys. Ordinarily the user will want
to use the CFILE routine, which handles errors internally.
⊗
HERE(RLJFN)
PUSHJ P,SAVE
MOVE LPSA,X22
SKIPL C,-1(P)
CAIL C,JFNSIZE
JRST RLJBAD
SKIPN 1,JFNTBL(C)
JRST RLJBAD
SETZM JFNTBL(C)
SKIPE B,CDBTBL(C)
PUSHJ P,CORREL
SETZM CDBTBL(C)
SETZM .SKIP. ;ASSUME NO ERROR
JSYS RLJFN
MOVEM 1,.SKIP. ;ERROR RETURN
RLJRET: JRST RESTR
RLJBAD: ERR <Illegal JFN>,1
SETOM .SKIP.
JRST RLJRET
DSCR INTEGER SIMPLE PROCEDURE GTSTS(INTEGER JFN);
Gets the file status.
WARNING: The results of this call are not necessarily appropriate
if the file is open in special character input mode. If you want to check
for end-of-file, examine the EOF variable instead.
⊗
HERE(GTSTS)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,<-1(P)>,GTSERR
JSYS GTSTS
MOVEM 2,RACS+A(USER)
GTSRET: JRST RESTR
GTSERR: ERR <Illegal JFN>,1
JRST GTSRET
DSCR BOOLEAN SIMPLE PROCEDURE STSTS(INTEGER JFN,STATUS);
Sets the status of JFN to STATUS using the STSTS jsys.
⊗
HERE(STSTS)
VALCH1 1,<-2(P)>,STSERR
MOVE 2,-1(P)
SETO 3, ;ASSUME SKIP
SETZM .SKIP.
JSYS STSTS
JRST [STERRT: SETZ 3, ;PROBLEM
MOVEM 1,.SKIP.
JRST .+1]
MOVE 1,3 ;RETURN
SUB P,X33
JRST @3(P)
STSERR: ERR <Illegal JFN>,1
JRST STERRT ;RETURN
DSCR BOOLEAN SIMPLE PROCEDURE RNAMF(INTEGER EXISTINGJFN,NEWJFN);
File open on EXISTINGJFN is renamed to file open
on NEWJFN.
⊗
HERE(RNAMF)
VALCH1 1,<-2(P)>,RNFERR
VALCH1 2,<-1(P)>,RNFERR
SETO 3, ;ASSUME OK
SETZM .SKIP.
JSYS RNAMF
JRST [RNERET: SETZ 3,
MOVEM 1,.SKIP.
JRST .+1]
RNFRET: MOVE 1,3 ;RETURN VALUE
SUB P,X33
JRST @3(P)
RNFERR: ERR <Illegal JFN>,1
JRST RNERET
ENDCOM(FILINF)
COMPIL(DEVINF,<CNDIR,ASND,RELD,GDSTS,SDSTS,STDEV,DEVST>
,<JFNTBL,CDBTBL,STRSND,X11,X22,X33,CORREL,.SKIP.,ZSETST,ZADJST>
,<DEVINF -- DEVICE AND DIRECTORY ROUTINES>)
DSCR BOOLEAN SIMPLE PROCEDURE CNDIR(INTEGER DIR; STRING PASSWORD);
Using the CNDIR jsys, connects to TENEX directory DIR (for
AC1.) PASSWORD is the password, which will usually be null, as
in the EXEC CONNECT command.
⊗
HERE(CNDIR)
PUSH P,[0]
PUSHJ P,CATCHR ;PUT A NULL ON THE END OF THE PASSWORD
POP SP,2 ;GET BP IN 2
SUB SP,X11 ;CLEAN UP SP STACK
MOVE 1,-1(P) ;DIRECTORY NO
SETO 3, ;ASSUME SUCCESS
SETZM .SKIP.
JSYS CNDIR
JRST [SETZ 3,
MOVEM 1,.SKIP.
JRST .+1]
MOVE 1,3
SUB P,X22
JRST @2(P)
DSCR BOOLEAN PROCEDURE ASND(INTEGER DEVICE)
Assigns the device specified by DEVICE using the ASND jsys.
Returns TRUE if successful, else error code in .SKIP.
⊗
HERE(ASND)
MOVE 1,-1(P) ;GET DEVICE DESIGNATOR
JSYS ASND
JRST [MOVEM 1,.SKIP.
SETZ 1,
JRST .+2]
SETO 1,
SUB P,X22
JRST @2(P)
DSCR BOOLEAN PROCEDURE RELD(INTEGER DEVICE)
Releases DEVICE using the RELD jsys. If DEVICE is -1,
then releases all devices assigned to this job.
⊗
HERE(RELD)
MOVE 1,-1(P)
JSYS RELD
JRST [MOVEM 1,.SKIP.
SETZ 1,
JRST .+2]
SETO 1,
SUB P,X22
JRST @2(P)
DSCR INTEGER SIMPLE PROCEDURE GDSTS(INTEGER CHAN; REFERENCE INTEGER WORDCNT)
Returns the device status of device open on CHAN using the GDSTS
jsys. The LH of WORDCNT has the word count of the last transfer completed,
negative if the last transfer completed unsuccessful.
⊗
HERE(GDSTS)
VALCH1 1,<-2(P)>,GDSERR
SETZM .SKIP.
JSYS GDSTS
MOVEM 3,@-1(P) ;REFERENCE ARG
MOVE 1,2 ;RETURN VALUE
GDSRET: SUB P,X33
JRST @3(P)
GDSERR: ERR <Illegal JFN>,1
SETOM .SKIP.
SETZ 1,
JRST GDSRET
DSCR PROCEDURE SDSTS(INTEGER JFN,NEWSTATUS)
⊗
HERE(SDSTS)
VALCH1 1,<-2(P)>,SDSERR
SETZM .SKIP. ;INDICATE NO ERROR
MOVE 2,-1(P)
JSYS SDSTS
SDSRET: SUB P,X33
JRST @3(P)
SDSERR: ERR <Illegal JFN>,1
SETOM .SKIP.
JRST SDSRET
DSCR INTEGER PROCEDURE STDEV(STRING S)
S is a string pointer to a string of the form DTA1.
The device designator is returned.
⊗
HERE(STDEV)
PUSH P,[0]
PUSHJ P,CATCHR
POP SP,1
SUB SP,X11 ;CLEAN SP STACK
SETZM .SKIP.
JSYS STDEV
JRST [MOVEM 2,.SKIP.
SETZ 1,
JRST .+2]
MOVE 1,2
POPJ P,
DSCR STRING PROCEDURE DEVST(INTEGER DEVICE)
⊗
HERE(DEVST)
PUSH P,[=100]
PUSHJ P,ZSETST ;GET A BP FOR 100 CHARS
SETZM .SKIP.
MOVE 2,-1(P)
JSYS DEVST
MOVEM 2,.SKIP. ;INDICATE ERROR
PUSH P,[=100]
PUSH P,1 ;UPDATED BP
PUSHJ P,ZADJST
SUB P,X22
JRST @2(P)
ENDCOM(DEVINF)
COMPIL(FIO,<OUT,CHAROUT,LINOUT,GTFDB>
,<CDBTBL,JFNTBL,X22,X33,X44,.SKIP.,SAVE,RESTR>
,<FILIO -- IO ROUTINES>)
DSCR SIMPLE PROCEDURE CHAROUT(INTEGER JFN; INTEGER JFN)
⊗
HERE(CHAROUT)
BEGIN CHAROUT
PUSH P,1
PUSH P,2
PUSH P,CDB
PUSH P,CHNL
SKIPL CHNL,-6(P) ;CHANNEL
CAIL CHNL,JFNSIZE
JRST CHOLIT ;USE JFN LITERALLY
MOVE CDB,CDBTBL(CHNL)
HRRZ 1,JFNTBL(CHNL)
SKIPN 1
JRST CHAOBAD
LDB 2,[POINT 6,OFL(CDB),5] ;GET BYTE SIZE
CAIN 2,=36
JRST B36
PUSHJ P,OPNCHK
MOVE 2,-5(P)
JSYS BOUT
JRST CHARET
B36: MOVE 2,-5(P)
SOSGE OCNT(CDB)
PUSHJ P,STRSN0 ;WITH 1,CDB,CHNL LOADED
IDPB 2,OBP(CDB)
CHARET: POP P,CHNL
POP P,CDB
POP P,2
POP P,1
SUB P,X33
JRST @3(P)
CHAOBAD: ERR <CHAROUT: Illegal JFN OR BYTE-SIZE>,1
JRST CHARET
CHOLIT: MOVE 1,-6(P)
MOVE 2,-5(P)
JSYS BOUT
JRST CHARET
BEND CHAROUT
DSCR SIMPLE PROCEDURE OUT(INTEGER JFN; STRING S)
Outputs a SAIL string to the JFN, which may be open
in DUMP mode.
⊗
HERE(OUT)
BEGIN OUT
PUSHJ P,SAVE
MOVE LPSA,X22
HRRZ 3,-1(SP) ; GET THE COUNT
JUMPE 3,SOURET ; DONT SEND NULL STRING
VALCHN 1,-1(P),SOUBAD
LDB 2,[POINT 6,OFL(CDB),5] ;GET BYTE SIZE
CAIN 2,7 ;7-BIT?
JRST USESOU ;USE SOUT
CAIE 2,=36 ;36-BIT?
JRST SOUBAD
;HERE TO DO BUFFERED OUTPUT
DMPAGN: ILDB 2,(SP) ;GET A CHARACTER
SOSGE OCNT(CDB) ;AND DECREMENT BUFFER COUNT
PUSHJ P,STRSN0 ;SO SEND THE BUFFER ;WITH 1,CDB,CHNL LOADED
IDPB 2,OBP(CDB) ;AND COPY THE CHARACTER
SOJG 3,DMPAGN ;STRING CHAR COUNT
SOURET: SUB SP,X22
JRST RESTR
USESOU: PUSHJ P,OPNCHK ;CHECK IF OPEN
MOVE 2,(SP) ; GET THE BYTE-POINTER
MOVN 3,3 ; NEGATE BYTE-COUNT
JSYS SOUT
JRST SOURET
SOUBAD: ERR <OUT Illegal JFN OR BYTE-SIZE>,1
JRST SOURET
BEND OUT
DSCR PROCEDURE LINOUT(INTEGER JFN,VALUE)
⊗
HERE(LINOUT)
BEGIN LINOUT
PUSHJ P,SAVE
VALCHN A,-2(P),LINBAD
LDB B,[POINT 6,OFL(CDB),5] ;GET BYTE-SIZE
CAIE B,=36 ;MUST BE 36-BIT
JRST LINBAD
SKIPG B,OCNT(CDB) ;ANY CHARS WAITING?
PUSHJ P,STRSND ;NO, SEND (OR PERHAPS JUST INITIALIZE)
MOVE TEMP,OBP(CDB) ;GET BP
LINOPL: TLNN TEMP,760000 ;LINED BP?
JRST OKLIGN
IBP TEMP
SOJA B,LINOPL
OKLIGN: MOVEM TEMP,OBP(CDB)
MOVEM B,OCNT(CDB)
CAIGE B,=10 ;ENOUGH FOR 10 CHARS?
PUSHJ P,STRSND ;NO
SKIPGE B,-1(P) ;GET LINE-NO
JRST [MOVNS B
MOVNI A,5
JRST NOCONV]
MOVNI A,6
MOVE C,[<ASCII /00000/>/2]
EXCH B,C
PUSH P,LNBAK
LNCONV: IDIVI C,=10
IORI D,"0"
DPB D,[POINT 7,(P),6]
SKIPE C
PUSHJ P,LNCONV ;THE RECURSIVE PRINTER
HLL C,(P)
LSHC B,7
LNBAK: POPJ P,.+1
LSH B,1
TRO B,1
NOCONV: AOS C,OBP(CDB) ;MOVE A WORD OUT
MOVEM B,(C)
ADDM A,OCNT(CDB)
MOVEI B,11
CAME A,[-5]
IDPB B,OBP(CDB) ;OUTPUT A TAB
NOTAB: MOVE LPSA,X33
JRST RESTR
LINBAD: ERR <LINOUT: Illegal JFN OR MODE>,
JRST NOTAB
BEND LINOUT
DSCR STRSND,STRSN0
CAL PUSHJ
SID SAVES ALL ACS
ARGS
1 JFN
CDB address of channel data block
1) does the dump mode output only if there are characters
to be sent, accounting for only as much of the buffer as is full.
2) resets the OCNT and OBP variables.
OCNT always has the number of free characters remaining
in the buffer. This means that routines such as RELEASE can call
STRSND, and STRSND will be able to account for how many characters
need to be sent. In this way, some of the classical problems
with counts are averted, since OCNT is honest.
The exception, of course, is in the tight loops for
character transmission. These are found in CHAROUT and OUT.
These are coded with (something like):
SOSGE OCNT(CDB)
PUSHJ P,STRSN0
ILDB CHAR,OBP(CDB)
At the call to STRSN0, OCNT is dishonest, reflecting the
fact that one character has already been promised. Thus,
the same code cannot be used for STRSND and STRSN0.
Hence, two entries to the code here.
⊗
BEGIN STRSND
↑↑STRSN0:
AOS OCNT(CDB) ;MAKE THE COUNT HONEST, TEMPORARILY
PUSHJ P,STRSND ;CALL STRSND
SOS OCNT(CDB) ;REFLECT THE FACT THAT A CHARACTER IS PROMISED
POPJ P, ;AND RETURN (TO CHARACTER OUTPUT CODE)
↑↑STRSND:
PUSHJ P,OPNCHK ;MAKE SURE OPEN
PUSH P,2 ;SAVE ACS
PUSH P,3
PUSH P,4
LDB 2,[POINT 4,OFL(CDB),9] ;GET MODE
JUMPE 2,STRSOU ;USE SOUT
CAIE 2,17 ;BETTER BE DUMP MODE
ERR <STRSND: MODE NOT 0 OR 17>
HRRZI 3,STARTPAGE(1) ;GET THE PAGE NUMBER FOR THE BUFFER
IMULI 3,1000 ;MAKE AN ADDRESS
SKIPN OBP(CDB) ;INITIALIZED?
JRST DMPINIT ;NO, JUST INITIALIZE
MOVEI 4,DMOCNT*5
CAMG 4,OCNT(CDB) ;ANY CHARS TO SEND
JRST STRRET ;NO
MOVEI 2,3
SUBI 3,1
MOVNI 4,DMOCNT ;WORD COUNT FOR DUMP MODE OUTPUT
HRL 3,4 ;MAKE AN IOWD
SETZ 4, ;MAKE A COMMAND LIST
JSYS DUMPO
ERR <DUMPOUT: CANNOT WRITE DATA IN DUMP MODE>,1
SETOM DMPED(CDB) ;AND INDICATE DONE
DMPINIT:
MOVEI 3,STARTPAGE(1)
IMULI 3,1000
HRL 2,3
HRRI 2,1(3)
SETZM (3)
BLT 2,DMOCNT-1(3) ;ZERO OUT
MOVEI 2,DMOCNT*5
MOVEM 2,OCNT(CDB) ;SAVE COUNT
HLL 3,[POINT 7,0,-1];FIX A BYTE-POINTER
MOVEM 3,OBP(CDB) ;AND SAVE BYTE-POINTER
STRRET: POP P,4 ;RESTORE AND RETURN
POP P,3
POP P,2
POPJ P,
STRSOU: SKIPN OBP(CDB) ;INITIALIZED?
JRST SOUINIT ;NO
MOVEI 3,1000*5
SUB 3,OCNT(CDB) ;NUMBER OF CHARACTERS ACTUALLY IN BUFFER
IDIVI 3,5 ;NUMBER OF WORDS
SKIPE 4 ;ANY REMAINDER?
AOJ 3, ;YES, ANOTHER WORD FOR EXTRA CHARACTERS
JUMPE 3,STRRET ;RETURN IF NO CHARACTERS TO SEND
MOVN 3,3 ;NEGATIVE WORD COUNT FOR SOUT
HRRZI 2,STARTPAGE(1)
IMULI 2,1000 ;CALCULATE ADDRESS
HRLI 2,444400 ;MAKE A BP
JSYS SOUT
SOUINIT:
HRRZI 2,STARTPAGE(1)
IMULI 2,1000
HRL 3,2
HRRI 3,1(2)
SETZM (2)
BLT 3,777(2) ;CLEAR OUT PAGE
HRLI 2,440700
MOVEM 2,OBP(CDB)
MOVEI 3,1000*5
MOVEM 3,OCNT(CDB)
JRST STRRET
BEND STRSND
DSCR SIMPLE PROCEDURE GTFDB(INTEGER JFN; REFERENCE INTEGER ARRAY BUF)
Entire FDB of JFN is read into BUF. No bounds checking,
so BUF should be at least '26 words.
⊗
HERE(GTFDB)
PUSHJ P,SAVE
MOVE LPSA,X33
VALCHN 1,<-2(P)>,GTFBAD
MOVSI 2,25 ;ALL 25 WORDS
HRRZ 3,-1(P) ;ADDRESS OF ARRAY
JSYS GTFDB
GTFRET: JRST RESTR
GTFBAD: ERR <Illegal JFN>,1
JRST GTFRET
ENDCOM(FIO)
COMPIL(BINROU,<WORDIN,WORDOUT,ARRYIN,ARRYOUT,MTOPR,SFPTR,RFPTR,BKJFN,RFBSZ>
,<JFNTBL,X22,X33,.SKIP.,CDBTBL,SAVE,RESTR>
,<BINROU -- BINARY ROUTINES>)
DSCR INTEGER SIMPLE PROCEDURE WORDIN(INTEGER JFN);
Does the BIN jsys on JFN.
⊗
HERE(WORDIN)
PUSH P,2
PUSH P,CHNL
PUSH P,CDB
VALCHN 1,<-4(P)>,BINBAD
PUSHJ P,OPNCHK
SKIPE ENDFL(CDB)
SETZM @ENDFL(CDB) ;ASSUME NO EOF
SETZM .SKIP. ;ALSO MARK FOR EOF
JSYS BIN
JUMPE 2,CKWEOF ;CHECK EOF
MOVE 1,2;
BINRET: POP P,CDB ;RESTORE
POP P,CHNL
POP P,2
SUB P,X22
JRST @2(P)
BINBAD: ERR <Illegal JFN>,1
SETZ 1, ;RETURN A NULL
JRST BINRET
CKWEOF: JSYS GTSTS ;CHECK STATUS
TESTE 2,<1B8> ;END-OF-FILE?
JRST [SKIPE ENDFL(CDB) ;EOF LOCATION
SETOM @ENDFL(CDB) ;YES
SETOM .SKIP. ;ALSO MARK
JRST .+1]
SETZ 1, ;RETURN NULL TO USER
JRST BINRET
DSCR SIMPLE PROCEDURE WORDOUT(INTEGER JFN,BYTE);
Does the BOUT jsys.;
⊗
HERE(WORDOUT)
PUSHJ P,SAVE
VALCHN 1,<-2(P)>,BOUBAD
PUSHJ P,OPNCHK
MOVE 2,-1(P);
JSYS BOUT
BOURET: MOVE LPSA,X33
JRST RESTR
BOUBAD: ERR <Illegal JFN>,1
JRST BOURET
DSCR SIMPLE PROCEDURE ARRYIN(INTEGER JFN; REFERENCE INTEGER LOC; INTEGER COUNT);
Reads in COUNT words into LOC from JFN. The file should be open
for 36-bit bytes for this to work.
WARNING: no array bounds checking.
⊗
HERE(ARRYIN)
PUSHJ P,SAVE
MOVE LPSA,X44
MOVN 3,-1(P) ;NEGATIVE WORD COUNT
JUMPE 3,ARIRET
JUMPG 3,ARIBAD ;NEGATIVE WORD COUNT
SKIPL CHNL,-3(P)
CAIL CHNL,JFNSIZE
JRST ARIBAD
MOVE CDB,CDBTBL(CHNL) ;GET CDB
SKIPN 1,JFNTBL(CHNL)
JRST ARIBAD
SKIPE ENDFL(CDB) ;EOF LOCATION?
SETZM @ENDFL(CDB) ;ASSUME GOOD
SETZM .SKIP.
HRRZ 1,1 ;THIS IS THE JFN NOW
PUSHJ P,OPNCHK ;MAKE CERTAIN WE ARE OPEN
LDB 2,[POINT 4,OFL(CDB),9] ;GET THE MODE
JUMPE 2,USESIN ;MODE ZERO?
CAIE 2,17 ;BETTER BE DUMP
JRST ARIBAD
USEDMP: MOVEI 2,3
HRL 3,3 ;NEGATIVE WORD COUNT
HRR 3,-2(P) ;ADDRESS OF BUFFER
SUBI 3,1
SETZB 4,.SKIP. ;ZERO NEXT LOCATION, ERROR WORD
JSYS DUMPI
JRST DMPERR
JRST ARIRET ;RETURN
USESIN: MOVSI 2,444400 ;BYTE-POINTER
HRR 2,-2(P) ;LOCATION
SETZM .SKIP. ;ASSUME NO ERROR
JSYS SIN
SKIPE 3 ;EVERYTHING READ ?
JRST SINEOF
ARIRET: JRST RESTR
SINEOF: ADD 3,-1(P) ;CALCULATE NO. OF WORDS READ IN
HRLI 3,-1 ;MAKE IT XWD -1,COUNT
SKIPE ENDFL(CDB) ;EOF LOCATION
MOVEM 3,@ENDFL(CDB) ;AND SAVE
SETOM .SKIP.
JRST ARIRET
ARIBAD: ERR <ARRYIN: NEGATIVE WORD COUNT, Illegal JFN OR ILLEGAL MODE>,1
ARIBA1: SETOM .SKIP.
JRST ARIRET
DMPERR: CAIN 1,600220 ;END OF FILE?
JRST DMPEOF
ERR <ARRYIN: DUMP MODE ERROR>,1
JRST ARIBA1
DMPEOF: SKIPE ENDFL(CDB) ;EOF LOCATION
SETOM @ENDFL(CDB) ;INDICATE EOF
SETOM .SKIP.
MOVE 1,DVTYP(CDB) ;GET DEVICE TYPE
CAIE 1,2 ;IS IT MAGNETIC TAPE?
JRST ARIRET ;NO
HRRZ 1,JFNTBL(CHNL) ;THE JFN
SETZ 2,
JSYS MTOPR ;CLEAR STATUS
JRST ARIRET ;AND RETURN
DSCR SIMPLE PROCEDURE ARRYOUT(INTEGER JFN; REFERENCE INTEGER LOC; INTEGER COUNT);
DESR
Writes COUNT words to JFN starting at LOC. The file should be open
in 36-bit bytes.;
⊗
HERE(ARRYOUT)
PUSHJ P,SAVE
MOVE LPSA,X44
MOVN 3,-1(P) ;COUNT
JUMPE 3,ARORET
JUMPG 3,AROBAD ;NEGATIVE COUNT?
SKIPL 1,-3(P) ;CHANNEL
CAIL 1,JFNSIZE
JRST AROBAD
MOVE CDB,CDBTBL(1)
SKIPN 1,JFNTBL(1)
JRST AROBAD
HRRZ 1,1 ;JFN
PUSHJ P,OPNCHK
LDB 2,[POINT 4,OFL(CDB),9] ;GET THE MODE
JUMPE 2,AROSOU ;MODE ZERO?
CAIE 2,17 ;BETTER BE DUMP
JRST AROBAD ;NOT OPEN IN DUMP MODE
ARODMP: MOVEI 2,3
HRL 3,3 ;NEGATIVE WORD COUNT
HRR 3,-2(P)
SUBI 3,1 ;MAKE AN IOWD
SETZB 4,.SKIP.
JSYS DUMPO
JRST DMPOER
SETOM DMPED(CDB) ;INDICATE DUMP MODE
JRST ARORET ;RETURN
AROSOU: MOVSI 2,444400 ;BYTE-POINTER
HRR 2,-2(P) ;LOCATION
SETZM .SKIP.
JSYS SOUT
ARORET: JRST RESTR
AROBAD: ERR <ARRYOUT: NEGATIVE WORD COUNT, Illegal JFN OR ILLEGAL MODE>,1
AROBA1: SETOM .SKIP.
JRST ARORET
DMPOER: ERR <ARRYOUT: DUMP MODE ERROR>,1
JRST AROBA1
DSCR SIMPLE PROCEDURE MTOPR(INTEGER JFN,FUNCTION,VALUE)
Does the MTOPR jsys.
⊗
HERE(MTOPR)
BEGIN MTOPR
PUSHJ P,SAVE
MOVE LPSA,X44
VALCHN 1,-3(P),MTBAD
MOVE 2,-2(P)
MOVE 3,-1(P)
JSYS MTOPR
MTRET: JRST RESTR
MTBAD: ERR <Illegal JFN>,1
JRST MTRET
BEND MTOPR
DSCR SIMPLE PROCEDURE SFPTR(INTEGER JFN,POINTER)
Sets the file open on JFN to byte POINTER (-1 for EOF).
Errors returned in .SKIP.
WARNING: presently not compatible with special character
mode.
⊗
HERE(SFPTR)
PUSHJ P,SAVE
MOVE LPSA,X33
VALCHN 1,-2(P),SFBAD
SETZM .SKIP.
MOVE 2,-1(P)
JSYS SFPTR
MOVEM 1,.SKIP.
SFRET: JRST RESTR
SFBAD: ERR <Illegal JFN>,1
SETOM .SKIP.
JRST SFRET
DSCR INTEGER SIMPLE PROCEDURE RFPTR(INTEGER JFN)
Reads the pointer of JFN. Error codes to .SKIP.
WARNING: presently does not work for files in special character
mode.
⊗
HERE(RFPTR)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,-1(P),RFBAD
SETZM .SKIP.
JSYS RFPTR
MOVEM 1,.SKIP.
MOVEM 2,RACS+A(USER) ;ANSWER IN 2
RFRET: JRST RESTR
RFBAD: ERR <Illegal JFN>,1
SETOM .SKIP.
JRST RFRET
DSCR SIMPLE PROCEDURE BKJFN(INTEGER JFN)
Does the BKJFN jsys on JFN, error code to .SKIP.
⊗
HERE(BKJFN)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,-1(P),BKBAD
SETZM .SKIP.
BKJF1: JSYS BKJFN
MOVEM 1,.SKIP. ;ERROR RETURN
BKRET: JRST RESTR
BKBAD: MOVE 1,-1(P) ;USE LITERALLY
JRST BKJF1
DSCR INTEGER SIMPLE PROCEDURE RFBSZ(INTEGER JFN);
Reads the byte-size of the file open on JFN.
⊗
HERE(RFBSZ)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCHN 1,-1(P),RFBBAD
JSYS RFBSZ
MOVEM 2,RACS+A(USER) ;ANSWER IN 2
RFBRET: JRST RESTR
RFBBAD: ERR <Illegal JFN>,1
JRST RFBRET
ENDCOM(BINROU)
IMSSS,<
COMPIL(DSKOPS,<DSKIN,DSKOUT>
,<JFNTBL,CDBTBL,.SKIP.>
,<DSKOPS -- DIRECT DSK ROUTINES>)
DSCR SIMPLE PROCEDURE
DSKIN(INTEGER MODULE,RECNO,COUNT; REFERENCE INTEGER LOC);
IMSSS only.
Does direct IO from the DSK (formerly device "PAK").
Modules 4-7 are legal for everyone. Other modules require enabled
status.
Count words are read into user's core at location LOC, from
MODULE, record RECNO. Error bits are in .SKIP.
Does the DSKOP jsys (as modified at IMSSS).
⊗
BEGIN DSKOPS
HERE(DSKIN)
PUSHJ P,SAVE
SETZ 4, ;INDICATE READ ONLY
DSK1: HRRZ 2,-2(P)
JUMPLE 2,DSBAD ;LEQ 0 -- ERROR
CAILE 2,1000 ;DONT READ MORE THAN 1000 WORDS
JRST DSBAD
IOR 2,4 ;PICK UP READ OR WRITE (SET IN 4)
HRLZ 1,-4(P) ;MODULE
HRR 1,-3(P) ;RECORD NO. IN RIGHT HALF
TLO 1,600000 ;SOFTWARD ADDRESS, IMSSS FORMAT (BITS 0 AND 1 RES.)
HRRZ 3,-1(P) ; GET THE USER LOCATION
JSYS DSKOP
DSDUN: MOVEM 1,.SKIP. ; SAVE ERROR BITS
DSRET: MOVE LPSA,[XWD 5,5] ; TO ADJUST STACK
JRST RESTR
DSBAD: ERR <DSKIN OR DSKOUT: WORD COUNT EITHER <= 0 OR > '1000>,1
SETOM .SKIP.
JRST DSRET
DSCR SIMPLE PROCEDURE
DSKOUT(INTEGER MODULE,RECNO,COUNT; REFERENCE INTEGER LOC)
DESR Similar to DSKIN, except that a write is done.
⊗
HERE(DSKOUT)
PUSHJ P,SAVE
MOVSI 4,(1B14) ;INDICATE WRITE (TO BE IOR'ED INTO AC 2)
JRST DSK1 ;AND TO THE ABOVE CODE
BEND DSKOPS
ENDCOM(DSKOP)
>;IMSSS
COMPIL(DEVS,<DEVTYPE,DVCHR,ERSTR>
,<X22,X44,.SKIP.,JFNTBL,CDBTBL>
,<DEVS -- DEVICE HANDLERS, ERROR ROUTINE>)
DSCR INTEGER SIMPLE PROCEDURE DEVTYPE(INTEGER JFN);
Returns (via the DEVCHR jsys) the device type of
the device open on JFN. The more general DEVCHR call is
also implemented (below).
⊗
HERE(DEVTYPE)
VALCHN 1,-1(P),DEVBAD
JSYS DVCHR
HLRZ 1,2
ANDI 1,777
DEVRET: SUB P,X22
JRST @2(P)
DEVBAD: ERR <Illegal JFN>,1
JRST DEVRET
DSCR INTEGER SIMPLE PROCEDURE DVCHR(INTEGER JFN; REFERENCE INTEGER AC1,AC3);
Does the DEVCHR jsys, returning the flags from AC2 as the
value of the call, and AC1 and AC3 get the contents of ac's 1 and 3.;
⊗
HERE(DVCHR)
VALCHN 1,-3(P),DVBAD
JSYS DVCHR
MOVEM 1,@-2(P)
MOVEM 3,@-1(P)
MOVE 1,2
DVRET: SUB P,X44
JRST @4(P)
DVBAD: ERR <Illegal JFN>,1
JRST DVRET
DSCR SIMPLE PROCEDURE ERSTR(INTEGER ERRNO,FORK)
Using the ERSTR jsys, types out on the console the TENEX error string
associated with ERRNO for FORK fork (0 for the current fork). Parameters (in
the sense of the ERSTR jsys) are expanded.
Types out the string ERSTR: UNDEFINED ERROR number if
something is with your error number or fork (and sets .SKIP. to -1).
⊗
HERE(ERSTR)
SETZM .SKIP.
MOVEI 1,101 ;PRIMARY OUTPUT
SKIPN 2,-1(P) ;ANY FORK MENTIONED?
MOVEI 2,400000 ;ASSUME CURRENT FORK
HRLZ 2,2 ;IN LEFT HALF
HRR 2,-2(P) ;THE ERROR NUMBER
SETZ 3, ;NO LIMIT TO SIZE OF STRING
JSYS ERSTR
JRST ERSERR
JRST ERSERR ;ERROR RETURNS
ERSRET: SUB P,X33
JRST @3(P)
ERSERR: HRROI 1,[ASCIZ/
ERSTR: UNDEFINED ERROR NUMBER
/]
JSYS PSOUT
SETOM .SKIP. ;INDICATE ERROR
JRST ERSRET
ENDCOM(DEVS)
COMPIL(UTILITY,<SETCHN,ZSETST,ZADJST,.RESET>
,<CORGET,GOGTAB,JFNTBL,CDBTBL,STRNGC,INSET>
,<UTILITY -- UTILITY TENEX ROUTINES>)
DSCR
SETCHN accepts in A the JFN, and returns in A the channel number associated with a JFN.
It sets up the JFNTBL, the CDBTBL table, and returns the address of the
file command block in ac CDB. Other acs are not modified (except USER).
In order to accommodate the open statement, a channel will be
considered allocated when it has a CDB, even if it does not yet have a jfn.
⊗
HERE(SETCHN)
MOVE USER,GOGTAB
PUSH P,B
PUSH P,C
PUSH P,D
CAIG A,JFNSIZE ;IS THE JFN BEYOND THE NUMBER OF CHANNELS
SKIPE CDBTBL(A) ;CAN WE USE THE SAME CHANNEL AS JFN?
JRST FNDCHN ;PERHAPS NOT, FIND ONE SOME HOW
HRRZ D,A ;USE JFN AS CHANNEL
;MUST GET A CHANNEL DATA BLOCK
GTCDB: MOVEI C,IOTLEN
PUSHJ P,CORGET
ERR <SETCHN: NO CORE>
MOVE CDB,B
MOVEM CDB,CDBTBL(D) ;SAVE ADDR OF CDB
;HERE WITH B,CDB, D LOADED WITH: CDBADDR,CDBADDR,CHANNEL
CLCDB:
HRL B,B
ADDI B,1
SETZM (CDB)
BLT B,IOTLEN-1(CDB)
GOTCHN:
MOVEM A,JFNTBL(D)
HRRZ 1,A ;JFN
JSYS DVCHR ;CLOBBERS 1,2,3
MOVEM 1,DVDSG(CDB) ;SAVE DESIGNATOR
MOVEM 2,DVCH(CDB) ;AND CHARACTERISTICS
HLRZ 1,2
ANDI 1,777 ;GET DEVICE TYPE
MOVEM 1,DVTYP(CDB) ;AND SAVE IT
HRRZ A,D ;CHANNEL INTO A
POP P,D ;RESTORE
POP P,C
POP P,B
POPJ P,
;FIND AN OPEN CHANNEL AND RETURN THE NUMBER IN D
;A HAS THE JFN NO. IN IT, SO CHECK TO SEE IF THE SAME
;B MAY BE CLOBBERED
FNDCHN: HRRZ D,JFNTBL(A) ;CHECK OLD JFN
CAIE D,(A) ;SAME AS THE NEW?
JRST FNDCH2 ;NO
MOVE CDB,CDBTBL(D) ;GET OLD CDB
MOVE B,CDB ;COPY CDB ADDR FOR BLT
JRST CLCDB
FNDCH2: SETZ D,
FNDCH1: CAIL D,JFNSIZE
ERR <SETCHN: JFN TABLE IS FULL (SHOULD NEVER HAPPEN)>
SKIPE CDBTBL(D) ;IS IT EMPTY?
AOJA D,FNDCH1 ;NO LOOK SOME MORE
JRST GTCDB ;YES, USE IT
DSCR SIMPLE INTEGER PROCEDURE ZSETST(INTEGER I);
Internal book-keeping routine not intended for
use from SAIL. Causes liberation from SAIL.
THE ARGUMENT IS THE MAXIMUM SIZE OF THE EXPECTED STRING.
THE RETURN IS THE BYTEPOINTER POINTING INTO THE TOP OF STRING SPACE
⊗
HERE(ZSETST)
MOVE USER,GOGTAB ; GET USER
SKIPE SGLIGN(USER)
PUSHJ P,INSET ;ASSUMING THAT IT IS TRANSPARENT FOR THE ACS
MOVE 1,-1(P) ;GET EXPECTED LENGTH
ADDM 1,REMCHR(USER) ; ADD ON
SKIPLE REMCHR(USER) ; NEED TO COLLECT?
PUSHJ P,GOCOLLECT ; YES
MOVE 1,TOPBYTE(USER) ; RETURN BP
SUB P,X22 ; ADJUST STACK
JRST @2(P) ; RETURN
GOCOLLECT:
MOVEM RF,RACS+RF(USER) ;SAVE RF
PUSHJ P,STRNGC ;
POPJ P, ; RETURN TO ABOVE
DSCR STRING SIMPLE PROCEDURE ZADJST(INTEGER CNTEST,BP)
Internal book-keeping routine.
ADJUSTS THE PARAMETERS ASSOCIATED WITH STRING SPACE.
BP IS OUR NEW TOPBYTE. CNTEST IS THE COUNT ESTIMATE WE
ORIGINALLY MADE.
FIRST, WE MUST MAKE REMCHR HONEST, THEN WE
CAN FIX TOPSTR AND THE USER'S LENGTH WORD.
⊗
HERE(ZADJST)
BEGIN ZADJST
MOVE USER,GOGTAB;
PUSH P,1
PUSH P,2
PUSH P,3
PUSH P,4
DEFINE CNTARG <-6(P)>
DEFINE BPARG <-5(P)>
MOVE 2,BPARG ;UPDATED BP
MOVE 1,TOPBYTE(USER) ; GET OLD TOPBYTE
CAMN 1,2 ; THE NULL STRING?
JRST NULRET; ;YES
;P. KANERVA'S BYTE ROUTINE
LDB 3,[POINT 6,1,5] ;BITS TO THE RIGHT OF BYTE 1
LDB 4,[POINT 6,2,5] ;BITS TO THE RIGHT OF BYTE 2
SUBI 3,(4) ;BIT DIFFERENCE
IDIVI 3,7 ;WITHIN-WORD BYTE DIFFERENCE
SUBI 2,(1) ;WORDS BETWEEN BYTES
HRRE 2,2 ;FULL WORD DIFFERENCE
IMULI 2,5 ;CONVERT IT TO BYTE DIFFERENCE
ADD 2,3 ;ADD COUNT DERIVED FROM WITHIN-WORD
;DIFFERENCE
CAMLE 2,CNTARG ;WITHIN RANGE?
ERR <ZADJST: TENEX WROTE TOO LONG A STRING, MAY BE FATAL>,1
GOTLNG: HRRO 1,2 ; XWD -1,COUNT
PUSH SP,1 ; XWD -1,COUNT
PUSH SP,TOPBYTE(USER) ; OLD TOPBYTE FOR BP FOR STRING
SUB 2,CNTARG ; SUBTRACT THE COUNT ESTIMATE
ADDM 2,REMCHR(USER) ; MAKE REMCHR HONEST
MOVE 2,BPARG ; GET THE NEW TOPBYTE
MOVEM 2,TOPBYTE(USER) ; AND SAVE IT
POP P,4
POP P,3
POP P,2
POP P,1
SUB P,X33 ; ADJUST STACK
JRST @3(P) ;
NULRET: SETZ 2,;
JRST GOTLNG ; BE SURE TO FIX UP ALL THE GOODIES
BEND ZADJST
DSCR
.RESET
SID SAVES ALL ACS
CAL PUSHJ, FROM SAIL AND THE COMPILER
RESETS TENEX IO AND BOOKKEEPING, AND SETS THE TTY MODE TO WAKEUP
ON EVERY CHARACTER. TTY WAKEUP IS NOT DONE IF THE JOB IS DETACHED.
THIS SHOULD ONLY BE CALLED INTERNALLY
⊗
HERE(.RESET)
BEGIN RESET
;ZERO OUT BOOKKEEPING
PUSH P,1
PUSH P,2
PUSH P,3
PUSH P,4
SETZM JFNTBL
MOVE 1,[XWD JFNTBL,JFNTBL+1]
BLT 1,JFNTBL+JFNSIZE-1
SETZM CDBTBL
MOVE 1,[XWD CDBTBL,CDBTBL+1]
BLT 1,CDBTBL+JFNSIZE-1
;RELEASE PAGES ASSOCIATED WITH FILES (FROM STARTPAGE TO STARTPAGE+JFNSIZE-1)
SETO 1, ;RELEASE PAGE
SETZ 3, ;FLAGS WORD
MOVE 2,[XWD 400000,STARTPAGE]
.RESE1: CAMN 2,[XWD 400000,STARTPAGE+JFNSIZE] ;THIS WOULD BE TOO MANY PAGES
JRST .RESE2
JSYS PMAP
AOJA 2,.RESE1 ;NEXT?
.RESE2:
JSYS RESET ;CLEAR ALL IO
;SET UP PSI SYSTEM
HRRZI 1,400000 ;USE EXISTING TABLE IF THERE
JSYS RIR
JUMPN 2,.+3 ;ALREADY THERE
MOVE 2,[XWD LEVTAB,CHNTAB]
JSYS SIR
JSYS EIR ;TURN ON INTERRUPTS
;CHECK AND SEE IF WE ARE DETACHED
JSYS GJINF
CAMN 4,[-1] ;-1 FOR DETACHED JOBS
JRST DTCHED ;YES IT IS DETACHED
;SET PRIMARY INPUT TO WAKE UP ON EVERY CHARACTER
;THE USER MAY RESET THIS.
MOVEI 1,100 ;PRIMARY INPUT
JSYS RFMOD
TRO 2,170000 ;WAKEUP ON ALL CHARS
JSYS SFMOD
DTCHED: SETZM CTLOSW ;CLEAR OUTPUT-SUPPRESSION SWITCH
POP P,4
POP P,3
POP P,2
POP P,1
POPJ P,
BEND RESET
;ROUTINE TO CHECK IF A JFN HAS BEEN CLOSED BY ONE OF
;THE DEC-STYLE CLOSE ROUTINES (IN WHICH CASE IT
;MUST BE AVAILABLE FOR RE-OPENING)
;ARGS:
; 1 JFN
; CDB THE CHANNEL DATA BLOCK
; CHNL THE CHANNEL NUMBER
↑OPNCHK:
SKIPN DECCLZ(CDB) ;CLOSED BY DEC?
POPJ P, ;NO
PUSH P,2 ;SAVE 2
MOVE 2,OFL(CDB) ;PREVIOUSLY USED FLAGS
JSYS OPENF ;OPEN
ERR <OPNCHK: CANNOT OPENF FILE>
SETZM DECCLZ(CDB)
POP P,2 ;RESTORE 2
POPJ P, ;RETURN
;SIMILAR TO OPNCHK EXCEPT THAT
;ARGS:
; CHNL THE CHANNEL NUMBER
; CDB THE CHANNEL DATA BLOCK
↑OPNCH1:
SKIPN DECCLZ(CDB) ;CLOSED BY DEC?
POPJ P,
PUSH P,1
PUSH P,2
HRRZ 1,JFNTBL(CHNL)
MOVE 2,OFL(CDB)
JSYS OPENF
ERR <OPNCHK: CANNOT OPENF FILE>
POP P,2
POP P,1
POPJ P, ;RETURN;
ENDCOM(UTILITY)
COMPIL(TTM,<RFMOD,SFMOD,RFCOC,SFCOC>
,<SAVE,RESTR,X22,X33,X44>
,<TTM -- TERMINAL MODE ROUTINES>)
DSCR INTEGER PROCEDURE RFMOD(INTEGER CHAN)
Reads a file's mode word.
PROCEDURE SFMOD(INTEGER CHAN,AC2)
Sets a file's mode word to argument AC2.
PROCEDURE RFCOC(INTEGER CHAN; REFERENCE INTEGER AC2,AC3)
Does RFCOC jsys, returning values in AC2 and AC3.
PROCEDURE SFCOC(INTEGER CHAN,AC2,AC3)
Does SFCOC jsys, setting to AC2 and AC3.
⊗
HERE(RFMOD)
PUSHJ P,SAVE
MOVE LPSA,X22
VALCH1 1,-1(P),RFMO1
RFMO2: JSYS RFMOD
MOVEM 2,RACS+A(USER)
JRST RESTR
RFMO1: MOVE 1,-1(P) ;USE LITERALLY
JRST RFMO2
HERE(SFMOD)
PUSHJ P,SAVE
MOVE LPSA,X33
VALCH1 1,-2(P),SFMO1
SFMO2: MOVE 2,-1(P)
JSYS SFMOD
JRST RESTR
SFMO1: MOVE 1,-2(P)
JRST SFMO2
HERE(RFCOC)
PUSHJ P,SAVE
MOVE LPSA,X44
VALCH1 1,-3(P),RFCO1
RFCO2: JSYS RFCOC
MOVEM 2,@-2(P)
MOVEM 3,@-1(P)
JRST RESTR
RFCO1: MOVE 1,-3(P) ;USE LITERALLY
JRST RFCO2
HERE(SFCOC)
PUSHJ P,SAVE
MOVE LPSA,X44
VALCH1 1,-3(P),SFCO1
SFCO2: MOVE 2,-2(P)
MOVE 3,-1(P)
JSYS SFCOC
JRST RESTR
SFCO1: MOVE 1,-3(P) ;USE LITERALLY
JRST SFCO2
ENDCOM(TTM)
COMPIL(PAGES,<PMAP>,<SAVE,RESTR,X44>
,<PAGES -- PAGE MANAGEMENT>)
DSCR SIMPLE PROCEDURE PMAP(INTEGER AC1,AC2,AC3);
DESR
Does the PMAP jsys, with these parameters:
ARGUMENTS:
AC1 contents of AC1
AC2 " of AC2
AC3 " of AC3
⊗
HERE(PMAP)
PUSHJ P,SAVE
MOVE LPSA,X44
MOVE 1,-3(P) ;FILEPAGE
MOVE 2,-2(P) ;XWD FORK,PAGE
MOVE 3,-1(P) ;ACCESS BITS
JSYS PMAP
JRST RESTR
ENDCOM(PAGES)
IMSSS,<
COMPIL(TT2,<PBTIN,INTTY>
,<X22,.SKIP.,ZSETST,ZADJST,CTLOSW>
,<TT2 -- IMSSS TTY ROUTINES>)
DSCR INTEGER SIMPLE PROCEDURE PBTIN(INTEGER SECONDS);
DESR
Executes the PBTIN jsys, with timing of SECONDS.
⊗
HERE(PBTIN)
SETZM CTLOSW ;PROGRAM REQUESTS INPUT
MOVE 1,-1(P) ;TIME IN SECONDS
JSYS PBTIN
SUB P,X22
JRST @2(P)
DSCR STRING SIMPLE PROCEDURE INTTY;
Using the PSTIN jsys, accepts as many as 200 characters from
the user's Teletype, with the standard system breakcharacters. The
breakcharacter itself is removed from the string, and
no timing is available. For fancier calls, see PSTIN routine.
⊗
HERE(INTTY)
PUSH P,1
PUSH P,2
PUSH P,3
SETZB 3,CTLOSW ;PROGRAM REQUESTS INPUT
MOVEI 2,=200 ;DEFAULT LENGTH
INTT2: PUSH P,2 ;LENGTH
PUSHJ P,ZSETST ;GET BP IN 1
JSYS PSTIN
CAIL 2,=200 ;DID WE GET 200 CHARS?
JRST [SETOM .SKIP.
JRST INTT1]
LDB 3,1 ;GET THE LAST CHAR
MOVEM 3,.SKIP. ;AND SAVE IT
SOJ 1, ;BACK UP BYTE-POINTER (OVER LAST CHAR)
IBP 1
IBP 1
IBP 1
IBP 1
INTT1: PUSH P,[=200]
PUSH P,1
PUSHJ P,ZADJST ;GET STRING ON STACK
POP P,3
POP P,2
POP P,1
POPJ P, ;RETURN
ENDCOM(TT2)
>;IMSSS
NOIMSSS<;NON-IMSSS VERSION OF INTTY FOR THOSE WHO SUFFER
;UNDER BBN'S LACK OF A SYSTEM LINE EDITOR
COMPIL(TT2,<INTTY>
,<X11,.SKIP.,ZSETST,ZADJST,CTLOSW,SAVE,RESTR>
,<TT2 -- INTTY FOR TENEX STYLE INPUT>)
DSCR INTTY
⊗;
HERE(INTTY)
BEGIN INTTY
ORIGCNT←←=200
;AC USES A,B,C JSYS TEMPORARIES
; D BYTEPOINTER
; E COUNT, INITIALLY 0
; Q1 (=6) ORIGINAL BP
PUSHJ P,SAVE
SETZM CTLOSW
MOVEI A,101
JSYS RFMOD
PUSH P,B ;SAVE THE TTY MODE
TRO B,170000 ;WAKEUP ON EVERYTHING
JSYS SFMOD
PUSH P,[ORIGCNT] ;
PUSHJ P,ZSETST ;GET A GOOD BP IN A
MOVE Q1,A
RESTRT: MOVE D,Q1 ;GET THE ORIGINAL BP
SETZ E, ;ZERO THE COUNT
INLUP: CAIL E,ORIGCNT
JRST CNTEXH ;COUNT EXHAUSTED
JSYS PBIN ;GET A CHAR
CAIE A,37 ;EOL?
CAIN A,33 ;ESCAPE?
JRST DONE
CAIE A,32 ;CTRL-Z
CAIN A,7 ;CTRL-G
JRST DONE
CAIE A,"R"-100 ;CTRL-R FOR REPEAT
JRST NOCTR
HRROI A,[ASCIZ/
/]
JSYS PSOUT
JUMPE E,INLUP
MOVEI A,101
MOVE B,Q1 ;ORIG BP
MOVN C,E ;COUNT THUS FAR
JSYS SOUT
JRST INLUP ;AND CONTINUE
NOCTR: CAIE A,"X"-100 ;CONTROL-X FOR DELETE LINE
JRST NOCTX
DOCTX: HRROI A,[ASCIZ/
/]
JSYS PSOUT
JRST RESTRT ;AND START ALL OVER
NOCTX: CAIE A,177 ;RUBOUT OR
CAIN A,"A"-100 ;CONTROL-A
JRST .+2
JRST NOCTA
JUMPLE E,DOCTX ;IF NO CHARS THEN DO A CONTROL-X
MOVEI A,"\"
JSYS PBOUT
LDB A,D ;LAST CHAR
JSYS PBOUT
MOVE A,D
JSYS BKJFN
JFCL
MOVEM A,D ;BACK UP BP
SOJA E,INLUP ;SUBTRACT 1 AND CONTINUE
NOCTA: IDPB A,D
AOJA E,INLUP ;ONE MORE CHAR
CNTEXH: SETO A, ;INDICATE NO COUNT
DONE: MOVEM A,.SKIP. ;BREAK CHAR, -1 FOR EXHAUSTED
PUSH P,[ORIGCNT]
PUSH P,D ;NEW BP
PUSHJ P,ZADJST ;FIX UP STRING SPACE, PUT STRING ON STACK
MOVEI A,101
POP P,B ;MODE SETTING
JSYS SFMOD ;RESET
MOVE LPSA,X11
JRST RESTR ;AND RETURN
BEND INTTY
ENDCOM(TT2)
>;NOIMSSS
COMMENT ⊗ TTY FUNCTIONS ⊗
DSCR TTY FUNCTIONS
CAL SAIL
⊗
Comment ⊗
INTEGER PROCEDURE INCHRW;
RETURN A CHAR FROM PBIN
INTEGER PROCEDURE INCHRS;
RETURN -1 IF NO CHAR WAITING, ELSE FIRST CHAR (SIBE FOLLOWED BY PBIN)
STRING PROCEDURE INCHWL;
WAIT FOR A LINE, THEN RETURN IT (PBINs, LINE EDITING)
STRING PROCEDURE INCHSL(REFERENCE INTEGER FLAG);
FLAG←-1, STR←NULL IF NO LINE, ELSE FLAG←0,
STR←LINE (SIBE, FOLLOWED BY PBINs)
STRING PROCEDURE INSTR(INTEGER BRCHAR);
RETURN ALL CHARS TO AND NOT INCLUDING BRCHAR (PBINs)
STRING PROCEDURE INSTRL(INTEGER BRCHAR);
WAIT FOR ONE LINE, THEN DO INSTR (PBINs WITH EDITING)
STRING PROCEDURE INSTRS(REFERENCE INTEGER FLAG; INTEGER BRCHAR);
FLAG←-1, STR←NULL IF NO LINES, ELSE FLAG←0,
STR←INSTR(BRCHAR)
PROCEDURE OUTCHR(INTEGER CHAR);
OUTPUT CHAR (PBOUT)
PROCEDURE OUTSTR(STRING STR);
OUTPUT STR (SOUT)
PROCEDURE CLRBUF;
CLEARS INPUT BUFFER (CFIBF)
TTYIN, TTYINS, TTYINL (TABLE, @BRCHAR);
TTYIN WORKS WITH TTCALL 0'S; TTYINS DOES A SKIP
ON LINE FIRST, RETURNING NULL AND -1 IN BREAK IF NO LINES
TTYINL DOES A WAIT FOR LINE FIRST.
FULL BREAKSET CAPABILITIES EXCEPT FOR
"R" MODE (AND OF COURSE, LINE NUM. STUFF)
TITLE TTYUUO
⊗
COMPIL(TTY,<PBIN,PBOUT,PSOUT,INCHRW,INCHRS,INCHWL,INCHSL,INSTR,OUTCHR,OUTSTR,INSTRL,INSTRS,CLRBUF,TTYIN,TTYINS,TTYINL,TTYUP
>
,<SAVE,RESTR,X11,X22,X33,INSET,CAT,STRNGC,GOGTAB,BRKMSK,.SKIP.,CTLOSW>
,<TELETYPE FUNCTIONS>)
;;#GF# DCS 2-1-72 (1-3) INCHWL BREAKS ON ALL ACTIVATION, TELLS WHICH IN .SKIP.
; .SKIP. EXTERNAL ABOVE
;;#GF#
HERE(PBIN)
HERE (INCHRW)
SETZM CTLOSW ;INPUT REQUESTED
INCHR1: JSYS PBIN
POPJ P,
HERE (INCHRS)
SETZM CTLOSW ;INPUT REQUESTED
MOVEI 1,100
JSYS SIBE
JRST INCHR1
SETO 1, ;RETURN -1
POPJ P,
HERE(PBOUT)
HERE (OUTCHR)
SKIPE CTLOSW ;DOING OUTPUT?
JRST OUTCRE ;NO
EXCH 1,-1(P) ;GET PARAMETER, SAVING AC 1
JSYS PBOUT ;OUTPUT CHAR
EXCH 1,-1(P) ;GET BACK 1
OUTCRE: SUB P,X22
JRST @2(P) ;RETURN
HERE(PSOUT)
HERE (OUTSTR)
SKIPE CTLOSW ;DOING OUTPUT?
JRST [SUB SP,X22
POPJ P,
]
EXCH 2,(SP) ;BP WORD
EXCH 3,-1(SP) ;LENGTH WORD
PUSH P,1 ;ALSO NEED 1
HRRZ 3,3 ;COUNT
JUMPE 3,NULSTR ;DONT SEND EMPTY STR
MOVEI 1,101 ;TERMINAL OUTPUT
MOVN 3,3
JSYS SOUT
NULSTR: POP P,1
POP SP,2
POP SP,3 ;ADJUSTS STACK AUTOMATICALLY
POPJ P, ;RETURN
;REDSTR (0) MARKS CTLOSW THAT INPUT WAS REQUESTED
;(1) PREPARES TO MAKE A STRING OF 200 CHARS,
;(2) ZEROS C FOR COUNT
;(3) SETS UP D WITH THE ORIGINAL BYTE-POINTER
REDSTR: SETZM CTLOSW ;INPUT REQUESTED
SKIPE SGLIGN(USER)
PUSHJ P,INSET
MOVEI A,=200
ADDM A,REMCHR(USER)
SKIPLE REMCHR(USER)
PUSHJ P,STRNGC
SETZ C, ;COUNT HERE
MOVE D,TOPBYTE(USER) ;ORIGINAL BYTE-POINTER, IF NEEDED
PUSH SP,[0] ;NULL STRING IF NOTHING DONE
PUSH SP,TOPBYTE(USER)
POPJ P,
FINSTR: MOVEI A,=200
SUB A,C ;NUMBER USED
ADDM A,REMCHR(USER)
HRROM C,-1(SP) ;STRING COUNT WORD
MOVEM D,TOPBYTE(USER) ;NEW TOPBYTE
JRST RESTR
;CALL TO HERE WITH A PUSHJ TO GET A CHAR IN AC1
;AC 3 HAS THE COUNT, D THE BYTE-POINTER
EDICHR:
JSYS PBIN ;GET A CHARACTER
CAIN 1,DELLINE ;DELETE LINE CHAR
JRST CTRLU
CAIN 1,RUBCHAR ;RUBOUT?
JRST RUBOUT
CAIN 1,37 ;PHONEY TENEX EOL?
MOVEI 1,12
CAIN 1,33 ;PHONEY TENEX ALTMODE?
MOVEI 1,ALTMODE ;DEC ALTMODE
POPJ P, ;GOOD CHAR FOR USER
CTRLU:
;AC 1 IS FREE
HRROI 1,[BYTE (7) 7,15,12,0,0]
JSYS PSOUT
JUMPE C,EDICHR ;IF NO CHARS THEN DO NOTHING
SETZ C,
MOVE D,TOPBYTE(USER)
JRST EDICHR
RUBOUT: JUMPE C,CTRLU ;IF NO CHARS THEN DO CTRLU
;AC 1 IS AVAILABLE
IMSSS<
MOVEI 1,101 ;PRIMARY OUTPUT
JSYS DELCH
JFCL
JRST DLTED ;DISPLAY -- LINE EMPTY
JRST DLTED ;DISPLAY -- DELETE DONE
>;IMSSS
MOVEI 1,"\"
JSYS PBOUT
LDB 1,D ;GET LAST CHAR
JSYS PBOUT ;AND SEND IT
DLTED:
SOJ D, ;BACK UP BP TO LAST CHAR
IBP D
IBP D
IBP D
IBP D
SOJA C,EDICHR ;AND GET ANOTHER CHAR
HERE(INSTRL)
HERE (INSTR)
PUSHJ P,SAVE
PUSHJ P,REDSTR
MOVE B,-1(P) ;BREAK CHAR
MOVE LPSA,X22 ;# TO REMOVE
INS1: CAIL C,=200 ;COUNT EXHAUSTED?
JRST FINSTR ;YES
INS2: PUSHJ P,EDICHR ;GET A CHAR IN 1, USING EDITING
CAMN 1,B ;BREAK?
JRST FINSTR ; YES, ALL DONE
IDPB 1,D ;PUT IT AWAY AND
AOJA C,INS1
HERE (INCHWL) PUSHJ P,SAVE
PUSHJ P,REDSTR
MOVE LPSA,X11
INS3: CAIL C,=200 ;COUNT EXHAUSTED?
JRST DNSTR1 ;YES
PUSHJ P,EDICHR ;GET A CHAR
CAIE 1,ALTMODE
CAIN 1,12
JRST DNSTR
CAIN 1,15 ;CR?
JRST INS3 ;IGNORE
IDPB 1,D ;PUT IT AWAY AND
AOJA C,INS3 ;NEXT CHARACTER
DNSTR: MOVEM 1,.SKIP. ;SET BREAK CHAR
JRST FINSTR
DNSTR1: SETOM .SKIP. ;INDICATE COUNT EXHAUSTED
JRST FINSTR
HERE (INCHSL) PUSHJ P,SAVE
MOVE LPSA,X22 ;PARAM (FLAG) AND RETURN
PUSHJ P,REDSTR
SETOM @-1(P) ;ASSUME FAILED
MOVEI 1,100 ;PRIMARY INPUT
JSYS SIBE ;CHARACTERS WAITING?
SKIPA ;YES
JRST FINSTR ;NO, FIX UP AND RETURN
SETZM @-1(P)
JRST INS3 ;AND USE INCHWL'S LOOP
HERE(INSTRS)
PUSHJ P,SAVE
MOVE LPSA,X33
PUSHJ P,REDSTR
SETOM @-2(P) ;ASSUME FAILED
MOVEI 1,100 ;RIMARY INPUT
JSYS SIBE ;CHARACTERS WAITING
SKIPA ;YES
JRST FINSTR ;NO, FIX UP AND RETURN
SETZM @-2(P) ;INDICATE SUCCESS
MOVE B,-1(P) ;GET BREAK CHARACTER
JRST INS2
HERE (CLRBUF)
PUSH P,1
MOVEI 1,100 ;PRIMARY INPUT
JSYS CFIBF ;CLEAR BUFFER
POP P,1
POPJ P,
HERE (TTYINS) PUSHJ P,SAVE
PUSHJ P,REDSTR ;PREPARE TO MAKE A STRING
MOVE LPSA,X33
SETOM @-1(P) ;ASSUME NO CHARS
MOVEI 1,100 ;PRIMARY INPUT
JSYS SIBE ;CHARS WAITING?
SKIPA ;YES
JRST FINSTR ;NONE WAITING
JRST TYIN1 ;GO AHEAD
NOBAIL<
HERE(TTYINL)
HERE (TTYIN) PUSHJ P,SAVE
>;NOBAIL
BAIL<
HERE(TTYINL)
HERE(TTYIN)
MOVEI LPSA,=71 ;PRIVILEGED MODE, 72 TABLES
JRST TTYIN2
;HERE(TTYINL)
;HERE(TTYIN)
MOVEI LPSA,=53 ;STANDARD MODE, 54 TABLES
TTYIN2:
>;BAIL
TYIN: PUSHJ P,REDSTR ;PREPARE STACK,A,STRNGC FOR A STRING
BAIL<
MOVE Y,LPSA
>;BAIL
MOVE LPSA,X33 ;PREPARE TO RETURN
TYIN1: SETZM @-1(P) ;ASSUME NO BREAK CHAR
NOBAIL<
SKIPL E,-2(P) ;TABLE #
CAILE E,=18
ERR <TTYIN: There are only 18 break tables>
HRRZ TEMP,USER
ADD TEMP,E ;TABLE NO(USER)
>;NOBAIL
BAIL<
SOSL X,-2(P) ;TABLE #
CAILE X,=53 ;CHECK FOR IN RANGE
ERR <TTYIN: There are only 54 break tables>
IDIVI X,=18
MOVEI CHNL,1(Y) ;CHNL NOW IN RANGE 1 TO 18
ADD X,USER ;RELOCATE GROUP NUMBER
SKIPN TEMP,BKTPTR(X) ;TEMP POINTS TO BLOCK FOR THIS GROUP
TYUNI: ERR <TTYIN: Uninitialized break table>
MOVE X,BKJFFO(TEMP) ;STATUS OF THIS GROUP
TDNN X,BRKMSK(CHNL) ;HAS IT BEEN INIT'ED?
JRST TYUNI ;NO
>;BAIL
MOVEI Z,1 ;FOR TESTING LINE NUMBERS
SKIPN LINTBL(TEMP) ;DON'T LET TEST SUCCEED IF
MOVEI Z,0 ;WE'RE TO LET LINE NUMBERS THRU
NOBAIL<
MOVE CHNL,BRKMSK(E) ;GET MASK FOR THIS TABLE
HRRZ Y,USER
>;NOBAIL
BAIL<
MOVE CHNL,BRKMSK(CHNL)
MOVE Y,TEMP
>;BAIL
ADD Y,[XWD 1,BRKTBL] ;BRKTBL+RLC(USER)
TTYN: CAIL C,=200 ;COUNT EXCEEDED?
JRST FINSTR ;YES
PUSHJ P,EDICHR ;GET A CHAR
TTYN1: TDNE CHNL,@Y ;BREAK OR OMIT?
JRST TTYSPC ; YES, FIND OUT WHICH
TTYC: IDPB 1,D ;PUT IT AWAY
AOJA C,TTYN ;COUNT AND CONTINUE
JRST FINSTR ;DONE
TTYSPC: HLLZ TEMP,@Y ;WHICH?
TDNN TEMP,CHNL
JRST TTYN ;OMIT
MOVEM 1,@-1(P)
NOBAIL<
MOVE Y,-2(P) ;WHAT TO DO WITH IT
ADD Y,USER
SKIPN Y,DSPTBL(Y)
>;NOBAIL
BAIL<
MOVE X,-2(P) ;TABLE #, BUT -1 SINCE WE SOS'ED IT
IDIVI X,=18
ADD X,USER ;RELOCATE GROUP NUMBER
MOVE Z,BKTPTR(X) ;Z GETS POINTER TO BLOCK FOR THIS GROUP
ADDI Z,1(Y) ;ADD RANGE 1 TO 18
SKIPN Y,DSPTBL(Y) ;WHAT TO DO WITH IT
>;BAIL
JRST FINSTR ;DONE, NO SAVE
JUMPL Y,TTYAPP ;APPEND
PUSH P,1 ;SAVE
MOVEI 1,100 ;PRIMARY INPUT
JSYS BKJFN
ERR <CAN'T RETAIN BREAK CHAR FROM TTYIN>,1
POP P,1
JRST FINSTR ;AND RETURN
TTYAPP: IDPB 1,D ;COUNT THE BREAK CHAR
ADDI C,1 ;ONE MORE HAPPY CHAR
JRST FINSTR
DSCR INTEGER PROCEDURE TTYUP(INTEGER NEWVALUE)
Using the RFMOD and SFMOD jsyses, sets lower-to-upper
case conversion to NEWVALUE, returning the oldvalue. Tests
and modifies bit 31 of the RFMOD word for the primary input
file.
⊗;
HERE(TTYUP)
PUSHJ P,SAVE
MOVE LPSA,X22 ;SET FOR RETURN
MOVEI A,101 ;PRIMARY INPUT FILE
JSYS RFMOD ;GET THE CURRENT SETTINGS
SETZ C, ;ASSUME NOT CURRENTLY SET
TRNE B,1B31 ;IS IT SET?
SETO C, ;IT WAS
MOVEM C,RACS+A(USER)
MOVE C,[TRO B,1B31] ;ASSUME WE WANT TO SET UP
SKIPN -1(P) ;DID WE REALLY?
MOVE C,[TRZ B,1B31] ;NO, DONT
XCT C
JSYS SFMOD
JRST RESTR ;AND RETURN
ENDCOM(TTY)
COMPIL(PTY)
ENDCOM(PTY)
COMPIL(FIL,<FILNAM>,<FLSCAN,X22>,<FILNAM SCANNING ROUTINE>)
COMMENT ⊗Filnam ⊗
DSCR FILNAM
CAL PUSHJ
PAR file name string on SP stack
of form FILENAME<.EXT><[PROJ,PROG]>
RES FNAME(USER) : SIXBIT /filename/
EXT(USER): SIXBIT /extension,,0/
0
PRPN(USER): SIXBIT /PRJ PRG/ (or zero)
SID uses D,X,Y (4-6), REMOVES STRING FROM STACK
⊗
↑↑FILNAM:
SUB SP,X22 ;ADJUST STACK
FOR II←1,3 <
SETZM FNAME+II(USER)>
MOVEI X,FNAME(USER) ;WHERE TO PUT IT
PUSHJ P,FLSCAN ;GET FILE NAME
JUMPE Y,FLDUN ;FILE NAME ONLY
CAIE Y,"." ;EXTENSION?
JRST FLEXT ;NO, CHECK PPN
MOVEI X,FNAME+1(USER)
PUSHJ P,FLSCAN
FLEXT: JUMPE Y,FLDUN ;NO PPN SPECIFIED
CAIE Y,"["
JRST FLERR ;INVALID CHARACTER
PUSHJ P,[
RJUST: SETZM PROJ(USER)
MOVEI X,PROJ(USER)
PUSHJ P,FLSCAN ;GET PROJ OR PROG IN SIXBIT
IFN SIXSW,<
MOVE X,PROJ(USER)
IMULI D,-6 ;SHIFT FACTOR
LSH X,(D) ;RIGHT-JUSTIFY THE PROJ OR PROG
>;IF SIXSW (SET IN HEAD, USUALLY CONDITIONED ON NOEXPO)
IFE SIXSW,<
MOVEI X,0
;;#GT# DCS 5-11-72 ALLOW LARGE OCTAL NUMBERS AT STD DEC SYSTEMS
MOVE D,PROJ(USER) ;WAS A HLLZ
;;
FBACK: MOVEI C,0
LSHC C,6 ;GET A SIXBIT CHAR
CAIL C,'0'
CAILE C,'7'
JRST FLERR ;INVALID OCTAL
LSH X,3
IORI X,-'0'(C)
JUMPN D,FBACK
>;NOT SIXSW (USUALLY CONDITIONED ON EXPO)
FPOP: POPJ P,]
HRLZM X,FNAME+3(USER)
CAIE Y,","
JRST FLERR ;INVALID CHAR
PUSHJ P,RJUST ;JUSTIFY(AND CONVERT IF EXPORT) PROG #
HRRM X,FNAME+3(USER)
CAIN Y,"]"
FLDUN: AOS (P) ;SUCCESSFUL
FLERR: POPJ P, ;DONE, NOT NECESSARILY RIGHT
ENDCOM(FIL)
COMPIL(FLS,<FLSCAN>,,<FLSCAN ROUTINE>)
COMMENT ⊗Flscan ⊗
DSCR FLSCAN
CAL PUSHJ
PAR X -- addr of destination SIXBIT
1(SP), 2(SP) -- input string
RES sixbit for next filename, etc in word addressed by X
break (punctuation) char in Y (0 if string exhausted)
D,X, input string adjusted
SID only those AC changes listed above (Y, for instance)
⊗
↑↑FLSCAN:
HRRZS 1(SP) ;WANT ONLY LENGTH PART
MOVEI D,6 ;MAX NUMBER PICKED UP
SETZM (X) ;ZERO DESTINATION
HRLI X,440600 ;BYTE POINTER NOW
FLN1: MOVEI Y,0 ;ASSUME NO STRING LEFT
SOSGE 1(SP) ;TEST 0-LENGTH STRING
POPJ P,
ILDB Y,2(SP) ;GET BYTE
CAIE Y,"." ;CHECK VALID BREAK CHAR
CAIN Y,"["
POPJ P,
CAIE Y,"]"
CAIN Y,","
POPJ P,
JUMPE D,FLN1 ;NEED NO MORE CHARS
TRZN Y,100 ;MOVE 100 BIT TO 40 BIT
TRZA Y,40 ; TO CONVERT TO SIXBIT
TRO Y,40 ; (NO CHECKING)
IDPB Y,X ;PUT IT AWAY
SOJA D,FLN1 ;CONTINUE
ENDCOM(FLS)
COMPIL(INP,<INPUT,CHARIN,SINI>
,<INSET,STRNGC,BRKMSK,X33,GOGTAB,JFNTBL,CDBTBL>
,<STRING INPUT ROUTINE>)
DSCR CHAR←CHARIN(CHANNEL)
⊗
HERE(CHARIN)
BEGIN CHARIN
PUSH P,CDB
PUSH P,CHNL
PUSH P,D
SKIPL CHNL,-4(P)
CAIL CHNL,JFNSIZE
JRST CHALIT
MOVE CDB,CDBTBL(CHNL) ;CDB
LDB D,[POINT 6,OFL(CDB),5] ;GET BYTE SIZE
CAIE D,=36 ;36-BIT?
JRST CHA7 ;TRY 7
HRRZ CHNL,JFNTBL(CHNL) ;JFN IN CHNL FOR DOINP
SKIPN CHNL
JRST CHABAD
SKIPE ENDFL(CDB) ;EOF LOCATION?
SETZM @ENDFL(CDB) ;YES, ASSUME GOOD
SETZM .SKIP.
SOSG ICOWNT(CDB)
JRST [PUSHJ P,DOINP
JRST IN1 ;36-BIT RETURN
JRST INB ;7-BIT RETURN (WITH CHAR IN D)
JRST CHAEOF ;END OF FILE OR ERROR
]
IN1: ILDB D,IBP(CDB)
INB: MOVE 1,D ;CHAR IN 1
CHARET: POP P,D
POP P,CHNL
POP P,CDB
SUB P,X22
JRST @2(P)
CHA7: PUSH P,2 ;SAVE 2
PUSHJ P,OPNCH1 ;MAKE SURE OPEN
HRRZ 1,JFNTBL(CDB)
JSYS BIN
JUMPE 2,[JSYS GTSTS
TLNE 2,(1B8)
JRST CH7EOF ;END OF FILE
SETZ 2,
JRST .+1
]
MOVE 1,2 ;GET CHAR
POP P,2 ;RESTORE 2
JRST CHARET
CH7EOF: SKIPE ENDFL(CDB)
SETOM @ENDFL(CDB)
SETOM .SKIP.
POP P,2
CHAEOF:
CHABA1: SETZ 1, ;RETURN NULL BYTE
JRST CHARET
CHABAD: ERR <Illegal JFN>,1
JRST CHABA1
CHALIT: PUSH P,2 ;HERE WITH A LITERAL CHAN
MOVE 1,CHNL
JSYS BIN
MOVE 1,2
POP P,2
JRST CHARET
BEND CHARIN
DSCR STRING SIMPLE PROCEDURE SINI(INTEGER JFN,MAXLENGTH,BRKCHAR);
Reads in a string of characters, terminated by BRKCHAR or
reaching maxlength, whichever happens first.
⊗
HERE(SINI)
BEGIN SINI
PUSHJ P,SAVE
MOVE LPSA,X44
VALCHN 1,<-3(P)>,SINBAD
SKIPE ENDFL(CDB) ;EOF LOCATION?
SETZM @ENDFL(CDB) ;YES, ASSUME NO EOF
SETZM .SKIP.
SKIPG C,-2(P) ;ANY COUNT?
JRST NULRET
LDB B,[POINT 6,OFL(CDB),5]
CAIE B,=36 ;36-BIT BYTES?
JRST SIN7
;WITH RF(=CHNL) STILL LOADED, IN CASE STRNGC IS CALLED
PUSH P,1 ;SAVE 1 (WITH JFN)
MOVE 1,C ;COUNT
SKIPE SGLIGN(USER)
PUSHJ P,INSET
ADDM 1,REMCHR(USER) ;NEW REMCHR
SKIPLE REMCHR(USER) ;COLLECT?
PUSHJ P,STRNGC ;YES
MOVE E,TOPBYTE(USER) ;GOOD BYTE-POINTER
PUSH SP,[0]
PUSH SP,E ;START OF THE STRING
POP P,1
HRRZ CHNL,1 ;JFN IN 1 FOR DOINP
MOVN C,C ;NEGATE THE COUNT
IN1: SOSG ICOWNT(CDB)
JRST [PUSHJ P,DOINP
JRST IN2 ;36-BIT
JRST SINBAD ;7-BIT??
JRST SINDUN]
IN2: ILDB D,IBP(CDB)
JUMPE D,IN1 ;IF NULL KEEP LOOKING
CAMN D,-1(P) ;BREAK CHARACTER?
JRST DOBRK ;YES
IDPB D,E
IN3: AOJL C,IN1 ;FALL THRU IF COUNT IS EXHAUSTED
SINDUN: ADDM C,REMCHR(USER) ;MAKE REMCHR HONEST
MOVEM E,TOPBYTE(USER) ;SAVE NEW TOPBYTE
ADD C,-2(P) ;GET ACTUAL NUMBER OF CHARACTERS TRANSFERRED
HRROM C,-1(SP) ;SAVE COUNT FOR USER
JRST RESTR
DOBRK: IDPB D,E ;SAVE THE BREAK CHARACTER (AS DOES THE SIN JSYS)
AOJ C, ;ADD 1 TO THE COUNT
JRST SINDUN ;AND FINISH UP
SIN7: CAIE 2,7 ;MUST BE 7-BIT
JRST SINBAD
;WITH RF (=CHNL) LOADED
PUSH P,-2(P) ;MAXLENGTH
PUSHJ P,ZSETST
MOVE 2,1 ;BYTE-POINTER IN 2
HRRZ 1,JFNTBL(CHNL) ;GET THE JFN BACK
PUSHJ P,OPNCHK ;MAKE SURE OPEN
MOVE 3,-2(P) ;MAXLENGTH
MOVE 4,-1(P) ;OPTIONAL BREAKCHARACTER
JSYS SIN
PUSH P,-2(P) ;MAXLENGTH
PUSH P,2 ;UPDATED BYTE-POINTER
PUSHJ P,ZADJST ;GET STRING ON STACK
HRRZ 1,JFNTBL(CHNL) ;JFN
JSYS GTSTS ;CHECK STATUS
TLNN 2,(1B8) ;LOOK FOR EOF
JRST RESTR ;NO EOF
SKIPE ENDFL(CDB)
SETOM @ENDFL(CDB)
SETOM .SKIP.
SINRET: JRST RESTR
SINBAD: ERR <SINI: Illegal JFN OR ILLEGAL BYTE-SIZE>,1
NULRET: PUSH SP,[0] ;RETURN NULL STRING
PUSH SP,[0]
JRST RESTR
BEND SINI
COMMENT ⊗Input ⊗
DSCR "STRING"←INPUT(CHANNEL,BREAK TABLE NUMBER);
CAL SAIL
SID NO ACS SAVED BY INPUT!!!!!!
⊗
NOBAIL<
.IN.:
HERE (INPUT)
>;NOBAIL
BAIL<
HERE (INPUT)
MOVEI LPSA,=71 ;IN PRIVILEGED MODE THERE ARE 72 TABLES
JRST INPU.1
;HERE (INPUT)
.IN.: MOVEI LPSA,=53 ;IN STANDARD MODE THERE ARE 54 TABLES
INPU.1:
>;BAIL
MOVE USER,GOGTAB ;GET TABLE POINTER
MOVEM RF,RACS+RF(USER);SAVE F-REGISTER
SKIPE SGLIGN(USER)
PUSHJ P,INSET
SKIPL CHNL,-2(P) ;CHANNEL NUMBER
CAIL CHNL,JFNSIZE
JRST INPBAD
MOVE CDB,CDBTBL(CHNL)
HRRZ CHNL,JFNTBL(CHNL)
SKIPN CHNL
JRST INPBAD
LDB E,[POINT 4,OFL(CDB),9] ;DATA MODE
SKIPE ENDFL(CDB) ;EOF LOCATION
SETZM @ENDFL(CDB) ;YES, HELP USER ASSUME NO EOF
SETZM .SKIP.
SKIPE BRCHAR(CDB) ;BRCHAR LOCATION
SETZM @BRCHAR(CDB) ;ASSUME NO BREAK CHAR
MOVEI A,=200 ;DEFAULT NO. OF CHARS
SKIPE ICOUNT(CDB) ;USER-SPECIFIED COUNT?
HRRZ A,@ICOUNT(CDB) ;MAX COUNT FOR INPUT STRING
ADDM A,REMCHR(USER)
SKIPLE REMCHR(USER) ;ENOUGH ROOM?
PUSHJ P,STRNGC ;NO, TRY TO GET SOME
NOBAIL<
SKIPL C,-1(P) ;GET TABLE #, CHECK IN BOUNDS
CAILE C,=18
ERR <IN: There are only 18 break tables>
HRRZ TEMP,USER
ADD TEMP,C ;TABLE NO(USER)
>;NOBAIL
BAIL<
SOSL X,-1(P) ;TABLE #, CHECK IT
CAILE X,(LPSA) ;FOR IN BOUNDS
ERR <IN: There are only 54 break tables>
IDIVI X,=18
MOVEI C,1(Y) ;C IN RANGE 1 TO 18
ADD X,USER ;RELOCATE GROUP NUMBER
SKIPN LPSA,BKTPTR(X) ;LPSA GETS POINTER TO CORRECT BLOCK OF TABLES
INUNI: ERR <IN: Uninitialized break table>
MOVE X,BKJFFO(LPSA) ;STATUS OF THIS GROUP
TDNN X,BRKMSK(C) ;HAS TABLE BEEN INIT'ED?
JRST INUNI ;NO
MOVE TEMP,LPSA
ADD TEMP,C ;TEMP IS RELOCATED TABLE NUMBER
>;BAIL
MOVEI Z,1 ;FOR TESTING LINE NUMBERS
SKIPN LINTBL(TEMP) ;DON'T LET TEST SUCCEED IF
MOVEI Z,0 ;WE'RE TO LET LINE NUMBERS THRU
MOVN B,A ;NEGATE MAX CHAR COUNT
PUSH SP,[0] ;LEAVE ROOM FOR FIRST STR WORD
PUSH SP,TOPBYTE(USER) ;SECOND STRING WORD
MOVE FF,BRKMSK(C) ;GET MASK FOR THIS TABLE
NOBAIL<
HRRZ Y,USER
>;NOBAIL
BAIL<
MOVE Y,LPSA
>;BAIL
ADD Y,[XWD D,BRKTBL] ;BRKTBL+RLC(USER)
JUMPE B,DONE1 ; BECAUSE THE AOJL WON'T
NOBAIL<
TRNE FF,@BRKCVT(USER) ;DOING UC COERCION?
>;NOBAIL
BAIL<
TRNE FF,@BRKCVT(T1) ;DOING UC COERCION?
>;BAIL
TLOA C,400000 ;YES
TLZ C,400000 ;NO
.IN: SOSG ICOWNT(CDB) ;BUFFER EMPTY?
JRST [ PUSHJ P,DOINP
JRST IN1 ;36-BIT RETURN
JRST INB ;7-BIT RETURN (WITH CHAR IN D)
JRST DONE1 ;EOF OR ERROR
]
IN1:
ILDB D,IBP(CDB) ;GET NEXT CHARACTER
TDNE Z,@IBP(CDB) ;LINE NUMBER (ALWAYS SKIPS IF NOT WORRIED)?
JRST INLINN ;YES, GO SEE WHAT TO DO
IN2:
INB: JUMPE D,.IN ;ALWAYS IGNORE 0'S
SKIPN LINNUM(CDB) ;COUNTING VIA SETPL FUNCTION??
JRST INB1 ;NO
CAIN D,12 ;LINE-FEED?
AOS @LINNUM(CDB) ;INDICATE ANOTHER LINE
CAIE D,14 ;FORM-FEED?
JRST INB1 ;NO
SKIPE PAGNUM(CDB)
AOS @PAGNUM(CDB) ;COUNT PAGES ALSO
SKIPE LINNUM(CDB)
SETZM @LINNUM(CDB) ;SET LINNUM TO ZERO (NEW PAGE)
INB1: JUMPGE C,NOCV.I ;NOT COERCING?
CAIL D,"a" ;ONLY COERCE LOWER CASE
CAILE D,"z" ;
JRST .+2 ;SPECIAL RHT "FAST SKIP"
TRZ D,40 ;MAKE UPPER CASE
NOCV.I: TDNE FF,@Y ;MUST WE DO SOMETHING SPECIAL?
JRST INSPC ;YES, HANDLE
MOVEC: IDPB D,TOPBYTE(USER) ;LENGTHEN STRING
AOJL B,.IN ;GET SOME MORE
JRST DONE1
INSPC: HLLZ TEMP,@Y ;IGNORE OR BREAK?
TDNN TEMP,FF ; (CHOOSE ONE)
JRST .IN ;IGNORE
; BREAK -- STORE BREAK CHAR, FINISH OFF
DONE: SKIPE BRCHAR(CDB) ;USER BRCHAR VAR?
MOVEM D,@BRCHAR(CDB) ;STORE BREAK CHAR
NOBAIL<
MOVE Y,-1(P) ;TABLE # AGAIN
ADD Y,USER ;RELOCATE
SKIPN Y,DSPTBL(Y) ;WHAT TO DO WITH BREAK CHAR?
>;NOBAIL
BAIL<
MOVE X,-1(P) ;TABLE # AGAIN, BUT -1 SINCE WE SOS'ED IT
IDIVI X,=18
ADD X,USER ;RELOCATE GROUP NUBER
MOVE Z,BKTPTR(X) ;Z IS POINTER TO BLOCK OF TABLES
ADDI Z,1(Y) ;ADD RANGE 1 TO 18
SKIPN Y,DSPTBL(Z) ;WHAT TO DO WITH BREAK CHAR?
>;BAIL
JRST DONE1 ;SKIP IT
JUMPL Y,APPEND ;ADD TO END OF INPUT STRING
RETAIN: PUSHJ P,BACKUP
JRST DONE1
APPEND: IDPB D,TOPBYTE(USER) ;PUT ON END
AOJA B,DONE1 ;ONE MORE TO COUNT
; DONE -- MARK STRING COUNT WORD
DONE1: ADDM B,REMCHR(USER) ;GIVE UP THOSE NOT USED
SKIPN ICOUNT(CDB) ;USER SUPPLIED COUNT?
JRST [ADDI B,=200 ;USER DEFAULT
JRST .+2]
ADD B,@ICOUNT(CDB) ;HOW MANY DID WE ACTUALLY GET?
;;#GI# DCS 2-5-72 REMOVE TOPSTR
HRROM B,-1(SP) ;MARK RESULT, NON-CONSTANT
;;#GI#
MOVE RF,RACS+RF(USER);GET F-REGISTER BACK
SUB P,X33 ;REMOVE INPUT PARAMETER, RETURN ADDRESS
JRST @3(P) ;RETURN
; CAN EITHER DELETE LINE NUMBER (Y GT 0) OR STOP,
; TELL THE USER (BRCHAR=-1), AND MARK LINE NUMBER
; NOT A LINE NUMBER FOR NEXT TIME
COMMENT ⊗ BACKUP, DOINP TO BACKUP JFN, DO INPUT. ⊗
;CALL TO HERE WITH A PUSHJ, WITH CDB,CHNL LOADED
↑BACKUP:
PUSH P,1
LDB 1,[POINT 6,OFL(CDB),5] ;BYTE-SIZE
CAIN 1,44
JRST BACKU1
;HERE USE BKJFN
HRRZ 1,CHNL ;THE JFN
JSYS BKJFN
ERR <BACKUP: CANNOT DO RETAIN MODE ON THIS FILE>,1
BACRET: POP P,1
POPJ P,
BACKU1: SOS IBP(CDB)
IBP IBP(CDB)
IBP IBP(CDB)
IBP IBP(CDB)
IBP IBP(CDB)
AOS ICOWNT(CDB)
JRST BACRET
;CALL TO HERE WITH PUSHJ
;RETURNS +1 FOR 36-BIT INPUT, +2 FOR 7 BIT INPUT (WITH CHAR IN D),
;+3 FOR END OF FILE
↑DOINP: PUSH P,1
PUSH P,2
PUSH P,3
SKIPE DECCLZ(CDB) ;CHANNEL CLOSED BY DEC?
JRST [ ;YES
HRRZ 1,CHNL ;JFN
MOVE 2,OFL(CDB) ;FLAGS
JSYS OPENF ;OPEN
ERR <OPNCHK: CANNOT OPENF FILE>
SETZM DECCLZ(CDB)
JRST .+1
]
OPNOK: LDB 1,[POINT 4,OFL(CDB),9] ;GET MODE
CAIN 1,17 ;DUMP MODE
JRST DMPI ; YES
;36 BIT BYTES (SIN) OR 7 BIT (BIN)
LDB 1,[POINT 6,OFL(CDB),5] ;BYTE-SIZE
CAIN 1,44 ;36 BIT
JRST DOSIN
CAIE 1,7 ;7-BIT
JRST INPBAD ;ERROR
;HERE TO DO 7-BIT INPUT
DOBIN:
HRRZ 1,CHNL
JSYS BIN
JUMPE 2,[JSYS GTSTS ;CHECK STATUS
TLNE 2,(1B8) ;EOF?
JRST DOIEOF
SETZ 2,
JRST .+1
]
MOVE D,2 ;GET THE CHAR IN D
;CHECK IF WE HAVE A TTY
MOVE 1,DVTYP(CDB) ;GET DEVICE TYPE
CAIE 1,12 ;A TTY?
JRST NOTTTY ;NO
CAIN D,32 ;A CONTROL-Z?
JRST DOIEOF ;CTRL-Z FROM TTY MEANS EOF
CAIN D,37 ;PHONEY TENEX EOL?
MOVEI D,12 ;LINE-FEED
CAIN D,33 ;ASCII ESCAPE?
MOVEI D,ALTMODE ;MAKE ALTMODE
NOTTTY: SETZM ICOWNT(CDB) ;0 COUNT (SINCE NO MORE ARE WAITING)
POP P,3
POP P,2
POP P,1
AOS (P) ;7-BIT RETURN
POPJ P,
DOIEOF: SKIPE ENDFL(CDB) ;LOCATION?
SETOM @ENDFL(CDB) ;YES, SET IT
SETOM .SKIP.
SETZM ICOWNT(CDB) ;ZERO THE COUNT
SETZM IBP(CDB) ;AND THE BP
POP P,3
POP P,2
POP P,1
AOS (P) ;INDICATE EOF
AOS (P)
POPJ P,
DOSIN: MOVE 1,CHNL ;JFN
SKIPE DVTYP(CDB) ;DEVICE DSK?
JRST DOSIN1 ;NO, USE SIN JSYS
;HERE TO PMAP CORRECT PAGE
;1, CHNL HAVE THE JFN, CDB IS LOADED, 2 AND 3 ARE FREE
MOVE 2,[XWD 2,11] ;READ TWO WORDS FROM FDB STARTING AT 11
MOVEI 3,2 ;INTO ACS 2 AND 3
JSYS GTFDB ;GET THE SIZE OF THE FILE IN 2
LDB 2,[POINT 6,2,11] ;BYTE SIZE FROM FDB
PUSH P,4
PUSH P,5
MOVEI 4,=36
IDIV 4,2
IDIV 3,4 ;3 NOW HAS THE NUMBER OF 36-BIT BYTES
SKIPE 4 ;REMAINDER?
AOJ 3, ;YES, ANOTHER WORD
POP P,5
POP P,4
JSYS RFPTR ;READ CURRENT FILE POINTER INTO 2
ERR <DRYROT AT DOINP>
CAML 2,3 ;IS THE FILE POINTER LESS THAN THE SIZE OF THE FILE?
JRST [MOVEI 2,STARTPAGE(1);PAGE
HRLI 2,400000;
SETO 1,
SETZ 3,
JSYS PMAP ;RELEASE PAGE
JRST DOIEOF ;INDICATE EOF
]
SUB 3,2 ;CALCULATE THE DIFFERENCE IN WORDS
CAILE 3,1000
MOVEI 3,1000
PUSH P,3 ;NO. OF GOOD WORDS ON THIS PAGE, PUSH IT
IDIVI 2,1000 ;CALCULATE THE PAGE NUMBER FOR THIS POINTER
SKIPE 3 ;ANY REMAINDER?
AOJ 2, ;YES, ANOTHER PAGE
PUSH P,2 ;SAVE THE PAGE WE ARE READING IN
HRL 1,CHNL
HRR 1,2 ;XWD JFN,PAGE
MOVEI 2,STARTPAGE(CHNL)
HRLI 2,400000 ;XWD THISFORK, CORE PAGE
SETO 3, ;FLAG WORD
JSYS PMAP
MOVE 1,CHNL
POP P,2 ;GET BACK THE PAGE NO.
AOJ 2, ;NEXT PAGE
LSH 2,=9 ;CONVERT TO BYTES
JSYS SFPTR ;AND SET THE FILE POINTER
ERR <DRYROT AT DOINP>
POP P,3 ;NUMBER OF GOOD WORDS
IMULI 3,5 ;NUMBER OF CHARACTERS
JRST DO36CN ;AND SET UP COUNT, BYTE-POINTERS
;HERE TO DO 36-BIT INPUT WITH THE SIN JSYS
DOSIN1: MOVEI 2,STARTPAGE(1)
IMULI 2,1000 ;THE CORE ADDRESS
HRL 3,2
HRRI 3,1(2)
SETZM (2)
BLT 3,777(2) ;ZERO BUFFER
HRLI 2,444400 ;BYTE-POINTER
MOVNI 3,1000 ;1000 WORDS
JSYS SIN ;INPUT
CAMG 3,[-1000] ;SOMETHING RECEIVED?
JRST [CAMN 3,[-1000] ;NOTHING AT ALL?
JRST DOIEOF ;NOT A SINGLE WORD
JRST .+1
]
ADDI 3,1000 ;GET NUMBER OF WORDS READ
IMULI 3,5 ;NUMBER OF CHARACTERS
DO36CN: MOVEM 3,ICOWNT(CDB) ;REMEMBER
MOVEI 2,STARTPAGE(1)
IMULI 2,1000
HRLI 2,440700 ;BYTE-POINTER
MOVEM 2,IBP(CDB) ;REMEMBER
DOIRET: POP P,3
POP P,2
POP P,1
POPJ P,
; DUMP MODE -- ESPECIALLY FOR MAGTAPES
DMPI:
PUSH P,4 ;SAVE AN EXTRA AC
MOVE 1,CHNL
MOVEI 3,STARTPAGE(1)
IMULI 3,1000 ;THE ADDRESS OF THE BUFFER
HRL 2,3 ;ZERO BUFFER
HRRI 2,1(3)
SETZM (3)
BLT 2,777(3)
SUBI 3,1
HRLI 3,-1000 ;MAKE AN IOWD
MOVEI 2,3 ;COMMAND LIST STARTS AT 3
SETZ 4, ;COMMAND LIST ENDS AT 4
JSYS DUMPI
JRST DMIERR ;AN ERROR
MOVEI 3,1000*5 ;NO. OF CHARACTERS
POP P,4 ;RESTORE EXTRA AC
JRST DO36CN ;SET UP COUNT, BP, AND RETURN
DMIERR: CAIE 1,600220 ;EOF?
ERR <INPUT: DUMP MODE ERROR>
DMIEOF:
POP P,4 ;FIRST RESTORE 4
MOVE 1,DVTYP(CDB)
CAIE 2,3 ;MAGTAPE?
JRST DOIEOF ;NO JUST INDICATE EOF
HRRZ 1,CHNL
SETZ 2,
JSYS MTOPR ;RESET STATUS
JRST DOIEOF ;AND INDICATE EOF
;LINE NUMBER STUFF
INLINN:
NOPGNN:
SKIPE SOSNUM(CDB) ;WANT THE NUMBER?
JRST [MOVE TEMP,@IBP(CDB) ;SAVE IT FOR THE USER
MOVEM TEMP,@SOSNUM(CDB)
JRST .+1]
MOVE TEMP,-1(P) ;GET LINE NUMBER DISPOSITION FLAG,
ADD TEMP,USER ;RLC+TABLE
SKIPGE TEMP,LINTBL(TEMP) ;LINTBL+RLC+TABLE
JRST GIVLIN ; WANTS IT NEXT TIME OR SOMETHING
JSP TEMP,EATLIN ;TOSS IT OUT, AND
JRST .IN ; CONTINUE
EATLIN:
AOS IBP(CDB) ;FORGET IT ENTIRELY
MOVNI A,5 ;INDICATE SKIPPING SIX
ADDB A,ICOWNT(CDB) ;IN COUNT
JUMPG A,(TEMP) ;OVERFLOW BUFFER??
PUSHJ P,DOINP
JRST OKLN ;36-BIT RETURN
ERR <INPUT: 7-BIT BYTES CANNOT HAVE LINE NUMBERS>
JRST DONE1 ;END-OF-FILE
OKLN:
IBP IBP(CDB) ;GET OVER TAB FINALLY
JRST (TEMP) ;AND CONTINUE
GIVLIN: TRNE TEMP,-1 ;WANT LINE NO IN BRCHAR WORD?
JRST GVLLN ;NO, WANTS IT NEXT TIME.
SKIPL TEMP,@IBP(CDB) ;NEGATED LINE NO
MOVNS TEMP
SKIPE BRCHAR(CDB) ;USER LOCATION?
MOVEM TEMP,@BRCHAR(CDB) ;STORE WHERE HE WANTS IT
JSP TEMP,EATLIN ;GO EAT UP LINE NUMBER AND
JRST DONE1 ;FINISH UP
GVLLN:
SKIPE BRCHAR(CDB)
SETOM @BRCHAR(CDB) ;TELL THE USER
AOS ICOWNT(CDB) ;REVERSE THE SOSLE
MOVEI Y,1 ;TURN OFF LINE NUMBER
ANDCAM Y,@IBP(CDB) ; BIT
MOVSI Y,070000 ;BACK UP BYTE POINTER
ADDM Y,IBP(CDB)
JRST DONE1 ;FINISH OFF IN BAZE OF GORY
INPBAD: ERR <INPUT: Illegal JFN OR BAD INPUT>
ENDCOM(INP)
COMPIL(NUM,<REALIN,REALSCAN,INTIN,INTSCAN>
,<SIMIO,SAVE,RESTR,X22,X33,GETCHN,NOTOPN,.CH.,.MT.,.TEN.,BACKUP,DOINP>
,<LOU PAUL'S NUMBER INPUT AND CONVERSION ROUTINES>)
COMMENT ⊗Realin, Realscan ⊗
DSCR REAL←REALIN(CHANNEL NUMBER);
CAL SAIL
⊗
HERE (REALIN)
IFN ALWAYS,<BEGIN NUMIN>
PUSHJ P,SAVE
PUSHJ P,NUMIN; GET NUMBER IN A AND TEN EXPONENT IN C
MOVE LPSA,X22
JRST REALFN
DSCR REAL←REALSCAN(@"STRING");
CAL SAIL
⊗
HERE (REALSCAN)
PUSHJ P,SAVE
PUSHJ P,STRIN
MOVE LPSA,X33
REALFN: SETZ D,; POS SIGN
JUMPE A,ADON
JUMPG A,FPOS
SETO D,; NUMBER NEGATIVE
MOVNS A
FPOS: ;WE NOW HAVE A POSITIVE NUMBER IN A WITH SIGN IN D
JFFO A,.+1; NUMBER OF LEADING ZEROS IN B
ASH A,-1(B); BIT0=0, BIT1=1
MOVN X,B; BIN EXPONENT -2
JUMPE C,FLO; IF TEN EXPONENT ZERO THEN FINISH
JUMPL C,FNEG
CAIL C,100; CHECK BOUND OF EXPOENT
JRST ERROV1
SETZ Y,
JRST TEST
FNEG: MOVNS C
CAIL C,100
JRST ERROV1
MOVEI Y,6
TEST: TRNE C,1; DEPENDING ON LOW ORDER BIT OF EXP
JRST MULT; EITHER MULTIPLY
NEXT: ASH C,-1; OR DON'T.
AOJA Y,TEST; INDEX INTO MULTIPLIER TABLE
MULT: ADD X,.CH.(Y); EXPONENT
MUL A,.MT.(Y) ;MULTIPLY AND NORMALIZE
TLNE A,200000
JRST DTEST
ASHC A,1
SOJA X,.+1
DTEST: SOJG C,NEXT
FLO: IDIVI A,1B18
FSC A,255
FSC B,234
FADR A,B
SKIPE D
MOVNS A
FSC A,(X); SCALE
JRST ALLDON
SUBTTL INTIN INTEGER NUMBER INPUT ROUTINE LOU PAUL
COMMENT ⊗Intin, Intscan ⊗
DSCR INTEGER←INTIN(CHANNEL NUMBER);
CAL SAIL
⊗
HERE (INTIN)
;INTEGER NUMBER INPUT ROUTINE RETURNS VALUE IN A
;USES NUMIN TO PERFORM FREE FIELD SCAN
PUSHJ P,SAVE
PUSHJ P,NUMIN; GET NUMBER IN A, TEN EXPONENT IN C
MOVE LPSA,X22
JRST INTFN
DSCR INTEGER←INTSCAN("STRING");
CAL SAIL
⊗
HERE (INTSCAN)
PUSHJ P,SAVE
PUSHJ P,STRIN
MOVE LPSA,X33
INTFN: JUMPE A,ADON
JUMPE C,ADON
JUMPL C,DIVOUT; IF EXPONENT NEG WE WILL DIVIDE
CAIL C,13
JRST ERROV1
IMUL A,.TEN.(C)
JRST ALLDON
DIVOUT: MOVNS C
CAIL C,13
JRST [SETZ A,
JRST ADON ]
MOVE C,.TEN.(C)
IDIV A,C
ASH C,-1
CAML B,C; ROUND POSITIVELY
AOJA A,ALLDON
MOVNS B
CAML B,C
SOJ A,
ALLDON: JOV ERROV1; CHECK FOR OVERFLOW
ADON: MOVEM A,RACS+1(USER)
JRST RESTR
ERROV1: PUSHJ P,ERROV
JRST ADON
SUBTTL FREE FIELD NUMBER SCANNER LOU PAUL
DSCR NUMIN
DES THE COMMON ROUTINE USED BY REALIN, REALSCAN, INTIN, ETC.
⊗
;NUMIN PERFORMS A FREE FIELD READ AND RETURNS THE MOST SIGNIFICIANT
;PART OF THE NUMBER IN A AND THE APPROPIATE TENS EXPONENT IN C
;TAKING CARE OF LEADING ZEROS AND TRUNCATION ETC.
;SCANNING IS ACCORDING TO THE FOLLOWING BNF
;<NUMBER>::=<DEL><SIGN><NUM><DEL>
;<NUM> ::=<NO>|<NO><EXP>|<EXP>
;<NO> ::=<INTEGER>|<INTEGER>.|
; <INTEGER>.<INTEGER>|.<INTEGER>
;<INTEGER>::=<DIGIT>|<INTEGER><DIGIT>
;<EXP> ::=E<SIGN><INTEGER>|@<SIGN><INTEGER>
;<DIGIT>::=0|1|2|3|4|5|6|7|8|9
;<SIGN> ::=+|-|<EMPTY>
;NULL AND CARR. RET. ARE IGNORED.
;SCANNING IS FACILITATED BY A CHARACTER CLASS TABLE "TAB" AND
;TWO MACROS AHEAD AND ASTERN. THE LEFT HALF OF THE 200+1 WORD TABLE
;CONTAINS -1 IF NOT A DIGIT AND THE VALUE OF THE DIGIT IF IT IS A DIGIT
;THE RIGHT HALF CONTAINS -1 IF A DIGIT AND THE CLASS NUMBER IF NOT.
;CLASS 0 NULL, CARR RET, NOTHING
;CLASS 1 .
;CLASS 2 -
;CLASS 3 +
;CLASS 4 @,E
;CLASS 5 ANY OTHER CHARACETR
;CLASS 6 END OF FILE
;TAB(200) IS USED FOR FND OF FILE
;MACRO AHEAD IS USED FOR FORWARD SCANNING, ASTERN FOR SCANNING
;THE STACK CONSISTING OF AC Y WHICH HAS CLASS SYMBOLS SHIFTED INTO IT.
DEFINE AHEAD(DIG,POINT,MINUS,PLUS,E,CHA,EOF)<
HRRE X,TAB(D)
JRST @.+2(X)
JUMP DIG
JRST .-4
JUMP POINT
JUMP MINUS
JUMP PLUS
JUMP E
JUMP CHA
JUMP EOF>
DEFINE ASTERN(NULL,POINT,MINUS,PLUS,E,CHA)<
SETZ X,
LSHC X,3
JRST @.+1(X)
JUMP NULL
JUMP POINT
JUMP MINUS
JUMP PLUS
JUMP E
JUMP CHA
JUMP CHA>
;NUMIN -- CONTD.
NUMIN:
SKIPL CHNL,-2(P) ;
CAIL CHNL,JFNSIZE
PUSHJ P,NUMBAD
MOVE CDB,CDBTBL(CHNL)
SKIPN CHNL,JFNTBL(CHNL)
PUSHJ P,NUMBAD
SKIPE ENDFL(CDB)
SETZM @ENDFL(CDB)
SETZM .SKIP.
SKIPE BRCHAR(CDB)
SETZM @BRCHAR(CDB)
MOVE LPSA,[JSP X,NCH]
MOVEI Z,1; FOR LINE NUMBER TEST
PUSHJ P,SCAN
SKIPE BRCHAR(CDB) ;USER WANTS BREAK CHARACTER?
MOVEM D,@BRCHAR(CDB); FIX UP BREAK CHARACTER
SOS IBP(CDB) ;BACK UP TO GET IT NEXT TIME
FOR II←1,4 <
IBP IBP(CDB)>
AOS ICOWNT(CDB)
POPJ P,
; READ A CHARACTER FROM INPUT FILE -- FOR SCAN.
NCH: SOSG ICOWNT(CDB); DECREMENT CHARACTER COUNT
JRST [PUSHJ P,DOINP
JRST NCH1 ;36-BIT RETURN
JRST NCH1.1 ;7-BIT RETURN
JRST NCH7 ;EOF OR ERROR
]
NCH1: ILDB D,IBP(CDB); LOAD BYTE
TDNE Z,@IBP(CDB); CHECK FOR LINE NUMBER
JRST NCH5
NCH1.1: SKIPN LINNUM(CDB) ;WANT SETPL THINGS?
JRST (X) ;NO RETURN
CAIN D,12 ;LINE FEED?
AOS @LINNUM(CDB) ;YES
CAIE D,14 ;FORM FEED?
JRST (X) ;NOPE, NOTHING
SKIPE PAGNUM(CDB)
AOS @PAGNUM(CDB) ;INCREMENT PAGE COUNTER
SKIPE LINNUM(CDB)
SETZM @LINNUM(CDB) ;AND ZERO LINE COUNTER
JRST (X); RETURN
NCH7: MOVEI D,200 ;EOF OR DATA ERROR.
JRST (X)
NCH5: SKIPE SOSNUM(CDB) ;WANT SETPL STUFF?
JRST [MOVE D,@IBP(CDB)
MOVEM D,@SOSNUM(CDB) ;INFORM USER ABOUT LINE NUMBER
JRST .+1]
AOS IBP(CDB); WE HAVE A LINE NUMBER
MOVNI D,5; MOVE OVER IT
ADDB D,ICOWNT(CDB)
SKIPLE D ;NOTHING LEFT?
JRST NCH ;DO ANOTHER INPUT
PUSHJ P,DOINP ;
JRST NCH6 ;36-BIT RETURN -- MUST BE
PUSHJ P,NUMBAD ;IMPOSSIBLE
JRST NCH7 ;EOF OR SOME SUCH
NCH6: SOSG ICOWNT(CDB); REMOVE TAB
JRST NCH7 ;NONE THERE OR ERROR
IBP IBP(CDB)
JRST NCH
;SETUP FOR STRING INPUT (REALSCAN, INTSCAN)
STRIN: MOVE LPSA,[JSP X,NCHA]
HRRZ Z,-3(P)
HRRZ Z,-1(Z)
HRRZS -3(P) ;SO CAN INDIRECT THROUGH IT.
PUSHJ P,SCAN
HRRZ X,-3(P)
SOS (X) ;BACK UP BYTE POINTER
FOR II←1,4<
IBP (X)>
AOJ Z,
HRRM Z,-1(X)
MOVEM D,@-2(P) ;STORE BREAK CHARACTER
POPJ P,
;READ A CHARACTER ROUTINE FOR STRINGS.
NCHA: SOJL Z,NCH7
ILDB D,@-4(P)
JRST (X)
;SCAN (CALLED BY NUMIN AND STRIN)
SCAN: JOV .+1
SETO TEMP, ;FLAG REGISTER.
SETZ Y,
SETZB A,C; NUMBER EXPOENT
MORE: XCT LPSA; THIS GETS A CHARACTER IN D,200 IF FO EOF
AHEAD(DIG1,STACK,STACK,STACK,STACK,STACK,DONE)
STACK: LSHC X,-3; PUSH SYMBOL ONTO STACK "AC Y"
JRST MORE
DIG1: SETZ TEMP,; FLAG REG.
ASTERN(INT1,FRA1,SIG1,SIG2,EXP1,INT1)
SIG1: TRO TEMP,4; NEGATIVE SIGN
SIG2: ASTERN(INT1,ERR2,ERR5,ERR5,EXP1,INT1)
EXP1: MOVEI A,1
ASTERN(EXP2,ERR2,SIG3,SIG4,ERR1,EXP2)
SIG3: MOVNS A
SIG4: ASTERN(EXP2,ERR2,ERR5,ERR5,ERR1,EXP2)
FRA1: TRO TEMP,1; DECIMAL POINT
SOJ C,
ASTERN(INT1,ERR2,SIG5,SIG6,ERR1,INT1)
SIG5: TRO TEMP,4; NEGATIVE SIGN
SIG6: ASTERN(INT1,ERR2,ERR5,ERR5,ERR1,INT1)
EXP2: HLRE FF,TAB(D); FIRST DIGIT
EXP5: XCT LPSA; GET NEXT CHARACTER
EXP9: HLRE B,TAB(D)
JUMPL B,EEXP; NEGATIVE IF NOT A DIGIT
IMULI FF,12
ADD FF,B
JRST EXP5
XCT LPSA
;;#QD# SEE DONE5: BELOW
EEXP: AHEAD(EXP9,ERR2,DONE5,DONE5,ERR1,EN,EN)
EN: TRNE TEMP,4; SIGN OF EXPONENT
MOVNS FF
ADD C,FF; FIX UP EXPONENT
JOV ERR3
;#QD# CHANGE ALL 'ERR5'S IN AHEAD MACROS DO 'DONE5'S, TO AVOID SNARFING EXTRA
;SIGNS ..... RFS 12-15-73 (TWO PLACES BELOW AND ONE ABOVE ALSO)
DONE5:
DONE: ANDI D,177
JUMPGE TEMP,.+2
SETO D,
POPJ P,
INT1: HLRE A,TAB(D); FIRST DIGIT
TRNE TEMP,4
MOVNS A; NEGATE IF NECESSARY
INT2: XCT LPSA; GET NEXT CHARACTER
INT5: HLRE B,TAB(D)
JUMPL B,EON; NEGATIVE IF NOT A NUMBER
TRNE TEMP,1; IF PASSED DECIMAL POINT THEN DEC EXP BY ONE
SOJ C,
TRNE TEMP,2; IF ENOUGH DIGITS THEN INC EXP BY ONE
INT3: AOJA C,INT2
MOVE X,A
IMULI A,12
TRNE TEMP,4; NEGATE DIGIT IS SIGN NEGATIVE
MOVNS B
ADD A,B
JOV INT4; CHECK FOR OVERFLOW
JRST INT2; IF SO USE LAST VALUE
INT4: TRO TEMP,2
MOVE A,X
JRST INT3
XCT LPSA
EON: AHEAD(INT5,DP1,DONE,DONE,EXP6,DONE,DONE)
DP1: TROE TEMP,1
JRST ERR2
XCT LPSA
;#QD# (SEE DONE5: ABOVE)
AHEAD(INT5,ERR2,DONE5,DONE5,EXP6,DONE,DONE)
EXP6: SETZ TEMP,
XCT LPSA
AHEAD(EXP2,ERR2,EXP7,EXP8,ERR1,ERR1,ERR1)
EXP7: TRO TEMP,4
EXP8: XCT LPSA
;#QD# (SEE DONE5: ABOVE)
AHEAD(EXP2,ERR2,DONE5,DONE5,ERR1,ERR1,ERR1)
ERR1: ERR(<NUMIN: IMPROPER EXPONENT>,1,RZ)
ERR2: ERR(<NUMIN: MISPLACED DECIMAL POINT>,1,RZ)
ERR3: ERR(<NUMIN: EXPONENT OUT OF BOUND>,1,RZ)
ERR5: ERR(<NUMIN: MISPLACED SIGN>,1,RZ)
ERROV: ERR(<NUMIN: NUMBER OUT OF BOUND>,1,RZ)
NUMBAD: ERR<NUMIN: Illegal JFN>
POPJ P,
RZ: SETZ A,
JRST DONE
; Character table for SCAN (Realscan,Intscan,Realin,Intin)
TAB: FOR A IN (0,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,0,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
;#QC# MAKE 32 (CONTROL Z) IGNORED
FOR A IN (5,5,0,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,3,5,2,1,5)<XWD -1,A
>
FOR A IN (0,1,2,3,4,5,6,7,10,11)<XWD A,-1
>
FOR A IN (5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (4,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
FOR A IN (5,5,5,5,5,5,5,5)<XWD -1,A
>
XWD -1,6
ENDCOM(NUM)
COMPIL(TBB,<.CH.,.TEN.,.MT.>,,<TABLES FOR L PAUL'S ROUTINES>)
DSCR DATA TABLES FOR REALIN, INTSCAN, ETC.
⊗
↑↑.CH.: 4
7
16
33
66
153
777777777775
777777777772
777777777763
777777777746
777777777713
777777777626
↑↑.MT.: 240000000000
310000000000
234200000000
276570200000
216067446770
235613266501
314631463147
243656050754
321556135310
253630734215
346453122767
317542172553
↑↑.TEN.: 1
=10
=100
=1000
=10000
=100000
=1000000
=10000000
=100000000
=1000000000
=10000000000
ENDCOM(TBB)
IFN ALWAYS,<
BEND
>;IFN ALWAYS
COMPIL(CAS,<CSERR,LPRYER>,<GOGTAB>
,<CSERR, LPRYER -- SUPPORT ROUTINES>)
HERE(CSERR) MOVE USER,GOGTAB
POP P,UUO1(USER) ;STANDARD PLACE
ERR <CASE INDEX OVERFLOW, VALUE IS >,13
JRST @UUO1(USER) ;RETURN OK
HERE (LPRYER) ERR <DATUM OF ARRAY NOT THERE>,1
POPJ P,
ENDCOM(CAS)
IFN ALWAYS, <BEND IOSER>
DSCR BEND IOSER ⊗
>;TENX