]> pilppa.org Git - uci.git/commitdiff
refactor, add uci_import
authorFelix Fietkau <nbd@openwrt.org>
Tue, 22 Jan 2008 22:34:04 +0000 (23:34 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 22 Jan 2008 22:34:04 +0000 (23:34 +0100)
Makefile
file.c [moved from parse.c with 85% similarity]
libuci.c
uci.h

index 1e0fce371d132da92cec2d35ef4d34bf2327c1a8..01063a87e8954769e02816f8def0f426f86531a3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ cli.o: cli.c uci.h
 uci: cli.o libuci.a
        $(CC) $(CFLAGS) -o $@ $^
 
-libuci.o: libuci.c parse.c uci.h list.c err.h
+libuci.o: libuci.c file.c uci.h list.c err.h
 libuci.a: libuci.o
        rm -f $@
        $(AR) rc $@ $^
diff --git a/parse.c b/file.c
similarity index 85%
rename from parse.c
rename to file.c
index 1297b80c75e3cd0348889f9e865fcbaa255b71f5..580ca1881043718348f65c081fabc482c53f20ba 100644 (file)
--- a/parse.c
+++ b/file.c
@@ -241,6 +241,42 @@ static void assert_eol(struct uci_context *ctx, char **str)
        }
 }
 
+/* 
+ * switch to a different config, either triggered by uci_load, or by a
+ * 'package <...>' statement in the import file
+ */
+static void uci_switch_config(struct uci_context *ctx)
+{
+       struct uci_parse_context *pctx;
+       const char *name;
+
+       pctx = ctx->pctx;
+       name = pctx->name;
+
+       /* add the last config to main config file list */
+       if (pctx->cfg) {
+               uci_list_add(&ctx->root, &pctx->cfg->list);
+
+               pctx->cfg = NULL;
+               pctx->section = NULL;
+       }
+
+       if (!name)
+               return;
+
+       /* 
+        * if an older config under the same name exists, unload it
+        * ignore errors here, e.g. if the config was not found
+        */
+       UCI_TRAP_SAVE(ctx, ignore);
+       uci_unload(ctx, name);
+       UCI_TRAP_RESTORE(ctx);
+ignore:
+       ctx->errno = 0;
+
+       pctx->cfg = uci_alloc_config(ctx, name);
+}
+
 /*
  * parse the 'config' uci command (open a section)
  */
@@ -249,6 +285,15 @@ static void uci_parse_config(struct uci_context *ctx, char **str)
        char *name = NULL;
        char *type = NULL;
 
+       if (!ctx->pctx->cfg) {
+               if (!ctx->pctx->name) {
+                       ctx->pctx->byte = *str - ctx->pctx->buf;
+                       ctx->pctx->reason = "attempting to import a file without a package name";
+                       UCI_THROW(ctx, UCI_ERR_PARSE);
+               }
+               uci_switch_config(ctx);
+       }
+
        /* command string null-terminated by strtok */
        *str += strlen(*str) + 1;
 
@@ -300,6 +345,7 @@ error:
        UCI_THROW(ctx, ctx->errno);
 }
 
+
 /*
  * parse a complete input line, split up combined commands by ';'
  */
@@ -333,29 +379,56 @@ static void uci_parse_line(struct uci_context *ctx)
        }
 }
 
