static query_result query_config_string(const char* str, const char* k) { size_t ksize = 0; while (k[ksize] && k[ksize] != '{') ksize++; int last = !k[ksize]; query_result res = {0, 0}; while (1) { const char* key_start = str = skip_whitespace(str); const char* key_end = str = skip_key(str); int match = (key_end - key_start) == ksize; if (match) for (size_t i = 0; i < ksize; i++) if (key_start[i] != k[i]) match = 0; const char* value_start = str = skip_whitespace(str); while (*str != ';') { if (!*str) { return res; } else if (*str == '"') { str = skip_string(str+1); } else if (*str == '{') { const char* search_key = match && !last ? k + ksize + 1 : ""; query_result inner_res = query_config_string(str + 1, search_key); if (inner_res.start) return inner_res; str = inner_res.end + 1; } else { str = skip_key(str); } str = skip_whitespace(str); } res.end = str; if (match && last) { res.start = value_start; return res; } str = skip_whitespace(str+1); if (*str == '}') { res.end = str; return res; } } }
/* * y_entries: * find the yacc tags and put them in. */ void y_entries(void) { int c; char *sp; bool in_rule; char tok[MAXTOKEN]; in_rule = NO; while (GETC(!=, EOF)) switch (c) { case '\n': SETLINE; /* FALLTHROUGH */ case ' ': case '\f': case '\r': case '\t': break; case '{': if (skip_key('}')) in_rule = NO; break; case '\'': case '"': if (skip_key(c)) in_rule = NO; break; case '%': if (GETC(==, '%')) return; (void)ungetc(c, inf); break; case '/': if (GETC(==, '*') || c == '/') skip_comment(c); else (void)ungetc(c, inf); break; case '|': case ';': in_rule = NO; break; default: if (in_rule || (!isalpha(c) && c != '.' && c != '_')) break; sp = tok; *sp++ = c; while (GETC(!=, EOF) && (intoken(c) || c == '.')) *sp++ = c; *sp = EOS; getline(); /* may change before ':' */ while (iswhite(c)) { if (c == '\n') SETLINE; if (GETC(==, EOF)) return; } if (c == ':') { pfnote(tok, lineno); in_rule = YES; } else (void)ungetc(c, inf); }