Annexe Unix 72

Voici le code source du compilateur C d’UNIX V2, ecrit en 1972.

Vous en trouverez des archives Ă  cette adresse : https://www.tuhs.org/Archive/Distributions/Research/ đŸŒâ€Ž

Ainsi que ici : https://www.tuhs.org/cgi-bin/utree.pl đŸŒâ€Ž

Cette version en comprenait pas de structures, de prĂ©processeur ou la possibilitĂ© d’initialiser une variable en meme temps que sa dĂ©clararion. La deeclaration de pointeurs ne se fait pas avec une astĂ©risque mais une paire de crochets vide : int p[]. L’aspect gĂ©nĂ©ral ressemble au B. Il est probable que certaines parties du code aient Ă©tĂ© portĂ©es directement depuis le B. Le mot clĂ© extern et auto y tiennent une place plus importante que dans des programmes en C ultĂ©rieurs.

Une syntaxe qui a Ă©tĂ© abandonnĂ©e depuis permet d’initialiser des variables externes ainsi line 1; (dĂ©clare une variable externe line de type int et initialisĂ©e Ă  1 ?). Il n’est pas possible d’initialiser et dĂ©clarer en meme temps des variables locales (automatiques) comme pour les variables externes. Il n’y a pas de “constantes” (ni #define, ni enum, ni const existent).

Une fonction ne peut pas retourner autre chose que int donc on ne dĂ©clare pas le type de la valeur retournĂ©e par une fonction. Le mot clĂ© void n’existe pas non plus : pas de distinction entre “routines” et “fonctions” comme dans Pascal et une seule convention d’appel est Ă  implĂ©menter en assembleur.

Il n’est pas possible de dĂ©clarer des fonctions (double ma_fonction();) : les forward declaration se font en signalant leur nom avec extern Ă  l’intĂ©rieur de la fonction qui veut les appeler.

Avec l’introduction du prĂ©processeur le mot clĂ© extern peut etre prĂ©sent en dehors d’une fonction : dans ce cas une dĂ©claration extern est valide pour toute l’unitĂ© de compilation qui suit. Au demeurant toutes les dĂ©clarations de fonction et de variables sont considĂ©rĂ©es comme extern par dĂ©faut, ce qui rend ce mot clĂ© utile uniquement pour les variables globales partagĂ©es par plusieur unitĂ©s de compilation qui sinon aloueraient chacune leur propre espace mĂ©moire pour celle ci.

Au demeurant tout appel Ă  une fonction que le compilateur rencontre pour la premiĂšre fois est supposĂ© implicitement ĂȘtre de la forme extern int fonction();. Pour cette raison, le programme « hello wold » dans la pemiere version du manuel K&R C s’Ă©crit ainsi

main()
{
    printf("Hello, Wold!\n");
}

pas besoin d’importer stdio.h car printf a la signature implicite extern int printf();.

Depuis le C99, une telle syntaxe n’est plus valide car une fonction doit dĂ©clarer son type de retour, int n’est plus implicite, gcc le tolĂšre jusqu’au C23, oĂč il devient obligatoire d’activer le mode -ansi pour que ce programme compile, voire -w : gcc -w -ansi prog.c.

c00.c

/* C compiler

Copyright 1972 Bell Telephone Laboratories, Inc. 

*/

ossiz 250;
ospace() {}	/* fake */

init(s, t)
char s[]; {
	extern lookup, symbuf, namsiz;
	char symbuf[], sp[];
	int np[], i;

	i = namsiz;
	sp = symbuf;
	while(i--)
		if ((*sp++ = *s++)=='\0') --s;
	np = lookup();
	*np++ = 1;
	*np = t;
}

main(argc, argv)
int argv[]; {
	extern init, flush;
	extern extdef, eof, open, creat;
	extern fout, fin, error, exit, nerror, tmpfil;

	if(argc<4) {
		error("Arg count");
		exit(1);
	}
	if((fin=open(argv[1],0))<0) {
		error("Can't find %s", argv[1]);
		exit(1);
	}
	if((fout=creat(argv[2], 017))<0) {
		error("Can't create %s", argv[2]);
		exit(1);
	}
	tmpfil = argv[3];
	init("int", 0);
	init("char", 1);
	init("float", 2);
	init("double", 3);
/*	init("long", 4);  */
	init("auto", 5);
	init("extern", 6);
	init("static", 7);
	init("goto", 10);
	init("return", 11);
	init("if", 12);
	init("while", 13);
	init("else", 14);
	init("switch", 15);
	init("case", 16);
	init("break", 17);
	init("continue", 18);
	init("do", 19);
	init("default", 20);
	while(!eof) {
		extdef();
		blkend();
	}
	flush();
	flshw();
	exit(nerror!=0);
}

lookup() {
	extern hshtab[], hshsiz, pssiz, symbuf[];
	extern hshlen, hshused, exit, error, nwps;
	auto i, j, np[], sp[], rp[];

	i = 0;
	sp = symbuf;
	j = nwps;
	while(j--)
		i =+ *sp++;
	if (i<0) i = -i;
	i =% hshsiz;
	i =* pssiz;
	while(*(np = &hshtab[i+4])) {
		sp = symbuf;
		j = nwps;
		while(j--)
			if (*np++ != *sp++) goto no;
		return(&hshtab[i]);
no:		if ((i =+ pssiz) >= hshlen) i = 0;
	}
	if(hshused++ > hshsiz) {
		error("Symbol table overflow");
		exit(1);
	}
	rp = np = &hshtab[i];
	sp = symbuf;
	j = 4;
	while(j--)
		*np++ = 0;
	j = nwps;
	while(j--)
		*np++ = *sp++;
	return(rp);
}

symbol() {
	extern peeksym, peekc, eof, getchar, subseq, error, line;
	extern csym[], getstr, symbuf, namsiz, lookup[], ctab, cval;
	auto b, c;
	char symbuf[], sp[], ctab[];

	if (peeksym>=0) {
		c = peeksym;
		peeksym = -1;
		return(c);
	}
	if (peekc) {
		c = peekc;
		peekc = 0;
	} else
		if (eof)
			return(0); else
			c = getchar();
loop:
	switch(ctab[c]) {

	case 125:	/* newline */
		line++;

	case 126:	/* white space */
		c = getchar();
		goto loop;

	case 0:		/* EOF */
		eof++;
		return(0);

	case 40:	/* + */
		return(subseq(c,40,30));

	case 41:	/* - */
		return(subseq(c,41,31));

	case 80:	/* = */
		if (subseq(' ',0,1)) return(80);
		c = symbol();
		if (c>=40 & c<=49)
			return(c+30);
		if (c==80)
			return(60);
		peeksym = c;
		return(80);

	case 63:	/* < */
		if (subseq(c,0,1)) return(46);
		return(subseq('=',63,62));

	case 65:	/* > */
		if (subseq(c,0,1)) return(45);
		return(subseq('=',65,64));

	case 34:	/* ! */
		return(subseq('=',34,61));

	case 43:	/* / */
		if (subseq('*',1,0))
			return(43);
com:
		c = getchar();
com1:
		if (c=='\0') {
			eof++;
			error("Nonterminated comment");
			return(0);
		}
		if (c=='\n')
			line++;
		if (c!='*')
			goto com;
		c = getchar();
		if (c!='/')
			goto com1;
		c = getchar();
		goto loop;

	case 124:	/* number */
		cval = 0;
		if (c=='0')
			b = 8; else
			b = 10;
		while(ctab[c]==124) {
			cval = cval*b + c -'0';
			c = getchar();
		}
		peekc = c;
		return(21);

	case 122:	/* " */
		return(getstr());

	case 121:	/* ' */
		return(getcc());

	case 123:	/* letter */
		sp = symbuf;
		while(ctab[c]==123 | ctab[c]==124) {
			if (sp<symbuf+namsiz) *sp++ = c;
			c = getchar();
		}
		while(sp<symbuf+namsiz)
			*sp++ = '\0';
		peekc = c;
		csym = lookup();
		if (csym[0]==1) {	/* keyword */
			cval = csym[1];
			return(19);
		}
		return(20);

	case 127:	/* unknown */
		error("Unknown character");
		c = getchar();
		goto loop;

	}
	return(ctab[c]);
}

subseq(c,a,b) {
	extern getchar, peekc;

	if (!peekc)
		peekc = getchar();
	if (peekc != c)
		return(a);
	peekc = 0;
	return(b);
}
getstr() {
	extern isn, cval;
	auto c;

	printf(".data;L%d:.byte ", cval=isn++);
	while((c=mapch('"')) >= 0)
		printf("%o,", c);
	printf("0;.even;.text\n");
	return(22);
}

getcc()
{
	extern cval, ncpw;
	auto c, cc;
	char cp[];

	cval = 0;
	cp = &cval;
	cc = 0;
	while((c=mapch('\'')) >= 0)
		if(cc++ < ncpw)
			*cp++ = c;
	if(cc>ncpw)
		error("Long character constant");
	return(21);
}

mapch(c)
{
	extern peekc, line;
	auto a;

	if((a=getchar())==c)
		return(-1);
	switch(a) {

	case '\n':
	case 0:
		error("Nonterminated string");
		peekc = a;
		return(-1);

	case '\\':
		switch (a=getchar()) {

		case 't':
			return('\t');

		case 'n':
			return('\n');

		case '0':
			return('\0');

		case 'r':
			return('\r');

		case '\n':
			line++;
			return('\n');
		}

	}
	return(a);
}

tree() {
	extern symbol, block, csym[], ctyp, isn,
		peeksym, opdope[], build, error, cp[], cmst[],
		space, ospace, cval, ossiz, exit, errflush, cmsiz;

	auto op[], opst[20], pp[], prst[20], andflg, o,
		p, ps, os;

	space = ospace;
	op = opst;
	pp = prst;
	cp = cmst;
	*op = 200;		/* stack EOF */
	*pp = 06;
	andflg = 0;

advanc:
	switch (o=symbol()) {

	/* name */
	case 20:
		if (*csym==0)
			if((peeksym=symbol())==6)
				*csym = 6;	/* extern */
			else {
				if(csym[2]==0)	/* unseen so far */
					csym[2] = isn++;
			}
			if(*csym==6)	/* extern */
			    *cp++ = block(5,20,csym[1],0,*csym,
					csym[4],csym[5],csym[6],csym[7]);
			else
			    *cp++ = block(2,20,csym[1],0,*csym,csym[2]);
		goto tand;

	/* short constant */
	case 21:
	case21:
		*cp++ = block(1,21,ctyp,0,cval);
		goto tand;

	/* string constant */
	case 22:
		*cp++ = block(1,22,17,0,cval);

tand:
		if(cp>=cmst+cmsiz) {
			error("Expression overflow");
			exit(1);
		}
		if (andflg)
			goto syntax;
		andflg = 1;
		goto advanc;

	/* ++, -- */
	case 30:
	case 31:
		if (andflg)
			o =+ 2;
		goto oponst;

	/* ! */
	case 34:
		if (andflg)
			goto syntax;
		goto oponst;

	/* - */
	case 41:
		if (!andflg) {
			peeksym = symbol();
			if (peeksym==21) {
				peeksym = -1;
				cval = -cval;
				goto case21;
			}
			o = 37;
		}
		andflg = 0;
		goto oponst;

	/* & */
	/* * */
	case 47:
	case 42:
		if (andflg)
			andflg = 0; else
			if(o==47)
				o = 35;
			else
				o = 36;
		goto oponst;

	/* ( */
	case 6:
		if (andflg) {
			o = symbol();
			if (o==7)
				o = 101; else {
				peeksym = o;
				o = 100;
				andflg = 0;
			}
		}
	goto oponst;

	/* ) */
	/* ] */
	case 5:
	case 7:
		if (!andflg)
			goto syntax;
		goto oponst;
	}

	/* binaries */
	if (!andflg)
		goto syntax;
	andflg = 0;

oponst:
	p = (opdope[o]>>9) & 077;
opon1:
	ps = *pp;
	if (p>ps | p==ps & (opdope[o]&0200)!=0) { /* right-assoc */
putin:
		switch (o) {

		case 6: /* ( */
		case 4: /* [ */
		case 100: /* call */
			p = 04;
		}
		if(op>=opst+20) {		/* opstack size */
			error("expression overflow");
			exit(1);
		}
		*++op = o;
		*++pp = p;
		goto advanc;
	}
	--pp;
	switch (os = *op--) {

	/* EOF */
	case 200:
		peeksym = o;
		return(*--cp);

	/* call */
	case 100:
		if (o!=7)
			goto syntax;
		build(os);
		goto advanc;

	/* mcall */
	case 101:
		*cp++ = 0;		/* 0 arg call */
		os = 100;
		goto fbuild;

	/* ( */
	case 6:
		if (o!=7)
			goto syntax;
		goto advanc;

	/* [ */
	case 4:
		if (o!=5)
			goto syntax;
		build(4);
		goto advanc;
	}
fbuild:
	build(os);
	goto opon1;

syntax:
	error("Expression syntax");
	errflush(o);
	return(0);
}

declare(kw) {
	extern csym[], symbol, paraml[], parame[];
	extern error, cval, errflush, peeksym, exit;
	int t[], n, o;

	while((o=symbol())==20) {		/* name */
		if(kw>=5) {			/* type or sort? */
			if(*csym>0)
				error("%p redeclared", csym[4]);
			*csym = kw;
		} else {
			if ((csym[1]&017)!=0)
				error("%p redeclared", &csym[4]);
			csym[1] =| csym[1]&0760 | kw;
			if (*csym==0)
				*csym = -2;
		}
		while((o=symbol())==4) {	/* [ */
			if((o=symbol())==21) {	/* const */
				if(csym[1]>=020)
					error("Bad vector");
				csym[3] = cval;
				o = symbol();
			}
			if (o!=5)		/* ] */
				goto syntax;
			csym[1] =+ 020;
		}
		if(kw==8)  {		/* parameter */
			*csym = -1;
			if (paraml==0)
				paraml = csym;
			else
				*parame = csym;
			parame = csym;
		}
		if (o!=9)	/* , */
			break;
	}
	if(o==1 & kw!=8 | o==7 & kw==8)
		return;
syntax:
	error("Declaration syntax");
	errflush(o);
}

/* storage */

regtab 0;
efftab 1;
cctab 2;
sptab 3;
symbuf[4];
pssiz 8;
namsiz 8;
nwps 4;
hshused 0;
hshsiz 100;
hshlen 800;	/* 8*hshsiz */
hshtab[800];
space 0;
cp 0;
cmsiz 40;
cmst[40];
ctyp 0;
isn 1;
swsiz 120;
swtab[120];
swp 0;
contlab 0;
brklab 0;
deflab 0;
nreg 4;
maprel[] 60,61,64,65,62,63,68,69,66,67;
nauto 0;
stack 0;
peeksym 0177777;
peekc 0;
eof 0;
line 1;
csym 0;
cval 0;
ncpw 2;
nerror 0;
paraml;
parame;
tmpfil;

c01.c

build(op) {
	extern cp[], error, block, opdope[], maprel[], chklval;
	extern chkw, cvtab, lintyp, dcalc;
	auto p1[], t1, d1, p2[], t2, d2, p3[], t3, d3, t;
	auto d, dope, lr, cvn;
	char cvtab[];

	if (op==4)  {		/* [] */
		build(40);  /* + */
		op = 36;
	}
	dope = opdope[op];
	if ((dope&01)!=0) {
		p2 = *--cp;
		t2 = p2[1];
		d2 = p2[2];
	}
	p1 = *--cp;
	t1 = p1[1];
	d1 = p1[2];
	switch (op) {

	/* , */
	case 9:
		*cp++ = block(2, 9, 0, 0, p1, p2);
		return;

	/* ? */
	case 90:
		if (*p2!=8)
			error("Illegal conditional");
		goto goon;

	/* call */
	case 100:
		*cp++ = block(2,100,t1,24,p1,p2);
		return;

	/* * */
	case 36:
		if ((t1 =- 16)<0)  {
			error("Illegal indirection");
			t1 =+ 16;
		}
		if (*p1!=20 & d1==0)
			d1 = 1;
		*cp++ = block(1,36,t1,d1,p1);
		return;

	/* & unary */
	case 35:
		if (*p1 == 36) {	/* * */
			*cp++ = p1[3];
			return;
		}
		if (*p1 == 20) {
			*cp++ = block(1,p1[3]==5?29:35,t1+16,1,p1);
			return;
		}
		error("Illegal lvalue");
	}
goon:
	if ((dope&02)!=0)		/* lvalue needed on left? */
		chklval(p1);
	if ((dope&020)!=0)		/* word operand on left? */
		chkw(p1);
	if ((dope&040)!=0)		/* word operand on right? */
		chkw(p2);
	if ((dope&01)!=0) {		/* binary op? */
		cvn = cvtab[9*lintyp(t1)+lintyp(t2)];
 		if ((dope&010)!=0)  {	/* assignment? */
			t = t1;
			lr = 1;
			cvn =& 07;
		} else {
			t = (cvn&0100)!=0? t2:t1;
			lr = cvn&0200;
			cvn = (cvn>>3)&07;
		}
		if (cvn) {
			if (cvn==07) {
				error("Illegal conversion");
				goto nocv;
			}
			cvn =+ (dope&010)!=0? 83:93;
			if (lr) {
				t2 = t;
				 d2 = (p2=convert(p2, t, d2, cvn))[2];
			} else {
				t1 = t;
				d1 = (p1=convert(p1, t, d1, cvn))[2];
			}
nocv:;		}
		if (d2>d1 & (dope&0100)!=0) {	/* flip commutative? */
			if ((dope&04)!=0)	/* relational? */
				op = maprel[op-60];
			d = d1;
			d1 = d2;
			d2 = d;
			d = p1;
			p1 = p2;
			p2 = d;
			d = t1;
			t1 = t2;
			t2 = d;
		}
		if (d1==d2)
			d = d1+1; else
			d = max(d1,d2);
		if ((dope&04)!=0)
			t = 0;		/* relational is integer */
		*cp++ = block(2,op,t,d,p1,p2);
		return;
	}
	*cp++ = block(1,op,t1,d1==0?1:d1,p1);
}

convert(p, t, d, cvn)
int p[];
{
	auto c;
	if (*p==21) {		/* constant */
		c = p[3];
		switch(cvn) {

		case 99:		/* c18 */
			c =<< 1;

		case 98:		/* c14 */
			c =<< 1;

		case 97:		/* c12 */
			c =<< 1;

			p[3] = c;
		return(p);
		}
	}
	return(block(1, cvn, t, max(1,d), p));
}

chkw(p)
int p[]; {
	extern error;
	auto t;

	if ((t=p[1])>1 & t<16)
		error("Integer operand required");
	return;
}

lintyp(t) {
	return(t<16? t:(t<32? t-12: 8));
}

error(s, p1, p2) {
	extern printf, line, fout, flush, putchar, nerror;
	int f;

	nerror++;
	flush();
	f = fout;
	fout = 1;
	printf("%d: ", line);
	printf(s, p1, p2);
	putchar('\n');
	fout = f;
}

block(n, op, t, d, p1,p2,p3)
int p1[],p2[],p3[]; {
	extern space[], error, exit, ossiz, ospace[];
	auto p[], ap[];

	p = space;
	ap = &op;
	n =+ 3;
	if(space+n >= ospace+ossiz) {
		error("Expression overflow");
		exit(1);
	}
	while(n--)
		*space++ = *ap++;
	return(p);
}

chklval(p)
int p[]; {
	extern error;
	if (*p!=20)
		if (*p!=36)
			error("Lvalue required");
}

notcompat(at, st) {

	if (st==0)		/* word, byte */
		return(at>1 & at<16);
	if (st==1)		/* word */
		return(at>0 & at<16);
	return((st-2) != at);
}

max(a, b)
{
	if (a>b)
		return(a);
	return(b);
}

c02.c

function() {
	extern declare, blkhed, blkend;
	extern printf, statement, peeksym, cval, symbol, retseq;
	extern paraml;
	auto o;

	printf(".text; 1:mov r5,-(sp); mov sp,r5\n");
	declare(8);
	declist();
	statement(1);
	retseq();
}

extdef() {
	extern eof, function, cval;
	extern symbol, block, printf, pname, errflush, csym[];
	extern error;
	auto o, c, cs[];
	char s[];

	if(((o=symbol())==0) | o==1)	/* EOF */
		return;
	if(o!=20)
		goto syntax;
	csym[0] = 6;
	cs = &csym[4];
	printf(".globl	%p\n", cs);
	s = ".data; %p:1f\n";
	switch(o=symbol()) {

	case 6:				/* ( */
		printf(s, cs);
		function();
		return;

	case 21:			/* const */
		printf(".data; %p: %o\n", cs, cval);
		if((o=symbol())!=1)	/* ; */
			goto syntax;
		return;

	case 1:				/* ; */
		printf(".bss; %p: .=.+2\n", cs);
		return;

	case 4:				/* [ */
		c = 0;
		if((o=symbol())==21) {	/* const */
			c = cval<<1;
			o = symbol();
		}
		if(o!=5)		/* ] */
			goto syntax;
		printf(s, cs);
		if((o=symbol())==1) {	/* ; */
			printf(".bss; 1:.=.+%o\n", c);
			return;
		}
		printf("1:");
		while(o==21) {		/* const */
			printf("%o\n", cval);
			c =- 2;
			if((o=symbol())==1)	/* ; */
				goto done;
			if(o!=9)		/* , */
				goto syntax;
			else
				o = symbol();
		}
		goto syntax;
	done:
		if(c>0)
			printf(".=.+%o\n", c);
		return;

	case 0:				/* EOF */
		return;
	}

syntax:
	error("External definition syntax");
	errflush(o);
	statement(0);
}

statement(d) {
	extern symbol, error, blkhed, eof, peeksym;
	extern blkend, csym[], rcexpr, block[], tree[], regtab[];
	extern retseq, jumpc, jump, label, contlab, brklab, cval;
	extern swp[], isn, pswitch, peekc, slabel;
	extern efftab[], declare, deflab, errflush, swtab[], swsiz, branch;

	int o, o1, o2, o3, np[];

stmt:
	switch(o=symbol()) {

	/* EOF */
	case 0:
		error("Unexpected EOF");
	/* ; */
	case 1:
	/* } */
	case 3:
		return;

	/* { */
	case 2: {
		if(d)
			blkhed();
		while (!eof) {
			if ((o=symbol())==3)	/* } */
				goto bend;
			peeksym = o;
			statement(0);
		}
		error("Missing '}'");
	bend:
		return;
	}

	/* keyword */
	case 19:
		switch(cval) {

		/* goto */
		case 10:
			o1 = block(1,102,0,0,tree());
			rcexpr(o1, regtab);
			goto semi;

		/* return */
		case 11:
			if((peeksym=symbol())==6)	/* ( */
				rcexpr(pexpr(), regtab);
			retseq();
			goto semi;

		/* if */
		case 12:
			jumpc(pexpr(), o1=isn++, 0);
			statement(0);
			if ((o=symbol())==19 & cval==14) {  /* else */
				o2 = isn++;
				(easystmt()?branch:jump)(o2);
				label(o1);
				statement(0);
				label(o2);
				return;
			}
			peeksym = o;
			label(o1);
			return;

		/* while */
		case 13:
			o1 = contlab;
			o2 = brklab;
			label(contlab = isn++);
			jumpc(pexpr(), brklab=isn++, 0);
			o3 = easystmt();
			statement(0);
			(o3?branch:jump)(contlab);
			label(brklab);
			contlab = o1;
			brklab = o2;
			return;

		/* break */
		case 17:
			if(brklab==0)
				error("Nothing to break from");
			jump(brklab);
			goto semi;

		/* continue */
		case 18:
			if(contlab==0)
				error("Nothing to continue");
			jump(contlab);
			goto semi;

		/* do */
		case 19:
			o1 = contlab;
			o2 = brklab;
			contlab = isn++;
			brklab = isn++;
			label(o3 = isn++);
			statement(0);
			label(contlab);
			contlab = o1;
			if ((o=symbol())==19 & cval==13) { /* while */
				jumpc(tree(), o3, 1);
				label(brklab);
				brklab = o2;
				goto semi;
			}
			goto syntax;

		/* case */
		case 16:
			if ((o=symbol())!=21)	/* constant */
				goto syntax;
			if ((o=symbol())!=8)	/* : */
				goto syntax;
			if (swp==0) {
				error("Case not in switch");
				goto stmt;
			}
			if(swp>=swtab+swsiz) {
				error("Switch table overflow");
			} else {
				*swp++ = isn;
				*swp++ = cval;
				label(isn++);
			}
			goto stmt;

		/* switch */
		case 15:
			o1 = brklab;
			brklab = isn++;
			np = pexpr();
			if (np[1]>1 & np[1]<16)
				error("Integer required");
			rcexpr(np, regtab);
			pswitch();
			brklab = o1;
			return;

		/* default */
		case 20:
			if (swp==0)
				error("Default not in switch");
			if ((o=symbol())!=8)	/* : */
				goto syntax;
			deflab = isn++;
			label(deflab);
			goto stmt;
		}

		error("Unknown keyword");
		goto syntax;

	/* name */
	case 20:
		if (peekc==':') {
			peekc = 0;
			if (csym[0]>0) {
				error("Redefinition");
				goto stmt;
			}
			csym[0] = 2;
			csym[1] = 020;	/* int[] */
			if (csym[2]==0)
				csym[2] = isn++;
			slabel();
			goto stmt;
		}
	}

	peeksym = o;
	rcexpr(tree(), efftab);
	goto semi;

semi:
	if ((o=symbol())!=1)		/* ; */
		goto syntax;
	return;

syntax:
	error("Statement syntax");
	errflush(o);
	goto stmt;
}

pexpr()
{
	auto o, t;

	if ((o=symbol())!=6)	/* ( */
		goto syntax;
	t = tree();
	if ((o=symbol())!=7)	/* ) */
		goto syntax;
	return(t);
syntax:
	error("Statement syntax");
	errflush(o);
	return(0);
}

pswitch() {
	extern swp[], isn, swtab[], printf, deflab, statement, brklab;
	extern label;
	int sswp[], dl, cv, swlab;

	sswp = swp;
	if (swp==0)
		swp = swtab;
	swlab = isn++;
	printf("jsr	pc,bswitch; l%d\n", swlab);
	dl = deflab;
	deflab = 0;
	statement(0);
	if (!deflab) {
		deflab = isn++;
		label(deflab);
	}
	printf("L%d:.data;L%d:", brklab, swlab);
	while(swp>sswp & swp>swtab) {
		cv = *--swp;
		printf("%o; l%d\n", cv, *--swp);
	}
	printf("L%d; 0\n.text\n", deflab);
	deflab = dl;
	swp = sswp;
}

blkhed()
{
	extern symbol, cval, declare, peeksym, paraml[], parame[];
	extern error, length, rlength, setstk, defvec, isn, defstat;
	extern stack, hshtab[], hshsiz, pssiz;
	int o, al, pl, cs[], hl;

	declist();
	stack = al = -2;
	pl = 4;
	while(paraml) {
		*parame = 0;
		paraml = *(cs = paraml);
		cs[2] = pl;
		*cs = 10;
		pl =+ rlength(cs[1]);
	}
	cs = hshtab;
	hl = hshsiz;
	while(hl--) {
	    if (cs[4])
		switch(cs[0]) {

		/* sort unmentioned */
		case 0177776:	/* -2 */
			cs[0] = 5;		/* auto */

		/* auto */
		case 5:
			if (cs[3]) {	/* vector */
				al =- (cs[3]*length(cs[1]-020)+1) & 077776;
				setstk(al);
				defvec(al);
			}
			cs[2] = al;
			al =- rlength(cs[1]);
			goto loop;

		/* parameter */
		case 10:
			cs[0] = 5;
			goto loop;

		/* static */
		case 7:
			cs[2] = isn++;
			defstat(cs);
			goto loop;

		loop:;
		}
		cs = cs+pssiz;
	}
	setstk(al);
}

blkend() {
	extern hshtab[], hshsiz, pssiz, hshused;
	auto i, hl;

	i = 0;
	hl = hshsiz;
	while(hl--) {
		if(hshtab[i+4])
			if (hshtab[i]==0)
				error("%p undefined", &hshtab[i+4]);
			if(hshtab[i]!=1) {	/* not keyword */
				hshused--;
				hshtab[i+4] = 0;
			}
		i =+ pssiz;
	}
}

errflush(o) {
	extern symbol, peeksym, eof;

	while(o>3)	/* ; { } */
		o = symbol();
	peeksym  = o;
}

declist()
{
	extern peeksym, peekc, csym[], cval;
	auto o;

	while((o=symbol())==19 & cval<10)
		declare(cval);
	peeksym = o;
}

easystmt()
{
	extern peeksym, peekc, cval;

	if((peeksym=symbol())==20)	/* name */
		return(peekc!=':');	 /* not label */
	if (peeksym==19) {		/* keyword */
		switch(cval)

		case 10:	/* goto */
		case 11:	/* return */
		case 17:	/* break */
		case 18:	/* continue */
			return(1);
		return(0);
	}
	return(peeksym!=2);		/* { */
}

branch(lab)
{
	printf("br	L%d\n", lab);
}

c03.c

jumpc(tree, lbl, cond)
int tree[];
{
	extern cctab, block, rcexpr;

	rcexpr(block(1,easystmt()+103,tree,lbl,cond),cctab);
}

rcexpr(tree, table)
int tree[], table;
{
	extern space, ospace, putwrd, putchar, line;
	int c, sp[];

	putchar('#');
	c = space-ospace;
	c =/ 2;		/* # addresses per word */
	sp = ospace;

	putwrd(c);
	putwrd(tree);
	putwrd(table);
	putwrd(line);
	while(c--)
		putwrd(*sp++);
}

jump(lab) {
	extern printf;

	printf("jmp\tl%d\n", lab);
}

label(l) {
	extern printf;

	printf("l%d:", l);
}

retseq() {
	extern printf;

	printf("jmp\tretrn\n");
}

slabel() {
	extern csym[], printf;

	printf(".data; l%d: 1f; .text; 1:\n", csym[2]);
}

setstk(a) {
	extern printf, stack;
	auto ts;

	ts = a-stack;
	stack = a;
	switch(ts) {

	case 0:
		return;

	case 0177776:	/* -2 */
		printf("tst	-(sp)\n");
		return;

	case 0177774:	/* -4 */
		printf("cmp	-(sp),-(sp)\n");
		return;
	}
	printf("add	$%o,sp\n", ts);
}

defvec() {
	extern printf, stack;

	printf("mov\tsp,r0\nmov\tr0,-(sp)\n");
	stack =- 2;
}

defstat(s)
int s[]; {
	extern printf, length;
	int len;

	len = length(s[1]);
	if (s[3])
		printf(".data; l%d:1f; .bss; 1:.=.+%o; .even; .text\n", s[2],
			s[3]*len);
	else
		printf(".bss; l%d:.=.+%o; .even; .text\n", s[2], len);
}

length(t) {

	if (t<0)
		t =+ 020;
	if (t>=020)
		return(2);
	switch(t) {

	case 0:
		return(2);

	case 1:
		return(1);

	case 2:
		return(4);

	case 3:
		return(8);

	case 4:
		return(4);

	}
	return(1024);
}

rlength(c) {
	extern length;
	auto l;

	return((l=length(c))==1? 2: l);
}

printn(n,b) {
	extern putchar;
	auto a;

	if(a=n/b) /* assignment, not test for equality */
		printn(a, b); /* recursive */
	putchar(n%b + '0');
}

printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9)
char fmt[]; {
	extern printn, putchar, namsiz, ncpw;
	char s[];
	auto adx[], x, c, i[];

	adx = &x1; /* argument pointer */
loop:
	while((c = *fmt++) != '%') {
		if(c == '\0')
			return;
		putchar(c);
	}
	x = *adx++;
	switch (c = *fmt++) {

	case 'd': /* decimal */
	case 'o': /* octal */
		if(x < 0) {
			x = -x;
			if(x<0)  {	/* - infinity */
				if(c=='o')
					printf("100000");
				else
					printf("-32767");
				goto loop;
			}
			putchar('-');
		}
		printn(x, c=='o'?8:10);
		goto loop;

	case 's': /* string */
		s = x;
		while(c = *s++)
			putchar(c);
		goto loop;

	case 'p':
		s = x;
		putchar('_');
		c = namsiz;
		while(c--)
			if(*s)
				putchar(*s++);
		goto loop;
	}
	putchar('%');
	fmt--;
	adx--;
	goto loop;
}

