recordformat pf(integer dest, srce, string (23) text) recordformat pe(integer dest, srce, p1, p2, p3, p4, p5, p6) constinteger amdahl = 369, xa = 371 INCLUDE "TARGET" if TARGET = 2900 start { machine specific constants } constinteger MAX LINE = 132 conststringname DATE = X'80C0003F' conststringname TIME = X'80C0004B' constinteger SEG SHIFT = 18 finish { 2900 } ! if TARGET = 370 start constinteger SEG SHIFT = 16 finish ! if TARGET = XA or TARGET = AMDAHL start constinteger SEG SHIFT = 20 finish ! unless TARGET = 2900 start constinteger com seg = 31 conststringname DATE = COM SEG << SEG SHIFT + X'3B' conststringname TIME = COM SEG << SEG SHIFT + X'47' constinteger MAX LINE = 80 { for convenience on terminals } finish !* COMMUNICATIONS RECORD FORMAT - EXTANT FROM CHOPSUPE 20A ONWARDS * ! ! This is the Supervisor Communications Record Format, defined in EMAS ! 2900 Supervisor Note 15. if TARGET = 2900 start recordformat c COMF(integer OCPTYPE, IPLDEV, SBLKS, SEPGS, NDISCS, DLVNADDR, GPCTABSIZE, GPCA, SFCTABSIZE, SFCA, SFCK, DIRSITE, DCODEDA, SUPLVN, TOJDAY, DATE0, DATE1, DATE2, TIME0, TIME1, TIME2, EPAGESIZE, USERS, CATTAD, SERVAAD, byteinteger NSACS, RESV1, SACPORT1, SACPORT0, NOCPS, RESV2, OCPPORT1, OCPPORT0, integer ITINT, CONTYPEA, GPCCONFA, FPCCONFA, SFCCONFA, BLKADDR, RATION, SMACS, TRANS, longinteger KMON, integer DITADDR, SMACPOS, SUPVSN, PSTVA, SECSFRMN, SECSTOCD, SYNC1DEST, SYNC2DEST, ASYNCDEST, MAXPROCS, KINSTRS, ELAPHEAD, COMMSRECA, STOREAAD, PROCAAD, SFCCTAD, DRUMTAD, TSLICE, FEPS, MAXCBT, PERFORMAD, INTEGER SP0,SP1,SP2,SP3,SP4,SP5, integer LSTL, LSTB, PSTL, PSTB, HKEYS, HOOT, SIM, CLKX, CLKY, CLKZ, HBIT, SLAVEOFF, INHSSR, SDR1, SDR2, SDR3, SDR4, SESR, HOFFBIT, BLOCKZBIT, BLKSHIFT, BLKSIZE, END) finish else start recordformat C COMF(integer OCPTYPE, SLIPL, TOPS, SEPGS, NDISCS, NSLDEVS, DLVNADDR, DITADDR, SLDEVTABAD, STEER INT, DIRSITE, DCODEDA, exSUPLVN, TOJDAY, DATE0, DATE1, DATE2, TIME0, TIME1, TIME2, PAGESIZE, USERS, CATTAD, SERVAAD, NOCPS, ITINT, RATION, TRANS, longinteger KMON, integer SUPVSN, SECSFRMN, SECSTOCD, SYNC1DEST, SYNC2DEST, ASYNCDEST, MAXPROCS, KINSTRS, ELAPHEAD, COMMSRECA, STOREAAD, PROCAAD, TSLICE, FEPS, MAXCBT, PERFORMAD, END) finish !* ! if TARGET = 2900 start recordformat file inff(string (11)NAME, integer SD,halfinteger PGS, H0, byteinteger CODES, CODES2, DAYNO, USE, OWNP, EEP, PHEAD, ARCH, byteinteger CCT, SSBYTE, halfinteger PREFIX) finish else start recordformat file inff(string (11)NAME, integer SD, shortinteger PGS, H0, byteinteger CODES, CODES2, DAYNO, USE, OWNP, EEP, PHEAD, ARCH, CCT, SSBYTE, shortinteger PREFIX) finish if TARGET # 2900 start RECORDFORMAT FINFF((INTEGER NKB, RUP, EEP, APF, USE, ARCH, FSYS, CONSEG, CCT, CODES, DAYNO, CODES2, SSBYTE or INTEGERARRAY i(0:12)),STRING (6)OFFER) finish else start RECORDFORMAT FINFF(INTEGER NKB, RUP, EEP, APF, USE, ARCH, FSYS, CONSEG, CCT, CODES, BYTEINTEGER SP1, DAYNO, SP2, CODES2, INTEGER SSBYTE,STRING (6)OFFER) finish !* recordformat daf((integer blksi, nblks, last blk, spare, integerarray da(1 : 512) or integer sparex, integerarray i(0:514))) ! if TARGET = 2900 start externalstringfnspec derrs(integer flag) externalintegerfnspec ddap(integerfn a(integer a,b,c), integer act, addr) externalintegerfnspec dsfi(string (6) user, integer fsys, integer type, set, address) externalroutinespec dstop(integer reason) !%externalintegerfnspec change context externalintegerfnspec d check bpass(string (6) user, string (63) bpass, integer fsys) externalintegerfnspec dpon3(string (6) user, record (pe)name p, integer invoc, msgtype, outno) externalroutinespec dpoff(record (pe)name p) externalroutinespec dtoff(record (pe)name p) externalintegerfnspec dgetda(string (6) user, string (11) file, integer fsys, address) externalintegerfnspec dchsize(string (6) user, string (11) file, integer fsys, newsize) externalroutinespec get av fsys(integername n, integerarrayname a) externalintegerfnspec dfsys(string (6) user, integername fsys) externalintegerfnspec dpermission( c string (6) owner, user, string (8) date, string (11) file, integer fsys, type, adrprm) externalintegerfnspec ddestroy(string (6) user, string (11) file, string (8) date, integer fsys, type) externalintegerfnspec ddisconnect(string (6) user, string (11) file c integer fsys, destroy) externalintegerfnspec drename(string (6) user, string (11) oldname, newname, integer fsys) externalintegerfnspec dfstatus(string (6) user, string (11) file, integer fsys, act, value) externalintegerfnspec dfilenames(string (6) user, record (file inff)arrayname inf, integername filenum, maxrec, nfiles, integer fsys, type) externalintegerfnspec dfinfo(string (6) user, string (11) file, integer fsys, address) externalintegerfnspec dcreate(string (6) user, string (11) file, integer fsys, nkb, type) externalintegerfnspec dconnect(string (6) user, string (11) file, integer fsys, mode, apf, integername seg, gap) externalintegerfnspec dmessage(string (6) user, integername l, integer act, fsys, adr) externalintegerfnspec dtransfer( c string (6) user1, user2, string (11) file, newname, integer fsys1, fsys2, type) externalintegerfnspec dnewgen(string (6) user, string (11) file, c newgen of file, integer fsys) finish else start EXTERNALINTEGERFNSPEC DCHECKBPASS(STRINGNAME USER, BPASS, INTEGERNAME FSYS) EXTERNALINTEGERFNSPEC DCHSIZE(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, NKB) ! The physical size of file FILE belonging to file index FILE INDEX on ! disc-pack FSYS (or -1) is altered (if necessary) so that its new size ! is NEWKB Kbytes. The size may not be reduced to zero. The file may ! be connected in the caller's virtual memory (only). If the caller is ! not the file owner, he must either have W access to the file index or ! be privileged. !%EXTERNALINTEGERFNSPEC CHANGE CONTEXT EXTERNALINTEGERFNSPEC DCONNECT(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, MODE, SEG, GAP) EXTERNALINTEGERFNSPEC DCREATE(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, NKB, TYPE, DA) ! A file of name FILE is created, in file index FILE INDEX on disc-pack ! FSYS, of E Epages, where E is the smallest number of Epages containing ! NKB Kbytes. The maximum size of file allowed is 16 Mbytes. Subsystems ! requiring larger files should arrange that they be made up of subfiles ! comprising files created by this procedure. ! ! Bits in TYPE may be set: ! ! 2**0 For a temporary file (destroyed when the creating process ! stops if the file was connected, or at System start-up). ! ! 2**1 For a very temporary file (destroyed when the file is ! disconnected). ! ! 2**2 For a file which is to be zeroed when created. ! ! 2**3 To set "CHERISHed" status for the file. ! ! ! Temporary files are made into ordinary files (that is, the "temporary" ! attribute is removed) on being RENAMEd, OFFERed, TRANSFERred or ! PERMITted, and also explicitly by an appropriate call on procedure ! DFSTATUS. ! ! The disc address of the first section of the file is returned in DA. EXTERNALINTEGERFNSPEC DDESTROY(STRINGNAME FILE INDEX, FILE, DATE, INTEGERNAME FSYS, TYPE) ! File FILE belonging to file index FILE INDEX on disc-pack FSYS, is ! destroyed. TYPE should be set to 1 to destroy a file from archive ! storage, otherwise it should be set to zero. When TYPE=1, DATE should ! be set to the archive date. DATE is ignored if TYPE=0. ! ! The procedure fails if 'OWNP' for the file is either zero (no access) ! or 8 (do not destroy). EXTERNALINTEGERFNSPEC DDISCONNECT(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, DSTRY) ! The file of name FILE belonging to file index FILE INDEX on disc-pack ! FSYS is disconnected from the caller's virtual memory. Parameter ! DESTROY should be set either to 0 or 1. If set to 1 the file will be ! destroyed, provided that it belongs to the process owner (not necessary ! if the process is privileged) and the "use-count" for the file is zero ! after disconnection. Otherwise the parameter is ignored. EXTERNALINTEGERFNSPEC DFILENAMES(STRINGNAME GROUP, INTEGERNAME FILENO, MAXREC, C NFILES, FSYS, TYPE, RECORD (file inff)ARRAYNAME INF) ! This procedure delivers, in the record array INFS (which should be ! declared (0:n)), a sequence of records describing the on-line files ! (for TYPE=0), archived files (for TYPE=1) or backed-up files (for ! TYPE=2) belonging to group GROUP on fsys FSYS (or -1 if not known). ! ! The procedure works differently for on-line files (TYPE=0) and ! off-line files (TYPE>0). ! ! For on-line files, the records returned give the names of files and ! groups belonging to GROUP but not the contents of any of these groups. ! DFILENAMES must be called again with GROUP set to the name of the ! subgroup to determine these. Thus ! ! FLAG = DFILENAMES(ERCC99,... ! ! returns the names of files and groups in ERCC99's main file index. If ! there is a group called PROJ:, the contents of it can be found with ! ! FLAG = DFILENAMES(ERCC99.PROJ:,... ! ! The group separator, :, may be omitted if desired. ! ! Note that the usage of . and : (USEP and GSEP) is reversed in EMAS3. ! The UINF fields USEP, USEPCH etc allow utilities to be written which ! will work for both EMAS2 and EMAS3. ! ! MAXREC is set by the caller to specify the maximum number of records he ! is prepared to accept in the array INFS, and is set by Director to be ! the number of records returned. ! ! NFILES is set by Director to be the number of files actually held on ! on-line storage or on archive storage, depending on the value of TYPE. ! ! FILENO is not normally used. [ If the top bit of MAXREC is set, FILENO ! is used in the same way as for off-line files, described below ] ! ! The format of the records returned in INFS is ! ! %string(11)NAME, %integer SPARE1, KBYTES, ! %byteinteger ARCH, CODES, CCT, OWNP, ! EEP, USE, CODES2, SSBYTE, SPARE2, PHEAD, DAYNO, GROUP ! ! ( 32 bytes ) ! PHEAD is non-zero if the file or group has been permitted itself to a ! user or user group. ! GROUP is non-zero if NAME is the name of a group. ! ! For off-line files, TYPE = 1 or 2, GROUP will normally be be the name ! of a file index eg ERCC99 or ERCC99{UTILS} when all the names in the ! index will be returned. If an actual group name is given eg ! ! ERCC99.PROJ: ! ! then only names of the form ! ! ERCC99.PROJ:name ! ! are returned. MAXREC and NFILES are used in the same way as above. ! ! Filenames are stored in chronological order of archive (or backup) date, ! youngest first. FILENO is set by the caller to specify the "file-number" ! from which names are to be returned, zero representing the most recently ! archived file. Thus the caller can conveniently receive subsets of names ! of a very large number of files. ! ! The format of the records returned in INFS is ! ! %string(11)NAME, %integer KBYTES, ! %string(8)DATE, %string(6)TAPE, ! %halfinteger PREFIX, CHAPTER, ! %byteinteger EEP, PHEAD, SPARE, COUNT ! ! ( 40 bytes ) ! To allow the full filenames to be reconstructed, the array INFS, in ! general, contains some records which hold group names. Records refering ! to filenames can be distinguished by the fact that KBYTES > 0. If PREFIX ! is > 0, the name is a member of a group whose name is given in the ! record INFS(PREFIX). The chain can be followed back until a record ! with a zero PREFIX field is found. ! ! Note. MAXREC does not give the number of filenames returned but the ! number of records in INFS. ! ! TAPE and CHAPTER are returned null to unprivileged callers. EXTERNALINTEGERFNSPEC DFINFO(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, C STRINGNAME S, INTEGERARRAYNAME I) ! This procedure returns detailed information about the attributes of ! file or group FILE belonging to file index FILE INDEX on disc-pack ! FSYS, in a record written to address ADR. ! ! A caller of the procedure having no permitted access to the file ! receives an error result of 32, as though the file did not exist. ! ! The format of the record returned is: ! recordformat DFINFOF((integer NKB, RUP, EEP, APF, USE, ARCH, FSYS, CONSEG, CCT, CODES, byteinteger SP1, DAYNO, SP2, CODES2, integer SSBYTE or INTEGERARRAY i(1:12)), string (6)OFFER) ! ! where ! NKB the number of Kbytes (physical file size) ! zero indicates a group name ! RUP the caller's permitted access modes ! EEP the general access permission ! APF 1-4-4 bits, right-justified, giving respectively the Execute, ! Write and Read fields of APF, if the file is connected in ! this VM ! USE the current number of users of the file ! ARCH the value of the archive byte for the file (see procedure ! DFSTATUS) ! FSYS disc-pack number on which the file resides ! CONSEG the segment number at which the file is connected in the ! caller's VM, zero if not connected ! CCT the number of times the file has been connected since this ! field was last zeroed (see procedure DFSTATUS) ! CODES information for privileged processes ! SP1 spare ! DAYNO Day number when file last connected ! SP2 spare ! CODES2 information for internal use ! SSBYTE information for the subsystem's exclusive use ! OFFER the username to which the file has been offered, otherwise ! null EXTERNALINTEGERFNSPEC DFLAG(INTEGERNAME FLAG, STRINGNAME TXT) EXTERNALINTEGERFNSPEC DFSTATUS(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, ACT, VALUE) ! This procedure is supplied to enable the attributes of file FILE ! belonging to file index FILE INDEX on disc-pack FSYS to be modified, ! as follows. ! ! Parameter VALUE is for use by the archive/backup program (ACT=13), ! and by the subsystem (ACT=18), otherwise it should be set to zero. ! ! ACT ACTION ! ! 0 HAZARD Remove CHERISHed attribute ! ! 1 CHERISH Make subject to automatic System back-up procedures ! Note: If the file is one of ! SS#DIR, SS#OPT or SS#PROFILE ! then the 'archive-inhibit' bit is also set. ! Similarly, the 'archive-inhibit' bit is ! cleared by HAZARD for these files. ! ! 2 UNARCHIVE Remove the "to-be-archived" attribute ! ! 3 ARCHIVE Mark the file for removal from on-line to archive ! storage. ! ! 4 NOT TEMP Remove the "temporary" attribute. ! ! 5 TEMPFI Mark the file as "temporary", that is, to be ! destroyed when the process belonging to the file ! owner stops (if the file is connected at that ! time), or at system start-up. ! ! 6 VTEMPFI Mark the file as "very temporary", that is, to be ! destroyed when it is disconnected from the owner's ! VM. ! ! 7 NOT PRIVATE May now be written to magnetic tape either for ! back-up or archive. May be called only by ! privileged programs. ! ! 8 PRIVATE Not to be written to magnetic tape either for ! back-up or archive. May be called only by ! privileged programs. ! ! 9 SET CCT Set the connect count for the file to VALUE. ! ! 11 ARCH Operation 1 (PRIVILEGED). ! Set currently-being-backed-up bit (bit 2**1 in ! ARCH byte), unless the file is currently connected ! in write mode, when error result 52 is given. ! ! 12 ARCH Operation 2 (PRIVILEGED). ! Clear currently-being-backed-up bit (2**1) and ! has-been-connected-in-write-mode bit (2**0). ! ! 14 ARCH Operation 4 (PRIVILEGED). ! Clear the UNAVAilable and privacy VIOLATed bits in ! CODES. Used by the back-up and archive programs ! when the file has been read in from magnetic tape. ! ! 15 CLR USE Clear file use-count and WRITE-CONNECTED status ! (PRIVILEGED). ! ! 16 CLR NOARCH Clear archive-inhibit bit in CODES. PRIVILEGED - ! for System ! ! 17 SET NOARCH Set archive-inhibit bit in CODES. Library use ! ! 18 SSBYTE Set SSBYTE to be the bottom 8 bits of VALUE (byte ! for a subsystem's exclusive use). ! ! 19 ARCH Operation 5 (PRIVILEGED). ! Set the WRCONN bit in CODES2. Used to prevent any ! user connecting the file in write mode during ! back-up or archive. ! ! 20 ARCH Operation 6 (PRIVILEGED). ! Clear the WRCONN bit in CODES2. Used when back-up ! is complete. ! ! 21 DAYNO Set DAYNO to bottom 8 bits of VALUE EXTERNALINTEGERFNSPEC DFSYS(STRINGNAME FILE INDEX, INTEGERNAME FSYS) EXTERNALINTEGERFNSPEC DFSYSDATA(INTEGERNAME FSYS, INTEGERARRAYNAME DATA) EXTERNALINTEGERFNSPEC DGETDA(STRINGNAME FILE INDEX, FILE, INTEGERNAME FSYS, INTEGERARRAYNAME I) ! This procedure provides the disc addresses of the sections of file FILE ! belonging to file index FILE INDEX on disc-pack FSYS. Data is written ! from address ADR in the format ! ! (%integer SECTSI, NSECTS, LASTSECT, %integerarray DA(0:255)) ! ! where SECTSI is the size (in epages) of the sections (except ! possibly the final section) ! ! NSECTS is the number of sections, and hence the number ! of entries returned in array DA ! ! LASTSECT is the size (in epages) of the final section ! ! In each entry in the DA array, the top byte contains the FSYS number. EXTERNALINTEGERFNSPEC DMESSAGE(STRINGNAME USER, INTEGERNAME LEN, ACT, INVOC, FSYS, ADR) EXTERNALINTEGERFNSPEC DNEWGEN(STRINGNAME FILE INDEX, FILE, NEWGEN, INTEGERNAME FSYS) ! This procedure provides a means of introducing an updated version ! (i.e. a new generation) of file FILE belonging to file index FILE INDEX ! even though it may be connected in other users' virtual memories. ! ! If FILE is not connected in any virtual memory, a call on DNEWGEN is ! equivalent to destroying FILE and then renaming NEWGEN to FILE, ! except that the new version of FILE retains the former FILE's access ! permissions. ! ! If FILE is connected in some virtual memory, then the filename ! NEWGEN "disappears", and any subsequent connection of FILE into ! a virtual memory yields the contents of the new generation formerly ! held in NEWGEN. ! ! When the number of users of a former copy of FILE becomes zero ! (i.e. when it is not connected in any virtual memory), that copy is ! destroyed. EXTERNALINTEGERFNSPEC DPERMISSION(STRINGNAME FILE INDEX, C USER, DATE, FILE, INTEGERNAME FSYS, TYPE, ADR) ! This procedure allows the caller to set access permissions, or specific ! preventions, for file connection to individual users, groups of users ! or to all users to file FILE belonging to file index FILE INDEX. It ! also allows a caller to determine the modes (if any) in which he may ! access the file. ! ! TYPE determines the service required of the procedure: ! ! TYPE Action ! ! 0 set OWNP (not for files on archive storage) ! 1 set EEP ! 2 put USER into the file list (see "Use of file ! access permissions", below) ! 3 remove USER from file list ! 4 return the file list ! 5 destroy the file list ! 6 put USER into the index list (see "Use of file ! access permissions", below) ! 7 remove USER from the index list ! 8 return the index list ! 9 destroy the index list ! 10 give modes of access available to USER for FILE ! 11 set EEP for the file index as a whole ! ! TYPEs 0 to 9 and 11 are available only to the file owner and to ! privileged processes. For TYPE 10, ADRPRM (see below) should be the ! address of an integer into which the access permission of USER to the ! file is returned. If USER has no access to the file, error result 32 ! will be returned from the function, as though the file did not exist. ! If the file is on archive storage, TYPE should be set to 16 plus the ! above values to obtain the equivalent effects. ! ! ADRPRM is either the permission being attached to the file, bit ! values interpreted as follows: ! ! all bits zero prevent access ! 2**0 allow READ access ! 2**1 allow WRITE access not allowed for files ! 2**2 allow EXECUTE access on archive storage ! 2**3 If TYPE = 0, prevent the file from being ! destroyed by e.g. DDESTROY, DDISCONNECT (and ! destroy). ! or, except for type 10, it is the address of an area into which access ! permission information is to be written ! ! %recordformat(%integer BYTES RETURNED, OWNP, EEP, SPARE, ! %record(EF)%array INDIV PRMS(0:15)) ! ! and EF is ! %recordformat EF(%string(6)USER, %byteinteger PERMISSION) ! ! where: ! ! BYTES indicates the amount of data returned. ! RETURNED ! ! OWNP is the file owner's own permission to the file, or the ! requesting user's "net" permission if the caller of the ! procedure is not the file owner (see "Use of file access ! permissions", below). ! ! EEP is the general (all users) access permission to the file ! ("everyone else's permission"). ! ! UPRM The PERMISSION values in the sub-records are those ! for the corresponding users or groups of users denoted by ! USER. Up to 16 such permissions may be attached to a ! file. ! ! Use of file access permissions ! ! The general scheme for permissions is as follows. With each file ! there are associated: ! ! OWNP the permission of the owner of the file to access it ! ! EEP everyone else's permission to access it (other than users ! whose names are explicitly or implicitly attached to the ! file) ! ! INDIV PRMS a list of up to 16 items describing permissions for ! individual users, e.g. ERCC00, or groups of users, e.g. ! ERCC?? (specifying all usernames of which the first four ! characters are "ERCC") ! ! In addition, a user may attach a similar list of up to 16 items to ! his file index as a whole and an EEP for the file index. These ! permissions apply to any file described in the index along with those ! attached to that particular file. ! In determining the mode or modes in which a particular user may access ! a file, the following rules apply: ! ! 1. If the user is the file owner then OWNP applies. ! ! 2. Otherwise, if the user's name appears explicitly in the list for ! the file, the corresponding permission applies. ! ! 3. Otherwise, if the user's name is a member of a group of users ! represented by a list item for the file, the corresponding ! permission applies. ! ! 4. Otherwise EEP applies if greater than zero. ! ! 5. Otherwise, if the user's name appears explicitly in the list for ! the index, the corresponding permission applies. ! ! 6. Otherwise, if the user's name is a member of a group of users ! represented by a list item for the index, the corresponding ! permission applies. ! ! 7. Otherwise, everybody else's permission to the file index applies. ! ! In the event of a user's name appearing more than once (implicitly) ! within groups specified in a single list, the actual list item to be ! selected to give the permission should be regarded as indeterminate. EXTERNALINTEGERFNSPEC DPOFF(RECORD (pe)NAME P) EXTERNALINTEGERFNSPEC DPON3(STRINGNAME USER, RECORD (pe)NAME P, C INTEGERNAME INVOC, MSGTYPE, OUTNO) EXTERNALINTEGERFNSPEC DRENAME(STRINGNAME FILE INDEX, OLDNAME, NEWNAME, INTEGERNAME FSYS) ! File OLDNAME belonging to file index FILE INDEX on disc-pack FSYS is ! renamed NEWNAME. ! ! A file may not be renamed while it is connected in any virtual memory. EXTERNALINTEGERFNSPEC DSTOP(INTEGERNAME REASON) EXTERNALINTEGERFNSPEC DSFI(STRINGNAME FILE INDEX, INTEGERNAME FSYS, TYPE, C SET, STRINGNAME S, INTEGERARRAYNAME I) ! This procedure is used to set or read information in file index FILE ! INDEX (or user record in some cases) on disc-pack FSYS. TYPE specifies ! which data item is to be referenced (see list below). SET must be 1 ! to write the data item into the index, or 0 to read the item from the ! index. ADR is the address of an area, which must be available in write ! or read mode, to or from which the data item is to be transferred. ! ! TYPE Data item Data type & size ! ! 0 BASEFILE name (the file to be connected ! and entered at process start-up) string(18) ! ! 1 DELIVERY information (to identify string(31) ! slow-device output requested by the ! index owner) ! ! 2 CONTROLFILE name (a file for use by the ! subsystem for retaining control information) string(18) ! ! 3 ADDRTELE address and telephone number of user string(63) ! ! 4 INDEX USE (may not be reset) ! Gives (in successive integers from ADR): ! a) number of files ! b) number of file descriptors currently in use ! c) number of free file descriptors ! d) index size (Kbytes) ! e) Number of section descriptors (SDs) ! f) Number of free section descriptors ! g) Number of permission descriptors (PDs) ! h) Number of free permission descriptors integer(x8) ! ! 5 Foreground and background passwords ! (reading is a privileged operation), a zero ! value means "do not change" integer(x2) ! ! 6 Date last logged-in: (Y-70)<<9 ! (M<<5) ! D and ! date last started (non-interactive) (same) ! (may not be reset) integer(x2) ! ! 7 ACR level at which the process owning this ! index is to run (may be set only by privileged ! processes) integer ! ! 8 Director Version (may be set only by privileged ! processes) integer(x2) ! ! 9 ARCHIVE INDEX USE (may not be reset) ! Gives (in successive integers from ADR): ! a) number of archived files ! b) number of archived Kbytes ! c) number of backed-up files ! d) number of backed-up Kbytes ! e) index size (Kbytes) ! f) number of file descriptors ! g) number of free file descriptors ! h) number of permission descriptors ! i) number of free permission descriptors integer(x9) ! ! 10 Stack size (Kbytes) integer ! ! 11 Limit for total size of all files in disc ! storage (Kbytes) (may be set only by privileged ! processes integer ! ! 12 Maximum file size (Kbytes) (may be set only by ! privileged processes) integer ! ! 13 Current numbers of interactive and batch ! processes, respectively, for the user (may ! not be reset) integer(x2) ! ! 14 Process concurrency limits (may be set only ! by privileged processes). The three words ! denote respectively the maximum number of ! interactive, batch and total processes which ! may be concurrently running for the user. ! (Setting the fields to -1 implies using ! the default values, currently 1, 1 and 1.) integer(x3) ! ! 15 When bit 2**0 is set, TELL messages to the ! index owner are rejected with flag 48. integer ! ! 16 Set Director monitor level (may be set only ! by privileged processes) integer(x2) ! ! 17 Set SIGNAL monitor level (may be set only ! by privileged processes) integer ! ! 18 Initials and surnames of user (may ! be set only by privileged processes) string(31) ! ! 19 Director monitor file string(11) ! ! 20 Thousands of instructions executed, interactive ! and batch modes (may be reset only by ! privileged processes) integer(x2) ! ! 21 Thousands of instructions executed (current ! session only) integer ! ! 22 Thousands of instructions executed in Director ! procedures (current process session only) ! (may not be reset) integer ! ! 23 Page-turns, interactive and batch modes ! (may be reset only by privileged processes) integer(x2) ! ! 24 Page-turns (current process session only) integer ! ! 25 Thousands of bytes output to slow-devices ! (local or remote) (may be reset only by ! privileged processes) integer ! ! 26 Thousands of bytes input from slow-devices ! (local or remote) (may be reset only by ! privileged processes) integer ! ! 27 Milliseconds of OCP time used, interactive ! and batch modes (may be reset only by ! privileged processes) integer(x2) ! ! 28 Milliseconds of OCP time used (current ! session only) integer ! ! 29 Seconds of interactive terminal connect time ! (may be reset only by privileged processes) integer ! ! 30 No. of disc files, total disc Kbytes, no. of ! cherished files, total cherished Kbytes, no. ! of temporary files, total temporary Kbytes ! (cannot be reset) integer(x6) ! ! 31 No. of archive files, total archive Kbytes integer(x2) ! ! 32 Interactive session length in minutes integer ! 0 or 5 <= x <= 240 ! ! 33 Funds integer ! ! 34 The FSYS of the Group Holder of the index integer ! owners funds, if he has a GH ! ! 35 Test BASEFILE name string(18) ! ! 36 Batch BASEFILE name string(18) ! ! 37 Group Holder of funds for scarce resources string(6) ! ! 38 Privileges integer ! ! 39 Default LP string(15) ! ! 40 Dates passwords last changed integer(x2) ! (may not be reset) ! ! 41 Password data integer(x8) ! ! 42 Get accounting data integer(x17) ! ! 43 Mail count integer ! (may be reset only by privileged processes) ! ! 44 Supervisor string(6) ! ! 45 Secure record about 512 bytes ! ! 46 Gateway access id string(15) ! ! 47 File index attributes byte ! ! 48 User type byte EXTERNALINTEGERFNSPEC DTOFF(RECORD (pe)NAME P) EXTERNALINTEGERFNSPEC DTRANSFER(STRINGNAME FILE INDEX1, FILE INDEX2, FILE1, C FILE2, INTEGERNAME FSYS1, FSYS2, TYPE) ! This procedure transfers FILE1 belonging to file index FILE INDEX1 on ! FSYS1 to the ownership of file index FILE INDEX2 on FSYS2 under name ! FILE2. ! ! TYPE = 0 'accepts' a file which has been 'offered'. This call ! is non-privileged. ! 1 a privileged call to transfer a file. ! 2 like 1, but, in addition, forces a re-allocation of the ! disc space. ! 3 a privileged call to copy the file. ! 4 as 3 but works even when file connected W (for test purposes) EXTERNALINTEGERFNSPEC DVALIDATE(INTEGERNAME ADR, LEN, RW) finish if TARGET = 2900 start systemroutinespec oper(integer oper no, string (255) s) finish else start externalintegerfnspec doper(stringname s) finish externalstring (6) spec my name externalintegerspec my service number externalintegerspec my fsys externalintegerspec oper no conststring (1) snl = " " constinteger atrans = x'80C0008F'; !ADDR OF MASTER I TO E AND E TO I TABLES constinteger not assigned = x'80808080'; !INTERNAL UNASSIGNED PATTERN constinteger r = b'00000001'; !READ ACCESS constinteger w = b'00000010'; !WRITE ACCESS constinteger sh = b'00001000'; !shared access constinteger section size = 64; !SECTION SIZE IN KBYTES constinteger file header size = 32; !STANDARD FILE HEADER SIZE constinteger max oper = 7; !MAXIMUM OPER NUMBER constinteger max streams = 19; !MAX NUMBER OF OUTPUT STREAMS constinteger already exists = 16; !FILE ALREADY EXISTS FLAG constinteger to queue dact = 10; !ACTIVITY TO PUT ONE OF SPOOLERS OWN FILES IN A QUEUE constinteger descriptor update = 12; !PERIODIC DOC DESCRIPTOR UPDATE. constinteger prompt reply dact = 19; !ACTIVITY SHOULD REQUIRES REPLIES FROM PROMPT ON constinteger oper prompt = x'320008'; !SERVICE NUMBER OF OPER PROMPT constbyteintegerarray hex(0 : 15) = c '0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F' routinespec iocp(integer ep, n) stringfnspec errs(integer flag) routinespec define(integer stream, size, string (15) q) recordformat fhf(integer end, start, size, type, spare, datetime, s1, s2) owninteger current stream = 0; !DEFAULT AND CURRENT OUTPUT STREAM ownstring (132) array oper buffer(0 : max oper) = c ""(max oper + 1) !OPER OUTPUT SAVED HERE UNTIL A NEWLINE OR FULL ownintegerarray conads(1 : max streams) = c 0(max streams) !CONNECT ADDRESS OF OUTPUT STREAMS externalintegerfn validate(integer adr, len, rw) !*********************************************************************** !* * !* FUNCTION VALIDATES THE AREA SPECIFIED FOR READ OR WRITE ACCESS * !* RESULT = 1 AREA OK (ACCESSIBLE) * !* RESULT = 0 AREA NOT OK (INACCESSIBLE) * !* RW SHOULD BE SET 0 (READ ACCESS) * !* OR 1 (WRITE ACCESS) * !* * !*********************************************************************** if TARGET = 2900 start integer inseg1, inseg2 longinteger dr constinteger write = 1 result = 0 unless 0 < len <= x'40000'; ! DON'T ALLOW > 1 SEG ANYWAY ! WE WANT TO COVER THE SEG BOUNDARY CASE HERE if adr>>18 # (adr+len-1)>>18 start inseg2 = (adr+len)&x'3FFFF'; !HIGHER SEGMENT NUMBER inseg1 = len-inseg2; !LOWER SEGMENT NUMBER result = validate(adr,inseg1,rw)&validate(adr+inseg1, inseg2,rw) !OK ONLY IF BOTH VALIDATE finish dr = x'1800000000000000'!(LENGTHENI(LEN)<<32)!ADR !SET UP A DESCIPTOR FOR AREA *ld_dr *val_(lnb +1) *jcc_8,<cczer> *jcc_4,<ccone> *jcc_2,<cctwo> ! THEN CC=3, INVALID result = 0 cczer: ! read and write permitted result = 1; ! OK ccone: ! read, but not write, permitted if rw = write then result = 0; ! BAD result = 1; ! OK cctwo: ! write, but not read, permitted result = 0; ! BAD finish else start {non 2900} integer flag flag = dvalidate(adr, len, rw) result = flag finish end ; !OF INTEGERFN VALIDATE !*********************************************************************** !* * !* 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 * !* * !*********************************************************************** stringfn s2(integer n) !THIS FUNCTION RETURNS A TWO DIGIT DECIMAL VALUE FOR N integer tens, units tens = n//10 units = n-10*tens result = tostring(tens+'0').tostring(units+'0') end ; !OF S2 externalstringfn unpack date(integer p) result = s2(p>>17&x'1F')."/".s2(p>>22&x'F')."/".s2((p>>26& c x'3F')+70) end ; !OF UNPACK DATE externalstringfn unpack time(integer p) result = s2(p>>12&x'1F').".".s2(p>>6&x'3F').".".s2(p&x'3F') end ; !OF UNPACK TIME 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 externalintegerfn pack date(string (8) date) integer ad ad = addr(date) result = ((i2(ad+7)-70)<<26)!(i2(ad+4)<<22)!(i2(ad+1)<<17) end ; !OF PACK DATE externalintegerfn pack date and time(string (8) date, time) integer at at = addr(time) result = pack date(date)!(i2(at+1)<<12)!(i2(at+4)<<6)!(i2( c at+7)) end ; !OF PACK DATE AND TIME stringfn errs(integer flag) integer i; string (63) error if TARGET = 2900 then result = derrs(flag) else START i = dflag(flag,error) result = error FINISH end externalroutine stop alias "S#STOP" integer flag if TARGET # 2900 then flag = dstop(100) else dstop(100) end ; !OF ROUTINE STOP if TARGET = 2900 start externalroutine i to e(integer ad, l) integer j j = integer(atrans); !ADDR OF I TO E TABLE IN PUBLIC SEGMENT *lb_l *ldtb_x'18000000' *ldb_b *lda_ad *lss_j *luh_x'18000100' *ttr_l =dr end ; !OF I TO E externalroutine e to i(integer ad, l) integer j j = integer(atrans)+256; !ADDR OF E TO I TABLE IN PUBLIC SEGMENT *lb_l *ldtb_x'18000000' *ldb_b *lda_ad *lss_j *luh_x'18000100' *ttr_l =dr end ; !OF E TO I systemroutine move(integer length, from, to) !*********************************************************************** !* * !* MOVES "LENGTH" BYTES "FROM" "TO" * !* * !*********************************************************************** *ldtb_x'18000000' *ldb_length ; *lda_from *cyd_0 ; *lda_to *mv_l =dr end ; !OF ROUTINE MOVE finish else start {NON 2900} !* externalroutine itoe(integer ad, l) !* iso to ebcdic integer i,j byteintegerarrayname table byteintegerarrayformat tablef(0:255) returnif l=0 constrecord (comf)name com = 31 << seg shift table==array(com_trans,tablef) for i=0,1,l cycle j=ad+i byteinteger(j)=table(byteinteger(j)) repeat end ; !of itoe !* !* externalroutine etoi(integer ad, l) !* ebcdic to iso integer i,j byteintegerarrayname table byteintegerarrayformat tablef(0:255) returnif l=0 constrecord (comf)name com = 31 << seg shift table==array(com_trans+256,tablef) for i=0,1,l cycle j=ad+i byteinteger(j)=table(byteinteger(j)) repeat end ; !of etoi !* !* externalroutine move(integer length, from, to) !*********************************************************************** !* moves "LENGTH" bytes "FROM" "TO" !*********************************************************************** integer i returnif length=0 byteinteger(to+i)=byteinteger(from+i) for i=0,1,length end ; !of routine move !* finish {of NON 2900} if TARGET = 2900 start systemroutine fill(integer length, from, filler) !*********************************************************************** !* * !* FILL "LENGTH" BYTES "FROM" WITH CHARACTER "FILLER" * !* * !*********************************************************************** *lb_length *ldtb_x'18000000' *ldb_b *lda_from *lb_filler *mvl_l =dr end finish else start {NON 2900} externalroutine fill(integer length, from, filler) integer i return if length = 0 byteinteger(from+i) = filler for i = 0 ,1 ,length end ; !OF ROUTINE FILL finish externalstring (15) fn i to s(integer n) !********************************************************************** !* * !* TURNS AN INTEGER INTO A STRING USES MACHINE CODE * !* * !********************************************************************** string (16) s integer d0, d1, d2, d3, sign,w,d if TARGET # 2900 start result ="0" if n=0 sign=1 sign=-1 and n=-n if n<0; ! which can overflow s="" while n>0 cycle w=n//10 d=n-w*10 s=tostring('0'+d).s n=w repeat s="-".s if sign<0 result =s finish else start {2900} *lss_n; *cdec_0 *ld_s; *inca_1; ! PAST LENGTH BYTE *cpb_b ; ! SET CC=0 *supk_l =15,0,32; ! UNPACK 15 DIGITS SPACE FILL *std_d2; ! FINAL DR FOR LENGTH CALCS *jcc_8,<waszero>; ! N=0 CASE *lsd_tos ; *st_d0; ! SIGN DESCRIPTOR STKED BY SUPK *ld_s; *inca_1 *mvl_l =15,15,48; ! FORCE IN ISO ZONE CODES if n < 0 then byteinteger(d1) = '-' and d1 = d1-1 byteinteger(d1) = d3-d1-1 result = string(d1) waszero: result = "0" finish end ; !OF STRINGFN I TO S if TARGET = 2900 start system string (255) fn substring(string name s, integer i,j) string (255) holds j = j - i + 1 length(holds) = j move(j, addr(s)+i, addr(holds)+1) result = holds end finish else start external string (255) fn substring(string name s, integer i,j) string (255) holds j = j - i + 1 length(holds) = j move(j, addr(s)+i, addr(holds)+1) result = holds end finish if TARGET = 2900 start systemroutine write(integer value, places) string (16) s integer d0, d1, d2, d3, l places = places&15 *lss_value; *cdec_0 *ld_s; *inca_1; *std_tos *cpb_b ; ! SET CC=0 *supk_l =15,0,32; ! UNPACK & SPACE FILL *std_d2; *jcc_8,<waszero> *ld_tos ; *std_d0; ! FOR SIGN INSERTION *ld_tos *mvl_l =15,63,0; ! FORCE ISO ZONE CODES if value < 0 then byteinteger(d1) = '-' l = d3-d1 out: if places >= l then l = places+1 d3 = d3-l-1 byteinteger(d3) = l iocp(15,d3) return waszero: byteinteger(d3-1) = '0' l = 2; -> out end ; !OF ROUTINE WRITE finish else start {NON 2900} !* externalroutine write alias "S#WRITE" (integer i, pl) string (31) s if i < 0 start print string("-") if i = x'80000000' then i = x'7FFFFFFF' else i = -i finish else print string(" ") s = itos(i) if length(s) < pl then spaces(pl-length(s)) printstring(s) end ; ! write !* finish {NON 2900} externalstring (8) fn h to s(integer value, places) !********************************************************************** !* * !* TURNS AN INTEGER INTO A HEXIDECIMAL STRING OF GIVEN LENGTH * !* USES MACHINE CODE * !* * !********************************************************************** string (8) s integer i if TARGET # 2900 start places=1 if places<1 places=8 if places>8 s="" cycle s=tostring(hex(value&15)).s places=places-1 result =s if places=0 value=value>>4 repeat finish else start {2900} i = 64-4*places *ld_s; *lss_places; *st_(dr ) *inca_1; *std_tos ; *std_tos *lss_value; *luh_0; *ush_i *mpsr_x'24'; ! SET CC=1 *supk_l =8 *ld_tos ; *ands_l =8,0,15; ! THROW AWAY ZONE CODES *lss_hex+4; *luh_x'18000010' *ld_tos ; *ttr_l =8 result = s finish {2900} end ; !OF STRINGFN H TO S externalintegerfn s to i(stringname s) !********************************************************************** !* * !* TURNS A STRING INTO AN INTEGER * !* * !********************************************************************** string (255) p, ns1, ns2 integer total, sign, ad, i, j, hex hex = 0; total = 0; sign = 1 ad = addr(p) a: if s ->ns1.(" ").ns2 and ns1="" then s=ns2 and -> a; !CHOP LEADING SPACES if s ->ns1.("-").ns2 and ns1="" then s=ns2 and sign = -1 if s ->ns1.("X").ns2 and ns1="" then s=ns2 and hex = 1 and -> a p = s unless s -> p.(" ").s then s = "" i = 1 while i <= byteinteger(ad) cycle j = byte integer(i+ad) -> fault unless '0' <= j <= '9' or (hex # 0 c and 'A' <= j <= 'F') if hex = 0 then total = 10*total c else total = total<<4+9*j>>6 total = total+j&15; i = i+1 repeat if hex # 0 and i > 9 then -> fault if i > 1 then result = sign*total fault: s = p.s result = not assigned end ; !OF INTEGERFN S TO I !* if TARGET # 2900 start externalroutine dump(integer start, finish, conad) !********************************************************************** !* dumps area specified by start and finish in hexidecimal !* accepts parameters as start, finish or as start,length with conad !* specifying the actual address of the area being dumped !********************************************************************** string (255)s integer i,j,above,actual start,prev start finish=start+finish-1 if finish<start; ! must mean start, length start=start&x'FFFFFFFC' actual start=start conad=conad&x'FFFFFFFC' finish=((finish+4)&x'FFFFFFFC')-1 returnif finish<start above = 0 -> printline; !must print first line in full ! nextline: -> printline if finish-start<32; ! must print last line prev start=start-32 for i=0,1,31 cycle if byteinteger(start+i)#byteinteger(prev start+i) then ->printline repeat above=above+1 start=start+32 -> nextline ! printline: if above#0 start spaces(50) if above=1 then print string(" line ") else printstring(i to s(above)." lines") print string(" as above".snl) above=0 finish s="*" for i=start,1,start+31 cycle j=byteinteger(i) unless 32<=j < 127 then j='_' s=s.to string(j) repeat s=s."* (".h to s(conad+(start-actual start), 8).") " for i=start,4,start+28 cycle s=s.h to s(integer(i), 8)." " repeat start=start+32 print string(s.snl) -> nextline unless start>finish end ; ! of dump finish else start {2900} externalroutine dump(integer start, finish, conad) !********************************************************************** !* * !* DUMPS AREA SPECIFIED BY START AND FINISH IN HEXIDECIMAL * !* ACCEPTS PARAMETERS AS START, FINISH OR AS START,LENGTH WITH CONAD * !* SPECIFYING THE ACTUAL ADDRESS OF THE AREA BEING DUMPED * !* * !********************************************************************** constbyteintegerarray table(0 : 255) = c '_'(32), ' ','!','"','#','$','%','&','''','(', ')','*','+',',','-','.','/','0','1', '2','3','4','5','6','7','8','9',':', ';','<','=','>','?','@','A','B','C', 'D','E','F','G','H','I','J','K','L', 'M','N','O','P','Q','R','S','T','U', 'V','W','X','Y','Z','[','¬',']','^', '_','`','a','b','c','d','e','f','g', 'h','i','j','k','l','m','n','o','p', 'q','r','s','t','u','v','w','x','y', 'z','{','|','}','~','_'(129) string (255) s integer i, j, above, actual start !TEST IS TO SEE IF LENGTH< START finish = start+finish-1 if finish < start !MUST MEAN START, LENGTH start = start&x'FFFFFFFC' actual start = start conad = conad&x'FFFFFFFC' finish = ((finish+4)&x'FFFFFFFC')-1 return if finish < start above = 0 -> printline; !MUST PRINT FIRST LINE IN FULL nextline: -> printline if finish-start < 32 !MUST PRINT LAST LINE *lda_start; !CHECK IF SAME AS PREVIOUS LINE *ldtb_x'18000020' *cyd_0 *inca_-32 *cps_ l = dr *jcc_7, < printline > above = above+1 start = start+32 -> nextline printline: if above # 0 start spaces(50) if above = 1 then print string(" LINE ") c else print string(i to s(above)." LINES ") print string("AS ABOVE".snl) above = 0 finish s = "*" ! %CYCLE I = START,1,START+31 ! J = BYTEINTEGER(I) ! %UNLESS 32 <= J < 127 %THEN J = '_' ! S = S.TO STRING(J) ! %REPEAT i = addr(table(0)) j = addr(s)+2 *ldtb_x'18000020' *lda_start *cyd_0 *lda_j *mv_l =dr *lb_32 *ldtb_x'18000000' *ldb_b *lda_j *lss_i *luh_x'18000100' *ttr_l =dr length(s) = 33 s = s."* (".h to s(conad+(start-actual start),8).") " cycle i = start,4,start+28 s = s.h to s(integer(i),8)." " repeat start = start+32 print string(s.snl) -> nextline unless start > finish end ; ! OF DUMP finish {2900} externalroutine pt rec(record (pe)name p) !******************************************************************** !* * !* PRINT RECORD P AS A STRING * !* * !******************************************************************** string (255) s integer i, j, k, char s = "" j = addr(p_dest) k = 1 cycle i = j,1,j+31 s = s.h to s(byteinteger(i),2); !DONE THIS WAY TO AVOID UNASSIGNED CHECK s = s." " and k = 0 if k = 4 k = k+1 repeat s = s." " j = addr(p_p1) cycle i = j,1,j+23 char = byteinteger(i) char = ' ' unless 32 < char < 127 s = s.to string(char) repeat print string(s.snl) end ; !OF ROUTINE PT REC externalroutine prompt(string (23) s) !*********************************************************************** !* * !* PUT A PROMPT UP ON THE CURRENT OPER * !* * !*********************************************************************** record (pf)p integer flag p_dest = oper prompt!(oper no)<<8 p_srce = my service number!prompt reply dact p_text = s flag = dpon3("",p,0,0,6) end ; !OF ROUTINE PROMPT externalroutine define(integer stream, size, string (15) q) !*********************************************************************** !* * !* DEFINE THE SPECIFIED OUTPUT STREAM AND CREATE A FILE OF THE GIVEN * !* SIZE. IF THE FILE ALREADY EXISTS SEND IT TO A QUEUE OR TO BE * !* DESTROYED. * !* * !*********************************************************************** recordformat pf(integer dest, srce, string (11) file, integer p4, p5, p6) record (pf)p record (fhf)name file header integer seg, gap, flag, i, ada string (11) file, newname string (255) failm if 1 <= stream <= max streams start ; !VALID STREAM NO? if 1 <= length(q) <= 15 start ; !VALID QUEUE NAME? if conads(stream) = 0 start ; !ALREADY DEFINED? if 1 <= size <= 1024 start ; !VALID SIZE? file = "STREAM".i to s(stream) if TARGET # 2900 then flag = dcreate(my name,file,my fsys,size,4,ada) c else flag = dcreate(my name,file,my fsys,size,4) if flag = already exists start cycle i = 0,1,99 newname = "S".i to s(stream).h to s( c pack date and time(date,time)+i,8) !A TEMP NAME flag = drename(myname,file,newname,myfsys) print string("RENAME ".myname.".".file. c " TO ".myname.".".newname." FAILS ". c errs(flag).snl) if flag # 0 exit if flag = 0 repeat p = 0 p_dest = my service number!to queue dact p_file = newname p_p4 = my fsys flag = dpon3("",p,0,0,6) if TARGET # 2900 then flag = dcreate(my name,file,my fsys,size,4,ada) c else flag = dcreate(my name,file,my fsys,size,4) finish if flag = 0 start seg = 0; gap = 0; !ANY SEGMENT MINIMUM GAP if TARGET # 2900 then flag = dconnect(my name,file,my fsys,r!w!sh,seg,gap) c else flag = dconnect(my name,file,my fsys,r!w!sh,0,seg,gap) if flag = 0 start conads(stream) = seg<<seg shift file header == record(conads(stream)) file header_start = file header size+16 !TO ALLOW FOR FILE NAME file header_end = file header size+16 !DITTO file header_size = size<<10 file header_type = 3 file header_datetime = c pack date and time(date,time) file header_s1 = x'FFFFFF02';!FOR JOURNAL ANALYSIS string(conads(stream)+31) = q return finish else failm = "CONNECT ".myname."." c .file." FAILS ".errs(flag) finish else failm = "CREATE ".myname.".". c file." FAILS ".errs(flag) finish else failm = "INVALID SIZE ".i to s(size). c "K" finish else failm = "ALREADY DEFINED" finish else failm = "INVALID OUTPUT QUEUE ".q finish else failm = "INVALID STREAM NUMBER" print string("DEFINE STREAM ".i to s(stream)." FAILS ". c failm.snl) end ; !OF ROUTINE DEFINE externalroutine close stream(integer stream, string (15) q) !*********************************************************************** !* * !* CLOSE THE SPECIFIED STREAM AND CHANGE THE DESTINATION IN ITS HEADER* !* IF REQUIRED. NOTE THAT NOTHING HAPPEND TO THE FILE AT THIS STAGE. * !* * !*********************************************************************** string (255) failm integer flag string (11) file if 1 <= stream <= max streams start if conads(stream) # 0 start ; !FILE CURRENTLY CONNECTED file = "STREAM".i to s(stream) string(conads(stream)+31) = q if q # "";!REROUTE FILE conads(stream) = 0 flag = ddisconnect(myname,file,myfsys,0) print string("DISCONNECT ".myname.".".file." FAILS " c .errs(flag).snl) if 39 # flag # 0 return finish else failm = "NOT DEFINED" finish else failm = "INVALID STREAM NO" print string("CLOSE STREAM ".i to s(stream)." FAILS ".failm. c snl) end ; !OF ROUTINE CLOSE STREAM routine update output(integer address, len) integer end, sym, size, stream, seg, gap, flag record (fhf)name file header record (pe)p string (11) file if current stream = 0 start ; !OPER CONSOLE end = address+len while address < end cycle sym = byteinteger(address) if sym = nl or length(oper buffer(oper no)) = 132 start if TARGET # 2900 then flag = doper(oper buffer(oper no)) else c oper(oper no,oper buffer(oper no)); !OUTPUT THE BUFFER if conads(1) # 0 start ; !IS THERE A MAINLOG select output(1); !MAIN LOG STREAM print string("DT: ".date." ".time." TO OPER". c i to s(oper no)." ".oper buffer(oper no).snl) select output(0) finish oper buffer(oper no) = "" finish oper buffer(oper no) = oper buffer(oper no).to string( c sym) if sym # nl address = address+1 repeat finish else start file header == record(conads(current stream)) if file header_end+len > file header_size start !END OF FILE size = file header_size>>10; !REMEMBER SIZE stream = current stream select output(0); !IN CASE ANY FAILURES DURING FILE SIZE CHANGE file = "STREAM".i to s(stream) flag = ddisconnect(my name,file,my fsys,0) if flag = 0 start size = size+section size; !EXTEND IT BY A SECTION !HERE PON OF MESSAGE TO MYSELF FOR THE PERIODIC DOC DESCRIPTOR UPDATE. p=0 p_dest=my service number ! descriptor update p_p1=0; !START LOOKING AT FSYS 0 flag=dpon3("",p,0,0,6) if size>256 then start !DO NOT ALLOW LOG TO EXCEED 256K. close stream(stream,"") define(stream,64,".JOURNAL") file header==record(conads(stream)) select output(stream) finish else start flag = dchsize(my name,file,my fsys,size) if flag = 0 start seg = 0; gap = 0 if TARGET # 2900 then flag = dconnect(my name,file,my fsys,r!w!sh,seg,gap) c else flag = dconnect(myname,file,my fsys,r!w!sh,0,seg,gap) if flag = 0 start conads(stream) = seg<<seg shift file header == record(conads(stream)) file header_size = size<<10 select output(stream) finish else print string("CONNECT ".myname. c ".".file." FAILS ".errs(flag).snl) finish else print string("CHSIZE ".myname.".". c file." FAILS ".errs(flag).snl) finish finish else print string("DISCONNECT ".myname.".". c file." FAILS ".errs(flag).snl) return if flag # 0 finish move(len,address,file header_end+conads(current stream)) file header_end = file header_end+len finish end ; !OF ROUTINE UPDATE OUTPUT externalroutine iocp alias "S#IOCP" (integer ep, n) integer num, sym byteintegerarray s(0 : 255) switch io(0 : 17) -> io(0) unless 0 < ep <= 17 -> io(ep) io(3): ! printsymbol(n) io(5): ! printch(n) update output(addr(n)+3,1) return io(7): ! printstring io(15): ! printstring (only valid chars allowed) update output(n+1,byteinteger(n)) return io(17): ! mulsymbol num = (n>>8)&255 sym = n&255 fill(num,addr(s(0)),sym) update output(addr(s(0)),num) return io(9): !select output if 0 <= n <= max streams start if n # 0 start ; !NOT OPER? if conads(n) = 0 start ; !NOT CONNECTED print string("SELECT OUTPUT ".i to s(n). c " FAILS STREAM NOT DEFINED".snl) return finish finish current stream = n finish else print string("SELECT OUTPUT ".i to s(n). c " FAILS INVALID STREAM NUMBER".snl) return io(16): !close stream close stream(n,"") return io(0): !invalid io(1): !read symbol io(2): !next symbol io(4): !read ch io(6): !reconstruct io(8): !select input io(10): !iso card io(11): !chop current output io(12): !set input margin io(13): !set output margin io(14): !set read address print string("ILLEGAL CALL ON IOCP EP = ") write(ep,2); newline end ; !OF ROUTINE IOCP endoffile