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 (11467B)


      1 /* C compiler
      2 
      3 Copyright 1972 Bell Telephone Laboratories, Inc. 
      4 
      5 */
      6 
      7 init(s, t)
      8 char s[]; {
      9 	extern symbuf, namsiz;
     10 	char symbuf[], sp[];
     11 	int np[], i;
     12 
     13 	i = namsiz;
     14 	sp = symbuf;
     15 	while(i--)
     16 		if ((*sp++ = *s++)=='\0') --s;
     17 	np = lookup();
     18 	*np++ = 1;
     19 	*np = t;
     20 }
     21 
     22 main(argc, argv)
     23 int argv[]; {
     24 	extern extdef, eof;
     25 	extern fout, fin, nerror, tmpfil, xdflg;
     26 
     27 	if(argc<4) {
     28 		error("Arg count");
     29 		exit(1);
     30 	}
     31 	if((fin=open(argv[1],0))<0) {
     32 		error("Can't find %s", argv[1]);
     33 		exit(1);
     34 	}
     35 	if((fout=creat(argv[2], 017))<0) {
     36 		error("Can't create %s", argv[2]);
     37 		exit(1);
     38 	}
     39 	tmpfil = argv[3];
     40 	xdflg++;
     41 	init("int", 0);
     42 	init("char", 1);
     43 	init("float", 2);
     44 	init("double", 3);
     45 	init("struct", 4);
     46 	init("auto", 5);
     47 	init("extern", 6);
     48 	init("static", 7);
     49 	init("goto", 10);
     50 	init("return", 11);
     51 	init("if", 12);
     52 	init("while", 13);
     53 	init("else", 14);
     54 	init("switch", 15);
     55 	init("case", 16);
     56 	init("break", 17);
     57 	init("continue", 18);
     58 	init("do", 19);
     59 	init("default", 20);
     60 	xdflg = 0;
     61 	while(!eof) {
     62 		extdef();
     63 		blkend();
     64 	}
     65 	flush();
     66 	flshw();
     67 	exit(nerror!=0);
     68 }
     69 
     70 lookup() {
     71 	extern hshtab, hshsiz, pssiz, symbuf, xdflg;
     72 	int hshtab[], symbuf[];
     73 	extern hshlen, hshused, nwps;
     74 	auto i, j, np[], sp[], rp[];
     75 
     76 	i = 0;
     77 	sp = symbuf;
     78 	j = nwps;
     79 	while(j--)
     80 		i =+ *sp++ & 077577;
     81 	if (i<0) i = -i;
     82 	i =% hshsiz;
     83 	i =* pssiz;
     84 	while(*(np = &hshtab[i+4])) {
     85 		sp = symbuf;
     86 		j = nwps;
     87 		while(j--)
     88 			if ((*np++&077577) != *sp++) goto no;
     89 		return(&hshtab[i]);
     90 no:		if ((i =+ pssiz) >= hshlen) i = 0;
     91 	}
     92 	if(++hshused > hshsiz) {
     93 		error("Symbol table overflow");
     94 		exit(1);
     95 	}
     96 	rp = np = &hshtab[i];
     97 	sp = symbuf;
     98 	j = 4;
     99 	while(j--)
    100 		*np++ = 0;
    101 	j = nwps;
    102 	while(j--)
    103 		*np++ = *sp++;
    104 	*np = 0;
    105 	if (xdflg)
    106 		rp[4] =| 0200;		/* mark non-deletable */
    107 	return(rp);
    108 }
    109 
    110 symbol() {
    111 	extern peeksym, peekc, eof, line;
    112 	extern csym, symbuf, namsiz, lookup, ctab, cval;
    113 	int csym[];
    114 	extern isn, mosflg, xdflg;
    115 	auto b, c;
    116 	char symbuf[], sp[], ctab[];
    117 
    118 	if (peeksym>=0) {
    119 		c = peeksym;
    120 		peeksym = -1;
    121 		if (c==20)
    122 			mosflg = 0;
    123 		return(c);
    124 	}
    125 	if (peekc) {
    126 		c = peekc;
    127 		peekc = 0;
    128 	} else
    129 		if (eof)
    130 			return(0); else
    131 			c = getchar();
    132 loop:
    133 	switch(ctab[c]) {
    134 
    135 	case 125:	/* newline */
    136 		line++;
    137 
    138 	case 126:	/* white space */
    139 		c = getchar();
    140 		goto loop;
    141 
    142 	case 0:		/* EOF */
    143 		eof++;
    144 		return(0);
    145 
    146 	case 40:	/* + */
    147 		return(subseq(c,40,30));
    148 
    149 	case 41:	/* - */
    150 		return(subseq(c,subseq('>',41,50),31));
    151 
    152 	case 80:	/* = */
    153 		if (subseq(' ',0,1)) return(80);
    154 		c = symbol();
    155 		if (c>=40 & c<=49)
    156 			return(c+30);
    157 		if (c==80)
    158 			return(60);
    159 		peeksym = c;
    160 		return(80);
    161 
    162 	case 63:	/* < */
    163 		if (subseq(c,0,1)) return(46);
    164 		return(subseq('=',63,62));
    165 
    166 	case 65:	/* > */
    167 		if (subseq(c,0,1)) return(45);
    168 		return(subseq('=',65,64));
    169 
    170 	case 34:	/* ! */
    171 		return(subseq('=',34,61));
    172 
    173 	case 43:	/* / */
    174 		if (subseq('*',1,0))
    175 			return(43);
    176 com:
    177 		c = getchar();
    178 com1:
    179 		if (c=='\0') {
    180 			eof++;
    181 			error("Nonterminated comment");
    182 			return(0);
    183 		}
    184 		if (c=='\n')
    185 			line++;
    186 		if (c!='*')
    187 			goto com;
    188 		c = getchar();
    189 		if (c!='/')
    190 			goto com1;
    191 		c = getchar();
    192 		goto loop;
    193 
    194 	case 120:	/* . */
    195 	case 124:	/* number */
    196 		peekc = c;
    197 		switch(c=getnum(c=='0'? 8:10)) {
    198 			case 25:		/* float 0 */
    199 				c = 23;
    200 				break;
    201 
    202 			case 23:		/* float non 0 */
    203 				cval = isn++;
    204 		}
    205 		return(c);
    206 
    207 	case 122:	/* " */
    208 		return(getstr());
    209 
    210 	case 121:	/* ' */
    211 		return(getcc());
    212 
    213 	case 123:	/* letter */
    214 		sp = symbuf;
    215 		if (mosflg) {
    216 			*sp++ = '.';
    217 			mosflg = 0;
    218 		}
    219 		while(ctab[c]==123 | ctab[c]==124) {
    220 			if (sp<symbuf+namsiz) *sp++ = c;
    221 			c = getchar();
    222 		}
    223 		while(sp<symbuf+namsiz)
    224 			*sp++ = '\0';
    225 		peekc = c;
    226 		csym = lookup();
    227 		if (csym[0]==1) {	/* keyword */
    228 			cval = csym[1];
    229 			return(19);
    230 		}
    231 		return(20);
    232 
    233 	case 127:	/* unknown */
    234 		error("Unknown character");
    235 		c = getchar();
    236 		goto loop;
    237 
    238 	}
    239 	return(ctab[c]);
    240 }
    241 
    242 subseq(c,a,b) {
    243 	extern peekc;
    244 
    245 	if (!peekc)
    246 		peekc = getchar();
    247 	if (peekc != c)
    248 		return(a);
    249 	peekc = 0;
    250 	return(b);
    251 }
    252 getstr() {
    253 	extern isn, cval, strflg;
    254 	auto c;
    255 	char t[], d[];
    256 
    257 	t = ".text";
    258 	d = ".data";
    259 	printf("%s;L%d:.byte ", (strflg?t:d), cval=isn++);
    260 	while((c=mapch('"')) >= 0)
    261 		printf("%o,", c);
    262 	printf("0;.even;%s\n", (strflg?d:t));
    263 	return(22);
    264 }
    265 
    266 getcc()
    267 {
    268 	extern cval, ncpw;
    269 	auto c, cc;
    270 	char cp[];
    271 
    272 	cval = 0;
    273 	cp = &cval;
    274 	cc = 0;
    275 	while((c=mapch('\'')) >= 0)
    276 		if(cc++ < ncpw)
    277 			*cp++ = c;
    278 	if(cc>ncpw)
    279 		error("Long character constant");
    280 	return(21);
    281 }
    282 
    283 mapch(c)
    284 {
    285 	extern peekc, line;
    286 	auto a;
    287 
    288 	if((a=getchar())==c)
    289 		return(-1);
    290 	switch(a) {
    291 
    292 	case '\n':
    293 	case 0:
    294 		error("Nonterminated string");
    295 		peekc = a;
    296 		return(-1);
    297 
    298 	case '\\':
    299 		switch (a=getchar()) {
    300 
    301 		case 't':
    302 			return('\t');
    303 
    304 		case 'n':
    305 			return('\n');
    306 
    307 		case '0':
    308 			return('\0');
    309 
    310 		case 'r':
    311 			return('\r');
    312 
    313 		case '\n':
    314 			line++;
    315 			return('\n');
    316 		}
    317 
    318 	}
    319 	return(a);
    320 }
    321 
    322 tree() {
    323 	extern csym, ctyp, isn, fcval, peeksym, opdope, cp, cmst;
    324 	int csym[], opdope[], cp[], cmst[];
    325 	extern space, cval, ossiz, cmsiz, mosflg, osleft;
    326 	double fcval;
    327 	int space[];
    328 
    329 	int op[], opst[20], pp[], prst[20], andflg, o,
    330 		p, ps, os;
    331 
    332 	osleft = ossiz;
    333 	space = 0;
    334 	*space++ = 0;
    335 	op = opst;
    336 	pp = prst;
    337 	cp = cmst;
    338 	*op = 200;		/* stack EOF */
    339 	*pp = 06;
    340 	andflg = 0;
    341 
    342 advanc:
    343 	switch (o=symbol()) {
    344 
    345 	/* name */
    346 	case 20:
    347 		if (*csym==0)
    348 			if((peeksym=symbol())==6) {	/* ( */
    349 				*csym = 6;		/* extern */
    350 				csym[1] = 020;		/* int() */
    351 			} else {
    352 				csym[1] = 030;		/* array */
    353 				if (csym[2]==0)
    354 					csym[2] = isn++;
    355 			}
    356 		*cp++ = block(2,20,csym[1],csym[3],*csym,0);
    357 		if (*csym==6) {			/* external */
    358 			o = 3;
    359 			while(++o<8) {
    360 				pblock(csym[o]);
    361 				if ((csym[o]&077400) == 0)
    362 					break;
    363 			}
    364 		} else
    365 			pblock(csym[2]);
    366 		goto tand;
    367 
    368 	/* short constant */
    369 	case 21:
    370 	case21:
    371 		*cp++ = block(1,21,ctyp,0,cval);
    372 		goto tand;
    373 
    374 	/* floating constant */
    375 	case 23:
    376 		*cp++ = block(1,23,3,0,cval);
    377 		if (cval)		/* non-0 */
    378 			printf(".data;L%d:%o;%o;%o;%o;.text\n",cval,fcval);
    379 		goto tand;
    380 
    381 	/* string constant: fake a static char array */
    382 	case 22:
    383 		*cp++ = block(3, 20, 031, 1, 7, 0, cval);
    384 
    385 tand:
    386 		if(cp>=cmst+cmsiz) {
    387 			error("Expression overflow");
    388 			exit(1);
    389 		}
    390 		if (andflg)
    391 			goto syntax;
    392 		andflg = 1;
    393 		goto advanc;
    394 
    395 	/* ++, -- */
    396 	case 30:
    397 	case 31:
    398 		if (andflg)
    399 			o =+ 2;
    400 		goto oponst;
    401 
    402 	/* ! */
    403 	case 34:
    404 	/* ~ */
    405 	case 38:
    406 		if (andflg)
    407 			goto syntax;
    408 		goto oponst;
    409 
    410 	/* - */
    411 	case 41:
    412 		if (!andflg) {
    413 			peeksym = symbol();
    414 			if (peeksym==21) {
    415 				peeksym = -1;
    416 				cval = -cval;
    417 				goto case21;
    418 			}
    419 			o = 37;
    420 		}
    421 		andflg = 0;
    422 		goto oponst;
    423 
    424 	/* & */
    425 	/* * */
    426 	case 47:
    427 	case 42:
    428 		if (andflg)
    429 			andflg = 0; else
    430 			if(o==47)
    431 				o = 35;
    432 			else
    433 				o = 36;
    434 		goto oponst;
    435 
    436 	/* ( */
    437 	case 6:
    438 		if (andflg) {
    439 			o = symbol();
    440 			if (o==7)
    441 				o = 101; else {
    442 				peeksym = o;
    443 				o = 100;
    444 				andflg = 0;
    445 			}
    446 		}
    447 	goto oponst;
    448 
    449 	/* ) */
    450 	/* ] */
    451 	case 5:
    452 	case 7:
    453 		if (!andflg)
    454 			goto syntax;
    455 		goto oponst;
    456 
    457 	case 39:	/* . */
    458 		mosflg++;
    459 		break;
    460 
    461 	}
    462 	/* binaries */
    463 	if (!andflg)
    464 		goto syntax;
    465 	andflg = 0;
    466 
    467 oponst:
    468 	p = (opdope[o]>>9) & 077;
    469 opon1:
    470 	ps = *pp;
    471 	if (p>ps | p==ps & (opdope[o]&0200)!=0) { /* right-assoc */
    472 putin:
    473 		switch (o) {
    474 
    475 		case 6: /* ( */
    476 		case 4: /* [ */
    477 		case 100: /* call */
    478 			p = 04;
    479 		}
    480 		if(op>=opst+20) {		/* opstack size */
    481 			error("expression overflow");
    482 			exit(1);
    483 		}
    484 		*++op = o;
    485 		*++pp = p;
    486 		goto advanc;
    487 	}
    488 	--pp;
    489 	switch (os = *op--) {
    490 
    491 	/* EOF */
    492 	case 200:
    493 		peeksym = o;
    494 		return(*--cp);
    495 
    496 	/* call */
    497 	case 100:
    498 		if (o!=7)
    499 			goto syntax;
    500 		build(os);
    501 		goto advanc;
    502 
    503 	/* mcall */
    504 	case 101:
    505 		*cp++ = block(0,0,0,0);	/* 0 arg call */
    506 		os = 100;
    507 		goto fbuild;
    508 
    509 	/* ( */
    510 	case 6:
    511 		if (o!=7)
    512 			goto syntax;
    513 		goto advanc;
    514 
    515 	/* [ */
    516 	case 4:
    517 		if (o!=5)
    518 			goto syntax;
    519 		build(4);
    520 		goto advanc;
    521 	}
    522 fbuild:
    523 	build(os);
    524 	goto opon1;
    525 
    526 syntax:
    527 	error("Expression syntax");
    528 	errflush(o);
    529 	return(0);
    530 }
    531 
    532 scdeclare(kw)
    533 {
    534 	extern csym, paraml, parame, peeksym;
    535 	int csym[], paraml[], parame[];
    536 	int o;
    537 
    538 	while((o=symbol())==20) {		/* name */
    539 		if(*csym>0 & *csym!=kw)
    540 			redec();
    541 		*csym = kw;
    542 		if(kw==8)  {		/* parameter */
    543 			*csym = -1;
    544 			if (paraml==0)
    545 				paraml = csym;
    546 			else
    547 				*parame = csym;
    548 			parame = csym;
    549 		}
    550 		if ((o=symbol())!=9)	/* , */
    551 			break;
    552 	}
    553 	if(o==1 & kw!=8 | o==7 & kw==8)
    554 		return;
    555 syntax:
    556 	decsyn(o);
    557 }
    558 
    559 tdeclare(kw, offset, mos)
    560 {
    561 	int o, elsize, ds[];
    562 	extern xdflg, peeksym, mosflg, defsym, csym;
    563 	int csym[], ssym[];
    564 
    565 	if (kw == 4) {				/* struct */
    566 		ssym = 0;
    567 		ds = defsym;
    568 		mosflg = mos;
    569 		if ((o=symbol())==20) {		/* name */
    570 			ssym = csym;
    571 			o = symbol();
    572 		}
    573 		mosflg = mos;
    574 		if (o != 6) {			/* ( */
    575 			if (ssym==0)
    576 				goto syntax;
    577 			if (*ssym!=8)		/* class structname */
    578 				error("Bad structure name");
    579 			if (ssym[3]==0) {	/* no size yet */
    580 				kw = 5;		/* deferred MOS */
    581 				elsize = ssym;
    582 			} else
    583 				elsize = ssym[3];
    584 			peeksym = o;
    585 		} else {
    586 			if (ssym) {
    587 				if (*ssym)
    588 					redec();
    589 				*ssym = 8;
    590 				ssym[3] = 0;
    591 			}
    592 			elsize = declist(4);
    593 			if ((elsize&01) != 0)
    594 				elsize++;
    595 			defsym = ds;
    596 			if ((o = symbol()) != 7)	/* ) */
    597 				goto syntax;
    598 			if (ssym)
    599 				ssym[3] = elsize;
    600 		}
    601 	}
    602 	mosflg = mos;
    603 	if ((peeksym=symbol()) == 1) {		/* ; */
    604 		peeksym = -1;
    605 		mosflg = 0;
    606 		return(offset);
    607 	}
    608 	do {
    609 		offset =+ t1dec(kw, offset, mos, elsize);
    610 		if (xdflg & !mos)
    611 			return;
    612 	} while ((o=symbol()) == 9);		/* , */
    613 	if (o==1)
    614 		return(offset);
    615 syntax:
    616 	decsyn(o);
    617 }
    618 
    619 t1dec(kw, offset, mos, elsize)
    620 {
    621 	int type, nel, defsym[], t1;
    622 	extern defsym, mosflg;
    623 
    624 	nel = 0;
    625 	mosflg = mos;
    626 	if ((t1=getype(&nel)) < 0)
    627 		goto syntax;
    628 	type = 0;
    629 	do
    630 		type = type<<2 | (t1 & 03);
    631 	while(t1 =>> 2);
    632 	t1 = type<<3 | kw;
    633 	if (defsym[1] & defsym[1]!=t1)
    634 		redec();
    635 	defsym[1] = t1;
    636 	defsym[3] = elsize;
    637 	elsize = length(defsym);
    638 	if (mos) {
    639 		if (*defsym)
    640 			redec();
    641 		else
    642 			*defsym = 4;
    643 		if ((offset&1)!=0 & elsize!=1)
    644 			offset++;
    645 		defsym[2] = offset;
    646 	} else
    647 		if (*defsym == 0)
    648 			*defsym = -2;		/* default auto */
    649 	if (nel==0)
    650 		nel = 1;
    651 	defsym[8] = nel;
    652 syntax:
    653 	return(nel*elsize);
    654 }
    655 
    656 getype(pnel)
    657 int pnel[];
    658 {
    659 	int o, type;
    660 	extern cval, peeksym, xdflg, defsym, csym, pssiz;
    661 	int defsym[], csym[];
    662 
    663 	switch(o=symbol()) {
    664 
    665 	case 42:					/* * */
    666 		return(getype(pnel)<<2 | 01);
    667 
    668 	case 6:						/* ( */
    669 		type = getype(pnel);
    670 		if ((o=symbol()) != 7)			/* ) */
    671 			goto syntax;
    672 		goto getf;
    673 
    674 	case 20:					/* name */
    675 		defsym = csym;
    676 		type = 0;
    677 	getf:
    678 		switch(o=symbol()) {
    679 
    680 		case 6:					/* ( */
    681 			if (xdflg) {
    682 				xdflg = 0;
    683 				o = defsym;
    684 				scdeclare(8);
    685 				defsym = o;
    686 				xdflg++;
    687 			} else
    688 				if ((o=symbol()) != 7)	/* ) */
    689 					goto syntax;
    690 			type = type<<2 | 02;
    691 			goto getf;
    692 
    693 		case 4:					/* [ */
    694 			if ((o=symbol()) != 5) {	/* ] */
    695 				if (o!=21)		/* const */
    696 					goto syntax;
    697 				*pnel = cval;
    698 				if ((o=symbol())!=5)
    699 					goto syntax;
    700 			}
    701 			type = type<<2 | 03;
    702 			goto getf;
    703 		}
    704 		peeksym = o;
    705 		return(type);
    706 	}
    707 syntax:
    708 	decsyn(o);
    709 	return(-1);
    710 }
    711 
    712 decsyn(o)
    713 {
    714 	error("Declaration syntax");
    715 	errflush(o);
    716 }
    717 
    718 redec()
    719 {
    720 	extern csym;
    721 	int csym[];
    722 
    723 	error("%p redeclared", &csym[4]);
    724 }
    725 
    726 /* storage */
    727 
    728 regtab 0;
    729 efftab 1;
    730 cctab 2;
    731 sptab 3;
    732 symbuf[4];
    733 pssiz 9;
    734 namsiz 8;
    735 nwps 4;
    736 hshused;
    737 hshsiz 100;
    738 hshlen 900;	/* 9*hshsiz */
    739 hshtab[900];
    740 space;
    741 cp;
    742 cmsiz 40;
    743 cmst[40];
    744 ctyp;
    745 isn 1;
    746 swsiz 120;
    747 swtab[120];
    748 swp;
    749 contlab;
    750 brklab;
    751 deflab;
    752 nreg 4;
    753 nauto;
    754 stack;
    755 peeksym 0177777;
    756 peekc;
    757 eof;
    758 line 1;
    759 defsym;
    760 xdflg;
    761 csym;
    762 cval;
    763 fcval 0;	/* a double number */
    764 fc1 0;
    765 fc2 0;
    766 fc3 0;
    767 ncpw 2;
    768 nerror;
    769 paraml;
    770 parame;
    771 tmpfil;
    772 strflg;
    773 ossiz 250;
    774 osleft;
    775 mosflg;
    776 debug 0;