Blob


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"
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 *);
12 int
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 }
24 int
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 }
37 double
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 }
86 double exprlist[100];
87 int nexpr = 0;
89 void exprsave(double f)
90 {
91 exprlist[nexpr++] = f;
92 }
94 char *sprintgen(char *fmt)
95 {
96 char buf[1000];
98 sprintf(buf, fmt, exprlist[0], exprlist[1], exprlist[2], exprlist[3], exprlist[4]);
99 nexpr = 0;
100 free(fmt);
101 return tostring(buf);
104 void makefattr(int type, int sub, double f) /* double attr */
106 YYSTYPE val;
107 val.f = f;
108 makeattr(type, sub, val);
111 void makeoattr(int type, obj *o) /* obj* attr */
113 YYSTYPE val;
114 val.o = o;
115 makeattr(type, 0, val);
118 void makeiattr(int type, int i) /* int attr */
120 YYSTYPE val;
121 val.i = i;
122 makeattr(type, 0, val);
125 void maketattr(int sub, char *p) /* text attribute: takes two */
127 YYSTYPE val;
128 val.p = p;
129 makeattr(TEXTATTR, sub, val);
132 void addtattr(int sub) /* add text attrib to existing item */
134 attr[nattr-1].a_sub |= sub;
137 void makevattr(char *p) /* varname attribute */
139 YYSTYPE val;
140 val.p = p;
141 makeattr(VARNAME, 0, val);
144 void makeattr(int type, int sub, YYSTYPE val) /* add attribute type and val */
146 if (type == 0 && val.i == 0) { /* clear table for next stat */
147 nattr = 0;
148 return;
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++;
159 void printexpr(double f) /* print expression for debugging */
161 printf("%g\n", f);
164 void printpos(obj *p) /* print position for debugging */
166 printf("%g, %g\n", p->o_x, p->o_y);
169 char *tostring(char *s)
171 register char *p;
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);
180 obj *makepos(double x, double y) /* make a position cell */
182 obj *p;
184 p = makenode(PLACE, 0);
185 p->o_x = x;
186 p->o_y = y;
187 return(p);
190 obj *makebetween(double f, obj *p1, obj *p2) /* make position between p1 and p2 */
192 obj *p;
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);
201 obj *getpos(obj *p, int corner) /* find position of point */
203 double x, y;
205 whatpos(p, corner, &x, &y);
206 return makepos(x, y);
209 int whatpos(obj *p, int corner, double *px, double *py) /* what is the position (no side effect) */
211 double x, y, x1, y1;
213 x1 = y1 = 0.0; /* Botch? (gcc) */
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];
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);
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;
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];
260 break;
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;
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;
292 break;
293 case MOVE:
294 /* really ought to be same as line... */
295 break;
297 dprintf("whatpos returns %g %g\n", x, y);
298 *px = x;
299 *py = y;
300 return 1;
303 obj *gethere(void) /* make a place for curx,cury */
305 dprintf("gethere %g %g\n", curx, cury);
306 return(makepos(curx, cury));
309 obj *getlast(int n, int t) /* find n-th previous occurrence of type t */
311 int i, k;
312 obj *p;
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;
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);
328 ERROR "there is no %dth last", n WARNING;
329 return(NULL);
332 obj *getfirst(int n, int t) /* find n-th occurrence of type t */
334 int i, k;
335 obj *p;
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;
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);
351 ERROR "there is no %dth ", n WARNING;
352 return(NULL);
355 double getblkvar(obj *p, char *s) /* find variable s2 in block p */
357 YYSTYPE y;
359 y = getblk(p, s);
360 return y.f;
363 obj *getblock(obj *p, char *s) /* find variable s in block p */
365 YYSTYPE y;
367 y = getblk(p, s);
368 return y.o;
371 YYSTYPE getblk(obj *p, char *s) /* find union type for s in p */
373 static YYSTYPE bug;
374 struct symtab *stp;
376 if (p->o_type != BLOCK) {
377 ERROR ".%s is not in that block", s WARNING;
378 return(bug);
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);
386 ERROR "there is no .%s in that []", s WARNING;
387 return(bug);
390 obj *fixpos(obj *p, double x, double y)
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);
396 obj *addpos(obj *p, obj *q)
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);
402 obj *subpos(obj *p, obj *q)
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);
408 obj *makenode(int type, int n)
410 obj *p;
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);
431 void extreme(double x, double y) /* record max and min x and y values */
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;