c0t.s

/ word I/O

.globl	_putwrd

.globl	_tmpfil
.globl	putw
.globl	fcreat
.globl	flush

.data
_putwrd: 1f
.text
1:
	tst	buf
	bne	1f
	mov	_tmpfil,r0
	jsr	r5,fcreat; buf
	bec	1f
	mov	$1,r0
	sys	write; botch; ebotch-botch
	sys	exit
1:
	mov	2(sp),r0
	jsr	r5,putw; buf
	rts	pc
.globl	_flshw
.data
_flshw:	1f
.text
1:
	jsr	r5,flush; buf
	rts	pc

botch:	<Temp file?\n\0>; ebotch:
.even

.bss
buf:	.=.+518.
.text

/ C operator and conversion tables

.globl	_opdope
.globl	_cvtab

_opdope:.+2
	00000	/ EOF
	00000	/ ;
	00000	/ {
	00000	/ }
	36000	/ [
	02000	/ ]
	36000	/ (
	02000	/ )
	14201	/ :
	07001	/ ,
	00000	/ 10
	00000	/ 11
	00000	/ 12
	00000	/ 13
	00000	/ 14
	00000	/ 15
	00000	/ 16
	00000	/ 17
	00000	/ 18
	00000	/ 19
	00000	/ name
	00000	/ short constant
	00000	/ string
	00000	/ float
	00000	/ double
	00000	/ 25
	00000	/ 26
	00000	/ 27
	00000	/ 28
	00000	/ 29
	34202	/ ++pre
	34202	/ --pre
	34202	/ ++post
	34202	/ --post
	34220	/ !un
	34202	/ &un
	34220	/ *un
	34200	/ -un
	34220	/ ~un
	00000	/ 39
	30101	/ +
	30001	/ -
	32101	/ *
	32001	/ /
	32001	/ %
	26061	/ >>
	26061	/ <<
	20161	/ &
	16161	/ |
	16161	/ ^
	00000	/ 50
	00000	/ 51
	00000	/ 52
	00000	/ 53
	00000	/ 54
	00000	/ 55
	00000	/ 56
	00000	/ 57
	00000	/ 58
	00000	/ 59
	22105	/ ==
	22105	/ !=
	24105	/ <=
	24105	/ <
	24105	/ >=
	24105	/ >
	24105	/ <p
	24105	/ <=p
	24105	/ >p
	24105	/ >=p
	12213	/ =+
	12213	/ =-
	12213	/ =*
	12213	/ =/
	12213	/ =%
	12253	/ =>>
	12253	/ =<<
	12253	/ =&
	12253	/ =|
	12253	/ =^
	12213	/ =
	00000	/ 81
	00000	/ 82
	00000	/ 83
	00000	/ int -> float
	00000	/ int -> double
	00000	/ float -> int
	00000	/ float -> double
	00000	/ double -> int
	00000	/ double -> float
	14201	/ ?
	00000	/ 91
	00000	/ 92
	00000	/ 93
	00000	/ int -> float
	00000	/ int -> double
	00000	/ float -> double
	00000	/ int -> int[]
	00000	/ int -> float[]
	00000	/ int -> double[]
	36001	/ call
	36001	/ mcall

