/* globals go before main */ global #define SAVEINC 100 /* not available before 1.3.0b25 */ #define I __i /* our save record contains a funcalc row record and a place for raw data */ typedef struct savestruct{ RowRec row; char *raw; } *Save, SaveRec; /* qsort comparison routine -- reverse order of x */ static int _Cmp(const void *s1, const void *s2) { Save f1 = (Save)s1; Save f2 = (Save)s2; /* order flag */ if( f1->row.x < f2->row.x ) return -1; if( f1->row.x > f2->row.x ) return 1; else return 0; } /* this is the heart of the algorithm */ static void ProcessRows(Fun fun, Fun ofun, Save save, int nsave) { int i; /* sort rows */ qsort(save, nsave, sizeof(SaveRec), _Cmp); /* output rows in new order */ for(i=0; ikey; /* save raw data for this set of rows */ FunInfoGet(fun, FUN_RAWBUF, &rptr, 0); /* if this key starts a new group, process and output previous group */ if( cur->key != lastkey ){ /* process current group */ ProcessRows(fun, ofun, save, nsave); /* restore the current row pointers so we can process the next row */ FunInfoPut(fun, FUN_RAWBUF, &rptr, 0); /* reset number of keys in this group */ nsave = 0; /* got another group */ group++; } /* user manipulation */ /* set values of a new column */ cur->group:I = group; /* manipulate one of the user columns */ cur->x = -cur->x; /* save this row ... first make sure we have enough space */ if( nsave >= maxsave ){ maxsave += SAVEINC; if( !save ) save = xmalloc(maxsave*sizeof(SaveRec)); else save = xrealloc(save, maxsave*sizeof(SaveRec)); /* clear what we just alloc'ed (wish realloc() would do this! */ memset(save+((maxsave-SAVEINC)*sizeof(SaveRec)), 0, SAVEINC*sizeof(SaveRec)); } /* save the user part of this row */ memcpy(&(save[nsave].row), cur, sizeof(RowRec)); /* might have to allocate space for raw */ if( !save[nsave].raw ) save[nsave].raw = xmalloc(rawsize); /* save raw data for this row */ memcpy(save[nsave].raw, rptr+(I*rawsize), rawsize); /* saved another key in this group */ nsave++; /* this key becomes last key */ lastkey = cur->key; /* prevent funcalc from writing out the current record */ continue; /* END OF INNER LOOP */ /* after we leave inner loop */ after /* process rows in last group */ ProcessRows(fun, ofun, save, nsave); /* restore raw buf pointer so FunClose can free it properly */ FunInfoPut(fun, FUN_RAWBUF, &rptr, 0); /* clean up saved data */ for(i=0; i