~jdpipe/ascend/trunk-old

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
/*	ASCEND modelling environment
	Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
	Copyright (C) 1996 Ben Allan, Vicente Rico-Ramirez
	Copyright (C) 2007 Carnegie Mellon University

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2, or (at your option)
	any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*//** @file
	Ascend Instance Tree Type Visit Implementation
*//*
	by Tom Epperly. 8/16,89. revised Ben Allan, Vicente Rico-Ramirez
	Last in CVS: $Revision: 1.12 $ $Date: 1997/12/20 17:51:56 $ $Author: ballan $
*/

#ifndef ASC_VISITINST_H
#define ASC_VISITINST_H

#include <ascend/general/platform.h>
#include "instance_enum.h"
#include "compiler.h"

/**	@addtogroup compiler_inst Compiler Instance Hierarchy
	@{
*/

typedef void (*VisitProc)(struct Instance *);
/**< 
 *  Typedef for a function that takes an instance;
 *  Used with VisitInstanceTree().
 */

typedef void (*VisitTwoProc)(struct Instance *,VOIDPTR);
/**<
 *  Typedef for a function that takes an instance and a user pointer;
 *  Used with VisitInstanceTreeTwo().
 */

typedef void (*IndexedVisitProc)(struct Instance *, unsigned long *,
                                 int, VOIDPTR);
/**<
 *  Used with IndexedVisitInstanceTree().
 *  fcn(i,llist,activelen,userdata);<br>
 *  The user supplied 'fcn' must accept the list of child indices from the
 *  root to the instance given and llist[0..activelen-1] contain
 *  valid data, though llist may have a higher capacity.
 *  If the user function needs to know the higher capacity or the
 *  root instance of the visit, that is it's job to keep track of in
 *  userdata.
 */

/** Mapinfo visit info. */
enum visitmap_enum {
  vimap_ERROR = -1, /**< mapinfo is not valid */
  vimap_DOWN,       /**< mapinfo represents visiting a child of inst */
  vimap_UP          /**< mapinfo represents returning from completed inst */
};

/**
 * Mapping node for instances seen maps.
 * The information recorded is redundant in some sense, but we
 * don't know the minimum desired by a given client.
 */
struct visitmapinfo {
  struct Instance *parent;  /**< inst came from to context. maybe NULL */
  struct Instance *context; /**< inst being visited. never NULL */
  enum visitmap_enum dir;   /**< see above */
  int last;                 /**< map index of last time left,if UP.else -1 */
  unsigned long child;      /**< child going to from inst */
};

/*
 *  Tree procedures
 */

extern void ResetVisitCounts(struct Instance *inst);
/**< 
 *  Resets the visit count of all instances in the tree rooted at i to 0.
 *  i must NOT be a fundamental instance (i.e. atom child) or a SIM_INST.
 *  Set global_visit_num = 0 after calling this on all instances.
 *  This will prevent integer overflow of visit counters in long
 *  duration ASCEND sessions.<br><br>
 *
 *  Note that because of the way prototypes and universal instances work,
 *  this function must be called on EVERY existing instance or the compiler
 *  and most ASCEND clients will malfunction SEVERELY.
 *  Instances in prototype libraries.
 *  Instances in all simulations.
 *  Who knows where else they lurk?
 *  Given these restrictions, it is obvious that it is an INTERFACE
 *  job to keep an eye on global_visit_num and call reset for everything
 *  in the environment and then set global_visit_num to 0.
 *
 *  @bug At present, no known interface calls this function yet.
 */

ASC_DLLSPEC void SilentVisitInstanceTree(struct Instance *inst,
                                    VisitProc proc, int depth, int leaf);
/**<
 *  Visit every node of an instance tree and call proc for each node.
 *  proc will be called on inst regardless of leaf, even it is an
 *  atom or child of an atom.<br><br>
 *
 *  SilentVisitInstanceTree() performs the same actions as
 *  FastVisitInstanceTree() and SlowVisitInstanceTree().  It is the
 *  fastest, however, since it tells you nothing when it encounters NULL.<br><br>
 *
 *  This function is an implementation function for VisitInstanceTree()
 *  when NDEBUG is defined.
 *
 *  @param inst   The Instance to visit.  Should not be a SIM_INST.
 *                Simulation instances appear always visited.
 *  @param proc   proc to call.  Will not be called with NULL instances.
 *  @param depth  Controls the order of the call.  If depth is true, the
 *                visitation will be bottom up (i.e. children before
 *                parents); otherwise, the visitation will be top down
 *                (i.e. parents before children).
 *  @param leaf   Determines if the children on atoms will be visited.
 *                If leaf is true, the children of atoms will be visited;
 *                otherwise, it won't.
*/

