6 typedef struct Symbol Symbol;
7 typedef struct Event Event;
8 typedef struct Signal Signal;
29 int lineno, lastc, peeked;
32 double width, rheight;
38 Signal *sigfirst, **siglast = &sigfirst;
66 n = va_arg(f->args, int);
67 if(n >= 0 && n < 0x80 && isprint(n))
68 return fmtprint(f, "'%c'", n);
71 case CMD: return fmtprint(f, ".%s", sname);
72 case SYM: return fmtprint(f, "'%s'", sname);
73 case NUM: return fmtprint(f, "%g", sval);
74 case EOF: return fmtprint(f, "EOF");
75 case STR: return fmtprint(f, "%#q", sname);
76 default: return fmtprint(f, "%d", n);
87 sysfatal("malloc: %r");
89 setmalloctag(v, getcallerpc(&n));
94 error(int l, char *fmt, ...)
100 s = vsmprint(fmt, va);
101 fprint(2, "%d %s\n", l, s);
111 for(c = 0; *s != 0; s++)
121 for(p = &stab[hash(st)%nelem(stab)]; s = *p, s != nil; p = &s->next){
122 if(strcmp(s->name, st) == 0)
125 s = emalloc(sizeof(Symbol));
126 s->name = strdup(st);
134 return isalnum(c) || c == '_' || c >= 0x80;
138 numfsm(int c, int *st)
153 return isdigit(c) || c == '.' || c == 'e';
157 return isdigit(c) || c == 'e';
160 return isdigit(c) || c == '+' || c == '-';
185 if(lastc == 10 && c == '.'){
186 for(p = sname; c = Bgetc(bp), issym(c); )
187 if(p < sname + sizeof(sname) - 1)
193 if(isdigit(c) || c == '.'){
195 for(p = sname; numfsm(c, &st); c = Bgetc(bp))
196 if(p < sname + sizeof(sname) - 1)
200 sval = strtol(sname, &p, 0);
202 sval = strtod(sname, &p);
204 error(lineno, "invalid number %s", sname);
208 for(p = sname; issym(c); c = Bgetc(bp))
209 if(p < sname + sizeof(sname) - 1)
216 for(p = sname; c = Bgetc(bp), c != '\'' || Bgetc(bp) == '\''; )
217 if(p < sname + sizeof(sname) - 1)
252 if((s = peek()) != n)
253 error(lineno, "expected %T, got %T", n, s);
258 static double expr(void);
273 error(lineno, "not a number: %s", s->name);
280 error(lineno, "factor: unexpected %T", t);
291 while(peek() == '*' || peek() == '/'){
293 case '*': g *= factor(); break;
294 case '/': g /= factor(); break;
307 if(peek() == '+' || peek() == '-')
308 s = next() == '-' ? -1 : 1;
310 while(peek() == '+' || peek() == '-'){
311 s = next() == '-' ? -1 : 1;
322 error(lineno, "symbol already exists: %s", s->name);
337 if(strcmp(sname, "x") == 0)
339 if(strcmp(sname, "z") == 0)
341 e->data = strdup(sname);
348 e->data = smprint("%g", sval);
351 e->data = strdup(sname);
354 error(lineno, "unexpected %T", t);
360 append(double off, Event ***ep, Event *e)
364 for(; e != nil; e = e->next){
365 f = emalloc(sizeof(Event));
370 f->data = strdup(e->data);
381 for(; e != nil; e = en){
389 events(double *off, int ronly)
414 e = emalloc(sizeof(Event));
416 e->val = parseval(e);
430 if(f < 0 || isNaN(f) || f >= 0x7fffffff){
431 error(lineno, "invalid repeat count");
438 for(i = 0; i < n; i++){
439 append(*off, &ep, e);
442 if(*off > maxt) maxt = *off;
447 error(lineno, "only relative addressing allowed");
454 error(lineno, "undefined %s", sy->name);
465 if(sy->t != SYMFREE && sy->t != SYMNUM)
466 error(lineno, "already defined %s", sy->name);
473 if(*off < mint) mint = *off;
474 if(*off > maxt) maxt = *off;
487 s = emalloc(sizeof(Signal));
488 s->name = strdup(st);
489 s->ev = events(&off, 0);
497 slantfill(double x1, double x2, double t, double b, double tw)
503 for(x = x1; x < x2 - sw; x += soff)
504 print("line from %g,%g to %g,%g\n", x, t, x+sw, b);
506 print("line from %g,%g to %g,%g\n", x, t, (2*sw*tw+2*tw*x+sw*x2)/(sw+2*tw), (sw*t+t*(x-x2)+b*(2*tw-x+x2))/(sw+2*tw));
510 sigout(Signal *s, double top)
513 double l, w, t, b, x1, x2, tw, m;
515 for(e = s->ev; e != nil && e->next != nil && e->next->t < left; e = e->next)
519 b = top - rheight * 0.75;
520 t = top - rheight * 0.25;
524 w = width * 0.8 / (right - left);
526 print("\"%s\" ljust at %g,%g\n", s->name, width * 0.1, m);
527 while(n = e->next, n != nil && n->t < right){
528 x2 = (n->t - left) * w + l;
530 print("line from %g,%g to %g,%g dashed\n", x2, 0.0, x2, nsig*rheight);
533 print("line from %g,%g to %g,%g\n", x1, m, x2, m);
536 print("line from %g,%g to %g,%g\n", x1, b, x2-tw, b);
537 print("line from %g,%g to %g,%g\n", x2-tw, b, x2, m);
540 print("line from %g,%g to %g,%g\n", x1, t, x2-tw, t);
541 print("line from %g,%g to %g,%g\n", x2-tw, t, x2, m);
544 print("\"%s\" at %g,%g\n", e->data, (x1+x2)/2, m);
547 slantfill(x1, x2-tw, t, b, tw);
549 print("line from %g,%g to %g,%g\n", x1, b, x2-tw, b);
550 print("line from %g,%g to %g,%g\n", x2-tw, b, x2, m);
551 print("line from %g,%g to %g,%g\n", x1, t, x2-tw, t);
552 print("line from %g,%g to %g,%g\n", x2-tw, t, x2, m);
555 fprint(2, "unknown event type %d\n", e->val);
559 print("line from %g,%g to %g,%g\n", x2, m, x2+tw, b);
562 print("line from %g,%g to %g,%g\n", x2, m, x2+tw, t);
566 print("line from %g,%g to %g,%g\n", x2, m, x2+tw, b);
567 print("line from %g,%g to %g,%g\n", x2, m, x2+tw, t);
576 x2 = (right - left) * w + l;
579 print("line from %g,%g to %g,%g\n", x1, m, x2, m);
582 print("line from %g,%g to %g,%g\n", x1, b, x2, b);
585 print("line from %g,%g to %g,%g\n", x1, t, x2, t);
588 print("\"%s\" at %g,%g\n", e->data, (x1+x2)/2, m);
591 slantfill(x1, x2, t, b, tw);
593 print("line from %g,%g to %g,%g\n", x1, b, x2, b);
594 print("line from %g,%g to %g,%g\n", x1, t, x2, t);
597 fprint(2, "unknown event type %d\n", e->val);
607 rc = tokenize(l, f, nelem(f));
609 error(lineno, ".TPS wrong syntax");
612 width = strtod(f[1], 0);
613 rheight = strtod(f[2], 0);
623 for(p = stab; p < stab + nelem(stab); p++)
624 for(s = *p, *p = nil; s != nil; s = sn){
630 memset(stab, 0, sizeof(stab));
632 for(si = sigfirst; si != nil; si = sin){
633 for(e = si->ev; e != nil; e = en){
671 if(strcmp(sname, "TPE") == 0)
673 error(lineno, "unknown command %s", sname);
676 error(lineno, "unexpected %T", t);
681 print(".PS %g %g\n", width, rheight * nsig);
684 top = rheight * nsig;
685 for(si = sigfirst; si != nil; si = si->next, top -= rheight)
698 bp = Bfdopen(0, OREAD);
700 bp = Bopen(f, OREAD);
702 sysfatal("open: %r");
707 l = Brdstr(bp, '\n', 1);
711 if(strncmp(l, ".TPS", 4) == 0 && (!l[4] || isspace(l[4])))
723 fprint(2, "usage: %s [ files ]\n", argv0);
728 main(int argc, char **argv)
732 fmtinstall('T', Tfmt);
742 for(i = 0; i < argc; i++)