static void generate_arrayr(Symbol* vsym, Bytebuffer* code, Datalist* list, Odometer* odom, int dimindex, Datalist* filler, Generator* generator ) { Symbol* basetype = vsym->typ.basetype; Dimset* dimset = &vsym->typ.dimset; int rank = dimset->ndims; int lastunlimited; int typecode = basetype->typ.typecode; lastunlimited = findlastunlimited(dimset); if(lastunlimited == rank) lastunlimited = 0; ASSERT(rank > 0); ASSERT(dimindex >= 0 && dimindex < rank); #ifdef CHARBUG ASSERT(typecode != NC_CHAR); #else /*!CHARBUG*/ if(dimindex == lastunlimited && typecode == NC_CHAR) { Bytebuffer* charbuf = bbNew(); gen_leafchararray(dimset,dimindex,list,charbuf,filler); generator->charconstant(generator,code,charbuf); bbFree(charbuf); } else #endif /*!CHARBUG*/ if(dimindex == lastunlimited) { int uid,i; Odometer* slabodom; /* build a special odometer to walk the last few dimensions (similar to case 2 above) */ slabodom = newsubodometer(odom,dimset,dimindex,rank); /* compute the starting offset in our datalist (Assumes that slabodom->index[i] == slabodom->start[i]) */ generator->listbegin(generator,LISTDATA,list->length,code,&uid); for(i=0;odometermore(slabodom);i++) { size_t offset = odometeroffset(slabodom); NCConstant* con = datalistith(list,offset); #ifdef USE_NOFILL if(nofill_flag && con == NULL) break; #endif generator->list(generator,LISTDATA,uid,i,code); generate_basetype(basetype,con,code,filler,generator); odometerincr(slabodom); } generator->listend(generator,LISTDATA,uid,i,code); odometerfree(slabodom); } else { /* If we are strictly to the left of the next unlimited then our datalist is a list of compounds representing the next unlimited; so walk the subarray from this index upto next unlimited. */ int i; Odometer* slabodom; int nextunlimited = findunlimited(dimset,dimindex+1); ASSERT((dimindex < nextunlimited && (dimset->dimsyms[nextunlimited]->dim.isunlimited))); /* build a sub odometer */ slabodom = newsubodometer(odom,dimset,dimindex,nextunlimited); /* compute the starting offset in our datalist (Assumes that slabodom->index[i] == slabodom->start[i]) */ for(i=0;odometermore(slabodom);i++) { size_t offset = odometeroffset(slabodom); NCConstant* con = datalistith(list,offset); #ifdef USE_NOFILL if(nofill_flag && con == NULL) break; #endif if(con == NULL || con->nctype == NC_FILL) { if(filler == NULL) filler = getfiller(vsym); generate_arrayr(vsym,code,filler,odom,nextunlimited,NULL,generator); } else if(!islistconst(con)) semwarn(constline(con),"Expected {...} representing unlimited list"); else { Datalist* sublist = con->value.compoundv; generate_arrayr(vsym,code,sublist,odom,nextunlimited,filler,generator); } odometerincr(slabodom); } odometerfree(slabodom); } return; }
/** The basic idea is to split the set of dimensions into groups and iterate over each group. A group is defined as the range of indices starting at an unlimited dimension upto (but not including) the next unlimited. The first group starts at index 0, even if dimension 0 is not unlimited. The last group is everything from the last unlimited dimension thru the last dimension (index rank-1). */ static void generate_arrayr(Symbol* vsym, Bytebuffer* code, Datalist* list, Odometer* odom, int dimindex, Datalist* filler, Generator* generator ) { int uid,i; Symbol* basetype = vsym->typ.basetype; Dimset* dimset = &vsym->typ.dimset; int rank = dimset->ndims; int lastunlimited = findlastunlimited(dimset); int nextunlimited = findunlimited(dimset,dimindex+1); int typecode = basetype->typ.typecode; int islastgroup = (lastunlimited == rank || dimindex >= lastunlimited || dimindex == rank-1); Odometer* subodom = NULL; ASSERT(rank > 0); ASSERT((dimindex >= 0 && dimindex < rank)); if(islastgroup) { /* Handle NC_CHAR case separately */ if(typecode == NC_CHAR) { Bytebuffer* charbuf = bbNew(); gen_chararray(dimset,dimindex,list,charbuf,filler); generator->charconstant(generator,code,charbuf); bbFree(charbuf); } else { /* build a special odometer to walk the last few dimensions */ subodom = newsubodometer(odom,dimset,dimindex,rank); generator->listbegin(generator,LISTDATA,list->length,code,&uid); for(i=0;odometermore(subodom);i++) { size_t offset = odometeroffset(subodom); NCConstant* con = datalistith(list,offset); generator->list(generator,LISTDATA,uid,i,code); generate_basetype(basetype,con,code,filler,generator); odometerincr(subodom); } generator->listend(generator,LISTDATA,uid,i,code); odometerfree(subodom); subodom = NULL; } } else {/* !islastgroup */ /* Our datalist must be a list of compounds representing the next unlimited; so walk the subarray from this index upto next unlimited. */ ASSERT((dimindex < nextunlimited)); ASSERT((isunlimited(dimset,nextunlimited))); /* build a sub odometer */ subodom = newsubodometer(odom,dimset,dimindex,nextunlimited); for(i=0;odometermore(subodom);i++) { size_t offset = odometeroffset(subodom); NCConstant* con = datalistith(list,offset); if(con == NULL || con->nctype == NC_FILL) { if(filler == NULL) filler = getfiller(vsym); generate_arrayr(vsym,code,filler,odom,nextunlimited,NULL,generator); } else if(islistconst(con)) { Datalist* sublist = compoundfor(con); generate_arrayr(vsym,code,sublist,odom,nextunlimited,filler,generator); } else { semerror(constline(con),"Expected {...} representing unlimited list"); return; } odometerincr(subodom); } odometerfree(subodom); subodom = NULL; } if(subodom != NULL) odometerfree(subodom); return; }