I have reconstituted Jon Bentley's DFORMAT preprocessor (troff and awk
source) and made it available on GitHub. See
This is an awk program that reads a description of data layouts, such
as registers or network packets, and generates PIC descriptions.
A Makefile generates PDF from the dformat.ms file using GNU troff.
Jon Bentley was helpful in the final stages, including contributing
his original files.
So in BSD family tree, there's a 2.9BSD-Seismo and a 2.9.1BSD listed.
Yet I can't seem to find them in the TUHS archive.
There is a 2.9-Patch directory dated 1985 the same as the date that's found
in the family tree. Is that the Seismo version?
And Kirk's archive has a 2.9pucc directory, which appears appears to be
from Purdue dated1987. How does this relate?
Thanks for any help you can provide
With some further reading and research (and the kind help of Heinz Lycklama and Jon Steinart) I’ve found that my understanding of early loop networks at Bell Labs confused several different systems. As far as I can currently tell there were at least 4 different loop networks developed around 1970 at Murray Hill.
1. The first one is the “Newhall Loop” (paper published in 1969). This loop used twisted pair cabling, ran at about 3Mhz and used variable sized messages. It seems to have used some sort of token to coordinate between hosts. This might have been the network that Ken Thompson recalled as having been in operation when he arrived at the labs in 1966.
2. The second one appears to have been the “Pierce Loop”, as described in 3 BSTJ papers submitted in 1970/71. This one was coax based, used T1 compatible frames and was used to connect H516 computers with various bits of equipment. It seems to have had a very short life span. Part of my confusion was that the term Pierce Loop also appears to have been used in a generic sense to denote loop networks with fixed-sized frames.
3. The third one is the “Weller Loop” (paper published in 1971). This loop used coax cabling, ran at 3.3Mhz and used fixed 35 bit frames/cells. Each cell carried one address byte and two data bytes. One participant on the loop was the controller and effectively polled the other stations. In its 1971 form it appears to have been for the H516’s only and was referred to as a “Serial I/O bus”. This is what Jon Steinhart was talking about.
The Weller loop was later redesigned (memo written in 1973) to interface with PDP-11’s as well. Heinz Lycklama used this loop in 1974 to connect several systems running (rump) Unix - see his paper about peripheral Unix here:
This Serial I/O bus remained in use for several years at least.
4. The fourth and best known one is the “Spider Loop” (memo published in 1974, but operational from 1972). Twisted pair cabling, using T1 compatible frames. In use until about 1978. Main uses appear to have been the ‘nfs’ file store and the ‘npr’ remote printing service.
My conclusion from all that is that in 1974 Unix had access to two networks, Spider and the Serial I/O bus. For both, first experiments would have been in 1973. It is hard to be sure which one came first. If I had to venture a guess today, I’d say that Spider connected to Unix several months before the Weller loop (even though the 1st generation Weller loop preceded Spider). Maybe the conclusion is that both happened more or less in parallel: Weller was also one of the designers of the Spider hardware.
I normally download items from the Society FTP site rather than from
the archival area on the website. And my clients kept getting bounced,
claiming that I should stop trying to connect frequently. Oddly enough
that was not the case a while ago. Was the archive recently updated
regarding hosting software?
On Windows it was FileZilla, and spun down to one rather than eight or
ten. And on the WSL SLES12 SP3 arrangement it was ncftp. Now
downloading the reports to go along with the one Paul made available
from the location is not important for today, I can wait until
tomorrow or the next day.
Gregg C Levine gregg.drwho8(a)gmail.com
"This signature fought the Time Wars, time and again."
Yeah, p is all we need. I think it originated with td at UofT. I might have
brought it with me to Bell Labs, or recreated it. Probably the former.
The former, I think. The source code in V10 is very similar
to that you left behind at Caltech (where I first encountered
p). Most differences have to do with using opendir and readdir
rather than reading raw directories in the SPname code.
A further clue is that, even in V10, p.c begins
/*%cc p.c pad.o spname.o
The tool that looked for such lines to tell it how to compile
things (I forget its name; was it comp?) doesn't seem to have
survived in the archival backup I have from Caltech HEP, but
I'm quite sure it came from U of T as well.
The C in v7 is, canonically, the language described in K&R, right?
I must be doing something dumb.
I am getting Webb Miller’s “s” editor built there, and I am down to one function.
/* chop_arg - chop a function's argument to a maximum length */
static chop_arg(fcn, arg, maxlen)
save = arg[maxlen];
arg[maxlen] = '\0';
arg[maxlen] = save;
This doesn’t like the function pointer.
$ cc -c choparg.c
choparg.c:11: Call of non-function
So, uh, what is the obvious thing I am missing? How am I supposed to be passing function pointers in the C compiler that comes with v7?
> From: Diomidis Spinellis
> From the 2.11 BSD sources I understand that the PDP-11/70 MMU address
> and data registers, KDSA and KDSD, start at 0172360 and 0172320
> respectively ...
Expressed as 16-bit addreses, on a PDP-11 with mapping disabled, yes.
> I checked this by looking at /dev/mem.
I don't know about 2.11, but in other PDP-11 Unixes, /dev/mem gives access to
the actual CPU memory bus (which on a /34, etc, is the 18-bit address UNIBUS;
on a /70 it's a separate 22-bit address bus). In the /70 memory address
space, the 'I/O page' (which is where the PxR's live) is at the top end of it,
i.e. the registers are at 017772360 (KDSAR0), etc.
> What am I missing?
PDP-11's have a plethora of address spaces, of different sizes. You need to
always be aware of which one you're working in.
> My goal is to access from the console the kernel's u area. According to
> mem(4) and the symbols in /unix, this should be at address 0140000.
In the kernel virtual address space, yes.
> Indeed, accessing it through /dev/kmem I get the expected results for
> e.g. u_comm and u_uid.
Because /dev/kmem gives access to kernel address space for the _current_
> I have been unable to find it in the machine's physical memory
By far and away the easiest thing, for the _current_ process, is to
use /dev/kmem, which automagally applies the correct mapping.
For other processes, if the process is swapped in, there's some field in the
proc structure which says where in physical memory it us. IIRC, the user
struct and the kernel stack are stored in the very bottom of that.
goes into some detail for V6. Not sure how different 2.11 is; I know it uses
one block of kernel address space to map in code overlays, but I don't know
all the details of how it works.)
Anyway, using that, one could read the user area in /dev/mem, at the
For swapped-out processes, a similar algorithm applies, but you'll
have to look in the swap device (obviously).
Interesting. My "speak" program had a trivial lexer that
recognized literal tokens, many of which were prefixes
of others, by maximum-munch binary search in a list of
1600 entries. Entries gave token+translation+rewrite.
The whole thing fit in 15K.
Many years later I wrote a regex recognizer that special-cased
alternations of lots of literals. I believe Gnu's regex.c does
that, too. (My regex also supported conjunction and negation--
legitimate regular-language operations--implemented by
continuation-passing to avoid huge finite-state machines.)
We have here a case of imperfect communication in 1127. Had I
been conscious of the lex-explosion problem, I might have
thought of speak and put support for speak-like tables
into lex. As it happened, I only used yacc/lex once, quite
successfully, for a small domain-specific language.
Steve Johnson wrote:
I also gave up on lex for parsing fairly early. The problem was
reserved words. These looked like identifiers, but the state machine to
pick out a couple of dozen reserved words out of all identifiers was too
big for the PDP-11. When I wrote spell, I ran into the same problem.
I had some rules that wanted to convert plurals to singular forms that
would be found in the dictionary. Writing a rule to recognize .*ies
and convert the "ies" to "y" blew out the memory after only a handful of
patterns. My solution was to pick up words and reverse them before
passing them through lex, so I looked for the pattern "sei.*", converted
it to "y" and then reversed the word again. As it turned out, I only
owned spell for a few weeks because Doug and others grabbed it and ran