+ free(ptr);
+ UCI_THROW(ctx, ctx->err);
+
+done:
+ return e;
+}
+
+static void
+uci_free_element(struct uci_element *e)
+{
+ if (e->name)
+ free(e->name);
+ if (!uci_list_empty(&e->list))
+ uci_list_del(&e->list);
+ free(e);
+}
+
+static struct uci_option *
+uci_alloc_option(struct uci_section *s, const char *name, const char *value)
+{
+ struct uci_package *p = s->package;
+ struct uci_context *ctx = p->ctx;
+ struct uci_option *o;
+
+ o = uci_alloc_element(ctx, option, name, strlen(value) + 1);
+ o->type = UCI_TYPE_STRING;
+ o->v.string = uci_dataptr(o);
+ o->section = s;
+ strcpy(o->v.string, value);
+ uci_list_add(&s->options, &o->e.list);
+
+ return o;
+}
+
+static inline void
+uci_free_option(struct uci_option *o)
+{
+ struct uci_element *e, *tmp;
+
+ switch(o->type) {
+ case UCI_TYPE_STRING:
+ if ((o->v.string != uci_dataptr(o)) &&
+ (o->v.string != NULL))
+ free(o->v.string);
+ break;
+ case UCI_TYPE_LIST:
+ uci_foreach_element_safe(&o->v.list, tmp, e) {
+ uci_free_element(e);
+ }
+ break;
+ default:
+ break;
+ }
+ uci_free_element(&o->e);
+}
+
+static struct uci_option *
+uci_alloc_list(struct uci_section *s, const char *name)
+{
+ struct uci_package *p = s->package;
+ struct uci_context *ctx = p->ctx;
+ struct uci_option *o;
+
+ o = uci_alloc_element(ctx, option, name, 0);
+ o->type = UCI_TYPE_LIST;
+ o->section = s;
+ uci_list_init(&o->v.list);
+ uci_list_add(&s->options, &o->e.list);
+
+ return o;