History

initial

rminnich committed 16 years ago

Commit 1fcdf79No parent (first commit)7733 files · +2461126 −-39Browse files

Showing the changes to sys/src/cmd/plot/plot.c (1 of 7733 files). Show all

Unified · Split

sys/src/cmd/plot/plot.c+623−0
@@ -0,0 +1,623 @@
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+ 0
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+}