X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=parse.c;h=3a8a2ca5fb1305f59de449cdfbe85fd2720bc25d;hp=b6ee73426f7321b716c1a040449b52cdda612e62;hb=cc84250572b1c506a5fb7be2dd783de916fddc42;hpb=d5b661a39ea9320c58f44cb4b32691deffc7cb30 diff --git a/parse.c b/parse.c index b6ee734..3a8a2ca 100644 --- a/parse.c +++ b/parse.c @@ -80,12 +80,19 @@ static void uci_parse_cleanup(struct uci_context *ctx) free(pctx); } +/* + * move the string pointer forward until a non-whitespace character or + * EOL is reached + */ static void skip_whitespace(char **str) { while (**str && isspace(**str)) *str += 1; } +/* + * parse a double quoted string argument from the command line + */ static char *parse_double_quote(char **str) { char *val; @@ -112,12 +119,18 @@ static char *parse_double_quote(char **str) return NULL; } +/* + * parse a single quoted string argument from the command line + */ static char *parse_single_quote(char **str) { /* TODO: implement */ return NULL; } +/* + * extract the next word from the command line (unquoted argument) + */ static char *parse_unquoted(char **str) { char *val; @@ -126,28 +139,60 @@ static char *parse_unquoted(char **str) while (**str && !isspace(**str)) *str += 1; - **str = 0; - *str += 1; + + if (**str) { + **str = 0; + *str += 1; + } return val; } -static char *next_arg(char **str) +/* + * extract the next argument from the command line + */ +static char *next_arg(struct uci_context *ctx, char **str, bool required) { + char *val; skip_whitespace(str); switch (**str) { case '"': - return parse_double_quote(str); + val = parse_double_quote(str); case '\'': - return parse_single_quote(str); + val = parse_single_quote(str); case 0: - return NULL; + val = NULL; default: - return parse_unquoted(str); + val = parse_unquoted(str); + } + + if (required && !val) { + ctx->pctx->byte = *str - ctx->pctx->buf; + UCI_THROW(ctx, UCI_ERR_PARSE); + } + + return val; +} + +/* + * verify that the end of the line or command is reached. + * throw an error if extra arguments are given on the command line + */ +static void assert_eol(struct uci_context *ctx, char **str) +{ + char *tmp; + + tmp = next_arg(ctx, str, false); + if (tmp) { + ctx->pctx->byte = tmp - ctx->pctx->buf; + UCI_THROW(ctx, UCI_ERR_PARSE); } } +/* + * parse the 'config' uci command (open a section) + */ static void uci_parse_config(struct uci_context *ctx, char **str) { char *type, *name; @@ -159,37 +204,32 @@ static void uci_parse_config(struct uci_context *ctx, char **str) UCI_THROW(ctx, UCI_ERR_PARSE); } - type = next_arg(str); - if (!type) { - ctx->pctx->byte = *str - ctx->pctx->buf; - UCI_THROW(ctx, UCI_ERR_PARSE); - } - - name = next_arg(str); + type = next_arg(ctx, str, true); + name = next_arg(ctx, str, false); + assert_eol(ctx, str); + DPRINTF("Section<%s>: %s\n", type, name); } +/* + * parse the 'option' uci command (open a value) + */ static void uci_parse_option(struct uci_context *ctx, char **str) { char *name, *value; *str += strlen(*str) + 1; - name = next_arg(str); - if (!name) { - ctx->pctx->byte = *str - ctx->pctx->buf; - UCI_THROW(ctx, UCI_ERR_PARSE); - } - - value = next_arg(str); - if (!value) { - ctx->pctx->byte = *str - ctx->pctx->buf; - UCI_THROW(ctx, UCI_ERR_PARSE); - } + name = next_arg(ctx, str, true); + value = next_arg(ctx, str, true); + assert_eol(ctx, str); DPRINTF("\tOption: %s=\"%s\"\n", name, value); } +/* + * parse a complete input line, split up combined commands by ';' + */ static void uci_parse_line(struct uci_context *ctx) { struct uci_parse_context *pctx = ctx->pctx;