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