uci: Fix extra semicolons warnings
[oweals/uci.git] / list.c
diff --git a/list.c b/list.c
index abb202f97764eb50af932e5ef5fbe5e548fb6d2c..24ed2ee6ddf1fa84adf84acc11ab455086f83df9 100644 (file)
--- a/list.c
+++ b/list.c
@@ -137,7 +137,7 @@ static unsigned int djbhash(unsigned int hash, char *str)
        int i;
 
        /* initial value */
-       if (hash == ~0)
+       if (hash == ~0U)
                hash = 5381;
 
        for(i = 0; i < len; i++) {
@@ -149,7 +149,7 @@ static unsigned int djbhash(unsigned int hash, char *str)
 /* fix up an unnamed section, e.g. after adding options to it */
 static void uci_fixup_section(struct uci_context *ctx, struct uci_section *s)
 {
-       unsigned int hash = ~0;
+       unsigned int hash = ~0U;
        struct uci_element *e;
        char buf[16];
 
@@ -182,6 +182,32 @@ static void uci_fixup_section(struct uci_context *ctx, struct uci_section *s)
        s->e.name = uci_strdup(ctx, buf);
 }
 
+/* fix up option list HEAD pointers and pointer to section in options */
+static void uci_section_fixup_options(struct uci_section *s, bool no_options)
+{
+       struct uci_element *e;
+
+       if (no_options) {
+               /*
+                * enforce empty list pointer state (s->next == s) when original
+                * section had no options in the first place
+                */
+               uci_list_init(&s->options);
+               return;
+       }
+
+       /* fix pointers to HEAD at end/beginning of list */
+       uci_list_fixup(&s->options);
+
+       /* fix back pointer to section in options */
+       uci_foreach_element(&s->options, e) {
+               struct uci_option *o;
+
+               o = uci_to_option(e);
+               o->section = s;
+       }
+}
+
 static struct uci_section *
 uci_alloc_section(struct uci_package *p, const char *type, const char *name)
 {
@@ -597,8 +623,8 @@ int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr)
 {
        /* NB: UCI_INTERNAL use means without delta tracking */
        bool internal = ctx && ctx->internal;
-       struct uci_option *prev = NULL;
-       const char *value2 = NULL;
+       struct uci_option *volatile prev = NULL;
+       const char *volatile value2 = NULL;
 
        UCI_HANDLE_ERR(ctx);
 
@@ -699,20 +725,29 @@ int uci_set(struct uci_context *ctx, struct uci_ptr *ptr)
                ptr->s = uci_alloc_section(ptr->p, ptr->value, ptr->section);
                ptr->last = &ptr->s->e;
        } else if (ptr->o && ptr->option) { /* update option */
+               struct uci_option *o;
+
                if ((ptr->o->type == UCI_TYPE_STRING) &&
                        !strcmp(ptr->o->v.string, ptr->value))
                        return 0;
-               uci_free_option(ptr->o);
+
+               o = ptr->o;
                ptr->o = uci_alloc_option(ptr->s, ptr->option, ptr->value);
+               uci_free_option(o);
                ptr->last = &ptr->o->e;
        } else if (ptr->s && ptr->section) { /* update section */
                char *s = uci_strdup(ctx, ptr->value);
 
                if (ptr->s->type == uci_dataptr(ptr->s)) {
+                       /* drop the in-section storage of type name */
+                       bool no_options;
+
+                       no_options = uci_list_empty(&ptr->s->options);
                        ptr->last = NULL;
                        ptr->last = uci_realloc(ctx, ptr->s, sizeof(struct uci_section));
                        ptr->s = uci_to_section(ptr->last);
                        uci_list_fixup(&ptr->s->e.list);
+                       uci_section_fixup_options(ptr->s, no_options);
                } else {
                        free(ptr->s->type);
                }