2004-05-15 23:24:00 +00:00
|
|
|
#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 *);
|
|
|
|
|
2004-05-16 07:56:41 +00:00
|
|
|
int
|
2004-05-15 23:24:00 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2004-05-16 07:56:41 +00:00
|
|
|
int
|
2004-05-15 23:24:00 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2004-05-16 07:56:41 +00:00
|
|
|
double
|
|
|
|
getcomp(obj *p, int t) /* return component of a position */
|
2004-05-15 23:24:00 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2004-05-16 07:56:41 +00:00
|
|
|
x1 = y1 = 0.0; /* Botch? (gcc) */
|
|
|
|
|
|
|
|
dprintf("whatpos %p %d %d\n", p, p->o_type, corner);
|
2004-05-15 23:24:00 +00:00
|
|
|
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);
|
|
|
|
}
|
2004-05-16 07:56:41 +00:00
|
|
|
ERROR "there is no %dth last", n WARNING;
|
2004-05-15 23:24:00 +00:00
|
|
|
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);
|
|
|
|
}
|
2004-05-16 07:56:41 +00:00
|
|
|
ERROR "there is no %dth ", n WARNING;
|
2004-05-15 23:24:00 +00:00
|
|
|
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;
|
|
|
|
}
|