+static void uci_parse_list(struct uci_context *ctx, char **str)
+{
+ struct uci_parse_context *pctx = ctx->pctx;
+ char *name = NULL;
+ char *value = NULL;
+
+ if (!pctx->section)
+ uci_parse_error(ctx, *str, "list command found before the first section");
+
+ /* command string null-terminated by strtok */
+ *str += strlen(*str) + 1;
+
+ name = next_arg(ctx, str, true, true);
+ 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);
+ }
+}
+