;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: 4Adding New Options for defsystem* =Text: 3ADDING NEW OPTIONS FOR DEFSYSTEM* Options to 2defsystem* are defined as macros on the 2si:defsystem-macro* property of the option keyword. Such a macro can expand into an existing option or transformation, or it can have side effects and return 2nil*. There are several variables they can use; the only one of general interest is 3si:*system-being-defined** 1Variable* The internal data structure that represents the system that is currently being constructed. 3si:define-defsystem-special-variable* 1variable* 1value* 1Macro* Causes 1value* to be evaluated and 1variable* to be bound to the result during the expansion of the 2defsystem* special form. This allows you to define new variables similar to the one listed above. 3si:define-simple-transformation* 1Macro* This is the most convenient way to define a new simple transformation. The form is 3(si:define-simple-transformation 1name* 1function** 3 1default-condition* 1input-file-types* 1output-file-types** 3 1pretty-names* 1compile-like* 1load-like*)* For example, 3(si:define-simple-transformation :compile si:qc-file-1* 3 si:file-newer-than-file-p (:lisp) (:qfasl))* 1input-file-types* and 1output-file-types* are how a transformation specifies how many input filenames and output filenames it should receive as arguments, in this case one of each. They also, obviously, specify the default file type for these pathnames. The 2si:qc-file-1* function is mostly like 2compile-file*, except for its interface to packages. It takes input-file and output-file arguments. 1pretty-names*, 1compile-like*, and 1load-like* are optional. 1pretty-names* specifies how messages printed for the user should print the name of the transformation. It can be a list of the imperative (``Compile''), the present participle (``Compiling''), and the past participle (``compiled''). Note that the past participle is not capitalized, because when used it does not come at the beginning of a sentence. 1pretty-names* can be just a string, which is taken to be the imperative, and the system will conjugate the participles itself. If 1pretty-names* is omitted or 2nil* it defaults to the name of the transformation. 1compile-like* and 1load-like* say when the transformation should be performed. Compile-like transformations are performed when the 2:compile* keyword is given to 2make-system*. Load-like transformations are performed unless the 2:noload* keyword is given to 2make-system*. By default 1compile-like* is 2t* but 1load-like* is 2nil*. Complex transformations are defined as normal macro expansions, for example, 3(defmacro (:compile-load si:defsystem-macro)* 3 (input &optional com-dep load-dep* 3 com-cond load-cond)* 3 `(:fasload (:compile ,input ,com-dep ,com-cond)* 3 ,load-dep ,load-cond))* =Node: 4More Esoteric Transformations* =Text: 3MORE ESOTERIC TRANSFORMATIONS* It is sometimes useful to specify a transformation upon which something else can depend, but which is performed not by default, but rather only when requested because of that dependency. The transformation nevertheless occupies a specific place in the hierarchy. The 2:skip* 2defsystem* macro allows specifying a transformation of this type. For example, suppose there is a special compiler for the read table which is not ordinarily loaded into the system. The compiled version should still be kept up to date, and it needs to be loaded if ever the read table needs to be recompiled. 3(defsystem reader* 3 (:pathname-default "SYS: IO;")* 3 (:package system-internals)* 3 (:module defs "RDDEFS")* 3 (:module reader "READ")* 3 (:module read-table-compiler "RTC")* 3 (:module read-table "RDTBL")* 3 (:compile-load defs)* 3 (:compile-load reader (:fasload defs))* 3 (:skip :fasload (:compile read-table-compiler))* 3 (:rtc-compile-load read-table (:fasload read-table-compiler)))* Assume that there is a complex transformation 2:rtc-compile-load*, which is like 2:compile-load* except that is is built on a transformation called something like 2:rtc-compile*, which uses the read table compiler rather than the Lisp compiler. In the above system, then, if the 2:rtc-compile* transformation is to be performed, the 2:fasload* transformation must be done on 2read-table-compiler* first, that is the read table compiler must be loaded if the read table is to be recompiled. If you say 2(make-system 'reader :compile)*, then the 2:compile* transformation is done on the 2read-table-compiler* module despite the 2:skip*, compiling the read table compiler if need be. If you say 2(make-system 'reader)*, the reader and the read table are loaded, but the 2:skip* keeps this from happening to the read table compiler. So far nothing has been said about what can be given as a 1condition* for a transformation except for the default functions, which check for conditions such as a source file being newer than the binary. In general, any function that takes the same arguments as the transformation function (e.g. 2compile-file*) and returns 2t* if the transformation needs to be performed, can be in this place as a symbol, including for example a closure. To take an example, suppose there is a file that contains 2compile-flavor-methods* for a system and that should therefore be recompiled if any of the flavor method definitions change. In this case, the condition function for compiling that file should return 2t* if either the source of that file itself or any of the files that define the flavors have changed. This is what the 2:compile-load-init* complex transformation is for. It is defined like this: 3(defmacro (:compile-load-init si:defsystem-macro)* 3 (input add-dep &optional com-dep load-dep* 3 &aux function)* 3 (setq function (let-closed ((*additional-dependent-modules** 3 add-dep))* 3 'compile-load-init-condition))* 3 `(:fasload (:compile ,input ,com-dep ,function) ,load-dep))* 3(defun compile-load-init-condition (source-file qfasl-file)* 3 (or (si:file-newer-than-file-p source-file qfasl-file)* 3 (local-declare ((special *additional-dependent-modules*))* 3 (si:other-files-newer-than-file-p* 3 *additional-dependent-modules** 3 qfasl-file))))* The condition function generated when this macro is used returns 2t* either if 2si:file-newer-than-file-p* would with those arguments, or if any of the other files in 2add-dep*, which presumably is a 1module specification*, are newer than the QFASL file. Thus the file (or module) to which the 2:compile-load-init* transformation applies will be compiled if it or any of the source files it depends on has been changed, and will be loaded under the normal conditions. In most (but not all cases), 2com-dep* is a 2:fasload* transformation of the same files as 2add-dep* specifies, so that all the files this one depends on will be loaded before compiling it. =Node: 4Common Lisp Modules* =Text: 3COMMON LISP MODULES* In Common Lisp, a 1module* is a name given to a group of files of code. Modules are not like systems because nothing records what the ``contents'' of any particular module may be. Instead, one of the files which defines the module contains a 2provide* form which says, when that file is loaded, ``Module 2foo* is now present.'' Other files may say, using 2require*, ``I want to use module 2foo*.'' Normally the 2require* form also specifies the files to load if 2foo* has not been 2provide*'d already. This is where the information of which files are in a module is stored. If the 2require* does not have file names in it, the module name 2foo* is used in an implementation-dependent manner to find files to load. The Lisp Machine does this by using it as a system name in 2make-system*. 3provide* 1module-name* Adds 1module-name* to the list 2*modules** of modules already loaded. 1module-name* should be a string; case is significant. 3require* 1module-name* &rest 1files* If module 1module-name* is not already loaded (on 2*modules**), 1files* are loaded in order to make the module available. 1module-name* should be a string; case is significant. The elements of 1files* should be pathnames or namestrings. If 1files* is 2nil*, 2(make-system 1module-name** 2:noconfirm)* is done. Note, however, that case is not significant in the argument to 2make-system*. 3*modules** 1Variable* A list of names (strings) of all modules 2provide*'d so far. =Node: The Patch Facility =Text: 3THE PATCH FACILITY* The patch facility allows a system maintainer to manage new releases of a large system and issue patches to correct bugs. It is designed to be used to maintain both the Lisp Machine system itself and applications systems that are large enough to be loaded up and saved on a disk partition. When a system of programs is very large, it needs to be maintained. Often problems are found and need to be fixed, or other little changes need to be made. However, it takes a long time to load up all of the files that make up such a system, and so rather than having every user load up all the files every time he wants to use the system, usually the files just get loaded once into a Lisp world, which is then saved away on a disk partition. Users then use this disk partition, copies of which may appear on many machines. The problem is that since the users don't load up the system every time they want to use it, they don't get all the latest changes. The purpose of the patch system is to solve this problem. A 1patch* file is a little file that, when you load it, updates the old version of the system into the new version of the system. Most often, patch files just contain new function definitions; old functions are redefined to do their new thing. When you want to use a system, you first use the Lisp environment saved on the disk, and then you load all the latest patches. Patch files are very small, so loading them doesn't take much time. You can even load the saved environment, load up the latest patches, and then save it away, to save future users the trouble of even loading the patches. (Of course, new patches may be made later, and then these will have to be loaded if you want to get the very latest version.) For every system, there is a series of patches that have been made to that system. To get the latest version of the system, you load each patch file in the series, in order. Sooner or later, the maintainer of a system wants to stop building more and more patches, and recompile everything, starting afresh. A complete recompilation is also necessary when a system is changed in a far-reaching way, that can't be done with a small patch; for example, if you completely reorganize a program, or change a lot of names or conventions, you might need to completely recompile it to make it work again. After a complete recompilation has been done, the old patch files are no longer suitable to use; loading them in might even break things. The way all this is kept track of is by labelling each version of a system with a two-part number. The two parts are called the 1major version number* and the 1minor version number*. The minor version number is increased every time a new patch is made; the patch is identified by the major and minor version number together. The major version number is increased when the program is completely recompiled, and at that time the minor version number is reset to zero. A complete system version is identified by the major version number, followed by a dot, followed by the minor version number. Thus, patch 293.9* is for major version 93 and minor version 9; it is followed by patch 293.10*. To clarify this, here is a typical scenario. A new system is created; its initial version number is 21.0*. Then a patch file is created; the version of the program that results from loading the first patch file into version 21.0* is called 21.1*. Then another patch file might be created, and loading that patch file into system 21.1* creates version 21.2*. Then the entire system is recompiled, creating version 22.0* from scratch. Now the two patch files are irrelevant, because they fix old software; the changes that they reflect are integrated into system 22.0*. Note that the second patch file should only be loaded into system 21.1* in order to create system 21.2*; you shouldn't load it into 21.0* or any other system besides 21.1*. It is important that all the patch files be loaded in the proper order, for two reasons. First, it is very useful that any system numbered 21.1* be exactly the same software as any other system numbered 21.1*, so that if somebody reports a bug in version 21.1*, it is clear just which software is being complained about. Secondly, one patch might patch another patch; loading them in some other order might have the wrong effect. The patch facility keeps track of all the patch files that exist, remembering which version each one creates. There is a separate numbered sequence of patch files for each major version of each system. All of them are stored in the file system, and the patch facility keeps track of where they all are. In addition to the patch files themselves, there are 1patch directory* files that contain the patch facility's data base by which it keeps track of what minor versions exist for a major version, and what the last major version of a system is. These files and how to make them are described below. In order to use the patch facility, you must define your system with 2defsystem* (see 4(SYSTEMS-0)Maintaining Large Systems*) and declare it as patchable with the 2:patchable* option. When you load your system (with 2make-system*, see 4(SYSTEMS-1)Making a System*), it is added to the list of all systems present in the world. The patch facility keeps track of which version of each patchable system is present and where the data about that system reside in the file system. This information can be used to update the Lisp world automatically to the latest versions of all the systems it contains. Once a system is present, you can ask for the latest patches to be loaded, ask which patches are already loaded, and add new patches. You can also load in patches or whole new systems and then save the entire Lisp environment away in a disk partition. This is explained on 4(MISCELL-3)Booting and Disk Partitions*. When a Lisp Machine is booted, it prints out a line of information for each patchable system present in the booted Lisp world, saying which major and minor versions are loaded. This is done by 2print-herald* (see 4(SYSTEMS-2)The Patch Facility*). 3print-system-modifications* &rest 1system-names* With no arguments, this lists all the systems present in this world and, for each system, all the patches that have been loaded into this world. For each patch it shows the major version number (which is always the same since a world can only contain one major version), the minor version number, and an explanation of what the patch does, as typed in by the person who made the patch. If 2print-system-modifications* is called with arguments, only the modifications to the systems named are listed. 3print-herald* &optional 1format-dest* Prints the names and loaded version numbers of all patchable systems loaded, and the microcode. Also printed are the number of the band you booted, the amount of physical and virtual memory you have, the host name of the machine, and its associated machine name. Example: 3MIT System, band 7 of CADR-1.* 3640K physical memory, 16127K virtual memory.* 3 System 98.43* 3 CADR 3.6* 3 ZMail 53.10* 3 MIT-Specific 22.0* 3 Microcode 309* 3MIT Lisp Machine One, with associated machine OZ.* 1format-dest* defaults to 2t*; if it is 2nil* the answer is returned as a string rather than printed out. 1format-dest* can also be a stream to print on. 3si:get-system-version* &optional 1system* Returns two values, the major and minor version numbers of the version of 1system* currently loaded into the machine, or 2nil* if that system is not present. 1system* defaults to 2"System"*. 3si:system-version-info* &optional 1(brief-p* 3nil1)** Returns a string giving information about which systems and what versions of the systems are loaded into the machine, and what microcode version is running. A typical string for it to produce is: 3"System 98.48, CADR 3.6, MIT-Specific 22.0, microcode 309"* If 1brief-p* is 2t*, it uses short names, suppresses the microcode version, any systems which should not appear in the disk label comment, the name 2System*, and the commas: 3"98.48"* =Node: 4Defining a System* =Text: 3DEFINING A SYSTEM* In order to use the patch facility, you must declare your system as patchable by giving the 2:patchable* option to 2defsystem* (see 4(SYSTEMS-0)Maintaining Large Systems*). The major version of your system in the file system is incremented whenever 2make-system* is used to compile it. Thus a major version is associated with a set of QFASL files. The major version of your system that is remembered as having been loaded into the Lisp environment is set to the major version in the file system whenever 2make-system* is used to load your system and the major version in the file system is greater than what you had loaded before. After loading your system, you can save it with the 2disk-save* function (see 4(MISCELL-3)Updating Software*). 2disk-save* asks you for any additional information you want printed as part of the greeting when the machine is booted. This is in addition to the names and versions of all the systems present in this world. If the system version does not fit in the partition comment field allocated in the disk label, 2disk-save* asks you to type in an abbreviated form. =Node: 4Loading Patches* =Text: 3LOADING PATCHES load-patches* &rest 1options* This function is used to bring the current world up to the latest minor version of whichever major version it is, for all systems present, or for certain specified systems. If there are any patches available, 2load-patches* offers to read them in. With no arguments, 2load-patches* updates all the systems present in this world. If you do not specify the systems to operate on, 2load-patches* also reloads the site files if they have changed (4(MISCELL-4)Site Options and Host Table*), and reloads the files defining logical host translations if they have changed (4(FILENAMES-3)Logical Pathnames*). 1options* is a list of keywords. Some keywords are followed by an argument. The following options are accepted: 2:systems 1list** 1list* is a list of names of systems to be brought up to date. If this option is not specified, all patchable systems loaded are processed. 2:unreleased* Loads unreleased patches with no special querying. These patches should be loaded for experimental use if you wish the benefit of the latest bug fixes, but should not be loaded if you plan to save a band. 2:site* Loads the latest site files if they have been changed since last loaded. This is the default if you do not specify explicitly which systems to process. 2:nosite* Prevents loading of site files. This is the default when you specify the systems to process. 2:hosts* Reloads the files defining logical host translations if they have been changed since last loaded. This is the default if you do not specify explicitly which systems to process. 2:nohosts* Prevents loading of logical host translation files. This is the default when you specify the systems to process. 2:verbose* Prints an explanation of what is being done. This is the default. 2:selective* For each patch, says what it is and then ask the user whether or not to load it. This is the default. If the user answers 2P* (for `Proceed'), selective mode is turned off for any remaining patches to the current system. 2:noselective* Turns off 2:selective*. 2:silent* Turns off both 2:selective* and 2:verbose*. In 2:silent* mode all necessary patches are loaded without printing anything and without querying the user. 2:force-unfinished* Loads patches that have not been finished yet, if they have been compiled. 2load-patches* returns 2t* if any patches were loaded. When you load a patchable system with 2make-system*, 2load-patches* is called automatically on that system. 3si:patch-loaded-p* 1major-version* 1minor-version* &optional 1(system-name* 3"SYSTEM"1)** Returns 2t* if the changes in patch 1major-version*.1minor-version* of system 1system-name* are loaded. If 1major-version* is the major version of that system which is currently loaded, then the changes in that patch are loaded if the current minor version is greater than or equal to 1minor-version*. If the currently loaded major version is greater than 1major-version* then it is assumed that the newer system version contains all the improvements patched into earlier versions, so the value is 2t*. =Node: 4Making Patches* =Text: 3MAKING PATCHES* There are two editor commands that are used to create patch files. During a typical maintenance session on a system you will make several edits to its source files. The patch system can be used to copy these edits into a patch file so that they can be automatically incorporated into the system to create a new minor version. Edits in a patch file can be modified function definitions, new functions, modified 2defvar*'s and 2defconst*'s, or arbitrary forms to be evaluated, even including 2load*'s of new files. The first step in making a patch is to 1start* it. At this stage you must specify which patchable system you are making a patch for. Then you 1add* one or more pieces of code from other source files to the patch. Finally you 1finish* the patch. This is when you fill in the description of what the patch does; this description is what 2load-patches* prints when it offers to load the patch. If you have any doubts about whether the patch will load and work properly, you finish it 1unreleased*; then you can load it to test it but no bands can be saved containing the patch until you explicitly release it later. It is important that any change you patch should go in a patch for the patchable system to which the changed source file belongs. This makes sure that nobody loads the change into a Lisp world which does not contain the file you were changing--something that might cause trouble. Also, it ensures that you never patch changes to the same piece of code in two different patchable systems' patches. This would lead to disaster because there is no constraint on the order in which patches to two different systems are loaded. Starting a patch can be done with 2Meta-X Start Patch*. It reads the name of the system to patch with the minibuffer. 2Meta-X Add Patch* can also start a patch, so an explicit 2Meta-X Start Patch* is needed only infrequently. 2Meta-X Add Patch* adds the region (if there is one) or the current ``defun'' to the patch file currently being constructed. If you change a function, you should recompile it, test it, then once it works use 2Add Patch* to put it in the patch file. If no patch is being constructed, one is started for you; you must type in the name of the system to patch. A convenient way to add all your changes to a patch file is to use 2Meta-X Add Patch Changed Sections* or 2Meta-X Add Patch Buffer Changed Sections*. These commands ask you, for each changed function (or each changed function in the current buffer), whether to add it to the patch being constructed. If you use these commands more than once, a function which has been added to the patch and has not been changed since is considered ``unchanged''. The patch file being constructed is in an ordinary editor buffer. If you mistakenly 2Add Patch* something that doesn't work, you can select the buffer containing the patch file and delete it. Then later you can 2Add Patch* the corrected version. While you are making your patch file, the minor version number that has been allocated for you is reserved so that nobody else can use it. This way if two people are patching a system at the same time, they do not both get the same minor version number. After testing and patching all of your changes, use 2Meta-X Finish Patch* to install the patch file so that other users can load it. This compiles the patch file if you have not done so yourself (patches are always compiled). It also asks you for a comment describing the reason for the patch; 2load-patches* and 2print-system-modifications* print these comments. If the patch is complex or it has a good chance of causing new problems, you should not use 2Meta-X Finish Patch*; instead, you should make an unreleased patch. A finished patch can be 1released* or 1unreleased*. If a patch is unreleased, it can be loaded in the usual manner if the user says `yes' to a special query, but once it has been loaded the user will be strongly discouraged from saving a band. Therefore, you still have a chance to edit the patch file and recompile it if there is something wrong with it. You can be sure that the old broken patch will not remain permanently in saved bands. To finish a patch without releasing it, use the command 2Meta-X Finish Patch Unreleased*. Then the patch can be tested by loading it. After a sufficient period for testing, you can release the patch with 2Meta-X Release Patch*. If you discover a bug in the patch after this point, it is not sufficient to correct it in this patch file; you must put the fix in a new patch to correct any bands already saved with the broken version of this patch. It is a good principle not to add any new features or fix any additional bugs in a patch once that patch is released; change it only to correct problems with that patch. New fixes to other bugs should go in new patches. You can only be constructing one patch at any time. 2Meta-X Add Patch* automatically adds to the patch you are constructing. But you can start constructing a different patch without finishing the first. If you use the command 2Meta-X Start Patch* while constructing a patch, you are given the option of starting a new patch. The old patch ceases to be the one you are constructing but the patch file remains in its editor buffer. Later, or in another session, you can go back to constructing the first patch with the command 2Meta-X Resume Patch*. This commands asks for both a patchable system name and the patch version to resume constructing. You can simply save the editor buffer of a patch file and resume constructing that patch in a later session. You can even resume constructing a finished patch; though it rarely makes sense to do this unless the patch is unreleased. If you start to make a patch and change your mind, use the command 2Meta-X Cancel Patch*. This deletes the record that says that this patch is being worked on. It also tells the editor that you are no longer constructing any patch. You can undo a finished (but unreleased) patch by using 2Resume Patch* and then 2Cancel Patch*. If a patch is released, you cannot remove it from saved bands, so it is not reasonable to cancel it at that stage. =Node: 4Private Patches* =Text: 3PRIVATE PATCHES* A private patch is a file of changes which is not installed to be loaded automatically in sequence by all users. It is loaded only by explicit request (using the function 2load*). A private patch is not associated with any particular patchable system, and has no version number. To make a private patch, use the editor command 2Meta-X Start Private Patch*. Instead of a patchable system name, you must specify a filename to use for the patch file; since the patch is not to be installed, there is no standard naming convention for it to follow. Add text to the patch using 2Meta-X Add Patch* and finish it using 2Meta-X Finish Patch*. There is no concept of release for private patches so there is no point in using 2Meta-X Finish Patch Unreleased*. There is also no data base recording all private patches, so 2Meta-X Start Private Patch* will resume an existing patch, or even a finished patch. In fact, finishing a private patch is merely a way to write a comment into it and compile it. Once the private patch file is made, you can load it like any other file. The private patch facility is just an easy way to copy code from various files into one new file with 2Patch-File: T* in its attribute list (to prevent warnings about redefining functions defined in other files) and compile that file. =Node: 4System Status* =Text: 3SYSTEM STATUS* The patch system has the concept of the 1status* of a major version of a system. A status keyword is recorded in the Lisp world for each patchable system that is loaded. There is also a current status for each major version of each system, recorded in the patch directory file for that major version. Loading patches updates the status in the Lisp world to match the current status stored in the patch directory. The status in the patch directory is changed with 2si:set-system-status*. The status is displayed when the system version is displayed, in places such as the system greeting message (2print-herald*) and the disk partition comment. The status is one of the following keywords: 2:experimental* The system has been built but has not yet been fully debugged and released to users. This is the default status when a new major version is created, unless it is overridden with the 2:initial-status* option to 2defsystem*. 2:released* The system is released for general use. This status produces no extra text in the system greeting and the disk partition comment. 2:obsolete* The system is no longer supported. 2:broken* This is like 2:experimental*, but is used when the system was thought incorrectly to have been debugged, and hence was 2:released* for a while. 2:inconsistent* Unreleased patches to this system have been loaded. If any patchable system is in this status, 2disk-save* demands extra confirmation, and the resulting saved band is identified as ``Bad'' in its disk partition comment. 3si:set-system-status* 1system* 1status* &optional 1major-version* Changes the current status of a system, as recorded in the patch directory file. 1system* is the name of the system. 1major-version* is the number of the major version to be changed; if unsupplied it defaults to the version currently loaded into the Lisp world. 1status* should be one of the keywords above. Do not set the current system status to 2:inconsistent*. A status of 2:inconsistent* is set up in the Lisp world when an unreleased patch is loaded, and once set that way it never changes in that Lisp world. The status recorded in the system's patch directory file should describe the situation where all currently released patches are loaded. It should never be 2:inconsistent*. =Node: 4Patch Files* =Text: 3PATCH FILES* The patch system maintains several different types of files in the directory associated with your system. This directory is specified to 2defsystem* via either the 2:patchable* option or the 2:pathname-default* option. These files are maintained automatically, but they are described here so that you can know what they are and when they are obsolete and can be deleted. If the 2:patchable* option to 2defsystem* had no argument, then the patch data files are stored on the host, device and directory specified as the system's pathname default. The names and types of the filenames are all standard and do not include the name of the system in any way. If the 2:patchable* option to 2defsystem* is given an argument, this argument is a file namestring specifying the host, device and directory to use for storing the patch data files. In addition, the system's short name is used in constructing the names of the files. This allows you to store the patch data files for several systems in the same directory. There are three kinds of files that record patch information: 3*2 the system patch directory** This file records the current major version number, so that when the system is recompiled a new number can be allocated. On Tops-20, this file has, by default, a name like 2OZ:PS:PATCH.DIRECTORY*, where the host, device, and directory (2OZ:PS:*) come from the system's 2:pathname-default* as explained above. If 2:patchable* is given an argument, this file for system 2FOO* has a name like 2OZ:PS:FOO.PATCH-DIRECTORY*, where the host, device and directory come from 2:patchable*'s argument. 3*2 the patch directory of a major version** There is a file of this kind for each major version of the system. It records the patches that have been made for that major version: the minor version, author, description and release status of each one. The data in this file are in the form of a printed representation of a Lisp list with two elements. The first is the system status of this major version (2:experimental*, 2:released*, 2:broken* or 2:obsolete*). The second is another list with an element for each patch. The element for a patch is a list of length four: the minor version, the patch description (a string) or 2nil* for an unfinished patch, the author's name (a string), and a flag that is 2t* if the patch is unreleased. On a Tops-20, for major version 259, this file has, by default, a name like 2OZ:PS:PATCH-259.DIRECTORY*. If 2:patchable* is given an argument, this file for system 2FOO* has a name like 2OZ:PS:FOO-259.PATCH-DIRECTORY*. 3*2 the individual patch** For each patch made, there is a Lisp source file and a QFASL file. On a Tops-20, for version 259.12, these files have, by default, names like 2OZ:PS:PATCH-259-12.LISP* and 2OZ:PS:PATCH-259-12.QFASL*. If 2:patchable* is given an argument, this file for system 2FOO* has a name like 2OZ:PS:FOO-259-12.PATCH-DIRECTORY*. On certain types of file systems, slightly different naming conventions are used to keep the names short enough to be legal.