Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include "plot.h"
5
#include <draw.h>
6
#include <event.h>
7
 
8
void	define(char*);
9
void	call(char*);
10
void	include(char*);
11
int	process(Biobuf*);
12
int	server(void);
13
 
14
enum{
15
	ARC,
16
	BOX,
17
	CALL,
18
	CFILL,
19
	CIRC,
20
	CLOSEPL,
21
	COLOR,
22
	CSPLINE,
23
	DEFINE,
24
	DISK,
25
	DSPLINE,
26
	ERASE,
27
	FILL,
28
	FRAME,
29
	FSPLINE,
30
	GRADE,
31
	IDLE,
32
	INCLUDE,
33
	LINE,
34
	LSPLINE,
35
	MOVE,
36
	OPENPL,
37
	PARABOLA,
38
	PEN,
39
	PAUSE,
40
	POINT,
41
	POLY,
42
	RANGE,
43
	RESTORE,
44
	RMOVE,
45
	RVEC,
46
	SAVE,
47
	SBOX,
48
	SPLINE,
49
	TEXT,
50
	VEC,
51
	LAST
52
};
53
 
54
struct pcall {
55
	char	*cc;
56
	int	numc;
57
} plots[] = {
58
	[ARC] 		"a", 	1,
59
	[BOX] 		"bo", 	2,
60
	[CALL]		"ca",	2,
61
	[CFILL] 	"cf", 	2,
62
	[CIRC] 		"ci", 	2,
63
	[CLOSEPL] 	"cl", 	2,
64
	[COLOR] 	"co", 	2,
65
	[CSPLINE]	"cs",	2,
66
	[DEFINE]	"de",	2,
67
	[DISK]		"di",	2,
68
	[DSPLINE]	"ds",	2,
69
	[ERASE] 	"e", 	1,
70
	[FILL] 		"fi", 	2,
71
	[FRAME] 	"fr", 	2,
72
	[FSPLINE]	"fs",	2,
73
	[GRADE] 	"g", 	1,
74
	[IDLE] 		"id", 	2,
75
	[INCLUDE]	"in",	2,
76
	[LINE] 		"li", 	2,
77
	[LSPLINE]	"ls",	2,
78
	[MOVE] 		"m", 	1,
79
	[OPENPL] 	"o", 	1,
80
	[PARABOLA] 	"par", 	3,
81
	[PEN] 		"pe", 	2,
82
	[PAUSE] 	"pau", 	3,
83
	[POINT] 	"poi", 	3,
84
	[POLY] 		"pol", 	3,
85
	[RANGE] 	"ra", 	2,
86
	[RESTORE] 	"re", 	2,
87
	[RMOVE] 	"rm", 	2,
88
	[RVEC] 		"rv", 	2,
89
	[SAVE] 		"sa", 	2,
90
	[SBOX] 		"sb", 	2,
91
	[SPLINE] 	"sp", 	2,
92
	[TEXT] 		"t", 	1,
93
	[VEC] 		"v", 	1,
94
	[LAST]	 	0, 	0,
95
};
96
 
97
struct pcall *pplots;		/* last command read */
98
 
99
#define MAXL 16
100
struct fcall {
101
	char *name;
102
	char *stash;
103
} flibr[MAXL];			/* define strings */
104
 
105
struct fcall *fptr = flibr;
106
 
107
#define	NFSTACK	50
108
struct fstack{
109
	int peekc;
110
	int lineno;
111
	char *corebuf;
112
	Biobuf *fd;
113
	double scale;
114
}fstack[NFSTACK];		/* stack of open input files & defines */
115
struct fstack *fsp=fstack;
116
 
117
#define	NARGSTR	8192
118
char argstr[NARGSTR+1];		/* string arguments */
119
 
120
#define	NX	8192
121
double x[NX];			/* numeric arguments */
122
 
123
#define	NPTS	256
124
int cnt[NPTS];			/* control-polygon vertex counts */
125
double *pts[NPTS];		/* control-polygon vertex pointers */
126
 
