]> mj.ucw.cz Git - libucw.git/commitdiff
Conf: Split off everything related to cf_getopt()
authorMartin Mares <mj@ucw.cz>
Sat, 28 Apr 2012 22:00:00 +0000 (00:00 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 29 Apr 2012 11:57:30 +0000 (13:57 +0200)
<ucw/getopt.h> now contains only cf_getopt() and related settings.
All high-level configuration functions have been moved to <ucw/conf.h>.

ucw/Makefile
ucw/conf-getopt.c [new file with mode: 0644]
ucw/conf-input.c
ucw/conf-internal.h
ucw/conf-intr.c
ucw/conf.h
ucw/getopt.h

index 62373ade03e4200dc60f9e1f4962ae79c7283f72..af6219bf7af434cd3a99c72b7cf5a1834902a75b 100644 (file)
@@ -13,7 +13,7 @@ LIBUCW_MODS= \
        partmap hashfunc \
        slists simple-lists bitsig \
        log log-stream log-file log-syslog log-conf tbf \
-       conf-context conf-alloc conf-dump conf-input conf-intr conf-journal conf-parse conf-section \
+       conf-context conf-alloc conf-dump conf-input conf-intr conf-journal conf-parse conf-section conf-getopt \
        ipaccess \
        fastbuf ff-binary ff-string ff-printf ff-unicode ff-stkstring \
        fb-file fb-mem fb-temp tempfile fb-mmap fb-limfd fb-buffer fb-grow fb-pool fb-atomic fb-param fb-socket \
diff --git a/ucw/conf-getopt.c b/ucw/conf-getopt.c
new file mode 100644 (file)
index 0000000..507c510
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *     UCW Library -- Configuration files: getopt wrapper
+ *
+ *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
+ *     (c) 2003--2012 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/conf.h>
+#include <ucw/conf-internal.h>
+#include <ucw/getopt.h>
+#include <ucw/fastbuf.h>
+
+#include <stdlib.h>
+
+#ifndef CONFIG_UCW_DEFAULT_CONFIG
+#define CONFIG_UCW_DEFAULT_CONFIG NULL
+#endif
+char *cf_def_file = CONFIG_UCW_DEFAULT_CONFIG;
+
+#ifndef CONFIG_UCW_ENV_VAR_CONFIG
+#define CONFIG_UCW_ENV_VAR_CONFIG NULL
+#endif
+char *cf_env_file = CONFIG_UCW_ENV_VAR_CONFIG;
+
+static void
+load_default(struct cf_context *cc)
+{
+  if (cc->config_loaded++)
+    return;
+  if (cf_def_file)
+    {
+      char *env;
+      if (cf_env_file && (env = getenv(cf_env_file)))
+        {
+         if (cf_load(env))
+           die("Cannot load config file %s", env);
+       }
+      else if (cf_load(cf_def_file))
+        die("Cannot load default config %s", cf_def_file);
+    }
+  else
+    {
+      // We need to create an empty pool and initialize all configuration items
+      struct cf_journal_item *oldj = cf_journal_new_transaction(1);
+      cf_init_stack(cc);
+      cf_done_stack(cc);
+      cf_journal_commit_transaction(1, oldj);
+    }
+}
+
+static void
+final_commit(struct cf_context *cc)
+{
+  if (cc->postpone_commit)
+    {
+      cc->postpone_commit = 0;
+      if (cf_done_stack(cc))
+       die("Cannot commit after the initialization");
+    }
+}
+
+int
+cf_getopt(int argc, char *const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
+{
+  struct cf_context *cc = cf_get_context();
+  cc->postpone_commit = 1;
+
+  while (1)
+    {
+      int res = getopt_long(argc, argv, short_opts, long_opts, long_index);
+      if (res == 'S' || res == 'C' || res == 0x64436667)
+       {
+         if (cc->other_options)
+           die("The -S and -C options must precede all other arguments");
+         if (res == 'S')
+           {
+             load_default(cc);
+             if (cf_set(optarg))
+               die("Cannot set %s", optarg);
+           }
+         else if (res == 'C')
+           {
+             if (cf_load(optarg))
+               die("Cannot load config file %s", optarg);
+           }
+#ifdef CONFIG_UCW_DEBUG
+         else
+           {                   /* --dumpconfig */
+             load_default(cc);
+             final_commit(cc);
+             struct fastbuf *b = bfdopen(1, 4096);
+             cf_dump_sections(b);
+             bclose(b);
+             exit(0);
+           }
+#endif
+       }
+      else
+       {
+         /* unhandled option or end of options */
+         if (res != ':' && res != '?')
+           {
+             load_default(cc);
+             final_commit(cc);
+           }
+         cc->other_options++;
+         return res;
+       }
+    }
+}
index f8ed1ff092def0014d415db32c67435ab8cb1386..5a782bf0d638fce13882b31b9eaa5e917b629cb1 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <ucw/lib.h>
 #include <ucw/conf.h>
-#include <ucw/getopt.h>
 #include <ucw/conf-internal.h>
 #include <ucw/clists.h>
 #include <ucw/mempool.h>
@@ -292,18 +291,6 @@ error:
   return "included from here";
 }
 
-static int
-done_stack(struct cf_context *cc)
-{
-  if (cf_check_stack(cc))
-    return 1;
-  if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL))
-    return 1;
-  if (!cc->postpone_commit)
-    cc->everything_committed = 1;
-  return 0;
-}
-
 static int
 load_file(struct cf_context *cc, const char *file)
 {
@@ -315,7 +302,7 @@ load_file(struct cf_context *cc, const char *file)
   }
   char *err_msg = parse_fastbuf(cc, file, fb, 0);
   bclose(fb);