_cvtab:	.+2
	.byte	000	/ i:i
	.byte	000	/ i:c
	.byte	113	/ i:f
	.byte	125	/ i:d
	.byte	140	/ i:i[]
	.byte	100	/ i:c[]
	.byte	150	/ i:f[]
	.byte	160	/ i:d[]
	.byte	140	/ i:[][]

	.byte	100	/ c:i
	.byte	100	/ c:c
	.byte	113	/ c:f
	.byte	125	/ c:d
	.byte	140	/ c:i[]
	.byte	100	/ c:c[]
	.byte	150	/ c:f[]
	.byte	160	/ c:d[]
	.byte	140	/ c[][]

	.byte	211	/ f:i
	.byte	211	/ f:c
	.byte	000	/ f:f
	.byte	136	/ f:d
	.byte	211	/ f:i[]
	.byte	211	/ f:c[]
	.byte	211	/ f:f[]
	.byte	211	/ f:d[]
	.byte	211	/ f:[][]

	.byte	222	/ d:i
	.byte	222	/ d:c
	.byte	234	/ d:f
	.byte	000	/ d:d
	.byte	222	/ d:i[]
	.byte	222	/ d:c[]
	.byte	222	/ d:f[]
	.byte	222	/ d:d[]
	.byte	222	/ d:[][]

	.byte	240	/ i[]:i
	.byte	240	/ i[]:c
	.byte	113	/ i[]:f
	.byte	125	/ i[]:d
	.byte	000	/ i[]:i[]
	.byte	000	/ i[]:c[]
	.byte	100	/ i[]:f[]
	.byte	100	/ i[]:d[]
	.byte	100	/ i[]:[][]

	.byte	000	/ c[]:i
	.byte	000	/ c[]:c
	.byte	113	/ c[]:f
	.byte	125	/ c[]:d
	.byte	200	/ c[]:i[]
	.byte	000	/ c[]:c[]
	.byte	200	/ c[]:f[]
	.byte	200	/ c[]:d[]
	.byte	200	/ c[]:[][]

	.byte	250	/ f[]:i
	.byte	250	/ f[]:c
	.byte	113	/ f[]:f
	.byte	125	/ f[]:d
	.byte	000	/ f[]:i[]
	.byte	000	/ f[]:c[]
	.byte	000	/ f[]:f[]
	.byte	100	/ f[]:d[]
	.byte	000	/ f[]:[][]

	.byte	260	/ d[]:i
	.byte	260	/ d[]:c
	.byte	113	/ d[]:f
	.byte	125	/ d[]:d
	.byte	000	/ d[]:i[]
	.byte	000	/ d[]:c[]
	.byte	000	/ d[]:f[]
	.byte	000	/ d[]:d[]
	.byte	000	/ d[]:[][]

	.byte	240	/ [][]:i
	.byte	240	/ [][]:c
	.byte	113	/ [][]:f
	.byte	125	/ [][]:d
	.byte	000	/ [][]:i[]
	.byte	000	/ [][]:c[]
	.byte	100	/ [][]:f[]
	.byte	100	/ [][]:d[]
	.byte	000	/ [][]:[][]

