Ejemplo n.º 1
0
int
bbCatbuf(Bytebuffer* bb, const Bytebuffer* s)
{
    if(bbLength(s) > 0)
	bbAppendn(bb,bbContents(s),bbLength(s));
    bbNull(bb);
    return 1;
}
Ejemplo n.º 2
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);
        }
    }
}
Ejemplo n.º 3
0
/* Recursive helper */
static void
gen_chararrayr(Dimset* dimset, int dimindex, int lastunlimited,
               Bytebuffer* databuf, Datalist* data, int fillchar,
	       int unitsize, int expectedsize)
{
    int i;
    size_t dimsize = dimset->dimsyms[dimindex]->dim.declsize;

    if(dimindex < lastunlimited) {
	/* keep recursing */
        for(i=0;i<dimsize;i++) {
	    NCConstant* c = datalistith(data,i);
	    ASSERT(islistconst(c));
	    gen_chararrayr(dimset,dimindex+1,lastunlimited,databuf,
			   c->value.compoundv,fillchar,unitsize,expectedsize);
	}
    } else {/* 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");
	    }
	}
    }
    /* 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");
    } 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);
	}
    }
}
Ejemplo n.º 4
0
static int
c_vlenstring(Generator* generator, Bytebuffer* vlenmem, int* uidp, size_t* countp,...)
{
    if(uidp) *uidp = ++c_uid;
    if(countp) *countp = bbLength(vlenmem);
    return 1;
}
Ejemplo n.º 5
0
void
gen_chararray(Dimset* dimset, Datalist* data, Bytebuffer* databuf, Datalist* fillsrc)
{
    int ndims,lastunlim;
    int fillchar = getfillchar(fillsrc);
    size_t expectedsize,xproduct;
    size_t unitsize;

    ASSERT(bbLength(databuf) == 0);

    ndims = dimset->ndims;


    /* Find the last unlimited */
    lastunlim = findlastunlimited(dimset);
    if(lastunlim < 0) lastunlim = 0; /* pretend */

    /* Compute crossproduct upto the last dimension,
       starting at the last unlimited
    */
    xproduct = crossproduct(dimset,lastunlim,ndims-1);
    if(ndims == 0) {
	unitsize = 1;
    } else if(lastunlim == ndims-1) {/* last dimension is unlimited */
        unitsize = 1;
    } else { /* last dim is not unlimited */
        unitsize = dimset->dimsyms[ndims-1]->dim.declsize;
    }

    expectedsize = (xproduct * unitsize);

    gen_chararrayr(dimset,0,lastunlim,databuf,data,fillchar,unitsize,expectedsize);
}
Ejemplo n.º 6
0
/* Used only for structure field arrays*/
static void
genbin_fieldarray(Symbol* basetype, Datasrc* src, Dimset* dimset, int index,
		Bytebuffer* memory)
{
    int i;
    Symbol* dim = dimset->dimsyms[index];
    unsigned int size = dim->dim.size;
    int lastdim = (index == (dimset->ndims - 1)); /* last dimension*/
    int chartype = (basetype->typ.typecode == NC_CHAR);

    if(chartype) {
	/* Collect the char field in a separate buffer */
	Bytebuffer* fieldbuf = bbNew();
        gen_charfield(src,dimset,index,fieldbuf);
        bbAppendn(memory,bbContents(fieldbuf),bbLength(fieldbuf));
	bbFree(fieldbuf);
    } else {
        ASSERT(size != 0);
        for(i=0;i<size;i++) {
            if(lastdim) {
	        genbin_data(basetype,src,NULL,memory);
            } else { /* !lastdim*/
	        genbin_fieldarray(basetype,src,dimset,index+1,memory);
	    }
	}
    }
}
Ejemplo n.º 7
0
static int
bin_listbegin(Generator* generator, Symbol* tsym, void* liststate, ListClass lc, size_t size, Bytebuffer* buf, int* uidp, ...)
{
    if(uidp) *uidp = ++bin_uid;
    if(lc == LISTCOMPOUND)
        *((int*)liststate) = bbLength(buf);
    return 1;
}
Ejemplo n.º 8
0
void
cquotestring(Bytebuffer* databuf, char quote)
{
    char* escaped = escapify(bbContents(databuf),'"',bbLength(databuf));
    bbClear(databuf);
    bbAppend(databuf,quote);
    bbCat(databuf,escaped);
    bbAppend(databuf,quote);
}
Ejemplo n.º 9
0
static void
write_alignment(int alignment, Bytebuffer* buf)
{
    int pad = 0;
    ptrdiff_t offset = bbLength(buf);
    pad = getpadding(offset,alignment);
    if(pad > 0) {
	bbAppendn(buf,(void*)zeros,pad);
    }
}
Ejemplo n.º 10
0
void
codeflush(void)
{
    if(bbLength(codebuffer) > 0) {
        bbNull(codebuffer);
        fputs(bbContents(codebuffer),stdout);
        fflush(stdout);
        bbClear(codebuffer);
    }
}
Ejemplo n.º 11
0
static void
alignto(int alignment, Bytebuffer* buf, ptrdiff_t base)
{
    int pad = 0;
    ptrdiff_t offset = bbLength(buf);
    offset -= base; /* Need to actually align wrt to the base */
    pad = getpadding(offset,alignment);
    if(pad > 0) {
	bbAppendn(buf,(void*)zeros,pad);
    }
}
Ejemplo n.º 12
0
void
commify(Bytebuffer* buf)
{
    char* list,*p;

    if(bbLength(buf) == 0) return;
    list = bbDup(buf);
    p = list;
    bbClear(buf);
    commifyr(p,buf);
    bbNull(buf);
    efree(list);
}
Ejemplo n.º 13
0
static int
bin_vlenstring(Generator* generator, Symbol* sym, Bytebuffer* codebuf, int* uidp, size_t* sizep,...)
{
    Bytebuffer* vlenmem;
    nc_vlen_t ptr;
    va_list ap;
    if(uidp) *uidp = ++bin_uid;
    va_start(ap,sizep);
    vlenmem = va_arg(ap, Bytebuffer*);
    va_end(ap);
    ptr.len = bbLength(vlenmem);
    ptr.p = bbDup(vlenmem);
    bbAppendn(codebuf,(char*)&ptr,sizeof(ptr));
    return 1;
}
Ejemplo n.º 14
0
void
alignbuffer(NCConstant* prim, Bytebuffer* buf)
{
    int alignment,pad,offset;

    if(prim->nctype == NC_ECONST)
        alignment = nctypealignment(prim->value.enumv->typ.typecode);
    else if(usingclassic && prim->nctype == NC_STRING)
        alignment = nctypealignment(NC_CHAR);
    else if(prim->nctype == NC_CHAR)
        alignment = nctypealignment(NC_CHAR);
    else
        alignment = nctypealignment(prim->nctype);
    offset = bbLength(buf);
    pad = getpadding(offset,alignment);
    if(pad > 0) {
	bbAppendn(buf,(void*)zeros,pad);
    }
}
Ejemplo n.º 15
0
void
gen_charvlen(Datalist* data, Bytebuffer* databuf)
{
    int i;
    NCConstant* c;

    ASSERT(bbLength(databuf) == 0);

    for(i=0;i<data->length;i++) {
        c = datalistith(data,i);
        if(isstringable(c->nctype)) {
            (void)gen_charconstant(c,databuf,NC_FILL_CHAR);
        } else {
            semerror(constline(c),
                     "Encountered non-string and non-char constant in datalist");
            return;
        }
    }
}
Ejemplo n.º 16
0
/*
This walk of the data lists collects
vlen sublists and constructs separate C constants
for each of them. The "id" of each list is then
recorded in the containing datalist.
*/
void
genbin_vlenconstants(List* vlenconstants)
{
    int i,nvlen;
    Datasrc* vlensrc;
    Bytebuffer* memory = bbNew();

    /* Prepare a place to store vlen constants */
    nvlen = listlength(vlenconstants);
    if(nvlen == 0) return;
    vlendata = (struct Vlendata*)emalloc(sizeof(struct Vlendata)*nvlen+1);
    memset((void*)vlendata,0,sizeof(struct Vlendata)*nvlen+1);

    for(i=0;i<nvlen;i++) {
	Constant* cmpd = (Constant*)listget(vlenconstants,i);
	int chartype;
	Symbol* tsym = cmpd->value.compoundv->vlen.schema;
	unsigned long uid = cmpd->value.compoundv->vlen.uid;
	unsigned long count;
        ASSERT(tsym != NULL);
        chartype = (tsym->typ.basetype->typ.typecode == NC_CHAR);

	vlensrc = datalist2src(cmpd->value.compoundv);

	bbClear(memory);
	count = 0;
	if(chartype) {
   	    /* Collect the char vlen in a separate buffer */
            gen_charvlen(vlensrc,memory);
	    count = bbLength(memory);
	} else {
  	    while(srcmore(vlensrc)) {
                genbin_data(tsym->typ.basetype,vlensrc,NULL,memory);
		count++;
	    }
	    ASSERT(count == cmpd->value.compoundv->vlen.count);
        }
	vlendata[uid].data = bbDup(memory);
	vlendata[uid].count = count;
    }
    bbFree(memory);
}
Ejemplo n.º 17
0
static void
gen_leafchararray(Dimset* dimset, int dimindex, Datalist* data,
                   Bytebuffer* charbuf, int fillchar)
{
    int i;
    size_t expectedsize,xproduct,unitsize;
    int rank = rankfor(dimset);

    ASSERT(bbLength(charbuf) == 0);
    ASSERT((findlastunlimited(dimset) == rank
            || findlastunlimited(dimset) == dimindex));

    /*
    There are a number of special cases that must be
    considered, mostly driven by the need to keep consistent
    with ncgen3.  These cases are driven by the number of
    dimensions, which dimensions are unlimited (if any), etc.

    The general rule is based on the size of the last
    dimension, we compute the required size (after padding)
    of each string constant. Expected size is then the size
    of concat of the string constants after padding.

    There is another special case used for back compatability with ncgen3.
    In the datalist, all sequences of character constants (i.e. 'X')
    are concatenated into a single string; the result, however is not
    concatenated with any trailing or leading string (with double quotes).
    */

    /* Rebuild the datalist to merge 'x' constants */
    {
	int i,cccount = 0;
	/* Do initial walk */
	for(i=0;i<datalistlen(data);i++) {
	    NCConstant* con = datalistith(data,i);
	    if(consttype(con) == NC_CHAR || consttype(con) == NC_BYTE) {
		cccount++;
	    }
	}
	if(cccount > 1) {
	    char* accum = (char*)malloc(cccount+1);
	    int len = 0;
	    Datalist* newlist = builddatalist(datalistlen(data));
	    int lineno = 0;
            NCConstant* con;
	    for(i=0;i<datalistlen(data);i++) {
	        con = datalistith(data,i);
	        if(consttype(con) == NC_CHAR || consttype(con) == NC_BYTE) {
		    if(len == 0)
			lineno = constline(con);
		    accum[len] = con->value.charv;
		    len++;
		} else {
		    if(len > 0) {
			con = makeconst(lineno,len,accum);
			len = 0;
			lineno = 0;
		    }
		    dlappend(newlist,con);
		}
	    }
	    /* deal with any unclosed strings */
	    if(len > 0) {
		con = makeconst(lineno,len,accum);
		len = 0;
		lineno = 0;
	        dlappend(newlist,con);
	    }
	    free(accum);
	    data = newlist;
	}
    }

    /* Compute crossproduct upto (but not includng) the last dimension */
    xproduct = crossproduct(dimset,dimindex,rank-1);

    /* Start casing it out */
    if(rank == 0) {
        unitsize = 1;
        expectedsize = (xproduct * unitsize);
    } else if(rank == 1) {
	unitsize = 1;
        expectedsize = (xproduct * declsizefor(dimset,rank-1));
    } else if(isunlimited(dimset,rank-1)) {/* last dimension is unlimited */
        unitsize = 1;
        expectedsize = (xproduct*declsizefor(dimset,rank-1));
    } else { /* rank > 0 && last dim is not unlimited */
	unitsize =  declsizefor(dimset,rank-1);
        expectedsize = (xproduct * unitsize);
    }

    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,charbuf,fillchar);
            if(constsize == 0 || constsize % unitsize > 0) {
                size_t padsize = unitsize - (constsize % unitsize);
                for(j=0;j<padsize;j++) bbAppend(charbuf,fillchar);
            }
        } else {
            semwarn(constline(c),"Encountered non-string and non-char constant in datalist; ignored");
        }
    }
    /* If |databuf| > expectedsize, complain: exception is zero length */
    if(bbLength(charbuf) == 0 && expectedsize == 1) {
        /* this is okay */
    } else if(bbLength(charbuf) > expectedsize) {
        semwarn(data->data[0].lineno,"character data list too long; expected %d character constant, found %d: ",expectedsize,bbLength(charbuf));
    } else {
        size_t bufsize = bbLength(charbuf);
        /* Pad to size dimproduct size */
        if(bufsize % expectedsize > 0) {
            size_t padsize = expectedsize - (bufsize % expectedsize);
            for(i=0;i<padsize;i++) bbAppend(charbuf,fillchar);
        }
    }
}
Ejemplo n.º 18
0
static void
genjstd_primattribute(Symbol* asym, Bytebuffer* code, unsigned long len)
{
    Symbol* basetype = asym->typ.basetype;
    nc_type typecode = basetype->typ.typecode;

    /* Handle NC_CHAR specially */
    if(typecode == NC_CHAR) {
        /* revise the length count */
        len = bbLength(code);
        if(len == 0) {bbAppend(code,'\0'); len++;}
        jquotestring(code,'"');
    } else {
        /* Convert to constant */
        char* code2 = bbDup(code);
        bbClear(code);
        nprintf(stmt,sizeof(stmt),"new %s[]",
                jarraytype(typecode));
        bbCat(code,stmt);
        bbCat(code,"{");
        bbCat(code,code2);
        bbCat(code,"}");
        efree(code2);
    }
    switch (typecode) {
    case NC_BYTE:
    case NC_SHORT:
    case NC_INT:
    case NC_FLOAT:
    case NC_DOUBLE:
	jlined(1,"{");
	nprintf(stmt,sizeof(stmt),"%sArray data = Array.factory(%s.class, new int[]{%lu}, ",
		indented(1),
		jtype(basetype->typ.typecode),
		len);
	jpartial(stmt);
        jprint(code);
	jline(");");
	if(asym->att.var == NULL) {
            nprintf(stmt,sizeof(stmt),"ncfile.addGlobalAttribute(\"%s\",data);",
                jescapifyname(asym->name));
	} else {
            nprintf(stmt,sizeof(stmt),"ncfile.addVariableAttribute(\"%s\",\"%s\",data);",
		jescapifyname(asym->att.var->name),
                jescapifyname(asym->name));
	}
        jlined(1,stmt);
	jlined(1,"}");
        jflush();
        break;

    case NC_CHAR:
	if(asym->att.var == NULL) {
            nprintf(stmt,sizeof(stmt),"ncfile.addGlobalAttribute(\"%s\",%s);",
                jescapifyname(asym->name),
		bbContents(code));
	} else {
            nprintf(stmt,sizeof(stmt),"ncfile.addVariableAttribute(\"%s\",\"%s\",%s);",
		jescapifyname(asym->att.var->name),
                jescapifyname(asym->name),
		bbContents(code));
	}
        jlined(1,stmt);
        jflush();
        break;

    default: break;
    }
}
Ejemplo n.º 19
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);
#if 0
            writer(generator,vsym,code,odom->rank,0,bbLength(charbuf));
