legacy-cc

The earliest versions of the very first c compiler known to exist in the wild written by the late legend himself dmr. https://github.com/mortdeus/legacy-cc
git clone http://git.hanabi.in/repos/legacy-cc.git
Log | Files | Refs | README

c00.c (8502B)


      1 /* C compiler
      2 
      3 Copyright 1972 Bell Telephone Laboratories, Inc. 
      4 
      5 */
      6 
      7 ossiz 250;
      8 ospace() {}	/* fake */
      9 
     10 init(s, t)
     11 char s[]; {
     12 	extern lookup, symbuf, namsiz;
     13 	char symbuf[], sp[];
     14 	int np[], i;
     15 
     16 	i = namsiz;
     17 	sp = symbuf;
     18 	while(i--)
     19 		if ((*sp++ = *s++)=='\0') --s;
     20 	np = lookup();
     21 	*np++ = 1;
     22 	*np = t;
     23 }
     24 
     25 main(argc, argv)
     26 int argv[]; {
     27 	extern init, flush;
     28 	extern extdef, eof, open, creat;
     29 	extern fout, fin, error, exit, nerror, tmpfil;
     30 
     31 	if(argc<4) {
     32 		error("Arg count");
     33 		exit(1);
     34 	}
     35 	if((fin=open(argv[1],0))<0) {
     36 		error("Can't find %s", argv[1]);
     37 		exit(1);
     38 	}
     39 	if((fout=creat(argv[2], 017))<0) {
     40 		error("Can't create %s", argv[2]);
     41 		exit(1);
     42 	}
     43 	tmpfil = argv[3];
     44 	init("int", 0);
     45 	init("char", 1);
     46 	init("float", 2);
     47 	init("double", 3);
     48 /*	init("long", 4);  */
     49 	init("auto", 5);
     50 	init("extern", 6);
     51 	init("static", 7);
     52 	init("goto", 10);
     53 	init("return", 11);
     54 	init("if", 12);
     55 	init("while", 13);
     56 	init("else", 14);
     57 	init("switch", 15);
     58 	init("case", 16);
     59 	init("break", 17);
     60 	init("continue", 18);
     61 	init("do", 19);
     62 	init("default", 20);
     63 	while(!eof) {
     64 		extdef();
     65 		blkend();
     66 	}
     67 	flush();
     68 	flshw();
     69 	exit(nerror!=0);
     70 }
     71 
     72 lookup() {
     73 	extern hshtab[], hshsiz, pssiz, symbuf[];
     74 	extern hshlen, hshused, exit, error, nwps;
     75 	auto i, j, np[], sp[], rp[];
     76 
     77 	i = 0;
     78 	sp = symbuf;
     79 	j = nwps;
     80 	while(j--)
     81 		i =+ *sp++;
     82 	if (i<0) i = -i;
     83 	i =% hshsiz;
     84 	i =* pssiz;
     85 	while(*(np = &hshtab[i+4])) {
     86 		sp = symbuf;
     87 		j = nwps;
     88 		while(j--)
     89 			if (*np++ != *sp++) goto no;
     90 		return(&hshtab[i]);
     91 no:		if ((i =+ pssiz) >= hshlen) i = 0;
     92 	}
     93 	if(hshused++ > hshsiz) {
     94 		error("Symbol table overflow");
     95 		exit(1);
     96 	}
     97 	rp = np = &hshtab[i];
     98 	sp = symbuf;
     99 	j = 4;
    100 	while(j--)
    101 		*np++ = 0;
    102 	j = nwps;
    103 	while(j--)
    104 		*np++ = *sp++;
    105 	return(rp);
    106 }
    107 
    108 symbol() {
    109 	extern peeksym, peekc, eof, getchar, subseq, error, line;
    110 	extern csym[], getstr, symbuf, namsiz, lookup[], ctab, cval;
    111 	auto b, c;
    112 	char symbuf[], sp[], ctab[];
    113 
    114 	if (peeksym>=0) {
    115 		c = peeksym;
    116 		peeksym = -1;
    117 		return(c);
    118 	}
    119 	if (peekc) {
    120 		c = peekc;
    121 		peekc = 0;
    122 	} else
    123 		if (eof)
    124 			return(0); else
    125 			c = getchar();
    126 loop:
    127 	switch(ctab[c]) {
    128 
    129 	case 125:	/* newline */
    130 		line++;
    131 
    132 	case 126:	/* white space */
    133 		c = getchar();
    134 		goto loop;
    135 
    136 	case 0:		/* EOF */
    137 		eof++;
    138 		return(0);
    139 
    140 	case 40:	/* + */
    141 		return(subseq(c,40,30));
    142 
    143 	case 41:	/* - */
    144 		return(subseq(c,41,31));
    145 
    146 	case 80:	/* = */
    147 		if (subseq(' ',0,1)) return(80);
    148 		c = symbol();
    149 		if (c>=40 & c<=49)
    150 			return(c+30);
    151 		if (c==80)
    152 			return(60);
    153 		peeksym = c;
    154 		return(80);
    155 
    156 	case 63:	/* < */
    157 		if (subseq(c,0,1)) return(46);
    158 		return(subseq('=',63,62));
    159 
    160 	case 65:	/* > */
    161 		if (subseq(c,0,1)) return(45);
    162 		return(subseq('=',65,64));
    163 
    164 	case 34:	/* ! */
    165 		return(subseq('=',34,61));
    166 
    167 	case 43:	/* / */
    168 		if (subseq('*',1,0))
    169 			return(43);
    170 com:
    171 		c = getchar();
    172 com1:
    173 		if (c=='\0') {
    174 			eof++;
    175 			error("Nonterminated comment");
    176 			return(0);
    177 		}
    178 		if (c=='\n')
    179 			line++;
    180 		if (c!='*')
    181 			goto com;
    182 		c = getchar();
    183 		if (c!='/')
    184 			goto com1;
    185 		c = getchar();
    186 		goto loop;
    187 
    188 	case 124:	/* number */
    189 		cval = 0;
    190 		if (c=='0')
    191 			b = 8; else
    192 			b = 10;
    193 		while(ctab[c]==124) {
    194 			cval = cval*b + c -'0';
    195 			c = getchar();
    196 		}
    197 		peekc = c;
    198 		return(21);
    199 
    200 	case 122:	/* " */
    201 		return(getstr());
    202 
    203 	case 121:	/* ' */
    204 		return(getcc());
    205 
    206 	case 123:	/* letter */
    207 		sp = symbuf;
    208 		while(ctab[c]==123 | ctab[c]==124) {
    209 			if (sp<symbuf+namsiz) *sp++ = c;
    210 			c = getchar();
    211 		}
    212 		while(sp<symbuf+namsiz)
    213 			*sp++ = '\0';
    214 		peekc = c;
    215 		csym = lookup();
    216 		if (csym[0]==1) {	/* keyword */
    217 			cval = csym[1];
    218 			return(19);
    219 		}
    220 		return(20);
    221 
    222 	case 127:	/* unknown */
    223 		error("Unknown character");
    224 		c = getchar();
    225 		goto loop;
    226 
    227 	}
    228 	return(ctab[c]);
    229 }
    230 
    231 subseq(c,a,b) {
    232 	extern getchar, peekc;
    233 
    234 	if (!peekc)
    235 		peekc = getchar();
    236 	if (peekc != c)
    237 		return(a);
    238 	peekc = 0;
    239 	return(b);
    240 }
    241 getstr() {
    242 	extern isn, cval;
    243 	auto c;
    244 
    245 	printf(".data;L%d:.byte ", cval=isn++);
    246 	while((c=mapch('"')) >= 0)
    247 		printf("%o,", c);
    248 	printf("0;.even;.text\n");
    249 	return(22);
    250 }
    251 
    252 getcc()
    253 {
    254 	extern cval, ncpw;
    255 	auto c, cc;
    256 	char cp[];
    257 
    258 	cval = 0;
    259 	cp = &cval;
    260 	cc = 0;
    261 	while((c=mapch('\'')) >= 0)
    262 		if(cc++ < ncpw)
    263 			*cp++ = c;
    264 	if(cc>ncpw)
    265 		error("Long character constant");
    266 	return(21);
    267 }
    268 
    269 mapch(c)
    270 {
    271 	extern peekc, line;
    272 	auto a;
    273 
    274 	if((a=getchar())==c)
    275 		return(-1);
    276 	switch(a) {
    277 
    278 	case '\n':
    279 	case 0:
    280 		error("Nonterminated string");
    281 		peekc = a;
    282 		return(-1);
    283 
    284 	case '\\':
    285 		switch (a=getchar()) {
    286 
    287 		case 't':
    288 			return('\t');
    289 
    290 		case 'n':
    291 			return('\n');
    292 
    293 		case '0':
    294 			return('\0');
    295 
    296 		case 'r':
    297 			return('\r');
    298 
    299 		case '\n':
    300 			line++;
    301 			return('\n');
    302 		}
    303 
    304 	}
    305 	return(a);
    306 }
    307 
    308 tree() {
    309 	extern symbol, block, csym[], ctyp, isn,
    310 		peeksym, opdope[], build, error, cp[], cmst[],
    311 		space, ospace, cval, ossiz, exit, errflush, cmsiz;
    312 
    313 	auto op[], opst[20], pp[], prst[20], andflg, o,
    314 		p, ps, os;
    315 
    316 	space = ospace;
    317 	op = opst;
    318 	pp = prst;
    319 	cp = cmst;
    320 	*op = 200;		/* stack EOF */
    321 	*pp = 06;
    322 	andflg = 0;
    323 
    324 advanc:
    325 	switch (o=symbol()) {
    326 
    327 	/* name */
    328 	case 20:
    329 		if (*csym==0)
    330 			if((peeksym=symbol())==6)
    331 				*csym = 6;	/* extern */
    332 			else {
    333 				if(csym[2]==0)	/* unseen so far */
    334 					csym[2] = isn++;
    335 			}
    336 			if(*csym==6)	/* extern */
    337 			    *cp++ = block(5,20,csym[1],0,*csym,
    338 					csym[4],csym[5],csym[6],csym[7]);
    339 			else
    340 			    *cp++ = block(2,20,csym[1],0,*csym,csym[2]);
    341 		goto tand;
    342 
    343 	/* short constant */
    344 	case 21:
    345 	case21:
    346 		*cp++ = block(1,21,ctyp,0,cval);
    347 		goto tand;
    348 
    349 	/* string constant */
    350 	case 22:
    351 		*cp++ = block(1,22,17,0,cval);
    352 
    353 tand:
    354 		if(cp>=cmst+cmsiz) {
    355 			error("Expression overflow");
    356 			exit(1);
    357 		}
    358 		if (andflg)
    359 			goto syntax;
    360 		andflg = 1;
    361 		goto advanc;
    362 
    363 	/* ++, -- */
    364 	case 30:
    365 	case 31:
    366 		if (andflg)
    367 			o =+ 2;
    368 		goto oponst;
    369 
    370 	/* ! */
    371 	case 34:
    372 		if (andflg)
    373 			goto syntax;
    374 		goto oponst;
    375 
    376 	/* - */
    377 	case 41:
    378 		if (!andflg) {
    379 			peeksym = symbol();
    380 			if (peeksym==21) {
    381 				peeksym = -1;
    382 				cval = -cval;
    383 				goto case21;
    384 			}
    385 			o = 37;
    386 		}
    387 		andflg = 0;
    388 		goto oponst;
    389 
    390 	/* & */
    391 	/* * */
    392 	case 47:
    393 	case 42:
    394 		if (andflg)
    395 			andflg = 0; else
    396 			if(o==47)
    397 				o = 35;
    398 			else
    399 				o = 36;
    400 		goto oponst;
    401 
    402 	/* ( */
    403 	case 6:
    404 		if (andflg) {
    405 			o = symbol();
    406 			if (o==7)
    407 				o = 101; else {
    408 				peeksym = o;
    409 				o = 100;
    410 				andflg = 0;
    411 			}
    412 		}
    413 	goto oponst;
    414 
    415 	/* ) */
    416 	/* ] */
    417 	case 5:
    418 	case 7:
    419 		if (!andflg)
    420 			goto syntax;
    421 		goto oponst;
    422 	}
    423 
    424 	/* binaries */
    425 	if (!andflg)
    426 		goto syntax;
    427 	andflg = 0;
    428 
    429 oponst:
    430 	p = (opdope[o]>>9) & 077;
    431 opon1:
    432 	ps = *pp;
    433 	if (p>ps | p==ps & (opdope[o]&0200)!=0) { /* right-assoc */
    434 putin:
    435 		switch (o) {
    436 
    437 		case 6: /* ( */
    438 		case 4: /* [ */
    439 		case 100: /* call */
    440 			p = 04;
    441 		}
    442 		if(op>=opst+20) {		/* opstack size */
    443 			error("expression overflow");
    444 			exit(1);
    445 		}
    446 		*++op = o;
    447 		*++pp = p;
    448 		goto advanc;
    449 	}
    450 	--pp;
    451 	switch (os = *op--) {
    452 
    453 	/* EOF */
    454 	case 200:
    455 		peeksym = o;
    456 		return(*--cp);
    457 
    458 	/* call */
    459 	case 100:
    460 		if (o!=7)
    461 			goto syntax;
    462 		build(os);
    463 		goto advanc;
    464 
    465 	/* mcall */
    466 	case 101:
    467 		*cp++ = 0;		/* 0 arg call */
    468 		os = 100;
    469 		goto fbuild;
    470 
    471 	/* ( */
    472 	case 6:
    473 		if (o!=7)
    474 			goto syntax;
    475 		goto advanc;
    476 
    477 	/* [ */
    478 	case 4:
    479 		if (o!=5)
    480 			goto syntax;
    481 		build(4);
    482 		goto advanc;
    483 	}
    484 fbuild:
    485 	build(os);
    486 	goto opon1;
    487 
    488 syntax:
    489 	error("Expression syntax");
    490 	errflush(o);
    491 	return(0);
    492 }
    493 
    494 declare(kw) {
    495 	extern csym[], symbol, paraml[], parame[];
    496 	extern error, cval, errflush, peeksym, exit;
    497 	int t[], n, o;
    498 
    499 	while((o=symbol())==20) {		/* name */
    500 		if(kw>=5) {			/* type or sort? */
    501 			if(*csym>0)
    502 				error("%p redeclared", csym[4]);
    503 			*csym = kw;
    504 		} else {
    505 			if ((csym[1]&017)!=0)
    506 				error("%p redeclared", &csym[4]);
    507 			csym[1] =| csym[1]&0760 | kw;
    508 			if (*csym==0)
    509 				*csym = -2;
    510 		}
    511 		while((o=symbol())==4) {	/* [ */
    512 			if((o=symbol())==21) {	/* const */
    513 				if(csym[1]>=020)
    514 					error("Bad vector");
    515 				csym[3] = cval;
    516 				o = symbol();
    517 			}
    518 			if (o!=5)		/* ] */
    519 				goto syntax;
    520 			csym[1] =+ 020;
    521 		}
    522 		if(kw==8)  {		/* parameter */
    523 			*csym = -1;
    524 			if (paraml==0)
    525 				paraml = csym;
    526 			else
    527 				*parame = csym;
    528 			parame = csym;
    529 		}
    530 		if (o!=9)	/* , */
    531 			break;
    532 	}
    533 	if(o==1 & kw!=8 | o==7 & kw==8)
    534 		return;
    535 syntax:
    536 	error("Declaration syntax");
    537 	errflush(o);
    538 }
    539 
    540 /* storage */
    541 
    542 regtab 0;
    543 efftab 1;
    544 cctab 2;
    545 sptab 3;
    546 symbuf[4];
    547 pssiz 8;
    548 namsiz 8;
    549 nwps 4;
    550 hshused 0;
    551 hshsiz 100;
    552 hshlen 800;	/* 8*hshsiz */
    553 hshtab[800];
    554 space 0;
    555 cp 0;
    556 cmsiz 40;
    557 cmst[40];
    558 ctyp 0;
    559 isn 1;
    560 swsiz 120;
    561 swtab[120];
    562 swp 0;
    563 contlab 0;
    564 brklab 0;
    565 deflab 0;
    566 nreg 4;
    567 maprel[] 60,61,64,65,62,63,68,69,66,67;
    568 nauto 0;
    569 stack 0;
    570 peeksym 0177777;
    571 peekc 0;
    572 eof 0;
    573 line 1;
    574 csym 0;
    575 cval 0;
    576 ncpw 2;
    577 nerror 0;
    578 paraml;
    579 parame;
    580 tmpfil;
    581