This commit was manufactured by cvs2svn to create tag 'buildscript'.
[IRC.git] /
1 #ifdef TASK
2 #include "runtime.h"
3 #include "structdefs.h"
4 #include "mem.h"
5 #include "checkpoint.h"
6 #include "Queue.h"
7 #include "SimpleHash.h"
8 #include "GenericHashtable.h"
9 #include <sys/select.h>
10 #include <sys/types.h>
11 #include <sys/mman.h>
12 #include <string.h>
13 #include <signal.h>
14
15 extern int injectfailures;
16 extern float failurechance;
17 extern int debugtask;
18 extern int instaccum;
19
20 #ifdef CONSCHECK
21 #include "instrument.h"
22 #endif
23
24 struct genhashtable * activetasks;
25 struct parameterwrapper * objectqueues[NUMCLASSES];
26 struct genhashtable * failedtasks;
27 struct taskparamdescriptor * currtpd;
28 struct ctable * forward;
29 struct ctable * reverse;
30
31 int main(int argc, char **argv) {
32 #ifdef BOEHM_GC
33   GC_init(); // Initialize the garbage collector
34 #endif
35 #ifdef CONSCHECK
36   initializemmap();
37 #endif
38   processOptions();
39   initializeexithandler();
40   /* Create table for failed tasks */
41   failedtasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
42                                    (int(*) (void *,void *)) &comparetpd);
43   /* Create queue of active tasks */
44   activetasks=genallocatehashtable((unsigned int(*) (void *)) &hashCodetpd,
45                                    (int(*) (void *,void *)) &comparetpd);
46
47   /* Process task information */
48   processtasks();
49
50   /* Create startup object */
51   createstartupobject(argc, argv);
52
53   /* Start executing the tasks */
54   executetasks();
55 }
56
57 void createstartupobject(int argc, char ** argv) {
58   int i;
59
60   /* Allocate startup object     */
61 #ifdef PRECISE_GC
62   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(NULL, STARTUPTYPE);
63   struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);
64 #else
65   struct ___StartupObject___ *startupobject=(struct ___StartupObject___*) allocate_new(STARTUPTYPE);
66   struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);
67 #endif
68   /* Build array of strings */
69   startupobject->___parameters___=stringarray;
70   for(i=1; i<argc; i++) {
71     int length=strlen(argv[i]);
72 #ifdef PRECISE_GC
73     struct ___String___ *newstring=NewString(NULL, argv[i],length);
74 #else
75     struct ___String___ *newstring=NewString(argv[i],length);
76 #endif
77     ((void **)(((char *)&stringarray->___length___)+sizeof(int)))[i-1]=newstring;
78   }
79
80   /* Set initialized flag for startup object */
81   flagorand(startupobject,1,0xFFFFFFFF);
82   enqueueObject(startupobject);
83 }
84
85 int hashCodetpd(struct taskparamdescriptor *ftd) {
86   int hash=(int)ftd->task;
87   int i;
88   for(i=0; i<ftd->numParameters; i++) {
89     hash^=(int)ftd->parameterArray[i];
90   }
91   return hash;
92 }
93
94 int comparetpd(struct taskparamdescriptor *ftd1, struct taskparamdescriptor *ftd2) {
95   int i;
96   if (ftd1->task!=ftd2->task)
97     return 0;
98   for(i=0; i<ftd1->numParameters; i++)
99     if(ftd1->parameterArray[i]!=ftd2->parameterArray[i])
100       return 0;
101 #ifdef OPTIONAL
102   for(i=0; i<ftd1->numParameters; i++) {
103     if(ftd1->failed[i]!=ftd2->failed[i])
104       return 0;
105   }
106 #endif
107   return 1;
108 }
109
110 /* This function sets a tag. */
111 #ifdef PRECISE_GC
112 void tagset(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
113 #else
114 void tagset(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
115 #endif
116   struct ___Object___ * tagptr=obj->___tags___;
117   if (tagptr==NULL) {
118     obj->___tags___=(struct ___Object___ *)tagd;
119   } else {
120     /* Have to check if it is already set */
121     if (tagptr->type==TAGTYPE) {
122       struct ___TagDescriptor___ * td=(struct ___TagDescriptor___ *) tagptr;
123       if (td==tagd)
124         return;
125 #ifdef PRECISE_GC
126       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
127       struct ArrayObject * ao=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL);
128       obj=(struct ___Object___ *)ptrarray[2];
129       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
130       td=(struct ___TagDescriptor___ *) obj->___tags___;
131 #else
132       struct ArrayObject * ao=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL);
133 #endif
134       ARRAYSET(ao, struct ___TagDescriptor___ *, 0, td);
135       ARRAYSET(ao, struct ___TagDescriptor___ *, 1, tagd);
136       obj->___tags___=(struct ___Object___ *) ao;
137       ao->___cachedCode___=2;
138     } else {
139       /* Array Case */
140       int i;
141       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
142       for(i=0; i<ao->___cachedCode___; i++) {
143         struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___*, i);
144         if (td==tagd)
145           return;
146       }
147       if (ao->___cachedCode___<ao->___length___) {
148         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, tagd);
149         ao->___cachedCode___++;
150       } else {
151 #ifdef PRECISE_GC
152         int ptrarray[]={2,(int) ptr, (int) obj, (int) tagd};
153         struct ArrayObject * aonew=allocate_newarray(&ptrarray,TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
154         obj=(struct ___Object___ *)ptrarray[2];
155         tagd=(struct ___TagDescriptor___ *) ptrarray[3];
156         ao=(struct ArrayObject *)obj->___tags___;
157 #else
158         struct ArrayObject * aonew=allocate_newarray(TAGARRAYTYPE,TAGARRAYINTERVAL+ao->___length___);
159 #endif
160         aonew->___cachedCode___=ao->___length___+1;
161         for(i=0; i<ao->___length___; i++) {
162           ARRAYSET(aonew, struct ___TagDescriptor___*, i, ARRAYGET(ao, struct ___TagDescriptor___*, i));
163         }
164         ARRAYSET(aonew, struct ___TagDescriptor___ *, ao->___length___, tagd);
165       }
166     }
167   }
168
169   {
170     struct ___Object___ * tagset=tagd->flagptr;
171     if(tagset==NULL) {
172       tagd->flagptr=obj;
173     } else if (tagset->type!=OBJECTARRAYTYPE) {
174 #ifdef PRECISE_GC
175       int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
176       struct ArrayObject * ao=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
177       obj=(struct ___Object___ *)ptrarray[2];
178       tagd=(struct ___TagDescriptor___ *)ptrarray[3];
179 #else
180       struct ArrayObject * ao=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
181 #endif
182       ARRAYSET(ao, struct ___Object___ *, 0, tagd->flagptr);
183       ARRAYSET(ao, struct ___Object___ *, 1, obj);
184       ao->___cachedCode___=2;
185       tagd->flagptr=(struct ___Object___ *)ao;
186     } else {
187       struct ArrayObject *ao=(struct ArrayObject *) tagset;
188       if (ao->___cachedCode___<ao->___length___) {
189         ARRAYSET(ao, struct ___Object___*, ao->___cachedCode___++, obj);
190       } else {
191         int i;
192 #ifdef PRECISE_GC
193         int ptrarray[]={2, (int) ptr, (int) obj, (int)tagd};
194         struct ArrayObject * aonew=allocate_newarray(&ptrarray,OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___);
195         obj=(struct ___Object___ *)ptrarray[2];
196         tagd=(struct ___TagDescriptor___ *)ptrarray[3];
197         ao=(struct ArrayObject *)tagd->flagptr;
198 #else
199         struct ArrayObject * aonew=allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL);
200 #endif
201         aonew->___cachedCode___=ao->___cachedCode___+1;
202         for(i=0; i<ao->___length___; i++) {
203           ARRAYSET(aonew, struct ___Object___*, i, ARRAYGET(ao, struct ___Object___*, i));
204         }
205         ARRAYSET(aonew, struct ___Object___ *, ao->___cachedCode___, obj);
206         tagd->flagptr=(struct ___Object___ *) aonew;
207       }
208     }
209   }
210 }
211
212 /* This function clears a tag. */
213 #ifdef PRECISE_GC
214 void tagclear(void *ptr, struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
215 #else
216 void tagclear(struct ___Object___ * obj, struct ___TagDescriptor___ * tagd) {
217 #endif
218   /* We'll assume that tag is alway there.
219      Need to statically check for this of course. */
220   struct ___Object___ * tagptr=obj->___tags___;
221
222   if (tagptr->type==TAGTYPE) {
223     if ((struct ___TagDescriptor___ *)tagptr==tagd)
224       obj->___tags___=NULL;
225     else
226       printf("ERROR 1 in tagclear\n");
227   } else {
228     struct ArrayObject *ao=(struct ArrayObject *) tagptr;
229     int i;
230     for(i=0; i<ao->___cachedCode___; i++) {
231       struct ___TagDescriptor___ * td=ARRAYGET(ao, struct ___TagDescriptor___ *, i);
232       if (td==tagd) {
233         ao->___cachedCode___--;
234         if (i<ao->___cachedCode___)
235           ARRAYSET(ao, struct ___TagDescriptor___ *, i, ARRAYGET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___));
236         ARRAYSET(ao, struct ___TagDescriptor___ *, ao->___cachedCode___, NULL);
237         if (ao->___cachedCode___==0)
238           obj->___tags___=NULL;
239         goto PROCESSCLEAR;
240       }
241     }
242     printf("ERROR 2 in tagclear\n");
243   }
244 PROCESSCLEAR:
245   {
246     struct ___Object___ *tagset=tagd->flagptr;
247     if (tagset->type!=OBJECTARRAYTYPE) {
248       if (tagset==obj)
249         tagd->flagptr=NULL;
250       else
251         printf("ERROR 3 in tagclear\n");
252     } else {
253       struct ArrayObject *ao=(struct ArrayObject *) tagset;
254       int i;
255       for(i=0; i<ao->___cachedCode___; i++) {
256         struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, i);
257         if (tobj==obj) {
258           ao->___cachedCode___--;
259           if (i<ao->___cachedCode___)
260             ARRAYSET(ao, struct ___Object___ *, i, ARRAYGET(ao, struct ___Object___ *, ao->___cachedCode___));
261           ARRAYSET(ao, struct ___Object___ *, ao->___cachedCode___, NULL);
262           if (ao->___cachedCode___==0)
263             tagd->flagptr=NULL;
264           goto ENDCLEAR;
265         }
266       }
267       printf("ERROR 4 in tagclear\n");
268     }
269   }
270 ENDCLEAR:
271   return;
272 }
273
274 /* This function allocates a new tag. */
275 #ifdef PRECISE_GC
276 struct ___TagDescriptor___ * allocate_tag(void *ptr, int index) {
277   struct ___TagDescriptor___ * v=(struct ___TagDescriptor___ *) mygcmalloc((struct garbagelist *) ptr, classsize[TAGTYPE]);
278 #else
279 struct ___TagDescriptor___ * allocate_tag(int index) {
280   struct ___TagDescriptor___ * v=FREEMALLOC(classsize[TAGTYPE]);
281 #endif
282   v->type=TAGTYPE;
283   v->flag=index;
284   return v;
285 }
286
287
288
289 /* This function updates the flag for object ptr.  It or's the flag
290    with the or mask and and's it with the andmask. */
291
292 void flagbody(struct ___Object___ *ptr, int flag);
293 #ifdef OPTIONAL
294 void enqueueoptional(struct ___Object___ * currobj, int numfailedfses, int * failedfses, struct taskdescriptor * task, int index);
295 #endif
296
297 int flagcomp(const int *val1, const int *val2) {
298   return (*val1)-(*val2);
299 }
300
301 void flagorand(void * ptr, int ormask, int andmask) {
302 #ifdef OPTIONAL
303   struct ___Object___ * obj = (struct ___Object___ *)ptr;
304   if(obj->numfses) { /*store the information about fses*/
305     int flag, i, j,counter, offset=0;
306     for(i=0; i<obj->numfses; i++) {
307       int oldoffset;
308       counter=obj->fses[offset++];
309       oldoffset=offset;
310       for(j=0; j<counter; j++) {
311         flag=obj->fses[offset];
312         obj->fses[offset++]=(flag|ormask)&andmask;
313       }
314       qsort(&obj->fses[oldoffset], sizeof(int), counter, (int(*) (const void *, const void *)) &flagcomp);
315     }
316     enqueueoptional(obj, 0, NULL, NULL, 0);
317   } else
318 #endif
319   {
320     int oldflag=((int *)ptr)[1];
321     int flag=ormask|oldflag;
322     flag&=andmask;
323     flagbody(ptr, flag);
324   }
325 }
326
327 bool intflagorand(void * ptr, int ormask, int andmask) {
328 #ifdef OPTIONAL
329   struct ___Object___ * obj = (struct ___Object___ *)ptr;
330   if(obj->numfses) { /*store the information about fses*/
331     int flag, i, j,counter, offset=0;
332     for(i=0; i<obj->numfses; i++) {
333       int oldoffset;
334       counter=obj->fses[offset++];
335       oldoffset=offset;
336       for(j=0; j<counter; j++) {
337         flag=obj->fses[offset];
338         obj->fses[offset++]=(flag|ormask)&andmask;
339       }
340       qsort(&obj->fses[oldoffset], sizeof(int), counter, (int(*) (const void *, const void *)) &flagcomp);
341     }
342     enqueueoptional(obj, 0, NULL, NULL, 0);
343   } else
344 #endif
345   {
346     int oldflag=((int *)ptr)[1];
347     int flag=ormask|oldflag;
348     flag&=andmask;
349     if (flag==oldflag)   /* Don't do anything */
350       return false;
351     else {
352       flagbody(ptr, flag);
353       return true;
354     }
355   }
356 }
357
358 void flagorandinit(void * ptr, int ormask, int andmask) {
359   int oldflag=((int *)ptr)[1];
360   int flag=ormask|oldflag;
361   flag&=andmask;
362   flagbody(ptr,flag);
363 }
364
365 void flagbody(struct ___Object___ *ptr, int flag) {
366   struct parameterwrapper *flagptr=(struct parameterwrapper *)ptr->flagptr;
367   ptr->flag=flag;
368
369   /*Remove object from all queues */
370   while(flagptr!=NULL) {
371     struct parameterwrapper *next;
372     int UNUSED, UNUSED2;
373     int * enterflags;
374     ObjectHashget(flagptr->objectset, (int) ptr, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
375     ObjectHashremove(flagptr->objectset, (int)ptr);
376     if (enterflags!=NULL)
377       free(enterflags);
378     flagptr=next;
379   }
380 }
381
382 void enqueueObject(void *vptr) {
383   struct ___Object___ *ptr = (struct ___Object___ *)vptr;
384
385   {
386     struct QueueItem *tmpptr;
387     struct parameterwrapper * parameter=objectqueues[ptr->type];
388     int i;
389     struct parameterwrapper * prevptr=NULL;
390     struct ___Object___ *tagptr=ptr->___tags___;
391
392     /* Outer loop iterates through all parameter queues an object of
393        this type could be in.  */
394
395     while(parameter!=NULL) {
396       /* Check tags */
397       if (parameter->numbertags>0) {
398         if (tagptr==NULL)
399           goto nextloop; //that means the object has no tag but that param needs tag
400         else if(tagptr->type==TAGTYPE) { //one tag
401           struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
402           for(i=0; i<parameter->numbertags; i++) {
403             //slotid is parameter->tagarray[2*i];
404             int tagid=parameter->tagarray[2*i+1];
405             if (tagid!=tagptr->flag)
406               goto nextloop; /*We don't have this tag */
407           }
408         } else { //multiple tags
409           struct ArrayObject * ao=(struct ArrayObject *) tagptr;
410           for(i=0; i<parameter->numbertags; i++) {
411             //slotid is parameter->tagarray[2*i];
412             int tagid=parameter->tagarray[2*i+1];
413             int j;
414             for(j=0; j<ao->___cachedCode___; j++) {
415               if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, j)->flag)
416                 goto foundtag;
417             }
418             goto nextloop;
419 foundtag:
420             ;
421           }
422         }
423       }
424
425       /* Check flags */
426       for(i=0; i<parameter->numberofterms; i++) {
427         int andmask=parameter->intarray[i*2];
428         int checkmask=parameter->intarray[i*2+1];
429         if ((ptr->flag&andmask)==checkmask) {
430           enqueuetasks(parameter, prevptr, ptr, NULL, 0);
431           prevptr=parameter;
432           break;
433         }
434       }
435 nextloop:
436       parameter=parameter->next;
437     }
438     ptr->flagptr=prevptr;
439   }
440 }
441
442 #ifdef OPTIONAL
443
444 int checktags(struct ___Object___ * currobj, struct fsanalysiswrapper * fswrapper) {
445   /* Check Tags */
446   struct ___Object___ * tagptr = currobj->___tags___;
447   if(fswrapper->numtags>0) {
448     if (tagptr==NULL)
449       return 0; //that means the object has no tag but that param
450     //needs tag
451     else if(tagptr->type==TAGTYPE) { //one tag
452       if(fswrapper->numtags!=1)
453         return 0; //we don't have the right number of tags
454       struct ___TagDescriptor___ * tag=(struct ___TagDescriptor___*) tagptr;
455       if (fswrapper->tags[0]!=tagptr->flag)
456         return 0;
457     } else {  //multiple tags
458       struct ArrayObject * ao=(struct ArrayObject *) tagptr;
459       int tag_counter=0;
460       int foundtag=0;
461
462       if(ao->___length___!=fswrapper->numtags)
463         return 0; //we don't have the right number of tags
464       for(tag_counter=0; tag_counter<fswrapper->numtags; tag_counter++) {
465         int tagid=fswrapper->tags[tag_counter];
466         int j;
467         for(j=0; j<ao->___cachedCode___; j++) {
468           if (tagid==ARRAYGET(ao, struct ___TagDescriptor___*, tag_counter)->flag)
469             return 1;
470         }
471         return 0;
472       }
473     }
474   }
475   return 1;
476 }
477
478 int getlength(int *flist, int len) {
479   int count=0;
480   int i;
481   for(i=0; i<len; i++) {
482     int size=flist[count];
483     count+=1+size;
484   }
485   return count;
486 }
487
488 int * domergeor(int *flist1, int len1, int *flist2, int len2) {
489   int size1=getlength(flist1, len1);
490   int size2=getlength(flist2, len2);
491   int *merge=RUNMALLOC((size1+size2)*sizeof(int));
492   memcpy(merge, flist1, size1*sizeof(int));
493   memcpy(&merge[size1], flist2, size2*sizeof(int));
494   return merge;
495 }
496
497 int domerge(int * flist1, int len1, int *flist2, int len2, int *merge) {
498   int count=0;
499   int i=0;
500   int j=0;
501   while(i<len1||j<len2) {
502     if (i<len1&&(j==len2||flist1[i]<flist2[j])) {
503       if(merge!=NULL) {
504         merge[count]=flist1[i];
505       }
506       i++;
507       count++;
508     } else if (j<len2&&(i==len1||flist2[j]<flist1[i])) {
509       if(merge!=NULL) {
510         merge[count]=flist2[j];
511       }
512       j++;
513       count++;
514     } else if (i<len1&&j<len2&&flist1[i]==flist2[j]) {
515       if(merge!=NULL) {
516         merge[count]=flist1[i];
517       }
518       i++;
519       j++;
520       count++;
521     }
522   }
523   return count;
524 }
525
526 /* Merge flags from ftlmerge into ftl. */
527 void mergeitems(struct failedtasklist *ftl, struct failedtasklist *ftlmerge) {
528   int length=0;
529   int i,j;
530   int *mergedlist;
531   int offset=0;
532   for(i=0; i<ftl->numflags; i++) {
533     int len=ftl->flags[offset++];
534     int offsetmerge=0;
535     for(j=0; j<ftlmerge->numflags; j++) {
536       int lenmerge=ftlmerge->flags[offsetmerge++];
537       length+=1+domerge(&ftl->flags[offset],len,&ftlmerge->flags[offsetmerge],lenmerge, NULL);
538       offsetmerge+=lenmerge;
539     }
540     offset+=len;
541   }
542   mergedlist=RUNMALLOC(sizeof(int)*length);
543
544   offset=0;
545   length=0;
546   for(i=0; i<ftl->numflags; i++) {
547     int len=ftl->flags[offset++];
548     int offsetmerge=0;
549     for(j=0; j<ftlmerge->numflags; j++) {
550       int lenmerge=ftlmerge->flags[offsetmerge++];
551       int size=domerge(&ftl->flags[offset],len,&ftlmerge->flags[offsetmerge],lenmerge,&mergedlist[length+1]);
552       mergedlist[length]=size;
553       length+=size+1;
554     }
555   }
556   RUNFREE(ftl->flags);
557   ftl->flags=mergedlist;
558   ftl->numflags*=ftlmerge->numflags;
559 }
560
561 void mergefailedlists(struct failedtasklist **andlist, struct failedtasklist *list) {
562   struct failedtasklist *tmpptr;
563   while((*andlist)!=NULL) {
564     struct failedtasklist *searchftl=list;
565     while(searchftl!=NULL) {
566       if ((*andlist)->task==searchftl->task&&
567           (*andlist)->index==searchftl->index) {
568         mergeitems(*andlist, searchftl);
569         break;
570       }
571       searchftl=searchftl->next;
572     }
573     if (searchftl==NULL) {
574       //didn't find andlist
575       tmpptr=*andlist;
576       *andlist=(*andlist)->next; //splice item out of list
577       RUNFREE(tmpptr->flags); //free the item
578       RUNFREE(tmpptr);
579     } else {
580       andlist=&((*andlist)->next); //iterate to next item
581     }
582   }
583   //free the list we're searching
584   while(list!=NULL) {
585     tmpptr=list->next;
586     RUNFREE(list->flags);
587     RUNFREE(list);
588     list=tmpptr;
589   }
590 }
591
592 struct failedtasklist * processfailstate(struct classanalysiswrapper * classwrapper, struct taskdescriptor *task, int index, struct ___Object___ * currobj, int flagstate) {
593   struct failedtasklist *list=NULL;
594   int i,h;
595   struct fsanalysiswrapper *fswrapper=NULL;
596   for(h=0; h<classwrapper->numfsanalysiswrappers; h++) {
597     struct fsanalysiswrapper * tmp=classwrapper->fsanalysiswrapperarray[h];
598     if (tmp->flags==flagstate&&checktags(currobj, tmp)) {
599       //we only match exactly here
600       fswrapper=tmp;
601       break;
602     }
603   }
604   if (fswrapper==NULL)
605     return list;
606   for(i=0; i<fswrapper->numtaskfailures; i++) {
607     int j;
608     struct taskfailure * taskfail=fswrapper->taskfailurearray[i];
609     if (taskfail->task==task&&taskfail->index==index) {
610       int start=0;
611       while(start<taskfail->numoptionaltaskdescriptors) {
612         struct taskdescriptor *currtask=NULL;
613         struct failedtasklist *tmpftl;
614         int currindex;
615         int totallength=0;
616         int *enterflags;
617         int numenterflags, offset;
618         struct parameterwrapper *pw;
619         for(j=start; j<taskfail->numoptionaltaskdescriptors; j++) {
620           struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[j];
621           if(currtask==NULL) {
622             currtask=otd->task;
623             currindex=otd->index;
624           } else if (currtask!=otd->task||currindex!=otd->index)
625             break;
626           totallength+=otd->numenterflags;
627         }
628         pw=currtask->descriptorarray[currindex]->queue;
629         enterflags=RUNMALLOC(totallength*sizeof(int));
630         numenterflags=j-start;
631         offset=0;
632         for(start; start<j; start++) {
633           struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[start];
634           enterflags[offset++]=otd->numenterflags;
635           memcpy(&enterflags[offset], otd->enterflags, otd->numenterflags*sizeof(int));
636           offset+=otd->numenterflags;
637         }
638         tmpftl=RUNMALLOC(sizeof(struct failedtasklist));
639         tmpftl->next=list;
640         tmpftl->task=currtask;
641         tmpftl->numflags=numenterflags;
642         tmpftl->flags=enterflags;
643         list=tmpftl;
644       }
645     }
646   }
647   return list;
648 }
649
650 struct failedtasklist * processnormfailstate(struct classanalysiswrapper * classwrapper, struct ___Object___ * currobj, int flagstate) {
651   struct failedtasklist *list=NULL;
652   int i,h;
653   int start=0;
654   struct fsanalysiswrapper *fswrapper=NULL;
655   for(h=0; h<classwrapper->numfsanalysiswrappers; h++) {
656     struct fsanalysiswrapper * tmp=classwrapper->fsanalysiswrapperarray[h];
657     if (tmp->flags==flagstate&&checktags(currobj, tmp)) {
658       //we only match exactly here
659       fswrapper=tmp;
660       break;
661     }
662   }
663   if(fswrapper==NULL)
664     return NULL;
665
666   while(start<fswrapper->numoptionaltaskdescriptors) {
667     struct taskdescriptor *currtask=NULL;
668     struct failedtasklist *tmpftl;
669     int j;
670     int currindex;
671     int totallength=0;
672     int *enterflags;
673     int numenterflags, offset;
674     struct parameterwrapper *pw;
675     for(j=start; j<fswrapper->numoptionaltaskdescriptors; j++) {
676       struct optionaltaskdescriptor *otd=fswrapper->optionaltaskdescriptorarray[j];
677       if(currtask==NULL) {
678         currtask=otd->task;
679         currindex=otd->index;
680       } else if (currtask!=otd->task||currindex!=otd->index)
681         break;
682       totallength+=otd->numenterflags;
683     }
684     pw=currtask->descriptorarray[currindex]->queue;
685     enterflags=RUNMALLOC(totallength*sizeof(int));
686     numenterflags=j-start;
687     offset=0;
688     for(start; start<j; start++) {
689       struct optionaltaskdescriptor *otd=fswrapper->optionaltaskdescriptorarray[start];
690       enterflags[offset++]=otd->numenterflags;
691       memcpy(&enterflags[offset], otd->enterflags, otd->numenterflags*sizeof(int));
692       offset+=otd->numenterflags;
693     }
694     tmpftl=RUNMALLOC(sizeof(struct failedtasklist));
695     tmpftl->next=list;
696     tmpftl->task=currtask;
697     tmpftl->numflags=numenterflags;
698     tmpftl->flags=enterflags;
699     list=tmpftl;
700   }
701   return list;
702 }
703
704
705
706 void enqueuelist(struct ___Object___ * currobj, struct failedtasklist * andlist) {
707   while(andlist!=NULL) {
708     struct failedtasklist *tmp=andlist;
709     struct parameterwrapper *pw=andlist->task->descriptorarray[andlist->index]->queue;
710     struct parmaeterwrapper *next;
711     int * flags;
712     int numflags;
713     int isnonfailed;
714
715     if (enqueuetasks(pw, currobj->flagptr, currobj, tmp->flags, tmp->numflags))
716       currobj->flagptr=pw;
717
718     andlist=andlist->next;
719     RUNFREE(tmp);
720   }
721 }
722
723 void enqueueoptional(struct ___Object___ * currobj, int numfailedfses, int * failedfses, struct taskdescriptor * task, int index) {
724   struct classanalysiswrapper * classwrapper=NULL;
725
726   /*test what optionaltaskdescriptors are available, find the class
727      corresponding*/
728   if (classanalysiswrapperarray[currobj->type]!=NULL) {
729     classwrapper = classanalysiswrapperarray[currobj->type];
730   } else
731     return;
732
733   if(task!=NULL) {
734     /* We have a failure */
735     if (failedfses==NULL) {
736       /* Failed in normal state */
737       /*first time the method is invoked*/
738       int i,h;
739       struct fsanalysiswrapper *fswrapper=NULL;
740
741       for(h=0; h<classwrapper->numfsanalysiswrappers; h++) {
742         struct fsanalysiswrapper * tmp=classwrapper->fsanalysiswrapperarray[h];
743         if (tmp->flags==currobj->flag&&checktags(currobj, tmp)) {
744           //we only match exactly here
745           fswrapper=tmp;
746           break;
747         }
748       }
749       if(fswrapper==NULL) //nothing to do in this state
750         return;
751       for(i=0; i<fswrapper->numtaskfailures; i++) {
752         int j;
753         struct taskfailure * taskfail=fswrapper->taskfailurearray[i];
754         if (taskfail->task==task&&taskfail->index==index) {
755           int start=0;
756           while(start<taskfail->numoptionaltaskdescriptors) {
757             struct taskdescriptor *currtask=NULL;
758             int currindex;
759             int totallength=0;
760             int *enterflags;
761             int numenterflags, offset;
762             struct parameterwrapper *pw;
763             for(j=start; j<taskfail->numoptionaltaskdescriptors; j++) {
764               struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[j];
765               if(currtask==NULL) {
766                 currtask=otd->task;
767                 currindex=otd->index;
768               } else if (currtask!=otd->task||currindex!=otd->index)
769                 break;
770               totallength+=otd->numenterflags; //1 is to store the lengths
771             }
772             pw=currtask->descriptorarray[currindex]->queue;
773             numenterflags=j-start;
774             enterflags=RUNMALLOC((totallength+numenterflags)*sizeof(int));
775
776             offset=0;
777             for(start; start<j; start++) {
778               struct optionaltaskdescriptor *otd=taskfail->optionaltaskdescriptorarray[start];
779               enterflags[offset++]=otd->numenterflags;
780               memcpy(&enterflags[offset], otd->enterflags, otd->numenterflags*sizeof(int));
781               offset+=otd->numenterflags;
782             }
783             //Enqueue this one
784             if (enqueuetasks(pw, currobj->flagptr, currobj, enterflags, numenterflags))
785               currobj->flagptr=pw;
786           }
787         }
788       }
789     } else {
790       /* Failed in failed state */
791       int i;
792       int offset=0;
793       for(i=0; i<numfailedfses; i++) {
794         int numfses=failedfses[offset++];
795         int j;
796         struct failedtasklist *andlist=NULL;
797         for(j=0; j<numfses; j++) {
798           int flagstate=failedfses[offset++];
799           struct failedtasklist *currlist=processfailstate(classwrapper, task, index, currobj, flagstate);
800           if (andlist==NULL)
801             andlist=currlist;
802           else
803             mergefailedlists(&andlist, currlist);
804         }
805         enqueuelist(currobj, andlist);
806       }
807     }
808   } else {
809     /* No failure, but we are in a failed state */
810     struct parameterwrapper *flagptr=(struct parameterwrapper *)currobj->flagptr;
811
812     /*Remove object from all queues */
813     while(flagptr!=NULL) {
814       struct parameterwrapper *next;
815       int UNUSED, UNUSED2;
816       int * enterflags;
817       ObjectHashget(flagptr->objectset, (int) currobj, (int *) &next, (int *) &enterflags, &UNUSED, &UNUSED2);
818       ObjectHashremove(flagptr->objectset, (int)currobj);
819       if (enterflags!=NULL)
820         free(enterflags);
821       flagptr=next;
822     }
823
824     /* Failed in failed state */
825     int i;
826     int offset=0;
827     for(i=0; i<currobj->numfses; i++) {
828       int numfses=currobj->fses[offset++];
829       int j;
830       struct failedtasklist *andlist=NULL;
831       for(j=0; j<numfses; j++) {
832         int flagstate=currobj->fses[offset++];
833         struct failedtasklist *currlist=processnormfailstate(classwrapper, currobj, flagstate);
834         if (andlist==NULL)
835           andlist=currlist;
836         else
837           mergefailedlists(&andlist, currlist);
838       }
839       enqueuelist(currobj, andlist);
840     }
841   }
842 }
843
844
845 #endif
846
847 int enqueuetasks(struct parameterwrapper *parameter, struct parameterwrapper *prevptr, struct ___Object___ *ptr, int * enterflags, int numenterflags) {
848   void * taskpointerarray[MAXTASKPARAMS];
849 #ifdef OPTIONAL
850   int failed[MAXTASKPARAMS];
851 #endif
852   int j;
853   int numparams=parameter->task->numParameters;
854   int numiterators=parameter->task->numTotal-1;
855   int retval=1;
856   int addnormal=1;
857   int adderror=1;
858
859   struct taskdescriptor * task=parameter->task;
860
861 #ifdef OPTIONAL
862   if (ObjectHashcontainskey(parameter->objectset, (int) ptr)) {
863     /* The object is already here...or it with the existing item */
864     int * oldflags;
865     int oldnumflags;
866     int oldptr;
867     int oldstatus;
868     int *mergedflags;
869     ObjectHashget(parameter->objectset, (int) ptr, &oldptr, (int *) &oldflags, &oldnumflags, &oldstatus);
870     mergedflags=domergeor(oldflags, oldnumflags, enterflags, numenterflags);
871     ObjectHashupdate(parameter->objectset, (int) ptr, oldptr, mergedflags, oldnumflags+numenterflags, oldstatus||(enterflags==NULL));
872
873     RUNFREE(oldflags);
874     RUNFREE(enterflags);
875
876     //only add if truly needed
877     if (oldstatus)
878       addnormal=0;
879     if (oldnumflags>0)
880       adderror=0;
881
882     retval=0;
883   } else {
884 #endif
885   ObjectHashadd(parameter->objectset, (int) ptr, (int) prevptr, (int) enterflags, numenterflags, enterflags==NULL);  //this add the object to parameterwrapper
886 #ifdef OPTIONAL
887 }
888 #endif
889
890   /* Add enqueued object to parameter vector */
891   taskpointerarray[parameter->slot]=ptr;
892 #ifdef OPTIONAL
893   failed[parameter->slot]=(enterflags!=NULL);
894 #endif
895
896   /* Reset iterators */
897   for(j=0; j<numiterators; j++) {
898     toiReset(&parameter->iterators[j]);
899   }
900
901   /* Find initial state */
902   for(j=0; j<numiterators; j++) {
903 backtrackinit:
904     if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed))) {
905       toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
906     } else if (j>0) {
907       /* Need to backtrack */
908       toiReset(&parameter->iterators[j]);
909       j--;
910       goto backtrackinit;
911     } else {
912       /* Nothing to enqueue */
913       return retval;
914     }
915   }
916
917
918   while(1) {
919     /* Enqueue current state */
920     int launch = 0;
921     struct taskparamdescriptor *tpd=RUNMALLOC(sizeof(struct taskparamdescriptor));
922     tpd->task=task;
923     tpd->numParameters=numiterators+1;
924     tpd->parameterArray=RUNMALLOC(sizeof(void *)*(numiterators+1));
925 #ifdef OPTIONAL
926     tpd->failed=RUNMALLOC(sizeof(int)*(numiterators+1));
927 #endif
928     for(j=0; j<=numiterators; j++) {
929       tpd->parameterArray[j]=taskpointerarray[j]; //store the actual parameters
930 #ifdef OPTIONAL
931       tpd->failed[j]=failed[j];
932       if (failed[j]!=0&&failed[j]!=1) {
933         printf("BAD\n");
934       }
935 #endif
936     }
937     /* Enqueue task */
938     if ((!gencontains(failedtasks, tpd)&&!gencontains(activetasks,tpd))) {
939       genputtable(activetasks, tpd, tpd);
940     } else {
941       RUNFREE(tpd->parameterArray);
942 #ifdef OPTIONAL
943       RUNFREE(tpd->failed);
944 #endif
945       RUNFREE(tpd);
946     }
947
948     /* This loop iterates to the next parameter combination */
949     if (numiterators==0)
950       return retval;
951
952     for(j=numiterators-1; j<numiterators; j++) {
953 backtrackinc:
954       if(toiHasNext(&parameter->iterators[j], taskpointerarray OPTARG(failed))) {
955         toiNext(&parameter->iterators[j], taskpointerarray OPTARG(failed));
956       } else if (j>0) {
957         /* Need to backtrack */
958         toiReset(&parameter->iterators[j]);
959         j--;
960         goto backtrackinc;
961       } else {
962         /* Nothing more to enqueue */
963         return retval;
964       }
965     }
966   }
967   return retval;
968 }
969
970 /* Handler for signals. The signals catch null pointer errors and
971    arithmatic errors. */
972
973 void myhandler(int sig, siginfo_t *info, void *uap) {
974   sigset_t toclear;
975 #ifdef DEBUG
976   printf("sig=%d\n",sig);
977   printf("signal\n");
978 #endif
979   sigemptyset(&toclear);
980   sigaddset(&toclear, sig);
981   sigprocmask(SIG_UNBLOCK, &toclear,NULL);
982   longjmp(error_handler,1);
983 }
984
985 fd_set readfds;
986 int maxreadfd;
987 struct RuntimeHash *fdtoobject;
988
989 void addreadfd(int fd) {
990   if (fd>=maxreadfd)
991     maxreadfd=fd+1;
992   FD_SET(fd, &readfds);
993 }
994
995 void removereadfd(int fd) {
996   FD_CLR(fd, &readfds);
997   if (maxreadfd==(fd+1)) {
998     maxreadfd--;
999     while(maxreadfd>0&&!FD_ISSET(maxreadfd-1, &readfds))
1000       maxreadfd--;
1001   }
1002 }
1003
1004 #ifdef PRECISE_GC
1005 #define OFFSET 2
1006 #else
1007 #define OFFSET 0
1008 #endif
1009
1010 #ifdef OPTIONAL
1011 int * fsescopy(int *src, int len) {
1012   int *dst;
1013   if (src==NULL)
1014     return NULL;
1015   dst=RUNMALLOC(len*sizeof(int));
1016   memcpy(dst, src, len*sizeof(int));
1017   return dst;
1018 }
1019 #endif
1020
1021 void executetasks() {
1022   void * taskpointerarray[MAXTASKPARAMS+OFFSET];
1023 #ifdef OPTIONAL
1024   int * fsesarray[MAXTASKPARAMS];
1025   int * oldfsesarray[MAXTASKPARAMS];
1026   int numfsesarray[MAXTASKPARAMS];
1027 #endif
1028
1029   /* Set up signal handlers */
1030   struct sigaction sig;
1031   sig.sa_sigaction=&myhandler;
1032   sig.sa_flags=SA_SIGINFO;
1033   sigemptyset(&sig.sa_mask);
1034
1035   /* Catch bus errors, segmentation faults, and floating point exceptions*/
1036   sigaction(SIGBUS,&sig,0);
1037   sigaction(SIGSEGV,&sig,0);
1038   sigaction(SIGFPE,&sig,0);
1039   sigaction(SIGPIPE,&sig,0);
1040
1041   /* Zero fd set */
1042   FD_ZERO(&readfds);
1043   maxreadfd=0;
1044   fdtoobject=allocateRuntimeHash(100);
1045
1046   /* Map first block of memory to protected, anonymous page */
1047   mmap(0, 0x1000, 0, MAP_SHARED|MAP_FIXED|MAP_ANON, -1, 0);
1048
1049 newtask:
1050   while((hashsize(activetasks)>0)||(maxreadfd>0)) {
1051
1052     /* Check if any filedescriptors have IO pending */
1053     if (maxreadfd>0) {
1054       int i;
1055       struct timeval timeout={0,0};
1056       fd_set tmpreadfds;
1057       int numselect;
1058       tmpreadfds=readfds;
1059       numselect=select(maxreadfd, &tmpreadfds, NULL, NULL, &timeout);
1060       if (numselect>0) {
1061         /* Process ready fd's */
1062         int fd;
1063         for(fd=0; fd<maxreadfd; fd++) {
1064           if (FD_ISSET(fd, &tmpreadfds)) {
1065             /* Set ready flag on object */
1066             void * objptr;
1067             //      printf("Setting fd %d\n",fd);
1068             if (RuntimeHashget(fdtoobject, fd,(int *) &objptr)) {
1069               if(intflagorand(objptr,1,0xFFFFFFFF)) { /* Set the first flag to 1 */
1070                 enqueueObject(objptr);
1071               }
1072             }
1073           }
1074         }
1075       }
1076     }
1077
1078     /* See if there are any active tasks */
1079     if (hashsize(activetasks)>0) {
1080       int i;
1081       currtpd=(struct taskparamdescriptor *) getfirstkey(activetasks);
1082       genfreekey(activetasks, currtpd);
1083
1084       /* Check if this task has failed, allow a task that contains optional objects to fire */
1085       if (gencontains(failedtasks, currtpd)) {
1086         // Free up task parameter descriptor
1087         RUNFREE(currtpd->parameterArray);
1088 #ifdef OPTIONAL
1089         RUNFREE(currtpd->failed);
1090 #endif
1091         RUNFREE(currtpd);
1092         goto newtask;
1093       }
1094       int numparams=currtpd->task->numParameters;
1095       int numtotal=currtpd->task->numTotal;
1096
1097       /* Make sure that the parameters are still in the queues */
1098       for(i=0; i<numparams; i++) {
1099         void * parameter=currtpd->parameterArray[i];
1100         struct parameterdescriptor * pd=currtpd->task->descriptorarray[i];
1101         struct parameterwrapper *pw=(struct parameterwrapper *) pd->queue;
1102         int j;
1103         /* Check that object is still in queue */
1104 #ifdef OPTIONAL
1105         {
1106           int UNUSED, UNUSED2;
1107           int *flags;
1108           int numflags, isnonfailed;
1109           int failed=currtpd->failed[i];
1110           if (!ObjectHashget(pw->objectset, (int) parameter, &UNUSED, (int *) &flags, &numflags, &isnonfailed)) {
1111             RUNFREE(currtpd->parameterArray);
1112             RUNFREE(currtpd->failed);
1113             RUNFREE(currtpd);
1114             goto newtask;
1115           } else {
1116             if (failed&&(flags!=NULL)) {
1117               //Failed parameter
1118               fsesarray[i]=flags;
1119               numfsesarray[i]=numflags;
1120             } else if (!failed && isnonfailed) {
1121               //Non-failed parameter
1122               fsesarray[i]=NULL;
1123               numfsesarray[i]=0;
1124             } else {
1125               RUNFREE(currtpd->parameterArray);
1126               RUNFREE(currtpd->failed);
1127               RUNFREE(currtpd);
1128               goto newtask;
1129             }
1130           }
1131         }
1132 #else
1133         {
1134           if (!ObjectHashcontainskey(pw->objectset, (int) parameter)) {
1135             RUNFREE(currtpd->parameterArray);
1136             RUNFREE(currtpd);
1137             goto newtask;
1138           }
1139         }
1140 #endif
1141 parameterpresent:
1142         ;
1143         /* Check that object still has necessary tags */
1144         for(j=0; j<pd->numbertags; j++) {
1145           int slotid=pd->tagarray[2*j]+numparams;
1146           struct ___TagDescriptor___ *tagd=currtpd->parameterArray[slotid];
1147           if (!containstag(parameter, tagd)) {
1148             RUNFREE(currtpd->parameterArray);
1149 #ifdef OPTIONAL
1150             RUNFREE(currtpd->failed);
1151 #endif
1152             RUNFREE(currtpd);
1153             goto newtask;
1154           }
1155         }
1156
1157         taskpointerarray[i+OFFSET]=parameter;
1158       }
1159       /* Copy the tags */
1160       for(; i<numtotal; i++) {
1161         taskpointerarray[i+OFFSET]=currtpd->parameterArray[i];
1162       }
1163
1164       {
1165         /* Checkpoint the state */
1166         forward=cCreate(256, 0.4);
1167         reverse=cCreate(256, 0.4);
1168         void ** checkpoint=makecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, forward, reverse);
1169         int x;
1170         if (x=setjmp(error_handler)) {
1171           int counter;
1172           /* Recover */
1173 #ifdef DEBUG
1174           printf("Fatal Error=%d, Recovering!\n",x);
1175 #endif
1176           genputtable(failedtasks,currtpd,currtpd);
1177           restorecheckpoint(currtpd->task->numParameters, currtpd->parameterArray, checkpoint, forward, reverse);
1178
1179 #ifdef OPTIONAL
1180           for(counter=0; counter<currtpd->task->numParameters; counter++) {
1181             //enqueue as failed
1182             enqueueoptional(currtpd->parameterArray[counter], numfsesarray[counter], fsesarray[counter], currtpd->task, counter);
1183
1184             //free fses copies
1185             if (fsesarray[counter]!=NULL)
1186               RUNFREE(fsesarray[counter]);
1187           }
1188 #endif
1189           cDelete(forward);
1190           cDelete(reverse);
1191           freemalloc();
1192           forward=NULL;
1193           reverse=NULL;
1194         } else {
1195           if (injectfailures) {
1196             if ((((double)random())/RAND_MAX)<failurechance) {
1197               printf("\nINJECTING TASK FAILURE to %s\n", currtpd->task->name);
1198               longjmp(error_handler,10);
1199             }
1200           }
1201           /* Actually call task */
1202 #ifdef PRECISE_GC
1203                                                                 ((int *)taskpointerarray)[0]=currtpd->numParameters;
1204           taskpointerarray[1]=NULL;
1205 #endif
1206 #ifdef OPTIONAL
1207           //get the task flags set
1208           for(i=0; i<numparams; i++) {
1209             oldfsesarray[i]=((struct ___Object___ *)taskpointerarray[i+OFFSET])->fses;
1210             fsesarray[i]=fsescopy(fsesarray[i], numfsesarray[i]);
1211             ((struct ___Object___ *)taskpointerarray[i+OFFSET])->fses=fsesarray[i];
1212           }
1213 #endif
1214           if(debugtask) {
1215             printf("ENTER %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
1216             ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
1217             printf("EXIT %s count=%d\n",currtpd->task->name, (instaccum-instructioncount));
1218           } else
1219             ((void(*) (void **))currtpd->task->taskptr)(taskpointerarray);
1220
1221 #ifdef OPTIONAL
1222           for(i=0; i<numparams; i++) {
1223             //free old fses
1224             if(oldfsesarray[i]!=NULL)
1225               RUNFREE(oldfsesarray[i]);
1226           }
1227 #endif
1228
1229           cDelete(forward);
1230           cDelete(reverse);
1231           freemalloc();
1232           // Free up task parameter descriptor
1233           RUNFREE(currtpd->parameterArray);
1234 #ifdef OPTIONAL
1235           RUNFREE(currtpd->failed);
1236 #endif
1237           RUNFREE(currtpd);
1238           forward=NULL;
1239           reverse=NULL;
1240         }
1241       }
1242     }
1243   }
1244 }
1245
1246 /* This function processes an objects tags */
1247 void processtags(struct parameterdescriptor *pd, int index, struct parameterwrapper *parameter, int * iteratorcount, int *statusarray, int numparams) {
1248   int i;
1249
1250   for(i=0; i<pd->numbertags; i++) {
1251     int slotid=pd->tagarray[2*i];
1252     int tagid=pd->tagarray[2*i+1];
1253
1254     if (statusarray[slotid+numparams]==0) {
1255       parameter->iterators[*iteratorcount].istag=1;
1256       parameter->iterators[*iteratorcount].tagid=tagid;
1257       parameter->iterators[*iteratorcount].slot=slotid+numparams;
1258       parameter->iterators[*iteratorcount].tagobjectslot=index;
1259       statusarray[slotid+numparams]=1;
1260       (*iteratorcount)++;
1261     }
1262   }
1263 }
1264
1265
1266 void processobject(struct parameterwrapper *parameter, int index, struct parameterdescriptor *pd, int *iteratorcount, int * statusarray, int numparams) {
1267   int i;
1268   int tagcount=0;
1269   struct ObjectHash * objectset=((struct parameterwrapper *)pd->queue)->objectset;
1270
1271   parameter->iterators[*iteratorcount].istag=0;
1272   parameter->iterators[*iteratorcount].slot=index;
1273   parameter->iterators[*iteratorcount].objectset=objectset;
1274   statusarray[index]=1;
1275
1276   for(i=0; i<pd->numbertags; i++) {
1277     int slotid=pd->tagarray[2*i];
1278     int tagid=pd->tagarray[2*i+1];
1279     if (statusarray[slotid+numparams]!=0) {
1280       /* This tag has already been enqueued, use it to narrow search */
1281       parameter->iterators[*iteratorcount].tagbindings[tagcount]=slotid+numparams;
1282       tagcount++;
1283     }
1284   }
1285   parameter->iterators[*iteratorcount].numtags=tagcount;
1286
1287   (*iteratorcount)++;
1288 }
1289
1290 /* This function builds the iterators for a task & parameter */
1291
1292 void builditerators(struct taskdescriptor * task, int index, struct parameterwrapper * parameter) {
1293   int statusarray[MAXTASKPARAMS];
1294   int i;
1295   int numparams=task->numParameters;
1296   int iteratorcount=0;
1297   for(i=0; i<MAXTASKPARAMS; i++) statusarray[i]=0;
1298
1299   statusarray[index]=1; /* Initial parameter */
1300   /* Process tags for initial iterator */
1301
1302   processtags(task->descriptorarray[index], index, parameter, &iteratorcount, statusarray, numparams);
1303
1304   while(1) {
1305 loopstart:
1306     /* Check for objects with existing tags */
1307     for(i=0; i<numparams; i++) {
1308       if (statusarray[i]==0) {
1309         struct parameterdescriptor *pd=task->descriptorarray[i];
1310         int j;
1311         for(j=0; j<pd->numbertags; j++) {
1312           int slotid=pd->tagarray[2*j];
1313           if(statusarray[slotid+numparams]!=0) {
1314             processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1315             processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1316             goto loopstart;
1317           }
1318         }
1319       }
1320     }
1321
1322     /* Next do objects w/ unbound tags*/
1323
1324     for(i=0; i<numparams; i++) {
1325       if (statusarray[i]==0) {
1326         struct parameterdescriptor *pd=task->descriptorarray[i];
1327         if (pd->numbertags>0) {
1328           processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1329           processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1330           goto loopstart;
1331         }
1332       }
1333     }
1334
1335     /* Nothing with a tag enqueued */
1336
1337     for(i=0; i<numparams; i++) {
1338       if (statusarray[i]==0) {
1339         struct parameterdescriptor *pd=task->descriptorarray[i];
1340         processobject(parameter, i, pd, &iteratorcount, statusarray, numparams);
1341         processtags(pd, i, parameter, &iteratorcount, statusarray, numparams);
1342         goto loopstart;
1343       }
1344     }
1345
1346     /* Nothing left */
1347     return;
1348   }
1349 }
1350
1351 void printdebug() {
1352   int i;
1353   int j;
1354   for(i=0; i<numtasks; i++) {
1355     struct taskdescriptor * task=taskarray[i];
1356     printf("%s\n", task->name);
1357     for(j=0; j<task->numParameters; j++) {
1358       struct parameterdescriptor *param=task->descriptorarray[j];
1359       struct parameterwrapper *parameter=param->queue;
1360       struct ObjectHash * set=parameter->objectset;
1361       struct ObjectIterator objit;
1362       printf("  Parameter %d\n", j);
1363       ObjectHashiterator(set, &objit);
1364       while(ObjhasNext(&objit)) {
1365         struct ___Object___ * obj=(struct ___Object___ *)Objkey(&objit);
1366         struct ___Object___ * tagptr=obj->___tags___;
1367         int nonfailed=Objdata4(&objit);
1368         int numflags=Objdata3(&objit);
1369         int flags=Objdata2(&objit);
1370         Objnext(&objit);
1371         printf("    Contains %lx\n", obj);
1372         printf("      flag=%d\n", obj->flag);
1373 #ifdef OPTIONAL
1374         printf("      flagsstored=%x\n",flags);
1375         printf("      numflags=%d\n", numflags);
1376         printf("      nonfailed=%d\n",nonfailed);
1377 #endif
1378         if (tagptr==NULL) {
1379         } else if (tagptr->type==TAGTYPE) {
1380           printf("      tag=%lx\n",tagptr);
1381         } else {
1382           int tagindex=0;
1383           struct ArrayObject *ao=(struct ArrayObject *)tagptr;
1384           for(; tagindex<ao->___cachedCode___; tagindex++) {
1385             printf("      tag=%lx\n",ARRAYGET(ao, struct ___TagDescriptor___*, tagindex));
1386           }
1387         }
1388       }
1389     }
1390   }
1391 }
1392
1393
1394 /* This function processes the task information to create queues for
1395    each parameter type. */
1396
1397 void processtasks() {
1398   int i;
1399   for(i=0; i<numtasks; i++) {
1400     struct taskdescriptor * task=taskarray[i];
1401     int j;
1402
1403     for(j=0; j<task->numParameters; j++) {
1404       struct parameterdescriptor *param=task->descriptorarray[j];
1405       struct parameterwrapper * parameter=RUNMALLOC(sizeof(struct parameterwrapper));
1406       struct parameterwrapper ** ptr=&objectqueues[param->type];
1407
1408       param->queue=parameter;
1409       parameter->objectset=allocateObjectHash(10);
1410       parameter->numberofterms=param->numberterms;
1411       parameter->intarray=param->intarray;
1412       parameter->numbertags=param->numbertags;
1413       parameter->tagarray=param->tagarray;
1414       parameter->task=task;
1415       parameter->slot=j;
1416       /* Link new queue in */
1417       while((*ptr)!=NULL)
1418         ptr=&((*ptr)->next);
1419       (*ptr)=parameter;
1420     }
1421
1422     /* Build iterators for parameters */
1423     for(j=0; j<task->numParameters; j++) {
1424       struct parameterdescriptor *param=task->descriptorarray[j];
1425       struct parameterwrapper *parameter=param->queue;
1426       builditerators(task, j, parameter);
1427     }
1428   }
1429 }
1430
1431 void toiReset(struct tagobjectiterator * it) {
1432   if (it->istag) {
1433     it->tagobjindex=0;
1434   } else if (it->numtags>0) {
1435     it->tagobjindex=0;
1436 #ifdef OPTIONAL
1437     it->failedstate=0;
1438 #endif
1439   } else {
1440     ObjectHashiterator(it->objectset, &it->it);
1441 #ifdef OPTIONAL
1442     it->failedstate=0;
1443 #endif
1444   }
1445 }
1446
1447 int toiHasNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
1448   if (it->istag) {
1449     /* Iterate tag */
1450     /* Get object with tags */
1451     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1452     struct ___Object___ *tagptr=obj->___tags___;
1453     if (tagptr->type==TAGTYPE) {
1454       if ((it->tagobjindex==0)&& /* First object */
1455           (it->tagid==((struct ___TagDescriptor___ *)tagptr)->flag)) /* Right tag type */
1456         return 1;
1457       else
1458         return 0;
1459     } else {
1460       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1461       int tagindex=it->tagobjindex;
1462       for(; tagindex<ao->___cachedCode___; tagindex++) {
1463         struct ___TagDescriptor___ *td=ARRAYGET(ao, struct ___TagDescriptor___ *, tagindex);
1464         if (td->flag==it->tagid) {
1465           it->tagobjindex=tagindex; /* Found right type of tag */
1466           return 1;
1467         }
1468       }
1469       return 0;
1470     }
1471   } else if (it->numtags>0) {
1472     /* Use tags to locate appropriate objects */
1473     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1474     struct ___Object___ *objptr=tag->flagptr;
1475     int i;
1476     if (objptr->type!=OBJECTARRAYTYPE) {
1477       if (it->tagobjindex>0)
1478         return 0;
1479       if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1480         return 0;
1481       for(i=1; i<it->numtags; i++) {
1482         struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1483         if (!containstag(objptr,tag2))
1484           return 0;
1485       }
1486 #ifdef OPTIONAL
1487       if (it->failedstate==1) {
1488         int UNUSED, UNUSED2;
1489         int * flags;
1490         int isnonfailed;
1491         ObjectHashget(it->objectset, (int) objptr, &UNUSED, (int *) &flags, &UNUSED2, &isnonfailed);
1492         if (flags!=NULL) {
1493           return 1;
1494         } else {
1495           it->tagobjindex++;
1496           it->failedstate=0;
1497           return 0;
1498         }
1499       } else {
1500         int UNUSED, UNUSED2;
1501         int * flags;
1502         int isnonfailed;
1503         ObjectHashget(it->objectset, (int) objptr, &UNUSED, (int *) &flags, &UNUSED2, &isnonfailed);
1504         if (!isnonfailed) {
1505           it->failedstate=1;
1506         }
1507         return 1;
1508       }
1509 #endif
1510       return 1;
1511     } else {
1512       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1513       int tagindex;
1514       int i;
1515 #ifdef OPTIONAL
1516       if (it->failedstate==1) {
1517         int UNUSED, UNUSED2;
1518         int * flags;
1519         int isnonfailed;
1520         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, it->tagobjindex);
1521         ObjectHashget(it->objectset, (int) objptr, &UNUSED, (int *) &flags, &UNUSED2, &isnonfailed);
1522         if (flags!=NULL) {
1523           return 1;
1524         } else {
1525           it->failedstate=0;
1526           it->tagobjindex++;
1527         }
1528       }
1529 #endif
1530       for(tagindex=it->tagobjindex; tagindex<ao->___cachedCode___; tagindex++) {
1531         struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
1532         if (!ObjectHashcontainskey(it->objectset, (int) objptr))
1533           continue;
1534         for(i=1; i<it->numtags; i++) {
1535           struct ___TagDescriptor___ *tag2=objectarray[it->tagbindings[i]];
1536           if (!containstag(objptr,tag2))
1537             goto nexttag;
1538         }
1539 #ifdef OPTIONAL
1540         {
1541           int UNUSED, UNUSED2;
1542           int flags, isnonfailed;
1543           struct ___Object___ *objptr=ARRAYGET(ao, struct ___Object___*, tagindex);
1544           ObjectHashget(it->objectset, (int) objptr, &UNUSED, &flags, &UNUSED2, &isnonfailed);
1545           if (!isnonfailed) {
1546             it->failedstate=1;
1547           }
1548         }
1549 #endif
1550         it->tagobjindex=tagindex;
1551         return 1;
1552 nexttag:
1553         ;
1554       }
1555       it->tagobjindex=tagindex;
1556       return 0;
1557     }
1558   } else {
1559 #ifdef OPTIONAL
1560     if (it->failedstate==1) {
1561       if (Objdata2(&it->it))
1562         return 1;
1563       else {
1564         it->failedstate=0;
1565         Objnext(&it->it);
1566       }
1567     }
1568     if (ObjhasNext(&it->it)) {
1569       if (!Objdata4(&it->it)) {
1570         //failed state only
1571         it->failedstate=1;
1572       }
1573       return 1;
1574     } else
1575       return 0;
1576 #else
1577     return ObjhasNext(&it->it);
1578 #endif
1579   }
1580 }
1581
1582 int containstag(struct ___Object___ *ptr, struct ___TagDescriptor___ *tag) {
1583   int j;
1584   struct ___Object___ * objptr=tag->flagptr;
1585   if (objptr->type==OBJECTARRAYTYPE) {
1586     struct ArrayObject *ao=(struct ArrayObject *)objptr;
1587     for(j=0; j<ao->___cachedCode___; j++) {
1588       if (ptr==ARRAYGET(ao, struct ___Object___*, j))
1589         return 1;
1590     }
1591     return 0;
1592   } else
1593     return objptr==ptr;
1594 }
1595
1596 void toiNext(struct tagobjectiterator *it, void ** objectarray OPTARG(int * failed)) {
1597   /* hasNext has all of the intelligence */
1598   if(it->istag) {
1599     /* Iterate tag */
1600     /* Get object with tags */
1601     struct ___Object___ *obj=objectarray[it->tagobjectslot];
1602     struct ___Object___ *tagptr=obj->___tags___;
1603 #ifdef OPTIONAL
1604     failed[it->slot]=0; //have to set it to something
1605 #endif
1606     if (tagptr->type==TAGTYPE) {
1607       it->tagobjindex++;
1608       objectarray[it->slot]=tagptr;
1609     } else {
1610       struct ArrayObject *ao=(struct ArrayObject *) tagptr;
1611       objectarray[it->slot]=ARRAYGET(ao, struct ___TagDescriptor___ *, it->tagobjindex++);
1612     }
1613   } else if (it->numtags>0) {
1614     /* Use tags to locate appropriate objects */
1615     struct ___TagDescriptor___ *tag=objectarray[it->tagbindings[0]];
1616     struct ___Object___ *objptr=tag->flagptr;
1617     if (objptr->type!=OBJECTARRAYTYPE) {
1618 #ifdef OPTIONAL
1619       failed[it->slot]=it->failedstate;
1620       objectarray[it->slot]=objptr;
1621       if (it->failedstate==0) {
1622         it->failedstate=1;
1623       } else {
1624         it->failedstate=0;
1625         it->tagobjindex++;
1626       }
1627 #else
1628       it->tagobjindex++;
1629       objectarray[it->slot]=objptr;
1630 #endif
1631     } else {
1632       struct ArrayObject *ao=(struct ArrayObject *) objptr;
1633 #ifdef OPTIONAL
1634       failed[it->slot]=it->failedstate;
1635       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex);
1636       if (it->failedstate==0) {
1637         it->failedstate=1;
1638       } else {
1639         it->failedstate=0;
1640         it->tagobjindex++;
1641       }
1642 #else
1643       objectarray[it->slot]=ARRAYGET(ao, struct ___Object___ *, it->tagobjindex++);
1644 #endif
1645     }
1646   } else {
1647     /* Iterate object */
1648     void * tmpp = (void *) Objkey(&it->it);
1649     objectarray[it->slot]=tmpp;
1650 #ifdef OPTIONAL
1651     failed[it->slot]=it->failedstate;
1652     if (it->failedstate==0) {
1653       it->failedstate=1;
1654     } else {
1655       it->failedstate=0;
1656       Objnext(&it->it);
1657     }
1658 #else
1659     Objnext(&it->it);
1660 #endif
1661   }
1662 }
1663 #endif