-  return !!err_msg || done_stack(cc);
+  return !!err_msg || cf_done_stack(cc);
 }
 
 static int
@@ -325,7 +312,7 @@ load_string(struct cf_context *cc, const char *string)
   struct fastbuf fb;
   fbbuf_init_read(&fb, (byte *)string, strlen(string), 0);
   char *msg = parse_fastbuf(cc, NULL, &fb, 0);
-  return !!msg || done_stack(cc);
+  return !!msg || cf_done_stack(cc);
 }
 
 /* Safe loading and reloading */
@@ -381,7 +368,7 @@ cf_reload(const char *file)
 
   cc->postpone_commit = 0;
   if (!err)
-    err |= done_stack(cc);
+    err |= cf_done_stack(cc);
 
   if (!err) {
     cf_journal_delete();
@@ -404,7 +391,7 @@ cf_load(const char *file)
   if (!err) {
     cf_journal_commit_transaction(1, oldj);
     cf_remember_entry(cc, CE_FILE, file);
-    cc->def_loaded = 1;
+    cc->config_loaded = 1;
   } else
     cf_journal_rollback_transaction(1, oldj);
   return err;
@@ -423,93 +410,3 @@ cf_set(const char *string)
     cf_journal_rollback_transaction(0, oldj);
   return err;
 }