127
void eresized(int new){
128
	if(new && getwindow(display, Refnone) < 0){
129
		fprint(2, "Can't reattach to window: %r\n");
130
		exits("resize");
131
	}
132
}
133
char *items[]={
134
	"exit",
135
 
136
};
137
Menu menu={items};
138
void
139
main(int arc, char *arv[]){
140
	char *ap;
141
	Biobuf *bp;
142
	int fd;
143
	int i;
144
	int dflag;
145
	char *oflag;
146
	Mouse m;
147
	bp = 0;
148
	fd = dup(0, -1);		/* because openpl will close 0! */
149
	dflag=0;
150
	oflag="";
151
	for(i=1;i!=arc;i++) if(arv[i][0]=='-') switch(arv[i][1]){
152
	case 'd': dflag=1; break;
153
	case 'o': oflag=arv[i]+2; break;
154
	case 's': fd=server(); break;
155
	}
156
	openpl(oflag);
157
	if(dflag) doublebuffer();
158
	for (; arc > 1; arc--, arv++) {
159
		if (arv[1][0] == '-') {
160
			ap = arv[1];
161
			ap++;
162
			switch (*ap) {
163
			default:
164
				fprint(2, "%s not allowed as argument\n", ap);
165
				exits("usage");
166
			case 'T': break;
167
			case 'D': break;
168
			case 'd': break;
169
			case 'o': break;
170
			case 'W': break;
171
			case 's': break;
172
			case 'e': erase(); break;
173
			case 'C': closepl(); break;
174
			case 'w': ppause(); break;
175
			case 'c': color(ap+1); break;
176
			case 'f': cfill(ap+1); break;
177
			case 'p': pen(ap+1); break;
178
			case 'g': grade(atof(ap+1)); break;
179
			}
180
		}
181
		else if ((bp = Bopen(arv[1], OREAD)) == 0) {
182
			perror(arv[1]);
183
			fprint(2, "Cannot find file %s\n", arv[1]);
184
		}
185
		else if(process(bp)) Bterm(fsp->fd);
186
		else break;
187
	}
188
	if (bp == 0){
189
		bp = malloc(sizeof *bp);
190
		Binit(bp, fd, OREAD);
191
		process(bp);
192
	}
193
	closepl();
194
	flushimage(display, 1);
195
	for(;;){
196
		m=emouse();
197
		if(m.buttons&4 && emenuhit(3, &m, &menu)==0) exits(0);
198
	}
199
}
200
int isalpha(int c)
201
{
202
	return ('a'<=c && c<='z') || ('A'<=c && c<='Z');
203
}
204
int isupper(int c)
205
{
206
	return 'A'<=c && c<='Z';
207
}
208
int isdigit(int c)
209
{
210
	return '0'<=c && c<='9';
211
}
212
int ispunct(int c)
213
{
214
	return strchr("!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~", c)!=0;
215
}
216
int isspace(int c)
217
{
218
	return strchr(" \t\n\v\f\r", c)!=0;
219
}
220
int nextc(void){
221
	int c;
222
	Rune r;
223
	for(;;){
224
		if(fsp->peekc!=Beof){
225
			c=fsp->peekc;
226
			fsp->peekc=Beof;
227
			return c;
228
		}
229
		if(fsp->fd)
230
			c=Bgetrune(fsp->fd);
231
		else if(*fsp->corebuf){
232
			fsp->corebuf+=chartorune(&r, fsp->corebuf);
233
			c=r;
234
		}else
235
			c=Beof;
236
		if(c!=Beof || fsp==fstack) break;
237
		if(fsp->fd) Bterm(fsp->fd);
238
		--fsp;
239
	}
240
	if(c=='\n') fsp->lineno++;
241
	return c;
242
}
243
/*
244
 * Read a string into argstr -- ignores leading spaces
245
 * and an optional leading quote-mark
246
 */
247
void
248
strarg(void){
249
	int c;
250
	Rune r;
251
	int quote=0;
252
	char *s=argstr;
253
	do
254
		c=nextc();
255
	while(c==' ' || c=='\t');
256
	if(c=='\'' || c=='"'){
257
		quote=c;
258
		c=nextc();
259
	}
260
	r = 0;
261
	while(c!='\n' && c!=Beof){
262
		r=c;
263
		s+=runetochar(s, &r);
264
		c=nextc();
265
	}
266
	if(quote && s!=argstr && r==quote) --s;
267
	*s='\0';
268
}
269
/*
270
 * Read a floating point number into argstr
271
 */
