static void processenums(void) { unsigned long i,j; #if 0 /* Unused? */ List* enumids = listnew(); #endif for(i=0;i<listlength(typdefs);i++) { Symbol* sym = (Symbol*)listget(typdefs,i); ASSERT(sym->objectclass == NC_TYPE); if(sym->subclass != NC_ENUM) continue; for(j=0;j<listlength(sym->subnodes);j++) { Symbol* esym = (Symbol*)listget(sym->subnodes,j); ASSERT(esym->subclass == NC_ECONST); #if 0 /* Unused? */ listpush(enumids,(void*)esym); #endif } } /* Convert enum values to match enum type*/ for(i=0;i<listlength(typdefs);i++) { Symbol* tsym = (Symbol*)listget(typdefs,i); ASSERT(tsym->objectclass == NC_TYPE); if(tsym->subclass != NC_ENUM) continue; for(j=0;j<listlength(tsym->subnodes);j++) { Symbol* esym = (Symbol*)listget(tsym->subnodes,j); NCConstant* newec = nullconst(); ASSERT(esym->subclass == NC_ECONST); newec->nctype = esym->typ.typecode; convert1(esym->typ.econst,newec); reclaimconstant(esym->typ.econst); esym->typ.econst = newec; } } }
NCConstant* list2const(Datalist* list) { NCConstant* con = nullconst(); ASSERT(list != NULL); con->nctype = NC_COMPOUND; con->lineno = list->data[0]->lineno; setconstlist(con,list); con->filled = 0; return con; }
/* Deep constant cloning; return struct not pointer to struct*/ NCConstant* cloneconstant(NCConstant* con) { NCConstant* newcon = NULL; Datalist* newdl = NULL; char* s = NULL; newcon = nullconst(); if(newcon == NULL) return newcon; *newcon = *con; switch (newcon->nctype) { case NC_STRING: if(newcon->value.stringv.len == 0) s = NULL; else { s = (char*)ecalloc(newcon->value.stringv.len+1); if(newcon->value.stringv.len > 0) memcpy(s,newcon->value.stringv.stringv,newcon->value.stringv.len); s[newcon->value.stringv.len] = '\0'; } newcon->value.stringv.stringv = s; break; case NC_OPAQUE: s = (char*)ecalloc(newcon->value.opaquev.len+1); if(newcon->value.opaquev.len > 0) memcpy(s,newcon->value.opaquev.stringv,newcon->value.opaquev.len); s[newcon->value.opaquev.len] = '\0'; newcon->value.opaquev.stringv = s; break; case NC_COMPOUND: newdl = clonedatalist(con->value.compoundv); setconstlist(newcon,newdl); break; default: break; } return newcon; }
/* Recursive helper that does the bulk of the work */ static int bin_generate_data_r(NCConstant* instance, Symbol* tsym, Datalist* fillvalue, Bytebuffer* databuf) { int stat = NC_NOERR; if(instance->nctype == NC_FILLVALUE) { /* replace with fillvalue for the type */ Datalist* filllist = (fillvalue == NULL ? getfiller(tsym) : fillvalue); ASSERT(datalistlen(filllist)==1) instance = datalistith(filllist,0); } switch (tsym->subclass) { case NC_PRIM: { switch (tsym->nc_id) { case NC_CHAR: { char* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_CHAR; convert1(instance,tmp); p = &tmp->value.charv;; bbAppendn(databuf,p,sizeof(char)); reclaimconstant(tmp); } break; case NC_BYTE: { signed char* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_BYTE; convert1(instance,tmp); p = &tmp->value.int8v; bbAppendn(databuf,p,sizeof(signed char)); reclaimconstant(tmp); } break; case NC_UBYTE: { unsigned char* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_UBYTE; convert1(instance,tmp); p = &tmp->value.uint8v; bbAppendn(databuf,p,sizeof(unsigned char)); reclaimconstant(tmp); } break; case NC_SHORT: { short* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_SHORT; convert1(instance,tmp); p = &tmp->value.int16v; bbAppendn(databuf,p,sizeof(short)); reclaimconstant(tmp); } break; case NC_USHORT: { unsigned short* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_USHORT; convert1(instance,tmp); p = &tmp->value.uint16v; bbAppendn(databuf,p,sizeof(unsigned short)); reclaimconstant(tmp); } break; case NC_INT: { int* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_INT; convert1(instance,tmp); p = &tmp->value.int32v; bbAppendn(databuf,p,sizeof(int)); reclaimconstant(tmp); } break; case NC_UINT: { unsigned int* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_UINT; convert1(instance,tmp); p = &tmp->value.uint32v; bbAppendn(databuf,p,sizeof(unsigned int)); reclaimconstant(tmp); } break; case NC_INT64: { long long* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_INT64; convert1(instance,tmp); p = &tmp->value.int64v; bbAppendn(databuf,p,sizeof(long long)); reclaimconstant(tmp); } break; case NC_UINT64: { unsigned long long* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_UINT64; convert1(instance,tmp); p = &tmp->value.uint64v; bbAppendn(databuf,p,sizeof(unsigned long long)); reclaimconstant(tmp); } break; case NC_FLOAT: { float* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_FLOAT; convert1(instance,tmp); p = &tmp->value.floatv; bbAppendn(databuf,p,sizeof(float)); reclaimconstant(tmp); } break; case NC_DOUBLE: { double* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_DOUBLE; convert1(instance,tmp); p = &tmp->value.doublev; bbAppendn(databuf,p,sizeof(double)); reclaimconstant(tmp); } break; case NC_STRING: { char* p = NULL; NCConstant* tmp = nullconst(); tmp->nctype = NC_STRING; convert1(instance,tmp); p = emalloc(tmp->value.stringv.len+1); memcpy(p,tmp->value.stringv.stringv,tmp->value.stringv.len); p[tmp->value.stringv.len] = '\0'; bbAppendn(databuf,&p,sizeof(char*)); reclaimconstant(tmp); } break; default: stat = NC_EINTERNAL; goto done; /* Should never happen */ } break; /*switch*/ } break; /*NC_PRIM*/ case NC_ENUM: { Symbol* basetype = tsym->typ.basetype; /* Pretend */ stat = bin_generate_data_r(instance,basetype,fillvalue,databuf); } break; case NC_OPAQUE: { unsigned char* bytes = NULL; size_t len = 0; if(instance->nctype != NC_OPAQUE) {stat = NC_EBADTYPE; goto done;} /* Assume the opaque string has been normalized */ bytes=makebytestring(instance->value.opaquev.stringv,&len); if(bytes == NULL) {stat = NC_ENOMEM; goto done;} bbAppendn(databuf,(void*)bytes,len); free(bytes); } break; case NC_VLEN: { Datalist* sublist = NULL; Bytebuffer* vlendata = NULL; nc_vlen_t p; if(instance->nctype != NC_COMPOUND) { nclog(NCLOGERR,"Translating vlen: expected sublist"); stat = NC_EBADTYPE; goto done; } sublist = instance->value.compoundv; vlendata = bbNew(); if((stat = binary_generate_data(sublist,tsym->typ.basetype,NULL,vlendata))) goto done; p.len = datalistlen(sublist); p.p = bbContents(vlendata); bbAppendn(databuf,(char*)&p,sizeof(nc_vlen_t)); } break; case NC_COMPOUND: { /* The really hard one */ size_t nfields, fid, i; Datalist* cmpd = instance->value.compoundv; write_alignment(tsym->typ.cmpdalign,databuf); /* Get info about each field in turn and build it*/ nfields = listlength(tsym->subnodes); for(fid=0;fid<nfields;fid++) { Symbol* field = listget(tsym->subnodes,fid); NCConstant* fieldinstance = datalistith(cmpd,fid); int ndims = field->typ.dimset.ndims; size_t arraycount; if(ndims == 0) { ndims=1; /* fake the scalar case */ } /* compute the total number of elements in the field array */ arraycount = 1; for(i=0;i<ndims;i++) arraycount *= field->typ.dimset.dimsyms[i]->dim.declsize; write_alignment(field->typ.alignment,databuf); /* Write the instances */ for(i=0;i<arraycount;i++) { if((stat = bin_generate_data_r(fieldinstance, field->typ.basetype, NULL, databuf))) goto done; } } } break; default: stat = NC_EINTERNAL; goto done; /* Should never happen */ } done: return stat; }