Release Notes for Allegro CL 5.0

Table of Contents

Information specific to Microsoft Windows (95/NT) users

Differences between the UNIX and Windows versions of Allegro CL

Changes from Allegro CL 4.3.2 to Allegro CL 5.0

Building custom Lisp images

Information specific to users of International Allegro CL

Changes from Allegro CL 4.3 to Allegro CL 4.3.2


Information specific to Microsoft Windows (95/NT) users

lisp.exe

Under normal circumstances, when lisp.exe is run it displays a window containing a read-eval-print loop, which we call the console window.

In addition to the console window, there is a Windows explorer tray icon, which can be used to interact with the Lisp.  Double left clicking on this icon in the tray will make the console visible (if necessary it will un-minimize and/or un-hide it, and it will raise it above other windows). A right click on the icon will bring up a menu.  There is a bug in that you have to click on the menu (or another Lisp-controlled window) to dismiss the menu. As a result there is a do-nothing menu item called Dismiss menu which you can use until we fix this bug.

If you are using an International version of Allegro CL, then you also have lispi.exe, which is the International version of lisp.exe.

command line arguments

You may use the following arguments to customize the behavior of lisp.exe.

+c Start ACL without a console window. Normally, there is a console window to read/write standard I/O. If you close the console window, the Lisp will be killed.
+cm Start the console window in a minimized state.  This used to be called the +m argument, which has been deprecated.
+cn Like +c, but don't activate the console window.  This allows Lisp to be started so as to not interfere with the currently selected window.  This used to be called the +n argument, which has been deprecated.
+cx Start the console in a hidden state.  Double-clicking on the tray icon will make the console visible.  See also the right-click menu on the tray icon.
+p Preserve the console window. Without this switch the console window goes away when Lisp exits with a zero exit status. If ACL is exiting unexpectedly you can use this switch to keep the window around to find out what it printed before it died.   This is the opposite of the +M argument.
+R Don't put the ACL icon in the tray.
+s scriptfile Standard input is initially bound to this file. When the file is completely read, standard input reverts to the console window, if there is one.
+M When this argument is present the console window does not need to be closed manually when Lisp exits with a non-zero exit status.  This is the opposite of the +p argument.
+d dll-name Use the given ACL dll instead of the default acl50xx.dll.
+t title Sets the title of the console to title.
+B Use no splash screen (a window that appears very quickly to let you know that Lisp is starting). The splash screen is stored in the image file. See the description of set-splash-screen below for information on user defined splash screens.
+b text Make the splash screen display text instead of the default bitmap. text just appears in a gray box.
+Bt Put up splash screen for a fixed amount of time (3 seconds).

Note: arguments starting with + must be given before (to the left of on the command line) arguments starting with -, when you give them on the command line.

On Windows, using the explorer, quoting of arguments is somewhat confusing.  To load a file, for example, from a short cut or from the Start -> Run... menu, you could do this:

lisp.exe -I dcl -e "(load "foo.cl")"

User control of application termination

There now exists a mechanism for allowing an application to control what happens when the close button is pressed on the console, or when the close menu item is selected.

When the user attemps to close the console, the generic function excl:console-close is called with one argument, the address of a longword in memory.

The default action of excl:console-close is to call (excl::mp-safe-exit 0) which will cause lisp to exit (unless errors occur during the stack unwinding process that preceeds the exiting). If the exiting process gets hung up due to errors, then the user can try to close the console again and this time the whole lisp process will exit without trying to clean up the lisp threads.

An application can put an :around or :before method on excl:console-close to change the default behavior. The argument passed in is the address of the flag which will determine whether to call excl:console-close the next time the close box is clicked. The default value is zero, meaning don't call console-close again. Set the flag to a non-zero value to cause excl:console-close to be called again.

For example, to cause the close of the console to be ignored:

(defmethod excl:console-close :around (x)
  (setf (sys::memref-int x 0 0 :unsigned-long) 1))

Output to the Lisp console

An example showing how to print to the Lisp console:

bar.c:

_declspec(dllexport) blarter(int i, int j)
{
    aclprintf("got %d and %d\n", i, j);
}

compile with:

cl /LD bar.c /link acl50pb56.lib

then run:

user(1): :ld bar.dll
; Foreign loading bar.dll.
user(2): (ff::defforeign 'blarter)
t
user(3): (blarter 1 2)
12

and you'll see output on the console.

The Integrated Development Environment (IDE)

Problems in the 5.0.beta release, which we plan to fix for final:

  1. cg:ask-user-for-choice-from-list: some arguments stick between calls. The :stream and the :dialog-exterior-box arguments are remembered between calls to this function. That is not inteneded. If you use either argument in any call to this function, we recommend you specify the arguments in all calls.
  2. cg:insert-selection does not work since methods for inserting for most objects are not present.
  3. cg:mci-sysinfo does not work.
  4. The pre-built International images which include the IDE do not startup properly.   If you want to use an International image, you cannot use the IDE.
  5. As discussed elsewhere, there is a one to one mapping between Allegro CL processes and operating system threads. This, coupled with the limitation of Microsoft Windows that events for a window can only be received on the thread that creates the window, and limitations of Common Graphics itself, Common Graphics in Allegro CL 5.0 must run within a single Allegro CL process.

    When the Integrated Development Environment (IDE) starts, a special process named "IDE/Common Graphics" is created. All Common Graphics and IDE functions are run within this process. When interacting with the "Debug Window", the current process (ie., the value of sys:*current-process*) is this same "IDE/Common Graphics" process. Therefore, it is possible to create windows and other Common Graphics entities directly as function calls from the "Debug Window". (This is similar to the features and functionality in the Allegro CL 3.0.x for Windows "Toploop".)

    In processes other than the "IDE/Common Graphics" process, it is not possible to create Common Graphics entities that require event handling (eg, Common Graphics windows). Attempts to do so in Allegro CL 5.0 signal an error. Therefore, one should not attempt to run Common Graphics functions from the Console, GNU Emacs Lisp Interface listeners, or any other listener outside the "IDE/Common Graphics" process.

Known limitations of the IDE:

  1. All editor commands that need to find the boundaries of a top-level form (e.g. beginning-of-definition or incremental-evaluation-command) find the start of a form simply by searching back from the cursor position for the closest open paren in the first column. The alternative would be to parse he entire file (which is, of course, what the Lisp reader does when the compiler or loader reads the file) but this would cause unacceptable delays for large files, and would fail completely if the entire file were not syntactically correct. This is often the case when a file is actively being edited.

    Searching backwards to the closest open parenthesis in the first column is simple, fast, and almost always suffices. But be aware that editor commands may not do what you want if some internal open parenthesis of a form is unindented, or conversely, if the first parenthesis of a form is not in column one. Remember that you can reindent a form by placing the cursor on the initial parenthesis and choosing Edit | Reindent.

build.exe

build.exe is a WIN32 console app, whereas lisp.exe is a WIN32 Windows application. If you want to run a command-line oriented version of ACL, use build.exe, but otherwise you should use lisp.exe. lisp.exe is intended to be used for development and delivery of applications on Windows.

There are issues with multiprocessing and build.exebuild.exe sometimes cannot tell if input is available or if a process that is waiting on input should wake up.  For this reason, we recommend you do not use build.exe with multiprocessing applications.

Note: build.exe does not accept the arguments that begin with +.

If you are using an International version of Allegro CL, then you also have buildi.exe, which is the International version of build.exe.


Pathnames on Windows

Windows filenames are really DOS filenames, and as a result they inherit their syntax and limitations from DOS. There are some significant differences in the syntax and semantics of filenames on Windows compared to UNIX. Our pathname implementation hides most of the differences, but there are some things you need to know:

  1. / and \ can both be used interchangeably in namestrings, however when \ is written inside a string it must be doubled, as in: "foo\\bar.cl" vs. "foo/bar.cl", because \ is the string escape character. ACL canonicalizes pathnames on output to use \.
  2. Avoid making assumptions about pathname construction. For example, this is wrong:
    (defvar *root*
      #+mswindows "d:/foo/bar/"
      #-mswindows "/usr/foo/")
    ...
      (make-pathname :directory *root* ...) 

    because d:/foo/bar/ is not a valid directory component of a pathname. This string contains two pathname components, the directory and device.

    make-pathname has an interesting property: while this function is a constructor, it does parsing for the directory slot. This is what the ANSI spec says about what can be given as the value of the make-pathname :directory keyword: 

    If the directory is a string, it should be the name of a top level directory, and should not contain any punctuation characters; that is, specifying a string, str, is equivalent to specifying the list (:absolute str). Specifying the symbol :wild is equivalent to specifying the list (:absolute :wild-inferiors), or (:absolute :wild) in a file system that does not support :wild-inferiors

    In other words, (make-pathname :directory "foo") should return #p"/foo/". The current ACL behavior of allowing a string which is parsed into a directory is an extension to Common Lisp and is not portable. We preserve this behavior for only one reason: our pathname implementation predates the ANSI spec and we didn't want to make an incompatible change to make-pathname just to conform. We do feel, however, using this feature is a very bad idea.

    The alternative to the above example is to use pathname or parse-namestring to do parsing, which doesn't have pitfalls when porting to Windows (or UNIX, if you start on Windows). So, the correct way to code the above example is: 

    (defvar *root*
      (pathname #+mswindows "d:/foo/bar/"
      #-mswindows "/usr/foo/"))
    ...
      (merge-pathnames ... *root*)
  3. UNC pathnames (e.g., \\<machine name>\<share name>\<path>) are supported, however the share name must be in the device slot of the pathname--this is needed if you build the pathname with make-pathname. If you use pathname or parse-namestring, it will be done for you. For example, acl.mak exists but aclx.mak does not:
    user(21): (probe-file (pathname "\\\\hobart\\cl\\src\\acl.mak"))
    #p"\\\\hobart\\cl\\src\\acl.mak"
    user(22): (probe-file (pathname "\\\\hobart\\cl\\src\\aclx.mak"))
    nil
    user(23): (inspect (pathname "\\\\hobart\\cl\\src\\acl.mak"))
    pathname structure instance @ #x3a21132 = <...>
    0 excl-type ----> Bit field: #x0f
    1 structure-name -> (# . #), a dotted list with 1 element
    2 host ---------> A simple-string (6) "hobart"
    3 device -------> A simple-string (2) "cl"
    4 directory ----> (:absolute "src"), a proper list with 2 elements
    5 name ---------> A simple-string (3) "acl"
    6 type ---------> A simple-string (3) "mak"
    7 version ------> The symbol :unspecific
    8 namestring ---> A simple-string (23) that starts "\\\\hobart\\cl\\src\\"
    9 hash ---------> The symbol nil
    [1i] user(24): 

    It also has ramifications for logical pathname translation:

    user(8): (setf (logical-pathname-translations "foo")
               '(("bar;**;*.*" "//host/bar/**/*.*")))
    ((#p"bar;**;*.*" #p"\\\\host\\bar\\**\\*.*"))
    user(9): (translate-logical-pathname "foo:bar;")
    #p"\\\\host\\bar\\"
    user(10): (setf (logical-pathname-translations "foo")
                '(("bar;**;*.*" "//host/share/bar/**/*.*")))
    ((#p"bar;**;*.*" #p"\\\\host\\share\\bar\\**\\*.*"))
    user(11): (translate-logical-pathname "foo:bar;")
    #p"\\\\host\\share\\bar\\"

Differences when running on Windows 95 and NT

It is our goal to make the NT and 95 versions of ACL exactly the same, from your point of view. This section details the features we have been unable to make work on both systems.

On NT, the heap is mapped (from the .dxl file) into memory (with the WIN32 memory mapping primitives). This allows for much faster startup, especially starting up multiple times using the same image.  Mapping the heap does not work on Windows 95 because the memory mapping primitives do not work there (this is apparently a feature, not a bug, in Windows 95). Note that .pll file mapping does work the same on Windows 95 and NT.  See the section on pure lisp libraries for more information on .pll files.

Profiling on Windows 95 and Windows NT: in both versions of Windows we sample using a real-time clock. Under NT, a clock interrupt results in a sample if there's a thread that has used the processor most of the time since the last tick. Under 95 we can't tell how much time the processor uses, so we take a sample if the current thread owner isn't in a sleep or a wait. This really only affects non-mp mode on 95, and means that you won't get samples inside a foreign subroutine call for which lisp released the heap. Since we have no way of knowing whether such a foreign function is burning cycles or sitting in a long-term wait, we couldn't produce any reliable information from such samples anyway.


Differences between the UNIX and Windows versions of Allegro CL

  1. There is no sbrk() in the Microsoft C runtime library. The WIN32 API function VirtualAlloc() can be used to allocate large blocks of memory. This method might be preferred over using malloc(), depending on how malloc() is implemented on Windows (which is unknown to us). When using dumplisp, understand that memory allocated with VirtualAlloc() and malloc() is not saved in the resulting image file. excl::malloc does not call the C runtime library version of malloc(). It instead calls another version, internal to ACL, and this memory is saved and restored by dumplisp.
  2. The home directory for loading the ~/.clinit.cl is hardwired to c:\.
  3. The only foreign code that can be loaded into Lisp is that in Dynamic Link Libraries (DLLs). Object files themselves cannot be loaded into Lisp, as in some other, older versions of Allegro CL on UNIX. See the section on foreign functions for more information on foreign functions.
  4. In a file containing text, Windows separates lines by two characters: a carriage return (ascii #x13) and a linefeed (ascii #x10). A Common Lisp program wants to use one character (which it calls #\newline) to separate lines.

    This incompatibility is solved by specifying a mode for each Common Lisp stream writing or reading a file. The mode :text means that when Common Lisp writes a #\newline, the carriage return and linefeed characters are written to the file. Also :text mode means that when a carriage return and linefeed are read from a file the single character #\newline is returned by read-char. A file opened in :binary mode does not have this translation done.

    The mode of a stream can be specified by the :mode argument to open. If there is no :mode argument then the :element-type argument determines the mode in this way: if the element type is character (which is the default) then :text mode is used, otherwise :binary mode is used.

    One further feature of :text mode is that a Control-Z character is an end of file marker--you can't read past a Control-Z in :text mode. This is due to our use of the built-in support for text mode in Windows. If we move the text mode processing into Lisp we will likely remove this behavior.

  5. excl:run-shell-command on Windows works as it does on UNIX except in these ways:
    1. The first argument to run-shell-command has to be a string (the Unix version will accept a vector of strings).
    2. The run-shell-command command will be started directly and the Windows command shell will not be invoked to start the command. Because the Windows shell is not involved, you cannot include shell operators in the command (e.g. <, >, and |).
    3. If the keyword arguments :input, :output and :error-output are given stream values, then that stream must be open to a file on the disk. In particular a stream such as *terminal-io* will not be accepted here, nor will a socket stream nor a stream returned by a previous run-shell-command.
    4. You can start a DOS (console mode) or a Windows program with run-shell-command. Note: a Windows program is unlikely to use standard input, output or error.
    5. If you use :wait nil to run the program asynchronously, be sure to call sys:os-wait when the process finishes in order to allow the spawned process to free its resources and leave the system. This is just like on Unix.
    6. When you use streams to communicate with the spawned process, keep in mind that the streams are operating in a raw mode that doesn't translate a carriage-return linefeed to a linefeed on input, and a linefeed to a carriage return followed by a linefeed on output.

    For other changes to run-shell-command see the Changes from Allegro 4.3 to 4.3.2 section below.

  6. The SIGIO facility documented in the Allegro CL User Guide is not implemented on Windows.  This facility uses UNIX features not present in Windows, and we do not foresee implementing it in a future release of ACL on Windows.

Changes from Allegro CL 4.3.2 to Allegro CL 5.0

pathnames and file changes

  1. The functions system:mkdir and system:rmdir have been unexported. In their place, use the functions:

        excl:make-directory pathname &optional (mode #o755)
        excl:delete-directory pathname

    pathname must name an empty directory for delete-directory to succeed.

  2. New functions:

    sys:make-temp-file-name &optional prefix directory

    Return a pathname corresponding to a non-existent temporary file. prefix defaults to "temp" and is used in the construction of the name. directory is the directory used in the constructed pathname. The default value is (sys:temporary-directory).

    sys:temporary-directory

    Return a pathname containing a directory which is to be used as a temporary location by ACL. This is used by sys:make-temp-file-name. On UNIX this returns #p"/tmp/". On Windows, the environment variables TEMP and TMP are consulted, then /tmp on the current drive and c:/ are used, in order.

  3. The operation of the *open-rename-function* was altered slightly to work better on Windows 95.  First, the default suffix was made "bak" (it used to be "-old"). If the file being renamed already has a pathname type, then the name and type are combined into the name (separated by a dot) and the type is set to bak.  If the file being renamed has no type, then bak becomes the type.
  4. New function:
    sys:copy-file from to
        &key (link-ok :hard)
             preserve-symbolic-links
             (element-type '(unsigned-byte 8))
             (preserve-time t)

    Copies from to to. If :link-ok is t, then copy by creating a symbolic link. If :link-ok is :hard, then copy by creating a hard link. If :link-ok is nil, just copy the file. If :preserve-symbolic-links is non-nil, copy a symbolic link by making a symbolic link, otherwise copy normally--:link-ok is ignored if from is a symbolic link. :element-type is given to open when from and to are opened and created, respectively. If :preserve-time is non-nil, then set the time on to to be the same as from.

    Both from and `to' can be streams, in which case all the keyword arguments are ignored. This allows for copying bytes from one stream to another.

  5. New functions exported from excl package:
    pathname-as-file pathname

    Return a new pathname based on pathname which moves the last directory name in the directory component into the name. #p"" is an illegal value for pathname. Example:

    user(10): (pathname-as-file #p"foo/")
    #p".\\foo"
    pathname-sans-file pathname

    Return a new pathname with the same host, device and directory components of pathname.

    map-over-directory function directory
       &key filter include-directories

    This function is used to walk a directory structure rooted at directory. function is applied to each file in the directory, recursively. directory can contain wildcards. No useful value is returned.

    If filter is non-nil, then this is a function used to filter out candidate files and directories--the filter function takes one argument, a pathname, and returns a non-nil value if function should be called on this file. It does not prevent recursion if the pathname is a directory.

    If include-directories is non-nil, then function also gets called on directories.

    copy-directory from-dir to-dir &allow-other-keys &key quiet

    Recursively copy the contents of from-dir to to-dir. If to-dir does not exist, then it is created. sys:copy-file is used to copy the files--all keyword arguments to sys:copy-file are accepted and passed on to sys:copy-file.

    pathname-as-directory thing

    Turn thing, a file namestring or pathname, into a pathname where all of thing is in the directory component. For example, (pathname-as-directory "foo") returns the same value as (pathname "foo/"), as does (pathname-as-directory (pathname "foo")), but (pathname-as-directory "foo/bar") returns the same value as (pathname "foo/bar/").

    delete-directory-and-files directory
       &key (if-does-not-exist :ignore) quiet

    Delete all the files in directory and all subdirectories of directory. directory itself is also removed. If if-does-not-exist is :ignore, then don't signal an error if the directory does not exist. If quiet is non-nil, then don't print informative text about the operations performed.

    directory-size pathname

    Returns the size, in bytes, of all the files in pathname, which should be a directory. It recursively descends into pathname.

  6. equal now compares the host and device fields of a pathname with equalp.

compiler

  1. In certain cases apply is now compiled more efficiently, to remove consing.  Consider the following code:
    (defun foo (x &rest y) (apply fcn 1 x 2 y))

    The &rest arg is used for nothing more than to supply a variable length argument list to apply. This case is now compiled in such a way that

    1. The last arg to apply is not actually used, but an index to the n'th arg to foo is compiled instead.
    2. The &rest arg is considered dead as if declared ignored.
    3. All aspects of the function are preserved (e.g. posssible argument checking for a minimum but not a maximum number of arguments, etc.)

    In this optimized case, the code works exactly as it did when the &rest arg was consed, but without the consing.

    Circumstances that will cause this optimization to not be used are if the &rest arg:

    • is declared special,
    • is a closed-over variable,
    • is set, or
    • is used anywhere except as the last argument to apply.

    Optimization hint: the following call to apply will not be optimized:

    (defun wrap-it (flag &rest x &key &allow-other-keys)
      (when flag
        (setq x (list* :new-key 10 x)))
      (apply 'wrapped flag x))

    If non-consed operation is desired, then the following modification will allow the optimization:

    (defun wrap-it (flag &rest x &key &allow-other-keys)
      (if flag
          (apply 'wrapped flag :new-key 10 x)
        (apply 'wrapped flag x)))
  2. The comp:verify-car-cdr-switch has been reinstated. This is due to the fact that although alignment traps are caught on almost all architectures, the operating systems will not allow for recognition of misalignment, so list-ness of the object being accessed via car/cdr cannot be verified by hardware. Those versions of Allegro CL for which v-c-c-s will have an effect now have :verify-car-cdr on the *features* list.
  3. *compile-print* has initial value nil instead of t.
  4. Fasl files (.fasl) are now identifiable in their first bytes, which are textual lines. This includes architecture, dates, plus compilation settings at the time of the fasl write. As long as speed, safety, etc. settings do not change during file compilation, the textual information about these global settings is accurate.
  5. A new function, comp:list-call-direct-possibilities, is callable with no arguments and returns a list of lists of descriptions which should aid in call-direct compilation. Each list represents a kind of argument or return value, and starts with a string describing what the rest of the list describes. For those descriptions which start "bad ..." the types listed will force the compilation of a call to the function to be compiled out-of-line. The other lists describe those arg/return types that are required in order to compile the call as a direct-call. These types are lisp types or specifiers; they can either be explicitly specified as te lisp type or implied by the C type of the arg or return value (see the description of ff:def-foreign-call in fspec50.htm).

misc

  1. The common-lisp-user package no longer uses the cltl1 package.
  2. GC printing messages are turned off by default.  Put (setf (sys:gsgc-switch :print) t) in your clinit.cl if you want the default as it was in ACL 4.3.
  3. New functionality for hooks before and after garbage collection is performed:
    excl:gc-before-c-hooks                   [Function]

    Returns a list whose entries each represent a C (or C-compatible) function to call before garbage collections of any kind. The typical declaration of the C function can be

    int mybeforehook(int gctype);

    where gctype is passed in as 0 if the current gc is a scavenge and 1 if a global-gc.

    The list entry itself must be an (unsigned-byte 32) array of at least 1 entry, and its first entry must be the address of the C function.

    Setf can be used to store into the list.

    A typical usage of this feature is

    (let ((myaddr (ff:get-entry-point "mybeforehook")))
       (push (make-array 1 :element-type '(unsigned-byte 32)
                         :initial-element myaddr)
             (excl:gc-before-hooks)))

    No gc hooks are saved across dumplisps. All applications are responsible for re-establishing their own gc-before-c-hooks.

    Warning: No before hook should ever call back into lisp. The fact that during the hook call a gc is about to begin means that most likely there is no space in lisp heap. Also, it should never be assumed that the callback will not require lisp heap, even if the lisp function itself does not cons. A program whose before-hook calls into lisp may not fail the majority of the time, but it is likely to fail at some inopportumne time with disastrous results.

    excl:gc-after-c-hooks                     [Function]

    Returns a list whose entries each represent a C (or C-compatible) function to call before garbage collections of any kind. The typical declaration of the C function can be

    int myafterhook(void);

    The list entry itself must be an (unsigned-byte 32) array of at least 1 entry, and its first entry must be the address of the C function.

    Setf can be used to store into the list.

    A typical usage of this feature is

    (let ((myaddr (ff:get-entry-point "myafterhook")))
       (push (make-array 1 :element-type '(unsigned-byte 32)
                         :initial-element myaddr)
             (excl:gc-after-hooks)))

    No gc hooks are saved across dumplisps. All applications are responsible for re-establishing their own gc-after-c-hooks.

  4. The profiler has been enhanced to separate closure calls. The new keyword :interpret-closures is added to prof:start-profiler and prof:with-profiling; when nil the behavior is the same as before. When non-nil, closures are saved and analyzed as separate profile entries, even though they may use the same template function.

    A new function spec called prof:closure is added; it is valid whenever an analyzed profile exists and identifies the closures which the profiler has seen. The spec is (prof:closure <n>) where <n> is a small integer enumerating the closures in the profile. This allows the user to grab the closure object and to do a prof:disassemble-profile on it without having to know what symbol holds its fdefinition (sometimes this is very hard).

    When flat profiles and call-graphs are reported, closures are identified by (prof:closure <n>), followed by the printed representation of the closure object itself.

  5. The cltl1 package (module) is now autoloaded. In order to get previous cltl1 compatibility, (require :cltl1) or simply reference the cltl1 package (either by using find-package or by qualifying a symbol with cltl1: or cltl1::).

    The following symbols are no longer defined (unless cltl1 is required):

    cltl1::'(applyhook char-bit char-bits char-bits-limit
             char-control-bit char-font char-font-limit
             char-hyper-bit char-meta-bit char-super-bit
             define-setf-method evalhook get-setf-method
             get-setf-method-multiple-value int-char
             make-char set-char-bit special-form-p)

    The following symbols are now internal in the excl package, but are used and re-exported by cltl1 if the module is required (these are symbols that are used by Allegro CL):

    excl::'(*applyhook* *break-on-warnings* *evalhook*
            compiler-let string-char string-char-p)
  6. Top-level initialization: the first one of .clinit.cl or clinit.cl in the usually searched directories is now loaded.
  7. Information about resources.
  8. sys:*autoload-search-list* and sys:*require-search-list* have been changed to looks for the first and not newest match:
    (defvar *autoload-search-list*
      '(:first
        #1=#p"sys:;code;.fasl"
        #2=#p"sys:;sys;.fasl"
        #3=#p"sys:;winapi;.fasl"
        #+(target :microsoft) #4=#p"sys:;ole;.fasl"
        (:lib-bundle #1#)
        (:lib-bundle #2#)
        (:lib-bundle #3#)
        #+(target :microsoft) (:lib-bundle #4#)
        #p"sys:;code;.cl"
        #p"sys:;sys;.cl"
        #p"sys:;winapi;.cl"
        #+(target :microsoft) #p"sys:;ole;.cl"))
  9. Inspect: The :i command allows a new mode to be set, called raw mode; it will cause standard-instances to be viewed with no special interpretation, instead of having its slots walked in standard CLOS manner. Raw mode is remembered in deeper recursions of inspect. The :i raw or :i raw t command will set raw mode, and the :i raw nil command will unset it.
  10. inspect will now show symbols with their packages in the package slot, unless :raw is specified. It will also show struct type structures as CLOS objects, unless :raw is specified.
  11. New command line options:
    • -C file: evaluates (compile-file file).
    • -d file: causes dribbling to file.
    • -H directory: overrides the default home location calculation using directory.
    • -kill: evaluates(exit 0).
    • -L file: evaluates (load file).
    • -Q: allows quiet startup (without pll, dll and dxl messages).
    • -W: evaluates (setq *break-on-warnings* t).
  12. *trace-output* and *error-output* are bound on a per-listener basis (like *standard-input*, *standard-output*, *debug-io*, and *query-io* always have been) to *terminal-io* for that listener.  A related change: because these specials are bound in listener processes, they were removed from the bound per process variables list. Specifically, all of these variables are no longer required top-level bindings.
  13. make-array takes an :allocation keyword; valid values are: :static-reclaimable and :lispstatic-reclaimable.  The former allocates an array with an underlying vector in malloc space, and places a finalization on the array to free the object before gc-ing it away.  The latter causes make-array to allocate the array in malloc space (the garbage collector will keep all lisp-valued slots in the object valid during a gc) and when the last lisp pointer to the array goes away the array will be freed from malloc space.
  14. disassemble can now accept a first ("function") argument that is a cons of two numbers; it will interpret the first as a start and the second as the end of the address range to disassemble.
  15. New exported symbol excl:*daylight-savings-time-observed-p* is used to signify that daylight savings time should be observed.
  16. New function, sys:user-name, that returns the name of the user executing lisp.  It works on all platforms.
  17. Two changes have been made to specialized array types:
    • The fixnum array type has been removed because it caused unexpected performance problems. If an element type of fixnum is specified, it is now upgraded to (signed-byte 32), which performs exactly like the fixnum arrays did (it requires a shift, and, if Lisp values are properly declared, accesses will not require a test for bignum-ness). If storage into arrays with no shifting is desired, use arrays of type t.
    • A new nybble array is available. It is specifically a (array (unsigned-byte 4) *), and includes both array headers and simple vectors. Internal access is not extremely fast, but is reasonable. The purpose for these arrays is for space savings when dealing with 4-bit pixmaps.
  18. New function:

    (excl:convert-mixed-case-symbols bool &key push pop)

    This function effects the behavior of excl:set-case-mode to convert, or not, symbols with mixed upper and lower case characters when it is doing a symbol name conversion operation. It also affects how symbols are created during fasl file reading.

    Symbol name conversion is done for two reasons:

    1. When a call to excl:set-case-mode requires it (when going between upper case and lower case preferred modes).
    2. When fasl is reading a fasl file compiled in a case mode other than the current case mode, and those case modes differ in whether upper case or lower case was the preferred mode.

    excl:convert-mixed-case-symbols returns the previous value of this switch.

    This function is used automatically during (require :winapi) and (require :ole) since these modules intentionally contain symbols with mixed case.

    If the keyword argment :push is given a non-nil value, then the old value is pushed on a private stack kept for this function. You can then call (excl::convert-mixed-case-symbols nil :pop t) to restore the setting to the old value at the top of the stack (and to pop that value off the saved values stack).

  19. The Lisp and C heap addresses are hardwired into the default images. For the Lisp heap, if that region isn't available Lisp will allocate the first available region of the given size.  Previously, Lisp would exit with an error message.
  20. New keyword to dumplisp, :suppress-allegro-cl-banner, can be used to suppress the Franz Inc. copyright and startup banner. When this keyword argument is given to dumplisp and it has a non-nil value, then the following warning is issued: You are allowed to suppress (i.e., not display) the Franz Inc. supplied copyright banner in your application, if and only if you agree to display Franz Inc. copyright and proprietary notices wherever you display your own copyright or other proprietary notices.
  21. The time macro now prints the number of static bytes allocated. The number of bytes freed is not printed thus you cannot use the allocation information to detect static memory leaks.
  22. New arguments to the function:

    cl:make-hash-table ... &key ... values weak-keys

    :values defaults to t, which specifies that the hash table will contain both a key and a value for each entry. If :values :weak is specified, then the hash table will only hold the value as long as it is referenced non-weakly by some other object. If no other objects reference the value, it becomes nil and a gethash on the key will return nil for the value (the value is collected by the gc). If :values is specified as nil, then a sans values hash table is created, and only keys are stored as the actual values. For this kind of hash-table, maphash will call the function with a nil as the value argument, in place of an actual value (but the key will be passed in as usual). Also, gethash returns the stored key as the value (which is not necessarily eq to the given key argument), and a new function excl:puthash-key is defined for storing into these hash-tables.

    :weak-keys defaults to nil, which specifies the default behavior. When :weak-keys is specified as non-nil, the keys of the resulting hash table are treated specially by the garbage-collector: when a key in such a hash table has no more references to it, the entire entry is removed from the hash table, and the hash-table-count is decremented. This entry removal will occur regardless of whether :values :weak is specified (which by itself will never affect the hash-table-count, but only the value of an entry).

    New function:

    excl:puthash-key key hash-table

    As a side effect, may add an entry to a sans values (a key-only) hash table, if the equivalent key entry is not already in the table. Regardless of whether the given key was added or an equivalent entry is found, puthash-key returns the key that is actually in the hash-table. This allows objects to be kept in a hash-table efficiently without duplication.

  23. New symbol exported from excl package: *save-function-lambda-expression*. Initial value is nil when the compiler is loaded, otherwise it is unbound. When this symbol has a non-nil value, compile will save the function's lambda expression so that uncompile can restore it.
  24. The class precedence list of parse-error was changed from (stream-error) to (error), and the cpl of reader-error from (parse-error) to (parse-error stream-error).
  25. The space profiler will now count the number bytes allocated from static space (i.e. allocated with excl::malloc).
  26. New variable: excl::*enclose-printer-errors*. This variable controls how to handle errors which occur during printing.

    Normal printing follows all of the rules of condition-system handling; and if any handled or unhandled condition results in a call to the debugger, a new break level is established, and the user is expected to deal with the low-level printer error (which usually results from a bad print-method or a trashed object).

    But normally, a user doesn't want to debug a bad object or print method, because it is usually part of a larger problem which is either more important or is the cause of the bad printing. So, when excl:*enclose-printer-errors* is true, Those errors result in a printing of an enclosed object that describes the problem. Formerly, the object looked like #<Printer Error>, but now, the object is described including a printing of the condition, for example,

    user(1): (format nil "~{abc~:}")
    "#<Printer Error, obj=#x30000bc5: Insufficient format args>"
    user(2): 

    excl:*enclose-printer-errors* should always be bound to true whenever objects are being printed, such as in terminal and window output functions like inspectors, debugers, etc.

    excl:*enclose-printer-errors* has a default binding of t. This is a controversial decision, because it could be interpreted as a non-conformance to the ANSI condition handling rules. However, it is set to true by default to protect against unwanted break-level processing in user code, especially when non Allegro CL printing tools are used. If this default is not desired, it can be set to nil.

  27. New defsystem module options:
    • :force-dependent-recompile: causes all modules examined, after a module with this option, to be recompiled even if they are up-to-date.  The main use of this is to cause recompilation of the rest of a system because critical definitions exist in a particular module that is out-of-date.
    • :concatenate-system-ignore: non-nil value causes concatenate-system to ignore this module.
    • :force-load: always load this file during compile-system.

The foreign function interface

There is a separate document describing the foreign function interface.  See fspec50.htm in the Allegro CL directory (you can only follow this link after you have installed Allegro CL).


Changes to malloc and free in Allegro CL 5.0

Allegro CL has always used some calls to malloc to allocate static blocks of data, and has provided an implementation of malloc and free (and other functions) that is both compatible with the system version of malloc and satisfies Allegro CL's requirements. The implementation was called pdmalloc.c and was freely available in source form on the ftp site. The malloc space was always preserved using dumplisp, and the programmer could always count on any block allocated in this space to be still at the same location after the dumped lisp was restarted. Under this system, all calls to malloc were shadowed and were in reality calls to this pd version of malloc.

In Allegro CL 5.0, the malloc situation has changed. The malloc and free functions (along with other functions associated with malloc) no longer shadowed by our own implementation, but are taken again from the system libraries. Instead, we introduce aclmalloc and aclfree, and provide interfaces both in C and in lisp to these functions. aclmalloc allows three possible allocation strategies:

  1. As before, the allocated block is not at all relocatable, and any attempts to do so result in a failed lisp restart.
  2. If the block contains no internal C pointers, the block itself can be moved if necessary. The creator of the block is responsible for finding all pointers to the block and adjusting them.
  3. If the block contains C pointers internally, then it is possible to call a function to relocate pointers within that block.

Warning:  The syntax for the above changes are in place, but the functionality for items #2 and #3 are not yet implemented.  Thus, the C portion of the heap must stay in one place as of ACL 5.0.

In 5.0, a decision will need to be made as to whether the data to be allocated should live across dumplisp boundaries; if the data must live across dumplisp boundaries then aclmalloc should be used, otherwise malloc should be used.  A simple rule-of-thumb to use is this: if the data is "owned" more by lisp functionality than C functionality, it should be allocated via aclmalloc, and if the data is owned more by C functionality than by lisp then it is better to use malloc instead. But this is only a rule-of-thumb, and there will be exceptions and non-obvious cases.

Programmer interface changes

Deprecated old functionality:

C side:
malloc(), free(), realloc() [,mallopt() ...]

All of the above functions are now no longer shadowed by Allegro CL; instead calls to these functions will use the system-supplied versions. This implies that the documentation for each implementation should be consulted for usage information.

All C space allocated with the above functions should be considered volatile with respect to the dumplisp/restart lisp functionality; any such space that was allocated in the dumping environment will not be available in the restarted environment. Program code that points to such space must arrange to have new allocations and updates to these pointers upon restart (or at least before the first usage of the pointers).

Lisp side:
excl::malloc, excl::free                     [Functions]

These functions were never documented, but are deprecated in 5.0. a call to excl::malloc is equivalent to a call to excl:aclmalloc with the :restart-relocation keyword set to nil.

New functionality:

C side:
void *aclmalloc(size_t nbytes, int reloc, int rfunc)
void aclfree(void *cp)

aclmalloc and aclfree have similar characteristics as the corresponding malloc and free libc functions. The major difference is in the semantics of a dumplisp/restart, and the syntax changes are explained as descriptions of the new arguments:

reloc - if zero, the allocated block cannot move during a restart; At restart time, if the block has not been freed (with aclfree), an attempt is made to place the block in the same location as it had started, and if that fails (e.g. something is already in that location), the lisp restart fails. If reloc is non-zero, and at restart time an attempt to place the still-allocated block in the same location as it started fails, then a new place is found and the offset recorded. No attempt is made to relocate pointers to the block, except for those pointers in lisp space.

rfunc - for future expansion.  This argument is ignored.

All blocks allocated with aclmalloc are persistent across dumplisp/restarts. Whether or not a block is relocatable depends on the reloc argument. When a lisp image is restarted, the space for malloc'd objects is re-allocated, preferably at the same location as it was allocated originally. If this fails, then the lisp restart will fail unless all currently allocated blocks are marked as relocatable.

void * aclrelocate (void *cp);

Returns the adjusted value for the cp value if it is within the range of the previous location for the malloc space. If the pointer was not in the previous malloc space or if it is NULL, then it is returned unchanged.

Lisp side:
excl:aclmalloc                                     [Function]
Arguments: size &key restart-relocation

Uses the C aclmalloc() function to allocate a data block that is persistent across dumplisp/restarts. The block is guaranteed to be aligned to at least an 8-byte boundary. The returned value is an integer whose magnitude is the machine address of the allocated block.

size - specifies the number of bytes to allocate. restart-relocation (default nil) specifies how the block is to be relocated. Currently the only two options are: nil - this block cannot be relocated at restart time. t - this block can be relocated at restart time.

excl:aclfree                                       [Function]
Arguments: address

Frees a data block previously allocated with aclmalloc.

address - an integer that has been returned by either aclmalloc and that has not been passed to free since being returned from either allocation function. The block represented by this integer should no longer be used after this call.


Windows specific changes

  1. Look for the pll file first in the Windows system directory, then in the home location. This is because the ACL installation on Windows now puts the pll (e.g., acl500.pll) into the Windows system directory.
  2. On Windows, when the console window is the active window, typing the Break key will send an interrupt to Lisp. Previously the F12 key was the interrupt key. It is still the case that if Lisp is in a loop where it isn't checking for interrupts, it is not possible to break Lisp out of this loop using the Break key.
  3. Multiprocessing: see the file ug_mp.txt in the Allegro CL directory for information on changes affecting Windows multiprocessing users.  Additional notes, from the information presented in ug_mp.txt:
    1. The lisp heap is, at all times, owned by at most one process. The owning process is the only one that can run lisp code, modify the lisp state, or safely read lisp data. Because each process has an associated OS thread, any process can be running non-lisp code when it does not own the heap.
    2. All processes except the heap owner will block at a mutex before entering lisp code from non-lisp code. The OS will let only one lisp process through the mutex. That process will release the mutex by leaving lisp code (to do a process-wait or a foreign
      function call) or by finishing or dying.
    3. process-priority now interacts with the OS priority. The process-priority is mapped to a process-effective-priority by ranges. The exported symbols process-max-effective-priority, process-min-effective-priority and process-effective-priority-scale define a mapping from process-priority to the integers in the range [process-min-effective-priority process-max-effective-priority] process-min-effective-priority < 0 < process-max-effective-priority. The mapping is (truncate (process-priority p) process-effective-priority-scale). An effective-priority of 0 corresponds to the OS default priority for a thread.
    4. Regarding the :survive-dumplisp property of a process object. The value of this property determines how a process object that existed before the dumplisp is treated after the lisp restarts. In the pre-native-threads implementation, the value of :survive-dumplisp could be a function to call on the lightweight process to end its life gracefully in the newly started lisp. That is no longer possible since the stack for the threads is no longer saved. Thus this property is either true or false: false (nil) means eliminate this process object, true (any non-nil value) means start process with a process-reset.   This is likely to be problematic for old code since the typical way of specifying that a process is to be killed after Lisp starts is to put mp:process-kill as the value of :survive-dumplisp. But since mp:process-kill is a non-nil value, this now means reset the process and restart it.
  4. On Windows (as UNIX has always done) the amount of space reserved for the Lisp heap is no longer the absolute limit on the heap size. Now when the reserved space runs out, Lisp will attempt to reserve more continguous space and commit it. This will fail if the space just beyond the Lisp heap is already reserved or in use, or if there is not enough swap space left to commit the memory.
  5. The profiler works best when the scheduler is running, as in that mode it is able to take a sample nearly every millisecond. When the scheduler is not running, the profiler can, at best, take a sample every 13 milliseconds.
  6. [Windows only] There is now a low-level OLE interface.  See ole/aclcom.htm and ole/reference.htm for more information (you can only follow these links after you have installed Allegro CL).
  7. Two new functions:
    sys:stack-cushion
    sys:set-stack-cushion size

    These allow inspection and modification of the current process's soft stack limit. The cushion value is either:

    • number of longs between the current frame pointer and the soft stack limit, or
    • nil if there is no effective soft stack limit.
  8. The maximum stack size is set at 16mb. This can't be changed while the program is running.

    When a stack exceeds 8mb a continuable stack-overflow error will be signalled. More than likely it's infinite recursion that has caused the problem and the user should examine the stack to diagnose the problem.

    After reaching the 8mb size, the stack overflow size check is set to 10mb. If that is reached the overflow check is set to 12mb then 14mb and then a fatal error occurs if the stack exceeds 16mb.

    The number of bytes before a stack-overflow error is signalled can be changed at anytime using the sys:set-stack-cushion function.


UNIX specific changes

  1. Several items are now on the *features* list based on architecture and/or operating system level. The currently added or subtracted ones are: For HP: :hpux-10; for SGI: :mips2, :r2000(removed), :irix6; For rs/6000: :aix-4-2.
  2. The command line arguments for heap size and placement, below in section Changes from Allegro CL 4.3 to Allegro CL 4.3.2, are now available on UNIX.
  3. There is a new command line argument to lisp, -:, which causes the Lisp shared library (libacl50xx.so or libacl50xx.sl) to be searched for in a system dependent way.  On Solaris 2 this means using the environment variable LD_LIBRARY_PATH; other systems might use other ways.

Building custom Lisp images

In Allegro CL 4.3 on UNIX, the programs config/install_lisp were used to create custom images.  In Allegro CL 4.3.2 on Windows, the config.exe Windows program was used to create custom images.  In Allegro CL 5.0, the Lisp function excl:build-lisp-image is used to create custom images.  To use excl:build-lisp-image, you must first evaluate (require :build).

(excl:build-lisp-image image-file
                       &key ...keywords... ...dumplisp-keywords...)

The valid keyword arguments are described in the table below.

build-lisp-image calls dumplisp, after doing many other things, to create the resulting image.

In addition to these keywords, build-lisp-image accepts and passes through to dumplisp all of dumplisp's keyword arguments.  You should not specify the dumplisp :name keyword, however, since this is used by build-lisp-image.

Evaluating (excl:build-lisp-image "new-lisp.dxl") will build an image equivalent to pre-built lisp.dxl in the Allegro CL directory.

argument config equivalent default value description/compatibility notes
:autoload-warning nil If non-nil, then a report of autoloadable functions will be made to autoloads.out.  Can also be a filename to use instead of autoloads.out.
:c-heap-size nil Allows specification of the total size of the C heap.  See the discussion of the -hc_size argument above.
:c-heap-start nil Allows specification of the start of the C heap.   See the discussion of the -hc_start argument above.
:case-mode case_mode= *current- case-mode* Sets the case mode of the resulting Lisp image.  Same as ACL 4.3.
:debug-on-error t Allows debugging of problems that occur while loading the input files.
:discard-arglists nil nil means keep all arglist information, :medium means discard actual symbols used and use dummy ones, t means discard all arglist information.
:discard-compiler nil Allows the compiler to be discarded after the input files are loaded. This might be necessary for some applications.
:discard-local-name-info t Controls throwing away local name information loaded from .fasl files as a result of the compiler switch comp:save-local-names-switch.
:discard-source-file-info t Controls throwing away source file information.  A non-nil value both discards source file info in the image being created and causes the initial value of *record-source-file-info* and *load-source-file-info* to be nil.
:discard-xref-info xref= t Controls throwing away xref information.  Same as ACL 4.3.  A non-nil value both discards cross reference info in the image being created and causes the initial value of *record-xref-info* and *load-xref-info* to be nil.
:dribble-file nil Allows specifying a dribble file which contains a transcript of the entire process of building the image.
:dst dst= t Controls daylight savings time inclusion in time computations.  Same as ACL 4.3.
:exit-after-image-build t Causes the new Lisp to exit at image creation.
:generate-fonts generate _fonts= nil UNIX only. Same as ACL 4.3.
:include-all nil Same as specifying t for all other :include-* arguments.
:include-clim clim=, clim2=, and clim2xm= *** UNIX only.  When non-nil, include CLIM in the resulting image.
:include-common-graphics *** Windows only.  When non-nil, include CG in the resulting image.
:include-compiler compiler= *** When non-nil, include the compiler in the resulting image.  When nil, the compiler will not be available at any point during the image building process. See the :discard-compiler option.
:include-composer composer= *** UNIX only.  When non-nil, include Composer in the resulting image.
:include-debugger t When non-nil, include the debugger in the resulting image.
:include-devel-env devel= *** When non-nil, include the non-graphical development environment in the resulting image.
:include-ide *** Windows only.  When non-nil, include the graphical development environment in the resulting image.
:include-tpl *** When non-nil, include the normal top-level in the resulting image.  Allows specification of another (possibly minimal) top level.
:include-xcw xcw= *** UNIX only.  When non-nil, include Common Windows in the resulting image.
:internal-debug config_debug= nil Causes the forms used to build the image to be saved in a file (the value of the keyword, or build.out if the value is not a string).
:lisp-heap-size nil Allows specification of the total size of the Lisp heap.  See the discussion of the -hlisp_size argument above.
:lisp-heap-start nil Allows specification of the start of the Lisp heap.  See the discussion of the -hlisp_start argument above.
:lisp-files nil Allows Lisp files to be loaded before the image is created.   The value of this argument is nil or a list of files to load.  The files can be a pathname, string or symbol.  In the case of a symbol, it is given to require to load.
:load-source-file-info *load-source- file-info* The value of this argument serves as the default value for *load-source-file-info* in the image to be built.
:load-xref-info xref= *load-xref -info* The value of this argument serves as the default value for *load-xref-info* in the image to be built.
:newspace newspace= Same as ACL 4.3.  Default value is 2mb if the :include-devel-env value is non-nil, 6k (or larger) otherwise.
:oldspace oldspace= Same as ACL 4.3.  Default value is 2mb if the :include-devel-env value is non-nil, 256k otherwise.
:opt-debug debug= 2 Same as ACL 4.3.
:opt-safety safety= 1 Same as ACL 4.3.
:opt-space 1 Same as ACL 4.3.
:opt-speed speed= 1 Same as ACL 4.3.
:pll-file lso_file= (excl:pll-file) Same as ACL 4.3.
:post-load-form nil A form to be evaluated just after the files given by :lisp-files are loaded.
:pre-load-form nil A form to be evaluated just before the files given by :lisp-files are loaded.
:preserve-documentation
-string
t If non-nil, then preserve documentation strings in the image being created.
:presto +presto nil Same as ACL 4.3.
:presto-flush-to-code-file code_file= nil Same as ACL 4.3.
:presto-lib stub_file= nil Same as ACL 4.3.
:print-startup-message :default If non-nil and not eq to :default, then the value of excl:*print-startup-message* is set to the value of this keyword argument in the image being created.
:read-init-files excl::
*init-file-names*
The value of excl::*init-file-names* is set to the value of this keyword argument in the image being created.  It allows an application to arrange for new initialization files to be read upon startup.  See src/aclstart.cl in the ACL directory.
:record-source-file-info *record-source- file-info* The value of this argument serves as the default value for *record-source-file-info* in the image to be built.
:record-xref-info xref= *record-xref- info* The value of this argument serves as the default value for *record-xref-info* in the image to be built.
:restart-app-function nil Causes *restart-app-function* to be set to this value.
:restart-init-function nil Causes *restart-init-function* to be set to this value.
:runtime See the section below on Allegro CL Runtime.
:server-name server_name= nil Same as ACL 4.3.
:show-window :showna Windows only.  The value of the :show-window keyword to run-shell-command, used to start the process to build the image being created.
:splash-from-file nil Windows only. Allows specification of a splash bitmap file.
:temporary-directory temp= Default value is architecture dependent.  Same as ACL 4.3.
:us-government gov_flags= nil Same as ACL 4.3.
:user-shared-libraries *.so, *.sl, *.dll nil Allows loading DLLs or shared objects.
:verbose nil Causes informative messages to be printed while the destination directory is created.
:wait nil Windows only. When non-nil, it requires the ACL console window to be manually closed. This allows the contents to be inspected before the window disappears.
binary= Obsolete. This is subsumed by the image-name argument.
CC= Obsolete.
default_external _format=
estimated_max _heap_size= Obsolete.
ffhole= Obsolete.
initial _oldspace= Obsolete, due to new memory management.
library= Obsolete.
libXol= Obsolete.
main_obj= Obsolete.
nis= Obsolete.
prealloc= Obsolete.
restart _function= Obsolete.
whichclim2= Obsolete.
+clean Obsolete.
*.o Obsolete.
*.a Obsolete.
*.cvs, *.cvs.gz Obsolete. See :pll-file argument.
fasl_trace= Obsolete.

*** The default value for this keyword is based on whether or not the product or module is loaded into the image evaluating build-lisp-image.


Information specific to users of International Allegro CL

Please note the following differences with the non-International version of Allegro CL:

  1. The vector version of run-shell-command is not supported, and the non-vector version is limited to 1048 (wide) characters.

Changes from Allegro CL 4.3 to Allegro CL 4.3.2

pathnames

  1. Regarding the merging of directory components by merge-pathnames: the first argument is now translated if it is a logical pathname--before any merging is done--when that pathname is a relative logical pathname and default (the second argument) is a physical absolute pathname.

    The long explanation:

    There is a problem with the behavior of the merge-pathnames on the directory component of pathnames, when first argument is a relative logical namestring/pathname and the second argument is absolute and either 1) non-logical, or 2) logical with a different host. Examples of this are:

    (merge-pathnames "src:;sys;make.cl" "/burn/layer/")
    (merge-pathnames "src:;sys;make.cl" "bar:;burn;layer;") 

    The ANSI CL rules for merging are: 

    Pathname merging treats a relative directory specially. If (pathname-directory pathname) is a list whose car is :relative, and (pathname-directory default-pathname) is a list, then the merged directory is the value of: 

    (append (pathname-directory default-pathname)
            (cdr ;remove :relative from the front
              (pathname-directory pathname))) 

    except that if the resulting list contains a string or :wild immediately followed by :back, both of them are removed. This removal of redundant :back keywords is repeated as many times as possible. If (pathname-directory default-pathname) is not a list or (pathname-directory pathname) is not a list whose car is :relative, the merged directory is:

    (or (pathname-directory pathname)
        (pathname-directory default-pathname))  

    In the non-logical world, merging relative and absolute directories is straightforward, in that what you see in the directory namestring of the relative pathname is what is appended to the end of the absolute directory. That is: 

    (merge-pathnames "some/day/" "/burn/layer/") 

    yields #p"/burn/layer/some/day/". Very clear.

    However, with a relative logical pathname there is often a hidden directory component that you cannot see unless you perform the translation. For example, in the pathname #p"src:;sys;make.cl", there is no way, except by examining the translation itself, to know what the directory component of the translated pathname will be. So, according to the directory merging rules above (merge-pathnames "src:;sys;make.cl" "/burn/layer/") would evaluate to #p"src:burn;layer;sys;make.cl", which probably will not make any sense.

    The solution to this problem is stated at the beginning of this discussion.

    The merging rules above indirectly state that an absolute directory component as the first argument to merge-pathnames is untouched. Is #p"foo:;bar;baz.cl" a relative pathname? It is relative with respect to the directory contained in the logical translation, which is most likely different than the physical translation, often an absolute pathname.

    The only statement in the ANSI specification about logical pathnames in the merge-pathnames definition: 

    merge-pathnames returns a logical pathname if and only if its first argument is a logical pathname, or its first argument is a logical pathname namestring with an explicit host, or its first argument does not specify a host and the default-pathname is a logical pathname. 

    We feel the specification does not address the issues raised here, so we have decided on an intentional non-conformance and to translate the logical pathname under the specific conditions listed at the beginning of this discussion above.

  2. *default-pathname-defaults* in ACL 4.3 was #p"". Prior to ACL 4.3 it started as the value of (excl:current-directory), and that behavior has been reinstated. Note: there is still a difference with pre-4.3 behavior: excl:chdir does not change *default-pathname-defaults*.
  3. logical-pathname-translations has a new :autoload keyword (default value t) which causes it to look at the sys:hosts.cl file, if that file hasn't already been loaded. Normally, load-logical-pathname-translations must be explicitly called to load the translations for a particular host.
  4. (namestring (make-pathname :directory '(:absolute :wild-inferiors)))previously printed as a relative pathname on UNIX and Windows.
  5. Merging ".." with absolute pathnames changed. For example, (merge-pathnames ".." "/") returns #p"/".

foreign functions

  1. New function: 
    (ff:foreign-files &key preloaded)

    This function returns a list of pathnames corresponding to all foreign objects (shared libraries, DLLs, and object files) loaded into Lisp. If :preloaded is non-nil, then only the foreign files preloaded into Lisp are returned.   Note: system libraries appear as a pathname in the list returned by this function, however probe-file will return nil when given these pathnames, unless *default-pathname-defaults* is set to the system directory containing the system file in question.  See section Changes in the semantics of cl:load below.

  2. New function: 
    (ff:unload-file pathname)

    This function reverses the effect of loading a foreign file into Lisp.  In particular, it removes the dependency on the foreign object so that a dumplisp image does not depend on it.

  3. ff:defforeign will accept :return-type :boolean. A foreign function declared to return :boolean will return either t or nil depending on whether the foreign code returns a non-zero or zero value.
  4. When Lisp starts, the list of loaded shared libraries (.sos, .sls and DLLs) is now initialized with the ones used by Lisp. This means the external symbols of these shared libraries can be accessed without any further work on your part.
  5. Foreign data (data allocated with malloc() from C code accessed from Lisp via the foreign function interface) is not restored by running a dumplisp image, however (make-array ... :allocation :static) objects are restored. You will either need to reinitialize your foreign data or you will need to save it before calling dumplisp and restore it when your application restarts.

emacs-lisp interface

  1. Emacs-Lisp interface: fi:common-lisp has another optional argument, the Lisp image to give to the -I argument to the Lisp executable (i.e., lisp.exe). Without this optional argument, the -I argument is not passed to the Lisp executable.
  2. All versions of ACL will now use the socket-based Emacs-Lisp interface. The dependencies on ipc.cl have been removed and this module will be deprecated in the next major release of ACL on UNIX.
  3. Emacs-Lisp interface: there is a new variable, fi:define-global-lisp-mode-bindings (initial value t, to make it the same as previous releases), which causes the Lisp mode bindings to be placed on the \C-x and \e keys.

misc

  1. New keyword argument to excl:run-shell-command, :separate-streams, causes separate streams to be returned for input and output.

    The value of :separate-streams only matters when the value of the :wait keyword argument is false. In that case, :separate-streams causes Lisp to create separate stream objects for reading from and writing to the new process.

    If :separate-streams is false (and :wait is false) then you have the previous behavior, and three values are returned: the I/O-stream for communicating with the process, the error-stream for reading errors, and the process id. If :separate-streams is true (and :wait is false) then four values are returned: a stream Lisp can write to send data to the process, a stream Lisp can read to read the standard output of the process, a stream Lisp can read to read the error output of the process, and the process id.

    In all cases, nil will be returned in place of a stream if the run-shell-command arguments don't ask that a particular stream be created.

  2. run-shell-command accepts a new keyword argument on all platforms (though it only has an effect on the Windows platform for now), created by :show-window. The value of :show-window controls how the window created by the program run by run-shell-command first appears. If the application is a console application (e.g. an MS DOS program) then this value controls how the console appears. The value of the parameter is :show-window either an integer or a symbol.

    If the value is an integer it should be the value of one of the SW_ constants defined in the winuser.h include file that is part of the Windows SDK.  The symbolic value should be preferred over an integer, however, since this will be portable in the face of changes to the Windows SDK header files and use on other operating systems.

    If the value is a symbol, it should be one of the following symbols:

    nil Let the process itself determine how it will show its window.
    :normal Display a window in neither a maximized nor minimized state. Same as integer value SW_NORMAL.
    :showna Show but do not select.  Same as integer value SW_SHOWNA.
    :hide Hide the window completely. It doesn't even appear in the task bar. Same as integer value SW_HIDE.
    :minimized Display the window as an icon in the task bar. Same as integer value SW_MINIMIZED.
    :maximized Display the window as a full screen maximized window. Same as integer value SW_MAXIMIZED. Console windows can not be maximized, however.

    For Windows specific information on run-shell-command see the Differences between the UNIX and Windows versions of Allegro CL section above.

  3. rmdir and mkdir are now exported from the excl package.  THIS CHANGE IS OBSOLETED IN ACL 5.0.
  4. The home location concept has been changed.  It no longer uses the environment variable ALLEGRO_CL_HOME.  It is set automatically to be the location of the Lisp executable image.
  5. The :checkpoint argument to dumplisp has been deprecated.  A warning is issued if it is used.
  6. The default value for the dumplisp keyword name is "savedcl.dxl" (from "savedcl").
  7. In ACL 4.3, 7 consecutive errors would cause Lisp to silently exit. Now, ACL prints a message (if it can) after 100 consecutive errors.
  8. Provision is now made to build and link .pll files (new name for .lso files) into a running Lisp that does not already have a .pll file. See the section on Pure Lisp Libraries for more details.
  9. The value of the variable comp:trust-dynamic-extent-declarations-switch (on by default) is a compiler switch that controls the trusting of dynamic-extent declarations. That is, the following declaration is trusted by default:
    (declare (dynamic-extent ...))

    The value of this variable can be set to nil if you suspect you have a bad dynamic-extent declaration. This would be the case if you use a variable declared dynamic-extent past the dynamic extent of the point of creation of the variable on the stack. For example, in this definition: 

    (defun foo (&rest bar) (declare (dynamic-extent bar)) bar)

    bar is erroneously declared dynamic-extent. This could be the cause of difficult to diagnose Lisp and GC errors.

  10. The :local debugger command now accepts :x as a flag and will print integer arguments in hexadecimal.
  11. The :cd, :popd, and :pushd top-level commands now side-effect *default-pathname-defaults*, as they did in ACL 4.2. chdir is unchanged from its ACL 4.3 behavior (it does not side-effect *default-pathname-defaults*).

windows specific

  1. If the Lisp scheduler is running and the variable mp::*message-peek-mode* is set to 1, then Lisp will not process Windows messages, and instead the scheduler will set mp::*pending-windows-message* to t and then look for a Lisp process that is runnable. This means that a user can create their own Lisp lightweight process to process Windows messages. The advantage of this is that it gets around the problem that errors cannot be debugged on the scheduler stack group (which is where Windows messages are normally processed). This is an experimental feature, subject to change. This variable is initially 0.
  2. To distinguish Lisp code running on Windows (95 and NT) from Lisp code running on other platforms, you can use the :mswindows *feature*.  That is, #+mswindows before Lisp expressions will cause those expressions to be read only when Lisp is executing on Windows 95 or NT.
  3. New function: 
    (sys:set-splash-bitmap &key filename data) 

    Sets the splash bitmap to be stored in subsequent dumplisp images and then displayed when those images are started.

    Exactly one of the keywords :filename and :data should be supplied. If :filename is supplied--the value should be a namestring or pathname--then it is the name of a file that contains a device independent bitmap. Such a file typically has the extension .bmp or .dib and the contents must begin with the two characters "BM". When set-splash-bitmap is called it reads the contents of that file into the Lisp heap, thus the bitmap file needn't exist when the dumplisp is done or the image is restarted.

    If the :data keyword is given, then its value must be an one-dimensional simple-array of type (unsigned-byte 8). The contents of the array is the bitmap, beginning with the bitmapinfo header. This is different than a bitmap stored on the disk (and read when the :filename keyword is given) which begins with a 14 byte bitmap file header.

    The user-defined splash bitmap used when an image starts will be saved by subsequent calls to dumplisp, except when the +B command line option is used for the image doing the dumplisp.

  4. The following command line arguments given to lisp.exe when building Lisp images allow customization of the memory allocator used on Windows. To specify the location and sizes of the Lisp and C heaps, use these options:
    -hlisp_start lstart
    -hlisp_size lsize
    -hc_start cstart
    -hc_size csize 

    Each command line argument is followed by a base 10 number. To make the Lisp heap larger, you need only specify lsize.  For large heap sizes, however, you might find that Lisp is unable to allocate the memory.  In this case, you will see a message like this: 

    Unable to reserve the region of memory 0x20000000 (536870912)
       to 0x9cffffff (-1660944385)
    <The Lisp process exited with status 1 (0x1)>

    To successfully allocate the heap, you will need to move the starting address of the Lisp heap to a location that will support a contiguous address range specified by the heap size you chose.  If you evaluate the following forms in Allegro CL a memory map of the current state of virtual memory on your machine will be printed:

    (ff:defforeign 'memory-status-dump
      :entry-point "memory_status_dump")
    (memory-status-dump "foo.xxx")

    If the filename argument is 0, then the console is used as output.  [If you're running Lisp in :case-sensitive-upper mode, you'll have to specify the entry point to ff:defforeign.]

    When you examine the output the last four characters show the state of the page:

    • r - read access
    • w - write access
    • x - execute access
    • c - mapped copy on write (and has not been copied yet).

    Note: for ACL 4.3.2, the above call to ff:defforeign used an :entry-point of '(:index "memory_status_dump").  The above form will work in ACL 5.0 only.

    You will need to locate a large chunk of free memory and specify to -hlisp_start a starting address that will support your heap size.


The foreign function interface in ACL 4.3.2

This section contained obsolete information and has been omitted.


Changes in the semantics of cl:load

The semantics of load have been changed to accommodate finding foreign files when just a name and type are given. Because what load does is complicated, below is a description of what load actually does in post-4.3 ACL: 

  1. If the argument is a stream, load from it (as a Lisp or fasl file) and return. 
  2. If the argument pathname is "" or nil, then one of the keyword arguments :foreign-files, :system-libraries or :unreferenced-lib-names must be given. In this case, do the foreign file processing below and return. Note: on ports which have :dlfcn or :dlwin on the *features* list, :foreign-files and :system-libraries are rejected keyword arguments. 
  3. The argument filename is converted to a pathname, called the argument pathname. The argument pathname is now put through search list processing, yielding the searched pathname. If the search was successful, the argument pathname is set to the searched pathname. 
  4. If the searched pathname has a type given by *load-foreign-types* (the test is case insensitive on Windows), do the foreign file processing below and return. 
  5. If loading from the bundle or the searched pathname has a type given by *fasl-default-type* or fasl (the test is case insensitive on Windows), load the fasl file and return. 
  6. Load the Lisp source file and return. 

Foreign file processing

For versions of Lisp with :dlfcn on *features* (e.g., SunOS 5.x): 

  1. If :unreferenced-lib-names was given, then make sure all entry points are defined and return. 
  2. If the searched pathname is non-nil and there is no directory or host component to this pathname, then merge in a ./ into the pathname. This forces load to only look in the current directory for the foreign file.
  3. If the searched pathname is nil and there is a directory or host component to this pathname, then signal an error, since dlopen() will not find the pathname. 
  4. Use dlopen() to map the searched pathname into the address space and return. 

For versions of Lisp with :dlwin on *features* (e.g. Windows): 

  1. If the searched pathname is nil and the argument pathname has a directory, device or host component, then signal an error, since GetModuleHandle() will not find the pathname. 
  2. Use GetModuleHandle() to map the searched pathname into the address space and return. 

If :dlfcn or :dlwin is not on *features*, then there are no changes in foreign file processing. 


Pure Lisp Libraries (formerly .lso files)

Pure Lisp Libraries (.pll files) allow code vectors and strings to be moved from the Lisp heap into read-only files which are mapped into memory in a shared mode. This is often more efficient, because the garbage collector does not have to scan those objects and multiple Lisp (operating system) processes share that memory mapped region (on most machines). To build an application that uses an .pll file, use the following recipe (this one is Windows specific, however):

  1. Record your code vectors and strings into .cvs and .str files, respectively. After starting Allegro CL, do the following in an image with your application loaded to find all the code vectors and strings associated with your application:
    (sys:write-codevectors "foo.cvs" t)
    (sys:record-strings "foo.str"
     (let ((vec (excl::get-objects 7)))
       (dotimes (i (svref vec 0))
         (excl::maybe-purify-string
          (symbol-name (svref vec (1+ i))) t))))
  2. Run the command cvdcvt.exe (in the Allegro CL directory) to combine .cvs and .str files into a single .pll file. For example, the first command just puts your strings and code vectors into foo.pll and the second command puts those and the base Lisp ones, too:
    cvdcvt -o foo.pll foo.cvs foo.str
    cvdcvt -o foo.pll foo.cvs foo.str lisp.cvs lisp.str
  3. See Building custom Lisp images below for instructions on building a new Lisp image without a .pll file.  Let's call this image lisp2.dxl.
  4. Now, build a new .dxl file which uses your new .pll file:
    lisp -I <ACL directory>\lisp2.dxl
    (use-pll-file "foo.pll" :global-gc t)
    (dumplisp :name "foo.dxl")

Note that steps (3) and (4) can be combined into one step: using the information in Building custom Lisp images below, you can build foo.dxl directly using foo.pll, without the step of building lisp2.dxl. If you are going to build multiple images, the extra step might save you time, however.

The details

See misc.htm for more information.