Пример #1
0
static void
fill(Symbol* tvsym, Datalist* filler)
{
    int i;
    Constant con;
    Datalist* sublist;
    /* NC_TYPE case*/
    switch (tvsym->subclass) {
    case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
        con.nctype = tvsym->typ.typecode;
        nc_getfill(&con);
	break;
    case NC_COMPOUND:
	sublist = builddatalist(listlength(tvsym->subnodes));
        for(i=0;i<listlength(tvsym->subnodes);i++) {
	    Symbol* field = (Symbol*)listget(tvsym->subnodes,i);
	    if(field->typ.dimset.ndims > 0) {	
                fillarray(field->typ.basetype,&field->typ.dimset,0,filler);
	    } else
		filllist(field->typ.basetype,sublist);
        }	  
	con = builddatasublist(sublist);
	break;
    case NC_VLEN:
	sublist = builddatalist(0);
	filllist(tvsym->typ.basetype,sublist); /* generate a single instance*/
	con = builddatasublist(sublist);
	break;
    default: PANIC1("fill: unexpected subclass %d",tvsym->subclass);
    }
    dlappend(filler,&con);
}
Пример #2
0
static void
filllist(Symbol* tsym, Datalist* dl)
{
    int i;
    Datalist* sublist;
    NCConstant con;
    con.filled = 0;

    ASSERT(tsym->objectclass == NC_TYPE);
    switch (tsym->subclass) {
    case NC_ENUM: case NC_OPAQUE: case NC_PRIM:
        con.nctype = tsym->typ.typecode;
        nc_getfill(&con);
	dlappend(dl,&con);
	break;
    case NC_COMPOUND:
	sublist = builddatalist(listlength(tsym->subnodes));
        for(i=0;i<listlength(tsym->subnodes);i++) {
	    Symbol* field = (Symbol*)listget(tsym->subnodes,i);
	    filllist(field->typ.basetype,sublist);
        }	  
	con = builddatasublist(sublist);
	dlappend(dl,&con);
	break;
    case NC_VLEN:
	sublist = builddatalist(0);
	filllist(tsym->typ.basetype,sublist); /* generate a single instance*/
	con = builddatasublist(sublist);
	dlappend(dl,&con);
	break;
    default: PANIC1("fill: unexpected subclass %d",tsym->subclass);
    }
}
Пример #3
0
static void
processattributes(void)
{
    int i,j;
    /* process global attributes*/
    for(i=0;i<listlength(gattdefs);i++) {
	Symbol* asym = (Symbol*)listget(gattdefs,i);
	/* If the attribute has a zero length, then default it */
	if(asym->data == NULL || asym->data->length == 0) {
	    asym->data = builddatalist(1);
	    emptystringconst(asym->lineno,&asym->data->data[asym->data->length]);
	    /* force type to be NC_CHAR */
	    asym->typ.basetype = primsymbols[NC_CHAR];
	}
	if(asym->typ.basetype == NULL) inferattributetype(asym);
        /* fill in the typecode*/
	asym->typ.typecode = asym->typ.basetype->typ.typecode;
    }
    /* process per variable attributes*/
    for(i=0;i<listlength(attdefs);i++) {
	Symbol* asym = (Symbol*)listget(attdefs,i);
	/* If the attribute has a zero length, then default it */
	if(asym->data == NULL || asym->data->length == 0) {
	    asym->data = builddatalist(1);
	    emptystringconst(asym->lineno,&asym->data->data[asym->data->length]);
	    /* force type to be NC_CHAR */
	    asym->typ.basetype = primsymbols[NC_CHAR];
	}
	/* If no basetype is specified, then try to infer it;
           the exception if _Fillvalue, whose type is that of the
           containing variable.
        */
        if(strcmp(asym->name,specialname(_FILLVALUE_FLAG)) == 0) {
	    /* This is _Fillvalue */
	    asym->typ.basetype = asym->att.var->typ.basetype; /* its basetype is same as its var*/
	    /* put the datalist into the specials structure */
	    if(asym->data == NULL) {
		/* Generate a default fill value */
	        asym->data = getfiller(asym->typ.basetype);
	    }
	    asym->att.var->var.special._Fillvalue = asym->data;
	} else if(asym->typ.basetype == NULL) {
	    inferattributetype(asym);
	}
	/* fill in the typecode*/
	asym->typ.typecode = asym->typ.basetype->typ.typecode;
    }
    /* collect per-variable attributes per variable*/
    for(i=0;i<listlength(vardefs);i++) {
	Symbol* vsym = (Symbol*)listget(vardefs,i);
	List* list = listnew();
        for(j=0;j<listlength(attdefs);j++) {
	    Symbol* asym = (Symbol*)listget(attdefs,j);
	    ASSERT(asym->att.var != NULL);
	    if(asym->att.var != vsym) continue;	    
            listpush(list,(void*)asym);
	}
	vsym->var.attributes = list;
    }
}
Пример #4
0
Datalist*
getfiller(Symbol* tvsym)
{
    Datalist* filler = NULL;
    Symbol* tsym = tvsym;
    ASSERT(tvsym->objectclass == NC_VAR || tvsym->objectclass == NC_TYPE);
    if(tvsym->objectclass == NC_VAR) {
	tsym = tvsym->typ.basetype;
        filler = tvsym->var.special._Fillvalue; /* get cached value (if any)*/
    }
    if(filler == NULL || tvsym->objectclass == NC_TYPE) {
        filler = tvsym->typ._Fillvalue; /* get cached value (if any)*/
    }
    if(filler == NULL) { /* need to compute it*/
        filler = builddatalist(0);
	fill(tsym,filler);
    }
#ifdef DEBUG2
    dumpdatalist(filler,"getfiller");
#endif
    if(tvsym->objectclass == NC_VAR) {
        tvsym->var.special._Fillvalue = filler;
    } else if(tvsym->objectclass == NC_TYPE) {
        tvsym->typ._Fillvalue = filler; /* cache value*/
    }
    return filler;        
}
Пример #5
0
static void
fillarray(Symbol* basetype, Dimset* dimset, int index, Datalist* arraylist)
{
    int i;
    Symbol* dim = dimset->dimsyms[index];
    unsigned int size = dim->dim.declsize;
    int isunlimited = (size == 0);
    int lastdim = (index == (dimset->ndims - 1));
    int firstdim = (index == 0);
    Datalist* sublist;

    sublist = (firstdim?builddatalist(0):arraylist);
    if(isunlimited) {
	/* do a single entry to satisfy*/
        if(lastdim) {
	    filllist(basetype,sublist);
	} else {
	    fillarray(basetype->typ.basetype,dimset,index+1,sublist);
	}
    } else { /* bounded*/
        if(lastdim) {
	    for(i=0;i<size;i++) filllist(basetype,sublist);
	} else {
	    for(i=0;i<size;i++) {
	        fillarray(basetype->typ.basetype,dimset,index+1,sublist);
	    }
	}
    }
}
Пример #6
0
Datalist*
datalistclone(Datalist* dl)
{
    int i;
    Datalist* clone = builddatalist(dl->length);
    for(i=0;i<dl->length;i++) {
	clone->data[i] = cloneconstant(dl->data+i);
    }
    return clone;
}
Пример #7
0
void
dumpconstant(NCConstant* con, char* tag)
{
    Bytebuffer* buf = bbNew();
    Datalist* dl = builddatalist(1);
    dlappend(dl,con);
    bufdump(dl,buf);
    fprintf(stderr,"%s: %s\n",tag,bbContents(buf));
    bbFree(buf);
}
Пример #8
0
Datalist*
const2list(NCConstant* con)
{
    Datalist* list;
    ASSERT(con != NULL);
    list = builddatalist(1);
    if(list != NULL) {
        dlappend(list,con);
    }
    return list;
}
Пример #9
0
static void
cdata_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* codebuf, Datalist* fillsrc)
{
    Constant* prim;
    Constant target;

    prim = srcnext(src);
    if(prim == NULL) prim = &fillconstant;

    ASSERT(prim->nctype != NC_COMPOUND);

    if(prim->nctype == NC_FILLVALUE) {
	Datalist* filler = getfiller(basetype,fillsrc);
	ASSERT(filler->length == 1);
	srcpushlist(src,filler);
	bbAppend(codebuf,' ');
        cdata_primdata(basetype,src,codebuf,NULL);
	srcpop(src);
	goto done;
    }

    target.nctype = basetype->typ.typecode;

    if(target.nctype != NC_ECONST) {
	convert1(prim,&target);
    }

    switch (target.nctype) {
    case NC_ECONST:
        if(basetype->subclass != NC_ENUM) {
	    semerror(prim->lineno,"Conversion to enum not supported (yet)");
	} else {
	    Datalist* econ = builddatalist(1);
	    Symbol* enumv = prim->value.enumv;
	    srcpushlist(src,econ);
	    dlappend(econ,&enumv->typ.econst);
	    cdata_primdata(enumv->typ.basetype,src,codebuf,fillsrc);
	    srcpop(src);
	 } break;
     case NC_OPAQUE: {
	    setprimlength(&target,basetype->typ.size*2);
	} break;
    default: break;
    }
    bbCat(codebuf,cdata_const(&target));
    
done:
    return;
}
Пример #10
0
static Datalist*
buildstringlist(char* s, size_t chunksize, int lineno)
{
    size_t slen,div,rem;
    Datalist* charlist;
    Constant* chars;

    if(s == NULL) s = "";
    slen = strlen(s);
    ASSERT(chunksize > 0);
    div = slen / chunksize;
    rem = slen % chunksize;
    if(rem > 0) div++;

    charlist = builddatalist(div);
    if(!charlist) return NULL;
    charlist->readonly = 0;
    charlist->length = div;
    chars=charlist->data;
    if(slen == 0) {
	/* Special case for null string */
	charlist->length = 1;
	chars->nctype = NC_STRING;
	chars->lineno = lineno;
        chars->value.stringv.len = 1;
        chars->value.stringv.stringv = nulldup("");
    } else {
	int i;
	for(i=0;i<(div-1);i++,chars++) {
	    chars->nctype = NC_STRING;
	    chars->lineno = lineno;
            chars->value.stringv.len = chunksize;
	    chars->value.stringv.stringv = (char*)emalloc(chunksize+1);
	    memcpy(chars->value.stringv.stringv,s,chunksize);
	    chars->value.stringv.stringv[chunksize] = '\0';
	    s += chunksize;
	}
	/* Do last chunk */
        chars->nctype = NC_STRING;
	chars->lineno = lineno;
        chars->value.stringv.len = strlen(s);
        chars->value.stringv.stringv = nulldup(s);
    }
    return charlist;
}
Пример #11
0
static Datalist*
buildfill(Symbol* tvasym)
{
    Datalist* filler = builddatalist(0);
    ASSERT(tvasym->objectclass == NC_VAR
	   || tvasym->objectclass == NC_TYPE
	   || tvasym->objectclass == NC_ATT);
    if(tvasym->objectclass == NC_VAR) {
	if(tvasym->typ.dimset.ndims > 0) {
	    fillarray(tvasym->typ.basetype,&tvasym->typ.dimset,0,filler);
	} else
	    fill(tvasym->typ.basetype,filler);
    } else if(tvasym->objectclass == NC_ATT) {
	    fill(tvasym->typ.basetype,filler);
    } else /*NC_TYPE*/
	fill(tvasym,filler);
    return filler;
}
Пример #12
0
Datalist*
convertstringtochars(Constant* str)
{
    int i;
    Datalist* dl;
    int slen;
    char* s;

    slen = str->value.stringv.len;
    dl = builddatalist(slen);
    s = str->value.stringv.stringv;
    for(i=0;i<slen;i++) {
	Constant con;
	con.nctype = NC_CHAR;
        con.lineno = str->lineno;
        con.value.charv = s[i];
	con.filled = 0;
	dlappend(dl,&con);
    }
    return dl;
}
Пример #13
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);
        }
    }
}
Пример #14
0
/*
Generate type definitions
*/
static void
genbin_deftype(Symbol* tsym)
{
    int i,stat;

    ASSERT(tsym->objectclass == NC_TYPE);
    switch (tsym->subclass) {
    case NC_PRIM: break; /* these are already taken care of*/
    case NC_OPAQUE:
	stat = nc_def_opaque(tsym->container->ncid,
			     tsym->typ.size,
			     tsym->name,
			     &tsym->ncid);
        check_err(stat,__LINE__,__FILE__);
	break;
    case NC_ENUM:
      {
        Bytebuffer* datum;
        Datalist* ecdl;
	stat = nc_def_enum(tsym->container->ncid,
			   tsym->typ.basetype->typ.typecode,
			   tsym->name,
			   &tsym->ncid);
        check_err(stat,__LINE__,__FILE__);
	datum = bbNew();
        ecdl = builddatalist(1);
        dlextend(ecdl); /* make room for one constant*/
	ecdl->length = 1;
	for(i=0;i<listlength(tsym->subnodes);i++) {
	  Symbol* econst = (Symbol*)listget(tsym->subnodes,i);
	  ASSERT(econst->subclass == NC_ECONST);
	  generator_reset(bin_generator,NULL);
	  bbClear(datum);
	  generate_basetype(econst->typ.basetype,&econst->typ.econst,datum,NULL,bin_generator);
	  stat = nc_insert_enum(tsym->container->ncid,
				tsym->ncid,
				econst->name,
				bbContents(datum));
	  check_err(stat,__LINE__,__FILE__);
	}
	bbFree(datum);
    dlfree(&ecdl);
      }
      break;
    case NC_VLEN:
	stat = nc_def_vlen(tsym->container->ncid,
			   tsym->name,
			   tsym->typ.basetype->ncid,
			   &tsym->ncid);
        check_err(stat,__LINE__,__FILE__);
	break;
    case NC_COMPOUND:
	stat = nc_def_compound(tsym->container->ncid,
			       tsym->typ.size,
			       tsym->name,
			       &tsym->ncid);
        check_err(stat,__LINE__,__FILE__);
	for(i=0;i<listlength(tsym->subnodes);i++) {
	    Symbol* efield = (Symbol*)listget(tsym->subnodes,i);
	    ASSERT(efield->subclass == NC_FIELD);
	    if(efield->typ.dimset.ndims == 0){
	        stat = nc_insert_compound(
				tsym->container->ncid,
				tsym->ncid,
				efield->name,
			        efield->typ.offset,
				efield->typ.basetype->ncid);
	    } else {
		int j;
		int dimsizes[NC_MAX_VAR_DIMS];
		/* Generate the field dimension constants*/
		for(j=0;j<efield->typ.dimset.ndims;j++) {
		     unsigned int size = efield->typ.dimset.dimsyms[j]->dim.declsize;
		     dimsizes[j] = size;
		}
	        stat = nc_insert_array_compound(
				tsym->container->ncid,
				tsym->ncid,
				efield->name,
			        efield->typ.offset,
				efield->typ.basetype->ncid,
				efield->typ.dimset.ndims,
				dimsizes);
	    }
            check_err(stat,__LINE__,__FILE__);
	}
	break;
    default: panic("definectype: unexpected type subclass");
    }
}
Пример #15
0
static void
processspecial1(Symbol* vsym)
{
    unsigned long flags = vsym->var.special.flags;
    int i,tag;
    Constant con;
    Datalist* dlist = NULL;
    if(flags == 0) return; /* no specials defined */
    con = nullconstant;
    if((tag=(flags & _CHUNKSIZES_FLAG))) {
	dlist = builddatalist(vsym->var.special.nchunks);
        for(i=0;i<vsym->var.special.nchunks;i++) {
            con = nullconstant;
            con.nctype = NC_INT;
            con.value.int32v = (int)vsym->var.special._ChunkSizes[i];
            dlappend(dlist,&con);
        }
    } else if((tag=(flags & _STORAGE_FLAG))) {
        con.nctype = NC_STRING;
        con.value.stringv.stringv
            = (vsym->var.special._Storage == NC_CHUNKED? "chunked"
                                                       : "contiguous");
        con.value.stringv.len = strlen(con.value.stringv.stringv);
        dlist = builddatalist(1);
        dlappend(dlist,&con);
    }
    if((tag=(flags & _FLETCHER32_FLAG))) {
        con.nctype = NC_STRING;
        con.value.stringv.stringv
            = (vsym->var.special._Fletcher32 == 1? "true"
                                                 : "false");
        con.value.stringv.len = strlen(con.value.stringv.stringv);
        dlist = builddatalist(1);
        dlappend(dlist,&con);
    }
    if((tag=(flags & _DEFLATE_FLAG))) {
        con.nctype = NC_INT;
        con.value.int32v = vsym->var.special._DeflateLevel;
        dlist = builddatalist(1);
        dlappend(dlist,&con);
    }
    if((tag=(flags & _SHUFFLE_FLAG))) {
        con.nctype = NC_STRING;
        con.value.stringv.stringv
            = (vsym->var.special._Shuffle == 1? "true"
                                              : "false");
        con.value.stringv.len = strlen(con.value.stringv.stringv);
        dlist = builddatalist(1);
        dlappend(dlist,&con);
    }
    if((tag=(flags & _ENDIAN_FLAG))) {
        con.nctype = NC_STRING;
        con.value.stringv.stringv
            = (vsym->var.special._Endianness == 1? "little"
                                                 :"big");
        con.value.stringv.len = strlen(con.value.stringv.stringv);
        dlist = builddatalist(1);
        dlappend(dlist,&con);
    }
    if((tag=(flags & _NOFILL_FLAG))) {
        con.nctype = NC_STRING;
        /* Watch out: flags is NOFILL, but we store FILL */
	if(vsym->var.special._Fill == 1) {
            con.value.stringv.stringv = "false";
	} else {
	    nofill_flag = 1;
            con.value.stringv.stringv = "true";
        }
        con.value.stringv.len = strlen(con.value.stringv.stringv);
        dlist = builddatalist(1);
        dlappend(dlist,&con);
    }
#ifdef NCF213 /*Jira NCF-213*/
/* We should not create an actual
   attribute for any of the
   special attributes.
*/
#endif /*NCF213*/
}
Пример #16
0
static void
genbin_primdata(Symbol* basetype, Datasrc* src, Datalist* fillsrc,
		Bytebuffer* memory)
{
    Constant* prim;
    Constant target;

    prim = srcnext(src);

    if(prim == NULL || prim->nctype == NC_FILLVALUE) {
	genbin_fillvalue(basetype,fillsrc,src,memory);	
	return;
    }

    target.nctype = basetype->typ.typecode;

    if(prim == NULL) {
#ifdef GENFILL
        /* generate a fill value*/
	nc_getfill(&target);
	/* fall thru*/
#else
	return;	
#endif
    }

    ASSERT(prim->nctype != NC_COMPOUND);

    if(target.nctype != NC_ECONST) {
	convert1(prim,&target);
        alignbuffer(&target,memory);
    }

    switch (target.nctype) {
        case NC_ECONST:
	    if(basetype->subclass != NC_ENUM) {
	        semerror(prim->lineno,"Conversion to enum not supported (yet)");
	    } else {
		Datalist* econ = builddatalist(1);
		srcpushlist(src,econ);
		dlappend(econ,&prim->value.enumv->typ.econst);
	        genbin_primdata(prim->value.enumv->typ.basetype,src,
				fillsrc,memory);
		srcpop(src);
	    }
   	    break;
        case NC_OPAQUE: {
	    unsigned char* bytes;
	    size_t len;
	    setprimlength(&target,basetype->typ.size*2);
	    bytes=makebytestring(target.value.opaquev.stringv,&len);
	    bbAppendn(memory,(void*)bytes,len);
	    } break;

        case NC_CHAR:
            bbAppendn(memory,&target.value.charv,sizeof(target.value.charv));
	    break;
        case NC_BYTE:
            bbAppendn(memory,(void*)&target.value.int8v,sizeof(target.value.int8v));
	    break;
        case NC_SHORT:
            bbAppendn(memory,(void*)&target.value.int16v,sizeof(target.value.int16v));
	    break;
        case NC_INT:
            bbAppendn(memory,(void*)&target.value.int32v,sizeof(target.value.int32v));
	    break;
        case NC_FLOAT:
            bbAppendn(memory,(void*)&target.value.floatv,sizeof(target.value.floatv));
	    break;
        case NC_DOUBLE:
            bbAppendn(memory,(void*)&target.value.doublev,sizeof(target.value.doublev));
	    break;
        case NC_UBYTE:
            bbAppendn(memory,(void*)&target.value.uint8v,sizeof(target.value.uint8v));
	    break;
        case NC_USHORT:
            bbAppendn(memory,(void*)&target.value.uint16v,sizeof(target.value.uint16v));
	    break;
        case NC_UINT:
            bbAppendn(memory,(void*)&target.value.uint32v,sizeof(target.value.uint32v));
	    break;
        case NC_INT64: {
	    union SI64 { char ch[8]; long long i64;} si64;
	    si64.i64 = target.value.int64v;
            bbAppendn(memory,(void*)si64.ch,sizeof(si64.ch));
	    } break;
        case NC_UINT64: {
	    union SU64 { char ch[8]; unsigned long long i64;} su64;
	    su64.i64 = target.value.uint64v;
            bbAppendn(memory,(void*)su64.ch,sizeof(su64.ch));
	    } break;
        case NC_STRING: {
            if(usingclassic) {
                bbAppendn(memory,target.value.stringv.stringv,target.value.stringv.len);
            } else if(target.nctype == NC_CHAR) {
                bbAppendn(memory,target.value.stringv.stringv,target.value.stringv.len);
            } else {
                char* ptr;
                int len = (size_t)target.value.stringv.len;
                ptr = poolalloc(len+1); /* CAREFUL: this has short lifetime*/
                memcpy(ptr,target.value.stringv.stringv,len);
                ptr[len] = '\0';
                bbAppendn(memory,(void*)&ptr,sizeof(ptr));
            }
        } break;

        default: PANIC1("genbin_primdata: unexpected type: %d",target.nctype);
    }
}