SNOBOL4 for VAX OpenVMS 7.3
My VAXstations now have SNOBOL4: the original Bell Labs SNOBOL4, the
string-processing language with patterns as values, built from a 1997
public-domain C translation of its portable implementation, as a kit for
OpenVMS VAX 7.3, with a handful of VMS-specific functions added: process,
system and device information, logical names, wild-card file searches and
RMS indexed files you can read and write from a SNOBOL4 program. The kit
is a BACKUP saveset with a DCL installer and a DCL uninstaller; it needs
nothing on the target but the tools every VMS has. The interpreter passes
all the regression tests that come with it.
Claude Code assisted, which (as usual) is to say, did much of the hard work.
One correction first, because I made the mistake myself: this is not Macro SPITBOL. My notes said I had Dewar’s SPITBOL on the DECUS tapes. I do not: the directory named in the note has no SPITBOL, nobody publishes a VAX/VMS SPITBOL source that I could find, and what the DECUS tapes really hold is the Bell Labs SNOBOL4 in C (1997, 1994 and an earlier native VAX translation from TRW, 1982). The interpreter here is the genuine article, the language of the “green book” (Griswold, Poage and Polonsky), with the SPITBOL-compatible extras Phil Budne added.
Downloads, with SHA-256 sums in SHA256SUMS.TXT:
- SNOBOL4_VAX_20261012.BCK (2.6 MB): the kit to install.
- SNOBOL4_INSTALL.COM and SNOBOL4_UNINSTALL.COM.
- README.TXT, which says everything below about installing in more detail, and SHA256SUMS.TXT.
- Source kit (524 KB): the original distribution as shipped, our eight changes as diffs and whole files, the build, kit and test procedures, the host tool, and the recipe to recreate the kit from scratch.
- Examples and tests: the programs below, their inputs, and expected output.
- The file list of the saveset: SNOBOL4_VAX_20261012_LIST.LIS.
SNOBOL4 is in the public domain; the notice is quoted below.
What SNOBOL4 is
A SNOBOL4 program is a list of statements, each with an optional label, a subject, a pattern, a replacement and a goto on success or failure. Patterns are first-class values you build, store in variables and combine, and matching backtracks through alternatives. A word-counting program is a loop and one statement:
SCAN LINE BREAK(&LCASE) SPAN(&LCASE) . W = :F(READ)
T<W> = T<W> + 1 :(SCAN)
BREAK(&LCASE) skips to the next letter, SPAN(&LCASE) . W captures the run of
letters into W, = deletes what matched from LINE, and the failure branch
goes back for the next line. T is a table indexed by strings. Here is the
keyword-in-context program of the picture above, doing the same with cursor
positions (@A, @B):
SCAN LINE POS(P) BREAK(LET) @A SPAN(LET) . W @B :F(READ)
SNOBOL4 is where the idea of patterns as data comes from, in the work of David Farber, Ralph Griswold and Ivan Polonsky at Bell Labs in the 1960s; Icon (the sibling post, by Griswold at Arizona) kept strings and threw the patterns away for goal-directed evaluation.
What was built
CSNOBOL4, Phil Budne’s “C-MAINBOL”, “The Macro Implementation of SNOBOL4 in C”, version 0.99.4 of August 1997, is the original Bell Labs SIL (SNOBOL4 Implementation Language) version 3.11 of 1975, translated into C by a SNOBOL4 program. Its README is short on ceremony:
This material is in the public domain. You may use and copy this material freely. This privilege extends to modifications, although any modified version of this system given to a third party should clearly identify your modifications as well as the original source.
All my changes are marked as mine; the kit’s SOURCES.TXT lists them.
It builds natively on the VAX with Compaq C V6.4, in 55 modules, no MACRO, no
MMS. What it needed (all eight changes are small and in the source kit):
- The shipped VMS build files describe the 0.91 sources of 1994, not these: wrong file names, missing objects. A source list file and a 53-line DCL procedure replace them.
/NAMES=AS_IS, because SNOBOL4’sany,sin,delete,exit,link… collide with the C library once names are upper-cased.- Two library functions with the same names as the C library’s: the private
getoptand the SIL procedureLINK. - The 1994 VAX C
times()is gone:clock(). - Two output bugs, both with the same cause (DEC C’s
fwrite(p, 1, n, f)on a record file writes every byte as a record): the>fileredirection helper and plain output into a DCL-made file (a batch log,SPAWN/OUTPUT=) – each line was printed as a column of single letters. - The
-INCLUDElibrary directory is the logical nameSNOLIB:.
Talking to VMS
SNOBOL4 on VMS cannot LOAD() a shared image, but the implementation has
“Poor Man’s LOAD”: external functions linked into the interpreter. Ours are in
vmscall.c:
GETJPI('USERNAME') GETSYI('VERSION') GETDVI('SYS$SYSDEVICE','FREEBLOCKS')
TRNLNM('SYS$NODE') GETTIM() VMSMSG(status) FINDFIRST('SYS$LIBRARY:*.OLB')
RMSOPEN('BOOK.IDX', 12, 60) RMSPUT RMSGET RMSDEL RMSREWIND RMSNEXT RMSCLOSE
The RMS functions give a SNOBOL4 program a keyed, persistent database: an indexed
file with fixed records and the first bytes as the primary key. A pipe to a DCL
subprocess also works (INPUT(.X, 99, , '|SHOW TIME')), through the C library’s
popen.
Installing
You need OpenVMS VAX 7.3, SYSTEM (or SYSPRV), and about 11,000 free
blocks on the system disk while installing. No compiler.
Put the saveset and the two
.COMfiles into one directory on the VAX. Transfer modes matter: the.BCKin binary, the.COMfiles in ASCII.A binary transfer loses the saveset’s record attributes; the installer puts them back itself:
$ SET FILE/ATTRIBUTE=(RFM:FIX,LRL:32256,MRS:32256,RAT:NONE) - SNOBOL4_VAX_20261012.BCKAs
SYSTEM:$ @SNOBOL4_INSTALL(12 seconds on the simulator, 40 on the VAXstation 4000/96, for 375 files.)
Each user, at the prompt or in
LOGIN.COM:$ @SYS$COMMON:[SYSLIB.SNOBOL]SNOBOL4_SETUP $ SNOBOL4 "-b" HELLO.SNO $ SNOBOL4 "-b" "-u" "BOOK.IDX" RMSBOOK.SNO "<COMMANDS.TXT" ">OUT.TXT"
DCL lower-cases an unquoted argument and SNOBOL4’s options are case-sensitive, so the options are quoted.
@SNOBOL4_UNINSTALL CHECK says what an uninstall would remove, and
@SNOBOL4_UNINSTALL does it: only files the manifest lists and that are
still as installed.
Examples (all with expected output and a test)
RUN_TESTS.COM runs 12 test cases from 10 programs and compares each with an
expected output made on the Linux host by an independent Python
implementation of the program’s specification (not by running the VAX
program):
| Program | What it shows |
|---|---|
WORDFREQ | tables, sorting, BREAK/SPAN |
CALC | recursive descent over patterns, error reporting, truncating integer division |
QUEENS | recursion and backtracking: 2, 10, 4, 40, 92 solutions for N = 4..8 |
KWIC | @ cursor assignment, SORT of a two-column table (the picture at the top) |
BF (+ HELLO.BF, REVERSE.BF) | a Brainf*** interpreter (a TABLE as the tape, computed goto), with bracket matching |
SYSINFO | GETJPI/GETSYI/GETDVI/TRNLNM checked against DCL’s own lexical functions |
RMSBOOK (two runs) | an address book in an RMS indexed file; the second run finds the first run’s entries |
FILES | FINDFIRST/FINDNEXT, then each file read with ordinary SNOBOL4 input |
VMSLIB_DEMO | -INCLUDE of a library found through the logical name SNOLIB: |
PIPES | DCL subprocess output through INPUT |
Results
Measured on a simulated MicroVAX 3900 (SIMH, OpenVMS VAX 7.3), except where the real machine is named:
- Build, link included: 45 s for 55 modules (the largest, the 215 KB
generated
ISNOBOL4.C, 22 s). The recipe from the original sources to a tested kit takes 1 min 7 s in one batch job. Simulated-VAX times say little about a real VAX; they are ratios. - The shipped regression tests: 64 of 64 pass (three of the test files need 8-bit or CR data that the text bundle used to move the sources cannot carry; they are reported as not in the tree).
- The 12 example tests: 12 of 12 as a fresh unprivileged user with the installed kit, 2.7 s.
- The kit: 5,166 blocks (2,644,992 bytes); 375 files once installed (4,283 blocks).
- QUEENS for N = 4..9 executes 459,992 statements, 165,845 of them failing, in 4.94 s of simulated CPU; the Linux host build executes exactly the same number.
- The lifecycle test (install, refuse a second install, uninstall
CHECK, uninstall that keeps a changed file and a user file,REPLACE, reinstall): 21 of 21 checks. - On my VAXstation 4000/96, installed system-wide on 12-OCT-2026: the 12 example tests passed, 9 s, and the 64 shipped tests passed, 30 s.
- The 1982 native MACRO-32 SNOBOL4 by Wendell Turner of TRW (
sno.exe, from DECUS VAX 84A), linked on a VAX/VMS of 1982-84, runs unmodified on VMS V7.3 and prints a factorial table: a different implementation of the same language, more than four decades apart.
What I did not check
- Real hardware, mostly: only the VAXstation 4000/96 (above). Not the 4000/60 or any other VAX.
LOAD()of shared images: not available on VMS; external functions are linked in.- Macro SPITBOL, as said above: no VAX source exists in any collection I could find. CSNOBOL4 2.x (a much later version) I did not attempt.
- Alpha and Itanium: nothing; this is a VAX build.
Rebuilding
REBUILD.md in the source kit has every command, in order, from
snobol-0_99_4.tgz (hash given) to a tested kit with the time of each
step. The VAX has no tar, so the tree goes over as one ASCII bundle made
by a small Python 3 script and is unpacked by a 60-line C program; the
whole rebuild is then one batch job.
How this was done
As with Emacs, Perl and Poplog: Claude sessions with written briefs, on a VAXstation and a simulator, with the rule that nothing counts until a test shows it, and the transcripts kept. Every number above comes from one of those transcripts.
Credits: David J. Farber, Ralph E. Griswold and Ivan P. Polonsky for SNOBOL4; Philip L. Budne for the C translation (CSNOBOL4) and its VMS build files; the DECUS library, which kept all of it; and Claude Code (Anthropic’s Claude models) for much of the building, debugging, testing and writing.
