more list macro conversion (issue #6361, plus documentation for new macro)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@10067 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kevin P. Fleming
2006-02-14 22:44:20 +00:00
parent 1c7126664d
commit ff7a90829d
3 changed files with 55 additions and 60 deletions

81
cli.c
View File

@@ -1,7 +1,7 @@
/* /*
* Asterisk -- An open source telephony toolkit. * Asterisk -- An open source telephony toolkit.
* *
* Copyright (C) 1999 - 2005, Digium, Inc. * Copyright (C) 1999 - 2006, Digium, Inc.
* *
* Mark Spencer <markster@digium.com> * Mark Spencer <markster@digium.com>
* *
@@ -77,9 +77,7 @@ void ast_cli(int fd, char *fmt, ...)
} }
} }
AST_MUTEX_DEFINE_STATIC(clilock); static AST_LIST_HEAD_STATIC(helpers, ast_cli_entry);
struct ast_cli_entry *helpers = NULL;
static char load_help[] = static char load_help[] =
"Usage: load <module name>\n" "Usage: load <module name>\n"
@@ -946,7 +944,7 @@ static struct ast_cli_entry *find_cli(char *const cmds[], int exact)
int match; int match;
struct ast_cli_entry *e=NULL; struct ast_cli_entry *e=NULL;
for (e=helpers;e;e=e->next) { AST_LIST_TRAVERSE(&helpers, e, list) {
match = 1; match = 1;
for (y=0;match && cmds[y]; y++) { for (y=0;match && cmds[y]; y++) {
if (!e->cmda[y] && !exact) if (!e->cmda[y] && !exact)
@@ -1025,72 +1023,47 @@ static char *find_best(char *argv[])
int ast_cli_unregister(struct ast_cli_entry *e) int ast_cli_unregister(struct ast_cli_entry *e)
{ {
struct ast_cli_entry *cur, *l=NULL;
ast_mutex_lock(&clilock);
cur = helpers;
while(cur) {
if (e == cur) {
if (e->inuse) { if (e->inuse) {
ast_log(LOG_WARNING, "Can't remove command that is in use\n"); ast_log(LOG_WARNING, "Can't remove command that is in use\n");
} else { } else {
/* Rewrite */ AST_LIST_LOCK(&helpers);
if (l) AST_LIST_REMOVE(&helpers, e, list);
l->next = e->next; AST_LIST_UNLOCK(&helpers);
else
helpers = e->next;
e->next = NULL;
break;
} }
}
l = cur;
cur = cur->next;
}
ast_mutex_unlock(&clilock);
return 0; return 0;
} }
int ast_cli_register(struct ast_cli_entry *e) int ast_cli_register(struct ast_cli_entry *e)
{ {
struct ast_cli_entry *cur, *l=NULL; struct ast_cli_entry *cur;
char fulle[80] ="", fulltst[80] =""; char fulle[80] ="", fulltst[80] ="";
static int len; static int len;
ast_mutex_lock(&clilock); AST_LIST_LOCK(&helpers);
join2(fulle, sizeof(fulle), e->cmda); join2(fulle, sizeof(fulle), e->cmda);
if (find_cli(e->cmda, -1)) { if (find_cli(e->cmda, -1)) {
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle); ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
return -1; return -1;
} }
for (cur = helpers; cur; cur = cur->next) { AST_LIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
join2(fulltst, sizeof(fulltst), cur->cmda); join2(fulltst, sizeof(fulltst), cur->cmda);
len = strlen(fulltst); len = strlen(fulltst);
if (strlen(fulle) < len) if (strlen(fulle) < len)
len = strlen(fulle); len = strlen(fulle);
if (strncasecmp(fulle, fulltst, len) < 0) { if (strncasecmp(fulle, fulltst, len) < 0) {
if (l) { AST_LIST_INSERT_BEFORE_CURRENT(&helpers, e, list);
e->next = l->next;
l->next = e;
} else {
e->next = helpers;
helpers = e;
}
break; break;
} }
l = cur;
} }
AST_LIST_TRAVERSE_SAFE_END;
if (!cur) { if (!cur)
if (l) AST_LIST_INSERT_TAIL(&helpers, e, list);
l->next = e;
else
helpers = e;
e->next = NULL;
}
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
return 0; return 0;
} }
@@ -1122,7 +1095,7 @@ static int help_workhorse(int fd, char *match[])
char *fullcmd = NULL; char *fullcmd = NULL;
struct ast_cli_entry *e, *e1, *e2; struct ast_cli_entry *e, *e1, *e2;
e1 = builtins; e1 = builtins;
e2 = helpers; e2 = AST_LIST_FIRST(&helpers);
if (match) if (match)
join(matchstr, sizeof(matchstr), match, 0); join(matchstr, sizeof(matchstr), match, 0);
while(e1->cmda[0] || e2) { while(e1->cmda[0] || e2) {
@@ -1136,7 +1109,7 @@ static int help_workhorse(int fd, char *match[])
e = e2; e = e2;
fullcmd = fullcmd2; fullcmd = fullcmd2;
/* Increment by going to next */ /* Increment by going to next */
e2 = e2->next; e2 = AST_LIST_NEXT(e2, list);
} else { } else {
/* Use e1 */ /* Use e1 */
e = e1; e = e1;
@@ -1322,9 +1295,9 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
if ((dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws))) { if ((dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws))) {
join(matchstr, sizeof(matchstr), argv, tws); join(matchstr, sizeof(matchstr), argv, tws);
if (lock) if (lock)
ast_mutex_lock(&clilock); AST_LIST_LOCK(&helpers);
e1 = builtins; e1 = builtins;
e2 = helpers; e2 = AST_LIST_FIRST(&helpers);
while(e1->cmda[0] || e2) { while(e1->cmda[0] || e2) {
if (e2) if (e2)
join(fullcmd2, sizeof(fullcmd2), e2->cmda, tws); join(fullcmd2, sizeof(fullcmd2), e2->cmda, tws);
@@ -1336,7 +1309,7 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
e = e2; e = e2;
fullcmd = fullcmd2; fullcmd = fullcmd2;
/* Increment by going to next */ /* Increment by going to next */
e2 = e2->next; e2 = AST_LIST_NEXT(e2, list);
} else { } else {
/* Use e1 */ /* Use e1 */
e = e1; e = e1;
@@ -1355,7 +1328,7 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
matchnum++; matchnum++;
if (matchnum > state) { if (matchnum > state) {
if (lock) if (lock)
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
free(dup); free(dup);
return strdup(res); return strdup(res);
} }
@@ -1368,7 +1341,7 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
fullcmd = e->generator(matchstr, word, (!ast_strlen_zero(word) ? (x - 1) : (x)), state); fullcmd = e->generator(matchstr, word, (!ast_strlen_zero(word) ? (x - 1) : (x)), state);
if (fullcmd) { if (fullcmd) {
if (lock) if (lock)
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
free(dup); free(dup);
return fullcmd; return fullcmd;
} }
@@ -1376,7 +1349,7 @@ static char *__ast_cli_generator(const char *text, const char *word, int state,
} }
if (lock) if (lock)
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
free(dup); free(dup);
} }
return NULL; return NULL;
@@ -1402,11 +1375,11 @@ int ast_cli_command(int fd, const char *s)
/* We need at least one entry, or ignore */ /* We need at least one entry, or ignore */
if (x > 0) { if (x > 0) {
ast_mutex_lock(&clilock); AST_LIST_LOCK(&helpers);
e = find_cli(argv, 0); e = find_cli(argv, 0);
if (e) if (e)
e->inuse++; e->inuse++;
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
if (e) { if (e) {
switch(e->handler(fd, x, argv)) { switch(e->handler(fd, x, argv)) {
case RESULT_SHOWUSAGE: case RESULT_SHOWUSAGE:
@@ -1416,9 +1389,9 @@ int ast_cli_command(int fd, const char *s)
} else } else
ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv)); ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv));
if (e) { if (e) {
ast_mutex_lock(&clilock); AST_LIST_LOCK(&helpers);
e->inuse--; e->inuse--;
ast_mutex_unlock(&clilock); AST_LIST_UNLOCK(&helpers);
} }
} }
free(dup); free(dup);