.even

/ character type table

.globl	_ctab

_ctab: .+2
	.byte 000.,127.,127.,127.,127.,127.,127.,127.
	.byte 127.,126.,125.,127.,127.,127.,127.,127.
	.byte 127.,127.,127.,127.,127.,127.,127.,127.
	.byte 127.,127.,127.,127.,127.,127.,127.,127.
	.byte 126.,034.,122.,127.,127.,044.,047.,121.
	.byte 006.,007.,042.,040.,009.,041.,127.,043.
	.byte 124.,124.,124.,124.,124.,124.,124.,124.
	.byte 124.,124.,008.,001.,063.,080.,065.,090.
	.byte 127.,123.,123.,123.,123.,123.,123.,123.
	.byte 123.,123.,123.,123.,123.,123.,123.,123.
	.byte 123.,123.,123.,123.,123.,123.,123.,123.
	.byte 123.,123.,123.,004.,127.,005.,049.,127.
	.byte 127.,123.,123.,123.,123.,123.,123.,123.
	.byte 123.,123.,123.,123.,123.,123.,123.,123.
	.byte 123.,123.,123.,123.,123.,123.,123.,123.
	.byte 123.,123.,123.,002.,048.,003.,127.,127.

c10.c

/*

	    	C compiler, part 2

	Copyright 1972 Bell Telephone Laboratories, Inc.

*/

