Index: pbx.c =================================================================== RCS file: /usr/cvsroot/asterisk/pbx.c,v retrieving revision 1.241 diff -u -r1.241 pbx.c --- pbx.c 8 May 2005 17:10:58 -0000 1.241 +++ pbx.c 13 May 2005 07:04:58 -0000 @@ -554,11 +554,9 @@ ast_log(LOG_WARNING, "Unable to obtain application lock\n"); return NULL; } - tmp = apps; - while(tmp) { + AST_SL_TRAVERSE(apps, tmp, next) { if (!strcasecmp(tmp->name, app)) break; - tmp = tmp->next; } ast_mutex_unlock(&applock); return tmp; @@ -572,11 +570,9 @@ ast_log(LOG_WARNING, "Unable to obtain application lock\n"); return NULL; } - asw = switches; - while(asw) { + AST_SL_TRAVERSE(switches, asw, next) { if (!strcasecmp(asw->name, sw)) break; - asw = asw->next; } ast_mutex_unlock(&switchlock); return asw; @@ -706,16 +702,17 @@ return 0; } +/* + * Find the named context. If name = NULL, just the head of the list ? XXX + */ struct ast_context *ast_context_find(const char *name) { struct ast_context *tmp; ast_mutex_lock(&conlock); if (name) { - tmp = contexts; - while(tmp) { + AST_SL_TRAVERSE(contexts, tmp, next) { if (!strcasecmp(name, tmp->name)) break; - tmp = tmp->next; } } else tmp = contexts; @@ -773,14 +761,12 @@ if (!strcasecmp(incstack[x], context)) return NULL; } - if (bypass) - tmp = bypass; - else - tmp = contexts; - while(tmp) { + AST_SL_TRAVERSE(bypass ? bypass:contexts, tmp, next) { + struct ast_exten *earlymatch = NULL; + /* Match context */ - if (bypass || !strcmp(tmp->name, context)) { - struct ast_exten *earlymatch = NULL; + if (!bypass && strcmp(tmp->name, context) != 0) + continue; /* not this one - XXX should change indent of next block */ if (*status < STATUS_NO_EXTENSION) *status = STATUS_NO_EXTENSION; @@ -797,10 +783,9 @@ So ignore it for now, unless there's a better match */ earlymatch = eroot; } else { - e = eroot; if (*status < STATUS_NO_PRIORITY) *status = STATUS_NO_PRIORITY; - while(e) { + AST_SL_TRAVERSE(eroot, e, peer) { /* Match priority */ if (action == HELPER_FINDLABEL) { if (*status < STATUS_NO_LABEL) @@ -815,7 +800,6 @@ *foundcontext = context; return e; } - e = e->peer; } } } @@ -828,8 +812,7 @@ return NULL; } /* Check alternative switches */ - sw = tmp->alts; - while(sw) { + AST_SL_TRAVERSE(tmp->alts, sw, next) { if ((asw = pbx_findswitch(sw->name))) { /* Substitute variables now */ if (sw->eval) @@ -850,25 +833,20 @@ } else { ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name); } - sw = sw->next; } /* Setup the stack */ incstack[*stacklen] = tmp->name; (*stacklen)++; /* Now try any includes we have in this context */ - i = tmp->includes; - while(i) { + AST_SL_TRAVERSE(tmp->includes, i, next) { if (include_valid(i)) { if ((e = pbx_find_extension(chan, bypass, i->rname, exten, priority, label, callerid, action, incstack, stacklen, status, swo, data, foundcontext))) return e; if (*swo) return NULL; } - i = i->next; } break; - } - tmp = tmp->next; } return NULL; } @@ -1175,8 +1136,7 @@ return NULL; } - acf = acf_root; - while (acf) { + AST_SL_TRAVERSE(acf_root, acf, next) { if (!strncasecmp(word, acf->name, strlen(word))) { if (++which > state) { char *ret = strdup(acf->name); @@ -1184,7 +1144,6 @@ return ret; } } - acf = acf->next; } ast_mutex_unlock(&acflock); @@ -1201,7 +1160,7 @@ return NULL; } - for (acfptr = acf_root; acfptr; acfptr = acfptr->next) { + AST_SL_TRAVERSE(acf_root, acfptr, next) { if (!strcmp(name, acfptr->name)) { break; } @@ -1226,7 +1185,7 @@ return -1; } - for (acfptr = acf_root; acfptr; acfptr = acfptr->next) { + AST_SL_TRAVERSE_PREV(acf_root, acfptr, lastacf, next) { if (acfptr == acf) { if (lastacf) { lastacf->next = acf->next; @@ -1236,7 +1195,6 @@ res = 0; break; } - lastacf = acfptr; } ast_mutex_unlock(&acflock); @@ -1809,18 +1767,13 @@ ast_mutex_lock(&hintlock); /* First check device callbacks */ - devcb = devcbs; - while(devcb) { + AST_SL_TRAVERSE(devcbs, devcb, next) { if (devcb->callback) devcb->callback(device, state, devcb->data); - devcb = devcb->next; } /* Then check callbacks in hints */ - list = hints; - - while (list) { - + AST_SL_TRAVERSE(hints, list, next) { strncpy(hint, ast_get_extension_app(list->exten), sizeof(hint) - 1); cur = hint; do { @@ -1839,17 +1792,13 @@ /* Device state changed since last check - notify the watcher */ /* For general callbacks */ - cblist = statecbs; - while (cblist) { + AST_SL_TRAVERSE(statecbs, cblist, next) { cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data); - cblist = cblist->next; } /* For extension callbacks */ - cblist = list->callbacks; - while (cblist) { + AST_SL_TRAVERSE(list->callbacks, cblist, next) { cblist->callback(list->exten->parent->name, list->exten->exten, state, cblist->data); - cblist = cblist->next; } list->laststate = state; @@ -1858,7 +1807,6 @@ } cur = rest; } while (cur); - list = list->next; } ast_mutex_unlock(&hintlock); return 1; @@ -1914,14 +1862,12 @@ if (!context && !exten) { ast_mutex_lock(&hintlock); - cblist = statecbs; - while (cblist) { + AST_SL_TRAVERSE(statecbs, cblist, next) { if (cblist->callback == callback) { cblist->data = data; ast_mutex_unlock(&hintlock); return 0; } - cblist = cblist->next; } /* Now insert the callback */ @@ -1953,12 +1899,9 @@ /* Find the hint in the list of hints */ ast_mutex_lock(&hintlock); - list = hints; - - while (list) { + AST_SL_TRAVERSE(hints, list, next) { if (list->exten == e) break; - list = list->next; } if (!list) { @@ -1996,52 +1939,37 @@ ast_mutex_lock(&hintlock); - /* id is zero is a callback without extension */ - if (!id) { - cbprev = NULL; - cblist = statecbs; - while (cblist) { + /* id == zero is a callback without extension */ + if (id == 0) { + AST_SL_TRAVERSE_PREV(statecbs, cblist, cbprev, next) { if (cblist->callback == callback) { if (!cbprev) - statecbs = cblist->next; + statecbs = cblist->next; else - cbprev->next = cblist->next; - + cbprev->next = cblist->next; free(cblist); - - ast_mutex_unlock(&hintlock); + ast_mutex_unlock(&hintlock); return 0; - } - cbprev = cblist; - cblist = cblist->next; + } } - ast_mutex_lock(&hintlock); return -1; } /* id greater than zero is a callback with extension */ /* Find the callback based on ID */ - list = hints; - while (list) { - cblist = list->callbacks; - cbprev = NULL; - while (cblist) { - if (cblist->id==id) { + AST_SL_TRAVERSE(hints, list, next) { + AST_SL_TRAVERSE_PREV(list->callbacks, cblist, cbprev, next) { + if (cblist->id==id) { if (!cbprev) - list->callbacks = cblist->next; + list->callbacks = cblist->next; else - cbprev->next = cblist->next; - + cbprev->next = cblist->next; free(cblist); - ast_mutex_unlock(&hintlock); return 0; - } - cbprev = cblist; - cblist = cblist->next; + } } - list = list->next; } ast_mutex_unlock(&hintlock); @@ -2057,17 +1985,14 @@ return -1; ast_mutex_lock(&hintlock); - list = hints; - /* Search if hint exists, do nothing */ - while (list) { + AST_SL_TRAVERSE(hints, list, next) { if (list->exten == e) { ast_mutex_unlock(&hintlock); if (option_debug > 1) ast_log(LOG_DEBUG, "HINTS: Not re-adding existing hint %s: %s\n", ast_get_extension_name(e), ast_get_extension_app(e)); return -1; } - list = list->next; } if (option_debug > 1) @@ -2097,15 +2022,12 @@ struct ast_hint *list; ast_mutex_lock(&hintlock); - list = hints; - - while(list) { + AST_SL_TRAVERSE(hints, list, next) { if (list->exten == oe) { - list->exten = ne; + list->exten = ne; ast_mutex_unlock(&hintlock); return 0; } - list = list->next; } ast_mutex_unlock(&hintlock); @@ -2124,32 +2046,28 @@ ast_mutex_lock(&hintlock); - list = hints; - while(list) { - if (list->exten==e) { - cbprev = NULL; - cblist = list->callbacks; - while (cblist) { - /* Notify with -1 and remove all callbacks */ - cbprev = cblist; - cblist = cblist->next; - cbprev->callback(list->exten->parent->name, list->exten->exten, -1, cbprev->data); - free(cbprev); - } - list->callbacks = NULL; - - if (!prev) - hints = list->next; - else - prev->next = list->next; - free(list); - - ast_mutex_unlock(&hintlock); - return 0; - } else { - prev = list; - list = list->next; + AST_SL_TRAVERSE_PREV(hints, list, prev, next) { + if (list->exten != e) + continue; + + cblist = list->callbacks; + while (cblist) { + /* Notify with -1 and remove all callbacks */ + cbprev = cblist; + cblist = cblist->next; + cbprev->callback(list->exten->parent->name, list->exten->exten, -1, cbprev->data); + free(cbprev); } + list->callbacks = NULL; + + if (!prev) + hints = list->next; + else + prev->next = list->next; + free(list); + + ast_mutex_unlock(&hintlock); + return 0; } ast_mutex_unlock(&hintlock); @@ -2446,6 +2364,7 @@ static void *pbx_thread(void *data) { + /* XXX what the comment on setjmp is about ??? */ /* Oh joyeous kernel, we're a new thread, with nothing to do but answer this channel and get it going. The setjmp stuff is fairly confusing, but necessary to get smooth transitions between @@ -2711,10 +2651,9 @@ return 0; } else { /* remove only extension with exten->priority == priority */ - struct ast_exten *previous_peer = NULL; + struct ast_exten *previous_peer; - peer = exten; - while (peer) { + AST_SL_TRAVERSE_PREV(exten, peer, previous_peer, peer) { /* is this our extension? */ if (peer->priority == priority && (!registrar || !strcmp(peer->registrar, registrar) )) { @@ -2752,10 +2691,6 @@ ast_mutex_unlock(&con->lock); return 0; - } else { - /* this is not right extension, skip to next peer */ - previous_peer = peer; - peer = peer->peer; } } @@ -2785,14 +2717,12 @@ ast_log(LOG_ERROR, "Unable to lock application list\n"); return -1; } - tmp = apps; - while(tmp) { + AST_SL_TRAVERSE(apps, tmp, next) { if (!strcasecmp(app, tmp->name)) { ast_log(LOG_WARNING, "Already have an application '%s'\n", app); ast_mutex_unlock(&applock); return -1; } - tmp = tmp->next; } tmp = malloc(length); if (tmp) { @@ -2802,13 +2732,9 @@ tmp->synopsis = synopsis; tmp->description = description; /* Store in alphabetical order */ - cur = apps; - prev = NULL; - while(cur) { + AST_SL_TRAVERSE_PREV(apps, cur, prev, next) { if (strcasecmp(tmp->name, cur->name) < 0) break; - prev = cur; - cur = cur->next; } if (prev) { tmp->next = prev->next; @@ -2835,12 +2761,9 @@ ast_log(LOG_ERROR, "Unable to lock switch lock\n"); return -1; } - tmp = switches; - while(tmp) { + AST_SL_TRAVERSE_PREV(switches, tmp, prev, next) { if (!strcasecmp(tmp->name, sw->name)) break; - prev = tmp; - tmp = tmp->next; } if (tmp) { ast_mutex_unlock(&switchlock); @@ -2863,8 +2786,7 @@ ast_log(LOG_ERROR, "Unable to lock switch lock\n"); return; } - tmp = switches; - while(tmp) { + AST_SL_TRAVERSE_PREV(switches, tmp, prev, next) { if (tmp == sw) { if (prev) prev->next = tmp->next; @@ -2873,8 +2795,6 @@ tmp->next = NULL; break; } - prev = tmp; - tmp = tmp->next; } ast_mutex_unlock(&switchlock); } @@ -2940,8 +2860,7 @@ } /* ... walk all applications ... */ - a = apps; - while (a) { + AST_SL_TRAVERSE(apps, a, next) { /* ... check if word matches this application ... */ if (!strncasecmp(word, a->name, strlen(word))) { /* ... if this is right app serve it ... */ @@ -2951,7 +2870,6 @@ return ret; } } - a = a->next; } /* no application match */ @@ -2973,8 +2891,7 @@ } /* ... go through all applications ... */ - a = apps; - while (a) { + AST_SL_TRAVERSE(apps, a, next) { /* ... compare this application name with all arguments given * to 'show application' command ... */ for (app = 2; app < argc; app++) { @@ -2986,6 +2903,7 @@ no_registered_app = 0; + /* XXX this code is replicated 2 times! */ if (a->synopsis) synopsis_size = strlen(a->synopsis) + 23; else @@ -3022,7 +2940,6 @@ } } } - a = a->next; } ast_mutex_unlock(&applock); @@ -3052,11 +2969,9 @@ ast_log(LOG_ERROR, "Unable to lock hints\n"); return -1; } - hint = hints; - while (hint) { + AST_SL_TRAVERSE(hints, hint, next) { ast_cli(fd, " %-20.20s: %-20.20s State %2d\n", ast_get_extension_name(hint->exten), ast_get_extension_app(hint->exten), hint->laststate ); num++; - hint = hint->next; } ast_cli(fd, "----------------\n"); ast_cli(fd, "- %d hints registred\n", num); @@ -3078,10 +2993,8 @@ ast_log(LOG_ERROR, "Unable to lock switches\n"); return -1; } - sw = switches; - while (sw) { + AST_SL_TRAVERSE(switches, sw, next) { ast_cli(fd, "%s: %s\n", sw->name, sw->description); - sw = sw->next; } ast_mutex_unlock(&switchlock); return RESULT_SUCCESS; @@ -3125,7 +3038,7 @@ } /* ... go through all applications ... */ - for (a = apps; a; a = a->next) { + AST_SL_TRAVERSE(apps, a, next) { /* ... show informations about applications ... */ int printapp=0; total_apps++; @@ -3525,8 +3436,7 @@ ast_log(LOG_ERROR, "Unable to lock application list\n"); return -1; } - tmp = apps; - while(tmp) { + AST_SL_TRAVERSE_PREV(apps, tmp, tmpl, next) { if (!strcasecmp(app, tmp->name)) { if (tmpl) tmpl->next = tmp->next; @@ -3538,8 +3448,6 @@ ast_mutex_unlock(&applock); return 0; } - tmpl = tmp; - tmp = tmp->next; } ast_mutex_unlock(&applock); return -1; @@ -3557,8 +3465,7 @@ } else local_contexts = extcontexts; - tmp = *local_contexts; - while(tmp) { + AST_SL_TRAVERSE(*local_contexts, tmp, next) { if (!strcasecmp(tmp->name, name)) { ast_mutex_unlock(&conlock); ast_log(LOG_WARNING, "Tried to register context '%s', already in use\n", name); @@ -3566,7 +3473,6 @@ ast_mutex_unlock(&conlock); return NULL; } - tmp = tmp->next; } tmp = malloc(length); if (tmp) { @@ -4037,16 +3943,13 @@ } /* ... go to last include and check if context is already included too... */ - i = con->includes; - while (i) { + AST_SL_TRAVERSE_PREV(con->includes, i, il, next) { if (!strcasecmp(i->name, new_include->name)) { free(new_include); ast_mutex_unlock(&con->lock); errno = EEXIST; return -1; } - il = i; - i = i->next; } /* ... include new context into context list, unlock, return */ @@ -4155,16 +4064,13 @@ } /* ... go to last sw and check if context is already swd too... */ - i = con->alts; - while (i) { + AST_SL_TRAVERSE_PREV(con->alts, i, il, next) { if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) { free(new_sw); ast_mutex_unlock(&con->lock); errno = EEXIST; return -1; } - il = i; - i = i->next; } /* ... sw new context into context list, unlock, return */ @@ -4216,8 +4127,7 @@ return -1; } - ip = con->ignorepats; - while (ip) { + AST_SL_TRAVERSE_PREV(con->ignorepats, ip, ipl, next) { if (!strcmp(ip->pattern, ignorepat) && (!registrar || (registrar == ip->registrar))) { if (ipl) { @@ -4230,7 +4140,6 @@ ast_mutex_unlock(&con->lock); return 0; } - ipl = ip; ip = ip->next; } ast_mutex_unlock(&con->lock); @@ -4283,16 +4196,13 @@ ignorepat->next = NULL; ignorepat->registrar = registrar; ast_mutex_lock(&con->lock); - ignorepatc = con->ignorepats; - while(ignorepatc) { - ignorepatl = ignorepatc; + AST_SL_TRAVERSE_PREV(con->ignorepats, ignorepatc, ignorepatl, next) { if (!strcasecmp(ignorepatc->pattern, value)) { /* Already there */ ast_mutex_unlock(&con->lock); errno = EEXIST; return -1; } - ignorepatc = ignorepatc->next; } if (ignorepatl) ignorepatl->next = ignorepat; @@ -4310,16 +4220,15 @@ con = ast_context_find(context); if (con) { - pat = con->ignorepats; - while (pat) { + AST_SL_TRAVERSE(con->ignorepats, pat, next) { if (ast_extension_match(pat->pattern, pattern)) return 1; - pat = pat->next; } } return 0; } + /* * EBUSY - can't lock * ENOENT - no existence of context @@ -4550,8 +4487,7 @@ errno = EBUSY; return -1; } - e = con->root; - while(e) { + AST_SL_TRAVERSE_PREV(con->root, e, el, next) { /* Make sure patterns are always last! */ if ((e->exten[0] != '_') && (extension[0] == '_')) res = -1; @@ -4572,7 +4508,12 @@ if (res == 0) { /* We have an exact match, now we find where we are and be sure there's no duplicates */ - while(e) { + /* + * traverse the list of peers. We can modify e safely + * because we will return at the end, thus exiting + * the previous loop. + */ + AST_SL_TRAVERSE_PREV(e, e, ep, peer) { if (e->priority == tmp->priority) { /* Can't have something exactly the same. Is this a replacement? If so, replace, otherwise, bonk. */ @@ -4639,8 +4580,6 @@ LOG; return 0; } - ep = e; - e = e->peer; } /* If we make it here, then it's time for us to go at the very end. ep *must* be defined or we couldn't have gotten here. */ @@ -4672,9 +4611,6 @@ LOG; return 0; } - - el = e; - e = e->next; } /* If we fall all the way through to here, then we need to be on the end. */ if (el) @@ -5116,8 +5052,7 @@ struct ast_ignorepat *ipi, *ipl = NULL; ast_mutex_lock(&conlock); - tmp = contexts; - while(tmp) { + AST_SL_TRAVERSE_PREV(contexts, tmp, tmpl, next) { if (((tmp->name && con && con->name && !strcasecmp(tmp->name, con->name)) || !con) && (!registrar || !strcasecmp(registrar, tmp->registrar))) { /* Okay, let's lock the structure to be sure nobody else @@ -5150,7 +5085,6 @@ swl = sw; sw = sw->next; free(swl); - swl = sw; } for (e = tmp->root; e;) { for (en = e->peer; en;) { @@ -5174,8 +5108,6 @@ ast_mutex_unlock(&conlock); return; } - tmpl = tmp; - tmp = tmp->next; } ast_mutex_unlock(&conlock); } @@ -5634,28 +5566,29 @@ struct ast_var_t *variables; struct varshead *headp; - if (chan) - headp=&chan->varshead; - else - headp=&globals; - - if (name) { + if (name == NULL) + return NULL; + /* run at most twice, once on chan->varshead and once on globals */ + for (headp = chan ? &chan->varshead : &globals; ; headp = &globals) { AST_LIST_TRAVERSE(headp,variables,entries) { if (!strcmp(name, ast_var_name(variables))) return ast_var_value(variables); } - if (headp != &globals) { - /* Check global variables if we haven't already */ - headp = &globals; - AST_LIST_TRAVERSE(headp,variables,entries) { - if (!strcmp(name, ast_var_name(variables))) - return ast_var_value(variables); - } - } + if (headp == &globals) + break; } return NULL; } +/* + * Set a variable or call the write method on a channel's function. + * XXX NOTE - reassigning the value of an existing variable is inefficient + * as it does a second pass of the list to remove the element, and then + * inserts at the head. It would make more sense to reassign the value + * to the existing variable. + * In any case a method AST_LIST_TRAVERSE2(headp, prev, curr, link_field) + * would be more useful here. + */ void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value) { struct ast_var_t *newvariable; @@ -6033,10 +5966,7 @@ */ struct ast_context *ast_walk_contexts(struct ast_context *con) { - if (!con) - return contexts; - else - return con->next; + return con ? con->next : contexts; } struct ast_exten *ast_walk_context_extensions(struct ast_context *con, @@ -6060,10 +5990,7 @@ struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority) { - if (!priority) - return exten; - else - return priority->peer; + return priority ? priority->peer : exten; } struct ast_include *ast_walk_context_includes(struct ast_context *con, @@ -6105,13 +6032,15 @@ if (!chan) return -2; + if (context == NULL) + context = chan->context; + if (exten == NULL) + exten = chan->exten; goto_func = (async) ? ast_async_goto : ast_explicit_goto; - if (ast_exists_extension(chan, context ? context : chan->context, - exten ? exten : chan->exten, priority, + if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num)) - return goto_func(chan, context ? context : chan->context, - exten ? exten : chan->exten, priority); + return goto_func(chan, context, exten, priority); else return -3; } Index: include/asterisk/linkedlists.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/linkedlists.h,v retrieving revision 1.12 diff -u -r1.12 linkedlists.h --- include/asterisk/linkedlists.h 21 Apr 2005 06:02:44 -0000 1.12 +++ include/asterisk/linkedlists.h 13 May 2005 07:05:23 -0000 @@ -284,4 +284,11 @@ } \ } while (0) +/* Traverse a simple list using the speecified link field */ +#define AST_SL_TRAVERSE(head, p, link_field) \ + for (p = (head); p != NULL ; p = p->link_field) + +#define AST_SL_TRAVERSE_PREV(head, p, prev, link_field) \ + for (prev = NULL, p = (head); p != NULL ; prev = p, p = p->link_field) + #endif