[tor-commits] [tor/master] Macros for declaring configuration structs and variable-tables

nickm at torproject.org nickm at torproject.org
Thu Nov 7 13:59:49 UTC 2019


commit 19cac400d9cf7dcc274c583bb3e942b2682c3663
Author: Nick Mathewson <nickm at torproject.org>
Date:   Sat Oct 26 17:46:16 2019 -0400

    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.
---
 src/feature/nodelist/routerset.h |   1 +
 src/lib/conf/confdecl.h          | 166 +++++++++++++++++++++++++++++++++++++++
 src/lib/conf/include.am          |   1 +
 3 files changed, 168 insertions(+)

diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h
index dc6ce0b66..6bd97f942 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 000000000..22812f046
--- /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 cb7126184..cb0b83fa6 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





More information about the tor-commits mailing list