#endif
	    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);
}
Ejemplo n.º 20
0
static void
genj_writeattr(Generator* generator, Symbol* asym, Bytebuffer* code,
               int rank, size_t* start, size_t* count)
{
    Symbol* basetype = asym->typ.basetype;
    nc_type typecode = basetype->typ.typecode;
    /* default assumption */
    size_t len = asym->data == NULL?0:asym->data->length; 

    codeprintf("%s/* attribute: %s */\n",indented(1),asym->name);

    /* Handle NC_CHAR specially */
    if(typecode == NC_CHAR) {
        /* revise the length count */
        len = bbLength(code);
        if(len == 0) {
	    bbAppend(code,'\0'); len++;
	    bbClear(code);
	    bbCat(code,"\"\"");
	    len++;
	} else
            jquotestring(code,'"');
	bbNull(code);
    } else { /* not NC_CHAR*/
        char* code2;
	commify(code);
        /* Convert to constant */
        code2 = bbDup(code);
        bbClear(code);
        bbprintf0(stmt,"new %s[]",
                jarraytype(typecode));
        bbCatbuf(code,stmt);
        bbCat(code,"{");
        bbCat(code,code2);
        bbCat(code,"}");
        efree(code2);
    }
    switch (typecode) {
    case NC_BYTE:
    case NC_SHORT:
    case NC_INT:
    case NC_FLOAT:
    case NC_DOUBLE:
	codelined(1,"{");
	bbprintf0(stmt,"%sArray data = Array.factory(%s.class, new int[]{%lu}, ",
		indented(1),
		jtype(basetype->typ.typecode),
		len);
	codedump(stmt);
        codedump(code);
	codeline(");");
	if(asym->att.var == NULL) {
            bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",data);\n",
                indented(1),jescapifyname(asym->name));
	} else {
            bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",data);\n",
		indented(1),
		jescapifyname(asym->att.var->name),
                jescapifyname(asym->name));
	}
        codedump(stmt);
	codelined(1,"}");
        codeflush();
        break;

    case NC_CHAR:
	if(asym->att.var == NULL) {
            bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",%s);\n",
		indented(1),
                jescapifyname(asym->name),
		bbContents(code));
	} else {
            bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",%s);\n",
		indented(1),
		jescapifyname(asym->att.var->name),
                jescapifyname(asym->name),
		bbContents(code));
	}
        codedump(stmt);
        codeflush();
        break;

    default: break;
    }
    codeflush();
}
Ejemplo n.º 21
0
void
gen_leafchararray(Dimset* dimset, int lastunlim, Datalist* data,
                   Bytebuffer* databuf, Datalist* fillsrc)
{
    int i;
    size_t expectedsize,xproduct,unitsize;
    int ndims = dimset->ndims;
    int fillchar = getfillchar(fillsrc);

    ASSERT(bbLength(databuf) == 0);

    /* Assume dimindex is the last unlimited (or 0 if their are
       no unlimiteds => we should be at a list of simple constants
    */

    /* Compute crossproduct upto the last dimension,
       starting at the last unlimited
    */
    xproduct = crossproduct(dimset,lastunlim,ndims-1);

    /* Compute the required size (after padding) of each string constant */
    /* expected size is the size of concat of the string constants
       after padding
    */
    if(ndims == 0) {
	unitsize = 1;
        expectedsize = (xproduct * unitsize);
    } else
    if(lastunlim == ndims-1) {/* last dimension is unlimited */
        unitsize = 1;
        expectedsize = (xproduct*dimset->dimsyms[lastunlim]->dim.declsize);
    } else
    { /* last dim is not unlimited */
        unitsize = dimset->dimsyms[ndims-1]->dim.declsize;
        expectedsize = (xproduct * unitsize);
    }

    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 == 0 || 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");
	}
    }
    /* 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");
    } 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);
	}
    }
}