{Begin SubSec File Package Commands} {Title File Package Commands} {Text {Tag FilePkgComs} {Tag FileComs} {index *PRIMARY* 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 using {index *PRIMARY* FILEPKGCOMSPLST Var}{var FILEPKGCOMSPLST} as a spelling list (unless {var DWIMFLG} or {var NOSPELLFLG}={lisp NIL}; see {PageRef Var NOSPELLFLG}).{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, 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. If the spelling correction is unsuccessful, the file package functions generate 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 documented in the following sections. {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} }} {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 Functions and Macros} {Title Functions and Macros} {Text {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 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 Term Advising functions}. Note: When advice is applied to a function programmatically or by hand, it is additive. That is, if a function already has some advice, further advice is added to the already-existing advice. However, when advice is applied to a function as a result of loading a file with an {lisp ADVISE} file package command, the new advice replaces any earlier advice. {lisp ADVISE} works this way to prevent problems with loading different versions of the same advice. If the user really wants to apply additive advice, a file package command such as {lisp (P (ADVISE {ellipsis}))} should be used (see {PageRef (File PAckage Command) P}). }} {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} ({PageRef Fn READVISE}) to reactivate the advice. }} {note "Advice saved on a file will go out with ADVISE rather than ADVICE" ??} {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}. }} }{End SubSec Functions and Macros} {Begin SubSec Variables} {Title Variables} {Text {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 {index ADDTOVAR Fn}{fn ADDTOVAR} ({PageRef 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. }} {Def {Type FileCom} {Name APPENDVARS} {Args {lisp ({arg VAR{sub 1}} . {arg LST{sub 1}})} {ellipsis} {lisp ({arg VAR{sub N}} . {arg LST{sub N}})}} {Text The same as {lisp ADDVARS}, except that the values are added to the end of the lists (using {index APPENDTOVAR Fn}{fn APPENDTOVAR}, {PageRef Fn APPENDTOVAR}), rather than at the beginning. }} {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 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 association list, 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 association lists ({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 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 Term Localvars}. }} {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} }} }{End SubSec Variables} {Begin SubSec Litatom Properties} {Title Litatom Properties} {Text {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 PROP file package command)} 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. }} }{End SubSec Litatom Properties} {Begin SubSec Miscellaneous File Package Commands} {Title Miscellaneous File Package Commands} {Text {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 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 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 RESOURCES} {Args RESOURCE{sub 1} {ellipsis} RESOURCE{sub N}} {Text Each {arg RESOURCES{sub i}} is the name of a resource (see {PageRef Term Resources}). Writes expressions which will redeclare the resource when the file is loaded. }} {Def {Type FileCom} {Name INITRESOURCES} {Args RESOURCE{sub 1} {ellipsis} RESOURCE{sub N}} {Text Parallel to {filecom INITRECORDS} ({PageRef FileCom INITRECORDS}), {filecom INITRESOURCES} writes expressions on a file to perform whatever initialization/allocation is necessary for the indicated resources, without writing the resource declaration itself. }} {Def {Type FileCom} {Name COURIERPROGRAMS} {Args NAME{sub 1} {ellipsis} NAME{sub N}} {Text Each {arg NAME{sub i}} is the name of a Courier program (see {PageRef Term Courier programs}). Writes expressions which will redeclare the Courier program 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 FILES} {Args FILE{sub 1} {ellipsis} FILE{sub N}} {Text Used to specify auxiliary files to be loaded in when the file is loaded. Dumps an expression calling {fn FILESLOAD} ({PageRef Fn FILESLOAD}), with {arg FILE{sub 1}} {ellipsis} {arg FILE{sub N}} as the arguments. {fn FILESLOAD} interprets {arg FILE{sub 1}} {ellipsis} {arg FILE{sub N}} as files to load, possibly interspersed with lists used to specify certain loading options. }} {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 *} {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. }} {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 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} }} }{End SubSec Miscellaneous File Package Commands} {Begin SubSec DECLARE:} {Title DECLARE:} {Text {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:} 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 {index *PRIMARY* EVAL@LOAD (DECLARE: Option)}{lisp EVAL@LOAD}} {Name {index *PRIMARY* DOEVAL@LOAD (DECLARE: Option)}{lisp DOEVAL@LOAD}} {Text Evaluate the following forms when the file is loaded (unless overridden by {lisp DONTEVAL@LOAD}). } {Name {index *PRIMARY* DONTEVAL@LOAD (DECLARE: Option)}{lisp DONTEVAL@LOAD}} {Text Do not evaluate the following forms when the file is loaded. } {Name {index *PRIMARY* EVAL@LOADWHEN (DECLARE: Option)}{lisp EVAL@LOADWHEN}} {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 {index *PRIMARY* COPY (DECLARE: Option)}{lisp COPY}} {Name {index *PRIMARY* DOCOPY (DECLARE: Option)}{lisp DOCOPY}} {Text When compiling, copy the following forms into the compiled file. } {Name {index *PRIMARY* DONTCOPY (DECLARE: Option)}{lisp DONTCOPY}} {Text When compiling, do not copy the following forms into the compiled file. Note: If the file package commands following {lisp DONTCOPY} include record declarations for datatypes, or records with initialization forms, it is necessary to include a {lisp INITRECORDS} file package command ({PageRef (File Package Command) INITRECORDS}) outside of the {lisp DONTCOPY} form so that the initialization information is copied. For example, if {lisp FOO} was defined as a datatype, {lispcode (DECLARE: DONTCOPY (RECORDS FOO)) (INITRECORDS FOO)} would copy the data type declaration for {lisp FOO}, but would not copy the whole record declaration. } {Name {index *PRIMARY* COPYWHEN (DECLARE: Option)}{lisp COPYWHEN}} {Text When compiling, if the next form evaluates to non-{lisp NIL}, copy the following forms into the compiled file. } {Name {index *PRIMARY* EVAL@COMPILE (DECLARE: Option)}{lisp EVAL@COMPILE}} {Name {index *PRIMARY* DOEVAL@COMPILE (DECLARE: Option)}{lisp DOEVAL@COMPILE}} {Text When compiling, evaluate the following forms. } {Name {index *PRIMARY* DONTEVAL@COMPILE (DECLARE: Option)}{lisp DONTEVAL@COMPILE}} {Text When compiling, do not evaluate the following forms. } {Name {index *PRIMARY* EVAL@COMPILEWHEN (DECLARE: Option)}{lisp EVAL@COMPILEWHEN}} {Text When compiling, if the next form evaluates to non-{lisp NIL}, evaluate the following forms. } {Name {index *PRIMARY* FIRST (DECLARE: Option)}{lisp FIRST}} {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 {index *PRIMARY* NOTFIRST (DECLARE: Option)}{lisp NOTFIRST}} {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, spelling correction is performed 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 BLOCKS} {Args BLOCK{sub 1} {ellipsis} BLOCK{sub N}} {Text For each {arg BLOCK{sub i}}, writes a {lisp DECLARE:} expression which the block compile functions interpret as a block declaration.{index Block declarations} See {PageRef Term Block Declarations}. }} }{End SubSec DECLARE:} {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. Thereafter, {fn GATHEREXPORTS} can be used to make a single file containing all the exports. {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}). }} {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, 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} Note: For the {filecom PROP}{index PROP FileCom} and {filecom IFPROP}{index IFPROP FileCom} commands ({PageRef FileCom PROP}), the {lisp *} follows the property name instead of the command, e.g., {lisp (PROP MACRO * FOOMACROS)}. Also, in the form {lisp (* * comment ...)}, the word {lisp comment} is not treated as a filevar. }{End SubSec FileVars} {Begin SubSec Defining New File Package Commands} {Title Defining New File Package Commands} {Text {index *PRIMARY* 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: {Def {Type (File Package Command Property)} {Name 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}. }} {Def {Type (File Package Command Property)} {Name 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?}. }} {Def {Type (File Package Command Property)} {Name 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. }} {Def {Type (File Package Command Property)} {Name CONTENTS}} {Def {Type (File Package Command Property)} {Name 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}. }} The function {fn FILEPKGCOM} is used to define new file package commands, or to change the properties 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 properties 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 (FILEPKGCOM {arg COMMANDNAME})} returns an alist of all of the defined properties of {arg COMMANDNAME}, using the property names as keys. {index *PRIMARY* Synonyms for file package commands} Note: Specifying {arg TYPE} as the litatom {lisp COM} can be used to define one file package command as a synonym of another. For example, {lisp (FILEPKGCOM 'INITVARIABLES 'COM 'INITVARS)} defines {lisp INITVARIABLES} as a synonym for the file package command {lisp INITVARS}. }} }{End SubSec Defining New File Package Commands} }{End SubSec File Package Commands} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ­¤­¤zē