!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! ! HOUSEKEEPING ROUTINES FOR CSDEPT ! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! %OWNSTRING (1) SNL=' ' %EXTERNALROUTINESPEC NEWPDFILE (%STRING (63) S) %EXTERNALROUTINESPEC CLOSE STREAM (%INTEGER I) %EXTERNALROUTINESPEC COPYFILE (%STRING (63) S) %EXTERNALROUTINESPEC DESTROY (%STRING (63) S) %EXTERNALROUTINESPEC PERMITFILE (%STRING (63) S) %EXTERNALROUTINESPEC PERMITLIB (%STRING (63) S) %EXTERNALROUTINESPEC PROMPT (%STRING (15) S) %EXTERNALROUTINESPEC CHERISH (%STRING (63) S) %EXTERNALROUTINESPEC USERLIB (%STRING(63) S) %EXTERNALROUTINESPEC INSERTFILE (%STRING (63) S) %EXTERNALROUTINESPEC ARCHIVE (%STRING (63) S) %EXTERNALINTEGERFNSPEC SSFAIL %EXTERNALROUTINESPEC SSFOFF %EXTERNALINTEGERFNSPEC EXIST (%STRING (63) S) %EXTERNALROUTINESPEC DEFINE (%STRING (63) S) %EXTERNALROUTINESPEC DISCONNECT (%STRING (63) S) ! ! ! ! Print an error message and give up. %ROUTINE FAIL (%STRING (63) S) SELECT OUTPUT (0) PRINTSTRING (S) ; NEWLINE %STOP %END ! ! ! ! Array of prompts used to set up the new DEPTFILE ! entry, also used as identifiers in PROGRAM INFO ! output. %OWNSTRING (15) %ARRAY FILE TYPE(1:7) ='PROGRAM ', 'LIBRARY ', 'OBJECT FILES', 'PDFILE NAME ', 'OTHER FILES ', 'DESCRIPTION ', 'ORIGINATOR ' %OWNSTRING (7) ENDOFFILE = '$$$ ' %OWNSTRING (3) END ENTRY = '$$ ' %OWNSTRING (3) SEPR = '$ ' ! ! The user prints a ':' to terminate an entry ! field, but the program puts it in DEPTFILE as a ! '$' since that is easier to find with the editor. %OWNINTEGER TERMINR = ':' ! %ROUTINE READ LINE (%STRINGNAME LINE) %STRING (1) CH LINE='' READ ITEM (CH) %AND LINE=LINE.CH %UNTIL CH=SNL %END ! ! ! ! Set up the DEPTFILE entry for a new program. ! %EXTERNALROUTINE NEW PROGRAM (%STRING (63) PROGRAM) %EXTERNALROUTINESPEC RENAME (%STRING (63) S) %ROUTINESPEC READ ENTRY %STRING (140) LINE %STRING (23) FILE DISP ! Check and split the parameters which are of the ! form :FILE DISP,PROGRAM name ! FILEDISP is only used to set up a new DEPTFILE, ! normally the parameter and the separating comma ! are omitted. PROGRAM may not contain spaces and ! is the first field in the DEPTFILE entry and is ! used by PROGRAM INFO and COPY PROGRAM (using ! FIND ENTRY) to identify the entry. %IF PROGRAM='' %THEN FAIL ('PROGRAM NAME ?') %UNLESS PROGRAM->FILE DISP.(',').PROGRAM %THEN FILE DISP='' %IF EXIST ('DEPTFILE')=0 %AND FILE DISP='' %THENC FAIL ('DEPTFILE DOES NOT EXIST') DEFINE('STREAM03,DEPTFILE') ! Temporary version of DEPTFILE DEFINE('STREAM04,SS#DEPT') ; SELECT OUTPUT(4) SET MARGINS (4,1,130) ! The new version goes at the top of the file. PRINTSTRING (END ENTRY) PRINTSTRING (PROGRAM.SEPR) ! Ask the user for the program information and put ! it in the temporary file. READ ENTRY PRINTSTRING (END ENTRY) %IF FILE DISP='NEWFILE' %THEN PRINTSTRING (ENDOFFILE) %ELSESTART ! Copy the rest of DEPTFILE to the temporary file. SELECT INPUT (3) READ LINE (LINE) %UNTIL LINE=END ENTRY READ LINE(LINE) %AND PRINTSTRING (LINE) %UNTIL LINE=ENDOFFILE SELECT INPUT (0) ; CLOSE STREAM (3) %FINISH SELECT OUTPUT (0) CLOSE STREAM (4) ! Destroy the old version of DEPTFILE and rename ! the temporary version to the permenant name. DESTROY ('DEPTFILE') %IF EXIST ('DEPTFILE')#0 RENAME ('SS#DEPT,DEPTFILE') CHERISH ('DEPTFILE') ! ! ! ! Read the entry fields and put them in the file. %ROUTINE READ ENTRY %INTEGER TYPE,CH ! Ignore newlines and spaces in file names. %ROUTINE GET SYMBOL (%INTEGERNAME CH) READSYMBOL (CH) %UNTIL NL#CH#' ' %END ! Read the library name(s) and object file name(s), ! plant a '*' symbol in front of each name to ! ensure that KEEPALIVE will connect it. %CYCLE TYPE=2,1,3 PROMPT (FILE TYPE (TYPE).':') GET SYMBOL (CH) ! Read a list of filenames and print them to the ! temporary file unless the field is null. %UNLESS CH=TERMINR %THENSTART %CYCLE %UNLESS CH='*' %THEN PRINTSYMBOL ('*') %UNTIL CH=',' %OR CH=TERMINR %THEN PRINTSYMBOL (CH) %C %AND GET SYMBOL (CH) %IF CH=TERMINR %THENEXIT PRINTSYMBOL (',') ; GET SYMBOL (CH) %REPEAT %FINISH PRINTSTRING (SEPR) %REPEAT ! Read a PDfile name and any other file names ! associated with the program (e.g. source or ! documentation). These are not connected by ! KEEPALIVE unless the user requests it by typing a ! '*' in front of the file name. %CYCLE TYPE=4, 1, 5 PROMPT (FILE TYPE (TYPE).':') GET SYMBOL(CH) ! Read the file list. %WHILE CH#TERMINR %THEN PRINTSYMBOL (CH) %AND GET SYMBOL (CH) PRINTSTRING (SEPR) %REPEAT ! Read text entries. Leave in spaces, newlines, ! blank lines etc. Do not format in any way. When ! lines are printed by PROGRAM INFO they are ! indented, so input lines should be kept short. ! The terminator symbol is only recognised as such ! when it occurs at the end of a line. %CYCLE TYPE=6,1,7 PROMPT (FILE TYPE(TYPE).':') GET SYMBOL (CH) %CYCLE %IF CH=TERMINR %AND NEXTSYMBOL=NL %THENEXIT PRINTSYMBOL (CH) READSYMBOL (CH) %REPEAT PRINTSTRING (SEPR) %REPEAT %END ! %END ! ! ! ! Search through DEPTFILE looking at the first line ! (program name) of each entry and comparing it ! with the parameter PROGRAM, return when a match ! is found or the end of the file is reached. If ! the parameter is null then the intention is to ! access each entry in turn, in which case set the ! parameter to be the next program name to be read ! in the file (if there is one). The result is set ! to 0 to indicate failure (end of file reached), ! and 1 to indicate success. %INTEGERFN FIND ENTRY (%STRINGNAME PROGRAM) %STRING (140) LINE,S1 %STRING (23) NAME ! Find the start of the next entry. READ LINE (LINE) %UNTIL LINE=END ENTRY READ LINE (LINE) %IF LINE=ENDOFFILE %THENRESULT=0 %IF PROGRAM='' %THEN LINE->PROGRAM.(SEPR).S1 %ANDRESULT=1 NAME=PROGRAM.SEPR ! Search the rest of the file for the program name. %CYCLE %IF LINE=NAME %THENRESULT=1 READ LINE (LINE) %UNTIL LINE=END ENTRY READ LINE (LINE) %IF LINE=ENDOFFILE %THENEXIT %REPEAT SELECT OUTPUT (0) PRINTSTRING ('NAME '.PROGRAM.' NOT FOUND') %RESULT=0 %END ! ! ! ! Print the information contained in DEPTFILE for ! the given program name. %EXTERNALROUTINE PROGRAM INFO (%STRING (63) PROGRAM) %INTEGER FLAG %STRING (140) LINE %STRING (23) OUTFILE %ROUTINESPEC PRINT ENTRY DEFINE('STREAM03,DEPTFILE') ; SELECT INPUT(3) SET MARGINS (3,1,130) ! Split up the parameters into the form: ! program name/output name ! The program name may be null, in which case each ! program entry in DEPTFILE is printed. If the ! output name (OUTFILE) is omitted the entries are ! printed on the console output stream, otherwise ! they are sent to the named file (or more likely a ! device name e.g. .LP). %IF PROGRAM->PROGRAM.('/').OUTFILE %THENC DEFINE('STREAM02,'.OUTFILE) %AND SELECT OUTPUT (2) %IF PROGRAM='' %THEN FLAG=1 %ELSE FLAG=0 ! Locate the program entry in DEPTFILE and print ! it. If the program name was given in the ! parameter then finish, otherwise process the next ! entry in the file. %CYCLE %IF FIND ENTRY (PROGRAM)=0 %THENRETURN NEWLINES(2) PRINTSTRING (FILE TYPE(1).' = '.PROGRAM) ; NEWLINE PRINT ENTRY %IF FLAG=0 %THENRETURN PROGRAM='' %REPEAT ! ! ! ! Print the fields in an entry (program name already ! printed), preceeded by the field identifier ! (which was used as a prompt when the field was ! read into DEPTFILE. %ROUTINE PRINT ENTRY %INTEGER TYPE %STRING (140) LINE,S1 %CYCLE TYPE=2,1,7 READ LINE (LINE) %UNLESS LINE->LINE.(SEPR) %THENSTART ! Print the relevant identifier followed by the ! field, as the field extends over more than one ! line indent the following lines. PRINTSTRING (FILE TYPE (TYPE).' = '.LINE) %CYCLE READLINE (LINE) SPACES (13) %IF LINE ->LINE.(SEPR) %THENC PRINTSTRING (LINE.SNL) %ANDEXIT PRINTSTRING (LINE) %REPEAT %FINISHELSESTART ! Print the single line field preceeded by its ! identifier. Do not print anything if the entry is ! null. i.e. The identifier does not appear in the ! output if there is no associated information. ! A field is null if the user typed the terminator ! immediately after the prompt or if the word NONE ! was typed as a field. %UNLESS LINE='' %OR LINE='NONE' %THENC PRINTSTRING (FILE TYPE(TYPE).' = '.LINE.SNL) %FINISH %REPEAT %END %END ! ! ! ! After the DEPTFILE entry has been set up for a ! new program copy the files, set up the library ! etc., using the filenames in the entry. ! The user may still have to handle files ! separately if the requirements differ in any way ! from the standard processing. %EXTERNALROUTINE COPY PROGRAM (%STRING (63) PROGRAM) %STRING (140) LIBRARY,OBJECT FILES,PDFILE,OTHER FILES,FILE %STRING (15) NUMBER %INTEGER MARK %OWNSTRING (3) SEPR = '$ ' %INTEGERFNSPEC GET FILE (%STRINGNAME FILE,LIST, %INTEGERNAME MARK) ! Split up the parameters, which should be of the ! form: user NUMBER.PROGRAM name ! neither of which may be ommitted. (If NUMBER is ! forgotten the routine will ask for it.) %UNLESS PROGRAM->NUMBER.('.').PROGRAM %THEN NUMBER='' DEFINE ('STREAM01,DEPTFILE') SELECT INPUT (1) ; SET MARGINS (1,1,130) ! Find the program antry in DEPTFILE if posible. ! (The program name is read but not the rest of the ! entry.) %IF FIND ENTRY (PROGRAM)=0 %THENRETURN READ LINE (LIBRARY) ; READ LINE (OBJECT FILES) READLINE (PDFILE); PDFILE->PDFILE.(SEPR) ! If a PDfile is named then create it ready to ! copy all the files into it. %UNLESS PDFILE='' %START NEWPDFILE (PDFILE) %IF EXIST(PDFILE)=0 CHERISH (PDFILE) PDFILE=PDFILE.'_' %FINISH READ LINE (OTHER FILES) ! If the user number (from which the files are to ! be copied) is ommitted, then output a prompt ! and read the number. There is no check on the ! validity of the number, COPY will take care of ! that. %IF NUMBER='' %START SELECT INPUT(0) ; PROMPT ('PRODUCER''S NO:') READ LINE (NUMBER); NUMBER->NUMBER.(SNL) %FINISH LIBRARY->LIBRARY.(SEPR) ! Remove the '*' from in front of the name to get a ! valid filename. %UNLESS LIBRARY->('*').LIBRARY %THEN LIBRARY=LIBRARY ! If there is a library name then create the ! library. %UNLESS LIBRARY='' %THENSTART USERLIB(LIBRARY) CHERISH (LIBRARY) %FINISH ! Extract each file name from the list of object ! files and copy the file from the program ! originator. Put the file in the library (if ! required) also copy it to the PDfile if there is ! one. If the COPY routine fails then it should ! print the error message. %WHILE GET FILE(FILE,OBJECT FILES,MARK)#'' %CYCLE COPYFILE (NUMBER.'.'.FILE.','.FILE) %IF SSFAIL=0 %THENSTART CHERISH (FILE) ; INSERTFILE(FILE) COPYFILE (FILE.','.PDFILE.FILE) %IF PDFILE#'' %FINISH %REPEAT ! If a library has been created then change back to ! the standard library and copy the new library ! into the PDfile (if any), then permit the new ! library (and its object files). (If there is no ! library then the user must permit the object file ! separately). %UNLESS LIBRARY='' %START USERLIB('ENTERLIB') ; PERMITLIB(LIBRARY) COPYFILE (LIBRARY.','.PDFILE.LIBRARY) %IF PDFILE#'' %FINISH ! Copy the other file into the PDfile, the ones ! that are marked for KEEP ALIVE ('*') are also ! copied as separate files, cherished and permitted ! for use. If there are any such other files then ! there must be a PDfile, as separate files should ! not be allowed in archive. %WHILE GET FILE (FILE,OTHER FILES,MARK)#'' %CYCLE COPYFILE (NUMBER.'.'.FILE.','.PDFILE.FILE) %IF SSFAIL=0 %START %IF MARK#'' %START COPYFILE (PDFILE.FILE.','.FILE) %IF PDFILE#'' CHERISH (FILE); PERMITFILE(FILE) %FINISH %FINISH %REPEAT ! Permit the the next two files ready to update the ! copies on the other machine. PERMITFILE('CONTENTS') ; PERMITFILE('DEPTFILE') ! ! ! ! Extract a file name (FILE) from the list of ! filenames (LIST), separated by commas. If the ! filename is preceeded by a '*' then remove it and ! set MARK accordingly. Remove the filename from ! the front of the list, so that a subsequent call ! will get the next filename. The sequence will ! terminate when FILE is found to be set to the ! remainder of the list. Thus the value of FILE ! should not be changed between calls. %INTEGERFN GET FILE (%STRINGNAME FILE,LIST, %INTEGERNAME MARK) ! Remove the terminator if there is one, in which ! case set FILE to null as this is the first call. %IF LIST->LIST.(SEPR) %THEN FILE='' MARK='' %IF FILE=LIST %OR '*'.FILE=LIST %THENRESULT='' %UNLESS LIST->FILE.(',').LIST %THEN FILE=LIST %IF FILE->('*').FILE %THEN MARK='*' %RESULT=1 %END %END ! ! ! ! Apply a single EMAS command to each of the *'ed ! files in a program entry. If the parameter is ! null then apply it to all programs in DEPTFILE. %ROUTINE APPLY TO PROGRAM FILES (%ROUTINE PROCESS, %C %STRING(63) PROGRAM) %SPEC PROCESS (%STRING (63) S) %STRING (72) LINE,FILE,SFILE %INTEGER FLAG,TYPE %IF PROGRAM='' %THEN FLAG=1 %ELSE FLAG=0 DEFINE ('STREAM03,DEPTFILE') SELECT INPUT(3) %CYCLE %IF FIND ENTRY (PROGRAM)=0 %THENRETURN ! Read all the filename fields and apply the ! command PROCESS to all the files with a '*' in ! front. %CYCLE TYPE=2,1,5 READ LINE (LINE) LINE->LINE.(SEPR) %UNLESS LINE='' %OR LINE='NONE' %THENSTART %UNTIL LINE=FILE %THENCYCLE %UNLESS LINE->FILE.(',').LINE %THEN FILE=LINE %IF FILE->('*').SFILE %THEN PROCESS (SFILE) %REPEAT %FINISH %REPEAT ! Continue to the next program if there was no ! program parameter. %IF FLAG=0 %THENRETURN PROGRAM='' %REPEAT %END ! %EXTERNALROUTINESPEC FILE ANAL (%STRING (63) S) ! ! ! ! Give file analysis on each *'ed file for the ! specified program (or all programs if one is not ! specified). An output file name (or device name) ! may be given, otherwise the output goes to the ! console. Parameters are of the form: ! program name/output name %EXTERNALROUTINE PROGRAM FILE ANAL (%STRING (63) S) %STRING (63 ) S2 ! If there is an output stream then set it up. %IF S->S.('/').S2 %THENSTART DEFINE ('STREAM10,'.S2) SELECT OUTPUT(10) %FINISH APPLY TO PROGRAM FILES (FILEANAL,S) %END ! %EXTERNALROUTINESPEC RESTORE( %STRING (63) S) %EXTERNALINTEGERFNSPEC SMADDR (%INTEGER J, %INTEGERNAME K) %OWNSTRING (255) FAILURES,REJECTS ! ! ! ! 'Use' a file to stop it being archived. ! If the file does not exist then it has probably ! been archived so RESTORE it and add its name to ! the list of failed files. If it cannot be ! RESTOREd then add its name to the list of ! rejected files. If the file exists then connect ! it in order to 'use' it, the easiest way to ! connect a file is as an SMFILE so there is no ! trouble with different file types. Cherish and ! permit the file in case the permissions have been ! lost or the file has been restored. %EXTERNALROUTINE CONNECT 6(%STRING (63) FILE) %INTEGER J,K %IF EXIST (FILE) =0 %THENSTART RESTORE (FILE) %IF SSFAIL=0 %THEN FAILURES=FAILURES.FILE.',' %ELSEC REJECTS=REJECTS.FILE.',' %RETURN %FINISH CHERISH (FILE); PERMITFILE (FILE) DEFINE ('SM06,'.FILE) J=SMADDR (6,K) CLOSE STREAM (6) ; DISCONNECT (FILE) %END ! ! ! ! This routine should be called at least once every ! 4 weeks to stop files being archived if they are ! not used (use tends to be seasonal). Use the ! DEPTFILE entry to get the filenames, only those ! preceeded by a '*' in the entry are 'kept alive'. ! A call to this routine will also CHERISH and ! permit the program files which is useful if a ! program has been set up without the aid of NEW ! PROGRAM or some or all of the program files have ! been restored. ! For those files which do not exist in current ! storoge an attempt is made to restore them from ! archive if this fails then thay must be recreated ! in some other way. E.g. copied from the other ! machine. %EXTERNALROUTINE KEEP ALIVE (%STRING (63) S) %STRING (255) S1,S2,S3 FAILURES='' ; REJECTS='' APPLY TO PROGRAM FILES (CONNECT 6,S) %UNLESS FAILURES='' %THEN PRINTSTRING (FAILURES. %C ' WILL BE RESTORED IF POSSIBLE. REMEMBER TO REPERMIT') NEWLINE %UNLESS REJECTS='' %START PRINTSTRING (REJECTS.' DO(ES) NOT EXIST IN THIS PROCESS.') NEWLINE PRINTSTRING ('COPY THEM/IT FROM THE OTHER MACHINE ') NEWLINE %FINISH %END ! ! ! ! Useful routine to transfer files from one process ! to another with one command. The routine ! parameters are of the form: ! NUMBER.filename1,filename2,filename3....... ! The files are copied from process NUMBER to files ! of the same name on this process (may be called ! in processes other then CSDEPT), the files are ! also permitted in read-shared mode so that they ! may be used by other proceses. E.g.Quick way of ! partially setting up a simple new program, ! updating one or two program files, copying from ! one CSDEPT process to another via the required ! intermediate process. %EXTERNALROUTINE PASS ON (%STRING (63) FILES) %STRING (63) OWNER,FILE %UNLESS FILES->OWNER.('.').FILES %THEN FAIL ('OWNER.FILENAME?') %UNTIL FILE=FILES %CYCLE %UNLESS FILES->FILE.(',').FILES %THEN FILE=FILES COPYFILE (OWNER.'.'.FILE.','.FILE) %IF SSFAIL=0 %THEN PERMITFILE (FILE) %REPEAT %END %ENDOFFILE