Stanford WAITS

WAITS was the operating system for the PDP-6 and PDP-10 at the first incarnation of the Stanford AI Laboratory (SAIL), running continuously from 1966 to 1991. Uniquely, its full file system was preserved and a snapshot of the system can be run under emulation.

/images/waits/sail-collage.jpg Collage of images from a visit from DEC staff to SAIL, 1976. Source: CHM.

SAIL was founded by John McCarthy in 1963 (before Stanford even had a CS department) with 6 researchers. This grew to 128 people by 1973, by which time the lab had became one of the principal centres for AI research. Work spanned robotics, heuristic programming, NLP and computational theory. Among its alumni were Arthur Samuel, Raj Reddy, Hans Moravec and Alan Kay. Several people not associated with AI also made the lab their home, including Whitfield Diffie, John Chowning and Donald Knuth.

SAIL started out with a PDP-1, for which they implemented a time-sharing system with interactive displays. No traces of this remain, but there is an amusing film about its superiority to batch computing. In 1966, they got a PDP-6. WAITS started off as a version of DEC's Monitor (the forerunner of TOPS-10) but was extensively modified to suit the needs of the lab. It was notable for its support of experimental peripherals - robot arms, autonomous vehicles, display terminals, audio/visual support, and the XGP, one of the first laser printers. Over its lifetime it moved from the PDP-6 to the PDP-10 KA in 1968 and then the KL, added paging (from Tenex) and more memory and disk. As of 1973, it had 256k words of memory, 86M words of disk and 64 display terminals. It was one of the first machines connected to the Arpanet. It was also installed on machines outside of SAIL for a brief time, including at Lawrence Livermore National Labs.

On the software side, most AI research was done in Lisp, but it also spawned its own dialect of Algol called SAIL, and a powerful assembler called FAIL. It had several text editors that made use of its interactive terminals, and had document compilers that could use the XGP, including the first version of TeX.

Incidentally, the name WAITS was adopted several years after the system was introduced, and there are multiple explanations for the name: Western AI Time-sharing System, West coast Alternative to ITS, Worst Acronym for a Time-sharing System, or simply that it waits on you hand and foot.

Preservation status

/images/waits/saildart.org.png Screenshot of saildart.org. Source: Rupert Lane. License: CC0.

The complete backup tapes for WAITS have been preserved and are available for access. Bruce Guenther Baumgart, who worked at SAIL, was asked by John McCarthy to preserve the tapes produced by the DART archive tool when the system was shut down. He has built an amazing archive site, saildart.org, where you can access files, documents and other information about the system. (Personal files are not publicly available.)

For most operating systems we will look at, we only have the material to install the officially published software. But in this case we have the full file system, so we get to see all the surrounding files that made up a living system. Most of the documentation for WAITS was produced on WAITS, so it is available in its original digital form. Also, as an incremental backup, we can see how files changed over time.

Beyond the file archive, Bruce has produced a snapshot of the system as of July 1974 - representative of the lab's peak activity period - that can be used by emulators.

Emulation status

There are two emulators for WAITS.

/images/waits/waits-saildart-emu-montage.png WAITS running on saildart.org's emulator. Source: Rupert Lane. License: CC0.

Bruce has produced an emulator that uses the 1974 snapshot and runs in your web browser at saildart.org. This has demonstrations of a number of interesting systems such as SUDS, the Stanford University Drawing System. It also has interactive access to the complete system using either the console or the III display terminal, so you can login and run commands. Without any additional setup, this allows you to try out the system, but note that your work is not persisted across sessions.

/images/waits/waits-simh.png WAITS running on simh. Source: Rupert Lane. License: CC0.

Richard Cornwell has adapted his simh PDP-10 KA emulator to incorporate some of the special hardware used by WAITS, and has provided disk images on his site. The emulator contains support for the III and DD display terminals, along with networking capabilities, which Lars Brinkhoff is currently trying to recreate its Arpanet connection at sailing-on-arpanet. The simh version needs some set up, but does allow you to import/export files and keep your changes over several runs of the system.

One important thing to note: neither emulator has complete coverage of WAITS features, and some programs do not work. This is not due to lack of effort on the part of the authors, rather due to the non-standard nature of the SAIL hardware, which often lacks docs and diagnostics, and the fact this is a snapshot of a running system rather than an official release.

Topics

