// write id:value, unless value is empty, in which case we erase the id void writeMacro(char *id) { eraseentry(id); // we need to know the macro value length to allocate space for it // we don't realistically have enough buffer space handy to parse it into // so this is a two-pass operation: first we measure the text, then on // the second pass we stuff it into the eeprom // // measure length of macro value // we get here with inchar = first char of macro and fetchptr one past that // char *fetchmark = --fetchptr; // back up and mark first char of macro text primec(); // re-prime expval = 0; // zero the count parsestring(&countByte); // now expval is the macro value length if (!expval) return; // empty string? we're done int addr = findhole(strlen(id) + expval + 2); // longjmps on fail if (addr >= 0) { saveString(addr, id); // reset parse context fetchptr = fetchmark; primec(); expval = addr + strlen(id) + 1; // set up address for saveByte parsestring(&saveByte); saveByte(0); } }
void parsearglist(void) { vpush((numvar) arg); // save base of current argblock #if defined(STRING_POOL) vpush((numvar) stringPool); // save stringPool base for later release strpush(idbuf); // save called function's name as arg[-1] #endif numvar *newarg = &vstack[vsptr]; // move global arg pointer to base of new block vpush(0); // initialize new arg(0) (a/k/a argc) to 0 if (sym == s_lparen) { getsym(); // eat arglist '(' while ((sym != s_rparen) && (sym != s_eof)) { #if defined(STRING_POOL) if (sym == s_quote) { vpush((numvar) stringPool); // push the string pointer parsestring(&spush); // parse it into the pool spush(0); // and terminate it getsym(); // eat closing " } else #endif vpush(getnum()); // push the value newarg[0]++; // bump the count if (sym == s_comma) getsym(); // eat arglist ',' and go around else break; } if (sym == s_rparen) getsym(); // eat the ')' else expected(M_rparen); } arg = newarg; // activate new argument frame }
static bool insert_statement( void ) { DEVELOPER_DEBUG( "insert_statement %s\n", cursor ); whitespace(); if ( ! parsestring( "INSERT" ) ) return false; if ( ! parsestring( "INTO" ) ) return false; if ( ! keyletters() ) return false; if ( ! parsestring( "VALUES" ) ) return false; if ( ! parsestring( "(" ) ) return false; values(); if ( ')' != *cursor ) return false; *cursor++ = 0; /* Zero out parenthesis to serve as delimeter. */ if ( ';' != *cursor ) return false; cursor++; return true; }
int main(int argc, char *argv[]) { char *str = ":camel"; int n; bencode_string *val; io_buf buf; io_reader r; memset(&buf, 0, sizeof(buf)); memset(&r, 0, sizeof(r)); buf.buf = str; buf.len = strlen(str); r.data = &buf; r.read = io_bufread; val = parsestring('5', &r, &n); assert(val != NULL); assert(strcmp(val->val, "camel") == 0); assert(n == strlen(str) + 1); exit(EXIT_SUCCESS); }
static tlHandle parse(tlBuffer* buf) { char c; do { c = tlBufferPeekByte(buf, 0); } while (c && c <= 32); trace("probing: %c", c); switch (c) { case '{': { tlBufferSkipByte(buf); trace("{"); tlHashMap* map = tlHashMapNew(); while (true) { tlHandle k = parsekey(buf); if (!k) break; do { c = tlBufferReadByte(buf); } while (c && c <= 32); if (c != '=') { warning("no '=' %c", c); return null; } tlHandle v = parse(buf); if (!v) { warning("no value"); return null; } tlHashMapSet(map, k, v); do { c = tlBufferReadByte(buf); } while (c && c <= 32); if (c != ',') { tlBufferRewind(buf, 1); break; } } c = tlBufferReadByte(buf); if (c != '}') { warning("no '}' %c", c); return null; } trace("}"); tlObject* res = tlHashMapToObject(map); trace("map: %d", tlObjectSize(res)); return res; } case '[': { tlBufferSkipByte(buf); trace("["); tlArray* ls = tlArrayNew(); while (true) { tlHandle h = parse(buf); if (!h) break; tlArrayAdd(ls, h); do { c = tlBufferReadByte(buf); } while (c && c <= 32); if (c != ',') { tlBufferRewind(buf, 1); break; } } c = tlBufferReadByte(buf); if (c != ']') { warning("no ']' %c", c); return null; } trace("]"); return tlArrayToList(ls); } case '"': case '\'': return parsestring(buf, c); case 'n': { tlBufferReadSkip(buf, 4); return tlNull; } case 'f': { tlBufferReadSkip(buf, 5); return tlFalse; } case 't': { tlBufferReadSkip(buf, 4); return tlTrue; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': case '+': case '.': return parsenum(buf); } warning("unparsable: %c", c); return null; }
static Jsonnode* json_parse_endp(const char *str,const char **endp){ Jsonnode *node; node=parsenumber(str,endp); if(node){SKIPSPACES(*endp); return node;} node=parsestring(str,endp); if(node){SKIPSPACES(*endp); return node;} node=parsebool (str,endp); if(node){SKIPSPACES(*endp); return node;} node=parsenull (str,endp); if(node){SKIPSPACES(*endp); return node;} node=parsearray (str,endp); if(node){SKIPSPACES(*endp); return node;} node=parseobject(str,endp); if(node){SKIPSPACES(*endp); return node;} return NULL; }
static tlHandle parsekey(tlBuffer* buf) { trace("parsekey"); char c; do { c = tlBufferReadByte(buf); } while (c && c <= 32); trace("probing: %c", c); if (!c) return null; tlBufferRewind(buf, 1); if (c == '"' || c == '\'') return tlSymFromString(parsestring(buf, c)); return parsesym(buf); }
static int parsepair(Parser *p, JSON *parent, JSON **kprev, JSON **vprev) { must(*p->s == '"'); must(parsestring(p, parent, kprev)); skipws(p); must(consume(p, ":")); skipws(p); must(parsevalue(p, parent, vprev)); return 1; }
static bool comment( void ) { s4_t guard_counter = 0; DEVELOPER_DEBUG( "comment %s\n", cursor ); whitespace(); if ( ! parsestring( "--" ) ) return false; do { cursor++; } while ( ( *cursor != '\n' ) && ( guard_counter++ < MAXLINELENGTH ) ); return true; }
struct pkg_format_node * pkg_format_parse(const char *fmt, struct dpkg_error *err) { struct pkg_format_node *head; struct pkg_format_node *cur; const char *fmtend; head = cur = NULL; while (*fmt) { if (cur) cur = cur->next = pkg_format_node_new(); else head = cur = pkg_format_node_new(); if (fmt[0] == '$' && fmt[1] == '{') { fmtend = strchr(fmt, '}'); if (!fmtend) { dpkg_put_error(err, _("missing closing brace")); pkg_format_free(head); return NULL; } if (!parsefield(cur, fmt + 2, fmtend - 1, err)) { pkg_format_free(head); return NULL; } fmt = fmtend + 1; } else { fmtend = fmt; do { fmtend += 1; fmtend = strchr(fmtend, '$'); } while (fmtend && fmtend[1] != '{'); if (!fmtend) fmtend = fmt + strlen(fmt); if (!parsestring(cur, fmt, fmtend - 1, err)) { pkg_format_free(head); return NULL; } fmt = fmtend; } } if (!head) dpkg_put_error(err, _("may not be empty string")); return head; }
struct lstitem * parseformat(const char *fmt) { struct lstitem *head; struct lstitem *cur; const char *fmtend; head = cur = NULL; while (*fmt) { if (cur) cur = cur->next = alloclstitem(); else head = cur = alloclstitem(); if (fmt[0] == '$' && fmt[1] == '{') { fmtend = strchr(fmt, '}'); if (!fmtend) { fprintf(stderr, _("Closing brace missing in format\n")); freeformat(head); return NULL; } if (!parsefield(cur, fmt + 2, fmtend - 1)) { freeformat(head); return NULL; } fmt = fmtend + 1; } else { fmtend = fmt; do { fmtend += 1; fmtend = strchr(fmtend, '$'); } while (fmtend && fmtend[1] != '{'); if (!fmtend) fmtend = fmt + strlen(fmt); if (!parsestring(cur, fmt, fmtend - 1)) { freeformat(head); return NULL; } fmt = fmtend; } } return head; }
static int parsevalue(Parser *p, JSON *parent, JSON **prev) { switch (*p->s) { case '{': return parseobject(p, parent, prev); case '[': return parsearray(p, parent, prev); case '"': return parsestring(p, parent, prev); case 't': return parsetrue(p, parent, prev); case 'f': return parsefalse(p, parent, prev); case 'n': return parsenull(p, parent, prev); case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return parsenumber(p, parent, prev); } return 0; }
int main(int argc, char *argv[]) { union { struct sockaddr sa; struct sockaddr_in sa_in; struct sockaddr_in6 sa_in6; } sa; char line[512], key3[8], *host = NULL, *origin = NULL, *key = NULL, *protocol; unsigned long minport, maxport, port; uint32_t key1 = 0, key2 = 0; socklen_t salen; pid_t pid; int fd, monitoring = 0, s; /* Squelch stderr when it is a socket. */ if (!isatty(STDERR_FILENO)) { fd = open("/dev/null", O_WRONLY); if (fd == -1) { perror("open"); return (1); } if (fd != STDERR_FILENO) { dup2(fd, STDERR_FILENO); close(fd); } } if (argc != 3) usage(); minport = strtoul(argv[1], NULL, 10); maxport = strtoul(argv[2], NULL, 10); if (1 > minport || minport > maxport || maxport > 65535) usage(); eat_flash_magic(); /* GET / header. */ if (fgets(line, sizeof line, stdin) == NULL) { perror("fgets"); return (1); } if (strncmp(line, "GET /", 5) != 0) { DPRINTF("malformed HTTP header received"); return (1); } if (strncmp(line, "GET /wsproxy-monitoring/ ", 25) == 0) { monitoring = 1; port = 0; /* Keep compiler happy. */ } else if (minport == maxport) { /* Simply ignore URL and connect to a single host. */ port = minport; } else { /* Multiplexing mode. Use port number in URL. */ port = strtoul(line + 5, NULL, 10); if (port < minport || port > maxport) { DPRINTF("port not allowed"); return (1); } } /* Parse HTTP headers. */ do { if (fgets(line, sizeof line, stdin) == NULL) { DPRINTF("partial HTTP header received"); return (1); } if (strncasecmp(line, "Host: ", 6) == 0) { host = parsestring(line + 6); } else if (strncasecmp(line, "Origin: ", 8) == 0) { origin = parsestring(line + 8); } else if (strncasecmp(line, "Sec-WebSocket-Key: ", 19) == 0) { hybi10 = 1; key = parsestring(line + 19); } else if (strncasecmp(line, "Sec-WebSocket-Key1: ", 20) == 0) { key1 = parsehdrkey(line + 20); } else if (strncasecmp(line, "Sec-WebSocket-Key2: ", 20) == 0) { key2 = parsehdrkey(line + 20); } else if (strncasecmp(line, "Sec-WebSocket-Protocol: ", 24) == 0) { protocol = parsestring(line + 24); if (strcmp(protocol, "base64") != 0) { DPRINTF("Unsupported protocol: %s", protocol); return (1); } } } while (strcmp(line, "\n") != 0 && strcmp(line, "\r\n") != 0); /* Simple monitoring. */ if (monitoring) { printf("HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "\r\n" "RUNNING\n"); return (0); } /* Eight byte payload. */ if (!hybi10) if (fread(key3, sizeof key3, 1, stdin) != 1) { DPRINTF("key data missing"); return (1); } /* Use our own address. Fall back to 127.0.0.1 on failure. */ salen = sizeof sa; if (getsockname(STDIN_FILENO, &sa.sa, &salen) == -1) { salen = sizeof sa.sa_in; memset(&sa.sa_in, 0, salen); sa.sa_in.sin_family = AF_INET; sa.sa_in.sin_addr.s_addr = inet_addr("127.0.0.1"); } switch (sa.sa.sa_family) { case AF_INET: sa.sa_in.sin_port = htons(port); break; case AF_INET6: sa.sa_in6.sin6_port = htons(port); break; default: /* Unknown protocol. */ DPRINTF("unsupported network protocol"); return (1); } s = socket(sa.sa.sa_family, SOCK_STREAM, 0); if (s == -1) { perror("socket"); return (1); } if (connect(s, &sa.sa, salen) == -1) { perror("connect"); return (1); } /* Send HTTP response, based on protocol version. */ if (hybi10) { char accepthdr[HYBI10_ACCEPTHDRLEN]; hybi10_calcaccepthdr(key, accepthdr); printf("HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %s\r\n" "Sec-WebSocket-Protocol: base64\r\n\r\n", accepthdr); } else { char response[MD5_DIGEST_LENGTH]; hixie76_calcresponse(key1, key2, key3, response); printf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" "Upgrade: WebSocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Origin: %s\r\n" "Sec-WebSocket-Location: ws://%s/%lu\r\n" "Sec-WebSocket-Protocol: base64\r\n\r\n", origin, host, port); fwrite(response, sizeof response, 1, stdout); } fflush(stdout); /* Spawn child process for bi-directional pipe. */ pid = fork(); if (pid == -1) { perror("fork"); return (1); } else if (pid == 0) { other = getppid(); if (hybi10) hybi10_decode(stdin, s); else hixie76_decode(stdin, s); } else { other = pid; if (hybi10) hybi10_encode(s, STDOUT_FILENO); else hixie76_encode(s, STDOUT_FILENO); } assert(0); }
void read_xpm_entry(FILE *in,t_matrix *mm) { t_mapping *map; char *line=NULL,*str,buf[256]; int i,m,col_len,nch,n_axis_x,n_axis_y,llmax; unsigned int r,g,b; double u; bool bGetOnWithIt; t_xpmelmt c; mm->flags=0; mm->title[0]=0; mm->legend[0]=0; mm->label_x[0]=0; mm->label_y[0]=0; mm->matrix=NULL; mm->axis_x=NULL; mm->axis_y=NULL; mm->bDiscrete=FALSE; llmax = STRLEN; while (fgetline(&line,llmax,in) && (strncmp(line,"static",6) != 0)) { parsestring(line,"title",(mm->title)); parsestring(line,"legend",(mm->legend)); parsestring(line,"x-label",(mm->label_x)); parsestring(line,"y-label",(mm->label_y)); parsestring(line,"type",buf); } if (buf[0] && (strcasecmp(buf,"Discrete")==0)) mm->bDiscrete=TRUE; if (debug) fprintf(debug,"%s %s %s %s\n", mm->title,mm->legend,mm->label_x,mm->label_y); if (strncmp(line,"static",6) != 0) gmx_input("Invalid XPixMap"); /* Read sizes */ bGetOnWithIt=FALSE; while (!bGetOnWithIt && fgetline(&line,llmax,in)) { while (( line[0] != '\"' ) && ( line[0] != '\0' )) line++; if ( line[0] == '\"' ) { line2string(&line); sscanf(line,"%d %d %d %d",&(mm->nx),&(mm->ny),&(mm->nmap),&nch); if (nch > 2) gmx_fatal(FARGS,"Sorry can only read xpm's with at most 2 caracters per pixel\n"); llmax = max(STRLEN,mm->nx+10); bGetOnWithIt=TRUE; } } if (debug) fprintf(debug,"mm->nx %d mm->ny %d mm->nmap %d nch %d\n", mm->nx,mm->ny,mm->nmap,nch); /* Read color map */ snew(map,mm->nmap); m=0; while ((m < mm->nmap) && fgetline(&line,llmax,in)) { line=strchr(line,'\"'); if (line) { line++; /* Read xpm color map entry */ map[m].code.c1 = line[0]; if (nch==1) map[m].code.c2 = 0; else map[m].code.c2 = line[1]; line += nch; str = strchr(line,'#'); if (str) { str++; col_len = 0; while (isxdigit(str[col_len])) col_len++; if (col_len==6) { sscanf(line,"%*s #%2x%2x%2x",&r,&g,&b); map[m].rgb.r=r/255.0; map[m].rgb.g=g/255.0; map[m].rgb.b=b/255.0; } else if (col_len==12) { sscanf(line,"%*s #%4x%4x%4x",&r,&g,&b); map[m].rgb.r=r/65535.0; map[m].rgb.g=g/65535.0; map[m].rgb.b=b/65535.0; } else gmx_file("Unsupported or invalid colormap in X PixMap"); } else { str = strchr(line,'c'); if (str) str += 2; else gmx_file("Unsupported or invalid colormap in X PixMap"); fprintf(stderr,"Using white for color \"%s",str); map[m].rgb.r = 1; map[m].rgb.g = 1; map[m].rgb.b = 1; } line=strchr(line,'\"'); line++; line2string(&line); map[m].desc = strdup(line); m++; } } if ( m != mm->nmap ) gmx_fatal(FARGS,"Number of read colors map entries (%d) does not match the number in the header (%d)",m,mm->nmap); mm->map = map; /* Read axes, if there are any */ n_axis_x=0; n_axis_y=0; bGetOnWithIt=FALSE; do { if (strstr(line,"x-axis")) { line=strstr(line,"x-axis"); skipstr(&line); if (mm->axis_x==NULL) snew(mm->axis_x,mm->nx + 1); while (sscanf(line,"%lf",&u)==1) { if (n_axis_x > mm->nx) { gmx_fatal(FARGS,"Too many x-axis labels in xpm (max %d)",mm->nx); } else if (n_axis_x == mm->nx) { mm->flags |= MAT_SPATIAL_X; } mm->axis_x[n_axis_x] = u; n_axis_x++; skipstr(&line); } } else if (strstr(line,"y-axis")) { line=strstr(line,"y-axis"); skipstr(&line); if (mm->axis_y==NULL) snew(mm->axis_y,mm->ny + 1); while (sscanf(line,"%lf",&u)==1) { if (n_axis_y > mm->ny) { gmx_file("Too many y-axis labels in xpm"); } else if (n_axis_y == mm->ny) { mm->flags |= MAT_SPATIAL_Y; } mm->axis_y[n_axis_y] = u; n_axis_y++; skipstr(&line); } } } while ((line[0] != '\"') && fgetline(&line,llmax,in)); /* Read matrix */ snew(mm->matrix,mm->nx); for(i=0; i<mm->nx; i++) snew(mm->matrix[i],mm->ny); m=mm->ny-1; do { if(m%(1+mm->ny/100)==0) fprintf(stderr,"%3d%%\b\b\b\b",(100*(mm->ny-m))/mm->ny); while ((line[0] != '\"') && (line[0] != '\0')) line++; if (line[0] != '\"') gmx_fatal(FARGS,"Not enough caracters in row %d of the matrix\n",m+1); else { line++; for(i=0; i<mm->nx; i++) { c.c1=line[nch*i]; if (nch==1) c.c2=0; else c.c2=line[nch*i+1]; mm->matrix[i][m]=searchcmap(mm->nmap,mm->map,c); } m--; } } while ((m>=0) && fgetline(&line,llmax,in)); if (m>=0) gmx_incons("Not enough rows in the matrix"); }
// Skip a statement without executing it // // { stmt; stmt; } // stmt; // void skipstatement(void) { signed char nestlevel = 0; #ifdef PARSER_TRACE if (trace) sp("SKP["); #endif // Skip a statement list in curly braces: { stmt; stmt; stmt; } // Eat until the matching s_rcurly if (sym == s_lcurly) { getsym(); // eat "{" while (sym != s_eof) { if (sym == s_lcurly) ++nestlevel; else if (sym == s_rcurly) { if (nestlevel <= 0) { getsym(); // eat "}" break; } else --nestlevel; } else if (sym == s_quote) parsestring(&skipbyte); getsym(); } } // skipping the if statement is a little tricky; same for switch else if ((sym == s_if) || (sym == s_switch)) { // find ';', '{', or end while ((sym != s_eof) && (sym != s_semi) && (sym != s_lcurly)) getsym(); if (sym == s_eof) return; else if (sym == s_lcurly) skipstatement(); // eat an if-true {statementlist;} else getsym(); // ate the statement; eat the ';' // now handle the optional 'else' part if (sym == s_else) { getsym(); // eat 'else' skipstatement(); // skip one statement and we're done } } // Skip a single statement, not a statementlist in braces: // eat until semicolon or ')' // ignoring embedded argument lists else { while (sym != s_eof) { if (sym == s_lparen) ++nestlevel; else if (sym == s_rparen) { if (nestlevel <= 0) { getsym(); break; } else --nestlevel; } else if (sym == s_quote) parsestring(&skipbyte); else if (nestlevel == 0) { //if ((sym == s_semi) || (sym == s_comma)) { if (sym == s_semi) { getsym(); // eat ";" break; } } getsym(); } } #ifdef PARSER_TRACE if (trace) sp("]SKP"); #endif }
dcpu16token nexttoken() { #define return_(x) /*printf("%d:%s\n", curline, #x);*/ return x; /* Skip all spaces TO the next token */ while (isspace(*cur_pos)) cur_pos++; /* Test some operators */ switch (*cur_pos++) { case '\0': case '\n': return_(T_NEWLINE); case ',': return_(T_COMMA); case '[': return_(T_LBRACK); case ']': return_(T_RBRACK); case '+': return_(T_PLUS); case ':': return_(T_COLON); case '\"': return parsestring(&cur_pos); default: break; } cur_pos--; #define TRY(i) if (!strncasecmp(cur_pos, #i, strlen(#i))) { \ if (!isalnum(*(cur_pos + strlen(#i)))) { \ cur_pos += strlen(#i); \ return_(T_ ## i); \ } \ } #define TRYM(i) if (!strncasecmp(cur_pos, "." #i, strlen(#i) + 1)) { \ cur_pos += strlen(#i) + 1; \ return_(T_ ## i); \ } /* Try assembler pseudo instructions */ TRYM(ORG); TRYM(DAT); /* Try instructions */ TRY(SET); TRY(ADD); TRY(SUB); TRY(MUL); TRY(DIV); TRY(MOD); TRY(SHL); TRY(SHR); TRY(AND); TRY(BOR); TRY(XOR); TRY(IFE); TRY(IFN); TRY(IFG); TRY(IFB); TRY(JSR); /* Compatibility for other assemblers */ TRY(DAT); TRY(ORG); /* And some "special" registers */ TRY(POP); TRY(PEEK); TRY(PUSH); TRY(SP); TRY(PC); TRY(O); #undef TRY #undef TRYM if (isalpha(*cur_pos)) { int strlength = 0; /* Register or label */ while (isalnum(*cur_pos) || (*cur_pos == '_')) { cur_pos++; strlength++; } if (strlength > 1) { strncpy(cur_tok.string, cur_pos - strlength, strlength); cur_tok.string[strlength] = '\0'; return_(T_IDENTIFIER); } else { return parseregister(*(cur_pos - strlength)); } } else if (isdigit(*cur_pos)) { cur_tok.number = parsenumeric(); return_(T_NUMBER); } error("Unrecognized input '%c'", *cur_pos); return T_NEWLINE; #undef return_ }
static Jsonnode* parseobject(const char *str,const char **endp){ SKIPSPACESRETNULL(str); if(*str!='{')return NULL; str++; SKIPSPACESRETNULL(str); if(*str=='}'){ Jsonnode *node=malloc(sizeof(Jsonnode)); assert(node); node->type=JSON_OBJECT; node->objval.capacity=1; node->objval.numkeys=0; node->objval.keys=malloc(1); assert(node->objval.keys); node->objval.values=malloc(1); assert(node->objval.values); *endp=str+1; return node; } int sz=16,numkeys=0; char **keys=malloc(sz*sizeof(char*)); assert(keys); Jsonnode **values=malloc(sz*sizeof(Jsonnode*)); assert(values); #define FAILRETURN \ do { \ for(int i=0;i<numkeys;i++)free(keys[i]); \ for(int i=0;i<numkeys;i++)json_free(values[i]); \ free(keys); free(values); \ return NULL; \ } while(0) const char *cursor=str; while(*cursor){ const char *keyend,*valend; Jsonnode *keynode=parsestring(cursor,&keyend); if(!keynode)FAILRETURN; SKIPSPACES(keyend); if(*keyend!=':'){ json_free(keynode); FAILRETURN; } cursor=keyend+1; SKIPSPACES(cursor); Jsonnode *valnode=json_parse_endp(cursor,&valend); if(!valnode){ json_free(keynode); FAILRETURN; } if(numkeys==sz){ sz*=2; keys=realloc(keys,sz*sizeof(char*)); assert(keys); values=realloc(values,sz*sizeof(Jsonnode*)); assert(values); } keys[numkeys]=keynode->strval; free(keynode); values[numkeys]=valnode; numkeys++; cursor=valend; SKIPSPACES(cursor); if(*cursor=='}')break; if(*cursor!=',')FAILRETURN; cursor++; } if(*cursor!='}')return NULL; Jsonnode *node=malloc(sizeof(Jsonnode)); assert(node); node->type=JSON_OBJECT; node->objval.numkeys=numkeys; node->objval.capacity=sz; node->objval.keys=keys; node->objval.values=values; *endp=cursor+1; return node; #undef FAILRETURN }