CTSS: The QED editor

The QED editor has a long history. It was originally created for the Berkeley Timesharing System running on the SDD 930/940 machine in 1965-6. Ken Thompson, who was part of the Bell Labs contingent working on Multics, re-implemented it for CTSS in around 3500 lines of FAP assembly code some time in 1969; he also produced a version for Multics using BCPL. While working on Unix, the ideas from QED inspired tools such as ed and sed.

Other authors produced implementations of QED for other time-sharing systems, and you can even find versions for Unix you can run on current systems.

/images/ctss/qed-session.png

A session using QED to move text to a new file.. Source: Rupert Lane. License: CC0.

Setup

Note that QED only supports 6- and 12-bit line-marked files and ASCII files, not card image files. If your file is in card image format, convert it using SQUASH first.

An editing session

QED has the concept of multiple buffers rather than working on a single file at a time. In the below I start QED and read in TPK MAD to the default buffer using the r command with the s option to mean 6-bit line-marked.

qed
W 1755.3
QED     
rs tpk mad

x will list the buffers in use: here we have the default buffer 0 with 23 lines:

x
"0" 0023

The p command prints lines from the buffer. Like many commands, it takes an optional range as its first argument. Without a range it defaults to . which is the current line, but I can specify line numbers or ranges of lines:

p                        
           END OF PROGRAM
10 p                     
           DIMENSION NUM(11)
3,5 p                       
           INTERNAL FUNCTION(X)
           ENTRY TO F.         
           FUNCTION RETURN SQRT.(.ABS.X) + 5 * X.P.3

1,$ p would print all lines of the file.

Range arguments can also be regular expressions enclosed in ~/~s.

/th.* input/,/read/ p            
           THROUGH INPUT,FOR J=0,1,J.GE.N
INPUT      READ FORMAT FMT,NUM(J)

Had we used the d command instead of p, it would delete those three lines.

The global command

As well as using regular expressions in ranges, we can use them as an argument to the global command g. As an example, to find all lines that match the string 11

gp/11/
           N = 11
           DIMENSION NUM(11)
           PRINT COMMENT $PLEASE ENTER 11 NUMBERS$

Here, the range is not specified before the command, so it is implicitly the whole file. The g command takes two parameters: the command to execute (p) and the regexp to max (/11/).

Search and replace

The s command takes two regexps as parameters for the text to find and the text to replace. So if I wanted to change all 11s to 15s I could do:

1,$ s/11/15/

The range, 1,$ needs to be supplied as otherwise this command will only operate on the current line.

Inserting text

Position yourself on the line after you want the new text to go and then use the i command. Terminate this with the escape character followed by f, ie \f

/other/                  
           OTHERWISE
i                   
           PRINT COMMENT $TRY AGAIN$
\f

a will append text directly to the end of the buffer.

Moving text

Let's say we want to move the internal function to an separate file, and make it an external function. We can use the m command with a range to determine what lines to move. Here this will move the text to buffer 1:

/internal func/,/end of func/ m1

We can use b to switch to the other buffer and look at it. We also change INTERNAL to EXTERNAL.

b1                       
1,$p
           INTERNAL FUNCTION(X)
           ENTRY TO F.         
           FUNCTION RETURN SQRT.(.ABS.X) + 5 * X.P.3
           END OF FUNCTION                          
/internal/
           INTERNAL FUNCTION(X)
s/int/ext/                     
p
           EXTERNAL FUNCTION(X)

Let's save it as func mad.

ws func mad

We then return to buffer 0 and confirm that it has gone by seeing the ?1 error message when searching for sqrt.

b0                        
/sqrt/
?1

Save the main file.

ws tpk mad

Execute system commands

QED can execute commands stored in a buffer and then return to the editor. Let's set up some compile/load commands in buffer 2:

b2                       
i
mad tpk
\f

Return to buffer 0 and execute it.

b0
e2
LENGTH 00152.  TV SIZE 00006.  ENTRY 00040

Other QED commands

  • f will replace the contents of the current buffer with information such as date, time, login details etc.
  • k will sort a range
  • l will list a file to the console
  • u - the audit command - will create a buffer showing the effect of all edits done since the last read.

Further information

QED is described more fully in the CTSS Programmer's Guide section AH.3.09 p353.

Source code for QED on a number of different systems is collected on Github at arnoldrobbins/qed-archive.

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 if needed.