static struct config_value *_type(struct parser *p) { /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */ struct config_value *v = _create_value(p->mem); char *str; if (!v) return NULL; switch (p->t) { case TOK_INT: v->type = CFG_INT; v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */ match(TOK_INT); break; case TOK_FLOAT: v->type = CFG_FLOAT; v->v.r = strtod(p->tb, NULL); /* FIXME: check error */ match(TOK_FLOAT); break; case TOK_STRING: v->type = CFG_STRING; p->tb++, p->te--; /* strip "'s */ if (!(v->v.str = _dup_tok(p))) return_0; p->te++; match(TOK_STRING); break; case TOK_STRING_ESCAPED: v->type = CFG_STRING; p->tb++, p->te--; /* strip "'s */ if (!(str = _dup_tok(p))) return_0; unescape_double_quotes(str); v->v.str = str; p->te++; match(TOK_STRING_ESCAPED); break; default: log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value", p->tb - p->fb + 1, p->line); return 0; } return v; }
static struct config_node *_section(struct parser *p) { /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */ struct config_node *root, *n, *l = NULL; if (!(root = _create_node(p->mem))) return_0; if (!(root->key = _dup_tok(p))) return_0; match(TOK_IDENTIFIER); if (p->t == TOK_SECTION_B) { match(TOK_SECTION_B); while (p->t != TOK_SECTION_E) { if (!(n = _section(p))) return_0; if (!root->child) root->child = n; else l->sib = n; n->parent = root; l = n; } match(TOK_SECTION_E); } else { match(TOK_EQ); if (!(root->v = _value(p))) return_0; } return root; }
static struct dm_config_value *_type(struct parser *p) { /* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */ struct dm_config_value *v = _create_value(p->mem); char *str; if (!v) { log_error("Failed to allocate type value"); return NULL; } switch (p->t) { case TOK_INT: v->type = DM_CFG_INT; v->v.i = strtoll(p->tb, NULL, 0); /* FIXME: check error */ match(TOK_INT); break; case TOK_FLOAT: v->type = DM_CFG_FLOAT; v->v.f = strtod(p->tb, NULL); /* FIXME: check error */ match(TOK_FLOAT); break; case TOK_STRING: v->type = DM_CFG_STRING; if (!(v->v.str = _dup_string_tok(p))) return_NULL; match(TOK_STRING); break; case TOK_STRING_BARE: v->type = DM_CFG_STRING; if (!(v->v.str = _dup_tok(p))) return_NULL; match(TOK_STRING_BARE); break; case TOK_STRING_ESCAPED: v->type = DM_CFG_STRING; if (!(str = _dup_string_tok(p))) return_NULL; dm_unescape_double_quotes(str); v->v.str = str; match(TOK_STRING_ESCAPED); break; default: log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value", p->tb - p->fb + 1, p->line); return NULL; } return v; }
static struct dm_config_node *_section(struct parser *p, struct dm_config_node *parent) { /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */ struct dm_config_node *root; struct dm_config_value *value; char *str; if (p->t == TOK_STRING_ESCAPED) { if (!(str = _dup_string_tok(p))) return_NULL; dm_unescape_double_quotes(str); match(TOK_STRING_ESCAPED); } else if (p->t == TOK_STRING) { if (!(str = _dup_string_tok(p))) return_NULL; match(TOK_STRING); } else { if (!(str = _dup_tok(p))) return_NULL; match(TOK_IDENTIFIER); } if (!strlen(str)) { log_error("Parse error at byte %" PRIptrdiff_t " (line %d): empty section identifier", p->tb - p->fb + 1, p->line); return NULL; } root = _find_or_make_node(p->mem, parent, str); if (p->t == TOK_SECTION_B) { match(TOK_SECTION_B); while (p->t != TOK_SECTION_E) { if (!(_section(p, root))) return_NULL; } match(TOK_SECTION_E); } else { match(TOK_EQ); if (!(value = _value(p))) return_NULL; if (root->v) log_warn("WARNING: Ignoring duplicate" " config value: %s", str); root->v = value; } return root; }
static int _write_node(const struct dm_config_node *cn, int only_one, dm_putline_fn putline, const struct dm_config_node_out_spec *out_spec, void *baton) { struct config_output out = { .mem = dm_pool_create("config_output", 1024), .putline = putline, .spec = out_spec, .baton = baton }; if (!out.mem) return_0; if (!_write_config(cn, only_one, &out, 0)) { dm_pool_destroy(out.mem); return_0; } dm_pool_destroy(out.mem); return 1; } int dm_config_write_one_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton) { return _write_node(cn, 1, putline, NULL, baton); } int dm_config_write_node(const struct dm_config_node *cn, dm_putline_fn putline, void *baton) { return _write_node(cn, 0, putline, NULL, baton); } int dm_config_write_one_node_out(const struct dm_config_node *cn, const struct dm_config_node_out_spec *out_spec, void *baton) { return _write_node(cn, 1, NULL, out_spec, baton); } int dm_config_write_node_out(const struct dm_config_node *cn, const struct dm_config_node_out_spec *out_spec, void *baton) { return _write_node(cn, 0, NULL, out_spec, baton); } /* * parser */ static char *_dup_string_tok(struct parser *p) { char *str; p->tb++, p->te--; /* strip "'s */ if (p->te < p->tb) { log_error("Parse error at byte %" PRIptrdiff_t " (line %d): " "expected a string token.", p->tb - p->fb + 1, p->line); return NULL; } if (!(str = _dup_tok(p))) return_NULL; p->te++; return str; }