ospace() {}	/* fake */

waste()		/* waste space */
{
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
	waste(waste(waste),waste(waste),waste(waste));
}
main(argc, argv)
char argv[][];
{
	extern fout, fin, nerror, line;
	extern getwrd, rcexpr, ospace, tmpfil;
	extern cctab[], regtab[], efftab[], sptab[];
	int sp[], c, table[], tabtab[3][], tree;

	if (argc<4) {
		error("Arg count");
		exit(1);
	}
	if((fin=open(argv[1],0))<0) {
		error("Cant't find %s", argv[1]);
		exit(1);
	}
	if((fout=creat(argv[3],017))<0) {
		error("Can't create %s", argv[3]);
		exit(1);
	}
	tmpfil = argv[2];

	tabtab[0] = regtab;
	tabtab[1] = efftab;
	tabtab[2] = cctab;
	tabtab[3] = sptab;
	while(c=getchar()) {
		if(c=='#') {
			sp = ospace;
			c = getwrd();
			tree = getwrd();
			table = tabtab[getwrd()];
			line = getwrd();
			while(c--)
				*sp++ = getwrd();
			rcexpr(tree, table, 0);
		} else
			putchar(c);
	}
	flush();
	exit(nerror!=0);
}

match(tree, table, nreg)
int tree[], table[]; {
	extern opdope[], dcalc, notcompat;
	int op, d1, d2, t1, t2, p1[], p2[];
	char mp[];

	if (tree==0)
		return(0);
	op = *tree;
	if (op>=29)			/* if not leaf */
		p1 = tree[3];
	else
		p1 = tree;
	t1 = p1[1];
	d1 = dcalc(p1, nreg);
	if ((opdope[op]&01)!=0) {	/* binary? */
		p2 = tree[4];
		t2 = p2[1];
		d2 = dcalc(p2, nreg);
	}
	while(*table) {
		if (*table++ == op) goto foundop;
		table++;
	}
	return(0);
foundop:
	table = *table;
nxtry:
	mp = table;
	if (*mp == 0)
		return(0);
	if (d1 > (*mp&077) | (*mp>=0100)&(*p1!=36))
		goto notyet;
	if (notcompat(t1, mp[1]))
		goto notyet;
	if ((opdope[op]&01)!=0 & p2!=0) {
		if (d2 > (mp[2]&077) | (mp[2]>=0100)&(*p2!=36))
			goto notyet;
		if (notcompat(t2,mp[3]))
			goto notyet;
	}
now:
	return(table[2]);
notyet:
	table = table+3;
	goto nxtry;
}

