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

📄 plot.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include "plot.h"#include <draw.h>#include <event.h>void	define(char*);void	call(char*);void	include(char*);int	process(Biobuf*);int	server(void);enum{	ARC,	BOX,	CALL,	CFILL,	CIRC,	CLOSEPL,	COLOR,	CSPLINE,	DEFINE,	DISK,	DSPLINE,	ERASE,	FILL,	FRAME,	FSPLINE,	GRADE,	IDLE,	INCLUDE,	LINE,	LSPLINE,	MOVE,	OPENPL,	PARABOLA,	PEN,	PAUSE,	POINT,	POLY,	RANGE,	RESTORE,	RMOVE,	RVEC,	SAVE,	SBOX,	SPLINE,	TEXT,	VEC,	LAST};struct pcall {	char	*cc;	int	numc;} plots[] = {	[ARC] 		"a", 	1,	[BOX] 		"bo", 	2,	[CALL]		"ca",	2,	[CFILL] 	"cf", 	2,	[CIRC] 		"ci", 	2,	[CLOSEPL] 	"cl", 	2,	[COLOR] 	"co", 	2,	[CSPLINE]	"cs",	2,	[DEFINE]	"de",	2,	[DISK]		"di",	2,	[DSPLINE]	"ds",	2,	[ERASE] 	"e", 	1,	[FILL] 		"fi", 	2,	[FRAME] 	"fr", 	2,	[FSPLINE]	"fs",	2,	[GRADE] 	"g", 	1,	[IDLE] 		"id", 	2,	[INCLUDE]	"in",	2,	[LINE] 		"li", 	2,	[LSPLINE]	"ls",	2,	[MOVE] 		"m", 	1,	[OPENPL] 	"o", 	1,	[PARABOLA] 	"par", 	3,	[PEN] 		"pe", 	2,	[PAUSE] 	"pau", 	3,	[POINT] 	"poi", 	3,	[POLY] 		"pol", 	3,	[RANGE] 	"ra", 	2,	[RESTORE] 	"re", 	2,	[RMOVE] 	"rm", 	2,	[RVEC] 		"rv", 	2,	[SAVE] 		"sa", 	2,	[SBOX] 		"sb", 	2,	[SPLINE] 	"sp", 	2,	[TEXT] 		"t", 	1,	[VEC] 		"v", 	1,	[LAST]	 	0, 	0,};struct pcall *pplots;		/* last command read */#define MAXL 16struct fcall {	char *name;	char *stash;} flibr[MAXL];			/* define strings */struct fcall *fptr = flibr;#define	NFSTACK	50struct fstack{	int peekc;	int lineno;	char *corebuf;	Biobuf *fd;	double scale;}fstack[NFSTACK];		/* stack of open input files & defines */struct fstack *fsp=fstack;#define	NARGSTR	8192char argstr[NARGSTR+1];		/* string arguments */#define	NX	8192double x[NX];			/* numeric arguments */#define	NPTS	256int cnt[NPTS];			/* control-polygon vertex counts */double *pts[NPTS];		/* control-polygon vertex pointers */void eresized(int new){	if(new && getwindow(display, Refnone) < 0){		fprint(2, "Can't reattach to window: %r\n");		exits("resize");	}}char *items[]={	"exit",	0};Menu menu={items};voidmain(int arc, char *arv[]){	char *ap;	Biobuf *bp;	int fd;	int i;	int dflag;	char *oflag;	Mouse m;	bp = 0;	fd = dup(0, -1);		/* because openpl will close 0! */	dflag=0;	oflag="";	for(i=1;i!=arc;i++) if(arv[i][0]=='-') switch(arv[i][1]){	case 'd': dflag=1; break;	case 'o': oflag=arv[i]+2; break;	case 's': fd=server(); break;	}	openpl(oflag);	if(dflag) doublebuffer();	for (; arc > 1; arc--, arv++) {		if (arv[1][0] == '-') {			ap = arv[1];			ap++;			switch (*ap) {			default:				fprint(2, "%s not allowed as argument\n", ap);				exits("usage");			case 'T': break;			case 'D': break;			case 'd': break;			case 'o': break;			case 'W': break;			case 's': break;			case 'e': erase(); break;			case 'C': closepl(); break;			case 'w': ppause(); break;			case 'c': color(ap+1); break;			case 'f': cfill(ap+1); break;			case 'p': pen(ap+1); break;			case 'g': grade(atof(ap+1)); break;			}		}		else if ((bp = Bopen(arv[1], OREAD)) == 0) {			perror(arv[1]);			fprint(2, "Cannot find file %s\n", arv[1]);		}		else if(process(bp)) Bterm(fsp->fd);		else break;	}	if (bp == 0){		bp = malloc(sizeof *bp);		Binit(bp, fd, OREAD);		process(bp);	}	closepl();	flushimage(display, 1);	for(;;){		m=emouse();		if(m.buttons&4 && emenuhit(3, &m, &menu)==0) exits(0);	}}int isalpha(int c){	return ('a'<=c && c<='z') || ('A'<=c && c<='Z');}int isupper(int c){	return 'A'<=c && c<='Z';}int isdigit(int c){	return '0'<=c && c<='9';}int ispunct(int c){	return strchr("!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~", c)!=0;}int isspace(int c){	return strchr(" \t\n\v\f\r", c)!=0;}int nextc(void){	int c;	Rune r;	for(;;){		if(fsp->peekc!=Beof){			c=fsp->peekc;			fsp->peekc=Beof;			return c;		}		if(fsp->fd)			c=Bgetrune(fsp->fd);		else if(*fsp->corebuf){			fsp->corebuf+=chartorune(&r, fsp->corebuf);			c=r;		}else			c=Beof;		if(c!=Beof || fsp==fstack) break;		if(fsp->fd) Bterm(fsp->fd);		--fsp;	}	if(c=='\n') fsp->lineno++;	return c;}/* * Read a string into argstr -- ignores leading spaces * and an optional leading quote-mark */voidstrarg(void){	int c;	Rune r;	int quote=0;	char *s=argstr;	do		c=nextc();	while(c==' ' || c=='\t');	if(c=='\'' || c=='"'){		quote=c;		c=nextc();	}	r = 0;	while(c!='\n' && c!=Beof){		r=c;		s+=runetochar(s, &r);		c=nextc();	}	if(quote && s!=argstr && r==quote) --s;	*s='\0';}/* * Read a floating point number into argstr */numstring(void){	int ndp=0;	int ndig=0;	char *s=argstr;	int c=nextc();	if(c=='+' || c=='-'){		*s++=c;		c=nextc();	}	while(isdigit(c) || c=='.'){		if(s!=&argstr[NARGSTR]) *s++=c;		if(c=='.') ndp++;		else ndig++;		c=nextc();	}	if(ndp>1 || ndig==0){		fsp->peekc=c;		return 0;	}	if(c=='e' || c=='E'){		if(s!=&argstr[NARGSTR]) *s++=c;		c=nextc();		if(c=='+' || c=='-'){			if(s!=&argstr[NARGSTR]) *s++=c;			c=nextc();		}		if(!isdigit(c)){			fsp->peekc=c;			return 0;		}		while(isdigit(c)){			if(s!=&argstr[NARGSTR]) *s++=c;			c=nextc();		}	}	fsp->peekc=c;	*s='\0';	return 1;}/* * Read n numeric arguments, storing them in * x[0], ..., x[n-1] */voidnumargs(int n){	int i, c;	for(i=0;i!=n;i++){		do{			c=nextc();		}while(strchr(" \t\n", c) || c!='.' && c!='+' && c!='-' && ispunct(c));		fsp->peekc=c;		if(!numstring()){			fprint(2, "line %d: number expected\n", fsp->lineno);			exits("input error");		}		x[i]=atof(argstr)*fsp->scale;	}}/* * Read a list of lists of control vertices, storing points in x[.], * pointers in pts[.] and counts in cnt[.] */voidpolyarg(void){	int nleft, l, r, c;	double **ptsp=pts, *xp=x;	int *cntp=cnt;	do{		c=nextc();	}while(c==' ' || c=='\t');	if(c=='{'){		l='{';		r='}';	}	else{		l=r='\n';		fsp->peekc=c;	}	nleft=1;	*cntp=0;	*ptsp=xp;	for(;;){		c=nextc();		if(c==r){			if(*cntp){				if(*cntp&1){					fprint(2, "line %d: phase error\n",						fsp->lineno);					exits("bad input");				}				*cntp/=2;				if(ptsp==&pts[NPTS]){					fprint(2, "line %d: out of polygons\n",						fsp->lineno);					exits("exceeded limit");				}				*++ptsp=xp;				*++cntp=0;			}			if(--nleft==0) return;		}		else switch(c){		case Beof:  return;		case ' ':  break;		case '\t': break;		case '\n': break;		case '.': case '+': case '-':		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':			fsp->peekc=c;			if(!numstring()){				fprint(2, "line %d: expected number\n", fsp->lineno);				exits("bad input");			}			if(xp==&x[NX]){				fprint(2, "line %d: out of space\n", fsp->lineno);				exits("exceeded limit");			}			*xp++=atof(argstr);			++*cntp;			break;		default:			if(c==l) nleft++;			else if(!ispunct(c)){				fsp->peekc=c;				return;			}		}	}}process(Biobuf *fd){	char *s;	int c;	fsp=fstack;	fsp->fd=fd;	fsp->corebuf=0;	fsp->peekc=Beof;	fsp->lineno=1;	fsp->scale=1.;	for(;;){		do			c=nextc();		while(c==' ' || c=='\t');		if(c==':'){			do				c=nextc();			while(c!='\n' && c!=Beof);			if(c==Beof) break;			continue;		}		while(c=='.'){			c=nextc();			if(isdigit(c)){				if(fsp->fd) Bungetc(fsp->fd);				else --fsp->corebuf;				c='.';				break;			}		}		if(c==Beof) break;		if(c=='\n') continue;		if(isalpha(c)){			s=argstr;			do{				if(isupper(c)) c=tolower(c);				if(s!=&argstr[NARGSTR]) *s++=c;				c=nextc();			}while(isalpha(c));			fsp->peekc=c;			*s='\0';			for(pplots=plots;pplots->cc;pplots++)				if(strncmp(argstr, pplots->cc, pplots->numc)==0)					break;			if(pplots->cc==0){				fprint(2, "line %d, %s unknown\n", fsp->lineno,					argstr);				exits("bad command");			}		}		else{			fsp->peekc=c;		}		if(!pplots){			fprint(2, "line %d, no command!\n", fsp->lineno);			exits("no command");		}		switch(pplots-plots){		case ARC:	numargs(7); rarc(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break;		case BOX:	numargs(4); box(x[0], x[1], x[2], x[3]); break;		case CALL:	strarg();   call(argstr); pplots=0; break;		case CFILL:	strarg();   cfill(argstr); pplots=0; break;		case CIRC:	numargs(3); circ(x[0], x[1], x[2]); break;		case CLOSEPL:	strarg();   closepl(); pplots=0; break;		case COLOR:	strarg();   color(argstr); pplots=0; break;		case CSPLINE:	polyarg();  splin(4, cnt, pts); break;		case DEFINE:	strarg();   define(argstr); pplots=0; break;		case DISK:	numargs(3); plotdisc(x[0], x[1], x[2]); break;		case DSPLINE:	polyarg();  splin(3, cnt, pts); break;		case ERASE:	strarg();   erase(); pplots=0; break;		case FILL:	polyarg();  fill(cnt, pts); break;		case FRAME:	numargs(4); frame(x[0], x[1], x[2], x[3]); break;		case FSPLINE:	polyarg();  splin(1, cnt, pts); break;		case GRADE:	numargs(1); grade(x[0]); break;		case IDLE:	strarg();   idle(); pplots=0; break;		case INCLUDE:	strarg();   include(argstr); pplots=0; break;		case LINE:	numargs(4); plotline(x[0], x[1], x[2], x[3]); break;		case LSPLINE:	polyarg();  splin(2, cnt, pts); break;		case MOVE:	numargs(2); move(x[0], x[1]); break;		case OPENPL:	strarg();   openpl(argstr); pplots=0; break;		case PARABOLA:	numargs(6); parabola(x[0],x[1],x[2],x[3],x[4],x[5]); break;		case PAUSE:	strarg();   ppause(); pplots=0; break;		case PEN:	strarg();   pen(argstr); pplots=0; break;		case POINT:	numargs(2); dpoint(x[0], x[1]); break;		case POLY:	polyarg();  plotpoly(cnt, pts); break;		case RANGE:	numargs(4); range(x[0], x[1], x[2], x[3]); break;		case RESTORE:	strarg();   restore(); pplots=0; break;		case RMOVE:	numargs(2); rmove(x[0], x[1]); break;		case RVEC:	numargs(2); rvec(x[0], x[1]); break;		case SAVE:	strarg();   save(); pplots=0; break;		case SBOX:	numargs(4); sbox(x[0], x[1], x[2], x[3]); break;		case SPLINE:	polyarg();  splin(0, cnt, pts); break;		case TEXT:	strarg();   text(argstr); pplots=0; break;		case VEC:	numargs(2); vec(x[0], x[1]); break;		default:			fprint(2, "plot: missing case %ld\n", pplots-plots);			exits("internal error");		}	}	return 1;}char *names = 0;char *enames = 0;char *bstash = 0;char *estash = 0;unsigned size = 1024;char *nstash = 0;void define(char *a){	char	*ap;	short	i, j;	int curly = 0;	ap = a;	while(isalpha(*ap))ap++;	if(ap == a){		fprint(2,"no name with define\n");		exits("define");	}	i = ap - a;	if(names+i+1 > enames){		names = malloc((unsigned)512);		enames = names + 512;	}	fptr->name = names;	strncpy(names, a,i);	names += i;	*names++ = '\0';	if(!bstash){		bstash = nstash = malloc(size);		estash = bstash + size;	}	fptr->stash = nstash;	while(*ap != '{')		if(*ap == '\n'){			if((ap=Brdline(fsp->fd, '\n'))==0){				fprint(2,"unexpected end of file\n");				exits("eof");			}		}		else ap++;	while((j=Bgetc(fsp->fd))!= Beof){		if(j == '{')curly++;		else if(j == '}'){			if(curly == 0)break;			else curly--;		}		*nstash++ = j;		if(nstash == estash){			free(bstash);			size += 1024;			bstash = realloc(bstash,size);			estash = bstash+size;		}	}	*nstash++ = '\0';	if(fptr++ >= &flibr[MAXL]){		fprint(2,"Too many objects\n");		exits("too many objects");	}}void call(char *a){	char *ap;	struct fcall *f;	char sav;	double SC;	ap = a;	while(isalpha(*ap))ap++;	sav = *ap;	*ap = '\0';	for(f=flibr;f<fptr;f++){		if (!(strcmp(a, f->name)))			break;	}	if(f == fptr){		fprint(2, "object %s not defined\n",a);		exits("undefined");	}	*ap = sav;	while (isspace(*ap) || *ap == ',') 		ap++;	if (*ap != '\0')		SC = atof(ap);	else SC = 1.;	if(++fsp==&fstack[NFSTACK]){		fprint(2, "input stack overflow\n");		exits("blew stack");	}	fsp->peekc=Beof;	fsp->lineno=1;	fsp->corebuf=f->stash;	fsp->fd=0;	fsp->scale=fsp[-1].scale*SC;}void include(char *a){	Biobuf *fd;	fd=Bopen(a, OREAD);	if(fd==0){		perror(a);		exits("can't include");	}	if(++fsp==&fstack[NFSTACK]){		fprint(2, "input stack overflow\n");		exits("blew stack");	}	fsp->peekc=Beof;	fsp->lineno=1;	fsp->corebuf=0;	fsp->fd=fd;}/* * Doesn't work.  Why? */int server(void){	int fd, p[2];	char buf[32];	pipe(p);	fd = create("/srv/plot", 1, 0666);	sprint(buf, "%d", p[1]);	write(fd, buf, strlen(buf));	close(fd);	close(p[1]);	return p[0];}

⌨️ 快捷键说明

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