ToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version

Loading

This document contains the following sections:

1.0 Using the load function
   1.1 EOF encountered error during a load
   1.2 Special utilities for loading applications
2.0 Search lists
   2.1 Search List Structure
   2.2 Search lists variables
   2.3 Search list example
3.0 The Allegro Presto facility has been removed
4.0 Loading and case modes


1.0 Using the load function

In Allegro CL, load has additional keyword arguments, searchlist, system-library, script, and foreign, described in the bullets below. Note that if the argument is a foreign library file (such as a so/sl/dll file) without any directory information, Allegro CL passes the filename off to the Operating System without merging the name with *default-pathname-defaults* or using the search list.

In earlier versions of Allegro CL, there was an additional libfasl keyword argument which is no longer supported.

Certain global variables are bound when load is loading a file. Therefore, setting those variables in a file such as an initialization file (e.g. .clinit.cl) may not have the desired effect. (Setting global values in an initialization file is discussed in Setting global variables in initialization files and in The package on startup (which discusses *package* specifically), both in startup.htm.) The following table shows what variables are bound by load:

Variable

Bound to

*package* *package*
*readtable* *readtable*
excl:*source-pathname* name of file being loaded
*redefinition-warnings* *redefinition-warnings*

Table 1 Variables bound by load

The top-level command :ld calls the load function. :ld will accept multiple filenames but it does not accept keyword arguments. :ld reads its arguments as strings and does not accept pathnames or streams as filename arguments. Therefore, to load the file test.cl, the following :ld command will work:

:ld test.cl 

The file is found via the load search list, described below. With the default value of the load search-list (it is the value of the variable *load-search-list*), the path provided is merged with *default-pathname-defaults*.

There are other keyword arguments for load in Allegro CL other than those specified by the ANSI standard, such as unreferenced-lib-names, used when load loads foreign (C or Fortran) object files. See foreign-functions.htm for details of these additional keyword arguments.


1.1 EOF encountered error during a load

If you try to load a file that contains an incomplete form (because of, e.g., a missing closing parenthesis), load signals an error with condition end-of-file. Consider the following file missing-paren.cl:

