forsyth20100406-1101c6b7dab16 years agoHistory
1195 lines · 22.4 KB · C
RawDownload
#include "lib9.h"#include "kernel.h"#include "draw.h"#include "tk.h" #define	O(t, e)		((long)(&((t*)0)->e)) static char* pdist(TkTop*, TkOption*, void*, char**, char*, char*);static char* pstab(TkTop*, TkOption*, void*, char**, char*, char*);static char* ptext(TkTop*, TkOption*, void*, char**, char*, char*);static char* pwinp(TkTop*, TkOption*, void*, char**, char*, char*);static char* pbmap(TkTop*, TkOption*, void*, char**, char*, char*);static char* pbool(TkTop*, TkOption*, void*, char**, char*, char*);static char* pfont(TkTop*, TkOption*, void*, char**, char*, char*);static char* pfrac(TkTop*, TkOption*, void*, char**, char*, char*);static char* pnnfrac(TkTop*, TkOption*, void*, char**, char*, char*);static char* pctag(TkTop*, TkOption*, void*, char**, char*, char*);static char* ptabs(TkTop*, TkOption*, void*, char**, char*, char*);static char* pcolr(TkTop*, TkOption*, void*, char**, char*, char*);static char* pimag(TkTop*, TkOption*, void*, char**, char*, char*);static char* psize(TkTop*, TkOption*, void*, char**, char*, char*);static char* pnndist(TkTop*, TkOption*, void*, char**, char*, char*);static char* pact(TkTop*, TkOption*, void*, char**, char*, char*);static char* pignore(TkTop*, TkOption*, void*, char**, char*, char*);static char* psticky(TkTop*, TkOption*, void*, char**, char*, char*);static char* plist(TkTop*, TkOption*, void*, char**, char*, char*); static char* (*oparse[])(TkTop*, TkOption*, void*, char**, char*, char*) ={	/* OPTdist */	pdist,	/* OPTstab */	pstab,	/* OPTtext */	ptext,	/* OPTwinp */	pwinp,	/* OPTflag */	pstab,	/* OPTbmap */	pbmap,	/* OPTbool */	pbool,	/* OPTfont */	pfont,	/* OPTfrac */	pfrac,	/* OPTnnfrac */	pnnfrac,	/* OPTctag */	pctag,	/* OPTtabs */	ptabs,	/* OPTcolr */	pcolr,	/* OPTimag */	pimag,	/* OPTsize */	psize,	/* OPTnndist */	pnndist,	/* OPTact */	pact,	/* OPTignore */	pignore,	/* OPTsticky */	psticky,	/* OPTlist */ plist,	/* OPTflags */	pstab,}; char*tkskip(char *s, char *bl){	char *p; 	while(*s) {		for(p = bl; *p; p++)			if(*p == *s)				break;		if(*p == '\0')			return s;			s++;	}	return s;} /* XXX - Tad: error propagation? */char*tkword(TkTop *t, char *str, char *buf, char *ebuf, int *gotarg){	int c, lev, tmp;	char *val, *e, *p, *cmd;	if (gotarg == nil)		gotarg = &tmp; 	/*	 * ebuf is one beyond last byte in buf; leave room for nul byte in	 * all cases.	 */	--ebuf; 	str = tkskip(str, " \t");	*gotarg = 1;	lev = 1;	switch(*str) {	case '{':		/* XXX - DBK: According to Ousterhout (p.37), while back=		 * slashed braces don't count toward finding the matching		 * closing braces, the backslashes should not be removed.		 * Presumably this also applies to other backslashed		 * characters: the backslash should not be removed.		 */		str++;		while(*str && buf < ebuf) {			c = *str++;			if(c == '\\') {				if(*str == '}' || *str == '{' || *str == '\\')					c = *str++;			} else if(c == '}') {				lev--;				if(lev == 0)					break;			} else if(c == '{')				lev++;			*buf++ = c;		}		break;	case '[':		/* XXX - DBK: According to Ousterhout (p. 33) command		 * substitution may occur anywhere within a word, not		 * only (as here) at the beginning.		 */		cmd = malloc(strlen(str));	/* not strlen+1 because the first character is skipped */		if ( cmd == nil ) {			buf[0] = '\0';	/* DBK - Why not an error message? */			return str;		}		p = cmd;		str++;		while(*str) {			c = *str++;			if(c == '\\') {				if(*str == ']' || *str == '[' || *str == '\\')					c = *str++;			} else if(c == ']') {				lev--;				if(lev == 0)					break;			} else if(c == '[')				lev++;			*p++ = c;		}		*p = '\0';		val = nil;		e = tkexec(t, cmd, &val);		free(cmd);		 /* XXX - Tad: is this appropriate behavior?		  *	      Am I sure that the error doesn't need to be		  *	      propagated back to the caller?		  */		if(e == nil && val != nil) {			strncpy(buf, val, ebuf-buf);			buf = ebuf;			free(val);		}		break;	case '\'':		str++;		while(*str && buf < ebuf)			*buf++ = *str++;		break;	case '\0':		*gotarg = 0;		break;	default:		/* XXX - DBK: See comment above about command substitution.		 * Also, any backslashed character should be replaced by		 * itself (e.g. to put a space, tab, or [ into a word.		 * We assume that the C compiler has already done the		 * standard ANSI C substitutions.  (But should we?)		 */		while(*str && *str != ' ' && *str != '\t' && buf < ebuf)			*buf++ = *str++;	}	*buf = '\0';	return str;} static TkOption*Getopt(TkOption *o, char *buf){	while(o->o != nil) {		if(strcmp(buf, o->o) == 0)			return o;		o++;	}	return nil;} TkName*tkmkname(char *name){	TkName *n; 	n = malloc(sizeof(struct TkName)+strlen(name));	if(n == nil)		return nil;	strcpy(n->name, name);	n->link = nil;	n->obj = nil;	return n;} char*tkparse(TkTop *t, char *str, TkOptab *ot, TkName **nl){	int l;	TkOptab *ft;	TkOption *o;	TkName *f, *n;	char *e, *buf, *ebuf; 	l = strlen(str);	if (l < Tkmaxitem)		l = Tkmaxitem;	buf = malloc(l + 1);	if(buf == 0)		return TkNomem;	ebuf = buf + l + 1; 	e = nil;	while(e == nil) {		str = tkword(t, str, buf, ebuf, nil);		switch(*buf) {		case '\0':			goto done;		case '-':			if (buf[1] != '\0') {				for(ft = ot; ft->ptr; ft++) {					o = Getopt(ft->optab, buf+1);					if(o != nil) {						e = oparse[o->type](t, o, ft->ptr, &str, buf, ebuf);						break;					}				}				if(ft->ptr == nil){					e = TkBadop;					tkerr(t, buf);				}				break;			}			/* fall through if we've got a singleton '-' */		default:			if(nl == nil) {				e = TkBadop;				tkerr(t, buf);				break;			}			n = tkmkname(buf);			if(n == nil) {				e = TkNomem;				break;			}			if(*nl == nil)				*nl = n;			else {				for(f = *nl; f->link; f = f->link)					;				f->link = n;			}		}			} 	if(e != nil && nl != nil)		tkfreename(*nl);done:	free(buf);	return e;} char*tkconflist(TkOptab *ot, char **val){	TkOption *o;	char *f, *e; 	f = "-%s";	while(ot->ptr != nil) {		o = ot->optab;		while(o->o != nil) {			e = tkvalue(val, f, o->o);			if(e != nil)				return e;			f = " -%s";			o++;		}		ot++;	}	return nil;} char*tkgencget(TkOptab *ft, char *arg, char **val, TkTop *t){	Tk *w;	char *c;	Point g;	TkEnv *e;	TkStab *s;	TkOption *o;	int wh, con, i, n, flag, *v;	char *r, *buf, *fmt, *out; 	buf = mallocz(Tkmaxitem, 0);	if(buf == nil)		return TkNomem; 	tkitem(buf, arg);	r = buf;	if(*r == '-')		r++;	o = nil;	while(ft->ptr) {		o = Getopt(ft->optab, r);		if(o != nil)			break;		ft++;	}	if(o == nil) {		tkerr(t, r);		free(buf);		return TkBadop;	} 	switch(o->type) {	default:		tkerr(t, r);		free(buf);		return TkBadop;	case OPTignore:		return nil;	case OPTact:		w = ft->ptr;		g = tkposn(w);		n = g.y;		if(o->aux == 0)			n = g.x;		free(buf);		return tkvalue(val, "%d", n);	case OPTdist:	case OPTnndist:		free(buf);		return tkvalue(val, "%d", OPTION(ft->ptr, int, o->offset));	case OPTsize:		w = ft->ptr;		if(strcmp(r, "width") == 0)			wh = w->req.width;		else			wh = w->req.height;		free(buf);		return tkvalue(val, "%d", wh);	case OPTtext:		c = OPTION(ft->ptr, char*, o->offset);		if(c == nil)			c = "";		free(buf);		return tkvalue(val, "%s", c);	case OPTwinp:		w = OPTION(ft->ptr, Tk*, o->offset);		if(w == nil || w->name == nil)			c = "";		else			c = w->name->name;		free(buf);		return tkvalue(val, "%s", c);	case OPTstab:		s = o->aux;		c = "";		con = OPTION(ft->ptr, int, o->offset);		while(s->val) {			if(con == s->con) {				c = s->val;				break;			}			s++;		}		free(buf);		return tkvalue(val, "%s", c);	case OPTflag:		con = OPTION(ft->ptr, int, o->offset);		flag = 0;		for (s = o->aux; s->val != nil; s++)			flag |= s->con;		c = "";		for (s = o->aux; s->val != nil; s++) {			if ((con & flag) == s->con) {				c = s->val;				break;			}		}		free(buf);		return tkvalue(val, "%s", c);	case OPTflags:		con = OPTION(ft->ptr, int, o->offset);		out = mallocz(Tkmaxitem, 0);		if(out == nil) {			free(buf);			return TkNomem;		}		c = out;		for (s = o->aux; s->val != nil; s++) {			if (s->con == (s->con&-s->con) && (con & s->con) != 0)				c = seprint(c, out+Tkmaxitem, " %s", s->val);	/* should this be quoted? */		}		free(buf);		*c = 0;		r = tkvalue(val, "%s", out);		free(out);		return r;	case OPTfont:		e = OPTION(ft->ptr, TkEnv*, o->offset);		free(buf);		if (e->font != nil)			return tkvalue(val, "%s", e->font->name);		return nil;	case OPTcolr:		e = OPTION(ft->ptr, TkEnv*, o->offset);		i = AUXI(o->aux);		free(buf);		return tkvalue(val, "#%.8lux", e->colors[i]);	case OPTfrac:	case OPTnnfrac:		v = &OPTION(ft->ptr, int, o->offset);		n = (int)o->aux;		if(n == 0)			n = 1;		fmt = "%s";		for(i = 0; i < n; i++) {			tkfprint(buf, *v++);			r = tkvalue(val, fmt, buf);			if(r != nil) {				free(buf);				return r;			}			fmt = " %s";		}		free(buf);		return nil;	case OPTbmap:		//free(buf);		return tkvalue(val, "%d", OPTION(ft->ptr, Image*, o->offset) != nil);	case OPTimag:		//free(buf);		return tkvalue(val, "%d", OPTION(ft->ptr, TkImg*, o->offset) != nil);	}} static char*pact(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf){	USED(buf);	USED(ebuf);	USED(str);	USED(place);	tkerr(t, o->o);	return TkBadop;} static char*pignore(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf){	char *p;	USED(t);	USED(o);	USED(place); 	p = tkword(t, *str, buf, ebuf, nil);	if(*buf == '\0')		return TkOparg;	*str = p;	return nil;} static char*pdist(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf){	int d;	char *e;	TkEnv *env; 	USED(buf);	USED(ebuf); 	/*	 * this is a bit of a hack, as 0 is a valid option offset,	 * but a nil aux is commonly used when 'w' and 'h' suffixes	 * aren't appropriate.	 * just make sure that no structure placed in TkOptab->ptr	 * with an OPTdist element has a TkEnv as its first member.	 */ 	if (o->aux == nil)		env = nil;	else		env = OPTION(place, TkEnv*, AUXI(o->aux));	e = tkfracword(t, str, &d, env);	if(e != nil)		return e;	OPTION(place, int, o->offset) = TKF2I(d);	return nil;} static char*pnndist(TkTop *t, TkOption *o, void *place, char **str, char *buf, char *ebuf){	char* e;	int oldv; 

Lines 1–500 of 1195.