Very early C compilers and language

Several years ago, Paul Vixie and Keith Bostic found a DECtape drive, attached it to a VAX, and offered to read old DECtapes. Even at the time, this was an antiquarian pursuit, and it presented an opportunity to mine beneath the raised floor of the computer room and unearth some of the DECtapes we'd stored since the early 1970s. Gradually, I've been curating some of this, and here offer some of the artifacts. Unfortunately existing tapes lack interesting things like earliest Unix OS source, but some indicative fossils have been prepared for exhibition.
数年前、 Paul Vixie と Keith Bostic は VAX に接続された DECtape ドライブを見つけ、 古い DECtape を読むことを申し出てくれました。 その時点ですら、これは大昔の仕事で、 コンピュータルームの底上げした床の下にあり、 1970 年代の初頭に記録した DECtape の一部を発見する 機会に恵まれたものです。 次第に、 私はこれの一部が何であるかを思い出し、 ここにその成果の一部を提供します。 残念なことに、 残されたテープには初期の Unix OS ソースなど興味深いものはありません。 しかし、幾つかの開示した化石は展示の準備をしたものです。

information: Warren Toomey, now at Bond University, has managed to make one of the compilers (last1120c, see below) compile itself using a First/Second edition Unix emulator for the PDP-11; see his ftp-available directory. More generally, it's worth looking into the PDP-11 Unix Preservation Society pages for sources and simulators.
現在 Bond University に在籍している Warren Toomey は PDP-11 用の First/Second edition Unix のエミュレータを使って、 それ自身をコンパイルできるコンパイラ (last1120c 後述) のうちの1つをどうにか作りました。 彼の ftp-available ディレクトリを参照してください。 より一般的な情報については、 PDP-11 Unix Preservation Society のソースとエミュレータのページをのぞく価値があります。

As described in the C History paper * , 1972-73 were the truly formative years in the development of the C language: this is when the transition from typeless B to weakly typed C took place, mediated by the (Neanderthal?) NB language, of which no source seems to survive. It was also the period in which Unix was rewritten in C.
C History paper * で説明した通り、 1972-73 は本当に C 言語の開発が形作られた年でした: これは、いつ 型のない B から ソースを紛失したと思われる (ネアンデルタール人の?) NB を経て 貧弱な型のある C への移行が発生したを示したものです。 また Unix が C で書き直された時期を示すものでもあります。

In looking over this material, I have mixed emotions; so much of this stuff is immature and not well-done, and there is an element of embarrassment about displaying it. But at the same time it does capture two moments in a period of creativeness and may have some historical interest.
このソースコードに目を通すと、入り交じった感情を持ちます。 非常多くのものが未完成であまり上手ではなく、 見せるにはバツの悪い代物もあります。 しかし同時に、 それは創造的な期間の2つの瞬間を切り取ったものであり、 歴史的な興味を持つものかも知れません。

Two tapes are present here; the first is labeled "last1120c", the second "prestruct-c". I know from distant memory what these names mean: the first is a saved copy of the compiler preserved just as we were abandoning the PDP-11/20, which did not have multiply or divide instructions, but instead a separate, optional unit that did these operations (and also shifts) by storing the operands into memory locations. (A story about using this hardware is told elsewhere.)
ここで紹介するテープは2つあります; 最初のものは "last1120c" のラベルが張られたもの、 そして2番目は "prestruct-c" のラベルがはられたものです。 これらの名前が意味する遠い記憶を思い出しました: 最初のものは、ちょうど PDP-11/20 (での作業) を 諦めつつあった時のコンパイラのコピーを保存したものです。 これは乗算と除算のインストラクションがありませんが、 その代わりに、メモリ上にオペラントをおいて、 これらの操作 (更にシフト演算) を行なう オプショナルユニットがありました。

"prestruct-c" is a copy of the compiler just before I started changing it to use structures itself.
"prestruct-c" はちょうど私がそれ自身に構造体を使った変更を始める直前の コンパイラのコピーです。

