forsyth20121205-174063a80cc13 years agoHistory
392 lines · 5.8 KB · C
RawDownload
#include	"cc.h"#include	"y.tab.h" enum{	Fnone	= 0,	Fl,	Fvl,	Fignor,	Fstar,	Fadj, 	Fverb	= 10,}; typedef	struct	Tprot	Tprot;struct	Tprot{	Type*	type;	Bits	flag;	Tprot*	link;}; typedef	struct	Tname	Tname;struct	Tname{	char*	name;	int	param;	Tname*	link;}; static	Type*	indchar;static	uchar	flagbits[256];static	char	fmtbuf[100];static	int	lastadj;static	int	lastverb;static	int	nstar;static	Tprot*	tprot;static	Tname*	tname; voidargflag(int c, int v){ 	switch(v) {	case Fignor:	case Fstar:	case Fl:	case Fvl:		flagbits[c] = v;		break;	case Fverb:		flagbits[c] = lastverb;/*print("flag-v %c %d\n", c, lastadj);*/		lastverb++;		break;	case Fadj:		flagbits[c] = lastadj;/*print("flag-l %c %d\n", c, lastadj);*/		lastadj++;		break;	}} Bitsgetflag(char *s){	Bits flag;	int c, f;	char *fmt; 	fmt = fmtbuf;	flag = zbits;	nstar = 0;	while(c = *s++) {		*fmt++ = c;		f = flagbits[c];		switch(f) {		case Fnone:			argflag(c, Fverb);			f = flagbits[c];			break;		case Fstar:			nstar++;		case Fignor:			continue;		case Fl:			if(bset(flag, Fl))				flag = bor(flag, blsh(Fvl));		}		flag = bor(flag, blsh(f));		if(f >= Fverb)			break;	}	*fmt = 0;	return flag;} voidnewprot(Sym *m, Type *t, char *s){	Bits flag;	Tprot *l; 	if(t == T) {		warn(Z, "%s: newprot: type not defined", m->name);		return;	}	flag = getflag(s);	for(l=tprot; l; l=l->link)		if(beq(flag, l->flag) && sametype(t, l->type))			return;	l = alloc(sizeof(*l));	l->type = t;	l->flag = flag;	l->link = tprot;	tprot = l;} voidnewname(char *s, int p){	Tname *l; 	for(l=tname; l; l=l->link)		if(strcmp(l->name, s) == 0) {			if(l->param != p)				yyerror("vargck %s already defined\n", s);			return;		}	l = alloc(sizeof(*l));	l->name = s;	l->param = p;	l->link = tname;	tname = l;} voidarginit(void){	int i; 	lastadj = Fadj;	lastverb = Fverb;	indchar = typ(TIND, types[TCHAR]); 	memset(flagbits, Fnone, sizeof(flagbits)); 	for(i='0'; i<='9'; i++)		argflag(i, Fignor);	argflag('.', Fignor);	argflag('#', Fignor);	argflag('u', Fignor);	argflag('+', Fignor);	argflag('-', Fignor); 	argflag('*', Fstar);	argflag('l', Fl); 	argflag('o', Fverb);	flagbits['x'] = flagbits['o'];	flagbits['X'] = flagbits['o'];} voidpragvararg(void){	Sym *s;	int n, c;	char *t; 	if(1)		goto out;	s = getsym();	if(s && strcmp(s->name, "argpos") == 0)		goto ckpos;	if(s && strcmp(s->name, "type") == 0)		goto cktype;	yyerror("syntax in #pragma varargck");	goto out; ckpos:/*#pragma	varargck	argpos	warn	2*/	s = getsym();	if(s == S)		goto bad;	n = getnsn();	if(n < 0)		goto bad;	newname(s->name, n);	goto out; cktype:/*#pragma	varargck	type	O	int*/	c = getnsc();	if(c != '"')		goto bad;	t = fmtbuf;	for(;;) {		c = getc();		if(c == ' ' || c == '\n')			goto bad;		if(c == '"')			break;		*t++ = c;	}	*t = 0;	t = strdup(fmtbuf);	s = getsym();	if(s == S)		goto bad;	c = getnsc();	unget(c);	if(c == '*')		newprot(s, typ(TIND, s->type), t);	else		newprot(s, s->type, t);	goto out; bad:	yyerror("syntax in #pragma varargck"); out:	while(getnsc() != '\n')		;} Node*nextarg(Node *n, Node **a){	if(n == Z) {		*a = Z;		return Z;	}	if(n->op == OLIST) {		*a = n->left;		return n->right;	}	*a = n;	return Z;} voidcheckargs(Node *nn, char *s, int pos){	Node *a, *n;	Bits flag;	Tprot *l; 	if(1)		return;	n = nn;	for(;;) {		s = strchr(s, '%');		if(s == 0) {			nextarg(n, &a);			if(a != Z)				warn(nn, "more arguments than format %T",					a->type);			return;		}		s++;		flag = getflag(s);		while(nstar > 0) {			n = nextarg(n, &a);			pos++;			nstar--;			if(a == Z) {				warn(nn, "more format than arguments %s",					fmtbuf);				return;			}			if(a->type == T)				continue;			if(!sametype(types[TINT], a->type) &&			   !sametype(types[TUINT], a->type))				warn(nn, "format mismatch '*' in %s %T, arg %d",					fmtbuf, a->type, pos);		}		for(l=tprot; l; l=l->link)			if(sametype(types[TVOID], l->type)) {				if(beq(flag, l->flag)) {					s++;					goto loop;				}			} 		n = nextarg(n, &a);		pos++;		if(a == Z) {			warn(nn, "more format than arguments %s",				fmtbuf);			return;		}		if(a->type == 0)			continue;		for(l=tprot; l; l=l->link)			if(sametype(a->type, l->type))				if(beq(flag, l->flag))					goto loop;		warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos);	loop:;	}} voiddpcheck(Node *n){	char *s;	Node *a, *b;	Tname *l;	int i; 	if(n == Z)		return;	b = n->left;	if(b == Z || b->op != ONAME)		return;	s = b->sym->name;	for(l=tname; l; l=l->link)		if(strcmp(s, l->name) == 0)			break;	if(l == 0)		return; 	i = l->param;	b = n->right;	while(i > 0) {		b = nextarg(b, &a);		i--;	}	if(a == Z) {		warn(n, "cant find format arg");		return;	}	if(!sametype(indchar, a->type)) {		warn(n, "format arg type %T", a->type);		return;	}	if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {/*		warn(n, "format arg not constant string");*/		return;	}	s = a->left->cstring;	checkargs(b, s, l->param);} voidpraghjdicks(void){	Sym *s; 	hjdickflg = 0;	s = getsym();	if(s) {		hjdickflg = atoi(s->name+1);		if(strcmp(s->name, "on") == 0 ||		   strcmp(s->name, "yes") == 0 ||		   strcmp(s->name, "dick") == 0)			hjdickflg = 1;	}	while(getnsc() != '\n')		;	if(0)		if(hjdickflg)			print("%4ld: hjdicks %d\n", lineno, hjdickflg);		else			print("%4ld: hjdicks off\n", lineno);} voidpragfpround(void){	Sym *s; 	fproundflg = 0;	s = getsym();	if(s) {		hjdickflg = atoi(s->name+1);		if(strcmp(s->name, "on") == 0 ||		   strcmp(s->name, "yes") == 0 ||		   strcmp(s->name, "dick") == 0)			fproundflg = 1;	}	while(getnsc() != '\n')		;	if(0)		if(fproundflg)			print("%4ld: fproundflg %d\n", lineno, fproundflg);		else			print("%4ld: fproundflg off\n", lineno);}