diff options
author | Jari Aalto <jari.aalto@cante.net> | 1996-12-23 17:02:34 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:46:49 +0000 |
commit | ccc6cda312fea9f0468ee65b8f368e9653e1380b (patch) | |
tree | b059878adcfd876c4acb8030deda1eeb918c7e75 /builtins/hash.def | |
parent | 726f63884db0132f01745f1fb4465e6621088ccf (diff) | |
download | android_external_bash-ccc6cda312fea9f0468ee65b8f368e9653e1380b.tar.gz android_external_bash-ccc6cda312fea9f0468ee65b8f368e9653e1380b.tar.bz2 android_external_bash-ccc6cda312fea9f0468ee65b8f368e9653e1380b.zip |
Imported from ../bash-2.0.tar.gz.
Diffstat (limited to 'builtins/hash.def')
-rw-r--r-- | builtins/hash.def | 270 |
1 files changed, 156 insertions, 114 deletions
diff --git a/builtins/hash.def b/builtins/hash.def index f4d319b..2f69f65 100644 --- a/builtins/hash.def +++ b/builtins/hash.def @@ -23,182 +23,167 @@ $PRODUCES hash.c $BUILTIN hash $FUNCTION hash_builtin -$SHORT_DOC hash [-r] [name ...] +$SHORT_DOC hash [-r] [-p pathname] [name ...] For each NAME, the full pathname of the command is determined and -remembered. The -r option causes the shell to forget all remembered -locations. If no arguments are given, information about remembered -commands is presented. +remembered. If the -p option is supplied, PATHNAME is used as the +full pathname of NAME, and no path search is performed. The -r +option causes the shell to forget all remembered locations. If no +arguments are given, information about remembered commands is displayed. $END +#include <config.h> + #include <sys/types.h> #include "../posixstat.h" #include <stdio.h> -#if defined (HAVE_STRING_H) -# include <string.h> -#else /* !HAVE_STRING_H */ -# include <strings.h> -#endif /* !HAVE_STRING_H */ +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "../bashansi.h" #include "../shell.h" #include "../builtins.h" #include "../flags.h" +#include "../execute_cmd.h" #include "hashcom.h" #include "common.h" -#include "../execute_cmd.h" +#include "bashgetopt.h" extern int dot_found_in_search; +extern char *this_command_name; + +static int add_hashed_command (); +static int print_hashed_commands (); + +static int hashing_initialized = 0; + +HASH_TABLE *hashed_filenames; void initialize_filename_hashing () { - hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS); + if (hashing_initialized == 0) + { + hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS); + hashing_initialized = 1; + } +} + +static void +free_filename_data (data) + char *data; +{ + free (((PATH_DATA *)data)->path); + free (data); +} + +void +flush_hashed_filenames () +{ + flush_hash_table (hashed_filenames, free_filename_data); +} + +/* Remove FILENAME from the table of hashed commands. */ +void +remove_hashed_filename (filename) + char *filename; +{ + register BUCKET_CONTENTS *item; + + if (hashing_enabled == 0) + return; + + item = remove_hash_item (filename, hashed_filenames); + if (item) + { + if (item->data) + free_filename_data (item->data); + free (item->key); + free (item); + } } /* Print statistics on the current state of hashed commands. If LIST is not empty, then rehash (or hash in the first place) the specified commands. */ +int hash_builtin (list) WORD_LIST *list; { - int expunge_hash_table = 0; - int any_failed = 0; + int expunge_hash_table, opt; + char *word, *pathname; - if (hashing_disabled) + if (hashing_enabled == 0) { builtin_error ("hashing disabled"); return (EXECUTION_FAILURE); } - while (list) + expunge_hash_table = 0; + pathname = (char *)NULL; + reset_internal_getopt (); + while ((opt = internal_getopt (list, "rp:")) != -1) { - char *arg = list->word->word; - - if (ISOPTION (arg, 'r')) + switch (opt) { + case 'r': expunge_hash_table = 1; - list = list->next; - } - else if (ISOPTION (arg, '-')) - { - list = list->next; break; - } - else if (*arg == '-') - { - bad_option (list->word->word); - builtin_error ("usage: hash [-r] [command ...]"); + case 'p': + pathname = list_optarg; + break; + default: + builtin_usage (); return (EX_USAGE); } - else - break; } + list = loptend; /* We want hash -r to be silent, but hash -- to print hashing info. That - is the reason for the !expunge_hash_table. */ - if (!list && !expunge_hash_table) + is the reason for the test of expunge_hash_table. */ + if (list == 0 && expunge_hash_table == 0) { - /* Print information about current hashed info. */ - int any_printed = 0; - int bucket = 0; - register BUCKET_CONTENTS *item_list; - - while (bucket < hashed_filenames->nbuckets) - { - item_list = get_hash_bucket (bucket, hashed_filenames); - if (item_list) - { - if (!any_printed) - { - printf ("hits\tcommand\n"); - any_printed++; - } - while (item_list) - { - printf ("%4d\t%s\n", - item_list->times_found, pathdata(item_list)->path); - item_list = item_list->next; - } - } - bucket++; - } - - if (!any_printed) - printf ("No commands in hash table.\n"); + if (print_hashed_commands () == 0) + printf ("%s: hash table empty\n", this_command_name); return (EXECUTION_SUCCESS); } if (expunge_hash_table) - { - int bucket = 0; - register BUCKET_CONTENTS *item_list, *prev; + flush_hashed_filenames (); - while (bucket < hashed_filenames->nbuckets) - { - item_list = get_hash_bucket (bucket, hashed_filenames); - if (item_list) - { - while (item_list) - { - prev = item_list; - free (item_list->key); - free (pathdata(item_list)->path); - free (item_list->data); - item_list = item_list->next; - free (prev); - } - hashed_filenames->bucket_array[bucket] = (BUCKET_CONTENTS *)NULL; - } - bucket++; - } - } - - while (list) + for (opt = EXECUTION_SUCCESS; list; list = list->next) { /* Add or rehash the specified commands. */ - char *word; - char *full_path; - SHELL_VAR *var; - word = list->word->word; - if (absolute_program (word)) - { - list = list->next; - continue; - } - full_path = find_user_command (word); - var = find_function (word); - - if (!find_shell_builtin (word) && (!var)) + if (pathname) + remember_filename (word, pathname, 0, 0); + else { - if (full_path && executable_file (full_path)) - remember_filename (word, full_path, dot_found_in_search, 0); - else + if (absolute_program (word)) { - builtin_error ("%s: not found", word); - any_failed++; + list = list->next; + continue; } - } - if (full_path) - free (full_path); - list = list->next; + if (add_hashed_command (word)) + opt = EXECUTION_FAILURE; + } } fflush (stdout); - if (any_failed) - return (EXECUTION_FAILURE); - else - return (EXECUTION_SUCCESS); + return (opt); } /* Place FILENAME (key) and FULL_PATHNAME (data->path) into the hash table. CHECK_DOT if non-null is for future calls to - find_hashed_filename (). FOUND is the initial value for - times_found. */ + find_hashed_filename (); it means that this file was found + in a directory in $PATH that is not an absolute pathname. + FOUND is the initial value for times_found. */ void remember_filename (filename, full_pathname, check_dot, found) char *filename, *full_pathname; @@ -206,17 +191,74 @@ remember_filename (filename, full_pathname, check_dot, found) { register BUCKET_CONTENTS *item; - if (hashing_disabled) + if (hashing_enabled == 0) return; + item = add_hash_item (filename, hashed_filenames); if (item->data) free (pathdata(item)->path); else { item->key = savestring (filename); - item->data = (char *)xmalloc (sizeof (PATH_DATA)); + item->data = xmalloc (sizeof (PATH_DATA)); } pathdata(item)->path = savestring (full_pathname); - pathdata(item)->check_dot = check_dot; + pathdata(item)->flags = 0; + if (check_dot) + pathdata(item)->flags |= HASH_CHKDOT; + if (*full_pathname != '/') + pathdata(item)->flags |= HASH_RELPATH; item->times_found = found; } + +static int +add_hashed_command (word, quiet) + char *word; + int quiet; +{ + int rv; + char *full_path; + + rv = 0; + if (find_function (word) == 0 && find_shell_builtin (word) == 0) + { + full_path = find_user_command (word); + if (full_path && executable_file (full_path)) + remember_filename (word, full_path, dot_found_in_search, 0); + else + { + if (quiet == 0) + builtin_error ("%s: not found", word); + rv++; + } + if (full_path) + free (full_path); + } + return (rv); +} + +/* Print information about current hashed info. */ +static int +print_hashed_commands () +{ + BUCKET_CONTENTS *item_list; + int bucket, any_printed; + + for (bucket = any_printed = 0; bucket < hashed_filenames->nbuckets; bucket++) + { + item_list = get_hash_bucket (bucket, hashed_filenames); + if (item_list == 0) + continue; + + if (any_printed == 0) + { + printf ("hits\tcommand\n"); + any_printed++; + } + + for ( ; item_list; item_list = item_list->next) + printf ("%4d\t%s\n", item_list->times_found, pathdata(item_list)->path); + + } + return (any_printed); +} |