aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/app_dial.c4
-rw-r--r--apps/app_meetme.c4
-rw-r--r--apps/app_queue.c4
-rw-r--r--channels/chan_iax2.c3
-rw-r--r--channels/chan_sip.c9
-rw-r--r--channels/chan_skinny.c3
-rw-r--r--include/asterisk/pbx.h38
-rw-r--r--include/asterisk/pval.h3
-rw-r--r--main/features.c15
-rw-r--r--main/pbx.c592
-rw-r--r--pbx/pbx_ael.c12
-rw-r--r--pbx/pbx_config.c16
-rw-r--r--res/ael/ael.flex4
-rw-r--r--res/ael/ael.tab.c502
-rw-r--r--res/ael/ael.tab.h2
-rw-r--r--res/ael/ael.y2
-rw-r--r--res/ael/ael_lex.c141
-rw-r--r--res/ael/pval.c6
-rw-r--r--utils/Makefile4
-rw-r--r--utils/ael_main.c33
-rw-r--r--utils/conf2ael.c45
-rw-r--r--utils/extconf.c1480
22 files changed, 1582 insertions, 1340 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index b52a97b2d..dfd6f8306 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -2096,9 +2096,7 @@ static int load_module(void)
int res;
struct ast_context *con;
- con = ast_context_find("app_dial_gosub_virtual_context");
- if (!con)
- con = ast_context_create(NULL, "app_dial_gosub_virtual_context", "app_dial");
+ con = ast_context_find_or_create(NULL, NULL, "app_dial_gosub_virtual_context", "app_dial");
if (!con)
ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
else
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index 471477a55..b7a72aeb7 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -5280,7 +5280,7 @@ static int sla_build_trunk(struct ast_config *cfg, const char *cat)
if (!ast_strlen_zero(trunk->autocontext)) {
struct ast_context *context;
- context = ast_context_find_or_create(NULL, trunk->autocontext, sla_registrar);
+ context = ast_context_find_or_create(NULL, NULL, trunk->autocontext, sla_registrar);
if (!context) {
ast_log(LOG_ERROR, "Failed to automatically find or create "
"context '%s' for SLA!\n", trunk->autocontext);
@@ -5417,7 +5417,7 @@ static int sla_build_station(struct ast_config *cfg, const char *cat)
if (!ast_strlen_zero(station->autocontext)) {
struct ast_context *context;
struct sla_trunk_ref *trunk_ref;
- context = ast_context_find_or_create(NULL, station->autocontext, sla_registrar);
+ context = ast_context_find_or_create(NULL, NULL, station->autocontext, sla_registrar);
if (!context) {
ast_log(LOG_ERROR, "Failed to automatically find or create "
"context '%s' for SLA!\n", station->autocontext);
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 5ab932c1c..bd2487d9b 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -6147,9 +6147,7 @@ static int load_module(void)
if (!reload_queues(0))
return AST_MODULE_LOAD_DECLINE;
- con = ast_context_find("app_queue_gosub_virtual_context");
- if (!con)
- con = ast_context_create(NULL, "app_queue_gosub_virtual_context", "app_queue");
+ con = ast_context_find_or_create(NULL, NULL, "app_queue_gosub_virtual_context", "app_queue");
if (!con)
ast_log(LOG_ERROR, "Queue virtual context 'app_queue_gosub_virtual_context' does not exist and unable to create\n");
else
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 1df3cf3e8..d19adbef0 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -10771,8 +10771,7 @@ static int set_config(char *config_file, int reload)
} else if (!strcasecmp(v->name, "regcontext")) {
ast_copy_string(regcontext, v->value, sizeof(regcontext));
/* Create context if it doesn't exist already */
- if (!ast_context_find(regcontext))
- ast_context_create(NULL, regcontext, "IAX2");
+ ast_context_find_or_create(NULL, NULL, regcontext, "IAX2");
} else if (!strcasecmp(v->name, "tos")) {
if (ast_str2tos(v->value, &tos))
ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 40645214a..a4afae1a9 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3388,6 +3388,7 @@ static void register_peer_exten(struct sip_peer *peer, int onoff)
{
char multi[256];
char *stringp, *ext, *context;
+ struct pbx_find_info q = { .stacklen = 0 };
/* XXX note that global_regcontext is both a global 'enable' flag and
* the name of the global regexten context, if not specified
@@ -3408,11 +3409,12 @@ static void register_peer_exten(struct sip_peer *peer, int onoff)
} else {
context = global_regcontext;
}
- if (onoff)
+ if (onoff) {
ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
ast_strdup(peer->name), ast_free_ptr, "SIP");
- else
+ } else if (pbx_find_extension(NULL, NULL, &q, context, ext, 1, NULL, "", E_MATCH)) {
ast_context_remove_extension(context, ext, 1, NULL);
+ }
}
}
@@ -20297,8 +20299,7 @@ static int reload_config(enum channelreloadreason reason)
/* Create contexts if they don't exist already */
while ((context = strsep(&stringp, "&"))) {
ast_copy_string(used_context, context, sizeof(used_context));
- if (!ast_context_find(context))
- ast_context_create(NULL, context, "SIP");
+ ast_context_find_or_create(NULL, NULL, context, "SIP");
}
ast_copy_string(global_regcontext, v->value, sizeof(global_regcontext));
} else if (!strcasecmp(v->name, "regextenonqualify")) {
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 44d88ae1f..4baa5771a 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -5801,8 +5801,7 @@ static int reload_config(void)
/* Create contexts if they don't exist already */
while ((context = strsep(&stringp, "&"))) {
ast_copy_string(used_context, context, sizeof(used_context));
- if (!ast_context_find(context))
- ast_context_create(NULL, context, "Skinny");
+ ast_context_find_or_create(NULL, NULL, context, "Skinny");
}
ast_copy_string(regcontext, v->value, sizeof(regcontext));
} else if (!strcasecmp(v->name, "dateformat")) {
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 1ba9b0d70..14e7af4b2 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -25,6 +25,7 @@
#include "asterisk/sched.h"
#include "asterisk/chanvars.h"
+#include "asterisk/hashtab.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
@@ -167,45 +168,36 @@ struct ast_app *pbx_findapp(const char *app);
int pbx_exec(struct ast_channel *c, struct ast_app *app, void *data);
/*!
- * \brief Register a new context
- *
- * \param extcontexts pointer to the ast_context structure pointer
- * \param name name of the new context
- * \param registrar registrar of the context
- *
- * This will first search for a context with your name. If it exists already, it will not
- * create a new one. If it does not exist, it will create a new one with the given name
- * and registrar.
- *
- * \return NULL on failure, and an ast_context structure on success
- */
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar);
-
-/*!
* \brief Register a new context or find an existing one
*
* \param extcontexts pointer to the ast_context structure pointer
+ * \param exttable pointer to the hashtable that contains all the elements in extcontexts
* \param name name of the new context
* \param registrar registrar of the context
*
+ * This function allows you to play in two environments: the global contexts (active dialplan)
+ * or an external context set of your choosing. To act on the external set, make sure extcontexts
+ * and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.
+ *
* This will first search for a context with your name. If it exists already, it will not
* create a new one. If it does not exist, it will create a new one with the given name
* and registrar.
*
* \return NULL on failure, and an ast_context structure on success
*/
-struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar);
+struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar);
/*!
* \brief Merge the temporary contexts into a global contexts list and delete from the
* global list the ones that are being added
*
- * \param extcontexts pointer to the ast_context structure pointer
+ * \param extcontexts pointer to the ast_context structure
+ * \param exttable pointer to the ast_hashtab structure that contains all the elements in extcontexts
* \param registrar of the context; if it's set the routine will delete all contexts
* that belong to that registrar; if NULL only the contexts that are specified
* in extcontexts
*/
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar);
+void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar);
/*!
* \brief Destroy a context (matches the specified context (or ANY context if NULL)
@@ -973,8 +965,18 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
struct ast_context *bypass, struct pbx_find_info *q,
const char *context, const char *exten, int priority,
const char *label, const char *callerid, enum ext_match_t action);
+
+
+/* every time a write lock is obtained for contexts,
+ a counter is incremented. You can check this via the
+ following func */
+
+int ast_wrlock_contexts_version(void);
+/* hashtable functions for contexts */
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+unsigned int ast_hashtab_hash_contexts(const void *obj);
#if defined(__cplusplus) || defined(c_plusplus)
}
diff --git a/include/asterisk/pval.h b/include/asterisk/pval.h
index edfd647b3..ea545e4a4 100644
--- a/include/asterisk/pval.h
+++ b/include/asterisk/pval.h
@@ -1,6 +1,7 @@
#ifndef _ASTERISK_PVAL_H
#define _ASTERISK_PVAL_H
+/* whatever includes this, better include asterisk/lock.h and asterisk/hashtab.h */
typedef enum
{
@@ -143,7 +144,7 @@ void destroy_extensions(struct ael_extension *exten);
static void gen_prios(struct ael_extension *exten, char *label, pval *statement, struct ael_extension *mother_exten, struct ast_context *context ); */
void set_priorities(struct ael_extension *exten);
void add_extensions(struct ael_extension *exten);
-void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root);
+void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root);
void destroy_pval(pval *item);
void destroy_pval_item(pval *item);
int is_float(char *arg );
diff --git a/main/features.c b/main/features.c
index d26ac5b91..2a284cb43 100644
--- a/main/features.c
+++ b/main/features.c
@@ -488,9 +488,7 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, in
ast_adsi_unload_session(peer);
}
- con = ast_context_find(parking_con);
- if (!con)
- con = ast_context_create(NULL, parking_con, registrar);
+ con = ast_context_find_or_create(NULL, NULL, parking_con, registrar);
if (!con) /* Still no context? Bad */
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
/* Tell the peer channel the number of the parking space */
@@ -2228,12 +2226,9 @@ static void *do_parking_thread(void *ignore)
if (peername_flat[i] == '/')
peername_flat[i]= '0';
}
- con = ast_context_find(parking_con_dial);
- if (!con) {
- con = ast_context_create(NULL, parking_con_dial, registrar);
- if (!con)
- ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
- }
+ con = ast_context_find_or_create(NULL, NULL, parking_con_dial, registrar);
+ if (!con)
+ ast_log(LOG_ERROR, "Parking dial context '%s' does not exist and unable to create\n", parking_con_dial);
if (con) {
char returnexten[AST_MAX_EXTENSION];
struct ast_datastore *features_datastore;
@@ -2822,7 +2817,7 @@ static int load_config(void)
ast_debug(1, "Removed old parking extension %s@%s\n", old_parking_ext, old_parking_con);
}
- if (!(con = ast_context_find(parking_con)) && !(con = ast_context_create(NULL, parking_con, registrar))) {
+ if (!(con = ast_context_find_or_create(NULL, NULL, parking_con, registrar))) {
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
return -1;
}
diff --git a/main/pbx.c b/main/pbx.c
index 8d9658f36..427c0cca9 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
+#include "asterisk/time.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
@@ -140,8 +141,8 @@ struct ast_exten {
void *data; /*!< Data to use (arguments) */
void (*datad)(void *); /*!< Data destructor */
struct ast_exten *peer; /*!< Next higher priority with our extension */
- struct ast_hashtab *peer_tree; /*!< Priorities list in tree form -- only on the head of the peer list */
- struct ast_hashtab *peer_label_tree; /*!< labeled priorities in the peer list -- only on the head of the peer list */
+ struct ast_hashtab *peer_table; /*!< Priorities list in hashtab form -- only on the head of the peer list */
+ struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
const char *registrar; /*!< Registrar */
struct ast_exten *next; /*!< Extension with a greater ID */
char stuff[0];
@@ -203,12 +204,13 @@ struct scoreboard /* make sure all fields are 0 before calling new_find_extensi
struct ast_context {
ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
struct ast_exten *root; /*!< The root of the list of extensions */
- struct ast_hashtab *root_tree; /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree */
+ struct ast_hashtab *root_table; /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree */
struct match_char *pattern_tree; /*!< A tree to speed up extension pattern matching */
struct ast_context *next; /*!< Link them together */
struct ast_include *includes; /*!< Include other contexts */
struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
const char *registrar; /*!< Registrar */
+ int refcount; /*!< each module that would have created this context should inc/dec this as appropriate */
AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
char name[0]; /*!< Name of the context */
@@ -327,17 +329,18 @@ static struct match_char *add_pattern_node(struct ast_context *con, struct match
static void create_match_char_tree(struct ast_context *con);
static struct ast_exten *get_canmatch_exten(struct match_char *node);
static void destroy_pattern_tree(struct match_char *pattern_tree);
-static int hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
-static unsigned int hashtab_hash_contexts(const void *obj);
+unsigned int ast_hashtab_hash_contexts(const void *obj);
static unsigned int hashtab_hash_extens(const void *obj);
static unsigned int hashtab_hash_priority(const void *obj);
static unsigned int hashtab_hash_labels(const void *obj);
+static void __ast_internal_context_destroy( struct ast_context *con);
/* labels, contexts are case sensitive priority numbers are ints */
-static int hashtab_compare_contexts(const void *ah_a, const void *ah_b)
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
{
const struct ast_context *ac = ah_a;
const struct ast_context *bc = ah_b;
@@ -376,7 +379,7 @@ static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
return strcmp(ac->label, bc->label);
}
-static unsigned int hashtab_hash_contexts(const void *obj)
+unsigned int ast_hashtab_hash_contexts(const void *obj)
{
const struct ast_context *ac = obj;
return ast_hashtab_hash_string(ac->name);
@@ -684,7 +687,7 @@ static struct pbx_builtin {
};
static struct ast_context *contexts;
-static struct ast_hashtab *contexts_tree = NULL;
+static struct ast_hashtab *contexts_table = NULL;
AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
@@ -1252,11 +1255,11 @@ static void create_match_char_tree(struct ast_context *con)
int biggest_bucket, resizes, numobjs, numbucks;
ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
- ast_hashtab_get_stats(con->root_tree, &biggest_bucket, &resizes, &numobjs, &numbucks);
+ ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
numobjs, numbucks, biggest_bucket, resizes);
#endif
- t1 = ast_hashtab_start_traversal(con->root_tree);
+ t1 = ast_hashtab_start_traversal(con->root_table);
while( (e1 = ast_hashtab_next(t1)) ) {
if (e1->exten)
add_exten_to_pattern_tree(con, e1, 0);
@@ -1582,12 +1585,13 @@ struct fake_context /* this struct is purely for matching in the hashtab */
{
ast_rwlock_t lock;
struct ast_exten *root;
- struct ast_hashtab *root_tree;
+ struct ast_hashtab *root_table;
struct match_char *pattern_tree;
struct ast_context *next;
struct ast_include *includes;
struct ast_ignorepat *ignorepats;
- const char *registrar;
+ const char *registrar;
+ int refcount;
AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
ast_mutex_t macrolock;
char name[256];
@@ -1599,8 +1603,8 @@ struct ast_context *ast_context_find(const char *name)
struct fake_context item;
strncpy(item.name,name,256);
ast_rdlock_contexts();
- if( contexts_tree ) {
- tmp = ast_hashtab_lookup(contexts_tree,&item);
+ if( contexts_table ) {
+ tmp = ast_hashtab_lookup(contexts_table,&item);
} else {
while ( (tmp = ast_walk_contexts(tmp)) ) {
if (!name || !strcasecmp(name, tmp->name))
@@ -1668,7 +1672,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
else { /* look in contexts */
struct fake_context item;
strncpy(item.name,context,256);
- tmp = ast_hashtab_lookup(contexts_tree,&item);
+ tmp = ast_hashtab_lookup(contexts_table,&item);
#ifdef NOTNOW
tmp = NULL;
while ((tmp = ast_walk_contexts(tmp)) ) {
@@ -1690,7 +1694,7 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
score.total_specificity = 0;
score.exten = 0;
score.total_length = 0;
- if (!tmp->pattern_tree && tmp->root_tree)
+ if (!tmp->pattern_tree && tmp->root_table)
{
create_match_char_tree(tmp);
#ifdef NEED_DEBUG
@@ -1750,9 +1754,9 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
if (action == E_FINDLABEL && label ) {
if (q->status < STATUS_NO_LABEL)
q->status = STATUS_NO_LABEL;
- e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
+ e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
} else {
- e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
+ e = ast_hashtab_lookup(eroot->peer_table, &pattern);
}
if (e) { /* found a valid match */
q->status = STATUS_SUCCESS;
@@ -1786,9 +1790,9 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
if (action == E_FINDLABEL && label ) {
if (q->status < STATUS_NO_LABEL)
q->status = STATUS_NO_LABEL;
- e = ast_hashtab_lookup(eroot->peer_label_tree, &pattern);
+ e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
} else {
- e = ast_hashtab_lookup(eroot->peer_tree, &pattern);
+ e = ast_hashtab_lookup(eroot->peer_table, &pattern);
}
#ifdef NOTNOW
while ( (e = ast_walk_extension_priorities(eroot, e)) ) {
@@ -2465,7 +2469,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
vare++;
}
if (brackets)
- ast_log(LOG_NOTICE, "Error in extension logic (missing '}')\n");
+ ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
len = vare - vars - 1;
/* Skip totally over variable string */
@@ -2552,7 +2556,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v
vare++;
}
if (brackets)
- ast_log(LOG_NOTICE, "Error in extension logic (missing ']')\n");
+ ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
len = vare - vars - 1;
/* Skip totally over expression */
@@ -3479,14 +3483,14 @@ static int increase_call_count(const struct ast_channel *c)
ast_mutex_lock(&maxcalllock);
if (option_maxcalls) {
if (countcalls >= option_maxcalls) {
- ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
+ ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
failed = -1;
}
}
if (option_maxload) {
getloadavg(&curloadavg, 1);
if (curloadavg >= option_maxload) {
- ast_log(LOG_NOTICE, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
+ ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
failed = -1;
}
}
@@ -3527,10 +3531,10 @@ static void destroy_exten(struct ast_exten *e)
if (e->priority == PRIORITY_HINT)
ast_remove_hint(e);
- if (e->peer_tree)
- ast_hashtab_destroy(e->peer_tree,0);
- if (e->peer_label_tree)
- ast_hashtab_destroy(e->peer_label_tree, 0);
+ if (e->peer_table)
+ ast_hashtab_destroy(e->peer_table,0);
+ if (e->peer_label_table)
+ ast_hashtab_destroy(e->peer_label_table, 0);
if (e->datad)
e->datad(e->data);
ast_free(e);
@@ -3627,8 +3631,7 @@ static struct ast_context *find_context_locked(const char *context)
ast_copy_string(item.name, context, sizeof(item.name));
ast_rdlock_contexts();
-
- c = ast_hashtab_lookup(contexts_tree,&item);
+ c = ast_hashtab_lookup(contexts_table,&item);
#ifdef NOTNOW
@@ -3789,19 +3792,19 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
/* Handle this is in the new world */
#ifdef NEED_DEBUG
- ast_log(LOG_NOTICE,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar);
+ ast_verb(3,"Removing %s/%s/%d from trees, registrar=%s\n", con->name, extension, priority, registrar);
#endif
/* find this particular extension */
ex.exten = dummy_name;
ex.matchcid = 0;
ast_copy_string(dummy_name,extension, sizeof(dummy_name));
- exten = ast_hashtab_lookup(con->root_tree, &ex);
+ exten = ast_hashtab_lookup(con->root_table, &ex);
if (exten) {
if (priority == 0)
{
- exten2 = ast_hashtab_remove_this_object(con->root_tree, exten);
+ exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
if (!exten2)
- ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_tree\n", extension, con->name);
+ ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
if (con->pattern_tree) {
struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
@@ -3815,24 +3818,28 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
}
} else {
ex.priority = priority;
- exten2 = ast_hashtab_lookup(exten->peer_tree, &ex);
+ exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
if (exten2) {
if (exten2->label) { /* if this exten has a label, remove that, too */
- exten3 = ast_hashtab_remove_this_object(exten->peer_label_tree,exten2);
+ exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
if (!exten3)
- ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_tree of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
+ ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
}
- exten3 = ast_hashtab_remove_this_object(exten->peer_tree, exten2);
+ exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
if (!exten3)
- ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_tree of context %s, extension %s!\n", priority, con->name, exten2->exten);
- if (ast_hashtab_size(exten->peer_tree) == 0) {
+ ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten);
+ if (exten2 == exten && exten2->peer) {
+ exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
+ ast_hashtab_insert_immediate(con->root_table, exten2->peer);
+ }
+ if (ast_hashtab_size(exten->peer_table) == 0) {
/* well, if the last priority of an exten is to be removed,
then, the extension is removed, too! */
- exten3 = ast_hashtab_remove_this_object(con->root_tree, exten);
+ exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
if (!exten3)
- ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_tree (%s) (priority %d)\n", exten->exten, con->name, priority);
+ ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
if (con->pattern_tree) {
struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
if (x->exten) { /* this test for safety purposes */
@@ -3848,7 +3855,7 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
}
} else {
/* hmmm? this exten is not in this pattern tree? */
- ast_log(LOG_WARNING,"Cannot find extension %s in root_tree in context %s\n",
+ ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
extension, con->name);
}
#ifdef NEED_DEBUG
@@ -3905,10 +3912,10 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
*/
struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
if (next_node && next_node == peer->peer) {
- next_node->peer_tree = exten->peer_tree; /* move the priority hash tabs over */
- exten->peer_tree = 0;
- next_node->peer_label_tree = exten->peer_label_tree;
- exten->peer_label_tree = 0;
+ next_node->peer_table = exten->peer_table; /* move the priority hash tabs over */
+ exten->peer_table = 0;
+ next_node->peer_label_table = exten->peer_label_table;
+ exten->peer_label_table = 0;
}
if (!prev_exten) { /* change the root... */
con->root = next_node;
@@ -3946,7 +3953,7 @@ int ast_context_lockmacro(const char *context)
ast_rdlock_contexts();
strncpy(item.name,context,256);
- c = ast_hashtab_lookup(contexts_tree,&item);
+ c = ast_hashtab_lookup(contexts_table,&item);
if (c)
ret = 0;
@@ -3984,7 +3991,7 @@ int ast_context_unlockmacro(const char *context)
ast_rdlock_contexts();
strncpy(item.name, context, 256);
- c = ast_hashtab_lookup(contexts_tree,&item);
+ c = ast_hashtab_lookup(contexts_table,&item);
if (c)
ret = 0;
#ifdef NOTNOW
@@ -4578,7 +4585,7 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
if (exten) {
/* Check all includes for the requested extension */
if (includecount >= AST_PBX_MAX_STACK) {
- ast_log(LOG_NOTICE, "Maximum include depth exceeded!\n");
+ ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
} else {
int dupe = 0;
int x;
@@ -5127,42 +5134,37 @@ int ast_unregister_application(const char *app)
return tmp ? 0 : -1;
}
-static struct ast_context *__ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar, int existsokay)
+struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
{
struct ast_context *tmp, **local_contexts;
struct fake_context search;
int length = sizeof(struct ast_context) + strlen(name) + 1;
- if (!contexts_tree) {
- contexts_tree = ast_hashtab_create(17,
- hashtab_compare_contexts,
+ if (!contexts_table) {
+ contexts_table = ast_hashtab_create(17,
+ ast_hashtab_compare_contexts,
ast_hashtab_resize_java,
ast_hashtab_newsize_java,
- hashtab_hash_contexts,
+ ast_hashtab_hash_contexts,
0);
}
+ strncpy(search.name,name,sizeof(search.name));
if (!extcontexts) {
ast_rdlock_contexts();
local_contexts = &contexts;
- strncpy(search.name,name,sizeof(search.name));
- tmp = ast_hashtab_lookup(contexts_tree, &search);
- if (!existsokay && tmp) {
- ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
- }
+ tmp = ast_hashtab_lookup(contexts_table, &search);
ast_unlock_contexts();
- if (tmp)
+ if (tmp) {
+ tmp->refcount++;
return tmp;
+ }
} else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
local_contexts = extcontexts;
- for (tmp = *local_contexts; tmp; tmp = tmp->next) {
- if (!strcasecmp(tmp->name, name)) {
- if (!existsokay) {
- ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name);
- tmp = NULL;
- }
- return tmp;
- }
+ tmp = ast_hashtab_lookup(exttable, &search);
+ if (tmp) {
+ tmp->refcount++;
+ return tmp;
}
}
@@ -5171,19 +5173,26 @@ static struct ast_context *__ast_context_create(struct ast_context **extcontexts
ast_mutex_init(&tmp->macrolock);
strcpy(tmp->name, name);
tmp->root = NULL;
- tmp->root_tree = NULL;
+ tmp->root_table = NULL;
tmp->registrar = registrar;
tmp->includes = NULL;
tmp->ignorepats = NULL;
+ tmp->refcount = 1;
+ } else {
+ ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
+ return NULL;
}
+
if (!extcontexts) {
ast_wrlock_contexts();
tmp->next = *local_contexts;
*local_contexts = tmp;
- ast_hashtab_insert_safe(contexts_tree, tmp); /*put this context into the tree */
+ ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
ast_unlock_contexts();
} else {
tmp->next = *local_contexts;
+ if (exttable)
+ ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
*local_contexts = tmp;
}
ast_debug(1, "Registered context '%s'\n", tmp->name);
@@ -5191,16 +5200,7 @@ static struct ast_context *__ast_context_create(struct ast_context **extcontexts
return tmp;
}
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
- return __ast_context_create(extcontexts, name, registrar, 0);
-}
-
-struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
- return __ast_context_create(extcontexts, name, registrar, 1);
-}
-void __ast_context_destroy(struct ast_context *con, const char *registrar);
+void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
struct store_hint {
char *context;
@@ -5213,17 +5213,89 @@ struct store_hint {
AST_LIST_HEAD(store_hints, store_hint);
+/* the purpose of this routine is to duplicate a context, with all its substructure,
+ except for any extens that have a matching registrar */
+static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
+{
+ struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
+ struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
+ struct ast_hashtab_iter *exten_iter;
+ struct ast_hashtab_iter *prio_iter;
+ int insert_count = 0;
+
+ /* We'll traverse all the extensions/prios, and see which are not registrar'd with
+ the current registrar, and copy them to the new context. If the new context does not
+ exist, we'll create it "on demand". If no items are in this context to copy, then we'll
+ only create the empty matching context if the old one meets the criteria */
+ if (context->root_table) {
+ exten_iter = ast_hashtab_start_traversal(context->root_table);
+ while ((exten_item=ast_hashtab_next(exten_iter))) {
+ if (new) {
+ new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
+ } else {
+ new_exten_item = NULL;
+ }
+ prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
+ while ((prio_item=ast_hashtab_next(prio_iter))) {
+ int res1;
+
+ if (new_exten_item) {
+ new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
+ } else {
+ new_prio_item = NULL;
+ }
+ if (strcmp(prio_item->registrar,registrar) == 0) {
+ continue;
+ }
+ /* make sure the new context exists, so we have somewhere to stick this exten/prio */
+ if (!new) {
+ new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
+ }
+ if (!new) {
+ ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
+ return; /* no sense continuing. */
+ }
+ /* we will not replace existing entries in the new context with stuff from the old context.
+ but, if this is because of some sort of registrar conflict, we ought to say something... */
+ res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label,
+ prio_item->cidmatch, prio_item->app, prio_item->data, prio_item->datad, prio_item->registrar);
+ if (!res1 && new_exten_item && new_prio_item){
+ ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
+ context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
+ } else {
+ prio_item->data = NULL; /* we pass the priority data from the old to the new */
+ insert_count++;
+ }
+ }
+ ast_hashtab_end_traversal(prio_iter);
+ }
+ ast_hashtab_end_traversal(exten_iter);
+ }
+
+ if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
+ (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
+
+ /* we could have given it the registrar of the other module who incremented the refcount,
+ but that's not available, so we give it the registrar we know about */
+ new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
+ }
+}
+
+
/* XXX this does not check that multiple contexts are merged */
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
+void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
{
- struct ast_context *tmp, *lasttmp = NULL;
+ double ft;
+ struct ast_context *tmp, *oldcontextslist;
+ struct ast_hashtab *oldtable;
struct store_hints store = AST_LIST_HEAD_INIT_VALUE;
struct store_hint *this;
struct ast_hint *hint;
struct ast_exten *exten;
int length;
struct ast_state_cb *thiscb, *prevcb;
-
+ struct ast_hashtab_iter *iter;
+
/* it is very important that this function hold the hint list lock _and_ the conlock
during its operation; not only do we need to ensure that the list of contexts
and extensions does not change, but also that no hint callbacks (watchers) are
@@ -5232,8 +5304,29 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char
in addition, the locks _must_ be taken in this order, because there are already
other code paths that use this order
*/
+
+ struct timeval begintime, writelocktime, endlocktime, enddeltime;
+ int wrlock_ver;
+
+ begintime = ast_tvnow();
+ ast_rdlock_contexts();
+ iter = ast_hashtab_start_traversal(contexts_table);
+ while ((tmp=ast_hashtab_next(iter))) {
+ context_merge(extcontexts, exttable, tmp, registrar);
+ }
+ ast_hashtab_end_traversal(iter);
+ wrlock_ver = ast_wrlock_contexts_version();
+
+ ast_unlock_contexts(); /* this feels real retarded, but you must do
+ what you must do If this isn't done, the following
+ wrlock is a guraranteed deadlock */
ast_wrlock_contexts();
+ if (ast_wrlock_contexts_version() > wrlock_ver+1) {
+ ast_log(LOG_WARNING,"Something changed the contexts in the middle of merging contexts!\n");
+ }
+
AST_RWLIST_WRLOCK(&hints);
+ writelocktime = ast_tvnow();
/* preserve all watchers for hints associated with this registrar */
AST_RWLIST_TRAVERSE(&hints, hint, list) {
@@ -5252,36 +5345,14 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char
}
}
- tmp = *extcontexts;
- if (registrar) {
- /* XXX remove previous contexts from same registrar */
- ast_debug(1, "must remove any reg %s\n", registrar);
- __ast_context_destroy(NULL,registrar);
- while (tmp) {
- lasttmp = tmp;
- tmp = tmp->next;
- }
- } else {
- /* XXX remove contexts with the same name */
- while (tmp) {
- ast_log(LOG_WARNING, "must remove %s reg %s\n", tmp->name, tmp->registrar);
- __ast_context_destroy(tmp,tmp->registrar);
- lasttmp = tmp;
- tmp = tmp->next;
- }
- }
- tmp = *extcontexts;
- while (tmp) {
- ast_hashtab_insert_safe(contexts_tree, tmp); /*put this context into the tree */
- tmp = tmp->next;
- }
- if (lasttmp) {
- lasttmp->next = contexts;
- contexts = *extcontexts;
- *extcontexts = NULL;
- } else
- ast_log(LOG_WARNING, "Requested contexts didn't get merged\n");
+ /* save the old table and list */
+ oldtable = contexts_table;
+ oldcontextslist = contexts;
+ /* move in the new table and list */
+ contexts_table = exttable;
+ contexts = *extcontexts;
+
/* restore the watchers for hints that can be found; notify those that
cannot be restored
*/
@@ -5316,7 +5387,36 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char
AST_RWLIST_UNLOCK(&hints);
ast_unlock_contexts();
+ endlocktime = ast_tvnow();
+
+ /* the old list and hashtab no longer are relevant, delete them while the rest of asterisk
+ is now freely using the new stuff instead */
+
+ ast_hashtab_destroy(oldtable, NULL);
+ for (tmp = oldcontextslist; tmp; ) {
+ struct ast_context *next; /* next starting point */
+ next = tmp->next;
+ __ast_internal_context_destroy(tmp);
+ tmp = next;
+ }
+ enddeltime = ast_tvnow();
+
+ ft = ast_tvdiff_us(writelocktime, begintime);
+ ft /= 1000000.0;
+ ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
+
+ ft = ast_tvdiff_us(endlocktime, writelocktime);
+ ft /= 1000000.0;
+ ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
+
+ ft = ast_tvdiff_us(enddeltime, endlocktime);
+ ft /= 1000000.0;
+ ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
+
+ ft = ast_tvdiff_us(enddeltime, begintime);
+ ft /= 1000000.0;
+ ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
return;
}
@@ -5854,6 +5954,7 @@ int ast_add_extension(const char *context, int replace, const char *extension,
application, data, datad, registrar);
ast_unlock_contexts();
}
+
return ret;
}
@@ -5980,9 +6081,9 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
break;
}
if (!e) { /* go at the end, and ep is surely set because the list is not empty */
- ast_hashtab_insert_safe(eh->peer_tree, tmp);
+ ast_hashtab_insert_safe(eh->peer_table, tmp);
if (tmp->label)
- ast_hashtab_insert_safe(eh->peer_label_tree, tmp);
+ ast_hashtab_insert_safe(eh->peer_label_table, tmp);
ep->peer = tmp;
return 0; /* success */
}
@@ -6002,25 +6103,25 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
tmp->next = e->next; /* not meaningful if we are not first in the peer list */
tmp->peer = e->peer; /* always meaningful */
if (ep) { /* We're in the peer list, just insert ourselves */
- ast_hashtab_remove_object_via_lookup(eh->peer_tree,e);
+ ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
if (e->label)
- ast_hashtab_remove_object_via_lookup(eh->peer_label_tree,e);
- ast_hashtab_insert_safe(eh->peer_tree,tmp);
+ ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
+ ast_hashtab_insert_safe(eh->peer_table,tmp);
if (tmp->label)
- ast_hashtab_insert_safe(eh->peer_label_tree,tmp);
+ ast_hashtab_insert_safe(eh->peer_label_table,tmp);
ep->peer = tmp;
} else if (el) { /* We're the first extension. Take over e's functions */
struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
- tmp->peer_tree = e->peer_tree;
- tmp->peer_label_tree = e->peer_label_tree;
- ast_hashtab_remove_object_via_lookup(tmp->peer_tree,e);
- ast_hashtab_insert_safe(tmp->peer_tree,tmp);
+ tmp->peer_table = e->peer_table;
+ tmp->peer_label_table = e->peer_label_table;
+ ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
+ ast_hashtab_insert_safe(tmp->peer_table,tmp);
if (e->label)
- ast_hashtab_remove_object_via_lookup(tmp->peer_label_tree,e);
+ ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
if (tmp->label)
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
- ast_hashtab_remove_object_via_lookup(con->root_tree, e);
- ast_hashtab_insert_safe(con->root_tree, tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table, e);
+ ast_hashtab_insert_safe(con->root_table, tmp);
el->next = tmp;
/* The pattern trie points to this exten; replace the pointer,
and all will be well */
@@ -6032,18 +6133,18 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
}
} else { /* We're the very first extension. */
struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
- ast_hashtab_remove_object_via_lookup(con->root_tree,e);
- ast_hashtab_insert_safe(con->root_tree,tmp);
- tmp->peer_tree = e->peer_tree;
- tmp->peer_label_tree = e->peer_label_tree;
- ast_hashtab_remove_object_via_lookup(tmp->peer_tree,e);
- ast_hashtab_insert_safe(tmp->peer_tree,tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table, e);
+ ast_hashtab_insert_safe(con->root_table, tmp);
+ tmp->peer_table = e->peer_table;
+ tmp->peer_label_table = e->peer_label_table;
+ ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
+ ast_hashtab_insert_safe(tmp->peer_table, tmp);
if (e->label)
- ast_hashtab_remove_object_via_lookup(tmp->peer_label_tree,e);
+ ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
if (tmp->label)
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
- ast_hashtab_remove_object_via_lookup(con->root_tree, e);
- ast_hashtab_insert_safe(con->root_tree, tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table, e);
+ ast_hashtab_insert_safe(con->root_table, tmp);
con->root = tmp;
/* The pattern trie points to this exten; replace the pointer,
and all will be well */
@@ -6064,20 +6165,20 @@ static int add_pri(struct ast_context *con, struct ast_exten *tmp,
tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
if (ep) { /* Easy enough, we're just in the peer list */
if (tmp->label)
- ast_hashtab_insert_safe(eh->peer_label_tree, tmp);
- ast_hashtab_insert_safe(eh->peer_tree, tmp);
+ ast_hashtab_insert_safe(eh->peer_label_table, tmp);
+ ast_hashtab_insert_safe(eh->peer_table, tmp);
ep->peer = tmp;
} else { /* we are the first in some peer list, so link in the ext list */
- tmp->peer_tree = e->peer_tree;
- tmp->peer_label_tree = e ->peer_label_tree;
- e->peer_tree = 0;
- e->peer_label_tree = 0;
- ast_hashtab_insert_safe(tmp->peer_tree,tmp);
+ tmp->peer_table = e->peer_table;
+ tmp->peer_label_table = e->peer_label_table;
+ e->peer_table = 0;
+ e->peer_label_table = 0;
+ ast_hashtab_insert_safe(tmp->peer_table, tmp);
if (tmp->label) {
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
}
- ast_hashtab_remove_object_via_lookup(con->root_tree,e);
- ast_hashtab_insert_safe(con->root_tree,tmp);
+ ast_hashtab_remove_object_via_lookup(con->root_table, e);
+ ast_hashtab_insert_safe(con->root_table, tmp);
if (el)
el->next = tmp; /* in the middle... */
else
@@ -6159,6 +6260,9 @@ int ast_add_extension2(struct ast_context *con,
if (!(tmp = ast_calloc(1, length)))
return -1;
+ if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
+ label = 0;
+
/* use p as dst in assignments, as the fields are const char * */
p = tmp->stuff;
if (label) {
@@ -6170,7 +6274,7 @@ int ast_add_extension2(struct ast_context *con,
p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
tmp->priority = priority;
tmp->cidmatch = p; /* but use p for assignments below */
- if (callerid) {
+ if (!ast_strlen_zero(callerid)) {
p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
tmp->matchcid = 1;
} else {
@@ -6192,11 +6296,11 @@ int ast_add_extension2(struct ast_context *con,
dummy_exten.exten = dummy_name;
dummy_exten.matchcid = 0;
dummy_exten.cidmatch = 0;
- tmp2 = ast_hashtab_lookup(con->root_tree,&dummy_exten);
+ tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
if (!tmp2) {
/* hmmm, not in the trie; */
add_exten_to_pattern_tree(con, tmp, 0);
- ast_hashtab_insert_safe(con->root_tree, tmp); /* for the sake of completeness */
+ ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
}
}
res = 0; /* some compilers will think it is uninitialized otherwise */
@@ -6230,48 +6334,48 @@ int ast_add_extension2(struct ast_context *con,
tmp->next = e;
if (el) { /* there is another exten already in this context */
el->next = tmp;
- tmp->peer_tree = ast_hashtab_create(13,
+ tmp->peer_table = ast_hashtab_create(13,
hashtab_compare_exten_numbers,
ast_hashtab_resize_java,
ast_hashtab_newsize_java,
hashtab_hash_priority,
0);
- tmp->peer_label_tree = ast_hashtab_create(7,
+ tmp->peer_label_table = ast_hashtab_create(7,
hashtab_compare_exten_labels,
ast_hashtab_resize_java,
ast_hashtab_newsize_java,
hashtab_hash_labels,
0);
if (label)
- ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
- ast_hashtab_insert_safe(tmp->peer_tree, tmp);
+ ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
+ ast_hashtab_insert_safe(tmp->peer_table, tmp);
} else { /* this is the first exten in this context */
- if (!con->root_tree)
- con->root_tree = ast_hashtab_create(27,
+ if (!con->root_table)
+ con->root_table = ast_hashtab_create(27,
hashtab_compare_extens,
ast_hashtab_resize_java,
ast_hashtab_newsize_java,
hashtab_hash_extens,
0);
con->root = tmp;
- con->root->peer_tree = ast_hashtab_create(13,
+ con->root->peer_table = ast_hashtab_create(13,
hashtab_compare_exten_numbers,
ast_hashtab_resize_java,
ast_hashtab_newsize_java,
hashtab_hash_priority,
0);
- con->root->peer_label_tree = ast_hashtab_create(7,
+ con->root->peer_label_table = ast_hashtab_create(7,
hashtab_compare_exten_labels,
ast_hashtab_resize_java,
ast_hashtab_newsize_java,
hashtab_hash_labels,
0);
if (label)
- ast_hashtab_insert_safe(con->root->peer_label_tree,tmp);
- ast_hashtab_insert_safe(con->root->peer_tree, tmp);
+ ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
+ ast_hashtab_insert_safe(con->root->peer_table, tmp);
}
- ast_hashtab_insert_safe(con->root_tree, tmp);
+ ast_hashtab_insert_safe(con->root_table, tmp);
ast_unlock_context(con);
if (tmp->priority == PRIORITY_HINT)
ast_add_hint(tmp);
@@ -6287,7 +6391,7 @@ int ast_add_extension2(struct ast_context *con,
}
if (tmp->matchcid) {
- ast_verb(3, "Added extension '%s' priority %d (CID match '%s')to %s\n",
+ ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
tmp->exten, tmp->priority, tmp->cidmatch, con->name);
} else {
ast_verb(3, "Added extension '%s' priority %d to %s\n",
@@ -6684,68 +6788,125 @@ outgoing_app_cleanup:
return res;
}
-void __ast_context_destroy(struct ast_context *con, const char *registrar)
+/* this is the guts of destroying a context --
+ freeing up the structure, traversing and destroying the
+ extensions, switches, ignorepats, includes, etc. etc. */
+
+static void __ast_internal_context_destroy( struct ast_context *con)
{
- struct ast_context *tmp, *tmpl=NULL;
struct ast_include *tmpi;
struct ast_sw *sw;
struct ast_exten *e, *el, *en;
struct ast_ignorepat *ipi;
+ struct ast_context *tmp = con;
- for (tmp = contexts; tmp; ) {
- struct ast_context *next; /* next starting point */
+ for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
+ struct ast_include *tmpil = tmpi;
+ tmpi = tmpi->next;
+ ast_free(tmpil);
+ }
+ for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
+ struct ast_ignorepat *ipl = ipi;
+ ipi = ipi->next;
+ ast_free(ipl);
+ }
+ /* destroy the hash tabs */
+ if (tmp->root_table) {
+ ast_hashtab_destroy(tmp->root_table, 0);
+ }
+ /* and destroy the pattern tree */
+ if (tmp->pattern_tree)
+ destroy_pattern_tree(tmp->pattern_tree);
+
+ while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
+ ast_free(sw);
+ for (e = tmp->root; e;) {
+ for (en = e->peer; en;) {
+ el = en;
+ en = en->peer;
+ destroy_exten(el);
+ }
+ el = e;
+ e = e->next;
+ destroy_exten(el);
+ }
+ tmp->root = NULL;
+ ast_rwlock_destroy(&tmp->lock);
+ ast_free(tmp);
+}
+
+
+void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
+{
+ struct ast_context *tmp, *tmpl=NULL;
+ struct ast_exten *exten_item, *prio_item;
+
+
+ for (tmp = list; tmp; ) {
+ struct ast_context *next = NULL; /* next starting point */
for (; tmp; tmpl = tmp, tmp = tmp->next) {
ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
- if ( (!registrar || !strcasecmp(registrar, tmp->registrar)) &&
- (!con || !strcasecmp(tmp->name, con->name)) )
+ if ( registrar || (con && strcasecmp(tmp->name, con->name)) )
break; /* found it */
}
if (!tmp) /* not found, we are done */
break;
ast_wrlock_context(tmp);
- ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
- ast_hashtab_remove_this_object(contexts_tree,tmp);
-
- next = tmp->next;
- if (tmpl)
- tmpl->next = next;
- else
- contexts = next;
- /* Okay, now we're safe to let it go -- in a sense, we were
- ready to let it go as soon as we locked it. */
- ast_unlock_context(tmp);
- for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
- struct ast_include *tmpil = tmpi;
- tmpi = tmpi->next;
- ast_free(tmpil);
- }
- for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
- struct ast_ignorepat *ipl = ipi;
- ipi = ipi->next;
- ast_free(ipl);
- }
- /* destroy the hash tabs */
- if (tmp->root_tree) {
- ast_hashtab_destroy(tmp->root_tree, 0);
- }
- /* and destroy the pattern tree */
- if (tmp->pattern_tree)
- destroy_pattern_tree(tmp->pattern_tree);
-
- while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
- ast_free(sw);
- for (e = tmp->root; e;) {
- for (en = e->peer; en;) {
- el = en;
- en = en->peer;
- destroy_exten(el);
+
+ if (registrar) {
+ /* then search thru and remove any extens that match registrar. */
+ struct ast_hashtab_iter *exten_iter;
+ struct ast_hashtab_iter *prio_iter;
+
+ if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
+ exten_iter = ast_hashtab_start_traversal(tmp->root_table);
+ while ((exten_item=ast_hashtab_next(exten_iter))) {
+ prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
+ while ((prio_item=ast_hashtab_next(prio_iter))) {
+ if (strcmp(prio_item->registrar, registrar) != 0) {
+ continue;
+ }
+ ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
+ tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
+
+ ast_context_remove_extension2(tmp, prio_item->exten, prio_item->priority, registrar);
+ }
+ ast_hashtab_end_traversal(prio_iter);
+ }
+ ast_hashtab_end_traversal(exten_iter);
}
- el = e;
- e = e->next;
- destroy_exten(el);
+
+ /* delete the context if it's registrar matches, is empty, has refcount of 1, */
+ if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root) {
+ ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
+ ast_hashtab_remove_this_object(contexttab, tmp);
+
+ next = tmp->next;
+ if (tmpl)
+ tmpl->next = next;
+ else
+ contexts = next;
+ /* Okay, now we're safe to let it go -- in a sense, we were
+ ready to let it go as soon as we locked it. */
+ ast_unlock_context(tmp);
+ __ast_internal_context_destroy(tmp);
+ }
+ } else if (con) {
+ ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
+ ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
+ ast_hashtab_remove_this_object(contexttab, tmp);
+
+ next = tmp->next;
+ if (tmpl)
+ tmpl->next = next;
+ else
+ contexts = next;
+ /* Okay, now we're safe to let it go -- in a sense, we were
+ ready to let it go as soon as we locked it. */
+ ast_unlock_context(tmp);
+ __ast_internal_context_destroy(tmp);
}
- ast_rwlock_destroy(&tmp->lock);
- ast_free(tmp);
+
/* if we have a specific match, we are done, otherwise continue */
tmp = con ? NULL : next;
}
@@ -6754,7 +6915,7 @@ void __ast_context_destroy(struct ast_context *con, const char *registrar)
void ast_context_destroy(struct ast_context *con, const char *registrar)
{
ast_wrlock_contexts();
- __ast_context_destroy(con,registrar);
+ __ast_context_destroy(contexts, contexts_table, con,registrar);
ast_unlock_contexts();
}
@@ -6899,7 +7060,7 @@ static int pbx_builtin_hangup(struct ast_channel *chan, void *data)
return -1;
}
- ast_log(LOG_NOTICE, "Invalid cause given to Hangup(): \"%s\"\n", (char *) data);
+ ast_log(LOG_WARNING, "Invalid cause given to Hangup(): \"%s\"\n", (char *) data);
}
if (!chan->hangupcause) {
@@ -7568,12 +7729,21 @@ int load_pbx(void)
return 0;
}
+static int conlock_wrlock_version = 0;
+
+int ast_wrlock_contexts_version(void)
+{
+ return conlock_wrlock_version;
+}
/*
* Lock context list functions ...
*/
int ast_wrlock_contexts()
{
+ int res = ast_rwlock_wrlock(&conlock);
+ if (!res)
+ ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
return ast_rwlock_wrlock(&conlock);
}
diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c
index fa4b7d516..0e40c9496 100644
--- a/pbx/pbx_ael.c
+++ b/pbx/pbx_ael.c
@@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/callerid.h"
+#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
#include "asterisk/pval.h"
#ifdef AAL_ARGCHECK
@@ -88,7 +89,7 @@ void linkprio(struct ael_extension *exten, struct ael_priority *prio);
void destroy_extensions(struct ael_extension *exten);
void set_priorities(struct ael_extension *exten);
void add_extensions(struct ael_extension *exten);
-void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root);
+void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root);
void destroy_pval(pval *item);
void destroy_pval_item(pval *item);
int is_float(char *arg );
@@ -108,6 +109,8 @@ static int pbx_load_module(void)
int errs=0, sem_err=0, sem_warn=0, sem_note=0;
char *rfilename;
struct ast_context *local_contexts=NULL, *con;
+ struct ast_hashtab *local_table=NULL;
+
struct pval *parse_tree;
ast_log(LOG_NOTICE, "Starting AEL load process.\n");
@@ -127,10 +130,13 @@ static int pbx_load_module(void)
ael2_semantic_check(parse_tree, &sem_err, &sem_warn, &sem_note);
if (errs == 0 && sem_err == 0) {
ast_log(LOG_NOTICE, "AEL load process: checked config file name '%s'.\n", rfilename);
- ast_compile_ael2(&local_contexts, parse_tree);
+ local_table = ast_hashtab_create(11, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
+ ast_compile_ael2(&local_contexts, local_table, parse_tree);
ast_log(LOG_NOTICE, "AEL load process: compiled config file name '%s'.\n", rfilename);
- ast_merge_contexts_and_delete(&local_contexts, registrar);
+ ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
+ local_table = NULL; /* it's the dialplan global now */
+ local_contexts = NULL;
ast_log(LOG_NOTICE, "AEL load process: merged config file name '%s'.\n", rfilename);
for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
ast_context_verify_includes(con);
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index 4a7a3d368..bf707a950 100644
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -51,7 +51,7 @@ static int extenpatternmatchnew_config = 0;
AST_MUTEX_DEFINE_STATIC(save_dialplan_lock);
static struct ast_context *local_contexts = NULL;
-
+static struct ast_hashtab *local_table = NULL;
/*
* Prototypes for our completion functions
*/
@@ -1371,7 +1371,6 @@ static int pbx_load_config(const char *config_file)
const char *aft;
const char *newpm;
struct ast_flags config_flags = { 0 };
-
cfg = ast_config_load(config_file, config_flags);
if (!cfg)
return 0;
@@ -1399,7 +1398,7 @@ static int pbx_load_config(const char *config_file)
/* All categories but "general" or "globals" are considered contexts */
if (!strcasecmp(cxt, "general") || !strcasecmp(cxt, "globals"))
continue;
- con=ast_context_find_or_create(&local_contexts,cxt, registrar);
+ con=ast_context_find_or_create(&local_contexts, local_table, cxt, registrar);
if (con == NULL)
continue;
@@ -1601,7 +1600,7 @@ static void pbx_load_users(void)
/* Only create a context here when it is really needed. Otherwise default empty context
created by pbx_config may conflict with the one explicitly created by pbx_ael */
if (!con)
- con = ast_context_find_or_create(&local_contexts, userscontext, registrar);
+ con = ast_context_find_or_create(&local_contexts, local_table, userscontext, registrar);
if (!con) {
ast_log(LOG_ERROR, "Can't find/create user context '%s'\n", userscontext);
@@ -1626,12 +1625,17 @@ static int pbx_load_module(void)
{
struct ast_context *con;
- if(!pbx_load_config(config))
+ if (!local_table)
+ local_table = ast_hashtab_create(17, ast_hashtab_compare_contexts, ast_hashtab_resize_java, ast_hashtab_newsize_java, ast_hashtab_hash_contexts, 0);
+
+ if (!pbx_load_config(config))
return AST_MODULE_LOAD_DECLINE;
pbx_load_users();
- ast_merge_contexts_and_delete(&local_contexts, registrar);
+ ast_merge_contexts_and_delete(&local_contexts, local_table, registrar);
+ local_table = NULL; /* the local table has been moved into the global one. */
+ local_contexts = NULL;
for (con = NULL; (con = ast_walk_contexts(con));)
ast_context_verify_includes(con);
diff --git a/res/ael/ael.flex b/res/ael/ael.flex
index cf2d36a2c..1ca6427f4 100644
--- a/res/ael/ael.flex
+++ b/res/ael/ael.flex
@@ -60,6 +60,7 @@
%option bison-locations
%{
+#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/types.h>
@@ -70,9 +71,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define GLOB_ABORTED GLOB_ABEND
#endif
# include <glob.h>
-
#include "asterisk/logger.h"
#include "asterisk/utils.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
#include "ael/ael.tab.h"
#include "asterisk/ael_structs.h"
diff --git a/res/ael/ael.tab.c b/res/ael/ael.tab.c
index aa1ec0fad..16c62ba71 100644
--- a/res/ael/ael.tab.c
+++ b/res/ael/ael.tab.c
@@ -188,6 +188,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include "asterisk/logger.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
pval * linku1(pval *head, pval *tail);
@@ -227,14 +229,14 @@ static char *ael_token_subst(const char *mess);
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 54 "ael.y"
+#line 56 "ael.y"
{
int intval; /* integer value, typically flags */
char *str; /* strings */
struct pval *pval; /* full objects */
}
/* Line 198 of yacc.c. */
-#line 238 "ael.tab.c"
+#line 240 "ael.tab.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -256,7 +258,7 @@ typedef struct YYLTYPE
/* Copy the second part of user declarations. */
-#line 60 "ael.y"
+#line 62 "ael.y"
/* declaring these AFTER the union makes things a lot simpler! */
void yyerror(YYLTYPE *locp, struct parse_io *parseio, char const *s);
@@ -279,7 +281,7 @@ static pval *update_last(pval *, YYLTYPE *);
/* Line 221 of yacc.c. */
-#line 283 "ael.tab.c"
+#line 285 "ael.tab.c"
#ifdef short
# undef short
@@ -625,21 +627,21 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 186, 186, 189, 190, 191, 194, 195, 196, 197,
- 200, 201, 204, 213, 214, 215, 216, 217, 220, 226,
- 232, 233, 234, 237, 237, 243, 243, 250, 251, 252,
- 253, 256, 257, 258, 261, 262, 263, 264, 265, 266,
- 267, 268, 269, 272, 277, 281, 289, 294, 299, 308,
- 309, 310, 316, 321, 325, 333, 333, 337, 340, 343,
- 354, 355, 362, 363, 367, 371, 377, 378, 383, 391,
- 392, 396, 402, 411, 414, 415, 416, 419, 422, 425,
- 426, 427, 425, 433, 437, 438, 439, 440, 443, 443,
- 476, 477, 478, 479, 483, 486, 487, 490, 491, 494,
- 497, 501, 505, 509, 515, 516, 520, 523, 529, 529,
- 534, 542, 542, 553, 560, 563, 564, 567, 568, 571,
- 574, 575, 578, 582, 586, 592, 593, 596, 597, 598,
- 604, 609, 614, 615, 616, 618, 621, 622, 629, 630,
- 631, 634, 637
+ 0, 188, 188, 191, 192, 193, 196, 197, 198, 199,
+ 202, 203, 206, 215, 216, 217, 218, 219, 222, 228,
+ 234, 235, 236, 239, 239, 245, 245, 252, 253, 254,
+ 255, 258, 259, 260, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 274, 279, 283, 291, 296, 301, 310,
+ 311, 312, 318, 323, 327, 335, 335, 339, 342, 345,
+ 356, 357, 364, 365, 369, 373, 379, 380, 385, 393,
+ 394, 398, 404, 413, 416, 417, 418, 421, 424, 427,
+ 428, 429, 427, 435, 439, 440, 441, 442, 445, 445,
+ 478, 479, 480, 481, 485, 488, 489, 492, 493, 496,
+ 499, 503, 507, 511, 517, 518, 522, 525, 531, 531,
+ 536, 544, 544, 555, 562, 565, 566, 569, 570, 573,
+ 576, 577, 580, 584, 588, 594, 595, 598, 599, 600,
+ 606, 611, 616, 617, 618, 620, 623, 624, 631, 632,
+ 633, 636, 639
};
#endif
@@ -1450,329 +1452,329 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, parseio)
switch (yytype)
{
case 43: /* "word" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1456 "ael.tab.c"
+#line 1458 "ael.tab.c"
break;
case 46: /* "objects" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1464 "ael.tab.c"
+#line 1466 "ael.tab.c"
break;
case 47: /* "object" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1472 "ael.tab.c"
+#line 1474 "ael.tab.c"
break;
case 48: /* "context_name" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1477 "ael.tab.c"
+#line 1479 "ael.tab.c"
break;
case 49: /* "context" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1485 "ael.tab.c"
+#line 1487 "ael.tab.c"
break;
case 51: /* "macro" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1493 "ael.tab.c"
+#line 1495 "ael.tab.c"
break;
case 52: /* "globals" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1501 "ael.tab.c"
+#line 1503 "ael.tab.c"
break;
case 53: /* "global_statements" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1509 "ael.tab.c"
+#line 1511 "ael.tab.c"
break;
case 54: /* "assignment" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1517 "ael.tab.c"
+#line 1519 "ael.tab.c"
break;
case 56: /* "local_assignment" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1525 "ael.tab.c"
+#line 1527 "ael.tab.c"
break;
case 58: /* "arglist" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1533 "ael.tab.c"
+#line 1535 "ael.tab.c"
break;
case 59: /* "elements" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1541 "ael.tab.c"
+#line 1543 "ael.tab.c"
break;
case 60: /* "element" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1549 "ael.tab.c"
+#line 1551 "ael.tab.c"
break;
case 61: /* "ignorepat" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1557 "ael.tab.c"
+#line 1559 "ael.tab.c"
break;
case 62: /* "extension" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1565 "ael.tab.c"
+#line 1567 "ael.tab.c"
break;
case 63: /* "statements" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1573 "ael.tab.c"
+#line 1575 "ael.tab.c"
break;
case 64: /* "timerange" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1578 "ael.tab.c"
+#line 1580 "ael.tab.c"
break;
case 65: /* "timespec" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1586 "ael.tab.c"
+#line 1588 "ael.tab.c"
break;
case 66: /* "test_expr" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1591 "ael.tab.c"
+#line 1593 "ael.tab.c"
break;
case 68: /* "if_like_head" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1599 "ael.tab.c"
+#line 1601 "ael.tab.c"
break;
case 69: /* "word_list" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1604 "ael.tab.c"
+#line 1606 "ael.tab.c"
break;
case 71: /* "word3_list" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1609 "ael.tab.c"
+#line 1611 "ael.tab.c"
break;
case 72: /* "goto_word" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1614 "ael.tab.c"
+#line 1616 "ael.tab.c"
break;
case 73: /* "switch_statement" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1622 "ael.tab.c"
+#line 1624 "ael.tab.c"
break;
case 74: /* "statement" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1630 "ael.tab.c"
+#line 1632 "ael.tab.c"
break;
case 79: /* "opt_else" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1638 "ael.tab.c"
+#line 1640 "ael.tab.c"
break;
case 80: /* "target" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1646 "ael.tab.c"
+#line 1648 "ael.tab.c"
break;
case 81: /* "opt_pri" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1651 "ael.tab.c"
+#line 1653 "ael.tab.c"
break;
case 82: /* "jumptarget" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1659 "ael.tab.c"
+#line 1661 "ael.tab.c"
break;
case 83: /* "macro_call" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1667 "ael.tab.c"
+#line 1669 "ael.tab.c"
break;
case 85: /* "application_call_head" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1675 "ael.tab.c"
+#line 1677 "ael.tab.c"
break;
case 87: /* "application_call" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1683 "ael.tab.c"
+#line 1685 "ael.tab.c"
break;
case 88: /* "opt_word" */
-#line 178 "ael.y"
+#line 180 "ael.y"
{ free((yyvaluep->str));};
-#line 1688 "ael.tab.c"
+#line 1690 "ael.tab.c"
break;
case 89: /* "eval_arglist" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1696 "ael.tab.c"
+#line 1698 "ael.tab.c"
break;
case 90: /* "case_statements" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1704 "ael.tab.c"
+#line 1706 "ael.tab.c"
break;
case 91: /* "case_statement" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1712 "ael.tab.c"
+#line 1714 "ael.tab.c"
break;
case 92: /* "macro_statements" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1720 "ael.tab.c"
+#line 1722 "ael.tab.c"
break;
case 93: /* "macro_statement" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1728 "ael.tab.c"
+#line 1730 "ael.tab.c"
break;
case 94: /* "switches" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1736 "ael.tab.c"
+#line 1738 "ael.tab.c"
break;
case 95: /* "eswitches" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1744 "ael.tab.c"
+#line 1746 "ael.tab.c"
break;
case 96: /* "switchlist" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1752 "ael.tab.c"
+#line 1754 "ael.tab.c"
break;
case 97: /* "included_entry" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1760 "ael.tab.c"
+#line 1762 "ael.tab.c"
break;
case 98: /* "includeslist" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1768 "ael.tab.c"
+#line 1770 "ael.tab.c"
break;
case 99: /* "includes" */
-#line 165 "ael.y"
+#line 167 "ael.y"
{
destroy_pval((yyvaluep->pval));
prev_word=0;
};
-#line 1776 "ael.tab.c"
+#line 1778 "ael.tab.c"
break;
default:
@@ -2095,57 +2097,57 @@ yyreduce:
switch (yyn)
{
case 2:
-#line 186 "ael.y"
+#line 188 "ael.y"
{ (yyval.pval) = parseio->pval = (yyvsp[(1) - (1)].pval); ;}
break;
case 3:
-#line 189 "ael.y"
+#line 191 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 4:
-#line 190 "ael.y"
+#line 192 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;}
break;
case 5:
-#line 191 "ael.y"
+#line 193 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (2)].pval);;}
break;
case 6:
-#line 194 "ael.y"
+#line 196 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 7:
-#line 195 "ael.y"
+#line 197 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 8:
-#line 196 "ael.y"
+#line 198 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 9:
-#line 197 "ael.y"
+#line 199 "ael.y"
{(yyval.pval)=0;/* allow older docs to be read */;}
break;
case 10:
-#line 200 "ael.y"
+#line 202 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); ;}
break;
case 11:
-#line 201 "ael.y"
+#line 203 "ael.y"
{ (yyval.str) = strdup("default"); ;}
break;
case 12:
-#line 204 "ael.y"
+#line 206 "ael.y"
{
(yyval.pval) = npval2(PV_CONTEXT, &(yylsp[(1) - (6)]), &(yylsp[(6) - (6)]));
(yyval.pval)->u1.str = (yyvsp[(3) - (6)].str);
@@ -2155,32 +2157,32 @@ yyreduce:
break;
case 13:
-#line 213 "ael.y"
+#line 215 "ael.y"
{ (yyval.intval) = 1; ;}
break;
case 14:
-#line 214 "ael.y"
+#line 216 "ael.y"
{ (yyval.intval) = 0; ;}
break;
case 15:
-#line 215 "ael.y"
+#line 217 "ael.y"
{ (yyval.intval) = 2; ;}
break;
case 16:
-#line 216 "ael.y"
+#line 218 "ael.y"
{ (yyval.intval)=3; ;}
break;
case 17:
-#line 217 "ael.y"
+#line 219 "ael.y"
{ (yyval.intval)=3; ;}
break;
case 18:
-#line 220 "ael.y"
+#line 222 "ael.y"
{
(yyval.pval) = npval2(PV_MACRO, &(yylsp[(1) - (8)]), &(yylsp[(8) - (8)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (8)].str); (yyval.pval)->u2.arglist = (yyvsp[(4) - (8)].pval); (yyval.pval)->u3.macro_statements = (yyvsp[(7) - (8)].pval);
@@ -2188,7 +2190,7 @@ yyreduce:
break;
case 19:
-#line 226 "ael.y"
+#line 228 "ael.y"
{
(yyval.pval) = npval2(PV_GLOBALS, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)]));
(yyval.pval)->u1.statements = (yyvsp[(3) - (4)].pval);
@@ -2196,27 +2198,27 @@ yyreduce:
break;
case 20:
-#line 232 "ael.y"
+#line 234 "ael.y"
{ (yyval.pval) = NULL; ;}
break;
case 21:
-#line 233 "ael.y"
+#line 235 "ael.y"
{(yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;}
break;
case 22:
-#line 234 "ael.y"
+#line 236 "ael.y"
{(yyval.pval)=(yyvsp[(2) - (2)].pval);;}
break;
case 23:
-#line 237 "ael.y"
+#line 239 "ael.y"
{ reset_semicount(parseio->scanner); ;}
break;
case 24:
-#line 237 "ael.y"
+#line 239 "ael.y"
{
(yyval.pval) = npval2(PV_VARDEC, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)]));
(yyval.pval)->u1.str = (yyvsp[(1) - (5)].str);
@@ -2224,12 +2226,12 @@ yyreduce:
break;
case 25:
-#line 243 "ael.y"
+#line 245 "ael.y"
{ reset_semicount(parseio->scanner); ;}
break;
case 26:
-#line 243 "ael.y"
+#line 245 "ael.y"
{
(yyval.pval) = npval2(PV_LOCALVARDEC, &(yylsp[(1) - (6)]), &(yylsp[(6) - (6)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (6)].str);
@@ -2237,94 +2239,94 @@ yyreduce:
break;
case 27:
-#line 250 "ael.y"
+#line 252 "ael.y"
{ (yyval.pval) = NULL; ;}
break;
case 28:
-#line 251 "ael.y"
+#line 253 "ael.y"
{ (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;}
break;
case 29:
-#line 252 "ael.y"
+#line 254 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (3)].pval), nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)]))); ;}
break;
case 30:
-#line 253 "ael.y"
+#line 255 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (2)].pval);;}
break;
case 31:
-#line 256 "ael.y"
+#line 258 "ael.y"
{(yyval.pval)=0;;}
break;
case 32:
-#line 257 "ael.y"
+#line 259 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;}
break;
case 33:
-#line 258 "ael.y"
+#line 260 "ael.y"
{ (yyval.pval)=(yyvsp[(2) - (2)].pval);;}
break;
case 34:
-#line 261 "ael.y"
+#line 263 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 35:
-#line 262 "ael.y"
+#line 264 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 36:
-#line 263 "ael.y"
+#line 265 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 37:
-#line 264 "ael.y"
+#line 266 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 38:
-#line 265 "ael.y"
+#line 267 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 39:
-#line 266 "ael.y"
+#line 268 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 40:
-#line 267 "ael.y"
+#line 269 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 41:
-#line 268 "ael.y"
+#line 270 "ael.y"
{free((yyvsp[(1) - (2)].str)); (yyval.pval)=0;;}
break;
case 42:
-#line 269 "ael.y"
+#line 271 "ael.y"
{(yyval.pval)=0;/* allow older docs to be read */;}
break;
case 43:
-#line 272 "ael.y"
+#line 274 "ael.y"
{
(yyval.pval) = npval2(PV_IGNOREPAT, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)]));
(yyval.pval)->u1.str = (yyvsp[(3) - (4)].str);;}
break;
case 44:
-#line 277 "ael.y"
+#line 279 "ael.y"
{
(yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.str = (yyvsp[(1) - (3)].str);
@@ -2332,7 +2334,7 @@ yyreduce:
break;
case 45:
-#line 281 "ael.y"
+#line 283 "ael.y"
{
(yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (5)]), &(yylsp[(3) - (5)]));
(yyval.pval)->u1.str = malloc(strlen((yyvsp[(1) - (5)].str))+strlen((yyvsp[(3) - (5)].str))+2);
@@ -2344,7 +2346,7 @@ yyreduce:
break;
case 46:
-#line 289 "ael.y"
+#line 291 "ael.y"
{
(yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (4)].str);
@@ -2353,7 +2355,7 @@ yyreduce:
break;
case 47:
-#line 294 "ael.y"
+#line 296 "ael.y"
{
(yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (7)]), &(yylsp[(7) - (7)]));
(yyval.pval)->u1.str = (yyvsp[(5) - (7)].str);
@@ -2362,7 +2364,7 @@ yyreduce:
break;
case 48:
-#line 299 "ael.y"
+#line 301 "ael.y"
{
(yyval.pval) = npval2(PV_EXTENSION, &(yylsp[(1) - (8)]), &(yylsp[(8) - (8)]));
(yyval.pval)->u1.str = (yyvsp[(6) - (8)].str);
@@ -2372,22 +2374,22 @@ yyreduce:
break;
case 49:
-#line 308 "ael.y"
+#line 310 "ael.y"
{ (yyval.pval) = NULL; ;}
break;
case 50:
-#line 309 "ael.y"
+#line 311 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;}
break;
case 51:
-#line 310 "ael.y"
+#line 312 "ael.y"
{(yyval.pval)=(yyvsp[(2) - (2)].pval);;}
break;
case 52:
-#line 316 "ael.y"
+#line 318 "ael.y"
{
asprintf(&(yyval.str), "%s:%s:%s", (yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), (yyvsp[(5) - (5)].str));
free((yyvsp[(1) - (5)].str));
@@ -2396,12 +2398,12 @@ yyreduce:
break;
case 53:
-#line 321 "ael.y"
+#line 323 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); ;}
break;
case 54:
-#line 325 "ael.y"
+#line 327 "ael.y"
{
(yyval.pval) = nword((yyvsp[(1) - (7)].str), &(yylsp[(1) - (7)]));
(yyval.pval)->next = nword((yyvsp[(3) - (7)].str), &(yylsp[(3) - (7)]));
@@ -2410,31 +2412,31 @@ yyreduce:
break;
case 55:
-#line 333 "ael.y"
+#line 335 "ael.y"
{ reset_parencount(parseio->scanner); ;}
break;
case 56:
-#line 333 "ael.y"
+#line 335 "ael.y"
{ (yyval.str) = (yyvsp[(3) - (4)].str); ;}
break;
case 57:
-#line 337 "ael.y"
+#line 339 "ael.y"
{
(yyval.pval)= npval2(PV_IF, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (2)].str); ;}
break;
case 58:
-#line 340 "ael.y"
+#line 342 "ael.y"
{
(yyval.pval) = npval2(PV_RANDOM, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)]));
(yyval.pval)->u1.str=(yyvsp[(2) - (2)].str);;}
break;
case 59:
-#line 343 "ael.y"
+#line 345 "ael.y"
{
(yyval.pval) = npval2(PV_IFTIME, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)]));
(yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval);
@@ -2442,12 +2444,12 @@ yyreduce:
break;
case 60:
-#line 354 "ael.y"
+#line 356 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str);;}
break;
case 61:
-#line 355 "ael.y"
+#line 357 "ael.y"
{
asprintf(&((yyval.str)), "%s%s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
free((yyvsp[(1) - (2)].str));
@@ -2456,12 +2458,12 @@ yyreduce:
break;
case 62:
-#line 362 "ael.y"
+#line 364 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str); ;}
break;
case 63:
-#line 363 "ael.y"
+#line 365 "ael.y"
{
asprintf(&((yyval.str)), "%s %s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
free((yyvsp[(1) - (2)].str));
@@ -2469,7 +2471,7 @@ yyreduce:
break;
case 64:
-#line 367 "ael.y"
+#line 369 "ael.y"
{
asprintf(&((yyval.str)), "%s:%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str));
free((yyvsp[(1) - (3)].str));
@@ -2477,7 +2479,7 @@ yyreduce:
break;
case 65:
-#line 371 "ael.y"
+#line 373 "ael.y"
{ /* there are often '&' in hints */
asprintf(&((yyval.str)), "%s&%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str));
free((yyvsp[(1) - (3)].str));
@@ -2485,12 +2487,12 @@ yyreduce:
break;
case 66:
-#line 377 "ael.y"
+#line 379 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str);;}
break;
case 67:
-#line 378 "ael.y"
+#line 380 "ael.y"
{
asprintf(&((yyval.str)), "%s%s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
free((yyvsp[(1) - (2)].str));
@@ -2499,7 +2501,7 @@ yyreduce:
break;
case 68:
-#line 383 "ael.y"
+#line 385 "ael.y"
{
asprintf(&((yyval.str)), "%s%s%s", (yyvsp[(1) - (3)].str), (yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str));
free((yyvsp[(1) - (3)].str));
@@ -2509,12 +2511,12 @@ yyreduce:
break;
case 69:
-#line 391 "ael.y"
+#line 393 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str);;}
break;
case 70:
-#line 392 "ael.y"
+#line 394 "ael.y"
{
asprintf(&((yyval.str)), "%s%s", (yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str));
free((yyvsp[(1) - (2)].str));
@@ -2522,7 +2524,7 @@ yyreduce:
break;
case 71:
-#line 396 "ael.y"
+#line 398 "ael.y"
{
asprintf(&((yyval.str)), "%s:%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str));
free((yyvsp[(1) - (3)].str));
@@ -2530,7 +2532,7 @@ yyreduce:
break;
case 72:
-#line 402 "ael.y"
+#line 404 "ael.y"
{
(yyval.pval) = npval2(PV_SWITCH, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (5)].str);
@@ -2538,60 +2540,60 @@ yyreduce:
break;
case 73:
-#line 411 "ael.y"
+#line 413 "ael.y"
{
(yyval.pval) = npval2(PV_STATEMENTBLOCK, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval); set_dads((yyval.pval),(yyvsp[(2) - (3)].pval));;}
break;
case 74:
-#line 414 "ael.y"
+#line 416 "ael.y"
{ (yyval.pval) = (yyvsp[(1) - (1)].pval); ;}
break;
case 75:
-#line 415 "ael.y"
+#line 417 "ael.y"
{ (yyval.pval) = (yyvsp[(1) - (1)].pval); ;}
break;
case 76:
-#line 416 "ael.y"
+#line 418 "ael.y"
{
(yyval.pval) = npval2(PV_GOTO, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval);;}
break;
case 77:
-#line 419 "ael.y"
+#line 421 "ael.y"
{
(yyval.pval) = npval2(PV_GOTO, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.list = (yyvsp[(2) - (3)].pval);;}
break;
case 78:
-#line 422 "ael.y"
+#line 424 "ael.y"
{
(yyval.pval) = npval2(PV_LABEL, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)]));
(yyval.pval)->u1.str = (yyvsp[(1) - (2)].str); ;}
break;
case 79:
-#line 425 "ael.y"
+#line 427 "ael.y"
{reset_semicount(parseio->scanner);;}
break;
case 80:
-#line 426 "ael.y"
+#line 428 "ael.y"
{reset_semicount(parseio->scanner);;}
break;
case 81:
-#line 427 "ael.y"
+#line 429 "ael.y"
{reset_parencount(parseio->scanner);;}
break;
case 82:
-#line 427 "ael.y"
+#line 429 "ael.y"
{ /* XXX word_list maybe ? */
(yyval.pval) = npval2(PV_FOR, &(yylsp[(1) - (12)]), &(yylsp[(12) - (12)]));
(yyval.pval)->u1.for_init = (yyvsp[(4) - (12)].str);
@@ -2601,7 +2603,7 @@ yyreduce:
break;
case 83:
-#line 433 "ael.y"
+#line 435 "ael.y"
{
(yyval.pval) = npval2(PV_WHILE, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (3)].str);
@@ -2609,34 +2611,34 @@ yyreduce:
break;
case 84:
-#line 437 "ael.y"
+#line 439 "ael.y"
{ (yyval.pval) = (yyvsp[(1) - (1)].pval); ;}
break;
case 85:
-#line 438 "ael.y"
+#line 440 "ael.y"
{ (yyval.pval) = update_last((yyvsp[(2) - (3)].pval), &(yylsp[(2) - (3)])); ;}
break;
case 86:
-#line 439 "ael.y"
+#line 441 "ael.y"
{ (yyval.pval) = update_last((yyvsp[(1) - (2)].pval), &(yylsp[(2) - (2)])); ;}
break;
case 87:
-#line 440 "ael.y"
+#line 442 "ael.y"
{
(yyval.pval)= npval2(PV_APPLICATION_CALL, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)]));
(yyval.pval)->u1.str = (yyvsp[(1) - (2)].str);;}
break;
case 88:
-#line 443 "ael.y"
+#line 445 "ael.y"
{reset_semicount(parseio->scanner);;}
break;
case 89:
-#line 443 "ael.y"
+#line 445 "ael.y"
{
char *bufx;
int tot=0;
@@ -2673,22 +2675,22 @@ yyreduce:
break;
case 90:
-#line 476 "ael.y"
+#line 478 "ael.y"
{ (yyval.pval) = npval2(PV_BREAK, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); ;}
break;
case 91:
-#line 477 "ael.y"
+#line 479 "ael.y"
{ (yyval.pval) = npval2(PV_RETURN, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); ;}
break;
case 92:
-#line 478 "ael.y"
+#line 480 "ael.y"
{ (yyval.pval) = npval2(PV_CONTINUE, &(yylsp[(1) - (2)]), &(yylsp[(2) - (2)])); ;}
break;
case 93:
-#line 479 "ael.y"
+#line 481 "ael.y"
{
(yyval.pval) = update_last((yyvsp[(1) - (3)].pval), &(yylsp[(2) - (3)]));
(yyval.pval)->u2.statements = (yyvsp[(2) - (3)].pval); set_dads((yyval.pval),(yyvsp[(2) - (3)].pval));
@@ -2696,41 +2698,41 @@ yyreduce:
break;
case 94:
-#line 483 "ael.y"
+#line 485 "ael.y"
{ (yyval.pval)=0; ;}
break;
case 95:
-#line 486 "ael.y"
+#line 488 "ael.y"
{ (yyval.pval) = (yyvsp[(2) - (2)].pval); ;}
break;
case 96:
-#line 487 "ael.y"
+#line 489 "ael.y"
{ (yyval.pval) = NULL ; ;}
break;
case 97:
-#line 490 "ael.y"
+#line 492 "ael.y"
{ (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;}
break;
case 98:
-#line 491 "ael.y"
+#line 493 "ael.y"
{
(yyval.pval) = nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)]));
(yyval.pval)->next = nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)])); ;}
break;
case 99:
-#line 494 "ael.y"
+#line 496 "ael.y"
{
(yyval.pval) = nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)]));
(yyval.pval)->next = nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)])); ;}
break;
case 100:
-#line 497 "ael.y"
+#line 499 "ael.y"
{
(yyval.pval) = nword((yyvsp[(1) - (5)].str), &(yylsp[(1) - (5)]));
(yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)]));
@@ -2738,7 +2740,7 @@ yyreduce:
break;
case 101:
-#line 501 "ael.y"
+#line 503 "ael.y"
{
(yyval.pval) = nword((yyvsp[(1) - (5)].str), &(yylsp[(1) - (5)]));
(yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)]));
@@ -2746,7 +2748,7 @@ yyreduce:
break;
case 102:
-#line 505 "ael.y"
+#line 507 "ael.y"
{
(yyval.pval) = nword(strdup("default"), &(yylsp[(1) - (5)]));
(yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)]));
@@ -2754,7 +2756,7 @@ yyreduce:
break;
case 103:
-#line 509 "ael.y"
+#line 511 "ael.y"
{
(yyval.pval) = nword(strdup("default"), &(yylsp[(1) - (5)]));
(yyval.pval)->next = nword((yyvsp[(3) - (5)].str), &(yylsp[(3) - (5)]));
@@ -2762,24 +2764,24 @@ yyreduce:
break;
case 104:
-#line 515 "ael.y"
+#line 517 "ael.y"
{ (yyval.str) = strdup("1"); ;}
break;
case 105:
-#line 516 "ael.y"
+#line 518 "ael.y"
{ (yyval.str) = (yyvsp[(2) - (2)].str); ;}
break;
case 106:
-#line 520 "ael.y"
+#line 522 "ael.y"
{ /* ext[, pri] default 1 */
(yyval.pval) = nword((yyvsp[(1) - (2)].str), &(yylsp[(1) - (2)]));
(yyval.pval)->next = nword((yyvsp[(2) - (2)].str), &(yylsp[(2) - (2)])); ;}
break;
case 107:
-#line 523 "ael.y"
+#line 525 "ael.y"
{ /* context, ext, pri */
(yyval.pval) = nword((yyvsp[(4) - (4)].str), &(yylsp[(4) - (4)]));
(yyval.pval)->next = nword((yyvsp[(1) - (4)].str), &(yylsp[(1) - (4)]));
@@ -2787,12 +2789,12 @@ yyreduce:
break;
case 108:
-#line 529 "ael.y"
+#line 531 "ael.y"
{reset_argcount(parseio->scanner);;}
break;
case 109:
-#line 529 "ael.y"
+#line 531 "ael.y"
{
/* XXX original code had @2 but i think we need @5 */
(yyval.pval) = npval2(PV_MACRO_CALL, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)]));
@@ -2801,19 +2803,19 @@ yyreduce:
break;
case 110:
-#line 534 "ael.y"
+#line 536 "ael.y"
{
(yyval.pval)= npval2(PV_MACRO_CALL, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.str = (yyvsp[(1) - (3)].str); ;}
break;
case 111:
-#line 542 "ael.y"
+#line 544 "ael.y"
{reset_argcount(parseio->scanner);;}
break;
case 112:
-#line 542 "ael.y"
+#line 544 "ael.y"
{
if (strcasecmp((yyvsp[(1) - (3)].str),"goto") == 0) {
(yyval.pval) = npval2(PV_GOTO, &(yylsp[(1) - (3)]), &(yylsp[(2) - (3)]));
@@ -2826,7 +2828,7 @@ yyreduce:
break;
case 113:
-#line 553 "ael.y"
+#line 555 "ael.y"
{
(yyval.pval) = update_last((yyvsp[(1) - (3)].pval), &(yylsp[(3) - (3)]));
if( (yyval.pval)->type == PV_GOTO )
@@ -2837,49 +2839,49 @@ yyreduce:
break;
case 114:
-#line 560 "ael.y"
+#line 562 "ael.y"
{ (yyval.pval) = update_last((yyvsp[(1) - (2)].pval), &(yylsp[(2) - (2)])); ;}
break;
case 115:
-#line 563 "ael.y"
+#line 565 "ael.y"
{ (yyval.str) = (yyvsp[(1) - (1)].str) ;}
break;
case 116:
-#line 564 "ael.y"
+#line 566 "ael.y"
{ (yyval.str) = strdup(""); ;}
break;
case 117:
-#line 567 "ael.y"
+#line 569 "ael.y"
{ (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;}
break;
case 118:
-#line 568 "ael.y"
+#line 570 "ael.y"
{
(yyval.pval)= npval(PV_WORD,0/*@1.first_line*/,0/*@1.last_line*/,0/* @1.first_column*/, 0/*@1.last_column*/);
(yyval.pval)->u1.str = strdup(""); ;}
break;
case 119:
-#line 571 "ael.y"
+#line 573 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (3)].pval), nword((yyvsp[(3) - (3)].str), &(yylsp[(3) - (3)]))); ;}
break;
case 120:
-#line 574 "ael.y"
+#line 576 "ael.y"
{ (yyval.pval) = NULL; ;}
break;
case 121:
-#line 575 "ael.y"
+#line 577 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;}
break;
case 122:
-#line 578 "ael.y"
+#line 580 "ael.y"
{
(yyval.pval) = npval2(PV_CASE, &(yylsp[(1) - (4)]), &(yylsp[(3) - (4)])); /* XXX 3 or 4 ? */
(yyval.pval)->u1.str = (yyvsp[(2) - (4)].str);
@@ -2887,7 +2889,7 @@ yyreduce:
break;
case 123:
-#line 582 "ael.y"
+#line 584 "ael.y"
{
(yyval.pval) = npval2(PV_DEFAULT, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));
(yyval.pval)->u1.str = NULL;
@@ -2895,7 +2897,7 @@ yyreduce:
break;
case 124:
-#line 586 "ael.y"
+#line 588 "ael.y"
{
(yyval.pval) = npval2(PV_PATTERN, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)])); /* XXX@3 or @4 ? */
(yyval.pval)->u1.str = (yyvsp[(2) - (4)].str);
@@ -2903,27 +2905,27 @@ yyreduce:
break;
case 125:
-#line 592 "ael.y"
+#line 594 "ael.y"
{ (yyval.pval) = NULL; ;}
break;
case 126:
-#line 593 "ael.y"
+#line 595 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (2)].pval), (yyvsp[(2) - (2)].pval)); ;}
break;
case 127:
-#line 596 "ael.y"
+#line 598 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 128:
-#line 597 "ael.y"
+#line 599 "ael.y"
{ (yyval.pval)=(yyvsp[(1) - (1)].pval);;}
break;
case 129:
-#line 598 "ael.y"
+#line 600 "ael.y"
{
(yyval.pval) = npval2(PV_CATCH, &(yylsp[(1) - (5)]), &(yylsp[(5) - (5)]));
(yyval.pval)->u1.str = (yyvsp[(2) - (5)].str);
@@ -2931,47 +2933,47 @@ yyreduce:
break;
case 130:
-#line 604 "ael.y"
+#line 606 "ael.y"
{
(yyval.pval) = npval2(PV_SWITCHES, &(yylsp[(1) - (4)]), &(yylsp[(2) - (4)]));
(yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;}
break;
case 131:
-#line 609 "ael.y"
+#line 611 "ael.y"
{
(yyval.pval) = npval2(PV_ESWITCHES, &(yylsp[(1) - (4)]), &(yylsp[(2) - (4)]));
(yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval); set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;}
break;
case 132:
-#line 614 "ael.y"
+#line 616 "ael.y"
{ (yyval.pval) = NULL; ;}
break;
case 133:
-#line 615 "ael.y"
+#line 617 "ael.y"
{ (yyval.pval) = linku1(nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)])), (yyvsp[(3) - (3)].pval)); ;}
break;
case 134:
-#line 616 "ael.y"
+#line 618 "ael.y"
{ char *x; asprintf(&x,"%s@%s", (yyvsp[(1) - (5)].str),(yyvsp[(3) - (5)].str)); free((yyvsp[(1) - (5)].str)); free((yyvsp[(3) - (5)].str));
(yyval.pval) = linku1(nword(x, &(yylsp[(1) - (5)])), (yyvsp[(5) - (5)].pval));;}
break;
case 135:
-#line 618 "ael.y"
+#line 620 "ael.y"
{(yyval.pval)=(yyvsp[(2) - (2)].pval);;}
break;
case 136:
-#line 621 "ael.y"
+#line 623 "ael.y"
{ (yyval.pval) = nword((yyvsp[(1) - (1)].str), &(yylsp[(1) - (1)])); ;}
break;
case 137:
-#line 622 "ael.y"
+#line 624 "ael.y"
{
(yyval.pval) = nword((yyvsp[(1) - (3)].str), &(yylsp[(1) - (3)]));
(yyval.pval)->u2.arglist = (yyvsp[(3) - (3)].pval);
@@ -2979,36 +2981,36 @@ yyreduce:
break;
case 138:
-#line 629 "ael.y"
+#line 631 "ael.y"
{ (yyval.pval) = (yyvsp[(1) - (2)].pval); ;}
break;
case 139:
-#line 630 "ael.y"
+#line 632 "ael.y"
{ (yyval.pval) = linku1((yyvsp[(1) - (3)].pval), (yyvsp[(2) - (3)].pval)); ;}
break;
case 140:
-#line 631 "ael.y"
+#line 633 "ael.y"
{(yyval.pval)=(yyvsp[(1) - (2)].pval);;}
break;
case 141:
-#line 634 "ael.y"
+#line 636 "ael.y"
{
(yyval.pval) = npval2(PV_INCLUDES, &(yylsp[(1) - (4)]), &(yylsp[(4) - (4)]));
(yyval.pval)->u1.list = (yyvsp[(3) - (4)].pval);set_dads((yyval.pval),(yyvsp[(3) - (4)].pval));;}
break;
case 142:
-#line 637 "ael.y"
+#line 639 "ael.y"
{
(yyval.pval) = npval2(PV_INCLUDES, &(yylsp[(1) - (3)]), &(yylsp[(3) - (3)]));;}
break;
/* Line 1270 of yacc.c. */
-#line 3012 "ael.tab.c"
+#line 3014 "ael.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -3227,7 +3229,7 @@ yyreturn:
}
-#line 642 "ael.y"
+#line 644 "ael.y"
static char *token_equivs1[] =
diff --git a/res/ael/ael.tab.h b/res/ael/ael.tab.h
index 95b011852..02c09dbb9 100644
--- a/res/ael/ael.tab.h
+++ b/res/ael/ael.tab.h
@@ -120,7 +120,7 @@
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-#line 54 "ael.y"
+#line 56 "ael.y"
{
int intval; /* integer value, typically flags */
char *str; /* strings */
diff --git a/res/ael/ael.y b/res/ael/ael.y
index a8df1cb51..97558eca4 100644
--- a/res/ael/ael.y
+++ b/res/ael/ael.y
@@ -31,6 +31,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include "asterisk/logger.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
pval * linku1(pval *head, pval *tail);
diff --git a/res/ael/ael_lex.c b/res/ael/ael_lex.c
index 26206af5d..8b7436374 100644
--- a/res/ael/ael_lex.c
+++ b/res/ael/ael_lex.c
@@ -803,9 +803,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define GLOB_ABORTED GLOB_ABEND
#endif
# include <glob.h>
-
#include "asterisk/logger.h"
#include "asterisk/utils.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
#include "ael/ael.tab.h"
#include "asterisk/ael_structs.h"
@@ -906,7 +907,7 @@ static void pbcwhere(const char *text, int *line, int *col )
#define STORE_POS
#define STORE_LOC
#endif
-#line 909 "ael_lex.c"
+#line 911 "ael_lex.c"
#define INITIAL 0
#define paren 1
@@ -1145,10 +1146,10 @@ YY_DECL
register int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 187 "ael.flex"
+#line 189 "ael.flex"
-#line 1151 "ael_lex.c"
+#line 1153 "ael_lex.c"
yylval = yylval_param;
@@ -1239,260 +1240,260 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
YY_RULE_SETUP
-#line 189 "ael.flex"
+#line 191 "ael.flex"
{ STORE_POS; return LC;}
YY_BREAK
case 2:
YY_RULE_SETUP
-#line 190 "ael.flex"
+#line 192 "ael.flex"
{ STORE_POS; return RC;}
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 191 "ael.flex"
+#line 193 "ael.flex"
{ STORE_POS; return LP;}
YY_BREAK
case 4:
YY_RULE_SETUP
-#line 192 "ael.flex"
+#line 194 "ael.flex"
{ STORE_POS; return RP;}
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 193 "ael.flex"
+#line 195 "ael.flex"
{ STORE_POS; return SEMI;}
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 194 "ael.flex"
+#line 196 "ael.flex"
{ STORE_POS; return EQ;}
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 195 "ael.flex"
+#line 197 "ael.flex"
{ STORE_POS; return COMMA;}
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 196 "ael.flex"
+#line 198 "ael.flex"
{ STORE_POS; return COLON;}
YY_BREAK
case 9:
YY_RULE_SETUP
-#line 197 "ael.flex"
+#line 199 "ael.flex"
{ STORE_POS; return AMPER;}
YY_BREAK
case 10:
YY_RULE_SETUP
-#line 198 "ael.flex"
+#line 200 "ael.flex"
{ STORE_POS; return BAR;}
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 199 "ael.flex"
+#line 201 "ael.flex"
{ STORE_POS; return EXTENMARK;}
YY_BREAK
case 12:
YY_RULE_SETUP
-#line 200 "ael.flex"
+#line 202 "ael.flex"
{ STORE_POS; return AT;}
YY_BREAK
case 13:
YY_RULE_SETUP
-#line 201 "ael.flex"
+#line 203 "ael.flex"
{/*comment*/}
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 202 "ael.flex"
+#line 204 "ael.flex"
{ STORE_POS; return KW_CONTEXT;}
YY_BREAK
case 15:
YY_RULE_SETUP
-#line 203 "ael.flex"
+#line 205 "ael.flex"
{ STORE_POS; return KW_ABSTRACT;}
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 204 "ael.flex"
+#line 206 "ael.flex"
{ STORE_POS; return KW_EXTEND;}
YY_BREAK
case 17:
YY_RULE_SETUP
-#line 205 "ael.flex"
+#line 207 "ael.flex"
{ STORE_POS; return KW_MACRO;};
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 206 "ael.flex"
+#line 208 "ael.flex"
{ STORE_POS; return KW_GLOBALS;}
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 207 "ael.flex"
+#line 209 "ael.flex"
{ STORE_POS; return KW_LOCAL;}
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 208 "ael.flex"
+#line 210 "ael.flex"
{ STORE_POS; return KW_IGNOREPAT;}
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 209 "ael.flex"
+#line 211 "ael.flex"
{ STORE_POS; return KW_SWITCH;}
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 210 "ael.flex"
+#line 212 "ael.flex"
{ STORE_POS; return KW_IF;}
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 211 "ael.flex"
+#line 213 "ael.flex"
{ STORE_POS; return KW_IFTIME;}
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 212 "ael.flex"
+#line 214 "ael.flex"
{ STORE_POS; return KW_RANDOM;}
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 213 "ael.flex"
+#line 215 "ael.flex"
{ STORE_POS; return KW_REGEXTEN;}
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 214 "ael.flex"
+#line 216 "ael.flex"
{ STORE_POS; return KW_HINT;}
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 215 "ael.flex"
+#line 217 "ael.flex"
{ STORE_POS; return KW_ELSE;}
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 216 "ael.flex"
+#line 218 "ael.flex"
{ STORE_POS; return KW_GOTO;}
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 217 "ael.flex"
+#line 219 "ael.flex"
{ STORE_POS; return KW_JUMP;}
YY_BREAK
case 30:
YY_RULE_SETUP
-#line 218 "ael.flex"
+#line 220 "ael.flex"
{ STORE_POS; return KW_RETURN;}
YY_BREAK
case 31:
YY_RULE_SETUP
-#line 219 "ael.flex"
+#line 221 "ael.flex"
{ STORE_POS; return KW_BREAK;}
YY_BREAK
case 32:
YY_RULE_SETUP
-#line 220 "ael.flex"
+#line 222 "ael.flex"
{ STORE_POS; return KW_CONTINUE;}
YY_BREAK
case 33:
YY_RULE_SETUP
-#line 221 "ael.flex"
+#line 223 "ael.flex"
{ STORE_POS; return KW_FOR;}
YY_BREAK
case 34:
YY_RULE_SETUP
-#line 222 "ael.flex"
+#line 224 "ael.flex"
{ STORE_POS; return KW_WHILE;}
YY_BREAK
case 35:
YY_RULE_SETUP
-#line 223 "ael.flex"
+#line 225 "ael.flex"
{ STORE_POS; return KW_CASE;}
YY_BREAK
case 36:
YY_RULE_SETUP
-#line 224 "ael.flex"
+#line 226 "ael.flex"
{ STORE_POS; return KW_DEFAULT;}
YY_BREAK
case 37:
YY_RULE_SETUP
-#line 225 "ael.flex"
+#line 227 "ael.flex"
{ STORE_POS; return KW_PATTERN;}
YY_BREAK
case 38:
YY_RULE_SETUP
-#line 226 "ael.flex"
+#line 228 "ael.flex"
{ STORE_POS; return KW_CATCH;}
YY_BREAK
case 39:
YY_RULE_SETUP
-#line 227 "ael.flex"
+#line 229 "ael.flex"
{ STORE_POS; return KW_SWITCHES;}
YY_BREAK
case 40:
YY_RULE_SETUP
-#line 228 "ael.flex"
+#line 230 "ael.flex"
{ STORE_POS; return KW_ESWITCHES;}
YY_BREAK
case 41:
YY_RULE_SETUP
-#line 229 "ael.flex"
+#line 231 "ael.flex"
{ STORE_POS; return KW_INCLUDES;}
YY_BREAK
case 42:
YY_RULE_SETUP
-#line 230 "ael.flex"
+#line 232 "ael.flex"
{ BEGIN(comment); my_col += 2; }
YY_BREAK
case 43:
YY_RULE_SETUP
-#line 232 "ael.flex"
+#line 234 "ael.flex"
{ my_col += yyleng; }
YY_BREAK
case 44:
/* rule 44 can match eol */
YY_RULE_SETUP
-#line 233 "ael.flex"
+#line 235 "ael.flex"
{ ++my_lineno; my_col=1;}
YY_BREAK
case 45:
YY_RULE_SETUP
-#line 234 "ael.flex"
+#line 236 "ael.flex"
{ my_col += yyleng; }
YY_BREAK
case 46:
/* rule 46 can match eol */
YY_RULE_SETUP
-#line 235 "ael.flex"
+#line 237 "ael.flex"
{ ++my_lineno; my_col=1;}
YY_BREAK
case 47:
YY_RULE_SETUP
-#line 236 "ael.flex"
+#line 238 "ael.flex"
{ my_col += 2; BEGIN(INITIAL); }
YY_BREAK
case 48:
/* rule 48 can match eol */
YY_RULE_SETUP
-#line 238 "ael.flex"
+#line 240 "ael.flex"
{ my_lineno++; my_col = 1; }
YY_BREAK
case 49:
YY_RULE_SETUP
-#line 239 "ael.flex"
+#line 241 "ael.flex"
{ my_col += yyleng; }
YY_BREAK
case 50:
YY_RULE_SETUP
-#line 240 "ael.flex"
+#line 242 "ael.flex"
{ my_col += (yyleng*8)-(my_col%8); }
YY_BREAK
case 51:
YY_RULE_SETUP
-#line 242 "ael.flex"
+#line 244 "ael.flex"
{
STORE_POS;
yylval->str = strdup(yytext);
@@ -1510,7 +1511,7 @@ YY_RULE_SETUP
case 52:
/* rule 52 can match eol */
YY_RULE_SETUP
-#line 258 "ael.flex"
+#line 260 "ael.flex"
{
if ( pbcpop(')') ) { /* error */
STORE_LOC;
@@ -1536,7 +1537,7 @@ YY_RULE_SETUP
case 53:
/* rule 53 can match eol */
YY_RULE_SETUP
-#line 280 "ael.flex"
+#line 282 "ael.flex"
{
char c = yytext[yyleng-1];
if (c == '(')
@@ -1548,7 +1549,7 @@ YY_RULE_SETUP
case 54:
/* rule 54 can match eol */
YY_RULE_SETUP
-#line 288 "ael.flex"
+#line 290 "ael.flex"
{
char c = yytext[yyleng-1];
if ( pbcpop(c)) { /* error */
@@ -1573,7 +1574,7 @@ YY_RULE_SETUP
case 55:
/* rule 55 can match eol */
YY_RULE_SETUP
-#line 310 "ael.flex"
+#line 312 "ael.flex"
{
char c = yytext[yyleng-1];
if (c == '(')
@@ -1585,7 +1586,7 @@ YY_RULE_SETUP
case 56:
/* rule 56 can match eol */
YY_RULE_SETUP
-#line 318 "ael.flex"
+#line 320 "ael.flex"
{
if ( pbcpop(')') ) { /* error */
STORE_LOC;
@@ -1613,7 +1614,7 @@ YY_RULE_SETUP
case 57:
/* rule 57 can match eol */
YY_RULE_SETUP
-#line 342 "ael.flex"
+#line 344 "ael.flex"
{
if( parencount != 0) { /* printf("Folding in a comma!\n"); */
yymore();
@@ -1631,7 +1632,7 @@ YY_RULE_SETUP
case 58:
/* rule 58 can match eol */
YY_RULE_SETUP
-#line 356 "ael.flex"
+#line 358 "ael.flex"
{
char c = yytext[yyleng-1];
if ( pbcpop(c) ) { /* error */
@@ -1652,7 +1653,7 @@ YY_RULE_SETUP
case 59:
/* rule 59 can match eol */
YY_RULE_SETUP
-#line 373 "ael.flex"
+#line 375 "ael.flex"
{
char c = yytext[yyleng-1];
yymore();
@@ -1662,7 +1663,7 @@ YY_RULE_SETUP
case 60:
/* rule 60 can match eol */
YY_RULE_SETUP
-#line 379 "ael.flex"
+#line 381 "ael.flex"
{
char c = yytext[yyleng-1];
if ( pbcpop(c) ) { /* error */
@@ -1678,7 +1679,7 @@ YY_RULE_SETUP
case 61:
/* rule 61 can match eol */
YY_RULE_SETUP
-#line 391 "ael.flex"
+#line 393 "ael.flex"
{
STORE_LOC;
yylval->str = strdup(yytext);
@@ -1691,7 +1692,7 @@ YY_RULE_SETUP
case 62:
/* rule 62 can match eol */
YY_RULE_SETUP
-#line 400 "ael.flex"
+#line 402 "ael.flex"
{
char fnamebuf[1024],*p1,*p2;
int glob_ret;
@@ -1741,7 +1742,7 @@ case YY_STATE_EOF(paren):
case YY_STATE_EOF(semic):
case YY_STATE_EOF(argg):
case YY_STATE_EOF(comment):
-#line 445 "ael.flex"
+#line 447 "ael.flex"
{
char fnamebuf[2048];
if (include_stack_index > 0 && include_stack[include_stack_index-1].globbuf_pos < include_stack[include_stack_index-1].globbuf.gl_pathc-1) {
@@ -1778,10 +1779,10 @@ case YY_STATE_EOF(comment):
YY_BREAK
case 63:
YY_RULE_SETUP
-#line 479 "ael.flex"
+#line 481 "ael.flex"
ECHO;
YY_BREAK
-#line 1784 "ael_lex.c"
+#line 1786 "ael_lex.c"
case YY_END_OF_BUFFER:
{
@@ -2906,7 +2907,7 @@ void *ael_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
-#line 479 "ael.flex"
+#line 481 "ael.flex"
diff --git a/res/ael/pval.c b/res/ael/pval.c
index 56794041d..38748ecde 100644
--- a/res/ael/pval.c
+++ b/res/ael/pval.c
@@ -3963,7 +3963,7 @@ static void fix_gotos_in_extensions(struct ael_extension *exten)
}
-void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root)
+void ast_compile_ael2(struct ast_context **local_contexts, struct ast_hashtab *local_table, struct pval *root)
{
pval *p,*p2;
struct ast_context *context;
@@ -3994,7 +3994,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root)
switch (p->type) {
case PV_MACRO:
- context = ast_context_create(local_contexts, p->u1.str, registrar);
+ context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
exten = new_exten();
exten->context = context;
@@ -4032,7 +4032,7 @@ void ast_compile_ael2(struct ast_context **local_contexts, struct pval *root)
break;
case PV_CONTEXT:
- context = ast_context_find_or_create(local_contexts, p->u1.str, registrar);
+ context = ast_context_find_or_create(local_contexts, local_table, p->u1.str, registrar);
/* contexts contain: ignorepat, includes, switches, eswitches, extensions, */
for (p2=p->u2.statements; p2; p2=p2->next) {
diff --git a/utils/Makefile b/utils/Makefile
index 4c6bb1114..5089ffe63 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -131,7 +131,7 @@ aelparse.c: $(ASTTOPDIR)/res/ael/ael_lex.c
aelparse.o: ASTCFLAGS+=-I$(ASTTOPDIR)/res -DSTANDALONE_AEL
-aelparse: aelparse.o aelbison.o pbx_ael.o ael_main.o ast_expr2f.o ast_expr2.o strcompat.o pval.o extconf.o
+aelparse: aelparse.o aelbison.o pbx_ael.o hashtab.o ael_main.o ast_expr2f.o ast_expr2.o strcompat.o pval.o extconf.o
astobj2.c: $(ASTTOPDIR)/main/astobj2.c
@cp $< $@
@@ -155,7 +155,7 @@ hashtest.o: ASTCFLAGS+=-O0
extconf.o: extconf.c
-conf2ael: conf2ael.o ast_expr2f.o ast_expr2.o aelbison.o aelparse.o pbx_ael.o pval.o extconf.o strcompat.o
+conf2ael: conf2ael.o ast_expr2f.o ast_expr2.o hashtab.o aelbison.o aelparse.o pbx_ael.o pval.o extconf.o strcompat.o
testexpr2s: $(ASTTOPDIR)/main/ast_expr2f.c $(ASTTOPDIR)/main/ast_expr2.c $(ASTTOPDIR)/main/ast_expr2.h
$(CC) -g -c -I$(ASTTOPDIR)/include -DSTANDALONE_AEL $(ASTTOPDIR)/main/ast_expr2f.c -o ast_expr2f.o
diff --git a/utils/ael_main.c b/utils/ael_main.c
index 7f20365f3..24349b457 100644
--- a/utils/ael_main.c
+++ b/utils/ael_main.c
@@ -19,6 +19,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/ast_expr.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
#include "asterisk/extconf.h"
@@ -582,3 +584,34 @@ int main(int argc, char **argv)
return 0;
}
+
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
+{
+ return 0;
+}
+
+unsigned int ast_hashtab_hash_contexts(const void *obj);
+
+unsigned int ast_hashtab_hash_contexts(const void *obj)
+{
+ return 0;
+}
+
+#ifdef DEBUG_THREADS
+
+void ast_mark_lock_acquired(void *lock_addr)
+{
+}
+
+void ast_remove_lock_info(void *lock_addr)
+{
+}
+
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+ int line_num, const char *func, const char *lock_name, void *lock_addr)
+{
+}
+
+#endif
diff --git a/utils/conf2ael.c b/utils/conf2ael.c
index fa6a3ccdb..56856efbf 100644
--- a/utils/conf2ael.c
+++ b/utils/conf2ael.c
@@ -47,6 +47,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/callerid.h"
+#include "asterisk/lock.h"
+#include "asterisk/hashtab.h"
#include "asterisk/ael_structs.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
@@ -604,14 +606,7 @@ int ast_context_add_include2(struct ast_context *con, const char *value,
return localized_context_add_include2(con, value,registrar);
}
-struct ast_context *ast_context_create(struct ast_context **extcontexts, const char *name, const char *registrar)
-{
- printf("Creating context %s, registrar=%s\n", name, registrar);
-
- return localized_context_create(extcontexts, name, registrar);
-}
-
-struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, const char *name, const char *registrar)
+struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
{
printf("find/Creating context %s, registrar=%s\n", name, registrar);
@@ -658,9 +653,9 @@ int ast_context_verify_includes(struct ast_context *con)
return localized_context_verify_includes(con);
}
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar);
+void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar);
-void ast_merge_contexts_and_delete(struct ast_context **extcontexts, const char *registrar)
+void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
{
localized_merge_contexts_and_delete(extcontexts, registrar);
}
@@ -688,3 +683,33 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
return localized_find_extension(bypass, q, context, exten, priority, label, callerid, action);
}
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
+
+int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
+{
+ return 0;
+}
+
+unsigned int ast_hashtab_hash_contexts(const void *obj);
+
+unsigned int ast_hashtab_hash_contexts(const void *obj)
+{
+ return 0;
+}
+
+#ifdef DEBUG_THREADS
+
+void ast_mark_lock_acquired(void *lock_addr)
+{
+}
+
+void ast_remove_lock_info(void *lock_addr)
+{
+}
+
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+ int line_num, const char *func, const char *lock_name, void *lock_addr)
+{
+}
+
+#endif
diff --git a/utils/extconf.c b/utils/extconf.c
index 5d4b21eac..9903ff295 100644
--- a/utils/extconf.c
+++ b/utils/extconf.c
@@ -23,6 +23,7 @@
* for operations outside of asterisk. A huge, awful hack.
*
*/
+#undef DEBUG_THREADS
#include "asterisk/compat.h"
#include "asterisk/paths.h" /* we use AST_CONFIG_DIR */
@@ -65,10 +66,9 @@ struct ast_channel
#include "asterisk/inline_api.h"
#include "asterisk/endian.h"
#include "asterisk/ast_expr.h"
-#include "asterisk/ael_structs.h"
-#include "asterisk/pval.h"
/* logger.h */
+
#define EVENTLOG "event_log"
#define QUEUELOG "queue_log"
@@ -147,6 +147,746 @@ void ast_console_toggle_mute(int fd);
#define __LOG_DTMF 6
#define LOG_DTMF __LOG_DTMF, _A_
+/* lock.h */
+
+#ifndef HAVE_MTX_PROFILE
+#define __MTX_PROF(a) return pthread_mutex_lock((a))
+#else
+#define __MTX_PROF(a) do { \
+ int i; \
+ /* profile only non-blocking events */ \
+ ast_mark(mtx_prof, 1); \
+ i = pthread_mutex_trylock((a)); \
+ ast_mark(mtx_prof, 0); \
+ if (!i) \
+ return i; \
+ else \
+ return pthread_mutex_lock((a)); \
+ } while (0)
+#endif /* HAVE_MTX_PROFILE */
+
+#define AST_PTHREADT_NULL (pthread_t) -1
+#define AST_PTHREADT_STOP (pthread_t) -2
+
+#if defined(SOLARIS) || defined(BSD)
+#define AST_MUTEX_INIT_W_CONSTRUCTORS
+#endif /* SOLARIS || BSD */
+
+/* Asterisk REQUIRES recursive (not error checking) mutexes
+ and will not run without them. */
+#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_MUTEX_RECURSIVE_NP)
+#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
+#else
+#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
+#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
+#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
+
+#ifdef DEBUG_THREADS
+
+#define __ast_mutex_logger(...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
+
+#ifdef THREAD_CRASH
+#define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
+#else
+#define DO_THREAD_CRASH do { } while (0)
+#endif
+
+#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
+
+#define AST_MAX_REENTRANCY 10
+
+struct ast_mutex_info {
+ pthread_mutex_t mutex;
+ /*! Track which thread holds this lock */
+ unsigned int track:1;
+ const char *file[AST_MAX_REENTRANCY];
+ int lineno[AST_MAX_REENTRANCY];
+ int reentrancy;
+ const char *func[AST_MAX_REENTRANCY];
+ pthread_t thread[AST_MAX_REENTRANCY];
+};
+
+typedef struct ast_mutex_info ast_mutex_t;
+
+typedef pthread_cond_t ast_cond_t;
+
+static pthread_mutex_t empty_mutex;
+
+static void __attribute__((constructor)) init_empty_mutex(void)
+{
+ memset(&empty_mutex, 0, sizeof(empty_mutex));
+}
+
+static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
+ const char *mutex_name, ast_mutex_t *t,
+ pthread_mutexattr_t *attr)
+{
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+ int canlog = strcmp(filename, "logger.c");
+
+ if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ if ((t->mutex) != (empty_mutex)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
+ filename, lineno, func, mutex_name);
+ __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
+ t->file[0], t->lineno[0], t->func[0], mutex_name);
+ DO_THREAD_CRASH;
+ return 0;
+ }
+ }
+#endif
+
+ t->file[0] = filename;
+ t->lineno[0] = lineno;
+ t->func[0] = func;
+ t->thread[0] = 0;
+ t->reentrancy = 0;
+
+ return pthread_mutex_init(&t->mutex, attr);
+}
+
+static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
+ const char *mutex_name, ast_mutex_t *t)
+{
+ static pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
+
+ return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
+}
+#define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
+
+static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
+ const char *mutex_name, ast_mutex_t *t)
+{
+ int res;
+ int canlog = strcmp(filename, "logger.c");
+
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+ if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ filename, lineno, func, mutex_name);
+ }
+#endif
+
+ res = pthread_mutex_trylock(&t->mutex);
+ switch (res) {
+ case 0:
+ pthread_mutex_unlock(&t->mutex);
+ break;
+ case EINVAL:
+ __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
+ filename, lineno, func, mutex_name);
+ break;
+ case EBUSY:
+ __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
+ filename, lineno, func, mutex_name);
+ __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
+ t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+ break;
+ }
+
+ if ((res = pthread_mutex_destroy(&t->mutex)))
+ __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
+ filename, lineno, func, strerror(res));
+#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+ else
+ t->mutex = PTHREAD_MUTEX_INIT_VALUE;
+#endif
+ t->file[0] = filename;
+ t->lineno[0] = lineno;
+ t->func[0] = func;
+
+ return res;
+}
+
+static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
+ const char* mutex_name, ast_mutex_t *t)
+{
+ int res;
+ int canlog = strcmp(filename, "logger.c");
+
+#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
+ if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ filename, lineno, func, mutex_name);
+ ast_mutex_init(t);
+ }
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+
+#ifdef DETECT_DEADLOCKS
+ {
+ time_t seconds = time(NULL);
+ time_t current;
+ do {
+#ifdef HAVE_MTX_PROFILE
+ ast_mark(mtx_prof, 1);
+#endif
+ res = pthread_mutex_trylock(&t->mutex);
+#ifdef HAVE_MTX_PROFILE
+ ast_mark(mtx_prof, 0);
+#endif
+ if (res == EBUSY) {
+ current = time(NULL);
+ if ((current - seconds) && (!((current - seconds) % 5))) {
+ __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
+ filename, lineno, func, (int)(current - seconds), mutex_name);
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
+ t->func[t->reentrancy-1], mutex_name);
+ }
+ usleep(200);
+ }
+ } while (res == EBUSY);
+ }
+#else
+#ifdef HAVE_MTX_PROFILE
+ ast_mark(mtx_prof, 1);
+ res = pthread_mutex_trylock(&t->mutex);
+ ast_mark(mtx_prof, 0);
+ if (res)
+#endif
+ res = pthread_mutex_lock(&t->mutex);
+#endif /* DETECT_DEADLOCKS */
+
+ if (!res) {
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = filename;
+ t->lineno[t->reentrancy] = lineno;
+ t->func[t->reentrancy] = func;
+ t->thread[t->reentrancy] = pthread_self();
+ t->reentrancy++;
+ } else {
+ __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ filename, lineno, func, mutex_name);
+ }
+ } else {
+ __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
+ filename, lineno, func, strerror(errno));
+ DO_THREAD_CRASH;
+ }
+
+ return res;
+}
+
+static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
+ const char* mutex_name, ast_mutex_t *t)
+{
+ int res;
+ int canlog = strcmp(filename, "logger.c");
+
+#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
+ if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ filename, lineno, func, mutex_name);
+ ast_mutex_init(t);
+ }
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+
+ if (!(res = pthread_mutex_trylock(&t->mutex))) {
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = filename;
+ t->lineno[t->reentrancy] = lineno;
+ t->func[t->reentrancy] = func;
+ t->thread[t->reentrancy] = pthread_self();
+ t->reentrancy++;
+ } else {
+ __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ filename, lineno, func, mutex_name);
+ }
+ } else {
+ __ast_mutex_logger("%s line %d (%s): Warning: '%s' was locked here.\n",
+ t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+ }
+
+ return res;
+}
+
+static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
+ const char *mutex_name, ast_mutex_t *t)
+{
+ int res;
+ int canlog = strcmp(filename, "logger.c");
+
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+ if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ filename, lineno, func, mutex_name);
+ }
+#endif
+
+ if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
+ __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
+ filename, lineno, func, mutex_name);
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+ DO_THREAD_CRASH;
+ }
+
+ if (--t->reentrancy < 0) {
+ __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
+ filename, lineno, func, mutex_name);
+ t->reentrancy = 0;
+ }
+
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = NULL;
+ t->lineno[t->reentrancy] = 0;
+ t->func[t->reentrancy] = NULL;
+ t->thread[t->reentrancy] = 0;
+ }
+
+ if ((res = pthread_mutex_unlock(&t->mutex))) {
+ __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
+ filename, lineno, func, strerror(res));
+ DO_THREAD_CRASH;
+ }
+
+ return res;
+}
+
+static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
+ const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
+{
+ return pthread_cond_init(cond, cond_attr);
+}
+
+static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
+ const char *cond_name, ast_cond_t *cond)
+{
+ return pthread_cond_signal(cond);
+}
+
+static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
+ const char *cond_name, ast_cond_t *cond)
+{
+ return pthread_cond_broadcast(cond);
+}
+
+static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
+ const char *cond_name, ast_cond_t *cond)
+{
+ return pthread_cond_destroy(cond);
+}
+
+static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
+ const char *cond_name, const char *mutex_name,
+ ast_cond_t *cond, ast_mutex_t *t)
+{
+ int res;
+ int canlog = strcmp(filename, "logger.c");
+
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+ if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ filename, lineno, func, mutex_name);
+ }
+#endif
+
+ if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
+ __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
+ filename, lineno, func, mutex_name);
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+ DO_THREAD_CRASH;
+ }
+
+ if (--t->reentrancy < 0) {
+ __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
+ filename, lineno, func, mutex_name);
+ t->reentrancy = 0;
+ }
+
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = NULL;
+ t->lineno[t->reentrancy] = 0;
+ t->func[t->reentrancy] = NULL;
+ t->thread[t->reentrancy] = 0;
+ }
+
+ if ((res = pthread_cond_wait(cond, &t->mutex))) {
+ __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
+ filename, lineno, func, strerror(res));
+ DO_THREAD_CRASH;
+ } else {
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = filename;
+ t->lineno[t->reentrancy] = lineno;
+ t->func[t->reentrancy] = func;
+ t->thread[t->reentrancy] = pthread_self();
+ t->reentrancy++;
+ } else {
+ __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ filename, lineno, func, mutex_name);
+ }
+ }
+
+ return res;
+}
+
+static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
+ const char *cond_name, const char *mutex_name, ast_cond_t *cond,
+ ast_mutex_t *t, const struct timespec *abstime)
+{
+ int res;
+ int canlog = strcmp(filename, "logger.c");
+
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+ if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
+ __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
+ filename, lineno, func, mutex_name);
+ }
+#endif
+
+ if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
+ __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
+ filename, lineno, func, mutex_name);
+ __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
+ t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+ DO_THREAD_CRASH;
+ }
+
+ if (--t->reentrancy < 0) {
+ __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
+ filename, lineno, func, mutex_name);
+ t->reentrancy = 0;
+ }
+
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = NULL;
+ t->lineno[t->reentrancy] = 0;
+ t->func[t->reentrancy] = NULL;
+ t->thread[t->reentrancy] = 0;
+ }
+
+ if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
+ __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
+ filename, lineno, func, strerror(res));
+ DO_THREAD_CRASH;
+ } else {
+ if (t->reentrancy < AST_MAX_REENTRANCY) {
+ t->file[t->reentrancy] = filename;
+ t->lineno[t->reentrancy] = lineno;
+ t->func[t->reentrancy] = func;
+ t->thread[t->reentrancy] = pthread_self();
+ t->reentrancy++;
+ } else {
+ __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
+ filename, lineno, func, mutex_name);
+ }
+ }
+
+ return res;
+}
+
+#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
+#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
+#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
+#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
+#define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
+#define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
+#define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
+#define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
+#define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
+#define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
+
+#else /* !DEBUG_THREADS */
+
+
+typedef pthread_mutex_t ast_mutex_t;
+
+#define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
+
+static inline int ast_mutex_init(ast_mutex_t *pmutex)
+{
+ pthread_mutexattr_t attr;
+
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
+
+ return pthread_mutex_init(pmutex, &attr);
+}
+
+#define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
+
+static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
+{
+ return pthread_mutex_unlock(pmutex);
+}
+
+static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
+{
+ return pthread_mutex_destroy(pmutex);
+}
+
+static inline int ast_mutex_lock(ast_mutex_t *pmutex)
+{
+ __MTX_PROF(pmutex);
+}
+
+static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
+{
+ return pthread_mutex_trylock(pmutex);
+}
+
+typedef pthread_cond_t ast_cond_t;
+
+static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
+{
+ return pthread_cond_init(cond, cond_attr);
+}
+
+static inline int ast_cond_signal(ast_cond_t *cond)
+{
+ return pthread_cond_signal(cond);
+}
+
+static inline int ast_cond_broadcast(ast_cond_t *cond)
+{
+ return pthread_cond_broadcast(cond);
+}
+
+static inline int ast_cond_destroy(ast_cond_t *cond)
+{
+ return pthread_cond_destroy(cond);
+}
+
+static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
+{
+ return pthread_cond_wait(cond, t);
+}
+
+static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
+{
+ return pthread_cond_timedwait(cond, t, abstime);
+}
+
+#endif /* !DEBUG_THREADS */
+
+#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
+/* If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
+ constructors/destructors to create/destroy mutexes. */
+#define __AST_MUTEX_DEFINE(scope, mutex) \
+ scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
+static void __attribute__ ((constructor)) init_##mutex(void) \
+{ \
+ ast_mutex_init(&mutex); \
+} \
+static void __attribute__ ((destructor)) fini_##mutex(void) \
+{ \
+ ast_mutex_destroy(&mutex); \
+}
+#else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
+/* By default, use static initialization of mutexes. */
+#define __AST_MUTEX_DEFINE(scope, mutex) \
+ scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+
+#define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
+#define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
+#define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
+#define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
+#define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
+#define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
+#define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
+#define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
+#define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
+#define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
+#define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
+#define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
+#define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
+
+#define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
+
+#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
+
+#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
+
+#ifndef __linux__
+#define pthread_create __use_ast_pthread_create_instead__
+#endif
+
+typedef pthread_rwlock_t ast_rwlock_t;
+
+static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
+{
+ pthread_rwlockattr_t attr;
+
+ pthread_rwlockattr_init(&attr);
+
+#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
+ pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
+#endif
+
+ return pthread_rwlock_init(prwlock, &attr);
+}
+
+static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
+{
+ return pthread_rwlock_destroy(prwlock);
+}
+
+static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
+{
+ return pthread_rwlock_unlock(prwlock);
+}
+
+static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
+{
+ return pthread_rwlock_rdlock(prwlock);
+}
+
+static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
+{
+ return pthread_rwlock_tryrdlock(prwlock);
+}
+
+static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
+{
+ return pthread_rwlock_wrlock(prwlock);
+}
+
+static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
+{
+ return pthread_rwlock_trywrlock(prwlock);
+}
+
+/* Statically declared read/write locks */
+
+#ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#define __AST_RWLOCK_DEFINE(scope, rwlock) \
+ scope ast_rwlock_t rwlock; \
+static void __attribute__ ((constructor)) init_##rwlock(void) \
+{ \
+ ast_rwlock_init(&rwlock); \
+} \
+static void __attribute__ ((destructor)) fini_##rwlock(void) \
+{ \
+ ast_rwlock_destroy(&rwlock); \
+}
+#else
+#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
+#define __AST_RWLOCK_DEFINE(scope, rwlock) \
+ scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
+#endif
+
+#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
+
+/*
+ * Initial support for atomic instructions.
+ * For platforms that have it, use the native cpu instruction to
+ * implement them. For other platforms, resort to a 'slow' version
+ * (defined in utils.c) that protects the atomic instruction with
+ * a single lock.
+ * The slow versions is always available, for testing purposes,
+ * as ast_atomic_fetchadd_int_slow()
+ */
+
+#if defined(HAVE_OSX_ATOMICS)
+#include "libkern/OSAtomic.h"
+#endif
+
+/*! \brief Atomically add v to *p and return * the previous value of *p.
+ * This can be used to handle reference counts, and the return value
+ * can be used to generate unique identifiers.
+ */
+
+#if defined(HAVE_GCC_ATOMICS)
+AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
+{
+ return __sync_fetch_and_add(p, v);
+})
+#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
+AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
+{
+ return OSAtomicAdd32(v, (int32_t *) p);
+})
+#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
+AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
+{
+ return OSAtomicAdd64(v, (int64_t *) p);
+#elif defined (__i386__) || defined(__x86_64__)
+AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
+{
+ __asm __volatile (
+ " lock xaddl %0, %1 ; "
+ : "+r" (v), /* 0 (result) */
+ "=m" (*p) /* 1 */
+ : "m" (*p)); /* 2 */
+ return (v);
+})
+#else
+static int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
+{
+ int ret;
+ ret = *p;
+ *p += v;
+ return ret;
+}
+AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
+{
+ return ast_atomic_fetchadd_int_slow(p, v);
+})
+#endif
+
+/*! \brief decrement *p by 1 and return true if the variable has reached 0.
+ * Useful e.g. to check if a refcount has reached 0.
+ */
+#if defined(HAVE_GCC_ATOMICS)
+AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
+{
+ return __sync_sub_and_fetch(p, 1) == 0;
+})
+#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
+AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
+{
+ return OSAtomicAdd32( -1, (int32_t *) p) == 0;
+})
+#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
+AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
+{
+ return OSAtomicAdd64( -1, (int64_t *) p) == 0;
+#else
+AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
+{
+ int a = ast_atomic_fetchadd_int(p, -1);
+ return a == 1; /* true if the value is 0 now (so it was 1 previously) */
+})
+#endif
+
+#ifndef DEBUG_CHANNEL_LOCKS
+/*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined
+ in the Makefile, print relevant output for debugging */
+#define ast_channel_lock(x) ast_mutex_lock(&x->lock)
+/*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined
+ in the Makefile, print relevant output for debugging */
+#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock)
+/*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined
+ in the Makefile, print relevant output for debugging */
+#define ast_channel_trylock(x) ast_mutex_trylock(&x->lock)
+#else
+
+/*! \brief Lock AST channel (and print debugging output)
+\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+int ast_channel_lock(struct ast_channel *chan);
+
+/*! \brief Unlock AST channel (and print debugging output)
+\note You need to enable DEBUG_CHANNEL_LOCKS for this function
+*/
+int ast_channel_unlock(struct ast_channel *chan);
+
+/*! \brief Lock AST channel (and print debugging output)
+\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
+int ast_channel_trylock(struct ast_channel *chan);
+#endif
+
+
+#include "asterisk/hashtab.h"
+#include "asterisk/ael_structs.h"
+#include "asterisk/pval.h"
+
/* from utils.h */
static unsigned int __unsigned_int_flags_dummy;
@@ -1119,742 +1859,6 @@ extern int ast_language_is_prefix;
-/* lock.h */
-
-#ifndef HAVE_MTX_PROFILE
-#define __MTX_PROF(a) return pthread_mutex_lock((a))
-#else
-#define __MTX_PROF(a) do { \
- int i; \
- /* profile only non-blocking events */ \
- ast_mark(mtx_prof, 1); \
- i = pthread_mutex_trylock((a)); \
- ast_mark(mtx_prof, 0); \
- if (!i) \
- return i; \
- else \
- return pthread_mutex_lock((a)); \
- } while (0)
-#endif /* HAVE_MTX_PROFILE */
-
-#define AST_PTHREADT_NULL (pthread_t) -1
-#define AST_PTHREADT_STOP (pthread_t) -2
-
-#if defined(SOLARIS) || defined(BSD)
-#define AST_MUTEX_INIT_W_CONSTRUCTORS
-#endif /* SOLARIS || BSD */
-
-/* Asterisk REQUIRES recursive (not error checking) mutexes
- and will not run without them. */
-#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_MUTEX_RECURSIVE_NP)
-#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
-#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
-#else
-#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
-#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
-#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
-
-#ifdef DEBUG_THREADS
-
-#define __ast_mutex_logger(...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
-
-#ifdef THREAD_CRASH
-#define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
-#else
-#define DO_THREAD_CRASH do { } while (0)
-#endif
-
-#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
-
-#define AST_MAX_REENTRANCY 10
-
-struct ast_mutex_info {
- pthread_mutex_t mutex;
- /*! Track which thread holds this lock */
- unsigned int track:1;
- const char *file[AST_MAX_REENTRANCY];
- int lineno[AST_MAX_REENTRANCY];
- int reentrancy;
- const char *func[AST_MAX_REENTRANCY];
- pthread_t thread[AST_MAX_REENTRANCY];
-};
-
-typedef struct ast_mutex_info ast_mutex_t;
-
-typedef pthread_cond_t ast_cond_t;
-
-static pthread_mutex_t empty_mutex;
-
-static void __attribute__((constructor)) init_empty_mutex(void)
-{
- memset(&empty_mutex, 0, sizeof(empty_mutex));
-}
-
-static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
- const char *mutex_name, ast_mutex_t *t,
- pthread_mutexattr_t *attr)
-{
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- int canlog = strcmp(filename, "logger.c");
-
- if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- if ((t->mutex) != (empty_mutex)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
- filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
- t->file[0], t->lineno[0], t->func[0], mutex_name);
- DO_THREAD_CRASH;
- return 0;
- }
- }
-#endif
-
- t->file[0] = filename;
- t->lineno[0] = lineno;
- t->func[0] = func;
- t->thread[0] = 0;
- t->reentrancy = 0;
-
- return pthread_mutex_init(&t->mutex, attr);
-}
-
-static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
- const char *mutex_name, ast_mutex_t *t)
-{
- static pthread_mutexattr_t attr;
-
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
-
- return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
-}
-#define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
-
-static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
- const char *mutex_name, ast_mutex_t *t)
-{
- int res;
- int canlog = strcmp(filename, "logger.c");
-
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
- filename, lineno, func, mutex_name);
- }
-#endif
-
- res = pthread_mutex_trylock(&t->mutex);
- switch (res) {
- case 0:
- pthread_mutex_unlock(&t->mutex);
- break;
- case EINVAL:
- __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
- filename, lineno, func, mutex_name);
- break;
- case EBUSY:
- __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
- filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
- t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
- break;
- }
-
- if ((res = pthread_mutex_destroy(&t->mutex)))
- __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
- filename, lineno, func, strerror(res));
-#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
- else
- t->mutex = PTHREAD_MUTEX_INIT_VALUE;
-#endif
- t->file[0] = filename;
- t->lineno[0] = lineno;
- t->func[0] = func;
-
- return res;
-}
-
-static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
- const char* mutex_name, ast_mutex_t *t)
-{
- int res;
- int canlog = strcmp(filename, "logger.c");
-
-#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
- if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
- filename, lineno, func, mutex_name);
- ast_mutex_init(t);
- }
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
-#ifdef DETECT_DEADLOCKS
- {
- time_t seconds = time(NULL);
- time_t current;
- do {
-#ifdef HAVE_MTX_PROFILE
- ast_mark(mtx_prof, 1);
-#endif
- res = pthread_mutex_trylock(&t->mutex);
-#ifdef HAVE_MTX_PROFILE
- ast_mark(mtx_prof, 0);
-#endif
- if (res == EBUSY) {
- current = time(NULL);
- if ((current - seconds) && (!((current - seconds) % 5))) {
- __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
- filename, lineno, func, (int)(current - seconds), mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
- t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
- t->func[t->reentrancy-1], mutex_name);
- }
- usleep(200);
- }
- } while (res == EBUSY);
- }
-#else
-#ifdef HAVE_MTX_PROFILE
- ast_mark(mtx_prof, 1);
- res = pthread_mutex_trylock(&t->mutex);
- ast_mark(mtx_prof, 0);
- if (res)
-#endif
- res = pthread_mutex_lock(&t->mutex);
-#endif /* DETECT_DEADLOCKS */
-
- if (!res) {
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- t->lineno[t->reentrancy] = lineno;
- t->func[t->reentrancy] = func;
- t->thread[t->reentrancy] = pthread_self();
- t->reentrancy++;
- } else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
- filename, lineno, func, mutex_name);
- }
- } else {
- __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
- filename, lineno, func, strerror(errno));
- DO_THREAD_CRASH;
- }
-
- return res;
-}
-
-static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
- const char* mutex_name, ast_mutex_t *t)
-{
- int res;
- int canlog = strcmp(filename, "logger.c");
-
-#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
- if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
- filename, lineno, func, mutex_name);
- ast_mutex_init(t);
- }
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
- if (!(res = pthread_mutex_trylock(&t->mutex))) {
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- t->lineno[t->reentrancy] = lineno;
- t->func[t->reentrancy] = func;
- t->thread[t->reentrancy] = pthread_self();
- t->reentrancy++;
- } else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
- filename, lineno, func, mutex_name);
- }
- } else {
- __ast_mutex_logger("%s line %d (%s): Warning: '%s' was locked here.\n",
- t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
- }
-
- return res;
-}
-
-static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
- const char *mutex_name, ast_mutex_t *t)
-{
- int res;
- int canlog = strcmp(filename, "logger.c");
-
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
- filename, lineno, func, mutex_name);
- }
-#endif
-
- if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
- filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
- t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
- DO_THREAD_CRASH;
- }
-
- if (--t->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
- filename, lineno, func, mutex_name);
- t->reentrancy = 0;
- }
-
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = NULL;
- t->lineno[t->reentrancy] = 0;
- t->func[t->reentrancy] = NULL;
- t->thread[t->reentrancy] = 0;
- }
-
- if ((res = pthread_mutex_unlock(&t->mutex))) {
- __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
- filename, lineno, func, strerror(res));
- DO_THREAD_CRASH;
- }
-
- return res;
-}
-
-static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
- const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
-{
- return pthread_cond_init(cond, cond_attr);
-}
-
-static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
- const char *cond_name, ast_cond_t *cond)
-{
- return pthread_cond_signal(cond);
-}
-
-static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
- const char *cond_name, ast_cond_t *cond)
-{
- return pthread_cond_broadcast(cond);
-}
-
-static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
- const char *cond_name, ast_cond_t *cond)
-{
- return pthread_cond_destroy(cond);
-}
-
-static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
- const char *cond_name, const char *mutex_name,
- ast_cond_t *cond, ast_mutex_t *t)
-{
- int res;
- int canlog = strcmp(filename, "logger.c");
-
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
- filename, lineno, func, mutex_name);
- }
-#endif
-
- if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
- filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
- t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
- DO_THREAD_CRASH;
- }
-
- if (--t->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
- filename, lineno, func, mutex_name);
- t->reentrancy = 0;
- }
-
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = NULL;
- t->lineno[t->reentrancy] = 0;
- t->func[t->reentrancy] = NULL;
- t->thread[t->reentrancy] = 0;
- }
-
- if ((res = pthread_cond_wait(cond, &t->mutex))) {
- __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
- filename, lineno, func, strerror(res));
- DO_THREAD_CRASH;
- } else {
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- t->lineno[t->reentrancy] = lineno;
- t->func[t->reentrancy] = func;
- t->thread[t->reentrancy] = pthread_self();
- t->reentrancy++;
- } else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
- filename, lineno, func, mutex_name);
- }
- }
-
- return res;
-}
-
-static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
- const char *cond_name, const char *mutex_name, ast_cond_t *cond,
- ast_mutex_t *t, const struct timespec *abstime)
-{
- int res;
- int canlog = strcmp(filename, "logger.c");
-
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
- if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
- __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
- filename, lineno, func, mutex_name);
- }
-#endif
-
- if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
- __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
- filename, lineno, func, mutex_name);
- __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
- t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
- DO_THREAD_CRASH;
- }
-
- if (--t->reentrancy < 0) {
- __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
- filename, lineno, func, mutex_name);
- t->reentrancy = 0;
- }
-
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = NULL;
- t->lineno[t->reentrancy] = 0;
- t->func[t->reentrancy] = NULL;
- t->thread[t->reentrancy] = 0;
- }
-
- if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
- __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
- filename, lineno, func, strerror(res));
- DO_THREAD_CRASH;
- } else {
- if (t->reentrancy < AST_MAX_REENTRANCY) {
- t->file[t->reentrancy] = filename;
- t->lineno[t->reentrancy] = lineno;
- t->func[t->reentrancy] = func;
- t->thread[t->reentrancy] = pthread_self();
- t->reentrancy++;
- } else {
- __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
- filename, lineno, func, mutex_name);
- }
- }
-
- return res;
-}
-
-#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
-#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
-#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
-#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
-#define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
-#define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
-#define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
-#define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
-#define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
-#define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
-
-#else /* !DEBUG_THREADS */
-
-
-typedef pthread_mutex_t ast_mutex_t;
-
-#define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
-
-static inline int ast_mutex_init(ast_mutex_t *pmutex)
-{
- pthread_mutexattr_t attr;
-
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
-
- return pthread_mutex_init(pmutex, &attr);
-}
-
-#define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
-
-static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
-{
- return pthread_mutex_unlock(pmutex);
-}
-
-static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
-{
- return pthread_mutex_destroy(pmutex);
-}
-
-static inline int ast_mutex_lock(ast_mutex_t *pmutex)
-{
- __MTX_PROF(pmutex);
-}
-
-static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
-{
- return pthread_mutex_trylock(pmutex);
-}
-
-typedef pthread_cond_t ast_cond_t;
-
-static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
-{
- return pthread_cond_init(cond, cond_attr);
-}
-
-static inline int ast_cond_signal(ast_cond_t *cond)
-{
- return pthread_cond_signal(cond);
-}
-
-static inline int ast_cond_broadcast(ast_cond_t *cond)
-{
- return pthread_cond_broadcast(cond);
-}
-
-static inline int ast_cond_destroy(ast_cond_t *cond)
-{
- return pthread_cond_destroy(cond);
-}
-
-static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
-{
- return pthread_cond_wait(cond, t);
-}
-
-static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
-{
- return pthread_cond_timedwait(cond, t, abstime);
-}
-
-#endif /* !DEBUG_THREADS */
-
-#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
-/* If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
- constructors/destructors to create/destroy mutexes. */
-#define __AST_MUTEX_DEFINE(scope, mutex) \
- scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
-static void __attribute__ ((constructor)) init_##mutex(void) \
-{ \
- ast_mutex_init(&mutex); \
-} \
-static void __attribute__ ((destructor)) fini_##mutex(void) \
-{ \
- ast_mutex_destroy(&mutex); \
-}
-#else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
-/* By default, use static initialization of mutexes. */
-#define __AST_MUTEX_DEFINE(scope, mutex) \
- scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
-#define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
-#define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
-#define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
-#define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
-#define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
-#define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
-#define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
-#define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
-#define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
-#define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
-#define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
-#define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
-#define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
-
-#define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
-
-#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
-
-#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
-
-#ifndef __linux__
-#define pthread_create __use_ast_pthread_create_instead__
-#endif
-
-typedef pthread_rwlock_t ast_rwlock_t;
-
-static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
-{
- pthread_rwlockattr_t attr;
-
- pthread_rwlockattr_init(&attr);
-
-#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
- pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
-#endif
-
- return pthread_rwlock_init(prwlock, &attr);
-}
-
-static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
-{
- return pthread_rwlock_destroy(prwlock);
-}
-
-static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
-{
- return pthread_rwlock_unlock(prwlock);
-}
-
-static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
-{
- return pthread_rwlock_rdlock(prwlock);
-}
-
-static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
-{
- return pthread_rwlock_tryrdlock(prwlock);
-}
-
-static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
-{
- return pthread_rwlock_wrlock(prwlock);
-}
-
-static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
-{
- return pthread_rwlock_trywrlock(prwlock);
-}
-
-/* Statically declared read/write locks */
-
-#ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
-#define __AST_RWLOCK_DEFINE(scope, rwlock) \
- scope ast_rwlock_t rwlock; \
-static void __attribute__ ((constructor)) init_##rwlock(void) \
-{ \
- ast_rwlock_init(&rwlock); \
-} \
-static void __attribute__ ((destructor)) fini_##rwlock(void) \
-{ \
- ast_rwlock_destroy(&rwlock); \
-}
-#else
-#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
-#define __AST_RWLOCK_DEFINE(scope, rwlock) \
- scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
-#endif
-
-#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
-
-/*
- * Initial support for atomic instructions.
- * For platforms that have it, use the native cpu instruction to
- * implement them. For other platforms, resort to a 'slow' version
- * (defined in utils.c) that protects the atomic instruction with
- * a single lock.
- * The slow versions is always available, for testing purposes,
- * as ast_atomic_fetchadd_int_slow()
- */
-
-#if defined(HAVE_OSX_ATOMICS)
-#include "libkern/OSAtomic.h"
-#endif
-
-/*! \brief Atomically add v to *p and return * the previous value of *p.
- * This can be used to handle reference counts, and the return value
- * can be used to generate unique identifiers.
- */
-
-#if defined(HAVE_GCC_ATOMICS)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
- return __sync_fetch_and_add(p, v);
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
- return OSAtomicAdd32(v, (int32_t *) p);
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
- return OSAtomicAdd64(v, (int64_t *) p);
-#elif defined (__i386__) || defined(__x86_64__)
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
- __asm __volatile (
- " lock xaddl %0, %1 ; "
- : "+r" (v), /* 0 (result) */
- "=m" (*p) /* 1 */
- : "m" (*p)); /* 2 */
- return (v);
-})
-#else
-static int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
-{
- int ret;
- ret = *p;
- *p += v;
- return ret;
-}
-AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
-{
- return ast_atomic_fetchadd_int_slow(p, v);
-})
-#endif
-
-/*! \brief decrement *p by 1 and return true if the variable has reached 0.
- * Useful e.g. to check if a refcount has reached 0.
- */
-#if defined(HAVE_GCC_ATOMICS)
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
- return __sync_sub_and_fetch(p, 1) == 0;
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
- return OSAtomicAdd32( -1, (int32_t *) p) == 0;
-})
-#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
- return OSAtomicAdd64( -1, (int64_t *) p) == 0;
-#else
-AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
-{
- int a = ast_atomic_fetchadd_int(p, -1);
- return a == 1; /* true if the value is 0 now (so it was 1 previously) */
-})
-#endif
-
-#ifndef DEBUG_CHANNEL_LOCKS
-/*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined
- in the Makefile, print relevant output for debugging */
-#define ast_channel_lock(x) ast_mutex_lock(&x->lock)
-/*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined
- in the Makefile, print relevant output for debugging */
-#define ast_channel_unlock(x) ast_mutex_unlock(&x->lock)
-/*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined
- in the Makefile, print relevant output for debugging */
-#define ast_channel_trylock(x) ast_mutex_trylock(&x->lock)
-#else
-
-/*! \brief Lock AST channel (and print debugging output)
-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
-int ast_channel_lock(struct ast_channel *chan);
-
-/*! \brief Unlock AST channel (and print debugging output)
-\note You need to enable DEBUG_CHANNEL_LOCKS for this function
-*/
-int ast_channel_unlock(struct ast_channel *chan);
-
-/*! \brief Lock AST channel (and print debugging output)
-\note You need to enable DEBUG_CHANNEL_LOCKS for this function */
-int ast_channel_trylock(struct ast_channel *chan);
-#endif
-
-
/* linkedlists.h */
#define AST_LIST_LOCK(head) \