+static void
+ucimap_add_fixup(struct uci_map *map, void *data, struct uci_optmap *om, const char *str)
+{
+ struct uci_fixup *f;
+
+ f = malloc(sizeof(struct uci_fixup));
+ if (!f)
+ return;
+
+ INIT_LIST_HEAD(&f->list);
+ f->sm = om->data.sm;
+ f->name = str;
+ f->target.type = om->type;
+ f->target.data.ptr = data;
+ list_add(&f->list, &map->fixup);
+}
+
+static void
+ucimap_add_value(union uci_datamap *data, struct uci_optmap *om, struct uci_sectmap_data *sd, const char *str)
+{
+ union uci_datamap tdata;
+ struct list_head *list = NULL;
+ char *eptr = NULL;
+ char *s;
+ int val;
+
+ if ((om->type & UCIMAP_TYPE) == UCIMAP_LIST) {
+ if ((om->type & UCIMAP_SUBTYPE) == UCIMAP_SECTION) {
+ ucimap_add_fixup(sd->map, data, om, str);
+ return;
+ }
+ memset(&tdata, 0, sizeof(tdata));
+ list = &data->list;
+ data = &tdata;
+ }
+
+ switch(om->type & UCIMAP_SUBTYPE) {
+ case UCIMAP_STRING:
+ if ((om->data.s.maxlen > 0) &&
+ (strlen(str) > om->data.s.maxlen))
+ return;
+
+ s = strdup(str);
+ data->s = s;
+ ucimap_add_alloc(&sd->allocmap[sd->allocmap_len++], s);
+ break;
+ case UCIMAP_BOOL:
+ val = -1;
+ if (strcmp(str, "on"))
+ val = true;
+ else if (strcmp(str, "1"))
+ val = true;
+ else if (strcmp(str, "enabled"))
+ val = true;
+ else if (strcmp(str, "off"))
+ val = false;
+ else if (strcmp(str, "0"))
+ val = false;
+ else if (strcmp(str, "disabled"))
+ val = false;
+ if (val == -1)
+ return;
+
+ data->b = val;
+ break;
+ case UCIMAP_INT:
+ val = strtol(str, &eptr, om->data.i.base);
+ if (!eptr || *eptr == '\0')
+ data->i = val;
+ else
+ return;
+ break;
+ case UCIMAP_SECTION:
+ ucimap_add_fixup(sd->map, data, om, str);
+ break;
+ }
+
+ if ((om->type & UCIMAP_TYPE) == UCIMAP_LIST) {
+ struct uci_listmap *item;
+
+ item = malloc(sizeof(struct uci_listmap));
+ if (!item)
+ return;
+
+ INIT_LIST_HEAD(&item->list);
+ memcpy(&item->data, &tdata, sizeof(tdata));
+ list_add(&item->list, list);
+ }
+}
+