1 #ifndef lint
2 static char *sccsid ="action.c	(CWI)	1.1	85/03/01";
3 #endif
4 #include "ideal.h"
5 #include "y.tab.h"
6 
7 LINEPTR rbuild (noadtree, linelist)
8 NOADPTR noadtree;
9 LINEPTR linelist;
10 {
11 	STMTPTR slist[2];
12 	STMTPTR curstmt, opqstmt;
13 	NOADPTR nextnoad;
14 	int i;
15 	slist[0] = noadtree->defnode->parm->stmtlist;
16 	slist[1] = findbox (noadtree->defnode->parm->name,FALSE)->stmtlist;
17 	nextnoad = noadtree->son;
18 	if ((opqstmt = nextstmt (OPAQUE, slist[0])) || (opqstmt = nextstmt (OPAQUE, slist[1])))
19 		linelist = opqact (opqstmt, noadtree, linelist);
20 	if (noadtree->defnode->parm->name == lookup ("circle"))
21 		linelist = circact (noadtree, linelist);
22 	else if (noadtree->defnode->parm->name == lookup ("arc"))
23 		linelist = arcact (noadtree, linelist);
24 	for (i = 0; i < 2; i ++)
25 	for (curstmt = slist[i]; curstmt; curstmt = curstmt->next) {
26 	switch (curstmt->kind) {
27 		case '=':
28 			break;
29 		case CONN:
30 			linelist = connact (
31 				(EXPRPTR) curstmt->stmt,
32 				noadtree,
33 				linelist
34 			);
35 			break;
36 		case USING:
37 			linelist = penact (
38 				(PENPTR) curstmt->stmt,
39 				noadtree,
40 				linelist
41 			);
42 			break;
43 		case PUT:
44 			if (((PUTPTR)curstmt->stmt)->p_or_c == PUT)
45 				linelist = rbuild (nextnoad, linelist);
46 			else if (((PUTPTR)curstmt->stmt)->p_or_c == CONSTRUCT)
47 				nextnoad->linelist = rbuild (nextnoad, nextnoad->linelist);
48 			else impossible ("rbuild (PUT)");
49 			nextnoad = nextnoad->brother;
50 			break;
51                         case DRAW:
52 			linelist = drawact (
53 				(MISCPTR) curstmt->stmt,
54 				noadtree,
55 				linelist
56 			);
57 			break;
58 		case STRING:
59 			linelist = stract (
60 				(STRPTR) curstmt->stmt,
61 				noadtree,
62 				linelist
63 			);
64 			break;
65 		case SPLINE:
66 			linelist = splact (
67 				(EXPRPTR) curstmt->stmt,
68 				noadtree,
69 				linelist
70 			);
71 			break;
72 		case OPAQUE:
73 			break;
74 		case BDLIST:
75 			break;
76 		case VAR:
77 			break;
78 		default:
79 			impossible ("rbuild");
80 		}
81 	}
82 	return (linelist);
83 }
84 
85 LINEPTR build (noadtree, linelist)
86 NOADPTR noadtree;
87 LINEPTR linelist;
88 {
89 	LINEPTR retval;
90 	if (when_bug & 040) bug_on;
91 	retval = rbuild (noadtree, linelist);
92 	bug_off;
93 	return (retval);
94 }
95 
96 LINEPTR connact (connstmt, noadtree, linelist)
97 EXPRPTR connstmt;
98 NOADPTR noadtree;
99 LINEPTR linelist;
100 {
101 	INTLPTR frompt, topt;
102 	LINEPTR newline;
103 	EXPRPTR linwalk;
104 	newline = NULL;
105 	frompt = expreval (connstmt->expr, noadtree);
106 	linwalk = connstmt->next;
107 	while (linwalk) {
108 		topt = expreval (linwalk->expr, noadtree);
109 		if (!known(frompt) || !known(topt)) {
110 			fprintf (stderr, "ideal: indeterminate endpoints\n   >>>conn ignored\n");
111 		} else {
112 			newline = linegen (
113 				Re(frompt), Im(frompt),
114 				Re(topt), Im(topt)
115 			);
116 			dprintf "Adding line (%f,%f) to (%f,%f)\n",
117 				Re(frompt), Im(frompt),
118 				Re(topt), Im(topt)
119 			);
120 			newline->next = linelist;
121 			linelist = newline;
122 		}
123 		intlfree (frompt);
124 		frompt = topt;
125 		linwalk = linwalk->next;
126 	}
127 	intlfree (topt);
128 	return (newline);
129 }
130 
131 LINEPTR penact (penstmt, noadtree, linelist)
132 PENPTR penstmt;
133 NOADPTR noadtree;
134 LINEPTR linelist;
135 {
136 	INTLPTR frompt, topt, copies;
137 	LINEPTR newline;
138 	frompt = expreval (penstmt->from, noadtree);
139 	topt = expreval (penstmt->to, noadtree);
140 	copies = expreval (penstmt->copies, noadtree);
141 	newline = linelist;
142 	if (!known(frompt) || !known(topt) || !known(copies)) {
143 		fprintf (stderr, "ideal: indeterminate pen\n   >>>pen ignored\n");
144 	} else {
145 		PUTNODE dummyput;
146 		NOADPTR pennoad;
147 		STMTPTR ostmthead;
148 		int i;
149 
150 		dprintf "Drawing pen from (%f,%f) to (%f,%f)\n",
151 			Re(frompt),
152 			Im(frompt),
153 			Re(topt),
154 			Im(topt)
155 		);
156 
157 		/* add key statements to beginning of parameter section */
158 		dummyput.name = 0;
159 		dummyput.parm = penstmt->pen;
160 		ostmthead = dummyput.parm->stmtlist;
161 		dummyput.parm->stmtlist = stmtgen (
162 			'=',
163 			(char *) intlgen (
164 				'=',
165 				(EXPR) extlgen (namegen (lookup ("$pencnt"))),
166 				(EXPR) fextlgen (0.0)
167 			)
168 		);
169 		dummyput.parm->stmtlist->next = stmtgen (
170 			'=',
171 			(char *) intlgen (
172 				'=',
173 				penstmt->start,
174 				bracket (
175 					(EXPR) intlgen (
176 						'/',
177 						(EXPR) extlgen(namegen(lookup("$pencnt"))),
178 						(EXPR) copies
179 					),
180 					(EXPR) frompt,
181 					(EXPR) topt
182 				)
183 			)
184 		);
185 		dummyput.parm->stmtlist->next->next = stmtgen (
186 			'=',
187 			(char *) intlgen (
188 				'=',
189 				penstmt->end,
190 				bracket (
191 					(EXPR) intlgen (
192 						'/',
193 						(EXPR) intlgen (
194 							'+',
195 							(EXPR) extlgen(namegen(lookup("$pencnt"))),
196 							(EXPR) fextlgen(1.0)
197 						),
198 						(EXPR) copies
199 					),
200 					(EXPR) frompt,
201 					(EXPR) topt
202 				)
203 			)
204 		);
205 		dummyput.parm->stmtlist->next->next->next = stmtgen (
206 			VAR,
207 			(char *) namegen (lookup ("$pencnt"))
208 		);
209 		dummyput.parm->stmtlist->next->next->next->next = ostmthead;
210 		/* make N copies */
211 		for (i = 0; i < Re(copies); i ++) {
212 			((EXTLPTR) ((INTLPTR) dummyput.parm->stmtlist->stmt)->right)->info.const = i;
213 			pennoad = buildnoadtree (&dummyput);
214 			pennoad->father = noadtree;
215 			eqneval (pennoad);
216 			nl_eval ();
217 			newline = build (pennoad, newline);
218 			depvarkill ();
219 			noadfree (pennoad);
220 		}
221 	if (dummyput.parm->stmtlist->next->next->next->next != ostmthead)
222 		impossible ("penact");
223 	dummyput.parm->stmtlist->next->next->next->next = NULL;
224 	/* will have to let garbage collector get dummyput.parm */
225 	penstmt->pen->stmtlist = ostmthead;
226 	}
227 	intlfree (frompt);
228 	intlfree (topt);
229 	intlfree (copies);
230 	return (newline);
231 }
232 
233 LINEPTR drawact (noadname, noadtree, linelist)
234 MISCPTR noadname;
235 NOADPTR noadtree;
236 LINEPTR linelist;
237 {
238 	NOADPTR noadwalk;
239 	LINEPTR nuline;
240 	for (noadwalk = noadtree->son;
241 		noadwalk && (noadwalk->defnode->name != noadname->info);
242 		noadwalk = noadwalk->brother)
243 		dprintf "%s %s",
244 			idprint(noadwalk->defnode->name),
245 			idprint(noadname->info)
246 		);
247 		;
248 	if (noadwalk) {
249 		((LINEPTR) tail ((BOXPTR) noadwalk->linelist))->next = linelist;
250 		nuline = noadwalk->linelist;
251 		noadwalk->linelist = NULL;
252 		return (nuline);
253 
254 	} else {
255 		fprintf (stderr, "ideal: can't find %s to draw it\n",
256 			idprint (noadname->info)
257 		);
258 		return (linelist);
259 	}
260 }
261 
262 LINEPTR stract (strstmt, noadtree, linelist)
263 STRPTR strstmt;
264 NOADPTR noadtree;
265 LINEPTR linelist;
266 {
267 	LINEPTR newline;
268 	INTLPTR atpt;
269 	atpt = expreval (strstmt->at, noadtree);
270 	if (!known(atpt)){
271 		fprintf (stderr, "ideal: indeterminate string location\n   >>>string ignored\n");
272 		newline = linelist;
273 	} else {
274 		dprintf "Adding string %s\n",
275 			strstmt->string);
276 		newline = textgen (
277 			strstmt->command,
278 			strstmt->string,
279 			Re(atpt),
280 			Im(atpt)
281 		);
282 		newline->next = linelist;
283 	}
284 	intlfree (atpt);
285 	return (newline);
286 }
287 
288 LINEPTR circact (noadtree, linelist)
289 NOADPTR noadtree;
290 LINEPTR linelist;
291 {
292 	LINEPTR newline;
293 	INTLPTR radius, center;
294 	radius = varfind (lookup ("radius"), noadtree);
295 	center = varfind (lookup ("center"), noadtree);
296 	if (!known(radius) || !known(center)) {
297 		fprintf (stderr, "ideal: indeterminate circle\n   >>>ignored\n");
298 		newline = linelist;
299 	} else {
300 		float rad;
301 		rad = Re(radius);
302 		dprintf "Adding circle %f %f %f\n",
303 			Re(center),
304 			Im(center),
305 			rad
306 		);
307 		newline = circgen (
308 			Re(center),
309 			Im(center),
310 			rad
311 		);
312 		newline->next = linelist;
313 	}
314 	intlfree (radius);
315 	intlfree (center);
316 	return (newline);
317 }
318 
319 LINEPTR arcact (noadtree, linelist)
320 NOADPTR noadtree;
321 LINEPTR linelist;
322 {
323 	LINEPTR newline;
324 	INTLPTR start, center, end;
325 	INTLPTR temp;
326 	float radius;
327 	float startang, midang, endang;
328 	center = varfind (lookup ("center"), noadtree);
329 	start = varfind (lookup ("start"), noadtree);
330 	end = varfind (lookup ("end"), noadtree);
331 	temp = varfind (lookup ("startang"), noadtree);
332 	startang = Re(temp);
333 	tryfree(temp);
334 	temp = varfind (lookup ("midang"), noadtree);
335 	midang = Re(temp);
336 	if (fabs(midang - startang) < EPSILON)
337 		midang = startang;
338 	tryfree(temp);
339 	temp = varfind (lookup ("endang"), noadtree);
340 	endang = Re(temp);
341 	tryfree(temp);
342 	if (!radflag) {
343 		dtor(startang);
344 		dtor(midang);
345 		dtor(endang);
346 	}
347 	startang = rprin (startang);
348 	midang = rprin (midang);
349 	endang = rprin (endang);
350 	if (fabs(startang - midang) < EPSILON
351 		&& startang > endang)
352 		endang += 2*PI;
353 	radius = ((DEPPTR) (varfind (lookup ("radius"), noadtree))->left)->coeff;
354 	if (!known(center) || !known(start) || !known(end)) {
355 		fprintf (stderr, "ideal: indeterminate arc\n   >>>ignored\n");
356 		newline = linelist;
357 	} else {
358 		angorder (&startang, midang, &endang);
359 		dprintf "Adding arc %f %f %f %f %f\n",
360 			Re(center),
361 			Im(center),
362 			radius,
363 			startang,
364 			endang
365 		);
366 		newline = angularc (
367 			Re(center),
368 			Im(center),
369 			radius,
370 			startang,
371 			endang
372 		);
373 		newline->next = linelist;
374 	}
375 	intlfree (center);
376 	intlfree (start);
377 	intlfree (end);
378 	return (newline);
379 }
380 
381 LINEPTR splact (splstmt, noadtree, linelist)
382 EXPRPTR splstmt;
383 NOADPTR noadtree;
384 LINEPTR linelist;
385 {
386 	EXPRNODE knotlist;
387 	EXPRPTR knotwalk;
388 	EXPRPTR splwalk;
389 	LINEPTR nuline;
390 
391 	if (when_bug & 0200) bug_on;
392 	knotwalk = &knotlist;
393 	knotwalk->next = NULL;
394 	for (splwalk = splstmt;
395 		splwalk;
396 		splwalk = splwalk->next
397 	) {
398 		knotwalk->next = exprgen (
399 			(EXPR) expreval (
400 				splwalk->expr,
401 				noadtree
402 			)
403 		);
404 		if (!known(((INTLPTR) knotwalk->next->expr))) {
405 			fprintf (stderr, "ideal: unknown spline knot\n   >>>spline ignored\n");
406 			return (linelist);
407 		}
408 		knotwalk = knotwalk->next;
409 		dprintf "spline knot: %f %f\n",
410 			Re(((INTLPTR) knotwalk->expr)),
411 			Im(((INTLPTR) knotwalk->expr))
412 		);
413 	}
414 	nuline = splgen (knotlist.next);
415 	nuline->next = linelist;
416 	return (nuline);
417 }
418