Пример #1
0
/* Recursive helper */
static void
gen_chararrayr(Dimset* dimset, int dimindex,
               Bytebuffer* databuf, Datalist* data, int fillchar,
	       int unitsize, int expectedsize)
{
    int i;
    size_t dimsize = declsizefor(dimset,dimindex);
    int rank = dimset->ndims;
    int firstunlim = findunlimited(dimset,0);
    int lastunlimited = findlastunlimited(dimset);
    int nextunlimited = findunlimited(dimset,dimindex+1);
    int islastgroup = (lastunlimited == rank || dimindex >= lastunlimited || dimindex == rank-1);
    Odometer* subodom = NULL;

    ASSERT(rank > 0);
    ASSERT((islastgroup));

    /* we should be at a list of simple constants */
    for(i=0;i<data->length;i++) {
        NCConstant* c = datalistith(data,i);
        ASSERT(!islistconst(c));
        if(isstringable(c->nctype)) {
            int j;
            size_t constsize;
            constsize = gen_charconstant(c,databuf,fillchar);
            if(constsize % unitsize > 0) {
                size_t padsize = unitsize - (constsize % unitsize);
                for(j=0;j<padsize;j++) bbAppend(databuf,fillchar);
            }
        } else {
            semwarn(constline(c),
                   "Encountered non-string and non-char constant in datalist; ignored");
        }
    }/* for */

    /* If |databuf| > expectedsize, complain: exception is zero length */
    if(bbLength(databuf) == 0 && expectedsize == 1) {
        /* this is okay */
    } else if(bbLength(databuf) > expectedsize) {
        semwarn(data->data[0].lineno,"character data list too long; expected %d character constant, found %d: ",expectedsize,bbLength(databuf));
    } else {
        size_t bufsize = bbLength(databuf);
        /* Pad to size dimproduct size */
        if(bufsize % expectedsize > 0) {
            size_t padsize = expectedsize - (bufsize % expectedsize);
            for(i=0;i<padsize;i++) bbAppend(databuf,fillchar);
        }
    }
}
Пример #2
0
static void
processunlimiteddims(void)
{
    int i;
    /* Set all unlimited dims to size 0; */
    for(i=0;i<listlength(dimdefs);i++) {
	Symbol* dim = (Symbol*)listget(dimdefs,i);
	if(dim->dim.isunlimited)
	    dim->dim.declsize = 0;
    }
    /* Walk all variables */
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* var = (Symbol*)listget(vardefs,i);
	int first,ischar;
	Dimset* dimset = &var->typ.dimset;
	if(dimset->ndims == 0) continue; /* ignore scalars */
	if(var->data == NULL) continue; /* no data list to walk */
	ischar = (var->typ.basetype->typ.typecode == NC_CHAR);
	first = findunlimited(dimset,0);
	if(first == dimset->ndims) continue; /* no unlimited dims */
	if(first == 0) {
	    computeunlimitedsizes(dimset,first,var->data,ischar);
	} else {
	    int j;
	    for(j=0;j<var->data->length;j++) {
	        NCConstant* con = var->data->data[j];
	        if(con->nctype != NC_COMPOUND)
		    semerror(con->lineno,"UNLIMITED dimension (other than first) must be enclosed in {}");
		else
	            computeunlimitedsizes(dimset,first,con->value.compoundv,ischar);
	    }
	}
    }
#ifdef GENDEBUG1
    /* print unlimited dim size */
    if(listlength(dimdefs) == 0)
        fprintf(stderr,"unlimited: no unlimited dimensions\n");
    else for(i=0;i<listlength(dimdefs);i++) {
	Symbol* dim = (Symbol*)listget(dimdefs,i);
	if(dim->dim.isunlimited)
	    fprintf(stderr,"unlimited: %s = %lu\n",
		    dim->name,
	            (unsigned long)dim->dim.declsize);
    }
