xref: /openbsd-src/gnu/lib/libreadline/tilde.c (revision 9704b281e65e1189747652d0ba55eee892cff5f7)
11acd27e7Smillert /* tilde.c -- Tilde expansion code (~/foo := $HOME/foo). */
21acd27e7Smillert 
31acd27e7Smillert /* Copyright (C) 1988,1989 Free Software Foundation, Inc.
41acd27e7Smillert 
51acd27e7Smillert    This file is part of GNU Readline, a library for reading lines
61acd27e7Smillert    of text with interactive input and history editing.
71acd27e7Smillert 
81acd27e7Smillert    Readline is free software; you can redistribute it and/or modify it
91acd27e7Smillert    under the terms of the GNU General Public License as published by the
101acd27e7Smillert    Free Software Foundation; either version 2, or (at your option) any
111acd27e7Smillert    later version.
121acd27e7Smillert 
131acd27e7Smillert    Readline is distributed in the hope that it will be useful, but
141acd27e7Smillert    WITHOUT ANY WARRANTY; without even the implied warranty of
151acd27e7Smillert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
161acd27e7Smillert    General Public License for more details.
171acd27e7Smillert 
181acd27e7Smillert    You should have received a copy of the GNU General Public License
191acd27e7Smillert    along with Readline; see the file COPYING.  If not, write to the Free
201acd27e7Smillert    Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
211acd27e7Smillert 
221acd27e7Smillert #if defined (HAVE_CONFIG_H)
231acd27e7Smillert #  include <config.h>
241acd27e7Smillert #endif
251acd27e7Smillert 
261acd27e7Smillert #if defined (HAVE_UNISTD_H)
271acd27e7Smillert #  ifdef _MINIX
281acd27e7Smillert #    include <sys/types.h>
291acd27e7Smillert #  endif
301acd27e7Smillert #  include <unistd.h>
311acd27e7Smillert #endif
321acd27e7Smillert 
331acd27e7Smillert #if defined (HAVE_STRING_H)
341acd27e7Smillert #  include <string.h>
351acd27e7Smillert #else /* !HAVE_STRING_H */
361acd27e7Smillert #  include <strings.h>
371acd27e7Smillert #endif /* !HAVE_STRING_H */
381acd27e7Smillert 
391acd27e7Smillert #if defined (HAVE_STDLIB_H)
401acd27e7Smillert #  include <stdlib.h>
411acd27e7Smillert #else
421acd27e7Smillert #  include "ansi_stdlib.h"
431acd27e7Smillert #endif /* HAVE_STDLIB_H */
441acd27e7Smillert 
451acd27e7Smillert #include <sys/types.h>
461acd27e7Smillert #include <pwd.h>
471acd27e7Smillert 
481acd27e7Smillert #include "tilde.h"
491acd27e7Smillert 
501acd27e7Smillert #if defined (TEST) || defined (STATIC_MALLOC)
51af70c2dfSkettenis static void *xmalloc (), *xrealloc ();
521acd27e7Smillert #else
53af70c2dfSkettenis #  include "xmalloc.h"
541acd27e7Smillert #endif /* TEST || STATIC_MALLOC */
551acd27e7Smillert 
561acd27e7Smillert #if !defined (HAVE_GETPW_DECLS)
57af70c2dfSkettenis extern struct passwd *getpwuid PARAMS((uid_t));
58af70c2dfSkettenis extern struct passwd *getpwnam PARAMS((const char *));
591acd27e7Smillert #endif /* !HAVE_GETPW_DECLS */
601acd27e7Smillert 
611acd27e7Smillert #if !defined (savestring)
6263bef317Sbeck #include <stdio.h>
6363bef317Sbeck static char *
xstrdup(const char * s)64af70c2dfSkettenis xstrdup(const char *s)
6563bef317Sbeck {
6663bef317Sbeck 	char * cp;
6763bef317Sbeck 	cp = strdup(s);
6863bef317Sbeck 	if (cp == NULL) {
6963bef317Sbeck 		fprintf (stderr, "xstrdup: out of virtual memory\n");
7063bef317Sbeck 		exit (2);
7163bef317Sbeck 	}
7263bef317Sbeck 	return(cp);
7363bef317Sbeck }
7463bef317Sbeck #define savestring(x) xstrdup(x)
751acd27e7Smillert #endif /* !savestring  */
761acd27e7Smillert 
771acd27e7Smillert #if !defined (NULL)
781acd27e7Smillert #  if defined (__STDC__)
791acd27e7Smillert #    define NULL ((void *) 0)
801acd27e7Smillert #  else
811acd27e7Smillert #    define NULL 0x0
821acd27e7Smillert #  endif /* !__STDC__ */
831acd27e7Smillert #endif /* !NULL */
841acd27e7Smillert 
851acd27e7Smillert /* If being compiled as part of bash, these will be satisfied from
861acd27e7Smillert    variables.o.  If being compiled as part of readline, they will
871acd27e7Smillert    be satisfied from shell.o. */
88af70c2dfSkettenis extern char *sh_get_home_dir PARAMS((void));
89af70c2dfSkettenis extern char *sh_get_env_value PARAMS((const char *));
901acd27e7Smillert 
911acd27e7Smillert /* The default value of tilde_additional_prefixes.  This is set to
921acd27e7Smillert    whitespace preceding a tilde so that simple programs which do not
931acd27e7Smillert    perform any word separation get desired behaviour. */
94af70c2dfSkettenis static const char *default_prefixes[] =
95af70c2dfSkettenis   { " ~", "\t~", (const char *)NULL };
961acd27e7Smillert 
971acd27e7Smillert /* The default value of tilde_additional_suffixes.  This is set to
981acd27e7Smillert    whitespace or newline so that simple programs which do not
991acd27e7Smillert    perform any word separation get desired behaviour. */
100af70c2dfSkettenis static const char *default_suffixes[] =
101af70c2dfSkettenis   { " ", "\n", (const char *)NULL };
1021acd27e7Smillert 
1031acd27e7Smillert /* If non-null, this contains the address of a function that the application
1041acd27e7Smillert    wants called before trying the standard tilde expansions.  The function
1051acd27e7Smillert    is called with the text sans tilde, and returns a malloc()'ed string
1061acd27e7Smillert    which is the expansion, or a NULL pointer if the expansion fails. */
107af70c2dfSkettenis tilde_hook_func_t *tilde_expansion_preexpansion_hook = (tilde_hook_func_t *)NULL;
1081acd27e7Smillert 
1091acd27e7Smillert /* If non-null, this contains the address of a function to call if the
1101acd27e7Smillert    standard meaning for expanding a tilde fails.  The function is called
1111acd27e7Smillert    with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
1121acd27e7Smillert    which is the expansion, or a NULL pointer if there is no expansion. */
113af70c2dfSkettenis tilde_hook_func_t *tilde_expansion_failure_hook = (tilde_hook_func_t *)NULL;
1141acd27e7Smillert 
1151acd27e7Smillert /* When non-null, this is a NULL terminated array of strings which
1161acd27e7Smillert    are duplicates for a tilde prefix.  Bash uses this to expand
1171acd27e7Smillert    `=~' and `:~'. */
118af70c2dfSkettenis char **tilde_additional_prefixes = (char **)default_prefixes;
1191acd27e7Smillert 
1201acd27e7Smillert /* When non-null, this is a NULL terminated array of strings which match
1211acd27e7Smillert    the end of a username, instead of just "/".  Bash sets this to
1221acd27e7Smillert    `:' and `=~'. */
123af70c2dfSkettenis char **tilde_additional_suffixes = (char **)default_suffixes;
124af70c2dfSkettenis 
125af70c2dfSkettenis static int tilde_find_prefix PARAMS((const char *, int *));
126af70c2dfSkettenis static int tilde_find_suffix PARAMS((const char *));
127af70c2dfSkettenis static char *isolate_tilde_prefix PARAMS((const char *, int *));
128af70c2dfSkettenis static char *glue_prefix_and_suffix PARAMS((char *, const char *, int));
1291acd27e7Smillert 
1301acd27e7Smillert /* Find the start of a tilde expansion in STRING, and return the index of
1311acd27e7Smillert    the tilde which starts the expansion.  Place the length of the text
1321acd27e7Smillert    which identified this tilde starter in LEN, excluding the tilde itself. */
1331acd27e7Smillert static int
tilde_find_prefix(string,len)1341acd27e7Smillert tilde_find_prefix (string, len)
135af70c2dfSkettenis      const char *string;
1361acd27e7Smillert      int *len;
1371acd27e7Smillert {
1381acd27e7Smillert   register int i, j, string_len;
1391acd27e7Smillert   register char **prefixes;
1401acd27e7Smillert 
1411acd27e7Smillert   prefixes = tilde_additional_prefixes;
1421acd27e7Smillert 
1431acd27e7Smillert   string_len = strlen (string);
1441acd27e7Smillert   *len = 0;
1451acd27e7Smillert 
1461acd27e7Smillert   if (*string == '\0' || *string == '~')
1471acd27e7Smillert     return (0);
1481acd27e7Smillert 
1491acd27e7Smillert   if (prefixes)
1501acd27e7Smillert     {
1511acd27e7Smillert       for (i = 0; i < string_len; i++)
1521acd27e7Smillert 	{
1531acd27e7Smillert 	  for (j = 0; prefixes[j]; j++)
1541acd27e7Smillert 	    {
1551acd27e7Smillert 	      if (strncmp (string + i, prefixes[j], strlen (prefixes[j])) == 0)
1561acd27e7Smillert 		{
1571acd27e7Smillert 		  *len = strlen (prefixes[j]) - 1;
1581acd27e7Smillert 		  return (i + *len);
1591acd27e7Smillert 		}
1601acd27e7Smillert 	    }
1611acd27e7Smillert 	}
1621acd27e7Smillert     }
1631acd27e7Smillert   return (string_len);
1641acd27e7Smillert }
1651acd27e7Smillert 
1661acd27e7Smillert /* Find the end of a tilde expansion in STRING, and return the index of
1671acd27e7Smillert    the character which ends the tilde definition.  */
1681acd27e7Smillert static int
tilde_find_suffix(string)1691acd27e7Smillert tilde_find_suffix (string)
170af70c2dfSkettenis      const char *string;
1711acd27e7Smillert {
1721acd27e7Smillert   register int i, j, string_len;
1731acd27e7Smillert   register char **suffixes;
1741acd27e7Smillert 
1751acd27e7Smillert   suffixes = tilde_additional_suffixes;
1761acd27e7Smillert   string_len = strlen (string);
1771acd27e7Smillert 
1781acd27e7Smillert   for (i = 0; i < string_len; i++)
1791acd27e7Smillert     {
1801acd27e7Smillert #if defined (__MSDOS__)
1811acd27e7Smillert       if (string[i] == '/' || string[i] == '\\' /* || !string[i] */)
1821acd27e7Smillert #else
1831acd27e7Smillert       if (string[i] == '/' /* || !string[i] */)
1841acd27e7Smillert #endif
1851acd27e7Smillert 	break;
1861acd27e7Smillert 
1871acd27e7Smillert       for (j = 0; suffixes && suffixes[j]; j++)
1881acd27e7Smillert 	{
1891acd27e7Smillert 	  if (strncmp (string + i, suffixes[j], strlen (suffixes[j])) == 0)
1901acd27e7Smillert 	    return (i);
1911acd27e7Smillert 	}
1921acd27e7Smillert     }
1931acd27e7Smillert   return (i);
1941acd27e7Smillert }
1951acd27e7Smillert 
1961acd27e7Smillert /* Return a new string which is the result of tilde expanding STRING. */
1971acd27e7Smillert char *
tilde_expand(string)1981acd27e7Smillert tilde_expand (string)
199af70c2dfSkettenis      const char *string;
2001acd27e7Smillert {
2011acd27e7Smillert   char *result;
2021acd27e7Smillert   int result_size, result_index;
2031acd27e7Smillert 
2041acd27e7Smillert   result_index = result_size = 0;
205*af1e7b8cSkrw   if ((result = strchr (string, '~')))
206af70c2dfSkettenis     result = (char *)xmalloc (result_size = (strlen (string) + 16));
2071acd27e7Smillert   else
208af70c2dfSkettenis     result = (char *)xmalloc (result_size = (strlen (string) + 1));
2091acd27e7Smillert 
2101acd27e7Smillert   /* Scan through STRING expanding tildes as we come to them. */
2111acd27e7Smillert   while (1)
2121acd27e7Smillert     {
2131acd27e7Smillert       register int start, end;
2141acd27e7Smillert       char *tilde_word, *expansion;
2151acd27e7Smillert       int len;
2161acd27e7Smillert 
2171acd27e7Smillert       /* Make START point to the tilde which starts the expansion. */
2181acd27e7Smillert       start = tilde_find_prefix (string, &len);
2191acd27e7Smillert 
2201acd27e7Smillert       /* Copy the skipped text into the result. */
2211acd27e7Smillert       if ((result_index + start + 1) > result_size)
222af70c2dfSkettenis 	result = (char *)xrealloc (result, 1 + (result_size += (start + 20)));
2231acd27e7Smillert 
2241acd27e7Smillert       strncpy (result + result_index, string, start);
2251acd27e7Smillert       result_index += start;
2261acd27e7Smillert 
2271acd27e7Smillert       /* Advance STRING to the starting tilde. */
2281acd27e7Smillert       string += start;
2291acd27e7Smillert 
2301acd27e7Smillert       /* Make END be the index of one after the last character of the
2311acd27e7Smillert 	 username. */
2321acd27e7Smillert       end = tilde_find_suffix (string);
2331acd27e7Smillert 
2341acd27e7Smillert       /* If both START and END are zero, we are all done. */
2351acd27e7Smillert       if (!start && !end)
2361acd27e7Smillert 	break;
2371acd27e7Smillert 
2381acd27e7Smillert       /* Expand the entire tilde word, and copy it into RESULT. */
239af70c2dfSkettenis       tilde_word = (char *)xmalloc (1 + end);
2401acd27e7Smillert       strncpy (tilde_word, string, end);
2411acd27e7Smillert       tilde_word[end] = '\0';
2421acd27e7Smillert       string += end;
2431acd27e7Smillert 
2441acd27e7Smillert       expansion = tilde_expand_word (tilde_word);
2451acd27e7Smillert       free (tilde_word);
2461acd27e7Smillert 
2471acd27e7Smillert       len = strlen (expansion);
248af70c2dfSkettenis #ifdef __CYGWIN__
2491acd27e7Smillert       /* Fix for Cygwin to prevent ~user/xxx from expanding to //xxx when
2501acd27e7Smillert 	 $HOME for `user' is /.  On cygwin, // denotes a network drive. */
2511acd27e7Smillert       if (len > 1 || *expansion != '/' || *string != '/')
2521acd27e7Smillert #endif
2531acd27e7Smillert 	{
2541acd27e7Smillert 	  if ((result_index + len + 1) > result_size)
255af70c2dfSkettenis 	    result = (char *)xrealloc (result, 1 + (result_size += (len + 20)));
2561acd27e7Smillert 
25763bef317Sbeck 	  strlcpy (result + result_index, expansion,
25863bef317Sbeck 		   result_size - result_index);
2591acd27e7Smillert 	  result_index += len;
2601acd27e7Smillert 	}
2611acd27e7Smillert       free (expansion);
2621acd27e7Smillert     }
2631acd27e7Smillert 
2641acd27e7Smillert   result[result_index] = '\0';
2651acd27e7Smillert 
2661acd27e7Smillert   return (result);
2671acd27e7Smillert }
2681acd27e7Smillert 
2691acd27e7Smillert /* Take FNAME and return the tilde prefix we want expanded.  If LENP is
2701acd27e7Smillert    non-null, the index of the end of the prefix into FNAME is returned in
2711acd27e7Smillert    the location it points to. */
2721acd27e7Smillert static char *
isolate_tilde_prefix(fname,lenp)2731acd27e7Smillert isolate_tilde_prefix (fname, lenp)
274af70c2dfSkettenis      const char *fname;
2751acd27e7Smillert      int *lenp;
2761acd27e7Smillert {
2771acd27e7Smillert   char *ret;
2781acd27e7Smillert   int i;
2791acd27e7Smillert 
280af70c2dfSkettenis   ret = (char *)xmalloc (strlen (fname));
2811acd27e7Smillert #if defined (__MSDOS__)
2821acd27e7Smillert   for (i = 1; fname[i] && fname[i] != '/' && fname[i] != '\\'; i++)
2831acd27e7Smillert #else
2841acd27e7Smillert   for (i = 1; fname[i] && fname[i] != '/'; i++)
2851acd27e7Smillert #endif
2861acd27e7Smillert     ret[i - 1] = fname[i];
2871acd27e7Smillert   ret[i - 1] = '\0';
2881acd27e7Smillert   if (lenp)
2891acd27e7Smillert     *lenp = i;
2901acd27e7Smillert   return ret;
2911acd27e7Smillert }
2921acd27e7Smillert 
2931acd27e7Smillert /* Return a string that is PREFIX concatenated with SUFFIX starting at
2941acd27e7Smillert    SUFFIND. */
2951acd27e7Smillert static char *
glue_prefix_and_suffix(prefix,suffix,suffind)2961acd27e7Smillert glue_prefix_and_suffix (prefix, suffix, suffind)
297af70c2dfSkettenis      char *prefix;
298af70c2dfSkettenis      const char *suffix;
2991acd27e7Smillert      int suffind;
3001acd27e7Smillert {
3011acd27e7Smillert   char *ret;
3021acd27e7Smillert   int plen, slen;
3031acd27e7Smillert 
3041acd27e7Smillert   plen = (prefix && *prefix) ? strlen (prefix) : 0;
3051acd27e7Smillert   slen = strlen (suffix + suffind);
306af70c2dfSkettenis   ret = (char *)xmalloc (plen + slen + 1);
3071acd27e7Smillert   if (plen)
30863bef317Sbeck     strlcpy (ret, prefix, plen + slen + 1);
30963bef317Sbeck   strlcat (ret, suffix + suffind, plen + slen + 1);
3101acd27e7Smillert   return ret;
3111acd27e7Smillert }
3121acd27e7Smillert 
3131acd27e7Smillert /* Do the work of tilde expansion on FILENAME.  FILENAME starts with a
3141acd27e7Smillert    tilde.  If there is no expansion, call tilde_expansion_failure_hook.
3151acd27e7Smillert    This always returns a newly-allocated string, never static storage. */
3161acd27e7Smillert char *
tilde_expand_word(filename)3171acd27e7Smillert tilde_expand_word (filename)
318af70c2dfSkettenis      const char *filename;
3191acd27e7Smillert {
3201acd27e7Smillert   char *dirname, *expansion, *username;
3211acd27e7Smillert   int user_len;
3221acd27e7Smillert   struct passwd *user_entry;
3231acd27e7Smillert 
3241acd27e7Smillert   if (filename == 0)
3251acd27e7Smillert     return ((char *)NULL);
3261acd27e7Smillert 
3271acd27e7Smillert   if (*filename != '~')
3281acd27e7Smillert     return (savestring (filename));
3291acd27e7Smillert 
3301acd27e7Smillert   /* A leading `~/' or a bare `~' is *always* translated to the value of
3311acd27e7Smillert      $HOME or the home directory of the current user, regardless of any
3321acd27e7Smillert      preexpansion hook. */
3331acd27e7Smillert   if (filename[1] == '\0' || filename[1] == '/')
3341acd27e7Smillert     {
3351acd27e7Smillert       /* Prefix $HOME to the rest of the string. */
336af70c2dfSkettenis       expansion = sh_get_env_value ("HOME");
3371acd27e7Smillert 
3381acd27e7Smillert       /* If there is no HOME variable, look up the directory in
3391acd27e7Smillert 	 the password database. */
34094bc1d69Smillert       if (expansion == 0 || *expansion == '\0')
341af70c2dfSkettenis 	expansion = sh_get_home_dir ();
3421acd27e7Smillert 
3431acd27e7Smillert       return (glue_prefix_and_suffix (expansion, filename, 1));
3441acd27e7Smillert     }
3451acd27e7Smillert 
3461acd27e7Smillert   username = isolate_tilde_prefix (filename, &user_len);
3471acd27e7Smillert 
3481acd27e7Smillert   if (tilde_expansion_preexpansion_hook)
3491acd27e7Smillert     {
3501acd27e7Smillert       expansion = (*tilde_expansion_preexpansion_hook) (username);
3511acd27e7Smillert       if (expansion)
3521acd27e7Smillert 	{
3531acd27e7Smillert 	  dirname = glue_prefix_and_suffix (expansion, filename, user_len);
3541acd27e7Smillert 	  free (username);
3551acd27e7Smillert 	  free (expansion);
3561acd27e7Smillert 	  return (dirname);
3571acd27e7Smillert 	}
3581acd27e7Smillert     }
3591acd27e7Smillert 
3601acd27e7Smillert   /* No preexpansion hook, or the preexpansion hook failed.  Look in the
3611acd27e7Smillert      password database. */
3621acd27e7Smillert   dirname = (char *)NULL;
3631acd27e7Smillert   user_entry = getpwnam (username);
3641acd27e7Smillert   if (user_entry == 0)
3651acd27e7Smillert     {
3661acd27e7Smillert       /* If the calling program has a special syntax for expanding tildes,
3671acd27e7Smillert 	 and we couldn't find a standard expansion, then let them try. */
3681acd27e7Smillert       if (tilde_expansion_failure_hook)
3691acd27e7Smillert 	{
3701acd27e7Smillert 	  expansion = (*tilde_expansion_failure_hook) (username);
3711acd27e7Smillert 	  if (expansion)
3721acd27e7Smillert 	    {
3731acd27e7Smillert 	      dirname = glue_prefix_and_suffix (expansion, filename, user_len);
3741acd27e7Smillert 	      free (expansion);
3751acd27e7Smillert 	    }
3761acd27e7Smillert 	}
3771acd27e7Smillert       free (username);
3781acd27e7Smillert       /* If we don't have a failure hook, or if the failure hook did not
3791acd27e7Smillert 	 expand the tilde, return a copy of what we were passed. */
3801acd27e7Smillert       if (dirname == 0)
3811acd27e7Smillert 	dirname = savestring (filename);
3821acd27e7Smillert     }
3831acd27e7Smillert   else
3841acd27e7Smillert     {
3851acd27e7Smillert       free (username);
3861acd27e7Smillert       dirname = glue_prefix_and_suffix (user_entry->pw_dir, filename, user_len);
3871acd27e7Smillert     }
3881acd27e7Smillert 
3891acd27e7Smillert   endpwent ();
3901acd27e7Smillert   return (dirname);
3911acd27e7Smillert }
3921acd27e7Smillert 
3931acd27e7Smillert 
3941acd27e7Smillert #if defined (TEST)
3951acd27e7Smillert #undef NULL
3961acd27e7Smillert #include <stdio.h>
3971acd27e7Smillert 
main(argc,argv)3981acd27e7Smillert main (argc, argv)
3991acd27e7Smillert      int argc;
4001acd27e7Smillert      char **argv;
4011acd27e7Smillert {
4021acd27e7Smillert   char *result, line[512];
4031acd27e7Smillert   int done = 0;
4041acd27e7Smillert 
4051acd27e7Smillert   while (!done)
4061acd27e7Smillert     {
4071acd27e7Smillert       printf ("~expand: ");
4081acd27e7Smillert       fflush (stdout);
4091acd27e7Smillert 
41063bef317Sbeck       if (!fgets (line, sizeof(line), stdin))
41163bef317Sbeck 	strlcpy (line, "done", sizeof(line));
41263bef317Sbeck       else if (line[strlen(line) - 1] == '\n')
41363bef317Sbeck 	      line[strlen(line) - 1] = '\0';
4141acd27e7Smillert       if ((strcmp (line, "done") == 0) ||
4151acd27e7Smillert 	  (strcmp (line, "quit") == 0) ||
4161acd27e7Smillert 	  (strcmp (line, "exit") == 0))
4171acd27e7Smillert 	{
4181acd27e7Smillert 	  done = 1;
4191acd27e7Smillert 	  break;
4201acd27e7Smillert 	}
4211acd27e7Smillert 
4221acd27e7Smillert       result = tilde_expand (line);
4231acd27e7Smillert       printf ("  --> %s\n", result);
4241acd27e7Smillert       free (result);
4251acd27e7Smillert     }
4261acd27e7Smillert   exit (0);
4271acd27e7Smillert }
4281acd27e7Smillert 
4291acd27e7Smillert static void memory_error_and_abort ();
4301acd27e7Smillert 
431af70c2dfSkettenis static void *
xmalloc(bytes)4321acd27e7Smillert xmalloc (bytes)
433af70c2dfSkettenis      size_t bytes;
4341acd27e7Smillert {
435af70c2dfSkettenis   void *temp = (char *)malloc (bytes);
4361acd27e7Smillert 
4371acd27e7Smillert   if (!temp)
4381acd27e7Smillert     memory_error_and_abort ();
4391acd27e7Smillert   return (temp);
4401acd27e7Smillert }
4411acd27e7Smillert 
442af70c2dfSkettenis static void *
xrealloc(pointer,bytes)4431acd27e7Smillert xrealloc (pointer, bytes)
444af70c2dfSkettenis      void *pointer;
4451acd27e7Smillert      int bytes;
4461acd27e7Smillert {
447af70c2dfSkettenis   void *temp;
4481acd27e7Smillert 
4491acd27e7Smillert   if (!pointer)
450af70c2dfSkettenis     temp = malloc (bytes);
4511acd27e7Smillert   else
452af70c2dfSkettenis     temp = realloc (pointer, bytes);
4531acd27e7Smillert 
4541acd27e7Smillert   if (!temp)
4551acd27e7Smillert     memory_error_and_abort ();
4561acd27e7Smillert 
4571acd27e7Smillert   return (temp);
4581acd27e7Smillert }
4591acd27e7Smillert 
4601acd27e7Smillert static void
memory_error_and_abort()4611acd27e7Smillert memory_error_and_abort ()
4621acd27e7Smillert {
4631acd27e7Smillert   fprintf (stderr, "readline: out of virtual memory\n");
4641acd27e7Smillert   abort ();
4651acd27e7Smillert }
4661acd27e7Smillert 
4671acd27e7Smillert /*
4681acd27e7Smillert  * Local variables:
4691acd27e7Smillert  * compile-command: "gcc -g -DTEST -o tilde tilde.c"
4701acd27e7Smillert  * end:
4711acd27e7Smillert  */
4721acd27e7Smillert #endif /* TEST */
473