[ dejagnu/ChangeLog ]
[deliverable/binutils-gdb.git] / readline / tilde.c
index 22890f4e6f308209f77638ca988ad4551bdccbf1..777b6559223798df6b1c1a5073d5f5f495614afa 100644 (file)
@@ -7,7 +7,7 @@
 
    Readline is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 1, or (at your option) any
+   Free Software Foundation; either version 2, or (at your option) any
    later version.
 
    Readline is distributed in the hope that it will be useful, but
 
    You should have received a copy of the GNU General Public License
    along with Readline; see the file COPYING.  If not, write to the Free
-   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if defined (__GNUC__)
-#  undef alloca
-#  define alloca __builtin_alloca
-#else /* !__GNUC__ */
-#  if defined (_AIX)
-     #pragma alloca
-#  else /* !_AIX */
-#    if defined (HAVE_ALLOCA_H)
-#      include <alloca.h>
-#    endif /* HAVE_ALLOCA_H */
-#  endif /* !AIX */
-#endif /* !__GNUC__ */
+   Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
 
 #if defined (HAVE_STRING_H)
 #  include <string.h>
 #  include "ansi_stdlib.h"
 #endif /* HAVE_STDLIB_H */
 
-#include <tilde/tilde.h>
+#include <sys/types.h>
 #include <pwd.h>
 
-#if !defined (sgi) && !defined (isc386)
-extern struct passwd *getpwnam (), *getpwuid ();
-#endif /* !sgi */
+#include "tilde.h"
+
+#if defined (TEST) || defined (STATIC_MALLOC)
+static char *xmalloc (), *xrealloc ();
+#else
+#  if defined __STDC__
+extern char *xmalloc (int);
+extern char *xrealloc (void *, int);
+#  else
+extern char *xmalloc (), *xrealloc ();
+#  endif /* !__STDC__ */
+#endif /* TEST || STATIC_MALLOC */
+
+#if !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid (), *getpwnam ();
+#endif /* !HAVE_GETPW_DECLS */
 
 #if !defined (savestring)
-extern char *xmalloc ();
 #  ifndef strcpy
 extern char *strcpy ();
 #  endif
@@ -67,11 +77,11 @@ extern char *strcpy ();
 #  endif /* !__STDC__ */
 #endif /* !NULL */
 
-#if defined (TEST) || defined (STATIC_MALLOC)
-static char *xmalloc (), *xrealloc ();
-#else
-extern char *xmalloc (), *xrealloc ();
-#endif /* TEST || STATIC_MALLOC */
+/* If being compiled as part of bash, these will be satisfied from
+   variables.o.  If being compiled as part of readline, they will
+   be satisfied from shell.o. */
+extern char *get_home_dir __P((void));
+extern char *get_env_value __P((char *));
 
 /* The default value of tilde_additional_prefixes.  This is set to
    whitespace preceding a tilde so that simple programs which do not
@@ -85,11 +95,17 @@ static char *default_prefixes[] =
 static char *default_suffixes[] =
   { " ", "\n", (char *)NULL };
 
+/* If non-null, this contains the address of a function that the application
+   wants called before trying the standard tilde expansions.  The function
+   is called with the text sans tilde, and returns a malloc()'ed string
+   which is the expansion, or a NULL pointer if the expansion fails. */
+CPFunction *tilde_expansion_preexpansion_hook = (CPFunction *)NULL;
+
 /* If non-null, this contains the address of a function to call if the
    standard meaning for expanding a tilde fails.  The function is called
    with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
    which is the expansion, or a NULL pointer if there is no expansion. */
-Function *tilde_expansion_failure_hook = (Function *)NULL;
+CPFunction *tilde_expansion_failure_hook = (CPFunction *)NULL;
 
 /* When non-null, this is a NULL terminated array of strings which
    are duplicates for a tilde prefix.  Bash uses this to expand
@@ -110,12 +126,14 @@ tilde_find_prefix (string, len)
      int *len;
 {
   register int i, j, string_len;
-  register char **prefixes = tilde_additional_prefixes;
+  register char **prefixes;
+
+  prefixes = tilde_additional_prefixes;
 
   string_len = strlen (string);
   *len = 0;
 
-  if (!*string || *string == '~')
+  if (*string == '\0' || *string == '~')
     return (0);
 
   if (prefixes)
@@ -142,13 +160,18 @@ tilde_find_suffix (string)
      char *string;
 {
   register int i, j, string_len;
-  register char **suffixes = tilde_additional_suffixes;
+  register char **suffixes;
 
+  suffixes = tilde_additional_suffixes;
   string_len = strlen (string);
 
   for (i = 0; i < string_len; i++)
     {
-      if (string[i] == '/' || !string[i])
+#if defined (__MSDOS__)
+      if (string[i] == '/' || string[i] == '\\' /* || !string[i] */)
+#else
+      if (string[i] == '/' /* || !string[i] */)
+#endif
        break;
 
       for (j = 0; suffixes && suffixes[j]; j++)
