Annexe Unix 72
Voici le premier compilateur écrit en C en 1972 : il s’agit du compilateur C pour UNIX V2. Il fait autorité quant à la première grammaire de ce langage.
Vous en trouverez des archives de plusieurs versions à cette adresse : https://www.tuhs.org/Archive/Distributions/Research/ 🌍⤴
Ainsi que ici : https://www.tuhs.org/cgi-bin/utree.pl 🌍⤴
Cette version comprenait la distinction entre int et char
et supportait les nombres flottants en simple et double
précision (float et double). Sont absents les entiers
short et long, les entiers unsigned et les char signed.
Trois classes de stockage sont gérés : auto, extern et static.
Tout le reste sont des instructions de saut : goto, return, if, while,
else, switch, case, break, continue, do, default.
La boucle for n’existe pas.
Les tableaux et les pointeurs sont présents mais pas les structures.
La déclaration de pointeurs ne se fait pas
avec une astérisque mais une paire de crochets vide : int p[]. L’aspect général
du code 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.
L’initialisation en meme temps que la déclaration n’est possible
que pour les variables externes, avec une syntaxe qui a disparu depuis :
par exemple line 1;.
Ce n’est valable que pour les variables globales non automatiques : 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).
Le nombre de caractères maximal que peut avoir un mot clé ou une variable est de 8
(namsiz 8). Seul le mot-clé continue utilise tous les 8 caractères. Tous les
noms de variables, de fonctions sont brefs.
Le mot clé void n’existe pas : une fonction ne peut retourner que un int
donc on ne déclare pas le type de la valeur retournée par une fonction.
Pas de distinction entre “routines” et “fonctions”
comme dans Pascal, il n’y a qu’une seule convention d’appel est à implémenter en assembleur. Si on
voulait qu’une fonction retourne un double, on passe soit par une variable externe (globale)
ou un pointeur.
Il n’est pas possible ni utile de déclarer les fonctions vu qu’elles ont toutes
la même signature : à savoir extern int fonction();.
Trois évolutions du langage ont été nécessaires pour éliminer la nécessité de déclarer dans chaque fonction les variables externes utilisées par celle-ci:
Pouvoir déclarer un symbole extern en dehors des fonctions, ce qui est l’équivalent
de réécrire extern fonction, variable, etc; dans chaque fonction.
fun1() {
extern fun;
}
fun2() {
extern fun;
}
fun() {}
Peut se simplifier
extern fun;
fun1() {
}
fun2() {
}
fun() {}
Une syntaxe pour distinguer déclaration de variable et déclaration de fonction sera aussi introduite
fun(); /* declare une fonction, extern implicite, n'alloue pas d'espace */
var; /* declare une variable, alloue de l'espace et l'intialise à zero */
extern var2; /* declare une variable sans lui allouer d'espace et sans l'initialiser,
utile dans les fichier en tetes qui arriveront plus tard,
pour signaler une variable partagée entee plusiers
unités de compilation */
extern fun2(); /* extern ici est optionnel, meme effet que la declaration de fonction precedente */
static fun3(); /* static permet de cacher une fonction à l'editeur de lien,
le mot-clé static etait deja utilisé pour des variables locales, il est réutilisé
car il n'y a pas d'ambiguité */
Une règle implicite vis à vis des déclarations de fonctions est que si il n’y en a pas,
le compilateur considère que celle ci est de la forme extern int fonction();, c’est à
dire une fonction retournant int et prenant un nombre quelconque d’aguments de type
quelconque. C’est pour cela que le « hello wold » du premier livre de référence du langage
C peut s’écrire ainsi.
main()
{
printf("Hello, Wold!\n");
}
pas besoin d’importer stdio.h car printf a la signature implicite
extern int printf();, et le compilateur lie implicitement la librairie C
qui contient la définition de la fonction printf. L’éditeur de lien sera
capable de lier l’appel à la fonction printf avec son emplacement effectif
dans le programme final. Autrement dit la commande shell cc prog.c
est synonyme de cc -lc prog.c.
Toutes les fonctions anciennes de la librairie C, retournent
quasiment toutes une valeur int.
Depuis le C99, une telle syntaxe n’est plus valide car une fonction doit déclarer son type de retour,
intn’est plus implicite pourmain: gcc le tolère jusqu’au C23, où il devient obligatoire d’activer le mode-ansiet-wpour que ce programme compile :gcc -w -ansi prog.c.
Le mot clé void permettra de déclarer une fonction qui ne retourne rien
de sorte à pouvoir émuler les “routines” du langage Pascal et faire l’économie d’une
instruction assembleur plaçant une valeur de retour sur la pile ou un
registre idoine. En sus de void une fonction pourra
retourner une valeur de type scalaire quelconque (char, float, double):
cela supposat d’implémenter plusieurs conventions d’appel de fonctions,
ce qui était hors de propos pour le
compilateur minimaliste des premières versions d’UNIX.
Et bien plus tard encore, le C++ a introduit la notion de prototype qui enrichit
la notion de déclaration de fonction : non seulement on peut décider le type
de valeur retournée par une fonction, ainsi que sa visibilité, mais également contraindre
le type et le nombre des arguments acceptés par la fonction, et en introduisant une syntaxe
nouvelle pour les fonctions a nombre variable d’arguments : int fontion(int, ...);.
Par pédantisme on peut considérer que la déclaration et le prototype d’une fonction sont deux choses différentes : si un prototype peut être considéré comme une déclaration, le contraire n’est pas forcément vrai.
extern fun; /* declaration "prehistorique" de fonction, locale */
fun(); /* déclaration plus moderne, externe */
void fun2(); /* déclaration d'une procedure, externe */
int fun3(float, int); /* déclaration moderne, aussi appellée protoype, dans fichier entete si non statique */
C’est surtout avec l’introduction du préprocesseur que les déclarations de fonctions et de variables globales partagées est devenue pertinente.
On rappelle que si le mot clé extern est présent en dehors
d’une fonction, celle-ci est valide pour toute l’unité
de compilation qui suit. Au demeurant toutes les déclarations de fonction
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.
On regroupe donc toutes les déclarations de fonctions utiles dans un fichier* “entête” et on l’inclut via le préprocesseur.
/* entete.h */
int foo();
double bar();
static baz();
extern toto;
/* main.c */
#include "entete.h"
toto = 1;
main() {
foo();
bar();
/* etc. */
}
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++;
}