13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier #include "plot.h" 5*7dd7cddfSDavid du Colombier #include <draw.h> 6*7dd7cddfSDavid 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 127*7dd7cddfSDavid du Colombier void eresized(int new){ 128*7dd7cddfSDavid du Colombier if(new && getwindow(display, Refnone) < 0){ 129*7dd7cddfSDavid du Colombier fprint(2, "Can't reattach to window: %r\n"); 130*7dd7cddfSDavid du Colombier exits("resize"); 131*7dd7cddfSDavid du Colombier } 132*7dd7cddfSDavid du Colombier } 133*7dd7cddfSDavid du Colombier char *items[]={ 134*7dd7cddfSDavid du Colombier "exit", 135*7dd7cddfSDavid du Colombier 0 136*7dd7cddfSDavid du Colombier }; 137*7dd7cddfSDavid du Colombier Menu menu={items}; 1383e12c5d1SDavid du Colombier void 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; 146*7dd7cddfSDavid 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*7dd7cddfSDavid du Colombier for(;;){ 195*7dd7cddfSDavid du Colombier m=emouse(); 196*7dd7cddfSDavid du Colombier if(m.buttons&4 && emenuhit(3, &m, &menu)==0) exits(0); 197*7dd7cddfSDavid du Colombier } 1983e12c5d1SDavid du Colombier } 1993e12c5d1SDavid du Colombier int isalpha(int c) 2003e12c5d1SDavid du Colombier { 2013e12c5d1SDavid du Colombier return ('a'<=c && c<='z') || ('A'<=c && c<='Z'); 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier int isupper(int c) 2043e12c5d1SDavid du Colombier { 2053e12c5d1SDavid du Colombier return 'A'<=c && c<='Z'; 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier int isdigit(int c) 2083e12c5d1SDavid du Colombier { 2093e12c5d1SDavid du Colombier return '0'<=c && c<='9'; 2103e12c5d1SDavid du Colombier } 2113e12c5d1SDavid du Colombier int ispunct(int c) 2123e12c5d1SDavid du Colombier { 2133e12c5d1SDavid du Colombier return strchr("!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~", c)!=0; 2143e12c5d1SDavid du Colombier } 2153e12c5d1SDavid du Colombier int isspace(int c) 2163e12c5d1SDavid du Colombier { 2173e12c5d1SDavid du Colombier return strchr(" \t\n\v\f\r", c)!=0; 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier int nextc(void){ 2203e12c5d1SDavid du Colombier int c; 2213e12c5d1SDavid du Colombier Rune r; 2223e12c5d1SDavid du Colombier for(;;){ 2233e12c5d1SDavid du Colombier if(fsp->peekc!=Beof){ 2243e12c5d1SDavid du Colombier c=fsp->peekc; 2253e12c5d1SDavid du Colombier fsp->peekc=Beof; 2263e12c5d1SDavid du Colombier return c; 2273e12c5d1SDavid du Colombier } 2283e12c5d1SDavid du Colombier if(fsp->fd) 2293e12c5d1SDavid du Colombier c=Bgetrune(fsp->fd); 2303e12c5d1SDavid du Colombier else if(*fsp->corebuf){ 2313e12c5d1SDavid du Colombier fsp->corebuf+=chartorune(&r, fsp->corebuf); 2323e12c5d1SDavid du Colombier c=r; 2333e12c5d1SDavid du Colombier }else 2343e12c5d1SDavid du Colombier c=Beof; 2353e12c5d1SDavid du Colombier if(c!=Beof || fsp==fstack) break; 236219b2ee8SDavid du Colombier if(fsp->fd) Bterm(fsp->fd); 2373e12c5d1SDavid du Colombier --fsp; 2383e12c5d1SDavid du Colombier } 2393e12c5d1SDavid du Colombier if(c=='\n') fsp->lineno++; 2403e12c5d1SDavid du Colombier return c; 2413e12c5d1SDavid du Colombier } 2423e12c5d1SDavid du Colombier /* 2433e12c5d1SDavid du Colombier * Read a string into argstr -- ignores leading spaces 2443e12c5d1SDavid du Colombier * and an optional leading quote-mark 2453e12c5d1SDavid du Colombier */ 2463e12c5d1SDavid du Colombier void 2473e12c5d1SDavid du Colombier strarg(void){ 2483e12c5d1SDavid du Colombier int c; 2493e12c5d1SDavid du Colombier Rune r; 2503e12c5d1SDavid du Colombier int quote=0; 2513e12c5d1SDavid du Colombier char *s=argstr; 2523e12c5d1SDavid du Colombier do 2533e12c5d1SDavid du Colombier c=nextc(); 2543e12c5d1SDavid du Colombier while(c==' ' || c=='\t'); 2553e12c5d1SDavid du Colombier if(c=='\'' || c=='"'){ 2563e12c5d1SDavid du Colombier quote=c; 2573e12c5d1SDavid du Colombier c=nextc(); 2583e12c5d1SDavid du Colombier } 2593e12c5d1SDavid du Colombier r = 0; 2603e12c5d1SDavid du Colombier while(c!='\n' && c!=Beof){ 2613e12c5d1SDavid du Colombier r=c; 2623e12c5d1SDavid du Colombier s+=runetochar(s, &r); 2633e12c5d1SDavid du Colombier c=nextc(); 2643e12c5d1SDavid du Colombier } 2653e12c5d1SDavid du Colombier if(quote && s!=argstr && r==quote) --s; 2663e12c5d1SDavid du Colombier *s='\0'; 2673e12c5d1SDavid du Colombier } 2683e12c5d1SDavid du Colombier /* 2693e12c5d1SDavid du Colombier * Read a floating point number into argstr 2703e12c5d1SDavid du Colombier */ 2713e12c5d1SDavid du Colombier numstring(void){ 2723e12c5d1SDavid du Colombier int ndp=0; 2733e12c5d1SDavid du Colombier int ndig=0; 2743e12c5d1SDavid du Colombier char *s=argstr; 2753e12c5d1SDavid du Colombier int c=nextc(); 2763e12c5d1SDavid du Colombier if(c=='+' || c=='-'){ 2773e12c5d1SDavid du Colombier *s++=c; 2783e12c5d1SDavid du Colombier c=nextc(); 2793e12c5d1SDavid du Colombier } 2803e12c5d1SDavid du Colombier while(isdigit(c) || c=='.'){ 2813e12c5d1SDavid du Colombier if(s!=&argstr[NARGSTR]) *s++=c; 2823e12c5d1SDavid du Colombier if(c=='.') ndp++; 2833e12c5d1SDavid du Colombier else ndig++; 2843e12c5d1SDavid du Colombier c=nextc(); 2853e12c5d1SDavid du Colombier } 2863e12c5d1SDavid du Colombier if(ndp>1 || ndig==0){ 2873e12c5d1SDavid du Colombier fsp->peekc=c; 2883e12c5d1SDavid du Colombier return 0; 2893e12c5d1SDavid du Colombier } 2903e12c5d1SDavid du Colombier if(c=='e' || c=='E'){ 2913e12c5d1SDavid du Colombier if(s!=&argstr[NARGSTR]) *s++=c; 2923e12c5d1SDavid du Colombier c=nextc(); 2933e12c5d1SDavid du Colombier if(c=='+' || c=='-'){ 2943e12c5d1SDavid du Colombier if(s!=&argstr[NARGSTR]) *s++=c; 2953e12c5d1SDavid du Colombier c=nextc(); 2963e12c5d1SDavid du Colombier } 2973e12c5d1SDavid du Colombier if(!isdigit(c)){ 2983e12c5d1SDavid du Colombier fsp->peekc=c; 2993e12c5d1SDavid du Colombier return 0; 3003e12c5d1SDavid du Colombier } 3013e12c5d1SDavid du Colombier while(isdigit(c)){ 3023e12c5d1SDavid du Colombier if(s!=&argstr[NARGSTR]) *s++=c; 3033e12c5d1SDavid du Colombier c=nextc(); 3043e12c5d1SDavid du Colombier } 3053e12c5d1SDavid du Colombier } 3063e12c5d1SDavid du Colombier fsp->peekc=c; 3073e12c5d1SDavid du Colombier *s='\0'; 3083e12c5d1SDavid du Colombier return 1; 3093e12c5d1SDavid du Colombier } 3103e12c5d1SDavid du Colombier /* 3113e12c5d1SDavid du Colombier * Read n numeric arguments, storing them in 3123e12c5d1SDavid du Colombier * x[0], ..., x[n-1] 3133e12c5d1SDavid du Colombier */ 3143e12c5d1SDavid du Colombier void 3153e12c5d1SDavid du Colombier numargs(int n){ 3163e12c5d1SDavid du Colombier int i, c; 3173e12c5d1SDavid du Colombier for(i=0;i!=n;i++){ 3183e12c5d1SDavid du Colombier do{ 3193e12c5d1SDavid du Colombier c=nextc(); 3203e12c5d1SDavid du Colombier }while(strchr(" \t\n", c) || c!='.' && c!='+' && c!='-' && ispunct(c)); 3213e12c5d1SDavid du Colombier fsp->peekc=c; 3223e12c5d1SDavid du Colombier if(!numstring()){ 3233e12c5d1SDavid du Colombier fprint(2, "line %d: number expected\n", fsp->lineno); 3243e12c5d1SDavid du Colombier exits("input error"); 3253e12c5d1SDavid du Colombier } 3263e12c5d1SDavid du Colombier x[i]=atof(argstr)*fsp->scale; 3273e12c5d1SDavid du Colombier } 3283e12c5d1SDavid du Colombier } 3293e12c5d1SDavid du Colombier /* 3303e12c5d1SDavid du Colombier * Read a list of lists of control vertices, storing points in x[.], 3313e12c5d1SDavid du Colombier * pointers in pts[.] and counts in cnt[.] 3323e12c5d1SDavid du Colombier */ 3333e12c5d1SDavid du Colombier void 3343e12c5d1SDavid du Colombier polyarg(void){ 3353e12c5d1SDavid du Colombier int nleft, l, r, c; 3363e12c5d1SDavid du Colombier double **ptsp=pts, *xp=x; 3373e12c5d1SDavid du Colombier int *cntp=cnt; 3383e12c5d1SDavid du Colombier do{ 3393e12c5d1SDavid du Colombier c=nextc(); 3403e12c5d1SDavid du Colombier }while(c==' ' || c=='\t'); 3413e12c5d1SDavid du Colombier if(c=='{'){ 3423e12c5d1SDavid du Colombier l='{'; 3433e12c5d1SDavid du Colombier r='}'; 3443e12c5d1SDavid du Colombier } 3453e12c5d1SDavid du Colombier else{ 3463e12c5d1SDavid du Colombier l=r='\n'; 3473e12c5d1SDavid du Colombier fsp->peekc=c; 3483e12c5d1SDavid du Colombier } 3493e12c5d1SDavid du Colombier nleft=1; 3503e12c5d1SDavid du Colombier *cntp=0; 3513e12c5d1SDavid du Colombier *ptsp=xp; 3523e12c5d1SDavid du Colombier for(;;){ 3533e12c5d1SDavid du Colombier c=nextc(); 3543e12c5d1SDavid du Colombier if(c==r){ 3553e12c5d1SDavid du Colombier if(*cntp){ 3563e12c5d1SDavid du Colombier if(*cntp&1){ 3573e12c5d1SDavid du Colombier fprint(2, "line %d: phase error\n", 3583e12c5d1SDavid du Colombier fsp->lineno); 3593e12c5d1SDavid du Colombier exits("bad input"); 3603e12c5d1SDavid du Colombier } 3613e12c5d1SDavid du Colombier *cntp/=2; 3623e12c5d1SDavid du Colombier if(ptsp==&pts[NPTS]){ 3633e12c5d1SDavid du Colombier fprint(2, "line %d: out of polygons\n", 3643e12c5d1SDavid du Colombier fsp->lineno); 3653e12c5d1SDavid du Colombier exits("exceeded limit"); 3663e12c5d1SDavid du Colombier } 3673e12c5d1SDavid du Colombier *++ptsp=xp; 3683e12c5d1SDavid du Colombier *++cntp=0; 3693e12c5d1SDavid du Colombier } 3703e12c5d1SDavid du Colombier if(--nleft==0) return; 3713e12c5d1SDavid du Colombier } 3723e12c5d1SDavid du Colombier else switch(c){ 3733e12c5d1SDavid du Colombier case Beof: return; 3743e12c5d1SDavid du Colombier case ' ': break; 3753e12c5d1SDavid du Colombier case '\t': break; 3763e12c5d1SDavid du Colombier case '\n': break; 3773e12c5d1SDavid du Colombier case '.': case '+': case '-': 3783e12c5d1SDavid du Colombier case '0': case '1': case '2': case '3': case '4': 3793e12c5d1SDavid du Colombier case '5': case '6': case '7': case '8': case '9': 3803e12c5d1SDavid du Colombier fsp->peekc=c; 3813e12c5d1SDavid du Colombier if(!numstring()){ 3823e12c5d1SDavid du Colombier fprint(2, "line %d: expected number\n", fsp->lineno); 3833e12c5d1SDavid du Colombier exits("bad input"); 3843e12c5d1SDavid du Colombier } 3853e12c5d1SDavid du Colombier if(xp==&x[NX]){ 3863e12c5d1SDavid du Colombier fprint(2, "line %d: out of space\n", fsp->lineno); 3873e12c5d1SDavid du Colombier exits("exceeded limit"); 3883e12c5d1SDavid du Colombier } 3893e12c5d1SDavid du Colombier *xp++=atof(argstr); 3903e12c5d1SDavid du Colombier ++*cntp; 3913e12c5d1SDavid du Colombier break; 3923e12c5d1SDavid du Colombier default: 3933e12c5d1SDavid du Colombier if(c==l) nleft++; 3943e12c5d1SDavid du Colombier else if(!ispunct(c)){ 3953e12c5d1SDavid du Colombier fsp->peekc=c; 3963e12c5d1SDavid du Colombier return; 3973e12c5d1SDavid du Colombier } 3983e12c5d1SDavid du Colombier } 3993e12c5d1SDavid du Colombier } 4003e12c5d1SDavid du Colombier } 4013e12c5d1SDavid du Colombier 4023e12c5d1SDavid du Colombier process(Biobuf *fd){ 4033e12c5d1SDavid du Colombier char *s; 4043e12c5d1SDavid du Colombier int c; 4053e12c5d1SDavid du Colombier fsp=fstack; 4063e12c5d1SDavid du Colombier fsp->fd=fd; 4073e12c5d1SDavid du Colombier fsp->corebuf=0; 4083e12c5d1SDavid du Colombier fsp->peekc=Beof; 4093e12c5d1SDavid du Colombier fsp->lineno=1; 4103e12c5d1SDavid du Colombier fsp->scale=1.; 4113e12c5d1SDavid du Colombier for(;;){ 4123e12c5d1SDavid du Colombier do 4133e12c5d1SDavid du Colombier c=nextc(); 4143e12c5d1SDavid du Colombier while(c==' ' || c=='\t'); 4153e12c5d1SDavid du Colombier if(c==':'){ 4163e12c5d1SDavid du Colombier do 4173e12c5d1SDavid du Colombier c=nextc(); 4183e12c5d1SDavid du Colombier while(c!='\n' && c!=Beof); 4193e12c5d1SDavid du Colombier if(c==Beof) break; 4203e12c5d1SDavid du Colombier continue; 4213e12c5d1SDavid du Colombier } 4223e12c5d1SDavid du Colombier while(c=='.'){ 4233e12c5d1SDavid du Colombier c=nextc(); 4243e12c5d1SDavid du Colombier if(isdigit(c)){ 4253e12c5d1SDavid du Colombier if(fsp->fd) Bungetc(fsp->fd); 4263e12c5d1SDavid du Colombier else --fsp->corebuf; 4273e12c5d1SDavid du Colombier c='.'; 4283e12c5d1SDavid du Colombier break; 4293e12c5d1SDavid du Colombier } 4303e12c5d1SDavid du Colombier } 4313e12c5d1SDavid du Colombier if(c==Beof) break; 4323e12c5d1SDavid du Colombier if(c=='\n') continue; 4333e12c5d1SDavid du Colombier if(isalpha(c)){ 4343e12c5d1SDavid du Colombier s=argstr; 4353e12c5d1SDavid du Colombier do{ 4363e12c5d1SDavid du Colombier if(isupper(c)) c=tolower(c); 4373e12c5d1SDavid du Colombier if(s!=&argstr[NARGSTR]) *s++=c; 4383e12c5d1SDavid du Colombier c=nextc(); 4393e12c5d1SDavid du Colombier }while(isalpha(c)); 4403e12c5d1SDavid du Colombier fsp->peekc=c; 4413e12c5d1SDavid du Colombier *s='\0'; 4423e12c5d1SDavid du Colombier for(pplots=plots;pplots->cc;pplots++) 4433e12c5d1SDavid du Colombier if(strncmp(argstr, pplots->cc, pplots->numc)==0) 4443e12c5d1SDavid du Colombier break; 4453e12c5d1SDavid du Colombier if(pplots->cc==0){ 4463e12c5d1SDavid du Colombier fprint(2, "line %d, %s unknown\n", fsp->lineno, 4473e12c5d1SDavid du Colombier argstr); 4483e12c5d1SDavid du Colombier exits("bad command"); 4493e12c5d1SDavid du Colombier } 4503e12c5d1SDavid du Colombier } 4513e12c5d1SDavid du Colombier else{ 4523e12c5d1SDavid du Colombier fsp->peekc=c; 4533e12c5d1SDavid du Colombier } 4543e12c5d1SDavid du Colombier if(!pplots){ 4553e12c5d1SDavid du Colombier fprint(2, "line %d, no command!\n", fsp->lineno); 4563e12c5d1SDavid du Colombier exits("no command"); 4573e12c5d1SDavid du Colombier } 4583e12c5d1SDavid du Colombier switch(pplots-plots){ 4593e12c5d1SDavid du Colombier case ARC: numargs(7); rarc(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break; 4603e12c5d1SDavid du Colombier case BOX: numargs(4); box(x[0], x[1], x[2], x[3]); break; 4613e12c5d1SDavid du Colombier case CALL: strarg(); call(argstr); pplots=0; break; 4623e12c5d1SDavid du Colombier case CFILL: strarg(); cfill(argstr); pplots=0; break; 4633e12c5d1SDavid du Colombier case CIRC: numargs(3); circ(x[0], x[1], x[2]); break; 4643e12c5d1SDavid du Colombier case CLOSEPL: strarg(); closepl(); pplots=0; break; 4653e12c5d1SDavid du Colombier case COLOR: strarg(); color(argstr); pplots=0; break; 4663e12c5d1SDavid du Colombier case CSPLINE: polyarg(); splin(4, cnt, pts); break; 4673e12c5d1SDavid du Colombier case DEFINE: strarg(); define(argstr); pplots=0; break; 468*7dd7cddfSDavid du Colombier case DISK: numargs(3); plotdisc(x[0], x[1], x[2]); break; 4693e12c5d1SDavid du Colombier case DSPLINE: polyarg(); splin(3, cnt, pts); break; 4703e12c5d1SDavid du Colombier case ERASE: strarg(); erase(); pplots=0; break; 4713e12c5d1SDavid du Colombier case FILL: polyarg(); fill(cnt, pts); break; 4723e12c5d1SDavid du Colombier case FRAME: numargs(4); frame(x[0], x[1], x[2], x[3]); break; 4733e12c5d1SDavid du Colombier case FSPLINE: polyarg(); splin(1, cnt, pts); break; 4743e12c5d1SDavid du Colombier case GRADE: numargs(1); grade(x[0]); break; 4753e12c5d1SDavid du Colombier case IDLE: strarg(); idle(); pplots=0; break; 4763e12c5d1SDavid du Colombier case INCLUDE: strarg(); include(argstr); pplots=0; break; 477*7dd7cddfSDavid du Colombier case LINE: numargs(4); plotline(x[0], x[1], x[2], x[3]); break; 4783e12c5d1SDavid du Colombier case LSPLINE: polyarg(); splin(2, cnt, pts); break; 4793e12c5d1SDavid du Colombier case MOVE: numargs(2); move(x[0], x[1]); break; 4803e12c5d1SDavid du Colombier case OPENPL: strarg(); openpl(argstr); pplots=0; break; 4813e12c5d1SDavid du Colombier case PARABOLA: numargs(6); parabola(x[0],x[1],x[2],x[3],x[4],x[5]); break; 4823e12c5d1SDavid du Colombier case PAUSE: strarg(); ppause(); pplots=0; break; 4833e12c5d1SDavid du Colombier case PEN: strarg(); pen(argstr); pplots=0; break; 4843e12c5d1SDavid du Colombier case POINT: numargs(2); dpoint(x[0], x[1]); break; 485*7dd7cddfSDavid du Colombier case POLY: polyarg(); plotpoly(cnt, pts); break; 4863e12c5d1SDavid du Colombier case RANGE: numargs(4); range(x[0], x[1], x[2], x[3]); break; 4873e12c5d1SDavid du Colombier case RESTORE: strarg(); restore(); pplots=0; break; 4883e12c5d1SDavid du Colombier case RMOVE: numargs(2); rmove(x[0], x[1]); break; 4893e12c5d1SDavid du Colombier case RVEC: numargs(2); rvec(x[0], x[1]); break; 4903e12c5d1SDavid du Colombier case SAVE: strarg(); save(); pplots=0; break; 4913e12c5d1SDavid du Colombier case SBOX: numargs(4); sbox(x[0], x[1], x[2], x[3]); break; 4923e12c5d1SDavid du Colombier case SPLINE: polyarg(); splin(0, cnt, pts); break; 4933e12c5d1SDavid du Colombier case TEXT: strarg(); text(argstr); pplots=0; break; 4943e12c5d1SDavid du Colombier case VEC: numargs(2); vec(x[0], x[1]); break; 4953e12c5d1SDavid du Colombier default: 496*7dd7cddfSDavid du Colombier fprint(2, "plot: missing case %ld\n", pplots-plots); 4973e12c5d1SDavid du Colombier exits("internal error"); 4983e12c5d1SDavid du Colombier } 4993e12c5d1SDavid du Colombier } 5003e12c5d1SDavid du Colombier return 1; 5013e12c5d1SDavid du Colombier } 5023e12c5d1SDavid du Colombier char *names = 0; 5033e12c5d1SDavid du Colombier char *enames = 0; 5043e12c5d1SDavid du Colombier char *bstash = 0; 5053e12c5d1SDavid du Colombier char *estash = 0; 5063e12c5d1SDavid du Colombier unsigned size = 1024; 5073e12c5d1SDavid du Colombier char *nstash = 0; 5083e12c5d1SDavid du Colombier void define(char *a){ 5093e12c5d1SDavid du Colombier char *ap; 5103e12c5d1SDavid du Colombier short i, j; 5113e12c5d1SDavid du Colombier int curly = 0; 5123e12c5d1SDavid du Colombier ap = a; 5133e12c5d1SDavid du Colombier while(isalpha(*ap))ap++; 5143e12c5d1SDavid du Colombier if(ap == a){ 5153e12c5d1SDavid du Colombier fprint(2,"no name with define\n"); 5163e12c5d1SDavid du Colombier exits("define"); 5173e12c5d1SDavid du Colombier } 5183e12c5d1SDavid du Colombier i = ap - a; 5193e12c5d1SDavid du Colombier if(names+i+1 > enames){ 5203e12c5d1SDavid du Colombier names = malloc((unsigned)512); 5213e12c5d1SDavid du Colombier enames = names + 512; 5223e12c5d1SDavid du Colombier } 5233e12c5d1SDavid du Colombier fptr->name = names; 5243e12c5d1SDavid du Colombier strncpy(names, a,i); 5253e12c5d1SDavid du Colombier names += i; 5263e12c5d1SDavid du Colombier *names++ = '\0'; 5273e12c5d1SDavid du Colombier if(!bstash){ 5283e12c5d1SDavid du Colombier bstash = nstash = malloc(size); 5293e12c5d1SDavid du Colombier estash = bstash + size; 5303e12c5d1SDavid du Colombier } 5313e12c5d1SDavid du Colombier fptr->stash = nstash; 5323e12c5d1SDavid du Colombier while(*ap != '{') 5333e12c5d1SDavid du Colombier if(*ap == '\n'){ 5343e12c5d1SDavid du Colombier if((ap=Brdline(fsp->fd, '\n'))==0){ 5353e12c5d1SDavid du Colombier fprint(2,"unexpected end of file\n"); 5363e12c5d1SDavid du Colombier exits("eof"); 5373e12c5d1SDavid du Colombier } 5383e12c5d1SDavid du Colombier } 5393e12c5d1SDavid du Colombier else ap++; 5403e12c5d1SDavid du Colombier while((j=Bgetc(fsp->fd))!= Beof){ 5413e12c5d1SDavid du Colombier if(j == '{')curly++; 5423e12c5d1SDavid du Colombier else if(j == '}'){ 5433e12c5d1SDavid du Colombier if(curly == 0)break; 5443e12c5d1SDavid du Colombier else curly--; 5453e12c5d1SDavid du Colombier } 5463e12c5d1SDavid du Colombier *nstash++ = j; 5473e12c5d1SDavid du Colombier if(nstash == estash){ 5483e12c5d1SDavid du Colombier free(bstash); 5493e12c5d1SDavid du Colombier size += 1024; 5503e12c5d1SDavid du Colombier bstash = realloc(bstash,size); 5513e12c5d1SDavid du Colombier estash = bstash+size; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier } 5543e12c5d1SDavid du Colombier *nstash++ = '\0'; 5553e12c5d1SDavid du Colombier if(fptr++ >= &flibr[MAXL]){ 5563e12c5d1SDavid du Colombier fprint(2,"Too many objects\n"); 5573e12c5d1SDavid du Colombier exits("too many objects"); 5583e12c5d1SDavid du Colombier } 5593e12c5d1SDavid du Colombier } 5603e12c5d1SDavid du Colombier void call(char *a){ 5613e12c5d1SDavid du Colombier char *ap; 5623e12c5d1SDavid du Colombier struct fcall *f; 5633e12c5d1SDavid du Colombier char sav; 5643e12c5d1SDavid du Colombier double SC; 5653e12c5d1SDavid du Colombier ap = a; 5663e12c5d1SDavid du Colombier while(isalpha(*ap))ap++; 5673e12c5d1SDavid du Colombier sav = *ap; 5683e12c5d1SDavid du Colombier *ap = '\0'; 5693e12c5d1SDavid du Colombier for(f=flibr;f<fptr;f++){ 5703e12c5d1SDavid du Colombier if (!(strcmp(a, f->name))) 5713e12c5d1SDavid du Colombier break; 5723e12c5d1SDavid du Colombier } 5733e12c5d1SDavid du Colombier if(f == fptr){ 5743e12c5d1SDavid du Colombier fprint(2, "object %s not defined\n",a); 5753e12c5d1SDavid du Colombier exits("undefined"); 5763e12c5d1SDavid du Colombier } 5773e12c5d1SDavid du Colombier *ap = sav; 5783e12c5d1SDavid du Colombier while (isspace(*ap) || *ap == ',') 5793e12c5d1SDavid du Colombier ap++; 5803e12c5d1SDavid du Colombier if (*ap != '\0') 5813e12c5d1SDavid du Colombier SC = atof(ap); 5823e12c5d1SDavid du Colombier else SC = 1.; 5833e12c5d1SDavid du Colombier if(++fsp==&fstack[NFSTACK]){ 5843e12c5d1SDavid du Colombier fprint(2, "input stack overflow\n"); 5853e12c5d1SDavid du Colombier exits("blew stack"); 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier fsp->peekc=Beof; 5883e12c5d1SDavid du Colombier fsp->lineno=1; 5893e12c5d1SDavid du Colombier fsp->corebuf=f->stash; 5903e12c5d1SDavid du Colombier fsp->fd=0; 5913e12c5d1SDavid du Colombier fsp->scale=fsp[-1].scale*SC; 5923e12c5d1SDavid du Colombier } 5933e12c5d1SDavid du Colombier void include(char *a){ 5943e12c5d1SDavid du Colombier Biobuf *fd; 5953e12c5d1SDavid du Colombier fd=Bopen(a, OREAD); 5963e12c5d1SDavid du Colombier if(fd==0){ 5973e12c5d1SDavid du Colombier perror(a); 5983e12c5d1SDavid du Colombier exits("can't include"); 5993e12c5d1SDavid du Colombier } 6003e12c5d1SDavid du Colombier if(++fsp==&fstack[NFSTACK]){ 6013e12c5d1SDavid du Colombier fprint(2, "input stack overflow\n"); 6023e12c5d1SDavid du Colombier exits("blew stack"); 6033e12c5d1SDavid du Colombier } 6043e12c5d1SDavid du Colombier fsp->peekc=Beof; 6053e12c5d1SDavid du Colombier fsp->lineno=1; 6063e12c5d1SDavid du Colombier fsp->corebuf=0; 6073e12c5d1SDavid du Colombier fsp->fd=fd; 6083e12c5d1SDavid du Colombier } 609219b2ee8SDavid du Colombier /* 610219b2ee8SDavid du Colombier * Doesn't work. Why? 611219b2ee8SDavid du Colombier */ 612219b2ee8SDavid du Colombier int server(void){ 613219b2ee8SDavid du Colombier int fd, p[2]; 614219b2ee8SDavid du Colombier char buf[32]; 615219b2ee8SDavid du Colombier pipe(p); 616219b2ee8SDavid du Colombier fd = create("/srv/plot", 1, 0666); 617219b2ee8SDavid du Colombier sprint(buf, "%d", p[1]); 618219b2ee8SDavid du Colombier write(fd, buf, strlen(buf)); 619219b2ee8SDavid du Colombier close(fd); 620219b2ee8SDavid du Colombier close(p[1]); 621219b2ee8SDavid du Colombier return p[0]; 622219b2ee8SDavid du Colombier } 623