/* 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); } }
static void generate_primdata(Symbol* basetype, Constant* prim, Bytebuffer* codebuf, Datalist* filler, Generator* generator) { Constant target; if(prim == NULL || isfillconst(prim)) { Datalist* fill = (filler==NULL?getfiller(basetype):filler); ASSERT(fill->length == 1); prim = datalistith(fill,0); } ASSERT(prim->nctype != NC_COMPOUND); 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(constline(prim),"Conversion to enum not supported (yet)"); } break; case NC_OPAQUE: setprimlength(&target,basetype->typ.size*2); break; default: break; } generator->constant(generator,&target,codebuf); return; }
static void generate_primdata(Symbol* basetype, NCConstant* prim, Bytebuffer* codebuf, Datalist* filler, Generator* generator) { NCConstant target; int match; if(prim == NULL || isfillconst(prim)) { Datalist* fill = (filler==NULL?getfiller(basetype):filler); ASSERT(fill->length == 1); prim = datalistith(fill,0); } ASSERT(prim->nctype != NC_COMPOUND); /* Verify that the constant is consistent with the type */ match = 1; switch (prim->nctype) { case NC_CHAR: case NC_BYTE: case NC_SHORT: case NC_INT: case NC_FLOAT: case NC_DOUBLE: case NC_UBYTE: case NC_USHORT: case NC_UINT: case NC_INT64: case NC_UINT64: case NC_STRING: match = (basetype->subclass == NC_PRIM ? 1 : 0); break; #ifdef USE_NETCDF4 case NC_NIL: match = (basetype->subclass == NC_PRIM && basetype->typ.typecode == NC_STRING ? 1 : 0); break; case NC_OPAQUE: /* OPAQUE is also consistent with numbers */ match = (basetype->subclass == NC_OPAQUE || basetype->subclass == NC_PRIM ? 1 : 0); break; case NC_ECONST: match = (basetype->subclass == NC_ENUM ? 1 : 0); if(match) { /* Make sure this econst belongs to this enum */ Symbol* ec = prim->value.enumv; Symbol* en = ec->container; match = (en == basetype); } break; #endif default: match = 0; } if(!match) { semerror(constline(prim),"Data value is not consistent with the expected type: %s", basetype->name); } 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(constline(prim),"Conversion to enum not supported (yet)"); } break; case NC_OPAQUE: normalizeopaquelength(&target,basetype->typ.size); break; default: break; } generator->constant(generator,&target,codebuf); return; }
/* 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); } }