In this series of blog posts I plan to cover

  • A quick tour of running WAITS on simh
  • Using the terminals
  • Files and directories
  • Users, jobs and security
  • Utilities and tools
  • Text editors
  • Getting data in and out of the system
  • Printing and documentation tools

    • The XGP
    • PUB
    • POX
    • TeX
  • Programming

    • SAIL
    • LISP

The main focus of this blog is the operating system and its associated tools, so I will not look in detail at all the user programs available on WAITS - but if time permits, I will try to cover some interesting examples.

Further information

For background information on the PDP-10, see my previous article.

As mentioned, there is a great deal of information on saildart.org. A good place to start is the booklet which gives an overview of SAIL WAITS, and the archive project. The Visitor 1976 gives a photo tour of the lab along with some of its equipment and people.

For more detail, look at the collection of AI Memos and SAIL Operation Notes, or dig further into specialised areas on the main page such as music.

References to files on the SAIL system can be viewed by prepending saildart.org. For example, to read the Lisp manual LISP.WD[S,DOC] you would go to https://www.saildart.org/LISP.WD[S,DOC]

AI Memo 228 gives a good overview of the work done at SAIL in its first 10 years.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


Site Update

That's all, for now, on TOPS-10. I've concentrated on the roughly pre-1975 era, using the PDP-10 KA CPU and operating system version 6.03; I may come back to this in the future and look at later versions if I find anything interesting.

Next update to this blog will be in June, where we will look at the Stanford University A.I. lab's operating system for the PDP-10, WAITS. This started out as a version of DEC's PDP-6 Monitor (which became TOPS-10) but WAITS evolved over the years to add support for experimental peripherals - display terminals, laser printers, robotics - and many interesting software features, as well as being an important platform for A.I. research.

As a taste of WAITS, here's a small demo I was involved in recently. PARRY, a chat program that mimics a paranoid patient, was written by Kenneth Colby on WAITS in 1972. Using simh, Lars Brinkhoff got PARRY running on WAITS for the first time in many years. I then got this talking to the ELIZA chat program running on CTSS, recreating a dotctor/patient dialogue done in 1973 as RFC 439. See Jeff Shrager's writeup, PARRY Parries Again, for more details.

Questions, corrections, comments

May 2026: Lars Brinkhoff correctly pointed out that WAITS derived from the PDP-6 Monitor rather than TOPS-10.

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


TOPS-10: Essex BCPL

BCPL - Basic Combined Programming Language - is probably best known as the ancestor of the C programming language made famous by Unix. But BCPL was an important and widely used language in its own right. First implemented by Martin Richards for CTSS, it spread to many different architectures during the 1970s, especially in the UK where it was used for teaching computer science, AI and in industry.

(Incidentally my first ever job, as an intern in 1990 working for the former British semiconductor company Inmos, was writing CAD tools using BCPL on a micro-VAX).

Essex BCPL for TOPS-10

The version we are looking at today for TOPS-10 is from the University of Essex and dates from the mid 1970s. The original compiler by Richards generated machine code for a generic stack machine, called OCODE, and the compiler itself was available in OCODE, so it was easy to port to new machines. Essex produced a version for the ICL 1900 to start with, and moved this across to TOPS-10 on their new PDP-10 in 1970. They then rewrote the compiler to remove the OCODE layer and improve performance.

This second implementation of BCPL is included in the TOPS-10 6.03 disk images we are using so there are no special set up instructions. The compilation system recognises files with a .BCP extension by default. Here's what a hello world program looks like and how to run it:

.type hello.bcp
GET "BCL:BCPLIB"
LET START() BE
$(
	WRITES(TTY,"Hello, world*C*L")
$)

.execute hello.bcp
BCPL:  HELLO	400031/2	32%
LINK:	Loading
[LNKXCT BCPL Execution]
Hello, world

EXIT

TPK in BCPL

Let's use the compiler to run the TPK algorithm. The source code can be found here. This can be loaded onto the disk using the techniques described in this article.

The TPK formula (√|x | + 5x³) is implemented as a function with a single expression:

LET TPK(X) = SQRT(#ABS X) #+ 5.0 #* X ** 3

As BCPL is typeless, different operators are needed for floating point and integer arithmetic such as #+ for floating point add. Note also that #ABS is a unary operator.

However, we have a problem in that SQRT is not part of the language library at this point in history. We can implement it using the Babylonian approximation:

LET SQRT(X) = VALOF
$(
    LET X1, X2 = X, X #/ 2.0
    WHILE #ABS (X1 #- X2) #> 0.0001 DO
    $(
        LET OLD = X2
        X2 := 0.5 #* (X1 #+ (X2 #/ X1))
        X1 := OLD
    $)
    RESULTIS X2
$)

This uses a VALOF expression which yields its results using RESULTIS. As there is more than one statement we use a block, marked by $( ... $). Semicolon can be used to separate statements, but is not needed if there is a single statement per line.

Inside the block we define a variable, LET OLD = X2, but note that assignment uses := ad plain = is used for comparison.

With this, we can supply the driving logic in START, BCPL's equivalent of C's main.

// Define constants
MANIFEST $( N = 11; IOVS = 300 $)

// Main program
LET START() BE
$(
    LET A = VEC N
    LET IOVECTOR = VEC IOVS
    INITIALISEIO(IOVECTOR, IOVS)
    WRITE(TTY, "Please enter :N numbers*C*L", N)
    FOR J = 0 TO N-1 DO A!J := RDF(TTY)
    WRITE(TTY, "Results are*C*L")
    FOR J = N-1 TO 0 BY -1 DO
    $(
        LET R = TPK(A!J)
        TEST R #> 400.0 THEN
            WRITE(TTY, "Too large*C*L")
        OR
            WRITE(TTY, ":F*C*L", R)
     $)
$)

BCPL allows both single line comments with // and block comments with /* ... */. C initially only took block comments, with single line comments first re-implemented by C++ and coming back to C in the 1999 standard.

MANIFEST sets up compile time constants, which we can use when declaring the stack vector LET A = VEC N. Elements of this vector can be accessed using infix !, eg A!2. Two FOR loops are used, one counting forwards to read in numbers and the second counting backwards to calculate and print results. BCPL has IF, but it only supports a single clause for the true case; TEST ... THEN ... OR supports both true and false cases.

I/O is done using RDF to read in a single floating point value and WRITE for output. I/O is stream based, and we use the predefined value TTY to communicate with the user's console. INITIALISEIO is needed before we use I/O to allocate buffers. WRITE supports output of different types using : as positional markers, eg :F for a floating point number. *C*L in the string means carriage return / line feed.

A full transcript of the program execution can be found here.

Further information

The Github PDP-10 organisation has the essex-bcpl repo which contains the source tape and manual for the version of the language. There is also MUD1 which is an early multi-user dungeon written in BCPL; this looks like it needs TOPS-10 7.03 and a KI CPU to run, however.

A completely separate implementation of BCPL on TENEX from BBN can also be found at tenex-bcpl.

The Computer History Museum Software Preservation Group has a detailed history of BCPL, including links to documents, papers and other implementations.

The classic reference to BCPL (and what I originally leaned the language from) is "BCPL - the language and its compiler" by Martin Richards and Colin Whitby-Strevens; there's a copy at the Internet Archive.

Martin Richards continues to work on BCPL and his home page has links to implementations for modern computers.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


AID - the JOSS language for TOPS-10

AID, or the Algebraic Interpretive Dialogue, was DEC's first public version of the JOSS interpreter for the PDP-6/10.

JOSS - the JOHNNIAC Open Shop System - was an early time-shared language created at the RAND corporation in 1963. This ran on JOHNNIAC, a computer they had built in house, and offered 20-30 users who were not expert programmers the ability to write short mathematical programs.

By 1964 the JOHNNIAC was not powerful enough to support demand so RAND and DEC worked together on a successor, JOSS-II, to run on the new PDP-6. This was a complete operating system allowing multiple users to run JOSS from their own teletype.

AID is a standalone version of JOSS that runs as a normal program on TOPS-10. I'm not sure on how much of the code of JOSS-II is in AID, but DEC's manual says:

Digital Equipment Corporation is grateful to The RAND Corporation for permission to adapt the language processors of JOSS for the PDP-l0.

Installing AID

By default, AID does not come with the 6.03 version of TOPS-10 we are using, so we will need to restore it first from a tape of customer supported programs from pdp-10.trailing-edge.com.

  • Get a copy of this tape file and decompress it using bunzip or similar.
  • Copy it to your simh installation directory.
  • With TOPS-10 running, press Control-E on the simh console and attach the tape file to MTA0
sim> at mta0 bb-x130a-sb.tap
%SIM-INFO: MTA0: Tape Image 'bb-x130a-sb.tap' scanned as SIMH format
sim> continue
  • Log in to TOPS-10 as user [1,2], password FAILSA. Run BACKUP and restore the executable file to SYS:
.r backup

/tape mta0:
/rewind
/restore dskb:[1,4]=aid.exe
!
"Done

/exit
  • Finally, still as [1,2], set permissions:
.protect sys:aid.exe <155>

AID can now be run via R AID by any user.

Using AID

After you start AID, you can enter simple expressions at the * prompt.

.r aid
AID 20A(32) AT YOUR SERVICE ...

*type 22/7
	22/7 =	      3.14285714
*a = 12
*b = 30
*type a+b
	 a+b =	     42

or you can enter programs, using decimal line numbers:

*1.0 Do part 5 for i=1(1)5
*5.0 Type "Hello, world"
*do part 1
Hello, world
Hello, world
Hello, world
Hello, world
Hello, world

Note that loops can be added at the end of any expression: here we call part 5 (the hello world print) via for i=1(1)5 with the numbers being the initial, step and final value.

Just like the original JOSS, any errors you make will be reported with the single message "Eh?"

It's possible to save your code (and variables defined in the environment) to a disk file. First you specify a file number to work with:

*use file 123
Roger.

and then save your code to a item number under that file:

*file all parts as item 5
Done.

If you quit out of AID with a Control-C and do a DIR you can see the file that has been created - in this case QQ0123.J05. This is in binary format and so cannot be easily manipulated by editors such as SOS

To load in the code from disk:

*use file 123
Roger.
*recall item 5
Done.
*list all parts

1.0 Do part 5 for i=1(1)5
...

Running TPK

Let's use AID to run the TPK algorithm. The source code can be found here but will need to be typed in to the interpreter directly.

.r aid


AID 20A(32) AT YOUR SERVICE ...

*1.000 Let t(x) = sqrt(!x!) + 5 * x ^ 3.
*1.010 Type "Please enter 11 numbers".
*1.020 Do part 2 for j=1(1)11.
*1.030 Type "Results are".
*1.040 Do part 3 for j=11(-1)1.
*1.050 Stop.
*
*2.000 Demand a(j).
*
*3.000 Let r = t(a(j)).
*3.010 Type "Too large" if r > 400.
*3.020 Type r if r <= 400.
*
*do part 1
Please enter 11 numbers
	a(1) = *10
	a(2) = *-1
	a(3) = *1
	a(4) = *2
	a(5) = *3
	a(6) = *4
	a(7) = *4.3
	a(8) = *4.305
	a(9) = *4.303
       a(10) = *4.302
       a(11) = *4.301
Results are
	   r =	    399.8863
Too large
Too large
Too large
	   r =	    399.608644
	   r =	    322
	   r =	    136.732051
	   r =	     41.4142136
	   r =	      6
	   r =	     -4
Too large
Stopped by step 1.05.

This exposed a number of differences from the original JOSS:

  • Variables and functions are single characters, but are case sensitive.
  • The character set is different: use * for multiplication. ^ for exponentiation and !x! to find the absolute value of x.
  • There is no support for comments (which JOSS defines as lines starting with or ending with *.

Further information

On Bitsavers, DEC's documentation of the AID system can be found in the PDP-10 Timesharing Handbook from 1970: see the section "Conversational Programming With AID" starting on page 123.

RAND's documentation for JOSS, such as The JOSS Primer, can be used for AID with small modifications.

There's a reconstruction effort for the original JOSS-II on github. This includes source code, and also many other JOSS documents in the doc/ directory.

Later on, DEC created FOCAL which made more extensive changes to the JOSS language. This is available on the 6.03 distribution we are using (via R FOCAL) but I will look at this later on when I cover TOPS-20.

I've written about other JOSS dialects before: WIPL for MCP on the Burroughs B5500 and PIL for the Michigan Terminal System on the IBM System/360.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


TOPS-10: Algol 60

This week it's time to look at the Algol 60 compiler on TOPS-10. This was a supported product from DEC that integrates with the standard COMPILE/EXEC system. Files should have an extension of .ALG to be automatically recognised as Algol

As with every Algol compiler, there are several implementation dependent features to deal with issues like character set and for unspecified facilities like I/O.

Single pass compiler

The compiler needs only a single pass over the source code, which makes it fast, but does mean that functions used before they are defined are flagged as errors. A non-standard keyword FORWARD was added to work around this, so you can say FORWARD REAL PROCEDURE x; and then define x later in the program.

Source format and special characters

This version of Algol does not require keywords to be quoted (eg FOR vs 'FOR' ), but if you have programs already using quoted keywords you can add the /Q switch to the COMPILE command to accept this. Periods are allowed in identifiers to improve readability.

Some additional characters are used to represent language features which are implementation dependent

  • := for left arrow assignment
  • # for not equals to
  • ^ for exponentiation
  • @ or & for floating point exponents
  • ! for comments

There are two special forms for constants. Octal constants are introduced by a leading %, eg %770. ASCII constants - ie a single word of memory containing up to 5 ASCII characters - start with a $ and the constant surrounded by the user's choice of delimiter, for r example $/ABC/.

Strings

TOPS-10 Algol adds a string type, which is implemented as a pointer to a character array internally.

    STRING S, T;
    S := "HELLO WORLD";
    T := S;

Here S and T would point to the same byte array in memory. If instead the last line was T := COPY(S); then T would point to its own string.

Square brackets inside double quotes are used to incorporate special characters, for example "HELLO[N]" would print HELLO and a carriage return/new line.

Input/Output

I/O is not part of the Algol spec, so all this is implementation dependent. The basic output functions are WRITE for character data and PRINT for numeric data. READ is used to input data based on the type of parameter.

By default, I/O goes to the user's typewriter. You can select other places by using INPUT or OUTPUT to define a channel, eg INPUT(5, "CDR"); will define input channel 5 as going to the card reader. You then need to do SELECTINPUT(5) to direct all future input via READ to come from this channel. This facility also allows input and output for disk files.

Other language extensions

  • There is a LONG REAL type for additional floating point precision.
  • Procedures can be marked as EXTERNAL and linkage to other languages is allowed.
  • While loops, eg WHILE X < 10 DO X := X + 1;.
  • Variables can be declared as OWN, which has similar semantics to C's static variables, ie their lifetime continues when the block they are defined in is exited.

Running TPK

Let's use the compiler to run the TPK algorithm. The source code can be found here. This can be loaded onto the disk using the techniques described in this article.

.type tpk.alg
BEGIN
    COMMENT TPK ALGORITHM IN ALGOL 60;

    REAL PROCEDURE FN(X);
    VALUE X;
    REAL X;
    BEGIN
        FN := SQRT(ABS(X)) + 5*X^3
    END PROCEDURE;

    COMMENT Main program;
    INTEGER N, J;
    REAL ARRAY A[1:11];
    N := 11;
    COMMENT Read numbers;
    FOR J := 1 STEP 1 UNTIL N DO
        READ(A[J]);
    WRITE("RESULTS ARE[N]");
    FOR J := N STEP -1 UNTIL 1 DO
    BEGIN
        REAL RESULT;
        RESULT := FN(A[J]);
        IF RESULT > 400.0 THEN
            WRITE("TOO LARGE")
        ELSE
            PRINT(RESULT);
        WRITE("[N]");
    END LOOP;
END PROGRAM

.exec tpk.alg
ALGOL: TPK
12  NO DECLARATION SHOULD FOLLOW PROCEDURE OR SWITCH DECLARATION
LINK:	Loading
[LNKXCT TPK Execution]
10
-1
1
2
3
4
4.3
4.305
4.303
4.302
4.301
RESULTS ARE
 3.9988630&  2
TOO LARGE
TOO LARGE
TOO LARGE
 3.9960864&  2
 3.2200000&  2
 1.3673205&  2
 4.1414214&  1
 6.0000000
-4.0000000
TOO LARGE


End of execution.

Note the warning that the declaration of INTEGER N, J; should not follow the procedure declaration. This is not something that other Algol compilers have picked up and it may be due to the single pass nature of the compiler mentioned earlier.

In the output section, numbers are printed with the mantissa and exponent separated by a space, eg 3.9960864& 2 means 399.60864.

Further information

On Bitsavers there's an Algol manual from 1974. The tape image from 1978 that was the source of this compiler has a readme on trailing-edge.

Questions, corrections, comments

I welcome any questions or comments, and also especially any corrections if I have got something wrong. Please email me at rupert@timereshared.com and I will add it here and update the main text.


Next →