void convert1(Constant* src, Constant* dst) { Constvalue tmp; unsigned char* bytes = NULL; size_t bytelen; dst->lineno = src->lineno; /* Need to translate all possible sources to all possible sinks.*/ /* Rather than have a nested switch, combine the src and target into*/ /* a single value so we can do a single n*n-way switch*/ /* special case for src being NC_FILLVALUE*/ if(src->nctype == NC_FILLVALUE) { if(dst->nctype != NC_FILLVALUE) { nc_getfill(dst); } return; } /* special case handling for src being NC_ECONST*/ if(src->nctype == NC_ECONST) { if(dst->nctype == NC_ECONST) { dst->value = src->value; } else { Symbol* econst; econst = src->value.enumv; convert1(&econst->typ.econst,dst); } return; } else if(dst->nctype == NC_ECONST) { /* special case for dst being NC_ECONST*/ semerror(lineno,"Conversion to enum not supported (yet)"); return; } if(src->nctype == NC_OPAQUE) { bytes = makebytestring(src->value.opaquev.stringv,&bytelen); } #define CASE(nc1,nc2) (nc1*256+nc2) switch (CASE(src->nctype,dst->nctype)) { case CASE(NC_CHAR,NC_CHAR): tmp.charv = src->value.charv; break; case CASE(NC_CHAR,NC_BYTE): tmp.int8v = (unsigned char)src->value.charv; break; case CASE(NC_CHAR,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.charv; break; case CASE(NC_CHAR,NC_USHORT): tmp.uint16v = (unsigned short)src->value.charv; break; case CASE(NC_CHAR,NC_UINT): tmp.uint32v = (unsigned int)src->value.charv; break; case CASE(NC_CHAR,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.charv; break; case CASE(NC_CHAR,NC_SHORT): tmp.int16v = (short)src->value.charv; break; case CASE(NC_CHAR,NC_INT): tmp.int32v = (int)src->value.charv; break; case CASE(NC_CHAR,NC_INT64): tmp.int64v = (long long)src->value.charv; break; case CASE(NC_CHAR,NC_FLOAT): tmp.floatv = (float)src->value.charv; break; case CASE(NC_CHAR,NC_DOUBLE): tmp.doublev = (double)src->value.charv; break; case CASE(NC_BYTE,NC_CHAR): tmp.charv = (char)src->value.uint8v; break; case CASE(NC_BYTE,NC_BYTE): tmp.uint8v = (unsigned char)src->value.uint8v; break; case CASE(NC_BYTE,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.uint8v; break; case CASE(NC_BYTE,NC_USHORT): tmp.uint16v = (unsigned short)src->value.uint8v; break; case CASE(NC_BYTE,NC_UINT): tmp.uint32v = (unsigned int)src->value.uint8v; break; case CASE(NC_BYTE,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.uint8v; break; case CASE(NC_BYTE,NC_SHORT): tmp.int16v = (short)src->value.uint8v; break; case CASE(NC_BYTE,NC_INT): tmp.int32v = (int)src->value.uint8v; break; case CASE(NC_BYTE,NC_INT64): tmp.int64v = (long long)src->value.uint8v; break; case CASE(NC_BYTE,NC_FLOAT): tmp.floatv = (float)src->value.uint8v; break; case CASE(NC_BYTE,NC_DOUBLE): tmp.doublev = (double)src->value.uint8v; break; case CASE(NC_UBYTE,NC_CHAR): tmp.charv = (char)src->value.uint8v; break; case CASE(NC_UBYTE,NC_BYTE): tmp.uint8v = (unsigned char)src->value.uint8v; break; case CASE(NC_UBYTE,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.uint8v; break; case CASE(NC_UBYTE,NC_USHORT): tmp.uint16v = (unsigned short)src->value.uint8v; break; case CASE(NC_UBYTE,NC_UINT): tmp.uint32v = (unsigned int)src->value.uint8v; break; case CASE(NC_UBYTE,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.uint8v; break; case CASE(NC_UBYTE,NC_SHORT): tmp.int16v = (short)src->value.uint8v; break; case CASE(NC_UBYTE,NC_INT): tmp.int32v = (int)src->value.uint8v; break; case CASE(NC_UBYTE,NC_INT64): tmp.int64v = (long long)src->value.uint8v; break; case CASE(NC_UBYTE,NC_FLOAT): tmp.floatv = (float)src->value.uint8v; break; case CASE(NC_UBYTE,NC_DOUBLE): tmp.doublev = (double)src->value.uint8v; break; case CASE(NC_USHORT,NC_BYTE): tmp.uint8v = (unsigned char)src->value.uint16v; break; case CASE(NC_USHORT,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.uint16v; break; case CASE(NC_USHORT,NC_USHORT): tmp.uint16v = (unsigned short)src->value.uint16v; break; case CASE(NC_USHORT,NC_UINT): tmp.uint32v = (unsigned int)src->value.uint16v; break; case CASE(NC_USHORT,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.uint16v; break; case CASE(NC_USHORT,NC_SHORT): tmp.int16v = (short)src->value.uint16v; break; case CASE(NC_USHORT,NC_INT): tmp.int32v = (int)src->value.uint16v; break; case CASE(NC_USHORT,NC_INT64): tmp.int64v = (long long)src->value.uint16v; break; case CASE(NC_USHORT,NC_FLOAT): tmp.floatv = (float)src->value.uint16v; break; case CASE(NC_USHORT,NC_DOUBLE): tmp.doublev = (double)src->value.uint16v; break; case CASE(NC_UINT,NC_BYTE): tmp.uint8v = (unsigned char)src->value.uint32v; break; case CASE(NC_UINT,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.uint32v; break; case CASE(NC_UINT,NC_USHORT): tmp.uint16v = (unsigned short)src->value.uint32v; break; case CASE(NC_UINT,NC_UINT): tmp.uint32v = (unsigned int)src->value.uint32v; break; case CASE(NC_UINT,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.uint32v; break; case CASE(NC_UINT,NC_SHORT): tmp.int16v = (short)src->value.uint32v; break; case CASE(NC_UINT,NC_INT): tmp.int32v = (int)src->value.uint32v; break; case CASE(NC_UINT,NC_INT64): tmp.int64v = (long long)src->value.uint32v; break; case CASE(NC_UINT,NC_FLOAT): tmp.floatv = (float)src->value.uint32v; break; case CASE(NC_UINT,NC_DOUBLE): tmp.doublev = (double)src->value.uint32v; break; case CASE(NC_UINT64,NC_BYTE): tmp.uint8v = (unsigned char)src->value.uint64v; break; case CASE(NC_UINT64,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.uint64v; break; case CASE(NC_UINT64,NC_USHORT): tmp.uint16v = (unsigned short)src->value.uint64v; break; case CASE(NC_UINT64,NC_UINT): tmp.uint32v = (unsigned int)src->value.uint64v; break; case CASE(NC_UINT64,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.uint64v; break; case CASE(NC_UINT64,NC_SHORT): tmp.int16v = (short)src->value.uint64v; break; case CASE(NC_UINT64,NC_INT): tmp.int32v = (int)src->value.uint64v; break; case CASE(NC_UINT64,NC_INT64): tmp.int64v = (long long)src->value.uint64v; break; case CASE(NC_UINT64,NC_FLOAT): tmp.floatv = (float)src->value.uint64v; break; case CASE(NC_UINT64,NC_DOUBLE): tmp.doublev = (double)src->value.uint64v; break; case CASE(NC_SHORT,NC_BYTE): tmp.uint8v = (unsigned char)src->value.int16v; break; case CASE(NC_SHORT,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.int16v; break; case CASE(NC_SHORT,NC_USHORT): tmp.uint16v = (unsigned short)src->value.int16v; break; case CASE(NC_SHORT,NC_UINT): tmp.uint32v = (unsigned int)src->value.int16v; break; case CASE(NC_SHORT,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.int16v; break; case CASE(NC_SHORT,NC_SHORT): tmp.int16v = (short)src->value.int16v; break; case CASE(NC_SHORT,NC_INT): tmp.int32v = (int)src->value.int16v; break; case CASE(NC_SHORT,NC_INT64): tmp.int64v = (long long)src->value.int16v; break; case CASE(NC_SHORT,NC_FLOAT): tmp.floatv = (float)src->value.int16v; break; case CASE(NC_SHORT,NC_DOUBLE): tmp.doublev = (double)src->value.int16v; break; case CASE(NC_INT,NC_BYTE): tmp.uint8v = (unsigned char)src->value.int32v; break; case CASE(NC_INT,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.int32v; break; case CASE(NC_INT,NC_USHORT): tmp.uint16v = (unsigned short)src->value.int32v; break; case CASE(NC_INT,NC_UINT): tmp.uint32v = (unsigned int)src->value.int32v; break; case CASE(NC_INT,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.int32v; break; case CASE(NC_INT,NC_SHORT): tmp.int16v = (short)src->value.int32v; break; case CASE(NC_INT,NC_INT): tmp.int32v = (int)src->value.int32v; break; case CASE(NC_INT,NC_INT64): tmp.int64v = (long long)src->value.int32v; break; case CASE(NC_INT,NC_FLOAT): tmp.floatv = (float)src->value.int32v; break; case CASE(NC_INT,NC_DOUBLE): tmp.doublev = (double)src->value.int32v; break; case CASE(NC_INT64,NC_BYTE): tmp.uint8v = (unsigned char)src->value.int64v; break; case CASE(NC_INT64,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.int64v; break; case CASE(NC_INT64,NC_USHORT): tmp.uint16v = (unsigned short)src->value.int64v; break; case CASE(NC_INT64,NC_UINT): tmp.uint32v = (unsigned int)src->value.int64v; break; case CASE(NC_INT64,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.int64v; break; case CASE(NC_INT64,NC_SHORT): tmp.int16v = (short)src->value.int64v; break; case CASE(NC_INT64,NC_INT): tmp.int32v = (int)src->value.int64v; break; case CASE(NC_INT64,NC_INT64): tmp.int64v = (long long)src->value.int64v; break; case CASE(NC_INT64,NC_FLOAT): tmp.floatv = (float)src->value.int64v; break; case CASE(NC_INT64,NC_DOUBLE): tmp.doublev = (double)src->value.int64v; break; case CASE(NC_FLOAT,NC_BYTE): tmp.uint8v = (unsigned char)src->value.floatv; break; case CASE(NC_FLOAT,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.floatv; break; case CASE(NC_FLOAT,NC_USHORT): tmp.uint16v = (unsigned short)src->value.floatv; break; case CASE(NC_FLOAT,NC_UINT): tmp.uint32v = (unsigned int)src->value.floatv; break; case CASE(NC_FLOAT,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.floatv; break; case CASE(NC_FLOAT,NC_SHORT): tmp.int16v = (short)src->value.floatv; break; case CASE(NC_FLOAT,NC_INT): tmp.int32v = (int)src->value.floatv; break; case CASE(NC_FLOAT,NC_INT64): tmp.int64v = (long long)src->value.floatv; break; case CASE(NC_FLOAT,NC_FLOAT): tmp.floatv = src->value.floatv; break; case CASE(NC_FLOAT,NC_DOUBLE): tmp.doublev = (isnan(src->value.floatv)?NAN:(double)src->value.floatv); break; case CASE(NC_DOUBLE,NC_BYTE): tmp.uint8v = (unsigned char)src->value.doublev; break; case CASE(NC_DOUBLE,NC_UBYTE): tmp.uint8v = (unsigned char)src->value.doublev; break; case CASE(NC_DOUBLE,NC_USHORT): tmp.uint16v = (unsigned short)src->value.doublev; break; case CASE(NC_DOUBLE,NC_UINT): tmp.uint32v = (unsigned int)src->value.doublev; break; case CASE(NC_DOUBLE,NC_UINT64): tmp.uint64v = (unsigned long long)src->value.doublev; break; case CASE(NC_DOUBLE,NC_SHORT): tmp.int16v = (short)src->value.doublev; break; case CASE(NC_DOUBLE,NC_INT): tmp.int32v = (int)src->value.doublev; break; case CASE(NC_DOUBLE,NC_INT64): tmp.int64v = (long long)src->value.doublev; break; case CASE(NC_DOUBLE,NC_FLOAT): tmp.floatv = (isnan(src->value.doublev)?NANF:(float)src->value.doublev); break; case CASE(NC_DOUBLE,NC_DOUBLE): tmp.doublev = (double)src->value.doublev; break; /* Conversion of a string to e.g. an integer should be what?*/ case CASE(NC_STRING,NC_BYTE): sscanf(src->value.stringv.stringv,"%hhd",&tmp.int8v); break; case CASE(NC_STRING,NC_UBYTE): sscanf(src->value.stringv.stringv,"%hhu",&tmp.uint8v); break; case CASE(NC_STRING,NC_USHORT): sscanf(src->value.stringv.stringv,"%hu",&tmp.uint16v); break; case CASE(NC_STRING,NC_UINT): sscanf(src->value.stringv.stringv,"%u",&tmp.uint32v); break; case CASE(NC_STRING,NC_UINT64): sscanf(src->value.stringv.stringv,"%llu",&tmp.uint64v); break; case CASE(NC_STRING,NC_SHORT): sscanf(src->value.stringv.stringv,"%hd",&tmp.int16v); break; case CASE(NC_STRING,NC_INT): sscanf(src->value.stringv.stringv,"%d",&tmp.int32v); break; case CASE(NC_STRING,NC_INT64): sscanf(src->value.stringv.stringv,"%lld",&tmp.int64v); break; case CASE(NC_STRING,NC_FLOAT): sscanf(src->value.stringv.stringv,"%g",&tmp.floatv); break; case CASE(NC_STRING,NC_DOUBLE): sscanf(src->value.stringv.stringv,"%lg",&tmp.doublev); break; case CASE(NC_STRING,NC_CHAR): tmp.charv = src->value.stringv.stringv[0]; break; case CASE(NC_STRING,NC_STRING): tmp.stringv.stringv = nulldup(src->value.stringv.stringv); tmp.stringv.len = src->value.stringv.len; break; /* What is the proper conversion for T->STRING?*/ case CASE(NC_CHAR,NC_STRING): sprintf(stmp,"%c",src->value.charv); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_BYTE,NC_STRING): sprintf(stmp,"%hhd",src->value.uint8v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_UBYTE,NC_STRING): sprintf(stmp,"%hhu",src->value.uint8v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_USHORT,NC_STRING): sprintf(stmp,"%hu",src->value.uint16v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_UINT,NC_STRING): sprintf(stmp,"%u",src->value.uint32v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_UINT64,NC_STRING): sprintf(stmp,"%llu",src->value.uint64v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_SHORT,NC_STRING): sprintf(stmp,"%hd",src->value.int16v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_INT,NC_STRING): sprintf(stmp,"%d",src->value.int32v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_INT64,NC_STRING): sprintf(stmp,"%lld",src->value.int64v); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_FLOAT,NC_STRING): sprintf(stmp,"%.8g",src->value.floatv); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_DOUBLE,NC_STRING): sprintf(stmp,"%.8g",src->value.doublev); tmp.stringv.len = nulllen(stmp); tmp.stringv.stringv = nulldup(stmp); break; case CASE(NC_OPAQUE,NC_CHAR): if(bytes) tmp.charv = *(char*)bytes; break; case CASE(NC_OPAQUE,NC_BYTE): if(bytes) tmp.uint8v = *(unsigned char*)bytes; break; case CASE(NC_OPAQUE,NC_UBYTE): if(bytes) tmp.uint8v = *(unsigned char*)bytes; break; case CASE(NC_OPAQUE,NC_USHORT): if(bytes) tmp.uint16v = *(unsigned short*)bytes; break; case CASE(NC_OPAQUE,NC_UINT): if(bytes) tmp.uint32v = *(unsigned int*)bytes; break; case CASE(NC_OPAQUE,NC_UINT64): if(bytes) tmp.uint64v = *(unsigned long long*)bytes; break; case CASE(NC_OPAQUE,NC_SHORT): if(bytes) tmp.int16v = *(short*)bytes; break; case CASE(NC_OPAQUE,NC_INT): if(bytes) tmp.int32v = *(int*)bytes; break; case CASE(NC_OPAQUE,NC_INT64): if(bytes) tmp.int64v = *(long long*)bytes; break; case CASE(NC_OPAQUE,NC_FLOAT): if(bytes) tmp.floatv = *(float*)bytes; break; case CASE(NC_OPAQUE,NC_DOUBLE): if(bytes) tmp.doublev = *(double*)bytes; break; case CASE(NC_OPAQUE,NC_OPAQUE): tmp.opaquev.stringv = (char*)malloc(src->value.opaquev.len+1); memcpy(tmp.opaquev.stringv,src->value.opaquev.stringv,src->value.opaquev.len); tmp.opaquev.len = src->value.opaquev.len; tmp.opaquev.stringv[tmp.opaquev.len] = '\0'; break; /* We are missing all CASE(X,NC_ECONST) cases*/ default: semerror(lineno,"transform: illegal conversion: %s/%d -> %s/%d", nctypename(src->nctype),src->nctype, nctypename(dst->nctype),dst->nctype); break;; } if(bytes != NULL) efree(bytes); /* cleanup*/ /* overwrite minimum necessary parts*/ dst->value = tmp; }
/* 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; }
static int bin_constant(Generator* generator, Symbol* sym, NCConstant* con, Bytebuffer* buf,...) { if(con->nctype != NC_ECONST) { alignbuffer(con,buf); } switch (con->nctype) { case NC_OPAQUE: { unsigned char* bytes = NULL; size_t len; /* Assume the opaque string has been normalized */ bytes=makebytestring(con->value.opaquev.stringv,&len); bbAppendn(buf,(void*)bytes,len); efree(bytes); } break; case NC_CHAR: bbAppendn(buf,&con->value.charv,sizeof(con->value.charv)); break; case NC_BYTE: bbAppendn(buf,(void*)&con->value.int8v,sizeof(con->value.int8v)); break; case NC_SHORT: bbAppendn(buf,(void*)&con->value.int16v,sizeof(con->value.int16v)); break; case NC_INT: bbAppendn(buf,(void*)&con->value.int32v,sizeof(con->value.int32v)); break; case NC_FLOAT: bbAppendn(buf,(void*)&con->value.floatv,sizeof(con->value.floatv)); break; case NC_DOUBLE: bbAppendn(buf,(void*)&con->value.doublev,sizeof(con->value.doublev)); break; case NC_UBYTE: bbAppendn(buf,(void*)&con->value.uint8v,sizeof(con->value.uint8v)); break; case NC_USHORT: bbAppendn(buf,(void*)&con->value.uint16v,sizeof(con->value.uint16v)); break; case NC_UINT: bbAppendn(buf,(void*)&con->value.uint32v,sizeof(con->value.uint32v)); break; case NC_INT64: { union SI64 { char ch[8]; long long i64;} si64; si64.i64 = con->value.int64v; bbAppendn(buf,(void*)si64.ch,sizeof(si64.ch)); } break; case NC_UINT64: { union SU64 { char ch[8]; unsigned long long i64;} su64; su64.i64 = con->value.uint64v; bbAppendn(buf,(void*)su64.ch,sizeof(su64.ch)); } break; case NC_NIL: case NC_STRING: { int len = (size_t)con->value.stringv.len; if(len == 0 && con->value.stringv.stringv == NULL) { char* nil = NULL; bbAppendn(buf,(void*)&nil,sizeof(nil)); } else { char* ptr = (char*)ecalloc(len+1); memcpy(ptr,con->value.stringv.stringv,len); ptr[len] = '\0'; bbAppendn(buf,(void*)&ptr,sizeof(ptr)); ptr = NULL; } } break; default: PANIC1("bin_constant: unexpected type: %d",con->nctype); } return 1; }
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); } }