!**DELSTART
!*
!*****RECORDFORMATS****
!*
!*
RECORDFORMAT  DIRINFF(STRING  (6) USER,  C 
   STRING  (31) BATCHFILE,  C 
   INTEGER  MARK, FSYS, PROCNO, ISUFF, REASON, BATCHID,  C 
   SESSICLIM, SCIDENSAD, SCIDENS, OPERNO, AIOSTAT, SCDATE,  C 
   SYNC1DEST, SYNC2DEST, ASYNCDEST, AACCTREC, AICREVS,  C 
   STRING  (15) BATCHIDEN)
 RECORDFORMAT  PDHF(INTEGER  DATAEND, DATASTART, SIZE, FILETYPE,  C 
   SUM, DATETIME, ADIR, COUNT)
 RECORDFORMAT  PDF(INTEGER  START, STRING  (11) NAME,  C 
   INTEGER  HOLE, S5, S6, S7)
RECORDFORMAT  SIGDATAF(INTEGER  PC, LNB, CLASS, SUBCLASS,  C 
   INTEGERARRAY  A(0 : 17))
RECORDFORMAT  DFF(INTEGER  NKB, RUP, EEP, MODE, USE, ARCH, FSYS,  C 
   CONSEG, CCT, CODES, CODES2, SSBYTE, STRING  (6) TRAN)
RECORDFORMAT  RF(INTEGER  CONAD, FILETYPE, DATASTART, DATAEND)
RECORDFORMAT  HF(INTEGER  DATAEND, DATASTART, FILESIZE, FILETYPE,  C 
   SUM, DATETIME, FORMAT, RECORDS)
RECORDFORMAT  FRF(INTEGER  CONAD, FILETYPE, DATASTART, DATEND,  C 
   SIZE, RUP, EEP, MODE, USERS, ARCH,  C 
   STRING  (6) TRAN, STRING  (8) DATE, TIME,  C 
   INTEGER  COUNT, SPARE1, SPARE2)
RECORDFORMAT  CONFF(STRING  (18) FILE,  C 
   INTEGER  CONAD, SIZE, HOLE, MODE, USE)
!*****SPECS OF DIRECTOR ROUTINES*****
EXTERNALINTEGERFNSPEC  DMESSAGE(STRING  (6) USER,  C 
   INTEGERNAME  LEN, INTEGER  ACT, FSYS, ADR)
EXTERNALINTEGERFNSPEC  DASYNCINH(INTEGER  MODE, ATW)
EXTERNALROUTINESPEC  DMONITOR(INTEGER  I)
EXTERNALROUTINESPEC  DRESUME(INTEGER  LNB, PC, AD18)
EXTERNALINTEGERFNSPEC  DFSTATUS(STRING  (6) USER,  C 
   STRING  (11) FILE, INTEGER  FSYS, ACT, VALUE)
ROUTINESPEC  FINFO(STRING  (31) FILE, INTEGER  MODE,  C 
   RECORDNAME  FR, INTEGERNAME  FLAG)
EXTERNALINTEGERFNSPEC  READID(INTEGER  AD)
EXTERNALINTEGERFNSPEC  DSFI(STRING  (6) USER,  C 
   INTEGER  FSYS, TYPE, SET, ADR)
EXTERNALINTEGERFNSPEC  DSETIC(INTEGER  KI)
! %EXTERNALINTEGERFNSPEC DNEWGEN(%STRING (6) USER,  %C
   STRING  (11) FILE, NEWGEN OF FILE, INTEGER  FSYS)
EXTERNALINTEGERFNSPEC  DPERMISSION( C 
   STRING  (6) OWNER, USER, STRING  (8) DATE,  C 
   STRING  (11) FILE, INTEGER  FSYS, TYPE, ADRPRM)
EXTERNALINTEGERFNSPEC  DCHSIZE(STRING  (6) USER,  C 
   STRING  (11) FILE, INTEGER  FSYS, NEWSIZE KB)
EXTERNALROUTINESPEC  DSTOP(INTEGER  REASON)
EXTERNALINTEGERFNSPEC  DCREATE(STRING  (6) USER,  C 
   STRING  (11) FILE, INTEGER  FSYS, NKB, TYPE)
EXTERNALINTEGERFNSPEC  DDESTROY(STRING  (6) USER,  C 
   STRING  (11) FILE, STRING  (6) DATE, INTEGER  FSYS, TYPE)
EXTERNALINTEGERFNSPEC  DDISCONNECT(STRING  (6) USER,  C 
   STRING  (11) FILE, INTEGER  FSYS, DESTROYMODE)
! %EXTERNALINTEGERFNSPEC DRENAME(%STRING (6) USER,  %C
   STRING  (11) OLD, NEW, INTEGER  FSYS)
EXTERNALINTEGERFNSPEC  DFINFO(STRING  (6) USER,  C 
   STRING  (11) FILE, INTEGER  FSYS, ADDR)
EXTERNALINTEGERFNSPEC  DCONNECT(STRING  (6) USER,  C 
   STRING  (11) FILE, INTEGER  FSYS, MODE, APF,  C 
   INTEGERNAME  SEG, GAP)
! %EXTERNALINTEGERFNSPEC DOFFER(%STRING (6) USER, TO,  %C
   STRING  (11) FILE, INTEGER  FSYS)
! %EXTERNALINTEGERFNSPEC DACCEPT(%STRING (6) USER,  %C
   STRING  (11) FILE, NEWNAME, INTEGER  FSYS)
!*
!*
!********SPECS OF SYSTEMROUTINES ELSEWHERE IN SUBSYSTEM*****
!*
!*
SYSTEMSTRINGFNSPEC  ITOS(INTEGER  N)
SYSTEMROUTINESPEC  PHEX(INTEGER  I)
SYSTEMROUTINESPEC  CONSOLE(INTEGER  EP, INTEGERNAME  P1, P2)
SYSTEMROUTINESPEC  CONTROL
!*
!*
!*****SPECS FOR ROUTINES IN THIS FILE****
!*
!*
!*
ROUTINESPEC  CONMEMBER(STRING  (31) FILE,  C 
   STRING  (11) MEMBER, INTEGER  PROTECTION,  C 
   RECORDNAME  R, INTEGERNAME  FLAG)
ROUTINESPEC  DISCONNECT(STRING  (31) FILE, INTEGERNAME  FLAG)
!*
!*
!****CONSTANTS********
!*
!*
EXTERNALINTEGER  SSDATELINKED = 0;         !PROPER VALUE IN GLOBALS
CONSTSTRING (4)LAST="}{|~";       !UNLIKELY PATTERN
CONSTSTRING  (6) SPOOLERNAME = "SPOOLR"
CONSTINTEGER  OPTFILESIZE=4096
CONSTINTEGERNAME  KIPS=X'80C000C0'
CONSTINTEGER  MAXCONF = 63
CONSTINTEGERARRAY  HEX(0 : 15) =   C 
 '0', '1', '2', '3', '4', '5', '6',  C 
  '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
CONSTINTEGER  SSPDFILETYPE = 6
CONSTINTEGER  SSTEMPDIRSIZE = X'4000';  !SIZE OF SESSION DIRECTORY
                                        !MUST BE CONSISTENT WITH COMMAND 'MAKEBASEFILE'
CONSTINTEGER  TEMPMARKER = X'40000000'
CONSTINTEGER  FILESIZEALLOC = 4096;     !SIZE IN BYTES OF FILE SIZE
                                        ! ALLOCATIONS
CONSTINTEGER  APDATE = X'80C0003F';     !ADDR(PUBLIC_DATE)
CONSTINTEGER  APTIME = X'80C0004B';     !ADDR(PUBLIC_TIME)
CONSTINTEGER  ATRANS = X'80C0008F';     !ADDR OF ITOE AND ETOI TABLES
CONSTINTEGER  SEGSIZE = X'40000'
CONSTINTEGER  SEGSHIFT = 18;            !SHIFT TO GIVE SEGMENTS
CONSTINTEGER  ABASEFILE = X'00800000';  !START OF BASEFILE AT SEG 32
CONSTINTEGER  MAXSIGLEVEL = 6
CONSTINTEGER  KSHIFT = 10;              !SHIFT BYTES TO KBYTES
!*
!*
!*
!*****EXTERNAL VARIABLES*****
!*
!*
EXTERNALINTEGER  ASSCOM
EXTERNALINTEGERARRAY  SAVEIDATA(-2 : 20,0:3);!TO HOLD INTERRUPT DATA
EXTERNALINTEGER  SSADEFOPT;             !ADDRESS OF DEFAULT OPTION FILE
EXTERNALINTEGER  BENCHMARK;             !IF SET THEN SUPPRESS OUTPUT TO .LP AND
                                        !START PROCESS FROM MANAGR.F1SCRIPT IF STARTED FROM OPER
EXTERNALINTEGER  INTINPROGRESS = 1;    !SET WHEN INT:A OR INT: C OCCURRS
EXTERNALINTEGER  AIOSTAT;               !ADDRESS OF IOSTAT RECORD
EXTERNALINTEGER  SSADIRINF;             !ADDRESS OF DIRECTOR RECORD
EXTERNALINTEGER  INHIBITSPOOLER
EXTERNALINTEGER  SSASESSDIR;            !ADDRESS OF SESSION DIR
EXTERNALINTEGER  SAVEIDPOINTER
EXTERNALRECORDARRAY  CONF(0 : 63)(CONFF)
EXTERNALINTEGERARRAY  SSCOMREG(0 : 60)
EXTERNALINTEGER  SSINITWORKSIZE = X'40000'
EXTERNALINTEGER  SSMAXWORKSIZE = X'100000'
EXTERNALINTEGER  SSINHIBIT, SSINTCOUNT; !THESE TWO MUST STAY TOGETHER
EXTERNALINTEGER  DIRDISCON = 1;         !SET TO 1 WHEN DIRECTORY DISCONNECTED
EXTERNALINTEGER  SSMAXFSIZE;            !MAXIMUM FILE SIZE ALLOWED
EXTERNALINTEGER  SSATEMPDIR;            !ADDRESS OF  TEMPORARY DIRECTORY
EXTERNALINTEGER  SSCURBGLA;             !CURRENT TOP OF BGLA
EXTERNALINTEGER  SSMAXBGLA;             !LAST BYTE OF BGLA
EXTERNALINTEGER  SSSCCOUNT
EXTERNALINTEGER  SSSCTABLE;             !ADDRESS OF SCTABLE
EXTERNALINTEGER  SSOPERNO;              !NO OF OPER STARTED FROM
EXTERNALINTEGER  SSREASON;              !REASON FOR STARTING
                                        ! 0=INTERACTIVE
                                        !1=STARTED FROM OPER.    2=BATCH
