diff --git a/lib/sh/stringlist.c b/lib/sh/stringlist.c index 6e7a7836..203aa303 100644 --- a/lib/sh/stringlist.c +++ b/lib/sh/stringlist.c @@ -47,7 +47,7 @@ strlist_create (size_t n) { ret->list = strvec_create (n+1); ret->list_size = n; - for (i = 0; i < n; i++) + for (i = 0; i <= n; i++) ret->list[i] = (char *)NULL; } else @@ -168,7 +168,7 @@ strlist_append (STRINGLIST *m1, STRINGLIST *m2) if (len2) { - m1 = strlist_resize (m1, len1 + len2 + 1); + m1 = strlist_resize (m1, len1 + len2); for (i = 0, n = len1; i < len2; i++, n++) m1->list[n] = STRDUP (m2->list[i]); m1->list[n] = (char *)NULL; diff --git a/pcomplete.c b/pcomplete.c index d7ecc16c..dbc1e78f 100644 --- a/pcomplete.c +++ b/pcomplete.c @@ -72,7 +72,7 @@ #endif #define STRDUP(x) ((x) ? savestring (x) : (char *)NULL) -typedef SHELL_VAR **SVFUNC (void); +typedef char **STRVECFUNC (const char *); extern STRING_INT_ALIST word_token_alist[]; extern char *signal_names[]; @@ -83,29 +83,29 @@ static void debug_printf (const char *, ...) __attribute__((__format__ (printf, static int it_init_joblist (ITEMLIST *, int); -static int it_init_aliases (ITEMLIST *); -static int it_init_arrayvars (ITEMLIST *); -static int it_init_bindings (ITEMLIST *); -static int it_init_builtins (ITEMLIST *); -static int it_init_disabled (ITEMLIST *); -static int it_init_enabled (ITEMLIST *); -static int it_init_exported (ITEMLIST *); -static int it_init_functions (ITEMLIST *); -static int it_init_helptopics (ITEMLIST *); -static int it_init_hostnames (ITEMLIST *); -static int it_init_jobs (ITEMLIST *); -static int it_init_running (ITEMLIST *); -static int it_init_stopped (ITEMLIST *); -static int it_init_keywords (ITEMLIST *); -static int it_init_signals (ITEMLIST *); -static int it_init_variables (ITEMLIST *); -static int it_init_setopts (ITEMLIST *); -static int it_init_shopts (ITEMLIST *); +static int it_init_aliases (ITEMLIST *, const char *); +static int it_init_arrayvars (ITEMLIST *, const char *); +static int it_init_bindings (ITEMLIST *, const char *); +static int it_init_builtins (ITEMLIST *, const char *); +static int it_init_disabled (ITEMLIST *, const char *); +static int it_init_enabled (ITEMLIST *, const char *); +static int it_init_exported (ITEMLIST *, const char *); +static int it_init_functions (ITEMLIST *, const char *); +static int it_init_helptopics (ITEMLIST *, const char *); +static int it_init_hostnames (ITEMLIST *, const char *); +static int it_init_jobs (ITEMLIST *, const char *); +static int it_init_running (ITEMLIST *, const char *); +static int it_init_stopped (ITEMLIST *, const char *); +static int it_init_keywords (ITEMLIST *, const char *); +static int it_init_signals (ITEMLIST *, const char *); +static int it_init_variables (ITEMLIST *, const char *); +static int it_init_setopts (ITEMLIST *, const char *); +static int it_init_shopts (ITEMLIST *, const char *); static int shouldexp_filterpat (char *); static char *preproc_filterpat (const char *, const char *); -static void init_itemlist_from_varlist (ITEMLIST *, SVFUNC *); +static void init_itemlist_from_strvec (ITEMLIST *, STRVECFUNC *, const char *); static STRINGLIST *gen_matches_from_itemlist (ITEMLIST *, const char *); static STRINGLIST *gen_action_completions (COMPSPEC *, const char *); @@ -211,9 +211,10 @@ set_itemlist_dirty (ITEMLIST *it) } void -initialize_itemlist (ITEMLIST *itp) +initialize_itemlist (ITEMLIST *itp, const char *hint_text) { - (*itp->list_getter) (itp); + itp->flags &= ~LIST_PREFIXFILTERED; + (*itp->list_getter) (itp, hint_text); itp->flags |= LIST_INITIALIZED; itp->flags &= ~LIST_DIRTY; } @@ -311,27 +312,13 @@ STRINGLIST * completions_to_stringlist (char **matches) { STRINGLIST *sl; - int i, n; - size_t mlen; - - mlen = (matches == 0) ? 0 : strvec_len (matches); - sl = strlist_create (mlen + 1); + sl = strlist_create (0); if (matches == 0 || matches[0] == 0) return sl; - if (matches[1] == 0) - { - sl->list[0] = STRDUP (matches[0]); - sl->list[sl->list_len = 1] = (char *)NULL; - return sl; - } - - for (i = 1, n = 0; i < mlen; i++, n++) - sl->list[n] = STRDUP (matches[i]); - sl->list_len = n; - sl->list[n] = (char *)NULL; - + sl->list = strvec_copy (matches); + sl->list_len = sl->list_size = strvec_len (matches); return sl; } @@ -339,7 +326,7 @@ completions_to_stringlist (char **matches) The caller is responsible for setting ITP->flags correctly. */ static int -it_init_aliases (ITEMLIST *itp) +it_init_aliases (ITEMLIST *itp, const char *) { #ifdef ALIAS alias_t **alias_list; @@ -355,7 +342,7 @@ it_init_aliases (ITEMLIST *itp) } for (n = 0; alias_list[n]; n++) ; - sl = strlist_create (n+1); + sl = strlist_create (n); for (i = 0; i < n; i++) sl->list[i] = STRDUP (alias_list[i]->name); sl->list[n] = (char *)NULL; @@ -369,34 +356,30 @@ it_init_aliases (ITEMLIST *itp) } static void -init_itemlist_from_varlist (ITEMLIST *itp, SVFUNC *svfunc) +init_itemlist_from_strvec (ITEMLIST *itp, STRVECFUNC *strvecfunc, const char *prefix) { - SHELL_VAR **vlist; + char **svec; STRINGLIST *sl; - int i; - size_t n; - vlist = (*svfunc) (); - if (vlist == 0) + svec = (*strvecfunc) (prefix); + if (svec == 0) { itp->slist = (STRINGLIST *)NULL; return; - } - for (n = 0; vlist[n]; n++) - ; - sl = strlist_create (n+1); - for (i = 0; i < n; i++) - sl->list[i] = savestring (vlist[i]->name); - sl->list[sl->list_len = n] = (char *)NULL; + } + + sl = strlist_create (0); + sl->list = svec; + sl->list_len = sl->list_size = strvec_len(svec); itp->slist = sl; - free (vlist); + itp->flags |= LIST_PREFIXFILTERED; } static int -it_init_arrayvars (ITEMLIST *itp) +it_init_arrayvars (ITEMLIST *itp, const char *prefix) { #if defined (ARRAY_VARS) - init_itemlist_from_varlist (itp, all_array_variables); + init_itemlist_from_strvec (itp, all_array_variables_matching_prefix, prefix); return 1; #else return 0; @@ -404,7 +387,7 @@ it_init_arrayvars (ITEMLIST *itp) } static int -it_init_bindings (ITEMLIST *itp) +it_init_bindings (ITEMLIST *itp, const char *) { char **blist; STRINGLIST *sl; @@ -422,7 +405,7 @@ it_init_bindings (ITEMLIST *itp) } static int -it_init_builtins (ITEMLIST *itp) +it_init_builtins (ITEMLIST *itp, const char *) { STRINGLIST *sl; int i; @@ -439,7 +422,7 @@ it_init_builtins (ITEMLIST *itp) } static int -it_init_enabled (ITEMLIST *itp) +it_init_enabled (ITEMLIST *itp, const char *) { STRINGLIST *sl; int i; @@ -458,7 +441,7 @@ it_init_enabled (ITEMLIST *itp) } static int -it_init_disabled (ITEMLIST *itp) +it_init_disabled (ITEMLIST *itp, const char *) { STRINGLIST *sl; int i; @@ -477,23 +460,23 @@ it_init_disabled (ITEMLIST *itp) } static int -it_init_exported (ITEMLIST *itp) +it_init_exported (ITEMLIST *itp, const char *prefix) { - init_itemlist_from_varlist (itp, all_exported_variables); + init_itemlist_from_strvec (itp, all_exported_variables_matching_prefix, prefix); return 0; } static int -it_init_functions (ITEMLIST *itp) +it_init_functions (ITEMLIST *itp, const char *prefix) { - init_itemlist_from_varlist (itp, all_visible_functions); + init_itemlist_from_strvec (itp, all_functions_matching_prefix, prefix); return 0; } /* Like it_init_builtins, but includes everything the help builtin looks at, not just builtins with an active implementing function. */ static int -it_init_helptopics (ITEMLIST *itp) +it_init_helptopics (ITEMLIST *itp, const char *) { STRINGLIST *sl; int i; @@ -509,7 +492,7 @@ it_init_helptopics (ITEMLIST *itp) } static int -it_init_hostnames (ITEMLIST *itp) +it_init_hostnames (ITEMLIST *itp, const char *) { STRINGLIST *sl; @@ -563,25 +546,25 @@ it_init_joblist (ITEMLIST *itp, int jstate) } static int -it_init_jobs (ITEMLIST *itp) +it_init_jobs (ITEMLIST *itp, const char *) { return (it_init_joblist (itp, -1)); } static int -it_init_running (ITEMLIST *itp) +it_init_running (ITEMLIST *itp, const char *) { return (it_init_joblist (itp, 0)); } static int -it_init_stopped (ITEMLIST *itp) +it_init_stopped (ITEMLIST *itp, const char *) { return (it_init_joblist (itp, 1)); } static int -it_init_keywords (ITEMLIST *itp) +it_init_keywords (ITEMLIST *itp, const char *) { STRINGLIST *sl; int i; @@ -599,7 +582,7 @@ it_init_keywords (ITEMLIST *itp) } static int -it_init_signals (ITEMLIST *itp) +it_init_signals (ITEMLIST *itp, const char *) { STRINGLIST *sl; @@ -612,14 +595,14 @@ it_init_signals (ITEMLIST *itp) } static int -it_init_variables (ITEMLIST *itp) +it_init_variables (ITEMLIST *itp, const char *prefix) { - init_itemlist_from_varlist (itp, all_visible_variables); + init_itemlist_from_strvec (itp, all_variables_matching_prefix, prefix); return 0; } static int -it_init_setopts (ITEMLIST *itp) +it_init_setopts (ITEMLIST *itp, const char *) { STRINGLIST *sl; @@ -632,7 +615,7 @@ it_init_setopts (ITEMLIST *itp) } static int -it_init_shopts (ITEMLIST *itp) +it_init_shopts (ITEMLIST *itp, const char *) { STRINGLIST *sl; @@ -656,28 +639,50 @@ gen_matches_from_itemlist (ITEMLIST *itp, const char *text) size_t tlen, i, n; char *ntxt; + ntxt = bash_dequote_text (text); + if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) || (itp->flags & LIST_INITIALIZED) == 0) { if (itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) clean_itemlist (itp); if ((itp->flags & LIST_INITIALIZED) == 0) - initialize_itemlist (itp); + initialize_itemlist (itp, ntxt); } if (itp->slist == 0) - return ((STRINGLIST *)NULL); - ret = strlist_create (itp->slist->list_len+1); - sl = itp->slist; - - ntxt = bash_dequote_text (text); - tlen = STRLEN (ntxt); + { + FREE (ntxt); + return ((STRINGLIST *)NULL); + } - for (i = n = 0; i < sl->list_len; i++) + if (itp->flags & LIST_PREFIXFILTERED) + { + /* When the items are aready filtered by itp->list_getter using the + prefix text "ntxt", flag LIST_PREFIXFILTERED is set. In this case, we + can simply pass or copy the created string list. */ + if (itp-> flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) + ret = strlist_copy (itp->slist); + else + { + ret = itp->slist; + itp->slist = (STRINGLIST *)NULL; + clean_itemlist (itp); + } + } + else { - if (tlen == 0 || STREQN (sl->list[i], ntxt, tlen)) - ret->list[n++] = STRDUP (sl->list[i]); + ret = strlist_create (itp->slist->list_len); + sl = itp->slist; + + tlen = STRLEN (ntxt); + + for (i = n = 0; i < sl->list_len; i++) + { + if (tlen == 0 || STREQN (sl->list[i], ntxt, tlen)) + ret->list[n++] = STRDUP (sl->list[i]); + } + ret->list[ret->list_len = n] = (char *)NULL; } - ret->list[ret->list_len = n] = (char *)NULL; FREE (ntxt); return ret; @@ -881,7 +886,7 @@ gen_wordlist_matches (COMPSPEC *cs, const char *text) dispose_words (l); nw = wlist_length (l2); - sl = strlist_create (nw + 1); + sl = strlist_create (nw); ntxt = bash_dequote_text (text); tlen = STRLEN (ntxt); diff --git a/pcomplete.h b/pcomplete.h index 6c0a0fbf..3c2dc0f3 100644 --- a/pcomplete.h +++ b/pcomplete.h @@ -88,7 +88,7 @@ typedef struct compspec { completions. */ typedef struct _list_of_items { int flags; - int (*list_getter) (struct _list_of_items *); /* function to call to get the list */ + int (*list_getter) (struct _list_of_items *, const char *); /* function to call to get the list */ STRINGLIST *slist; @@ -105,6 +105,7 @@ typedef struct _list_of_items { #define LIST_MUSTSORT 0x008 #define LIST_DONTFREE 0x010 #define LIST_DONTFREEMEMBERS 0x020 +#define LIST_PREFIXFILTERED 0x040 #define EMPTYCMD "_EmptycmD_" #define DEFAULTCMD "_DefaultCmD_" diff --git a/variables.c b/variables.c index eb803efc..c10e7cec 100644 --- a/variables.c +++ b/variables.c @@ -4495,32 +4495,70 @@ all_array_variables (void) } #endif /* ARRAY_VARS */ -char ** -all_variables_matching_prefix (const char *prefix) +static struct { + sh_var_map_func_t *func; + const char *prefix; + size_t plen; +} name_matching_prefix_context; + +static int +name_matching_prefix (SHELL_VAR *var) +{ + sh_var_map_func_t *func = name_matching_prefix_context.func; + const char *prefix = name_matching_prefix_context.prefix; + size_t plen = name_matching_prefix_context.plen; + return func(var) && (plen == 0 || STREQN (prefix, var->name, plen)); +} + +static char ** +all_names_matching_prefix (SHELL_VAR ** (*apply)(sh_var_map_func_t *), sh_var_map_func_t *func, const char *prefix) { SHELL_VAR **varlist; char **rlist; int rind; - size_t plen, vind; + size_t vind; - plen = STRLEN (prefix); - varlist = all_visible_variables (); + name_matching_prefix_context.func = func; + name_matching_prefix_context.prefix = prefix; + name_matching_prefix_context.plen = STRLEN (prefix); + varlist = apply (name_matching_prefix); for (vind = 0; varlist && varlist[vind]; vind++) ; if (varlist == 0 || vind == 0) return ((char **)NULL); rlist = strvec_create (vind + 1); for (vind = rind = 0; varlist[vind]; vind++) - { - if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen)) - rlist[rind++] = savestring (varlist[vind]->name); - } + rlist[rind++] = savestring (varlist[vind]->name); rlist[rind] = (char *)0; free (varlist); return rlist; } +char ** +all_variables_matching_prefix (const char *prefix) +{ + return all_names_matching_prefix (vapply, visible_var, prefix); +} + +char ** +all_exported_variables_matching_prefix (const char *prefix) +{ + return all_names_matching_prefix (vapply, visible_and_exported, prefix); +} + +char ** +all_array_variables_matching_prefix (const char *prefix) +{ + return all_names_matching_prefix (vapply, visible_array_vars, prefix); +} + +char ** +all_functions_matching_prefix (const char *prefix) +{ + return all_names_matching_prefix (fapply, visible_var, prefix); +} + /* **************************************************************** */ /* */ /* Managing temporary variable scopes */ diff --git a/variables.h b/variables.h index a8a0214f..3bbea5d3 100644 --- a/variables.h +++ b/variables.h @@ -329,6 +329,9 @@ extern SHELL_VAR **all_local_variables (int); extern SHELL_VAR **all_array_variables (void); #endif extern char **all_variables_matching_prefix (const char *); +extern char **all_exported_variables_matching_prefix (const char *); +extern char **all_array_variables_matching_prefix (const char *); +extern char **all_functions_matching_prefix (const char *); extern char **make_var_array (HASH_TABLE *); extern char **add_or_supercede_exported_var (char *, int);