-
-/* Command-line parser */
-
-#ifndef CONFIG_UCW_DEFAULT_CONFIG
-#define CONFIG_UCW_DEFAULT_CONFIG NULL
-#endif
-char *cf_def_file = CONFIG_UCW_DEFAULT_CONFIG;
-
-#ifndef CONFIG_UCW_ENV_VAR_CONFIG
-#define CONFIG_UCW_ENV_VAR_CONFIG NULL
-#endif
-char *cf_env_file = CONFIG_UCW_ENV_VAR_CONFIG;
-
-static void
-load_default(struct cf_context *cc)
-{
-  if (cc->def_loaded++)
-    return;
-  if (cf_def_file)
-    {
-      char *env;
-      if (cf_env_file && (env = getenv(cf_env_file)))
-        {
-         if (cf_load(env))
-           die("Cannot load config file %s", env);
-       }
-      else if (cf_load(cf_def_file))
-        die("Cannot load default config %s", cf_def_file);
-    }
-  else
-    {
-      // We need to create an empty pool and initialize all configuration items
-      struct cf_journal_item *oldj = cf_journal_new_transaction(1);
-      cf_init_stack(cc);
-      done_stack(cc);
-      cf_journal_commit_transaction(1, oldj);
-    }
-}
-
-static void
-final_commit(struct cf_context *cc)
-{
-  if (cc->postpone_commit) {
-    cc->postpone_commit = 0;
-    if (done_stack(cc))
-      die("Cannot commit after the initialization");
-  }
-}
-
-int
-cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
-{
-  struct cf_context *cc = cf_get_context();
-  cc->postpone_commit = 1;
-
-  while (1) {
-    int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
-    if (res == 'S' || res == 'C' || res == 0x64436667)
-    {
-      if (cc->other_options)
-       die("The -S and -C options must precede all other arguments");
-      if (res == 'S') {
-       load_default(cc);
-       if (cf_set(optarg))
-         die("Cannot set %s", optarg);
-      } else if (res == 'C') {
-       if (cf_load(optarg))
-         die("Cannot load config file %s", optarg);
-      }
-#ifdef CONFIG_UCW_DEBUG
-      else {   /* --dumpconfig */
-       load_default(cc);
-       final_commit(cc);
-       struct fastbuf *b = bfdopen(1, 4096);
-       cf_dump_sections(b);
-       bclose(b);
-       exit(0);
-      }
-#endif
-    } else {
-      /* unhandled option or end of options */
-      if (res != ':' && res != '?') {
-       load_default(cc);
-       final_commit(cc);
-      }
-      cc->other_options++;
-      return res;
-    }
-  }
-}
index bab5383740ec4f7f01d493532ec677007669e744..ee6d08d4d80c35a0b7ffbaae664094574f6a86ba 100644 (file)
@@ -42,7 +42,7 @@ struct dirty_section {
 struct cf_context {
   struct mempool *pool;
   int is_active;
-  int def_loaded;
+  int config_loaded;                   // at least one config file was loaded
   struct cf_parser_state *parser;
   uns everything_committed;            // after the 1st load, this flag is set on
   uns postpone_commit;                 // used internally by cf_getopt()
@@ -85,7 +85,7 @@ extern char *cf_type_names[];
 uns cf_type_size(enum cf_type type, struct cf_user_type *utype);
 char *cf_interpret_line(struct cf_context *cc, char *name, enum cf_operation op, int number, char **pars);
 void cf_init_stack(struct cf_context *cc);
-int cf_check_stack(struct cf_context *cc);
+int cf_done_stack(struct cf_context *cc);
 
 /* conf-journal.c */
 void cf_journal_swap(void);
index f42265102593beda40bd62136f0983cd3c831784..0b5d5407397ac95d2e37cddeb5bdd533f940e780 100644 (file)
@@ -652,11 +652,15 @@ cf_init_stack(struct cf_context *cc)
 }
 
 int
-cf_check_stack(struct cf_context *cc)
+cf_done_stack(struct cf_context *cc)
 {
   if (cc->stack_level > 0) {
     msg(L_ERROR, "Unterminated block");
     return 1;
   }
+  if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL))
+    return 1;
+  if (!cc->postpone_commit)
+    cc->everything_committed = 1;
   return 0;
 }
index 07d83e7b479db72b27c225eef6cb69ec5fa13a4f..bef4553e155a5477cb1abb664d27c1da62785be1 100644 (file)
@@ -49,6 +49,22 @@ void cf_free_context(struct cf_context *cc);
  **/
 struct cf_context *cf_switch_context(struct cf_context *cc);
 