rcexpr(tree, table, reg)
int tree[]; {
	extern cexpr, regtab, cctab, sptab, printf, error;
	extern jumpc, cbranch;

	if(tree==0)
		return;
	if(*tree >= 103) {
		(*tree==103?jumpc:cbranch)(tree[1],tree[2],tree[3],0);
		return;
	}
	if (cexpr(tree, table, reg))
		return;
	if (table!=regtab) 
		if(cexpr(tree, regtab, reg)) {
			if (table==sptab)
				printf("mov	r%d,-(sp)\n", reg);
			if (table==cctab)
				printf("tst	r%d\n", reg);
			return;
		}
	error("No match for op %d", *tree);
}

cexpr(tree, table, reg)
int tree[][], table[]; {
	extern match, nreg, printf, pname, putchar, regtab;
	extern sptab, cctab, rcexpr, prins, rlength, popstk;
	extern collcon, isn, label, branch, cbranch, fltmod;
	int p1[], p2[], c, r, p[], otable[], ctable[], regtab[], cctab[];
	char string[], match[];

	if ((c = *tree)==100) {		/* call */
		p1 = tree[3];
		p2 = tree[4];
		r = 0;
		if(p2) {
			while (*p2==9) { /* comma */
				rcexpr(p2[4], sptab, 0);
				r =+ rlength((p=p2[4])[1]);
				p2 = p2[3];
			}
			rcexpr(p2, sptab, 0);
			r =+ rlength(p2[1]);
		}
		*tree = 101;
		tree[2] = r;		/* save arg length */
	}
	if(c==90) {		/* ? */
		cbranch(tree[3], c=isn++, 0, reg);
		rcexpr(tree[4][3], table, reg);
		branch(r=isn++, 0);
		label(c);
		rcexpr(tree[4][4], table, reg);
		label(r);
		return(1);
	}
	if ((string=match(tree, table, nreg-reg))==0) 
		return(0);
	p1 = tree[3];
	p2 = tree[4];
loop:
	switch(c = *string++) {

	case '\0':
		p = tree;
		if (*p==101 & p[2]>0) {
			popstk(p[2]);
		}
		return(1);

	/* A1 */
	case 'A':
		p = tree[3];
		goto adr;

	/* A2 */
	case 'B':
		p = tree[4];
		goto adr;

	/* A */
	case 'O':
		p = tree;
	adr:
		pname(p);
		goto loop;

	/* I */
	case 'M':
		if ((c = *string)=='\'')
			string++; else
			c = 0;
		prins(*tree, c);
		goto loop;

	/* B1 */
	case 'C':
		p = tree[3];
		goto pbyte;

	/* BF */
	case 'P':
		p = tree;
		goto pb1;

	/* B2 */
	case 'D':
		p = tree[4];
	pbyte:
		if (p[1]==1)	/* char type? */
			putchar('b');
pb1:
		if (isfloat(p))
			putchar('f');
		goto loop;

	/* BE */
	case 'L':
		if (tree[3][1]==1 | tree[4][1]==1)
			putchar('b');
		goto loop;

	/* C1 */
	case 'E':
		p = p1[3];
		goto const;

	/* C2 */
	case 'F':
		p = p2[3];
	const:
		printf("%o", p);
		goto loop;

	/* F */
	case 'G':
		p = p1;
		goto subtre;

	/* S */
	case 'K':
		p = p2;
		goto subtre;

	/* H */
	case 'H':
		p = tree;

	subtre:
		ctable = regtab;
		r = reg;
		c = *string++ - 'A';
		if ((c&02)!=0)
			ctable = sptab;
		if ((c&04)!=0)
			ctable = cctab;
		if((c&010)!=0)
			r = reg+1;
		if((c&01)!=0)
			if(*p==36) {
				p = p[3];
				if(collcon(p) & ctable!=sptab)
					p = p[3];
			}
		rcexpr(p, ctable, r);
		goto loop;

	/* R */
	case 'I':
		r = reg;
		goto preg;

	/* R1 */
	case 'J':
		r = reg+1;
	preg:
		printf("r%d", r);
		goto loop;

	case '#':
		p = p1[3];
		goto nmbr;

	case '"':
		p = p2[3];
		goto nmbr;
	case '~':
		p = tree[3];

	nmbr:
		if(collcon(p)) {
			c = *p;
			if(r = (p=p[4])[3])
				printf("%o", c==40?r:-r);
		}
		goto loop;

	/* M */
	case 'N':
		if ((c=isfloat(tree, &string))==fltmod)
			goto loop;
		printf((fltmod=c)==2?"setf\n":"setd\n");
		goto loop;

	/* Z */
	case 'Z':
		printf("$%o", p1[4]);
		goto loop;
	}
	putchar(c);
	goto loop;
}

