!TITLE Subsystem maintenance utilities ! ! ! This package is a collection of utility commands which are primarily ! intended for supporting and maintaining the Edinburgh Subsystem. ! ! ! Subjects covered are: ! ! 1 Updating members of pdfiles ! 2 Messages of the day ! 3 Altering the ALERT time ! 4 Subsystem basefiles ! 5 Subsystem option files ! 6 Handling of user suggestions ! 7 Checking partitioned files ! ! ! !STOP ! ! !*********************************************************************** !* !* Subsystem maintenance utilities !* !* Copyright (C) R.D. Eager University of Kent MCMLXXXI !* !*********************************************************************** ! ! !*********************************************************************** !* !* Constants !* !*********************************************************************** ! CONSTINTEGER NO = 0, YES = 1 CONSTINTEGER INCHAN = 1, OUTCHAN = 2 CONSTINTEGER BACKGROUND = 0, FOREGROUND = 1, BOTH = 2 CONSTINTEGER SSOBJFILETYPE = 1 CONSTINTEGER SSCHARFILETYPE = 3 CONSTINTEGER SSDATAFILETYPE = 4 CONSTINTEGER SSOPTFILETYPE = 9 CONSTINTEGER ALERTSIZE = 27; ! Size of 'alert' part of message of the day CONSTINTEGER SEGSIZE = X'00040000' CONSTINTEGER ABASEFILE = X'00800000'; ! Address of basefile when loaded CONSTSTRING (1) SNL = " " CONSTSTRING (6) OWNER = "SUBSYS" CONSTSTRING (11) DEFAULTPD = "SYSTEM"; ! For UPDATEPD command CONSTSTRING (11) DEFAULTACTIVEDIR = "SS#DIR" CONSTSTRING (10) TEMPDIR = "T#TEMPDIR" CONSTSTRING (17) SSBLKBRD = "SUBSYS.SUGGESTION" CONSTSTRING (11)ARRAY MESSAGEFILE(BACKGROUND:BOTH) = C "BMESSAGE","FMESSAGE","FMESSAGE" CONSTSTRING (8)ARRAY OPNAME(BACKGROUND:BOTH) = C "SETBMESS","SETFMESS","SETBOTH" CONSTSTRING (8) SANAME = "SETALERT" ! CONSTSTRING (10)ARRAY BKEYS(1:2) = "BRACKETS","NOBRACKETS" CONSTBYTEINTEGERARRAY BVALUES(1:2) = 1,2 CONSTSTRING (8)ARRAY EKEYS(1:3) = "NOECHO","PARTECHO","FULLECHO" CONSTBYTEINTEGERARRAY EVALUES(1:3) = 0,1,2 CONSTSTRING (10)ARRAY JKEYS(1:3) = "NORECALL","TEMPRECALL","PERMRECALL" CONSTBYTEINTEGERARRAY JVALUES(1:3) = 0,1,2 CONSTSTRING (12)ARRAY LKEYS(1:2) = "BLANKLINES","NOBLANKLINES" CONSTBYTEINTEGERARRAY LVALUES(1:2) = 0,1 ! CONSTBYTEINTEGERARRAY HEX(0:15) = C '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' ! ! !*********************************************************************** !* !* Subsystem references !* !*********************************************************************** ! SYSTEMROUTINESPEC CHANGEACCESS(STRING (31) FILE,INTEGER MODE,C INTEGERNAME FLAG) SYSTEMINTEGERMAPSPEC COMREG(INTEGER I) SYSTEMROUTINESPEC CONNECT(STRING (31) FILE,INTEGER MODE,HOLE,C PROT,RECORDNAME R,INTEGERNAME FLAG) EXTERNALSTRINGFNSPEC DATE SYSTEMROUTINESPEC DEFINE(INTEGER CHAN,STRING (31) IDEN,C INTEGERNAME AFD,FLAG) EXTERNALROUTINESPEC DEFINFO(INTEGER CHAN,STRINGNAME FILENAME,C INTEGERNAME STATUS) SYSTEMROUTINESPEC DESTROY(STRING (31) FILE,INTEGERNAME FLAG) SYSTEMROUTINESPEC DISCONNECT(STRING (31) FILE,INTEGERNAME FLAG) SYSTEMSTRINGFNSPEC FAILUREMESSAGE(INTEGER MESS) SYSTEMROUTINESPEC FILL(INTEGER LENGTH,FROM,FILLER) SYSTEMSTRINGFNSPEC ITOS(INTEGER N) SYSTEMROUTINESPEC MODDIRFILE(INTEGER EP,STRING (31) DIRFILE,ENTRY,C FILENAME,INTEGER TYPE,DR0,DR1,C INTEGERNAME FLAG) SYSTEMROUTINESPEC MODPDFILE(INTEGER EP,STRING (31) PDFILE,C STRING (11) MEMBER,STRING (31) INFILE,C INTEGERNAME FLAG) SYSTEMROUTINESPEC MOVE(INTEGER LENGTH,FROM,TO) SYSTEMROUTINESPEC NEWGEN(STRING (31) FILE,NEWFILE,INTEGERNAME FLAG) SYSTEMSTRINGFNSPEC NEXTTEMP SYSTEMROUTINESPEC OUTFILE(STRING (31) FILE,INTEGER SIZE,HOLE,C PROT,INTEGERNAME CONAD,FLAG) EXTERNALINTEGERFNSPEC OUTPOS SYSTEMINTEGERFNSPEC PARMAP SYSTEMROUTINESPEC PERMIT(STRING (31) FILE,STRING (6) USER,C INTEGER MODE,INTEGERNAME FLAG) EXTERNALROUTINESPEC PROMPT(STRING (255) S) SYSTEMINTEGERFNSPEC PSTOI(STRING (63) S) SYSTEMROUTINESPEC SETFNAME(STRING (63) S) SYSTEMROUTINESPEC SETPAR(STRING (255) S) EXTERNALROUTINESPEC SET RETURN CODE(INTEGER I) SYSTEMSTRINGFNSPEC SPAR(INTEGER N) EXTERNALSTRINGFNSPEC TIME SYSTEMROUTINESPEC UCTRANSLATE(INTEGER AD,LEN) EXTERNALINTEGERFNSPEC UINFI(INTEGER ENTRY) EXTERNALSTRINGFNSPEC UINFS(INTEGER N) ! EXTERNALROUTINESPEC CHERISH(STRING (255) S) EXTERNALROUTINESPEC CLEAR(STRING (255) S) EXTERNALROUTINESPEC PARM(STRING (255) S) ! ! !*********************************************************************** !* !* Record and array formats !* !*********************************************************************** ! RECORDFORMAT CONTF(INTEGER DATAEND,DATASTART,PSIZE,FILETYPE,C SUM,DATETIME,SP0,SP1,MARK,NULL1,UGLA,ASTK,USTK,C NULL2,ITWIDTH,LDELIM,RDELIM,JOURNAL,C SEARCHDIRCOUNT,ARRAYDIAG,INITWORKSIZE,SPARE,C ITINSIZE,ITOUTSIZE,NOBL,ISTK,C LONGINTEGER INITPARMS,INTEGER DATAECHO,C TERMINAL,I23,I24,I25,I26,I27,I28,I29,I30,I31,I32,C STRING (31) FSTARTFILE,BSTARTFILE,PRELOADFILE,C MODDIR,CFAULTS,S6,S7,S8,S9,S10,S11,S12,S13,S14,C S15,S16,S17,S18,S19,S20,S21,S22,S23,S24,S25,S26,C S27,S28,S29,S30,S31,S32,C STRING (31)ARRAY SEARCHDIR(1:16)) RECORDFORMAT DIRINFF(STRING (6) USER,STRING (31) BATCHFILE,C INTEGER MARK,FSYS,PROCNO,ISUFF,REASON,BATCHID,C SESSICLIM,SCIDENSAD,SCIDENS,OPERNO,AIOSTAT,C SCDATE,SYNC1DEST,SYNC2DEST,ASYNCDEST,AACCTREC,C AICREVS,STRING (15) BATCHIDEN,C STRING (31) BASEFILE,INTEGER PREVIC,ITADDR0,C ITADDR1,ITADDR2,ITADDR3,ITADDR4,STREAMID,DIDENT,C SCARCITY,PREEMPTAT,STRING (11) SPOOLRFILE,C INTEGER RESUNITS,SESSLEN,PRIORITY,DECKS,DRIVES,C UEND) RECORDFORMAT EP4F(INTEGER LINK,DISP,L,A,STRING (31) IDEN) RECORDFORMAT HF(INTEGER DATAEND,DATASTART,FILESIZE,FILETYPE,C SUM,DATETIME,FORMAT,RECORDS) RECORDFORMAT OFMF(INTEGER START,LEN,PROPS) RECORDFORMAT OHF(INTEGER DATAEND,DATASTART,FILESIZE,FILETYPE,SUM,C DATETIME,LDA,OFM) RECORDFORMAT PDF(INTEGER START,STRING (11) NAME,C INTEGER HOLE,S5,S6,S7) RECORDFORMAT PDHF(INTEGER DATAEND,DATASTART,SIZE,FILETYPE,SUM,C DATETIME,ADIR,COUNT) RECORDFORMAT RF(INTEGER CONAD,FILETYPE,DATASTART,DATAEND) ! OWNINTEGERARRAYFORMAT LDATAF(0:14) OWNBYTEINTEGERARRAYFORMAT BIF(1:10000) OWNRECORDARRAYFORMAT OFMAF(1:7)(OFMF) OWNRECORDARRAYFORMAT PDAF(1:4095)(PDF) ! ! !*********************************************************************** !* !* Service routines !* !*********************************************************************** ! STRING (255)FN SPECMESSAGE(INTEGER FLAG) SWITCH SW(1000:1002) ! -> SW(FLAG) ! SW(1000): RESULT = "Catastrophic failure" SW(1001): RESULT = "May be used only by ".OWNER SW(1002): RESULT = "Entry SSDATELINKED not found" END ; ! of SPECMESSAGE ! ! ROUTINE FAIL(STRING (15) OP,INTEGER FLAG) SELECTOUTPUT(0) PRINTSTRING(SNL.OP." fails -") IF FLAG < 1000 THEN START PRINTSTRING(FAILUREMESSAGE(FLAG)) FINISH ELSE START PRINTSTRING(" ".SPECMESSAGE(FLAG).SNL) FINISH SET RETURN CODE(FLAG) STOP END ; ! of FAIL ! ! ROUTINE CHECKUSER(STRING (15) OP) IF UINFS(1) # OWNER THEN START PRINTSTRING(OP." may be used only by ".OWNER.SNL) SET RETURN CODE(1000) STOP FINISH END ; ! of CHECKUSER ! ! ROUTINE READLINE(STRINGNAME S) INTEGER C ! S = "" CYCLE READSYMBOL(C) EXIT IF C = NL S <- S.TOSTRING(C) REPEAT ! WHILE LENGTH(S) > 0 CYCLE IF CHARNO(S,LENGTH(S)) # ' ' THEN EXIT LENGTH(S) = LENGTH(S) - 1 REPEAT END ; ! of READLINE ! ! STRING (8)FN HTOS(INTEGER VALUE,PLACES) INTEGER I STRING (8) S ! 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 END ; ! of HTOS ! ! INTEGERFN GETVAL(STRING (255) PR,INTEGER MIN,MAX,DEFAULT,MULT) INTEGER I STRING (255) S ! PROMPT(PR.": ") CYCLE READLINE(S) IF S = "" THEN START PRINTSTRING("[".ITOS(DEFAULT//MULT)."]".SNL) RESULT = DEFAULT FINISH I = PSTOI(S) IF I < 0 THEN START PRINTSTRING("Invalid number".SNL) CONTINUE FINISH I = I*MULT IF MIN <= I <= MAX THEN RESULT = I PRINTSTRING("Number outside permitted range".SNL) REPEAT END ; ! of GETVAL ! ! INTEGERFN GET SETTING(STRING (255) PR,INTEGER NSETTINGS,C STRINGARRAYNAME KEYS,C BYTEINTEGERARRAYNAME VALUES,STRING (31) DEFAULT) INTEGER I STRING (255) S ! PROMPT(PR.": ") CYCLE READLINE(S) UCTRANSLATE(ADDR(S)+1,LENGTH(S)) IF S = "" THEN START PRINTSTRING("[".DEFAULT."]".SNL) S = DEFAULT FINISH CYCLE I = 1,1,NSETTINGS IF S = KEYS(I) THEN RESULT = VALUES(I) REPEAT PRINTSTRING("Invalid setting".SNL) REPEAT END ; ! of GET SETTING ! ! STRING (255)FN GETSTR(STRING (255) PR,INTEGER MAXLEN,C STRING (255) DEFAULT) STRING (255) S ! CYCLE PROMPT(PR.": ") READLINE(S) UCTRANSLATE(ADDR(S)+1,LENGTH(S)) IF S = "." THEN RESULT = "" IF S = "" THEN START PRINTSTRING("[".DEFAULT."]".SNL) RESULT = DEFAULT FINISH IF LENGTH(S) <= MAXLEN THEN RESULT = S PRINTSTRING("Reply must not exceed ".ITOS(MAXLEN)." characters".SNL) REPEAT END ; ! of GETSTR ! ! INTEGERFN ROUNDUP(INTEGER N,R) R = R - 1 RESULT = (N+R) & (¬R) END ; ! of ROUNDUP ! ! ROUTINE CONNECT OR CREATE(STRING (11) FILE,RECORDNAME RR,C STRING (15) OP) RECORDSPEC RR(RF) INTEGER FLAG,CONAD RECORDNAME R(HF) ! CONNECT(FILE,1,0,0,RR,FLAG) IF FLAG = 218 THEN START ; ! File does not exist - create it PRINTSTRING("There is no ".FILE." file".SNL) PRINTSTRING("It is being created".SNL.SNL) OUTFILE(FILE,4096,0,0,CONAD,FLAG) IF FLAG = 0 THEN START R == RECORD(CONAD) R_FILETYPE = SSCHARFILETYPE PERMIT(FILE,"",1,FLAG); ! Set EEP = R CHERISH(FILE) FILL(ALERTSIZE-1,CONAD+R_DATASTART,' ') BYTEINTEGER(CONAD+R_DATASTART+ALERTSIZE-1) = NL R_DATAEND = R_DATASTART + ALERTSIZE FINISH CONNECT(FILE,1,0,0,RR,FLAG) FINISH IF FLAG # 0 THEN FAIL(OP,FLAG) END ; ! of CONNECT OR CREATE ! ! ROUTINE PRINTMESSAGE(INTEGER CONAD,STRING (7) TYPE) INTEGER I,J RECORDNAME R(HF) ! R == RECORD(CONAD) J = R_DATASTART + ALERTSIZE IF J >= R_DATAEND THEN START PRINTSTRING("The ".TYPE." message is null".SNL) FINISH ELSE START PRINTSTRING("The ".TYPE." message is:-".SNL.SNL) CYCLE I = CONAD+J,1,CONAD+R_DATAEND-1 PRINTSYMBOL(BYTEINTEGER(I)) REPEAT FINISH NEWLINE END ; ! of PRINT MESSAGE ! ! ROUTINE SETMESSAGE(STRINGNAME PARMS,INTEGER TYPE,MODE) INTEGER FLAG,CONAD,COUNT,J STRING (11) FILE,TEMPFILE STRING (15) OP STRING (255) LINE RECORD RR(RF) RECORDNAME R(HF) ! SET RETURN CODE(1000) FILE = MESSAGEFILE(TYPE) OP = OPNAME(MODE) CHECKUSER(OP) ! SETPAR(PARMS) IF PARMAP # 0 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH ! CONNECT OR CREATE(FILE,RR,OP) PRINTMESSAGE(RR_CONAD,"current") ! TEMPFILE = "T#".NEXTTEMP CYCLE PRINTSTRING("Type new message - terminated by :".SNL) ! LOOP: PROMPT("Message: ") OUTFILE(TEMPFILE,4096,0,0,CONAD,FLAG) -> ERR IF FLAG # 0 R == RECORD(CONAD) R_FILETYPE = SSCHARFILETYPE MOVE(ALERTSIZE,RR_CONAD+RR_DATASTART,CONAD+R_DATASTART) COUNT = R_DATASTART + ALERTSIZE CYCLE READLINE(LINE) EXIT IF LINE = ":" IF LENGTH(LINE) = 255 THEN LENGTH(LINE) = 254 LINE = LINE.SNL J = LENGTH(LINE) IF COUNT + J >= R_FILESIZE THEN START PRINTSTRING("Message too long - try again".SNL) -> LOOP FINISH MOVE(J,ADDR(LINE)+1,CONAD+COUNT) COUNT = COUNT + J REPEAT R_DATAEND = COUNT PRINTMESSAGE(CONAD,"new") PROMPT("OK? ") READLINE(LINE) UNTIL LINE # "" UCTRANSLATE(ADDR(LINE)+1,1) EXIT IF CHARNO(LINE,1) = 'Y' REPEAT ! NEWGEN(TEMPFILE,FILE,FLAG) -> ERR IF FLAG # 0 PRINTSTRING("New ".FILE." in use".SNL) SET RETURN CODE(0) RETURN ! ERR: FAIL(OP,FLAG) END ; ! of SETMESSAGE ! ! !*********************************************************************** !* !* U P D A T E P D !* !*********************************************************************** ! !<Updating members of pdfiles ! ! The command UPDATEPD is used to add a new member to, update an ! existing member in, or delete a member from, a pdfile which may be in ! use by other processes. ! ! The command takes the form: ! ! UPDATEPD(pdfile_member,option) ! ! where:- ! ! pdfile_member - specifies the member to be operated on ! option - if null, the member must already exist ! - if N, the member must not already ! exist ! - if D, the old member is simply deleted. ! ! ! ! ! ! It is assumed that any file which is to be a replacement for a member ! has the same name as the member itself, and resides in the same ! process. ! ! Since the most common use of this utility is to update members of ! SUBSYS.SYSTEM, the pdfile part of the parameter defaults to SYSTEM. !> ! EXTERNALROUTINE UPDATEPD(STRING (255) PARMS) INTEGER FLAG,CONAD,SAVEDT,OPTION STRING (11) MEMBER,TEMPFILE STRING (31) FILE,S RECORD RR(RF) RECORDNAME IR,OR(HF) ! SET RETURN CODE(1000) SETPAR(PARMS) IF 1 # PARMAP # 3 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH IF PARMAP & 2 # 0 THEN START S <- SPAR(2) IF "D" # S # "N" THEN START SETFNAME(S) FLAG = 202; ! Invalid parameter -> ERR FINISH OPTION = CHARNO(S,1) FINISH ELSE OPTION = 'Z'; ! Dummy value S <- SPAR(1) UNLESS S -> FILE.("_").MEMBER THEN START SETFNAME(PARMS) FLAG = 202; ! Invalid parameter -> ERR FINISH ! IF FILE = "" THEN FILE = DEFAULTPD ! UNLESS OPTION = 'D' THEN START CONNECT(MEMBER,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 FINISH CONNECT(FILE."_".MEMBER,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 AND OPTION # 'N' IF FLAG = 0 AND OPTION = 'N' THEN START FLAG = 287; ! Member already exists -> ERR FINISH CONNECT(FILE,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 IR == RECORD(RR_CONAD) ! ! Make temporary copy of pdfile ! TEMPFILE = "T#".NEXTTEMP OUTFILE(TEMPFILE,IR_FILESIZE,0,0,CONAD,FLAG) -> ERR IF FLAG # 0 OR == RECORD(CONAD) SAVEDT = OR_DATETIME; ! Save creation date over copy MOVE(IR_FILESIZE,RR_CONAD,CONAD); ! Take the copy OR_DATETIME = SAVEDT; ! Restore date ! ! Delete any existing copy of member. Ignore failures, except in the ! case of the 'D' option. ! MODPDFILE(2,TEMPFILE,MEMBER,"",FLAG) IF FLAG # 0 AND OPTION = 'D' THEN -> ERR ! ! Insert new copy of member if appropriate ! MODPDFILE(1,TEMPFILE,MEMBER,MEMBER,FLAG) UNLESS OPTION = 'D' -> ERR IF FLAG # 0 ! ! Put new copy of pdfile into service ! NEWGEN(TEMPFILE,FILE,FLAG) -> ERR IF FLAG # 0 PRINTSTRING("Member ".FILE."_".MEMBER) IF OPTION = 'D' THEN S = "destroyed" IF OPTION = 'N' THEN S = "inserted" IF OPTION = 'Z' THEN S = "replaced" PRINTSTRING(" ".S.SNL) SET RETURN CODE(0) STOP ! ERR: FAIL("UPDATEPD",FLAG) END ; ! of UPDATEPD ! ! !*********************************************************************** !* !* S E T F M E S S !* !*********************************************************************** ! !<Messages of the day ! ! ! Three commands are provided to alter the 'messages of the day' which ! are displayed at process start-up. These are described in the ! following Sections: ! ! !<Changing the foreground message ! ! ! ! The command SETFMESS is used to change the 'message of the day' ! displayed to foreground users when they log on. This special command ! is necessary to avoid problems if the file is currently in use, and ! to avoid disturbing the first line of the message, which always ! carries the date and time of the most recent ALERT text. ! ! SETFMESS takes no parameters. The user is prompted for the message, ! which should be terminated by a colon (:) on a line on its own. An ! opportunity is then given to amend the message if it is not ! satisfactory. !> ! EXTERNALROUTINE SETFMESS(STRING (255) PARMS) SETMESSAGE(PARMS,FOREGROUND,FOREGROUND) END ; ! of SETFMESS ! ! !*********************************************************************** !* !* S E T B M E S S !* !*********************************************************************** ! !<Changing the background message ! ! ! ! The command SETBMESS is used to change the 'message of the day' ! displayed to background users when their job starts. This special ! command is necessary to avoid problems if the file is currently in ! use, and to avoid disturbing the first line of the message, which ! always carries the date and time of the most recent ALERT text. ! ! SETBMESS takes no parameters. The user is prompted for the message, ! which should be terminated by a colon (:) on a line on its own. An ! opportunity is then given to amend the message if it is not ! satisfactory. !> ! EXTERNALROUTINE SETBMESS(STRING (255) PARMS) SETMESSAGE(PARMS,BACKGROUND,BACKGROUND) END ; ! of SETBMESS ! ! !*********************************************************************** !* !* S E T B O T H !* !*********************************************************************** ! !<Changing both messages ! ! ! ! The command SETBOTH is used to change both 'messages of the day' ! displayed to users on process start-up. This special command is ! necessary to avoid problems if the file is currently in use, and ! to avoid disturbing the first line of the message, which always ! carries the date and time of the most recent ALERT text. ! ! SETBOTH takes no parameters. The user is prompted for the message, ! which should be terminated by a colon (:) on a line on its own. An ! opportunity is then given to amend the message if it is not ! satisfactory. !> !> ! EXTERNALROUTINE SETBOTH(STRING (255) PARMS) INTEGER FLAG,CONAD STRING (11) TEMPFILE RECORD RR(RF) ! SETMESSAGE(PARMS,FOREGROUND,BOTH) ! TEMPFILE = "T#".NEXTTEMP CONNECT(MESSAGEFILE(FOREGROUND),1,0,0,RR,FLAG) -> ERR IF FLAG # 0 OUTFILE(TEMPFILE,4096,0,0,CONAD,FLAG) -> ERR IF FLAG # 0 MOVE(4096,RR_CONAD,CONAD) ! NEWGEN(TEMPFILE,MESSAGEFILE(BACKGROUND),FLAG) -> ERR IF FLAG # 0 ! PRINTSTRING("New ".MESSAGEFILE(BACKGROUND)." in use".SNL) SET RETURN CODE(0) STOP ! ERR: FAIL(OPNAME(BOTH),FLAG) END ; ! of SETBOTH ! ! !*********************************************************************** !* !* S E T A L E R T !* !*********************************************************************** ! !<Altering the ALERT time ! ! ! ! The command SETALERT is used to alter the date and time given in the ! 'Latest ALERT' message which forms a permanent part of the message ! of the day, for both foreground and background users. ! ! SETALERT takes up to two parameters:- ! ! 1) The time to be used in the message. Exactly four characters are ! expected, i.e.: hhmm. If this parameter is omitted, a prompt ! is issued for it. ! ! 2) The date to be used in the message. Standard EMAS date format is ! assumed, i.e.: dd/mm/yy. If this parameter is omitted, the ! current date is assumed. !> ! EXTERNALROUTINE SETALERT(STRING (255) PARMS) INTEGER CONAD,I,SAVEDT,FLAG STRING (11) FILE,TEMPFILE STRING (255) ASTRING,D,T RECORD RR(RF) RECORDNAME OR(HF) ! SET RETURN CODE(1000) CHECKUSER(SANAME) SETPAR(PARMS) IF PARMAP > 3 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH T = SPAR(1) D = SPAR(2) IF D = "" THEN D = DATE IF LENGTH(D) # 8 THEN START SETFNAME(D) FLAG = 202; ! Invalid parameter -> ERR FINISH CYCLE IF T = "" THEN START PROMPT("Time: ") READLINE(T) UNTIL T # "" FINISH IF LENGTH(T) = 4 THEN EXIT PRINTSTRING("Invalid time".SNL) T = "" REPEAT ASTRING = "Latest ALERT=".D." ".T.SNL ! CYCLE I = BACKGROUND,1,FOREGROUND FILE = MESSAGEFILE(I) CONNECT OR CREATE(FILE,RR,SANAME) TEMPFILE = "T#".NEXTTEMP OUTFILE(TEMPFILE,4096,0,0,CONAD,FLAG) -> ERR IF FLAG # 0 OR == RECORD(CONAD) SAVEDT = OR_DATETIME; ! Save creation date over copy MOVE(4096,RR_CONAD,CONAD); ! Take the copy OR_DATETIME = SAVEDT; ! Restore date MOVE(ALERTSIZE,ADDR(ASTRING)+1,CONAD+OR_DATASTART) NEWGEN(TEMPFILE,FILE,FLAG) -> ERR IF FLAG # 0 REPEAT PRINTSTRING(ASTRING.SNL) SET RETURN CODE(0) STOP ! ERR: FAIL(SANAME,FLAG) END ; ! of SETALERT ! ! !*********************************************************************** !* !* M A K E B A S E F I L E !* !*********************************************************************** ! !<Subsystem basefiles ! ! ! ! The Edinburgh Subsystem resides in a file which is commonly called ! the 'basefile'. ! ! This Section describes the structure of the basefile, and how to ! create a new one. ! ! ! !<Basefile structure ! ! ! The basefile for the Edinburgh Subsystem is a partitioned file which ! contains three members: ! ! a) The subsystem object file, with the code fixed up (using the FIX ! utility) to start at segment 32, and the GLA fixed up to start at ! the next free segment after the code. ! ! b) A default 'option' file, connected and used in the absence of the ! user's own option file. When the user sets a non-default option, ! a copy of the default file is made (as SS#OPT), and the modified ! option included in the copy. ! ! c) A directory file, containing the entry points found in the ! subsystem object file. This is the first directory searched by the ! loader. !> !<The MAKEBASEFILE command ! ! ! This command takes up to three parameters. These are: ! ! ! 1) The name of the subsystem object file to be used for input. ! ! 2) The name of the default option file to be included in the ! completed basefile. ! ! 3) The destination of the completed basefile. ! ! ! If any of these parameters is omitted, a prompt is issued for it. !> !> ! EXTERNALROUTINE MAKEBASEFILE(STRING (255) PARMS) INTEGER FLAG,OBJCONAD,DIRLENGTH,LINK,GLASTART STRING (31) BASEOBJECT,OPTIONFILE,BASEFILE RECORD RR(RF) INTEGERARRAYNAME LDATA RECORDNAME DIRINF(DIRINFF) RECORDNAME EP4(EP4F) RECORDNAME H(OHF) RECORDNAME R(HF) RECORDARRAYNAME OFM(OFMF) INTEGERARRAY BASE(0:7) ! SET RETURN CODE(1000) SETPAR(PARMS) IF PARMAP > 7 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH ! BASEOBJECT = SPAR(1) OPTIONFILE = SPAR(2) BASEFILE = SPAR(3) ! PROMPT("Object file: ") READLINE(BASEOBJECT) WHILE BASEOBJECT = "" PROMPT("Option file: ") READLINE(OPTIONFILE) WHILE OPTIONFILE = "" PROMPT("Basefile: ") READLINE(BASEFILE) WHILE BASEFILE = "" ! DESTROY(BASEFILE,FLAG); ! Ignore flag MODPDFILE(4,BASEFILE,"","",FLAG); ! Create pdfile -> ERR IF FLAG # 0 ! CONNECT(BASEOBJECT,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 IF RR_FILETYPE # SSOBJFILETYPE THEN START SETFNAME(BASEOBJECT) FLAG = 267; ! Invalid filetype -> ERR FINISH MODPDFILE(1,BASEFILE,"BASEOBJECT",BASEOBJECT,FLAG) ! Insert member - order is critical -> ERR IF FLAG # 0 ! CONNECT(OPTIONFILE,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 IF RR_FILETYPE # SSOPTFILETYPE THEN START SETFNAME(OPTIONFILE) FLAG = 267; ! Invalid filetype -> ERR FINISH MODPDFILE(1,BASEFILE,"OPTIONFILE",OPTIONFILE,FLAG) ! Insert member -> ERR IF FLAG # 0 ! DESTROY(TEMPDIR,FLAG); ! Ignore flag MODDIRFILE(10,TEMPDIR,"","",0,759,1164,FLAG) ! Create directory -> ERR IF FLAG # 0 CONNECT(TEMPDIR,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 R == RECORD(RR_CONAD) DIRLENGTH = R_FILESIZE ! CONNECT(BASEFILE,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 ! ! Set BASE(2) to the address of the base GLA, forming a pseudo ! object file map ! BASE(2) = ROUNDUP(ABASEFILE+RR_DATAEND+DIRLENGTH,SEGSIZE) MODDIRFILE(4,TEMPDIR,"",BASEFILE."_BASEOBJECT",0,ADDR(BASE(1)),0,FLAG) ! Insert data and proc entries -> ERR IF FLAG # 0 ! ! Copy directory into basefile ! MODPDFILE(1,BASEFILE,"BASEDIR",TEMPDIR,FLAG) -> ERR IF FLAG # 0 DESTROY(TEMPDIR,FLAG); ! Ignore flag ! ! Now locate the external integer SSDATELINKED, and fill in the date ! of the current system call table in Director ! DIRINF == RECORD(UINFI(10)) CONNECT(BASEFILE."_BASEOBJECT",1,0,0,RR,FLAG) -> ERR IF FLAG # 0 CHANGEACCESS(BASEFILE,3,FLAG); ! To write to member -> ERR IF FLAG # 0 OBJCONAD = RR_CONAD H == RECORD(OBJCONAD) OFM == ARRAY(OBJCONAD+H_OFM+4,OFMAF); ! Object file map GLASTART = OFM(2)_START LDATA == ARRAY(OBJCONAD+H_LDA,LDATAF) LINK = LDATA(4) WHILE LINK # 0 CYCLE ; ! Search data entry list EP4 == RECORD(OBJCONAD+LINK) IF EP4_IDEN = "SSDATELINKED" THEN START INTEGER(OBJCONAD+GLASTART+EP4_DISP) = DIRINF_SCDATE INTEGER(OBJCONAD) = X'1B800010'; ! Jump over header of BASEOBJECT -> FOUND FINISH LINK = EP4_LINK REPEAT FLAG = 1002 -> ERR ! FOUND: DISCONNECT(BASEFILE,FLAG) SET RETURN CODE(0) STOP ! ERR: FAIL("MAKEBASEFILE",FLAG) END ; ! of MAKEBASEFILE ! ! !*********************************************************************** !* !* M A K E O P T I O N F I L E !* !*********************************************************************** ! !<Subsystem option files ! ! ! The Edinburgh Subsystem makes use of a file containing 'options' set ! by the user to tailor his process to his own needs. This Section ! describes how the initial option file used by the Subsystem is ! created, and explains the entries in it. ! ! !<Making the file ! ! ! The command MAKEOPTIONFILE takes a single parameter, which is the name ! of the option file to be generated. If this parameter is omitted, a ! prompt is issued for it. ! ! A series of prompts is then issued. A value for the appropriate option ! may then be given, or the default setting invoked by simply typing ! 'return'. In the latter case, the actual value used is displayed, ! for information. ! ! The only exception to all this is the initial PARM setting - see ! Section 5.2.1. !> !<Description of options ! ! ! ! ! ! Some of the values stored in the option file are integers, and others ! are strings. Generally, they describe items such as the size of ! a particular workfile, terminal characteristics, directory search ! lists, etc. ! ! ! The rest of this Section describes each option in detail. ! !PAGE ! !<Initial PARM setting ! ! The value of this option is made the current PARM setting at log-on. ! MAKEOPTIONFILE uses the value actually in force when the option file ! is being created, as this saves it from having to decode large numbers ! of PARM keywords. !> !<Auxiliary stack size ! ! The auxiliary stack is a separate file which is used to store large ! data areas in user programs, due to the limitations on the size of the ! run-time stack in the ICL 2900 series. ! ! Keyword: AUXSTACKSIZE ! ! Default value: 128 Kbytes !> !<User stack size ! ! The user stack contains all local variables needed by a normal user ! program. ! ! Keyword: USERSTACKSIZE ! ! Default value: 252 Kbytes !> !<Initialised stack size ! ! The initialised stack is a pre-allocated part of the user stack. It ! must be at least 32 Kbytes smaller than the user stack as a whole. ! It is used as a data area by FORTRAN programs, but need only be ! pre-allocated if it is intended to load FORTRAN programs from other ! programs. ! ! Keyword: INITSTACKSIZE ! ! Default value: 100 Kbytes !> !<Interactive terminal width ! ! Subsystem commands such as ANALYSE and FILES assume the terminal ! width given by this option when planning their output. ! ! Keyword: ITWIDTH ! ! Default value: 72 !> !<Array diagnostic level ! ! When a diagnostic traceback is given for a program, the number of ! elements of each array which are actually printed is given by this ! option. ! ! Keyword: ARRAYDIAG ! ! Default value: 10 !> !<The session workfile ! ! Many subsystem commands (particularly the compilers) make use of a ! common workfile. The size of the workfile is determined by this ! option setting. ! ! Keyword: INITWORKSIZE ! ! Default value: 256 Kbytes !> !<Interactive terminal buffers ! ! The subsystem requires two buffers for interactive terminal I/O. ! One is used solely for input, and the other solely for output. ! Two options are provided in order that the sizes of these buffers ! may be altered. ! ! Keyword (input): ITINSIZE ! ! Default value (input) : 1 Kbyte ! ! ! Keyword (output): ITOUTSIZE ! ! Default value (output): 3 Kbytes ! !> !<Terminal type ! ! The terminal/screen control package (used by screen editors, etc.) ! uses this option to determine how an interactive terminal is to be ! driven. ! ! In general, this option will not be set by means of the OPTION ! command, although the keyword TERMINAL is provided. It is expected ! that users will select the appropriate terminal type (which is an ! integer) by means of a special command. ! ! The default value supplied is zero, which should correspond to ! 'unspecified terminal'. This means that a user dialogue will be ! entered when the screen control package is first used. ! !> !<Brackets/Nobrackets ! ! There are two different command formats which are accepted by the ! subsystem: ! ! a) Spaces in commands are not significant, and any parameters must ! be enclosed in brackets. ! ! b) Spaces in commands are not allowed, since one or more spaces are ! used to separate the command from its parameters, which should ! not be enclosed in brackets. ! ! The actual format accepted depends on this option. ! ! Keywords: BRACKETS and NOBRACKETS ! ! Default value: BRACKETS ! !> !<Recall of terminal I/O ! ! The subsystem provides facilities for storing and retrieving ! transactions on an interactive terminal. The three possible values ! for this option are: ! ! NORECALL - nothing is stored ! TEMPRECALL - the current session is stored ! PERMRECALL - the last few sessions are stored ! ! Default value: TEMPRECALL !> !<Suppression of blank lines ! ! This option is provided to enable all blank lines output to the ! terminal to be suppressed. ! ! Keywords: BLANKLINES and NOBLANKLINES ! ! Default value: BLANKLINES !> !<Echoing of OBEY files ! ! When an OBEY file is being processed, the subsystem may or may not ! 'echo' the resulting transactions on the user's terminal. This option ! controls the amount echoed. The possible settings are: ! ! NOECHO - nothing at all is echoed ! PARTECHO - only 'Command:' lines are echoed ! FULLECHO - all input is echoed, including program input ! ! Batch jobs are treated by the subsystem as if they are effectively ! OBEY files for the purposes of this option. !> !<Foreground start-up file ! ! This option allows the user to nominate a file of commands which are ! to be OBEYed on foreground process start-up. ! ! Keywords: NOFSTARTFILE and FSTARTFILE ! ! Default value: NOFSTARTFILE !> !<Background start-up file ! ! This option allows the user to nominate a file of commands which are ! to be OBEYed on background process start-up. ! ! Keywords: NOBSTARTFILE and BSTARTFILE ! ! Default value: NOBSTARTFILE !> !<Pre-loading file ! ! This option allows the user to nominate object files which are to ! be 'pre-loaded' on process start-up. It is not currently implemented. !> !<Active directory ! ! This option selects the file which is to be used as the 'active ! directory' for the INSERT and REMOVE commands, and associated actions. ! This is the first user directory searched by the loader, immediately ! after searching the session directory (see Section 4.1). ! ! Keyword: ACTIVEDIR ! ! Default value: SS#DIR !> !<Compiler fault file ! ! This option allows the user to select another file, in addition to the ! compiler listing file, to which compilation fault messages may be ! sent. ! ! Keyword: CFAULTS ! ! Default value: .OUT !> !<Search directories ! ! Up to 16 additional directories may be added to the search list for ! a process. They are searched immediately after the active directory. ! ! Keywords: SEARCHDIR and REMOVEDIR ! ! Default value: No search directories !> !> !> ! EXTERNALROUTINE MAKEOPTIONFILE(STRING (255) PARMS) INTEGER FLAG,CONAD,I STRING (31) FILE STRING (255) S RECORDNAME C(CONTF) ! SET RETURN CODE(1000) SETPAR(PARMS) IF PARMAP > 1 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH FILE <- SPAR(1) IF FILE = "" THEN START PROMPT("Option file: ") READLINE(FILE) FINISH ! OUTFILE(FILE,4096,0,0,CONAD,FLAG) -> ERR IF FLAG # 0 C == RECORD(CONAD) C_DATAEND = 4096 C_FILETYPE = SSOPTFILETYPE ! FILL(C_DATAEND-C_DATASTART,CONAD+C_DATASTART,X'FF') ! Fill whole file with -1 FILL(5*32,CONAD+C_DATASTART+128,0); ! Clear used strings FILL(16*32,ADDR(C_SEARCHDIR(1)),0); ! Set all search directories to null C_MARK = 4; ! Mark four option file format ! ! Fill in the installation-dependent values ! C_INITPARMS = LONGINTEGER(ADDR(COMREG(27))) PRINTSTRING("Init "); PARM("?") C_ASTK = GETVAL("Aux stack",64<<10,1024<<10,128<<10,1024) C_USTK = GETVAL("User stack",64<<10,252<<10,252<<10,1024) C_ISTK = GETVAL("Init stack",0,C_USTK-(32<<10),100<<10,1024) C_ITWIDTH = GETVAL("IT width",20,132,80,1) C_ARRAYDIAG = GETVAL("Arraydiag",0,1000,10,1) C_INITWORKSIZE = GETVAL("Initworksize",256<<10,1024<<10,256<<10,1024) C_ITINSIZE = GETVAL("IT insize",1<<10,16<<10,1<<10,1024) C_ITOUTSIZE = GETVAL("IT outsize",1<<10,16<<10,3<<10,1024) C_TERMINAL = GETVAL("Terminal",-1,100,4,1) ! FLAG = GET SETTING("(No)Brackets",2,BKEYS,BVALUES,"BRACKETS") IF FLAG = 1 THEN START C_LDELIM = '(' C_RDELIM = ')' FINISH ELSE START C_LDELIM = ' ' C_RDELIM = NL FINISH C_JOURNAL = GET SETTING("Recall",3,JKEYS,JVALUES,"TEMPRECALL") C_NOBL = GET SETTING("(No)Blanks",2,LKEYS,LVALUES,"BLANKLINES") C_DATAECHO = GET SETTING("Echo",3,EKEYS,EVALUES,"PARTECHO") ! C_FSTARTFILE = GETSTR("Fstartfile",31,"") C_BSTARTFILE = GETSTR("Bstartfile",31,"") C_PRELOADFILE = GETSTR("Preloadfile",31,"") C_MODDIR = GETSTR("Activedir",31,DEFAULTACTIVEDIR) C_CFAULTS = GETSTR("Cfaults",31,".OUT") ! CYCLE I = 1,1,16 PROMPT("Searchdir ".ITOS(I).": ") ASK: READLINE(S) UCTRANSLATE(ADDR(S)+1,LENGTH(S)) IF S = "" OR S = ".END" THEN START C_SEARCHDIRCOUNT = I - 1 EXIT FINISH IF LENGTH(S) > 31 THEN START PRINTSTRING("Reply must not exceed 31 characters".SNL) -> ASK FINISH C_SEARCHDIR(I) = S REPEAT ! DISCONNECT(FILE,FLAG) PRINTSTRING("Finished".SNL) SET RETURN CODE(0) STOP ! ERR: FAIL("MAKEOPTIONFILE",FLAG) END ; ! of MAKEOPTIONFILE ! ! !*********************************************************************** !* !* M A K E S U G G E S T I O N F I L E !* !*********************************************************************** ! !<The suggestion file ! ! ! The Edinburgh Subsystem supports the SUGGESTION command, which ! provides a simple way for users to make comments for improvements to ! the system. Two utility commands are used in the administration of ! this file. ! ! !<Making a suggestion file ! ! ! The command MAKESUGGESTIONFILE takes up to one parameter, this being ! the name of the empty suggestion file to be created. If this parameter ! is omitted, the name SUBSYS.SUGGESTION is assumed. !> ! EXTERNALROUTINE MAKESUGGESTIONFILE(STRING (255) PARMS) INTEGER CONAD,FLAG STRING (31) FILE RECORDNAME R(HF) ! SET RETURN CODE(1000) SETPAR(PARMS) IF PARMAP > 1 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH FILE <- SPAR(1) IF FILE = "" THEN FILE = SSBLKBRD ! OUTFILE(FILE,64<<10,0,0,CONAD,FLAG) -> ERR IF FLAG # 0 CHERISH(FILE) PERMIT(FILE,"",3,FLAG); ! Set EEP = RW -> ERR IF FLAG # 0 R == RECORD(CONAD) R_DATAEND = R_FILESIZE R_FILETYPE = SSDATAFILETYPE R_FORMAT = 3; ! Un-structured INTEGER(CONAD+R_DATASTART) = 35; ! Set current 'top' of file DISCONNECT(FILE,FLAG) SET RETURN CODE(0) STOP ! ERR: FAIL("MAKESUGGESTIONFILE",FLAG) END ; ! of MAKESUGGESTIONFILE ! ! !*********************************************************************** !* !* L I S T S U G G E S T I O N F I L E !* !*********************************************************************** ! !<Listing the suggestion file ! ! ! The command LISTSUGGESTIONFILE takes up to one parameter, this being ! the file or device to which the suggestion listing is to be written. ! If this parameter is omitted, a prompt is issued for it. ! !<Additional facilities ! ! If there are no suggestions in the file, the subsystem return code is ! set to -1, otherwise it is set to zero (or some error code). This ! allows suggestions to be checked and listed, if present, by suitable ! Job Control statements. !> !> !> ! EXTERNALROUTINE LISTSUGGESTIONFILE(STRING (255) PARMS) INTEGER CONAD,FLAG,AFD,CURTOP,START,I,INDEFINED STRING (31) OUT STRING (255) S RECORD RR(RF) BYTEINTEGERARRAYNAME TEXT RECORDNAME R(HF) ! SET RETURN CODE(1000) SETPAR(PARMS) IF PARMAP > 1 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH OUT <- SPAR(1) IF OUT = "" THEN START PROMPT("Output: ") READLINE(OUT) UNTIL OUT # "" FINISH CONNECT(SSBLKBRD,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 CONAD = RR_CONAD R == RECORD(CONAD) IF INTEGER(CONAD+R_DATASTART) = 35 THEN START ! File is empty PRINTSTRING("Suggestion file empty".SNL) SET RETURN CODE(-1) STOP FINISH DEFINE(OUTCHAN,OUT,AFD,FLAG) -> ERR IF FLAG # 0 SELECTOUTPUT(OUTCHAN) PRINTSTRING("Contents of ".SSBLKBRD." on ".DATE." at ".TIME.SNL.SNL) CURTOP = CONAD + INTEGER(CONAD+R_DATASTART) START = CONAD + R_DATASTART + 4 WHILE START < CURTOP CYCLE TEXT == ARRAY(START,BIF) IF TEXT(1) # 1 THEN START SETFNAME(SSBLKBRD) FLAG = 311; ! Corrupt file -> ERR FINISH CYCLE I = 2,1,5000 EXIT IF TEXT(I) = 0 PRINTSYMBOL(TEXT(I)) REPEAT NEWLINES(4) START = ADDR(TEXT(I)) + 1 REPEAT IF FROMSTRING(SSBLKBRD,1,6) = UINFS(1) THEN START ! User is owner of file INDEFINED = NO DEFINFO(INCHAN,S,FLAG) IF FLAG = 0 THEN START DEFINE(INCHAN,".IN",AFD,FLAG) -> ERR IF FLAG # 0 INDEFINED = YES FINISH SELECTINPUT(INCHAN) PROMPT("Reset? ") READLINE(S) UNTIL S # "" UCTRANSLATE(ADDR(S)+1,LENGTH(S)) IF CHARNO(S,1) = 'Y' THEN START CHANGEACCESS(SSBLKBRD,3,FLAG) IF FLAG # 0 THEN PRINTSTRING(FAILUREMESSAGE(FLAG)) ELSE START INTEGER(CONAD+R_DATASTART) = 35 FINISH FINISH FINISH DISCONNECT(SSBLKBRD,FLAG) SELECTINPUT(0) SELECTOUTPUT(0) CLOSESTREAM(INCHAN) CLOSESTREAM(OUTCHAN) CLEAR(ITOS(OUTCHAN)) IF INDEFINED = YES THEN CLEAR(ITOS(INCHAN)) SET RETURN CODE(0) STOP ! ERR: FAIL("LISTSUGGESTIONFILE",FLAG) END ; ! of LISTSUGGESTIONFILE ! ! !*********************************************************************** !* !* C H E C K P D !* !*********************************************************************** ! !<Checking partitioned files ! ! Partitioned files greater than 256 Kbytes in size present special ! problems if they contain members which are object files. An object ! file that crosses a 256 Kbyte boundary may not execute correctly, ! so the action of the subsystem loader is to make a copy of such a ! member, and execute that. This is clearly inefficient. ! The CHECKPD command provides facilities for identifying such problem ! members. It also flags other conditions which cause the loader to make ! a copy of an object file. ! The command takes exactly one parameter, the meaning of which is ! given in the following subsections. ! !<Finding the offsets of members ! ! If CHECKPD is given the name of a partitioned file, it simply lists ! the relative offset (in hexadecimal) of each member of that file. !> !<Checking for possible problems ! ! If CHECKPD is given the name of a single member of a partitioned file, ! it determines whether either of two conditions would force the ! subsystem to copy the file when attempting to load it. These ! conditions are: ! ! a) The code of the member crosses a 256 Kbyte boundary ! ! b) The code of the member is not shareable (possible for converted ! ICL object files) !> !> ! EXTERNALROUTINE CHECKPD(STRING (255) PARMS) INTEGER FLAG,CONAD,I STRING (11) MEMBER STRING (31) PDFILE,FILE RECORD RR(RF) RECORDNAME OR(OHF) RECORDNAME PD(PDF) RECORDNAME PR(PDHF) RECORDARRAYNAME OFM(OFMF) RECORDARRAYNAME PDA(PDF) ! SET RETURN CODE(1000) SETPAR(PARMS) IF PARMAP # 1 THEN START FLAG = 263; ! Wrong number of parameters -> ERR FINISH FILE <- SPAR(1) ! CONNECT(FILE,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 ! IF FILE -> PDFILE.("_").MEMBER THEN START CONNECT(FILE,1,0,0,RR,FLAG) -> ERR IF FLAG # 0 CONAD = RR_CONAD OR == RECORD(CONAD) IF OR_FILETYPE # SSOBJFILETYPE THEN START PRINTSTRING("Member ".MEMBER." is not an object file".SNL) -> OK FINISH OFM == ARRAY(CONAD+OR_OFM+4,OFMAF); ! Object file map IF (CONAD+OFM(1)_START) >> 18 # C (CONAD+OFM(1)_START+OFM(1)_LEN) >> 18 THEN START PRINTSTRING("Code of member ".MEMBER.C " crosses a 256 Kbyte boundary".SNL) -> OK FINISH IF OFM(1)_PROPS & 1 # 0 THEN START PRINTSTRING("Code of member ".MEMBER." is not shareable".SNL) -> OK FINISH PRINTSTRING("No problems with member ".MEMBER.SNL) -> OK FINISH ELSE START CONAD = RR_CONAD PR == RECORD(CONAD) PDA == ARRAY(CONAD+PR_ADIR,PDAF) I = 1 WHILE I <= PR_COUNT CYCLE PD == PDA(I) PRINTSTRING(PD_NAME) SPACES(15-OUTPOS) PRINTSTRING("X".HTOS(PD_START,6).SNL) I = I + 1 REPEAT FINISH ! OK: SET RETURN CODE(0) STOP ! ERR: FAIL("CHECKPD",FLAG) END ; ! of CHECKPD ENDOFFILE