1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10
11
12 #include <dx/dx.h>
13 #ifndef TRUE
14 #define TRUE 1
15 #define FALSE 0
16 #endif
17
18 extern int DXLoopFirst(); /* from dpexec/evalgraph.c */
19 extern void DXLoopDone(int); /* from dpexec/evalgraph.c */
20 extern void DXSaveForId(char *); /* from dpexec/evalgraph.c */
21
22 struct NextNState {
23 int start;
24 int end;
25 int delta;
26 int direction;
27 int next;
28 };
29
30 struct NextGroupState {
31 int next;
32 int end;
33 };
34
35 struct NextArrayState {
36 int next;
37 ArrayHandle ahandle;
38 Object in_obj;
39 Type type;
40 Category category;
41 int items, rank, shape[50], isize;
42 Pointer buf;
43 };
44
NextArrState_delete(Pointer in)45 Error NextArrState_delete(Pointer in)
46 {
47 struct NextArrayState *astate=NULL;
48 if(in)
49 astate = (struct NextArrayState *)in;
50 if(astate->buf)
51 DXFree(astate->buf);
52 if(astate->ahandle)
53 DXFreeArrayHandle(astate->ahandle);
54 if(astate->in_obj)
55 DXDelete(astate->in_obj);
56 DXFree(in);
57 return OK;
58 }
59
NextState_delete(Pointer in)60 Error NextState_delete(Pointer in)
61 {
62 if(in)
63 DXFree(in);
64 return OK;
65 }
66
67 Error
m_First(Object * in,Object * out)68 m_First(Object *in, Object *out)
69 {
70 int first;
71 out[0] = NULL;
72
73 first = DXLoopFirst();
74
75 out[0] = (Object)DXMakeInteger(first);
76 return OK;
77 }
78
79 Error
m_Done(Object * in,Object * out)80 m_Done(Object *in, Object *out)
81 {
82 int done;
83
84 if(!in[0]) {
85 DXSetError(ERROR_BAD_PARAMETER, "Done value must be set");
86 return ERROR;
87 }
88
89 if(!DXExtractInteger(in[0], &done)) {
90 DXSetError(ERROR_BAD_PARAMETER, "#10010", "Done value");
91 return ERROR;
92 }
93 DXLoopDone(done);
94 return OK;
95 }
96
97 Error
m_ForEachN(Object * in,Object * out)98 m_ForEachN(Object *in, Object *out)
99 {
100 struct NextNState *state = NULL;
101 Object obj;
102 char *modid;
103 int first;
104
105 out[0] = NULL;
106 out[1] = NULL;
107
108 modid = DXGetModuleId();
109
110 first = DXLoopFirst();
111 if(first) {
112 if(!in[0]) {
113 DXSetError(ERROR_MISSING_DATA,"start must be specified");
114 goto error_return;
115 }
116 if(!in[1]) {
117 DXSetError(ERROR_MISSING_DATA,"end must be specified");
118 goto error_return;
119 }
120
121 state = DXAllocateZero(sizeof(struct NextNState));
122 if(state == NULL)
123 goto error_return;
124 if(!DXExtractInteger(in[0], &state->start)) {
125 DXSetError(ERROR_BAD_PARAMETER, "#10010", "start value");
126 goto error_return;
127 }
128
129 if(!DXExtractInteger(in[1], &state->end)) {
130 DXSetError(ERROR_BAD_PARAMETER, "#10010", "end value");
131 goto error_return;
132 }
133
134 if(!in[2])
135 state->delta = 1;
136 else if(!DXExtractInteger(in[2], &state->delta)) {
137 DXSetError(ERROR_BAD_PARAMETER, "#10010", "delta value");
138 goto error_return;
139 }
140
141 DXLoopDone(FALSE);
142 state->next = state->start;
143 if(state->delta < 0) state->direction = -1;
144 else state->direction = 1;
145 if((state->start*state->direction) > (state->end*state->direction)) {
146 DXLoopDone(TRUE);
147 DXFreeModuleId(modid);
148 DXFree(state);
149 return OK;
150 }
151 /* cache the state information */
152 obj = (Object) DXNewPrivate((Pointer)state, NextState_delete);
153 DXSetCacheEntryV(obj, CACHE_PERMANENT, modid, 0, 0, NULL);
154 }
155 else {
156 obj = DXGetCacheEntryV(modid, 0, 0, NULL);
157 DXDelete(obj);
158 if(obj == NULL) {
159 DXSetError(ERROR_INTERNAL, "Lost state information for loop");
160 goto error_return;
161 }
162 state = (struct NextNState *) DXGetPrivateData ((Private) obj);
163 state->next += state->delta;
164 }
165
166 out[0] = (Object)DXMakeInteger(state->next);
167
168 if(state->next*state->direction>(state->end-state->delta)*state->direction)
169 {
170 #if 0
171 /* This will be taken care of by ExCleanupForState */
172 DXSetCacheEntryV(NULL, 0, modid, 0, 0, NULL);
173 #endif
174 DXLoopDone(TRUE);
175 out[1] = (Object)DXMakeInteger(1);
176 }
177 else out[1] = (Object)DXMakeInteger(0);
178
179 /* if it's the first time we save the modid so that the program */
180 /* can clean up the state information when it terminates */
181 if(first)
182 DXSaveForId(modid);
183 else
184 DXFreeModuleId(modid);
185 return OK;
186
187 error_return:
188 out[0] = NULL;
189 out[1] = NULL;
190 if(state)
191 DXFree(state);
192 DXFreeModuleId(modid);
193 DXLoopDone(TRUE);
194 return ERROR;
195 }
196
197 Error
m_ForEachMember(Object * in,Object * out)198 m_ForEachMember(Object *in, Object *out)
199 {
200 Group group;
201 struct NextGroupState *gstate = NULL;
202 struct NextArrayState *astate = NULL;
203 Array array, retarray;
204 Pointer nextitem;
205 char *modid;
206 Object obj;
207 int first;
208
209 modid = DXGetModuleId();
210
211 if(!in[0]) {
212 DXSetError(ERROR_BAD_PARAMETER, "#10000", "group or list");
213 goto error_return;
214 }
215
216 out[0] = out[1] = out[2] = NULL;
217
218 first = DXLoopFirst();
219
220 switch(DXGetObjectClass(in[0])) {
221 case CLASS_MULTIGRID:
222 case CLASS_COMPOSITEFIELD:
223 case CLASS_SERIES:
224 case CLASS_GROUP:
225 group = (Group)(in[0]);
226 if(first) {
227 DXLoopDone(FALSE);
228 gstate = DXAllocateZero(sizeof(struct NextGroupState));
229 if(gstate == NULL)
230 goto error_return;
231 gstate->next = 0;
232 DXGetMemberCount(group, &gstate->end);
233 gstate->end--;
234 obj = (Object)DXNewPrivate((Pointer)gstate, NextState_delete);
235 DXSetCacheEntryV((Object)obj, CACHE_PERMANENT,
236 modid, 0, 0, NULL);
237 }
238 else {
239 obj = DXGetCacheEntryV(modid, 0, 0, NULL);
240 DXDelete(obj);
241 if(obj == NULL) {
242 DXSetError(ERROR_INTERNAL, "Lost state information for loop");
243 goto error_return;
244 }
245 gstate = (struct NextGroupState *) DXGetPrivateData((Private)obj);
246 gstate->next++;
247 }
248 if(gstate->end >= 0) {
249 out[0] = (Object)DXGetEnumeratedMember(group, gstate->next, NULL);
250 out[1] = (Object)DXMakeInteger(gstate->next);
251 if(gstate->next == gstate->end) {
252 DXLoopDone(TRUE);
253 out[2] = (Object)DXMakeInteger(1);
254 }
255 else
256 out[2] = (Object)DXMakeInteger(0);
257 }
258 else { /* we have an empty group */
259 out[0] = NULL;
260 out[1] = (Object)DXMakeInteger(0);
261 out[2] = (Object)DXMakeInteger(1);
262 DXLoopDone(TRUE);
263 }
264 break;
265 case CLASS_ARRAY:
266 case CLASS_REGULARARRAY:
267 case CLASS_PATHARRAY:
268 case CLASS_PRODUCTARRAY:
269 case CLASS_MESHARRAY:
270 array = (Array)in[0];
271 if(first) {
272 DXLoopDone(FALSE);
273 astate = DXAllocateZero(sizeof(struct NextArrayState));
274 if(astate == NULL)
275 goto error_return;
276 DXGetArrayInfo(array, &astate->items, &astate->type,
277 &astate->category, &astate->rank, astate->shape);
278 astate->isize = DXGetItemSize(array);
279 astate->buf = DXAllocate(astate->isize);
280 if(astate->buf == NULL)
281 goto error_return;
282 astate->ahandle = DXCreateArrayHandle(array);
283 if(!astate->ahandle)
284 goto error_return;
285 DXReference(in[0]);
286 astate->in_obj = in[0];
287 astate->next = 0;
288 astate->items--;
289 obj = (Object)DXNewPrivate((Pointer)astate, NextArrState_delete);
290 DXSetCacheEntryV((Object)obj, CACHE_PERMANENT,
291 modid, 0, 0, NULL);
292 }
293 else {
294 obj = DXGetCacheEntryV(modid, 0, 0, NULL);
295 DXDelete(obj);
296 if(obj == NULL) {
297 DXSetError(ERROR_INTERNAL, "Lost state information for loop");
298 goto error_return;
299 }
300 astate = (struct NextArrayState *) DXGetPrivateData((Private)obj);
301 astate->next++;
302 }
303 if(astate->items >= 0) {
304 nextitem = DXGetArrayEntry(astate->ahandle, astate->next,
305 astate->buf);
306 retarray = DXNewArrayV(astate->type, astate->category,
307 astate->rank, astate->shape);
308 retarray = DXAddArrayData(retarray, 0, 1, nextitem);
309 out[0] = (Object)retarray;
310 out[1] = (Object)DXMakeInteger(astate->next);
311 if(astate->next == astate->items) {
312 DXLoopDone(TRUE);
313 out[2] = (Object)DXMakeInteger(1);
314 }
315 else out[2] = (Object)DXMakeInteger(0);
316 }
317 else { /* empty array */
318 out[0] = NULL;
319 out[1] = (Object)DXMakeInteger(0);
320 out[2] = (Object)DXMakeInteger(1);
321 DXLoopDone(TRUE);
322 }
323 break;
324 default:
325 DXSetError(ERROR_BAD_PARAMETER, "input must be group or list");
326 goto error_return;
327 }
328
329 /* if it's the first time we save the modid so that the program */
330 /* can clean up the state information when it terminates */
331 if(first)
332 DXSaveForId(modid);
333 else
334 DXFreeModuleId(modid);
335 return OK;
336
337 error_return:
338 out[0] = NULL;
339 out[1] = NULL;
340 out[2] = NULL;
341 if(astate)
342 DXFree(astate);
343 if(gstate)
344 DXFree(gstate);
345 DXFreeModuleId(modid);
346 DXLoopDone(TRUE);
347 return ERROR;
348 }
349