Blob


1 #include <stdio.h>
2 #include <string.h>
3 #include <math.h>
4 #include "pic.h"
5 #include "y.tab.h"
7 int
8 setdir(int n) /* set direction (hvmode) from LEFT, RIGHT, etc. */
9 {
10 switch (n) {
11 case UP: hvmode = U_DIR; break;
12 case DOWN: hvmode = D_DIR; break;
13 case LEFT: hvmode = L_DIR; break;
14 case RIGHT: hvmode = R_DIR; break;
15 }
16 return(hvmode);
17 }
19 int
20 curdir(void) /* convert current dir (hvmode) to RIGHT, LEFT, etc. */
21 {
22 switch (hvmode) {
23 case R_DIR: return RIGHT;
24 case L_DIR: return LEFT;
25 case U_DIR: return UP;
26 case D_DIR: return DOWN;
27 }
28 ERROR "can't happen curdir" FATAL;
29 return 0;
30 }
32 double
33 getcomp(obj *p, int t) /* return component of a position */
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 case PLACE:
53 return 0;
54 }
55 case DOTHT:
56 switch (p->o_type) {
57 case BOX:
58 case BLOCK:
59 case TEXT:
60 return p->o_val[1];
61 case CIRCLE:
62 case ELLIPSE:
63 return 2 * p->o_val[1];
64 case LINE:
65 case ARROW:
66 return p->o_val[1] - p->o_y;
67 case PLACE:
68 return 0;
69 }
70 case DOTRAD:
71 switch (p->o_type) {
72 case CIRCLE:
73 case ELLIPSE:
74 return p->o_val[0];
75 }
76 }
77 ERROR "you asked for a weird dimension or position" WARNING;
78 return 0;
79 }
81 double exprlist[100];
82 int nexpr = 0;
84 void
85 exprsave(double f)
86 {
87 exprlist[nexpr++] = f;
88 }
90 char*
91 sprintgen(char *fmt)
92 {
93 char buf[1000];
95 sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
96 nexpr = 0;
97 free(fmt);
98 return tostring(buf);
99 }
101 void
102 makefattr(int type, int sub, double f) /* double attr */
104 YYSTYPE val;
105 val.f = f;
106 makeattr(type, sub, val);
109 void
110 makeoattr(int type, obj *o) /* obj* attr */
112 YYSTYPE val;
113 val.o = o;
114 makeattr(type, 0, val);
117 void
118 makeiattr(int type, int i) /* int attr */
120 YYSTYPE val;
121 val.i = i;
122 makeattr(type, 0, val);
125 void
126 maketattr(int sub, char *p) /* text attribute: takes two */
128 YYSTYPE val;
129 val.p = p;
130 makeattr(TEXTATTR, sub, val);
133 void
134 addtattr(int sub) /* add text attrib to existing item */
136 attr[nattr-1].a_sub |= sub;
139 void
140 makevattr(char *p) /* varname attribute */
142 YYSTYPE val;
143 val.p = p;
144 makeattr(VARNAME, 0, val);
147 void
148 makeattr(int type, int sub, YYSTYPE val) /* add attribute type and val */
150 if (type == 0 && val.i == 0) { /* clear table for next stat */
151 nattr = 0;
152 return;
154 if (nattr >= nattrlist)
155 attr = (Attr *) grow((char *)attr, "attr", nattrlist += 100, sizeof(Attr));
156 dprintf("attr %d: %d %d %d\n", nattr, type, sub, val.i);
157 attr[nattr].a_type = type;
158 attr[nattr].a_sub = sub;
159 attr[nattr].a_val = val;
160 nattr++;
163 void
164 printexpr(double f) /* print expression for debugging */
166 printf("%g\n", f);
169 void
170 printpos(obj *p) /* print position for debugging */
172 printf("%g, %g\n", p->o_x, p->o_y);
175 char*
176 tostring(char *s)
178 char *p;
180 p = malloc(strlen(s)+1);
181 if (p == NULL)
182 ERROR "out of space in tostring on %s", s FATAL;
183 strcpy(p, s);
184 return(p);
187 obj*
188 makepos(double x, double y) /* make a position cell */
190 obj *p;
192 p = makenode(PLACE, 0);
193 p->o_x = x;
194 p->o_y = y;
195 return(p);
198 obj*
199 makebetween(double f, obj *p1, obj* p2) /* make position between p1 and p2 */
201 obj *p;
203 dprintf("fraction = %.2f\n", f);
204 p = makenode(PLACE, 0);
205 p->o_x = p1->o_x + f * (p2->o_x - p1->o_x);
206 p->o_y = p1->o_y + f * (p2->o_y - p1->o_y);
207 return(p);
210 obj*
211 getpos(obj *p, int corner) /* find position of point */
213 double x, y;
215 whatpos(p, corner, &x, &y);
216 return makepos(x, y);
219 int
220 whatpos(obj *p, int corner, double *px, double *py) /* what is the position (no side effect) */
222 double x, y, x1, y1;
224 dprintf("whatpos %p %d %d\n", p, p->o_type, corner);
225 x = p->o_x;
226 y = p->o_y;
227 x1 = 0;
228 y1 = 0;
229 if (p->o_type != PLACE) {
230 x1 = p->o_val[0];
231 y1 = p->o_val[1];
233 switch (p->o_type) {
234 case PLACE:
235 break;
236 case BOX:
237 case BLOCK:
238 case TEXT:
239 switch (corner) {
240 case NORTH: y += y1 / 2; break;
241 case SOUTH: y -= y1 / 2; break;
242 case EAST: x += x1 / 2; break;
243 case WEST: x -= x1 / 2; break;
244 case NE: x += x1 / 2; y += y1 / 2; break;
245 case SW: x -= x1 / 2; y -= y1 / 2; break;
246 case SE: x += x1 / 2; y -= y1 / 2; break;
247 case NW: x -= x1 / 2; y += y1 / 2; break;
248 case START:
249 if (p->o_type == BLOCK)
250 return whatpos(objlist[(int)p->o_val[2]], START, px, py);
251 case END:
252 if (p->o_type == BLOCK)
253 return whatpos(objlist[(int)p->o_val[3]], END, px, py);
255 break;
256 case ARC:
257 switch (corner) {
258 case START:
259 if (p->o_attr & CW_ARC) {
260 x = p->o_val[2]; y = p->o_val[3];
261 } else {
262 x = x1; y = y1;
264 break;
265 case END:
266 if (p->o_attr & CW_ARC) {
267 x = x1; y = y1;
268 } else {
269 x = p->o_val[2]; y = p->o_val[3];
271 break;
273 if (corner == START || corner == END)
274 break;
275 x1 = y1 = sqrt((x1-x)*(x1-x) + (y1-y)*(y1-y));
276 /* Fall Through! */
277 case CIRCLE:
278 case ELLIPSE:
279 switch (corner) {
280 case NORTH: y += y1; break;
281 case SOUTH: y -= y1; break;
282 case EAST: x += x1; break;
283 case WEST: x -= x1; break;
284 case NE: x += 0.707 * x1; y += 0.707 * y1; break;
285 case SE: x += 0.707 * x1; y -= 0.707 * y1; break;
286 case NW: x -= 0.707 * x1; y += 0.707 * y1; break;
287 case SW: x -= 0.707 * x1; y -= 0.707 * y1; break;
289 break;
290 case LINE:
291 case SPLINE:
292 case ARROW:
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;
303 break;
304 case MOVE:
305 /* really ought to be same as line... */
306 break;
308 dprintf("whatpos returns %g %g\n", x, y);
309 *px = x;
310 *py = y;
311 return 1;
314 obj*
315 gethere(void) /* make a place for curx,cury */
317 dprintf("gethere %g %g\n", curx, cury);
318 return(makepos(curx, cury));
321 obj*
322 getlast(int n, int t) /* find n-th previous occurrence of type t */
324 int i, k;
325 obj *p;
327 k = n;
328 for (i = nobj-1; i >= 0; i--) {
329 p = objlist[i];
330 if (p->o_type == BLOCKEND) {
331 i = p->o_val[4];
332 continue;
334 if (p->o_type != t)
335 continue;
336 if (--k > 0)
337 continue; /* not there yet */
338 dprintf("got a last of x,y= %g,%g\n", p->o_x, p->o_y);
339 return(p);
341 ERROR "there is no %dth last", n WARNING;
342 return(NULL);
345 obj*
346 getfirst(int n, int t) /* find n-th occurrence of type t */
348 int i, k;
349 obj *p;
351 k = n;
352 for (i = 0; i < nobj; i++) {
353 p = objlist[i];
354 if (p->o_type == BLOCK && t != BLOCK) { /* skip whole block */
355 i = p->o_val[5] + 1;
356 continue;
358 if (p->o_type != t)
359 continue;
360 if (--k > 0)
361 continue; /* not there yet */
362 dprintf("got a first of x,y= %g,%g\n", p->o_x, p->o_y);
363 return(p);
365 ERROR "there is no %dth ", n WARNING;
366 return(NULL);
369 double
370 getblkvar(obj *p, char *s) /* find variable s2 in block p */
372 YYSTYPE y;
374 y = getblk(p, s);
375 return y.f;
378 obj*
379 getblock(obj *p, char *s) /* find variable s in block p */
381 YYSTYPE y;
383 y = getblk(p, s);
384 return y.o;
387 YYSTYPE
388 getblk(obj *p, char *s) /* find union type for s in p */
390 static YYSTYPE bug;
391 struct symtab *stp;
393 if (p->o_type != BLOCK) {
394 ERROR ".%s is not in that block", s WARNING;
395 return(bug);
397 for (stp = p->o_symtab; stp != NULL; stp = stp->s_next)
398 if (strcmp(s, stp->s_name) == 0) {
399 dprintf("getblk %s found x,y= %g,%g\n",
400 s, (stp->s_val.o)->o_x, (stp->s_val.o)->o_y);
401 return(stp->s_val);
403 ERROR "there is no .%s in that []", s WARNING;
404 return(bug);
407 obj*
408 fixpos(obj *p, double x, double y)
410 dprintf("fixpos returns %g %g\n", p->o_x + x, p->o_y + y);
411 return makepos(p->o_x + x, p->o_y + y);
414 obj*
415 addpos(obj *p, obj *q)
417 dprintf("addpos returns %g %g\n", p->o_x+q->o_x, p->o_y+q->o_y);
418 return makepos(p->o_x+q->o_x, p->o_y+q->o_y);
421 obj*
422 subpos(obj *p, obj *q)
424 dprintf("subpos returns %g %g\n", p->o_x-q->o_x, p->o_y-q->o_y);
425 return makepos(p->o_x-q->o_x, p->o_y-q->o_y);
428 obj*
429 makenode(int type, int n)
431 obj *p;
433 p = (obj *) calloc(1, sizeof(obj) + (n-1)*sizeof(ofloat));
434 if (p == NULL)
435 ERROR "out of space in makenode" FATAL;
436 p->o_type = type;
437 p->o_count = n;
438 p->o_nobj = nobj;
439 p->o_mode = hvmode;
440 p->o_x = curx;
441 p->o_y = cury;
442 p->o_nt1 = ntext1;
443 p->o_nt2 = ntext;
444 ntext1 = ntext; /* ready for next caller */
445 if (nobj >= nobjlist)
446 objlist = (obj **) grow((char *) objlist, "objlist",
447 nobjlist *= 2, sizeof(obj *));
448 objlist[nobj++] = p;
449 return(p);
452 void
453 extreme(double x, double y) /* record max and min x and y values */
455 if (x > xmax)
456 xmax = x;
457 if (y > ymax)
458 ymax = y;
459 if (x < xmin)
460 xmin = x;
461 if (y < ymin)
462 ymin = y;