#endif
}
Пример #3
0
void
gen_chararray(Dimset* dimset, int dimindex, Datalist* data, Bytebuffer* charbuf, Datalist* fillsrc)
{
    int fillchar = getfillchar(fillsrc);
    int rank = rankfor(dimset);
    int firstunlim = findunlimited(dimset,0);
    int nunlim = countunlimited(dimset);
    int nc3unlim = (nunlim <= 1 && (firstunlim == 0 || firstunlim == rank)); /* netcdf-3 case of at most 1 unlim in 0th dimension */

    /* Case: netcdf3 case */
    if(nc3unlim) {
	gen_leafchararray(dimset,0,data,charbuf,fillchar);
	return;
    }

    /* else generate should have done all the hard work */
    gen_leafchararray(dimset,dimindex,data,charbuf,fillchar);
}
Пример #4
0
static void
generate_array(Symbol* vsym,
               Bytebuffer* code,
               Datalist* filler,
               Generator* generator,
	       Writer writer
              )
{
    Dimset* dimset = &vsym->typ.dimset;
    int rank = dimset->ndims;
    Symbol* basetype = vsym->typ.basetype;
    nc_type typecode = basetype->typ.typecode;
    Odometer* odom;
    nciter_t iter;

    ASSERT(rank > 0);

    /* Start by doing easy cases */

#ifdef CHARBUG
    if(typecode == NC_CHAR) { /* case: character typed variable, rank > 0 */
	Bytebuffer* charbuf = bbNew();
        gen_chararray(dimset,vsym->data,charbuf,filler);
	generator->charconstant(generator,code,charbuf);
	bbFree(charbuf);
        odom = newodometer(dimset,NULL,NULL);
        writer(generator,vsym,code,odom->rank,odom->start,odom->count);
    } else
#else /*!CHARBUG*/
    /* Case: char var && dim 1..n are not unlimited */
    if(findunlimited(dimset,1) == rank && typecode == NC_CHAR) {
	Bytebuffer* charbuf = bbNew();
	gen_leafchararray(dimset,0,vsym->data,charbuf,filler);
	generator->charconstant(generator,code,charbuf);
	bbFree(charbuf);
        odom = newodometer(dimset,NULL,NULL);
        writer(generator,vsym,code,odom->rank,odom->start,odom->count);
    } else
#endif
    /* Case 2: dim 1..n are not unlimited */
    if(findunlimited(dimset,1) == rank) {
	size_t offset = 0; /* where are we in the data list */
	size_t nelems = 0; /* # of data list items to read */
        /* Create an iterator and odometer and just walk the datalist */
        nc_get_iter(vsym,nciterbuffersize,&iter);
        odom = newodometer(dimset,NULL,NULL);
	for(;;offset+=nelems) {
	     int i,uid;
             nelems=nc_next_iter(&iter,odom->start,odom->count);
             if(nelems == 0) break;
	     bbClear(code);
             generator->listbegin(generator,LISTDATA,vsym->data->length,code,&uid);
	     for(i=0;i<nelems;i++) {
#ifdef ITERBUG
	 	Constant* con = datalistith(vsym->data,i);
#else
        NCConstant* con = datalistith(vsym->data,i+offset);
#endif
                generator->list(generator,LISTDATA,uid,i,code);
#ifdef USE_NOFILL
		if(nofill_flag && con == NULL)
		    break;
		else
#endif
                    generate_basetype(basetype,con,code,filler,generator);
 	    }
	    generator->listend(generator,LISTDATA,uid,i,code);
#ifdef USE_NOFILL
            writer(generator,vsym,code,rank,odom->start,odom->index);
#else
            writer(generator,vsym,code,rank,odom->start,odom->count);
#endif
	}
    } else

    { /* Hard case: multiple unlimited dimensions */
        /* Setup iterator and odometer */
#ifdef CHARBUG
        nc_get_iter(vsym,nciterbuffersize,&iter);
#else
	nc_get_iter(vsym,NC_MAX_UINT,&iter); /* effectively infinite */
#endif
        odom = newodometer(dimset,NULL,NULL);
	for(;;) {/* iterate in nelem chunks */
	    /* get nelems count and modify odometer */
   	    size_t nelems=nc_next_iter(&iter,odom->start,odom->count);
	    if(nelems == 0) break;
            generate_arrayr(vsym,code,vsym->data,
			    odom,
                            /*dim index=*/0,
			    filler,generator
			   );
#ifdef USE_NOFILL
            writer(generator,vsym,code,odom->rank,odom->start,odom->index);
#else
            writer(generator,vsym,code,odom->rank,odom->start,odom->count);
#endif
        }
    }
    odometerfree(odom);
}
Пример #5
0
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;
}
Пример #6
0
static void
computeunlimitedsizes(Dimset* dimset, int dimindex, Datalist* data, int ischar)
{
    int i;
    size_t xproduct, unlimsize;
    int nextunlim,lastunlim;
    Symbol* thisunlim = dimset->dimsyms[dimindex];
    size_t length;

    ASSERT(thisunlim->dim.isunlimited);
    nextunlim = findunlimited(dimset,dimindex+1);
    lastunlim = (nextunlim == dimset->ndims);

    xproduct = crossproduct(dimset,dimindex+1,nextunlim);

    if(!lastunlim) {
	/* Compute candidate size of this unlimited */
        length = data->length;
	unlimsize = length / xproduct;
	if(length % xproduct != 0)
	    unlimsize++; /* => fill requires at some point */
#ifdef GENDEBUG2
fprintf(stderr,"unlimsize: dim=%s declsize=%lu xproduct=%lu newsize=%lu\n",
thisunlim->name,
(unsigned long)thisunlim->dim.declsize,
(unsigned long)xproduct,
(unsigned long)unlimsize);
#endif
	if(thisunlim->dim.declsize < unlimsize) /* want max length of the unlimited*/
            thisunlim->dim.declsize = unlimsize;
        /*!lastunlim => data is list of sublists, recurse on each sublist*/
	for(i=0;i<data->length;i++) {
	    NCConstant* con = data->data[i];
	    if(con->nctype != NC_COMPOUND) {
		semerror(con->lineno,"UNLIMITED dimension (other than first) must be enclosed in {}");
	    }
	    computeunlimitedsizes(dimset,nextunlim,con->value.compoundv,ischar);
	}
    } else {			/* lastunlim */
	if(ischar) {
	    /* Char case requires special computations;
	       compute total number of characters */
	    length = 0;
	    for(i=0;i<data->length;i++) {
		NCConstant* con = data->data[i];
		switch (con->nctype) {
	        case NC_CHAR: case NC_BYTE: case NC_UBYTE:
		    length++;
		    break;
		case NC_STRING:
		    length += con->value.stringv.len;
	            break;
		case NC_COMPOUND:
		    semwarn(datalistline(data),"Expected character constant, found {...}");
		    break;
		default:
		    semwarn(datalistline(data),"Illegal character constant: %d",con->nctype);
	        }
	    }
	} else { /* Data list should be a list of simple non-char constants */
   	    length = data->length;
	}
	unlimsize = length / xproduct;
	if(length % xproduct != 0)
	    unlimsize++; /* => fill requires at some point */
#ifdef GENDEBUG2
fprintf(stderr,"unlimsize: dim=%s declsize=%lu xproduct=%lu newsize=%lu\n",
thisunlim->name,
(unsigned long)thisunlim->dim.declsize,
(unsigned long)xproduct,
(unsigned long)unlimsize);
#endif
	if(thisunlim->dim.declsize < unlimsize) /* want max length of the unlimited*/
            thisunlim->dim.declsize = unlimsize;
    }
}
Пример #7
0
/**
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;
}
Пример #8
0
static void
generate_array(Symbol* vsym,
               Bytebuffer* code,
               Datalist* filler,
               Generator* generator,
	       Writer writer
              )
{
    Dimset* dimset = &vsym->typ.dimset;
    int rank = dimset->ndims;
    Symbol* basetype = vsym->typ.basetype;
    nc_type typecode = basetype->typ.typecode;
    Odometer* odom = NULL;
    nciter_t iter;
    int firstunlim = findunlimited(dimset,1);
    int nunlim = countunlimited(dimset);
    int isnc3unlim = (nunlim <= 1 && (firstunlim == 0 || firstunlim == rank)); /* netcdf-3 case of at most 1 unlim in 0th dimension */

    ASSERT(rank > 0);

    if(isnc3unlim) {
        /* Handle NC_CHAR case separately */
        if(typecode == NC_CHAR) {
            Bytebuffer* charbuf = bbNew();
            gen_chararray(dimset,0,vsym->data,charbuf,filler);
	    generator->charconstant(generator,code,charbuf);
	    /* Create an odometer to get the dimension info */
            odom = newodometer(dimset,NULL,NULL);
            writer(generator,vsym,code,odom->rank,odom->start,odom->count);
//            writer(generator,vsym,code,odom->rank,0,bbLength(charbuf));
	    bbFree(charbuf);
	} else { /* typecode != NC_CHAR */
            /* Case: dim 1..rank-1 are not unlimited, dim 0 might be */
            size_t offset = 0; /* where are we in the data list */
            size_t nelems = 0; /* # of data list items to generate */
            /* Create an iterator and odometer and just walk the datalist */
            nc_get_iter(vsym,nciterbuffersize,&iter);
            odom = newodometer(dimset,NULL,NULL);
            for(;;offset+=nelems) {
                int i,uid;
                nelems=nc_next_iter(&iter,odometerstartvector(odom),odometercountvector(odom));
                if(nelems == 0)
		    break;
                bbClear(code);
                generator->listbegin(generator,LISTDATA,vsym->data->length,code,&uid);
                for(i=0;i<nelems;i++) {
                    NCConstant* con = datalistith(vsym->data,i+offset);
                    generator->list(generator,LISTDATA,uid,i,code);
                    generate_basetype(basetype,con,code,filler,generator);
                }
                generator->listend(generator,LISTDATA,uid,i,code);
                writer(generator,vsym,code,rank,odom->start,odom->count);
            }
	}
    } else { /* Hard case: multiple unlimited dimensions or unlim in dim > 0*/
        /* Setup iterator and odometer */
        nc_get_iter(vsym,NC_MAX_UINT,&iter); /* effectively infinite */
        odom = newodometer(dimset,NULL,NULL);
        for(;;) {/* iterate in nelem chunks */
            /* get nelems count and modify odometer */
            size_t nelems=nc_next_iter(&iter,odom->start,odom->count);
            if(nelems == 0) break;
            generate_arrayr(vsym,code,vsym->data,
                            odom,
                            /*dim index=*/0,
                            filler,generator
                           );
            writer(generator,vsym,code,odom->rank,odom->start,odom->count);
        }
    }
    if(odom != NULL)
        odometerfree(odom);
}