It's a bit hard to get really accurate dates for these compilers, except that they are certainly 1972-73. There are date bits on the tape image, but they suffer from a possible off-by-a-year error because we changed epochs more than once during this era, and also because the files may have been copied or fiddled after they were the source for the compiler in contemporaneous use.
これらのコンパイラの正確な日付を知るのはいささか困難ですが、 1972 年から 1973 年の間のものであることは間違いありません。 テープイメージには日付のビットがありますが、 この時期に何度も時間を変更した上に、 ファイルはコンパイラを生成したソースを コピーあるいはいじられているかもしれないので、 off-by-a-year エラーの疑いがあります。

The earlier compiler does not know about structures at all: the string "struct" does not appear anywhere. The second tape has a compiler that does implement structures in a way that begins to approach their current meaning. Their declaration syntax seems to use () instead of {}, but . and -> for specifying members of a structure itself and members of a pointed-to structure are both there.
初期のコンパイラは構造体を全く知りませんでした: "struct" の文字列はどこにも登場しません。 2番目のテープは現在の意味に近い方法で構造体を実装したコンパイラです。 その宣言の文法では {} の代わりに () を 使っていたようですが、 構造体自身のメンバを示す . と 構造体のポインタからメンバを示す -> は 既に存在していました。

Neither compiler yet handled the general declaration syntax of today or even K&R I, with its compound declarators like the one in int **ipp; . The compilers have not yet evolved the notion of compounding of type constructors ("array of pointers to functions", for example). These would appear, though, by 5th or 6th edition Unix (say 1975), as described (in Postscript) in the C manual a couple of years after these versions.
コンパイラは int **ipp; といった 複合した宣言子を使う、 今日の一般的な宣言の文法も そして K&R さえも まだ扱うことができませんでした。 コンパイラはまだ タイプ・コンストラクタを組み合わせた表記へ 進化していませんでした。 (例えば、関数へのポインタの配列など) しかしながら、 5th/6th Edition の数年後の (Postscript による) C manual の記述によると、 これは 5th/6th Edition の Unix のものと思われます。

Instead, pointer declarations were written in the style int ip[];. A fossil from this era survives even in modern C, where the notation can be used in declarations of arguments. On the other hand, the later of the two does accept the * notation, even though it doesn't use it. (Evolving compilers written in their own language are careful not to take advantage of their own latest features.)
代わりに、 ポインタの宣言は int ip[]; というスタイルで書かれています。 この時代の化石は 引数の宣言に使うことのできる表記として、 現在の C でも生き残っています。 一方、 この2つの後のものは それを使わなくても * の記法を受け付けます。 (それ自身の言語で書かれたコンパイラを発展させる場合は 最新の機能を殺さないように慎重におこなわなければなりません)

It's interesting to note that the earlier compiler has a commented-out preparation for a "long" keyword; the later one takes over its slot for "struct." Implementation of long was a few years away.
初期のコンパイラで "long" というキーワードの前処理を コメントアウトしているところが面白いです; 後のものは "struct" のためにそのスロットを引き継ぎます。 long の実装は数年後のことでした。

Aside from their small size, perhaps the most striking thing about these programs is their primitive construction, particularly the many constants strewn throughout; they are used for names of tokens, for example. This is because the preprocessor didn't exist at the time.
その小さなサイズはさておき、 おそらくこのプログラムの最も目を引くところは その古い構成、特に多くの定数が至るところに散りばめられていることです; 例えば、トークンの名前のために使われています。 これはこの時点ではプリプロセッサが存在していなかったからでしょう。

A second, less noticeable, but astonishing peculiarity is the space allocation: temporary storage is allocated that deliberately overwrites the beginning of the program, smashing its initialization code to save space. The two compilers differ in the details in how they cope with this. In the earlier one, the start is found by naming a function; in the later, the start is simply taken to be 0. This indicates that the first compiler was written before we had a machine with memory mapping, so the origin of the program was not at location 0, whereas by the time of the second, we had a PDP-11 that did provide mapping. (See the Unix History paper ). In one of the files (prestruct-c/c10.c) the kludgery is especially evident.
次に、あまり目につかないが驚くべき変わった点はスペースの確保です: 一時的な記憶領域は意図的にプログラムの先頭を上書きするように確保し、 スペースを節約するための最高の初期化コードになっています。 これの対処方法について2つのコンパイラでは詳細が異なります。 古いものは関数の名前により先頭を見つけますが、 新しいものは単純に0としています。 これは、最初のコンパイラはメモリマッピングが できるマシンを手に入れる以前に書かれたものであり、 故にプログラムの先頭は0でないことに対し、 2番目のコンパイラの時にはマッピングができる PDP-11 を手に入れていたことを示しています。 ( Unix History paper 参照) あるファイル (prestruct-c/c10.c) がやっつけ仕事であることが明らかです。

