[asterisk-commits] twilson: branch twilson/config_work r366739 - in /team/twilson/config_work: a...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 16 14:39:10 CDT 2012
Author: twilson
Date: Wed May 16 14:39:05 2012
New Revision: 366739
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=366739
Log:
Address many of Matt's suggestions
This doesn't have:
1) Rewriting of app_skel to be better for more complex examples
2) Documentation additions to .c files
3) Improved support for handling multiple config files
Modified:
team/twilson/config_work/apps/app_skel.c
team/twilson/config_work/configs/app_skel.conf.sample
team/twilson/config_work/include/asterisk/config_options.h
team/twilson/config_work/include/asterisk/utils.h
team/twilson/config_work/main/astobj2.c
team/twilson/config_work/main/config_options.c
team/twilson/config_work/main/udptl.c
Modified: team/twilson/config_work/apps/app_skel.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/apps/app_skel.c?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/apps/app_skel.c (original)
+++ team/twilson/config_work/apps/app_skel.c Wed May 16 14:39:05 2012
@@ -16,7 +16,7 @@
* at the top of the source tree.
*
* Please follow coding guidelines
- * http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
+ * https://wiki.asterisk.org/wiki/display/AST/Coding+Guidelines
*/
/*! \file
@@ -164,7 +164,7 @@
static AO2_GLOBAL_OBJ_STATIC(globals);
CONFIG_INFO_STANDARD(cfg_info, "app_skel.conf", globals, skel_config_alloc,
- .types = { &general_options, &private_options, NULL },
+ .types = ACO_TYPES(&general_options, &private_options),
);
static void skel_global_config_destructor(void *obj)
Modified: team/twilson/config_work/configs/app_skel.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/configs/app_skel.conf.sample?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/configs/app_skel.conf.sample (original)
+++ team/twilson/config_work/configs/app_skel.conf.sample Wed May 16 14:39:05 2012
@@ -19,3 +19,7 @@
bit2=yes
[pvt3]
+
+[pvt4]
+bit1=yes
+bit2=yes
Modified: team/twilson/config_work/include/asterisk/config_options.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/include/asterisk/config_options.h?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/include/asterisk/config_options.h (original)
+++ team/twilson/config_work/include/asterisk/config_options.h Wed May 16 14:39:05 2012
@@ -35,6 +35,7 @@
struct aco_option;
struct aco_type;
+struct aco_info_internal;
enum aco_type_t {
ACO_GLOBAL_OBJ,
@@ -142,14 +143,24 @@
struct aco_info {
const char *module; /*!< The name of the module whose config is being processed */
const char *filename; /*!< The config filename */
- struct ao2_container *opts; /*!< Internal use - options to parse */
aco_pre_apply_config pre_apply_config; /*!< A callback called after processing, but before changes are applied */
aco_snapshot_alloc snapshot_alloc; /*!< Allocate an object to hold all global configs and private containers */
struct ao2_global_obj *global_obj; /*!< The global object array that holds the user-defined config object */
- void *new_config; /*!< Internal use - A cache of newly created config */
const char **preload; /*!< Categories to parse first. Do something like char *arr[] = {"general", NULL}; and do .preload = arr */
+ struct aco_info_internal *internal;
struct aco_type *types[]; /*!< The list of types for this config. Required. Use a sentinel! */
};
+
+/*! \brief A helper macro to ensure that aco_info types always have a sentinel */
+#define ACO_TYPES(...) { __VA_ARGS__, NULL, }
+
+/*! \brief Get pending config changes
+ * \note This will most likely be called from the pre_apply_config callback function
+ * \param info An initialized aco_info
+ * \retval NULL error
+ * \retval non-NULL A pointer to the user-defined config object with un-applied changes
+ */
+void *aco_pending_config(struct aco_info *info);
/*! \def CONFIG_INFO_STANDARD
* \brief Declare an aco_info struct with default module and preload values
@@ -238,21 +249,26 @@
*/
struct aco_option *aco_option_find(struct ao2_container *container, const char *name, const char *category);
-/*! \brief Completely handle simple configs
- *
- * \note This is for configs that have no relationship between global options and
- * those for any private objects (peers, etc.) If a config is well designed, this
- * should be the case since config templates should be used for setting default
- * values for individual objects.
+/*! \brief Process a config info via the options registered with an aco_info
*
* \param info The config_options_info to be used for handling the config
- * \param filename The filename of the config
* \param reload Whether or not this is a reload
*
* \retval 0 Success
* \retval -1 Failure
*/
int aco_process_config(struct aco_info *info, int reload);
+
+/*! \brief Process config info from an ast_config via options registered with an aco_info
+ *
+ * \param info The aco_info to be used for handling the config
+ * \param cfg A pointer to a loaded ast_config to parse
+ * \param reload Whether or not this is a reload
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int aco_process_ast_config(struct aco_info *info, struct ast_config *cfg, int reload);
/*! \brief Parse each option defined in a config category
* \param container The container of options from which to configure \a obj
@@ -275,7 +291,7 @@
*/
int aco_set_defaults(struct ao2_container *container, const char *category, void *obj);
-/*! \brief build a config option
+/*! \brief register a config option
*
* \note this should probably only be called by one of the aco_option_register* macros
*
@@ -288,9 +304,10 @@
* \param argc The number for variadic arguments
* \param ... field offsets to store for default handlers
*
- * \returns An option on success, NULL on failure
- */
-struct aco_option *__aco_option_build(const char *name, struct aco_type *obj,
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int __aco_option_register(struct aco_info *info, const char *name, struct aco_type *obj,
const char *default_val, enum aco_option_type type, aco_option_handler handler, unsigned int flags, size_t argc, ...);
/* \brief Register a config option
@@ -303,13 +320,8 @@
*
* \returns An option on success, NULL on failure
*/
-#define aco_option_register(info, name, obj, default_val, opt_type, flags, ...) {\
- struct aco_option *__opt; \
- if ((__opt = __aco_option_build(name, obj, default_val, opt_type, NULL, flags, VA_NARGS(__VA_ARGS__), __VA_ARGS__))){ \
- ao2_link((info)->opts, __opt); \
- ao2_ref(__opt, -1); \
- } \
-}
+#define aco_option_register(info, name, obj, default_val, opt_type, flags, ...) \
+ __aco_option_register(info, name, obj, default_val, opt_type, NULL, flags, VA_NARGS(__VA_ARGS__), __VA_ARGS__);
/* \brief Register a config option
* \param info A pointer to the aco_info struct
@@ -321,13 +333,8 @@
*
* \returns An option on success, NULL on failure
*/
-#define aco_option_register_custom(info, name, obj, default_val, handler, flags) { \
- struct aco_option *__opt = __aco_option_build(name, obj, default_val, OPT_CUSTOM_T, handler, flags, 0); \
- if (__opt) { \
- ao2_link((info)->opts, __opt); \
- ao2_ref(__opt, -1); \
- } \
-}
+#define aco_option_register_custom(info, name, obj, default_val, handler, flags) \
+ __aco_option_register(info, name, obj, default_val, OPT_CUSTOM_T, handler, flags, 0);
/*! \note Everything below this point is to handle converting varargs
* containing field names, to varargs containing a count of args, followed
@@ -345,14 +352,18 @@
* \param varargs The rest of the fields
*
* Example usage:
- * struct foo {
- * int a;
- * char *b;
- * foo *c;
- * };
- * ARGMAP(offsetof, struct foo, a, c)
+ * \code
+ * struct foo {
+ * int a;
+ * char *b;
+ * foo *c;
+ * };
+ * ARGMAP(offsetof, struct foo, a, c)
+ * \endcode
* produces the string:
- * 2, offsetof(struct foo, a), offsetof(struct foo, b)
+ * \code
+ * 2, offsetof(struct foo, a), offsetof(struct foo, b)
+ * \encode
* which can be passed as the varargs to some other function
*
* The macro isn't limited to offsetof, but that is the only purpose for
@@ -432,7 +443,7 @@
* \brief Convert a struct and list of fields to an argument list of field offsets
* \param type The type with the fields (e.g. "struct my_struct")
* \param varags The fields in the struct whose offsets are needed as arguments
- *
+ *
* For example:
* \code
* struct foo {int a, char b[128], char *c};
Modified: team/twilson/config_work/include/asterisk/utils.h
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/include/asterisk/utils.h?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/include/asterisk/utils.h (original)
+++ team/twilson/config_work/include/asterisk/utils.h Wed May 16 14:39:05 2012
@@ -863,7 +863,49 @@
*/
char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size);
-#define RAII_VAR(vartype,varname,initval,dtor) \
+/*! \brief Declare a variable that will call a destructor function when it goes out of scope
+ * \param vartype The type of the variable
+ * \param varname The name of the variable
+ * \param initval The initial value of the variable
+ * \param dtor The destructor function of type' void func(vartype *)'
+ *
+ * \code
+ * void mything_cleanup(struct mything *t)
+ * {
+ * if (t) {
+ * ast_free(t->stuff);
+ * }
+ * }
+ *
+ * void do_stuff(const char *name)
+ * {
+ * RAII_VAR(struct mything *, thing, mything_alloc(name), mything_cleanup);
+ * ...
+ * }
+ *
+ * \note This macro is especially useful for working with ao2 objects. A common idiom
+ * would be a function that needed to look up an ao2 object and might have several error
+ * conditions after the allocation that would normally need to unref the ao2 object.
+ * With RAII_VAR, it is possible to just return and leave the cleanup to the destructor
+ * function. For example:
+ * \code
+ * void do_stuff(const char *name)
+ * {
+ * RAII_VAR(struct mything *, thing, find_mything(name), ao2_cleanup);
+ * if (!thing) {
+ * return;
+ * }
+ * if (error) {
+ * return;
+ * }
+ * do_stuff_with_thing(thing);
+ * return;
+ * }
+ * }
+ * \encode
+ *
+ */
+#define RAII_VAR(vartype, varname, initval, dtor) \
auto void _dtor_ ## varname (vartype * v); \
auto void _dtor_ ## varname (vartype * v) { dtor(*v); } \
vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
Modified: team/twilson/config_work/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/main/astobj2.c?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/main/astobj2.c (original)
+++ team/twilson/config_work/main/astobj2.c Wed May 16 14:39:05 2012
@@ -638,6 +638,7 @@
{
if (!holder) {
/* For sanity */
+ ast_log(LOG_ERROR, "Must be called with a global object!\n");
return;
}
if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
@@ -660,6 +661,7 @@
if (!holder) {
/* For sanity */
+ ast_log(LOG_ERROR, "Must be called with a global object!\n");
return NULL;
}
if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
@@ -696,8 +698,10 @@
if (!holder) {
/* For sanity */
- return NULL;
- }
+ ast_log(LOG_ERROR, "Must be called with a global object!\n");
+ return NULL;
+ }
+
if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
/* Could not get the read lock. */
return NULL;
Modified: team/twilson/config_work/main/config_options.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/main/config_options.c?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/main/config_options.c (original)
+++ team/twilson/config_work/main/config_options.c Wed May 16 14:39:05 2012
@@ -39,6 +39,14 @@
#define CONFIG_OPT_BUCKETS 53
#endif /* LOW_MEMORY */
+/*! \brief Bits of aco_info that shouldn't be assigned outside this file
+ * \internal
+ */
+struct aco_info_internal {
+ struct ao2_container *opts; /*!< The container of options registered to the aco_info */
+ void *pending; /*!< The user-defined config object awaiting application */
+};
+
struct aco_option {
const char *name;
const char *default_val;
@@ -51,6 +59,15 @@
size_t args[0];
};
+void *aco_pending_config(struct aco_info *info)
+{
+ if (!(info && info->internal)) {
+ ast_log(LOG_ERROR, "This may not be called without an initialized aco_info!\n");
+ return NULL;
+ }
+ return info->internal->pending;
+}
+
static void config_option_destroy(void *obj)
{
return;
@@ -93,8 +110,9 @@
}
if ((res = regcomp(regex, text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
- char buf[80];
- regerror(res, regex, buf, sizeof(buf));
+ size_t len = regerror(res, regex, NULL, 0);
+ char buf[len];
+ regerror(res, regex, buf, len);
ast_log(LOG_ERROR, "Could not compile regex '%s': %s\n", text, buf);
ast_free(regex);
return NULL;
@@ -103,10 +121,7 @@
return regex;
}
-/*! \brief build a config option
- * \note this should probably only be called by one of the aco_option_register* macros
- */
-struct aco_option *__aco_option_build(const char *name, struct aco_type *obj,
+int __aco_option_register(struct aco_info *info, const char *name, struct aco_type *obj,
const char *default_val, enum aco_option_type type, aco_option_handler handler, unsigned int flags, size_t argc, ...)
{
struct aco_option *opt;
@@ -115,15 +130,15 @@
/* Custom option types require a handler */
if (!handler && type == OPT_CUSTOM_T) {
- return NULL;
+ return -1;
}
if (!obj) {
- return NULL;
+ return -1;
}
if (!(opt = ao2_alloc(sizeof(*opt) + argc * sizeof(opt->args[0]), config_option_destroy))) {
- return NULL;
+ return -1;
}
va_start(ap, argc);
@@ -141,11 +156,18 @@
opt->argc = argc;
if (!opt->handler && !(opt->handler = ast_config_option_default_handler(opt->type))) {
+ /* This should never happen */
+ ast_log(LOG_ERROR, "No handler provided, and no default handler exists for type %d\n", opt->type);
ao2_ref(opt, -1);
- return NULL;
+ return -1;
};
- return opt;
+ if (!ao2_link(info->internal->opts, opt)) {
+ ao2_ref(opt, -1);
+ return -1;
+ }
+
+ return 0;
}
static int config_opt_hash(const void *obj, const int flags)
@@ -242,19 +264,19 @@
}
/* if type == GLOBAL_OBJ, set defaults and configure the cached cfg object */
- if (obj->type == ACO_GLOBAL_OBJ && info->new_config + obj->cfg_offset) {
- void **field = info->new_config + obj->cfg_offset;
-
- if (aco_set_defaults(info->opts, cat, *field)) {
+ if (obj->type == ACO_GLOBAL_OBJ && info->internal->pending + obj->cfg_offset) {
+ void **field = info->internal->pending + obj->cfg_offset;
+
+ if (aco_set_defaults(info->internal->opts, cat, *field)) {
ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", info->filename, cat);
return -1;
}
- if (aco_process_category_options(info->opts, cfg, cat, *field)) {
+ if (aco_process_category_options(info->internal->opts, cfg, cat, *field)) {
ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", info->filename, cat);
return -1;
}
} else if (obj->type == ACO_PRIVATE_OBJ) {
- void **field = info->new_config + obj->pvt_offset;
+ void **field = info->internal->pending + obj->pvt_offset;
/* If we've already linked a private for cat in newpvts, don't add a second one with the same name */
if (*field) {
if ((tmppvt = obj->find_pvt(*field, cat))) {
@@ -276,7 +298,7 @@
return -1;
}
- if (aco_set_defaults(info->opts, cat, tmpcfg)) {
+ if (aco_set_defaults(info->internal->opts, cat, tmpcfg)) {
ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", info->filename, cat);
return -1;
}
@@ -286,7 +308,7 @@
return -1;
}
- if (aco_process_category_options(info->opts, cfg, cat, tmpcfg)) {
+ if (aco_process_category_options(info->internal->opts, cfg, cat, tmpcfg)) {
ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", info->filename, cat);
return -1;
}
@@ -301,7 +323,7 @@
ast_log(LOG_ERROR, "In %s: Linking private for %s failed\n", info->filename, cat);
return -1;
}
- field = info->new_config + obj->cfg_offset;
+ field = info->internal->pending + obj->cfg_offset;
if (!ao2_link(*field, tmpcfg)) {
ast_log(LOG_ERROR, "In %s: Linking config for %s failed\n", info->filename, cat);
return -1;
@@ -312,38 +334,17 @@
static int apply_config(struct aco_info *info)
{
- ao2_global_obj_replace_unref(*info->global_obj, info->new_config);
-
- return 0;
-}
-
-int aco_process_config(struct aco_info *info, int reload)
-{
- struct ast_config *cfg;
- struct ast_flags cfg_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0, };
+ ao2_global_obj_replace_unref(*info->global_obj, info->internal->pending);
+
+ return 0;
+}
+
+int aco_process_ast_config(struct aco_info *info, struct ast_config *cfg, int reload)
+{
const char *cat = NULL;
int res;
- if (ast_strlen_zero(info->filename)) {
- ast_log(LOG_ERROR, "No filename given, cannot proceed!\n");
- return -1;
- }
-
- if (!(cfg = ast_config_load(info->filename, cfg_flags))) {
- ast_log(LOG_ERROR, "Unable to load config file '%s'\n", info->filename);
- return -1;
- } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
- ast_debug(1, "%s was unchanged\n", info->filename);
- return 0;
- } else if (cfg == CONFIG_STATUS_FILEINVALID) {
- ast_log(LOG_ERROR, "Contents of %s are invalid and cannot be parsed\n", info->filename);
- return -1;
- } else if (cfg == CONFIG_STATUS_FILEMISSING) {
- ast_log(LOG_ERROR, "%s is missing! Cannot load %s\n", info->filename, info->module);
- return -1;
- }
-
- if (!(info->new_config = info->snapshot_alloc())) {
+ if (!(info->internal->pending = info->snapshot_alloc())) {
ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", info->filename);
goto error;
}
@@ -363,21 +364,49 @@
}
}
- ast_config_destroy(cfg);
-
if (info->pre_apply_config && info->pre_apply_config()) {
goto error;
}
res = apply_config(info); /* The module already knows where the objects are */
- ao2_ref(info->new_config, -1);
-
+ ao2_ref(info->internal->pending, -1);
return res;
error:
ast_config_destroy(cfg);
- ao2_ref(info->new_config, -1);
+ ao2_ref(info->internal->pending, -1);
return -1;
+}
+
+int aco_process_config(struct aco_info *info, int reload)
+{
+ struct ast_config *cfg;
+ struct ast_flags cfg_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0, };
+ int res;
+
+ if (ast_strlen_zero(info->filename)) {
+ ast_log(LOG_ERROR, "No filename given, cannot proceed!\n");
+ return -1;
+ }
+
+ if (!(cfg = ast_config_load(info->filename, cfg_flags))) {
+ ast_log(LOG_ERROR, "Unable to load config file '%s'\n", info->filename);
+ return -1;
+ } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
+ ast_debug(1, "%s was unchanged\n", info->filename);
+ return 0;
+ } else if (cfg == CONFIG_STATUS_FILEINVALID) {
+ ast_log(LOG_ERROR, "Contents of %s are invalid and cannot be parsed\n", info->filename);
+ return -1;
+ } else if (cfg == CONFIG_STATUS_FILEMISSING) {
+ ast_log(LOG_ERROR, "%s is missing! Cannot load %s\n", info->filename, info->module);
+ return -1;
+ }
+
+ res = aco_process_ast_config(info, cfg, reload);
+ ast_config_destroy(cfg);
+
+ return res;
}
int aco_process_category_options(struct ao2_container *container, struct ast_config *cfg, const char *cat, void *obj)
@@ -435,31 +464,39 @@
{
size_t x;
struct aco_type *t;
- if (!(info->opts = aco_option_container_alloc())) {
- return -1;
+
+ if (!(info->internal = ast_calloc(1, sizeof(*info->internal)))) {
+ return -1;
+ }
+
+ if (!(info->internal->opts = aco_option_container_alloc())) {
+ goto error;
}
for (x = 0, t = info->types[x]; t; t = info->types[++x]) {
if (internal_type_init(t)) {
- ao2_ref(info->opts, -1);
- info->opts = NULL;
- internal_info_types_destroy(info);
- return -1;
- }
- }
-
- return 0;
+ goto error;
+ }
+ }
+
+ return 0;
+error:
+ aco_info_destroy(info);
+ return -1;
}
void aco_info_destroy(struct aco_info *info)
{
- if (info->opts) {
- ao2_ref(info->opts, -1);
+ if (info->internal) {
+ ao2_cleanup(info->internal->opts);
+ ast_free(info->internal);
+ info->internal = NULL;
}
internal_info_types_destroy(info);
}
/*! \brief match for anything where the category passes (or fails if !category_allow) the category regex
+ * \internal
*/
static int match_option_by_category(void *obj, void *arg, int flags)
{
Modified: team/twilson/config_work/main/udptl.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/config_work/main/udptl.c?view=diff&rev=366739&r1=366738&r2=366739
==============================================================================
--- team/twilson/config_work/main/udptl.c (original)
+++ team/twilson/config_work/main/udptl.c Wed May 16 14:39:05 2012
@@ -82,9 +82,6 @@
#define DEFAULT_UDPTLSTART 4000
#define DEFAULT_UDPTLEND 4999
-#define STR(x) STR1(x)
-#define STR1(x) #x
-
static int udptldebug; /*!< Are we debugging? */
static struct ast_sockaddr udptldebugaddr; /*!< Debug packets to/from this host */
@@ -202,7 +199,7 @@
};
CONFIG_INFO_STANDARD(cfg_info, "udptl.conf", globals, udptl_snapshot_alloc,
- .types = { &general_options, NULL },
+ .types = ACO_TYPES(&general_options),
.pre_apply_config = udptl_pre_apply_config,
);
@@ -1412,7 +1409,7 @@
}
static int udptl_pre_apply_config(void) {
- struct udptl_config *cfg = cfg_info.new_config;
+ struct udptl_config *cfg = aco_pending_config(&cfg_info);
if (!cfg->general) {
return -1;
@@ -1431,7 +1428,7 @@
ast_log(LOG_NOTICE, "Odd numbered udptlstart specified but use_even_ports enabled. udptlstart is now %d\n", cfg->general->start);
}
if (cfg->general->start > cfg->general->end) {
- ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %s-%s.\n", STR(DEFAULT_UDPTLSTART), STR(DEFAULT_UDPTLEND));
+ ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end ports; defaulting to %s-%s.\n", __stringify(DEFAULT_UDPTLSTART), __stringify(DEFAULT_UDPTLEND));
cfg->general->start = DEFAULT_UDPTLSTART;
cfg->general->end = DEFAULT_UDPTLEND;
}
@@ -1455,11 +1452,11 @@
return;
}
- aco_option_register(&cfg_info, "udptlstart", &general_options, STR(DEFAULT_UDPTLSTART),
+ aco_option_register(&cfg_info, "udptlstart", &general_options, __stringify(DEFAULT_UDPTLSTART),
OPT_UINT_T, PARSE_IN_RANGE | PARSE_DEFAULT,
FLDSET(struct udptl_global_options, start), DEFAULT_UDPTLSTART, 1024, 65535);
- aco_option_register(&cfg_info, "udptlend", &general_options, STR(DEFAULT_UDPTLEND),
+ aco_option_register(&cfg_info, "udptlend", &general_options, __stringify(DEFAULT_UDPTLEND),
OPT_UINT_T, PARSE_IN_RANGE | PARSE_DEFAULT,
FLDSET(struct udptl_global_options, end), DEFAULT_UDPTLEND, 1024, 65535);
More information about the asterisk-commits
mailing list