1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include "pic.h"
6 #include "y.tab.h"
7 
8 int whatpos(obj *p, int corner, double *px, double *py);
9 void makeattr(int type, int sub, YYSTYPE val);
10 YYSTYPE getblk(obj *, char *);
11 
12 int
setdir(int n)13 setdir(int n)	/* set direction (hvmode) from LEFT, RIGHT, etc. */
14 {
15 	switch (n) {
16 	case UP:	hvmode = U_DIR; break;
17 	case DOWN:	hvmode = D_DIR; break;
18 	case LEFT:	hvmode = L_DIR; break;
19 	case RIGHT:	hvmode = R_DIR; break;
20 	}
21  	return(hvmode);
22 }
23 
24 int
curdir(void)25 curdir(void)	/* convert current dir (hvmode) to RIGHT, LEFT, etc. */
26 {
27 	switch (hvmode) {
28 	case R_DIR:	return RIGHT;
29 	case L_DIR:	return LEFT;
30 	case U_DIR:	return UP;
31 	case D_DIR:	return DOWN;
32 	}
33 	ERROR "can't happen curdir" FATAL;
34 	return 0;
35 }
36 
37 double
getcomp(obj * p,int t)38 getcomp(obj *p, int t)	/* return component of a position */
39 {
40 	switch (t) {
41 	case DOTX:
42 		return p->o_x;
43 	case DOTY:
44 		return p->o_y;
45 	case DOTWID:
46 		switch (p->o_type) {
47 		case BOX:
48 		case BLOCK:
49 		case TEXT:
50 			return p->o_val[0];
51 		case CIRCLE:
52 		case ELLIPSE:
53 			return 2 * p->o_val[0];
54 		case LINE:
55 		case ARROW:
56 			return p->o_val[0] - p->o_x;
57 		case PLACE:
58 			return 0;
59 		}
60 	case DOTHT:
61 		switch (p->o_type) {
62 		case BOX:
63 		case BLOCK:
64 		case TEXT:
65 			return p->o_val[1];
66 		case CIRCLE:
67 		case ELLIPSE:
68 			return 2 * p->o_val[1];
69 		case LINE:
70 		case ARROW:
71 			return p->o_val[1] - p->o_y;
72 		case PLACE:
73 			return 0;
74 		}
75 	case DOTRAD:
76 		switch (p->o_type) {
77 		case CIRCLE:
78 		case ELLIPSE:
79 			return p->o_val[0];
80 		}
81 	}
82 	ERROR "you asked for a weird dimension or position" WARNING;
83 	return 0;
84 }
85 
86 double	exprlist[100];
87 int	nexpr	= 0;
88 
exprsave(double f)89 void exprsave(double f)
90 {
91 	exprlist[nexpr++] = f;
92 }
93 
sprintgen(char * fmt)94 char *sprintgen(char *fmt)
95 {
96 	char buf[1000];
97 
98 	sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
99 	nexpr = 0;
100 	free(fmt);
101 	return tostring(buf);
102 }
103 
makefattr(int type,int sub,double f)104 void makefattr(int type, int sub, double f)	/* double attr */
105 {
106 	YYSTYPE val;
107 	val.f = f;
108 	makeattr(type, sub, val);
109 }
110 
makeoattr(int type,obj * o)111 void makeoattr(int type, obj *o)	/* obj* attr */
112 {
113 	YYSTYPE val;
114 	val.o = o;
115 	makeattr(type, 0, val);
116 }
117 
makeiattr(int type,int i)118 void makeiattr(int type, int i)	/* int attr */
119 {
120 	YYSTYPE val;
121 	val.i = i;
122 	makeattr(type, 0, val);
123 }
124 
maketattr(int sub,char * p)125 void maketattr(int sub, char *p)	/* text attribute: takes two */
126 {
127 	YYSTYPE val;
128 	val.p = p;
129 	makeattr(TEXTATTR, sub, val);
130 }
131 
addtattr(int sub)132 void addtattr(int sub)		/* add text attrib to existing item */
133 {
134 	attr[nattr-1].a_sub |= sub;
135 }
136 
makevattr(char * p)137 void makevattr(char *p)	/* varname attribute */
138 {
139 	YYSTYPE val;
140 	val.p = p;
141 	makeattr(VARNAME, 0, val);
142 }
143 
makeattr(int type,int sub,YYSTYPE val)144 void makeattr(int type, int sub, YYSTYPE val)	/* add attribute type and val */
145 {
146 	if (type == 0 && val.i == 0) {	/* clear table for next stat */
147 		nattr = 0;
148 		return;
149 	}
150 	if (nattr >= nattrlist)
151 		attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
152 	dprintf("attr %d:  %d %d %d\n", nattr, type, sub, val.i);
153 	attr[nattr].a_type = type;
154 	attr[nattr].a_sub = sub;
155 	attr[nattr].a_val = val;
156 	nattr++;
157 }
158 
printexpr(double f)159 void printexpr(double f)	/* print expression for debugging */
160 {
161 	printf("%g\n", f);
162 }
163 
printpos(obj * p)164 void printpos(obj *p)	/* print position for debugging */
165 {
166 	printf("%g, %g\n", p->o_x, p->o_y);
167 }
168 
tostring(char * s)169 char *tostring(char *s)
170 {
171 	register char *p;
172 
173 	p = malloc(strlen(s)+1);
174 	if (p == NULL)
175 		ERROR "out of space in tostring on %s", s FATAL;
176 	strcpy(p, s);
177 	return(p);
178 }
179 
makepos(double x,double y)180 obj *makepos(double x, double y)	/* make a position cell */
181 {
182 	obj *p;
183 
184 	p = makenode(PLACE, 0);
185 	p->o_x = x;
186 	p->o_y = y;
187 	return(p);
188 }
189 
makebetween(double f,obj * p1,obj * p2)190 obj *makebetween(double f, obj *p1, obj *p2)	/* make position between p1 and p2 */
191 {
192 	obj *p;
193 
194 	dprintf("fraction = %.2f\n", f);
195 	p = makenode(PLACE, 0);
196 	p->o_x = p1->o_x + f * (p2->o_x - p1->o_x);
197 	p->o_y = p1->o_y + f * (p2->o_y - p1->o_y);
198 	return(p);
199 }
200 
getpos(obj * p,int corner)201 obj *getpos(obj *p, int corner)	/* find position of point */
202 {
203 	double x, y;
204 
205 	whatpos(p, corner, &x, &y);
206 	return makepos(x, y);
207 }
208 
whatpos(obj * p,int corner,double * px,double * py)209 int whatpos(obj *p, int corner, double *px, double *py)	/* what is the position (no side effect) */
210 {
211 	double x, y, x1, y1;
212 
213 	x1 = y1 = 0.0; /* Botch? (gcc) */
214 
215 	dprintf("whatpos %p %d %d\n", (void*)p, p->o_type, corner);
216 	x = p->o_x;
217 	y = p->o_y;
218 	if (p->o_type != PLACE && p->o_type != MOVE) {
219 		x1 = p->o_val[0];
220 		y1 = p->o_val[1];
221 	}
222 	switch (p->o_type) {
223 	case PLACE:
224 		break;
225 	case BOX:
226 	case BLOCK:
227 	case TEXT:
228 		switch (corner) {
229 		case NORTH:	y += y1 / 2; break;
230 		case SOUTH:	y -= y1 / 2; break;
231 		case EAST:	x += x1 / 2; break;
232 		case WEST:	x -= x1 / 2; break;
233 		case NE:	x += x1 / 2; y += y1 / 2; break;
234 		case SW:	x -= x1 / 2; y -= y1 / 2; break;
235 		case SE:	x += x1 / 2; y -= y1 / 2; break;
236 		case NW:	x -= x1 / 2; y += y1 / 2; break;
237 		case START:
238 			if (p->o_type == BLOCK)
239 				return whatpos(objlist[(int)p->o_val[2]], START, px, py);
240 		case END:
241 			if (p->o_type == BLOCK)
242 				return whatpos(objlist[(int)p->o_val[3]], END, px, py);
243 		}
244 		break;
245 	case ARC:
246 		switch (corner) {
247 		case START:
248 			if (p->o_attr & CW_ARC) {
249 				x = p->o_val[2]; y = p->o_val[3];
250 			} else {
251 				x = x1; y = y1;
252 			}
253 			break;
254 		case END:
255 			if (p->o_attr & CW_ARC) {
256 				x = x1; y = y1;
257 			} else {
258 				x = p->o_val[2]; y = p->o_val[3];
259 			}
260 			break;
261 		}
262 		if (corner == START || corner == END)
263 			break;
264 		x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
265 		/* Fall Through! */
266 	case CIRCLE:
267 	case ELLIPSE:
268 		switch (corner) {
269 		case NORTH:	y += y1; break;
270 		case SOUTH:	y -= y1; break;
271 		case EAST:	x += x1; break;
272 		case WEST:	x -= x1; break;
273 		case NE:	x += 0.707 * x1; y += 0.707 * y1; break;
274 		case SE:	x += 0.707 * x1; y -= 0.707 * y1; break;
275 		case NW:	x -= 0.707 * x1; y += 0.707 * y1; break;
276 		case SW:	x -= 0.707 * x1; y -= 0.707 * y1; break;
277 		}
278 		break;
279 	case LINE:
280 	case SPLINE:
281 	case ARROW:
282 		switch (corner) {
283 		case START:	break;	/* already in place */
284 		case END:	x = x1; y = y1; break;
285 		default: /* change! */
286 		case CENTER:	x = (x+x1)/2; y = (y+y1)/2; break;
287 		case NORTH:	if (y1 > y) { x = x1; y = y1; } break;
288 		case SOUTH:	if (y1 < y) { x = x1; y = y1; } break;
289 		case EAST:	if (x1 > x) { x = x1; y = y1; } break;
290 		case WEST:	if (x1 < x) { x = x1; y = y1; } break;
291 		}
292 		break;
293 	case MOVE:
294 		/* really ought to be same as line... */
295 		break;
296 	}
297 	dprintf("whatpos returns %g %g\n", x, y);
298 	*px = x;
299 	*py = y;
300 	return 1;
301 }
302 
gethere(void)303 obj *gethere(void)	/* make a place for curx,cury */
304 {
305 	dprintf("gethere %g %g\n", curx, cury);
306 	return(makepos(curx, cury));
307 }
308 
getlast(int n,int t)309 obj *getlast(int n, int t)	/* find n-th previous occurrence of type t */
310 {
311 	int i, k;
312 	obj *p;
313 
314 	k = n;
315 	for (i = nobj-1; i >= 0; i--) {
316 		p = objlist[i];
317 		if (p->o_type == BLOCKEND) {
318 			i = p->o_val[4];
319 			continue;
320 		}
321 		if (p->o_type != t)
322 			continue;
323 		if (--k > 0)
324 			continue;	/* not there yet */
325 		dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
326 		return(p);
327 	}
328 	ERROR "there is no %dth last", n WARNING;
329 	return(NULL);
330 }
331 
getfirst(int n,int t)332 obj *getfirst(int n, int t)	/* find n-th occurrence of type t */
333 {
334 	int i, k;
335 	obj *p;
336 
337 	k = n;
338 	for (i = 0; i < nobj; i++) {
339 		p = objlist[i];
340 		if (p->o_type == BLOCK && t != BLOCK) {	/* skip whole block */
341 			i = p->o_val[5] + 1;
342 			continue;
343 		}
344 		if (p->o_type != t)
345 			continue;
346 		if (--k > 0)
347 			continue;	/* not there yet */
348 		dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
349 		return(p);
350 	}
351 	ERROR "there is no %dth ", n WARNING;
352 	return(NULL);
353 }
354 
getblkvar(obj * p,char * s)355 double getblkvar(obj *p, char *s)	/* find variable s2 in block p */
356 {
357 	YYSTYPE y;
358 
359 	y = getblk(p, s);
360 	return y.f;
361 }
362 
getblock(obj * p,char * s)363 obj *getblock(obj *p, char *s)	/* find variable s in block p */
364 {
365 	YYSTYPE y;
366 
367 	y = getblk(p, s);
368 	return y.o;
369 }
370 
getblk(obj * p,char * s)371 YYSTYPE getblk(obj *p, char *s)	/* find union type for s in p */
372 {
373 	static YYSTYPE bug;
374 	struct symtab *stp;
375 
376 	if (p->o_type != BLOCK) {
377 		ERROR ".%s is not in that block", s WARNING;
378 		return(bug);
379 	}
380 	for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
381 		if (strcmp(s, stp->s_name) == 0) {
382 			dprintf("getblk %s found x,y= %g,%g\n",
383 				s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
384 			return(stp->s_val);
385 		}
386 	ERROR "there is no .%s in that []", s WARNING;
387 	return(bug);
388 }
389 
fixpos(obj * p,double x,double y)390 obj *fixpos(obj *p, double x, double y)
391 {
392 	dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
393 	return makepos(p->o_x + x, p->o_y + y);
394 }
395 
addpos(obj * p,obj * q)396 obj *addpos(obj *p, obj *q)
397 {
398 	dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
399 	return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
400 }
401 
subpos(obj * p,obj * q)402 obj *subpos(obj *p, obj *q)
403 {
404 	dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
405 	return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
406 }
407 
makenode(int type,int n)408 obj *makenode(int type, int n)
409 {
410 	obj *p;
411 
412 	p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
413 	if (p == NULL)
414 		ERROR "out of space in makenode" FATAL;
415 	p->o_type = type;
416 	p->o_count = n;
417 	p->o_nobj = nobj;
418 	p->o_mode = hvmode;
419 	p->o_x = curx;
420 	p->o_y = cury;
421 	p->o_nt1 = ntext1;
422 	p->o_nt2 = ntext;
423 	ntext1 = ntext;	/* ready for next caller */
424 	if (nobj >= nobjlist)
425 		objlist = (obj **) grow((char *) objlist, "objlist",
426 			nobjlist *= 2, sizeof(obj *));
427 	objlist[nobj++] = p;
428 	return(p);
429 }
430 
extreme(double x,double y)431 void extreme(double x, double y)	/* record max and min x and y values */
432 {
433 	if (x > xmax)
434 		xmax = x;
435 	if (y > ymax)
436 		ymax = y;
437 	if (x < xmin)
438 		xmin = x;
439 	if (y < ymin)
440 		ymin = y;
441 }
442