extern void FastVisitInstanceTree(struct Instance *inst,
                                  VisitProc proc, int depth, int leaf);
/**<
 *  Visit every node of an instance tree and call proc for each node.
 *  proc will be called on inst regardless of leaf, even it is an
 *  atom or child of an atom.<br><br>
 *
 *  FastVisitInstanceTree() performs the same actions as
 *  SilentVisitInstanceTree() and SlowVisitInstanceTree().  It is
 *  intermediate in speed since it tells you when, but not where, it
 *  finds NULL children.
 *
 *  @param inst   The Instance to visit.  Should not be a SIM_INST.
 *                Simulation instances appear always visited.
 *  @param proc   proc to call.  Will not be called with NULL instances.
 *  @param depth  Controls the order of the call.  If depth is true, the
 *                visitation will be bottom up (i.e. children before
 *                parents); otherwise, the visitation will be top down
 *                (i.e. parents before children).
 *  @param leaf   Determines if the children on atoms will be visited.
 *                If leaf is true, the children of atoms will be visited;
 *                otherwise, it won't.
 */

ASC_DLLSPEC void SlowVisitInstanceTree(struct Instance *inst, 
                                  VisitProc proc, int depth, int leaf);
/**<
 *  Visit every node of an instance tree and call proc for each node.
 *  proc will be called on inst regardless of leaf, even it is an
 *  atom or child of an atom.<br><br>
 *
 *  SlowVisitInstanceTree() performs the same actions as
 *  SilentVisitInstanceTree() and FaseVisitInstanceTree().  It is
 *  the slowest in speed since it can tell you where it finds NULL
 *  children. Information costs time.
 *
 *  This function is an implementation function for VisitInstanceTree()
 *  when NDEBUG is not defined (i.e. in debug mode).
 *
 *  @param inst   The Instance to visit.  Should not be a SIM_INST.
 *                Simulation instances appear always visited.
 *  @param proc   proc to call.  Will not be called with NULL instances.
 *  @param depth  Controls the order of the call.  If depth is true, the
 *                visitation will be bottom up (i.e. children before
 *                parents); otherwise, the visitation will be top down
 *                (i.e. parents before children).
 *  @param leaf   Determines if the children on atoms will be visited.
 *                If leaf is true, the children of atoms will be visited;
 *                otherwise, it won't.
 */

#ifndef NDEBUG
#define VisitInstanceTree(a,b,c,d) SlowVisitInstanceTree(a,b,c,d)
/**<  @see SlowVisitInstanceTree(). */
#else
#define VisitInstanceTree(a,b,c,d) SilentVisitInstanceTree(a,b,c,d)
/**<  @see SilentVisitInstanceTree(). */
#endif
/* OLD GROUP COMMENT */
/*
 *  macro VisitInstanceTree(inst,proc,depth,leaf)
 *
 *  void FastVisitInstanceTree(inst,proc,depth,leaf)
 *  void SlowVisitInstanceTree(inst,proc,depth,leaf)
 *  void SilentVisitInstanceTree(inst,proc,depth,leaf)
 *  struct Instance *inst;
 *  VisitProc proc;
 *  int depth,leaf;
 *
 *  i should not be a SIM_INST. Simulation instances appear always visited.
 *  This procedure will visit every node of an instance tree and call
 *  proc for each node, subject to the following conditions:
 *
 *  proc will not be called with NULL instances.
 *
 *  The integer leaf determines if this procedure will
 *  visit the children on atoms.  If leaf is true, if will visit the children
 *  of atoms; otherwise, it won't.
 *
 *  depth controls the order of the call.  If depth is true, the
 *  visitation will be bottom up (i.e., children before parents); otherwise,
 *  the visitation will be top down(i.e, parents before children).
 *
 *  In all cases, proc will be called on the given inst
 *  (even it is an atom or child of an atom regardless of leaf).
 *
 *  FastVisitInstanceTree is just as above except that it
 *  tells you when, but not where, it finds NULL children.
 *
 *  SlowVisitInstanceTree is just as above except that it
 *  can tell you where it finds NULL children. Information costs time.
 *
 *  SilentVisitInstanceTree is the fastest as it
 *  tells you nothing when it encounters NULL.
 */

extern void IndexedVisitInstanceTree(struct Instance *inst,
                                     IndexedVisitProc proc,
                                     int depth,
                                     int leaf,
                                     unsigned long **llist,
                                     unsigned int * llen,
                                     VOIDPTR userdata);