EXTERNALINTEGER  SSOWNFSYS;             !FSYS FOR THIS USER
EXTERNALSTRING  (1) SSSUFFIX;           !ADDED TO NAMES OF TEMP FILES
EXTERNALSTRING  (6) SSOWNER
EXTERNALSTRING  (40) SSFNAME;           !NAME FOR PSYSMES
!*
!*
!**DELEND
!******OWNS******
!*
!*
OWNINTEGER  CURFSYS
OWNSTRING  (6) CURFOWNER
OWNSTRING  (11) CURFNAME
OWNSTRING  (18) CURFILE
OWNSTRING  (11) CURMEMBER
OWNINTEGER  ABGLA;                      !START OF BGLA
OWNSTRING  (31) BASEFILE
OWNRECORDARRAY  SIGDATA(1 : 6)(SIGDATAF)
                                        !CURRENT MAX OF 4
OWNINTEGER  LATEST;                     !IMPOSSIBLE VALUE
!*
!***END OF DECLARATIONS
!*
!*
!*

SYSTEMINTEGERFN  DIRTOSS(INTEGER  FLAG)
                                        !RESULT IS SUBSYSTEM FAULT
                                        ! NUMBER EQUIV TO DIRECTOR
                                        ! FAULT NO
CONSTBYTEINTEGERARRAY  DSS(1 : 52) =   C 
 1, 2, 3, 4, 5, 173, 7, 8, C 
            174, 175, 
          11, 12, 13, 14, 176, 119, 176, 120, 19, 173, 
          21, 22, 23, 177, 178, 26, 27, 28, 29, 30, 
          177, 118, 179, 34, 35, 176, 203, 156, 156, 178, 
          180, 178, 176, 44, 45, 46, 47, 48, 181, 182, 
          183, 52
CONSTINTEGER  MAXDSS = 52
   IF  FLAG = 0 THEN  RESULT  = 0;      !MOST LIKELY RESULT
   IF  1 <= FLAG <= MAXDSS THEN  START 
      FLAG = DSS(FLAG)
      IF  FLAG < 100 THEN  FLAG = FLAG+500 ELSE  FLAG = FLAG+100
                                        !DIRECTOR FAILURES 501-599
   FINISH  ELSE  FLAG = FLAG+500
   RESULT  = FLAG
END ;                                   !OF DIRTOSS
!***********************************************************************
!*                                                                     *
!* THESE FUNCTIONS ALL USE A PACKED FORMAT OF DATE AND TIME OF THE     *
!* FOLLOWING FORM. BITS ARE NUMBERED FROM 31 (MOST SIGNIFICANT) TO     *
!* 0 (LEAST SIGNIFICANT)                                               *
!* BITS    USE                                                         *
!* 31-26  YEAR-70  (VALID FOR 1970-2033)                               *
!* 25-22  MONTH                                                        *
!* 21-17  DAY                                                          *
!* 16-12  HOUR                                                         *
!* 11- 6  MINUTE                                                       *
!*  5- 0  SECOND                                                       *
!*                                                                     *
!***********************************************************************

INTEGERFN  I2(INTEGER  AD)
                                        !AD POINTS TO THE FIRST OF A PAIR OF DECIMAL CHARACTERS. THE RESULT
                                        !IS THE NUMERIC VALUE OF THE CHAS
   RESULT  = 10*(BYTEINTEGER(AD)&X'F')+(BYTEINTEGER(AD+1)&X'F')
END ;                                   !OF I2

INTEGERFN  PACKDATE(STRING  (8) DATE)
INTEGER  AD
   AD = ADDR(DATE)
   RESULT  = ((I2(AD+7)-70)<<26)!(I2(AD+4)<<22)!(I2(AD+1)<<17)
END ;                                   !OF PACKDATE

INTEGERFN  PACKDATEANDTIME(STRING  (8) DATE, TIME)
INTEGER  AT
   AT = ADDR(TIME)
   RESULT  = PACKDATE(DATE)!(I2(AT+1)<<12)!(I2(AT+4)<<6)!(I2( C 
      AT+7))
END ;                                   !OF PACKDATEANDTIME

SYSTEMINTEGERFN  ROUNDUP(INTEGER  N, ROUND)
                                        !RESULT IS N ROUNDED UP TO
                                        ! MULTIPLE OF ROUND >=N
   ROUND = ROUND-1
   RESULT  = (N+ROUND)&(¬ROUND);        ! AND WITH NOT ROUND
END ;                                   !OF ROUNDUP

SYSTEMROUTINE  MOVE(INTEGER  LENGTH, FROM, TO)
   *LB_LENGTH
   *JAT_14,<L99>
   *LDTB_X'18000000'
   *LDB_B 
   *LDA_FROM
   *CYD_0
   *LDA_TO
   *MV_L =DR 
L99:

END ;                                   !OF MOVE

SYSTEMROUTINE  FILL(INTEGER  LENGTH, FROM, FILLER)
   *LB_LENGTH
   *JAT_14,<L99>;                       !RETURN IF LENGTH<=0
   *LDTB_X'18000000'
   *LDB_B 
   *LDA_FROM
   *LB_FILLER
   *MVL_L =DR 
L99:

END ;                                   !OF FILL

SYSTEMROUTINE  ITOE(INTEGER  AD, L)
INTEGER  J
   J = SSCOMREG(12);                    !ADDR OF ITOE TABLE IN PUBLIC SEGMENT
   *LB_L
   *JAT_14,<L99>
   *LDTB_X'18000000'
   *LDB_B 
   *LDA_AD
   *LSS_J
   *LUH_X'18000100'
   *TTR_L =DR 
L99:

END ;                                   !OF ITOE

SYSTEMROUTINE  ETOI(INTEGER  AD, L)
INTEGER  J
   J = SSCOMREG(11);                    !ADDR OF ETOI TABLE IN PUBLIC SEGMENT
   *LB_L
   *JAT_14,<L99>
   *LDTB_X'18000000'
   *LDB_B 
   *LDA_AD
   *LSS_J
   *LUH_X'18000100'
   *TTR_L =DR 
L99:

END ;                                   !OF ETOI

SYSTEMROUTINE  ALLOW INTERRUPTS
INTEGER  I
   SSINHIBIT = 0;                       !TO ALLOW INTERRUPTS AGAIN
   WHILE  SSINTCOUNT > 0 THEN  I = DASYNCINH(1,0);!TAKE ANY OUTSTANDING ONES
END ;                                   !OF ALLOW INTERRUPTS

SYSTEMROUTINE  SIGNAL(INTEGER  EP, P1, P2, INTEGERNAME  FLAG)
RECORDNAME  D(SIGDATAF)
INTEGERNAME  SIGLEVEL
INTEGER  LNB, AD18, PC, I
SWITCH  SW(-1 : 6)
   FLAG = 0;                            !DEFAULT
   SIGLEVEL == SSCOMREG(34)
   UNLESS  -1 <= EP <= 6 THEN  FLAG = 1 AND  -> ERR
   -> SW(EP)
    SW(-1):
SW(0):

   UNLESS  0 <= SIGLEVEL < MAXSIGLEVEL THEN  FLAG = 1 AND  -> ERR
                                        !SIGNAL STACK FULL
   SIGLEVEL = SIGLEVEL+1
   D == SIGDATA(SIGLEVEL)
   D_PC = P1;                           !PROGRAM COUNTER
   D_LNB = P2;                          !LOCAL NAME BASE
   -> ERR
SW(1):                                  !UNSTACK
   UNLESS  0 < SIGLEVEL <= MAXSIGLEVEL THEN  FLAG = 1 AND  -> ERR
   IF  P1 = 0 THEN  SIGLEVEL = SIGLEVEL-1 ELSE  SIGLEVEL = 0
   -> ERR
SW(2):                                  !SIGNAL ERROR AT CURRENT LLEVEL
   IF  MAXSIGLEVEL >= SIGLEVEL > 0 C 
      THEN  I = SIGLEVEL AND  SIGLEVEL = SIGLEVEL-1 C 
      ELSE  DSTOP(101)
                                        !SIGNAL STACK EMPTY
   -> COMMON
SW(3):

   UNLESS  0 < SIGLEVEL <= MAXSIGLEVEL THEN  DSTOP(102)
                                        !NO CONTS STACKED
   I = 1;                               !SIGNAL AT OUTER LEVEL
COMMON:

   D == SIGDATA(I)
   LATEST = I;                          !POINTS TO LAST USED LEVEL
   *STLN_LNB;                           !STORE LOCAL NAME BASE
   D_CLASS = P1;                        !CLASS OF ERROR
   D_SUBCLASS = P2
   IF  P1 > 70 START ;                  !SOFTWARE GEN FAULT
      D_A(0) = INTEGER(LNB);            !OLD LNB
      D_A(2) = INTEGER(LNB+8);          !OLD PC
   FINISH 
   PC = D_PC
   LNB = D_LNB
   AD18 = ADDR(D_CLASS)
   DRESUME(LNB,PC,AD18)
   DSTOP(117);                          !SHOULD NEVER GET HERE
SW(4):                                  !REPEAT LAST CONTINGENCY
   IF  SIGLEVEL # LATEST > 0 C 
      THEN  MOVE(72,ADDR(SIGDATA(LATEST)_CLASS),ADDR(SIGDATA( C 
      SIGLEVEL)_CLASS))
   SIGLEVEL = SIGLEVEL-1
   -> COMMON
SW(5):

   MONITOR 
   STOP 
SW(6):

   INTEGER(P1) = SIGLEVEL
ERR:

END ;                                   !OF SIGNAL

SYSTEMROUTINE  DIRTRAP(INTEGER  CLASS, SUBCLASS)
INTEGER  FLAG, LNB, SIGNALAT
INTEGERARRAY  IDATA(0 : 17)
INTEGERNAME  SIGLEVEL
RECORDNAME  D(SIGDATAF)
   SIGNALAT = 2;                        !NORMALLY SIGNALAT CURRENT LEVEL
   SIGLEVEL == SSCOMREG(34)
   UNLESS  0 < SIGLEVEL <= MAXSIGLEVEL THEN  DSTOP(103)
   FLAG = READID(ADDR(IDATA(0)));       !READ INTERRUPT DATA
                                        ! NOW FRIG DISPLAY FOR THIS
                                        ! ROUTINE BECAUSE IT MIGHT BE
                                        ! USED 
                                        !BY ONCOND IN NDIAGS
   *STLN_LNB;                           !CURRENT LNB
   INTEGER(LNB+4) = X'E1000000'!(IDATA(1)&X'FFFFFF')
                                        !CODE DESCRIPTOR WITH PART OF PSR
   IF  CLASS = 64 START ;               !IC OVERFLOW
      FLAG = DSETIC(30000);             !GET 1 MIN NOW  
   FINISH 
   IF  CLASS = 65 START ;               !INTERRUPT FROM USER
      IF  SUBCLASS = 'Y' THEN  DSTOP(113)
                                        !INT:Y - GENERATED BY FEP TO
                                        ! CAUSE LOG-OFF
