forsyth20121205-174063a80cc13 years agoHistory
856 lines · 11.9 KB · Text
RawDownload
#define VARMAC 0x80 longgetnsn(void){	long n;	int c; 	c = getnsc();	if(c < '0' || c > '9')		return -1;	n = 0;	while(c >= '0' && c <= '9') {		n = n*10 + c-'0';		c = getc();	}	unget(c);	return n;} Sym*getsym(void){	int c;	char *cp; 	c = getnsc();	if(!isalpha(c) && c != '_') {		unget(c);		return S;	}	for(cp = symb;;) {		if(cp <= symb+NSYMB-4)			*cp++ = c;		c = getc();		if(isalnum(c) || c == '_')			continue;		unget(c);		break;	}	*cp = 0;	if(cp > symb+NSYMB-4)		yyerror("symbol too large: %s", symb);	return lookup();} Sym*getsymdots(int *dots){	int c;	Sym *s; 	s = getsym();	if(s != S)		return s; 	c = getnsc();	if(c != '.'){		unget(c);		return S;	}	if(getc() != '.' || getc() != '.')		yyerror("bad dots in macro");	*dots = 1;	return slookup("__VA_ARGS__");} intgetcom(void){	int c; 	for(;;) {		c = getnsc();		if(c != '/')			break;		c = getc();		if(c == '/') {			while(c != '\n')				c = getc();			break;		}		if(c != '*')			break;		c = getc();		for(;;) {			if(c == '*') {				c = getc();				if(c != '/')					continue;				c = getc();				break;			}			if(c == '\n') {				yyerror("comment across newline");				break;			}			c = getc();		}		if(c == '\n')			break;	}	return c;} voiddodefine(char *cp){	Sym *s;	char *p;	long l; 	strcpy(symb, cp);	p = strchr(symb, '=');	if(p) {		*p++ = 0;		s = lookup();		l = strlen(p) + 2;	/* +1 null, +1 nargs */		while(l & 3)			l++;		while(nhunk < l)			gethunk();		*hunk = 0;		strcpy(hunk+1, p);		s->macro = hunk;		hunk += l;		nhunk -= l;	} else {		s = lookup();		s->macro = "\0001";	/* \000 is nargs */	}	if(debug['m'])		print("#define (-D) %s %s\n", s->name, s->macro+1);} struct{	char	*macname;	void	(*macf)(void);} mactab[] ={	"ifdef",	0,	/* macif(0) */	"ifndef",	0,	/* macif(1) */	"else",		0,	/* macif(2) */ 	"line",		maclin,	"define",	macdef,	"include",	macinc,	"undef",	macund, 	"pragma",	macprag,	"endif",	macend,	0}; voiddomacro(void){	int i;	Sym *s; 	s = getsym();	if(s == S)		s = slookup("endif");	for(i=0; mactab[i].macname; i++)		if(strcmp(s->name, mactab[i].macname) == 0) {			if(mactab[i].macf)				(*mactab[i].macf)();			else				macif(i);			return;		}	yyerror("unknown #: %s", s->name);	macend();} voidmacund(void){	Sym *s; 	s = getsym();	macend();	if(s == S) {		yyerror("syntax in #undef");		return;	}	s->macro = 0;} #define	NARG	25voidmacdef(void){	Sym *s, *a;	char *args[NARG], *np, *base;	int n, i, c, len, dots;	int ischr; 	s = getsym();	if(s == S)		goto bad;	if(s->macro)		yyerror("macro redefined: %s", s->name);	c = getc();	n = -1;	dots = 0;	if(c == '(') {		n++;		c = getnsc();		if(c != ')') {			unget(c);			for(;;) {				a = getsymdots(&dots);				if(a == S)					goto bad;				if(n >= NARG) {					yyerror("too many arguments in #define: %s", s->name);					goto bad;				}				args[n++] = a->name;				c = getnsc();				if(c == ')')					break;				if(c != ',' || dots)					goto bad;			}		}		c = getc();	}	if(isspace(c))		if(c != '\n')			c = getnsc();	base = hunk;	len = 1;	ischr = 0;	for(;;) {		if(isalpha(c) || c == '_') {			np = symb;			*np++ = c;			c = getc();			while(isalnum(c) || c == '_') {				*np++ = c;				c = getc();			}			*np = 0;			for(i=0; i<n; i++)				if(strcmp(symb, args[i]) == 0)					break;			if(i >= n) {				i = strlen(symb);				base = allocn(base, len, i);				memcpy(base+len, symb, i);				len += i;				continue;			}			base = allocn(base, len, 2);			base[len++] = '#';			base[len++] = 'a' + i;			continue;		}		if(ischr){			if(c == '\\'){ 				base = allocn(base, len, 1);				base[len++] = c;				c = getc();			}else if(c == ischr)				ischr = 0;		}else{			if(c == '"' || c == '\''){				base = allocn(base, len, 1);				base[len++] = c;				ischr = c;				c = getc();				continue;			}			if(c == '/') {				c = getc();				if(c == '/'){					c = getc();					for(;;) {						if(c == '\n')							break;						c = getc();					}					continue;				}				if(c == '*'){					c = getc();					for(;;) {						if(c == '*') {							c = getc();							if(c != '/')								continue;							c = getc();							break;						}						if(c == '\n') {							yyerror("comment and newline in define: %s", s->name);							break;						}						c = getc();					}					continue;				}				base = allocn(base, len, 1);				base[len++] = '/';				continue;			}		}		if(c == '\\') {			c = getc();			if(c == '\n') {				c = getc();				continue;			}			else if(c == '\r') {				c = getc();				if(c == '\n') {					c = getc();					continue;				}			}			base = allocn(base, len, 1);			base[len++] = '\\';			continue;		}		if(c == '\n')			break;		if(c == '#')		if(n > 0) {			base = allocn(base, len, 1);			base[len++] = c;		}		base = allocn(base, len, 1);		base[len++] = c;		c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));		if(c == '\n')			lineno++;		if(c == -1) {			yyerror("eof in a macro: %s", s->name);			break;		}	}	do {		base = allocn(base, len, 1);		base[len++] = 0;	} while(len & 3); 	*base = n+1;	if(dots)		*base |= VARMAC;	s->macro = base;	if(debug['m'])		print("#define %s %s\n", s->name, s->macro+1);	return; bad:	if(s == S)		yyerror("syntax in #define");	else		yyerror("syntax in #define: %s", s->name);	macend();} voidmacexpand(Sym *s, char *b){	char buf[2000];	int n, l, c, nargs;	char *arg[NARG], *cp, *ob, *ecp, dots; 	ob = b;	if(*s->macro == 0) {		strcpy(b, s->macro+1);		if(debug['m'])			print("#expand %s %s\n", s->name, ob);		return;	}		nargs = (char)(*s->macro & ~VARMAC) - 1;	dots = *s->macro & VARMAC; 	c = getnsc();	if(c != '(')		goto bad;	n = 0;	c = getc();	if(c != ')') {		unget(c);		l = 0;		cp = buf;		ecp = cp + sizeof(buf)-4;		arg[n++] = cp;		for(;;) {			if(cp >= ecp)				goto toobig;			c = getc();			if(c == '"')				for(;;) {					if(cp >= ecp)						goto toobig;					*cp++ = c;					c = getc();					if(c == '\\') {						*cp++ = c;						c = getc();						continue;					}					if(c == '\n')						goto bad;					if(c == '"')						break;				}			if(c == '\'')				for(;;) {					if(cp >= ecp)						goto toobig;					*cp++ = c;					c = getc();					if(c == '\\') {						*cp++ = c;						c = getc();						continue;					}					if(c == '\n')						goto bad;					if(c == '\'')						break;				}			if(c == '/') {				c = getc();				switch(c) {				case '*':					for(;;) {						c = getc();						if(c == '*') {							c = getc();							if(c == '/')								break;						}					}					*cp++ = ' ';					continue;				case '/':					while((c = getc()) != '\n')						;					break;				default:					unget(c);					c = '/';				}			}			if(l == 0) {				if(c == ',') {					if(n == nargs && dots) {						*cp++ = ',';						continue;					}					*cp++ = 0;					arg[n++] = cp;					if(n > nargs)						break;					continue;				}				if(c == ')')					break;			}			if(c == '\n')				c = ' ';			*cp++ = c;			if(c == '(')				l++;			if(c == ')')				l--;		}		*cp = 0;	}	if(n != nargs) {		yyerror("argument mismatch expanding: %s", s->name);		*b = 0;		return;	}	cp = s->macro+1;	for(;;) {		c = *cp++;		if(c == '\n')			c = ' ';		if(c != '#') {			*b++ = c;			if(c == 0)				break;			continue;		}		c = *cp++;		if(c == 0)			goto bad;		if(c == '#') {			*b++ = c;			continue;

Lines 1–500 of 856.