/[ascend]/trunk/base/generic/compiler/visitinst.c
ViewVC logotype

Contents of /trunk/base/generic/compiler/visitinst.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download) (as text)
Wed Nov 30 05:53:20 2005 UTC (18 years, 7 months ago) by johnpye
File MIME type: text/x-csrc
File size: 23722 byte(s)
My first commit:
Added 'error_reporter' for standardised error reporting
Working on getting external functions running again
Also: issue 130, issue 68, issue 131, issue 89, issue 127, issue 138, issue 94.
1 /*
2 * Ascend Instance Tree Type Visit Implementation
3 * by Tom Epperly
4 * 9/3/89
5 * Version: $Revision: 1.21 $
6 * Version control file: $RCSfile: visitinst.c,v $
7 * Date last modified: $Date: 1998/02/26 15:59:37 $
8 * Last modified by: $Author: mthomas $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1996 Benjamin Allan
13 * based on instance.c
14 * Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
15 *
16 * The Ascend Language Interpreter is free software; you can redistribute
17 * it and/or modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of the
19 * License, or (at your option) any later version.
20 *
21 * The Ascend Language Interpreter is distributed in hope that it will be
22 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with the program; if not, write to the Free Software Foundation,
28 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
29 * COPYING.
30 *
31 */
32
33 #include <stdarg.h>
34 #include "utilities/ascConfig.h"
35 #include "utilities/ascPanic.h"
36 #include "utilities/ascMalloc.h"
37 #include "general/list.h"
38 #include "general/dstring.h"
39 #include "compiler/compiler.h"
40 #include "compiler/symtab.h"
41 #include "compiler/fractions.h"
42 #include "compiler/dimen.h"
43 #include "compiler/functype.h"
44 #include "compiler/types.h"
45 #include "compiler/child.h"
46 #include "compiler/type_desc.h"
47 #include "compiler/instance_enum.h"
48 #include "compiler/instance_name.h"
49 #include "compiler/instquery.h"
50 #include "compiler/instance_io.h"
51 #include "compiler/instmacro.h"
52 #include "compiler/parentchild.h"
53 #include "compiler/when_util.h"
54 #include "compiler/instance_types.h"
55 #include "compiler/tmpnum.h"
56 #include "compiler/visitinst.h"
57
58 #ifndef lint
59 static CONST char InstanceVisitModuleID[] = "$Id: visitinst.c,v 1.21 1998/02/26 15:59:37 mthomas Exp $";
60 #endif
61
62 unsigned long global_visit_num = 0;
63 int g_iscomplete = 1;
64 /************* VisitInstance stuff **************************************/
65
66 #define OLDCHECKVISIT 0
67 #if OLDCHECKVISIT
68 /* returns 1 if not visited yet, 0 if been here already. */
69 static int CheckVisitNumber(struct Instance *i)
70 {
71 AssertMemory(i);
72 switch(i->t) {
73 case MODEL_INST:
74 if (global_visit_num > MOD_INST(i)->visited) {
75 MOD_INST(i)->visited = global_visit_num;
76 return 1;
77 }
78 else return 0;
79 case REAL_CONSTANT_INST:
80 if (global_visit_num > RC_INST(i)->visited) {
81 RC_INST(i)->visited = global_visit_num;
82 return 1;
83 }
84 else return 0;
85 case BOOLEAN_CONSTANT_INST:
86 if (global_visit_num > BC_INST(i)->visited) {
87 BC_INST(i)->visited = global_visit_num;
88 return 1;
89 }
90 else return 0;
91 case INTEGER_CONSTANT_INST:
92 if (global_visit_num > IC_INST(i)->visited) {
93 IC_INST(i)->visited = global_visit_num;
94 return 1;
95 }
96 else return 0;
97 case SYMBOL_CONSTANT_INST:
98 if (global_visit_num > SYMC_INST(i)->visited) {
99 SYMC_INST(i)->visited = global_visit_num;
100 return 1;
101 }
102 else return 0;
103 case REAL_ATOM_INST:
104 if (global_visit_num > RA_INST(i)->visited) {
105 RA_INST(i)->visited = global_visit_num;
106 return 1;
107 }
108 else return 0;
109 case BOOLEAN_ATOM_INST:
110 if (global_visit_num > BA_INST(i)->visited) {
111 BA_INST(i)->visited = global_visit_num;
112 return 1;
113 }
114 else return 0;
115 case INTEGER_ATOM_INST:
116 if (global_visit_num > IA_INST(i)->visited) {
117 IA_INST(i)->visited = global_visit_num;
118 return 1;
119 }
120 else return 0;
121 case SET_ATOM_INST:
122 if (global_visit_num > SA_INST(i)->visited) {
123 SA_INST(i)->visited = global_visit_num;
124 return 1;
125 } else {
126 return 0;
127 }
128 case SYMBOL_ATOM_INST:
129 if (global_visit_num > SYMA_INST(i)->visited) {
130 SYMA_INST(i)->visited = global_visit_num;
131 return 1;
132 } else {
133 return 0;
134 }
135 case REL_INST:
136 if (global_visit_num > RELN_INST(i)->visited) {
137 RELN_INST(i)->visited = global_visit_num;
138 return 1;
139 } else {
140 return 0;
141 }
142 case LREL_INST:
143 if (global_visit_num > LRELN_INST(i)->visited) {
144 LRELN_INST(i)->visited = global_visit_num;
145 return 1;
146 } else {
147 return 0;
148 }
149 case WHEN_INST:
150 if (global_visit_num > W_INST(i)->visited) {
151 W_INST(i)->visited = global_visit_num;
152 return 1;
153 } else {
154 return 0;
155 }
156 case ARRAY_INT_INST:
157 case ARRAY_ENUM_INST:
158 if (global_visit_num > ARY_INST(i)->visited) {
159 ARY_INST(i)->visited = global_visit_num;
160 return 1;
161 } else {
162 return 0;
163 }
164 case DUMMY_INST:
165 if (global_visit_num > D_INST(i)->visited) {
166 D_INST(i)->visited = global_visit_num;
167 return 1;
168 } else {
169 return 0;
170 }
171 case REAL_INST:
172 case INTEGER_INST:
173 case BOOLEAN_INST:
174 case SET_INST:
175 case SYMBOL_INST:
176 return 1; /* assumed always unvisited */
177 /* since they have exactly one ATOM parent */
178 default:
179 Asc_Panic(2, "VisitInstanceTree",
180 "Instance tree contains illegal instance.");
181 break;
182 }
183 }
184 #else /* oldcheckvisit alternative, faster? needs testing */
185
186 /* returns 1 if not visited yet, 0 if been here already or i bogus. */
187 static int CheckVisitNumber(struct Instance *i)
188 {
189 AssertMemory(i);
190 if (i->t & IERRINST) {
191 FPRINTF(ASCERR,"CheckVisitNumber called with bad instance\n");
192 return 0;
193 }
194 /* models arrays atoms relations constants */
195 if (IsCompoundInstance(i)) {
196 /* models arrays, maybe lists in future */
197 if (IsArrayInstance(i)) {
198 /* arrays */
199 if (global_visit_num > ARY_INST(i)->visited) {
200 ARY_INST(i)->visited = global_visit_num;
201 return 1;
202 } else {
203 return 0;
204 }
205 } else {
206 /* models */
207 if (i->t == MODEL_INST && global_visit_num > MOD_INST(i)->visited) {
208 MOD_INST(i)->visited = global_visit_num;
209 return 1;
210 } else {
211 return 0;
212 /* sim instances are assumed visited, especially since they
213 * should never be seen by VisitTree.
214 */
215 }
216 }
217 } else { /* atoms and relations constants */
218 if (IsAtomicInstance(i)) {
219 if (global_visit_num > CA_INST(i)->visited) {
220 CA_INST(i)->visited = global_visit_num;
221 return 1;
222 } else {
223 return 0;
224 }
225 }
226 if (IsConstantInstance(i)) {
227 /* constants */
228 if (global_visit_num > CI_INST(i)->visited) {
229 CI_INST(i)->visited = global_visit_num;
230 return 1;
231 } else {
232 return 0;
233 }
234 }
235 /* would be nice to have a CommonEqnInstance
236 * here for whenrellogrel CE_INST.
237 */
238 if (i->t == REL_INST) {
239 if (global_visit_num > RELN_INST(i)->visited) {
240 RELN_INST(i)->visited = global_visit_num;
241 return 1;
242 } else {
243 return 0;
244 }
245 }
246 if (i->t == LREL_INST) {
247 if (global_visit_num > LRELN_INST(i)->visited) {
248 LRELN_INST(i)->visited = global_visit_num;
249 return 1;
250 } else {
251 return 0;
252 }
253 }
254 if (i->t == WHEN_INST) {
255 if (global_visit_num > W_INST(i)->visited) {
256 W_INST(i)->visited = global_visit_num;
257 return 1;
258 } else {
259 return 0;
260 }
261 }
262 }
263 /* fundamentals and rogues */
264 if (IsFundamentalInstance(i) ) {
265 /* fundamentals assumed always unvisited */
266 return 1;
267 }
268 if ( InstanceKind(i)==DUMMY_INST) {
269 if (global_visit_num > D_INST(i)->visited) {
270 D_INST(i)->visited = global_visit_num;
271 return 1;
272 } else {
273 return 0;
274 }
275 } else {
276 /* rogues */
277 Asc_Panic(2, "VisitInstanceTree",
278 "VisitInstanceTree: Instance tree contains illegal instance.");
279 exit(2);/* Needed to keep gcc from whining */
280 }
281 }
282 #endif /* OLDCHECKVISIT */
283
284 #if 0 /* old unused code. might be handy for debugging someday */
285 /* if visit number of i is nonzero sets it 0 and returns 1, else 0 */
286 static int ZeroVisitNumber(struct Instance *i)
287 {
288 AssertMemory(i);
289 switch(i->t) {
290 case MODEL_INST:
291 if (MOD_INST(i)->visited) {
292 MOD_INST(i)->visited=0;
293 return 1;
294 }
295 else return 0;
296 case REAL_CONSTANT_INST:
297 if (RC_INST(i)->visited) {
298 RC_INST(i)->visited=0;
299 return 1;
300 }
301 else return 0;
302 case BOOLEAN_CONSTANT_INST:
303 if (BC_INST(i)->visited) {
304 BC_INST(i)->visited=0;
305 return 1;
306 }
307 else return 0;
308 case INTEGER_CONSTANT_INST:
309 if (IC_INST(i)->visited) {
310 IC_INST(i)->visited=0;
311 return 1;
312 }
313 else return 0;
314 case SYMBOL_CONSTANT_INST:
315 if (SYMC_INST(i)->visited) {
316 SYMC_INST(i)->visited=0;
317 return 1;
318 }
319 else return 0;
320 case REAL_ATOM_INST:
321 if (RA_INST(i)->visited) {
322 RA_INST(i)->visited=0;
323 return 1;
324 }
325 else return 0;
326 case BOOLEAN_ATOM_INST:
327 if (BA_INST(i)->visited) {
328 BA_INST(i)->visited=0;
329 return 1;
330 }
331 else return 0;
332 case INTEGER_ATOM_INST:
333 if (IA_INST(i)->visited) {
334 IA_INST(i)->visited=0;
335 return 1;
336 }
337 else return 0;
338 case SET_ATOM_INST:
339 if (SA_INST(i)->visited) {
340 SA_INST(i)->visited=0;
341 return 1;
342 }
343 else return 0;
344 case SYMBOL_ATOM_INST:
345 if (SYMA_INST(i)->visited) {
346 SYMA_INST(i)->visited=0;
347 return 1;
348 }
349 else return 0;
350 case REL_INST:
351 if (RELN_INST(i)->visited) {
352 RELN_INST(i)->visited=0;
353 return 1;
354 }
355 else return 0;
356 case LREL_INST:
357 if (LRELN_INST(i)->visited) {
358 LRELN_INST(i)->visited=0;
359 return 1;
360 }
361 else return 0;
362 case WHEN_INST:
363 if (W_INST(i)->visited) {
364 W_INST(i)->visited=0;
365 return 1;
366 }
367 else return 0;
368 case ARRAY_INT_INST:
369 case ARRAY_ENUM_INST:
370 if (ARY_INST(i)->visited) {
371 ARY_INST(i)->visited=0;
372 return 1;
373 }
374 else return 0;
375 case REAL_INST:
376 case INTEGER_INST:
377 case BOOLEAN_INST:
378 case SET_INST:
379 case SYMBOL_INST:
380 case DUMMY_INST:
381 return 0; /* assumed always unvisited */
382 /* since they have exactly one ATOM parent */
383 default:
384 Asc_Panic(2, NULL, "ZeroVisitInstanceTree:"
385 " Instance tree contains illegal instance.\n");
386 /*NOTREACHED*/
387 }
388 exit(2); /* Needed to keep gcc from whining */
389 }
390
391 #endif /* old unused code. might be handy for debugging someday */
392
393 static
394 void WriteWhereNull(FILE *f, struct Instance *i)
395 {
396 (void) i;
397 FPRINTF(f,"Null instance in tree at ???? (null child of instance of type '%s')\n", SCP(InstanceType(i)) );
398 g_iscomplete=0;
399 }
400
401 /* set global_visit_num = 0 after calling this for all instances
402 * in simulation universe and prototype libraries.
403 */
404 void ResetVisitCounts(struct Instance *inst)
405 {
406 unsigned long nc,c;
407 struct Instance *child;
408 AssertMemory(inst);
409 if (InstanceKind(inst) == SIM_INST) return; /* ack!! */
410 if (CheckVisitNumber(inst)){
411 /* subtree has been visited in the past, not 0d */
412 if (NotAtom(inst)) {
413 nc = NumberChildren(inst);
414 for(c=1;c<=nc;c++) {
415 if ((child = InstanceChild(inst,c))!=NULL) {
416 ResetVisitCounts(child);
417 /* don't really care about NULL */
418 }
419 }
420 }
421 }
422 }
423
424 static void SlowVisitTree(struct Instance *inst,
425 VisitProc proc,
426 int depth, int leaf)
427 {
428 unsigned long nc,c;
429 struct Instance *child;
430 unsigned nullchildren=0;
431
432 AssertMemory(inst); /* If null got here, die */
433 if (CheckVisitNumber(inst)){ /* Not here another way already.*/
434 if (!depth) (*proc)(inst); /* Apply on the way down, if top down.*/
435 if (leaf||NotAtom(inst)) { /* Go down on all children not null.*/
436 nc = NumberChildren(inst);
437 for(c=1;c<=nc;c++) {
438 if ((child = InstanceChild(inst,c))!=NULL) { /* don't go down NULL */
439 SlowVisitTree(child,proc,depth,leaf);
440 } else {
441 nullchildren++;
442 /* no point in whining about someplace we can't give a name */
443 }
444 }
445 if (nullchildren) {
446 FPRINTF(ASCERR,"Found %u NULL children of ",nullchildren);
447 WriteInstanceName(ASCERR,inst,NULL);
448 FPRINTF(ASCERR,".\n");
449 }
450 }
451 if (depth) (*proc)(inst); /* Apply on way up, if bottom up.*/
452 }
453 }
454
455 void SlowVisitInstanceTree(struct Instance *inst,
456 VisitProc proc,
457 int depth, int leaf)
458 {
459 global_visit_num++;
460 AssertMemory(inst);
461 if (inst!=NULL) {
462 SlowVisitTree(inst,proc,depth,leaf);
463 } else {
464 FPRINTF(ASCERR,"SlowVisitInstanceTree called with NULL.");
465 }
466 }
467
468 static
469 void FastVisitTree(struct Instance *inst, VisitProc proc,int depth, int leaf)
470 {
471 unsigned long nc,c;
472 struct Instance *child;
473 AssertMemory(inst);
474 if (CheckVisitNumber(inst)){
475 if (!depth) (*proc)(inst);
476 if (leaf||NotAtom(inst)) {
477 nc = NumberChildren(inst);
478 for(c=1;c<=nc;c++)
479 if ((child = InstanceChild(inst,c))!=NULL) {
480 FastVisitTree(child,proc,depth,leaf);
481 } else {
482 WriteWhereNull(ASCERR,inst);
483 }
484 }
485 if (depth) (*proc)(inst);
486 }
487 }
488
489 static
490 void SilentVisitTree(struct Instance *inst,VisitProc proc, int depth, int leaf)
491 {
492 unsigned long nc,c;
493 struct Instance *child;
494 AssertMemory(inst);
495 if (CheckVisitNumber(inst)){
496 if (!depth) (*proc)(inst);
497 if (leaf||NotAtom(inst)) {
498 nc = NumberChildren(inst);
499 for(c=1;c<=nc;c++) {
500 if ((child = InstanceChild(inst,c))!=NULL) {
501 SilentVisitTree(child,proc,depth,leaf);
502 }
503 }
504 }
505 if (depth) (*proc)(inst);
506 }
507 }
508
509 void FastVisitInstanceTree(struct Instance *inst, VisitProc proc,
510 int depth, int leaf)
511 {
512 global_visit_num++;
513 AssertMemory(inst);
514 FastVisitTree(inst,proc,depth,leaf);
515 }
516
517 void SilentVisitInstanceTree(struct Instance *inst, VisitProc proc,
518 int depth, int leaf)
519 {
520 global_visit_num++;
521 AssertMemory(inst);
522 SilentVisitTree(inst,proc,depth,leaf);
523 }
524
525 #define IVIT_MIN_LEN 20
526 static
527 void IndexedVisitCheckSize(unsigned long **llist, unsigned int *llen, int len)
528 {
529 unsigned long *old;
530 if ( *llen < (unsigned int)len || !(*llen) || llist == NULL) {
531 old = *llist;
532 if (*llist != NULL) {
533 *llist = (unsigned long *)ascrealloc(*llist,
534 sizeof(unsigned long)*(*llen+IVIT_MIN_LEN));
535 } else {
536 *llist = (unsigned long *)ascmalloc(sizeof(unsigned long)*IVIT_MIN_LEN);
537 }
538 if (*llist == NULL) {
539 *llist = old;
540 Asc_Panic(2,"IndexedVisitInstanceTree","insufficient memory");
541 }
542 }
543 }
544
545 static
546 void IndexedVisitTree(struct Instance *inst, IndexedVisitProc proc,
547 int depth, int leaf,
548 unsigned long **llist, unsigned int *llen, int len,
549 VOIDPTR userdata)
550 {
551 unsigned long nc,c;
552 struct Instance *child;
553 int oldlen;
554
555 AssertMemory(inst);
556 if (CheckVisitNumber(inst)){
557 if (!depth) (*proc)(inst,*llist,len,userdata);
558 if (leaf||NotAtom(inst)) {
559 oldlen = len;
560 len++;
561 nc = NumberChildren(inst);
562 IndexedVisitCheckSize(llist,llen,len);
563 for (c = 1; c <= nc; c++) {
564 child = InstanceChild(inst,c);
565 if (child != NULL) {
566 (*llist)[oldlen] = c;
567 IndexedVisitTree(child,proc,depth,leaf,llist,llen,len,userdata);
568 }
569 }
570 len--;
571 }
572 if (depth) (*proc)(inst,*llist,len,userdata);
573 }
574 }
575
576 void IndexedVisitInstanceTree(struct Instance *inst, IndexedVisitProc proc,
577 int depth, int leaf, unsigned long **llist,
578 unsigned int *llen, VOIDPTR userdata)
579 {
580 global_visit_num++;
581 AssertMemory(inst);
582
583 assert(llist != NULL);
584 assert(llen != NULL);
585 IndexedVisitCheckSize(llist,llen,IVIT_MIN_LEN);
586
587 IndexedVisitTree(inst,proc,depth,leaf,llist,llen,0,userdata);
588 }
589 #undef IVIT_MIN_LEN
590
591 static
592 void SilentVisitTreeTwo(struct Instance *inst,
593 VisitTwoProc proc,
594 int depth, int leaf,VOIDPTR userdata)
595 {
596 unsigned long nc,c;
597 struct Instance *child;
598 AssertMemory(inst);
599 if (CheckVisitNumber(inst)){
600 if (!depth) {
601 (*proc)(inst,userdata);
602 }
603 if (leaf||NotAtom(inst)) {
604 nc = NumberChildren(inst);
605 for(c=1;c<=nc;c++) {
606 if ( (child = InstanceChild(inst,c)) !=NULL) {
607 SilentVisitTreeTwo(child,proc,depth,leaf,userdata);
608 }
609 }
610 }
611 if (depth) {
612 (*proc)(inst,userdata);
613 }
614 }
615 }
616
617 static
618 void VisitTreeTwo(struct Instance *inst,
619 VisitTwoProc proc,
620 int depth, int leaf,VOIDPTR userdata)
621 {
622 unsigned long nc,c;
623 struct Instance *child;
624 AssertMemory(inst);
625 if (CheckVisitNumber(inst)){
626 if (!depth) {
627 (*proc)(inst,userdata);
628 }
629 if (leaf||NotAtom(inst)) {
630 nc = NumberChildren(inst);
631 for(c=1;c<=nc;c++) {
632 if ( (child = InstanceChild(inst,c)) !=NULL) {
633 VisitTreeTwo(child,proc,depth,leaf,userdata);
634 } else {
635 WriteWhereNull(ASCERR,inst);
636 }
637 }
638 }
639 if (depth) {
640 (*proc)(inst,userdata);
641 }
642 }
643 }
644
645
646 void SilentVisitInstanceTreeTwo(struct Instance *inst,
647 VisitTwoProc proc,
648 int depth, int leaf,
649 VOIDPTR userdata)
650 {
651 global_visit_num++;
652 AssertMemory(inst);
653 SilentVisitTreeTwo(inst,proc,depth,leaf,userdata);
654 }
655
656 void VisitInstanceTreeTwo(struct Instance *inst,
657 VisitTwoProc proc,
658 int depth, int leaf,
659 VOIDPTR userdata)
660 {
661 global_visit_num++;
662 AssertMemory(inst);
663 VisitTreeTwo(inst,proc,depth,leaf,userdata);
664 }
665
666 static
667 void SilentVisitFringeTwo(struct Instance *inst,
668 VisitTwoProc proc, VisitTwoProc proc2,
669 int depth, int leaf,VOIDPTR userdata)
670 {
671 unsigned long nc,c;
672 struct Instance *child;
673 AssertMemory(inst);
674 if (CheckVisitNumber(inst)){
675 if (!depth) {
676 (*proc)(inst,userdata);
677 }
678 if (leaf||NotAtom(inst)) {
679 nc = NumberChildren(inst);
680 for(c=1;c<=nc;c++) {
681 if ( (child = InstanceChild(inst,c)) !=NULL) {
682 SilentVisitFringeTwo(child,proc,proc2,depth,leaf,userdata);
683 }
684 }
685 }
686 if (depth) {
687 (*proc)(inst,userdata);
688 }
689 } else {
690 /* play it again sam */
691 (*proc2)(inst,userdata);
692 }
693 }
694
695 static
696 void VisitFringeTwo(struct Instance *inst,
697 VisitTwoProc proc, VisitTwoProc proc2,
698 int depth, int leaf,VOIDPTR userdata)
699 {
700 unsigned long nc,c;
701 struct Instance *child;
702 AssertMemory(inst);
703 if (CheckVisitNumber(inst)){
704 if (!depth) {
705 (*proc)(inst,userdata);
706 }
707 if (leaf||NotAtom(inst)) {
708 nc = NumberChildren(inst);
709 for(c=1;c<=nc;c++) {
710 if ( (child = InstanceChild(inst,c)) !=NULL) {
711 VisitFringeTwo(child,proc,proc2,depth,leaf,userdata);
712 } else {
713 WriteWhereNull(ASCERR,inst);
714 }
715 }
716 }
717 if (depth) {
718 (*proc)(inst,userdata);
719 }
720 } else {
721 /* play it again sam */
722 (*proc2)(inst,userdata);
723 }
724 }
725
726
727 void SilentVisitInstanceFringeTwo(struct Instance *inst,
728 VisitTwoProc proc,
729 VisitTwoProc proc2,
730 int depth, int leaf,
731 VOIDPTR userdata)
732 {
733 global_visit_num++;
734 AssertMemory(inst);
735 SilentVisitFringeTwo(inst,proc,proc2,depth,leaf,userdata);
736 }
737
738 void VisitInstanceFringeTwo(struct Instance *inst,
739 VisitTwoProc proc,
740 VisitTwoProc proc2,
741 int depth, int leaf,
742 VOIDPTR userdata)
743 {
744 global_visit_num++;
745 AssertMemory(inst);
746 VisitFringeTwo(inst,proc,proc2,depth,leaf,userdata);
747 }
748
749 static
750 void SilentVisitRootsTwo(struct Instance *inst, VisitTwoProc proc,
751 int depth,VOIDPTR userdata)
752 {
753 unsigned long nc,c;
754 struct Instance *parent;
755 AssertMemory(inst);
756 if (CheckVisitNumber(inst)) {
757 if (!depth) {
758 (*proc)(inst,userdata);
759 }
760 nc = NumberParents(inst);
761 for (c=1; c <= nc; c++) {
762 parent = InstanceParent(inst,c);
763 assert(parent != NULL);
764 SilentVisitRootsTwo(parent,proc,depth,userdata);
765 }
766 if (depth) {
767 (*proc)(inst,userdata);
768 }
769 }
770 }
771
772 void SilentVisitInstanceRootsTwo(struct Instance *inst, VisitTwoProc proc,
773 int depth, VOIDPTR userdata)
774 {
775 global_visit_num++;
776 AssertMemory(inst);
777 SilentVisitRootsTwo(inst,proc,depth,userdata);
778 }
779
780 /* struct visitmapinfo *MakeVisitMap(i,&len);
781 * Returns a vector len long of visitmapinfos collected showing the instances
782 * and how they are encountered in a visitation.
783 * example: (i, icld, ignd are instance ptrs)
784 *[parent,context,dir,child]
785 * [NULL,root,DOWN,1],
786 * [root,icld,DOWN,1],
787 * [icld,ignd,-UP-,1],
788 * [root,icld,-UP-,1],
789 * [NULL,root,DOWN,2],
790 * [root,icld,-UP-,1],
791 * [NULL,root,-UP-,0].
792 *
793 * The visitation indicated by this mapping (both bottom-up and top-down)
794 * is:
795 * v<i>
796 * v<i>.b
797 * ^<i>.b.f
798 * ^<i>.b
799 * v<i>
800 * ^<i>.c
801 * ^<i>
802 */
803 static
804 void MakeMap(struct Instance *inst,
805 struct Instance *parent,
806 unsigned long parents_child_num_of_i,
807 unsigned long *lensofar,
808 struct visitmapinfo *map)
809 {
810 unsigned long c,nc;
811 struct Instance *ch;
812 /* account for the children if we haven't been here before */
813 if (CheckVisitNumber(inst) && NotAtom(inst)) {
814 nc = NumberChildren(inst);
815 for (c=1; c <= nc; c++) {
816 ch=InstanceChild(inst,c);
817 if (ch != NULL) {
818 map[*lensofar].parent = parent;
819 map[*lensofar].context = inst;
820 map[*lensofar].dir = vimap_DOWN;
821 map[*lensofar].last = -1;
822 map[*lensofar].child = c;
823 (*lensofar)++;
824 MakeMap(ch,inst,c,lensofar,map);
825 }
826 }
827 }
828 /* if been here before or not, must record seeing here. */
829 map[*lensofar].parent = parent;
830 map[*lensofar].context = inst;
831 map[*lensofar].dir = vimap_UP;
832 map[*lensofar].last = (int)GetTmpNum(inst);
833 map[*lensofar].child = parents_child_num_of_i;
834 SetTmpNum(inst,*lensofar);
835 (*lensofar)++;
836 }
837
838 /*
839 * CalcMapSize(i,&len);
840 * calculate the number of instances seen and reseen in a visit
841 * and return it in len. Init len to 0 before calling.
842 */
843 static
844 void CalcMapSize(struct Instance *inst,unsigned long *lensofar)
845 {
846 unsigned long c,nc;
847 struct Instance *ch;
848 /* account for the children if we haven't been here before */
849 if (CheckVisitNumber(inst) && NotAtom(inst)) {
850 nc = NumberChildren(inst);
851 for (c=1; c <= nc; c++) {
852 ch=InstanceChild(inst,c);
853 if (ch != NULL) {
854 (*lensofar)++;
855 CalcMapSize(ch,lensofar);
856 }
857 }
858 }
859 /* if been here before or not, must record seeing here. */
860 SetTmpNum(inst,INT_MAX);
861 (*lensofar)++;
862 }
863
864 struct visitmapinfo *MakeVisitMap(struct Instance *root,unsigned long *len)
865 {
866 struct visitmapinfo *map;
867 unsigned long maplen;
868
869 AssertMemory(root);
870 global_visit_num++;
871 *len = 0; /* we don't count root entry, since we don't know context. */
872 CalcMapSize(root,len);
873 map = (struct visitmapinfo *)ascmalloc(sizeof(struct visitmapinfo) *
874 ((*len)+1)
875 );
876 if (map==NULL) {
877 return NULL;
878 }
879 /* put some crap at the END that should signal any reasonable program
880 * should also check this for being same before freeing.
881 */
882 map[*len].parent = NULL;
883 map[*len].context = NULL;
884 map[*len].child = 0UL;
885 map[*len].last = INT_MAX;
886 map[*len].dir = vimap_ERROR;
887 /* record info */
888 global_visit_num++;
889 maplen = 0;
890 MakeMap(root,NULL,0,&maplen,map);
891 assert(map[*len].parent==NULL);
892 assert(map[*len].context==NULL);
893 assert(map[*len].child==0UL);
894 assert(maplen==(*len));
895 return map;
896 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22