View File

@@ -29,6 +29,8 @@ extern "C" {
#include <stdarg.h> #include <stdarg.h>
#include "asterisk/linkedlists.h"
void ast_cli(int fd, char *fmt, ...) void ast_cli(int fd, char *fmt, ...)
__attribute__ ((format (printf, 2, 3))); __attribute__ ((format (printf, 2, 3)));
@@ -67,10 +69,10 @@ struct ast_cli_entry {
until a NULL is returned. until a NULL is returned.
*/ */
char *(*generator)(const char *line, const char *word, int pos, int n); char *(*generator)(const char *line, const char *word, int pos, int n);
/*! For linking */
struct ast_cli_entry *next;
/*! For keeping track of usage */ /*! For keeping track of usage */
int inuse; int inuse;
/*! For linking */
AST_LIST_ENTRY(ast_cli_entry) list;
}; };

View File

@@ -1,7 +1,7 @@
/* /*
* Asterisk -- An open source telephony toolkit. * Asterisk -- An open source telephony toolkit.
* *
* Copyright (C) 1999 - 2005, Digium, Inc. * Copyright (C) 1999 - 2006, Digium, Inc.
* *
* Mark Spencer <markster@digium.com> * Mark Spencer <markster@digium.com>
* Kevin P. Fleming <kpfleming@digium.com> * Kevin P. Fleming <kpfleming@digium.com>
@@ -313,6 +313,26 @@ struct { \
if (!__list_next) \ if (!__list_next) \
(head)->last = __list_prev; (head)->last = __list_prev;
/*!
\brief Inserts a list entry before the current entry during a traversal.
\param head This is a pointer to the list head structure
\param elm This is a pointer to the entry to be inserted.
\param field This is the name of the field (declared using AST_LIST_ENTRY())
used to link entries of this list together.
\note This macro can \b only be used inside an AST_LIST_TRAVERSE_SAFE_BEGIN()
block.
*/
#define AST_LIST_INSERT_BEFORE_CURRENT(head, elm, field) do { \
if (__list_prev) { \
(elm)->field.next = __list_prev->field.next; \
__list_prev->field.next = elm; \
} else { \
(elm)->field.next = (head)->first; \
(head)->first = (elm); \
} \
} while (0)
/*! /*!
\brief Closes a safe loop traversal block. \brief Closes a safe loop traversal block.
*/ */