1 #ifndef lint
2 static char *sccsid ="memut.c (CWI) 1.1 85/03/01";
3 #endif
4 /* memory utilities */
5
6 #include "ideal.h"
7 #include "y.tab.h"
8
9 char *fooalloc;
10 #define tryalloc(new,kind) \
11 if (!(new =(kind *) malloc(sizeof (kind)))) {\
12 emergency ();\
13 if (!(new =(kind *) malloc(sizeof (kind)))) {\
14 fprintf (stderr, "ideal: Out of space\n");\
15 exit (1);\
16 }\
17 };\
18 for (fooalloc = (char *) new;\
19 fooalloc < ((char *) new) + sizeof (kind);\
20 fooalloc ++)\
21 *fooalloc = '\0';
22
stmtgen(kind,stmt)23 STMTPTR stmtgen (kind, stmt)
24 int kind;
25 char *stmt;
26 {
27 register STMTPTR newguy;
28 tryalloc(newguy,STMTNODE);
29 newguy->kind = kind;
30 newguy->stmt = stmt;
31 return (newguy);
32 }
33
boxgen(name,stmtlist)34 BOXPTR boxgen (name,stmtlist)
35 int name;
36 STMTPTR stmtlist;
37 {
38 register BOXPTR newguy;
39 STMTPTR bdstmt;
40 tryalloc(newguy,BOXNODE);
41 newguy->name = name;
42 /* the stmts are in reverse order (check the yacc grammar) */
43 newguy->stmtlist = reverse (stmtlist);
44 if (bdstmt = nextstmt (BDLIST, stmtlist))
45 bdstmt->stmt = (char *) reverse ((STMTPTR) bdstmt->stmt);
46 return (newguy);
47 }
48
namegen(name)49 NAMEPTR namegen (name)
50 int name;
51 {
52 register NAMEPTR newguy;
53 tryalloc(newguy,NAMENODE);
54 newguy->name = name;
55 return (newguy);
56 }
57
exprgen(expr)58 EXPRPTR exprgen (expr)
59 EXPR expr;
60 {
61 register EXPRPTR newguy;
62 tryalloc(newguy,EXPRNODE);
63 newguy->expr = expr;
64 return (newguy);
65 }
66
putgen(name,parm,p_or_c)67 PUTPTR putgen (name, parm, p_or_c)
68 int name;
69 BOXPTR parm;
70 int p_or_c;
71 {
72 register PUTPTR newguy;
73 tryalloc(newguy,PUTNODE);
74 newguy->name = name;
75 newguy->parm = parm;
76 newguy->p_or_c = p_or_c;
77 return (newguy);
78 }
79
pengen(from,to,copies,start,end,pen)80 PENPTR pengen (from, to, copies, start, end, pen)
81 EXPR from,
82 to,
83 copies,
84 start,
85 end;
86 BOXPTR pen;
87 {
88 register PENPTR newguy;
89 tryalloc(newguy,PEN_NODE);
90 newguy->from = from;
91 newguy->to = to;
92 newguy->copies = copies;
93 newguy->start = start;
94 newguy->end = end;
95 newguy->pen = pen;
96 return (newguy);
97 }
98
miscgen(info)99 MISCPTR miscgen (info)
100 int info;
101 {
102 register MISCPTR newguy;
103 tryalloc(newguy,MISCNODE);
104 newguy->info = info;
105 return (newguy);
106 }
107
intlgen(oper,left,right)108 INTLPTR intlgen (oper, left, right)
109 int oper;
110 EXPR left,
111 right;
112 {
113 register INTLPTR newguy;
114 tryalloc(newguy,EXPRINTL);
115 newguy->leaf = FALSE;
116 newguy->oper = oper;
117 newguy->left = left;
118 newguy->right = right;
119 return (newguy);
120 }
121
commagen(real,imag)122 INTLPTR commagen (real, imag)
123 float real,
124 imag;
125 {
126 register INTLPTR newguy;
127 tryalloc(newguy,EXPRINTL);
128 newguy->leaf = FALSE;
129 newguy->oper = ';';
130 newguy->left = (EXPR) depgen ((VARPTR) NULL, real);
131 newguy->right = (EXPR) depgen ((VARPTR) NULL, imag);
132 return (newguy);
133 }
134
extlgen(path)135 EXTLPTR extlgen (path)
136 NAMEPTR path;
137 {
138 register EXTLPTR newguy;
139 tryalloc(newguy,EXPREXTL);
140 newguy->leaf = TRUE;
141 newguy->info.path = path;
142 newguy->kind = PATH;
143 return (newguy);
144 }
145
fextlgen(value)146 EXTLPTR fextlgen (value)
147 float value;
148 {
149 register EXTLPTR newguy;
150 tryalloc(newguy,EXPREXTL);
151 newguy->leaf = TRUE;
152 newguy->info.const = value;
153 newguy->kind = CONST;
154 return (newguy);
155 }
156
noadgen(defnode,edgevarlist,boxvarlist)157 NOADPTR noadgen (defnode, edgevarlist, boxvarlist)
158 PUTPTR defnode;
159 VARPTR edgevarlist;
160 VARPTR boxvarlist;
161 {
162 register NOADPTR newguy;
163 tryalloc(newguy,NOAD);
164 newguy->defnode = defnode;
165 newguy->edgevarlist = edgevarlist;
166 newguy->boxvarlist = boxvarlist;
167 return (newguy);
168 }
169
vargen(name,re,deplist)170 VARPTR vargen (name, re, deplist)
171 int name;
172 boolean re;
173 DEPPTR deplist;
174 {
175 register VARPTR newguy;
176 tryalloc(newguy,VARNODE);
177 newguy->re_name = re?name:-name;
178 newguy->deplist = deplist;
179 return (newguy);
180 }
181
182 static DEPPTR depavh = NULL;
183 static DEPPTR depavt = NULL;
184
depgen(var,coeff)185 DEPPTR depgen (var, coeff)
186 VARPTR var;
187 float coeff;
188 {
189 register DEPPTR newguy;
190 if (depavh) {
191 newguy = depavh;
192 depavh = depavh->next;
193 if (!depavh)
194 depavt = NULL;
195 newguy->next = NULL;
196 } else
197 tryalloc(newguy,DEPNODE);
198 newguy->var = var;
199 newguy->coeff = coeff;
200 return (newguy);
201 }
202
linegen(x0,y0,x1,y1)203 LINEPTR linegen (x0, y0, x1, y1)
204 float x0,
205 y0,
206 x1,
207 y1;
208 {
209 register LINEPTR newguy;
210 tryalloc(newguy,LINENODE);
211 newguy->kind = LINE;
212 newguy->x0 = x0;
213 newguy->y0 = y0;
214 newguy->x1 = x1;
215 newguy->y1 = y1;
216 return (newguy);
217 }
218
edgeline(x0,y0,x1,y1)219 EDGEPTR edgeline (x0, y0, x1, y1)
220 float x0,
221 y0,
222 x1,
223 y1;
224 {
225 EDGEPTR newguy;
226 tryalloc(newguy,EDGENODE);
227 newguy->fax = (ARCPTR) NULL;
228 newguy->sx = x0;
229 newguy->sy = y0;
230 newguy->ex = x1;
231 newguy->ey = y1;
232 newguy->stx = newguy->sx + 0.2*(newguy->ex - newguy->sx);
233 newguy->sty = newguy->sy + 0.2*(newguy->ey - newguy->sy);
234 newguy->etx = newguy->ex + 0.2*(newguy->sx - newguy->ex);
235 newguy->ety = newguy->ey + 0.2*(newguy->sy - newguy->ey);
236 dprintf "opaque polygon edge: %f,%f -- %f,%f\n",
237 x0,y0, x1,y1
238 );
239 return (newguy);
240 }
241
circgen(x0,y0,r)242 LINEPTR circgen (x0, y0, r)
243 float x0,
244 y0,
245 r;
246 {
247 register CIRCPTR newguy;
248 tryalloc(newguy,CIRCNODE);
249 newguy->kind = CIRCLE;
250 newguy->x0 = x0;
251 newguy->y0 = y0;
252 newguy->r = r;
253 return ((LINEPTR) newguy);
254 }
255
256 /*
257 LINEPTR arcgen (x0, y0, x1, y1, x2, y2, theta1, theta2, radius)
258 float x0,
259 y0,
260 x1,
261 y1,
262 x2,
263 y2,
264 theta1,
265 theta2,
266 radius;
267 {
268 register ARCPTR newguy;
269 tryalloc(newguy,ARCNODE);
270 newguy->kind = ARC;
271 newguy->x0 = x0;
272 newguy->y0 = y0;
273 newguy->x1 = x1;
274 newguy->y1 = y1;
275 newguy->x2 = x2;
276 newguy->y2 = y2;
277 newguy->theta1 = theta1;
278 newguy->theta2 = theta2;
279 newguy->radius = radius;
280 return ((LINEPTR) newguy);
281 }
282 */
283
angularc(x0,y0,radius,theta1,theta2)284 LINEPTR angularc (x0, y0, radius, theta1, theta2)
285 float x0,
286 y0,
287 theta1,
288 theta2,
289 radius;
290 {
291 /* theta1 and theta2 should be in radians */
292 register ARCPTR newguy;
293 tryalloc(newguy,ARCNODE);
294 radius = fabs(radius);
295 newguy->kind = ARC;
296 newguy->x0 = x0;
297 newguy->y0 = y0;
298 newguy->x1 = x0 + cos (theta1)*radius;
299 newguy->y1 = y0 + sin (theta1)*radius;
300 newguy->x2 = x0 + cos (theta2)*radius;
301 newguy->y2 = y0 + sin (theta2)*radius;
302 theta1 = rprin (theta1);
303 theta2 = rprin (theta2);
304 while (theta2 - theta1 < EPSILON)
305 theta2 += 2*PI;
306 if (fabs(theta2 - theta1) > PI)
307 radius *= -1;
308 newguy->theta1 = theta1;
309 newguy->theta2 = theta2;
310 newguy->radius = radius;
311 return ((LINEPTR) newguy);
312 }
313
pointarc(x1,y1,x2,y2,x3,y3)314 LINEPTR pointarc (x1,y1, x2,y2, x3,y3)
315 float x1,y1, x2,y2, x3,y3;
316 {
317 float A, B, C, D, E, F;
318 float denom, x, y;
319 float startang, midang, endang;
320 A = -2.0*(x2 - x1);
321 B = -2.0*(y2 - y1);
322 C = -2.0*(x3 - x2);
323 D = -2.0*(y3 - y2);
324 denom = A*D - B*C;
325 if (fabs(denom) < EPSILON) {
326 dprintf "pointarc: (%f,%f) (%f,%f) (%f,%f) collinear\n", x1,y1, x2,y2, x3,y3);
327 return (linegen (x1,y1, x3,y3));
328 }
329 E = x1*x1 + y1*y1 - x2*x2 - y2*y2;
330 F = x2*x2 + y2*y2 - x3*x3 - y3*y3;
331 x = E*D - F*B;
332 x /= denom;
333 y = A*F - C*E;
334 y /= denom;
335 startang = rprin(atan2 (y1-y, x1-x));
336 midang = rprin(atan2 (y2-y, x2-x));
337 endang = rprin(atan2 (y3-y, x3-x));
338 angorder (&startang, midang, &endang);
339 dprintf "pointarc: (%f,%f) (%f,%f) (%f,%f)\n", x1,y1, x2,y2, x3,y3);
340 dprintf "pointarc: (%f,%f) %f\n", x, y, hypot(x1-x,y1-y));
341 dprintf "pointarc: /_%f -- /_%f\n", startang, endang);
342 return (angularc (x, y, hypot(x1-x,y1-y), startang, endang));
343 }
344
edgearc(x1,y1,x2,y2,x3,y3)345 EDGEPTR edgearc (x1,y1, x2,y2, x3,y3)
346 float x1,y1, x2,y2, x3,y3;
347 {
348 EDGEPTR newguy;
349 tryalloc(newguy,EDGENODE);
350 newguy->fax = (ARCPTR) pointarc (x1,y1, x2,y2, x3,y3);
351 if (newguy->fax->kind == LINE) {
352 newguy->sx = newguy->etx = x1;
353 newguy->sy = newguy->ety = y1;
354 newguy->ex = newguy->stx = x3;
355 newguy->ey = newguy->sty = y3;
356 tryfree(newguy->fax);
357 newguy->fax = NULL;
358 newguy->flipped = FALSE;
359 } else if (newguy->fax->kind == ARC) {
360 ARCPTR temp;
361 temp = newguy->fax;
362 newguy->sx = x1;
363 newguy->sy = y1;
364 newguy->ex = x3;
365 newguy->ey = y3;
366 newguy->stx = temp->x0 + fabs(temp->radius)*cos(temp->theta1 + 0.2);
367 newguy->sty = temp->y0 + fabs(temp->radius)*sin(temp->theta1 + 0.2);
368 newguy->etx = temp->x0 + fabs(temp->radius)*cos(temp->theta2 - 0.2);
369 newguy->ety = temp->y0 + fabs(temp->radius)*sin(temp->theta2 - 0.2);
370 if ((fabs(newguy->sx - temp->x1) > EPSILON)
371 || (fabs(newguy->sy - temp->y1) > EPSILON)) {
372 newguy->flipped = TRUE;
373 fexch(&newguy->stx,&newguy->etx);
374 fexch(&newguy->sty,&newguy->ety);
375 } else
376 newguy->flipped = FALSE;
377 dprintf "edgearc: (%f,%f) --> (%f,%f)\n",
378 newguy->sx, newguy->sy,
379 newguy->ex, newguy->ey
380 );
381 dprintf "edgearc: st (%f,%f); et (%f,%f)\n",
382 newguy->stx, newguy->sty,
383 newguy->etx, newguy->ety
384 );
385 dprintf "edgearc: %sflipped\n", newguy->flipped?"":"UN");
386 } else impossible ("edgearc");
387 return (newguy);
388 }
389
textgen(command,string,x0,y0)390 LINEPTR textgen (command, string, x0, y0)
391 int command;
392 char *string;
393 float x0,
394 y0;
395 {
396 register TEXTPTR newguy;
397 tryalloc(newguy,TEXTNODE);
398 newguy->kind = STRING;
399 newguy->command = command;
400 newguy->string = string;
401 newguy->x0 = x0;
402 newguy->y0 = y0;
403 return ((LINEPTR) newguy);
404 }
405
splgen(knotlist)406 LINEPTR splgen (knotlist)
407 EXPRPTR knotlist;
408 {
409 register SPLPTR newguy;
410 tryalloc(newguy,SPLNODE);
411 newguy->kind = SPLINE;
412 newguy->knotlist = knotlist;
413 return ((LINEPTR) newguy);
414 }
415
strgen(command,string,at)416 STRPTR strgen (command, string, at)
417 int command;
418 char *string;
419 EXPR at;
420 {
421 register STRPTR newguy;
422 tryalloc(newguy,STRNODE);
423 newguy->command = command;
424 newguy->string = string;
425 newguy->at = at;
426 return (newguy);
427 }
428
429
eqngen(eqn,noad)430 EQNPTR eqngen (eqn, noad)
431 EXPR eqn;
432 NOADPTR noad;
433 {
434 register EQNPTR newguy;
435 tryalloc(newguy,EQNNODE);
436 newguy->eqn = eqn;
437 newguy->noad = noad;
438 return (newguy);
439 }
opqgen(code,alpha)440 OPQPTR opqgen (code, alpha)
441 int code;
442 float alpha;
443 {
444 OPQPTR newguy;
445 tryalloc(newguy,OPQNODE);
446 newguy->code = code;
447 newguy->alpha = alpha;
448 return (newguy);
449 }
450
depfree(doomed)451 void depfree (doomed)
452 DEPPTR doomed;
453 {
454 register DEPPTR doomwalk;
455 if (!doomed || doomed == depavt)
456 return;
457 if (!depavh) {
458 depavt = depavh = doomed;
459 while (depavt->next)
460 depavt = depavt->next;
461 return;
462 }
463 doomwalk = doomed;
464 while (doomwalk->next) {
465 if (doomwalk->next == depavt)
466 return;
467 doomwalk = doomwalk->next;
468 }
469 depavt->next = doomed;
470 depavt = doomwalk;
471 }
472
nextfree(doomed)473 void nextfree (doomed)
474 DEPPTR doomed;
475 {
476 register DEPPTR walk;
477 while (doomed) {
478 walk = doomed->next;
479 tryfree(doomed);
480 doomed = walk;
481 }
482 }
483
namefree(doomed)484 void namefree (doomed)
485 NAMEPTR doomed;
486 {
487 nextfree ((DEPPTR) doomed);
488 }
489
exprlsfree(doomed)490 void exprlsfree (doomed)
491 EXPRPTR doomed;
492 {
493 register EXPRPTR walk;
494 while (doomed) {
495 walk = doomed->next;
496 exprfree (doomed->expr);
497 tryfree(doomed);
498 doomed = walk;
499 }
500 }
501
linefree(doomed)502 void linefree (doomed)
503 LINEPTR doomed;
504 {
505 nextfree ((DEPPTR) doomed);
506 }
507
intlfree(doomed)508 void intlfree (doomed)
509 INTLPTR doomed;
510 {
511 depfree ((DEPPTR) doomed->left);
512 depfree ((DEPPTR) doomed->right);
513 tryfree(doomed);
514 }
515
noadfree(doomed)516 void noadfree (doomed)
517 NOADPTR doomed;
518 {
519 if (!doomed)
520 return;
521 noadfree (doomed->son);
522 noadfree (doomed->brother);
523 varfree (doomed->edgevarlist);
524 varfree (doomed->boxvarlist);
525 linefree(doomed->linelist);
526 tryfree(doomed);
527 }
528
varfree(doomed)529 void varfree (doomed)
530 VARPTR doomed;
531 {
532 if (!doomed)
533 return;
534 varfree (doomed->next);
535 depfree (doomed->deplist);
536 tryfree(doomed);
537 }
538
539
exprfree(doomed)540 void exprfree (doomed)
541 EXPR doomed;
542 {
543 if (!doomed)
544 return;
545 if (!((EXTLPTR) doomed)->leaf) {
546 /* convention for functions (name in left, arg list hanging
547 /* off right) will ream you if not careful
548 /* This also depends on the allocator not complaining if
549 /* you free things twice with no intervening allocation.
550 /* (see processing of alpha[x,y] in idyac.y) */
551 if (((INTLPTR) doomed)->oper == NAME) {
552 exprfree (((EXPRPTR)((INTLPTR) doomed)->right)->expr);
553 tryfree(((INTLPTR) doomed)->right);
554 } else if (((INTLPTR) doomed)->oper == ';') {
555 depfree ((DEPPTR)((INTLPTR) doomed)->left);
556 depfree ((DEPPTR)((INTLPTR) doomed)->right);
557 } else {
558 exprfree (((INTLPTR) doomed)->left);
559 exprfree (((INTLPTR) doomed)->right);
560 }
561 }
562 tryfree(doomed);
563 }
564
565
566
boxfree(doomed)567 void boxfree (doomed)
568 BOXPTR doomed;
569 {
570 register STMTPTR curstmt, nextstmt;
571 for (curstmt = doomed->stmtlist;
572 curstmt;
573 curstmt = nextstmt) {
574 switch (curstmt->kind) {
575 case '=':
576 exprfree ((EXPR) curstmt->stmt);
577 break;
578 case CONN:
579 exprlsfree ((EXPRPTR) curstmt->stmt);
580 break;
581 case USING:
582 exprfree (((PENPTR) curstmt->stmt)->from);
583 exprfree (((PENPTR) curstmt->stmt)->to);
584 exprfree (((PENPTR) curstmt->stmt)->copies);
585 exprfree (((PENPTR) curstmt->stmt)->start);
586 exprfree (((PENPTR) curstmt->stmt)->end);
587 boxfree (((PENPTR) curstmt->stmt)->pen);
588 tryfree(curstmt->stmt);
589 break;
590 case PUT:
591 boxfree (((PUTPTR) curstmt->stmt)->parm);
592 tryfree(curstmt->stmt);
593 break;
594 case DRAW:
595 tryfree(curstmt->stmt);
596 break;
597 case STRING:
598 /* if using malloc to get string space, can use the real free here */
599 free(((STRPTR) curstmt->stmt)->string);
600 exprfree (((STRPTR) curstmt->stmt)->at);
601 tryfree(curstmt->stmt);
602 break;
603 case SPLINE:
604 exprlsfree ((EXPRPTR) curstmt->stmt);
605 break;
606 case OPAQUE:
607 tryfree(curstmt->stmt);
608 break;
609 case BDLIST:
610 exprlsfree ((EXPRPTR) curstmt->stmt);
611 break;
612 case VAR:
613 namefree ((NAMEPTR) curstmt->stmt);
614 break;
615 }
616 nextstmt = curstmt->next;
617 tryfree(curstmt);
618 }
619 }
620
emergency()621 void emergency ()
622 {
623 nextfree (depavh);
624 depavh = depavt = NULL;
625 }
626