/* Used only for structure field arrays*/ static void cdata_fieldarray(Symbol* basetype, Datasrc* src, Odometer* odom, int index, Bytebuffer* codebuf) { int i; int rank = odom->rank; unsigned int size = odom->declsize[index]; int lastdim = (index == (rank - 1)); /* last dimension*/ int chartype = (basetype->typ.typecode == NC_CHAR); if(chartype) { /* Collect the char field in a separate buffer */ Bytebuffer* fieldbuf = bbNew(); gen_charfield(src,odom,index,fieldbuf); /* Add to the existing data buf as a single constant */ cquotestring(fieldbuf); bbCat(codebuf," "); bbCatbuf(codebuf,fieldbuf); bbFree(fieldbuf); } else { ASSERT(size != 0); for(i=0;i<size;i++) { if(lastdim) { bbAppend(codebuf,' '); cdata_basetype(basetype,src,codebuf,NULL); } else { /* !lastdim*/ cdata_fieldarray(basetype,src,odom,index+1,codebuf); } } } }
/* 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); }
static int bin_charconstant(Generator* generator, Symbol* sym, Bytebuffer* buf, ...) { /* Just transfer charbuf to codebuf */ Bytebuffer* charbuf; va_list ap; va_start(ap,buf); charbuf = va_arg(ap, Bytebuffer*); va_end(ap); bbNull(charbuf); bbCatbuf(buf,charbuf); return 1; }
static int j_charconstant(Generator* generator, Symbol* sym, Bytebuffer* codebuf, ...) { /* Escapes and quoting will be handled in genc_write */ /* Just transfer charbuf to codebuf */ Bytebuffer* charbuf; va_list ap; va_start(ap,codebuf); charbuf = va_arg(ap, Bytebuffer*); va_end(ap); bbNull(charbuf); bbCatbuf(codebuf,charbuf); return 1; }
static int c_vlendecl(Generator* generator, Bytebuffer* codebuf, Symbol* tsym, int uid, size_t count, ...) { /* Build a bytebuffer to capture the vlen decl */ List* declstack = (List*)generator->state; Bytebuffer* decl = bbNew(); Bytebuffer* vlenbuf; va_list ap; vastart(ap,count); vlenbuf = va_arg(ap, Bytebuffer*); va_end(ap); bbprintf0(decl,"static const %s vlen_%u[] = {", ctypename(tsym->typ.basetype), uid); commify(vlenbuf); bbCatbuf(decl,vlenbuf); bbCat(decl,"} ;"); listpush(declstack,(void*)decl); /* Now generate the reference to buffer */ bbprintf(codebuf,"{%u,(void*)vlen_%u}",count,uid); return 1; }
static int j_constant(Generator* generator, Symbol* sym, NCConstant* con, Bytebuffer* buf,...) { Bytebuffer* codetmp = bbNew(); char* special = NULL; switch (con->nctype) { case NC_CHAR: if(con->value.charv == '\'') bbprintf(codetmp,"'\\''"); else bbprintf(codetmp,"'%c'",con->value.charv); break; case NC_BYTE: bbprintf(codetmp,"%hhd",con->value.int8v); break; case NC_SHORT: bbprintf(codetmp,"%hd",con->value.int16v); break; case NC_INT: bbprintf(codetmp,"%d",con->value.int32v); break; case NC_FLOAT: /* Special case for nan */ if(isnan(con->value.floatv)) bbprintf(codetmp,"Float.NaN"); else bbprintf(codetmp,"%f",con->value.floatv); break; case NC_DOUBLE: /* Special case for nan */ if(isnan(con->value.doublev)) bbprintf(codetmp,"Double.NaN"); else bbprintf(codetmp,"%lf",con->value.doublev); break; case NC_UBYTE: bbprintf(codetmp,"%hhu",con->value.uint8v); break; case NC_USHORT: bbprintf(codetmp,"%hu",con->value.uint16v); break; case NC_UINT: bbprintf(codetmp,"%uU",con->value.uint32v); break; case NC_INT64: bbprintf(codetmp,"%lldLL",con->value.int64v); break; case NC_UINT64: bbprintf(codetmp,"%lluLLU",con->value.uint64v); break; case NC_STRING: { /* handle separately */ char* escaped = escapify(con->value.stringv.stringv, '"',con->value.stringv.len); special = poolalloc(1+2+strlen(escaped)); strcpy(special,"\""); strcat(special,escaped); strcat(special,"\""); } break; default: PANIC1("ncstype: bad type code: %d",con->nctype); } if(special == NULL) bbCatbuf(buf,codetmp); else bbCat(buf,special); bbFree(codetmp); return 1; }
void codedump(Bytebuffer* buf) { bbCatbuf(codebuffer,buf); bbClear(buf); }
static void genj_writeattr(Generator* generator, Symbol* asym, Bytebuffer* code, int rank, size_t* start, size_t* count) { Symbol* basetype = asym->typ.basetype; nc_type typecode = basetype->typ.typecode; /* default assumption */ size_t len = asym->data == NULL?0:asym->data->length; codeprintf("%s/* attribute: %s */\n",indented(1),asym->name); /* Handle NC_CHAR specially */ if(typecode == NC_CHAR) { /* revise the length count */ len = bbLength(code); if(len == 0) { bbAppend(code,'\0'); len++; bbClear(code); bbCat(code,"\"\""); len++; } else jquotestring(code,'"'); bbNull(code); } else { /* not NC_CHAR*/ char* code2; commify(code); /* Convert to constant */ code2 = bbDup(code); bbClear(code); bbprintf0(stmt,"new %s[]", jarraytype(typecode)); bbCatbuf(code,stmt); bbCat(code,"{"); bbCat(code,code2); bbCat(code,"}"); efree(code2); } switch (typecode) { case NC_BYTE: case NC_SHORT: case NC_INT: case NC_FLOAT: case NC_DOUBLE: codelined(1,"{"); bbprintf0(stmt,"%sArray data = Array.factory(%s.class, new int[]{%lu}, ", indented(1), jtype(basetype->typ.typecode), len); codedump(stmt); codedump(code); codeline(");"); if(asym->att.var == NULL) { bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",data);\n", indented(1),jescapifyname(asym->name)); } else { bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",data);\n", indented(1), jescapifyname(asym->att.var->name), jescapifyname(asym->name)); } codedump(stmt); codelined(1,"}"); codeflush(); break; case NC_CHAR: if(asym->att.var == NULL) { bbprintf0(stmt,"%sncfile.addGlobalAttribute(\"%s\",%s);\n", indented(1), jescapifyname(asym->name), bbContents(code)); } else { bbprintf0(stmt,"%sncfile.addVariableAttribute(\"%s\",\"%s\",%s);\n", indented(1), jescapifyname(asym->att.var->name), jescapifyname(asym->name), bbContents(code)); } codedump(stmt); codeflush(); break; default: break; } codeflush(); }
static int c_constant(Generator* generator, NCConstant* con, Bytebuffer* buf,...) { Bytebuffer* codetmp = bbNew(); char* special = NULL; switch (con->nctype) { case NC_CHAR: if(con->value.charv == '\'') bbprintf(codetmp,"'\\''"); else bbprintf(codetmp,"'%s'",cescapifychar(con->value.charv,'\'')); break; case NC_BYTE: bbprintf(codetmp,"%hhd",con->value.int8v); break; case NC_SHORT: bbprintf(codetmp,"%hd",con->value.int16v); break; case NC_INT: bbprintf(codetmp,"%d",con->value.int32v); break; case NC_FLOAT: /* Special case for nanf */ if(isnan(con->value.floatv)) bbprintf(codetmp,"nanf"); else bbprintf(codetmp,"%f",con->value.floatv); break; case NC_DOUBLE: /* Special case for nan */ if(isnan(con->value.doublev)) bbprintf(codetmp,"nan"); else bbprintf(codetmp,"%lf",con->value.doublev); break; case NC_UBYTE: bbprintf(codetmp,"%hhu",con->value.uint8v); break; case NC_USHORT: bbprintf(codetmp,"%hu",con->value.uint16v); break; case NC_UINT: bbprintf(codetmp,"%uU",con->value.uint32v); break; case NC_INT64: bbprintf(codetmp,"%lldLL",con->value.int64v); break; case NC_UINT64: bbprintf(codetmp,"%lluLLU",con->value.uint64v); break; case NC_ECONST: bbprintf(codetmp,"%s",cname(con->value.enumv)); break; case NC_NIL: case NC_STRING: { /* handle separately */ if(con->value.stringv.len == 0 && con->value.stringv.stringv == NULL) { bbprintf(codetmp,"NULL"); } else { char* escaped = escapify(con->value.stringv.stringv, '"',con->value.stringv.len); special = poolalloc(1+2+strlen(escaped)); strcpy(special,"\""); strcat(special,escaped); strcat(special,"\""); } } break; case NC_OPAQUE: { char* p; int bslen; bslen=(4*con->value.opaquev.len); special = poolalloc(bslen+2+1); strcpy(special,"\""); p = con->value.opaquev.stringv; while(*p) { strcat(special,"\\x"); strncat(special,p,2); p += 2; } strcat(special,"\""); } break; default: PANIC1("ncstype: bad type code: %d",con->nctype); } if(special == NULL) bbCatbuf(buf,codetmp); else bbCat(buf,special); bbFree(codetmp); return 1; }
/* Generate an instance of the basetype using datasrc */ void cdata_basetype(Symbol* tsym, Datasrc* datasrc, Bytebuffer* codebuf, Datalist* fillsrc) { int usecmpd; switch (tsym->subclass) { case NC_ENUM: case NC_OPAQUE: case NC_PRIM: if(issublist(datasrc)) { semerror(srcline(datasrc),"Expected primitive found {..}"); } bbAppend(codebuf,' '); cdata_primdata(tsym,datasrc,codebuf,fillsrc); break; case NC_COMPOUND: { int i; Constant* con; if(!isfillvalue(datasrc) && !issublist(datasrc)) {/* fail on no compound*/ semerror(srcline(datasrc),"Compound data must be enclosed in {..}"); } con = srcnext(datasrc); if(con->nctype == NC_FILLVALUE) { Datalist* filler = getfiller(tsym,fillsrc); ASSERT(filler->length == 1); con = &filler->data[0]; if(con->nctype != NC_COMPOUND) { semerror(con->lineno,"Compound data fill value is not enclosed in {..}"); } } srcpushlist(datasrc,con->value.compoundv); /* enter the sublist*/ bbAppend(codebuf,'{'); for(i=0;i<listlength(tsym->subnodes);i++) { Symbol* field = (Symbol*)listget(tsym->subnodes,i); bbAppend(codebuf,' '); cdata_basetype(field,datasrc,codebuf,NULL); } bbAppend(codebuf,'}'); srcpop(datasrc); } break; case NC_VLEN: { Constant* con; if(!isfillvalue(datasrc) && !issublist(datasrc)) {/* fail on no compound*/ semerror(con->lineno,"Vlen data must be enclosed in {..}"); } con = srcnext(datasrc); if(con->nctype == NC_FILLVALUE) { Datalist* filler = getfiller(tsym,fillsrc); ASSERT(filler->length == 1); con = &filler->data[0]; if(con->nctype != NC_COMPOUND) { semerror(con->lineno,"Vlen data fill value is not enclosed in {..}"); } } /* generate the nc_vlen_t instance*/ bbprintf0(stmt,"{%u (void*)vlen_%u}", con->value.compoundv->vlen.count, con->value.compoundv->vlen.uid); bbCatbuf(codebuf,stmt); } break; case NC_FIELD: /* enclose in braces if and only if field is an array */ usecmpd = (issublist(datasrc) && tsym->typ.dimset.ndims > 0); if(usecmpd) srcpush(datasrc); if(tsym->typ.dimset.ndims > 0) { Odometer* fullodom = newodometer(&tsym->typ.dimset,NULL,NULL); cdata_fieldarray(tsym->typ.basetype,datasrc,fullodom,0,codebuf); odometerfree(fullodom); } else { cdata_basetype(tsym->typ.basetype,datasrc,codebuf,NULL); } if(usecmpd) srcpop(datasrc); break; default: PANIC1("cdata_basetype: unexpected subclass %d",tsym->subclass); } }