static int pair(rconlexer* lexer, rconnode** nodep) { rconnode* node = NULL; int token = 0; ENTER(_pair); node = createrconnode(lexer,rcon_pair); if(!node) goto fail; if(!makeconst(lexer,&node->pair.key)) FAIL(lexer,"map key is not a string or word"); if(node->pair.key->constclass != rcon_string) FAIL(lexer,"map key is not a string or word"); token = nexttoken(lexer); if(token != ':') goto fail; if(!value(lexer,&node->pair.value)) FAIL(lexer,"invalid map value"); if(nodep) *nodep = node; LEAVE(_pair,1); return 1; fail: if(node != NULL) rconnodefree(node); LEAVE(_pair,0); return 0; }
static int value(rconlexer* lexer, rconnode** nodep) { rconnode* node = NULL; int token = 0; ENTER(_value); token = nexttoken(lexer); switch (lexer->token) { case LBRACE: if(!map(lexer,&node,!OPTIONAL)) goto fail; break; case LBRACK: if(!array(lexer,&node)) goto fail; break; case _STRING: case _NUMBER: case _NULL: case _TRUE: case _FALSE: pushtoken(lexer); if(!makeconst(lexer,&node)) goto fail; break; case _ILLEGAL: default: goto fail; } if(nodep) *nodep = node; LEAVE(_value,1); return 1; fail: LEAVE(_value,0); return 0; }
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); } } }