{Begin SubSec File Package Commands} {Title File Package Commands} {Text {Tag FilePkgComs} {Tag FileComs} {index *BEGIN* file package commands} {index *PRIMARY* filecoms} The basic mechanism for creating symbolic files is the function {fn MAKEFILE} ({PageRef Fn MAKEFILE}). For each file, the file package has a data structure known as the "filecoms", which specifies what typed descriptions are contained in the file. A filecoms is a list of file package commands, each of which specifies objects of a certain file package type which should be dumped. For example, the filecoms {lispcode ( (FNS FOO) (VARS FOO BAR BAZ) (RECORDS XYZZY) )} has a {filecom FNS}, a {filecom VARS}, and a {filecom RECORDS} file package command. This filecoms specifies that the function definition for {lisp FOO}, the variable values of {lisp FOO}, {lisp BAR}, and {lisp BAZ}, and the record declaration for {lisp XYZZY} should be dumped. By convention, the filecoms of a file {arg X} is stored as the value of the litatom {lisp {arg X}COMS}. For example, {lisp (MAKEFILE 'FOO.;27)} will use the value of {lisp FOOCOMS} as the filecoms. This variable can be directly manipulated, but the file package contains facilities which make constructing and updating filecoms easier, and in some cases automatic (See {PageRef Tag ManipulatingFileComs}). A file package command is an instruction to {fn MAKEFILE} to perform an explicit, well-defined operation, usually printing an expression. Usually there is a one-to-one correspondence between file package types and file package commands; for each file package type, there is a file package command which is used for writing objects of that type to a file, and each file package command is used to write objects of a particular type. However, in some cases, the same file package type can be dumped by several different file package commands. For example, the file package commands {filecom PROP}, {filecom IFPROP}, and {filecom PROPS} all dump out objects with the file package type {lisp PROPS}. This means if the user changes an object of file package type {lisp PROPS} via {fn EDITP}, a typed-in call to {fn PUTPROP}, or via an explicit call to {fn MARKASCHANGED}, this object can be written out with any of the above three commands. Thus, when the file package attempts to determine whether this typed object is contained on a particular file, it must look at instances of all three file package commands {filecom PROP}, {filecom IFPROP}, and {filecom PROPS}, to see if the corresponding atom and property are specified. It is also permissible for a single file package command to dump several different file package types. For example, the user can define a file package command which dumps both a function definition and its macro. Conversely, some file package comands do not dump any file package types at all, such as the {filecom E} command. For each file package command, the file package must be able to determine what typed definitions the command will cause to be printed so that the file package can determine on what file (if any) an object of a given type is contained (by searching through the filecoms). Similarly, for each file package type, the file package must be able to construct a command that will print out an object of that type. In other words, the file package must be able to map file package commands into file package types, and vice versa. Information can be provided to the file package about a particular file package command via the function {fn FILEPKGCOM} ({PageRef Fn FILEPKGCOM}), and information about a particular file package type via the function {fn FILEPKGTYPE} ({PageRef Fn FILEPKGTYPE}). In the absence of other information, the default is simply that a file package command of the form {lisp ({arg X} {arg NAME})} prints out the definition of {arg NAME} as a type {arg X}, and, conversely, if {arg NAME} is an object of type {arg X}, then {arg NAME} can be written out by a command of the form {lisp ({arg X} {arg NAME})}. If a file package function is given a command or type that is not defined, it attempts spelling correction{foot unless {var DWIMFLG} or {var NOSPELLFLG}={lisp NIL}. See {PageRef Var NOSPELLFLG}. }{comment endfootnote} using {index *PRIMARY* FILEPKGCOMSPLST Var}{var FILEPKGCOMSPLST} as a spelling list.{index spelling lists}{index spelling correction} If successful, the corrected version of the list of file package commands is written (again) on the output file.{foot since at this point, the uncorrected list of file package commands would already have been printed on the output file. When the file is loaded, this will result in {lisp {arg FILE}COMS} being reset, and may cause a message to be printed, e.g., {lisp (FOOCOMS RESET)}. The value of {lisp FOOCOMS} would then be the corrected version. }{comment endfootnote} If unsuccessful, generates an error, {lisp BAD FILE PACKAGE COMMAND}.{index BAD FILE PACKAGE COMMAND Error} File package commands can be used to save on the output file definitions of functions, values of variables, property lists of atoms, advised functions, edit macros, record declarations, etc. The interpretation of each file package command is as follows: {Note Some thought should be given to how these file commands are presented. At the moment they are presented in no particular order, except that some of the most commonly-used ones are at the beginning, and ones which are obviously related are presented together. Perhaps this section should be broken doen into several sections. On the other hand, it is good to have all of these commands in one place.} {Def {Type FileCom} {Name FNS} {Args FN{sub 1} {ellipsis} FN{sub N}} {Text Writes a {fn DEFINEQ} expression with the function definitions of {arg FN{sub 1}} {ellipsis} {arg FN{sub N}}. The user should never print a {lisp DEFINEQ} expression directly onto a file himself (by using the {filecom P} file package command, for example), because {fn MAKEFILE} generates the filemap of function definitions from the {filecom FNS} file package commands (see {PageRef Tag FileMaps}). }} {Def {Type FileCom} {Name VARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} {Text For each {arg VAR{sub i}}, writes an expression to set its top level value when the file is loaded. If {arg VAR{sub i}} is atomic, {filecom VARS} writes out an expression to set {arg VAR{sub i}} to the top-level value it had at the time the file was written. If {arg VAR{sub i}} is non-atomic, it is interpreted as {lisp ({arg VAR} {arg FORM})}, and {filecom VARS} write out an expression to set {arg VAR} to the value of {arg FORM} (evaluated when the file is loaded). {filecom VARS} prints out expressions using {fn RPAQQ} and {fn RPAQ}, which are like {fn SETQQ} and {fn SETQ} except that they also perform some special operations with respect to the file package (see {PageRef Fn RPAQ}). Note: {filecom VARS} cannot be used for putting arbitrary variable values on files. For example, if the value of a variable is an array (or many other data types), a litatom which represents the array is dumped in the file instead of the array itself. The {filecom HORRIBLEVARS} file package command ({PageRef FileCom HORRIBLEVARS}) provides a way of saving and reloading variables whose values contain re-entrant or circular list structure, user data types, arrays, or hash arrays. }} {Def {Type FileCom} {Name INITVARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} {Text {filecom INITVARS} is used for initializing variables, setting their values only when they are currently {lisp NOBIND}. A variable value defined in an {filecom INITVARS} command will not change an already established value. This means that re-loading files to get some other information will not automatically revert to the initialization values. The format of an {filecom INITVARS} command is just like {filecom VARS}. The only difference is that if {arg VAR{sub i}} is atomic, the current value is not dumped; instead {lisp NIL} is defined as the initialization value. Therefore, {lisp (INITVARS FOO (FUM 2))} is the same as {lisp (VARS (FOO NIL)(FUM 2))}, if {lisp FOO} and {lisp FUM} are both {lisp NOBIND}. {filecom INITVARS} writes out an {fn RPAQ?} expression on the file instead of {fn RPAQ} or {fn RPAQQ}. {Begin Note} Date: 13 June 1982 11:12 pm PDT (Sunday) From: JonL.PA Subject: Re: New FILEPKG command: INITVARS; also RPAQ? etc. In-reply-to: KAPLAN's message of 12 JUN 1982 1522-PDT One thing that has to be considered about this feature is how to load "patch" files so that the INITVARS vars *do* get reset; the LISPM people have some trivial little thing to override the non-reSETting nature of a CommonLisp DEFVAR when a "patch" file is loaded, and I don't remember exactly how it works, but I'm sure almost any little trick will do once the problem is faced. {End Note} }} {Def {Type FileCom} {Name ADDVARS} {Args {lisp ({arg VAR{sub 1}} . {arg LST{sub 1}})} {ellipsis} {lisp ({arg VAR{sub N}} . {arg LST{sub N}})}} {Text For each {lisp ({arg VAR{sub i}} . {arg LST{sub i}})}, writes an {fn ADDTOVAR} to add each element of {arg LST{sub i}} to the list that is the value of {arg VAR{sub i}} at the time the file is loaded. The new value of {arg VAR{sub i}} will be the union of its old value and {arg LST{sub i}}. If the value of {arg VAR{sub i}} is {lisp NOBIND}, it is first set to {lisp NIL}. For example, {lisp (ADDVARS (DIRECTORIES LISP LISPUSERS))} will add {lisp LISP} and {lisp LISPUSERS} to the value of {var DIRECTORIES}. If {arg LST{sub i}} is not specified, {arg VAR{sub i}} is initialized to {lisp NIL} if its current value is {lisp NOBIND}. In other words, {lisp (ADDVARS ({arg VAR}))} will initialize {arg VAR} to {lisp NIL} if {arg VAR} has not previously been set. {note not entirely clear --- does ADDVARS only work with top-level values? Also, what if initial value is not a list and is not NOBIND??} {Begin Note} Date: 27 FEB 1979 1948-PST From: TEITELMAN when given a null list, e.g. (ADDVARS (FOO)), and the value of the indicated variable is NOBIND, ADDVARS initialies it to NIL (same as before). however if FOO is not NOBIND, ADDVARS does nothing. (ADDVARS (FOO . lst)) works as before. {End Note} }} {Def {Type FileCom} {Name ALISTS} {Args {lisp ({arg VAR{sub 1}} {arg KEY{sub 1}} {arg KEY{sub 2}} {ellipsis})} {ellipsis} {lisp ({arg VAR{sub N}} {arg KEY{sub 3}} {arg KEY{sub 4}} {ellipsis})} } {Text {arg VAR{sub i}} is a variable whose value is an alist, such as {var EDITMACROS}, {var BAKTRACELST}, etc. For each {arg VAR{sub i}}, {filecom ALISTS} writes out expressions which will restore the values associated with the specified keys. For example, {lisp (ALISTS (BREAKMACROS BT BTV))} will dump the definition for the {breakcom BT} and {breakcom BTV} commands on {lisp BREAKMACROS}. Some alists ({var USERMACROS}, {var LISPXMACROS}, etc.) are used to implement other file package types, and they have their own file package commands. }} {Def {Type FileCom} {Name PROP} {Args PROPNAME LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Writes a {fn PUTPROPS} expression to restore the value of the {arg PROPNAME} property of each litatom {arg LITATOM{sub i}} when the file is loaded. If {arg PROPNAME} is a list, expressions will be written for each property on that list. If {arg PROPNAME} is the litatom {lisp ALL},{index ALL (in file package command PROP)} the values of all user properties (on the property list of each {arg LITATOM{sub i}}) are saved. {index SYSPROPS Var}{var SYSPROPS} is a list of properties used by system functions. Only properties {it not} on that list are dumped when the {lisp ALL} option is used. If {arg LITATOM{sub i}} does not have the property {arg PROPNAME} (as opposed to having the property with value {lisp NIL}), a warning message {lisp "NO {arg PROPNAME} PROPERTY FOR {arg LITATOM{sub i}}"}{index NO PROPERTY FOR Error} is printed. The command {filecom IFPROP} can be used if it is not known whether or not an atom will have the corresponding property. }} {Def {Type FileCom} {Name IFPROP} {Args PROPNAME LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Same as the {filecom PROP} file package command, except that it only saves the properties that actually appear on the property list of the corresponding atom. For example, if {lisp FOO1} has property {lisp PROP1} and {lisp PROP2}, {lisp FOO2} has {lisp PROP3}, and {lisp FOO3} has property {lisp PROP1} and {lisp PROP3}, then {lisp (IFPROP (PROP1 PROP2 PROP3) FOO1 FOO2 FOO3)} will save only those five property values. }} {Def {Type FileCom} {Name PROPS} {Args {lisp ({arg LITATOM{sub 1}} {arg PROPNAME{sub 1}})} {ellipsis} {lisp ({arg LITATOM{sub N}} {arg PROPNAME{sub N}})} } {Text Similar to {filecom PROP} command. Writes a {fn PUTPROPS} expression to restore the value of {arg PROPNAME{sub i}} for each {arg LITATOM{sub i}} when the file is loaded. As with the {filecom PROP} command, if {arg LITATOM{sub i}} does not have the property {arg PROPNAME} (as opposed to having the property with {lisp NIL} value), a warning message {lisp "NO {arg PROPNAME{sub i}} PROPERTY FOR {arg LITATOM{sub i}}"}{index NO PROPERTY FOR Error} is printed. }} {Def {Type FileCom} {Name P} {Args EXP{sub 1} {ellipsis} EXP{sub N}} {Text Writes each of the expressions {arg EXP{sub 1}} {ellipsis} {arg EXP{sub N}} on the output file, where they will be evaluated when the file is loaded. }} {Def {Type FileCom} {Name E} {Args FORM{sub 1} {ellipsis} FORM{sub N}} {Text Each of the forms {arg FORM{sub 1}} {ellipsis} {arg FORM{sub N}} is evaluated at {it output} time, when {fn MAKEFILE} interpretes this file package command. }} {Def {Type FileCom} {Name COMS} {Args COM{sub 1} {ellipsis} COM{sub N}} {Text Each of the commands {arg COM{sub 1}} {ellipsis} {arg COM{sub N}} is interpreted as a file package command. }} {Def {Type FileCom} {Name *} {Args {lisp .} TEXT} {Text Used for inserting comments in a file. The file package command is simply written on the output file; it will be ignored when the file is loaded. If the first element of {arg TEXT} is another {lisp *}, a form-feed is printed on the file before the comment. {Begin Note} Date: 11 MAY 1981 2324-PDT From: KAPLAN We introduced a variable LAMBDAFONTLINELENGTH, to hold the linelength for comments in the lambda font. This variable is set in the fontdefs. (This is temporary, since we are heading towards a variable- pitched font world. A final thing about the * command: We removed the DECLARE: expressions that used to be put out around comments. It was argued that not that much structure is involved in that, and eventually recompile can be changed to simply suppress copying comment expressions. {End Note} }} {Def {Type FileCom} {Name ADVISE} {Args FN{sub 1} {ellipsis} FN{sub N}} {Text For each function {arg FN{sub i}}, writes expressions to reinstate the function to its advised state when the file is loaded. See {PageRef Tag Advising}. }} {Def {Type FileCom} {Name ADVICE} {Args FN{sub 1} {ellipsis} FN{sub N}} {Text For each function {arg FN{sub i}}, writes a {fn PUTPROPS} expression which will put the advice back on the property list of the function. The user can then use {index READVISE FN}{fn READVISE} to reactivate the advice. }} {note "Advice saved on a file will go out with ADVISE rather than ADVICE" ??} {Def {Type FileCom} {Name USERMACROS} {Args LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Each litatom {arg LITATOM{sub i}} is the name of a user edit macro. Writes expressions to add the edit macro definitions of {arg LITATOM{sub i}} to {index USERMACROS Var}{var USERMACROS}, and adds the names of the commands to the appropriate spelling lists. If {arg LITATOM{sub i}} is not a user macro, a warning message {lisp "no EDIT MACRO for {arg LITATOM{sub i}}"}{index NO USERMACRO FOR Error} is printed. {Begin Note} Date: 16 Oct 1978 1:42 pm (Monday) From: Masinter (undocumented feature) The USERMACROS file package command will now also dump entries on EDITMACROS as well (so that system files can contain EDITMACROS entries). {End Note} }} {Def {Type FileCom} {Name FILEPKGCOMS} {Args LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Each litatom {arg LITATOM{sub i}} is either the name of a user-defined file package command or a user-defined file package type (or both). Writes expressions which will restore each command/type. If {arg LITATOM{sub i}} is not a file package command or type, a warning message {lisp "no FILE PACKAGE COMMAND for {arg LITATOM{sub i}}"}{index NO FILE PACKAGE COMMAND FOR Error} is printed. {note can this be used to save additions to system filepkgcoms/types??} }} {Def {Type FileCom} {Name LISPXMACROS} {Args LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Each {arg LITATOM{sub i}} is defined on {var LISPXMACROS} or {var LISPXHISTORYMACROS} (see {PageRef Var LISPXMACROS}). Writes expressions which will save and restore the definition for each macro, as well as making the necessary additions to {var LISPXCOMS}{index LISPXCOMS Var} }} {Def {Type FileCom} {Name RECORDS} {Args REC{sub 1} {ellipsis} REC{sub N}} {Text Each {arg REC{sub i}} is the name of a record (see {PageRef Tag RecordPackage}). Writes expressions which will redeclare the records when the file is loaded. }} {Def {Type FileCom} {Name INITRECORDS} {Args REC{sub 1} {ellipsis} REC{sub N}} {Text Similar to {filecom RECORDS}, {filecom INITRECORDS} writes expressions on a file that will, when loaded, perform whatever initialization/allocation is necessary for the indicated records. However, the record declarations themselves are not written out. This facility is useful for building systems on top of Interlisp, in which the implementor may want to eliminate the record declarations from a production version of the system, but the allocation for these records must still be done. }} {Def {Type FileCom} {Name I.S.OPRS} {Args OPR{sub 1} {ellipsis} OPR{sub N}} {Text Each {arg OPR{sub i}} is the name of a user-defined i.s.opr (see {PageRef Fn I.S.OPR}). Writes expressions which will redefine the i.s.oprs when the file is loaded. }} {Def {Type FileCom} {Name TEMPLATES} {Args LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Each {arg LITATOM{sub i}} is a litatom which has a Masterscope template (see {PageRef Fn GETTEMPLATE}). Writes expressions which will restore the templates when the file is loaded. }} {Def {Type FileCom} {Name BLOCKS} {Args BLOCK{sub 1} {ellipsis} BLOCK{sub N}} {Text For each {arg BLOCK{sub i}}, writes a {index DECLARE: expression}{lisp DECLARE:} expression which the block compile functions interpret as a block declaration.{index block declarations} See {PageRef Tag BlockDeclarations}. }} {Def {Type FileCom} {Name MACROS} {Args LITATOM{sub 1} {ellipsis} LITATOM{sub N}} {Text Each {arg LITATOM{sub i}} is a litatom with a {lisp MACRO} definition (and/or a {lisp DMACRO}, {lisp 10MACRO}, etc.). Writes out an expression to restore all of the macro properties for each {arg LITATOM{sub i}}, embedded in a {lisp DECLARE: EVAL@COMPILE} so the macros will be defined when the file is compiled. See {PageRef Tag Macros}. }} {Def {Type FileCom} {Name SPECVARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} } {Def {Type FileCom} {Name LOCALVARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} } {Def {Type FileCom} {Name GLOBALVARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} {Text Outputs the corresponding compiler declaration embedded in a {lisp DECLARE: DOEVAL@COMPILE DONTCOPY}. See {PageRef Tag GlobalVars}. }} {Def {Type FileCom} {Name UGLYVARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} {Text Like {filecom VARS}, except that the value of each {arg VAR{sub i}} may contain structures for which {fn READ} is not an inverse of {fn PRINT}, e.g. arrays, readtables, user data types, etc. Uses {fn HPRINT} ({PageRef Fn HPRINT}). }} {Def {Type FileCom} {Name HORRIBLEVARS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} {Text Like {filecom UGLYVARS}, except structures may also contain circular pointers. Uses {fn HPRINT} ({PageRef Fn HPRINT}). The values of {arg VAR{sub 1}} {ellipsis} {arg VAR{sub N}} are printed in the same operation, so that they may contain pointers to common substructures. {filecom UGLYVARS} does not do any checking for circularities, which results in a large speed and internal-storage advantage over {filecom HORRIBLEVARS}. Thus, if it is known that the data structures do {it not} contain circular pointers, {filecom UGLYVARS} should be used instead of {filecom HORRIBLEVARS}. }} {Def {Type FileCom} {Name DECLARE:} {Args {lisp .} FILEPKGCOMS/FLAGS} {Text Normally expressions written onto a symbolic file are (1) evaluated when loaded; (2) copied to the compiled file when the symbolic file is compiled (see {PageRef Tag Compiler}); and (3) not evaluated at compile time. {filecom DECLARE:} allows the user to override these defaults. {arg FILEPKGCOMS/FLAGS} is a list of file package commands, possibly interspersed with "tags". The output of those file package commands within {arg FILEPKGCOMS/FLAGS} is embedded in a {fn DECLARE:}{index DECLARE: expression} expression, along with any tags that are specified. For example, {lisp (DECLARE: EVAL@COMPILE DONTCOPY (FNS {ellipsis}) (PROP {ellipsis}))} would produce {lisp (DECLARE: EVAL@COMPILE DONTCOPY (DEFINEQ {ellipsis}) (PUTPROPS {ellipsis}))}. {fn DECLARE:}{index DECLARE: Fn} is {it defined} as an nlambda nospread function, which processes its arguments by evaluating or not evaluating each expression depending on the setting of internal state variables. The initial setting is to evaluate, but this can be overridden by specifying the {lisp DONTEVAL@LOAD} tag. {fn DECLARE:} expressions are specially processed by the compiler. For the purposes of compilation, {fn DECLARE:} has two principal applications: (1) to specify forms that are to be evaluated at compile time, presumably to affect the compilation, e.g., to set up macros; and/or (2) to indicate which expressions appearing in the symbolic file are {it not} to be copied to the output file. (Normally, expressions are {it not} evaluated and {it are} copied.) Each expression in {fn CDR} of a {lisp DECLARE:} form is either evaluated/not-evaluated and copied/not-copied depending on the settings of two internal state variables, initially set for copy and not-evaluate. These state variables can be reset for the remainder of the expressions in the {lisp DECLARE:} by means of the tags {lisp DONTCOPY}, {lisp EVAL@COMPILE}, etc. The tags are: {Begin LabeledList DECLARE: tags} {Name {lisp EVAL@LOAD}{index *PRIMARY* EVAL@LOAD (DECLARE: Option)}} {Name {lisp DOEVAL@LOAD}{index *PRIMARY* DOEVAL@LOAD (DECLARE: Option)}} {Text Evaluate the following forms when the file is loaded (unless overridden by {lisp DONTEVAL@LOAD}). } {Name {lisp DONTEVAL@LOAD}{index *PRIMARY* DONTEVAL@LOAD (DECLARE: Option)}} {Text Do not evaluate the following forms when the file is loaded. } {Name {lisp EVAL@LOADWHEN}{index *PRIMARY* EVAL@LOADWHEN (DECLARE: Option)}} {Text This tag can be used to provide conditional evaluation. The value of the expression immediately following the tag determines whether or not to evaluate subsequent expressions when loading. {lisp {ellipsis} EVAL@LOADWHEN T {ellipsis}} is equivalent to {lisp {ellipsis} EVAL@LOAD {ellipsis}} } {Name {lisp COPY}{index *PRIMARY* COPY (DECLARE: Option)}} {Name {lisp DOCOPY}{index *PRIMARY* DOCOPY (DECLARE: Option)}} {Text When compiling, copy the following forms into the compiled file. } {Name {lisp DONTCOPY}{index *PRIMARY* DONTCOPY (DECLARE: Option)}} {Text When compiling, do not copy the following forms into the compiled file. } {Name {lisp COPYWHEN}{index *PRIMARY* COPYWHEN (DECLARE: Option)}} {Text When compiling, if the next form evaluates to non-{lisp NIL}, copy the following forms into the compiled file. } {Name {lisp EVAL@COMPILE}{index *PRIMARY* EVAL@COMPILE (DECLARE: Option)}} {Name {lisp DOEVAL@COMPILE}{index *PRIMARY* DOEVAL@COMPILE (DECLARE: Option)}} {Text When compiling, evaluate the following forms. } {Name {lisp DONTEVAL@COMPILE}{index *PRIMARY* DONTEVAL@COMPILE (DECLARE: Option)}} {Text When compiling, do not evaluate the following forms. } {Name {lisp EVAL@COMPILEWHEN}{index *PRIMARY* EVAL@COMPILEWHEN (DECLARE: Option)}} {Text When compiling, if the next form evaluates to non-{lisp NIL}, evaluate the following forms. } {Name {lisp FIRST}{index *PRIMARY* FIRST (DECLARE: Option)}} {Text For expressions that are to be copied to the compiled file, the tag {lisp FIRST} can be used to specify that the following expressions in the {lisp DECLARE:} are to appear at the front of the compiled file, before anything else except the {lisp FILECREATED} expressions (see {PageRef Fn FILECREATED}). For example, {lisp (DECLARE: COPY FIRST (P (PRINT {arg MESS1} T)) NOTFIRST (P (PRINT {arg MESS2} T)))} will cause {lisp (PRINT {arg MESS1} T)} to appear first in the compiled file, followed by any functions, then {lisp (PRINT {arg MESS2} T)}. } {Name {lisp NOTFIRST}{index *PRIMARY* NOTFIRST (DECLARE: Option)}} {Text Reverses the effect of {lisp FIRST}. } {End LabeledList DECLARE: tags} The value of {var DECLARETAGSLST}{index DECLARETAGSLST Var} is a list of all the tags used in {lisp DECLARE:} expressions. If a tag not on this list appears in a {filecom DECLARE:} file package command, performs spelling correction using {var DECLARETAGSLST} as a spelling list.{index spelling lists}{index spelling correction} Note that the function {fn LOADCOMP} ({PageRef Fn LOADCOMP}) provides a convenient way of obtaining information from the {lisp DECLARE:} expressions in a file, without reading in the entire file. This information may be used for compiling other files. }} {Def {Type FileCom} {Name EXPORT} {Args COM{sub 1} {ellipsis} COM{sub N}} {Text This command is used for "exporting" definitions. Like {filecom COM}, each of the commands {arg COM{sub 1}} {ellipsis} {arg COM{sub N}} is interpreted as a file package command. The commands are also flagged in the file as being "exported" commands, for use with {fn GATHEREXPORTS} (see {PageRef Fn GATHEREXPORTS}). }} {Def {Type FileCom} {Name CONSTANTS} {Args VAR{sub 1} {ellipsis} VAR{sub N}} {Text Like {filecom VARS}, for each {arg VAR{sub i}} writes an expression to set its top level value when the file is loaded. Also writes a {fn CONSTANTS} expression to declare these variables as constants (see {PageRef Fn CONSTANTS}). Both of these expressions are wrapped in a {lisp (DECLARE: EVAL@COMPILE {ellipsis})} expression, so they can be used by the compiler. Like {filecom VARS}, {arg VAR{sub i}} can be non-atomic, in which case it is interpreted as {lisp ({arg VAR} {arg FORM})}, and passed to {fn CONSTANTS} (along with the variable being initialized to {arg FORM}). {Begin Note} Date: 12 MAR 1981 2000-PST From: MASINTER.PA Subject: new CONSTANTS ... The CONSTANTS file package command (CONSTANTS var1 var2 (var3 form) var4) is equivalent to (DECLARE: EVAL@COMPILE (VARS var1 var2 (var3 form) var4) (P (CONSTANTS var1 var2 (var3 form) var4))) Note that CONSTANTS are no longer DONTCOPY as the default. {End Note} }} {Def {Type FileCom} {Name ORIGINAL} {Args COM{sub 1} {ellipsis} COM{sub N}} {Text Each of the commands {arg COM{sub i}} will be interpreted as a file package command without regard to any file package macros (as defined by the {lisp MACRO} property of the {fn FILEPKGCOM} function, {PageRef Fn FILEPKGCOM}). Useful for redefining a built-in file package command in terms of itself. Note that some of the "built-in" file package commands are defined by file package macros, so interpreting them (or new user-defined file package commands) with {filecom ORIGINAL} will fail. {filecom ORIGINAL} was never intended to be used outside of a file package command macro. {Begin Note} Date: 3 JAN 1983 2252-PST From: MASINTER at PARC-MAXC Subject: (ORIGINAL (VARS --)). What the manual is not explicit about is that ORIGINAL is only intended to occur inside otherwise recursive MACROS as a way of breaking the recursion and 'modifying' rather than 'overriding' the built-in commands. As such, you have to know which built-in, documented commands are in fact implemented as MACROS. In any case, it was never intended for ORIGINAL to be used OUTSIDE of a file package command macro. {End Note} }} {Def {Type FileCom} {Name FILES} {Args {lisp .} FILES/LISTS} {Text Used to specify auxiliary files to be loaded in when the file is loaded. {arg FILES/LISTS} is a list of files, possibly interspersed with lists, which may be used to specify certain loading options. Within these lists, the following tokens are recognized: The elements of the {filecom FILES} command are the (namefield) of the files to load. There are actually several other ways to load in files; the {filecom FILES} command interprets {fn LISTP} elements of the commands as a series of tokens which change its state. Those tokens can be: {Begin LabeledList FILES tokens} {Name {lisp FROM {arg DIRECTORY}}} {Text Pack the given directory onto the beginning of the file. For example, {lisp (FILES (FROM LISPUSERS) CJSYS)}. If this is not specified, the default is to use the same directory as the file containing the {filecom FILES} command. } {Name {lisp SOURCE}} {Text Load the source version of the file rather than the compiled version. } {Name {lisp COMPILED}} {Text Load the compiled version of the file (the default). } {Name {lisp LOAD}} {Text Load the file with by calling {fn LOAD?} (the default). } {Name {lisp LOADCOMP}} {Text Load the file with {fn LOADCOMP?} rather than {fn LOAD?}. Automatically implies {lisp SOURCE}. } {Name {lisp LOADFROM}} {Text Load the file with {fn LOADFROM} rather than {fn LOAD?}. } {Name {lisp SYSLOAD}} {Text Load the file with {arg LDFLG}={lisp SYSOUT}. This is mainly used when loading system files. } {Name {lisp PROP}} {Text Load the file with {arg LDFLG}={lisp PROP}, so function definitions loaded will be stored on property lists. } {Name {lisp ALLPROP}} {Text Load the file with {arg LDFLG}={lisp ALLPROP}, so both function definitions and variable values loaded will be stored on property lists. } {End LabeledList FILES tokens} These tokens can be joined together in a single list. For example, an actual command in the FTP package is: {lispcode (FILES (LOADCOMP) NET (SYSLOAD FROM LISPUSERS) CJSYS)} }} {Begin Note} Date: 23 JUL 1979 2327-PDT From: KAPLAN 1. I added a feature to the FILES command originally requested by Yonke so that he could more easily specify where lispusers files were to come from. The keyword FROM can be followed by the keyword VALUEOF, in which case a FINDFILE exprssion gets put out instead of a simple quote. E.g. (FILES (SYSLOAD FROM VALUEOF LISPUSERSDIRECTORIES) HASH) yields the expression (LOAD? (FINDFILE (QUOTE HASH.COM) T LISPUSERSDIRECTORIES) (QUOTE SYSLOAD)) I think this does what Yoke wanted. The only glitch is in the case the file isn't found anywhere, the error message gives NIL not fond instead of HASH.COM not found (cause the FINDFILE returns NIL). I guess I could put out a more coplicted prog and test the value, but this will do for now. Date: 18 JUL 1980 1202-PDT From: KAPLAN I changed the way the FILES command works so that it puts out an expression that interprets the arguments at load-time instead of dump-time. In particular, this means that the load-time compile.ext will be used, so that the appropriate choice between COM and DBYTE will be made. The format of the command is checked at dump-time, by the function MAKEFILESCOMS, to make sure that there is no striking error. The expression put out on the file is of the form (FILESLOAD . arguments to the FILES command), where FILESLOAD is a new function that interprets the command. Date: 13 FEB 83 02:33 PST From: JONL.PA Subject: FILESLOAD FILESLOAD isn't documented in either the Blue manual or the User's Guide; did it make it into the new manual? I've also fixed a couple of minor glitches and lacunae in FILESLOAD and MAKEFILESCOMS -- (1) made the check in MAKEFILECOMS for "bad options" consistent with the actual options used in FILESLOAD (2) added an extra localvar to FILESLOAD so that it can distinguish between defaulting to .DCOM, and having been forced by user request; in the latter case, you don't want the search for sources which would occur should the .DCOM not be found [actually, this isn't .DCOM, but the value of COMPILE.EXT] (3) added a NOERROR option so that FILES and FILESLOAD may be used in a "soft" mode, as well as in a "required files" mode. E.g. (FILES (SYSLOAD COMPILED FROM LISPUSERS NOERROR) HISTMENU) will cause HISTMENU to be sysLOADed, if it exists on LISPUSERSDIRECTORIES, but do nothing if it isn't found. (4) added another kludge to the case of "FROM" (FILES (SYSLOAD COMPILED FROM VALUE OF LISPUSERSDIRECTORIES) ...) will act as if "VALUE OF" were typed in as "VALUEOF". Before you question this kludgery, you ought to consider why (FILES (FROM LISPUSERS) MUMBLE) gets MUMBLE from <LISPUSERS>NEW>, whereas (FILES (FROM <LISPUSERS>) MUMBLE) gets it from <LISPUSERS>. Whoever invented this crock ought to be . . . {End Note} {Begin Note} Date: 25 MAR 83 00:01 PST From: KAPLAN.PA Subject: FILEPKG - FILES glitches fixed I tried to fix (or at least improve) the various glitches with FILES that have been reported with increasing frequency recently: 1. I changed HASDEF so that only names actually on FILELST are thought of as FILES. 2. Ditto for GETDEF. 3. I changed INFILECOMS? so that nothing of type FILES belongs to anything. 4. I changed MARKASCHANGED so that if asked to mark something of type FILES as changed, it marks (FILECOMS something) as a VAR instead. (Although the symptom that Beau reported (as I remember) might in fact be a consequence of a more general problem in EDITDEF/PUTDEF.) General comment: It appears to me that the FILES command is a mistake, and that we should gradually de-commit from it. (FILES . xxx) is exactly equivalent to (P (FILESLOAD . xxx)). It hardly seems worth all the cruft and confusion to avoid a simple P. Do you agree ? (By de-commit, I mean don't bother to document it in the manual, and gradually remove it from files before it gets too widespread). {End Note} {note DOC?? other file package commands from FILEPKGCOMSPLST: CURSORS BITMAPS GLOBALRESOURCES SYSRECORDS FILEVARS DEFS APPENDVARS} {note synonyms from FILEPKGCOMSPLST: (PRETTYDEFMACROS . FILEPKGCOMS) (FILEPKGTYPES . FILEPKGCOMS)} {Begin SubSec Exporting Definitions} {Title Exporting Definitions} {Text When building a large system in Interlisp, it is often the case that there are record definitions, macros and the like that are needed by several different system files when running, analyzing and compiling the source code of the system, but which are not needed for running the compiled code. By using the {FileCom DECLARE:} file package command with tag {lisp DONTCOPY} ({PageRef FileCom DECLARE:}), these definitions can be kept out of the compiled files, and hence out of the system constructed by loading the compiled files files into Interlisp. This saves loading time, space in the resulting system, and whatever other overhead might be incurred by keeping those definitions around, e.g., burden on the record package to consider more possibilities in translating record accesses, or conflicts between system record fields and user record fields. However, if the implementor wants to debug or compile code in the resulting system, the definitions are needed. And even if the definitions {it had} been copied to the compiled files, a similar problem arises if one wants to work on system code in a regular Interlisp environment where none of the system files had been loaded. One could mandate that any definition needed by more than one file in the system should reside on a distinguished file of definitions, to be loaded into any environment where the system files are worked on. Unfortunately, this would keep the definitions away from where they logically belong. The {lisp EXPORT} mechanism is designed to solve this problem. To use the mechanism, the implementor identifies any definitions needed by files other than the one in which the definitions reside, and wraps the corresponding file package commands in the {FileCom EXPORT} file package command ({PageRef FileCom EXPORT}). Thereafter, {fn GATHEREXPORTS} can be used to make a single file containing all the exports. {FnDef {Name GATHEREXPORTS} {Args FROMFILES TOFILE FLG} {Text {Arg FROMFILES} is a list of files containing {FileCom EXPORT} commands. {fn GATHEREXPORTS} extracts all the exported commands from those files and produces a loadable file {arg TOFILE} containing them. If {arg FLG} = {lisp EVAL}, the expressions are evaluated as they are gathered; i.e., the exports are effectively loaded into the current environment as well as being written to {arg TOFILE}. }} {FnDef {Name IMPORTFILE} {Args FILE RETURNFLG} {Text If {arg RETURNFLG} is {lisp NIL}, this loads any exported definitions from {arg FILE} into the current environment. If {arg RETURNFLG} is {lisp T}, this returns a list of the exported definitions (evaluable expressions) without actually evaluating them. }} {FnDef {Name CHECKIMPORTS} {Args FILES NOASKFLG} {Text Checks each of the files in {arg FILES} to see if any exists in a version newer than the one from which the exports in memory were taken ({fn GATHEREXPORTS} and {fn IMPORTFILE} note the creation dates of the files involved), or if any file in the list has not had its exports loaded at all. If there are any such files, the user is asked for permission to {fn IMPORTFILE} each such file. If {arg NOASKFLG} is non-{lisp NIL}, {fn IMPORTFILE} is performed without asking. }} For example, suppose file {lisp FOO} contains records {lisp R1}, {lisp R2}, and {lisp R3}, macros {lisp BAR} and {lisp BAZ}, and constants {lisp CON1} and {lisp CON2}. If the definitions of {lisp R1}, {lisp R2}, {lisp BAR}, and {lisp BAZ} are needed by files other than {lisp FOO}, then the file commands for {lisp FOO} might contain the command {lispCode (DECLARE: EVAL@COMPILE DONTCOPY (EXPORT (RECORDS R1 R2) (MACROS BAR BAZ)) (RECORDS R3) (CONSTANTS BAZ))} None of the commands inside this {FileCom DECLARE:} would appear on {lisp FOO}'s compiled file, but {lisp (GATHEREXPORTS '(FOO) 'MYEXPORTS)} would copy the record definitions for {lisp R1} and {lisp R2} and the macro definitions for {lisp BAR} and {lisp BAZ} to the file {lisp MYEXPORTS}. }{End SubSec Exporting Definitions} {Begin SubSec FileVars} {Title FileVars} {Text {Tag FileVars} {index *PRIMARY* filevars} In each of the file package commands described above, if the litatom {atom *}{index * (in file package command)} follows the command type,{foot Except for the {filecom PROP}{index PROP FileCom} and {filecom IFPROP}{index IFPROP FileCom} commands, in which case the {lisp *} follows the property name, e.g., {lisp (PROP MACRO * FOOMACROS)}. }{comment endfootnote} the form following the {atom *}, i.e., {fn CADDR} of the command, is evaluated and its value used in executing the command, e.g., {lisp (FNS * (APPEND FNS1 FNS2))}. When this form is a litatom, e.g. {lisp (FNS * FOOFNS)}, we say that the variable is a "filevar". Note that {lisp (COMS * {arg FORM})} provides a way of {it computing} what should be done by {fn MAKEFILE}. Example: {lispcode ← (SETQ FOOFNS '(FOO1 FOO2 FOO3)) (FOO1 FOO2 FOO3) ← (SETQ FOOCOMS '( (FNS * FOOFNS) (VARS FIE) (PROP MACRO FOO1 FOO2) (P (MOVD 'FOO1 'FIE1))] ← (MAKEFILE 'FOO)} would create a file {lisp FOO} containing: {lispcode (FILECREATED "{it time and date the file was made}" . "{it other information}") (PRETTYCOMPRINT FOOCOMS) (RPAQQ FOOCOMS ((FNS * FOOFNS) {ellipsis}) (RPAQQ FOOFNS (FOO1 FOO3 FOO3)) (DEFINEQ "{it definitions of {lisp FOO1}, {lisp FOO2}, and {lisp FOO3}}") (RPAQQ FIE "{it value of {lisp FIE}}") (PUTPROPS FOO1 MACRO {arg PROPVALUE}) (PUTPROPS FOO2 MACRO {arg PROPVALUE}) (MOVD (QUOTE FOO1) (QUOTE FIE1)) STOP} }{End SubSec FileVars} {Begin SubSec Defining New File Package Commands} {Title Defining New File Package Commands} {Text {index *BEGIN* defining file package commands} A file package command is defined by specifying the values of certain properties. The user can specify the various attributes of a file package command for a new command, or respecify them for an existing command. The following properties are used: {Begin LabeledList FILEPKGCOM PROP is one of} {Label {lisp MACRO}} {Text Defines how to dump the file package command. Used by {fn MAKEFILE}. Value is a pair {lisp ({arg ARGS} . {arg COMS})}. The "arguments" to the file package command are substituted for {arg ARGS} throughout {arg COMS}, and the result treated as a list of file package commands. For example, following {lisp (FILEPKGCOM 'FOO 'MACRO '((X Y) . {arg COMS}))}, the file package command {lisp (FOO A B)} will cause {lisp A} to be substituted for {lisp X} and {lisp B} for {lisp Y} throughout {arg COMS}, and then {arg COMS} treated as a list of commands. The substitution is carried out by {fn SUBPAIR} ({PageRef Fn SUBPAIR}), so that the "argument list" for the macro can also be atomic. For example, if {lisp (X . {arg COMS})} was used instead of {lisp ((X Y) . {arg COMS})}, then the command {lisp (FOO A B)} would cause {lisp (A B)} to be substituted for {lisp X} throughout {arg COMS}. Note: Filevars are evaluated {it before} substitution. For example, if the litatom {atom *} follows {arg NAME} in the command, {fn CADDR} of the command is evaluated substituting in {arg COMS}. } {Label {lisp ADD}} {Text Specifies how (if possible) to add an instance of an object of a particular type to a given file package command. Used by {fn ADDTOFILE}. Value is {arg FN}, a function of three arguments, {arg COM}, a file package command {fn CAR} of which is {fn EQ} to {arg COMMANDNAME}, {arg NAME}, a typed object, and {arg TYPE}, its type. {arg FN} should return {lisp T} if it (undoably) adds {arg NAME} to {arg COM}, {lisp NIL} if not. If no {lisp ADD} property is specified, then the default is (1) if {lisp (CAR {arg COM})}={arg TYPE} and {lisp (CADR {arg COM})}={lisp *}, and {lisp (CADDR {arg COM})} is a filevar (i.e. a literal atom), add {arg NAME} to the value of the filevar, or (2) if {lisp (CAR {arg COM})}={arg TYPE} and {lisp (CADR {arg COM})} is not {lisp *}, add {arg NAME} to {lisp (CDR {arg COM})}. Actually, the function is given a fourth argument, {arg NEAR}, which if non-{lisp NIL}, means the function should try to add the item after {arg NEAR}. See discussion of {fn ADDTOFILES?}, {PageRef Fn ADDTOFILES?}. } {Label {lisp DELETE}} {Text Specifies how (if possible) to delete an instance of an object of a particular type from a given file package command. Used by {fn DELFROMFILES}. Value is {arg FN}, a function of three arguments, {arg COM}, {arg NAME}, and {arg TYPE}, same as for {lisp ADD}. {arg FN} should return {lisp T} if it (undoably) deletes {arg NAME} from {arg COM}, {lisp NIL} if not. If no {lisp DELETE} property is specified, then the default is (1) {lisp (CAR {arg COM})}={arg TYPE} and {lisp (CADR {arg COM})}={lisp *}, and {lisp (CADDR {arg COM})} is a filevar (i.e. a literal atom), and {arg NAME} is contained in the value of the filevar, then remove {arg NAME} from the filevar, or (2) if {lisp (CAR {arg COM})}={arg TYPE} and {lisp (CADR {arg COM})} is not {lisp *}, and {arg NAME} is contained in {lisp (CDR {arg COM})}, then remove {arg NAME} from {lisp (CDR {arg COM})}. If {arg FN} returns the value of {lisp ALL}, it means that the command is now "empty", and can be deleted entirely from the command list. } {Label {lisp CONTENTS}} {Label {lisp CONTAIN}} {Text Determines whether an instance of an object of a given type is contained in a given file package command. Used by {fn WHEREIS} and {fn INFILECOMS?}. Value is {arg FN}, a function of three arguments, {arg COM}, a file package command {fn CAR} of which is {fn EQ} to {arg COMMANDNAME}, {arg NAME}, and {arg TYPE}. The interpretation of {arg NAME} is as follows: if {arg NAME} is {lisp NIL}, {arg FN} should return a list of elements of type {arg TYPE} contained in {arg COM}. If {arg NAME} is {lisp T}, {arg FN} should return {lisp T} if there are {it any} elements of type {arg TYPE} in {arg COM}. If {arg NAME} is an atom other than {lisp T} or {lisp NIL}, return {lisp T} if {arg NAME} of type {arg TYPE} is contained in {arg COM}. Finally, if {arg NAME} is a list, return a list of those elements of type {arg TYPE} contained in {arg COM} that are also contained in {arg NAME}. Note that it is sufficient for the {lisp CONTENTS} function to simply return the list of items of type {arg TYPE} in command {arg COM}, i.e. it can in fact ignore the {arg NAME} argument. The {arg NAME} argument is supplied mainly for those situations where producing the entire list of items involves significantly more computation or creates more storage than simply determining whether a particular item (or any item) of type {arg TYPE} is contained in the command. If a {lisp CONTENTS} property is specified and the corresponding function application returns {lisp NIL} and {lisp (CAR {arg COM})}={arg TYPE}, then the operation indicated by {arg NAME} is performed (1) on the value of {lisp (CADDR {arg COM})}, if {lisp (CADR {arg COM})}={lisp *}, otherwise (2) on {lisp (CDR {arg COM})}. In other words, by specifying a {lisp CONTENTS} property that returns {lisp NIL}, e.g. the function {fn NILL}, the user specifies that a file package command of name {lisp FOO} produces objects of file package type {lisp FOO} and only objects of type {lisp FOO}. If the {lisp CONTENTS} property is not provided, the command is simply expanded according to its {lisp MACRO} definition, and each command on the resulting command list is then interrogated. Note that if {arg COMMANDNAME} is a file package command that is used frequently, its expansion by the various parts of the system that need to interrogate files can result in a large number of {fn CONS}es and garbage collections. By informing the file package as to what this command actually does and does not produce via the {lisp CONTENTS} property, this expansion is avoided. For example, suppose the user has a file package command called {lisp GRAMMARS} which dumps various property lists but no functions. The file package could ignore this command when seeking information about {lisp FNS}. } {End LabeledList FILEPKGCOM PROP is one of} The function {fn FILEPKGCOM} is used to define new file package commands, or to change the attributes of existing commands. Note that it is possible to redefine the attributes of system file package commands, such as {lisp FNS} or {lisp PROPS}, and to cause unpredictable results. {FnDef {FnName FILEPKGCOM} {FnArgs COMMANDNAME PROP{SUB 1} VAL{SUB 1} {ellipsis} PROP{SUB N} VAL{SUB N}} {Type NOSPREAD} {Text Nospread function for defining new file package commands, or changing attributes of existing file package commands. {arg PROP{sub i}} is one of of the property names described above; {arg VAL{sub i}} is the value to be given that property of the file package command {arg COMMANDNAME}. Returns {arg COMMANDNAME}. {lisp (FILEPKGCOM {arg COMMANDNAME} {arg PROP})} returns the value of the property {arg PROP}, without changing it. {lisp (FILEPKGTYPE {arg COMMANDNAME}} returns an alist of all of the defined properties of {arg COMMANDNAME}, using the property names as keys. }} {index *END* defining file package commands} }{End SubSec Defining New File Package Commands} {index *END* file package commands} }{End SubSec File Package Commands}