⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lex.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 */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, dup(1, -1), OWRITE);			dup(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);			}			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;			*cp++ = c;			c = c1;			c1 = 0;			goto casedot;		}		break;	case '"':		strcpy(symb, "\"<string>\"");		cp = alloc(0);		c1 = 0;		/* "..." */		for(;;) {			c = escchar('"', 0, 1);			if(c == EOF)				break;			if(c & ESC) {				cp = allocn(cp, c1, 1);				cp[c1++] = c;			} else {				rune = c;				c = runelen(rune);				cp = allocn(cp, c1, c);				runetochar(cp+c1, &rune);				c1 += c;			}		}		yylval.sval.l = c1;		do {			cp = allocn(cp, c1, 1);			cp[c1++] = 0;		} while(c1 & MAXALIGN);		yylval.sval.s = cp;		return LSTRING;	caselq:		/* L"..." */		strcpy(symb, "\"L<string>\"");		cp = alloc(0);		c1 = 0;		for(;;) {			c = escchar('"', 1, 0);			if(c == EOF)				break;			cp = allocn(cp, c1, sizeof(ushort));			*(ushort*)(cp + c1) = c;			c1 += sizeof(ushort);		}		yylval.sval.l = c1;		do {			cp = allocn(cp, c1, sizeof(ushort));			*(ushort*)(cp + c1) = 0;			c1 += sizeof(ushort);		} while(c1 & MAXALIGN);		yylval.sval.s = cp;		return LLSTRING;	case '\'':		/* '.' */		c = escchar('\'', 0, 0);		if(c == EOF)			c = '\'';		c1 = escchar('\'', 0, 0);		if(c1 != EOF) {			yyerror("missing '");			peekc = c1;		}		vv = c;		yylval.vval = convvtox(vv, TUCHAR);		if(yylval.vval != vv)			yyerror("overflow in character constant: 0x%lx", c);		else		if(c & 0x80){			nearln = lineno;			warn(Z, "sign-extended character constant");		}		yylval.vval = convvtox(vv, TCHAR);		return LCONST;	case '/':		c1 = GETC();		if(c1 == '*') {			for(;;) {				c = getr();				while(c == '*') {					c = getr();					if(c == '/')						goto l0;				}				if(c == EOF) {					yyerror("eof in comment");					errorexit();				}			}		}		if(c1 == '/') {			for(;;) {				c = getr();				if(c == '\n')					goto l0;				if(c == EOF) {					yyerror("eof in comment");					errorexit();				}			}		}		if(c1 == '=')			return LDVE;		break;	case '*':		c1 = GETC();		if(c1 == '=')			return LMLE;		break;	case '%':		c1 = GETC();		if(c1 == '=')			return LMDE;		break;	case '+':		c1 = GETC();		if(c1 == '+')			return LPP;		if(c1 == '=')			return LPE;		break;	case '-':		c1 = GETC();		if(c1 == '-')			return LMM;		if(c1 == '=')			return LME;		if(c1 == '>')			return LMG;		break;	case '>':		c1 = GETC();		if(c1 == '>') {			c = LRSH;			c1 = GETC();			if(c1 == '=')				return LRSHE;			break;		}		if(c1 == '=')			return LGE;		break;	case '<':		c1 = GETC();		if(c1 == '<') {			c = LLSH;			c1 = GETC();			if(c1 == '=')				return LLSHE;			break;		}		if(c1 == '=')			return LLE;		break;	case '=':		c1 = GETC();		if(c1 == '=')			return LEQ;		break;	case '!':		c1 = GETC();		if(c1 == '=')			return LNE;		break;	case '&':		c1 = GETC();		if(c1 == '&')			return LANDAND;		if(c1 == '=')			return LANDE;		break;	case '|':		c1 = GETC();		if(c1 == '|')			return LOROR;		if(c1 == '=')			return LORE;		break;	case '^':		c1 = GETC();		if(c1 == '=')			return LXORE;		break;	default:		return c;	}	peekc = c1;	return c;talph:	/*	 * cp is set to symb and some	 * prefix has been stored	 */	for(;;) {		if(c >= Runeself) {			for(c1=0;;) {				cp[c1++] = c;				if(fullrune(cp, c1))					break;				c = GETC();			}			cp += c1;			c = GETC();			continue;		}		if(!isalnum(c) && c != '_')			break;		*cp++ = c;		c = GETC();	}	*cp = 0;	if(debug['L'])		print("%L: %s\n", lineno, symb);	peekc = c;	s = lookup();	if(s->macro) {		newio();		cp = ionext->b;		macexpand(s, cp);		pushio();		ionext->link = iostack;		iostack = ionext;		fi.p = cp;		fi.c = strlen(cp);		if(peekc != IGN) {			cp[fi.c++] = peekc;			cp[fi.c] = 0;			peekc = IGN;		}		goto l0;	}	yylval.sym = s;	if(s->class == CTYPEDEF || s->class == CTYPESTR)		return LTYPE;	return s->lexical;tnum:	c1 = 0;	cp = symb;	if(c != '0') {		c1 |= Numdec;		for(;;) {			*cp++ = c;			c = GETC();			if(isdigit(c))				continue;			goto dc;		}	}	*cp++ = c;	c = GETC();	if(c == 'x' || c == 'X')		for(;;) {			*cp++ = c;			c = GETC();			if(isdigit(c))				continue;			if(c >= 'a' && c <= 'f')				continue;			if(c >= 'A' && c <= 'F')

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -