123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "plot.h"
- #include <draw.h>
- #include <event.h>
- void define(char*);
- void call(char*);
- void include(char*);
- int process(Biobuf*);
- int server(void);
- enum{
- ARC,
- BOX,
- CALL,
- CFILL,
- CIRC,
- CLOSEPL,
- COLOR,
- CSPLINE,
- DEFINE,
- DISK,
- DSPLINE,
- ERASE,
- FILL,
- FRAME,
- FSPLINE,
- GRADE,
- IDLE,
- INCLUDE,
- LINE,
- LSPLINE,
- MOVE,
- OPENPL,
- PARABOLA,
- PEN,
- PAUSE,
- POINT,
- POLY,
- RANGE,
- RESTORE,
- RMOVE,
- RVEC,
- SAVE,
- SBOX,
- SPLINE,
- TEXT,
- VEC,
- LAST
- };
- struct pcall {
- char *cc;
- int numc;
- } plots[] = {
- [ARC] "a", 1,
- [BOX] "bo", 2,
- [CALL] "ca", 2,
- [CFILL] "cf", 2,
- [CIRC] "ci", 2,
- [CLOSEPL] "cl", 2,
- [COLOR] "co", 2,
- [CSPLINE] "cs", 2,
- [DEFINE] "de", 2,
- [DISK] "di", 2,
- [DSPLINE] "ds", 2,
- [ERASE] "e", 1,
- [FILL] "fi", 2,
- [FRAME] "fr", 2,
- [FSPLINE] "fs", 2,
- [GRADE] "g", 1,
- [IDLE] "id", 2,
- [INCLUDE] "in", 2,
- [LINE] "li", 2,
- [LSPLINE] "ls", 2,
- [MOVE] "m", 1,
- [OPENPL] "o", 1,
- [PARABOLA] "par", 3,
- [PEN] "pe", 2,
- [PAUSE] "pau", 3,
- [POINT] "poi", 3,
- [POLY] "pol", 3,
- [RANGE] "ra", 2,
- [RESTORE] "re", 2,
- [RMOVE] "rm", 2,
- [RVEC] "rv", 2,
- [SAVE] "sa", 2,
- [SBOX] "sb", 2,
- [SPLINE] "sp", 2,
- [TEXT] "t", 1,
- [VEC] "v", 1,
- [LAST] 0, 0,
- };
- struct pcall *pplots; /* last command read */
- #define MAXL 16
- struct fcall {
- char *name;
- char *stash;
- } flibr[MAXL]; /* define strings */
- struct fcall *fptr = flibr;
- #define NFSTACK 50
- struct fstack{
- int peekc;
- int lineno;
- char *corebuf;
- Biobuf *fd;
- double scale;
- }fstack[NFSTACK]; /* stack of open input files & defines */
- struct fstack *fsp=fstack;
- #define NARGSTR 8192
- char argstr[NARGSTR+1]; /* string arguments */
- #define NX 8192
- double x[NX]; /* numeric arguments */
- #define NPTS 256
- int cnt[NPTS]; /* control-polygon vertex counts */
- double *pts[NPTS]; /* control-polygon vertex pointers */
- void eresized(int new){
- if(new && getwindow(display, Refnone) < 0){
- fprint(2, "Can't reattach to window: %r\n");
- exits("resize");
- }
- }
- char *items[]={
- "exit",
- 0
- };
- Menu menu={items};
- void
- main(int arc, char *arv[]){
- char *ap;
- Biobuf *bp;
- int fd;
- int i;
- int dflag;
- char *oflag;
- Mouse m;
- bp = 0;
- fd = dup(0, -1); /* because openpl will close 0! */
- dflag=0;
- oflag="";
- for(i=1;i!=arc;i++) if(arv[i][0]=='-') switch(arv[i][1]){
- case 'd': dflag=1; break;
- case 'o': oflag=arv[i]+2; break;
- case 's': fd=server(); break;
- }
- openpl(oflag);
- if(dflag) doublebuffer();
- for (; arc > 1; arc--, arv++) {
- if (arv[1][0] == '-') {
- ap = arv[1];
- ap++;
- switch (*ap) {
- default:
- fprint(2, "%s not allowed as argument\n", ap);
- exits("usage");
- case 'T': break;
- case 'D': break;
- case 'd': break;
- case 'o': break;
- case 'W': break;
- case 's': break;
- case 'e': erase(); break;
- case 'C': closepl(); break;
- case 'w': ppause(); break;
- case 'c': color(ap+1); break;
- case 'f': cfill(ap+1); break;
- case 'p': pen(ap+1); break;
- case 'g': grade(atof(ap+1)); break;
- }
- }
- else if ((bp = Bopen(arv[1], OREAD)) == 0) {
- perror(arv[1]);
- fprint(2, "Cannot find file %s\n", arv[1]);
- }
- else if(process(bp)) Bterm(fsp->fd);
- else break;
- }
- if (bp == 0){
- bp = malloc(sizeof *bp);
- Binit(bp, fd, OREAD);
- process(bp);
- }
- closepl();
- for(;;){
- m=emouse();
- if(m.buttons&4 && emenuhit(3, &m, &menu)==0) exits(0);
- }
- }
- int isalpha(int c)
- {
- return ('a'<=c && c<='z') || ('A'<=c && c<='Z');
- }
- int isupper(int c)
- {
- return 'A'<=c && c<='Z';
- }
- int isdigit(int c)
- {
- return '0'<=c && c<='9';
- }
- int ispunct(int c)
- {
- return strchr("!\"#$%&'()*+,-./:;<=>?@[\]^_`{|}~", c)!=0;
- }
- int isspace(int c)
- {
- return strchr(" \t\n\v\f\r", c)!=0;
- }
- int nextc(void){
- int c;
- Rune r;
- for(;;){
- if(fsp->peekc!=Beof){
- c=fsp->peekc;
- fsp->peekc=Beof;
- return c;
- }
- if(fsp->fd)
- c=Bgetrune(fsp->fd);
- else if(*fsp->corebuf){
- fsp->corebuf+=chartorune(&r, fsp->corebuf);
- c=r;
- }else
- c=Beof;
- if(c!=Beof || fsp==fstack) break;
- if(fsp->fd) Bterm(fsp->fd);
- --fsp;
- }
- if(c=='\n') fsp->lineno++;
- return c;
- }
- /*
- * Read a string into argstr -- ignores leading spaces
- * and an optional leading quote-mark
- */
- void
- strarg(void){
- int c;
- Rune r;
- int quote=0;
- char *s=argstr;
- do
- c=nextc();
- while(c==' ' || c=='\t');
- if(c=='\'' || c=='"'){
- quote=c;
- c=nextc();
- }
- r = 0;
- while(c!='\n' && c!=Beof){
- r=c;
- s+=runetochar(s, &r);
- c=nextc();
- }
- if(quote && s!=argstr && r==quote) --s;
- *s='\0';
- }
- /*
- * Read a floating point number into argstr
- */
- numstring(void){
- int ndp=0;
- int ndig=0;
- char *s=argstr;
- int c=nextc();
- if(c=='+' || c=='-'){
- *s++=c;
- c=nextc();
- }
- while(isdigit(c) || c=='.'){
- if(s!=&argstr[NARGSTR]) *s++=c;
- if(c=='.') ndp++;
- else ndig++;
- c=nextc();
- }
- if(ndp>1 || ndig==0){
- fsp->peekc=c;
- return 0;
- }
- if(c=='e' || c=='E'){
- if(s!=&argstr[NARGSTR]) *s++=c;
- c=nextc();
- if(c=='+' || c=='-'){
- if(s!=&argstr[NARGSTR]) *s++=c;
- c=nextc();
- }
- if(!isdigit(c)){
- fsp->peekc=c;
- return 0;
- }
- while(isdigit(c)){
- if(s!=&argstr[NARGSTR]) *s++=c;
- c=nextc();
- }
- }
- fsp->peekc=c;
- *s='\0';
- return 1;
- }
- /*
- * Read n numeric arguments, storing them in
- * x[0], ..., x[n-1]
- */
- void
- numargs(int n){
- int i, c;
- for(i=0;i!=n;i++){
- do{
- c=nextc();
- }while(strchr(" \t\n", c) || c!='.' && c!='+' && c!='-' && ispunct(c));
- fsp->peekc=c;
- if(!numstring()){
- fprint(2, "line %d: number expected\n", fsp->lineno);
- exits("input error");
- }
- x[i]=atof(argstr)*fsp->scale;
- }
- }
- /*
- * Read a list of lists of control vertices, storing points in x[.],
- * pointers in pts[.] and counts in cnt[.]
- */
- void
- polyarg(void){
- int nleft, l, r, c;
- double **ptsp=pts, *xp=x;
- int *cntp=cnt;
- do{
- c=nextc();
- }while(c==' ' || c=='\t');
- if(c=='{'){
- l='{';
- r='}';
- }
- else{
- l=r='\n';
- fsp->peekc=c;
- }
- nleft=1;
- *cntp=0;
- *ptsp=xp;
- for(;;){
- c=nextc();
- if(c==r){
- if(*cntp){
- if(*cntp&1){
- fprint(2, "line %d: phase error\n",
- fsp->lineno);
- exits("bad input");
- }
- *cntp/=2;
- if(ptsp==&pts[NPTS]){
- fprint(2, "line %d: out of polygons\n",
- fsp->lineno);
- exits("exceeded limit");
- }
- *++ptsp=xp;
- *++cntp=0;
- }
- if(--nleft==0) return;
- }
- else switch(c){
- case Beof: return;
- case ' ': break;
- case '\t': break;
- case '\n': break;
- case '.': case '+': case '-':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- fsp->peekc=c;
- if(!numstring()){
- fprint(2, "line %d: expected number\n", fsp->lineno);
- exits("bad input");
- }
- if(xp==&x[NX]){
- fprint(2, "line %d: out of space\n", fsp->lineno);
- exits("exceeded limit");
- }
- *xp++=atof(argstr);
- ++*cntp;
- break;
- default:
- if(c==l) nleft++;
- else if(!ispunct(c)){
- fsp->peekc=c;
- return;
- }
- }
- }
- }
- process(Biobuf *fd){
- char *s;
- int c;
- fsp=fstack;
- fsp->fd=fd;
- fsp->corebuf=0;
- fsp->peekc=Beof;
- fsp->lineno=1;
- fsp->scale=1.;
- for(;;){
- do
- c=nextc();
- while(c==' ' || c=='\t');
- if(c==':'){
- do
- c=nextc();
- while(c!='\n' && c!=Beof);
- if(c==Beof) break;
- continue;
- }
- while(c=='.'){
- c=nextc();
- if(isdigit(c)){
- if(fsp->fd) Bungetc(fsp->fd);
- else --fsp->corebuf;
- c='.';
- break;
- }
- }
- if(c==Beof) break;
- if(c=='\n') continue;
- if(isalpha(c)){
- s=argstr;
- do{
- if(isupper(c)) c=tolower(c);
- if(s!=&argstr[NARGSTR]) *s++=c;
- c=nextc();
- }while(isalpha(c));
- fsp->peekc=c;
- *s='\0';
- for(pplots=plots;pplots->cc;pplots++)
- if(strncmp(argstr, pplots->cc, pplots->numc)==0)
- break;
- if(pplots->cc==0){
- fprint(2, "line %d, %s unknown\n", fsp->lineno,
- argstr);
- exits("bad command");
- }
- }
- else{
- fsp->peekc=c;
- }
- if(!pplots){
- fprint(2, "line %d, no command!\n", fsp->lineno);
- exits("no command");
- }
- switch(pplots-plots){
- case ARC: numargs(7); rarc(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break;
- case BOX: numargs(4); box(x[0], x[1], x[2], x[3]); break;
- case CALL: strarg(); call(argstr); pplots=0; break;
- case CFILL: strarg(); cfill(argstr); pplots=0; break;
- case CIRC: numargs(3); circ(x[0], x[1], x[2]); break;
- case CLOSEPL: strarg(); closepl(); pplots=0; break;
- case COLOR: strarg(); color(argstr); pplots=0; break;
- case CSPLINE: polyarg(); splin(4, cnt, pts); break;
- case DEFINE: strarg(); define(argstr); pplots=0; break;
- case DISK: numargs(3); plotdisc(x[0], x[1], x[2]); break;
- case DSPLINE: polyarg(); splin(3, cnt, pts); break;
- case ERASE: strarg(); erase(); pplots=0; break;
- case FILL: polyarg(); fill(cnt, pts); break;
- case FRAME: numargs(4); frame(x[0], x[1], x[2], x[3]); break;
- case FSPLINE: polyarg(); splin(1, cnt, pts); break;
- case GRADE: numargs(1); grade(x[0]); break;
- case IDLE: strarg(); idle(); pplots=0; break;
- case INCLUDE: strarg(); include(argstr); pplots=0; break;
- case LINE: numargs(4); plotline(x[0], x[1], x[2], x[3]); break;
- case LSPLINE: polyarg(); splin(2, cnt, pts); break;
- case MOVE: numargs(2); move(x[0], x[1]); break;
- case OPENPL: strarg(); openpl(argstr); pplots=0; break;
- case PARABOLA: numargs(6); parabola(x[0],x[1],x[2],x[3],x[4],x[5]); break;
- case PAUSE: strarg(); ppause(); pplots=0; break;
- case PEN: strarg(); pen(argstr); pplots=0; break;
- case POINT: numargs(2); dpoint(x[0], x[1]); break;
- case POLY: polyarg(); plotpoly(cnt, pts); break;
- case RANGE: numargs(4); range(x[0], x[1], x[2], x[3]); break;
- case RESTORE: strarg(); restore(); pplots=0; break;
- case RMOVE: numargs(2); rmove(x[0], x[1]); break;
- case RVEC: numargs(2); rvec(x[0], x[1]); break;
- case SAVE: strarg(); save(); pplots=0; break;
- case SBOX: numargs(4); sbox(x[0], x[1], x[2], x[3]); break;
- case SPLINE: polyarg(); splin(0, cnt, pts); break;
- case TEXT: strarg(); text(argstr); pplots=0; break;
- case VEC: numargs(2); vec(x[0], x[1]); break;
- default:
- fprint(2, "plot: missing case %ld\n", pplots-plots);
- exits("internal error");
- }
- }
- return 1;
- }
- char *names = 0;
- char *enames = 0;
- char *bstash = 0;
- char *estash = 0;
- unsigned size = 1024;
- char *nstash = 0;
- void define(char *a){
- char *ap;
- short i, j;
- int curly = 0;
- ap = a;
- while(isalpha(*ap))ap++;
- if(ap == a){
- fprint(2,"no name with define\n");
- exits("define");
- }
- i = ap - a;
- if(names+i+1 > enames){
- names = malloc((unsigned)512);
- enames = names + 512;
- }
- fptr->name = names;
- strncpy(names, a,i);
- names += i;
- *names++ = '\0';
- if(!bstash){
- bstash = nstash = malloc(size);
- estash = bstash + size;
- }
- fptr->stash = nstash;
- while(*ap != '{')
- if(*ap == '\n'){
- if((ap=Brdline(fsp->fd, '\n'))==0){
- fprint(2,"unexpected end of file\n");
- exits("eof");
- }
- }
- else ap++;
- while((j=Bgetc(fsp->fd))!= Beof){
- if(j == '{')curly++;
- else if(j == '}'){
- if(curly == 0)break;
- else curly--;
- }
- *nstash++ = j;
- if(nstash == estash){
- free(bstash);
- size += 1024;
- bstash = realloc(bstash,size);
- estash = bstash+size;
- }
- }
- *nstash++ = '\0';
- if(fptr++ >= &flibr[MAXL]){
- fprint(2,"Too many objects\n");
- exits("too many objects");
- }
- }
- void call(char *a){
- char *ap;
- struct fcall *f;
- char sav;
- double SC;
- ap = a;
- while(isalpha(*ap))ap++;
- sav = *ap;
- *ap = '\0';
- for(f=flibr;f<fptr;f++){
- if (!(strcmp(a, f->name)))
- break;
- }
- if(f == fptr){
- fprint(2, "object %s not defined\n",a);
- exits("undefined");
- }
- *ap = sav;
- while (isspace(*ap) || *ap == ',')
- ap++;
- if (*ap != '\0')
- SC = atof(ap);
- else SC = 1.;
- if(++fsp==&fstack[NFSTACK]){
- fprint(2, "input stack overflow\n");
- exits("blew stack");
- }
- fsp->peekc=Beof;
- fsp->lineno=1;
- fsp->corebuf=f->stash;
- fsp->fd=0;
- fsp->scale=fsp[-1].scale*SC;
- }
- void include(char *a){
- Biobuf *fd;
- fd=Bopen(a, OREAD);
- if(fd==0){
- perror(a);
- exits("can't include");
- }
- if(++fsp==&fstack[NFSTACK]){
- fprint(2, "input stack overflow\n");
- exits("blew stack");
- }
- fsp->peekc=Beof;
- fsp->lineno=1;
- fsp->corebuf=0;
- fsp->fd=fd;
- }
- /*
- * Doesn't work. Why?
- */
- int server(void){
- int fd, p[2];
- char buf[32];
- pipe(p);
- fd = create("/srv/plot", 1, 0666);
- sprint(buf, "%d", p[1]);
- write(fd, buf, strlen(buf));
- close(fd);
- close(p[1]);
- return p[0];
- }
|