Move responsibility for config var macros

The testing-only parts now live in a conftesting.h; the shared parts
of the macros live in confmacros.h
This commit is contained in:
Nick Mathewson 2019-06-20 15:55:59 -04:00
parent 4d101b39d7
commit c553750e32
10 changed files with 168 additions and 117 deletions

View File

@ -259,28 +259,12 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
* or_options_t.<b>member</b>"
*/
#define VAR(varname,conftype,member,initvalue) \
{ { .name = varname, \
.type = CONFIG_TYPE_ ## conftype, \
.offset = offsetof(or_options_t, member), \
}, \
initvalue CONF_TEST_MEMBERS(or_options_t, conftype, member) }
#ifdef TOR_UNIT_TESTS
#define DUMMY_TEST_MEMBERS , {.INT=NULL}
#else
#define DUMMY_TEST_MEMBERS
#endif
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, initvalue)
/* As VAR, but uses a type definition in addition to a type enum. */
#define VAR_D(varname,conftype,member,initvalue) \
{ { .name = varname, \
.type = CONFIG_TYPE_ ## conftype, \
.type_def = &conftype ## _type_defn, \
.offset = offsetof(or_options_t, member), \
}, \
initvalue DUMMY_TEST_MEMBERS }
CONFIG_VAR_DEFN(or_options_t, varname, conftype, member, initvalue)
/** As VAR, but the option name and member name are the same. */
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
@ -289,9 +273,7 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
VAR_D(#member, type, member, initvalue)
/** An entry for config_vars: "The option <b>varname</b> is obsolete." */
#define OBSOLETE(varname) \
{ { .name = varname, .type = CONFIG_TYPE_OBSOLETE, }, NULL \
DUMMY_TEST_MEMBERS }
#define OBSOLETE(varname) CONFIG_VAR_OBSOLETE(varname)
/**
* Macro to declare *Port options. Each one comes in three entries.

View File

@ -14,6 +14,7 @@
#define TOR_CONFPARSE_H
#include "lib/conf/conftypes.h"
#include "lib/conf/confmacros.h"
/** An abbreviation for a configuration option allowed on the command line. */
typedef struct config_abbrev_t {
@ -32,44 +33,6 @@ typedef struct config_deprecation_t {
* you can abbreviate <b>tok</b>s as <b>tok</b>". */
#define PLURAL(tok) { #tok, #tok "s", 0, 0 }
/* Macros to define extra members inside config_var_t fields, and at the
* end of a list of them.
*/
#ifdef TOR_UNIT_TESTS
/* This is a somewhat magic type-checking macro for users of confparse.c.
* It initializes a union member "confparse_dummy_values_t.conftype" with
* the address of a static member "tp_dummy.member". This
* will give a compiler warning unless the member field is of the correct
* type.
*
* (This warning is mandatory, because a type mismatch here violates the type
* compatibility constraint for simple assignment, and requires a diagnostic,
* according to the C spec.)
*
* For example, suppose you say:
* "CONF_CHECK_VAR_TYPE(or_options_t, STRING, Address)".
* Then this macro will evaluate to:
* { .STRING = &or_options_t_dummy.Address }
* And since confparse_dummy_values_t.STRING has type "char **", that
* expression will create a warning unless or_options_t.Address also
* has type "char *".
*/
#define CONF_CHECK_VAR_TYPE(tp, conftype, member) \
{ . conftype = &tp ## _dummy . member }
#define CONF_TEST_MEMBERS(tp, conftype, member) \
, CONF_CHECK_VAR_TYPE(tp, conftype, member)
#define END_OF_CONFIG_VARS \
{ { .name = NULL }, NULL, { .INT=NULL } }
#define DUMMY_TYPECHECK_INSTANCE(tp) \
static tp tp ## _dummy
#else /* !(defined(TOR_UNIT_TESTS)) */
#define CONF_TEST_MEMBERS(tp, conftype, member)
#define END_OF_CONFIG_VARS { { .name = NULL, }, NULL }
/* Repeatedly declarable incomplete struct to absorb redundant semicolons */
#define DUMMY_TYPECHECK_INSTANCE(tp) \
struct tor_semicolon_eater
#endif /* defined(TOR_UNIT_TESTS) */
/** Type of a callback to validate whether a given configuration is
* well-formed and consistent. See options_trial_assign() for documentation
* of arguments. */

View File

@ -70,14 +70,9 @@ static config_abbrev_t state_abbrevs_[] = {
* members with CONF_CHECK_VAR_TYPE. */
DUMMY_TYPECHECK_INSTANCE(or_state_t);
/*XXXX these next two are duplicates or near-duplicates from config.c */
#define VAR(varname,conftype,member,initvalue) \
{ { .name = varname, \
.type = CONFIG_TYPE_ ## conftype, \
.offset = offsetof(or_state_t, member), }, \
initvalue CONF_TEST_MEMBERS(or_state_t, conftype, member) }
/** As VAR, but the option name and member name are the same. */
#define V(member,conftype,initvalue) \
CONFIG_VAR_ETYPE(or_state_t, varname, conftype, member, initvalue)
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
/** Array of "state" variables saved to the ~/.tor/state file. */

View File

@ -51,15 +51,11 @@ static const char dstate_cur_srv_key[] = "SharedRandCurrentValue";
* members with CONF_CHECK_VAR_TYPE. */
DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t);
/* These next two are duplicates or near-duplicates from config.c */
#define VAR(varname, conftype, member, initvalue) \
{ { .name = varname, \
.type = CONFIG_TYPE_ ## conftype, \
.offset = offsetof(sr_disk_state_t, member), }, \
initvalue CONF_TEST_MEMBERS(sr_disk_state_t, conftype, member) }
/* As VAR, but the option name and member name are the same. */
#define V(member, conftype, initvalue) \
#define VAR(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(sr_disk_state_t, varname, conftype, member, initvalue)
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
/* Our persistent state magic number. */
#define SR_DISK_STATE_MAGIC 0x98AB1254

View File

@ -1,2 +1,3 @@
orconfig.h
lib/cc/*.h
lib/conf/*.h

61
src/lib/conf/confmacros.h Normal file
View File

@ -0,0 +1,61 @@
/* 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 confmacros.h
* @brief Macro definitions for declaring configuration variables
**/
#ifndef TOR_LIB_CONF_CONFMACROS_H
#define TOR_LIB_CONF_CONFMACROS_H
#include "orconfig.h"
#include "lib/conf/conftesting.h"
/**
* Used to indicate the end of an array of configuration variables.
**/
#define END_OF_CONFIG_VARS \
{ { .name = NULL }, NULL DUMMY_CONF_TEST_MEMBERS }
/**
* Declare a config_var_t as a member named <b>membername</b> of the structure
* <b>structtype</b>, whose user-visible name is <b>varname</b>, whose
* type corresponds to the config_type_t member CONFIG_TYPE_<b>vartype</b>,
* and whose initial value is <b>intval</b>.
*
* Most modules that use this macro should wrap it in a local macro that
* sets structtype to the local configuration type.
**/
#define CONFIG_VAR_ETYPE(structtype, varname, vartype, membername, initval) \
{ .member = \
{ .name = varname, \
.type = CONFIG_TYPE_ ## vartype, \
.offset = offsetof(structtype, membername), \
}, \
.initvalue = initval \
CONF_TEST_MEMBERS(structtype, vartype, membername) \
}
/**
* As CONFIG_VAR_XTYPE, but declares a value using an extension type whose
* type definition is <b>vartype</b>_type_defn.
**/
#define CONFIG_VAR_DEFN(structtype, varname, vartype, membername, initval) \
{ .member = \
{ .name = varname, \
.type = CONFIG_TYPE_EXTENDED, \
.type_def = &vartype ## _type_defn, \
.offset = offsetof(structtype, membername), \
}, \
.initvalue = initval \
CONF_TEST_MEMBERS(structtype, vartype, membername) \
}
#define CONFIG_VAR_OBSOLETE(varname) \
{ .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE } }
#endif /* !defined(TOR_LIB_CONF_CONFMACROS_H) */

View File

@ -0,0 +1,86 @@
/* 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 conftesting.h
* @brief Macro and type declarations for testing
**/
#ifndef TOR_LIB_CONF_CONFTESTING_H
#define TOR_LIB_CONF_CONFTESTING_H
#ifdef TOR_UNIT_TESTS
/**
* Union used when building in test mode typechecking the members of a type
* used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
* it is used. */
typedef union {
char **STRING;
char **FILENAME;
int *POSINT; /* yes, this 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.
*/
uint64_t *UINT64;
int *INT;
int *INTERVAL;
int *MSEC_INTERVAL;
uint64_t *MEMUNIT;
double *DOUBLE;
int *BOOL;
int *AUTOBOOL;
time_t *ISOTIME;
struct smartlist_t **CSV;
int *CSV_INTERVAL;
struct config_line_t **LINELIST;
struct config_line_t **LINELIST_S;
struct config_line_t **LINELIST_V;
// XXXX this doesn't belong at this level of abstraction.
struct routerset_t **ROUTERSET;
} confparse_dummy_values_t;
#endif /* defined(TOR_UNIT_TESTS) */
/* Macros to define extra members inside config_var_t fields, and at the
* end of a list of them.
*/
#ifdef TOR_UNIT_TESTS
/* This is a somewhat magic type-checking macro for users of confparse.c.
* It initializes a union member "confparse_dummy_values_t.conftype" with
* the address of a static member "tp_dummy.member". This
* will give a compiler warning unless the member field is of the correct
* type.
*
* (This warning is mandatory, because a type mismatch here violates the type
* compatibility constraint for simple assignment, and requires a diagnostic,
* according to the C spec.)
*
* For example, suppose you say:
* "CONF_CHECK_VAR_TYPE(or_options_t, STRING, Address)".
* Then this macro will evaluate to:
* { .STRING = &or_options_t_dummy.Address }
* And since confparse_dummy_values_t.STRING has type "char **", that
* expression will create a warning unless or_options_t.Address also
* has type "char *".
*/
#define CONF_CHECK_VAR_TYPE(tp, conftype, member) \
{ . conftype = &tp ## _dummy . member }
#define CONF_TEST_MEMBERS(tp, conftype, member) \
, CONF_CHECK_VAR_TYPE(tp, conftype, member)
#define DUMMY_CONF_TEST_MEMBERS , { .INT=NULL }
#define DUMMY_TYPECHECK_INSTANCE(tp) \
static tp tp ## _dummy
#else /* !(defined(TOR_UNIT_TESTS)) */
#define CONF_TEST_MEMBERS(tp, conftype, member)
/* Repeatedly declarable incomplete struct to absorb redundant semicolons */
#define DUMMY_TYPECHECK_INSTANCE(tp) \
struct tor_semicolon_eater
#define DUMMY_CONF_TEST_MEMBERS
#endif /* defined(TOR_UNIT_TESTS) */
#endif /* !defined(TOR_LIB_CONF_CONFTESTING_H) */

View File

@ -29,6 +29,9 @@
#define TOR_SRC_LIB_CONF_CONFTYPES_H
#include "lib/cc/torint.h"
#ifdef TOR_UNIT_TESTS
#include "lib/conf/conftesting.h"
#endif
/** Enumeration of types which option values can take */
typedef enum config_type_t {
@ -59,9 +62,6 @@ typedef enum config_type_t {
CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
* context-sensitive config lines when fetching.
*/
// XXXX this doesn't belong at this level of abstraction.
CONFIG_TYPE_ROUTERSET, /**< A list of router names, addrs, and fps,
* parsed into a routerset_t. */
CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
CONFIG_TYPE_EXTENDED, /**< Extended type; definition will appear in
* pointer. */
@ -105,37 +105,6 @@ typedef struct struct_magic_decl_t {
int magic_offset;
} struct_magic_decl_t;
#ifdef TOR_UNIT_TESTS
/**
* Union used when building in test mode typechecking the members of a type
* used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
* it is used. */
typedef union {
char **STRING;
char **FILENAME;
int *POSINT; /* yes, this 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.
*/
uint64_t *UINT64;
int *INT;
int *INTERVAL;
int *MSEC_INTERVAL;
uint64_t *MEMUNIT;
double *DOUBLE;
int *BOOL;
int *AUTOBOOL;
time_t *ISOTIME;
struct smartlist_t **CSV;
int *CSV_INTERVAL;
struct config_line_t **LINELIST;
struct config_line_t **LINELIST_S;
struct config_line_t **LINELIST_V;
// XXXX this doesn't belong at this level of abstraction.
struct routerset_t **ROUTERSET;
} confparse_dummy_values_t;
#endif /* defined(TOR_UNIT_TESTS) */
/** A variable allowed in the configuration file or on the command line. */
typedef struct config_var_t {
struct_member_t member; /** A struct member corresponding to this

View File

@ -1,4 +1,6 @@
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
src/lib/conf/conftypes.h
src/lib/conf/conftesting.h \
src/lib/conf/conftypes.h \
src/lib/conf/confmacros.h

View File

@ -49,13 +49,9 @@ typedef struct test_struct_t {
static test_struct_t test_struct_t_dummy;
#define VAR(varname,conftype,member,initvalue) \
{ { .name = varname, \
.type = CONFIG_TYPE_##conftype, \
.offset = offsetof(test_struct_t, member), }, \
initvalue CONF_TEST_MEMBERS(test_struct_t, conftype, member) }
#define V(name,conftype,initvalue) \
VAR( #name, conftype, name, initvalue )
CONFIG_VAR_ETYPE(test_struct_t, varname, conftype, member, initvalue)
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
#define OBSOLETE(varname) \
{ { .name=varname, .type=CONFIG_TYPE_OBSOLETE }, NULL, {.INT=NULL} }
@ -83,7 +79,7 @@ static config_var_t test_vars[] = {
OBSOLETE("obsolete"),
{
{ .name = "routerset",
.type = CONFIG_TYPE_ROUTERSET,
.type = CONFIG_TYPE_EXTENDED,
.type_def = &ROUTERSET_type_defn,
.offset = offsetof(test_struct_t, routerset),
},