aboutsummaryrefslogtreecommitdiffstats
path: root/builtins/hash.def
diff options
context:
space:
mode:
authorJari Aalto <jari.aalto@cante.net>1996-12-23 17:02:34 +0000
committerJari Aalto <jari.aalto@cante.net>2009-09-12 16:46:49 +0000
commitccc6cda312fea9f0468ee65b8f368e9653e1380b (patch)
treeb059878adcfd876c4acb8030deda1eeb918c7e75 /builtins/hash.def
parent726f63884db0132f01745f1fb4465e6621088ccf (diff)
downloadandroid_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.def270
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);
+}