xref: /plan9/sys/src/cmd/plot/plot.c (revision a84536681645e23c630ce4ef2e5c3b284d4c590b)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include "plot.h"
57dd7cddfSDavid du Colombier #include <draw.h>
67dd7cddfSDavid du Colombier #include <event.h>
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier void	define(char*);
93e12c5d1SDavid du Colombier void	call(char*);
103e12c5d1SDavid du Colombier void	include(char*);
113e12c5d1SDavid du Colombier int	process(Biobuf*);
12219b2ee8SDavid du Colombier int	server(void);
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier enum{
153e12c5d1SDavid du Colombier 	ARC,
163e12c5d1SDavid du Colombier 	BOX,
173e12c5d1SDavid du Colombier 	CALL,
183e12c5d1SDavid du Colombier 	CFILL,
193e12c5d1SDavid du Colombier 	CIRC,
203e12c5d1SDavid du Colombier 	CLOSEPL,
213e12c5d1SDavid du Colombier 	COLOR,
223e12c5d1SDavid du Colombier 	CSPLINE,
233e12c5d1SDavid du Colombier 	DEFINE,
243e12c5d1SDavid du Colombier 	DISK,
253e12c5d1SDavid du Colombier 	DSPLINE,
263e12c5d1SDavid du Colombier 	ERASE,
273e12c5d1SDavid du Colombier 	FILL,
283e12c5d1SDavid du Colombier 	FRAME,
293e12c5d1SDavid du Colombier 	FSPLINE,
303e12c5d1SDavid du Colombier 	GRADE,
313e12c5d1SDavid du Colombier 	IDLE,
323e12c5d1SDavid du Colombier 	INCLUDE,
333e12c5d1SDavid du Colombier 	LINE,
343e12c5d1SDavid du Colombier 	LSPLINE,
353e12c5d1SDavid du Colombier 	MOVE,
363e12c5d1SDavid du Colombier 	OPENPL,
373e12c5d1SDavid du Colombier 	PARABOLA,
383e12c5d1SDavid du Colombier 	PEN,
393e12c5d1SDavid du Colombier 	PAUSE,
403e12c5d1SDavid du Colombier 	POINT,
413e12c5d1SDavid du Colombier 	POLY,
423e12c5d1SDavid du Colombier 	RANGE,
433e12c5d1SDavid du Colombier 	RESTORE,
443e12c5d1SDavid du Colombier 	RMOVE,
453e12c5d1SDavid du Colombier 	RVEC,
463e12c5d1SDavid du Colombier 	SAVE,
473e12c5d1SDavid du Colombier 	SBOX,
483e12c5d1SDavid du Colombier 	SPLINE,
493e12c5d1SDavid du Colombier 	TEXT,
503e12c5d1SDavid du Colombier 	VEC,
513e12c5d1SDavid du Colombier 	LAST
523e12c5d1SDavid du Colombier };
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier struct pcall {
553e12c5d1SDavid du Colombier 	char	*cc;
563e12c5d1SDavid du Colombier 	int	numc;
573e12c5d1SDavid du Colombier } plots[] = {
583e12c5d1SDavid du Colombier 	[ARC] 		"a", 	1,
593e12c5d1SDavid du Colombier 	[BOX] 		"bo", 	2,
603e12c5d1SDavid du Colombier 	[CALL]		"ca",	2,
613e12c5d1SDavid du Colombier 	[CFILL] 	"cf", 	2,
623e12c5d1SDavid du Colombier 	[CIRC] 		"ci", 	2,
633e12c5d1SDavid du Colombier 	[CLOSEPL] 	"cl", 	2,
643e12c5d1SDavid du Colombier 	[COLOR] 	"co", 	2,
653e12c5d1SDavid du Colombier 	[CSPLINE]	"cs",	2,
663e12c5d1SDavid du Colombier 	[DEFINE]	"de",	2,
673e12c5d1SDavid du Colombier 	[DISK]		"di",	2,
683e12c5d1SDavid du Colombier 	[DSPLINE]	"ds",	2,
693e12c5d1SDavid du Colombier 	[ERASE] 	"e", 	1,
703e12c5d1SDavid du Colombier 	[FILL] 		"fi", 	2,
713e12c5d1SDavid du Colombier 	[FRAME] 	"fr", 	2,
723e12c5d1SDavid du Colombier 	[FSPLINE]	"fs",	2,
733e12c5d1SDavid du Colombier 	[GRADE] 	"g", 	1,
743e12c5d1SDavid du Colombier 	[IDLE] 		"id", 	2,
753e12c5d1SDavid du Colombier 	[INCLUDE]	"in",	2,
763e12c5d1SDavid du Colombier 	[LINE] 		"li", 	2,
773e12c5d1SDavid du Colombier 	[LSPLINE]	"ls",	2,
783e12c5d1SDavid du Colombier 	[MOVE] 		"m", 	1,
793e12c5d1SDavid du Colombier 	[OPENPL] 	"o", 	1,
803e12c5d1SDavid du Colombier 	[PARABOLA] 	"par", 	3,
813e12c5d1SDavid du Colombier 	[PEN] 		"pe", 	2,
823e12c5d1SDavid du Colombier 	[PAUSE] 	"pau", 	3,
833e12c5d1SDavid du Colombier 	[POINT] 	"poi", 	3,
843e12c5d1SDavid du Colombier 	[POLY] 		"pol", 	3,
853e12c5d1SDavid du Colombier 	[RANGE] 	"ra", 	2,
863e12c5d1SDavid du Colombier 	[RESTORE] 	"re", 	2,
873e12c5d1SDavid du Colombier 	[RMOVE] 	"rm", 	2,
883e12c5d1SDavid du Colombier 	[RVEC] 		"rv", 	2,
893e12c5d1SDavid du Colombier 	[SAVE] 		"sa", 	2,
903e12c5d1SDavid du Colombier 	[SBOX] 		"sb", 	2,
913e12c5d1SDavid du Colombier 	[SPLINE] 	"sp", 	2,
923e12c5d1SDavid du Colombier 	[TEXT] 		"t", 	1,
933e12c5d1SDavid du Colombier 	[VEC] 		"v", 	1,
943e12c5d1SDavid du Colombier 	[LAST]	 	0, 	0,
953e12c5d1SDavid du Colombier };
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier struct pcall *pplots;		/* last command read */
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier #define MAXL 16
1003e12c5d1SDavid du Colombier struct fcall {
1013e12c5d1SDavid du Colombier 	char *name;
1023e12c5d1SDavid du Colombier 	char *stash;
1033e12c5d1SDavid du Colombier } flibr[MAXL];			/* define strings */
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier struct fcall *fptr = flibr;
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier #define	NFSTACK	50
1083e12c5d1SDavid du Colombier struct fstack{
1093e12c5d1SDavid du Colombier 	int peekc;
1103e12c5d1SDavid du Colombier 	int lineno;
1113e12c5d1SDavid du Colombier 	char *corebuf;
1123e12c5d1SDavid du Colombier 	Biobuf *fd;
1133e12c5d1SDavid du Colombier 	double scale;
1143e12c5d1SDavid du Colombier }fstack[NFSTACK];		/* stack of open input files & defines */
1153e12c5d1SDavid du Colombier struct fstack *fsp=fstack;
1163e12c5d1SDavid du Colombier 
1173e12c5d1SDavid du Colombier #define	NARGSTR	8192
1183e12c5d1SDavid du Colombier char argstr[NARGSTR+1];		/* string arguments */
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier #define	NX	8192
1213e12c5d1SDavid du Colombier double x[NX];			/* numeric arguments */
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier #define	NPTS	256
1243e12c5d1SDavid du Colombier int cnt[NPTS];			/* control-polygon vertex counts */
1253e12c5d1SDavid du Colombier double *pts[NPTS];		/* control-polygon vertex pointers */
1263e12c5d1SDavid du Colombier 
eresized(int new)1277dd7cddfSDavid du Colombier void eresized(int new){
1287dd7cddfSDavid du Colombier 	if(new && getwindow(display, Refnone) < 0){
1297dd7cddfSDavid du Colombier 		fprint(2, "Can't reattach to window: %r\n");
1307dd7cddfSDavid du Colombier 		exits("resize");
1317dd7cddfSDavid du Colombier 	}
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier char *items[]={
1347dd7cddfSDavid du Colombier 	"exit",
1357dd7cddfSDavid du Colombier 	0
1367dd7cddfSDavid du Colombier };
1377dd7cddfSDavid du Colombier Menu menu={items};
1383e12c5d1SDavid du Colombier void
main(int arc,char * arv[])1393e12c5d1SDavid du Colombier main(int arc, char *arv[]){
1403e12c5d1SDavid du Colombier 	char *ap;
141219b2ee8SDavid du Colombier 	Biobuf *bp;
142219b2ee8SDavid du Colombier 	int fd;
143219b2ee8SDavid du Colombier 	int i;
144219b2ee8SDavid du Colombier 	int dflag;
145219b2ee8SDavid du Colombier 	char *oflag;
1467dd7cddfSDavid du Colombier 	Mouse m;
147219b2ee8SDavid du Colombier 	bp = 0;
148219b2ee8SDavid du Colombier 	fd = dup(0, -1);		/* because openpl will close 0! */
149219b2ee8SDavid du Colombier 	dflag=0;
150219b2ee8SDavid du Colombier 	oflag="";
151219b2ee8SDavid du Colombier 	for(i=1;i!=arc;i++) if(arv[i][0]=='-') switch(arv[i][1]){
152219b2ee8SDavid du Colombier 	case 'd': dflag=1; break;
153219b2ee8SDavid du Colombier 	case 'o': oflag=arv[i]+2; break;
154219b2ee8SDavid du Colombier 	case 's': fd=server(); break;
155219b2ee8SDavid du Colombier 	}
156219b2ee8SDavid du Colombier 	openpl(oflag);
157219b2ee8SDavid du Colombier 	if(dflag) doublebuffer();
1583e12c5d1SDavid du Colombier 	for (; arc > 1; arc--, arv++) {
1593e12c5d1SDavid du Colombier 		if (arv[1][0] == '-') {
1603e12c5d1SDavid du Colombier 			ap = arv[1];
1613e12c5d1SDavid du Colombier 			ap++;
1623e12c5d1SDavid du Colombier 			switch (*ap) {
1633e12c5d1SDavid du Colombier 			default:
164219b2ee8SDavid du Colombier 				fprint(2, "%s not allowed as argument\n", ap);
1653e12c5d1SDavid du Colombier 				exits("usage");
166219b2ee8SDavid du Colombier 			case 'T': break;
167219b2ee8SDavid du Colombier 			case 'D': break;
168219b2ee8SDavid du Colombier 			case 'd': break;
169219b2ee8SDavid du Colombier 			case 'o': break;
170219b2ee8SDavid du Colombier 			case 'W': break;
171219b2ee8SDavid du Colombier 			case 's': break;
172219b2ee8SDavid du Colombier 			case 'e': erase(); break;
173219b2ee8SDavid du Colombier 			case 'C': closepl(); break;
174219b2ee8SDavid du Colombier 			case 'w': ppause(); break;
175219b2ee8SDavid du Colombier 			case 'c': color(ap+1); break;
176219b2ee8SDavid du Colombier 			case 'f': cfill(ap+1); break;
177219b2ee8SDavid du Colombier 			case 'p': pen(ap+1); break;
178219b2ee8SDavid du Colombier 			case 'g': grade(atof(ap+1)); break;
1793e12c5d1SDavid du Colombier 			}
1803e12c5d1SDavid du Colombier 		}
181219b2ee8SDavid du Colombier 		else if ((bp = Bopen(arv[1], OREAD)) == 0) {
1823e12c5d1SDavid du Colombier 			perror(arv[1]);
1833e12c5d1SDavid du Colombier 			fprint(2, "Cannot find file %s\n", arv[1]);
1843e12c5d1SDavid du Colombier 		}
185219b2ee8SDavid du Colombier 		else if(process(bp)) Bterm(fsp->fd);
186219b2ee8SDavid du Colombier 		else break;
1873e12c5d1SDavid du Colombier 	}
188219b2ee8SDavid du Colombier 	if (bp == 0){
189219b2ee8SDavid du Colombier 		bp = malloc(sizeof *bp);
190219b2ee8SDavid du Colombier 		Binit(bp, fd, OREAD);
191219b2ee8SDavid du Colombier 		process(bp);
1923e12c5d1SDavid du Colombier 	}
1933e12c5d1SDavid du Colombier 	closepl();
194*a8453668SDavid du Colombier 	flushimage(display, 1);
1957dd7cddfSDavid du Colombier 	for(;;){
1967dd7cddfSDavid du Colombier 		m=emouse();
1977dd7cddfSDavid du Colombier 		if(m.buttons&4 && emenuhit(3, &m, &menu)==0) exits(0);
1987dd7cddfSDavid du Colombier 	}
1993e12c5d1SDavid du Colombier }
isalpha(int c)2003e12c5d1SDavid du Colombier int isalpha(int c)
2013e12c5d1SDavid du Colombier {
2023e12c5d1SDavid du Colombier 	return ('a'<=c && c<='z') || ('A'<=c && c<='Z');
2033e12c5d1SDavid du Colombier }
isupper(int c)2043e12c5d1SDavid du Colombier int isupper(int c)
2053e12c5d1SDavid du Colombier {
2063e12c5d1SDavid du Colombier 	return 'A'<=c && c<='Z';
2073e12c5d1SDavid du Colombier }
isdigit(int c)2083e12c5d1SDavid du Colombier int isdigit(int c)
2093e12c5d1SDavid du Colombier {
2103e12c5d1SDavid du Colombier 	return '0'<=c && c<='9';
2113e12c5d1SDavid du Colombier }
ispunct(int c)2123e12c5d1SDavid du Colombier int ispunct(int c)
2133e12c5d1SDavid du Colombier {
2143e12c5d1SDavid du Colombier 	return strchr("!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~", c)!=0;
2153e12c5d1SDavid du Colombier }
isspace(int c)2163e12c5d1SDavid du Colombier int isspace(int c)
2173e12c5d1SDavid du Colombier {
2183e12c5d1SDavid du Colombier 	return strchr(" \t\n\v\f\r", c)!=0;
2193e12c5d1SDavid du Colombier }
nextc(void)2203e12c5d1SDavid du Colombier int nextc(void){
2213e12c5d1SDavid du Colombier 	int c;
2223e12c5d1SDavid du Colombier 	Rune r;
2233e12c5d1SDavid du Colombier 	for(;;){
2243e12c5d1SDavid du Colombier 		if(fsp->peekc!=Beof){
2253e12c5d1SDavid du Colombier 			c=fsp->peekc;
2263e12c5d1SDavid du Colombier 			fsp->peekc=Beof;
2273e12c5d1SDavid du Colombier 			return c;
2283e12c5d1SDavid du Colombier 		}
2293e12c5d1SDavid du Colombier 		if(fsp->fd)
2303e12c5d1SDavid du Colombier 			c=Bgetrune(fsp->fd);
2313e12c5d1SDavid du Colombier 		else if(*fsp->corebuf){
2323e12c5d1SDavid du Colombier 			fsp->corebuf+=chartorune(&r, fsp->corebuf);
2333e12c5d1SDavid du Colombier 			c=r;
2343e12c5d1SDavid du Colombier 		}else
2353e12c5d1SDavid du Colombier 			c=Beof;
2363e12c5d1SDavid du Colombier 		if(c!=Beof || fsp==fstack) break;
237219b2ee8SDavid du Colombier 		if(fsp->fd) Bterm(fsp->fd);
2383e12c5d1SDavid du Colombier 		--fsp;
2393e12c5d1SDavid du Colombier 	}
2403e12c5d1SDavid du Colombier 	if(c=='\n') fsp->lineno++;
2413e12c5d1SDavid du Colombier 	return c;
2423e12c5d1SDavid du Colombier }
2433e12c5d1SDavid du Colombier /*
2443e12c5d1SDavid du Colombier  * Read a string into argstr -- ignores leading spaces
2453e12c5d1SDavid du Colombier  * and an optional leading quote-mark
2463e12c5d1SDavid du Colombier  */
2473e12c5d1SDavid du Colombier void
strarg(void)2483e12c5d1SDavid du Colombier strarg(void){
2493e12c5d1SDavid du Colombier 	int c;
2503e12c5d1SDavid du Colombier 	Rune r;
2513e12c5d1SDavid du Colombier 	int quote=0;
2523e12c5d1SDavid du Colombier 	char *s=argstr;
2533e12c5d1SDavid du Colombier 	do
2543e12c5d1SDavid du Colombier 		c=nextc();
2553e12c5d1SDavid du Colombier 	while(c==' ' || c=='\t');
2563e12c5d1SDavid du Colombier 	if(c=='\'' || c=='"'){
2573e12c5d1SDavid du Colombier 		quote=c;
2583e12c5d1SDavid du Colombier 		c=nextc();
2593e12c5d1SDavid du Colombier 	}
2603e12c5d1SDavid du Colombier 	r = 0;
2613e12c5d1SDavid du Colombier 	while(c!='\n' && c!=Beof){
2623e12c5d1SDavid du Colombier 		r=c;
2633e12c5d1SDavid du Colombier 		s+=runetochar(s, &r);
2643e12c5d1SDavid du Colombier 		c=nextc();
2653e12c5d1SDavid du Colombier 	}
2663e12c5d1SDavid du Colombier 	if(quote && s!=argstr && r==quote) --s;
2673e12c5d1SDavid du Colombier 	*s='\0';
2683e12c5d1SDavid du Colombier }
2693e12c5d1SDavid du Colombier /*
2703e12c5d1SDavid du Colombier  * Read a floating point number into argstr
2713e12c5d1SDavid du Colombier  */
numstring(void)2723e12c5d1SDavid du Colombier numstring(void){
2733e12c5d1SDavid du Colombier 	int ndp=0;
2743e12c5d1SDavid du Colombier 	int ndig=0;
2753e12c5d1SDavid du Colombier 	char *s=argstr;
2763e12c5d1SDavid du Colombier 	int c=nextc();
2773e12c5d1SDavid du Colombier 	if(c=='+' || c=='-'){
2783e12c5d1SDavid du Colombier 		*s++=c;
2793e12c5d1SDavid du Colombier 		c=nextc();
2803e12c5d1SDavid du Colombier 	}
2813e12c5d1SDavid du Colombier 	while(isdigit(c) || c=='.'){
2823e12c5d1SDavid du Colombier 		if(s!=&argstr[NARGSTR]) *s++=c;
2833e12c5d1SDavid du Colombier 		if(c=='.') ndp++;
2843e12c5d1SDavid du Colombier 		else ndig++;
2853e12c5d1SDavid du Colombier 		c=nextc();
2863e12c5d1SDavid du Colombier 	}
2873e12c5d1SDavid du Colombier 	if(ndp>1 || ndig==0){
2883e12c5d1SDavid du Colombier 		fsp->peekc=c;
2893e12c5d1SDavid du Colombier 		return 0;
2903e12c5d1SDavid du Colombier 	}
2913e12c5d1SDavid du Colombier 	if(c=='e' || c=='E'){
2923e12c5d1SDavid du Colombier 		if(s!=&argstr[NARGSTR]) *s++=c;
2933e12c5d1SDavid du Colombier 		c=nextc();
2943e12c5d1SDavid du Colombier 		if(c=='+' || c=='-'){
2953e12c5d1SDavid du Colombier 			if(s!=&argstr[NARGSTR]) *s++=c;
2963e12c5d1SDavid du Colombier 			c=nextc();
2973e12c5d1SDavid du Colombier 		}
2983e12c5d1SDavid du Colombier 		if(!isdigit(c)){
2993e12c5d1SDavid du Colombier 			fsp->peekc=c;
3003e12c5d1SDavid du Colombier 			return 0;
3013e12c5d1SDavid du Colombier 		}
3023e12c5d1SDavid du Colombier 		while(isdigit(c)){
3033e12c5d1SDavid du Colombier 			if(s!=&argstr[NARGSTR]) *s++=c;
3043e12c5d1SDavid du Colombier 			c=nextc();
3053e12c5d1SDavid du Colombier 		}
3063e12c5d1SDavid du Colombier 	}
3073e12c5d1SDavid du Colombier 	fsp->peekc=c;
3083e12c5d1SDavid du Colombier 	*s='\0';
3093e12c5d1SDavid du Colombier 	return 1;
3103e12c5d1SDavid du Colombier }
3113e12c5d1SDavid du Colombier /*
3123e12c5d1SDavid du Colombier  * Read n numeric arguments, storing them in
3133e12c5d1SDavid du Colombier  * x[0], ..., x[n-1]
3143e12c5d1SDavid du Colombier  */
3153e12c5d1SDavid du Colombier void
numargs(int n)3163e12c5d1SDavid du Colombier numargs(int n){
3173e12c5d1SDavid du Colombier 	int i, c;
3183e12c5d1SDavid du Colombier 	for(i=0;i!=n;i++){
3193e12c5d1SDavid du Colombier 		do{
3203e12c5d1SDavid du Colombier 			c=nextc();
3213e12c5d1SDavid du Colombier 		}while(strchr(" \t\n", c) || c!='.' && c!='+' && c!='-' && ispunct(c));
3223e12c5d1SDavid du Colombier 		fsp->peekc=c;
3233e12c5d1SDavid du Colombier 		if(!numstring()){
3243e12c5d1SDavid du Colombier 			fprint(2, "line %d: number expected\n", fsp->lineno);
3253e12c5d1SDavid du Colombier 			exits("input error");
3263e12c5d1SDavid du Colombier 		}
3273e12c5d1SDavid du Colombier 		x[i]=atof(argstr)*fsp->scale;
3283e12c5d1SDavid du Colombier 	}
3293e12c5d1SDavid du Colombier }
3303e12c5d1SDavid du Colombier /*
3313e12c5d1SDavid du Colombier  * Read a list of lists of control vertices, storing points in x[.],
3323e12c5d1SDavid du Colombier  * pointers in pts[.] and counts in cnt[.]
3333e12c5d1SDavid du Colombier  */
3343e12c5d1SDavid du Colombier void
polyarg(void)3353e12c5d1SDavid du Colombier polyarg(void){
3363e12c5d1SDavid du Colombier 	int nleft, l, r, c;
3373e12c5d1SDavid du Colombier 	double **ptsp=pts, *xp=x;
3383e12c5d1SDavid du Colombier 	int *cntp=cnt;
3393e12c5d1SDavid du Colombier 	do{
3403e12c5d1SDavid du Colombier 		c=nextc();
3413e12c5d1SDavid du Colombier 	}while(c==' ' || c=='\t');
3423e12c5d1SDavid du Colombier 	if(c=='{'){
3433e12c5d1SDavid du Colombier 		l='{';
3443e12c5d1SDavid du Colombier 		r='}';
3453e12c5d1SDavid du Colombier 	}
3463e12c5d1SDavid du Colombier 	else{
3473e12c5d1SDavid du Colombier 		l=r='\n';
3483e12c5d1SDavid du Colombier 		fsp->peekc=c;
3493e12c5d1SDavid du Colombier 	}
3503e12c5d1SDavid du Colombier 	nleft=1;
3513e12c5d1SDavid du Colombier 	*cntp=0;
3523e12c5d1SDavid du Colombier 	*ptsp=xp;
3533e12c5d1SDavid du Colombier 	for(;;){
3543e12c5d1SDavid du Colombier 		c=nextc();
3553e12c5d1SDavid du Colombier 		if(c==r){
3563e12c5d1SDavid du Colombier 			if(*cntp){
3573e12c5d1SDavid du Colombier 				if(*cntp&1){
3583e12c5d1SDavid du Colombier 					fprint(2, "line %d: phase error\n",
3593e12c5d1SDavid du Colombier 						fsp->lineno);
3603e12c5d1SDavid du Colombier 					exits("bad input");
3613e12c5d1SDavid du Colombier 				}
3623e12c5d1SDavid du Colombier 				*cntp/=2;
3633e12c5d1SDavid du Colombier 				if(ptsp==&pts[NPTS]){
3643e12c5d1SDavid du Colombier 					fprint(2, "line %d: out of polygons\n",
3653e12c5d1SDavid du Colombier 						fsp->lineno);
3663e12c5d1SDavid du Colombier 					exits("exceeded limit");
3673e12c5d1SDavid du Colombier 				}
3683e12c5d1SDavid du Colombier 				*++ptsp=xp;
3693e12c5d1SDavid du Colombier 				*++cntp=0;
3703e12c5d1SDavid du Colombier 			}
3713e12c5d1SDavid du Colombier 			if(--nleft==0) return;
3723e12c5d1SDavid du Colombier 		}
3733e12c5d1SDavid du Colombier 		else switch(c){
3743e12c5d1SDavid du Colombier 		case Beof:  return;
3753e12c5d1SDavid du Colombier 		case ' ':  break;
3763e12c5d1SDavid du Colombier 		case '\t': break;
3773e12c5d1SDavid du Colombier 		case '\n': break;
3783e12c5d1SDavid du Colombier 		case '.': case '+': case '-':
3793e12c5d1SDavid du Colombier 		case '0': case '1': case '2': case '3': case '4':
3803e12c5d1SDavid du Colombier 		case '5': case '6': case '7': case '8': case '9':
3813e12c5d1SDavid du Colombier 			fsp->peekc=c;
3823e12c5d1SDavid du Colombier 			if(!numstring()){
3833e12c5d1SDavid du Colombier 				fprint(2, "line %d: expected number\n", fsp->lineno);
3843e12c5d1SDavid du Colombier 				exits("bad input");
3853e12c5d1SDavid du Colombier 			}
3863e12c5d1SDavid du Colombier 			if(xp==&x[NX]){
3873e12c5d1SDavid du Colombier 				fprint(2, "line %d: out of space\n", fsp->lineno);
3883e12c5d1SDavid du Colombier 				exits("exceeded limit");
3893e12c5d1SDavid du Colombier 			}
3903e12c5d1SDavid du Colombier 			*xp++=atof(argstr);
3913e12c5d1SDavid du Colombier 			++*cntp;
3923e12c5d1SDavid du Colombier 			break;
3933e12c5d1SDavid du Colombier 		default:
3943e12c5d1SDavid du Colombier 			if(c==l) nleft++;
3953e12c5d1SDavid du Colombier 			else if(!ispunct(c)){
3963e12c5d1SDavid du Colombier 				fsp->peekc=c;
3973e12c5d1SDavid du Colombier 				return;
3983e12c5d1SDavid du Colombier 			}
3993e12c5d1SDavid du Colombier 		}
4003e12c5d1SDavid du Colombier 	}
4013e12c5d1SDavid du Colombier }
4023e12c5d1SDavid du Colombier 
process(Biobuf * fd)4033e12c5d1SDavid du Colombier process(Biobuf *fd){
4043e12c5d1SDavid du Colombier 	char *s;
4053e12c5d1SDavid du Colombier 	int c;
4063e12c5d1SDavid du Colombier 	fsp=fstack;
4073e12c5d1SDavid du Colombier 	fsp->fd=fd;
4083e12c5d1SDavid du Colombier 	fsp->corebuf=0;
4093e12c5d1SDavid du Colombier 	fsp->peekc=Beof;
4103e12c5d1SDavid du Colombier 	fsp->lineno=1;
4113e12c5d1SDavid du Colombier 	fsp->scale=1.;
4123e12c5d1SDavid du Colombier 	for(;;){
4133e12c5d1SDavid du Colombier 		do
4143e12c5d1SDavid du Colombier 			c=nextc();
4153e12c5d1SDavid du Colombier 		while(c==' ' || c=='\t');
4163e12c5d1SDavid du Colombier 		if(c==':'){
4173e12c5d1SDavid du Colombier 			do
4183e12c5d1SDavid du Colombier 				c=nextc();
4193e12c5d1SDavid du Colombier 			while(c!='\n' && c!=Beof);
4203e12c5d1SDavid du Colombier 			if(c==Beof) break;
4213e12c5d1SDavid du Colombier 			continue;
4223e12c5d1SDavid du Colombier 		}
4233e12c5d1SDavid du Colombier 		while(c=='.'){
4243e12c5d1SDavid du Colombier 			c=nextc();
4253e12c5d1SDavid du Colombier 			if(isdigit(c)){
4263e12c5d1SDavid du Colombier 				if(fsp->fd) Bungetc(fsp->fd);
4273e12c5d1SDavid du Colombier 				else --fsp->corebuf;
4283e12c5d1SDavid du Colombier 				c='.';
4293e12c5d1SDavid du Colombier 				break;
4303e12c5d1SDavid du Colombier 			}
4313e12c5d1SDavid du Colombier 		}
4323e12c5d1SDavid du Colombier 		if(c==Beof) break;
4333e12c5d1SDavid du Colombier 		if(c=='\n') continue;
4343e12c5d1SDavid du Colombier 		if(isalpha(c)){
4353e12c5d1SDavid du Colombier 			s=argstr;
4363e12c5d1SDavid du Colombier 			do{
4373e12c5d1SDavid du Colombier 				if(isupper(c)) c=tolower(c);
4383e12c5d1SDavid du Colombier 				if(s!=&argstr[NARGSTR]) *s++=c;
4393e12c5d1SDavid du Colombier 				c=nextc();
4403e12c5d1SDavid du Colombier 			}while(isalpha(c));
4413e12c5d1SDavid du Colombier 			fsp->peekc=c;
4423e12c5d1SDavid du Colombier 			*s='\0';
4433e12c5d1SDavid du Colombier 			for(pplots=plots;pplots->cc;pplots++)
4443e12c5d1SDavid du Colombier 				if(strncmp(argstr, pplots->cc, pplots->numc)==0)
4453e12c5d1SDavid du Colombier 					break;
4463e12c5d1SDavid du Colombier 			if(pplots->cc==0){
4473e12c5d1SDavid du Colombier 				fprint(2, "line %d, %s unknown\n", fsp->lineno,
4483e12c5d1SDavid du Colombier 					argstr);
4493e12c5d1SDavid du Colombier 				exits("bad command");
4503e12c5d1SDavid du Colombier 			}
4513e12c5d1SDavid du Colombier 		}
4523e12c5d1SDavid du Colombier 		else{
4533e12c5d1SDavid du Colombier 			fsp->peekc=c;
4543e12c5d1SDavid du Colombier 		}
4553e12c5d1SDavid du Colombier 		if(!pplots){
4563e12c5d1SDavid du Colombier 			fprint(2, "line %d, no command!\n", fsp->lineno);
4573e12c5d1SDavid du Colombier 			exits("no command");
4583e12c5d1SDavid du Colombier 		}
4593e12c5d1SDavid du Colombier 		switch(pplots-plots){
4603e12c5d1SDavid du Colombier 		case ARC:	numargs(7); rarc(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break;
4613e12c5d1SDavid du Colombier 		case BOX:	numargs(4); box(x[0], x[1], x[2], x[3]); break;
4623e12c5d1SDavid du Colombier 		case CALL:	strarg();   call(argstr); pplots=0; break;
4633e12c5d1SDavid du Colombier 		case CFILL:	strarg();   cfill(argstr); pplots=0; break;
4643e12c5d1SDavid du Colombier 		case CIRC:	numargs(3); circ(x[0], x[1], x[2]); break;
4653e12c5d1SDavid du Colombier 		case CLOSEPL:	strarg();   closepl(); pplots=0; break;
4663e12c5d1SDavid du Colombier 		case COLOR:	strarg();   color(argstr); pplots=0; break;
4673e12c5d1SDavid du Colombier 		case CSPLINE:	polyarg();  splin(4, cnt, pts); break;
4683e12c5d1SDavid du Colombier 		case DEFINE:	strarg();   define(argstr); pplots=0; break;
4697dd7cddfSDavid du Colombier 		case DISK:	numargs(3); plotdisc(x[0], x[1], x[2]); break;
4703e12c5d1SDavid du Colombier 		case DSPLINE:	polyarg();  splin(3, cnt, pts); break;
4713e12c5d1SDavid du Colombier 		case ERASE:	strarg();   erase(); pplots=0; break;
4723e12c5d1SDavid du Colombier 		case FILL:	polyarg();  fill(cnt, pts); break;
4733e12c5d1SDavid du Colombier 		case FRAME:	numargs(4); frame(x[0], x[1], x[2], x[3]); break;
4743e12c5d1SDavid du Colombier 		case FSPLINE:	polyarg();  splin(1, cnt, pts); break;
4753e12c5d1SDavid du Colombier 		case GRADE:	numargs(1); grade(x[0]); break;
4763e12c5d1SDavid du Colombier 		case IDLE:	strarg();   idle(); pplots=0; break;
4773e12c5d1SDavid du Colombier 		case INCLUDE:	strarg();   include(argstr); pplots=0; break;
4787dd7cddfSDavid du Colombier 		case LINE:	numargs(4); plotline(x[0], x[1], x[2], x[3]); break;
4793e12c5d1SDavid du Colombier 		case LSPLINE:	polyarg();  splin(2, cnt, pts); break;
4803e12c5d1SDavid du Colombier 		case MOVE:	numargs(2); move(x[0], x[1]); break;
4813e12c5d1SDavid du Colombier 		case OPENPL:	strarg();   openpl(argstr); pplots=0; break;
4823e12c5d1SDavid du Colombier 		case PARABOLA:	numargs(6); parabola(x[0],x[1],x[2],x[3],x[4],x[5]); break;
4833e12c5d1SDavid du Colombier 		case PAUSE:	strarg();   ppause(); pplots=0; break;
4843e12c5d1SDavid du Colombier 		case PEN:	strarg();   pen(argstr); pplots=0; break;
4853e12c5d1SDavid du Colombier 		case POINT:	numargs(2); dpoint(x[0], x[1]); break;
4867dd7cddfSDavid du Colombier 		case POLY:	polyarg();  plotpoly(cnt, pts); break;
4873e12c5d1SDavid du Colombier 		case RANGE:	numargs(4); range(x[0], x[1], x[2], x[3]); break;
4883e12c5d1SDavid du Colombier 		case RESTORE:	strarg();   restore(); pplots=0; break;
4893e12c5d1SDavid du Colombier 		case RMOVE:	numargs(2); rmove(x[0], x[1]); break;
4903e12c5d1SDavid du Colombier 		case RVEC:	numargs(2); rvec(x[0], x[1]); break;
4913e12c5d1SDavid du Colombier 		case SAVE:	strarg();   save(); pplots=0; break;
4923e12c5d1SDavid du Colombier 		case SBOX:	numargs(4); sbox(x[0], x[1], x[2], x[3]); break;
4933e12c5d1SDavid du Colombier 		case SPLINE:	polyarg();  splin(0, cnt, pts); break;
4943e12c5d1SDavid du Colombier 		case TEXT:	strarg();   text(argstr); pplots=0; break;
4953e12c5d1SDavid du Colombier 		case VEC:	numargs(2); vec(x[0], x[1]); break;
4963e12c5d1SDavid du Colombier 		default:
4977dd7cddfSDavid du Colombier 			fprint(2, "plot: missing case %ld\n", pplots-plots);
4983e12c5d1SDavid du Colombier 			exits("internal error");
4993e12c5d1SDavid du Colombier 		}
5003e12c5d1SDavid du Colombier 	}
5013e12c5d1SDavid du Colombier 	return 1;
5023e12c5d1SDavid du Colombier }
5033e12c5d1SDavid du Colombier char *names = 0;
5043e12c5d1SDavid du Colombier char *enames = 0;
5053e12c5d1SDavid du Colombier char *bstash = 0;
5063e12c5d1SDavid du Colombier char *estash = 0;
5073e12c5d1SDavid du Colombier unsigned size = 1024;
5083e12c5d1SDavid du Colombier char *nstash = 0;
define(char * a)5093e12c5d1SDavid du Colombier void define(char *a){
5103e12c5d1SDavid du Colombier 	char	*ap;
5113e12c5d1SDavid du Colombier 	short	i, j;
5123e12c5d1SDavid du Colombier 	int curly = 0;
5133e12c5d1SDavid du Colombier 	ap = a;
5143e12c5d1SDavid du Colombier 	while(isalpha(*ap))ap++;
5153e12c5d1SDavid du Colombier 	if(ap == a){
5163e12c5d1SDavid du Colombier 		fprint(2,"no name with define\n");
5173e12c5d1SDavid du Colombier 		exits("define");
5183e12c5d1SDavid du Colombier 	}
5193e12c5d1SDavid du Colombier 	i = ap - a;
5203e12c5d1SDavid du Colombier 	if(names+i+1 > enames){
5213e12c5d1SDavid du Colombier 		names = malloc((unsigned)512);
5223e12c5d1SDavid du Colombier 		enames = names + 512;
5233e12c5d1SDavid du Colombier 	}
5243e12c5d1SDavid du Colombier 	fptr->name = names;
5253e12c5d1SDavid du Colombier 	strncpy(names, a,i);
5263e12c5d1SDavid du Colombier 	names += i;
5273e12c5d1SDavid du Colombier 	*names++ = '\0';
5283e12c5d1SDavid du Colombier 	if(!bstash){
5293e12c5d1SDavid du Colombier 		bstash = nstash = malloc(size);
5303e12c5d1SDavid du Colombier 		estash = bstash + size;
5313e12c5d1SDavid du Colombier 	}
5323e12c5d1SDavid du Colombier 	fptr->stash = nstash;
5333e12c5d1SDavid du Colombier 	while(*ap != '{')
5343e12c5d1SDavid du Colombier 		if(*ap == '\n'){
5353e12c5d1SDavid du Colombier 			if((ap=Brdline(fsp->fd, '\n'))==0){
5363e12c5d1SDavid du Colombier 				fprint(2,"unexpected end of file\n");
5373e12c5d1SDavid du Colombier 				exits("eof");
5383e12c5d1SDavid du Colombier 			}
5393e12c5d1SDavid du Colombier 		}
5403e12c5d1SDavid du Colombier 		else ap++;
5413e12c5d1SDavid du Colombier 	while((j=Bgetc(fsp->fd))!= Beof){
5423e12c5d1SDavid du Colombier 		if(j == '{')curly++;
5433e12c5d1SDavid du Colombier 		else if(j == '}'){
5443e12c5d1SDavid du Colombier 			if(curly == 0)break;
5453e12c5d1SDavid du Colombier 			else curly--;
5463e12c5d1SDavid du Colombier 		}
5473e12c5d1SDavid du Colombier 		*nstash++ = j;
5483e12c5d1SDavid du Colombier 		if(nstash == estash){
5493e12c5d1SDavid du Colombier 			free(bstash);
5503e12c5d1SDavid du Colombier 			size += 1024;
5513e12c5d1SDavid du Colombier 			bstash = realloc(bstash,size);
5523e12c5d1SDavid du Colombier 			estash = bstash+size;
5533e12c5d1SDavid du Colombier 		}
5543e12c5d1SDavid du Colombier 	}
5553e12c5d1SDavid du Colombier 	*nstash++ = '\0';
5563e12c5d1SDavid du Colombier 	if(fptr++ >= &flibr[MAXL]){
5573e12c5d1SDavid du Colombier 		fprint(2,"Too many objects\n");
5583e12c5d1SDavid du Colombier 		exits("too many objects");
5593e12c5d1SDavid du Colombier 	}
5603e12c5d1SDavid du Colombier }
call(char * a)5613e12c5d1SDavid du Colombier void call(char *a){
5623e12c5d1SDavid du Colombier 	char *ap;
5633e12c5d1SDavid du Colombier 	struct fcall *f;
5643e12c5d1SDavid du Colombier 	char sav;
5653e12c5d1SDavid du Colombier 	double SC;
5663e12c5d1SDavid du Colombier 	ap = a;
5673e12c5d1SDavid du Colombier 	while(isalpha(*ap))ap++;
5683e12c5d1SDavid du Colombier 	sav = *ap;
5693e12c5d1SDavid du Colombier 	*ap = '\0';
5703e12c5d1SDavid du Colombier 	for(f=flibr;f<fptr;f++){
5713e12c5d1SDavid du Colombier 		if (!(strcmp(a, f->name)))
5723e12c5d1SDavid du Colombier 			break;
5733e12c5d1SDavid du Colombier 	}
5743e12c5d1SDavid du Colombier 	if(f == fptr){
5753e12c5d1SDavid du Colombier 		fprint(2, "object %s not defined\n",a);
5763e12c5d1SDavid du Colombier 		exits("undefined");
5773e12c5d1SDavid du Colombier 	}
5783e12c5d1SDavid du Colombier 	*ap = sav;
5793e12c5d1SDavid du Colombier 	while (isspace(*ap) || *ap == ',')
5803e12c5d1SDavid du Colombier 		ap++;
5813e12c5d1SDavid du Colombier 	if (*ap != '\0')
5823e12c5d1SDavid du Colombier 		SC = atof(ap);
5833e12c5d1SDavid du Colombier 	else SC = 1.;
5843e12c5d1SDavid du Colombier 	if(++fsp==&fstack[NFSTACK]){
5853e12c5d1SDavid du Colombier 		fprint(2, "input stack overflow\n");
5863e12c5d1SDavid du Colombier 		exits("blew stack");
5873e12c5d1SDavid du Colombier 	}
5883e12c5d1SDavid du Colombier 	fsp->peekc=Beof;
5893e12c5d1SDavid du Colombier 	fsp->lineno=1;
5903e12c5d1SDavid du Colombier 	fsp->corebuf=f->stash;
5913e12c5d1SDavid du Colombier 	fsp->fd=0;
5923e12c5d1SDavid du Colombier 	fsp->scale=fsp[-1].scale*SC;
5933e12c5d1SDavid du Colombier }
include(char * a)5943e12c5d1SDavid du Colombier void include(char *a){
5953e12c5d1SDavid du Colombier 	Biobuf *fd;
5963e12c5d1SDavid du Colombier 	fd=Bopen(a, OREAD);
5973e12c5d1SDavid du Colombier 	if(fd==0){
5983e12c5d1SDavid du Colombier 		perror(a);
5993e12c5d1SDavid du Colombier 		exits("can't include");
6003e12c5d1SDavid du Colombier 	}
6013e12c5d1SDavid du Colombier 	if(++fsp==&fstack[NFSTACK]){
6023e12c5d1SDavid du Colombier 		fprint(2, "input stack overflow\n");
6033e12c5d1SDavid du Colombier 		exits("blew stack");
6043e12c5d1SDavid du Colombier 	}
6053e12c5d1SDavid du Colombier 	fsp->peekc=Beof;
6063e12c5d1SDavid du Colombier 	fsp->lineno=1;
6073e12c5d1SDavid du Colombier 	fsp->corebuf=0;
6083e12c5d1SDavid du Colombier 	fsp->fd=fd;
6093e12c5d1SDavid du Colombier }
610219b2ee8SDavid du Colombier /*
611219b2ee8SDavid du Colombier  * Doesn't work.  Why?
612219b2ee8SDavid du Colombier  */
server(void)613219b2ee8SDavid du Colombier int server(void){
614219b2ee8SDavid du Colombier 	int fd, p[2];
615219b2ee8SDavid du Colombier 	char buf[32];
616219b2ee8SDavid du Colombier 	pipe(p);
617219b2ee8SDavid du Colombier 	fd = create("/srv/plot", 1, 0666);
618219b2ee8SDavid du Colombier 	sprint(buf, "%d", p[1]);
619219b2ee8SDavid du Colombier 	write(fd, buf, strlen(buf));
620219b2ee8SDavid du Colombier 	close(fd);
621219b2ee8SDavid du Colombier 	close(p[1]);
622219b2ee8SDavid du Colombier 	return p[0];
623219b2ee8SDavid du Colombier }
624