123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "pic.h"
- #include "y.tab.h"
- int whatpos(obj *p, int corner, double *px, double *py);
- void makeattr(int type, int sub, YYSTYPE val);
- YYSTYPE getblk(obj *, char *);
- setdir(int n) /* set direction (hvmode) from LEFT, RIGHT, etc. */
- {
- switch (n) {
- case UP: hvmode = U_DIR; break;
- case DOWN: hvmode = D_DIR; break;
- case LEFT: hvmode = L_DIR; break;
- case RIGHT: hvmode = R_DIR; break;
- }
- return(hvmode);
- }
- curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */
- {
- switch (hvmode) {
- case R_DIR: return RIGHT;
- case L_DIR: return LEFT;
- case U_DIR: return UP;
- case D_DIR: return DOWN;
- }
- ERROR "can't happen curdir" FATAL;
- return 0;
- }
- double getcomp(obj *p, int t) /* return component of a position */
- {
- switch (t) {
- case DOTX:
- return p->o_x;
- case DOTY:
- return p->o_y;
- case DOTWID:
- switch (p->o_type) {
- case BOX:
- case BLOCK:
- case TEXT:
- return p->o_val[0];
- case CIRCLE:
- case ELLIPSE:
- return 2 * p->o_val[0];
- case LINE:
- case ARROW:
- return p->o_val[0] - p->o_x;
- case PLACE:
- return 0;
- }
- case DOTHT:
- switch (p->o_type) {
- case BOX:
- case BLOCK:
- case TEXT:
- return p->o_val[1];
- case CIRCLE:
- case ELLIPSE:
- return 2 * p->o_val[1];
- case LINE:
- case ARROW:
- return p->o_val[1] - p->o_y;
- case PLACE:
- return 0;
- }
- case DOTRAD:
- switch (p->o_type) {
- case CIRCLE:
- case ELLIPSE:
- return p->o_val[0];
- }
- }
- ERROR "you asked for a weird dimension or position" WARNING;
- return 0;
- }
- double exprlist[100];
- int nexpr = 0;
- void exprsave(double f)
- {
- exprlist[nexpr++] = f;
- }
- char *sprintgen(char *fmt)
- {
- char buf[1000];
- sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
- nexpr = 0;
- free(fmt);
- return tostring(buf);
- }
- void makefattr(int type, int sub, double f) /* double attr */
- {
- YYSTYPE val;
- val.f = f;
- makeattr(type, sub, val);
- }
- void makeoattr(int type, obj *o) /* obj* attr */
- {
- YYSTYPE val;
- val.o = o;
- makeattr(type, 0, val);
- }
- void makeiattr(int type, int i) /* int attr */
- {
- YYSTYPE val;
- val.i = i;
- makeattr(type, 0, val);
- }
- void maketattr(int sub, char *p) /* text attribute: takes two */
- {
- YYSTYPE val;
- val.p = p;
- makeattr(TEXTATTR, sub, val);
- }
- void addtattr(int sub) /* add text attrib to existing item */
- {
- attr[nattr-1].a_sub |= sub;
- }
- void makevattr(char *p) /* varname attribute */
- {
- YYSTYPE val;
- val.p = p;
- makeattr(VARNAME, 0, val);
- }
- void makeattr(int type, int sub, YYSTYPE val) /* add attribute type and val */
- {
- if (type == 0 && val.i == 0) { /* clear table for next stat */
- nattr = 0;
- return;
- }
- if (nattr >= nattrlist)
- attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
- dprintf("attr %d: %d %d %d\n", nattr, type, sub, val.i);
- attr[nattr].a_type = type;
- attr[nattr].a_sub = sub;
- attr[nattr].a_val = val;
- nattr++;
- }
- void printexpr(double f) /* print expression for debugging */
- {
- printf("%g\n", f);
- }
- void printpos(obj *p) /* print position for debugging */
- {
- printf("%g, %g\n", p->o_x, p->o_y);
- }
- char *tostring(char *s)
- {
- register char *p;
- p = malloc(strlen(s)+1);
- if (p == NULL)
- ERROR "out of space in tostring on %s", s FATAL;
- strcpy(p, s);
- return(p);
- }
- obj *makepos(double x, double y) /* make a position cell */
- {
- obj *p;
- p = makenode(PLACE, 0);
- p->o_x = x;
- p->o_y = y;
- return(p);
- }
- obj *makebetween(double f, obj *p1, obj *p2) /* make position between p1 and p2 */
- {
- obj *p;
- dprintf("fraction = %.2f\n", f);
- p = makenode(PLACE, 0);
- p->o_x = p1->o_x + f * (p2->o_x - p1->o_x);
- p->o_y = p1->o_y + f * (p2->o_y - p1->o_y);
- return(p);
- }
- obj *getpos(obj *p, int corner) /* find position of point */
- {
- double x, y;
- whatpos(p, corner, &x, &y);
- return makepos(x, y);
- }
- int whatpos(obj *p, int corner, double *px, double *py) /* what is the position (no side effect) */
- {
- double x, y, x1, y1;
- if (p == NULL)
- ERROR "null object" FATAL;
- dprintf("whatpos %o %d %d\n", p, p->o_type, corner);
- x = p->o_x;
- y = p->o_y;
- if (p->o_type != PLACE && p->o_type != MOVE) {
- x1 = p->o_val[0];
- y1 = p->o_val[1];
- }
- switch (p->o_type) {
- case PLACE:
- break;
- case BOX:
- case BLOCK:
- case TEXT:
- switch (corner) {
- case NORTH: y += y1 / 2; break;
- case SOUTH: y -= y1 / 2; break;
- case EAST: x += x1 / 2; break;
- case WEST: x -= x1 / 2; break;
- case NE: x += x1 / 2; y += y1 / 2; break;
- case SW: x -= x1 / 2; y -= y1 / 2; break;
- case SE: x += x1 / 2; y -= y1 / 2; break;
- case NW: x -= x1 / 2; y += y1 / 2; break;
- case START:
- if (p->o_type == BLOCK)
- return whatpos(objlist[(int)p->o_val[2]], START, px, py);
- case END:
- if (p->o_type == BLOCK)
- return whatpos(objlist[(int)p->o_val[3]], END, px, py);
- }
- break;
- case ARC:
- switch (corner) {
- case START:
- if (p->o_attr & CW_ARC) {
- x = p->o_val[2]; y = p->o_val[3];
- } else {
- x = x1; y = y1;
- }
- break;
- case END:
- if (p->o_attr & CW_ARC) {
- x = x1; y = y1;
- } else {
- x = p->o_val[2]; y = p->o_val[3];
- }
- break;
- }
- if (corner == START || corner == END)
- break;
- x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
- /* Fall Through! */
- case CIRCLE:
- case ELLIPSE:
- switch (corner) {
- case NORTH: y += y1; break;
- case SOUTH: y -= y1; break;
- case EAST: x += x1; break;
- case WEST: x -= x1; break;
- case NE: x += 0.707 * x1; y += 0.707 * y1; break;
- case SE: x += 0.707 * x1; y -= 0.707 * y1; break;
- case NW: x -= 0.707 * x1; y += 0.707 * y1; break;
- case SW: x -= 0.707 * x1; y -= 0.707 * y1; break;
- }
- break;
- case LINE:
- case SPLINE:
- case ARROW:
- switch (corner) {
- case START: break; /* already in place */
- case END: x = x1; y = y1; break;
- default: /* change! */
- case CENTER: x = (x+x1)/2; y = (y+y1)/2; break;
- case NORTH: if (y1 > y) { x = x1; y = y1; } break;
- case SOUTH: if (y1 < y) { x = x1; y = y1; } break;
- case EAST: if (x1 > x) { x = x1; y = y1; } break;
- case WEST: if (x1 < x) { x = x1; y = y1; } break;
- }
- break;
- case MOVE:
- /* really ought to be same as line... */
- break;
- }
- dprintf("whatpos returns %g %g\n", x, y);
- *px = x;
- *py = y;
- return 1;
- }
- obj *gethere(void) /* make a place for curx,cury */
- {
- dprintf("gethere %g %g\n", curx, cury);
- return(makepos(curx, cury));
- }
- obj *getlast(int n, int t) /* find n-th previous occurrence of type t */
- {
- int i, k;
- obj *p;
- k = n;
- for (i = nobj-1; i >= 0; i--) {
- p = objlist[i];
- if (p->o_type == BLOCKEND) {
- i = p->o_val[4];
- continue;
- }
- if (p->o_type != t)
- continue;
- if (--k > 0)
- continue; /* not there yet */
- dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
- return(p);
- }
- ERROR "there is no %dth last", n FATAL;
- return(NULL);
- }
- obj *getfirst(int n, int t) /* find n-th occurrence of type t */
- {
- int i, k;
- obj *p;
- k = n;
- for (i = 0; i < nobj; i++) {
- p = objlist[i];
- if (p->o_type == BLOCK && t != BLOCK) { /* skip whole block */
- i = p->o_val[5] + 1;
- continue;
- }
- if (p->o_type != t)
- continue;
- if (--k > 0)
- continue; /* not there yet */
- dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
- return(p);
- }
- ERROR "there is no %dth ", n FATAL;
- return(NULL);
- }
- double getblkvar(obj *p, char *s) /* find variable s2 in block p */
- {
- YYSTYPE y;
- y = getblk(p, s);
- return y.f;
- }
- obj *getblock(obj *p, char *s) /* find variable s in block p */
- {
- YYSTYPE y;
- y = getblk(p, s);
- return y.o;
- }
- YYSTYPE getblk(obj *p, char *s) /* find union type for s in p */
- {
- static YYSTYPE bug;
- struct symtab *stp;
- if (p->o_type != BLOCK) {
- ERROR ".%s is not in that block", s WARNING;
- return(bug);
- }
- for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
- if (strcmp(s, stp->s_name) == 0) {
- dprintf("getblk %s found x,y= %g,%g\n",
- s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
- return(stp->s_val);
- }
- ERROR "there is no .%s in that []", s WARNING;
- return(bug);
- }
- obj *fixpos(obj *p, double x, double y)
- {
- dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
- return makepos(p->o_x + x, p->o_y + y);
- }
- obj *addpos(obj *p, obj *q)
- {
- dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
- return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
- }
- obj *subpos(obj *p, obj *q)
- {
- dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
- return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
- }
- obj *makenode(int type, int n)
- {
- obj *p;
- p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
- if (p == NULL)
- ERROR "out of space in makenode" FATAL;
- p->o_type = type;
- p->o_count = n;
- p->o_nobj = nobj;
- p->o_mode = hvmode;
- p->o_x = curx;
- p->o_y = cury;
- p->o_nt1 = ntext1;
- p->o_nt2 = ntext;
- ntext1 = ntext; /* ready for next caller */
- if (nobj >= nobjlist)
- objlist = (obj **) grow((char *) objlist, "objlist",
- nobjlist *= 2, sizeof(obj *));
- objlist[nobj++] = p;
- return(p);
- }
- void extreme(double x, double y) /* record max and min x and y values */
- {
- if (x > xmax)
- xmax = x;
- if (y > ymax)
- ymax = y;
- if (x < xmin)
- xmin = x;
- if (y < ymin)
- ymin = y;
- }
|