diff --git a/main/pbx.c b/main/pbx.c index 25a4dbde7fbad4e0ddea8bcb119fd53ea10cc6de..7a8923f8e3c271ce09a6351f1badbfd295654a68 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -1001,25 +1001,49 @@ static struct ast_exten *trie_find_next_match(struct match_char *node) return NULL; } +#ifdef DEBUG_THIS +static char *action2str(enum ext_match_t action) +{ + switch(action) + { + case E_MATCH: + return "MATCH"; + case E_CANMATCH: + return "CANMATCH"; + case E_MATCHMORE: + return "MATCHMORE"; + case E_FINDLABEL: + return "FINDLABEL"; + case E_SPAWN: + return "SPAWN"; + default: + return "?ACTION?"; + } +} + +#endif + static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, enum ext_match_t action) { struct match_char *p; /* note minimal stack storage requirements */ #ifdef DEBUG_THIS if (tree) - ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s\n", str, tree->x); + ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action)); else - ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL\n", str); + ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action)); #endif for (p=tree; p; p=p->alt_char) { if (p->x[0] == 'N') { if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) { #define NEW_MATCHER_CHK_MATCH \ - if (p->exten && !(*(str+1))) { /* if a shorter pattern matches along the way, might as well report it */ \ - if (action == E_MATCH) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ - update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p); \ - if (!p->deleted) \ - return; /* the first match, by definition, will be the best, because of the sorted tree */ \ - } \ + if (p->exten && !(*(str+1))) { /* if a shorter pattern matches along the way, might as well report it */ \ + if (action == E_MATCH || action == E_SPAWN) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \ + update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p); \ + if (!p->deleted) { \ + ast_debug(4,"returning an exact match-- first found-- %s\n", p->exten->exten); \ + return; /* the first match, by definition, will be the best, because of the sorted tree */ \ + } \ + } \ } #define NEW_MATCHER_RECURSE \ @@ -1027,18 +1051,25 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct || p->next_char->x[0] == '!')) { \ if (*(str+1) || p->next_char->x[0] == '!') { \ new_find_extension(str+1, score, p->next_char, length+1, spec+p->specificity, callerid, action); \ - if (score->exten) \ + if (score->exten) { \ + ast_debug(4,"returning an exact match-- %s\n", score->exten->exten); \ return; /* the first match is all we need */ \ + } \ } else { \ new_find_extension("/", score, p->next_char, length+1, spec+p->specificity, callerid, action); \ - if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) \ + if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \ + ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \ + "NULL"); \ return; /* the first match is all we need */ \ + } \ } \ } else if (p->next_char && !*(str+1)) { \ score->canmatch = 1; \ score->canmatch_exten = get_canmatch_exten(p); \ - if (action == E_CANMATCH || action == E_MATCHMORE) \ + if (action == E_CANMATCH || action == E_MATCHMORE) { \ + ast_debug(4,"returning a canmatch/matchmore--- str=%s\n", str); \ return; \ + } \ } NEW_MATCHER_CHK_MATCH; @@ -1064,13 +1095,17 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct } if (p->exten && *str2 != '/') { update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p); - if (score->exten) \ - return; /* the first match is all we need */ \ + if (score->exten) { + ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten); + return; /* the first match is all we need */ + } } if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, action); - if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) + if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { + ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL"); return; /* the first match is all we need */ + } } } else if (p->x[0] == '!' && p->x[1] == 0) { /* how many chars will the . match against? */ @@ -1082,26 +1117,33 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct } if (p->exten && *str2 != '/') { update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p); - if (score->exten) \ - return; /* the first match is all we need */ \ + if (score->exten) { + ast_debug(4,"return because scoreboard has a '!' match--- %s\n", score->exten->exten); + return; /* the first match is all we need */ + } } if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) { new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid, action); - if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) + if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { + ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL"); return; /* the first match is all we need */ + } } } else if (p->x[0] == '/' && p->x[1] == 0) { /* the pattern in the tree includes the cid match! */ if (p->next_char && callerid && *callerid) { new_find_extension(callerid, score, p->next_char, length+1, spec, callerid, action); - if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) + if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { + ast_debug(4,"return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL"); return; /* the first match is all we need */ + } } } else if (index(p->x, *str)) { NEW_MATCHER_CHK_MATCH; NEW_MATCHER_RECURSE; } } + ast_debug(4,"return at end of func\n"); } /* the algorithm for forming the extension pattern tree is also a bit simple; you @@ -1117,7 +1159,8 @@ static void new_find_extension(const char *str, struct scoreboard *score, struct * * I guess forming this pattern tree would be analogous to compiling a regex. Except * that a regex only handles 1 pattern, really. This trie holds any number - * of patterns. + * of patterns. Well, really, it **could** be considered a single pattern, + * where the "|" (or) operator is allowed, I guess, in a way, sort of... */ static struct match_char *already_in_tree(struct match_char *current, char *pat)