(defun foo nil nil)
(defun bar (a b) (+ a b)

The closing parenthesis is missing from the definition of bar. When Lisp tries to load this file, it signals an error:

USER(1): :ld missing-paren.cl
; Loading /net/rubix/usr/tech/dm/missing-paren.cl.
Error: eof encountered on stream #<EXCL::CHARACTER-INPUT-FILE-STREAM
#p"/net/rubix/usr/tech/dm/missing-paren.cl" pos 45 @ #xa91f02>
starting at position 20.
 [condition type: END-OF-FILE]

Restart actions (select using :continue):
 0: retry the load of missing-paren.cl
[1] USER(2):

Note the line:

starting at position 20.

That indicates that the incomplete form starts at position 20 in the file. Opening the file in Emacs and entering the command C-u 20 C-f (assuming standard keybindings) should bring you to the beginning of the incomplete form.


1.2 Special utilities for loading applications

Allegro CL does provide certain utilities for loading collections of files, in particular collections of files which comprise an application. The primary utility for this purpose is the defsystem utility, described in defsystem.htm. A couple of simpler utilities are also available: the macros load-application and tenuring.

tenuring allows evaluation of forms with all live objects tenured at the end of the evaluation. You might want to call load within that macro. See the discussion in gc.htm for more information.

load-application allows you to specify the environment in which the loading takes place.



2.0 Search lists

Now that logical pathnames are available in Lisp, search lists may be obsolete. However, they are preserved for backward compatibility.

This section describes how load and require find the files they are called upon to load. Novice users, who keep the files to load in the same directory as they run Lisp need not concern themselves with the subtleties of this section. However, the facilities defined in this section are very powerful, allowing complicated mechanisms to be defined for finding files specified without directory paths or with only relative directory paths. If such capability will be useful to you, you should read on.

The functions require and load (and the top-level command :ld) read files. The Common Lisp standard specifies how the filename argument to these functions is processed to yield the true name of the file to be read: the argument is merged (using the Common Lisp function merge-pathnames) with the value of *default-pathname-defaults*. This file-finding mechanism is inadequate for all but the simplest of applications although logical pathnames may be adequate. Note that using the initial value of the load search-list, pathnames are merged with *default-pathname-defaults*. Note further that the directory specified by *default-pathname-defaults* may be different from the directory returned by current-directory (see the description of chdir).

Addressing the need for a more flexible file-finding mechanism, Allegro CL incorporates search lists, data structures embodying information about how the functions require and load will find a file to load into Lisp. Both functions have their own search list.

Autoloading (where an action like calling a function triggers the loading of the module containing the associated functionality) also uses a search list. We do not discuss it much in this document since autoloading is usually invisible to the user.

Search lists permit the user to specify a sequence of pathnames to be merged with the filename argument to require or load. We henceforth refer to this filename argument as the supplied name. From among those pathnames resulting from the sequence of merging operations, the first pathname that satisfies the given criteria will be loaded. Further, it is possible to specify side effects, e.g. to compile a file if the source file has been modified more recently than the corresponding compiled (fasl) file. This very general mechanism provides considerable control over file-loading operations.

In general, most of the default Lisp functionality stored in a file called the bundle file, whose name is files and whose extension is bu or ebu. When you load a module (for example, inspect, foreign-functions, trace, etc.) the system must know to look in the bundle file instead of looking for the fasl file in the Lisp library. The :lib-bundle search list keyword argument provides this functionality.


2.1 Search List Structure

A search list is a recursive data structure. It may be a symbol, string, pathname, or a list of search lists. (The car of a list is interpreted specially.) The elements of a search list are processed sequentially. If the search list is recursive, it is processed in depth-first fashion. The goal of processing a search list is to locate a file to be loaded -- in effect a search list returns the pathname of a file. It is often convenient to refer to search lists as returning a pathname, especially when discussing recursive search lists. It is an error if a file cannot be located within the given constraints. The different kinds of search lists are handled as follows:

We now define the effect of the keywords that can be the car of a search list which is a list. In the definitions below, we borrow the Common Lisp notation &rest search-list to represent the rest of the list.

Keyword Arguments Description
:first &rest search-list search-list may be one or more symbols, strings, pathnames or lists of search lists. When this search list keyword is processed, each element of search-list is merged with the supplied name and the first existing file is returned. Once an existing file is found, any remaining elements in search-list are not processed. search-list is processed sequentially from head to tail. The search list returns nil if, after processing all elements of search-list, no such file exists. Note that if no search list keyword is specified, then the search list is treated as if it began with :first.
:newest &rest search-list search-list may be one or more symbols, strings, pathnames or lists of search-lists. When this search list keyword is processed, all of the elements in search-list are merged with the supplied name and the newest file is returned. If no files exist then nil is returned.
:newest-ask-compile fasl-name &rest search-list fasl-name must be a string or pathname. search-list may be one or more symbols, strings, pathnames or lists of search-lists. fasl-name is merged with the supplied name and the resulting pathname must name a fasl (compiled Lisp) file. Each element of search-list is then merged with the supplied name and the first existing file denoted among them, which should be a source file, is selected. If the fasl file exists, and if it is newer than the first source file, the pathname of the fasl file will be returned. If no source file exists, the fasl file is returned. If no fasl file exists, or if the fasl file is older than the first source file, the user is asked whether the source file should be compiled to yield a new fasl file. If the response is affirmative, the file is compiled and the pathname of the fasl file is returned. Otherwise, the pathname of the newest source file is returned. If neither fasl file nor source file exists, nil is returned.
:newest-do-compile fasl-name &rest search-list fasl-name must be a string or pathname. search-list may be one or more symbols, strings, pathnames or lists of search-lists. A list containing this keyword is processed identically to a list containing the :newest-ask-compile keyword, except that the user is not asked whether a file should be compiled. The compilation is always performed if required and the pathname of the resulting fasl file is returned. Note that if two source files mutually require each other, then this option can result in an infinite loop (where neither can be compiled until the other is). To resolve this conflict, one of the files must be loaded interpreted. Therefore, the :newest-do-compile option is not recommended for *require-search-list*.
:call function &rest search-list function must be funcallable. search-list may be one or more symbols, strings, pathnames or lists of search-lists. This search list keyword argument can be used by the user to add a new feature to search list processing. Note that misuse of this search list keyword argument can make it difficult to use Lisp. Most users will never have a use for this search list keyword argument. This function is applied, once, to five arguments: the supplied name, search-list, order, check-bundle, and check-lower-case. The argument order defaults to :first, but may be set to other values while processing an earlier search list (see the example below). check-bundle is non-nil if the bundle is to be checked. check-lower-case is non-nil is there are no lowercase characters in the filename (meaning it might be worth checking a lowercase version of the name). The function must return a pathname or a string or nil, and this value is returned by the search list. See the example just below this table. Note: the fifth argument, check-lower-case, was added in release 7.0.
:lib-bundle sub-pathname &optional default-pathname sub-pathname and default-pathname can each be either pathnames or symbols whose symbol-value is a pathname. sub-pathname may be a list of pathnames that are merged together when the search list is processed.

This search list keyword argument first merges the supplied name and sub-pathname. Then the enough-namestring function is used to find the shortest string to identify uniquely the pathname relative to default-pathname. In other words, the pathname to be processed is determined by the form below:

(enough-namestring (merge-pathname supplied-name sub-path)
default-pathname)

If the pathname produced by the form above is in the bundle, then three values are returned: the pathname, the Allegro CL compiler time stamp and t. If the pathname is not in the bundle, then nil is returned.

For an example using :call, a user supplied function could look like:

(defun my-call 
 (target search-list order check-bundle)
 ;; User supplied code, eventually returning a pathname,
 ;; a string or nil.
 )
;; A sample searchlist that uses :call.
(:newest
 (:call my-call . . .)
 (:call my-call . . .))
;; The order argument to my-call will be :newest instead
;; of :first. 

2.2 Search lists variables

The search list for the load function is bound to the symbol *load-search-list*. The default value on many platforms for this symbol is

(#p"" #p(:type "fasl") #p(:type
      "cl") #p(:type "lisp"))

Thus load function looks for its file first by its supplied name in the directory which is the value of *default-pathname-defaults*. If it cannot find the file there, it looks in the same place for a file with a "fasl" file type, then with a "cl" file type, and then with a "lisp" file type. If no file is found, then the search list returns nil indicating no satisfactory file corresponding to the supplied name was found.

The search list for the require function is bound to the symbol *require-search-list*. The initial value for this symbol changed in release 6.0 compared to earlier releases. Its value is now:

((:first #p"sys:;code;.fasl"
	 #p"sys:;private;.fasl"
	 #p"sys:;clos;.fasl"
	 #p"sys:;sys;.fasl"
         (:lib-bundle #p"sys:;code;.fasl")
         (:lib-bundle #p"sys:;private;.fasl")
         (:lib-bundle #p"sys:;clos;.fasl")
         (:lib-bundle #p"sys:;sys;.fasl"))
 #p"src:;code;.cl"
 #p"src:;private;.cl"
 #p"src:;clos;.cl"
 #p"src:;sys;.cl")

require now only looks for fasl files in subdirectories of sys: and for source files in subdirectories of src:. In sys: it also looks in the bundle file. A problem with require in earlier releases, where it looked in the current directory as well as library directories, was that files with names the same as module name ("build" for example) were loaded in preference to the library file, with undesired results.

Note that looking in the bundle file is preceded by looking in code/. If a file exists in both the bundle and in the code/ subdirectory, then the first file encountered will be in code/ and will be used. (This ensures that a fixed fasl file which was originally part of the bundle, supplied as a patch and placed in code/, will be used instead of the version in the bundle file.)

There is also an autoload search list, the value of *autoload-search-list*, which is used by the system when an autoload is triggered. Autoloads are triggered by actions such as calling a function whose functionality is not presently in the system. (Not all such functions trigger autoloads. Typically only the important functions of a facility.) Autoloading is usually nearly invisible to users. Most modules are autoloaded from the bundle. The structure of the search list, however, ensures that updated fasl files which replace fasl files in the bundle are found and used correctly.


2.3 Search list example

Suppose that you maintain a personal Lisp library in a subdirectory of your home-directory, and that you wish to have the load function look for files in this subdirectory. Let us assume this subdirectory is named lisplib. It would be reasonable to search your library directory after searching the directory which is the value of *default-pathname-defaults*. (Note that the directory specified by *default-pathname-defaults* may be different from the directory returned by current-directory. See the description of chdir.)

Further, say you would like to compile automatically all files that are in your working or library directories. The following definition of system:*load-search-list* in an initialization file (such as .clinit.cl) will accomplish this. Your home directory pathname is denoted with a tilde (`~').

(setq system:*load-search-list*
  '(:first
    (:newest-do-compile 
      #.(make-pathname :type "fasl")
      #.(make-pathname :type "cl"))
     (:newest-do-compile
     #.(make-pathname :directory "~/lisplib"
:type "fasl")
      #.(make-pathname :directory "~/lisplib"
:type "cl"))
 ))

If you start up Lisp in the directory ~/work, the expression

(load "foo") 

will result in the following pathnames being generated.

>~/work/foo.fasl ;; these two point to
~/work/foo.cl ;; the current directory
~/lisplib/foo.fasl ;; these two point to the 
~/lisplib/foo.cl ;; lisplib directory

If ~/work/foo.cl exists, it will be compiled, if necessary, and ~/work/foo.fasl will be loaded. If ~/work/foo.fasl exists but ~/work/foo.cl does not, ~/work/foo.fasl will be loaded. If neither of these files exists, the next two files are examined. If ~/lisplib/foo.cl exists, it will be compiled, if necessary, and ~/lisplib/foo.fasl will be loaded. If ~/lisplib/foo.fasl exists but ~/lisplib/foo.cl does not, ~/lisplib/foo.fasl will be loaded. If neither of these files exist, an error is signaled.

Note: if you change the value of *require-search-list*, you must include

(:newest (:lib-bundle #p"sys:;code;.fasl") 
         #p"sys:;code;.fasl"
         #p"sys:;code;.cl" 

so that Lisp will be able to find library files such as foreign.fasl.



3.0 The Allegro Presto facility has been removed

The Allegro Presto facility was a space saving option in releases of Allegro CL prior to 7.0. It is no longer supported. It worked by only partially loading function definitions when a fasl file was loaded in libfasl mode, loading the full definition only when the function was actually called. It has been removed bacause the space savings can, for the most part, be obtained in other ways, for example by using pll files, and the residual space savings no longer justify the costs of Allegro Presto. (The main cost was extra complexity, both within Allegro CL and in user code and applications. This complexity could result in bugs which were often subtle and difficult to fix.)

For the most part, few or no changes to user code are necessitated by the removal of the Allegro Presto facility. The operators, variables, and arguments associated with Allegro Presto are retained for backward compatibility (although use in some cases signals a warning), but are effectively no-ops. Here is a list of specific changes:



4.0 Loading and case modes

Allegro CL supports both modes regarding case of letters in symbols naming Common Lisp objects: a case-insensitive mode where foo, FOO, foO, Foo, etc. all name the same symbol; and a case-sensitive mode where they all name different symbols. See case.htm for information on deciding upon, setting, and changing the case mode in Allegro CL. (Besides case-sensitivity, the mode also controls case preference, specifying the case of standard Common Lisp symbols, among other things, as described in case.htm.)

A problem with allowing different case modes is that a fasl file compiled in an image using one mode will not behave as expected when loaded into an image. Consider for example the file containing two function definitions:

(in-package :cl-user)

(defun FOO (x) (+ 1 x))

(defun foo (y) (* 2 y))

In an ANSI-mode (case-insensitive) image, loading this file (as a source file) would result in one function definition, on the symbol FOO, which multiplied the argument by 2 and returned the result. In a modern-mode (case-sensitive) image, loading this file would result in two function definitions, one on FOO, and one on foo.

That problem (different behavior when the same source file is loaded into images using different modes) is, however, not surprising given the nature of case-sensitivity. Users working in different modes must manage the issue of symbols differing only in the case of the alphabetic letters in the name of the symbol.

A more serious problem occurs when dealing with compiled (fasl) files. If the file above is compiled in an ANSI-mode image, it will contain two (compiled) definitions of the function named by the symbol FOO. If the file is compiled in a modern-mode image, it will contain, again, two definitions: one on FOO, and one on foo. Now consider what happens when these fasl files are loaded. Let us consider all the cases (we are assuming the setting of convert-mixed-case-symbols is its initial value t, see below in this section for the behavior when the value is nil) :

Note the fourth case: when the file is compiled in ANSI-mode and loaded into modern-mode, the behavior is different from the source file being loaded into a modern-mode image. In all other cases, loading the source file and loading the compiled file produces the same behavior. Therefore, Allegro CL signals a continuable error with condition type excl:fasl-casemode-mismatch when an attempt is made to load a fasl file compiled in an ANSI-mode image into a modern-mode image:

; Fast loading x.fasl
Error: #p"x.fasl" was compiled in case-insensitive-upper mode.  
      Continuing to load this file may result in symbol-name mismatches.
 [condition type: fasl-casemode-mismatch]

Restart actions (select using :continue):
0: Continue loading x.fasl
1: retry the load of x.fasl
2: skip loading x.fasl
3: Return to Top Level (an "abort" restart)
4: Abort #<process Initial Lisp Listener>
[1] cl-user(2): 

The correct thing to do at this point is to recompile the source file in the modern-mode image (assuming that is possible). The results of choosing to continue (by, e.g. calling :continue) are undefined (but will not be untoward if in fact there are no name conflicts).

Note that the setting of convert-mixed-case-symbols does not affect compilation: all (unescaped) symbol names are converted to uppercase in ANSI-mode images during compilation. The setting does affect loading of fasl files, however. If the setting is nil (the initial setting is t), then the second case listed above:

produces the results: two definitions, one on FOO and one on |foo| (we are using escapes to indicate that the print name of the symbol is all lower case).


Copyright (c) 1998-2022, Franz Inc. Lafayette, CA., USA. All rights reserved.
This page was not revised from the 10.0 page.
Created 2019.8.20.

ToCDocOverviewCGDocRelNotesFAQIndexPermutedIndex
Allegro CL version 10.1
Unrevised from 10.0 to 10.1.
10.0 version