Links to the source of the compilers are listed below. The files named c0?.c are the first passes, which parse source and writes syntax trees intermingled with some text on an intermediate file. The c1?.c files are the code generators, which read the trees and generate code. The format is straight text (with just NL characters separating lines; the browsers I've tried cope with this).
リンクするべきコンパイラのソースは下記に一覧を示します。 c0?.c という名前のファイルは第1パスで、 ソースを解釈し、中間ファイルにテキストが混ざった構文木を書きます。 c1?.c という名前のファイルはコード生成で、 構文木を読んでコードを生成します。 フォーマットは普通のテキストです。 (改行文字で行に分割されたもので、 私が試したブラウザではこれをうまく処理できます)

The code generation technique uses tables of instruction prototypes; a parse tree is recursively matched against the part of the table corresponding to its root operator. Restrictions on the types and complexity of the operands can be expressed, and the table is searched sequentially for the earliest matching fragment. Following each restriction specification is the expansion specification; lower case letters are literal, upper case things are replaced by things from the operands in the tree. This is described in more detail in the paper A Tour through the PDP-11 Compiler. (This reference is troff source; it can also be found in Postscript or PDF forms, though bundled with other papers, under the 7th Edition Manual's home page). But do note that this Tour describes the state of things after several years had passed.
コード生成にはインストラクションプロトタイプのテーブルを使います。 解析木はそのルートオペレータに対応するテーブルの一部と再帰的に比較されます。 型や複雑なオペラントの制限を表現することができます。 また、テーブルは最も最初に一致するフラグメントを求めて シーケンシャルに探索されます。 個々の制限の仕様記述に続くのは拡張の仕様記述です。 小文字の文字は文字どおりです。 大文字のものは解析木のオペラントのものと置き換えられます。 これは 論文 A Tour through the PDP-11 Compiler で、より詳細が説明されています。 (これは troff のそーすです。 7th Edition Manual's ホームページには、他の論文も付属した Postscript や PDF 形式のものもあります) しかしこのツアーが数年経過した後の状態について 記述していることに注意してください。

There are four tables specifying how to compile an expression to a register, to compile only for side effects, to compile only to test condition codes, and to compile to push on the stack (used for function arguments, or for temporaries). They were saved only with the "last1120c" compiler; the tables for the later one would have been similar.
式からレジスタへのコンパイル方法、 副作用のみのコンパイル方法、 状態コードをテストするためのコンパイル方法、 スタックへプッシュするためのコンパイル方法 (関数の引数や一時的な領域のために使います) を定義した4つのテーブルがあります。 これらは "last1120c" コンパイラだけに保存されています。 後のコンパイラのテーブルも類似したものでしょう。

The source for the last1120c compiler also has a subsidiary table for each pass with a bit of stuff that was not in the library, and some encoding of facts about various operators as .s (assembler language) files.
last1120c コンパイラのソースには ライブラリにはなく、 .s (アセンブリ言語) ファイルとしていろいろなオペレータの実際のエンコーディングための 僅かな情報と個々のパスのための補助テーブルもあります。

Finally, there is the cvopt program, used to convert the nonce-language expression template tables into assembler. With a lot of handwork, there is probably enough material to construct a working version of the last1120c compiler, where "works" means "turns source into PDP-11 assembler." (See the top of the page for one who succeeded.)
最後に、 cvopt というプログラムがあり、 一時的な言語表現のテンプレートテーブルを アセンブラに変換するために使います。 いろいろ手作業が必要になりますが、 last1120c コンパイラの作業バージョンを 作成するために必要なものはおそらく揃っているでしょう。 "works" とは "PDP-11 アセンブラのソースが生成できる" という意味です。

The links for the files are:

last1120c

c00.c
c01.c
c02.c
c03.c
c0t.s
c10.c
c11.c
c1t.s
regtab.s
cctab.s
sptab.s
efftab.s
cvopt.c

prestruct-c

c00.c
c01.c
c02.c
c03.c
c10.c
c11.c