forsyth20121205-174063a80cc13 years agoHistory
1550 lines · 24.0 KB · C
RawDownload
#include	"cc.h"#include	"y.tab.h" #ifndef	CPP#define	CPP	"/bin/cpp"#endif /* * known debug flags *	-a		acid declaration output *	-A		!B *	-B		non ANSI *	-d		print declarations *	-D name		define *	-F		format specification check *	-i		print initialization *	-I path		include *	-l		generate little-endian code *	-L		print every NAME symbol *	-M		constant multiplication *	-m		print add/sub/mul trees *	-n		print acid to file (%.c=%.acid) (with -a or -aa) *	-o file		output file *	-p		use standard cpp ANSI preprocessor (not on windows) *	-r		print registerization *	-s		print structure offsets (with -a or -aa) *	-S		print assembly *	-t		print type trees *	-V		enable void* conversion warnings *	-v		verbose printing *	-w		print warnings *	-X		abort on error *	-.		Inhibit search for includes in source directory */ voidmain(int argc, char *argv[]){	char *defs[50], *p;	int nproc, nout, status, i, c, ndef; 	memset(debug, 0, sizeof(debug));	tinit();	cinit();	ginit();	arginit(); 	profileflg = 1;	/* #pragma can turn it off */	tufield = simplet((1L<<tfield->etype) | BUNSIGNED);	ndef = 0;	outfile = 0;	include[ninclude++] = ".";	ARGBEGIN {	default:		c = ARGC();		if(c >= 0 && c < sizeof(debug))			debug[c]++;		break; 	case 'l':			/* for little-endian mips */		if(thechar != 'v'){			print("can only use -l with vc");			errorexit();		}		thechar = '0';		thestring = "spim";		break; 	case 'o':		outfile = ARGF();		break; 	case 'D':		p = ARGF();		if(p) {			defs[ndef++] = p;			dodefine(p);		}		break; 	case 'I':		p = ARGF();		setinclude(p);		break;	} ARGEND	if(argc < 1 && outfile == 0) {		print("usage: %cc [-options] files\n", thechar);		errorexit();	}	if(argc > 1 && systemtype(Windows)){		print("can't compile multiple files on windows\n");		errorexit();	}	if(argc > 1 && !systemtype(Windows)) {		nproc = 1;		/*		 * if we're writing acid to standard output, don't compile		 * concurrently, to avoid interleaving output.		 */		if(((!debug['a'] && !debug['Z']) || debug['n']) &&		    (p = getenv("NPROC")) != nil)			nproc = atol(p);	/* */		c = 0;		nout = 0;		for(;;) {			while(nout < nproc && argc > 0) {				i = myfork();				if(i < 0) {					i = mywait(&status);					if(i < 0) {						print("cannot create a process\n");						errorexit();					}					if(status)						c++;					nout--;					continue;				}				if(i == 0) {					fprint(2, "%s:\n", *argv);					if (compile(*argv, defs, ndef))						errorexit();					exits(0);				}				nout++;				argc--;				argv++;			}			i = mywait(&status);			if(i < 0) {				if(c)					errorexit();				exits(0);			}			if(status)				c++;			nout--;		}	} 	if(argc == 0)		c = compile("stdin", defs, ndef);	else		c = compile(argv[0], defs, ndef); 	if(c)		errorexit();	exits(0);} intcompile(char *file, char **defs, int ndef){	char ofile[400], incfile[20];	char *p, *av[100], opt[256];	int i, c, fd[2];	static int first = 1; 	strcpy(ofile, file);	p = utfrrune(ofile, pathchar());	if(p) {		*p++ = 0;		if(!debug['.'])			include[0] = strdup(ofile);	} else		p = ofile; 	if(outfile == 0) {		outfile = p;		if(outfile) {			if(p = utfrrune(outfile, '.'))				if(p[1] == 'c' && p[2] == 0)					p[0] = 0;			p = utfrune(outfile, 0);			if(debug['a'] && debug['n'])				strcat(p, ".acid");			else if(debug['Z'] && debug['n'])				strcat(p, "_pickle.c");			else {				p[0] = '.';				p[1] = thechar;				p[2] = 0;			}		} else			outfile = "/dev/null";	} 	if(p = getenv("INCLUDE")) {		setinclude(p);	} else {		if(systemtype(Plan9)) {			sprint(incfile, "/%s/include", thestring);			setinclude(strdup(incfile));			setinclude("/sys/include");		}	}	if (first)		Binit(&diagbuf, 1, OWRITE);	/*	 * if we're writing acid to standard output, don't keep scratching	 * outbuf.	 */	if((debug['a'] || debug['Z']) && !debug['n']) {		if (first) {			outfile = 0;			Binit(&outbuf, mydup(1, -1), OWRITE);			mydup(2, 1);		}	} else {		c = mycreat(outfile, 0664);		if(c < 0) {			diag(Z, "cannot open %s - %r", outfile);			outfile = 0;			errorexit();		}		Binit(&outbuf, c, OWRITE);	}	newio();	first = 0; 	/* Use an ANSI preprocessor */	if(debug['p']) {		if(systemtype(Windows)) {			diag(Z, "-p option not supported on windows");			errorexit();		}		if(myaccess(file) < 0) {			diag(Z, "%s does not exist", file);			errorexit();		}		if(mypipe(fd) < 0) {			diag(Z, "pipe failed");			errorexit();		}		switch(myfork()) {		case -1:			diag(Z, "fork failed");			errorexit();		case 0:			close(fd[0]);			mydup(fd[1], 1);			close(fd[1]);			av[0] = CPP;			i = 1;			if(debug['.']){				sprint(opt, "-.");				av[i++] = strdup(opt);			}			if(debug['+']) {				sprint(opt, "-+");				av[i++] = strdup(opt);			}			for(c = 0; c < ndef; c++) {				sprint(opt, "-D%s", defs[c]);				av[i++] = strdup(opt);			}			for(c = 0; c < ninclude; c++) {				sprint(opt, "-I%s", include[c]);				av[i++] = strdup(opt);			}			if(strcmp(file, "stdin") != 0)				av[i++] = file;			av[i] = 0;			if(debug['p'] > 1) {				for(c = 0; c < i; c++)					fprint(2, "%s ", av[c]);				fprint(2, "\n");			}			myexec(av[0], av);			fprint(2, "can't exec C preprocessor %s: %r\n", CPP);			errorexit();		default:			close(fd[1]);			newfile(file, fd[0]);			break;		}	} else {		if(strcmp(file, "stdin") == 0)			newfile(file, 0);		else			newfile(file, -1);	}	yyparse();	if(!debug['a'] && !debug['Z'])		gclean();	return nerrors;} voiderrorexit(void){	if(outfile)		remove(outfile);	exits("error");} voidpushio(void){	Io *i; 	i = iostack;	if(i == I) {		yyerror("botch in pushio");		errorexit();	}	i->p = fi.p;	i->c = fi.c;} voidnewio(void){	Io *i;	static int pushdepth = 0; 	i = iofree;	if(i == I) {		pushdepth++;		if(pushdepth > 1000) {			yyerror("macro/io expansion too deep");			errorexit();		}		i = alloc(sizeof(*i));	} else		iofree = i->link;	i->c = 0;	i->f = -1;	ionext = i;} voidnewfile(char *s, int f){	Io *i; 	if(debug['e'])		print("%L: %s\n", lineno, s); 	i = ionext;	i->link = iostack;	iostack = i;	i->f = f;	if(f < 0)		i->f = open(s, 0);	if(i->f < 0) {		yyerror("%cc: %r: %s", thechar, s);		errorexit();	}	fi.c = 0;	linehist(s, 0);} Sym*slookup(char *s){ 	strcpy(symb, s);	return lookup();} Sym*lookup(void){	Sym *s;	ulong h;	char *p;	int c, n; 	h = 0;	for(p=symb; *p;) {		h = h * 3;		h += *p++;	}	n = (p - symb) + 1;	if((long)h < 0)		h = ~h;	h %= NHASH;	c = symb[0];	for(s = hash[h]; s != S; s = s->link) {		if(s->name[0] != c)			continue;		if(strcmp(s->name, symb) == 0)			return s;	}	s = alloc(sizeof(*s));	s->name = alloc(n);	memmove(s->name, symb, n); 	strcpy(s->name, symb);	s->link = hash[h];	hash[h] = s;	syminit(s); 	return s;} voidsyminit(Sym *s){	s->lexical = LNAME;	s->block = 0;	s->offset = 0;	s->type = T;	s->suetag = T;	s->class = CXXX;	s->aused = 0;	s->sig = SIGNONE;} #define	EOF	(-1)#define	IGN	(-2)#define	ESC	(1<<20)#define	GETC()	((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff)) enum{	Numdec		= 1<<0,	Numlong		= 1<<1,	Numuns		= 1<<2,	Numvlong	= 1<<3,	Numflt		= 1<<4,}; longyylex(void){	vlong vv;	long c, c1, t;	char *cp;	Rune rune;	Sym *s; 	if(peekc != IGN) {		c = peekc;		peekc = IGN;		goto l1;	}l0:	c = GETC(); l1:	if(c >= Runeself) {		/*		 * extension --		 *	all multibyte runes are alpha		 */		cp = symb;		goto talph;	}	if(isspace(c)) {		if(c == '\n')			lineno++;		goto l0;	}	if(isalpha(c)) {		cp = symb;		if(c != 'L')			goto talph;		*cp++ = c;		c = GETC();		if(c == '\'') {			/* L'x' */			c = escchar('\'', 1, 0);			if(c == EOF)				c = '\'';			c1 = escchar('\'', 1, 0);			if(c1 != EOF) {				yyerror("missing '");				peekc = c1;			}			yylval.vval = convvtox(c, TUSHORT);			return LUCONST;		}		if(c == '"') {			goto caselq;		}		goto talph;	}	if(isdigit(c))		goto tnum;	switch(c)	{ 	case EOF:		peekc = EOF;		return -1; 	case '_':		cp = symb;		goto talph; 	case '#':		domacro();		goto l0; 	case '.':		c1 = GETC();		if(isdigit(c1)) {			cp = symb;

Lines 1–500 of 1550.