272
numstring(void){
273
	int ndp=0;
274
	int ndig=0;
275
	char *s=argstr;
276
	int c=nextc();
277
	if(c=='+' || c=='-'){
278
		*s++=c;
279
		c=nextc();
280
	}
281
	while(isdigit(c) || c=='.'){
282
		if(s!=&argstr[NARGSTR]) *s++=c;
283
		if(c=='.') ndp++;
284
		else ndig++;
285
		c=nextc();
286
	}
287
	if(ndp>1 || ndig==0){
288
		fsp->peekc=c;
289
		return 0;
290
	}
291
	if(c=='e' || c=='E'){
292
		if(s!=&argstr[NARGSTR]) *s++=c;
293
		c=nextc();
294
		if(c=='+' || c=='-'){
295
			if(s!=&argstr[NARGSTR]) *s++=c;
296
			c=nextc();
297
		}
298
		if(!isdigit(c)){
299
			fsp->peekc=c;
300
			return 0;
301
		}
302
		while(isdigit(c)){
303
			if(s!=&argstr[NARGSTR]) *s++=c;
304
			c=nextc();
305
		}
306
	}
307
	fsp->peekc=c;
308
	*s='\0';
309
	return 1;
310
}
311
/*
312
 * Read n numeric arguments, storing them in
313
 * x[0], ..., x[n-1]
314
 */
315
void
316
numargs(int n){
317
	int i, c;
318
	for(i=0;i!=n;i++){
319
		do{
320
			c=nextc();
321
		}while(strchr(" \t\n", c) || c!='.' && c!='+' && c!='-' && ispunct(c));
322
		fsp->peekc=c;
323
		if(!numstring()){
324
			fprint(2, "line %d: number expected\n", fsp->lineno);
325
			exits("input error");
326
		}
327
		x[i]=atof(argstr)*fsp->scale;
328
	}
329
}
330
/*
331
 * Read a list of lists of control vertices, storing points in x[.],
332
 * pointers in pts[.] and counts in cnt[.]
333
 */
334
void
335
polyarg(void){
336
	int nleft, l, r, c;
337
	double **ptsp=pts, *xp=x;
338
	int *cntp=cnt;
339
	do{
340
		c=nextc();
341
	}while(c==' ' || c=='\t');
342
	if(c=='{'){
343
		l='{';
344
		r='}';
345
	}
346
	else{
347
		l=r='\n';
348
		fsp->peekc=c;
349
	}
350
	nleft=1;
351
	*cntp=0;
352
	*ptsp=xp;
353
	for(;;){
354
		c=nextc();
355
		if(c==r){
356
			if(*cntp){
357
				if(*cntp&1){
358
					fprint(2, "line %d: phase error\n",
359
						fsp->lineno);
360
					exits("bad input");
361
				}
362
				*cntp/=2;
363
				if(ptsp==&pts[NPTS]){
364
					fprint(2, "line %d: out of polygons\n",
365
						fsp->lineno);
366
					exits("exceeded limit");
367
				}
368
				*++ptsp=xp;
369
				*++cntp=0;
370
			}
371
			if(--nleft==0) return;
372
		}
373
		else switch(c){
374
		case Beof:  return;
375
		case ' ':  break;
376
		case '\t': break;
377
		case '\n': break;
378
		case '.': case '+': case '-':
379
		case '0': case '1': case '2': case '3': case '4':
380
		case '5': case '6': case '7': case '8': case '9':
381
			fsp->peekc=c;
382
			if(!numstring()){
383
				fprint(2, "line %d: expected number\n", fsp->lineno);
384
				exits("bad input");
385
			}
386
			if(xp==&x[NX]){
387
				fprint(2, "line %d: out of space\n", fsp->lineno);
388
				exits("exceeded limit");
389
			}
390
			*xp++=atof(argstr);
391
			++*cntp;
392
			break;
393
		default:
394
			if(c==l) nleft++;
395
			else if(!ispunct(c)){
396
				fsp->peekc=c;
397
				return;
398
			}
399
		}
400
	}
401
}
402
 