pname(p)
int p[][][]; {
	extern putchar, printf, error;
	char np[];
	int i;

loop:
	switch(*p) {

	case 21:		/* const */
		printf("$%o", p[3]);
		return;

	case 22:		/* string */
		printf("$l%d", p[3]);
		return;

	case 20:		/* name */
		switch(p[3]) {

		case 5:		/* auto, param */
			printf("%o(r5)", p[4]);
			return;

		/* extern */
		case 6:
			printf("%p", &p[4]);
			return;

		}
		printf("L%d", p[4]);
		return;

	case 35:		/* & */
		putchar('$');
		p = p[3];
		goto loop;

	case 36:		/* * */
		putchar('*');
		p = p[3];
		goto loop;
	}
	error("pname called illegally");
}

dcalc(p, nreg)
int p[]; {
	int op, t;

	if (p==0)
		return(0);
	op = *p;
	switch (op) {

	case 20:		/* name */
	case 22:		/* string */
	case 23:		/* float */
	case 24:		/* double */
		return(12);

	case 21:		/* short constant */
		return(p[3]==0? 4:8);

	case 35:		/* & */
		return(12);

	case 36:		/* * */
		if ((op=dcalc(p[3], nreg))<16)
			return(16);
	}

def:
	return(p[2]<=nreg? 20: 24);
}

notcompat(at, st) {

	if (st==0)		/* word, byte */
		return(at>1 & at<16);
	if (st==1)		/* word */
		return(at>0 & at<16);
	st =- 2;
	if (st==2 & at==3)
		at = 2;
	return(st != at);
}

prins(op, c) {
	extern instab[], printf;
	int insp[];

	insp = instab;
	while(*insp) {
		if (*insp++ == op) {
			if ((c = insp[c!=0])==0)
				goto err;
			printf("%s", c);
			return;
		} else
			insp = insp + 2;
	}
err:
	error("No match' for op %d", op);
}

collcon(p)
int p[]; {
	int p1[];

	if(*p==40 | *p==41)
		if(*(p1=p[4])==21)
			return(1);
	return(0);
}

isfloat(t, s)
int t[];
char s[][];
{
	extern opdope[];
	int rt;

	rt = **s - '0';
	if (rt==2 | rt==4) {
		(*s)++;
		return(rt>2?3:2);
	}
	if ((opdope[t[0]]&010)!=0)	/* relational */
		t = t[3];
	if ((rt=t[1])>=2 & rt<=3)
		return(rt);
	return(0);
}

nreg 4;
isn 10000;
namsiz 8;
line;
tmpfil;
nerror;
fltmod;

c11.c

jumpc(tree, lbl, cond)
int tree[]; {
	extern jump, cctab[], rcexpr, isn, label, branch, cbranch;
	int l1, l2;

	if (tree==0)
		return;
	switch(*tree) {

	/* & */
	case 47:
		if (cond) {
			cbranch(tree[3], l1=isn++, 0, 0);
			cbranch(tree[4], l1, 0, 0);
			jump(lbl);
			label(l1);
		} else {
			cbranch(tree[3], l1=isn++, 0, 0);
			cbranch(tree[4], l2=isn++, 1, 0);
			label(l1);
			jump(lbl);
			label(l2);
		}
		return;

	/* | */
	case 48:
		if (cond) {
			cbranch(tree[3], l1=isn++, 1, 0);
			cbranch(tree[4], l2=isn++, 0, 0);
			label(l1);
			jump(lbl);
			label(l2);
		} else {
			cbranch(tree[3], l1=isn++, 1, 0);
			cbranch(tree[4], l1, 1, 0);
			jump(lbl);
			label(l1);
		}
		return;

	/* ! */
	case 34:
		jumpc(tree[3], lbl, !cond);
		return;
	}
	rcexpr(tree, cctab, 0);
	branch(l1=isn++, *tree, cond);
	jump(lbl);
	label(l1);
	return;
}

cbranch(tree, lbl, cond, reg)
int tree[]; {
	extern branch, cctab[], rcexpr, isn, label;
	int l1;

	if (tree==0)
		return;
	switch(*tree) {

	/* & */
	case 47:
		if (cond) {
			cbranch(tree[3], l1=isn++, 0, reg);
			cbranch(tree[4], lbl, 1, reg);
			label(l1);
		} else {
			cbranch(tree[3], lbl, 0, reg);
			cbranch(tree[4], lbl, 0, reg);
		}
		return;

	/* | */
	case 48:
		if (cond) {
			cbranch(tree[3], lbl, 1, reg);
			cbranch(tree[4], lbl, 1, reg);
		} else {
			cbranch(tree[3], l1=isn++, 1, reg);
			cbranch(tree[4], lbl, 0, reg);
			label(l1);
		}
		return;

	/* ! */
	case 34:
		cbranch(tree[3], lbl, !cond, reg);
		return;
	}
	rcexpr(tree, cctab, reg);
	branch(lbl, *tree, !cond);
	return;
}


