/* Used only for structure field arrays*/ static void generate_fieldarray(Symbol* basetype, NCConstant* con, Dimset* dimset, Bytebuffer* codebuf, Datalist* filler, Generator* generator) { int i; int chartype = (basetype->typ.typecode == NC_CHAR); Datalist* data; ASSERT(dimset->ndims > 0); if(con != NULL && !isfillconst(con)) data = con->value.compoundv; else data = NULL; if(chartype) { /* Collect the char field in a separate buffer */ Bytebuffer* charbuf = bbNew(); gen_chararray(dimset,data,charbuf,filler); generator->charconstant(generator,codebuf,charbuf); bbFree(charbuf); } else { int uid; size_t xproduct = crossproduct(dimset,0,0); /* compute total number of elements */ generator->listbegin(generator,LISTFIELDARRAY,xproduct,codebuf,&uid); for(i=0;i<xproduct;i++) { con = (data == NULL ? NULL : datalistith(data,i)); generator->list(generator,LISTFIELDARRAY,uid,i,codebuf); generate_basetype(basetype,con,codebuf,NULL,generator); } generator->listend(generator,LISTFIELDARRAY,uid,i,codebuf); } }
/* Used only for structure field arrays*/ static void cdata_fieldarray(Symbol* basetype, Datasrc* src, Odometer* odom, int index, Bytebuffer* codebuf) { int i; int rank = odom->rank; unsigned int size = odom->declsize[index]; int lastdim = (index == (rank - 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,odom,index,fieldbuf); /* Add to the existing data buf as a single constant */ cquotestring(fieldbuf); bbCat(codebuf," "); bbCatbuf(codebuf,fieldbuf); bbFree(fieldbuf); } else { ASSERT(size != 0); for(i=0;i<size;i++) { if(lastdim) { bbAppend(codebuf,' '); cdata_basetype(basetype,src,codebuf,NULL); } else { /* !lastdim*/ cdata_fieldarray(basetype,src,odom,index+1,codebuf); } } } }
/* 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); } } } }
void dumpdatalist(Datalist* list, char* tag) { Bytebuffer* buf = bbNew(); bufdump(list,buf); fprintf(stderr,"%s: %s\n",tag,bbContents(buf)); bbFree(buf); }
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); }
static void genj_defineattr(Symbol* asym) { Bytebuffer* code; /* capture so we can dump vlens first */ ASSERT(asym->data != NULL); code = bbNew(); generator_reset(j_generator,NULL); generate_attrdata(asym,j_generator,(Writer)genj_write,code); bbFree(code); }
static void genj_definevardata(Symbol* vsym) { Bytebuffer* code; /* capture so we can dump vlens first */ if(vsym->data == NULL) return; code = bbNew(); generator_reset(j_generator,NULL); generate_vardata(vsym,j_generator,(Writer)genj_write,code); bbFree(code); }
void report(char* lead, Datalist* list) { extern void bufdump(Datalist*,Bytebuffer*); Bytebuffer* buf = bbNew(); bufdump(list,buf); fprintf(stderr,"\n%s::%s\n",lead,bbContents(buf)); fflush(stderr); bbFree(buf); }
/* 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 cdata_vlenconstants(List* vlenconstants, Bytebuffer* codebuf) { int i,nvlen; Datasrc* vlensrc; Bytebuffer* tmp = bbNew(); nvlen = listlength(vlenconstants); for(i=0;i<nvlen;i++) { Constant* cmpd = (Constant*)listget(vlenconstants,i); int chartype; Symbol* tsym = cmpd->value.compoundv->vlen.schema; ASSERT(tsym != NULL); chartype = (tsym->typ.basetype->typ.typecode == NC_CHAR); bbprintf0(tmp,"static const %s vlen_%u[] = ", ctypename(tsym->typ.basetype), cmpd->value.compoundv->vlen.uid); bbCatbuf(codebuf,tmp); vlensrc = datalist2src(cmpd->value.compoundv); bbAppend(codebuf,'{'); if(chartype) { /* Collect the char vlen in a separate buffer */ Bytebuffer* vlenbuf = bbNew(); gen_charvlen(vlensrc,vlenbuf); /* Add to the existing data buf as a single constant */ cquotestring(vlenbuf); bbCatbuf(codebuf,vlenbuf); bbFree(vlenbuf); } else { size_t count = 0; while(srcmore(vlensrc)) { if(count > 0) bbCat(codebuf,", "); cdata_basetype(tsym->typ.basetype,vlensrc,codebuf,NULL); count++; } ASSERT(count == cmpd->value.compoundv->vlen.count); } bbCat(codebuf,"} ;\n"); } bbFree(tmp); }
char* xescapify(char* s0, int quote, size_t len) { int i; char* result; Bytebuffer* escaped = bbNew(); for(i=0;i<len;i++) { xescapifychar((unsigned int)s0[i],quote,escaped); } result = pooldup(bbContents(escaped)); bbFree(escaped); return result; }
/* Result is a pool string or a constant => do not free*/ char* f77data_const(Constant* ci) { char tmp[64]; char* result = NULL; tmp[0] = '\0'; switch (ci->nctype) { case NC_CHAR: { strcpy(tmp,"'"); escapifychar(ci->value.charv,tmp+1,'\''); strcat(tmp,"'"); } break; case NC_BYTE: sprintf(tmp,"%hhd",ci->value.int8v); break; case NC_SHORT: sprintf(tmp,"%hd",ci->value.int16v); break; case NC_INT: sprintf(tmp,"%d",ci->value.int32v); break; case NC_FLOAT: sprintf(tmp,"%.8g",ci->value.floatv); break; case NC_DOUBLE: { char* p = tmp; /* FORTRAN requires e|E->D */ sprintf(tmp,"%.16g",ci->value.doublev); while(*p) {if(*p == 'e' || *p == 'E') {*p = 'D';}; p++;} } break; case NC_STRING: { Bytebuffer* buf = bbNew(); bbAppendn(buf,ci->value.stringv.stringv,ci->value.stringv.len); f77quotestring(buf); result = bbDup(buf); bbFree(buf); goto done; } break; default: PANIC1("ncstype: bad type code: %d",ci->nctype); } result = pooldup(tmp); done: return result; /*except for NC_STRING and NC_OPAQUE*/ }
void _bbVecFree( void *vec,BBVecType *type ){ if( type->elementType->type==BBTYPE_STR ){ BBStr **p=(BBStr**)vec; for( int k=0;k<type->size;++p,++k ){ if( *p ) _bbStrRelease( *p ); } }else if( type->elementType->type==BBTYPE_OBJ ){ BBObj **p=(BBObj**)vec; for( int k=0;k<type->size;++p,++k ){ if( *p ) _bbObjRelease( *p ); } } bbFree( vec ); }
void destroy( bbGCNode *p ){ // printf( "destroying: %s %p\n",p->typeName(),p ); #if BBGC_DEBUG p->flags=3; #else p->~bbGCNode(); bbFree( p ); #endif }
static int f77_constant(Generator* generator, NCConstant* ci, Bytebuffer* codebuf,...) { char tmp[64]; char* special = NULL; switch (ci->nctype) { case NC_CHAR: if(ci->value.charv == '\'') sprintf(tmp,"'\\''"); else sprintf(tmp,"'%c'",ci->value.charv); break; case NC_BYTE: sprintf(tmp,"%hhd",ci->value.int8v); break; case NC_SHORT: sprintf(tmp,"%hd",ci->value.int16v); break; case NC_INT: sprintf(tmp,"%d",ci->value.int32v); break; case NC_FLOAT: sprintf(tmp,"%.8g",ci->value.floatv); break; case NC_DOUBLE: { char* p = tmp; /* FORTRAN requires e|E->D */ sprintf(tmp,"%.16g",ci->value.doublev); while(*p) {if(*p == 'e' || *p == 'E') {*p = 'D';}; p++;} } break; case NC_STRING: { Bytebuffer* buf = bbNew(); bbAppendn(buf,ci->value.stringv.stringv,ci->value.stringv.len); f77quotestring(buf); special = bbDup(buf); bbFree(buf); } break; default: PANIC1("f77data: bad type code: %d",ci->nctype); } if(special != NULL) bbCat(codebuf,special); else bbCat(codebuf,tmp); return 1; }
void _bbUndimArray( BBArray *array ){ if( void *t=array->data ){ if( array->elementType==BBTYPE_STR ){ BBStr **p=(BBStr**)t; int size=array->scales[array->dims-1]; for( int k=0;k<size;++p,++k ){ if( *p ) _bbStrRelease( *p ); } }else if( array->elementType==BBTYPE_OBJ ){ BBObj **p=(BBObj**)t; int size=array->scales[array->dims-1]; for( int k=0;k<size;++p,++k ){ if( *p ) _bbObjRelease( *p ); } } bbFree( t ); array->data=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); }
void gen_charvlen(Datasrc* vlensrc, Bytebuffer* databuf) { int count; Bytebuffer* vlenbuf = bbNew(); Constant* con; count = 0; while((con=srcnext(vlensrc)) != NULL) { if(!isstringable(con->nctype)) { semerror(srcline(vlensrc), "Encountered non-string constant in vlen constant"); goto done; } count += collectstring(con,0,vlenbuf); } done: bbFree(vlenbuf); }
/* * Return java type name for netCDF type, given type code. */ static void genjstd_defineattribute(Symbol* asym) { unsigned long len; Datalist* list; Bytebuffer* code = NULL; /* capture other decls*/ list = asym->data; if(list == NULL) len = 0; else len = asym->att.count; nprintf(stmt,sizeof(stmt),"/* attribute: %s */",asym->name); jlined(1,stmt); code = bbNew(); genjstd_attrdata(asym,code); /* Handle primitives separately */ if(asym->typ.basetype->typ.typecode != NC_CHAR) commify(code); genjstd_primattribute(asym, code, len); bbFree(code); }
/* 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"); } }
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); }
/* Generate an instance of the basetype */ void generate_basetype(Symbol* tsym, NCConstant* con, Bytebuffer* codebuf, Datalist* filler, Generator* generator) { Datalist* data; switch (tsym->subclass) { case NC_ENUM: case NC_OPAQUE: case NC_PRIM: if(islistconst(con)) { semerror(constline(con),"Expected primitive found {..}"); } generate_primdata(tsym,con,codebuf,filler,generator); break; case NC_COMPOUND: { int i,uid, nfields, dllen; if(con == NULL || isfillconst(con)) { Datalist* fill = (filler==NULL?getfiller(tsym):filler); ASSERT(fill->length == 1); con = &fill->data[0]; if(!islistconst(con)) semerror(con->lineno,"Compound data fill value is not enclosed in {..}"); } if(!islistconst(con)) {/* fail on no compound*/ semerror(constline(con),"Compound data must be enclosed in {..}"); } data = con->value.compoundv; nfields = listlength(tsym->subnodes); dllen = datalistlen(data); if(dllen > nfields) { semerror(con->lineno,"Datalist longer than the number of compound fields"); break; } generator->listbegin(generator,LISTCOMPOUND,listlength(tsym->subnodes),codebuf,&uid); for(i=0;i<nfields;i++) { Symbol* field = (Symbol*)listget(tsym->subnodes,i); con = datalistith(data,i); generator->list(generator,LISTCOMPOUND,uid,i,codebuf); generate_basetype(field,con,codebuf,NULL,generator); } generator->listend(generator,LISTCOMPOUND,uid,i,codebuf); } break; case NC_VLEN: { Bytebuffer* vlenbuf; int uid; size_t count; if(con == NULL || isfillconst(con)) { Datalist* fill = (filler==NULL?getfiller(tsym):filler); ASSERT(fill->length == 1); con = &fill->data[0]; if(con->nctype != NC_COMPOUND) { semerror(con->lineno,"Vlen data fill value is not enclosed in {..}"); } } if(!islistconst(con)) { semerror(constline(con),"Vlen data must be enclosed in {..}"); } data = con->value.compoundv; /* generate the nc_vlen_t instance*/ vlenbuf = bbNew(); if(tsym->typ.basetype->typ.typecode == NC_CHAR) { gen_charvlen(data,vlenbuf); generator->vlenstring(generator,vlenbuf,&uid,&count); } else { generator->listbegin(generator,LISTVLEN,data->length,codebuf,&uid); for(count=0;count<data->length;count++) { NCConstant* con; generator->list(generator,LISTVLEN,uid,count,vlenbuf); con = datalistith(data,count); generate_basetype(tsym->typ.basetype,con,vlenbuf,NULL,generator); } generator->listend(generator,LISTVLEN,uid,count,codebuf,(void*)vlenbuf); } generator->vlendecl(generator,codebuf,tsym,uid,count,vlenbuf); bbFree(vlenbuf); } break; case NC_FIELD: if(tsym->typ.dimset.ndims > 0) { /* Verify that we have a sublist (or fill situation) */ if(con != NULL && !isfillconst(con) && !islistconst(con)) semerror(constline(con),"Dimensioned fields must be enclose in {...}"); generate_fieldarray(tsym->typ.basetype,con,&tsym->typ.dimset,codebuf,filler,generator); } else { generate_basetype(tsym->typ.basetype,con,codebuf,NULL,generator); } break; default: PANIC1("generate_basetype: unexpected subclass %d",tsym->subclass); } }
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; }
static int j_constant(Generator* generator, Symbol* sym, NCConstant* con, Bytebuffer* buf,...) { Bytebuffer* codetmp = bbNew(); char* special = NULL; switch (con->nctype) { case NC_CHAR: if(con->value.charv == '\'') bbprintf(codetmp,"'\\''"); else bbprintf(codetmp,"'%c'",con->value.charv); break; case NC_BYTE: bbprintf(codetmp,"%hhd",con->value.int8v); break; case NC_SHORT: bbprintf(codetmp,"%hd",con->value.int16v); break; case NC_INT: bbprintf(codetmp,"%d",con->value.int32v); break; case NC_FLOAT: /* Special case for nan */ if(isnan(con->value.floatv)) bbprintf(codetmp,"Float.NaN"); else bbprintf(codetmp,"%f",con->value.floatv); break; case NC_DOUBLE: /* Special case for nan */ if(isnan(con->value.doublev)) bbprintf(codetmp,"Double.NaN"); else bbprintf(codetmp,"%lf",con->value.doublev); break; case NC_UBYTE: bbprintf(codetmp,"%hhu",con->value.uint8v); break; case NC_USHORT: bbprintf(codetmp,"%hu",con->value.uint16v); break; case NC_UINT: bbprintf(codetmp,"%uU",con->value.uint32v); break; case NC_INT64: bbprintf(codetmp,"%lldLL",con->value.int64v); break; case NC_UINT64: bbprintf(codetmp,"%lluLLU",con->value.uint64v); break; case NC_STRING: { /* handle separately */ char* escaped = escapify(con->value.stringv.stringv, '"',con->value.stringv.len); special = poolalloc(1+2+strlen(escaped)); strcpy(special,"\""); strcat(special,escaped); strcat(special,"\""); } break; default: PANIC1("ncstype: bad type code: %d",con->nctype); } if(special == NULL) bbCatbuf(buf,codetmp); else bbCat(buf,special); bbFree(codetmp); return 1; }
/* * Generate C code for creating netCDF from in-memory structure. */ void gen_netcdf(const char *filename) { int stat, ncid; int idim, ivar, iatt; int ndims, nvars, natts, ngatts; #ifdef USE_NETCDF4 int ntyps, ngrps, igrp; #endif Bytebuffer* databuf = bbNew(); ndims = listlength(dimdefs); nvars = listlength(vardefs); natts = listlength(attdefs); ngatts = listlength(gattdefs); #ifdef USE_NETCDF4 ntyps = listlength(typdefs); ngrps = listlength(grpdefs); #endif /*USE_NETCDF4*/ /* create netCDF file, uses NC_CLOBBER mode */ cmode_modifier |= NC_CLOBBER; #ifdef USE_NETCDF4 if(!usingclassic) cmode_modifier |= NC_NETCDF4; #endif stat = nc_create(filename, cmode_modifier, &ncid); check_err(stat,__LINE__,__FILE__); /* ncid created above is also root group*/ rootgroup->ncid = ncid; #ifdef USE_NETCDF4 /* Define the group structure */ /* walking grdefs list will do a preorder walk of all defined groups*/ for(igrp=0;igrp<ngrps;igrp++) { Symbol* gsym = (Symbol*)listget(grpdefs,igrp); if(gsym == rootgroup) continue; /* ignore root group*/ stat = nc_def_grp(gsym->container->ncid,gsym->name,&gsym->ncid); check_err(stat,__LINE__,__FILE__); } #endif #ifdef USE_NETCDF4 /* Define the types*/ if (ntyps > 0) { int ityp; for(ityp = 0; ityp < ntyps; ityp++) { Symbol* tsym = (Symbol*)listget(typdefs,ityp); genbin_deftype(tsym); } } #endif /* define dimensions from info in dims array */ if (ndims > 0) { for(idim = 0; idim < ndims; idim++) { Symbol* dsym = (Symbol*)listget(dimdefs,idim); stat = nc_def_dim(dsym->container->ncid, dsym->name, (dsym->dim.isunlimited?NC_UNLIMITED:dsym->dim.declsize), &dsym->ncid); check_err(stat,__LINE__,__FILE__); } } /* define variables from info in vars array */ if (nvars > 0) { for(ivar = 0; ivar < nvars; ivar++) { Symbol* vsym = (Symbol*)listget(vardefs,ivar); if (vsym->typ.dimset.ndims > 0) { /* a dimensioned variable */ /* construct a vector of dimension ids*/ int dimids[NC_MAX_VAR_DIMS]; for(idim=0;idim<vsym->typ.dimset.ndims;idim++) dimids[idim] = vsym->typ.dimset.dimsyms[idim]->ncid; stat = nc_def_var(vsym->container->ncid, vsym->name, vsym->typ.basetype->ncid, vsym->typ.dimset.ndims, dimids, &vsym->ncid); } else { /* a scalar */ stat = nc_def_var(vsym->container->ncid, vsym->name, vsym->typ.basetype->ncid, vsym->typ.dimset.ndims, NULL, &vsym->ncid); } check_err(stat,__LINE__,__FILE__); } } #ifdef USE_NETCDF4 /* define special variable properties */ if(nvars > 0) { for(ivar = 0; ivar < nvars; ivar++) { Symbol* var = (Symbol*)listget(vardefs,ivar); genbin_definespecialattributes(var); } } #endif /*USE_NETCDF4*/ /* define global attributes */ if(ngatts > 0) { for(iatt = 0; iatt < ngatts; iatt++) { Symbol* gasym = (Symbol*)listget(gattdefs,iatt); genbin_defineattr(gasym); } } /* define per-variable attributes */ if(natts > 0) { for(iatt = 0; iatt < natts; iatt++) { Symbol* asym = (Symbol*)listget(attdefs,iatt); genbin_defineattr(asym); } } if (nofill_flag) { stat = nc_set_fill(rootgroup->ncid, NC_NOFILL, 0); check_err(stat,__LINE__,__FILE__); } /* leave define mode */ stat = nc_enddef(rootgroup->ncid); check_err(stat,__LINE__,__FILE__); if(!header_only) { /* Load values into those variables with defined data */ if(nvars > 0) { for(ivar = 0; ivar < nvars; ivar++) { Symbol* vsym = (Symbol*)listget(vardefs,ivar); if(vsym->data != NULL) { bbClear(databuf); genbin_definevardata(vsym); } } } } bbFree(databuf); }
void dumpconstant1(NCConstant* con) { switch (con->nctype) { case NC_COMPOUND: { Datalist* dl = con->value.compoundv; Bytebuffer* buf = bbNew(); bufdump(dl,buf); /* fprintf(stderr,"(0x%lx){",(unsigned long)dl);*/ fprintf(stderr,"{%s}",bbDup(buf)); bbFree(buf); } break; case NC_STRING: if(con->value.stringv.len > 0 && con->value.stringv.stringv != NULL) fprintf(stderr,"\"%s\"",con->value.stringv.stringv); else fprintf(stderr,"\"\""); break; case NC_OPAQUE: if(con->value.opaquev.len > 0 && con->value.opaquev.stringv != NULL) fprintf(stderr,"0x%s",con->value.opaquev.stringv); else fprintf(stderr,"0x--"); break; case NC_ECONST: fprintf(stderr,"%s",(con->value.enumv==NULL?"?":con->value.enumv->name)); break; case NC_FILLVALUE: fprintf(stderr,"_"); break; case NC_CHAR: fprintf(stderr,"'%c'",con->value.charv); break; case NC_BYTE: fprintf(stderr,"%hhd",con->value.int8v); break; case NC_UBYTE: fprintf(stderr,"%hhu",con->value.uint8v); break; case NC_SHORT: fprintf(stderr,"%hd",con->value.int16v); break; case NC_USHORT: fprintf(stderr,"%hu",con->value.uint16v); break; case NC_INT: fprintf(stderr,"%d",con->value.int32v); break; case NC_UINT: fprintf(stderr,"%u",con->value.uint32v); break; case NC_INT64: fprintf(stderr,"%lld",con->value.int64v); break; case NC_UINT64: fprintf(stderr,"%llu",con->value.uint64v); break; case NC_FLOAT: fprintf(stderr,"%g",con->value.floatv); break; case NC_DOUBLE: fprintf(stderr,"%g",con->value.doublev); break; default: fprintf(stderr,"<unknown>"); break; } fflush(stderr); }
/** 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; }
static void genj_writevar(Generator* generator, Symbol* vsym, Bytebuffer* code, int rank, size_t* start, size_t* count) { Dimset* dimset = &vsym->typ.dimset; int typecode = vsym->typ.basetype->typ.typecode; int i; codeline(""); codelined(1,"{"); /* Enclose in {...} for scoping */ if(rank == 0) { bbprintf0(stmt,"%sArray%s.D0 data = new Array%s.D0();\n", indented(1),jtypecap(typecode), jtypecap(typecode)); codedump(stmt); if(typecode == NC_CHAR) { /* Construct the data Array */ jquotestring(code,'\''); bbprintf0(stmt,"%sdata.set((char)%s);\n", indented(1),bbContents(code)); } else { commify(code); bbprintf0(stmt,"%sdata.set((%s)%s);\n", indented(1),jtype(typecode),bbContents(code)); } codedump(stmt); /* do the actual write */ bbprintf0(stmt,"%sncfile.write(\"%s\",data);\n", indented(1),jescapifyname(vsym->name)); codedump(stmt); } else { /* array */ Bytebuffer* dimbuf = bbNew(); /* Construct the dimension set*/ bbCat(dimbuf,"new int[]{"); for(i=0;i<rank;i++) { Symbol* dsym = dimset->dimsyms[i]; char tmp[32]; nprintf(tmp,sizeof(tmp),"%lu",dsym->dim.declsize); if(i>0) {bbCat(dimbuf,", ");} bbCat(dimbuf,tmp); } bbCat(dimbuf,"}"); /* Construct the data array and capture its index */ if(typecode == NC_CHAR) { jquotestring(code,'"'); bbprintf0(stmt,"%sString contents = ", indented(1)); } else { bbprintf0(stmt,"%s%s[] contents = new %s[] {", indented(1),jtype(typecode),jtype(typecode)); commify(code); } codedump(stmt); codedump(code); if(typecode != NC_CHAR) codepartial("}"); codeline(";"); bbprintf0(stmt,"%sArray%s data = new Array%s(%s);\n", indented(1), jtypecap(typecode), jtypecap(typecode), bbContents(dimbuf)); codedump(stmt); codelined(1,"IndexIterator iter = data.getIndexIterator();"); codelined(1,"int count = 0;"); codelined(1,"while(iter.hasNext())"); if(typecode == NC_CHAR) bbprintf0(stmt, "%siter.setCharNext(contents.charAt(count++));\n",indented(2)); else bbprintf0(stmt,"%siter.set%sNext(contents[count++]);\n", indented(2),jtypecap(typecode)); codedump(stmt); bbFree(dimbuf); /* Construct the origin set from the start set */ bbprintf0(stmt,"%sint[] origin = new int[]{",indented(1)); for(i=0;i<rank;i++) { bbprintf(stmt,"%s%lu",(i>0?", ":""),start[i]); } bbCat(stmt,"};\n"); codedump(stmt); /* do the actual write */ bbprintf0(stmt,"%sncfile.write(\"%s\",origin,data);\n", indented(1),jescapifyname(vsym->name)); codedump(stmt); } codelined(1,"}"); /* Enclose in {...} for scoping */ codeflush(); }
static void genjstd_definevardata(Symbol* vsym) { Dimset* dimset = &vsym->typ.dimset; Symbol* basetype = vsym->typ.basetype; int rank = dimset->ndims; int isscalar = (dimset->ndims == 0); Bytebuffer* code; nc_type typecode = basetype->typ.typecode; if(vsym->data == NULL) return; code = bbNew(); jlined(1,"{"); /* Handle special cases first*/ if(isscalar) { /* Construct the data Array */ nprintf(stmt,sizeof(stmt),"Array%s.D0 data = new Array%s.D0();", jtypecap(typecode), jtypecap(typecode)); jlined(1,stmt); /* Fill it */ genjstd_scalardata(vsym,code); if(typecode == NC_CHAR) { nprintf(stmt,sizeof(stmt),"data.set(%s.charAt(0));", bbContents(code)); } else { nprintf(stmt,sizeof(stmt),"data.set((%s)%s);", jtype(typecode),bbContents(code)); } jlined(1,stmt); } else { /* Non-scalar*/ int i; Bytebuffer* dimbuf = bbNew(); /* Store the data */ genjstd_arraydata(vsym,NULL,code); /* Construct the dimension set*/ bbCat(dimbuf,"new int[]{"); for(i=0;i<rank;i++) { Symbol* dsym = dimset->dimsyms[i]; char tmp[32]; if(i==0 && dsym->dim.size == NC_UNLIMITED) nprintf(tmp,sizeof(tmp),"%lu",dsym->dim.unlimitedsize); else nprintf(tmp,sizeof(tmp),"%lu",dsym->dim.size); if(i>0) {bbCat(dimbuf,", ");} bbCat(dimbuf,tmp); } bbCat(dimbuf,"}"); /* Construct the data array and capture its index */ if(typecode == NC_CHAR) nprintf(stmt,sizeof(stmt),"%sString contents = ", indented(1)); else nprintf(stmt,sizeof(stmt),"%s%s[] contents = new %s[] {", indented(1),jtype(typecode),jtype(typecode)); jpartial(stmt); commify(code); jprint(code); if(typecode != NC_CHAR) jpartial("}"); jline(";"); nprintf(stmt,sizeof(stmt),"Array%s data = new Array%s(%s);", jtypecap(typecode), jtypecap(typecode), bbContents(dimbuf)); jlined(1,stmt); jlined(1,"IndexIterator iter = data.getIndexIterator();"); jlined(1,"int count = 0;"); jlined(1,"while(iter.hasNext())"); if(typecode == NC_CHAR) nprintf(stmt,sizeof(stmt), "iter.setCharNext(contents.charAt(count++));"); else nprintf(stmt,sizeof(stmt),"iter.set%sNext(contents[count++]);", jtypecap(typecode)); jlined(2,stmt); bbFree(dimbuf); } /* do the actual write */ nprintf(stmt,sizeof(stmt),"ncfile.write(\"%s\",data);", jescapifyname(vsym->name)); jlined(1,stmt); bbFree(code); jlined(1,"}"); jflush(); }
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); }
static int c_constant(Generator* generator, NCConstant* con, Bytebuffer* buf,...) { Bytebuffer* codetmp = bbNew(); char* special = NULL; switch (con->nctype) { case NC_CHAR: if(con->value.charv == '\'') bbprintf(codetmp,"'\\''"); else bbprintf(codetmp,"'%s'",cescapifychar(con->value.charv,'\'')); break; case NC_BYTE: bbprintf(codetmp,"%hhd",con->value.int8v); break; case NC_SHORT: bbprintf(codetmp,"%hd",con->value.int16v); break; case NC_INT: bbprintf(codetmp,"%d",con->value.int32v); break; case NC_FLOAT: /* Special case for nanf */ if(isnan(con->value.floatv)) bbprintf(codetmp,"nanf"); else bbprintf(codetmp,"%f",con->value.floatv); break; case NC_DOUBLE: /* Special case for nan */ if(isnan(con->value.doublev)) bbprintf(codetmp,"nan"); else bbprintf(codetmp,"%lf",con->value.doublev); break; case NC_UBYTE: bbprintf(codetmp,"%hhu",con->value.uint8v); break; case NC_USHORT: bbprintf(codetmp,"%hu",con->value.uint16v); break; case NC_UINT: bbprintf(codetmp,"%uU",con->value.uint32v); break; case NC_INT64: bbprintf(codetmp,"%lldLL",con->value.int64v); break; case NC_UINT64: bbprintf(codetmp,"%lluLLU",con->value.uint64v); break; case NC_ECONST: bbprintf(codetmp,"%s",cname(con->value.enumv)); break; case NC_NIL: case NC_STRING: { /* handle separately */ if(con->value.stringv.len == 0 && con->value.stringv.stringv == NULL) { bbprintf(codetmp,"NULL"); } else { char* escaped = escapify(con->value.stringv.stringv, '"',con->value.stringv.len); special = poolalloc(1+2+strlen(escaped)); strcpy(special,"\""); strcat(special,escaped); strcat(special,"\""); } } break; case NC_OPAQUE: { char* p; int bslen; bslen=(4*con->value.opaquev.len); special = poolalloc(bslen+2+1); strcpy(special,"\""); p = con->value.opaquev.stringv; while(*p) { strcat(special,"\\x"); strncat(special,p,2); p += 2; } strcat(special,"\""); } break; default: PANIC1("ncstype: bad type code: %d",con->nctype); } if(special == NULL) bbCatbuf(buf,codetmp); else bbCat(buf,special); bbFree(codetmp); return 1; }