/* 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); }
/* 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_charattr(Datalist* data, Bytebuffer* databuf) { gen_charvlen(data,databuf); }
/* 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); } }