XLISP-PLUS 3.05, Tom Almy’s Common-Lisp-flavoured descendant of David Betz’s
small Lisp, is now running on my VAXstations under OpenVMS VAX 7.3: bignums, ratios,
complex numbers, FORMAT, structures, and XLISP’s own object system, all from
a 590-block image. It is built with DEC C, installed for every user with an
installer and an uninstaller, and runs as an ordinary unprivileged user.
Alongside it is XLISP 1.4 from 1985, the original VAX/VMS port, rebuilt with
DEC C from the unchanged sources.
Claude Code did most of the hard work.
This one needed a source change, so the download folder has
the whole story: the upstream archives with their hashes, my patches kept apart
from the upstream files, and a recipe to recreate the kit from nothing. The
change is one new file, the “system module” that every XLISP port has to supply
(vmsstuff.c, 363 lines), plus 38 lines of configuration in the header files.
No XLISP language source was touched.
Downloads, with SHA-256 sums in SHA256SUMS.TXT:
- XLISP_VAX_305.BCK (2.2 MB): the
kit to install (a
BACKUPsaveset). - XLISP_INSTALL.COM, XLISP_UNINSTALL.COM and XLISP_SETUP.COM (each user runs it).
- README.TXT, and NOTES.TXT (the “notes for VMS users” below).
- The licence and the provenance: XLISP_LICENSE.TXT and SOURCES.TXT.
- Source kit:
the upstream archives, the patches, the build and kit procedures, the lifecycle
test and
RECREATE.md. - Examples: five programs with their expected output and the test procedure.
- The file list of the saveset: XLISP_VAX_305_LIST.LIS.
What it is
XLISP is David Betz’s tiny Lisp for microcomputers; version 1.4
(January 1985) is the one that was ported to the VAX. Version 2 added the
Common-Lisp-like parts. XLISP-PLUS, Tom Almy’s version, is the most capable
one that exists in source: arbitrary-precision integers, exact ratios, complex
numbers, &key arguments, FORMAT, DEFSTRUCT, sequence functions, and the original
class-and-message object system, in an interpreter whose VAX image is 295 kilobytes. Version 3.05 is the 2015 release.
I weighed these, all checked 14-OCT-2026:
| Version | Where | What I did |
|---|---|---|
| XLISP-PLUS 3.05 | almy.us/xlisp.html | built: needs a VMS system module (Unix, DOS, Windows, Amiga, OS X modules exist) |
| XLISP 1.4 (1985, VAX/VMS port) | DECUS VAX85A on my CD-ROM set | built unchanged; installed as XLISP14 |
| XLISP 2.0 / 2.1 (Betz) | my DECUS CDs, CMU AI repository | not built: a subset of PLUS, PC-only system code |
| “XLISP 3.0” | no source found | XLISP-PLUS’s 3.x is Almy’s numbering |
What was built
- Source:
xl305src.zip, 390,123 bytes, SHA-256f0eeb81447eff358a95b5702aaa224206cdfec64f2af8eae40ea121a0908da14, and the Lisp libraryxl305req.zip(ddee2919...), both fromalmy.us/files/. - Compiler: DEC C V6.4,
CC/NAMES=AS_IS/FLOAT=G_FLOAT/OPTIMIZE, a short DCL procedure instead of the Unix makefile; no MMS. - Measured on the VAXstation 4000/90 (71 MHz KA49): 29 modules, 0 compile
failures, 3 minutes 35 seconds in a batch job, a 590-block
XLISP.EXE. XLISP 1.4: 23 modules, 1 minute 4 seconds, a 114-block image. The kit withBACKUP: 10 seconds. - Findings that cost a build each (3.5 minutes; this machine is fast):
- the code wants
ANSIdefined (prototypes withcharparameters clash with unprototyped declarations; the Unix branch gets away with it); - the VAX default floating format, D_float, stops at 1.7E38 and the sources
compare against
1e100: I compile with/FLOAT=G_FLOAT, which has the range of an IEEE double (1E308); - the evaluation stack (4000 entries on Unix) overflows at a recursion depth
of about 1,000, so a naive
(fact 1000)died; the VMS block sets 40,000 and 60,000 and it works (1000! has 2,568 digits and prints; all five examples together run in 8 seconds).
- the code wants
The source change
XLISP keeps everything operating-system specific in one “stuff” file per
platform: the terminal, the file names, time, SYSTEM. The author’s own note
says “you’ll need to write a *STUFF.C file for your system”. The Unix one is
built around a raw termio terminal and its own line editor. On a VT-style
Telnet session under VMS the terminal driver already echoes and edits a line,
so vmsstuff.c is the short one:
- input is read a line at a time with
fgets;Ctrl/Zis end of file; Ctrl/Carrives asSIGINT(the C library turns it into one); the handler sets a flag and the evaluator’s regularoscheck()and the line reader turn it into a return to the top level. Measured: an endless(loop (setq x 1))stops at once and the prompt comes back;(system "DIRECTORY")runs a DCL command in a subprocess and returnsTfor an odd (success) VMS status, otherwise the number. An empty string is an error: the other ports start an interactive shell, which here would leave a subprocess behind a Telnet line;- file names are VMS names:
SYS$SCRATCH:XLISP_DEMO.TMP, logical names, search lists ((load "hanoi")looks inXLPATH:first, then the current directory); - backup copies are not made: VMS file versions are the backup.
xlisp.h gets an #ifdef XLVMS block modelled on the Unix one, and the two
function-table headers lose GET-KEY (it needs a raw terminal). That is all;
the patches are separate files in the source kit, with a reason for each hunk.
Installing and using
You need OpenVMS VAX 7.3 and SYSTEM (or SYSPRV). About 3,700 free blocks.
- Put the saveset and the two
.COMfiles in one directory on the VAX (.BCKin binary,.COMin ASCII; the installer puts back the saveset’s record attributes that a binary transfer loses). - As
SYSTEM:$ @XLISP_INSTALL. It restores 112 files intoSYS$COMMON:[SYSLIB.XLISP], writes a manifest (name, size and revision date of every file), and smoke-tests the result. NoINSTALL, no rights identifier, no startup or login file, no account touched. Measured: the whole procedure takes 20 seconds on the 4000/90 and 30 on the 4000/60. - Each user:
$ @SYS$COMMON:[SYSLIB.XLISP]XLISP_SETUP, then$ XLISP.
$ XLISP
XLISP-PLUS version 3.05
Portions Copyright (c) 1988, by David Betz.
Modified by Thomas Almy and others.
OpenVMS VAX version
...
> (defun fact (n) (if (<= n 1) 1 (* n (fact (- n 1)))))
fact
> (fact 40)
815915283247897734345611269596115894272000000000
> (list (/ 1 3) (+ 1/3 1/6) (sqrt 2) (float (/ 355 113)))
(1/3 1/2 1.41421 3.14159)
> (system "WRITE SYS$OUTPUT F$GETSYI(\"HW_NAME\")")
VAXstation 4000-90
t
> (exit)
That is a real session as USER1 on the 4000/90. XLISP14 starts the 1985
version (integers only: 1.5 is not a number to it).
@XLISP_UNINSTALL CHECK shows what would go, @XLISP_UNINSTALL does it: only
the files the manifest lists, and only if they are still as installed; a file
you changed, or put in the directory, stays, and so does its directory.
Notes for VMS users
ERRSETonly catches an error when*BREAKENABLE*isNIL. Otherwise XLISP enters its break loop (1>) first.(setq *breakenable* nil).READ-LINEat end of file is an error, as in Common Lisp:(read-line stream nil nil)returnsNILinstead.DELETE-FILEremoves the newest version only (it is the Cremove). A second run of a program that createsX.TMPand fails before deleting it leavesX.TMP;1behind, and the nextOPENof the name finds it.- The Telnet terminal driver breaks a line at the screen width; the same program with its output redirected to a file does not, so the expected-output files have lines of over 80 characters (100!) where a terminal shows two.
- Switches go in quotes (
XLISP "-b" FILE.LSP): DCL changes case.-bis “batch”: an uncaught error ends the program instead of entering the break loop. WithSYS$INPUTredirected (DEFINE/USER SYS$INPUT NL:) the program exits at end of input, which is how the test procedures use it. Ctrl/Yreturns to DCL and leaves the program suspended;CONTINUEresumes it (measured once: the first line typed afterCONTINUEwas not seen; press Return first), anything else ends it. Measured:LOGOUTafterCtrl/Yleaves no process.- XLISP-PLUS’s own library prefers its package system:
(load "common")first if a library file complains aboutprovide.
Examples
Five programs in [.EXAMPLES] (and the zip): all produce the same output on both
machines, and RUN_EXAMPLES.COM compares each with its .EXP file. I checked
the numbers against an independent calculation (Python’s integers and fractions),
not only against themselves.
RECURSION.LSP: factorial with bignums (30!, 100!, 1000! has 2568 digits), Fibonacci, Ackermann, Towers of Hanoi (1023 moves for 10 disks),2^200,gcd(20!, 2^70) = 262144,1/3 + 1/6 = 1/2, the Collatz length of 27 (111).DERIV.LSP: a symbolic differentiator with simplification, then numeric evaluation of the derivatives (d/dx x^5at 3 is 405).OBJECTS.LSP: XLISP’s own class system: ashapeclass with a class variable,circle,rectangleandsquaresubclasses,send-super, an account object that refuses an overdraft. With355/113for pi the areas are exact ratios:35500/113and a total area of39681/113.FILEIO.LSP: write a file by VMS name, read it back (READ-LINE,READ), count lines and words, delete it.VMSDCL.LSP:(system ...)with DCL lexical functions (F$GETSYI("VERSION")printsV7.3) and the status values it returns.
Tests
All measured on the real machines, as the unprivileged USER1 over Telnet.
LIFECYCLE_TEST.COM: install; refused second install; uninstallCHECK; uninstall that keeps a changed file and a user’s file in a sub-directory; uninstall; second uninstall says “not installed”; reinstall;REPLACE. 21 of 21 passed, in 1 minute 58 seconds on the 4000/90 and 3 minutes 9 seconds on the 4000/60.RUN_EXAMPLES: 5 of 5, 8 seconds on the 4000/90 (19 seconds on the 4000/60).- A REPL session: evaluate,
LOADby full VMS name and fromXLPATH:, an endless loop andCtrl/C,Ctrl/Z,(exit),Ctrl/YandCONTINUE;SHOW USERSafterwards each time: no process left.
Not measured
- I did not run XLISP’s own regression suite (
[.LSP.VERIFY]) as a gate; it is installed. - Saving and restoring a workspace (
SAVE,RESTORE) is compiled in but I did not test it on VMS. - Graphics,
GET-KEYandPOPENare not available, by choice. - I did not try VAX C, GNU C or Alpha/Itanium; the system module should work with any DEC C but I have only run the VAX.
Licence
XLISP is not free software in the GNU sense. Every XLISP source file carries
Copyright (c) 1985, by David Michael Betz
All Rights Reserved
Permission is granted for unrestricted non-commercial use
and Tom Almy’s page says “distribution is limited to non-commercial or
educational use”. The 1985 version says the same in its manual (“free of charge
to non-commercial users”). So: non-commercial use only. I redistribute the
kit on that basis, with the notices intact (the exact texts are in
XLISP_LICENSE.TXT). Most of the contributors to XLISP-PLUS put their work in the
public domain; the installer, uninstaller, setup procedure, the system module
and the examples are mine, under the same terms as XLISP.
