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;
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;
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;
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;