From: Felix Fietkau Date: Fri, 22 Aug 2008 18:11:02 +0000 (+0200) Subject: code cleanup, some api changes for new uci_ptr struct X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=563f8dd6f0eb56780a00f5856bf7fcf40e39d845;p=uci.git code cleanup, some api changes for new uci_ptr struct --- diff --git a/cli.c b/cli.c index 16306ff..5a260ef 100644 --- a/cli.c +++ b/cli.c @@ -179,53 +179,44 @@ static void uci_show_changes(struct uci_package *p) static int package_cmd(int cmd, char *tuple) { - struct uci_package *p; - struct uci_section *s; struct uci_element *e = NULL; + struct uci_ptr ptr; - if (uci_lookup_ext(ctx, &e, tuple) != UCI_OK) { + if (uci_lookup_ptr(ctx, &ptr, tuple, true) != UCI_OK) { cli_perror(); return 1; } - switch(e->type) { - case UCI_TYPE_PACKAGE: - p = uci_to_package(e); - break; - case UCI_TYPE_SECTION: - s = uci_to_section(e); - p = s->package; - break; - case UCI_TYPE_OPTION: - s = uci_to_option(e)->section; - p = s->package; - break; - default: - return 0; - } + + if (ptr.o) + e = &ptr.o->e; + else if (ptr.s) + e = &ptr.s->e; + else + e = &ptr.p->e; switch(cmd) { case CMD_CHANGES: - uci_show_changes(p); + uci_show_changes(ptr.p); break; case CMD_COMMIT: if (flags & CLI_FLAG_NOCOMMIT) return 0; - if (uci_commit(ctx, &p, false) != UCI_OK) + if (uci_commit(ctx, &ptr.p, false) != UCI_OK) cli_perror(); break; case CMD_EXPORT: - uci_export(ctx, stdout, p, true); + uci_export(ctx, stdout, ptr.p, true); break; case CMD_SHOW: switch(e->type) { case UCI_TYPE_PACKAGE: - uci_show_package(p); + uci_show_package(ptr.p); break; case UCI_TYPE_SECTION: - uci_show_section(uci_to_section(e)); + uci_show_section(ptr.s); break; case UCI_TYPE_OPTION: - uci_show_option(uci_to_option(e)); + uci_show_option(ptr.o); break; default: /* should not happen */ @@ -234,7 +225,7 @@ static int package_cmd(int cmd, char *tuple) break; } - uci_unload(ctx, p); + uci_unload(ctx, ptr.p); return 0; } @@ -335,74 +326,36 @@ done: static int uci_do_section_cmd(int cmd, int argc, char **argv) { - struct uci_package *p = NULL; - struct uci_section *s = NULL; - struct uci_element *e = NULL; - struct uci_option *o = NULL; - char *section = NULL; - char *option = NULL; - char *value = NULL; + struct uci_element *e; + struct uci_ptr ptr; int ret = UCI_OK; - char *str; if (argc != 2) return 255; - value = strchr(argv[1], '='); - if (value) { - *value = 0; - value++; - if (!uci_validate_text(value)) - return 1; - } - - if (value && (cmd != CMD_SET) && (cmd != CMD_ADD_LIST) && (cmd != CMD_RENAME)) - return 1; - - do { - str = strchr(argv[1], '.'); /* look up section part */ - if (!str) - break; - - str++; - str = strchr(str, '.'); /* look up option part */ - if (!str) - break; - - /* separate option from the rest of the pointer */ - *str = 0; - option = str + 1; - } while (0); - - if (uci_lookup_ext(ctx, &e, argv[1]) != UCI_OK) { + if (uci_lookup_ptr(ctx, &ptr, argv[1], true) != UCI_OK) { cli_perror(); return 1; } - switch(e->type) { - case UCI_TYPE_PACKAGE: - p = uci_to_package(e); - break; - case UCI_TYPE_SECTION: - s = uci_to_section(e); - break; - default: + if (ptr.value && (cmd != CMD_SET) && (cmd != CMD_ADD_LIST) && (cmd != CMD_RENAME)) return 1; - } - if (s) { - section = s->e.name; - p = s->package; - } + + if (ptr.o) + e = &ptr.o->e; + else if (ptr.s) + e = &ptr.s->e; + else + e = &ptr.p->e; switch(cmd) { case CMD_GET: switch(e->type) { case UCI_TYPE_SECTION: - printf("%s\n", s->type); + printf("%s\n", ptr.s->type); break; case UCI_TYPE_OPTION: - o = uci_to_option(e); - uci_show_value(o); + uci_show_value(ptr.o); break; default: break; @@ -410,19 +363,19 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv) /* throw the value to stdout */ break; case CMD_RENAME: - ret = uci_rename(ctx, p, section, option, value); + ret = uci_rename(ctx, &ptr); break; case CMD_REVERT: - ret = uci_revert(ctx, &p, section, option); + ret = uci_revert(ctx, &ptr.p, ptr.section, ptr.option); break; case CMD_SET: - ret = uci_set(ctx, p, section, option, value, NULL); + ret = uci_set(ctx, ptr.p, ptr.section, ptr.option, ptr.value, NULL); break; case CMD_ADD_LIST: - ret = uci_add_list(ctx, p, section, option, value, NULL); + ret = uci_add_list(ctx, &ptr); break; case CMD_DEL: - ret = uci_delete(ctx, p, section, option); + ret = uci_delete(ctx, &ptr); break; } @@ -432,7 +385,7 @@ static int uci_do_section_cmd(int cmd, int argc, char **argv) /* save changes, but don't commit them yet */ if (ret == UCI_OK) - ret = uci_save(ctx, p); + ret = uci_save(ctx, ptr.p); if (ret != UCI_OK) { cli_perror(); diff --git a/file.c b/file.c index d551208..c670f04 100644 --- a/file.c +++ b/file.c @@ -167,6 +167,7 @@ error: static void uci_parse_list(struct uci_context *ctx, char **str) { struct uci_parse_context *pctx = ctx->pctx; + struct uci_ptr ptr; char *name = NULL; char *value = NULL; @@ -180,27 +181,14 @@ static void uci_parse_list(struct uci_context *ctx, char **str) value = next_arg(ctx, str, false, false); assert_eol(ctx, str); - if (pctx->merge) { - UCI_TRAP_SAVE(ctx, error); - uci_add_list(ctx, pctx->package, pctx->section->e.name, name, value, NULL); - UCI_TRAP_RESTORE(ctx); - return; -error: - UCI_THROW(ctx, ctx->err); - } else { - struct uci_option *o; - struct uci_element *e; - - e = uci_lookup_list(&pctx->section->options, name); - o = uci_to_option(e); - if (!o) { - o = uci_alloc_list(pctx->section, name); - } else { - if (o->type != UCI_TYPE_LIST) - uci_parse_error(ctx, *str, "conflicting list/option keywords"); - } - UCI_INTERNAL(uci_add_element_list, ctx, o, value); - } + UCI_NESTED(uci_fill_ptr, ctx, &ptr, &pctx->section->e, false); + ptr.option = name; + ptr.value = value; + + UCI_INTERNAL(uci_lookup_ptr, ctx, &ptr, NULL, false); + + ctx->internal = !pctx->merge; + UCI_NESTED(uci_add_list, ctx, &ptr); } diff --git a/history.c b/history.c index 4e97524..07db1d3 100644 --- a/history.c +++ b/history.c @@ -150,13 +150,13 @@ static void uci_parse_history_line(struct uci_context *ctx, struct uci_package * switch(cmd) { case UCI_CMD_RENAME: - UCI_INTERNAL(uci_rename, ctx, p, ptr.section, ptr.option, ptr.value); + UCI_INTERNAL(uci_rename, ctx, &ptr); break; case UCI_CMD_REMOVE: - UCI_INTERNAL(uci_delete, ctx, p, ptr.section, ptr.option); + UCI_INTERNAL(uci_delete, ctx, &ptr); break; case UCI_CMD_LIST_ADD: - UCI_INTERNAL(uci_add_list, ctx, p, ptr.section, ptr.option, ptr.value, NULL); + UCI_INTERNAL(uci_add_list, ctx, &ptr); break; case UCI_CMD_ADD: case UCI_CMD_CHANGE: diff --git a/list.c b/list.c index d7b9f69..e770234 100644 --- a/list.c +++ b/list.c @@ -253,6 +253,22 @@ uci_free_package(struct uci_package **package) *package = NULL; } +static void +uci_free_any(struct uci_element **e) +{ + switch((*e)->type) { + case UCI_TYPE_SECTION: + uci_free_section(uci_to_section(*e)); + break; + case UCI_TYPE_OPTION: + uci_free_option(uci_to_option(*e)); + break; + default: + break; + } + *e = NULL; +} + static struct uci_element *uci_lookup_list(struct uci_list *list, const char *name) { struct uci_element *e; @@ -264,51 +280,21 @@ static struct uci_element *uci_lookup_list(struct uci_list *list, const char *na return NULL; } -int uci_lookup_ext(struct uci_context *ctx, struct uci_element **res, char *str) +static struct uci_element *uci_lookup_ext_section(struct uci_context *ctx, struct uci_ptr *ptr) { - struct uci_package *p = NULL; - struct uci_element *e; + char *idxstr, *t, *section, *name; + struct uci_element *e = NULL; struct uci_section *s; - struct uci_ptr ptr; - char *idxstr, *t; int idx, c; - UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, res != NULL); - UCI_ASSERT(ctx, str != NULL); - - UCI_INTERNAL(uci_parse_ptr, ctx, &ptr, str); + section = uci_strdup(ctx, ptr->section); + name = idxstr = section + 1; - /* look up the package first */ - e = uci_lookup_list(&ctx->root, ptr.package); - if (!e) { - UCI_INTERNAL(uci_load, ctx, ptr.package, &p); - if (!p) - goto notfound; - e = &p->e; - } else { - p = uci_to_package(e); - } - - if (!ptr.section) - goto done; - - /* if the section name validates as a regular name, pass through - * to the regular uci_lookup function call */ - if (!(ptr.flags & UCI_LOOKUP_EXTENDED)) { - UCI_INTERNAL(uci_lookup, ctx, &e, p, ptr.section, ptr.option); - goto done; - } - - /* name did not validate, that means we have an extended lookup call - * parse it here. for now only the section index syntax is supported */ - if (ptr.section[0] != '@') + if (section[0] != '@') goto error; - ptr.section++; - /* parse the section index part */ - idxstr = strchr(ptr.section, '['); + idxstr = strchr(idxstr, '['); if (!idxstr) goto error; *idxstr = 0; @@ -326,18 +312,18 @@ int uci_lookup_ext(struct uci_context *ctx, struct uci_element **res, char *str) if (t && *t) goto error; - if (!*ptr.section) - ptr.section = NULL; - if (ptr.section && !uci_validate_str(ptr.section, false)) + if (!*name) + name = NULL; + else if (!uci_validate_str(name, false)) goto error; /* if the given index is negative, it specifies the section number from * the end of the list */ if (idx < 0) { c = 0; - uci_foreach_element(&p->sections, e) { + uci_foreach_element(&ptr->p->sections, e) { s = uci_to_section(e); - if (ptr.section && (strcmp(s->type, ptr.section) != 0)) + if (name && (strcmp(s->type, name) != 0)) continue; c++; @@ -346,55 +332,75 @@ int uci_lookup_ext(struct uci_context *ctx, struct uci_element **res, char *str) } c = 0; - uci_foreach_element(&p->sections, e) { + uci_foreach_element(&ptr->p->sections, e) { s = uci_to_section(e); - if (ptr.section && (strcmp(s->type, ptr.section) != 0)) + if (name && (strcmp(s->type, name) != 0)) continue; if (idx == c) - goto found; + goto done; c++; } - goto notfound; - -found: - if (ptr.option) - e = uci_lookup_list(&s->options, ptr.option); -done: - *res = e; - return 0; + e = NULL; + goto done; -notfound: - UCI_THROW(ctx, UCI_ERR_NOTFOUND); error: + e = NULL; + memset(ptr, 0, sizeof(struct uci_ptr)); UCI_THROW(ctx, UCI_ERR_INVAL); - return 0; +done: + free(section); + return e; } -int uci_lookup(struct uci_context *ctx, struct uci_element **res, struct uci_package *p, const char *section, const char *option) +int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended) { struct uci_element *e; - struct uci_section *s; UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, res != NULL); - UCI_ASSERT(ctx, p != NULL); - UCI_ASSERT(ctx, section && uci_validate_name(section)); - if (option) - UCI_ASSERT(ctx, uci_validate_name(option)); + UCI_ASSERT(ctx, ptr != NULL); + + if (str) + UCI_INTERNAL(uci_parse_ptr, ctx, ptr, str); + + ptr->flags |= UCI_LOOKUP_DONE; + + /* look up the package first */ + e = uci_lookup_list(&ctx->root, ptr->package); + if (!e) { + UCI_INTERNAL(uci_load, ctx, ptr->package, &ptr->p); + if (!ptr->p) + goto notfound; + } else { + ptr->p = uci_to_package(e); + } + + if (!ptr->section) + goto complete; + + /* if the section name validates as a regular name, pass through + * to the regular uci_lookup function call */ + if (ptr->flags & UCI_LOOKUP_EXTENDED) + e = uci_lookup_ext_section(ctx, ptr); + else + e = uci_lookup_list(&ptr->p->sections, ptr->section); - e = uci_lookup_list(&p->sections, section); if (!e) - goto notfound; + goto abort; - if (option) { - s = uci_to_section(e); - e = uci_lookup_list(&s->options, option); + ptr->s = uci_to_section(e); + + if (ptr->option) { + e = uci_lookup_list(&ptr->s->options, ptr->option); if (!e) - goto notfound; + goto abort; + + ptr->o = uci_to_option(e); } - *res = e; +complete: + ptr->flags |= UCI_LOOKUP_COMPLETE; +abort: return 0; notfound: @@ -402,75 +408,84 @@ notfound: return 0; } -int uci_del_element(struct uci_context *ctx, struct uci_element *e) +int +uci_fill_ptr(struct uci_context *ctx, struct uci_ptr *ptr, struct uci_element *e, bool complete) { - /* NB: UCI_INTERNAL use means without history tracking */ - bool internal = ctx->internal; - struct uci_package *p = NULL; - struct uci_section *s = NULL; - struct uci_option *o = NULL; - struct uci_element *i, *tmp; - char *option = NULL; - UCI_HANDLE_ERR(ctx); + UCI_ASSERT(ctx, ptr != NULL); UCI_ASSERT(ctx, e != NULL); + memset(ptr, 0, sizeof(struct uci_ptr)); switch(e->type) { - case UCI_TYPE_SECTION: - s = uci_to_section(e); - uci_foreach_element_safe(&s->options, tmp, i) { - uci_del_element(ctx, i); - } - break; case UCI_TYPE_OPTION: - o = uci_to_option(e); - s = o->section; - p = s->package; - option = e->name; - break; + ptr->o = uci_to_option(e); + goto fill_option; + case UCI_TYPE_SECTION: + ptr->s = uci_to_section(e); + goto fill_section; + case UCI_TYPE_PACKAGE: + ptr->p = uci_to_package(e); + goto fill_package; default: UCI_THROW(ctx, UCI_ERR_INVAL); - break; } - p = s->package; - if (!internal && p->has_history) - uci_add_history(ctx, &p->history, UCI_CMD_REMOVE, s->e.name, option, NULL); +fill_option: + ptr->option = ptr->o->e.name; + ptr->s = ptr->o->section; +fill_section: + ptr->section = ptr->s->e.name; + ptr->p = ptr->s->package; +fill_package: + ptr->package = ptr->p->e.name; - switch(e->type) { - case UCI_TYPE_SECTION: - uci_free_section(s); - break; - case UCI_TYPE_OPTION: - uci_free_option(o); - break; - default: - break; - } + ptr->flags |= UCI_LOOKUP_DONE; + if (complete) + ptr->flags |= UCI_LOOKUP_COMPLETE; return 0; } -int uci_add_element_list(struct uci_context *ctx, struct uci_option *o, const char *value) +static struct uci_element * +expand_ptr(struct uci_context *ctx, struct uci_ptr *ptr, bool complete) { - struct uci_element *e; - struct uci_package *p; - struct uci_section *s; - bool internal = ctx->internal; + UCI_ASSERT(ctx, ptr != NULL); - UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, (o != NULL) && (o->type == UCI_TYPE_LIST) && uci_validate_text(value)); + if (!(ptr->flags & UCI_LOOKUP_DONE)) + uci_lookup_ptr(ctx, ptr, NULL, 1); + if (complete && !(ptr->flags & UCI_LOOKUP_COMPLETE)) + UCI_THROW(ctx, UCI_ERR_NOTFOUND); + UCI_ASSERT(ctx, ptr->p != NULL); + + /* fill in missing string info */ + if (ptr->p && !ptr->package) + ptr->package = ptr->p->e.name; + if (ptr->s && !ptr->section) + ptr->section = ptr->s->e.name; + if (ptr->o && !ptr->option) + ptr->option = ptr->o->e.name; + + if (ptr->o) + return &ptr->o->e; + if (ptr->s) + return &ptr->s->e; + if (ptr->p) + return &ptr->p->e; + else + return NULL; +} - s = o->section; - p = s->package; +static void uci_add_element_list(struct uci_context *ctx, struct uci_ptr *ptr, bool internal) +{ + struct uci_element *e; + struct uci_package *p; + p = ptr->p; if (!internal && p->has_history) - uci_add_history(ctx, &p->history, UCI_CMD_LIST_ADD, s->e.name, o->e.name, value); + uci_add_history(ctx, &p->history, UCI_CMD_LIST_ADD, ptr->section, ptr->option, ptr->value); - e = uci_alloc_generic(ctx, UCI_TYPE_ITEM, value, sizeof(struct uci_option)); - uci_list_add(&o->v.list, &e->list); - - return 0; + e = uci_alloc_generic(ctx, UCI_TYPE_ITEM, ptr->value, sizeof(struct uci_option)); + uci_list_add(&ptr->o->v.list, &e->list); } int uci_set_element_value(struct uci_context *ctx, struct uci_element **element, const char *value) @@ -544,7 +559,7 @@ int uci_set_element_value(struct uci_context *ctx, struct uci_element **element, if ((e->type == UCI_TYPE_OPTION) && (size == 0)) { o = uci_alloc_option(s, option, value); - UCI_INTERNAL(uci_del_element, ctx, e); + uci_free_any(&e); *element = &o->e; goto done; } @@ -570,24 +585,29 @@ done: return 0; } -int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name) +int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr) { /* NB: UCI_INTERNAL use means without history tracking */ bool internal = ctx->internal; struct uci_element *e; + struct uci_package *p; + char *n; UCI_HANDLE_ERR(ctx); - /* NB: p, section, option validated by uci_lookup */ - UCI_INTERNAL(uci_lookup, ctx, &e, p, section, option); + e = expand_ptr(ctx, ptr, true); + p = ptr->p; + + UCI_ASSERT(ctx, ptr->s); + UCI_ASSERT(ctx, ptr->value); if (!internal && p->has_history) - uci_add_history(ctx, &p->history, UCI_CMD_RENAME, section, option, name); + uci_add_history(ctx, &p->history, UCI_CMD_RENAME, ptr->section, ptr->option, ptr->value); - name = uci_strdup(ctx, name); + n = uci_strdup(ctx, ptr->value); if (e->name) free(e->name); - e->name = name; + e->name = n; return 0; } @@ -608,71 +628,66 @@ int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char * return 0; } -int uci_delete(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option) +int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr) { /* NB: pass on internal flag to uci_del_element */ bool internal = ctx->internal; + struct uci_package *p; struct uci_element *e; UCI_HANDLE_ERR(ctx); - /* NB: p, section, option validated by uci_lookup */ - UCI_INTERNAL(uci_lookup, ctx, &e, p, section, option); + e = expand_ptr(ctx, ptr, true); + p = ptr->p; - ctx->internal = internal; - return uci_del_element(ctx, e); + UCI_ASSERT(ctx, ptr->s); + + if (!internal && p->has_history) + uci_add_history(ctx, &p->history, UCI_CMD_REMOVE, ptr->section, ptr->option, NULL); + + uci_free_any(&e); + return 0; } -int uci_add_list(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option, const char *value, struct uci_option **result) +int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr) { /* NB: UCI_INTERNAL use means without history tracking */ bool internal = ctx->internal; - struct uci_element *e; - struct uci_section *s; - struct uci_option *o; struct uci_option *prev = NULL; const char *value2 = NULL; UCI_HANDLE_ERR(ctx); - UCI_ASSERT(ctx, p && section && option && value && uci_validate_text(value)); - /* look up the section first */ - UCI_INTERNAL(uci_lookup, ctx, &e, p, section, NULL); - s = uci_to_section(e); + expand_ptr(ctx, ptr, false); + UCI_ASSERT(ctx, ptr->s); + UCI_ASSERT(ctx, ptr->value); - e = uci_lookup_list(&s->options, option); - if (e) { - o = uci_to_option(e); - switch (o->type) { + if (ptr->o) { + switch (ptr->o->type) { case UCI_TYPE_STRING: - /* we already have a string value, let's convert that to a list */ - prev = o; - value2 = value; - value = o->v.string; + /* we already have a string value, convert that to a list */ + prev = ptr->o; + value2 = ptr->value; + ptr->value = ptr->o->v.string; break; case UCI_TYPE_LIST: - if (result) - *result = o; - - ctx->internal = internal; - return uci_add_element_list(ctx, o, value); + uci_add_element_list(ctx, ptr, internal); + return 0; default: UCI_THROW(ctx, UCI_ERR_INVAL); break; } } - o = uci_alloc_list(s, option); - if (result) - *result = o; + ptr->o = uci_alloc_list(ptr->s, ptr->option); if (prev) { - UCI_INTERNAL(uci_add_element_list, ctx, o, value); + uci_add_element_list(ctx, ptr, true); uci_free_option(prev); - value = value2; + ptr->value = value2; } + uci_add_element_list(ctx, ptr, internal); - ctx->internal = internal; - return uci_add_element_list(ctx, o, value); + return 0; } int uci_set(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option, const char *value, struct uci_element **result) diff --git a/uci.h b/uci.h index fe05bb3..ed1a834 100644 --- a/uci.h +++ b/uci.h @@ -123,44 +123,21 @@ extern int uci_load(struct uci_context *ctx, const char *name, struct uci_packag extern int uci_unload(struct uci_context *ctx, struct uci_package *p); /** - * uci_lookup: Look up an uci element - * - * @ctx: uci context - * @res: where to store the result - * @package: uci_package struct - * @section: config section (optional) - * @option: option to search for (optional) - * - * If section is omitted, then a pointer to the config package is returned - * If option is omitted, then a pointer to the config section is returned - */ -extern int uci_lookup(struct uci_context *ctx, struct uci_element **res, struct uci_package *package, const char *section, const char *option); - -/** - * uci_lookup_ptr: Split an uci tuple string and look up elements + * uci_lookup_ptr: Split an uci tuple string and look up an element tree * @ctx: uci context * @ptr: lookup result struct * @str: uci tuple string to look up * @extended: allow extended syntax lookup - */ -extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended); - -/** - * uci_lookup_ext: Extended lookup for an uci element - * - * @ctx: uci context - * @res: where to store the result - * @ptr: uci pointer tuple * - * Looks up an element using the extended syntax. - * It can look up sections by an index with an optional type. + * if extended is set to true, uci_lookup_ptr supports the following + * extended syntax: * * Examples: * network.@interface[0].ifname ('ifname' option of the first interface section) * network.@interface[-1] (last interface section) * Note: uci_lookup_ext will automatically load a config package if necessary */ -extern int uci_lookup_ext(struct uci_context *ctx, struct uci_element **res, char *ptr); +extern int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended); /** * uci_add_section: Add an unnamed section @@ -182,14 +159,6 @@ extern int uci_add_section(struct uci_context *ctx, struct uci_package *p, const */ extern int uci_set_element_value(struct uci_context *ctx, struct uci_element **element, const char *value); -/** - * uci_add_element_list: Append a string to a list option - * @ctx: uci context - * @option: pointer to the uci option element - * @value: string to append - */ -extern int uci_add_element_list(struct uci_context *ctx, struct uci_option *o, const char *value); - /** * uci_set: Set an element's value; create the element if necessary * @ctx: uci context @@ -204,42 +173,26 @@ extern int uci_set(struct uci_context *ctx, struct uci_package *p, const char *s /** * uci_add_list: Append a string to an element list * @ctx: uci context - * @package: package name - * @section: section name - * @option: option name - * @value: string value - * @result: store the updated element in this variable (optional) + * @ptr: uci pointer (with value) * - * Note: if the given option already contains a string, convert it to an 1-element-list - * before appending the next element + * Note: if the given option already contains a string value, + * it will be converted to an 1-element-list before appending the next element */ -extern int uci_add_list(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option, const char *value, struct uci_option **result); +extern int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr); /** * uci_rename: Rename an element * @ctx: uci context - * @package: package name - * @section: section name - * @option: option name - * @name: new name + * @ptr: uci pointer (with value) */ -extern int uci_rename(struct uci_context *ctx, struct uci_package *p, char *section, char *option, char *name); - -/** - * uci_delete_element: Delete a section or option - * @ctx: uci context - * @e: element (section or option) - */ -extern int uci_delete_element(struct uci_context *ctx, struct uci_element *e); +extern int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr); /** * uci_delete: Delete a section or option * @ctx: uci context - * @p: uci package - * @section: section name - * @option: option name (optional) + * @ptr: uci pointer */ -extern int uci_delete(struct uci_context *ctx, struct uci_package *p, const char *section, const char *option); +extern int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr); /** * uci_save: save change history for a package @@ -395,7 +348,7 @@ struct uci_context int err; const char *func; jmp_buf trap; - bool internal; + bool internal, nested; char *buf; int bufsz; }; @@ -464,11 +417,12 @@ struct uci_ptr struct uci_package *p; struct uci_section *s; struct uci_option *o; + struct uci_element *last; - char *package; - char *section; - char *option; - char *value; + const char *package; + const char *section; + const char *option; + const char *value; }; diff --git a/uci_internal.h b/uci_internal.h index eba0143..111982e 100644 --- a/uci_internal.h +++ b/uci_internal.h @@ -114,9 +114,10 @@ struct uci_backend _var = { \ ctx->err = 0; \ if (!ctx) \ return UCI_ERR_INVAL; \ - if (!ctx->internal) \ + if (!ctx->internal && !ctx->nested) \ __val = setjmp(ctx->trap); \ ctx->internal = false; \ + ctx->nested = false; \ if (__val) { \ DPRINTF("LEAVE: %s, ret=%d\n", __func__, __val); \ ctx->err = __val; \ @@ -155,6 +156,18 @@ struct uci_backend _var = { \ func(ctx, __VA_ARGS__); \ } while (0) +/** + * UCI_NESTED: Do an normal nested call of a public API function + * + * Sets Exception handling to passthrough mode. + * Allows API functions to change behavior compared to public use + */ +#define UCI_NESTED(func, ctx, ...) do { \ + ctx->nested = true; \ + func(ctx, __VA_ARGS__); \ +} while (0) + + /* * check the specified condition. * throw an invalid argument exception if it's false