@@ -165,11 +188,14 @@ char *
 tilde_expand (string)
      char *string;
 {
-  char *result, *tilde_expand_word ();
+  char *result;
   int result_size, result_index;
 
-  result_size = result_index = 0;
-  result = (char *)NULL;
+  result_index = result_size = 0;
+  if (result = strchr (string, '~'))
+    result = xmalloc (result_size = (strlen (string) + 16));
+  else
+    result = xmalloc (result_size = (strlen (string) + 1));
 
   /* Scan through STRING expanding tildes as we come to them. */
   while (1)
@@ -183,7 +209,7 @@ tilde_expand (string)
 
       /* Copy the skipped text into the result. */
       if ((result_index + start + 1) > result_size)
-       result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
+       result = xrealloc (result, 1 + (result_size += (start + 20)));
 
       strncpy (result + result_index, string, start);
       result_index += start;
@@ -200,7 +226,7 @@ tilde_expand (string)
        break;
 
       /* Expand the entire tilde word, and copy it into RESULT. */
-      tilde_word = (char *)xmalloc (1 + end);
+      tilde_word = xmalloc (1 + end);
       strncpy (tilde_word, string, end);
       tilde_word[end] = '\0';
       string += end;
@@ -209,11 +235,18 @@ tilde_expand (string)
       free (tilde_word);
 
       len = strlen (expansion);
-      if ((result_index + len + 1) > result_size)
-       result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
+#ifdef __CYGWIN32__
+      /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
+         $HOME for `user' is /.  On cygwin, // denotes a network drive. */
+      if (len > 1 || *expansion != '/' || *string != '/')
+#endif
+       {
+         if ((result_index + len + 1) > result_size)
+           result = xrealloc (result, 1 + (result_size += (len + 20)));
 
-      strcpy (result + result_index, expansion);
-      result_index += len;
+         strcpy (result + result_index, expansion);
+         result_index += len;
+       }
       free (expansion);
     }
 
@@ -222,96 +255,126 @@ tilde_expand (string)
   return (result);
 }
 
+/* Take FNAME and return the tilde prefix we want expanded.  If LENP is
+   non-null, the index of the end of the prefix into FNAME is returned in
+   the location it points to. */
+static char *
+isolate_tilde_prefix (fname, lenp)
+     char *fname;
+     int *lenp;
+{
+  char *ret;
+  int i;
+
+  ret = xmalloc (strlen (fname));
+#if defined (__MSDOS__)
+  for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
+#else
+  for (i = 1; fname[i] && fname[i] != '/'; i++)
+#endif
+    ret[i - 1] = fname[i];
+  ret[i - 1] = '\0';
+  if (lenp)
+    *lenp = i;
+  return ret;
+}
+
+/* Return a string that is PREFIX concatenated with SUFFIX starting at
+   SUFFIND. */
+static char *
+glue_prefix_and_suffix (prefix, suffix, suffind)
+     char *prefix, *suffix;
+     int suffind;
+{
+  char *ret;
+  int plen, slen;
+
+  plen = (prefix && *prefix) ? strlen (prefix) : 0;
+  slen = strlen (suffix + suffind);
+  ret = xmalloc (plen + slen + 1);
+  if (plen)
+    strcpy (ret, prefix);
+  strcpy (ret + plen, suffix + suffind);
+  return ret;
+}
+
 /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
-   tilde.  If there is no expansion, call tilde_expansion_failure_hook. */
+   tilde.  If there is no expansion, call tilde_expansion_failure_hook.
+   This always returns a newly-allocated string, never static storage. */
 char *
 tilde_expand_word (filename)
      char *filename;
 {
-  char *dirname;
+  char *dirname, *expansion, *username;
+  int user_len;
+  struct passwd *user_entry;
+
+  if (filename == 0)
+    return ((char *)NULL);
 
-  dirname = filename ? savestring (filename) : (char *)NULL;
+  if (*filename != '~')
+    return (savestring (filename));
 
-  if (dirname && *dirname == '~')
+  /* A leading `~/' or a bare `~' is *always* translated to the value of
+     $HOME or the home directory of the current user, regardless of any
+     preexpansion hook. */
+  if (filename[1] == '\0' || filename[1] == '/')
     {
-      char *temp_name;
-      if (!dirname[1] || dirname[1] == '/')
-       {
-         /* Prepend $HOME to the rest of the string. */
-         char *temp_home = (char *)getenv ("HOME");
+      /* Prefix $HOME to the rest of the string. */
+      expansion = get_env_value ("HOME");
 
-         /* If there is no HOME variable, look up the directory in
-            the password database. */
-         if (!temp_home)
-           {
-             struct passwd *entry;
+      /* If there is no HOME variable, look up the directory in
+        the password database. */
+      if (expansion == 0)
+       expansion = get_home_dir ();
 
-             entry = getpwuid (getuid ());
-             if (entry)
-               temp_home = entry->pw_dir;
-           }
+      return (glue_prefix_and_suffix (expansion, filename, 1));
+    }
 
-         temp_name = (char *)alloca (1 + strlen (&dirname[1])
-                                     + (temp_home ? strlen (temp_home) : 0));
-         temp_name[0] = '\0';
-         if (temp_home)
-           strcpy (temp_name, temp_home);
-         strcat (temp_name, &dirname[1]);
-         free (dirname);
-         dirname = savestring (temp_name);
-       }
-      else
-       {
-         struct passwd *user_entry;
-         char *username = (char *)alloca (257);
-         int i, c;
+  username = isolate_tilde_prefix (filename, &user_len);
 
-         for (i = 1; c = dirname[i]; i++)
-           {
-             if (c == '/')
-               break;
-             else
-               username[i - 1] = c;
-           }
-         username[i - 1] = '\0';
+  if (tilde_expansion_preexpansion_hook)
+    {
+      expansion = (*tilde_expansion_preexpansion_hook) (username);
+      if (expansion)
+       {
+         dirname = glue_prefix_and_suffix (expansion, filename, user_len);
+         free (username);
+         free (expansion);
+         return (dirname);
+       }
+    }
 
-         if (!(user_entry = getpwnam (username)))
-           {
-             /* If the calling program has a special syntax for
-                expanding tildes, and we couldn't find a standard
-                expansion, then let them try. */
-             if (tilde_expansion_failure_hook)
-               {
-                 char *expansion;
-
-                 expansion =
-                   (char *)(*tilde_expansion_failure_hook) (username);
-
-                 if (expansion)
-                   {
-                     temp_name = (char *)alloca (1 + strlen (expansion)
-                                                 + strlen (&dirname[i]));
-                     strcpy (temp_name, expansion);
-                     strcat (temp_name, &dirname[i]);
-                     free (expansion);
-                     goto return_name;
-                   }
-               }
-             /* We shouldn't report errors. */
-           }
-         else
+  /* No preexpansion hook, or the preexpansion hook failed.  Look in the
+     password database. */
+  dirname = (char *)NULL;
+  user_entry = getpwnam (username);
+  if (user_entry == 0)
+    {
+      /* If the calling program has a special syntax for expanding tildes,
+        and we couldn't find a standard expansion, then let them try. */
+      if (tilde_expansion_failure_hook)
+       {
+         expansion = (*tilde_expansion_failure_hook) (username);
+         if (expansion)
            {
-             temp_name = (char *)alloca (1 + strlen (user_entry->pw_dir)
-                                         + strlen (&dirname[i]));
-             strcpy (temp_name, user_entry->pw_dir);
-             strcat (temp_name, &dirname[i]);
-           return_name:
-             free (dirname);
-             dirname = savestring (temp_name);
+             dirname = glue_prefix_and_suffix (expansion, filename, user_len);
+             free (expansion);
            }
-           endpwent ();
        }
+      free (username);
+      /* If we don't have a failure hook, or if the failure hook did not
+        expand the tilde, return a copy of what we were passed. */
+      if (dirname == 0)
+       dirname = savestring (filename);
     }
+  else
+    {
+      free (username);
+      dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
+    }
+
+  endpwent ();
   return (dirname);
 }
 
@@ -384,7 +447,7 @@ xrealloc (pointer, bytes)
 static void
 memory_error_and_abort ()
 {
-  fprintf (stderr, "readline: Out of virtual memory!\n");
+  fprintf (stderr, "readline: out of virtual memory\n");
   abort ();
 }
 
This page took 0.033048 seconds and 4 git commands to generate.