Index: include/asterisk.h =================================================================== --- include/asterisk.h (revision 161213) +++ include/asterisk.h (working copy) @@ -89,6 +89,7 @@ */ const char *ast_file_version_find(const char *file); +char *ast_complete_source_filename(const char *partial, int n); /*! * \brief Register/unregister a source code file with the core. Index: main/asterisk.c =================================================================== --- main/asterisk.c (revision 161213) +++ main/asterisk.c (working copy) @@ -313,6 +313,24 @@ ast_free(find); } +char *ast_complete_source_filename(const char *partial, int n) +{ + struct file_version *find; + size_t len = strlen(partial); + int count = 0; + char *res = NULL; + + AST_RWLIST_RDLOCK(&file_versions); + AST_RWLIST_TRAVERSE(&file_versions, find, list) { + if (!strncasecmp(find->file, partial, len) && ++count > n) { + res = ast_strdup(find->file); + break; + } + } + AST_RWLIST_UNLOCK(&file_versions); + return res; +} + /*! \brief Find version for given module name */ const char *ast_file_version_find(const char *file) { Index: main/cli.c =================================================================== --- main/cli.c (revision 161213) +++ main/cli.c (working copy) @@ -317,6 +317,47 @@ return df; } +static char *complete_number(const char *partial, unsigned int min, unsigned int max, int n) +{ + int i, count = 0; + unsigned int prospective[2]; + unsigned int part = strtoul(partial, NULL, 10); + char next[12]; + + if (part < min || part > max) { + return NULL; + } + + for (i = 0; i < 21; i++) { + if (i == 0) { + prospective[0] = prospective[1] = part; + } else if (i < 11) { + prospective[0] = prospective[1] = part * 10 + (i - 1); + } else { + prospective[0] = (part * 10 + (i - 11)) * 10; + prospective[1] = prospective[0] + 9; + } + if (i < 11 && (prospective[0] < min || prospective[0] > max)) { + continue; + } else if (prospective[1] < min || prospective[0] > max) { + continue; + } + + if (++count > n) { + if (i < 11) { + snprintf(next, sizeof(next), "%u", prospective[0]); + } else { + if (prospective[0] == 0) { + continue; + } + snprintf(next, sizeof(next), "%u...", prospective[0] / 10); + } + return ast_strdup(next); + } + } + return NULL; +} + static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int oldval; @@ -325,6 +366,7 @@ int fd = a->fd; int argc = a->argc; char **argv = a->argv; + char *argv3 = a->argv ? S_OR(a->argv[3], "") : ""; int *dst; char *what; struct debug_file_list *dfl; @@ -333,7 +375,7 @@ switch (cmd) { case CLI_INIT: - e->command = "core set {debug|verbose} [off|atleast]"; + e->command = "core set {debug|verbose}"; e->usage = "Usage: core set {debug|verbose} [atleast] [filename]\n" " core set {debug|verbose} off\n" @@ -344,6 +386,21 @@ return NULL; case CLI_GENERATE: + if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) { + if (a->n < 21) { + return complete_number(a->pos == 3 ? argv3 : S_OR(a->argv[4], ""), 0, 0x7fffffff, a->n); + } else if (a->n == 21) { + if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) { + return ast_strdup("off"); + } else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) { + return ast_strdup("atleast"); + } + } else if (a->n == 22 && a->pos == 3 && ast_strlen_zero(argv3)) { + return ast_strdup("atleast"); + } + } else if (a->pos == 4 || (a->pos == 5 && !strcasecmp(argv3, "atleast"))) { + return ast_complete_source_filename(a->pos == 4 ? S_OR(a->argv[4], "") : S_OR(a->argv[5], ""), a->n); + } return NULL; } /* all the above return, so we proceed with the handler. @@ -352,7 +409,7 @@ if (argc < e->args) return CLI_SHOWUSAGE; - if (!strcasecmp(argv[e->args - 2], "debug")) { + if (!strcasecmp(argv[e->args - 1], "debug")) { dst = &option_debug; oldval = option_debug; what = "Core debug"; @@ -361,7 +418,7 @@ oldval = option_verbose; what = "Verbosity"; } - if (argc == e->args && !strcasecmp(argv[e->args - 1], "off")) { + if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) { unsigned int debug = (*what == 'C'); newlevel = 0; @@ -375,17 +432,17 @@ goto done; } - if (!strcasecmp(argv[e->args-1], "atleast")) + if (!strcasecmp(argv[e->args], "atleast")) atleast = 1; - if (argc != e->args + atleast && argc != e->args + atleast + 1) + if (argc != e->args + atleast + 1 && argc != e->args + atleast + 2) return CLI_SHOWUSAGE; - if (sscanf(argv[e->args + atleast - 1], "%d", &newlevel) != 1) + if (sscanf(argv[e->args + atleast], "%d", &newlevel) != 1) return CLI_SHOWUSAGE; - if (argc == e->args + atleast + 1) { + if (argc == e->args + atleast + 2) { unsigned int debug = (*what == 'C'); dfl = debug ? &debug_files : &verbose_files; - fn = argv[e->args + atleast]; + fn = argv[e->args + atleast + 1]; AST_RWLIST_WRLOCK(dfl);