-/*
- * Clean up all extra memory used by the parser and exporter
- */
-static void uci_file_cleanup(struct uci_context *ctx)
-{
- struct uci_parse_context *pctx;
-
- if (ctx->buf) {
- free(ctx->buf);
- ctx->buf = NULL;
- ctx->bufsz = 0;
- }
-
- pctx = ctx->pctx;
- if (!pctx)
- return;
-
- ctx->pctx = NULL;
- if (pctx->package)
- uci_free_package(&pctx->package);
-
- if (pctx->buf)
- free(pctx->buf);
-
- free(pctx);
-}
-
-
-/*
- * parse a character escaped by '\'
- * returns true if the escaped character is to be parsed
- * returns false if the escaped character is to be ignored
- */
-static inline bool parse_backslash(struct uci_context *ctx, char **str)
-{
- /* skip backslash */
- *str += 1;
-
- /* undecoded backslash at the end of line, fetch the next line */
- if (!**str) {
- *str += 1;
- uci_getln(ctx, *str - ctx->pctx->buf);
- return false;
- }
-
- /* FIXME: decode escaped char, necessary? */
- return true;
-}
-
-/*
- * move the string pointer forward until a non-whitespace character or
- * EOL is reached
- */
-static void skip_whitespace(struct uci_context *ctx, char **str)
-{
-restart:
- while (**str && isspace(**str))
- *str += 1;
-
- if (**str == '\\') {
- if (!parse_backslash(ctx, str))
- goto restart;
- }
-}
-
-static inline void addc(char **dest, char **src)
-{
- **dest = **src;
- *dest += 1;
- *src += 1;
-}
-
-/*
- * parse a double quoted string argument from the command line
- */
-static void parse_double_quote(struct uci_context *ctx, char **str, char **target)
-{
- char c;
-
- /* skip quote character */
- *str += 1;
-
- while ((c = **str)) {
- switch(c) {
- case '"':
- **target = 0;
- *str += 1;
- return;
- case '\\':
- if (!parse_backslash(ctx, str))
- continue;
- /* fall through */
- default:
- addc(target, str);
- break;
- }
- }
- uci_parse_error(ctx, *str, "unterminated \"");
-}
-
-/*
- * parse a single quoted string argument from the command line
- */
-static void parse_single_quote(struct uci_context *ctx, char **str, char **target)
-{
- char c;
- /* skip quote character */
- *str += 1;
-
- while ((c = **str)) {
- switch(c) {
- case '\'':
- **target = 0;
- *str += 1;
- return;
- default:
- addc(target, str);
- }
- }
- uci_parse_error(ctx, *str, "unterminated '");
-}
-
-/*
- * parse a string from the command line and detect the quoting style
- */
-static void parse_str(struct uci_context *ctx, char **str, char **target)
-{
- do {
- switch(**str) {
- case '\'':
- parse_single_quote(ctx, str, target);
- break;
- case '"':
- parse_double_quote(ctx, str, target);
- break;
- case '#':
- **str = 0;
- /* fall through */
- case 0:
- goto done;
- case '\\':
- if (!parse_backslash(ctx, str))
- continue;
- /* fall through */
- default:
- addc(target, str);
- break;
- }
- } while (**str && !isspace(**str));
-done:
-
- /*
- * if the string was unquoted and we've stopped at a whitespace
- * character, skip to the next one, because the whitespace will
- * be overwritten by a null byte here
- */
- if (**str)
- *str += 1;
-
- /* terminate the parsed string */
- **target = 0;
-}
-
-/*
- * extract the next argument from the command line
- */
-static char *next_arg(struct uci_context *ctx, char **str, bool required, bool name)
-{
- char *val;
- char *ptr;
-
- val = ptr = *str;
- skip_whitespace(ctx, str);
- parse_str(ctx, str, &ptr);
- if (!*val) {
- if (required)
- uci_parse_error(ctx, *str, "insufficient arguments");
- goto done;
- }
-
- if (name && !uci_validate_name(val))
- uci_parse_error(ctx, val, "invalid character in field");
-
-done:
- return val;
-}