403
process(Biobuf *fd){
404
	char *s;
405
	int c;
406
	fsp=fstack;
407
	fsp->fd=fd;
408
	fsp->corebuf=0;
409
	fsp->peekc=Beof;
410
	fsp->lineno=1;
411
	fsp->scale=1.;
412
	for(;;){
413
		do
414
			c=nextc();
415
		while(c==' ' || c=='\t');
416
		if(c==':'){
417
			do
418
				c=nextc();
419
			while(c!='\n' && c!=Beof);
420
			if(c==Beof) break;
421
			continue;
422
		}
423
		while(c=='.'){
424
			c=nextc();
425
			if(isdigit(c)){
426
				if(fsp->fd) Bungetc(fsp->fd);
427
				else --fsp->corebuf;
428
				c='.';
429
				break;
430
			}
431
		}
432
		if(c==Beof) break;
433
		if(c=='\n') continue;
434
		if(isalpha(c)){
435
			s=argstr;
436
			do{
437
				if(isupper(c)) c=tolower(c);
438
				if(s!=&argstr[NARGSTR]) *s++=c;
439
				c=nextc();
440
			}while(isalpha(c));
441
			fsp->peekc=c;
442
			*s='\0';
443
			for(pplots=plots;pplots->cc;pplots++)
444
				if(strncmp(argstr, pplots->cc, pplots->numc)==0)
445
					break;
446
			if(pplots->cc==0){
447
				fprint(2, "line %d, %s unknown\n", fsp->lineno,
448
					argstr);
449
				exits("bad command");
450
			}
451
		}
452
		else{
453
			fsp->peekc=c;
454
		}
455
		if(!pplots){
456
			fprint(2, "line %d, no command!\n", fsp->lineno);
457
			exits("no command");
458
		}
459
		switch(pplots-plots){
460
		case ARC:	numargs(7); rarc(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break;
461
		case BOX:	numargs(4); box(x[0], x[1], x[2], x[3]); break;
462
		case CALL:	strarg();   call(argstr); pplots=0; break;
463
		case CFILL:	strarg();   cfill(argstr); pplots=0; break;
464
		case CIRC:	numargs(3); circ(x[0], x[1], x[2]); break;
465
		case CLOSEPL:	strarg();   closepl(); pplots=0; break;
466
		case COLOR:	strarg();   color(argstr); pplots=0; break;
467
		case CSPLINE:	polyarg();  splin(4, cnt, pts); break;
468
		case DEFINE:	strarg();   define(argstr); pplots=0; break;
469
		case DISK:	numargs(3); plotdisc(x[0], x[1], x[2]); break;
470
		case DSPLINE:	polyarg();  splin(3, cnt, pts); break;
471
		case ERASE:	strarg();   erase(); pplots=0; break;
472
		case FILL:	polyarg();  fill(cnt, pts); break;
473
		case FRAME:	numargs(4); frame(x[0], x[1], x[2], x[3]); break;
474
		case FSPLINE:	polyarg();  splin(1, cnt, pts); break;
475
		case GRADE:	numargs(1); grade(x[0]); break;
476
		case IDLE:	strarg();   idle(); pplots=0; break;
477
		case INCLUDE:	strarg();   include(argstr); pplots=0; break;
478
		case LINE:	numargs(4); plotline(x[0], x[1], x[2], x[3]); break;
479
		case LSPLINE:	polyarg();  splin(2, cnt, pts); break;
480
		case MOVE:	numargs(2); move(x[0], x[1]); break;
481
		case OPENPL:	strarg();   openpl(argstr); pplots=0; break;
482
		case PARABOLA:	numargs(6); parabola(x[0],x[1],x[2],x[3],x[4],x[5]); break;
483
		case PAUSE:	strarg();   ppause(); pplots=0; break;
484
		case PEN:	strarg();   pen(argstr); pplots=0; break;
485
		case POINT:	numargs(2); dpoint(x[0], x[1]); break;
486
		case POLY:	polyarg();  plotpoly(cnt, pts); break;
487
		case RANGE:	numargs(4); range(x[0], x[1], x[2], x[3]); break;
488
		case RESTORE:	strarg();   restore(); pplots=0; break;
489
		case RMOVE:	numargs(2); rmove(x[0], x[1]); break;
490
		case RVEC:	numargs(2); rvec(x[0], x[1]); break;
491
		case SAVE:	strarg();   save(); pplots=0; break;
492
		case SBOX:	numargs(4); sbox(x[0], x[1], x[2], x[3]); break;
493
		case SPLINE:	polyarg();  splin(0, cnt, pts); break;
494
		case TEXT:	strarg();   text(argstr); pplots=0; break;
495
		case VEC:	numargs(2); vec(x[0], x[1]); break;
496
		default:
497
			fprint(2, "plot: missing case %ld\n", pplots-plots);
498
			exits("internal error");
499
		}
500
	}
501
	return 1;
502
}
503
char *names = 0;
504
char *enames = 0;
505
char *bstash = 0;
506
char *estash = 0;
507
unsigned size = 1024;
508
char *nstash = 0;
509
void define(char *a){
510
	char	*ap;
511
	short	i, j;
512
	int curly = 0;
513
	ap = a;
514
	while(isalpha(*ap))ap++;
515
	if(ap == a){
516
		fprint(2,"no name with define\n");
517
		exits("define");
518
	}
519
	i = ap - a;
520
	if(names+i+1 > enames){
521
		names = malloc((unsigned)512);
522
		enames = names + 512;
523
	}
524
	fptr->name = names;
525
	strncpy(names, a,i);
526
	names += i;
527
	*names++ = '\0';
528
	if(!bstash){
529
		bstash = nstash = malloc(size);
530
		estash = bstash + size;
531
	}
532
	fptr->stash = nstash;
533
	while(*ap != '{')
534
		if(*ap == '\n'){
535
			if((ap=Brdline(fsp->fd, '\n'))==0){
536
				fprint(2,"unexpected end of file\n");
537
				exits("eof");
538
			}
539
		}
540
		else ap++;
541
	while((j=Bgetc(fsp->fd))!= Beof){
542
		if(j == '{')curly++;
543
		else if(j == '}'){
544
			if(curly == 0)break;
545
			else curly--;
546
		}
547
		*nstash++ = j;
548
		if(nstash == estash){
549
			free(bstash);
550
			size += 1024;
551
			bstash = realloc(bstash,size);
552
			estash = bstash+size;
553
		}
554
	}
555
	*nstash++ = '\0';
556
	if(fptr++ >= &flibr[MAXL]){
557
		fprint(2,"Too many objects\n");
558
		exits("too many objects");
559
	}
560
}
561
void call(char *a){
562
	char *ap;
563
	struct fcall *f;
564
	char sav;
565
	double SC;
566
	ap = a;
567
	while(isalpha(*ap))ap++;
568
	sav = *ap;
569
	*ap = '\0';
570
	for(f=flibr;f<fptr;f++){
571
		if (!(strcmp(a, f->name)))
572
			break;
573
	}
574
	if(f == fptr){
575
		fprint(2, "object %s not defined\n",a);
576
		exits("undefined");
577
	}
578
	*ap = sav;
579
	while (isspace(*ap) || *ap == ',') 
580
		ap++;
581
	if (*ap != '\0')
582
		SC = atof(ap);
583
	else SC = 1.;
584
	if(++fsp==&fstack[NFSTACK]){
585
		fprint(2, "input stack overflow\n");
586
		exits("blew stack");
587
	}
588
	fsp->peekc=Beof;
589
	fsp->lineno=1;
590
	fsp->corebuf=f->stash;
591
	fsp->fd=0;
592
	fsp->scale=fsp[-1].scale*SC;
593
}
594
void include(char *a){
595
	Biobuf *fd;
596
	fd=Bopen(a, OREAD);
597
	if(fd==0){
598
		perror(a);
599
		exits("can't include");
600
	}
601
	if(++fsp==&fstack[NFSTACK]){
602
		fprint(2, "input stack overflow\n");
603
		exits("blew stack");
604
	}
605
	fsp->peekc=Beof;
606
	fsp->lineno=1;
607
	fsp->corebuf=0;
608
	fsp->fd=fd;
609
}
610
/*
611
 * Doesn't work.  Why?
612
 */
613
int server(void){
614
	int fd, p[2];
615
	char buf[32];
616
	pipe(p);
617
	fd = create("/srv/plot", 1, 0666);
618
	sprint(buf, "%d", p[1]);
619
	write(fd, buf, strlen(buf));
620
	close(fd);
621
	close(p[1]);
622
	return p[0];
623
}