{Begin SubSec Databasefns} {Title Databasefns} {Text {note The databasefns package was written by R. M. Kaplan.} {Tag Databasefns} {it Note: Databasefns is a LispUsers package that is contained on the file {lisp DATABASEFNS.DCOM}. } {index *BEGIN* databasefns package} {index databasefns package} Databasefns is a very small package whose purpose is to make the construction and maintenance of {fn MASTERSCOPE} databases an essentially automatic process. It modifies {fn MAKEFILE}, {fn LOAD}, and {fn LOADFROM} to behave in the following way: {index DATABASE Prop} A database will be maintained automatically for any file (containing functions) whose file name has the property {prop DATABASE} with value {lisp YES}. Whenever such a file is dumped via {fn MAKEFILE}, {fn MASTERSCOPE} will analyse any new or changed functions on the file, and a database for all of the functions on the file will be written on a separate file whose name is of the form {lisp {arg FILE}.DATABASE}. Whenever a file which has a {prop DATABASE} property with value {lisp YES} is loaded via {fn LOAD} or {fn LOADFROM}, then the corresponding {lisp .DATABASE} file, if any, is also loaded. The database will not be dumped or loaded if the value of the {prop DATABASE} property for the file is {lisp NO}. The {prop DATABASE} property is considered to be {lisp NO} if the file is loaded with {arg LDFLG}={lisp SYSLOAD}. If the {lisp DATABASE} property is not {lisp YES} or {lisp NO}, then {fn MAKEFILE}, {fn LOAD}, and {fn LOADFROM} will ask the user whether he wants automatic database maintenance. The user's answer will be stored on the {prop DATABASE} property so that he will not be asked again. Thus when a file is dumped for the first time, the user will be asked "Do you want a Masterscope Database for this file?". Similarly, if the user loads a file which has an associated database, the user will be asked "load database for {arg FILE}?". The above interactions may be controlled via the global variables {var SAVEDBFLG}{index SAVEDBFLG Var} and {var LOADDBFLG}{index LOADDBFLG Var}. When a file which has neither a {lisp YES} or {lisp NO} database property is being dumped, {fn MAKEFILE} will assume (and store) a {lisp YES} value if the value of {var SAVEDBLFG} is {lisp YES}, and a {lisp NO} value if {var SAVEDBFLG} is {lisp NO}. The user will be queried only if {var SAVEDBFLG} is {lisp ASK} (its initial value). Similarly, if {var LOADDBFLG} is {lisp YES}, {fn LOAD} and {fn LOADFROM} will automatically load an existing {lisp .DATABASE} file for a file which does not have a {lisp YES} or {lisp NO} value for its {prop DATABASE} property. The database will not be loaded if {var LOADDBFLG} is {lisp NO}, and the user will be interrogated as described above if {var LOADDBFLG} is {lisp ASK} (its initial value). The user can dump and restore databases explicitly via the following functions: {FnDef {FnName DUMPDB} {FnArgs FILE} {Text Dumps a database for {arg FILE} then sets the {prop DATABASE} property to {lisp YES}, so that database maintenance for {arg FILE} will subsequently be automatic. }} {FnDef {FnName LOADDB} {FnArgs FILE} {Text Loads the file {lisp {arg FILE}.DATABASE} if one exists. After the database is loaded, the {prop DATABASE} property for {arg FILE} is set to {lisp YES}, so that maintenance will thereafter be automatic. Database files include the date and full filename of the file to which they correspond. {fn LOADDB} will print out a warning message if it loads a database that does not correspond to the in-core version of the file, and ask the user if he approves. Note that {fn LOADDB} is the only approved way of loading a database: Attempting to {fn LOAD} a database file will cause an error. }} {index *END* databasefns package} }{End SubSec Databasefns} {Begin SubSec Lambdatran} {Title Lambdatran} {Text {index *BEGIN* lambdatran package} {note The lambdatran package was written by R. M. Kaplan.} {Tag Lambdatran} {it Note: Lambdatran is a LispUsers package that is contained on the file {lisp LAMBDATRAN.DCOM}. } The purpose of this package is to facilitate defining new {lisp LAMBDA} words in such a way that a variety of other system packages will respond to them appropriately. A {lisp LAMBDA} word is a word that can appear as {fn CAR} of a function definition, like {lisp LAMBDA} and {lisp NLAMBDA}. New {lisp LAMBDA} words are useful because they enable the user to define his own conventions about such things as the interpretation of arguments, and to build in certain defaults about how values are returned. For example, the DECL package ({PageRef Tag DECL}) defines {lisp DLAMBDA} as a new {lisp LAMBDA} word with unconventional arguments such as the following: {lisp (DLAMBDA ((A FLOATP) (B FIXP) (RETURNS SMALLP)) (FOO A B))} In order for such an expression to be executable and compilable, a mechanism must be provided for translating this expression to an ordinary {lisp LAMBDA} or {lisp NLAMBDA}, with the special behavior associated with the arguments built into the function body. The lambdatran package accomplishes this via an appropriate entry on {index DWIMUSERFORMS Var}{var DWIMUSERFORMS} (see {PageRef Var DWIMUSERFORMS}) that computes the translation. Besides executing and compiling, Interlisp applies a number of other operations to function definitions (e.g. breaking, advising), many of which depend on the system being able to determine certain properties of the function, such as the names of its arguments, their number, and the type of the function ({lisp EXPR}, {lisp FEXPR}, etc.). The lambdatran package also provides new definitions for the functions {fn FNTYP}, {fn ARGLST}, {fn NARGS}, and {fn ARGTYPE} which can be told how to compute properties for the user's {lisp LAMBDA}-words. A new {lisp LAMBDA}-word is defined in the following way: 1. Add the {lisp LAMBDA}-word itself (e.g. the atom {lisp DLAMBDA}) to the list {var LAMBDASPLST}.{index LAMBDASPLST Var} This suppresses attempts to correct the spelling of the {lisp LAMBDA}-word. 2. Add an entry for the {lisp LAMBDA}-word to the association-list {var LAMBDATRANFNS},{index LAMBDATRANFNS Var} which is a list of elements of the form: {lisp ({arg LAMBDA-WORD} {arg TRANFN} {arg FNTYP} {arg ARGLIST})}, where {arg LAMBDA-WORD} is the name of the {lisp LAMBDA}-word (e.g. {lisp DLAMBDA}). {arg TRANFN} is a function of one argument that will be called whenever a real definition is needed for the {lisp LAMBDA}-word definition. Its argument is the {lisp LAMBDA}-word definition, and its value should be a conventional {lisp LAMBDA} or {lisp NLAMBDA} expression which will become the translation of the {lisp LAMBDA}-word form. The free variable {var FAULTFN} is bound to the name of the function in which the {lisp LAMBDA}-word form appeared (or {lisp TYPE-IN} if the form was typed in). {arg FNTYP} determines the function-type of a definition beginning with {arg LAMBDA-WORD}. It is consulted if the definition does not already have a translation from which the function type may be deduced. If {arg FNTYP} is one of the atoms {lisp EXPR}, {lisp FEXPR}, {lisp EXPR*}, {lisp FEXPR*}, then all definitions beginning with {lisp LAMBDA}-word are assumed to have that type. Otherwise, {arg FNTYP} is a function of one argument that will be applied to the {lisp LAMBDA}-word definition. Its value should be one of the above four function types. {arg ARGLIST} determines the argument list of the definition if it has not already been translated (if it has, the {arg ARGLIST} is simply the {arg ARGLIST} of the translation). It is also a function of one argument, the {lisp LAMBDA}-word definition, and its value should be the list of arguments for the function (e.g. {lisp (A B)} in the {lisp DLAMBDA} example above). If the {lisp LAMBDA}-word definition is ill-formed and the argument list cannot be computed, the function should return {lisp T}. If an {arg ARGLIST} entry is not provided in the {var LAMBDATRANFNS} element, then the argument list defaults to the second element of the definition. As an example, the {var LAMBDATRANFNS} entry for {lisp DLAMBDA} is {lisp (DLAMBDA DECL EXPR DLAMARGLIST)}, where {lisp DECL} and {lisp DLAMARGLIST} are functions of one argument. Note: if the {lisp LAMBDA}-word definition has an argument list with argument names appearing either as literal atoms or as the first element of a list, the user should also put the property {prop INFO}{index INFO Prop} with value {lisp BINDS} on the property list of the {lisp LAMBDA}-word in order to inform {fn DWIMIFY} ({PageRef Fn DWIMIFY}) to take notice of the names of the arguments when {fn DWIMIFY}ing. {index *END* lambdatran package} }{End SubSec Lambdatran} {Begin SubSec Permstatus} {Title Permstatus} {Text {note The permstatus package was written by R. M. Kaplan.} {it Note: Permstatus is a LispUsers package that is contained on the file {lisp PERMSTATUS.COM}. } {Tag Permstatus} The function {fn PERMSTATUS}{index *PRIMARY* PERMSTATUS FN} defined in this package can be used in conjunction with {fn WHENCLOSE}{index WHENCLOSE FN} ({PageRef Fn WHENCLOSE}) to make a file "permanently" open in the sense that as much of its status as possible will be restored when a {fn SYSOUT} is resumed. This includes its access mode, file-pointer position, bytesize, and any pages mapped in by the page mapping facility ({PageRef Tag PageMapping}). The desired effect is achieved by saying {lisp (WHENCLOSE {arg FILENAME} 'STATUS 'PERMSTATUS)} after the file has been opened. Note that the permanency of files is not guaranteed in that files may be deleted or renamed, or their contents changed, despite their permanent attribute in some {fn SYSOUT}. When restarting a {fn SYSOUT}, a warning message will be printed if the file cannot be found or restored. However, {fn PERMSTATUS} will not be able to detect that the contents of a file have been modified since the {fn SYSOUT} was created. Note also that "permanent" files will still be closed by {fn CLOSEF}, and will not be immune to {fn CLOSEALL} or to closing on end-of-file errors unless the appropriate {fn WHENCLOSE} attributes for {fn CLOSEALL} and {lisp EOF} are also established. }{End SubSec Permstatus}