;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: 4Defaults and Merging* =Text: 3DEFAULTS AND MERGING* When the user is asked to type in a pathname, it is of course unreasonable to require the user to type a complete pathname, containing all components. Instead there are defaults, so that components not specified by the user can be supplied automatically by the system. Each program that deals with pathnames typically has its own set of defaults. The system defines an object called a 1defaults alist*. Functions are provided to create one, get the default pathname out of one, merge a pathname with one, and store a pathname back into one. A defaults alist can remember more than one default pathname if defaults are being kept separately for each host; this is controlled by the variable 2fs:*defaults-are-per-host**. The main primitive for using defaults is the function 2fs:merge-pathname-defaults* (see 4(FILENAMES-2)Pathname Functions*). In place of a defaults alist, you may use just a pathname. Defaulting one pathname from another is useful for cases such as a program that has an input file and an output file, and asks the user for the name of both, letting the unsupplied components of one name default from the other. Unspecified components of the output pathname come from the input pathname, except that the type should default not to the type of the input but to the appropriate default type for output from this program. The implementation of a defaults alist is an association list of host names and default pathnames. The host name 2nil* is special and holds the defaults for all hosts, when defaults are not per-host. The 1merging* operation takes as input a pathname, a defaults alist (or another pathname), a default type, and a default version, and returns a pathname. Basically, the missing components in the pathname are filled in from the defaults alist. However, if a name is specified but the type or version is not, then the type or version is treated specially. Here are the merging rules in full detail. If no host is specified, the host is taken from the defaults. If the pathname explicitly specifies a host and does not supply a device, then the the default file device for that host is used. If the pathname specifies a device named 2DSK*, that is replaced with the 1working device* for the pathname's host, and the directory defaults to the 1working directory* for the host if it is not specified. See 2fs:set-host-working-directory*, below. Next, if the pathname does not specify a host, device, directory, or name, that component comes from the defaults. If the value of 2fs:*always-merge-type-and-version** is non-2nil*, the type and version are merged just like the other components. If 2fs:*always-merge-type-and-version** is 2nil*, as it normally is, the merging rules for the type and version are more complicated and depend on whether the pathname specifies a name. If the pathname doesn't specify a name, then the type and version, if not provided, come from the defaults, just like the other components. However, if the pathname does specify a name, then the type and version come from the 1default-type* and 1default-version* arguments to 2merge-pathname-defaults*. If those arguments were omitted, the value of 2fs:*name-specified-default-type** (initially, 2:lisp*) is used as the default type, and 2:newest* is used as the default version. The reason for this is that the type and version ``belong to'' some other filename, and are thought to be unlikely to have anything to do with the new filename you are typing in. 3fs:set-host-working-directory* 1host* 1pathname* Sets the 1working device* and 1working directory* for 1host* to those specified in 1pathname*. 1host* should be a host object or the name of a host. 1pathname* may be a string or a pathname. The working device and working directory are used for defaulting pathnames in which the device is specified as 2DSK*. The editor command 2Meta-X Set Working Directory* provides a convenient interface to this function. The following special variables are parts of the pathname interface that are relevant to defaults. 3fs:*defaults-are-per-host** 1Variable* This is a user customization option intended to be set by a user's 2LISPM INIT* file (see 4(MISCELL-2)Logging In*). The default value is 2nil*, which means that each program's set of defaults contains only one default pathname. If you type in just a host name and a colon, the other components of the name default from the previous host, with appropriate translation to the new host's pathname syntax. If 2fs:*defaults-are-per-host** is set to 2t*, each program's set of defaults maintains a separate default pathname for each host. If you type in just a host name and a colon, the last file that was referenced on that host is used. 3fs:*always-merge-type-and-version** 1Variable* If this variable is non-2nil*, then the type and version are defaulted only from the pathname defaults just like the other components. 3fs:*name-specified-default-type** 1Variable* If 2fs:*always-merge-type-and-version** is 2nil*, then when a name is specified but not a type, the type defaults from an argument to the merging function. If that argument is not specified, this variable's value is used. It may be a string or a canonical type keyword. The value is initially 2:lisp*. 3*default-pathname-defaults** 1Variable* This is the default defaults alist; if the pathname primitives that need a set of defaults are not given one, they use this one. Most programs, however, should have their own defaults rather than using these. 3cli:*default-pathname-defaults** 1Variable* The Common Lisp version of the default pathname defaults. The value of this variable is a pathname rather than an alist. This variable is magically (with a forwarding pointer) identified with a cell in the defaults-alist which the system really uses, so that setting this variable modifies the contents of the alist. 3fs:last-file-opened* 1Variable* This is the pathname of the last file that was opened. Occasionally this is useful as a default. Since some programs deal with files without notifying the user, you must not expect the user to know what the value of this symbol is. Using this symbol as a default may cause unfortunate surprises if you don't announce it first, and so such use is discouraged. These functions are used to manipulate defaults alists directly. 3fs:make-pathname-defaults* Creates a defaults alist initially containing no defaults. If you ask this empty set of defaults for its default pathname before anything has been stored into it you get the file 2FOO* on the user's home directory on the host he logged in to. 3fs:copy-pathname-defaults* 1defaults* Creates a defaults alist, initially a copy of 1defaults*. 3fs:default-pathname* &optional 1defaults* 1host* 1default-type* 1default-version* This is the primitive function for getting a default pathname out of a defaults alist. Specifying the optional arguments 1host*, 1default-type*, and 1default-version* to be non-2nil* forces those fields of the returned pathname to contain those values. If 2fs:*defaults-are-per-host** is 2nil* (its default value), this gets the one relevant default from the alist. If it is 2t*, this gets the default for 1host* if one is specified, otherwise for the host most recently used. If 1defaults* is not specified, the default defaults are used. This function also has an additional optional argument 1internal-p*, which is obsolete. 3fs:default-host* 1defaults* Returns the default host object specified by the defaults-alist 1defaults*. This is the host used by pathname defaulting with the given defaults if no host is specified. 3fs:set-default-pathname* 1pathname* &optional 1defaults* This is the primitive function for updating a set of defaults. It stores 1pathname* into 1defaults*. If 1defaults* is not specified, the default defaults are used. =Node: 4Pathname Functions* =Text: 3PATHNAME FUNCTIONS* This function obtains a pathname from an object if that is possible. 3pathname* 1object* Converts 1object* to a pathname and returns that, if possible. If 1object* is a string or symbol, it is parsed. If 1object* is a plausible stream, it is asked for its pathname with the 2:pathname* operation. If 1object* is a pathname, it is simply returned. Any other kind of 1object* causes an error. These functions are what programs use to parse and default file names that have been typed in or otherwise supplied by the user. 3parse-namestring* 1thing* &optional 1host* 1defaults* &key 1(start* 10)* 1end* 1junk-allowed* Is the Common Lisp function for parsing file names. It is equivalent to 2fs:parse-pathname* except in that it takes some keyword arguments where the other function takes all positional arguments. 3fs:parse-pathname* 1thing* &optional 1host* 1defaults* 1(start* 10)* 1end* 1junk-allowed* This turns 1thing*, which can be a pathname, a string, a symbol, or a Maclisp-style name list, into a pathname. Most functions that are advertised to take a pathname argument call 2fs:parse-pathname* on it so that they can accept anything that can be turned into a pathname. If 2thing* is itself a pathname, it is returned unchanged. If 1thing* is a string, 1start* and 1end* are interpreted as indices specifying a substring to parse. They are just like the second and third arguments to 2substring*. The rest of 1thing* is ignored. 1start* and 1end* are ignored if 1thing* is not a string. If 1junk-allowed* is non-2nil*, parsing stops without error if the syntax is invalid, and this function returns 2nil*. The second value is then the index of the invalid character. If parsing is successful, the second value is the index of the place at which parsing was supposed to stop (1end*, or the end of 1thing*). If 1junk-allowed* is 2nil*, invalid syntax signals an error. This function does 1not* do defaulting, even though it has an argument named 1defaults*; it only does parsing. The 1host* and 1defaults* arguments are there because in order to parse a string into a pathname, it is necessary to know what host it is for so that it can be parsed with the file name syntax peculiar to that host. If 1thing* does not contain a manifest host name, then if 1host* is non-2nil*, it is the host name to use, as a string. If 1thing* is a string, a manifest host name may be at the beginning or the end, and consists of the name of a host followed by a colon. If 1host* is 2nil* then the host name is obtained from the default pathname in 1defaults*. If 1defaults* is not supplied, the default defaults (2*default-pathname-defaults**) are used. Note that if 1host* is specified, and 1thing* contains a host name, an error is signaled if they are not the same host. 3fs:pathname-parse-error* (3fs:pathname-error* 3error*) 1Condition* This condition is signaled when 2fs:parse-pathname* finds a syntax error in the string it is given. 2fs:parse-pathname* sets up a nonlocal proceed type 2:new-pathname* for this condition. The proceed type expects one argument, a pathname, which is returned from 2fs:parse-pathname*. 3fs:merge-pathname-defaults* 1pathname* &optional 1defaults* 1default-type* 1default-version* Fills in unspecified components of 1pathname* from the defaults and returns a new pathname. This is the function that most programs should call to process a file name supplied by the user. 1pathname* can be a pathname, a string, a symbol, or a Maclisp namelist. The returned value is always a pathname. The merging rules are documented on 4(FILENAMES-2)Defaults and Merging*. If 1defaults* is a pathname, rather than a defaults alist, then the defaults are taken from its components. This is how you merge two pathnames. (In Maclisp that operation is called 2mergef*.) 1defaults* defaults to the value of 2*default-pathname-defaults** if unsupplied. 1default-type* defaults to the value of 2fs:*name-specified-default-type**. 1default-version* defaults to 2:newest*. 3merge-pathnames* 1pathname* &optional 1defaults* 1(default-version* 1:newest)* Is the Common Lisp function for pathname defaulting. It does only some of the things that 2fs:merge-pathname-defaults* does. It merges defaults from 1defaults* (which defaults to the value of 2*default-pathname-defaults**) into 1pathname* to get a new pathname, which is returned. 1pathname* can be a string (or symbol); then it is parsed and the result is defaulted. 1default-version* is used as the version when pathname has a name but no version. 3fs:merge-and-set-pathname-defaults* 1pathname* &optional 1defaults* 1default-type* 1default-version* This is the same as 2fs:merge-pathname-defaults* except that after it is done the defaults-list 1defaults* is modified so that the merged pathname is the new default. This is handy for programs that have sticky defaults, which means that the default for each command is the last filename used. (If 1defaults* is a pathname rather than a defaults alist, then no storing back is done.) The optional arguments default the same way as in 2fs:merge-pathname-defaults*. These functions convert a pathname into a namestring for all or some of the pathname's components. 3namestring* 1pathname* Returns a string containing the printed form of 1pathname*, as you would type it in. This uses the 2:string-for-printing* operation. 3file-namestring* 1pathname* Returns a string showing just the name, type and version of 1pathname*. This uses the 2:string-for-dired* operation. 3directory-namestring* 1pathname* Returns a string showing just the device and directory of 1pathname*. This uses the 2:string-for-directory* operation. 3enough-namestring* 1pathname* &optional 1defaults* Returns a string showing just the components of 1pathname* which would not be obtained by defaulting from 1defaults*. This is the shortest string that would suffice to specify pathname, given those defaults. It is made by using the 2:string-for-printing* operation on a modified pathname. This function yields a pathname given its components. 3make-pathname* &key 1(defaults* 3t1)** 1host* 1device* 1raw-device* 1directory* 1raw-directory* 1name* 1raw-name* 1type* 1raw-type* 1version* 1canonical-type* 1original-type* Returns a pathname whose components are as specified. If 1defaults* is a pathname or a defaults-alist, any components not explicitly specified default from it. If 1defaults* is 2t* (which is the default), then unspecified components default to 2nil*, except for the host (since every pathname must have a specific host), which defaults based on 2*default-pathname-defaults**. These functions give the components of a pathname. 3pathname-host* 1pathname* Returns the host component of 1pathname*. 3pathname-device* 1pathname* 3pathname-directory* 1pathname* 3pathname-name* 1pathname* 3pathname-type* 1pathname* 3pathname-version* 1pathname* Likewise, for the other components These functions return useful information. 3fs:user-homedir* &optional 1host* 1reset-p* 1(user* 1user-id)* 1force-p* 3user-homedir-pathname* &optional 1host* 1reset-p* 1(user* 1user-id)* 1force-p* Returns the pathname of the 1user*'s home directory on 1host*. These default to the logged in user and the host logged in to. Home directory is a somewhat system-dependent concept, but from the point of view of the Lisp Machine it is the directory where the user keeps personal files such as init files and mail. This function returns a pathname without any name, type, or version component (those components are all 2nil*). If 1reset-p* is specified non-2nil*, the machine the user is logged in to is changed to be 1host*. The synonym 2user-homedir-pathname* is from Common Lisp. 3init-file-pathname* 1program-name* &optional 1host* Returns the pathname of the logged-in user's init file for the program 1program-name*, on the 1host*, which defaults to the host the user logged in to. Programs that load init files containing user customizations call this function to find where to look for the file, so that they need not know the separate init file name conventions of each host operating system. The 1program-name* 2"LISPM"* is used by the 2login* function. These functions are useful for poking around. 3fs:describe-pathname* 1pathname* If 1pathname* is a pathname object, this describes it, showing you its properties (if any) and information about files with that name that have been loaded into the machine. If 1pathname* is a string, this describes all interned pathnames that match that string, ignoring components not specified in the string. One thing this is useful for is finding the directory of a file whose name you remember. Giving 2describe* (see 4(MISCELL-1)Poking Around in the Lisp World*) a pathname object invokes this function. 3fs:pathname-plist* 1pathname* Parses and defaults 1pathname*, then returns the list of properties of that pathname. 3fs:*pathname-hash-table** 1Variable* This is the hash table in which pathname objects are interned. You can find all pathnames ever constructed by applying the function 2maphash* to this hash table. =Node: 4Generic Pathnames* =Text: 3GENERIC PATHNAMES* A generic pathname stands for a whole family of files. The property list of a generic pathname is used to remember information about the family, some of which (such as the package) comes from the 3-*-* line (see 4(FILEACCESS-2)File Attribute Lists*) of a source file in the family. Several types of files with that name, in that directory, belong together. They are different members of the same family; for example, they may be source code and compiled code. However, there may be several other types of files that form a logically distinct group even though they have this same name; 2TEXT* and 2PRESS* for example. The exact mapping is done on a per host basis since it can sometimes be affected by host naming conventions. The generic pathname of pathname 1p* usually has the same host, device, directory, and name as 1p* does. However, it has a version of 2:unspecific*. The type of the generic pathname is obtained by sending a 2:generic-base-type* 1type-of-p* message to the host of 1p*. The default response to this message is to return the associated type from 2fs:*generic-base-type-alist** if there is one, else 1type-of-p*. Both the argument and the value are either strings, in interchange form, or canonical type symbols. However, the ITS file system presents special problems. One cannot distinguish multiple generic base types in this same way since the type component does not exist as such; it is derived from the second filename, which unfortunately is also sometimes used as a version number. Thus, on ITS, the type of a generic pathname is always 2:unspecific* if there is any association for the type of the pathname on 2fs:*generic-base-type-alist**. Since generic pathnames are primarily useful for storing properties, it is important that they be as standardized and conceptualized as possible. For this reason, generic pathnames are defined to be backtranslated, i.e. the generic pathname of a pathname that is (or could be) the result of a logical host translation has the host and directory of the logical pathname. For example, the generic pathname of 2OZ:;STREAM LISP* would be 2SYS:WINDOW;STREAM  * if 2OZ* is the system host. All version numbers of a particular pathname share the same identical generic pathname. If the values of particular properties have changed between versions, it is possible for confusion to result. One way to deal with this problem is to have the property be a list associating version number with the actual desired property. Then it is relatively easy to determine which versions have which values for the property in question and select one appropriately. But in the applications for which generic pathnames are typically used, this is not necessary. The 2:generic-pathname* operation on a pathname returns its corresponding generic pathname. See . The 2:source-pathname* operation on a pathname returns the actual or probable pathname of the corresponding source file (with 2:newest* as the version). See . 3fs:*generic-base-type-alist** 1Variable* This is an association list of the file types and the type of the generic pathname used for the group of which that file type is a part. Constructing a generic pathname replaces the file type with the association from this list, if there is one (except that ITS hosts always replace with 2:unspecific*). File types not in this list are really part of the name in some sense. The initial list is 3 ((:text . :text) ("DOC" . :text)* 3 (:press . :text) ("XGP" . :text)* 3 (:lisp . :unspecific) (:qfasl . :unspecific)* 3 (nil . :unspecific))* The association of 2:lisp* and 2:unspecific* is unfortunately made necessary by the problems of ITS mentioned previously. This way makes the generic pathnames of logically mapped 2LISP* files identical no matter whether the logical host is mapped to an ITS host or not. The first entry in the list with a particular cdr is the entry for the type that source files have. Note how the first element whose cdr is 2:unspecific* is the one for 2:lisp*. This is how the 2:source-pathname* operation knows what to do, by default. Some users may need to add to this list. The system records certain properties on generic pathnames automatically. 2:warnings* This property is used to record compilation and other warnings for the file. 2:definitions* This property records all the functions and other things defined in the file. The value has one element for each package into which the file has been loaded; the element's car is the package itself and the cdr is a list of definitions made. Each definition is a cons whose car is the symbol or function spec defined and whose cdr is the type of definition (usually one of the symbols 2defun*, 2defvar*, 2defflavor* and 2defstruct*). 2:systems* This property's value is a list of the names of all the systems (defined with 2defsystem*, see 4(SYSTEMS-1)Defining a System*) of which this is a source file. 2:file-id-package-alist* This property records what version of the file was most recently loaded. In case the file has been loaded into more than one package, as is sometimes necessary, the loaded version is remembered for each package separately. This is how 2make-system* tells whether a file needs to be reloaded. The value is a list with an element for each package that the file has been loaded into; the elements look like 3(package file-information)* 1package* is the package object itself; 1file-information* is the value returned by the 2:info* operation on a file stream, and is usually a cons whose car is the truename (a pathname) and whose cdr is the file creation date (a universal time number). Some additional properties are put on the generic pathname by reading the attribute list of the file (see 4(FILEACCESS-2)File Attribute Lists*). It is not completely clear that this is the right place to store these properties, so it may change in the future. Any property name can appear in the attributes list and get onto the generic pathname; the standard ones are described in 4(FILEACCESS-2)File Attribute Lists*.