+/***
+ * [[conf_load]]
+ * Safe configuration loading
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * These functions can be used to to safely load or reload configuration.
+ */
+
+int cf_reload(const char *file);       /** Reload configuration from @file, replace the old one. **/
+int cf_load(const char *file);         /** Load configuration from @file. If @file is NULL, reload all loaded configuration files. **/
+/**
+ * Parse some part of configuration passed in @string.
+ * The syntax is the same as in the <<config:,configuration file>>.
+ **/
+int cf_set(const char *string);
+
 /*** === Data types [[conf_types]] ***/
 
 enum cf_class {                                /** Class of the configuration item. **/
@@ -364,7 +380,11 @@ char *cf_printf(const char *fmt, ...) FORMAT_CHECK(printf,1,2); /** printf() int
  * Undo journal
  * ~~~~~~~~~~~~
  *
- * For error recovery when <<reload,reloading configuration>>.
+ * The configuration system uses journaling to safely reload
+ * configuration. It begins a transaction and tries to load the
+ * configuration. If it fails, it restores the original state.
+ *
+ * The behaviour of journal is described in <<reload,reloading configuration>>.
  ***/
 /**
  * By default, the configuration mechanism remembers all changes in a journal,
@@ -382,6 +402,31 @@ void cf_set_journalling(int enable);
 void cf_journal_block(void *ptr, uns len);
 #define CF_JOURNAL_VAR(var) cf_journal_block(&(var), sizeof(var))      // Store single value into journal.
 
+struct cf_journal_item;                /** Opaque identifier of the journal state. **/
+/**
+ * Starts a new transaction. It returns the current state so you can
+ * get back to it. The @new_pool parameter tells if a new memory pool
+ * should be created and used from now.
+ **/
+struct cf_journal_item *cf_journal_new_transaction(uns new_pool);
+/**
+ * Marks current state as a complete transaction. The @new_pool
+ * parameter tells if the transaction was created with new memory pool
+ * (the parameter must be the same as the one with
+ * @cf_journal_new_transaction() was called with). The @oldj parameter
+ * is the journal state returned from last
+ * @cf_journal_new_transaction() call.
+ **/
+void cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj);
+/**
+ * Returns to an old journal state, reverting anything the current
+ * transaction did. The @new_pool parameter must be the same as the
+ * one you used when you created the transaction. The @oldj parameter
+ * is the journal state you got from @cf_journal_new_transaction() --
+ * it is the state to return to.
+ **/
+void cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj);
+
 /***
  * [[declare]]
  * Section declaration
@@ -421,4 +466,55 @@ char *cf_parse_u64(const char *str, u64 *ptr);             /** Parser for 64 unsigned integ
 char *cf_parse_double(const char *str, double *ptr);   /** Parser for doubles. **/
 char *cf_parse_ip(const char *p, u32 *varp);           /** Parser for IP addresses. **/
 
+/***
+ * [[conf_direct]]
+ * Direct access
+ * ~~~~~~~~~~~~~
+ *
+ * Direct access to configuration items.
+ * You probably should not need this.
+ ***/
+
+/**
+ * List of operations used on items.
+ * This macro is used to generate internal source code,
+ * but you may be interested in the list of operations it creates.
+ *
+ * Each operation corresponds to the same-named operation
+ * described in <<config:operations,configuration syntax>>.
+ **/
+#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(ALL) \
+  T(APPEND) T(PREPEND) T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(COPY) T(RESET)
+  /* Closing brace finishes previous block.
+   * Basic attributes (static, dynamic, parsed) can be used with SET.
+   * Dynamic arrays can be used with SET, APPEND, PREPEND.
+   * Sections can be used with SET.
+   * Lists can be used with everything. */
+#define T(x) OP_##x,
+enum cf_operation { CF_OPERATIONS };   /** Allowed operations on items. See <<def_CF_OPERATIONS,`CF_OPERATIONS`>> for list (they have an `OP_` prefix -- it means you use `OP_SET` instead of just `SET`). **/
+#undef T
+
+/**
+ * Searches for a configuration item called @name.
+ * If it is found, it is copied into @item and NULL is returned.
+ * Otherwise, an error is returned and @item is zeroed.
+ **/
+char *cf_find_item(const char *name, struct cf_item *item);
+/**
+ * Performs a single operation on a given item.
+ **/
+char *cf_modify_item(struct cf_item *item, enum cf_operation op, int number, char **pars);
+
+/***
+ * [[conf_dump]]
+ * Debug dumping
+ * ~~~~~~~~~~~~~
+ ***/
+
+struct fastbuf;
+/**
+ * Take everything and write it into @fb.
+ **/
+void cf_dump_sections(struct fastbuf *fb);
+
 #endif
index 6263d47fb6df6acd8e19968216cab5cd9614efbf..68d106335cb45edac2dc990ca45599251a1b5e58 100644 (file)
@@ -2,7 +2,7 @@
  *     UCW Library -- Parsing of configuration and command-line options
  *
  *     (c) 2001--2006 Robert Spalek <robert@ucw.cz>
- *     (c) 2003--2006 Martin Mares <mj@ucw.cz>
+ *     (c) 2003--2012 Martin Mares <mj@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
 #include <getopt.h>
 #endif
 
