X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=file.c;h=d5512084c1445399a26880bab28cbe329b6ab56d;hp=19c6b07d6eb04b58e546b672fc6c9c119fdf5ef6;hb=87e893157980abef163575ad7aedbcc96c41b0c6;hpb=8a06b55c63b13123ffcec33aff7f1fd752786dd1 diff --git a/file.c b/file.c index 19c6b07..d551208 100644 --- a/file.c +++ b/file.c @@ -24,6 +24,7 @@ #include #include #include +#include static struct uci_backend uci_file_backend; @@ -163,6 +164,45 @@ error: uci_alloc_option(pctx->section, name, value); } +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); + } +} + /* * parse a complete input line, split up combined commands by ';' @@ -186,19 +226,33 @@ static void uci_parse_line(struct uci_context *ctx, bool single) case 'p': if ((word[1] == 0) || !strcmp(word + 1, "ackage")) uci_parse_package(ctx, &word, single); + else + goto invalid; break; case 'c': if ((word[1] == 0) || !strcmp(word + 1, "onfig")) uci_parse_config(ctx, &word); + else + goto invalid; break; case 'o': if ((word[1] == 0) || !strcmp(word + 1, "ption")) uci_parse_option(ctx, &word); + else + goto invalid; break; - default: - uci_parse_error(ctx, word, "unterminated command"); + case 'l': + if ((word[1] == 0) || !strcmp(word + 1, "ist")) + uci_parse_list(ctx, &word); + else + goto invalid; break; + default: + goto invalid; } + continue; +invalid: + uci_parse_error(ctx, word, "invalid command"); } while (1); } @@ -255,7 +309,7 @@ static char *uci_escape(struct uci_context *ctx, const char *str) static void uci_export_package(struct uci_package *p, FILE *stream, bool header) { struct uci_context *ctx = p->ctx; - struct uci_element *s, *o; + struct uci_element *s, *o, *i; if (header) fprintf(stream, "package '%s'\n", uci_escape(ctx, p->e.name)); @@ -267,8 +321,21 @@ static void uci_export_package(struct uci_package *p, FILE *stream, bool header) fprintf(stream, "\n"); uci_foreach_element(&sec->options, o) { struct uci_option *opt = uci_to_option(o); - fprintf(stream, "\toption '%s'", uci_escape(ctx, opt->e.name)); - fprintf(stream, " '%s'\n", uci_escape(ctx, opt->value)); + switch(opt->type) { + case UCI_TYPE_STRING: + fprintf(stream, "\toption '%s'", uci_escape(ctx, opt->e.name)); + fprintf(stream, " '%s'\n", uci_escape(ctx, opt->v.string)); + break; + case UCI_TYPE_LIST: + uci_foreach_element(&opt->v.list, i) { + fprintf(stream, "\tlist '%s'", uci_escape(ctx, opt->e.name)); + fprintf(stream, " '%s'\n", uci_escape(ctx, i->name)); + } + break; + default: + fprintf(stream, "\t# unknown type for option '%s'\n", uci_escape(ctx, opt->e.name)); + break; + } } } fprintf(stream, "\n");