;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: 4Manipulating Files* =Text: 3MANIPULATING FILES* This section describes functions for doing things to files aside from reading or writing their contents. 3truename* 1object* Returns the truename of the file specified somehow by 1object*. If 1object* is a plausible stream, it is asked for the truename with the 2:truename* operation. Otherwise, 1object* is converted to a pathname and that pathname is opened to get its file's truename. 3delete-file* 1file* &key 1(error-p* 3t1)** 1query?* 3deletef* 1file* &optional 1(error-p* 3t1)** 1query?* Both delete the specified file. The two functions differ in accepting keyword arguments versus positional arguments. 1file* may contain wildcard characters, in which case multiple files are deleted. If 1query?* is non-2nil*, the user is queried about each file (whether there are wildcards or not). Only the files that the user confirms are actually deleted. If 1error-p* is 2t*, then if an error occurs it is signaled as a Lisp error. If 1error-p* is 2nil* and an error occurs, the error message is returned as a condition object. Otherwise, the value is a list of elements, one for each file considered. The car of each element is the truename of the file, and the cadr is non-2nil* if the file was actually deleted (it is always 2t* unless querying was done). 3undelete-file* 1file* &key 1(error-p* 3t1)** 1query?* 3undeletef* 1file* &optional 1(error-p* 3t1)** 1query?* Both undelete the specified file. Wildcards are allowed, just as in 2deletef*. The rest of the calling conventions are the same as well. The two functions differ in taking keyword arguments versus positional arguments. Not all file systems support undeletion, and if it is not supported on the one you are using, it gets an error or returns a string according to 1error-p*. To find out whether a particular file system supports this, send the 2:undeletable-p* operation to a pathname. If it returns 2t*, the file system of that pathname supports undeletion. 3rename-file* 1file* 1new-name* &key 1(error-p* 3t1)** 1query?* 3renamef* 1file* 1new-name* &optional 1(error-p* 3t1)** 1query?* Both rename the specified file to 1new-name* (a pathname or string). The two functions differ in taking keyword arguments versus positional arguments. 1file* may contain wildcards, in which case multiple files are renamed. Each file's new name is produced by passing 1new-name* to 2merge-pathname-defaults* with the file's truename as the defaults. Therefore, 1new-name* should be a string in this case. If 1query?* is non-2nil*, the user is queried about each file (whether there are wildcards or not). Only the files that the user confirms are actually renamed. If 1error-p* is 2t*, then if an error occurs it is signaled as a Lisp error. If 1error-p* is 2nil* and an error occurs, the error message is returned as a condition object. Otherwise, the value is a list of elements, one for each file considered. The car of each element is the original truename of the file, the cadr is the name it was to be renamed to, and the caddr is non-2nil* if the file was renamed. The caddr is 2nil* if the user was queried and said no. 3copy-file* 1file* 1new-name* &key 1(error* 3t1)** 1(copy-creation-date* 3t1)** 1(copy-author* 3t1)** 1report-stream* 1(create-directories* 3:query1)** 1(characters* 3:default1)** 1(byte-size* 3:default1)** Copies the file specified by 1file* to the name 1new-name*. 1characters* and 1byte-size* specify what mode of I/O to use to transfer the data. 1characters* can be 2t* to specify character input and output. 2nil* for binary input and output, 2:ask* meaning ask the user which one 2:maybe-ask* meaning ask if it is not possible to tell with certainty which method is best, 2:default* meaning to guess as well as possible automatically. If binary transfer is done, 1byte-size* specifies the byte size to use; 2:default* means to ask the file system for the byte size that the old file is stored in, just as it does in 2open*. 1copy-author* and 1copy-creation-date* say whether to set those properties of the new file to be the same as those of the old file. If a property is not copied, it is set to your login name or the current date and time. 1report-stream*, if non-2nil*, is a stream on which a message should be printed describing the file copied, where it is copied to, and which mode was used. 1create-directories* says what to do if the output filename specifies a directory that does not exist. It can be 2t* meaning create the directory, 2nil* meaning treat it as an error, or 2:query* meaning ask the user which one to do. The default is 2:query*. 1error*, if 2nil*, means that if an error happens then this function should just return an error indication. If the pathname to copy from contains wildcards, multiple files are copied. The new name for each file is obtained by merging 1new-name* (parsed into a pathname) with that file's truename as a default. The mode of copy is determined for each file individually, and each copy is reported on the 1report-stream* if there is one. If 1error* is 2nil*, an error in copying one file does not prevent the others from being copied. There are four values. If wildcards were used, each value is a list with one element describing each file that matched; otherwise, each value describes the single file specified (though the value may be a list anyway). The values, for each file, are: 1output-file* The defaulted pathname to be opened for output in copying this file. 1truename* The truename of the file copied 1outcome* The truename of the new file, If the file was successfully copied. A condition object, if there was an error and 1error* was 2nil*. 2nil* if the user was asked whether to copy this file and said no. 1mode* A Common Lisp type descriptor such as 2string-char* or 2(unsigned-byte 8)* saying how the file was copied. 3probe-file* 1file* 3probef* 1file* Returns 2nil* if there is no file named 1file*; otherwise returns a pathname that is the true name of the file, which can be different from 1file* because of file links, version numbers, etc. If 1file* is a stream, this function cannot return 2nil*. Any problem in opening the file except for 2fs:file-not-found* signals an error. 2probef* is the Maclisp name; 2probe-file* is the Common Lisp name. 3file-write-date* 1file* Returns the creation date/time of 1file*, as a universal time. 3file-author* 1file* Returns the name of the author of 1file* (the user who wrote it), as a string. 3viewf* 2file* &optional 1(output-stream* 3*standard-output*1)** 1leader* Copies the contents of the specified file, opened in character mode, onto 2output-stream*. Normally this has the effect of printing the file on the terminal. 1leader* is passed along to 2stream-copy-until-eof* (see 4(IOSYSTEM-1)Output Functions*). 3fs:create-link* 1link-name* 1link-to* &key 1(error* 3t1)** Creates a link named 1link-name* which points to a file named 1link-to*. An error happens if the host specified in 1link-name* does not support links, or for any of the usual problems that can happen in creating a file. =Node: 4Loading Files* =Text: 3LOADING FILES* To 1load* a file is to read through the file, evaluating each form in it. Programs are typically stored in files; the expressions in the file are mostly special forms such as 2defun* and 2defvar* which define the functions and variables of the program. Loading a compiled (or QFASL) file is similar, except that the file does not contain text but rather pre-digested expressions created by the compiler which can be loaded more quickly. These functions are for loading single files. There is a system for keeping track of programs which consist of more than one file; for further information refer to 4(SYSTEMS-0)Maintaining Large Systems*. 3load* 1file* &key 1verbose* 1print* 1(if-does-not-exist* 3t1)** 1set-default-pathname* 1package* Loads the specified file into the Lisp environment. If 1file* is a stream, 2load* reads from it; otherwise 1file* is defaulted from the default pathname defaults and the result specifies a file to be opened. If the file is a QFASL file, 2fasload* is used; otherwise 2readfile* is used. If 1file* specifies a name but no type, 2load* looks first for the canonical type 2:qfasl* and then for the canonical type 2:lisp*. Normally the file is read into the package specified in its attribute list, but if 1package* is supplied then the file is read in that package. If 1package* is 2nil* and 1verbose* is 2nil*, 2load* prints a message saying what file is being loaded and what package is being used. 1verbose* defaults to the value of 2*load-verbose**. If 1if-does-not-exist* is 2nil*, 2load* just returns 2nil* if no file with the specified name exists. Error conditions other than 2fs:file-not-found* are not handled by this option. If a file is loaded, 2load* returns the file's truename. If 1print* is non-2nil*, the value of each expression evaluated from the file is printed on 2*standard-output**. 1pathname* is defaulted from the default pathname defaults. If 1set-default-pathname* is non-2nil*, the pathname defaults are set to the name of the file loaded. The default for 1set-default-pathname* is 2t*. 2load* used to be called with a different calling sequence: 3(load 1pathname* 1pkg* 1nonexistent-ok** 3 1dont-set-default*)* This calling sequence is detected and still works, but it is obsolete. 3*load-verbose** 1Variable* Is the default value for the 1verbose* argument to 2load*. 3readfile* 1file* &optional 1pkg* 1no-msg-p* 2readfile* is the version of 2load* for text files. It reads and evaluates each expression in the file. As with 2load*, 1pkg* can specify what package to read the file into. Unless 1no-msg-p* is 2t*, a message is printed indicating what file is being read into what package. 3fasload* 1file* &optional 1pkg* 1no-msg-p* 2fasload* is the version of 2load* for QFASL files. It defines functions and performs other actions as directed by the specifications inserted in the file by the compiler. As with 2load*, 1pkg* can specify what package to read the file into. Unless 1no-msg-p* is 2t*, a message is printed indicating what file is being read into what package. =Node: 4Pathname Operations *t4hat Access Files* =Text: 3PATHNAME OPERATIONS THAT ACCESS FILES* Here are the operations that access files. Many accept an argument 1error* or 1error-p* which specifies whether to signal an error or to return a condition instance, if the file cannot be accessed. For these arguments, 2nil* and non-2nil* are the only significant values. 2:reprompt* has no special meaning as a value. That value when passed to one of the file accessing functions (2open*, 2deletef*, etc.) has its special significance at a higher level. 3:truename* 1Operation on 2pathname** Returns a pathname object describing the exact name of the file specified by the pathname the object is sent to. This may be different from the original pathname. For example, the original pathname may have 2:newest* as the version, but the truename always has a number as the version if the file system supports versions. 3:open* 1pathname* &rest 1options* 1Operation on 2pathname** Opens a stream for the file named by the pathname. The argument 1pathname* is what the 2:pathname* operation on the resulting stream should return. When a logical pathname is opened, 1pathname* is that logical pathname, but 2self* is its translated pathname. 1options* is a list of alternating keywords and values, as would be passed to 2open*. The old style of 2open* keywords are not allowed; when they are used with 2open*, 2open* converts them to the new style before sending the 2:open* message. 3:delete* &optional 1(error-p* 3t1)** 1Operation on 2pathname** 3:undelete* &optional 1(error-p* 3t1)** 1Operation on 2pathname** Respectively delete or undelete the file specified by the pathname. All file systems support 2:delete* but not all support 2:undelete*. If 1error-p* is 2nil*, problems such as nonexistent files cause a string describing the problem to be returned. Otherwise, they signal an error. 3:undeletable-p* 1Operation on 2pathname** Returns 2t* if this pathname is for a file system which allows deletion to be undone. Such pathnames support the 2:undelete* and 2:expunge* operations. 3:rename* 1new-name* &optional 1(error-p* 3t1)** 1Operation on 2pathname** Renames the file specified by the pathname. 1new-name*, a string or pathname, specifies the name to rename to. If it is a string, it is parsed using 2self* as the defaults. If 1error-p* is 2nil*, problems such as nonexistent files cause a string describing the problem to be returned. Otherwise, they signal an error. 3:complete-string* 1string* 1options* 1Operation on 2pathname** Attempts to complete the filename 1string*, returning the results. This operation is used by the function 2fs:complete-pathname* (see 4(FILEACCESS-3)Accessing Directories*). The pathname the message is sent to is used for defaults. 1options* is a list whose elements may include 2:deleted*, 2:read* (file is for input), 2:write* (it's for output), 2:old* (only existing files allowed), or 2:new-ok* (new files are allowed too). There are two values: a string, which is the completion as far as possible, and a flag, which can be 2:old*, 2:new* or 2nil*. 2:old* says that the returned string names an existing file, 2:new* says that the returned string is no file but some completion was done, 2nil* says that no completion was possible. 3:change-properties* 1error-p* &rest 1properties* 1Operation on 2pathname** Changes the properties of the file specified by the pathname. 1properties* should be an alternating list of property names and values. 3:directory-list* 1options* 1Operation on 2pathname** Performs the work of 2(fs:directory-list 1this-pathname* 1options*...)*. 3:properties* 1Operation on 2pathname** Returns a property list (in the form of a directory-list element) and a list of settable properties. See 4(FILEACCESS-3)Accessing Directories* for more information on file properties. 3:wildcard-map* 1function* 1plistp* 1dir-list-options* &rest 1args* 1Operation on 2pathname** Maps 1function* over all the files specified by this pathname (which may contain wildcards). Each time 1function* is called, its first argument is a pathname with no wildcards, or else a directory-list element (whose car is a pathname and whose cdr contains property names and values). The elements of 1args* are given to 1function* as additional arguments. 1plistp* says whether 1function*'s first argument should be a directory-list element or just a pathname. 2t* specifies a directory-list element. That provides more information, but it makes it necessary to do extra work if the specified pathname does 1not* contain wildcards. 1dir-list-options* is passed to 2fs:directory-list*. You can use this to get deleted files mentioned in the list, for example. The remaining file-access operations are defined only on certain file systems. 3:expunge* &key 1(error* 3t1)** 1Operation on 2pathname** Expunges the directory specified by the host, device and directory components of the pathname. The argument 1error* says whether to signal an error if the directory does not exist. 2nil* means just return a string instead. 3:create-directory* &key 1(error* 3t1)** 1Operation on 2pathname** Creates the directory specified in this pathname. 3:remote-connect* &key 1(error* 3t1)** 1access* 1Operation on 2pathname** Performs the work of 2fs:remote-connect* with the same arguments on this pathname's host. =Node: 4File Attribute Lists* =Text: 3FILE ATTRIBUTE LISTS* Any text file can contain an 1attribute list* that specifies several attributes of the file. The above loading functions, the compiler, and the editor look at this property list. Attribute lists are especially useful in program source files, i.e. a file that is intended to be loaded (or compiled and then loaded). QFASL files also contain attribute lists, copied from their source files. If the first non-blank line in a text file contains the three characters `3-*-*', some text, and `3-*-*' again, the text is recognized as the file's attribute list. Each attribute consists of the attribute name, a colon, and the attribute value. If there is more than one attribute they are separated by semicolons. An example of such an attribute list is: 3; -*- Mode:Lisp; Package:Cellophane; Base:10 -*-* This defines three attributes: mode, package, and base. The initial semicolon makes the line look like a comment rather than a Lisp expression. Another example is: 3.c Part of the Lisp Machine manual. -*- Mode:Bolio -*-* An attribute name is made up of letters, numbers, and otherwise-undefined punctuation characters such as hyphens. An attribute value can be such a name, or a decimal number, or several such items separated by commas. Spaces may be used freely to separate tokens. Upper and lower-case letters are not distinguished. There is 1no* quoting convention for special characters such as colons and semicolons. If the attribute list text contains no colons, it is an old Emacs format, containing only the value of the 2Mode* attribute. The file attribute list format actually has nothing to do with Lisp; it is just a convention for placing some information into a file that is easy for a program to interpret. The Emacs editor on the PDP-10 knows how to interpret these attribute lists (primarily in order to look at the 2Mode* attribute). The Lisp Machine handles the attribute list stored in the file by parsing it into a Lisp data structure, a property list. Attribute names are interpreted as Lisp symbols and are interned on the keyword package. Numbers are interpreted as Lisp fixnums and are read in decimal. If a attribute value contains any commas, then the commas separate several expressions that are formed into a list. When a file is compiled, its attribute list data structure is stored in the QFASL file. It can be loaded back from the QFASL file as well. The representation in the QFASL file resembles nothing described here, but when the attribute list is extracted from there, the same Lisp data structure described above is obtained. When a file is edited, loaded, or compiled, its file attribute list is read in and the properties are stored on the property list of the generic pathname (see 4(FILENAMES-2)Generic Pathnames*) for that file, where they can be retrieved with the 2:get* and 2:plist* messages. This is done using the function 2fs:read-attribute-list*, below. So the way you examine the properties of a file is usually to use messages to a pathname object that represents the generic pathname of a file. Note that there are other properties there, too. Here the attribute names with standard meanings: The editor major mode to be used when editing this file. This is typically the name of the language in which the file is written. The most common values are 2Lisp* and 2Text*. 2Package* This attribute specifies the package in which symbols in the file should be interned. The attribute may be either the name of a package, or a list that specifies both the package name and how to create the package if it does not exist. If it is a list, it should look like 2(1name* 1superpackage* 1initial-size* 1...options...*)*. See 4(PACKAGES-0)Packages* for more information about packages. 2Base* The number base in which the file is written (remember, it is always parsed in decimal). This affects both 2*read-base** and 2*print-base**, since it is confusing to have the input and output bases be different. The most common values are 8 and 10. 2Readtable* The value specifies the syntax (that is, the choice of readtable) to use for reading Lisp objects from this file. The defined values are 2t* or 2traditional* for traditional Lisp Machine syntax, and 2cl* or 2common-lisp* for Common Lisp syntax. If you do not specify this option, the objects in the file are read using whatever readtable is current in the program that reads them. 2Lowercase* If the attribute value is not 2nil*, the file is written in lower-case letters and the editor does not translate to upper case. (The editor does not translate to upper case by default unless the user enables Electric Shift Lock mode.) 2Fonts* The attribute value is a list of font names, separated by commas. The editor uses this for files that are to be displayed in a specific font, or contain multiple fonts. If this attribute is present, the file is actually stored in the file system with font-change indicators. A font-change indicator is an epsilon (3*) followed by a digit or 3**. 31n** means to enter font 1n*. The previous font is saved on a stack and 31*** means to pop the stack, returning to the previous font. If the file includes an epsilon as part of its contents, it is stored as 3*. When expressions are read from such files, font-change indicators are ignored, and 3* is treated as a single 3*. 2Backspace* If the attribute value is not 2nil*, 2Overstrike* characters in the file should cause characters to overprint on each other. The default is to disallow overprinting and display 2Overstrike* the way other special function keys are displayed. This default is to prevent the confusion that can be engendered by overstruck text. 2Patch-File* If the attribute value is not 2nil*, the file is a 1patch file*. When it is loaded the system will not complain about function redefinitions. In a patch file, the 2defvar* special-form turns into 2defconst*; thus patch files always reinitialize variables. Patch files are usually created by special editor commands described in 4(SYSTEMS-2)The Patch Facility*. 2Cold-Load* A non-2nil* value for this attribute identifies files that are part of the cold load, the core from which a new system version is built. Certain features that do not work in the cold load check this flag to give an error or a compiler warning if used in such files, so that the problem can be detected sooner. You are free to define additional file attributes of your own. However, to avoid accidental name conflicts, you should choose names that are different from all the names above, and from any names likely to be defined by anybody else's programs. The following functions are used to examine file attribute lists: 3fs:file-attribute-list* 1pathname* Returns the attribute list of the file specified by the pathname. This works on both text files and QFASL files. 3fs:extract-attribute-list* 1stream* Returns the attribute list read from the specified stream, which should be pointing to the beginning of a file. This works on both text streams and QFASL file binary streams. After the attribute list is read, the stream's pointer is set back to the beginning of the file using the 2:set-pointer* file stream operation (see ). 3fs:read-attribute-list* 1pathname* 1stream* 1pathname* should be a pathname object (1not* a string or namelist, but an actual pathname); usually it is a generic pathname (see 4(FILENAMES-2)Generic Pathnames*). 1stream* should be a stream that has been opened and is pointing to the beginning of the file whose file attribute list is to be parsed. The attribute list is read from the stream and then corresponding properties are placed on the specified 1pathname*. The attribute list is also returned. The fundamental way that programs in the Lisp Machine notice the presence of properties on a file's attribute list is by examining the property list in the generic pathname. However, there is another way that is more convenient for some applications. File attributes can cause special variables to be bound whenever Lisp expressions are being read from the file--when the file is being loaded, when it is being compiled, when it is being read from by the editor, and when its QFASL file is being loaded. This is how the 2Package* and 2Base* attributes work. You can also deal with attributes this way, by using the following function: 3fs:file-attribute-bindings* 1pathname* Returns values describing the special variables that should be bound before reading expressions from file 1pathname*. It examines the property list of 1pathname* and finds all those property names that have 2fs:file-attribute-bindings* properties. Each such property name specifies a set of variables to bind and a set of values to which to bind them. This function returns two values, a list of all the variables and a list of all the corresponding values. Usually you use this function by calling it on a generic pathname that has had 2fs:read-attribute-list* done on it, and then you use the two returned values as the first two arguments of a 2progv* special form (see 4(EVAL-1)Variable Binding Constructs*). Inside the body of the 2progv* the specified bindings will be in effect. 1pathname* may be anything acceptable as the first argument of 2get*. Usually it is a generic pathname. Of the standard attribute names, the following ones have 2fs:file-attribute-bindings*, with the following effects. 2Package* binds the variable 2package* (see 4(PACKAGES-1)The Current Package*) to the package. 2Base* binds the variables 2*print-base** (see 4(READPRINT-1)Options that Control Printing*) and 2*read-base** (see 4(READPRINT-2)What The Reader Accepts*) to the value. 2Readtable* binds the variable 2readtable* to a value computed from the specified attribute. 2Patch-file* binds 2fs:this-is-a-patch-file* to the value. 2Cold-load* binds 2si:file-in-cold-load* to the value. 2Fonts* binds 2si:read-discard-font-changes* to 2t*. Any properties whose names do not have 2fs:file-attribute-bindings* properties are ignored completely. You can also add your own attribute names that affect bindings. If an indicator symbol has an 2fs:file-attribute-bindings* property, the value of that property is a function that is called when a file with a file attribute of that name is going to be read from. The function is given three arguments: the file pathname, the attribute name, and the attribute value. It must return two values: a list of variables to be bound and a list of values to bind them to. The function for the 2Base* keyword could have been defined by: 3(defun (:base file-attribute-bindings) (file ignore bse)* 3 (if (not (and (typep bse 'fixnum)* 3(> bse 1)* 3(< bse 37.)))* 3 (ferror 'fs:invalid-file-attrbute* 3 "File ~A has an illegal -*- Base:~D -*-"* 3 file bse))* 3 (values (list 'base 'ibase) (list bse bse))) fs:extract-attribute-bindings* 1stream* Returns two values: a list of variables, and a corresponding list of values to bind them to, giving the attribute bindings of the attribute list found on 1stream* 3fs:invalid-file-attribute* (3error*) 1Condition* An attribute in the file attribute list had a bad value. This is detected within 2fs:file-attribute-bindings*.