int collectstring(Constant* con, size_t declsize, Bytebuffer* databuf) { int i = 0; if(con != NULL) { ASSERT(isstringable(con->nctype)); if(con->nctype == NC_STRING) { if(declsize > 0 && con->value.stringv.len >= (declsize-i)) { bbAppendn(databuf,con->value.stringv.stringv,con->value.stringv.len); i = declsize; } else if(con->value.stringv.len == 0) { i = 0; } else { /* Append */ bbCat(databuf,con->value.stringv.stringv); i = con->value.stringv.len; } } else if(con->nctype == NC_FILLVALUE) { bbAppend(databuf,NC_FILL_CHAR); i = 1; } else { /* Append */ bbAppend(databuf,con->value.charv); i = 1; } } return i; }
void gen_charattr(Symbol* asym, Bytebuffer* databuf) { Datasrc* src; Constant* con; if(asym->data == NULL) return; src = datalist2src(asym->data); while((con=srcnext(src))) { switch (con->nctype) { /* Following list should be consistent with isstringable */ case NC_CHAR: bbAppend(databuf,con->value.charv); break; case NC_BYTE: bbAppend(databuf,con->value.int8v); break; case NC_UBYTE: bbAppend(databuf,con->value.uint8v); break; case NC_STRING: bbCat(databuf,con->value.stringv.stringv); bbNull(databuf); break; case NC_FILL: bbAppend(databuf,NC_FILL_CHAR); break; default: semerror(srcline(src), "Encountered non-string constant in attribute: %s", asym->name); return; } } }
static size_t gen_charconstant(NCConstant* con, Bytebuffer* databuf, int fillchar) { /* Following cases should be consistent with isstringable */ size_t constsize = 1; switch (con->nctype) { case NC_CHAR: bbAppend(databuf,con->value.charv); break; case NC_BYTE: bbAppend(databuf,con->value.int8v); break; case NC_UBYTE: bbAppend(databuf,con->value.uint8v); break; case NC_STRING: constsize = con->value.stringv.len; bbAppendn(databuf,con->value.stringv.stringv, con->value.stringv.len); bbNull(databuf); break; case NC_FILL: bbAppend(databuf,fillchar); break; default: PANIC("unexpected constant type"); } return constsize; }
/* Requires that the string be balanced WRT to braces */ static char* commifyr(char* p, Bytebuffer* buf) { int comma = 0; int c; while((c=*p++)) { if(c == ' ') continue; if(c == ',') continue; else if(c == '}') { break; } if(comma) bbCat(buf,", "); else comma=1; if(c == '{') { bbAppend(buf,'{'); p = commifyr(p,buf); bbAppend(buf,'}'); } else if(c == '\'' || c == '\"') { p = wordstring(p,buf,c); } else { bbAppend(buf,c); p=word(p,buf); } } return p; }
void cquotestring(Bytebuffer* databuf, char quote) { char* escaped = escapify(bbContents(databuf),'"',bbLength(databuf)); bbClear(databuf); bbAppend(databuf,quote); bbCat(databuf,escaped); bbAppend(databuf,quote); }
static void jescapifychar(UTF16 c, int quote, Bytebuffer* s) { /* Separate out ascii from UTF16 */ if(c <= '\177') { /* Separate printables from controls */ if(c >= ' ' && c < '\177') { if (c == quote) { bbAppend(s,'\\'); } bbAppend(s,(char)c); } else switch (c) { case '\t': bbCat(s,"\\t"); break; case '\b': bbCat(s,"\\b"); break; case '\n': bbCat(s,"\\n"); break; case '\r': bbCat(s,"\\r"); break; case '\f': bbCat(s,"\\f"); break; default: { /* Do hex escape */ int hex1 = (c & 0x0f); int hex2 = ((c >> 4) & 0x0f); int hex3 = ((c >> 8) & 0x0f); int hex4 = ((c >> 12) & 0x0f); bbAppend(s,'\\'); bbAppend(s,'u'); bbAppend(s,hexdigits[hex4]); bbAppend(s,hexdigits[hex3]); bbAppend(s,hexdigits[hex2]); bbAppend(s,hexdigits[hex1]); } break; } } else { /* Do \uxxxx escapes */
/* Recursive helper */ static void gen_chararrayr(Dimset* dimset, int dimindex, Bytebuffer* databuf, Datalist* data, int fillchar, int unitsize, int expectedsize) { int i; size_t dimsize = declsizefor(dimset,dimindex); int rank = dimset->ndims; int firstunlim = findunlimited(dimset,0); int lastunlimited = findlastunlimited(dimset); int nextunlimited = findunlimited(dimset,dimindex+1); int islastgroup = (lastunlimited == rank || dimindex >= lastunlimited || dimindex == rank-1); Odometer* subodom = NULL; ASSERT(rank > 0); ASSERT((islastgroup)); /* we should be at a list of simple constants */ for(i=0;i<data->length;i++) { NCConstant* c = datalistith(data,i); ASSERT(!islistconst(c)); if(isstringable(c->nctype)) { int j; size_t constsize; constsize = gen_charconstant(c,databuf,fillchar); if(constsize % unitsize > 0) { size_t padsize = unitsize - (constsize % unitsize); for(j=0;j<padsize;j++) bbAppend(databuf,fillchar); } } else { semwarn(constline(c), "Encountered non-string and non-char constant in datalist; ignored"); } }/* for */ /* If |databuf| > expectedsize, complain: exception is zero length */ if(bbLength(databuf) == 0 && expectedsize == 1) { /* this is okay */ } else if(bbLength(databuf) > expectedsize) { semwarn(data->data[0].lineno,"character data list too long; expected %d character constant, found %d: ",expectedsize,bbLength(databuf)); } else { size_t bufsize = bbLength(databuf); /* Pad to size dimproduct size */ if(bufsize % expectedsize > 0) { size_t padsize = expectedsize - (bufsize % expectedsize); for(i=0;i<padsize;i++) bbAppend(databuf,fillchar); } } }
/* Recursive helper */ static void gen_chararrayr(Dimset* dimset, int dimindex, int lastunlimited, Bytebuffer* databuf, Datalist* data, int fillchar, int unitsize, int expectedsize) { int i; size_t dimsize = dimset->dimsyms[dimindex]->dim.declsize; if(dimindex < lastunlimited) { /* keep recursing */ for(i=0;i<dimsize;i++) { NCConstant* c = datalistith(data,i); ASSERT(islistconst(c)); gen_chararrayr(dimset,dimindex+1,lastunlimited,databuf, c->value.compoundv,fillchar,unitsize,expectedsize); } } else {/* we should be at a list of simple constants */ for(i=0;i<data->length;i++) { NCConstant* c = datalistith(data,i); ASSERT(!islistconst(c)); if(isstringable(c->nctype)) { int j; size_t constsize; constsize = gen_charconstant(c,databuf,fillchar); if(constsize % unitsize > 0) { size_t padsize = unitsize - (constsize % unitsize); for(j=0;j<padsize;j++) bbAppend(databuf,fillchar); } } else { semwarn(constline(c), "Encountered non-string and non-char constant in datalist; ignored"); } } } /* If |databuf| > expectedsize, complain: exception is zero length */ if(bbLength(databuf) == 0 && expectedsize == 1) { /* this is okay */ } else if(bbLength(databuf) > expectedsize) { semwarn(data->data[0].lineno,"character data list too long"); } else { size_t bufsize = bbLength(databuf); /* Pad to size dimproduct size */ if(bufsize % expectedsize > 0) { size_t padsize = expectedsize - (bufsize % expectedsize); for(i=0;i<padsize;i++) bbAppend(databuf,fillchar); } } }
static void f77data_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* codebuf, Datalist* fillsrc) { Constant* prim; Constant target; prim = srcnext(src); if(prim == NULL) prim = &fillconstant; ASSERT(prim->nctype != NC_COMPOUND); if(prim->nctype == NC_FILLVALUE) { Datalist* filler = getfiller(basetype,fillsrc); ASSERT(filler->length == 1); srcpushlist(src,filler); bbAppend(codebuf,' '); f77data_primdata(basetype,src,codebuf,NULL); srcpop(src); goto done; } target.nctype = basetype->typ.typecode; convert1(prim,&target); bbCat(codebuf,f77data_const(&target)); done: return; }
/* 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); } } } }
/* Add invisible NULL terminator */ int bbNull(Bytebuffer* bb) { bbAppend(bb,'\0'); bb->length--; return 1; }
char* word(char* p, Bytebuffer* buf) { int c; while((c=*p++)) { if(c == '}' || c == ' ' || c == ',') break; if(c == '\\') { bbAppend(buf,c); c=*p++; if(!c) break; } bbAppend(buf,(char)c); } p--; /* leave terminator for parent */ return p; }
/* Fill */ static int fillstring(size_t declsize, int len, Bytebuffer* databuf) { for(;len<declsize;len++) bbAppend(databuf,NC_FILL_CHAR); return len; }
static char* wordstring(char* p, Bytebuffer* buf, int quote) { int c; bbAppend(buf,quote); while((c=*p++)) { if(c == '\\') { bbAppend(buf,c); c = *p++; if(c == '\0') return --p; } else if(c == quote) { bbAppend(buf,c); return p; } bbAppend(buf,c); } return p; }
static void vbbprintf(Bytebuffer* buf, const char* fmt, va_list argv) { char tmp[128]; const char* p; int c; int hcount; int lcount; char* text; for(p=fmt;(c=*p++);) { hcount = 0; lcount = 0; switch (c) { case '%': retry: switch ((c=*p++)) { case '\0': bbAppend(buf,'%'); p--; break; case '%': bbAppend(buf,c); break; case 'h': hcount++; while((c=*p) && (c == 'h')) {hcount++; p++;} if(hcount > 2) hcount = 2; goto retry; case 'l': lcount++; while((c=*p) && (c == 'l')) { lcount++; p++; } if(lcount > 2) lcount = 2; goto retry; case 'u': if(hcount == 2) { snprintf(tmp,sizeof(tmp),"%hhu", (unsigned int)va_arg(argv,unsigned int)); } else if(hcount == 1) { snprintf(tmp,sizeof(tmp),"%hu", (unsigned int)va_arg(argv,unsigned int)); } else if(lcount == 2) {
static void cdata_primdata(Symbol* basetype, Datasrc* src, Bytebuffer* codebuf, Datalist* fillsrc) { Constant* prim; Constant target; prim = srcnext(src); if(prim == NULL) prim = &fillconstant; ASSERT(prim->nctype != NC_COMPOUND); if(prim->nctype == NC_FILLVALUE) { Datalist* filler = getfiller(basetype,fillsrc); ASSERT(filler->length == 1); srcpushlist(src,filler); bbAppend(codebuf,' '); cdata_primdata(basetype,src,codebuf,NULL); srcpop(src); goto done; } 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(prim->lineno,"Conversion to enum not supported (yet)"); } else { Datalist* econ = builddatalist(1); Symbol* enumv = prim->value.enumv; srcpushlist(src,econ); dlappend(econ,&enumv->typ.econst); cdata_primdata(enumv->typ.basetype,src,codebuf,fillsrc); srcpop(src); } break; case NC_OPAQUE: { setprimlength(&target,basetype->typ.size*2); } break; default: break; } bbCat(codebuf,cdata_const(&target)); done: return; }
static int c_listend(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* buf, ...) { switch (lc) { case LISTCOMPOUND: case LISTFIELDARRAY: bbAppend(buf,'}'); break; case LISTDATA: case LISTVLEN: case LISTATTR: break; } return 1; }
static int c_listbegin(Generator* generator, ListClass lc, size_t size, Bytebuffer* codebuf, int* uidp, ...) { if(uidp) *uidp = ++c_uid; switch (lc) { case LISTVLEN: case LISTATTR: case LISTDATA: break; case LISTFIELDARRAY: case LISTCOMPOUND: bbAppend(codebuf,'{'); break; } return 1; }
static int c_list(Generator* generator, ListClass lc, int uid, size_t count, Bytebuffer* codebuf, ...) { switch (lc) { case LISTVLEN: case LISTATTR: if(count > 0) bbCat(codebuf,", "); break; case LISTDATA: case LISTCOMPOUND: case LISTFIELDARRAY: bbAppend(codebuf,' '); break; } return 1; }
/* Generate an instance of the basetype using datasrc */ void f77data_basetype(Symbol* tsym, Datasrc* datasrc, Bytebuffer* codebuf, Datalist* fillsrc) { switch (tsym->subclass) { case NC_PRIM: if(issublist(datasrc)) { semerror(srcline(datasrc),"Expected primitive found {..}"); } bbAppend(codebuf,' '); f77data_primdata(tsym,datasrc,codebuf,fillsrc); break; default: PANIC1("f77data_basetype: unexpected subclass %d",tsym->subclass); } }
/* 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); } } }
/* 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 void xescapifychar(unsigned int c, int quote, Bytebuffer* s) { if(c >= ' ' && c < '\177') { char* p; char** q; for(p=printescapable,q=printescape;*p;p++,q++) {if(c==*p) break;} if(*p) { bbAppend(s,'&'); bbCat(s,*q); bbAppend(s,';'); } else bbAppend(s,(char)c); } else { /* Do hex escape */ unsigned int hex1 = (c & 0x0f); unsigned int hex2 = ((c >> 4) & 0x0f); bbCat(s,"&#"); bbAppend(s,hexdigits[hex2]); bbAppend(s,hexdigits[hex1]); bbAppend(s,';'); } }
static void genjstd_primattribute(Symbol* asym, Bytebuffer* code, unsigned long len) { Symbol* basetype = asym->typ.basetype; nc_type typecode = basetype->typ.typecode; /* Handle NC_CHAR specially */ if(typecode == NC_CHAR) { /* revise the length count */ len = bbLength(code); if(len == 0) {bbAppend(code,'\0'); len++;} jquotestring(code,'"'); } else { /* Convert to constant */ char* code2 = bbDup(code); bbClear(code); nprintf(stmt,sizeof(stmt),"new %s[]", jarraytype(typecode)); bbCat(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: jlined(1,"{"); nprintf(stmt,sizeof(stmt),"%sArray data = Array.factory(%s.class, new int[]{%lu}, ", indented(1), jtype(basetype->typ.typecode), len); jpartial(stmt); jprint(code); jline(");"); if(asym->att.var == NULL) { nprintf(stmt,sizeof(stmt),"ncfile.addGlobalAttribute(\"%s\",data);", jescapifyname(asym->name)); } else { nprintf(stmt,sizeof(stmt),"ncfile.addVariableAttribute(\"%s\",\"%s\",data);", jescapifyname(asym->att.var->name), jescapifyname(asym->name)); } jlined(1,stmt); jlined(1,"}"); jflush(); break; case NC_CHAR: if(asym->att.var == NULL) { nprintf(stmt,sizeof(stmt),"ncfile.addGlobalAttribute(\"%s\",%s);", jescapifyname(asym->name), bbContents(code)); } else { nprintf(stmt,sizeof(stmt),"ncfile.addVariableAttribute(\"%s\",\"%s\",%s);", jescapifyname(asym->att.var->name), jescapifyname(asym->name), bbContents(code)); } jlined(1,stmt); jflush(); break; default: break; } }
static void gen_leafchararray(Dimset* dimset, int dimindex, Datalist* data, Bytebuffer* charbuf, int fillchar) { int i; size_t expectedsize,xproduct,unitsize; int rank = rankfor(dimset); ASSERT(bbLength(charbuf) == 0); ASSERT((findlastunlimited(dimset) == rank || findlastunlimited(dimset) == dimindex)); /* There are a number of special cases that must be considered, mostly driven by the need to keep consistent with ncgen3. These cases are driven by the number of dimensions, which dimensions are unlimited (if any), etc. The general rule is based on the size of the last dimension, we compute the required size (after padding) of each string constant. Expected size is then the size of concat of the string constants after padding. There is another special case used for back compatability with ncgen3. In the datalist, all sequences of character constants (i.e. 'X') are concatenated into a single string; the result, however is not concatenated with any trailing or leading string (with double quotes). */ /* Rebuild the datalist to merge 'x' constants */ { int i,cccount = 0; /* Do initial walk */ for(i=0;i<datalistlen(data);i++) { NCConstant* con = datalistith(data,i); if(consttype(con) == NC_CHAR || consttype(con) == NC_BYTE) { cccount++; } } if(cccount > 1) { char* accum = (char*)malloc(cccount+1); int len = 0; Datalist* newlist = builddatalist(datalistlen(data)); int lineno = 0; NCConstant* con; for(i=0;i<datalistlen(data);i++) { con = datalistith(data,i); if(consttype(con) == NC_CHAR || consttype(con) == NC_BYTE) { if(len == 0) lineno = constline(con); accum[len] = con->value.charv; len++; } else { if(len > 0) { con = makeconst(lineno,len,accum); len = 0; lineno = 0; } dlappend(newlist,con); } } /* deal with any unclosed strings */ if(len > 0) { con = makeconst(lineno,len,accum); len = 0; lineno = 0; dlappend(newlist,con); } free(accum); data = newlist; } } /* Compute crossproduct upto (but not includng) the last dimension */ xproduct = crossproduct(dimset,dimindex,rank-1); /* Start casing it out */ if(rank == 0) { unitsize = 1; expectedsize = (xproduct * unitsize); } else if(rank == 1) { unitsize = 1; expectedsize = (xproduct * declsizefor(dimset,rank-1)); } else if(isunlimited(dimset,rank-1)) {/* last dimension is unlimited */ unitsize = 1; expectedsize = (xproduct*declsizefor(dimset,rank-1)); } else { /* rank > 0 && last dim is not unlimited */ unitsize = declsizefor(dimset,rank-1); expectedsize = (xproduct * unitsize); } for(i=0;i<data->length;i++) { NCConstant* c = datalistith(data,i); ASSERT(!islistconst(c)); if(isstringable(c->nctype)) { int j; size_t constsize; constsize = gen_charconstant(c,charbuf,fillchar); if(constsize == 0 || constsize % unitsize > 0) { size_t padsize = unitsize - (constsize % unitsize); for(j=0;j<padsize;j++) bbAppend(charbuf,fillchar); } } else { semwarn(constline(c),"Encountered non-string and non-char constant in datalist; ignored"); } } /* If |databuf| > expectedsize, complain: exception is zero length */ if(bbLength(charbuf) == 0 && expectedsize == 1) { /* this is okay */ } else if(bbLength(charbuf) > expectedsize) { semwarn(data->data[0].lineno,"character data list too long; expected %d character constant, found %d: ",expectedsize,bbLength(charbuf)); } else { size_t bufsize = bbLength(charbuf); /* Pad to size dimproduct size */ if(bufsize % expectedsize > 0) { size_t padsize = expectedsize - (bufsize % expectedsize); for(i=0;i<padsize;i++) bbAppend(charbuf,fillchar); } } }
/* 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); } }
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(); }
void expand_escapes( Bytebuffer *s, /* fill with contents of yytext, with escapes expanded */ char *yytext, int yyleng) { char *t, *endp; yytext[yyleng-1]='\0'; /* don't copy quotes */ /* expand "\" escapes, e.g. "\t" to tab character */ t = yytext+1; while(*t) { if (*t == '\\') { t++; switch (*t) { case 'a': bbAppend(s,'\007'); t++; /* will use '\a' when STDC */ break; case 'b': bbAppend(s,'\b'); t++; break; case 'f': bbAppend(s,'\f'); t++; break; case 'n': bbAppend(s,'\n'); t++; break; case 'r': bbAppend(s,'\r'); t++; break; case 't': bbAppend(s,'\t'); t++; break; case 'v': bbAppend(s,'\v'); t++; break; case '\\': bbAppend(s,'\\'); t++; break; case '?': bbAppend(s,'\177'); t++; break; case '\'': bbAppend(s,'\''); t++; break; case '\"': bbAppend(s,'\"'); t++; break; case 'x': t++; /* now t points to one or more hex digits */ bbAppend(s,(char) strtol(t, &endp, 16)); t = endp; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* t now points to octal digits */ bbAppend(s,(char) strtol(t, &endp, 8)); t = endp; break; default: bbAppend(s,*t); t++; break; } } else { bbAppend(s,*t); t++; } } bbNull(s); bbSetlength(s,strlen(bbContents(s))); return; }
void gen_leafchararray(Dimset* dimset, int lastunlim, Datalist* data, Bytebuffer* databuf, Datalist* fillsrc) { int i; size_t expectedsize,xproduct,unitsize; int ndims = dimset->ndims; int fillchar = getfillchar(fillsrc); ASSERT(bbLength(databuf) == 0); /* Assume dimindex is the last unlimited (or 0 if their are no unlimiteds => we should be at a list of simple constants */ /* Compute crossproduct upto the last dimension, starting at the last unlimited */ xproduct = crossproduct(dimset,lastunlim,ndims-1); /* Compute the required size (after padding) of each string constant */ /* expected size is the size of concat of the string constants after padding */ if(ndims == 0) { unitsize = 1; expectedsize = (xproduct * unitsize); } else if(lastunlim == ndims-1) {/* last dimension is unlimited */ unitsize = 1; expectedsize = (xproduct*dimset->dimsyms[lastunlim]->dim.declsize); } else { /* last dim is not unlimited */ unitsize = dimset->dimsyms[ndims-1]->dim.declsize; expectedsize = (xproduct * unitsize); } for(i=0;i<data->length;i++) { NCConstant* c = datalistith(data,i); ASSERT(!islistconst(c)); if(isstringable(c->nctype)) { int j; size_t constsize; constsize = gen_charconstant(c,databuf,fillchar); if(constsize == 0 || constsize % unitsize > 0) { size_t padsize = unitsize - (constsize % unitsize); for(j=0;j<padsize;j++) bbAppend(databuf,fillchar); } } else { semwarn(constline(c),"Encountered non-string and non-char constant in datalist; ignored"); } } /* If |databuf| > expectedsize, complain: exception is zero length */ if(bbLength(databuf) == 0 && expectedsize == 1) { /* this is okay */ } else if(bbLength(databuf) > expectedsize) { semwarn(data->data[0].lineno,"character data list too long"); } else { size_t bufsize = bbLength(databuf); /* Pad to size dimproduct size */ if(bufsize % expectedsize > 0) { size_t padsize = expectedsize - (bufsize % expectedsize); for(i=0;i<padsize;i++) bbAppend(databuf,fillchar); } } }