From mboxrd@z Thu Jan 1 00:00:00 1970 From: doug@remarque.org (Doug Merritt) Date: Wed, 14 May 2008 20:03:45 -0700 (PDT) Subject: [Unix-jun72] Observations about this ancient C dialect In-Reply-To: <20080515014608.GA3761@minnie.tuhs.org> Message-ID: <20080515030345.151AA5A525@remarque.org> 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