branch(lbl, op, c) {
	extern printf, prins, opdope[];

	if(op) {
		if((opdope[op]&04)==0)
			op = 61;
		prins(op,c);
	} else
		printf("br");
	printf("\tl%d\n", lbl);
}

jump(lab) {
	extern printf;

	printf("jmp\tl%d\n", lab);
}

label(l) {
	extern printf;

	printf("l%d:", l);
}


popstk(a) {
	extern printf;

	switch(a) {

	case 0:
		return;

	case 2:
		printf("tst	(sp)+\n");
		return;

	case 4:
		printf("cmp	(sp)+,(sp)+\n");
		return;
	}
	printf("add	$%o,sp\n", a);
}

length(t) {

	if (t<0)
		t =+ 020;
	if (t>=020)
		return(2);
	switch(t) {

	case 0:
		return(2);

	case 1:
		return(1);

	case 2:
		return(4);

	case 3:
		return(8);

	case 4:
		return(4);

	}
	return(1024);
}

rlength(c) {
	extern length;
	auto l;

	return((l=length(c))==1? 2: l);
}

printn(n,b) {
	extern putchar;
	auto a;

	if(a=n/b) /* assignment, not test for equality */
		printn(a, b); /* recursive */
	putchar(n%b + '0');
}

printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9)
char fmt[]; {
	extern printn, putchar, namsiz, ncpw;
	char s[];
	auto adx[], x, c, i[];

	adx = &x1; /* argument pointer */
loop:
	while((c = *fmt++) != '%') {
		if(c == '\0')
			return;
		putchar(c);
	}
	x = *adx++;
	switch (c = *fmt++) {

	case 'd': /* decimal */
	case 'o': /* octal */
		if(x < 0) {
			x = -x;
			if(x<0)  {	/* - infinity */
				if(c=='o')
					printf("100000");
				else
					printf("-32767");
				goto loop;
			}
			putchar('-');
		}
		printn(x, c=='o'?8:10);
		goto loop;

	case 's': /* string */
		s = x;
		while(c = *s++)
			putchar(c);
		goto loop;

	case 'p':
		s = x;
		putchar('_');
		c = namsiz;
		while(c--)
			if(*s)
				putchar(*s++);
		goto loop;
	}
	putchar('%');
	fmt--;
	adx--;
	goto loop;
}

error(s, p1, p2) {
	extern printf, line, fout, flush, putchar, nerror;
	int f;

	nerror++;
	flush();
	f = fout;
	fout = 1;
	printf("%d: ", line);
	printf(s, p1, p2);
	putchar('\n');
	fout = f;
}

c1t.s

/ C operator tables

.globl	_getwrd

.globl	getw
.globl	fopen
.globl	_tmpfil

.data
_getwrd: 1f
.text
1:
	tst	buf
	bne	1f
	mov	_tmpfil,r0
	jsr	r5,fopen; buf
	bes	botchp
1:
	jsr	r5,getw; buf
	bes	botchp
	rts	pc
botchp:
	mov	$1,r0
	sys	write; botch; ebotch-botch
	sys	exit
botch:
	<Temp file botch.\n>; ebotch:
.even
.bss
buf:	.=.+518.
.text
.globl	_opdope
.globl	_instab

_instab:.+2
	40.; 1f; 1f; .data; 1:<add\0>; .text
	70.; 1b; 1b
	41.; 2f; 2f; .data; 2:<sub\0>; .text
	71.; 2b; 2b
	30.; 3f; 1b; .data; 3:<inc\0>; .text
	31.; 4f; 2b; .data; 4:<dec\0>; .text
	32.; 3b; 1b
	33.; 4b; 2b

	45.; 2b; 5f; .data; 5:<ac\0>; .text
	46.; 6f; 7f; .data; 6:<mov\0>; 7:<(r4)\0>; .text
	75.; 2b; 5b
	76.; 6b; 7b
	43.; 7b; 1f; .data; 1:<divf\0>; .text
	44.; 5b; 0
	73.; 7b; 1b
	74.; 5b; 0

	60.; 0f; 1f; .data; 0:<beq\0>; 1:<bne\0>; .text
	61.; 1b; 0b
	62.; 2f; 5f; .data; 2:<ble\0>; 5:<bgt\0>; .text
	63.; 3f; 4f; .data; 3:<blt\0>; 4:<bge\0>; .text
	64.; 4b; 3b
	65.; 5b; 2b
	66.; 6f; 9f; .data; 6:<blos\0>; 9:<bhi\0>; .text
	67.; 7f; 8f; .data; 7:<blo\0>; 8:<bhis\0>; .text
	68.; 8b; 7b
	69.; 9b; 6b
	0
	.data
	.even
	.text

_opdope:.+2
	00000	/ EOF
	00000	/ ;
	00000	/ {
	00000	/ }
	36000	/ [
	02000	/ ]
	36000	/ (
	02000	/ )
	02000	/ :
	07001	/ ,
	00000	/ 10
	00000	/ 11
	00000	/ 12
	00000	/ 13
	00000	/ 14
	00000	/ 15
	00000	/ 16
	00000	/ 17
	00000	/ 18
	00000	/ 19
	00000	/ name
	00000	/ short constant
	00000	/ string
	00000	/ float
	00000	/ double
	00000	/ 25
	00000	/ 26
	00000	/ 27
	00000	/ 28
	00000	/ 29
	34002	/ ++pre
	34002	/ --pre
	34002	/ ++post
	34002	/ --post
	34020	/ !un
	34002	/ &un
	34020	/ *un
	34000	/ -un
	34020	/ ~un
	00000	/ 39
	30101	/ +
	30001	/ -
	32101	/ *
	32001	/ /
	32001	/ %
	26061	/ >>
	26061	/ <<
	20161	/ &
	16161	/ |
	16161	/ ^
	00000	/ 50
	00000	/ 51
	00000	/ 52
	00000	/ 53
	00000	/ 54
	00000	/ 55
	00000	/ 56
	00000	/ 57
	00000	/ 58
	00000	/ 59
	22105	/ ==
	22105	/ !=
	24105	/ <=
	24105	/ <
	24105	/ >=
	24105	/ >
	24105	/ <p
	24105	/ <=p
	24105	/ >p
	24105	/ >=p
	12013	/ =+
	12013	/ =-
	12013	/ =*
	12013	/ =/
	12013	/ =%
	12053	/ =>>
	12053	/ =<<
	12053	/ =&
	12053	/ =|
	12053	/ =^
	12013	/ =
	00000	/ 81
	00000	/ 82
	00000	/ 83
	00000	/ int -> float
	00000	/ int -> double
	00000	/ float -> int
	00000	/ float -> double
	00000	/ double -> int
	00000	/ double -> float
	14001	/ ?
	00000	/ 91
	00000	/ 92
	00000	/ 93
	00000	/ int -> float
	00000	/ int -> double
	00000	/ float -> double
	00000	/ int -> int[]
	00000	/ int -> float[]
	00000	/ int -> double[]
	36001	/ call
	36001	/ mcall

t.c

main() {
	extern a, b, c, i;
	float a, b;
	double c;
	int i;

	a = b;
	a = b*c;
	a = b*c/a;
	a = c;
	c = a;
	a = c*c+a;
	a = 1;
	a = a+1;
	i = a;
	i = c;
	a++;
	c++;
}