IF  INTINPROGRESS#0 THEN  ->CONTINUE
     IF  SUBCLASS='T' START 
INTINPROGRESS=1
 CONSOLE(12,FLAG,FLAG)
INTINPROGRESS=0
->CONTINUE
FINISH 
      IF  ('Q' # SUBCLASS # 'A' AND  SUBCLASS # 'C') THEN ->CONTINUE
                                        !IGNORE SINGLE CHAR INTS
                                        ! APART FROM  A,C AND Q  PROTEM
                                        !IGNORE EVEN THEM IF INT:A OR INT:C STILL BEING HANDLED
      IF  SUBCLASS # 'Q' START 
         SIGNALAT = 3;                  !INT:A AND INT:C AT OUTER LEVEL
         INTINPROGRESS = 1;            !TO INDICATE THAT AN INT:A OR AN INT:C IS BEING HANDLED
      FINISH 
   FINISH 
   IF  CLASS = 66 START ;               !MESSAGE FROM OPERATOR
      CONSOLE(6,FLAG,FLAG);             !SEND CONSOLE OUTPUT REQUEST
      DRESUME(0,0,ADDR(IDATA(0)));      !GO ON WHERE WE LEFT OFF
   FINISH 
   IF  SIGNALAT = 2 START 
      D == SIGDATA(SIGLEVEL);           !MOVE IDATA TO ARRAY
      MOVE(72,ADDR(IDATA(0)),ADDR(D_A(0)))
      MOVE(72,ADDR(IDATA(0)),ADDR(SAVEIDATA(0,SAVEIDPOINTER)))
                                        !MOVE INTO SAVEIDATA
      SAVEIDATA(-2,SAVEIDPOINTER) = CLASS
      SAVEIDATA(-1,SAVEIDPOINTER) = SUBCLASS
      MOVE(9,APTIME,ADDR(SAVEIDATA(18,SAVEIDPOINTER)))
                                        !PUT TIME INTO RECORD
      SAVEIDPOINTER = (SAVEIDPOINTER+1)&3
   FINISH 
   SIGNAL(SIGNALAT,CLASS,SUBCLASS,FLAG)
CONTINUE:
         DRESUME(0,0,ADDR(IDATA(0)));       !GO ON WHERE INTERRUPTED
END ;                                   !OF DIRTRAP

SYSTEMROUTINE  QUIT
                                        !CALL DIRECTOR STOP TO STOP
                                        ! PROCESS
   DSTOP(100)
END ;                                   !OF QUIT

SYSTEMINTEGERFN  CHECKFILENAME(STRING  (31) FILE, INTEGER  TYPE)
                                        !CHECKS FILENAME ACCORDING TO
                                        ! TYPE
                                        !2**0 OWN FILE - STD NAME
                                        !2**1 ANY FILE - STD NAME
                                        !2**2  ANY NAME (INCLUDING #)
                                        !2**3 PD MEMBERNAME
                                        !IF OK PUTS OWNER AND NAME
                                        ! BACK IN CUFOWNER,CURFNAME
                                        ! AND CURFILE
                                        !  WITH NO CHANCE OF CAPACITY
                                        ! EXCEEDED
INTEGER  I, CHAR, LENN
STRING  (18) OWNER, NAME, MEMBER
   IF  FILE = LAST THEN  RESULT  = 0;    !CURRENT FILE
   IF  LENGTH(FILE) > 30 THEN  RESULT  = 220
                                        !INVALID FILENAME
    IF  FILE -> FILE.("_").MEMBER START 
                                         !FILE INCLUDES MEMBERNAME
       IF  TYPE&8 # 8 THEN  RESULT  = 269
                                         !ILLEGAL USE OF PDFILE MEMBER
    FINISH  ELSE  MEMBER = ""
   IF  LENGTH(FILE) > 18 THEN  RESULT  = 220
                                        !INVALID FILENAME
   UNLESS  FILE -> OWNER.(".").NAME C 
      THEN  OWNER = SSOWNER AND  NAME = FILE
   IF  LENGTH(OWNER) # 6 THEN   SSFNAME=OWNER AND  RESULT  = 201
                                        !INVALID OWNER
   LENN = LENGTH(NAME)
   IF  2 <= LENN AND  CHARNO(NAME,1) = 'T' C 
      AND  CHARNO(NAME,2) = '#' THEN  NAME = NAME.SSSUFFIX
                                        !T# NAME MUST HAVE PROC SUFFIX APPENDED -
                                        !THIS AUTOMATICALLY DEALS WITH MULTIPLE LOG-ONS TO SAME USER
   UNLESS  1 <= LENN <= 11 THEN  RESULT  = 220
                                        !INVALID FILENAME
                                        !INVALID NAME
!    %IF TYPE&2 = 0 %AND OWNER # SSOWNER %THEN %RESULT = 258
                                        !NOT OWN FILE
   IF  TYPE&1 = 0 AND  OWNER = SSOWNER THEN  RESULT  = 259
                                        !OWN FILE NOT ALLOWED
   I = 1
   WHILE  I < LENN CYCLE ;              !LOOK FOR VALID CHAS
      I = I+1
      CHAR = CHARNO(NAME,I)
      UNLESS  'A' <= CHAR <= 'Z' OR  '0' <= CHAR <= '9' C 
         OR  (TYPE&4 = 4 AND  CHAR = '#') THEN  RESULT  = 220
                                        !INVALID FILENAME
   REPEAT 
   IF  MEMBER # "" START 
      LENN = LENGTH(MEMBER)
      UNLESS  1 <= LENN <= 11 THEN  SSFNAME=MEMBER AND  RESULT  = 270
                                        !INVALID MEMBER
      I = 1
      WHILE  I < LENN CYCLE 
         I = I+1
         CHAR = CHARNO(MEMBER,I)
         UNLESS  'A' <= CHAR <= 'Z' OR  '0' <= CHAR <= '9' C 
            THEN  SSFNAME=MEMBER AND  RESULT  = 270
      REPEAT 
   FINISH 
   CURFOWNER = OWNER
   CURFNAME = NAME
   CURFILE = OWNER.".".NAME;            !RETURN FILE IN STANDARD FORM
   CURMEMBER = MEMBER
   IF  CURFOWNER = SSOWNER THEN  CURFSYS = SSOWNFSYS C 
      ELSE  CURFSYS = -1
   RESULT  = 0
END ;                                   !OF CHECKFILENAME

INTEGERFN  HASHFN(STRING  (31) FILENAME)
                                        !RETURNS VALUE IN THE RANGE
                                        ! 0-MAXCONF FOR FINDING ENTRY IN THE
                                        !CONNECTED FILE TABLE. A
                                        ! BETTER ALGORITH COULD BE
                                        ! DEVISED.
INTEGER  EIGHTH, LASTCHAR
   EIGHTH = CHARNO(FILENAME,8);         !FIRST CHAR OF FILENAME(AFTER
                                        ! USER.)
   LASTCHAR = CHARNO(FILENAME,LENGTH(FILENAME))
   RESULT  = ((EIGHTH&7)!(LASTCHAR<<3))&MAXCONF
END ;                                   !OF HASHFN

INTEGERFN  FINDFN(STRING  (31) FILE, INTEGERNAME  POS)
                                        !LOOK FOR FILE IN CONF. SET
                                        ! POS TO POSITION OR TO POSITION
                                        !OF HOLE IF NOT FOUND.
                                        ! RESULT=0 IF FOUND
                                        !IF FILENAME IS "EMPTY" THEN
                                        ! POSITION CAN BE RE-USED. IT HAS
                                        !TO BE LEFT LIKE THIS TO
                                        ! PREVENT A SEARCH CHAIN
                                        ! BEING BROKEN
INTEGER  EMPTY, STARTPOS
STRING  (31) HOLDFILE
   EMPTY = -1;                          !IMPOSSIBLE VALUE
   POS = HASHFN(FILE)
   STARTPOS = POS
   CYCLE 
      HOLDFILE = CONF(POS)_FILE
      IF  HOLDFILE = FILE THEN  RESULT  = 0
      IF  HOLDFILE = "" START ;         !GOT TO END OF CHAIN
         IF  EMPTY # -1 THEN  POS = EMPTY
         RESULT  = 1;                   !FILE NOT FOUND - POS POINTS
                                        ! TO FREE HOLE
      FINISH 
      IF  HOLDFILE = "EMPTY" AND  EMPTY = -1 THEN  EMPTY = POS
                                        !FIRST EMPTY CELL IN CHAIN
      POS = (POS+1)&MAXCONF;            !WRAP ROUND AT TOP OF CONF
      IF  POS = STARTPOS START ;        !GONE RIGHT ROUND
         IF  EMPTY = -1 THEN  RESULT  = 310; !TOO MANY FILES CONNECTED
         POS = EMPTY;                   !USE FIRST EMPTY HOLE FOUND
         RESULT  = 1;                   !FILE NOT CONNECTED
      FINISH 
   REPEAT 
END ;                                   !OF FINDFN

ROUTINE  CLEARFN(INTEGER  POS)
!CLEARS OUT ENTRY POS IN ARRAYCONF. ALSO CLEARS ANY PRECEEDING
! "EMPTY" SLOTS IF THE NEXT ONE IS EMPTY. USED BY DISCONNECT,
!CHANGEFILESIZE AND CHANGEACCESS.
RECORDNAME  CUR(CONFF)
   CUR == CONF(POS)
   CUR = 0
   IF  CONF((POS+1)&MAXCONF)_FILE = "" START 
      CYCLE ;                           !NOW CLEAR ANY REMAINING
                                        ! "EMPTY" CELLS
         POS = (POS-1)&MAXCONF;         !NEXT LOWER - WITH WRAP ROUND
         EXIT  IF  CONF(POS)_FILE # "EMPTY"
         CONF(POS) = 0;                 !NOW SAFE TO CLEAR IT OUT
      REPEAT 
   FINISH  ELSE  CUR_FILE = "EMPTY"
                                        !TO KEEP CHAIN TOGETHER
END ;                                   !OF CLEARFN

SYSTEMSTRINGFN  CONFILE(INTEGER  AD)
                                        !RETURNS NAME OF FILE
                                        ! CONNECTED AT VIRTUAL
                                        ! ADDRESS "AD"
                                        !ELSE NULL STRING
STRING  (18) RES
INTEGER  P
RECORDNAME  CUR(CONFF)
   CYCLE  P = 0,1,MAXCONF;              !CYCLE THROUGH CONNECTED FILE
                                        ! TABLE
      CUR == CONF(P)
      IF  CUR_CONAD <= AD < CUR_CONAD+CUR_SIZE START 
         IF  CUR_FILE = "EMPTY" THEN  EXIT 
         RES = CUR_FILE;                !THE NAME OF THE CONNECTED FILE
         IF  LENGTH(RES) > 8 AND  FROMSTRING(RES,8,9) = "T#" C 
            THEN  LENGTH(RES) = LENGTH(RES)-1
         !TRUNCATE SUFFIX
         RESULT  = RES
      FINISH 
   REPEAT 
   RESULT  = "";                        !NO FILE THERE
END ;                                   !OF CONFILE



SYSTEMROUTINE  SETUSE(STRING  (31) FILE, INTEGER  MODE, VALUE)
!***********************************************************************
!*                                                                     *
!* This routine is used to modify the USE field in the CONNECT record: *
!* Mode=0 Set use to value                                             *
!* Mode=1 Add 1 to use Mode=-1 Subtract 1 from use                     *
!*                                                                     *
!***********************************************************************
RECORDNAME  CUR(CONFF)
INTEGER  POS, FLAG
   FLAG = CHECKFILENAME(FILE,15);       !ANY INCLUDING PD MEMBER
   -> ERR IF  FLAG # 0;                 !INVALID FILENAME
   FLAG = FINDFN(CURFILE,POS)
   -> ERR IF  FLAG # 0;                 !NOT CONNECTED
   CUR == CONF(POS)
   IF  MODE = 0 THEN  CUR_USE = VALUE AND  -> ERR;!USE VALUE PROVIDED
   IF  MODE = 1 THEN  CUR_USE = CUR_USE+1  AND  -> ERR
                                        !ADD ONE
   IF  MODE = -1 AND  CUR_USE > 0 THEN  CUR_USE = CUR_USE-1
                                        !SUBTRACT ONE
ERR:

END ;                                   !OF SETUSE
SYSTEMROUTINE  CONNECT(STRING  (31) FILE,  C 
   INTEGER  MODE, HOLE, PROT, RECORDNAME  R, INTEGERNAME  FLAG)
RECORDNAME  H(HF);                      !FILE HEADER 
RECORDNAME  CUR(CONFF)
RECORD  FR(FRF)
RECORDSPEC  R(RF)
INTEGER  CONSEG, POS
   R = 0;                               !CLEAR OUT RECORD
   FLAG = CHECKFILENAME(FILE,15);       !ANY FILE NAME INCLUDING PD
                                        ! MEMBER
   -> ERR IF  FLAG # 0
    IF  CURMEMBER # "" START ;           !MEMBER OF PDFILE
       IF  MODE&1 = 1 THEN  FLAG = 271 AND  -> ERR
                                         !ATTEMPT TO WRITE TO MEMBER
                                         ! OF PDFILE
       CONMEMBER(CURFILE,CURMEMBER,PROT,R,FLAG)
       -> ERR
    FINISH 
                                        !LOOK IN TABLE OF CURRENTLY
                                        ! CONNECTED FILES
   FLAG = FINDFN(CURFILE,POS);          !0=FILE ALREADY CONNECTED
   -> ERR IF  FLAG > 1;                 !0=CONNECTED,1=NOT CONNECTED, >1 FAILURE
   CUR == CONF(POS)
   IF  PROT&X'80' # 0 THEN  CURFSYS = (PROT>>8)&X'FF'
                                        !USER HAS SPECIFIED FILE SYSTEM
   IF  FLAG # 0 START ;                 !FILE NOT CONNECTED SO CONNECT IT
      FINFO(LAST,0,FR,FLAG);             !GET FILEINFO TO GET SIZE
      -> ERR IF  FLAG # 0;              !FINFO FAILS
      HOLE = ROUNDUP(HOLE,SEGSIZE)>>SEGSHIFT
                                        !HOLE IN SEGMENTS
      CONSEG = 0;                       !ALLOW DIRECTOR TO CHOOSE HOLE
      IF  CURFNAME = "T#US".SSSUFFIX THEN  MODE = MODE!X'80'
                                        !TEMP
      SSINHIBIT = 1;                    !HOLD OFF INTERRUPTS
      FLAG = DCONNECT(CURFOWNER,CURFNAME,CURFSYS,MODE!1,0, C 
         CONSEG,HOLE)
                                        !ALWAYS INCLUDE READ PROTEM   
      FLAG = DIRTOSS(FLAG)
      IF  FLAG # 0 THEN  SSFNAME = CURFILE AND  -> ERR
      CUR = 0
      CUR_FILE = CURFILE
      CUR_SIZE = FR_SIZE;               !PHYSICAL SIZE FROM FINFO RECORD
      CUR_CONAD = CONSEG<<SEGSHIFT
                                        !CONNECT ADDRESS
      CUR_HOLE = HOLE<<SEGSHIFT
      CUR_MODE = MODE!1;                !ALWAYS INCLUDE READ
      CUR_USE = 0
   FINISH  ELSE  START 
                                        !MUST BE CONNECTED ALREADY -
                                        ! CHECK MODE AND HOLE
      IF  0 # MODE&X'F' # CUR_MODE&X'F' OR  HOLE > CUR_HOLE START 
                                        !ONLY COMPARE SIGNIF.MODES
         DISCONNECT(LAST,FLAG);          !NO CHANGE ACCESS AVAILABLE YET
         -> ERR IF  FLAG # 0
         CONNECT(LAST,MODE,HOLE,PROT,R,FLAG)
                                        !RECONNECT 
         -> ERR
      FINISH 
   FINISH 
                                        ! MODE AND HOLE OK - NOW MOVE
                                        ! INFO FROM CUR INTO RECORD R
   R_CONAD = CUR_CONAD;                 !CONNECT ADDRESS
   H == RECORD(CUR_CONAD);              !MAP H ONTO FILE HEADER
   R_FILETYPE = H_FILETYPE
   R_FILETYPE = 3 IF  H_FILETYPE = 0
   R_DATASTART = H_DATASTART
   R_DATAEND = H_DATAEND
   CUR_USE = CUR_USE!(PROT&X'7F');      !SIMPLE PROTECTION FACILITY
   IF  MODE&2 = 2 AND  H_DATASTART >= 32 START 
                                        !EXPLICIT CONNECT IN WRITE MODE
                                        !AND HEADER AT LEAST 32 BYTES
                                        ! LONG
      H_DATETIME = PACKDATEANDTIME(STRING(APDATE),STRING( C 
         APTIME))
   FINISH 
ERR:

   ALLOW INTERRUPTS
END ;                                   !OF CONNECT

SYSTEMROUTINE  FINFO(STRING  (31) FILE, INTEGER  MODE,  C 
   RECORDNAME  FR, INTEGERNAME  FLAG)
RECORD  DF(DFF)
RECORDSPEC  FR(FRF)
   FLAG = CHECKFILENAME(FILE,7);        !ANY FILENAME
   -> ERR IF  FLAG # 0
   FR = 0;                              !CLEAR WHOLE RECORD
   IF  MODE = 1 START ;                 !MUST CONNECT
      CONNECT(LAST,0,0,0,FR,FLAG)
                                        !ANY MODE
      -> ERR IF  FLAG # 0
   FINISH 
   FLAG = DFINFO(CURFOWNER,CURFNAME,CURFSYS,ADDR(DF))
   FLAG = DIRTOSS(FLAG)
   -> ERR IF  FLAG # 0
                                        !FILL IN INFO FROM DFINFO CALL
   FR_SIZE = DF_NKB<<KSHIFT;            !PHYSICAL SIZE IN BYTES
   FR_RUP = DF_RUP;                     !REQUESTING USERS PERMISSION
   FR_EEP = DF_EEP;                     !EVERYONE ELSE"S PERMISSION
   FR_MODE = DF_MODE;                   !CONNECT MODE
   FR_CONAD = DF_CONSEG<<SEGSHIFT
                                        !CONNECT ADDRESS
   FR_USERS = DF_USE
   FR_ARCH = (DF_ARCH&X'80')!((DF_CODES&X'10')>>4)
                                        !ARCHIVE WORD
                                        !WITH CHERISH BIT IN 2**0
   FR_TRAN = DF_TRAN;                   !ON OFFER TO
ERR:

   IF  FLAG # 0 THEN  SSFNAME = CURFILE
END ;                                   !OF FINFO

SYSTEMROUTINE  DISCONNECT(STRING  (31) FILE, INTEGERNAME  FLAG)
RECORDNAME  CUR(CONFF)
INTEGER  POS
   FLAG = CHECKFILENAME(FILE,7);        !ANY FILE
   -> ERR IF  FLAG # 0
   FLAG = FINDFN(CURFILE,POS)
   IF  FLAG = 0 START ;                 !FILE IS CONNECTED
      CUR == CONF(POS)
      IF  INTEGER(CUR_CONAD+12) = 2 THEN  DIRDISCON = 1
                                        !TO WARN LOADER THAT A DIRECTORY HAS BEEN DISCONNECTED
      IF  CUR_USE#0 THEN  FLAG = 266 AND  -> ERR
                                        !NEVER DISCONNECT
      SSINHIBIT = 1;                    !HOLD OFF INTERRUPTS
      FLAG = DDISCONNECT(CURFOWNER,CURFNAME,CURFSYS,0)
      FLAG = DIRTOSS(FLAG)
      CLEARFN(POS);                     !CLEAR IT OUT OF ARRAY CONF
   FINISH  ELSE  FLAG = 256 AND  SSFNAME = CURFILE
                                        !FILE NOT CONNECTED
ERR:

   ALLOW INTERRUPTS
END ;                                   !OF DISCONNECT

SYSTEMROUTINE  SDISCONNECT(STRING  (31) FILE,  C 
   INTEGER  FSYS, INTEGERNAME  FLAG)
!***********************************************************************
!*                                                                     *
!* SDISCONNECT provided for JOBBER and JOURNAL allows for              *
!* disconnection of a particular file on a particular FSYS. It is      *
!* used in conjunction with a facility in CONNECT which allows the     *
!* user to specify the FSYS of the file he wishes to connect.          *
!*                                                                     *
!***********************************************************************
   FLAG = CHECKFILENAME(FILE,7);        !ANY FILE
   -> ERR IF  FLAG # 0
   CURFSYS = FSYS;                      !USER SUPPLIES FSYS
   DISCONNECT(LAST,FLAG);                !TO ENSURE USE OF CORRECT CURFSYS
ERR:

END ;                                   !OF SDISCONNECT

SYSTEMROUTINE  DESTROY(STRING  (31) FILE, INTEGERNAME  FLAG)
   FLAG = CHECKFILENAME(FILE,5);        !ANY OWN FILE
   -> ERR IF  FLAG # 0
   DISCONNECT(LAST,FLAG);                !IGNORE FLAG AT PRESENT
   FLAG = DDESTROY(CURFOWNER,CURFNAME,"",CURFSYS,0)
   FLAG = DIRTOSS(FLAG)
ERR:

   IF  FLAG # 0 THEN  SSFNAME = CURFILE
END ;                                   !OF DESTROY

! %SYSTEMROUTINE RENAME(%STRING (31) FILE, NEWFILE,  %C
!    %INTEGERNAME FLAG)
! %STRING (11) NEWNAME
!    FLAG = CHECKFILENAME(NEWFILE,5)
!                                         !CHECK NEWNAME FIRST
!    -> ERR %IF FLAG # 0
!    NEWNAME = CURFNAME;                  !HOLD NEWNAME
!    FLAG = CHECKFILENAME(FILE,5);        !NOW CHECK OLD NAME
!    -> ERR %IF FLAG # 0
!    DISCONNECT(LAST,FLAG);                !IGNORE FLAG PROTEM
!    FLAG = DRENAME(CURFOWNER,CURFNAME,NEWNAME,CURFSYS)
!    FLAG = DIRTOSS(FLAG)
! ERR:
! 
! %END;                                   !OF RENAME
! 
! %SYSTEMROUTINE NEWGEN(%STRING (31) FILE, NEWFILE,  %C
!    %INTEGERNAME FLAG)
! %STRING (11) NEWNAME
!    FLAG = CHECKFILENAME(NEWFILE,5)
!                                         !CHECK NEWNAME FIRST
!    -> ERR %IF FLAG # 0
!    DISCONNECT(LAST,FLAG);                !TRY AND DISCONNECT - IGNORE FLAG
!    NEWNAME = CURFNAME;                  !HOLD NEWNAME
!    FLAG = CHECKFILENAME(FILE,5)
!    -> ERR %IF FLAG # 0
!    DISCONNECT(LAST,FLAG);                !MUST DISCONNECT IF CONNECTED
!    -> ERR %UNLESS FLAG = 0 %OR FLAG = 256
!                                         !OK OR NOT CONNECTED
!    FLAG = DNEWGEN(CURFOWNER,NEWNAME,CURFNAME,CURFSYS)
!    FLAG = DIRTOSS(FLAG)
! ERR:
! 
! %END;                                   !OF NEWGEN
! 
! %SYSTEMROUTINE OFFER(%STRING (31) FILE,  %C
!    %STRING (6) TO, %INTEGERNAME FLAG)
!    FLAG = CHECKFILENAME(FILE,5)
!    -> ERR %IF FLAG # 0
!    DISCONNECT(LAST,FLAG);                !IGNORE FLAG
!    FLAG = DOFFER(CURFOWNER,TO,CURFNAME,CURFSYS)
!    FLAG = DIRTOSS(FLAG)
! ERR:
! 
! %END;                                   !OF OFFER
! 
! %SYSTEMROUTINE ACCEPT(%STRING (31) FILE, NEWNAME,  %C
!    %INTEGERNAME FLAG)
! %STRING (6) OWNER
! %STRING (11) NAME
! %INTEGER FSYS
!    FLAG = CHECKFILENAME(FILE,6);        !ANY NAME EXCEPT OWN
!    -> ERR %IF FLAG # 0
!    OWNER = CURFOWNER
!    NAME = CURFNAME;                     !HOLD FOR USE IN CALL OF DACCEPT
!    FSYS = CURFSYS
!    %IF NEWNAME # "" %START;             !NEW NAME TO BE GIVEN TO FILE
!       FLAG = CHECKFILENAME(NEWNAME,5)
!                                         !ANY OWN FILE
!       -> ERR %IF FLAG # 0
!    %FINISH
!    NEWNAME = CURFNAME;                  !PROTEM - DEFAULT VALUE OF
!                                         ! NEWNAME IS SAME AS ORIGINAL
!                                         ! CURFNAME
!    FLAG = DACCEPT(OWNER,NAME,NEWNAME,FSYS)
!    FLAG = DIRTOSS(FLAG)
! ERR:
! 
! %END;                                   !OF ACCEPT
 SYSTEMROUTINE  FSTATUS(STRING  (31)FILE, INTEGER  ACT, VALUE C 
  INTEGERNAME  FLAG)
FLAG = CHECKFILENAME(FILE,5);           !ANY OWN FILE
-> ERR IF  FLAG # 0
FLAG = DFSTATUS(SSOWNER,CURFNAME,SSOWNFSYS,ACT,VALUE)
FLAG = DIRTOSS(FLAG)
ERR:
IF  FLAG#0 THEN  SSFNAME=FILE

END ;                                   !OF FSTATUS

SYSTEMROUTINE  PERMIT(STRING  (31) FILE,  C 
   STRING  (6) USER, INTEGER  MODE, INTEGERNAME  FLAG)
INTEGER  TYPE
   IF  FILE # "" START ;                !PERMIT 1 FILE
      FLAG = CHECKFILENAME(FILE,5)
                                        !ANY OWN FILE
      -> ERR IF  FLAG # 0
      FILE = CURFNAME;                  !FILE USED IN CALL OF DPERMISSION
      IF  USER = SSOWNER THEN  TYPE = 0 AND  -> TYPESET
                                        !SET OWNP
      IF  USER = "" THEN  TYPE = 1 AND  -> TYPESET
                                        !SET EEP
      IF  MODE >= 0 THEN  TYPE = 2 AND  -> TYPESET
                                        !ADD USER TO LIST
      TYPE = 3;                         !REMOVE USER FROM LIST
TYPESET:

   FINISH  ELSE  START ;                !WHOLE INDEX PERMISSION
      IF  MODE >= 0 THEN  TYPE = 6 ELSE  TYPE = 7
                                        !ADD OR REMOVE PERMISSION
   FINISH 
   FLAG = DPERMISSION(SSOWNER,USER,"",FILE,SSOWNFSYS,TYPE,MODE)
   FLAG = DIRTOSS(FLAG)
ERR:

END 
                                        !     SET OWNP

SYSTEMROUTINE  CHANGEACCESS(STRING  (31) FILE,  C 
   INTEGER  MODE, INTEGERNAME  FLAG)
INTEGER  CURMODE, POS, GAP, CONSEG, I
RECORDNAME  CUR(CONFF)
   FLAG = CHECKFILENAME(FILE,7);        !ANY FILE
   -> ERR IF  FLAG # 0
   FLAG = FINDFN(CURFILE,POS);          !FIND IT IN CONNECTED FILE TABLE
   IF  FLAG # 0 THEN  FLAG = 256 AND  -> ERR;!NOT CONNECTED
   CUR == CONF(POS)
   CURMODE = CUR_MODE
   CONSEG = CUR_CONAD>>SEGSHIFT;        !CURRENT CONNECT SEGMENT
   GAP = CUR_HOLE>>SEGSHIFT;            !CURRENT CONNECT HOLE
   IF  CURMODE&X'F' = MODE&X'F' THEN  -> ERR;!CURRENT MODE OK
   SSINHIBIT = 1;                       !HOLD OFF INTERRUPTS
   FLAG = DDISCONNECT(CURFOWNER,CURFNAME,CURFSYS,0)
   -> ERR IF  FLAG # 0
   FLAG = DCONNECT(CURFOWNER,CURFNAME,CURFSYS,MODE,0,CONSEG, C 
      GAP)
   FLAG = DIRTOSS(FLAG)
                                        !IF NOT OK THEN RE-CONNECT WITH ORIGINAL MODE
   IF  FLAG # 0 START 
      I = DCONNECT(CURFOWNER,CURFNAME,CURFSYS,CURMODE&X'F',0, C 
         CONSEG,GAP)
      IF  FLAG # 0 THEN  CLEARFN(POS);  !CORRECT TABLE IF UNABLE TO RE-CONNECT
      -> ERR
   FINISH 
   CUR_MODE = MODE
ERR:

   ALLOW INTERRUPTS
END ;                                   !OF CHANGEACCESS
SYSTEMROUTINE  CHANGEFILESIZE(STRING  (31)FILE, INTEGER  NEWSIZE, C    
  INTEGERNAME  FLAG)
INTEGER  NEWKSIZE, POS, HOLDFLAG, GAP, CONSEG
RECORDNAME  CUR(CONFF)
RECORD  FR(FRF)
NEWSIZE = ROUNDUP(NEWSIZE,FILESIZEALLOC)
NEWKSIZE = NEWSIZE>>KSHIFT;             !NUMBER OF KBYTES TO ALTER
                                        !NEW SIZE IN KB
FLAG = CHECKFILENAME(FILE,5);           !ANY OWN FILE
-> ERR IF  FLAG # 0
FINFO(LAST,0,FR,FLAG)
-> ERR IF  FLAG # 0
IF  NEWKSIZE = FR_SIZE>>KSHIFT THEN  -> ERR
                                        !SIZE OK - RETURN
IF  FR_CONAD = 0 START ;                !NOT CONNECTED
   FLAG = DCHSIZE(CURFOWNER,CURFNAME,CURFSYS,NEWKSIZE)
   FLAG = DIRTOSS(FLAG)
   -> ERR
FINISH 
                                        !FILE MUST BE CONNECTED -
                                        ! HAVE TO DO TEMPORARY DISCONNECT
FLAG = FINDFN(CURFILE,POS);             !FIND POS IN TABLE
CUR == CONF(POS)
IF  NEWSIZE > CUR_HOLE THEN  FLAG = 261 AND  -> ERR
                                        !HOLE TOO SMALL
SSINHIBIT = 1;                          !HOLD OFF INTERRUPTS
FLAG = DDISCONNECT(CURFOWNER,CURFNAME,CURFSYS,0)
                                        !CANNOT USE DISCONNECT -
                                        ! MIGHT BE PREVENTED
-> ERR IF  FLAG # 0
FLAG = DCHSIZE(CURFOWNER,CURFNAME,CURFSYS,NEWKSIZE)
HOLDFLAG = DIRTOSS(FLAG);               !NEEDED LATER
CONSEG = CUR_CONAD>>SEGSHIFT
GAP = CUR_HOLE>>SEGSHIFT
FLAG = DCONNECT(CURFOWNER,CURFNAME,CURFSYS,CUR_MODE&X'F',0, C 
   CONSEG,GAP)
                                        !OR OUT NEW-COPY IF PRESENT
IF  FLAG # 0 THEN  CLEARFN(POS);        !CORRECT TABLE IF UNABLE TO RE-CONNECT
FLAG = DIRTOSS(FLAG)
-> ERR IF  FLAG # 0;                    !CANNOT RE-CONNECT
CUR_SIZE = NEWSIZE
FLAG = HOLDFLAG
-> ERR IF  FLAG # 0
ERR:

ALLOW INTERRUPTS
END ;                                   !OF CHANGEFILESIZE

SYSTEMROUTINE  TRIM(STRING  (31) FILE, INTEGERNAME  FLAG)
RECORD  RR(RF)
INTEGER  SIZE
   CONNECT(FILE,3,0,0,RR,FLAG)
   -> ERR IF  FLAG # 0
   SIZE = RR_DATAEND
   CHANGEFILESIZE(FILE,SIZE,FLAG)
   -> ERR IF  FLAG # 0
   IF  INTEGER(RR_CONAD+12) <= 16 C 
      THEN  INTEGER(RR_CONAD+8) = ROUNDUP(SIZE,FILESIZEALLOC)
                                        !DONT ALTER 3RD WORD OF
                                        ! OBJECT FILES PROTEM
ERR:

END ;                                   !OF TRIM
SYSTEMROUTINE  OUTFILE(STRING  (31) FILE, INTEGER  FILESIZE, HOLE,  C 
   PROT, INTEGERNAME  CONAD, FLAG)
                                        !APPROPRIATE SIZE AND
                                        ! CONNECTS IT IN WRITE MODE.
RECORD  FR(FRF)
RECORDNAME  H(HF)
RECORD  R(RF)
INTEGER  POS, CURSIZE, PSIZE, TYPE, ATLEAST
RECORDNAME  CUR(CONFF)
STRING  (11) REST
   IF  FILESIZE < 0 THEN  FILESIZE = -FILESIZE C 
      AND  ATLEAST = 1 ELSE  ATLEAST = 0
   !NEGATIVE SIZE MEANS CREATE AT LEAST THIS SIZE
                                        !TREAT NEG SIZE AS POS.
   FLAG = CHECKFILENAME(FILE,5);        !OWN FILE ANY NAME
   -> ERR IF  FLAG # 0
UNLESS  'A'<=CHARNO(CURFNAME,1)<='Z'C  
   THEN  FLAG=220 AND  ->ERR
!INVALID NEW FILENAME
   PSIZE = ROUNDUP(FILESIZE,FILESIZEALLOC)
                                        !PHYSICAL SIZE
   IF  PROT&TEMPMARKER # 0 OR  CURFNAME -> ("T#").REST C 
      THEN  TYPE = 1 ELSE  TYPE = 0
                                        !TYPE=1 IS TEMP FILE
   FLAG = FINDFN(CURFILE,POS)
   CUR == CONF(POS)
   IF  FLAG = 0 THEN  CURSIZE = CUR_SIZE ELSE  START 
      FINFO(LAST,0,FR,FLAG);             !SEE IF IT EXISTS
      IF  FLAG = 0 THEN  CURSIZE = FR_SIZE
                                        !IT DOES
   FINISH 
   IF  FLAG = 0 START 
      IF  CURSIZE # PSIZE THEN  START 
                                        !WRONG SIZE
         IF  CURSIZE < PSIZE OR  (TYPE = 0 = ATLEAST) START 
                                        !MUST CHANGE SIZE BECAUSE EITHER
                                        !TOO SMALL OR (PERMANENT FILE AND PRECISE SIZE REQUESTED)
            CHANGEFILESIZE(LAST,PSIZE,FLAG)
                                        !CHANGE SIZE IF NEC
            IF  FLAG = 261 START ;      !VM HOLE TOO SMALL
               DISCONNECT(LAST,FLAG)
                                        !MUST DISCONNECT IT
               -> ERR IF  FLAG # 0
               CHANGEFILESIZE(LAST,PSIZE,FLAG)
                                        !TRY AGAIN
            FINISH 
            -> ERR IF  FLAG # 0
         FINISH 
      FINISH 
   FINISH  ELSE  START ;                !DOES NOT EXIST SO CREATE IT
      FLAG = DCREATE(CURFOWNER,CURFNAME,CURFSYS,PSIZE>>KSHIFT, C 
         TYPE)
      FLAG = DIRTOSS(FLAG)
      -> ERR IF  FLAG # 0
!     *** INSERT BEGINS
!        %IF CURFOWNER#SSOWNER %START
!         FLAG=DPERMISSION(CURFOWNER,SSOWNER,"",CURFNAME,CURFSYS,1,3)
!              FLAG=DIRTOSS(FLAG)
!             ->ERR %IF FLAG#0
!           %FINISH
!      *** INSERT ENDS
   FINISH 
   CONNECT(LAST,19,HOLE,PROT,R,FLAG)
                                        !READ-WRITE-NEWCOPY
                                        !MUST BE RIGHT ONE
   -> ERR IF  FLAG # 0
   CONAD = R_CONAD
   H == RECORD(CONAD)
   H = 0;                               !CLEAR IT OUT
   H_DATAEND = 32;                      !DEFAULT
   H_DATASTART = 32
   H_FILESIZE = PSIZE
   H_DATETIME = PACKDATEANDTIME(STRING(APDATE),STRING(APTIME))
ERR:

END ;                                   !OF OUTFILE

 SYSTEMROUTINE  MODPDFILE(INTEGER  EP,  C 
    STRING  (31) PDFILE, STRING  (11) MEMBER,  C 
    STRING  (31) INFILE, INTEGERNAME  FLAG)
                                         !THIS ROUTINE PROVIDES
                                         ! SERVICES FOR MODIFYING PD FILES
                                         !   EP=1  INSERT
                                         !   EP=2  REMOVE
                                         !    EP=3  RENAME
                                         !       EP=4 CREATE PDFILE
 INTEGER  I, FILELENGTH, BASE, NEWSIZE, ADIR, OLDSIZE, OLDLENGTH
 INTEGER  LEN, NEWSTART, NEWLENGTH
 STRING  (6) OWNER
 SWITCH  SW(1 : 4)
 RECORD  PDR, FR(RF)
 RECORDNAME  PD(PDF)
 RECORDNAME  PDH(PDHF)
 
    ROUTINE  BMOVE(INTEGER  LENGTH, FROM, TO)
    INTEGER  I
       RETURN  IF  LENGTH <= 0
       IF  FROM > TO OR  FROM+LENGTH <= TO START 
                                         !SAFE TO USE NORMAL MOVE - NO
                                         ! OVERLAP
          MOVE(LENGTH,FROM,TO)
       FINISH  ELSE  START ;             !FIELDS OVERLAP
          CYCLE  I = LENGTH-1,-1,0
             BYTEINTEGER(TO+I) = BYTEINTEGER(FROM+I)
          REPEAT 
       FINISH 
    END ;                                !OF BMOVE
 
    INTEGERFN  CHECKMEMBERNAME(STRING  (11) S)
                                         !CHECKS THAT MEMBER HAS
                                         ! STANDARD NAME
    INTEGER  I
       SSFNAME = S;                      !FOR FAILURE MESSAGE
       RESULT  = 270 UNLESS  1 <= LENGTH(S) <= 11 C 
          AND  'A' <= CHARNO(S,1) <= 'Z'
       I = 1
       WHILE  I < LENGTH(S) CYCLE 
          I = I+1
          RESULT  = 270 UNLESS  'A' <= CHARNO(S,I) <= 'Z' C 
             OR  '0' <= CHARNO(S,I) <= '9'
       REPEAT 
       RESULT  = 0;                      !O.K.
    END ;                                !OF CHECKMEMBERNAME
    BASE = 0
    UNLESS  1 <= EP <= 4 THEN  FLAG = -1 AND  -> ERR
    IF  EP <= 3 START 
                                         !NOW CONNECT PD FILE IN WRITE
                                         ! MODE
       IF  PDFILE -> OWNER.(".").PDFILE AND  OWNER # SSOWNER START 
          FLAG = 258;                    !ILLEGAL USE OF ANOTHER"S FILE
          -> ERR
       FINISH 
       CONNECT(PDFILE,3,0,0,PDR,FLAG)
       -> ERR IF  FLAG # 0
       IF  PDR_FILETYPE # SSPDFILETYPE C 
          THEN  FLAG = 286 AND  -> ERR
                                         !NOT A PD FILE
       BASE = PDR_CONAD
       PDH == RECORD(BASE)
       ADIR = PDH_ADIR+BASE;             !ABS ADDR OF DIRECTORY
    FINISH 
    -> SW(EP)
 SW(1):                                  !INSERT FILE
    FLAG = CHECKMEMBERNAME(MEMBER)
    -> ERR IF  FLAG # 0
    CONNECT(INFILE,0,0,0,FR,FLAG)
                                         !CONNECT FILE TO BE INSERTED
    IF  FLAG # 0 THEN  -> ERR
    FILELENGTH = (FR_DATAEND+7)&X'FFFFF8'
                                         !DW ALIGN
    IF  FILELENGTH < 16 THEN  FILELENGTH = 16
                                         !MINIMUM LENGTH
                                         !CHECK THAT MEMBER NOT
                                         ! ALREADY THERE
    I = 0
    WHILE  I < PDH_COUNT CYCLE 
       PD == RECORD(ADIR+I*32)
       IF  PD_NAME = MEMBER THEN  FLAG = 287 AND  -> ERR
                                         !ALREADY THERE
       I = I+1
    REPEAT 
    OLDLENGTH = PDR_DATAEND
    OLDSIZE = ROUNDUP(OLDLENGTH,FILESIZEALLOC)
    NEWLENGTH = OLDLENGTH+FILELENGTH+32
                                         !ALLOW FOR NEW FILE AND DIR ENTRY
    IF  NEWLENGTH > OLDSIZE START ;      !GREATER THAN PHYSICAL SIZE
       CONNECT(PDFILE,3,NEWLENGTH,0,PDR,FLAG)
                                         !RE-CONNECT - IN CASE NEEDS
                                         !MORE ROOM
       -> ERR IF  FLAG # 0
       CHANGEFILESIZE(PDFILE,NEWLENGTH,FLAG)
       -> ERR IF  FLAG # 0
       NEWSIZE = ROUNDUP(NEWLENGTH,FILESIZEALLOC)
                                         !NEW PHYSICAL SIZE
       BASE = PDR_CONAD
       PDH == RECORD(BASE);              !RE-MAP - MIGHT HAVE MOVED
       PDH_SIZE = NEWSIZE;               !NEW PHYSICAL SIZE
       ADIR = PDH_ADIR+BASE
    FINISH 
    SSINHIBIT = 1
    PDH_DATAEND = NEWLENGTH
    BMOVE(32*PDH_COUNT,ADIR,ADIR+FILELENGTH)
                                         !NOT SAFE TO USE MOVE- MIGHT
                                         ! OVERLAP
    NEWSTART = ADIR;                     !FILE GOES TO EXISTING START
                                         ! OF DIRECTORY
    PDH_ADIR = PDH_ADIR+FILELENGTH
    ADIR = PDH_ADIR+BASE
    MOVE(FILELENGTH,FR_CONAD,NEWSTART)
                                         !MOVE IN FILE
    PD == RECORD(ADIR+32*PDH_COUNT)
                                         !NEW DIRECTORY RECORD
    PD = 0;                              !CLEAR IT
    PD_NAME = MEMBER
    PD_START = NEWSTART-BASE;            !OFFSET OF START
    PDH_COUNT = PDH_COUNT+1;             !INCREMENT COUNTER
    -> ERR
 SW(2):                                  !DELETE MEMBER
    I = 0
    SSINHIBIT = 1
    WHILE  I < PDH_COUNT CYCLE 
       PD == RECORD(ADIR+I*32)
       IF  PD_NAME = MEMBER THEN  -> MEMBER FOUND
       I = I+1
    REPEAT 
    SSFNAME = MEMBER
    FLAG = 288;                          !MEMBER NOT FOUND
    -> ERR
 MEMBER FOUND:
 
    FILELENGTH = (INTEGER(BASE+PD_START)+7)&X'FFFFF8'
    IF  FILELENGTH < 16 THEN  FILELENGTH = 16
                                         !DW ROUND
    I = I+1
    WHILE  I < PDH_COUNT CYCLE 
       PD == RECORD(ADIR+I*32)
       LEN = (INTEGER(BASE+PD_START)+7)&X'FFFFF8'
       IF  LEN < 16 THEN  LEN = 16;      !MINIMUM LENGTH OF FILE
       MOVE(LEN,BASE+PD_START,BASE+PD_START-FILELENGTH)
       PD_START = PD_START-FILELENGTH
       MOVE(32,ADIR+I*32,ADIR+(I-1)*32)
                                         !MOVE RECORD DOWN A PLACE
       I = I+1
    REPEAT 
    PDH_COUNT = PDH_COUNT-1
    MOVE(32*PDH_COUNT,ADIR,ADIR-FILELENGTH)
                                         !MOVE DIR BACK
    PDH_ADIR = PDH_ADIR-FILELENGTH
    PDH_DATAEND = PDH_DATAEND-(FILELENGTH+32)
    TRIM(PDFILE,FLAG)
    -> ERR
 SW(3):                                  !RENAME (MEMBER,FILE)
    FLAG = CHECKMEMBERNAME(INFILE)
    -> ERR IF  FLAG # 0
    I = 0
    WHILE  I < PDH_COUNT CYCLE 
       PD == RECORD(ADIR+I*32)
       IF  PD_NAME = INFILE THEN  FLAG = 90 AND  -> ERR
       I = I+1
    REPEAT 
    I = 0
    WHILE  I < PDH_COUNT CYCLE 
       PD == RECORD(ADIR+I*32)
       IF  PD_NAME = MEMBER THEN  PD_NAME = INFILE AND  -> ERR
       I = I+1
    REPEAT 
    SSFNAME = MEMBER
    FLAG = 288;                          !MEMBER NOT FOUND
    -> ERR
 SW(4):                                  !CREATE EMPTY PDFILE
    OUTFILE(PDFILE,4096,4096,0,BASE,FLAG)
    -> ERR IF  FLAG # 0
    PDH == RECORD(BASE)
    PDH_FILETYPE = 6;                    !TYPE=PARTITIONED
    PDH_ADIR = 32;                       !START OF DIRECTORY
    PDH_COUNT = 0;                       !NO MEMBERS
    -> ERR
 ERR:
 
    ALLOW INTERRUPTS
 END ;                                   !OF MODPDFILE

  ROUTINE  CONMEMBER(STRING  (31) FILE,  C 
     STRING  (11) MEMBER, INTEGER  PROTECTION,  C 
     RECORDNAME  R, INTEGERNAME  FLAG)
  !***********************************************************************
  !*                                                                     *
  !* THIS ROUTINE IS USED TO CONNECT A MEMBER OF A PARTITIONED FILE     *
  !* AND RETURNS IN RECORD R THE DETAILS OF THE MEMBER. NOTE THAT       *
  !* ONLY THE FOLLOWING FIELDS REFER TO THE MEMBER ITSELF - CONAD,      *
  !* SIZE, FILETYPE, DATASTART, DATAEND. ALL THE OTHER FIELDS REFER      *
  !* TO THE PD FILE.                                                     *
  !*                                                                     *
  !***********************************************************************
  INTEGER  I, P
  RECORDSPEC  R(RF)
  RECORDNAME  PDH(PDHF)
  RECORDNAME  PD(PDF)
     CONNECT(FILE,0,0,PROTECTION,R,FLAG); !CONNECT WITH NO PROTECTION
     -> ERR IF  FLAG # 0
     IF  R_FILETYPE # SSPDFILETYPE THEN  FLAG = 286 AND  -> ERR
                                          !NOT A PD FILE
     PDH == RECORD(R_CONAD)
                                          !NOW LOOK FOR REQUIRED MEMBER
     I = 0
     P = PDH_ADIR+R_CONAD;                !START OF DIRECTORY
     WHILE  I < PDH_COUNT CYCLE 
        PD == RECORD(P+I*32)
        IF  PD_NAME = MEMBER THEN  -> MEMBER FOUND
        I = I+1
     REPEAT 
     SSFNAME = MEMBER
     FLAG = 288;                          !MEMBER NOT FOUND
     -> ERR
  MEMBER FOUND:
  
     R_CONAD = R_CONAD+PD_START;          !ABS ADDR OF MEMBER
     R_DATASTART = INTEGER(R_CONAD+4)
     R_DATAEND = INTEGER(R_CONAD)
     R_FILETYPE = INTEGER(R_CONAD+12)
                                          !TYPE
     IF  R_FILETYPE = 0 THEN  R_FILETYPE = 3
  ERR:
  
  END ;                                   !OF CONMEMBER

ROUTINE  FILLSYSTEMCALLS(INTEGER  SCTABLE, COUNT)
!***********************************************************************
!*                                                                     *
!*THIS VERSION CHANGED 17.8.78 FOR NEW FORMAT OBJECT FILES             *
!* THIS ROUTINE FILLS IN THE SYSTEM CALL DESCRIPTORS IN THE BGLA       *
!* USING INFORMATION IN A TABLE AT SCTABLE. THE INFORMATION            *
!* CONSISTS OF AN I AND J VALUE FOR EACH OF THE DIRECTOR ROUTINES      *
!* WHICH CAN BE ACCESSED BY SYSTEM CALL.                               *
!*                                                                     *
!***********************************************************************
RECORDFORMAT  TABF(STRING  (31) NAME, INTEGER  I, J)
RECORDARRAYFORMAT  TABLEF(1 : COUNT)(TABF)
RECORDARRAYNAME  TABLE(TABF)
RECORDFORMAT  EPREFF(INTEGER  LINK, REFLOC, STRING  (31) IDEN)
RECORDNAME  EPREF(EPREFF)
INTEGER  LD, LOC, LINK, P, ABGLA
   ABGLA = ABASEFILE+((INTEGER(ABASEFILE)+X'3FFFF')& C 
      X'FFFC0000')
                                        !BASEGLA STARTS AT FIRST FREE SEG BEYOND BASEFILE
   TABLE == ARRAY(SCTABLE,TABLEF);      !MAP ARRAY TABLE ONTO THE TABLE
   LD = ABASEFILE+INTEGER(ABASEFILE+24);!START OF BASE LOAD DATA
   LINK = INTEGER(LD+28);               !TOP OF EPREF LIST
   WHILE  LINK # 0 CYCLE 
      EPREF == RECORD(LINK+ABASEFILE);  !MAP EACH REF ONTO EPREF
      CYCLE  P = 1,1,COUNT;             !LOOK THROUGH SCTABLE
         IF  TABLE(P)_NAME = EPREF_IDEN START 
            LOC = (EPREF_REFLOC&X'FFFFFF')+ABGLA; !ASSUME IN GLA (NOT PLT)
            INTEGER(LOC) = X'E3000000'!TABLE(P)_I
                                        !SYS CALL DESCRIPTOR
            INTEGER(LOC+4) = TABLE(P)_J
                                        !SECOND WORD
            EXIT 
         FINISH 
      REPEAT 
      LINK = EPREF_LINK
   REPEAT 
END ;                                   !OF FIL SYSTEM CALLS

SYSTEMROUTINE  SSINIT(INTEGER  MARK, ADIRINF)
                                        !THIS IS THE INITIALISATION
                                        ! ROUTINE FOR THE SUBSYSTEM.
                                        ! IT IS ENTERED
                                        !ONCE FROM SSLDR AT THE START
                                        ! OF A SESSION
INTEGER  FLAG, I, POS, BASEHOLE, BGLALEN, AOFM
RECORDNAME  DIRINF(DIRINFF)
RECORDNAME  CUR(CONFF)

   ROUTINE  CALL CONTROL
   INTEGER  LNB
      *STLN_LNB;                        !PUT LNB FOR THIS ROUTINE INTO I
      SSCOMREG(36) = LNB;               !AND STORE IN COMREG 36
      CONTROL;                          !CALL SS CODE
                                        !IF FAILURE THEN EFFECTIVELY
                                        ! RETURN FROM THIS ROUTINE
   END ;                                !OF CALL CONTROL
   DIRINF == RECORD(ADIRINF);           !DIRECTOR INFO RECORD
   BASEHOLE = ROUNDUP(INTEGER(ABASEFILE),SEGSIZE)
                                        !HOLE FOR BASEFILE
   AOFM = ABASEFILE+INTEGER(ABASEFILE+28);   !ADDRESS OF OBJECT FILE MAP
   BGLALEN = INTEGER(AOFM+20)+INTEGER(AOFM+56);   !LENGTH OF AREA 2(GLA)+LENGTH OF AREA 5(UST)
   ABGLA = ABASEFILE+BASEHOLE;          !BGLA STARTS AT NEXT SEGMENT
   SSCOMREG(35) = ABGLA;                !ADDRESS OF BGLA
   SSOWNER = DIRINF_USER;               !EXTRACT INFO FROM DIRINF
   SSOWNFSYS = DIRINF_FSYS
   SSREASON = DIRINF_REASON
   SSOPERNO = DIRINF_OPERNO
   AIOSTAT = DIRINF_AIOSTAT
   SSSUFFIX = TOSTRING(DIRINF_ISUFF)
                                        !CHAR TO BE ADDED TO END OF
                                        ! TEMP FILENAMES
   SSSCTABLE = DIRINF_SCIDENSAD
    SSSCCOUNT = DIRINF_SCIDENS
    SSADIRINF = ADIRINF
    IF  DIRINF_SCDATE # SSDATELINKED C 
       THEN  FILLSYSTEMCALLS(SSSCTABLE,SSSCCOUNT)
                                         !ONLY NEED TO FILL IF RUNNING ON DIFFERENT DIRECTOR
    FLAG = DSFI(SSOWNER,SSOWNFSYS,0,0,ADDR(BASEFILE))
                                         !GET NAME OF BASEFILE
    IF  BASEFILE = "" THEN  BASEFILE = "#SUBSYS"
                                         !DEFAULT NAME
    FLAG = DSFI(SSOWNER,SSOWNFSYS,12,0,ADDR(SSMAXFSIZE))
    SSMAXFSIZE = SSMAXFSIZE<<10;         !MAXIMUM FILE SIZE IN BYTES
    FLAG = FINDFN(BASEFILE,POS)
    CUR == CONF(POS)
    CUR_FILE = BASEFILE;                 !PUT NAME IN TABLE
    CUR_SIZE = ROUNDUP(INTEGER(ABASEFILE),FILESIZEALLOC)
    CUR_CONAD = ABASEFILE;               !ADDRESS OF BASEFILE
    CUR_HOLE = BASEHOLE
    CUR_USE = 8;                         !NEVER DISCONNECT
                                         !PUT SS#BGLA INTO CONF TABLE
    FLAG = FINDFN(SSOWNER.".T#BGLA",POS)
    CUR == CONF(POS)
    CUR_FILE = SSOWNER.".T#BGLA"
    CUR_CONAD = ABGLA
    CUR_HOLE = SEGSIZE
    CUR_SIZE = SEGSIZE
    CUR_USE = 8;                         !NEVER DISCONNECT
    SSASESSDIR = ABASEFILE+INTEGER(ABASEFILE)-SSTEMPDIRSIZE
    SSADEFOPT=SSASESSDIR-OPTFILESIZE;         !ADDRESS OF DEFAULT OPTION FILE
    SSATEMPDIR = ABGLA+BGLALEN;          !ADDR OF SESSION DIRECTORY
    SSCURBGLA = SSATEMPDIR+SSTEMPDIRSIZE
    SSMAXBGLA = ABGLA+SEGSIZE-1;         !LAST BYTE IN BGLA
    SSCOMREG(11) = INTEGER(ATRANS)+256;  !ADDRESS OF ETOI TABLE
   ASSCOM=ADDR(SSCOMREG(0))  ;! LET JOBBER SEE COMREGS
    SSCOMREG(12) = INTEGER(ATRANS);      !ADDRESS OF ITOE TABLE
    I = DSETIC(4000000);                 !LARGE DEFAULT TIME LIMIT
    CALL CONTROL;                        !THIS IS SUBSYSTEM
    DSTOP(104);                          !IN CASE WE GET BACK HERE
 END ;                                   !OF SSINIT
 
 SYSTEMROUTINE  SETWORK(INTEGERNAME  AD, FLAG)
                                         !ON ENTRY AD CONTAINS LENGTH REQUIRED
 INTEGER  CONAD
                                         ! ADDRESS IN AD
 OWNINTEGER  CURLENGTH
    IF  AD < SSINITWORKSIZE THEN  AD = SSINITWORKSIZE
                                         !MINIMUM SIZE
    IF  AD > SSMAXWORKSIZE THEN  AD = SSMAXWORKSIZE
                                         !MAX SIZE
    IF  AD <= CURLENGTH START 
       AD = SSCOMREG(14)
       INTEGER(AD) = 32;                 !FILL IN HEADER AGAIN LEST IT HAS BEEN CORRUPTED
       INTEGER(AD+4) = 32
       INTEGER(AD+8) = CURLENGTH
       INTEGER(AD+12) = 0
       FLAG = 0
    FINISH  ELSE  START 
       OUTFILE("T#WRK",AD,X'100000',TEMPMARKER,CONAD,FLAG)
                                         !UNIQUE NAME FOR THIS PROCESS
       IF  FLAG = 0 START 
          SSCOMREG(14) = CONAD
          CURLENGTH = AD
          AD = CONAD
       FINISH 
    FINISH 
 END ;                                   !OF SETWORK
 
 SYSTEMLONGREALFN  CPUTIME
 INTEGER  RES, FLAG
    FLAG = DSFI(SSOWNER,SSOWNFSYS,21,0,ADDR(RES))
    RESULT  = RES/KIPS;                  !TIME IN SECONDS
 END ;                                   !OF CPUTIME
 
 EXTERNALINTEGERFN  PAGETURNS
 INTEGER  FLAG
 INTEGERARRAY  HOLD(1 : 8)
    FLAG = DSFI(SSOWNER,SSOWNFSYS,24,0,ADDR(HOLD(1)))
                                         !PAGETURNS THIS SESSION
    RESULT  = HOLD(1)
 END ;                                   !OF PAGETURNS
 
 SYSTEMINTEGERMAP  COMREG(INTEGER  I)
    RESULT  == SSCOMREG(I)
 END ;                                   !OF COMREG
 
 EXTERNALSTRINGFN  DATE
    RESULT  = STRING(APDATE)
 END ;                                   !OF DATE
 
 EXTERNALSTRINGFN  TIME
    RESULT  = STRING(APTIME)
 END ;                                   !OF TIME
 SYSTEMSTRINGFN  NEXTTEMP
 OWNINTEGER  SEQ
    SEQ = SEQ+1
    RESULT  = TOSTRING(HEX((SEQ>>8)&X'F')).TOSTRING(HEX((SEQ>>4)& C 
       X'F')).TOSTRING(HEX(SEQ&X'F'))
 END ;                                   !OF NEXTTEMP
 
 SYSTEMROUTINE  SENDFILE(STRING  (31) FILE,  C 
    STRING  (8) DEVICE, INTEGER  COPIES, FORMS,  C 
    INTEGERNAME  FLAG)
 STRING  (8) HOLD DEVICE
 CONSTBYTEINTEGERARRAY  PARITY(0 : 127) = C 
 0,129,130,3,132,5,6,135,136,9,10,139,12,141,142,15,
 144,17,18,147,20,149,150,23,24,153,154,27,156,29,30,159,
 160,33,34,163,36,165,166,39,40,169,170,43,172,45,46,175,
 48,177,178,51,180,53,54,183,184,57,58,187,60,189,190,63,
 192,65,66,195,68,197,198,71,72,201,202,75,204,77,78,207,
 80,209,210,83,212,85,86,215,216,89,90,219,92,221,222,95,
 96,225,226,99,228,101,102,231,232,105,106,235,108,237,238,111,
 240,113,114,243,116,245,246,119,120,249,250,123,252,125,126,255
 RECORD  RR(RF)
 INTEGER  I, LEN, DATALENGTH
 STRING  (4) DEPT
 STRING  (255) MESSAGE
    IF  BENCHMARK # 0 START ;            !BENCHMARK JOB - DELETE FILE
       DESTROY(FILE,FLAG)
       FLAG = 0
       -> ERR
    FINISH 
    HOLDDEVICE = DEVICE
    IF  DEVICE -> (".").DEVICE THEN  START 
    FINISH 
    FLAG = CHECKFILENAME(FILE,5);        !ANY OWN FILE
    -> ERR IF  FLAG # 0
    CONNECT(LAST,0,0,0,RR,FLAG);          !TO GET LENGTH
    -> ERR IF  FLAG # 0
    DATALENGTH = RR_DATAEND-RR_DATASTART
    IF  DATALENGTH <= 0 THEN  DESTROY(FILE,FLAG) AND  -> ERR
                                         !EMPTY FILE
    DISCONNECT(LAST,FLAG)
    -> ERR IF  FLAG # 0
    IF  DEVICE = "SGP" THEN  DEVICE = "GP" AND  FORMS = 1
    MESSAGE = "DOCUMENT SRCE=".CURFNAME.",DEST=".DEVICE. C 
       ",START=".ITOS(RR_DATASTART).",LENGTH=".ITOS(DATALENGTH)
    IF  FORMS # 0 THEN  MESSAGE = MESSAGE.",FORMS=".ITOS(FORMS)
    IF  COPIES # 0 THEN  MESSAGE = MESSAGE.",COPIES=".ITOS( C 
       COPIES)
    LEN = LENGTH(MESSAGE)
    IF  INHIBITSPOOLER = 0 START 
       FLAG = DMESSAGE(SPOOLERNAME,LEN,1,-1,ADDR(MESSAGE)+1)
    FINISH  ELSE  START 
       PRINTSTRING(MESSAGE)
       FLAG = 1001
    FINISH 
    IF  FLAG # 0 START 
       IF  FLAG = 202 THEN  FLAG = 264 C 
          AND  SSFNAME = HOLDDEVICE ELSE  FLAG = DIRTOSS(FLAG)
 !**PROTEM CONVERT INVALID DEVICE CODE - OTHERWISE DIRECTOR FAULT
 !THE PREVIOUS LINE SHOULD BE ALTERED TO ACCOMODATE OTHER SPOOLR FAULTS 
    FINISH 
 ERR:
 
 END ;                                   !OF SENDFILE
 ENDOFFILE