aboutsummaryrefslogtreecommitdiff
path: root/src/lib/conf/confdecl.h
blob: c2d3fb335d62e4df07c130058e764336cd2d4ff5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, 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[]`.
 *
 * For lower-level modules, you can say <tt>\#define CONF_TABLE LL_TABLE</tt>,
 * and get a table definition suitable for use in modules that are at a lower
 * level than lib/confmgt.  Note that the types for these tables cannot
 * include any extended types.
 **/

#ifndef TOR_LIB_CONF_CONFDECL_H
#define TOR_LIB_CONF_CONFDECL_H

#undef CONF_CONTEXT
#include "lib/cc/tokpaste.h"
#include "lib/cc/torint.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                                         \
  },
/**@}*/

/**
 * @defgroup LL_TABLE_MACROS Internal macros: low-level table definitions.
 * Implementation helpers: the regular confdecl macros expand to these
 * when CONF_CONTEXT is defined to LL_TABLE.  Don't use them directly.
 * @{*/
#define BEGIN_CONF_STRUCT__LL_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__LL_TABLE(structname)   \
  { .member = { .name = NULL } }                \
    };
#define CONF_VAR__LL_TABLE(varname, vartype, varflags, initval) \
  {                                                             \
   .member =                                                    \
   { .name = #varname,                                          \
     .type = CONFIG_TYPE_ ## vartype,                           \
     .offset=offsetof(config_var_reference__obj, varname),      \
   },                                                           \
   .flags = varflags,                                           \
   .initvalue = initval                                         \
  },
/**@}*/

/** @defgroup STUB_TABLE_MACROS Internal macros: stub table declarations,
 * for use when a module is disabled.
 * Implementation helpers: the regular confdecl macros expand to these
 * when CONF_CONTEXT is defined to LL_TABLE.  Don't use them directly.
 * @{ */
#define BEGIN_CONF_STRUCT__STUB_TABLE(structname)                       \
  static const config_var_t structname##_vars[] = {
#define END_CONF_STRUCT__STUB_TABLE(structname)   \
  { .member = { .name = NULL } }                \
    };
#define CONF_VAR__STUB_TABLE(varname, vartype, varflags, initval)       \
  {                                                             \
   .member =                                                    \
   { .name = #varname,                                          \
     .type = CONFIG_TYPE_IGNORE,                                \
     .offset = -1,                                              \
   },                                                           \
   .flags = CFLG_GROUP_DISABLED,                                \
  },
/**@}*/

#endif /* !defined(COCCI) */

/** 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;
extern const struct var_type_def_t IGNORE_type_defn;
extern const struct var_type_def_t OBSOLETE_type_defn;
/**@}*/

#endif /* !defined(TOR_LIB_CONF_CONFDECL_H) */