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