diff options
-rwxr-xr-x | apps/app_sql_postgres.c | 2 | ||||
-rwxr-xr-x | channel.c | 2 | ||||
-rwxr-xr-x | include/asterisk/linkedlists.h | 67 | ||||
-rwxr-xr-x | pbx.c | 4 | ||||
-rwxr-xr-x | pbx/pbx_dundi.c | 2 | ||||
-rwxr-xr-x | pbx/pbx_loopback.c | 2 |
6 files changed, 60 insertions, 19 deletions
diff --git a/apps/app_sql_postgres.c b/apps/app_sql_postgres.c index f2e99dea4..ddbd1ca73 100755 --- a/apps/app_sql_postgres.c +++ b/apps/app_sql_postgres.c @@ -191,7 +191,7 @@ static int del_identifier(int identifier,int identifier_type) { AST_LIST_TRAVERSE(headp,i,entries) { if ((i->identifier==identifier) && (i->identifier_type==identifier_type)) { - AST_LIST_REMOVE(headp,i,ast_PGSQL_id,entries); + AST_LIST_REMOVE(headp,i,entries); free(i); found=1; break; @@ -673,7 +673,7 @@ void ast_channel_free(struct ast_channel *chan) /* no need to lock the list, as the channel is already locked */ while (!AST_LIST_EMPTY(headp)) { /* List Deletion. */ - vardata = AST_LIST_REMOVE_HEAD(headp, ast_var_t, entries); + vardata = AST_LIST_REMOVE_HEAD(headp, entries); /* printf("deleting var %s=%s\n",ast_var_name(vardata),ast_var_value(vardata)); */ ast_var_delete(vardata); } diff --git a/include/asterisk/linkedlists.h b/include/asterisk/linkedlists.h index 5e306fe37..bf2009635 100755 --- a/include/asterisk/linkedlists.h +++ b/include/asterisk/linkedlists.h @@ -148,6 +148,50 @@ struct { \ for((var) = (head)->first; (var); (var) = (var)->field.next) /*! + \brief Loops safely over (traverses) the entries in a list. + \param head This is a pointer to the list head structure + \param var This is the name of the variable that will hold a pointer to the + current list entry on each iteration. It must be declared before calling + this macro. + \param field This is the name of the field (declared using AST_LIST_ENTRY()) + used to link entries of this list together. + + This macro is used to safely loop over (traverse) the entries in a list. It + uses a \a for loop, and supplies the enclosed code with a pointer to each list + entry as it loops. It is typically used as follows: + \code + static AST_LIST_HEAD(entry_list, list_entry) entries; + ... + struct list_entry { + ... + AST_LIST_ENTRY(list_entry) list; + } + ... + struct list_entry *current; + ... + AST_LIST_TRAVERSE_SAFE_BEGIN(&entries, current, list_entry, list) { + (do something with current here) + } + AST_LIST_TRAVERSE_SAFE_END + \endcode + + It differs from AST_LIST_TRAVERSE in that the code inside the loop can modify + (or even free) the entry pointed to by the \a current pointer without affecting + the loop traversal. +*/ +#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field) { \ + typeof((head)->first) __list_next; \ + for ((var) = (head)->first, __list_next = (var) ? (var)->field.next : NULL; \ + (var); \ + (var) = __list_next, __list_next = (var) ? (var)->field.next : NULL \ + ) + +/*! + \brief Closes a safe loop traversal block. + */ +#define AST_LIST_TRAVERSE_SAFE_END } + +/*! \brief Initializes a list head structure. \param head This is a pointer to the list head structure @@ -188,34 +232,32 @@ struct { \ \brief Inserts a list entry at the tail of a list. \param head This is a pointer to the list head structure \param elm This is a pointer to the entry to be inserted. - \param type This is the type of each list entry. \param field This is the name of the field (declared using AST_LIST_ENTRY()) used to link entries of this list together. */ -#define AST_LIST_INSERT_TAIL(head, elm, type, field) do { \ - struct type *curelm = (head)->first; \ - if(!curelm) { \ +#define AST_LIST_INSERT_TAIL(head, elm, field) do { \ + typeof(elm) curelm = (head)->first; \ + if (!curelm) { \ AST_LIST_INSERT_HEAD(head, elm, field); \ } else { \ - while ( curelm->field.next!=NULL ) { \ + while (curelm->field.next!=NULL) { \ curelm=curelm->field.next; \ } \ - AST_LIST_INSERT_AFTER(curelm,elm,field); \ + AST_LIST_INSERT_AFTER(curelm, elm, field); \ } \ } while (0) /*! \brief Removes and returns the head entry from a list. \param head This is a pointer to the list head structure - \param type This is the type of each list entry. \param field This is the name of the field (declared using AST_LIST_ENTRY()) used to link entries of this list together. Removes the head entry from the list, and returns a pointer to it. The forward-link pointer in the returned entry is \b not cleared. */ -#define AST_LIST_REMOVE_HEAD(head, type, field) ({ \ - struct type *cur = (head)->first; \ +#define AST_LIST_REMOVE_HEAD(head, field) ({ \ + typeof((head)->first) cur = (head)->first; \ (head)->first = (head)->first->field.next; \ cur; \ }) @@ -224,17 +266,16 @@ struct { \ \brief Removes a specific entry from a list. \param head This is a pointer to the list head structure \param elm This is a pointer to the entry to be removed. - \param type This is the type of each list entry. \param field This is the name of the field (declared using AST_LIST_ENTRY()) used to link entries of this list together. \warning The removed entry is \b not freed nor modified in any way. */ -#define AST_LIST_REMOVE(head, elm, type, field) do { \ +#define AST_LIST_REMOVE(head, elm, field) do { \ if ((head)->first == (elm)) { \ - AST_LIST_REMOVE_HEAD((head), type, field); \ + AST_LIST_REMOVE_HEAD((head), field); \ } \ else { \ - struct type *curelm = (head)->first; \ + typeof(elm) curelm = (head)->first; \ while( curelm->field.next != (elm) ) \ curelm = curelm->field.next; \ curelm->field.next = \ @@ -5052,7 +5052,7 @@ void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value AST_LIST_TRAVERSE (headp, newvariable, entries) { if (strcasecmp(ast_var_name(newvariable), name) == 0) { /* there is already such a variable, delete it */ - AST_LIST_REMOVE(headp, newvariable, ast_var_t, entries); + AST_LIST_REMOVE(headp, newvariable, entries); ast_var_delete(newvariable); break; } @@ -5155,7 +5155,7 @@ void pbx_builtin_clear_globals(void) { struct ast_var_t *vardata; while (!AST_LIST_EMPTY(&globals)) { - vardata = AST_LIST_REMOVE_HEAD(&globals, ast_var_t, entries); + vardata = AST_LIST_REMOVE_HEAD(&globals, entries); ast_var_delete(vardata); } } diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index d0cab9c7d..6274aa89f 100755 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -551,7 +551,7 @@ static int dundi_lookup_local(struct dundi_result *dr, struct dundi_mapping *map AST_LIST_INSERT_HEAD(&headp, newvariable, entries); pbx_substitute_variables_varshead(&headp, map->dest, dr[anscnt].dest, sizeof(dr[anscnt].dest)); while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */ - newvariable = AST_LIST_REMOVE_HEAD(&headp, ast_var_t, entries); + newvariable = AST_LIST_REMOVE_HEAD(&headp, entries); ast_var_delete(newvariable); } } else diff --git a/pbx/pbx_loopback.c b/pbx/pbx_loopback.c index 16b854099..0868cd7c4 100755 --- a/pbx/pbx_loopback.c +++ b/pbx/pbx_loopback.c @@ -81,7 +81,7 @@ static char *loopback_helper(char *buf, int buflen, const char *exten, const cha pbx_substitute_variables_varshead(&headp, data, buf, buflen); /* Substitute variables */ while (!AST_LIST_EMPTY(&headp)) { /* List Deletion. */ - newvariable = AST_LIST_REMOVE_HEAD(&headp, ast_var_t, entries); + newvariable = AST_LIST_REMOVE_HEAD(&headp, entries); ast_var_delete(newvariable); } return buf; |