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