-int uci_load(struct uci_context *ctx, const char *name, struct uci_config **cfg)
+int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct uci_config **cfg)
 {
        struct uci_parse_context *pctx;
+
+       /* make sure no memory from previous parse attempts is leaked */
+       uci_parse_cleanup(ctx);
+
+       pctx = (struct uci_parse_context *) uci_malloc(ctx, sizeof(struct uci_parse_context));
+       ctx->pctx = pctx;
+       pctx->file = stream;
+
+       /*
+        * If 'name' was supplied, assume that the supplied stream does not contain
+        * the appropriate 'package <name>' string to specify the config name
+        * NB: the config file can still override the package name
+        */
+       if (name)
+               pctx->name = name;
+
+       while (!feof(pctx->file)) {
+               uci_getln(ctx);
+               if (pctx->buf[0])
+                       uci_parse_line(ctx);
+       }
+
+       if (cfg)
+               *cfg = pctx->cfg;
+
+       pctx->name = NULL;
+       uci_switch_config(ctx);
+
+       /* no error happened, we can get rid of the parser context now */
+       uci_parse_cleanup(ctx);
+
+       return 0;
+}
+
+int uci_load(struct uci_context *ctx, const char *name, struct uci_config **cfg)
+{
        struct stat statbuf;
        char *filename;
        bool confpath;
+       FILE *file;
 
        UCI_HANDLE_ERR(ctx);
        UCI_ASSERT(ctx, name != NULL);
 
-       UCI_TRAP_SAVE(ctx, ignore);
-       uci_unload(ctx, name);
-       UCI_TRAP_RESTORE(ctx);
-
 ignore:
        ctx->errno = 0;
 
-       /* make sure no memory from previous parse attempts is leaked */
-       uci_parse_cleanup(ctx);
-
-       pctx = (struct uci_parse_context *) uci_malloc(ctx, sizeof(struct uci_parse_context));
-       ctx->pctx = pctx;
-
        switch (name[0]) {
        case '.':
        case '/':
@@ -375,31 +448,13 @@ ignore:
                UCI_THROW(ctx, UCI_ERR_NOTFOUND);
        }
 
-       pctx->file = fopen(filename, "r");
+       file = fopen(filename, "r");
        if (filename != name)
                free(filename);
 
-       if (!pctx->file)
+       if (!file)
                UCI_THROW(ctx, UCI_ERR_IO);
 
-       pctx->cfg = uci_alloc_config(ctx, name);
-
-       while (!feof(pctx->file)) {
-               uci_getln(ctx);
-               if (pctx->buf[0])
-                       uci_parse_line(ctx);
-       }
-
-       /* add to main config file list */
-       uci_list_add(&ctx->root, &pctx->cfg->list);
-       if (cfg)
-               *cfg = pctx->cfg;
-
-       pctx->cfg = NULL;
-
-       /* no error happened, we can get rid of the parser context now */
-       uci_parse_cleanup(ctx);
-
-       return 0;
+       return uci_import(ctx, file, name, cfg);
 }
 
index ada75c04cb2aef36e325d1b3aab86140f95dd4dc..4a06d7143adf0c989224ebf5e5d4b42c9bccd7a3 100644 (file)
--- a/libuci.c
+++ b/libuci.c
@@ -79,7 +79,7 @@ static char *uci_strdup(struct uci_context *ctx, const char *str)
 }
 
 #include "list.c"
-#include "parse.c"
+#include "file.c"
 
 /* externally visible functions */
 
diff --git a/uci.h b/uci.h
index c5594d8c1aebe4f9b2e9868054c743f807b99232..7cd7eb9fe6256398a9776cc301ec434e740d57d2 100644 (file)
--- a/uci.h
+++ b/uci.h
@@ -61,6 +61,17 @@ extern void uci_free(struct uci_context *ctx);
  */
 extern void uci_perror(struct uci_context *ctx, const char *str);
 
+/**
+ * uci_import: Import uci config data from a stream
+ * @ctx: uci context
+ * @stream: file stream to import from
+ * @name: (optional) assume the config has the given name
+ * @cfg: (optional) store the last parsed config package in this variable
+ *
+ * the name parameter is for config files that don't explicitly use the 'package <...>' keyword
+ */
+extern int uci_import(struct uci_context *ctx, FILE *stream, const char *name, struct uci_config **cfg);
+
 /**
  * uci_load: Parse an uci config file and store it in the uci context
  *
@@ -107,6 +118,7 @@ struct uci_context
 
 struct uci_parse_context
 {
+       const char *reason;
        int line;
        int byte;
 
@@ -114,8 +126,8 @@ struct uci_parse_context
        struct uci_config *cfg;
        struct uci_section *section;
        FILE *file;
+       const char *name;
        char *buf;
-       char *reason;
        int bufsz;
 };