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