aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2019-10-26 17:46:16 -0400
committerNick Mathewson <nickm@torproject.org>2019-11-07 07:28:43 -0500
commit19cac400d9cf7dcc274c583bb3e942b2682c3663 (patch)
tree1737611f3262a3a1f759a0fe3a3afb250e4455ef
parent4541a590192a97d56c7a303492a2bc1bbeacb441 (diff)
downloadtor-19cac400d9cf7dcc274c583bb3e942b2682c3663.tar.gz
tor-19cac400d9cf7dcc274c583bb3e942b2682c3663.zip
Macros for declaring configuration structs and variable-tables
In our old design, we had to declare configuration structures (like or_options_t) and variable tables (like option_vars_) separately, and we used some magic to enforce their consistency (see conftesting.h). With this design, we write a single definition for the configuration object and its fields, and use C macros to expand it either into a structure, or a variable table. Since they are both made from the same source, they can't become inconsistent. The two designs can coexist happily, and we can migrate from one to the other at our convenience.
-rw-r--r--src/feature/nodelist/routerset.h1
-rw-r--r--src/lib/conf/confdecl.h166
-rw-r--r--src/lib/conf/include.am1
3 files changed, 168 insertions, 0 deletions
diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h
index dc6ce0b667..6bd97f9422 100644
--- a/src/feature/nodelist/routerset.h
+++ b/src/feature/nodelist/routerset.h
@@ -46,6 +46,7 @@ int routerset_len(const routerset_t *set);
struct var_type_def_t;
extern const struct var_type_def_t ROUTERSET_type_defn;
+typedef routerset_t config_decl_ROUTERSET;
#ifdef ROUTERSET_PRIVATE
#include "lib/container/bitarray.h"
diff --git a/src/lib/conf/confdecl.h b/src/lib/conf/confdecl.h
new file mode 100644
index 0000000000..22812f046e
--- /dev/null
+++ b/src/lib/conf/confdecl.h
@@ -0,0 +1,166 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file confdecl.h
+ * @brief Macros for generating a configuration struct from a list
+ * of its individual fields.
+ *
+ * This header defines three important macros: BEGIN_CONF_STRUCT(),
+ * END_CONF_STRUCT(), and CONF_VAR(). They're meant to be used together to
+ * define a configuration structure and the means for encoding and decoding
+ * it.
+ *
+ * To use them, make a new header with a name like `MOD_options.inc`. Start
+ * it with a BEGIN_CONF_STRUCT(), then define your variables with CONF_VAR(),
+ * then end the header with END_CONF_STRUCT(), as in:
+ *
+ * BEGIN_CONF_STRUCT(module_options_t)
+ * CONF_VAR(ModuleIsActive, BOOLEAN, 0, "1")
+ * END_CONF_STRUCT(module_options_t)
+ *
+ * Once you've done that, you can use that header to define a configuration
+ * structure by saying:
+ *
+ * typedef struct module_options_t module_options_t;
+ * #define CONF_CONTEXT STRUCT
+ * #include "MOD_options.inc"
+ * #undef CONF_CONTEXT
+ *
+ * And you can define your field definition table by saying:
+ *
+ * #define CONF_CONTEXT TABLE
+ * #include "MOD_options.inc"
+ * #undef CONF_CONTEXT
+ *
+ * The two above snippets will define a structure called `module_options_t`
+ * with appropriate members, and a table of config_var_t objects called
+ * `module_options_t_vars[]`.
+ **/
+
+#ifndef TOR_LIB_CONF_CONFDECL_H
+#define TOR_LIB_CONF_CONFDECL_H
+
+#undef CONF_CONTEXT
+#include "lib/cc/tokpaste.h"
+
+/**
+ * Begin the definition of a configuration object called `name`.
+ **/
+#define BEGIN_CONF_STRUCT(name) \
+ PASTE(BEGIN_CONF_STRUCT__, CONF_CONTEXT)(name)
+/**
+ * End the definition of a configuration object called `name`.
+ **/
+#define END_CONF_STRUCT(name) \
+ PASTE(END_CONF_STRUCT__, CONF_CONTEXT)(name)
+/**
+ * Declare a single configuration field with name `varname`, type `vartype`,
+ * flags `varflags`, and initial value `initval`.
+ **/
+#define CONF_VAR(varname, vartype, varflags, initval) \
+ PASTE(CONF_VAR__, CONF_CONTEXT)(varname, vartype, varflags, initval)
+
+#ifndef COCCI
+/**
+ * @defgroup STRUCT_MACROS Internal macros: struct definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to STRUCT. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__STRUCT(name) \
+ struct name { \
+ uint32_t magic;
+#define END_CONF_STRUCT__STRUCT(name) \
+ };
+#define CONF_VAR__STRUCT(varname, vartype, varflags, initval) \
+ config_decl_ ## vartype varname;
+/** @} */
+
+/**
+ * @defgroup TABLE_MACROS Internal macros: table definitions.
+ * Implementation helpers: the regular confdecl macros expand to these
+ * when CONF_CONTEXT is defined to TABLE. Don't use them directly.
+ * @{*/
+#define BEGIN_CONF_STRUCT__TABLE(structname) \
+ /* We use this typedef so we can refer to the config type */ \
+ /* without having its name as a macro argument to CONF_VAR. */ \
+ typedef struct structname config_var_reference__obj; \
+ static const config_var_t structname##_vars[] = {
+#define END_CONF_STRUCT__TABLE(structname) \
+ { .member = { .name = NULL } } \
+ };
+#define CONF_VAR__TABLE(varname, vartype, varflags, initval) \
+ { \
+ .member = \
+ { .name = #varname, \
+ .type = CONFIG_TYPE_EXTENDED, \
+ .type_def = &vartype ## _type_defn, \
+ .offset=offsetof(config_var_reference__obj, varname), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ },
+/**@}*/
+#endif
+
+/** Type aliases for the "commonly used" configuration types.
+ *
+ * Defining them in this way allows our CONF_VAR__STRUCT() macro to declare
+ * structure members corresponding to the configuration types. For example,
+ * when the macro sees us declare a configuration option "foo" of type STRING,
+ * it can emit `config_decl_STRING foo;`, which is an alias for `char *foo`.
+ */
+/**{*/
+typedef char *config_decl_STRING;
+typedef char *config_decl_FILENAME;
+/* Yes, "POSINT" is really an int, and not an unsigned int. For
+ * historical reasons, many configuration values are restricted
+ * to the range [0,INT_MAX], and stored in signed ints.
+ */
+typedef int config_decl_POSINT;
+typedef uint64_t config_decl_UINT64;
+typedef int config_decl_INT;
+typedef int config_decl_INTERVAL;
+typedef int config_decl_MSEC_INTERVAL;
+typedef uint64_t config_decl_MEMUNIT;
+typedef double config_decl_DOUBLE;
+typedef int config_decl_BOOL;
+typedef int config_decl_AUTOBOOL;
+typedef time_t config_decl_ISOTIME;
+typedef struct smartlist_t config_decl_CSV;
+typedef int config_decl_CSV_INTERVAL;
+typedef struct config_line_t *config_decl_LINELIST;
+typedef struct config_line_t *config_decl_LINELIST_V;
+typedef struct nonexistent_struct *config_decl_LINELIST_S;
+/**@}*/
+
+struct var_type_def_t;
+
+/* Forward declarations for configuration type definitions. These are used by
+ * the CONF_VAR__TABLE macro to set the definition of each variable type
+ * correctly.
+ */
+/**@{*/
+extern const struct var_type_def_t STRING_type_defn;
+extern const struct var_type_def_t FILENAME_type_defn;
+extern const struct var_type_def_t POSINT_type_defn;
+extern const struct var_type_def_t UINT64_type_defn;
+extern const struct var_type_def_t INT_type_defn;
+extern const struct var_type_def_t INTERVAL_type_defn;
+extern const struct var_type_def_t MSEC_INTERVAL_type_defn;
+extern const struct var_type_def_t MEMUNIT_type_defn;
+extern const struct var_type_def_t DOUBLE_type_defn;
+extern const struct var_type_def_t BOOL_type_defn;
+extern const struct var_type_def_t AUTOBOOL_type_defn;
+extern const struct var_type_def_t ISOTIME_type_defn;
+extern const struct var_type_def_t CSV_type_defn;
+extern const struct var_type_def_t CSV_INTERVAL_type_defn;
+extern const struct var_type_def_t LINELIST_type_defn;
+extern const struct var_type_def_t LINELIST_V_type_defn;
+extern const struct var_type_def_t LINELIST_S_type_defn;
+/**@}*/
+
+#endif /* !defined(TOR_LIB_CONF_CONFDECL_H) */
diff --git a/src/lib/conf/include.am b/src/lib/conf/include.am
index cb7126184d..cb0b83fa64 100644
--- a/src/lib/conf/include.am
+++ b/src/lib/conf/include.am
@@ -1,6 +1,7 @@
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
+ src/lib/conf/confdecl.h \
src/lib/conf/conftesting.h \
src/lib/conf/conftypes.h \
src/lib/conf/confmacros.h