/**<
 *  As SilentVisitInstancetree(), except that at each visited node,
 *  proc is called with llist and the current length of the data
 *  in the llist. The data in the llist is the child list index of
 *  each child visited, and llen then is obviously the relative depth.
 *  So, for example, llen = 0 when proc is called on the instance
 *  given, and llen = 1 with llist[0] = 2 when visiting the second
 *  child of the instance given.<br><br>
 *
 *  llist is a handle to an array of unsigned long. If the depth
 *  visited exceeds *llen, then llist will be reallocated and both
 *  *llist and *llen will be updated so that the caller is made
 *  aware of the change.
 */

extern void SilentVisitInstanceTreeTwo(struct Instance *inst,
                                       VisitTwoProc proc,
                                       int depth,
                                       int leaf,
                                       VOIDPTR userdata);
/**<
 *  This function has exactly the same functionality as SilentVisitInstanceTree(),
 *  *except* that it allows the user to pass in an optional argument.
 *  This may be a pointer to anything and must be cast appropriately.
 *  The use of this function arises, e.g., when visiting the instance tree
 *  and based on certain queries needing to append to a list. This second
 *  argument may now be a pointer to that list. Otherwise a global list
 *  structure would have to be created. This just avoids the clutter of
 *  global variables.
 */

ASC_DLLSPEC void VisitInstanceTreeTwo(struct Instance *inst,
                                 VisitTwoProc proc,
                                 int depth,
                                 int leaf,
                                 VOIDPTR userdata);
/**<
 *  This function has exactly the same functionality as FastVisitInstanceTree(),
 *  *except* that it allows the user to pass in an optional argument.
 *  This may be a pointer to anything and must be cast appropriately.
 *  The use of this function arises, e.g., when visiting the instance tree
 *  and based on certain queries needing to append to a list. This second
 *  argument may now be a pointer to that list. Otherwise a global list
 *  structure would have to be created. This just avoids the clutter of
 *  global variables.<br><br>
 *
 *  Note: the Slow mode is not supported.
 *  Was extern
 */

extern void SilentVisitInstanceFringeTwo(struct Instance *inst,
                                         VisitTwoProc proc1,
                                         VisitTwoProc proc2,
                                         int depth,
                                         int leaf,
                                         VOIDPTR userdata);
/**<
 *  This function has exactly the same functionality as
 *  SilentVisitInstanceTreeTwo(), *except* when an instance is seen again,
 *  it is revisited with proc2,  but there the revisit stops --
 *  the children of revisited instances are not revisited.<br><br>
 *
 *  This is a damned weird function. With it, UNIVERSALs are seen
 *  more than once, in the case of Dummy lots of times. The user
 *  is responsible for doing the right thing with redundant visits.
 */

extern void VisitInstanceFringeTwo(struct Instance *inst,
                                   VisitTwoProc proc1,
                                   VisitTwoProc proc2,
                                   int depth,
                                   int leaf,
                                   VOIDPTR userdata);
/**<
 *  This function has exactly the same functionality as
 *  VisitInstanceTreeTwo(), *except* when an instance is seen again,
 *  it is revisited with proc2, but there the revisit stops --
 *  the children of revisited instances are not revisited.<br><br>
 *
 *  This is a damned weird function. With it, UNIVERSALs are seen
 *  more than once, in the case of Dummy lots of times. The user
 *  is responsible for doing the right thing with redundant visits.
 */

extern void SilentVisitInstanceRootsTwo(struct Instance *inst,
                                        VisitTwoProc proc,
                                        int depth,
                                        VOIDPTR userdata);
/**<
 * Like SilentVisitInstanceTreeTwo(), except goes up the tree instead
 * of down, so leaf is not needed. The meaning of depth is sort of
 * inverted also. Eg. when visiting the instances in the name a.b.c,
 * depth = 0 --> the VisitTwoProc will be applied to c, then b, then a.
 */

extern struct visitmapinfo *MakeVisitMap(struct Instance *inst, unsigned long *maplen);
/**<
 * Returns a map of the instances which will be encountered (and how)
 * in the course of a VisitInstance(). User should free map when done with it.
 * maplist is as described by the comments for visitmapinfo above.
 * The map returned is actually size maplen+1, and the last element may be
 * used to store checksums or other info to detect array overrun. The last
 * element is initialized to 0/NULL/ERROR at creation.<br><br>
 *
 * The visitation indicated by this mapping (both bottom-up and top-down) is:
 * - v<i>
 * - v<i>.b
 * - ^<i>.b.f
 * - ^<i>.b
 * - v<i>
 * - ^<i>.c
 * - ^<i>
 *
 * To avoid reallocation for what is potentially a darn big piece of
 * memory, we visit the tree to get size then again to get data.
 */

/* @} */

#endif  /* ASC_VISITINST_H */