int srcmore(Datasrc* ds) { if(ds == NULL) return 0; if(ds->index < ds->length) return 1; if(ds->spliced) return srcmore(ds->prev); return 0; }
static int checkfill(Symbol* tsym, Datasrc* src) { int i,iscmpd,result; Constant* con; Symbol* original = tsym; result = 1; switch (tsym->subclass) { case NC_ENUM: case NC_OPAQUE: case NC_PRIM: con = srcnext(src); if(src == NULL) { semerror(srcline(src),"%s: malformed _FillValue",original->name); result = 0; } else if(con->nctype != tsym->typ.typecode) result = 0; /* wrong type*/ break; case NC_COMPOUND: if(!issublist(src)) {/* fail on no compound*/ semerror(srcline(src),"Compound constants must be enclosed in {..}"); } srcpush(src); for(i=0;i<listlength(tsym->subnodes);i++) { Symbol* field = (Symbol*)listget(tsym->subnodes,i); result = checkfill(field,src,original); if(!result) break; } srcpop(src); break; case NC_VLEN: if(!issublist(src)) { semerror(srcline(src),"%s: vlen instances in _FillValue must be enclosed in {...}",original->name); result = 0; } else { srcpush(src); while(srcmore(src)) { result = checkfill(tsym->typ.basetype,src,original); if(!result) break; } srcpop(src); } break; case NC_FIELD: /* Braces are optional */ if((iscmpd=issublist(src))) srcpush(src); if(tsym->typ.dimset.ndims > 0) { result = checkarray(tsym->typ.basetype,&tsym->typ.dimset,0,src,original,!TOPLEVEL); } else result = checkfill(tsym->typ.basetype,src,original); if(iscmpd) srcpop(src); break; default: PANIC1("checkfillvalue: unexpected subclass %d",tsym->subclass); } return result; }
static int checkarray(Symbol* basetype, Dimset* dimset, int index, Datasrc* src, Symbol* original, int toplevel) { int i,result; Symbol* dim = dimset->dimsyms[index]; unsigned int size = dim->dim.declsize; int lastdim = (index == (dimset->ndims - 1)); int isunlimited = (size == 0); result = 1; if(isunlimited) { if(!toplevel) { if(!issublist(src)) { semerror(srcline(src),"UNLIMITED dimension constants (other than top level) must be enclosed in {...}"); result = 0; goto done; } else srcpush(src); } if(lastdim) { while(srcmore(src) && result) { result = checkfill(basetype,src,original); } } else { /*!lastdim*/ while(srcmore(src) && result) { result = checkarray(basetype,dimset,index+1,src,original,toplevel); } } } else { /* bounded*/ if(lastdim) { for(i=0;i<size && result;i++) { result = checkfill(basetype,src,original); } } else { /* !lastdim*/ for(i=0;i<size && result;i++) { result = checkarray(basetype,dimset,index+1,src,original,toplevel); } } } done: return result; }
/* Specialty wrappers for genbin_data */ void genbin_attrdata(Symbol* asym, Bytebuffer* memory) { Datasrc* src; int chartype = (asym->typ.basetype->typ.typecode == NC_CHAR); if(asym->data == NULL) return; if(chartype) {gen_charattr(asym,memory); return;} src = datalist2src(asym->data); while(srcmore(src)) { genbin_data(asym->typ.basetype,src,NULL,memory); } } #if 0 /* Apparently not used */ void genbin_scalardata(Symbol* vsym, Bytebuffer* memory) { Datasrc* src; if(vsym->data == NULL) return; src = datalist2src(vsym->data); genbin_data(vsym->typ.basetype,src, vsym->var.special._Fillvalue,memory); if(srcmore(src)) { semerror(srcline(src),"Extra data at end of datalist"); } }
/* Specialty wrappers for genbin_data */ void genbin_attrdata(Symbol* asym, Bytebuffer* memory) { Datasrc* src; int chartype = (asym->typ.basetype->typ.typecode == NC_CHAR); if(asym->data == NULL) return; if(chartype) {gen_charattr(asym,memory); return;} src = datalist2src(asym->data); while(srcmore(src)) { genbin_data(asym->typ.basetype,src,NULL,memory); } }
/* Specialty wrappers for f77data_data */ void f77data_attrdata(Symbol* asym, Bytebuffer* databuf) { Datasrc* src; int typecode = asym->typ.basetype->typ.typecode; if(asym->data == NULL) return; if(typecode == NC_CHAR) { gen_charattr(asym,databuf); } else { src = datalist2src(asym->data); while(srcmore(src)) { bbAppend(databuf,' '); f77data_basetype(asym->typ.basetype,src,databuf,NULL); } } }
static nc_type inferattributetype1(Datasrc* src) { nc_type result = NC_NAT; /* Recurse down any enclosing compound markers to find first non-fill "primitive"*/ while(result == NC_NAT && srcmore(src)) { if(issublist(src)) { srcpush(src); result = inferattributetype1(src); srcpop(src); } else { Constant* con = srcnext(src); if(isprimplus(con->nctype)) result = con->nctype; /* else keep looking*/ } } return result; }
/* 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); }
/* Used for compound instances */ static void genbin_compound(Symbol* tsym, Datasrc* datasrc, Datalist* fillsrc, Bytebuffer* memory) { int i; int base = bblength(memory); if(!issublist(datasrc)) { semerror(srcline(datasrc),"Compound data must be enclosed in {..}"); } /* Use this datasrc list to get values for compound fields */ srcpush(datasrc); for(i=0;i<listlength(tsym->subnodes);i++) { Symbol* field = (Symbol*)listget(tsym->subnodes,i); if(!srcmore(datasrc)) { /* generate a fill value*/ Datalist* fillsrc = getfiller(tsym); genbin_data(field,datasrc,fillsrc,memory); } else genbin_data(field,datasrc,NULL,memory); } srcpop(datasrc); /* Re: github issue 323: we may need to pad the end of the structure to make its size be a multiple of the largest alignment. */ alignto(tsym->cmpdalignment,buf,base); }