/[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 222 - (show annotations) (download) (as text)
Fri Jan 27 04:23:20 2006 UTC (14 years, 10 months ago) by johnpye
File MIME type: text/x-csrc
File size: 23800 byte(s)
Updating for Jerry's new error_reporter syntax, bug #179
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 ERROR_REPORTER_START_HERE(ASC_PROG_ERR);
447 FPRINTF(ASCERR,"Found %u NULL children of '",nullchildren);
448 WriteInstanceName(ASCERR,inst,NULL);
449 FPRINTF(ASCERR,"'.\n");
450 error_reporter_end_flush();
451 }
452 }
453 if (depth) (*proc)(inst); /* Apply on way up, if bottom up.*/
454 }
455 }
456
457 void SlowVisitInstanceTree(struct Instance *inst,
458 VisitProc proc,
459 int depth, int leaf)
460 {
461 global_visit_num++;
462 AssertMemory(inst);
463 if (inst!=NULL) {
464 SlowVisitTree(inst,proc,depth,leaf);
465 } else {
466 FPRINTF(ASCERR,"SlowVisitInstanceTree called with NULL.");
467 }
468 }
469
470 static
471 void FastVisitTree(struct Instance *inst, VisitProc proc,int depth, int leaf)
472 {
473 unsigned long nc,c;
474 struct Instance *child;
475 AssertMemory(inst);
476 if (CheckVisitNumber(inst)){
477 if (!depth) (*proc)(inst);
478 if (leaf||NotAtom(inst)) {
479 nc = NumberChildren(inst);
480 for(c=1;c<=nc;c++)
481 if ((child = InstanceChild(inst,c))!=NULL) {
482 FastVisitTree(child,proc,depth,leaf);
483 } else {
484 WriteWhereNull(ASCERR,inst);
485 }
486 }
487 if (depth) (*proc)(inst);
488 }
489 }
490
491 static
492 void SilentVisitTree(struct Instance *inst,VisitProc proc, int depth, int leaf)
493 {
494 unsigned long nc,c;
495 struct Instance *child;
496 AssertMemory(inst);
497 if (CheckVisitNumber(inst)){
498 if (!depth) (*proc)(inst);
499 if (leaf||NotAtom(inst)) {
500 nc = NumberChildren(inst);
501 for(c=1;c<=nc;c++) {
502 if ((child = InstanceChild(inst,c))!=NULL) {
503 SilentVisitTree(child,proc,depth,leaf);
504 }
505 }
506 }
507 if (depth) (*proc)(inst);
508 }
509 }
510
511 void FastVisitInstanceTree(struct Instance *inst, VisitProc proc,
512 int depth, int leaf)
513 {
514 global_visit_num++;
515 AssertMemory(inst);
516 FastVisitTree(inst,proc,depth,leaf);
517 }
518
519 void SilentVisitInstanceTree(struct Instance *inst, VisitProc proc,
520 int depth, int leaf)
521 {
522 global_visit_num++;
523 AssertMemory(inst);
524 SilentVisitTree(inst,proc,depth,leaf);
525 }
526
527 #define IVIT_MIN_LEN 20
528 static
529 void IndexedVisitCheckSize(unsigned long **llist, unsigned int *llen, int len)
530 {
531 unsigned long *old;
532 if ( *llen < (unsigned int)len || !(*llen) || llist == NULL) {
533 old = *llist;
534 if (*llist != NULL) {
535 *llist = (unsigned long *)ascrealloc(*llist,
536 sizeof(unsigned long)*(*llen+IVIT_MIN_LEN));
537 } else {
538 *llist = (unsigned long *)ascmalloc(sizeof(unsigned long)*IVIT_MIN_LEN);
539 }
540 if (*llist == NULL) {
541 *llist = old;
542 Asc_Panic(2,"IndexedVisitInstanceTree","insufficient memory");
543 }
544 }
545 }
546
547 static
548 void IndexedVisitTree(struct Instance *inst, IndexedVisitProc proc,
549 int depth, int leaf,
550 unsigned long **llist, unsigned int *llen, int len,
551 VOIDPTR userdata)
552 {
553 unsigned long nc,c;
554 struct Instance *child;
555 int oldlen;
556
557 AssertMemory(inst);
558 if (CheckVisitNumber(inst)){
559 if (!depth) (*proc)(inst,*llist,len,userdata);
560 if (leaf||NotAtom(inst)) {
561 oldlen = len;
562 len++;
563 nc = NumberChildren(inst);
564 IndexedVisitCheckSize(llist,llen,len);
565 for (c = 1; c <= nc; c++) {
566 child = InstanceChild(inst,c);
567 if (child != NULL) {
568 (*llist)[oldlen] = c;
569 IndexedVisitTree(child,proc,depth,leaf,llist,llen,len,userdata);
570 }
571 }
572 len--;
573 }
574 if (depth) (*proc)(inst,*llist,len,userdata);
575 }
576 }
577
578 void IndexedVisitInstanceTree(struct Instance *inst, IndexedVisitProc proc,
579 int depth, int leaf, unsigned long **llist,
580 unsigned int *llen, VOIDPTR userdata)
581 {
582 global_visit_num++;
583 AssertMemory(inst);
584
585 assert(llist != NULL);
586 assert(llen != NULL);
587 IndexedVisitCheckSize(llist,llen,IVIT_MIN_LEN);
588
589 IndexedVisitTree(inst,proc,depth,leaf,llist,llen,0,userdata);
590 }
591 #undef IVIT_MIN_LEN
592
593 static
594 void SilentVisitTreeTwo(struct Instance *inst,
595 VisitTwoProc proc,
596 int depth, int leaf,VOIDPTR userdata)
597 {
598 unsigned long nc,c;
599 struct Instance *child;
600 AssertMemory(inst);
601 if (CheckVisitNumber(inst)){
602 if (!depth) {
603 (*proc)(inst,userdata);
604 }
605 if (leaf||NotAtom(inst)) {
606 nc = NumberChildren(inst);
607 for(c=1;c<=nc;c++) {
608 if ( (child = InstanceChild(inst,c)) !=NULL) {
609 SilentVisitTreeTwo(child,proc,depth,leaf,userdata);
610 }
611 }
612 }
613 if (depth) {
614 (*proc)(inst,userdata);
615 }
616 }
617 }
618
619 static
620 void VisitTreeTwo(struct Instance *inst,
621 VisitTwoProc proc,
622 int depth, int leaf,VOIDPTR userdata)
623 {
624 unsigned long nc,c;
625 struct Instance *child;
626 AssertMemory(inst);
627 if (CheckVisitNumber(inst)){
628 if (!depth) {
629 (*proc)(inst,userdata);
630 }
631 if (leaf||NotAtom(inst)) {
632 nc = NumberChildren(inst);
633 for(c=1;c<=nc;c++) {
634 if ( (child = InstanceChild(inst,c)) !=NULL) {
635 VisitTreeTwo(child,proc,depth,leaf,userdata);
636 } else {
637 WriteWhereNull(ASCERR,inst);
638 }
639 }
640 }
641 if (depth) {
642 (*proc)(inst,userdata);
643 }
644 }
645 }
646
647
648 void SilentVisitInstanceTreeTwo(struct Instance *inst,
649 VisitTwoProc proc,
650 int depth, int leaf,
651 VOIDPTR userdata)
652 {
653 global_visit_num++;
654 AssertMemory(inst);
655 SilentVisitTreeTwo(inst,proc,depth,leaf,userdata);
656 }
657
658 void VisitInstanceTreeTwo(struct Instance *inst,
659 VisitTwoProc proc,
660 int depth, int leaf,
661 VOIDPTR userdata)
662 {
663 global_visit_num++;
664 AssertMemory(inst);
665 VisitTreeTwo(inst,proc,depth,leaf,userdata);
666 }
667
668 static
669 void SilentVisitFringeTwo(struct Instance *inst,
670 VisitTwoProc proc, VisitTwoProc proc2,
671 int depth, int leaf,VOIDPTR userdata)
672 {
673 unsigned long nc,c;
674 struct Instance *child;
675 AssertMemory(inst);
676 if (CheckVisitNumber(inst)){
677 if (!depth) {
678 (*proc)(inst,userdata);
679 }
680 if (leaf||NotAtom(inst)) {
681 nc = NumberChildren(inst);
682 for(c=1;c<=nc;c++) {
683 if ( (child = InstanceChild(inst,c)) !=NULL) {
684 SilentVisitFringeTwo(child,proc,proc2,depth,leaf,userdata);
685 }
686 }
687 }
688 if (depth) {
689 (*proc)(inst,userdata);
690 }
691 } else {
692 /* play it again sam */
693 (*proc2)(inst,userdata);
694 }
695 }
696
697 static
698 void VisitFringeTwo(struct Instance *inst,
699 VisitTwoProc proc, VisitTwoProc proc2,
700 int depth, int leaf,VOIDPTR userdata)
701 {
702 unsigned long nc,c;
703 struct Instance *child;
704 AssertMemory(inst);
705 if (CheckVisitNumber(inst)){
706 if (!depth) {
707 (*proc)(inst,userdata);
708 }
709 if (leaf||NotAtom(inst)) {
710 nc = NumberChildren(inst);
711 for(c=1;c<=nc;c++) {
712 if ( (child = InstanceChild(inst,c)) !=NULL) {
713 VisitFringeTwo(child,proc,proc2,depth,leaf,userdata);
714 } else {
715 WriteWhereNull(ASCERR,inst);
716 }
717 }
718 }
719 if (depth) {
720 (*proc)(inst,userdata);
721 }
722 } else {
723 /* play it again sam */
724 (*proc2)(inst,userdata);
725 }
726 }
727
728
729 void SilentVisitInstanceFringeTwo(struct Instance *inst,
730 VisitTwoProc proc,
731 VisitTwoProc proc2,
732 int depth, int leaf,
733 VOIDPTR userdata)
734 {
735 global_visit_num++;
736 AssertMemory(inst);
737 SilentVisitFringeTwo(inst,proc,proc2,depth,leaf,userdata);
738 }
739
740 void VisitInstanceFringeTwo(struct Instance *inst,
741 VisitTwoProc proc,
742 VisitTwoProc proc2,
743 int depth, int leaf,
744 VOIDPTR userdata)
745 {
746 global_visit_num++;
747 AssertMemory(inst);
748 VisitFringeTwo(inst,proc,proc2,depth,leaf,userdata);
749 }
750
751 static
752 void SilentVisitRootsTwo(struct Instance *inst, VisitTwoProc proc,
753 int depth,VOIDPTR userdata)
754 {
755 unsigned long nc,c;
756 struct Instance *parent;
757 AssertMemory(inst);
758 if (CheckVisitNumber(inst)) {
759 if (!depth) {
760 (*proc)(inst,userdata);
761 }
762 nc = NumberParents(inst);
763 for (c=1; c <= nc; c++) {
764 parent = InstanceParent(inst,c);
765 assert(parent != NULL);
766 SilentVisitRootsTwo(parent,proc,depth,userdata);
767 }
768 if (depth) {
769 (*proc)(inst,userdata);
770 }
771 }
772 }
773
774 void SilentVisitInstanceRootsTwo(struct Instance *inst, VisitTwoProc proc,
775 int depth, VOIDPTR userdata)
776 {
777 global_visit_num++;
778 AssertMemory(inst);
779 SilentVisitRootsTwo(inst,proc,depth,userdata);
780 }
781
782 /* struct visitmapinfo *MakeVisitMap(i,&len);
783 * Returns a vector len long of visitmapinfos collected showing the instances
784 * and how they are encountered in a visitation.
785 * example: (i, icld, ignd are instance ptrs)
786 *[parent,context,dir,child]
787 * [NULL,root,DOWN,1],
788 * [root,icld,DOWN,1],
789 * [icld,ignd,-UP-,1],
790 * [root,icld,-UP-,1],
791 * [NULL,root,DOWN,2],
792 * [root,icld,-UP-,1],
793 * [NULL,root,-UP-,0].
794 *
795 * The visitation indicated by this mapping (both bottom-up and top-down)
796 * is:
797 * v<i>
798 * v<i>.b
799 * ^<i>.b.f
800 * ^<i>.b
801 * v<i>
802 * ^<i>.c
803 * ^<i>
804 */
805 static
806 void MakeMap(struct Instance *inst,
807 struct Instance *parent,
808 unsigned long parents_child_num_of_i,
809 unsigned long *lensofar,
810 struct visitmapinfo *map)
811 {
812 unsigned long c,nc;
813 struct Instance *ch;
814 /* account for the children if we haven't been here before */
815 if (CheckVisitNumber(inst) && NotAtom(inst)) {
816 nc = NumberChildren(inst);
817 for (c=1; c <= nc; c++) {
818 ch=InstanceChild(inst,c);
819 if (ch != NULL) {
820 map[*lensofar].parent = parent;
821 map[*lensofar].context = inst;
822 map[*lensofar].dir = vimap_DOWN;
823 map[*lensofar].last = -1;
824 map[*lensofar].child = c;
825 (*lensofar)++;
826 MakeMap(ch,inst,c,lensofar,map);
827 }
828 }
829 }
830 /* if been here before or not, must record seeing here. */
831 map[*lensofar].parent = parent;
832 map[*lensofar].context = inst;
833 map[*lensofar].dir = vimap_UP;
834 map[*lensofar].last = (int)GetTmpNum(inst);
835 map[*lensofar].child = parents_child_num_of_i;
836 SetTmpNum(inst,*lensofar);
837 (*lensofar)++;
838 }
839
840 /*
841 * CalcMapSize(i,&len);
842 * calculate the number of instances seen and reseen in a visit
843 * and return it in len. Init len to 0 before calling.
844 */
845 static
846 void CalcMapSize(struct Instance *inst,unsigned long *lensofar)
847 {
848 unsigned long c,nc;
849 struct Instance *ch;
850 /* account for the children if we haven't been here before */
851 if (CheckVisitNumber(inst) && NotAtom(inst)) {
852 nc = NumberChildren(inst);
853 for (c=1; c <= nc; c++) {
854 ch=InstanceChild(inst,c);
855 if (ch != NULL) {
856 (*lensofar)++;
857 CalcMapSize(ch,lensofar);
858 }
859 }
860 }
861 /* if been here before or not, must record seeing here. */
862 SetTmpNum(inst,INT_MAX);
863 (*lensofar)++;
864 }
865
866 struct visitmapinfo *MakeVisitMap(struct Instance *root,unsigned long *len)
867 {
868 struct visitmapinfo *map;
869 unsigned long maplen;
870
871 AssertMemory(root);
872 global_visit_num++;
873 *len = 0; /* we don't count root entry, since we don't know context. */
874 CalcMapSize(root,len);
875 map = (struct visitmapinfo *)ascmalloc(sizeof(struct visitmapinfo) *
876 ((*len)+1)
877 );
878 if (map==NULL) {
879 return NULL;
880 }
881 /* put some crap at the END that should signal any reasonable program
882 * should also check this for being same before freeing.
883 */
884 map[*len].parent = NULL;
885 map[*len].context = NULL;
886 map[*len].child = 0UL;
887 map[*len].last = INT_MAX;
888 map[*len].dir = vimap_ERROR;
889 /* record info */
890 global_visit_num++;
891 maplen = 0;
892 MakeMap(root,NULL,0,&maplen,map);
893 assert(map[*len].parent==NULL);
894 assert(map[*len].context==NULL);
895 assert(map[*len].child==0UL);
896 assert(maplen==(*len));
897 return map;
898 }

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