X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=file.c;h=c670f0449e3fddd29531730586ea8efe9b2d37bd;hp=19c6b07d6eb04b58e546b672fc6c9c119fdf5ef6;hb=563f8dd6f0eb56780a00f5856bf7fcf40e39d845;hpb=8a06b55c63b13123ffcec33aff7f1fd752786dd1 diff --git a/file.c b/file.c index 19c6b07..c670f04 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,33 @@ 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; + struct uci_ptr ptr; + 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); + + UCI_NESTED(uci_fill_ptr, ctx, &ptr, &pctx->section->e, false); + ptr.option = name; + ptr.value = value; + + UCI_INTERNAL(uci_lookup_ptr, ctx, &ptr, NULL, false); + + ctx->internal = !pctx->merge; + UCI_NESTED(uci_add_list, ctx, &ptr); +} + /* * parse a complete input line, split up combined commands by ';' @@ -186,19 +214,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 +297,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 +309,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");