USE - A Facility for Selective Execution of Lines Within a Command Procedure Raymond P. Bovet National Center for Atmospheric Research Boulder, Colorado ABSTRACT ________ The need for a facility to execute lines within a command procedure based on modification dates of the input and output files is presented. This is followed by a description of the USE facility designed to fill this need. To illustrate the power of USE a number of examples are given. INTRODUCTION The Perceived Need ___ _________ ____ As a system manager, I often hear complaints such as, "Gee, I put a TYPE statement into my program but nothing came out on my terminal. What happened ?" The answer is usually that the user remembered to recompile the program but didn't relink it (or vice versa). This is one reason for developing the USE facility. But, even if your users are too clever to ever make this kind of mistake, there is another reason for using USE. The best way to document the commands needed to create a piece of software is to provide the actual command procedure which was used. Then, when it needs to be rebuilt, you can be sure the commands are performed in the proper order with the correct switches and options merely by invoking the same command procedure. However, in the development cycle the software may need to be rebuilt often. This points out a need to have the repeatability provided by a command procedure without having to recompile and relink everything every time a small change is made to one routine. Similar Facilities in Other Systems _______ __________ __ _____ _______ The Unix operating system provides a very similar utility called MAKE. I believe that DEC 10 systems also provide a facility for at least compiling and linking a program if needed before running it. The MAKE command of UNIX was the primary model for USE although they differ in at least one key area. Design Goals ______ _____ Since the USE facility was to be used not only by designers of complex Page 2 software systems but also by naive users it had to be easy to use. The first requirement, then, was that it must look as much like a normal command procedure as possible. Second, if users were to begin routinely typing "USE filename" instead of "RUN filename" the USE facility had to be relatively fast. The third design goal was that USE not only look like a normal command procedure but act like one as well. This required the ability to handle continuation lines and other such details in essentially the same way a normal command procedure would. The USE Facility I will now present the USE facility in terms of syntax, implementation details, and current limitations. Syntax ______ The USE facility is invoked by typing USE or USE filespec. If the filespec is omitted, USE prompts for it. If no filetype is given (this is normally the case), a type of .USE is assumed. The device and directory fields are filled in with the user's current defaults if omitted. The most recent version number is used unless explicitly specified. USE first attempts to open the specified file. If it is unable to (presumably because the file is not there), USE tries to open a default use file defined by the logical name USE_DEFAULT. This provides a convenient mechanism for establishing a system-wide default USE file. In addition, groups or individual users can override the system default USE file with their own default USE file defined in the group or process logical name tables. Within the USE file any mixture of upper and lower case characters can be used. As in DCL, all characters are internally converted to upper case. Continuation lines are also allowed. All command lines allowed in DCL are legal in USE. In addition, several special constructs are provided. To enable the conditional execution feature, the input and output files for a given line must be identified to USE. Input filenames are indentified by !I immediately following them while output files are identified by !O. If a line includes an input file specifier, the line will be executed only if some output file is older than one of the input files. Non-existent output files are considered very old. ____ Since most commands allow default filetypes, USE does also. The algorithm USE employs for default filetypes is normally that the input filetype is made up of the first 3 characters of the command name. The default for output filetype is .OBJ. This convention works well for FORTRAN, for example. In addition, USE knows about certain commands which don't obey this convention. These include MACRO for which the default input filetype is forced to .MAR, IFTRAN (a FORTRAN preprocessor used at our installation) whose default output filetype is .FOR, LIBRARY whose default input and output are .OBJ and .OLB, and LINK whose default input and output are .OBJ and .EXE. Sites which make frequent use of other commands needing different default file types can easily add them. Page 3 Some commands allow several different types of input files. There is no problem with this as long as the file types are explicit in the USE file. However, for two common cases, USE allows a special notation. These are for macro and object libraries as input files. They are designated by !M and !L respectively, rather than the normal !I. The ability to work with a default USE file requires that USE provide some mechanism for substituting the filename with which it was invoked into the lines of the default command procedure. This is handled with the special construct !?. This construct is valid in any USE file but is especially appropriate in a default USE file. Implementation ______________ The current implementation of the USE facility is the result of trying a number of different approaches. The first USE was developed strictly as a command procedure. While it provided essentially the full functionality described above it was clearly too slow. Subsequent approaches have all been based on a combination of command procedure and compiled code (mainly FORTRAN) with the program handling most of the work. The most promising alternative was to execute each line via a subprocess running LOGINOUT as soon as it was determined that the line should be executed. The principle disadvantages of this technique were that the subprocess did not have the same logical name table as the main process, that allocated devices could not be shared between the main and sub processes, and that problems could arise with quota limits (this was especially serious before version 2.0 of VMS). The current implementation of USE involves an image which reads the USE file, determines which lines are to be executed, writes them to a temporary file, and then executes that file as a command procedure. One complication this introduces is that USE must remember when execution of a given line will modify a file which serves as input to a subsequent command line. The present version of USE handles this by maintaining an internal table of files which will be updated as part of the command procedure to follow. USE looks up input files for all subsequent command lines in this table. If they exist in the table USE knows they will have been updated by the time the subsequent line is executed. Current Limitations _______ ___________ The defect in this scheme is that USE does not add files to the table when dealing with lines which are to be unconditionally executed (since the filetypes might not conform to its defaults USE can't be sure of what the output filespecs of unconditional lines are). Further, USE doesn't understand anything about branching and IF statements. Thus, it assumes that all lines which pass the input and output file date test will be executed and in the order specified. These are likely to be problems only in rather sophisticated (ie. weird) applications of USE. Another shortcoming of the current implementation of USE is that no attempt has been made to teach it about DCL symbols and symbol substitution. In practice, I have not found this to be a serious problem, but it is a deviation from the goal of acting just like a normal command procedure. The other limitation of which I am aware is Page 4 that USE does not handle continuation lines exactly the way DCL does. USE always assumes that a hyphen at the end of a line means that the next line is a continuation line. DCL, on the other hand, ignores comments in defining the end of the line. This is of little consequence in most cases. Also, USE concatenates continuation lines into a single line on input, and breaks lines up into continuation lines on output. Since the line length changes due to omission of the special USE syntax, the continuations don't usually occur at the same place on output as on input. The most serious problem is that under VMS 2.0, DCL does not allow (as far as I can tell) double quoted strings to be interrupted by a hyphen to indicate continuation. Thus, if a double quoted string happens to span a line boundary you will have problems. Finally, there are some fundamental limitations with this approach. Obviously, it does not include any code control system to define who has the right to modify code, force them to give an explanation of the changes made, or keep track of previous versions of the software. These capabilities, while very desirable, are far beyond the scope of USE. The other fundamental limitation has to do with libraries. USE can certainly be used in conjunction with libraries. However, when a library is updated, there is no obvious, immediate way for USE to know whether the changes involved modules which a given image actually takes from the library or not. If you include the object library as an input file to your link commands you will do lots of unecessary links when unused parts of the library are changed. On the other hand, if you omit it you run the risk of not having the most recent versions in your image. It would clearly be desirable to extend USE so that it could determine which modules within a library were to be used and only consider the modification dates of those. EXAMPLES The Standard Default USE File ___ ________ _______ ___ ____ On our system the most common procedure for a user is to write a short FORTRAN program which is linked only to system default libraries and then run. Thus our system-wide default USE file looks like this: USE.DFT _______ $ FORTRAN !?!I!O $ LINK !?!I!O $ ASSIGN/USER SYS$COMMAND SYS$INPUT $ RUN !? Note that !? is used to indicate the filename actually supplied with the USE command. Perhaps the only other point to mention here is the assignment of SYS$COMMAND to SYS$INPUT. This is probably quite familiar to most users of command procedures. Its effect is to cause input to the image to come from the terminal (or whatever the original SYS$INPUT for the process was) rather than from the command procedure itself. Implicit Input Files ________ _____ _____ Sometimes it is desirable to tell USE about input files which are not Page 5 explicitly specified in the command line. This can be done by including them in a comment field which is interpreted by USE but ignored by the actual command. One frequent use for this technique is in compiling FORTRAN files which contain the INCLUDE statement. A simple example of an appropriate USE file for this case follows: SAMPLE1.USE ___________ $ FORTRAN MYPROG!I!O ! here's the INCLUDE file: MYINCLUDE!I $ LINK MYPROG!I!O $ ASSIGN/USER SYS$COMMAND SYS$INPUT $ RUN MYPROG When USE looks at the first line, it finds two input files, MYPROG and MYINCLUDE. If either of these has changed since MYPROG.OBJ was created the line will be executed. Before the line is written to the temporary command procedure file, USE strips out the !I and !O so the line finally looks like: $ FORTRAN MYPROG ! here's the INCLUDE file: MYINCLUDE This same technique is used when a LINK command involving an option file is given. In this case the input files are listed in the option file rather than on the link command line. Again, they can be included in the conditional test by putting them in a comment field. A Complex Example - The NCAR Graphics Package _ _______ _______ _ ___ ____ ________ _______ When a project involves a significant number of individual files USE can be especially helpful in keeping everything up to date. The example below is from the NCAR graphics package, a collection of basic plotting subroutines and graphic utility routines. Most of these routines are gathered into a single object library. GRAPHICS.USE ____________ $ LIB /CREATE=MODULES:300 NCAR.OLB!I!O $ FOR PLOT48!I!O! omit /CHECK since these routines cheat $ LIBR NCAR!O PLOT48!I $ FOR/CHECK FRAME!I!O $ LIBR NCAR!O FRAME!I $ FOR/CHECK LOCAL12!I!O $ LIBR NCAR!O LOCAL12!I $ FOR/CHECK PWRY!I!O $ LIBR NCAR!O PWRY!I $ FOR/CHECK ENCD!I!O $ LIBR NCAR!O ENCD!I $ FOR/CHECK Q8QST4!I!O $ LIBR NCAR!O Q8QST4!I $ FOR/CHECK AUTOGRAPH!I!O $ LIBR NCAR!O AUTOGRAPH!I $ FOR/CHECK CONREC!I!O $ LIBR NCAR!O CONREC!I $ FOR/CHECK DASHCHAR!I!O $ LIBR NCAR!O DASHCHAR!I $ FOR/CHECK HAFTON!I!O $ LIBR NCAR!O HAFTON!I $ FOR/CHECK ISOSRF!I!O $ LIBR NCAR!O ISOSRF!I $ FOR/CHECK ISOSRFHR!I!O Page 6 $ LIBR NCAR!O ISOSRFHR!I $ FOR/CHECK SRFACE!I!O $ LIBR NCAR!O SRFACE!I $ FOR/CHECK SUPMAP!I!O $ LIBR NCAR!O SUPMAP!I $ FOR/CHECK THREED!I!O $ LIBR NCAR!O THREED!I $ FOR/CHECK VELVCT!I!O $ LIBR NCAR!O VELVCT!I $ FOR/CHECK INTER!I!O $ LIBR NCAR!O INTER!I $ FOR/CHECK INTERRD!I!O $ LIBR NCAR!O INTERRD!I $ FOR/CHECK INTERWRT!I!O $ LIBR NCAR!O INTERWRT!I $ FOR/CHECK INTERSET!I!O $ LIBR NCAR!O INTERSET!I $ FOR/CHECK MCDECODE!I!O $ LIBR NCAR!O MCDECODE!I $ FOR/CHECK PWRITX!I!O $ LIBR NCAR!O PWRITX!I $ FOR/CHECK STRMLN!I!O $ LIBR NCAR!O STRMLN!I $ FOR/CHECK CONRECQCK!I!O $ FOR/CHECK DASHLINE!I!O $ FOR/CHECK DASHSMTH!I!O $ FOR/CHECK DASHSUPR!I!O Although the main reason for including this example is to emphasize how necessary some sort of automation becomes for a reasonably large project, this example illustrates another point which is worth mentioning. The first line creates an object library file. Clearly, it should only be executed if there isn't one already in existence. This is done by specifying the same filespec as both an input and an output file. If the input file doesn't exist USE reacts as if there were no input files mentioned in the command and therefore executes it. However, if the file already exists, then the output file is as recent as the input file so the line is suppressed. Thus, USE can also execute lines based on the existence of a given file. Along with the graphics package itself, we maintain a suite of test programs which exercise the graphics package. The following USE file updates all the test programs and reruns them as needed. Note that the test routines are kept in a separate directory from the graphics package itself. TEST.USE ________ $ FOR AUTOGRTST!I!O $ FOR AUTOGSTST!I!O $ FOR CONQCKTST!I!O $ FOR CONRECTST!I!O $ FOR CONSMTTST!I!O $ FOR DASHCHTST!I!O $ FOR DASHLNTST!I!O $ FOR DASHSMTST!I!O Page 7 $ FOR DASHSUTST!I!O $ FOR HAFTONTST!I!O $ FOR ISOSHRTST!I!O $ FOR ISOSRFTST!I!O $ FOR PWRITXTST!I!O $ FOR PWRYTST!I!O $ FOR SRFACETST!I!O $ FOR STRMLNTST!I!O $ FOR SUPMAPTST!I!O $ FOR THREEDTST!I!O $ FOR VELVCTTST!I!O $ FOR CHINA!I!O $ LINK AUTOGRTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,- NCARGRLIB:Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:AUTOGRAPH!I $ LINK AUTOGSTST!I!O,NCARGRLIB:DASHSMTH!I,PLOT:/L- IB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,- NCARGRLIB:ENCD!I,NCARGRLIB:Q8QST4!I,NCARGRLIB:DASHCHAR!I,- NCARGRLIB:AUTOGRAPH!I $ LINK CONQCKTST!I!O,NCARGRLIB:CONRECQCK!I,PLOT:/- LIB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,NCARGRLIB:- PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:Q8QST4!I,NCARGRLIB:DASHCHAR!I $ LINK CONRECTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:CONREC!I $ LINK CONSMTTST!I!O,NCARGRLIB:DASHSMTH!I,PLOT:/L- IB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,- NCARGRLIB:PWRY!I,NCARGRLIB:- ENCD!I,NCARGRLIB:Q8QST4!I,NCARGRLIB:CONREC!I $ LINK DASHCHTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I $ LINK DASHLNTST!I!O,NCARGRLIB:DASHLINE!I,PLOT:/L- IB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,NCARGRLIB:- PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:Q8QST4!I $ LINK DASHSMTST!I!O,NCARGRLIB:DASHSMTH!I,PLOT:/L- IB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,- NCARGRLIB:PWRY!I,NCARGRLIB:- ENCD!I,NCARGRLIB:Q8QST4!I $ LINK DASHSUTST!I!O,NCARGRLIB:DASHSUPR!I,PLOT:/L- IB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,- NCARGRLIB:PWRY!I,NCARGRLIB:- ENCD!I,NCARGRLIB:Q8QST4!I $ LINK HAFTONTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:HAFTON!I $ LINK ISOSHRTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:ISOSRFHR!I $ LINK ISOSRFTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:ISOSRF!I $ LINK PWRITXTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:PWRITX!I Page 8 $ LINK PWRYTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!I,NCARGRLIB:- LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I $ LINK SRFACETST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:SRFACE!I $ LINK STRMLNTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:STRMLN!I $ LINK SUPMAPTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:SUPMAP!I $ LINK THREEDTST!I!O,NCARGRLIB:THREED!I,PLOT:/LIB- !,NCARGRLIB:PLOT48!I,NCARGRLIB:LOCAL12!I,- NCARGRLIB:PWRY!I,NCARGRLIB:- ENCD!I,NCARGRLIB:Q8QST4!I,NCARGRLIB:DASHCHAR!I $ LINK VELVCTTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!- I,NCARGRLIB:LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:VELVCT!I $ LINK CHINA!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!I,NCARGRLIB:LO- CAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:SUPMAP!I $ FOR INTERTST!I!O $ FOR INTERTSTT!I!O $ FOR INTERTSTF!I!O $ LINK INTERTST!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!I,NCARGRLIB:- LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:AUTOGRAPH!I,- NCARGRLIB:INTERSET!I,NCARGRLIB:- INTERWRT!I,NCARGRLIB:INTERRD!I,NCARGRLIB:MCDECODE!I $ LINK INTERTSTT!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!I,NCARGRLIB:- LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:AUTOGRAPH!I,- NCARGRLIB:INTER!I,NCARGRLIB:- INTERWRT!I,NCARGRLIB:INTERRD!I,NCARGRLIB:MCDECODE!I $ LINK INTERTSTF!I!O,PLOT:/LIB!,NCARGRLIB:PLOT48!I,NCARGRLIB:- LOCAL12!I,NCARGRLIB:PWRY!I,NCARGRLIB:ENCD!I,NCARGRLIB:- Q8QST4!I,NCARGRLIB:DASHCHAR!I,NCARGRLIB:AUTOGRAPH!I,- NCARGRLIB:INTER!I,NCARGRLIB:- INTERWRT!I,NCARGRLIB:INTERRD!I,NCARGRLIB:MCDECODE!I $ ASSIGN/USER AUTOGRTST.DAT IOP020 $ RUN AUTOGRTST.EXE!I!,AUTOGRTST.DAT!O $ ASSIGN/USER AUTOGSTST.DAT IOP020 $ RUN AUTOGSTST.EXE!I!,AUTOGSTST.DAT!O $ ASSIGN/USER CONQCKTST.DAT IOP020 $ RUN CONQCKTST.EXE!I!,CONQCKTST.DAT!O $ ASSIGN/USER CONRECTST.DAT IOP020 $ RUN CONRECTST.EXE!I!,CONRECTST.DAT!O $ ASSIGN/USER CONSMTTST.DAT IOP020 $ RUN CONSMTTST.EXE!I!,CONSMTTST.DAT!O $ ASSIGN/USER DASHCHTST.DAT IOP020 $ RUN DASHCHTST.EXE!I!,DASHCHTST.DAT!O $ ASSIGN/USER DASHLNTST.DAT IOP020 $ RUN DASHLNTST.EXE!I!,DASHLNTST.DAT!O $ ASSIGN/USER DASHSMTST.DAT IOP020 Page 9 $ RUN DASHSMTST.EXE!I!,DASHSMTST.DAT!O $ ASSIGN/USER DASHSUTST.DAT IOP020 $ RUN DASHSUTST.EXE!I!,DASHSUTST.DAT!O $ ASSIGN/USER HAFTONTST.DAT IOP020 $ RUN HAFTONTST.EXE!I!,HAFTONTST.DAT!O $ ASSIGN/USER ISOSHRTST.DAT IOP020 $ RUN ISOSHRTST.EXE!I!,ISOSHRTST.DAT!O $ ASSIGN/USER ISOSRFTST.DAT IOP020 $ RUN ISOSRFTST.EXE!I!,ISOSRFTST.DAT!O $ ASSIGN/USER PWRITXTST.DAT IOP020 $ RUN PWRITXTST.EXE!I!,PWRITXTST.DAT!O $ ASSIGN/USER PWRYTST.DAT IOP020 $ RUN PWRYTST.EXE!I!,PWRYTST.DAT!O $ ASSIGN/USER SRFACETST.DAT IOP020 $ RUN SRFACETST.EXE!I!,SRFACETST.DAT!O $ ASSIGN/USER STRMLNTST.DAT IOP020 $ RUN STRMLNTST.EXE!I!,STRMLNTST.DAT!O $ ASSIGN/USER SUPMAPTST.DAT IOP020 $ RUN SUPMAPTST.EXE!I!,SUPMAPTST.DAT!O $ ASSIGN/USER THREEDTST.DAT IOP020 $ RUN THREEDTST.EXE!I!,THREEDTST.DAT!O $ ASSIGN/USER VELVCTTST.DAT IOP020 $ RUN VELVCTTST.EXE!I!,VELVCTTST.DAT!O $ ASSIGN/USER CHINA.DAT IOP020 $ RUN CHINA.EXE!I!,CHINA.DAT!O $ DEASSIGN IOP020 The most interesting point about this example is that the LINK commands explicitly call out which object files within the library each image actually uses. Thus, only the test programs which use a particular subroutine are relinked and rerun when that routine is changed. While this technique works, it is very tedious to figure out all the routines a particular program uses. Modifying an Installed Global Section _________ __ _________ ______ _______ This example shows the steps involved in modifying an installed global section (in this case a FORTRAN COMMON). The example given here is taken from Using Shared FORTRAN COMMONs in VMS which appears elsewhere _____ ______ _______ _______ __ ___ in these proceedings. $ FORTRAN MYBLOCK!I!O!,MYCOMMON!I $ LINK/SHARE MYBLOCK!I!O $ NEW_COMMON := NO $ NEW_COMMON := YES !,MYBLOCK.EXE!I MYBLOCK.CUR!O $ IF .NOT.NEW_COMMON THEN GOTO NO_NEW $ COPY MYBLOCK.EXE MYBLOCK.CUR $ MCR INSTALL DBA0:[SYSMGR]MAINPROG.EXE /DELETE $ RUN SAVECOM $ MCR INSTALL DBA0:[SYSMGR]MYBLOCK.EXE /DELETE DBA0:[SYSMGR]MYBLOCK.EXE /SHARE /WRITE $ ASSIGN/SYSTEM DBA0:[SYSMGR]MYBLOCK.EXE MYBLOCK $ NO_NEW: $ FORTRAN MAINPROG!I!O! MYCOMMON!I Page 10 $ LINK MAINPROG!I!O/OPTIONS! MYBLOCK.CUR!I $ FORTRAN SAVECOM!I!O! MYCOMMON!I $ LINK SAVECOM!I!O/OPTIONS! MYBLOCK.CUR!I $ FORTRAN LOADCOM!I!O! MYCOMMON!I $ LINK LOADCOM!I!O/OPTIONS! MYBLOCK.CUR!I $ IF .NOT.NEW_COMMON THEN GOTO NO_NEW2 $ RUN LOADCOM $ MCR INSTALL DBA0:[SYSMGR]MAINPROG.EXE /PRIV=SYSPRV $ EXIT $ NO_NEW2: $ MCR INSTALL DBA0:[SYSMGR]MAINPROG.EXE /REPLACE Note that the above example includes a mixture of explicit IFs and GOTOs as well as USE conditional lines. It is save (ie results are what you'd expect) to do this as long as the IFs and GOTOs don't cause conditional USE lines to be either skipped or executed more than once. The reason they are used above is that depending on the result of a particular test several lines may need to be performed. While the Unix based MAKE command provides explicitly for this possibility, USE does not. This is done to simplify its use in very simple applications. In terms of the content of the example, note that a copy of the current shareable image file (MYBLOCK.EXE) is always kept in MYBLOCK.CUR. Programs which use the COMMON link to this copy since MYBLOCK.EXE is locked once it is installed. SAVECOM is a program which writes out the current contents of the COMMON to disk whenever a new shareable image file is created. This allows you to maintain data values even during development of the application. LOADCOM is the program which reloads the COMMON from the values saved on disk by SAVECOM. Rather than using the REPLACE option in INSTALL, we separately DELETE and install MYBLOCK.EXE. This way we can use the same USE file even the first time around (provided we ignore the warning from INSTALL). Further details on this example can be found in the paper Using Shared FORTRAN COMMONs in VMS. _____ ______ _______ _______ __ ___ CONCLUSIONS I hope that I have demonstrated the value of the USE facility. I have tried to outline its weaknesses as well as its strong points. As I mentioned, such a facility is only the first step toward a full source code control system (such as that implemented as a part of Western Electric's Programmer's Work Bench for example). However, I have found that its usefulness has been well worth the effort required to implement it.