aboutsummaryrefslogtreecommitdiffstats
path: root/include/asterisk/config.h
diff options
context:
space:
mode:
authorrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2007-12-20 12:56:07 +0000
committerrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2007-12-20 12:56:07 +0000
commit91f1b6959dd053e976e91f50254e2205fa35eb1e (patch)
tree9d693aab885404d655ae9ef42e0bc104756aef39 /include/asterisk/config.h
parent0a8518b7c882ee0c0e954fac34fb488d42a9fc00 (diff)
add some macros to simplify parsing the config file,
see description in config.h . They are a variant of the set of macros i used in chan_oss.c, structured in a way to be more robust to the presence of spurious ';' - basically, they define wrappers for 'do {' and '} while (0)', plus some helper functions to deal with simple cases such as ast_copy_string, ast_malloc, strtoul, ast_true ... The prefix (CV_ as 'Config Variable') tries to be easy to remember and has been chosen to not conflict with other existing macros in the tree. For the time being, I have only updated the three source files in the tree that used the old M_* macros. Hopefully, more files will be converted. NOTE: I understand that inventing my own dialect of C is generally wrong; however, the lack of adequate support in the language encourages lazy programming practices (such as ignoring errors, bounds, etc.) and this increases the chance of vulnerability in the code, especially because we are parsing user input here. Hopefully, these macros and the use of ast_parse_arg (in config.h) should encourage the programmer to write more robust code. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@94191 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'include/asterisk/config.h')
-rw-r--r--include/asterisk/config.h40
1 files changed, 40 insertions, 0 deletions
diff --git a/include/asterisk/config.h b/include/asterisk/config.h
index ebc71fb8a..7a2d10135 100644
--- a/include/asterisk/config.h
+++ b/include/asterisk/config.h
@@ -271,6 +271,7 @@ int ast_variable_update(struct ast_category *category, const char *variable,
int config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator);
struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file);
+
/*! \brief Support code to parse config file arguments
*
* The function ast_parse_arg() provides a generic interface to parse
@@ -358,6 +359,45 @@ enum ast_parse_flags {
int ast_parse_arg(const char *arg, enum ast_parse_flags flags,
void *result, ...);
+/*
+ * Parsing config file options in C is slightly annoying because we cannot use
+ * string in a switch() statement, yet we need a similar behaviour, with many
+ * branches and a break on a matching one.
+ * The following somehow simplifies the job: we create a block using
+ * the CV_START and CV_END macros, and then within the block we can run
+ * actions such as "if (condition) { body; break; }"
+ * Additional macros are present to run simple functions (e.g. ast_copy_string)
+ * or to pass arguments to ast_parse_arg()
+ *
+ * As an example:
+
+ CV_START(v->name, v->value); // start the block
+ CV_STR("foo", x_foo); // static string
+ CV_DSTR("bar", y_bar); // malloc'ed string
+ CV_F("bar", ...); // call a generic function
+ CV_END; // end the block
+ */
+
+/*! \brief the macro to open a block for variable parsing */
+#define CV_START(__in_var, __in_val) \
+ do { \
+ const char *__var = __in_var; \
+ const char *__val = __in_val;
+
+/*! \brief close a variable parsing block */
+#define CV_END } while (0)
+
+/*! \brief call a generic function if the name matches. */
+#define CV_F(__pattern, __body) if (!strcasecmp((__var), __pattern)) { __body; break; }
+
+/*! \brief helper macros to assign the value to a BOOL, UINT, static string and
+ * dynamic string
+ */
+#define CV_BOOL(__x, __dst) CV_F(__x, (__dst) = ast_true(__val) )
+#define CV_UINT(__x, __dst) CV_F(__x, (__dst) = strtoul(__val, NULL, 0) )
+#define CV_STR(__x, __dst) CV_F(__x, ast_copy_string(__dst, __val, sizeof(__dst)))
+#define CV_DSTR(__x, __dst) CV_F(__x, if (__dst) ast_free(__dst); __dst = ast_strdup(__val))
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif