xref: /plan9/sys/src/cmd/pic/misc.c (revision 392dc26962a4986819d746514f28dfe13b47a3d3)
13e12c5d1SDavid du Colombier #include <stdio.h>
23e12c5d1SDavid du Colombier #include <string.h>
33e12c5d1SDavid du Colombier #include <stdlib.h>
43e12c5d1SDavid du Colombier #include <math.h>
53e12c5d1SDavid du Colombier #include "pic.h"
63e12c5d1SDavid du Colombier #include "y.tab.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier int whatpos(obj *p, int corner, double *px, double *py);
93e12c5d1SDavid du Colombier void makeattr(int type, int sub, YYSTYPE val);
103e12c5d1SDavid du Colombier YYSTYPE getblk(obj *, char *);
113e12c5d1SDavid du Colombier 
setdir(int n)123e12c5d1SDavid du Colombier setdir(int n)	/* set direction (hvmode) from LEFT, RIGHT, etc. */
133e12c5d1SDavid du Colombier {
143e12c5d1SDavid du Colombier 	switch (n) {
153e12c5d1SDavid du Colombier 	case UP:	hvmode = U_DIR; break;
163e12c5d1SDavid du Colombier 	case DOWN:	hvmode = D_DIR; break;
173e12c5d1SDavid du Colombier 	case LEFT:	hvmode = L_DIR; break;
183e12c5d1SDavid du Colombier 	case RIGHT:	hvmode = R_DIR; break;
193e12c5d1SDavid du Colombier 	}
203e12c5d1SDavid du Colombier  	return(hvmode);
213e12c5d1SDavid du Colombier }
223e12c5d1SDavid du Colombier 
curdir(void)233e12c5d1SDavid du Colombier curdir(void)	/* convert current dir (hvmode) to RIGHT, LEFT, etc. */
243e12c5d1SDavid du Colombier {
253e12c5d1SDavid du Colombier 	switch (hvmode) {
263e12c5d1SDavid du Colombier 	case R_DIR:	return RIGHT;
273e12c5d1SDavid du Colombier 	case L_DIR:	return LEFT;
283e12c5d1SDavid du Colombier 	case U_DIR:	return UP;
293e12c5d1SDavid du Colombier 	case D_DIR:	return DOWN;
303e12c5d1SDavid du Colombier 	}
313e12c5d1SDavid du Colombier 	ERROR "can't happen curdir" FATAL;
323e12c5d1SDavid du Colombier 	return 0;
333e12c5d1SDavid du Colombier }
343e12c5d1SDavid du Colombier 
getcomp(obj * p,int t)353e12c5d1SDavid du Colombier double getcomp(obj *p, int t)	/* return component of a position */
363e12c5d1SDavid du Colombier {
373e12c5d1SDavid du Colombier 	switch (t) {
383e12c5d1SDavid du Colombier 	case DOTX:
393e12c5d1SDavid du Colombier 		return p->o_x;
403e12c5d1SDavid du Colombier 	case DOTY:
413e12c5d1SDavid du Colombier 		return p->o_y;
423e12c5d1SDavid du Colombier 	case DOTWID:
433e12c5d1SDavid du Colombier 		switch (p->o_type) {
443e12c5d1SDavid du Colombier 		case BOX:
453e12c5d1SDavid du Colombier 		case BLOCK:
463e12c5d1SDavid du Colombier 		case TEXT:
473e12c5d1SDavid du Colombier 			return p->o_val[0];
483e12c5d1SDavid du Colombier 		case CIRCLE:
493e12c5d1SDavid du Colombier 		case ELLIPSE:
503e12c5d1SDavid du Colombier 			return 2 * p->o_val[0];
513e12c5d1SDavid du Colombier 		case LINE:
523e12c5d1SDavid du Colombier 		case ARROW:
533e12c5d1SDavid du Colombier 			return p->o_val[0] - p->o_x;
543e12c5d1SDavid du Colombier 		case PLACE:
553e12c5d1SDavid du Colombier 			return 0;
563e12c5d1SDavid du Colombier 		}
573e12c5d1SDavid du Colombier 	case DOTHT:
583e12c5d1SDavid du Colombier 		switch (p->o_type) {
593e12c5d1SDavid du Colombier 		case BOX:
603e12c5d1SDavid du Colombier 		case BLOCK:
613e12c5d1SDavid du Colombier 		case TEXT:
623e12c5d1SDavid du Colombier 			return p->o_val[1];
633e12c5d1SDavid du Colombier 		case CIRCLE:
643e12c5d1SDavid du Colombier 		case ELLIPSE:
653e12c5d1SDavid du Colombier 			return 2 * p->o_val[1];
663e12c5d1SDavid du Colombier 		case LINE:
673e12c5d1SDavid du Colombier 		case ARROW:
683e12c5d1SDavid du Colombier 			return p->o_val[1] - p->o_y;
693e12c5d1SDavid du Colombier 		case PLACE:
703e12c5d1SDavid du Colombier 			return 0;
713e12c5d1SDavid du Colombier 		}
723e12c5d1SDavid du Colombier 	case DOTRAD:
733e12c5d1SDavid du Colombier 		switch (p->o_type) {
743e12c5d1SDavid du Colombier 		case CIRCLE:
753e12c5d1SDavid du Colombier 		case ELLIPSE:
763e12c5d1SDavid du Colombier 			return p->o_val[0];
773e12c5d1SDavid du Colombier 		}
783e12c5d1SDavid du Colombier 	}
793e12c5d1SDavid du Colombier 	ERROR "you asked for a weird dimension or position" WARNING;
803e12c5d1SDavid du Colombier 	return 0;
813e12c5d1SDavid du Colombier }
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier double	exprlist[100];
843e12c5d1SDavid du Colombier int	nexpr	= 0;
853e12c5d1SDavid du Colombier 
exprsave(double f)863e12c5d1SDavid du Colombier void exprsave(double f)
873e12c5d1SDavid du Colombier {
883e12c5d1SDavid du Colombier 	exprlist[nexpr++] = f;
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier 
sprintgen(char * fmt)913e12c5d1SDavid du Colombier char *sprintgen(char *fmt)
923e12c5d1SDavid du Colombier {
933e12c5d1SDavid du Colombier 	char buf[1000];
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
963e12c5d1SDavid du Colombier 	nexpr = 0;
973e12c5d1SDavid du Colombier 	free(fmt);
983e12c5d1SDavid du Colombier 	return tostring(buf);
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier 
makefattr(int type,int sub,double f)1013e12c5d1SDavid du Colombier void makefattr(int type, int sub, double f)	/* double attr */
1023e12c5d1SDavid du Colombier {
1033e12c5d1SDavid du Colombier 	YYSTYPE val;
1043e12c5d1SDavid du Colombier 	val.f = f;
1053e12c5d1SDavid du Colombier 	makeattr(type, sub, val);
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier 
makeoattr(int type,obj * o)1083e12c5d1SDavid du Colombier void makeoattr(int type, obj *o)	/* obj* attr */
1093e12c5d1SDavid du Colombier {
1103e12c5d1SDavid du Colombier 	YYSTYPE val;
1113e12c5d1SDavid du Colombier 	val.o = o;
1123e12c5d1SDavid du Colombier 	makeattr(type, 0, val);
1133e12c5d1SDavid du Colombier }
1143e12c5d1SDavid du Colombier 
makeiattr(int type,int i)1153e12c5d1SDavid du Colombier void makeiattr(int type, int i)	/* int attr */
1163e12c5d1SDavid du Colombier {
1173e12c5d1SDavid du Colombier 	YYSTYPE val;
1183e12c5d1SDavid du Colombier 	val.i = i;
1193e12c5d1SDavid du Colombier 	makeattr(type, 0, val);
1203e12c5d1SDavid du Colombier }
1213e12c5d1SDavid du Colombier 
maketattr(int sub,char * p)1223e12c5d1SDavid du Colombier void maketattr(int sub, char *p)	/* text attribute: takes two */
1233e12c5d1SDavid du Colombier {
1243e12c5d1SDavid du Colombier 	YYSTYPE val;
1253e12c5d1SDavid du Colombier 	val.p = p;
1263e12c5d1SDavid du Colombier 	makeattr(TEXTATTR, sub, val);
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier 
addtattr(int sub)1293e12c5d1SDavid du Colombier void addtattr(int sub)		/* add text attrib to existing item */
1303e12c5d1SDavid du Colombier {
1313e12c5d1SDavid du Colombier 	attr[nattr-1].a_sub |= sub;
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier 
makevattr(char * p)1343e12c5d1SDavid du Colombier void makevattr(char *p)	/* varname attribute */
1353e12c5d1SDavid du Colombier {
1363e12c5d1SDavid du Colombier 	YYSTYPE val;
1373e12c5d1SDavid du Colombier 	val.p = p;
1383e12c5d1SDavid du Colombier 	makeattr(VARNAME, 0, val);
1393e12c5d1SDavid du Colombier }
1403e12c5d1SDavid du Colombier 
makeattr(int type,int sub,YYSTYPE val)1413e12c5d1SDavid du Colombier void makeattr(int type, int sub, YYSTYPE val)	/* add attribute type and val */
1423e12c5d1SDavid du Colombier {
1433e12c5d1SDavid du Colombier 	if (type == 0 && val.i == 0) {	/* clear table for next stat */
1443e12c5d1SDavid du Colombier 		nattr = 0;
1453e12c5d1SDavid du Colombier 		return;
1463e12c5d1SDavid du Colombier 	}
1473e12c5d1SDavid du Colombier 	if (nattr >= nattrlist)
1483e12c5d1SDavid du Colombier 		attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
1493e12c5d1SDavid du Colombier 	dprintf("attr %d:  %d %d %d\n", nattr, type, sub, val.i);
1503e12c5d1SDavid du Colombier 	attr[nattr].a_type = type;
1513e12c5d1SDavid du Colombier 	attr[nattr].a_sub = sub;
1523e12c5d1SDavid du Colombier 	attr[nattr].a_val = val;
1533e12c5d1SDavid du Colombier 	nattr++;
1543e12c5d1SDavid du Colombier }
1553e12c5d1SDavid du Colombier 
printexpr(double f)1563e12c5d1SDavid du Colombier void printexpr(double f)	/* print expression for debugging */
1573e12c5d1SDavid du Colombier {
1583e12c5d1SDavid du Colombier 	printf("%g\n", f);
1593e12c5d1SDavid du Colombier }
1603e12c5d1SDavid du Colombier 
printpos(obj * p)1613e12c5d1SDavid du Colombier void printpos(obj *p)	/* print position for debugging */
1623e12c5d1SDavid du Colombier {
1633e12c5d1SDavid du Colombier 	printf("%g, %g\n", p->o_x, p->o_y);
1643e12c5d1SDavid du Colombier }
1653e12c5d1SDavid du Colombier 
tostring(char * s)1663e12c5d1SDavid du Colombier char *tostring(char *s)
1673e12c5d1SDavid du Colombier {
1683e12c5d1SDavid du Colombier 	register char *p;
1693e12c5d1SDavid du Colombier 
1703e12c5d1SDavid du Colombier 	p = malloc(strlen(s)+1);
1713e12c5d1SDavid du Colombier 	if (p == NULL)
1723e12c5d1SDavid du Colombier 		ERROR "out of space in tostring on %s", s FATAL;
1733e12c5d1SDavid du Colombier 	strcpy(p, s);
1743e12c5d1SDavid du Colombier 	return(p);
1753e12c5d1SDavid du Colombier }
1763e12c5d1SDavid du Colombier 
makepos(double x,double y)1773e12c5d1SDavid du Colombier obj *makepos(double x, double y)	/* make a position cell */
1783e12c5d1SDavid du Colombier {
1793e12c5d1SDavid du Colombier 	obj *p;
1803e12c5d1SDavid du Colombier 
1813e12c5d1SDavid du Colombier 	p = makenode(PLACE, 0);
1823e12c5d1SDavid du Colombier 	p->o_x = x;
1833e12c5d1SDavid du Colombier 	p->o_y = y;
1843e12c5d1SDavid du Colombier 	return(p);
1853e12c5d1SDavid du Colombier }
1863e12c5d1SDavid du Colombier 
makebetween(double f,obj * p1,obj * p2)1873e12c5d1SDavid du Colombier obj *makebetween(double f, obj *p1, obj *p2)	/* make position between p1 and p2 */
1883e12c5d1SDavid du Colombier {
1893e12c5d1SDavid du Colombier 	obj *p;
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier 	dprintf("fraction = %.2f\n", f);
1923e12c5d1SDavid du Colombier 	p = makenode(PLACE, 0);
1933e12c5d1SDavid du Colombier 	p->o_x = p1->o_x + f * (p2->o_x - p1->o_x);
1943e12c5d1SDavid du Colombier 	p->o_y = p1->o_y + f * (p2->o_y - p1->o_y);
1953e12c5d1SDavid du Colombier 	return(p);
1963e12c5d1SDavid du Colombier }
1973e12c5d1SDavid du Colombier 
getpos(obj * p,int corner)1983e12c5d1SDavid du Colombier obj *getpos(obj *p, int corner)	/* find position of point */
1993e12c5d1SDavid du Colombier {
2003e12c5d1SDavid du Colombier 	double x, y;
2013e12c5d1SDavid du Colombier 
2023e12c5d1SDavid du Colombier 	whatpos(p, corner, &x, &y);
2033e12c5d1SDavid du Colombier 	return makepos(x, y);
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier 
whatpos(obj * p,int corner,double * px,double * py)2063e12c5d1SDavid du Colombier int whatpos(obj *p, int corner, double *px, double *py)	/* what is the position (no side effect) */
2073e12c5d1SDavid du Colombier {
2083e12c5d1SDavid du Colombier 	double x, y, x1, y1;
2093e12c5d1SDavid du Colombier 
210*392dc269SDavid du Colombier 	if (p == NULL)
211*392dc269SDavid du Colombier 		ERROR "null object" FATAL;
2123e12c5d1SDavid du Colombier 	dprintf("whatpos %o %d %d\n", p, p->o_type, corner);
2133e12c5d1SDavid du Colombier 	x = p->o_x;
2143e12c5d1SDavid du Colombier 	y = p->o_y;
2153e12c5d1SDavid du Colombier 	if (p->o_type != PLACE && p->o_type != MOVE) {
2163e12c5d1SDavid du Colombier 		x1 = p->o_val[0];
2173e12c5d1SDavid du Colombier 		y1 = p->o_val[1];
2183e12c5d1SDavid du Colombier 	}
2193e12c5d1SDavid du Colombier 	switch (p->o_type) {
2203e12c5d1SDavid du Colombier 	case PLACE:
2213e12c5d1SDavid du Colombier 		break;
2223e12c5d1SDavid du Colombier 	case BOX:
2233e12c5d1SDavid du Colombier 	case BLOCK:
2243e12c5d1SDavid du Colombier 	case TEXT:
2253e12c5d1SDavid du Colombier 		switch (corner) {
2263e12c5d1SDavid du Colombier 		case NORTH:	y += y1 / 2; break;
2273e12c5d1SDavid du Colombier 		case SOUTH:	y -= y1 / 2; break;
2283e12c5d1SDavid du Colombier 		case EAST:	x += x1 / 2; break;
2293e12c5d1SDavid du Colombier 		case WEST:	x -= x1 / 2; break;
2303e12c5d1SDavid du Colombier 		case NE:	x += x1 / 2; y += y1 / 2; break;
2313e12c5d1SDavid du Colombier 		case SW:	x -= x1 / 2; y -= y1 / 2; break;
2323e12c5d1SDavid du Colombier 		case SE:	x += x1 / 2; y -= y1 / 2; break;
2333e12c5d1SDavid du Colombier 		case NW:	x -= x1 / 2; y += y1 / 2; break;
2343e12c5d1SDavid du Colombier 		case START:
2353e12c5d1SDavid du Colombier 			if (p->o_type == BLOCK)
2363e12c5d1SDavid du Colombier 				return whatpos(objlist[(int)p->o_val[2]], START, px, py);
2373e12c5d1SDavid du Colombier 		case END:
2383e12c5d1SDavid du Colombier 			if (p->o_type == BLOCK)
2393e12c5d1SDavid du Colombier 				return whatpos(objlist[(int)p->o_val[3]], END, px, py);
2403e12c5d1SDavid du Colombier 		}
2413e12c5d1SDavid du Colombier 		break;
2423e12c5d1SDavid du Colombier 	case ARC:
2433e12c5d1SDavid du Colombier 		switch (corner) {
2443e12c5d1SDavid du Colombier 		case START:
2453e12c5d1SDavid du Colombier 			if (p->o_attr & CW_ARC) {
2463e12c5d1SDavid du Colombier 				x = p->o_val[2]; y = p->o_val[3];
2473e12c5d1SDavid du Colombier 			} else {
2483e12c5d1SDavid du Colombier 				x = x1; y = y1;
2493e12c5d1SDavid du Colombier 			}
2503e12c5d1SDavid du Colombier 			break;
2513e12c5d1SDavid du Colombier 		case END:
2523e12c5d1SDavid du Colombier 			if (p->o_attr & CW_ARC) {
2533e12c5d1SDavid du Colombier 				x = x1; y = y1;
2543e12c5d1SDavid du Colombier 			} else {
2553e12c5d1SDavid du Colombier 				x = p->o_val[2]; y = p->o_val[3];
2563e12c5d1SDavid du Colombier 			}
2573e12c5d1SDavid du Colombier 			break;
2583e12c5d1SDavid du Colombier 		}
2593e12c5d1SDavid du Colombier 		if (corner == START || corner == END)
2603e12c5d1SDavid du Colombier 			break;
2613e12c5d1SDavid du Colombier 		x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
2623e12c5d1SDavid du Colombier 		/* Fall Through! */
2633e12c5d1SDavid du Colombier 	case CIRCLE:
2643e12c5d1SDavid du Colombier 	case ELLIPSE:
2653e12c5d1SDavid du Colombier 		switch (corner) {
2663e12c5d1SDavid du Colombier 		case NORTH:	y += y1; break;
2673e12c5d1SDavid du Colombier 		case SOUTH:	y -= y1; break;
2683e12c5d1SDavid du Colombier 		case EAST:	x += x1; break;
2693e12c5d1SDavid du Colombier 		case WEST:	x -= x1; break;
2703e12c5d1SDavid du Colombier 		case NE:	x += 0.707 * x1; y += 0.707 * y1; break;
2713e12c5d1SDavid du Colombier 		case SE:	x += 0.707 * x1; y -= 0.707 * y1; break;
2723e12c5d1SDavid du Colombier 		case NW:	x -= 0.707 * x1; y += 0.707 * y1; break;
2733e12c5d1SDavid du Colombier 		case SW:	x -= 0.707 * x1; y -= 0.707 * y1; break;
2743e12c5d1SDavid du Colombier 		}
2753e12c5d1SDavid du Colombier 		break;
2763e12c5d1SDavid du Colombier 	case LINE:
2773e12c5d1SDavid du Colombier 	case SPLINE:
2783e12c5d1SDavid du Colombier 	case ARROW:
2793e12c5d1SDavid du Colombier 		switch (corner) {
2803e12c5d1SDavid du Colombier 		case START:	break;	/* already in place */
2813e12c5d1SDavid du Colombier 		case END:	x = x1; y = y1; break;
2823e12c5d1SDavid du Colombier 		default: /* change! */
2833e12c5d1SDavid du Colombier 		case CENTER:	x = (x+x1)/2; y = (y+y1)/2; break;
2843e12c5d1SDavid du Colombier 		case NORTH:	if (y1 > y) { x = x1; y = y1; } break;
2853e12c5d1SDavid du Colombier 		case SOUTH:	if (y1 < y) { x = x1; y = y1; } break;
2863e12c5d1SDavid du Colombier 		case EAST:	if (x1 > x) { x = x1; y = y1; } break;
2873e12c5d1SDavid du Colombier 		case WEST:	if (x1 < x) { x = x1; y = y1; } break;
2883e12c5d1SDavid du Colombier 		}
2893e12c5d1SDavid du Colombier 		break;
2903e12c5d1SDavid du Colombier 	case MOVE:
2913e12c5d1SDavid du Colombier 		/* really ought to be same as line... */
2923e12c5d1SDavid du Colombier 		break;
2933e12c5d1SDavid du Colombier 	}
2943e12c5d1SDavid du Colombier 	dprintf("whatpos returns %g %g\n", x, y);
2953e12c5d1SDavid du Colombier 	*px = x;
2963e12c5d1SDavid du Colombier 	*py = y;
2973e12c5d1SDavid du Colombier 	return 1;
2983e12c5d1SDavid du Colombier }
2993e12c5d1SDavid du Colombier 
gethere(void)3003e12c5d1SDavid du Colombier obj *gethere(void)	/* make a place for curx,cury */
3013e12c5d1SDavid du Colombier {
3023e12c5d1SDavid du Colombier 	dprintf("gethere %g %g\n", curx, cury);
3033e12c5d1SDavid du Colombier 	return(makepos(curx, cury));
3043e12c5d1SDavid du Colombier }
3053e12c5d1SDavid du Colombier 
getlast(int n,int t)3063e12c5d1SDavid du Colombier obj *getlast(int n, int t)	/* find n-th previous occurrence of type t */
3073e12c5d1SDavid du Colombier {
3083e12c5d1SDavid du Colombier 	int i, k;
3093e12c5d1SDavid du Colombier 	obj *p;
3103e12c5d1SDavid du Colombier 
3113e12c5d1SDavid du Colombier 	k = n;
3123e12c5d1SDavid du Colombier 	for (i = nobj-1; i >= 0; i--) {
3133e12c5d1SDavid du Colombier 		p = objlist[i];
3143e12c5d1SDavid du Colombier 		if (p->o_type == BLOCKEND) {
3153e12c5d1SDavid du Colombier 			i = p->o_val[4];
3163e12c5d1SDavid du Colombier 			continue;
3173e12c5d1SDavid du Colombier 		}
3183e12c5d1SDavid du Colombier 		if (p->o_type != t)
3193e12c5d1SDavid du Colombier 			continue;
3203e12c5d1SDavid du Colombier 		if (--k > 0)
3213e12c5d1SDavid du Colombier 			continue;	/* not there yet */
3223e12c5d1SDavid du Colombier 		dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
3233e12c5d1SDavid du Colombier 		return(p);
3243e12c5d1SDavid du Colombier 	}
32580ee5cbfSDavid du Colombier 	ERROR "there is no %dth last", n FATAL;
3263e12c5d1SDavid du Colombier 	return(NULL);
3273e12c5d1SDavid du Colombier }
3283e12c5d1SDavid du Colombier 
getfirst(int n,int t)3293e12c5d1SDavid du Colombier obj *getfirst(int n, int t)	/* find n-th occurrence of type t */
3303e12c5d1SDavid du Colombier {
3313e12c5d1SDavid du Colombier 	int i, k;
3323e12c5d1SDavid du Colombier 	obj *p;
3333e12c5d1SDavid du Colombier 
3343e12c5d1SDavid du Colombier 	k = n;
3353e12c5d1SDavid du Colombier 	for (i = 0; i < nobj; i++) {
3363e12c5d1SDavid du Colombier 		p = objlist[i];
3373e12c5d1SDavid du Colombier 		if (p->o_type == BLOCK && t != BLOCK) {	/* skip whole block */
3383e12c5d1SDavid du Colombier 			i = p->o_val[5] + 1;
3393e12c5d1SDavid du Colombier 			continue;
3403e12c5d1SDavid du Colombier 		}
3413e12c5d1SDavid du Colombier 		if (p->o_type != t)
3423e12c5d1SDavid du Colombier 			continue;
3433e12c5d1SDavid du Colombier 		if (--k > 0)
3443e12c5d1SDavid du Colombier 			continue;	/* not there yet */
3453e12c5d1SDavid du Colombier 		dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
3463e12c5d1SDavid du Colombier 		return(p);
3473e12c5d1SDavid du Colombier 	}
34880ee5cbfSDavid du Colombier 	ERROR "there is no %dth ", n FATAL;
3493e12c5d1SDavid du Colombier 	return(NULL);
3503e12c5d1SDavid du Colombier }
3513e12c5d1SDavid du Colombier 
getblkvar(obj * p,char * s)3523e12c5d1SDavid du Colombier double getblkvar(obj *p, char *s)	/* find variable s2 in block p */
3533e12c5d1SDavid du Colombier {
3543e12c5d1SDavid du Colombier 	YYSTYPE y;
3553e12c5d1SDavid du Colombier 
3563e12c5d1SDavid du Colombier 	y = getblk(p, s);
3573e12c5d1SDavid du Colombier 	return y.f;
3583e12c5d1SDavid du Colombier }
3593e12c5d1SDavid du Colombier 
getblock(obj * p,char * s)3603e12c5d1SDavid du Colombier obj *getblock(obj *p, char *s)	/* find variable s in block p */
3613e12c5d1SDavid du Colombier {
3623e12c5d1SDavid du Colombier 	YYSTYPE y;
3633e12c5d1SDavid du Colombier 
3643e12c5d1SDavid du Colombier 	y = getblk(p, s);
3653e12c5d1SDavid du Colombier 	return y.o;
3663e12c5d1SDavid du Colombier }
3673e12c5d1SDavid du Colombier 
getblk(obj * p,char * s)3683e12c5d1SDavid du Colombier YYSTYPE getblk(obj *p, char *s)	/* find union type for s in p */
3693e12c5d1SDavid du Colombier {
3703e12c5d1SDavid du Colombier 	static YYSTYPE bug;
3713e12c5d1SDavid du Colombier 	struct symtab *stp;
3723e12c5d1SDavid du Colombier 
3733e12c5d1SDavid du Colombier 	if (p->o_type != BLOCK) {
3743e12c5d1SDavid du Colombier 		ERROR ".%s is not in that block", s WARNING;
3753e12c5d1SDavid du Colombier 		return(bug);
3763e12c5d1SDavid du Colombier 	}
3773e12c5d1SDavid du Colombier 	for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
3783e12c5d1SDavid du Colombier 		if (strcmp(s, stp->s_name) == 0) {
3793e12c5d1SDavid du Colombier 			dprintf("getblk %s found x,y= %g,%g\n",
3803e12c5d1SDavid du Colombier 				s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
3813e12c5d1SDavid du Colombier 			return(stp->s_val);
3823e12c5d1SDavid du Colombier 		}
3833e12c5d1SDavid du Colombier 	ERROR "there is no .%s in that []", s WARNING;
3843e12c5d1SDavid du Colombier 	return(bug);
3853e12c5d1SDavid du Colombier }
3863e12c5d1SDavid du Colombier 
fixpos(obj * p,double x,double y)3873e12c5d1SDavid du Colombier obj *fixpos(obj *p, double x, double y)
3883e12c5d1SDavid du Colombier {
3893e12c5d1SDavid du Colombier 	dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
3903e12c5d1SDavid du Colombier 	return makepos(p->o_x + x, p->o_y + y);
3913e12c5d1SDavid du Colombier }
3923e12c5d1SDavid du Colombier 
addpos(obj * p,obj * q)3933e12c5d1SDavid du Colombier obj *addpos(obj *p, obj *q)
3943e12c5d1SDavid du Colombier {
3953e12c5d1SDavid du Colombier 	dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
3963e12c5d1SDavid du Colombier 	return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
3973e12c5d1SDavid du Colombier }
3983e12c5d1SDavid du Colombier 
subpos(obj * p,obj * q)3993e12c5d1SDavid du Colombier obj *subpos(obj *p, obj *q)
4003e12c5d1SDavid du Colombier {
4013e12c5d1SDavid du Colombier 	dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
4023e12c5d1SDavid du Colombier 	return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
4033e12c5d1SDavid du Colombier }
4043e12c5d1SDavid du Colombier 
makenode(int type,int n)4053e12c5d1SDavid du Colombier obj *makenode(int type, int n)
4063e12c5d1SDavid du Colombier {
4073e12c5d1SDavid du Colombier 	obj *p;
4083e12c5d1SDavid du Colombier 
4093e12c5d1SDavid du Colombier 	p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
4103e12c5d1SDavid du Colombier 	if (p == NULL)
4113e12c5d1SDavid du Colombier 		ERROR "out of space in makenode" FATAL;
4123e12c5d1SDavid du Colombier 	p->o_type = type;
4133e12c5d1SDavid du Colombier 	p->o_count = n;
4143e12c5d1SDavid du Colombier 	p->o_nobj = nobj;
4153e12c5d1SDavid du Colombier 	p->o_mode = hvmode;
4163e12c5d1SDavid du Colombier 	p->o_x = curx;
4173e12c5d1SDavid du Colombier 	p->o_y = cury;
4183e12c5d1SDavid du Colombier 	p->o_nt1 = ntext1;
4193e12c5d1SDavid du Colombier 	p->o_nt2 = ntext;
4203e12c5d1SDavid du Colombier 	ntext1 = ntext;	/* ready for next caller */
4213e12c5d1SDavid du Colombier 	if (nobj >= nobjlist)
4223e12c5d1SDavid du Colombier 		objlist = (obj **) grow((char *) objlist, "objlist",
4233e12c5d1SDavid du Colombier 			nobjlist *= 2, sizeof(obj *));
4243e12c5d1SDavid du Colombier 	objlist[nobj++] = p;
4253e12c5d1SDavid du Colombier 	return(p);
4263e12c5d1SDavid du Colombier }
4273e12c5d1SDavid du Colombier 
extreme(double x,double y)4283e12c5d1SDavid du Colombier void extreme(double x, double y)	/* record max and min x and y values */
4293e12c5d1SDavid du Colombier {
4303e12c5d1SDavid du Colombier 	if (x > xmax)
4313e12c5d1SDavid du Colombier 		xmax = x;
4323e12c5d1SDavid du Colombier 	if (y > ymax)
4333e12c5d1SDavid du Colombier 		ymax = y;
4343e12c5d1SDavid du Colombier 	if (x < xmin)
4353e12c5d1SDavid du Colombier 		xmin = x;
4363e12c5d1SDavid du Colombier 	if (y < ymin)
4373e12c5d1SDavid du Colombier 		ymin = y;
4383e12c5d1SDavid du Colombier }
439