[Unix-jun72] Observations about this ancient C dialect

Doug Merritt doug at remarque.org
Thu May 15 13:03:45 AEST 2008


Warren wrote:
> Remember, the C files will not compile with the existing
compiler.

For your amusement, and in case it helps, below are the notes I took
on observations on the weirdness of this old C, from reading the C
files and the C compiler source code the first day of my start on
this project (Apr 18 -- long, long ago :-)

E.g. the "C preprocessor" didn't exist at the time, but
an "expand()" function was called on lines starting with '%',
to perform a non-recursive file inclusion.

(BTW I've spoken with John Reiser since then to check some history.
He said he arrived at BTL in 1977, and did much rewriting of cpp
largely because it was a buggy crock. That places him significantly
later than my previous understanding; I had thought he implemented
the original cpp championed by Snyder and designed by Lesk, but
perhaps...but no, Lesk wouldn't have cranked out cruft.  Hmm. Some
years ago Snyder more or less told me me he denied much involvement
in cpp, beyond pitching the idea of macro processing.  Could mean
any number of things. :-) Always seemed strange, though, since
McIlroy is the one with a large historical presence associated with
macro processing. History is confusing.)

I've used the pre-stdio "portable I/O library", although my
notes don't indicate so, and there are other real or apparent
signs of cluelessness. My own Unix involvement originally
went back only as far as version 6, and my memory is imperfect
anyway.

And there are plain errors. This is as-is.

See below.
	Doug
--
Professional Wild-eyed Visionary        Member, Crusaders for a Better Tomorrow
--------------------------------- cut here ------------------------

form1.s: daytab gives 29 days to february (changed to 28 in Unix v5 s1/form1.s),
perhaps confirming that this source code is from 1972 in particular,
which was a leap year.

cc.c:
	Exactly 2 flags (other cmd line "-" treated as input files):
		-c	produce .o, as today
		-2	Use Fortran startup,loader ( /lib/crt20.o )
				callsys("/usr/lib/ld20", av);
			library:
			av[2] = "/lib/20.s";
			callsys("/bin/ld", av);
	No C preprocessor; function expand() does include files
		marked by input lines starting with '%'
		Non-recursive.
		Appends SOH after each newline. Weird.
	Verbose; if more than 1 c file, then:
		printf("%s:\n", clist[i]);
	Automatically sets -c flag if expand() fails.
	(cflag causes early abort, no later stages)
		...ah, that just means "early exit"
		if (av[1] == 0) {
			cflag++;
	Passes:
		av[0] = "c0";
		av[1] = expand(clist[i]);
		if (callsys("/lib/c0", av)) {
		if(callsys("/lib/c1", av)) {
		callsys("/bin/as", av);
		moves .o to a.out before calling ld
		callsys("/bin/ld", av);
	tmp files:
		tries /tmp/ctm0[a...] until finds nonexisting creatable name
		That one is just used as filesys lock on this range of names
		Then uses /tmp/ctm[1..4]a for pass tmp files
	No '=' for init, e.g.
		char *tmp0 "//";
	Exotic keyboard interrupt handling:
		intr(delfil);
		...
		delfil:
			dexit();
	Single '&', '|' used for both bitwise and logical, e.g.
		return((status>>8) & 0377);
		if (nc==1 & nl==1)
		if(link("a.out", t) | unlink("a.out")) {
	Old style op-equals, e.g.
		s =- 3;
	Exotic file I/O, 259 int buffers:
		int ibuf1[259], ibuf2[259], obuf[259];
		if (fopen(file, ibuf1)<0) ...
		if (getc(ibuf1) != '%') {
		if (fcreat(tmp4, obuf) < 0) {
		while((creat(tmp0, 012))<0)
			tmp0[9]++;
		Buf struct:
			ibuf1[1]++;		/* back up over % */
			ibuf1[2]--;
			So file buf[1] -> avail count
			   file buf[2] -> first char index/ptr
			getc() decremented the first, incremented the second
			file buf[3] must hold the file descriptor
	Same process management as today; callsys uses:
		if ((t=fork())==0) {
			execv(f, v);
			printf("Can't find %s\n", f);
			exit(1);
		} else
			if (t == -1) {
				printf("Try again\n");
				return(1);
			}
		while(t!=wait(&status));
		if ((t=(status&0377)) != 0 & t!=14) {
			if (t!=12)		/* interrupt */
				printf("Fatal error in %s\n", f);
			dexit();
		}
		return((status>>8) & 0377);
cp.c:
	No structures; just array of int
		fstat(fold,buf);
		mode = buf[2] & 037;
	Return status survives func call, used as exit code:
		fstat(fnew,buf);
		exit();
ls.s:
	Uses both "jsr, r5" (mostly) and also 3 "jsr pc":
		jsr	pc,ctime	# external func
		jsr	pc,puid		# local func
		jsr	pc,do		# local func
	I think pc is with stack params and r5 is with funky
		param-in-next slot after jsr, mostly
	Indication of structure of stat() buffer ("dska" is perhaps
	"disk address"? "dska" also appears in frag0):
		mov     (r0)+,(r1)+     /flags
		mov     (r0)+,(r1)+     /nlinks, uid
		mov     r0,-(sp)
		mov     (r0),r0
		jsr     r5,calcb
		add     r0,tblocks
		mov     (sp)+,r0
		mov     (r0)+,(r1)+     /size
		add     $20.,r0         /dska, ctim
		mov     (r0)+,(r1)+     /mtim
		mov     (r0)+,(r1)+
		mov     statb,(r1)+     /inode
	uniq -d, -u:
	Routines defined and used within ls.s:
		calcb
		decimal
		do
		gstat
		mode
		pentry
		pstring
		puid
		questf
	Routines defined but not called:
		eloop		# branch target
		euidbuf		# data synonym
		listl		# branch target
		loop		# branch target
		nondir		# branch target
		pass2		# branch target
		pass3		# unused branch target
	Routines called but not defined:
		ctime
		flush
		fopen
		getc
		getw
		putc




More information about the TUHS mailing list