-void reset_getopt(void);       /** If you want to start parsing of the arguments from the first one again. **/
-
 /***
- * [[conf_load]]
- * Safe configuration loading
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * These functions can be used to to safely load or reload configuration.
- */
+ * [[conf_getopt]]
+ * Loading by @cf_getopt()
+ * ~~~~~~~~~~~~~~~~~~~~~~~
+ ***/
 
 /**
  * The default config (as set by `CONFIG_UCW_DEFAULT_CONFIG`) or NULL if already loaded.
@@ -37,109 +33,6 @@ extern char *cf_def_file;
  * Defaults to `CONFIG_UCW_ENV_VAR_CONFIG`.
  **/
 extern char *cf_env_file;
-int cf_reload(const char *file);       /** Reload configuration from @file, replace the old one. **/
-int cf_load(const char *file);         /** Load configuration from @file. If @file is NULL, reload all loaded configuration files. **/
-/**
- * Parse some part of configuration passed in @string.
- * The syntax is the same as in the <<config:,configuration file>>.
- **/
-int cf_set(const char *string);
-
-/***
- * [[conf_direct]]
- * Direct access
- * ~~~~~~~~~~~~~
- *
- * Direct access to configuration items.
- * You probably should not need this.
- ***/
-
-/**
- * List of operations used on items.
- * This macro is used to generate internal source code,
- * but you may be interested in the list of operations it creates.
- *
- * Each operation corresponds to the same-named operation
- * described in <<config:operations,configuration syntax>>.
- **/
-#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(ALL) \
-  T(APPEND) T(PREPEND) T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(COPY) T(RESET)
-  /* Closing brace finishes previous block.
-   * Basic attributes (static, dynamic, parsed) can be used with SET.
-   * Dynamic arrays can be used with SET, APPEND, PREPEND.
-   * Sections can be used with SET.
-   * Lists can be used with everything. */
-#define T(x) OP_##x,
-enum cf_operation { CF_OPERATIONS };   /** Allowed operations on items. See <<def_CF_OPERATIONS,`CF_OPERATIONS`>> for list (they have an `OP_` prefix -- it means you use `OP_SET` instead of just `SET`). **/
-#undef T
-
-struct cf_item;
-/**
- * Searches for a configuration item called @name.
- * If it is found, it is copied into @item and NULL is returned.
- * Otherwise, an error is returned and @item is zeroed.
- **/
-char *cf_find_item(const char *name, struct cf_item *item);
-/**
- * Performs a single operation on a given item.
- **/
-char *cf_modify_item(struct cf_item *item, enum cf_operation op, int number, char **pars);
-
-/***
- * [[conf_dump]]
- * Debug dumping
- * ~~~~~~~~~~~~~
- ***/
-
-struct fastbuf;
-/**
- * Take everything and write it into @fb.
- **/
-void cf_dump_sections(struct fastbuf *fb);
-
-/***
- * [[conf_journal]]
- * Journaling control
- * ~~~~~~~~~~~~~~~~~~
- *
- * The configuration system uses journaling to safely reload
- * configuration. It begins a transaction and tries to load the
- * configuration. If it fails, it restores the original state.
- *
- * The behaviour of journal is described in <<reload,reloading configuration>>.
- ***/
-
-struct cf_journal_item;                /** Opaque identifier of the journal state. **/
-/**
- * Starts a new transaction. It returns the current state so you can
- * get back to it. The @new_pool parameter tells if a new memory pool
- * should be created and used from now.
- **/
-struct cf_journal_item *cf_journal_new_transaction(uns new_pool);
-/**
- * Marks current state as a complete transaction. The @new_pool
- * parameter tells if the transaction was created with new memory pool
- * (the parameter must be the same as the one with
- * @cf_journal_new_transaction() was called with). The @oldj parameter
- * is the journal state returned from last
- * @cf_journal_new_transaction() call.
- **/
-void cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj);
-/**
- * Returns to an old journal state, reverting anything the current
- * transaction did. The @new_pool parameter must be the same as the
- * one you used when you created the transaction. The @oldj parameter
- * is the journal state you got from @cf_journal_new_transaction() --
- * it is the state to return to.
- **/
-void cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj);
-
-/***
- * [[conf_getopt]]
- * Loading by @cf_getopt()
- * ~~~~~~~~~~~~~~~~~~~~~~~
- ***/
-
 /**
  * Short options for loading configuration by @cf_getopt().
  * Prepend to your own options.
@@ -189,4 +82,6 @@ void cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj)
  **/
 int cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index);
 
+void reset_getopt(void);       /** If you want to start parsing of the arguments from the first one again. **/
+
 #endif