OSDN Git Service

Mark ChangeLog
[pf3gnuchains/gcc-fork.git] / libiberty / cplus-dem.c
index b186963..e948487 100644 (file)
@@ -1,6 +1,6 @@
 /* Demangler for GNU C++
    Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
    Written by James Clark (jjc@jclark.uucp)
    Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
    Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
@@ -27,8 +27,8 @@ Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public
 License along with libiberty; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 /* This file exports two functions; cplus_mangle_opname and cplus_demangle.
 
@@ -52,8 +52,8 @@ Boston, MA 02111-1307, USA.  */
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #else
-char * malloc ();
-char * realloc ();
+void * malloc ();
+void * realloc ();
 #endif
 
 #include <demangle.h>
@@ -62,8 +62,6 @@ char * realloc ();
 
 #include "libiberty.h"
 
-static char *ada_demangle (const char *, int);
-
 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
 
 /* A value at least one greater than the maximum number of characters
@@ -414,7 +412,7 @@ static int do_type (struct work_stuff *, const char **, string *);
 
 static int do_arg (struct work_stuff *, const char **, string *);
 
-static void
+static int
 demangle_function_name (struct work_stuff *, const char **, string *,
                         const char *);
 
@@ -478,8 +476,6 @@ demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
 static void
 recursively_demangle (struct work_stuff *, const char **, string *, int);
 
-static void grow_vect (char **, size_t *, size_t, int);
-
 /* Translate count to integer, consuming tokens in the process.
    Conversion terminates on the first non-digit character.
 
@@ -872,126 +868,268 @@ cplus_demangle (const char *mangled, int options)
     }
 
   if (GNAT_DEMANGLING)
-    return ada_demangle(mangled,options);
+    return ada_demangle (mangled, options);
 
   ret = internal_cplus_demangle (work, mangled);
   squangle_mop_up (work);
   return (ret);
 }
 
+/* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
 
-/* Assuming *OLD_VECT points to an array of *SIZE objects of size
-   ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
-   updating *OLD_VECT and *SIZE as necessary.  */
-
-static void
-grow_vect (char **old_vect, size_t *size, size_t min_size, int element_size)
-{
-  if (*size < min_size)
-    {
-      *size *= 2;
-      if (*size < min_size)
-       *size = min_size;
-      *old_vect = (void *) xrealloc (*old_vect, *size * element_size);
-    }
-}
-
-/* Demangle ada names:
-   1. Discard final __{DIGIT}+ or ${DIGIT}+
-   2. Convert other instances of embedded "__" to `.'.
-   3. Discard leading _ada_.
-   4. Remove everything after first ___ if it is followed by 'X'.
-   5. Put symbols that should be suppressed in <...> brackets.
-   The resulting string is valid until the next call of ada_demangle.  */
-
-static char *
+char *
 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
 {
-  int i, j;
   int len0;
   const char* p;
-  char *demangled = NULL;
-  int changed;
-  size_t demangled_size = 0;
+  char *d;
+  char *demangled;
   
-  changed = 0;
-
+  /* Discard leading _ada_, which is used for library level subprograms.  */
   if (strncmp (mangled, "_ada_", 5) == 0)
-    {
-      mangled += 5;
-      changed = 1;
-    }
-  
-  if (mangled[0] == '_' || mangled[0] == '<')
-    goto Suppress;
+    mangled += 5;
+
+  /* All ada unit names are lower-case.  */
+  if (!ISLOWER (mangled[0]))
+    goto unknown;
+
+  /* Most of the demangling will trivially remove chars.  Operator names
+     may add one char but because they are always preceeded by '__' which is
+     replaced by '.', they eventually never expand the size.
+     A few special names such as '___elabs' add a few chars (at most 7), but
+     they occur only once.  */
+  len0 = strlen (mangled) + 7 + 1;
+  demangled = XNEWVEC (char, len0);
   
-  p = strstr (mangled, "___");
-  if (p == NULL)
-    len0 = strlen (mangled);
-  else
+  d = demangled;
+  p = mangled;
+  while (1)
     {
-      if (p[3] == 'X')
-       {
-         len0 = p - mangled;
-         changed = 1;
-       }
+      /* An entity names is expected.  */
+      if (ISLOWER (*p))
+        {
+          /* An identifier, which is always lower case.  */
+          do
+            *d++ = *p++;
+          while (ISLOWER(*p) || ISDIGIT (*p)
+                 || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
+        }
+      else if (p[0] == 'O')
+        {
+          /* An operator name.  */
+          static const char * const operators[][2] =
+            {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
+             {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
+             {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
+             {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
+             {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
+             {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
+             {"Oexpon", "**"}, {NULL, NULL}};
+          int k;
+
+          for (k = 0; operators[k][0] != NULL; k++)
+            {
+              size_t slen = strlen (operators[k][0]);
+              if (strncmp (p, operators[k][0], slen) == 0)
+                {
+                  p += slen;
+                  slen = strlen (operators[k][1]);
+                  *d++ = '"';
+                  memcpy (d, operators[k][1], slen);
+                  d += slen;
+                  *d++ = '"';
+                  break;
+                }
+            }
+          /* Operator not found.  */
+          if (operators[k][0] == NULL)
+            goto unknown;
+        }
       else
-       goto Suppress;
-    }
-  
-  /* Make demangled big enough for possible expansion by operator name.  */
-  grow_vect (&demangled,
-            &demangled_size,  2 * len0 + 1,
-            sizeof (char));
-  
-  if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
-    for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
-      ;
-    if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
-      {
-       len0 = i - 1;
-       changed = 1;
-      }
-    else if (mangled[i] == '$')
-      {
-       len0 = i;
-       changed = 1;
-      }
-  }
-  
-  for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
-       i += 1, j += 1)
-    demangled[j] = mangled[i];
-  
-  while (i < len0)
-    {
-      if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
-       {
-         demangled[j] = '.';
-         changed = 1;
-         i += 2; j += 1;
-       }
+        {
+          /* Not a GNAT encoding.  */
+          goto unknown;
+        }
+
+      /* The name can be directly followed by some uppercase letters.  */
+      if (p[0] == 'T' && p[1] == 'K')
+        {
+          /* Task stuff.  */
+          if (p[2] == 'B' && p[3] == 0)
+            {
+              /* Subprogram for task body.  */
+              break;
+            }
+          else if (p[2] == '_' && p[3] == '_')
+            {
+              /* Inner declarations in a task.  */
+              p += 4;
+              *d++ = '.';
+              continue;
+            }
+          else
+            goto unknown;
+        }
+      if (p[0] == 'E' && p[1] == 0)
+        {
+          /* Exception name.  */
+          goto unknown;
+        }
+      if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
+        {
+          /* Protected type subprogram.  */
+          break;
+        }
+      if ((*p == 'N' || *p == 'S') && p[1] == 0)
+        {
+          /* Enumerated type name table.  */
+          goto unknown;
+        }
+      if (p[0] == 'X')
+        {
+          /* Body nested.  */
+          p++;
+          while (p[0] == 'n' || p[0] == 'b')
+            p++;
+        }
+      if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
+        {
+          /* Stream operations.  */
+          const char *name;
+          switch (p[1])
+            {
+            case 'R':
+              name = "'Read";
+              break;
+            case 'W':
+              name = "'Write";
+              break;
+            case 'I':
+              name = "'Input";
+              break;
+            case 'O':
+              name = "'Output";
+              break;
+            default:
+              goto unknown;
+            }
+          p += 2;
+          strcpy (d, name);
+          d += strlen (name);
+        }
+      else if (p[0] == 'D')
+        {
+          /* Controlled type operation.  */
+          const char *name;
+          switch (p[1])
+            {
+            case 'F':
+              name = ".Finalize";
+              break;
+            case 'A':
+              name = ".Adjust";
+              break;
+            default:
+              goto unknown;
+            }
+          strcpy (d, name);
+          d += strlen (name);
+          break;
+        }
+
+      if (p[0] == '_')
+        {
+          /* Separator.  */
+          if (p[1] == '_')
+            {
+              /* Standard separator.  Handled first.  */
+              p += 2;
+
+              if (ISDIGIT (*p))
+                {
+                  /* Overloading number.  */
+                  do
+                    p++;
+                  while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
+                  if (*p == 'X')
+                    {
+                      p++;
+                      while (p[0] == 'n' || p[0] == 'b')
+                        p++;
+                    }
+                }
+              else if (p[0] == '_' && p[1] != '_')
+                {
+                  /* Special names.  */
+                  static const char * const special[][2] = {
+                    { "_elabb", "'Elab_Body" },
+                    { "_elabs", "'Elab_Spec" },
+                    { "_size", "'Size" },
+                    { "_alignment", "'Alignment" },
+                    { "_assign", ".\":=\"" },
+                    { NULL, NULL }
+                  };
+                  int k;
+
+                  for (k = 0; special[k][0] != NULL; k++)
+                    {
+                      size_t slen = strlen (special[k][0]);
+                      if (strncmp (p, special[k][0], slen) == 0)
+                        {
+                          p += slen;
+                          slen = strlen (special[k][1]);
+                          memcpy (d, special[k][1], slen);
+                          d += slen;
+                          break;
+                        }
+                    }
+                  if (special[k][0] != NULL)
+                    break;
+                  else
+                    goto unknown;
+                }
+              else
+                {
+                  *d++ = '.';
+                  continue;
+                }
+            }
+          else if (p[1] == 'B' || p[1] == 'E')
+            {
+              /* Entry Body or barrier Evaluation.  */
+              p += 2;
+              while (ISDIGIT (*p))
+                p++;
+              if (p[0] == 's' && p[1] == 0)
+                break;
+              else
+                goto unknown;
+            }
+          else
+            goto unknown;
+        }
+
+      if (p[0] == '.' && ISDIGIT (p[1]))
+        {
+          /* Nested subprogram.  */
+          p += 2;
+          while (ISDIGIT (*p))
+            p++;
+        }
+      if (*p == 0)
+        {
+          /* End of mangled name.  */
+          break;
+        }
       else
-       {
-         demangled[j] = mangled[i];
-         i += 1;  j += 1;
-       }
+        goto unknown;
     }
-  demangled[j] = '\000';
-  
-  for (i = 0; demangled[i] != '\0'; i += 1)
-    if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
-      goto Suppress;
+  *d = 0;
+  return demangled;
 
-  if (! changed)
-    return NULL;
-  else
-    return demangled;
-  
- Suppress:
-  grow_vect (&demangled,
-            &demangled_size,  strlen (mangled) + 3,
-            sizeof (char));
+ unknown:
+  len0 = strlen (mangled);
+  demangled = XNEWVEC (char, len0 + 3);
 
   if (mangled[0] == '<')
      strcpy (demangled, mangled);
@@ -1102,56 +1240,52 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
 
   /* Deep-copy dynamic storage.  */
   if (from->typevec_size)
-    to->typevec
-      = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0]));
+    to->typevec = XNEWVEC (char *, from->typevec_size);
 
   for (i = 0; i < from->ntypes; i++)
     {
       int len = strlen (from->typevec[i]) + 1;
 
-      to->typevec[i] = xmalloc (len);
+      to->typevec[i] = XNEWVEC (char, len);
       memcpy (to->typevec[i], from->typevec[i], len);
     }
 
   if (from->ksize)
-    to->ktypevec
-      = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0]));
+    to->ktypevec = XNEWVEC (char *, from->ksize);
 
   for (i = 0; i < from->numk; i++)
     {
       int len = strlen (from->ktypevec[i]) + 1;
 
-      to->ktypevec[i] = xmalloc (len);
+      to->ktypevec[i] = XNEWVEC (char, len);
       memcpy (to->ktypevec[i], from->ktypevec[i], len);
     }
 
   if (from->bsize)
-    to->btypevec
-      = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0]));
+    to->btypevec = XNEWVEC (char *, from->bsize);
 
   for (i = 0; i < from->numb; i++)
     {
       int len = strlen (from->btypevec[i]) + 1;
 
-      to->btypevec[i] = xmalloc (len);
+      to->btypevec[i] = XNEWVEC (char , len);
       memcpy (to->btypevec[i], from->btypevec[i], len);
     }
 
   if (from->ntmpl_args)
-    to->tmpl_argvec
-      = (char **) xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0]));
+    to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
 
   for (i = 0; i < from->ntmpl_args; i++)
     {
       int len = strlen (from->tmpl_argvec[i]) + 1;
 
-      to->tmpl_argvec[i] = xmalloc (len);
+      to->tmpl_argvec[i] = XNEWVEC (char, len);
       memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len);
     }
 
   if (from->previous_argument)
     {
-      to->previous_argument = (string*) xmalloc (sizeof (string));
+      to->previous_argument = XNEW (string);
       string_init (to->previous_argument);
       string_appends (to->previous_argument, from->previous_argument);
     }
@@ -1177,8 +1311,7 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
       int i;
 
       for (i = 0; i < work->ntmpl_args; i++)
-       if (work->tmpl_argvec[i])
-         free ((char*) work->tmpl_argvec[i]);
+       free ((char*) work->tmpl_argvec[i]);
 
       free ((char*) work->tmpl_argvec);
       work->tmpl_argvec = NULL;
@@ -1895,7 +2028,7 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled,
            string_appendn (s, "0", 1);
          else
            {
-             char *p = xmalloc (symbol_len + 1), *q;
+             char *p = XNEWVEC (char, symbol_len + 1), *q;
              strncpy (p, *mangled, symbol_len);
              p [symbol_len] = '\0';
              /* We use cplus_demangle here, rather than
@@ -2001,7 +2134,7 @@ demangle_template (struct work_stuff *work, const char **mangled,
   if (!is_type)
     {
       /* Create an array for saving the template argument values. */
-      work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
+      work->tmpl_argvec = XNEWVEC (char *, r);
       work->ntmpl_args = r;
       for (i = 0; i < r; i++)
        work->tmpl_argvec[i] = 0;
@@ -2026,7 +2159,7 @@ demangle_template (struct work_stuff *work, const char **mangled,
                {
                  /* Save the template argument. */
                  int len = temp.p - temp.b;
-                 work->tmpl_argvec[i] = xmalloc (len + 1);
+                 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
                  memcpy (work->tmpl_argvec[i], temp.b, len);
                  work->tmpl_argvec[i][len] = '\0';
                }
@@ -2054,7 +2187,7 @@ demangle_template (struct work_stuff *work, const char **mangled,
                {
                  /* Save the template argument. */
                  int len = r2;
-                 work->tmpl_argvec[i] = xmalloc (len + 1);
+                 work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
                  memcpy (work->tmpl_argvec[i], *mangled, len);
                  work->tmpl_argvec[i][len] = '\0';
                }
@@ -2100,7 +2233,7 @@ demangle_template (struct work_stuff *work, const char **mangled,
          if (!is_type)
            {
              int len = s->p - s->b;
-             work->tmpl_argvec[i] = xmalloc (len + 1);
+             work->tmpl_argvec[i] = XNEWVEC (char, len + 1);
              memcpy (work->tmpl_argvec[i], s->b, len);
              work->tmpl_argvec[i][len] = '\0';
 
@@ -2497,10 +2630,7 @@ iterate_demangle_function (struct work_stuff *work, const char **mangled,
      "__"-sequence.  This is the normal case.  */
   if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING
       || strstr (scan + 2, "__") == NULL)
-    {
-      demangle_function_name (work, mangled, declp, scan);
-      return 1;
-    }
+    return demangle_function_name (work, mangled, declp, scan);
 
   /* Save state so we can restart if the guess at the correct "__" was
      wrong.  */
@@ -2517,10 +2647,12 @@ iterate_demangle_function (struct work_stuff *work, const char **mangled,
 
   while (scan[2])
     {
-      demangle_function_name (work, mangled, declp, scan);
-      success = demangle_signature (work, mangled, declp);
-      if (success)
-       break;
+      if (demangle_function_name (work, mangled, declp, scan))
+       {
+         success = demangle_signature (work, mangled, declp);
+         if (success)
+           break;
+       }
 
       /* Reset demangle state for the next round.  */
       *mangled = mangle_init;
@@ -2998,7 +3130,7 @@ recursively_demangle(struct work_stuff *work, const char **mangled,
   char * recurse = (char *)NULL;
   char * recurse_dem = (char *)NULL;
 
-  recurse = (char *) xmalloc (namelength + 1);
+  recurse = XNEWVEC (char, namelength + 1);
   memcpy (recurse, *mangled, namelength);
   recurse[namelength] = '\000';
 
@@ -3697,7 +3829,7 @@ demangle_fund_type (struct work_stuff *work,
 {
   int done = 0;
   int success = 1;
-  char buf[10];
+  char buf[INTBUF_SIZE + 5 /* 'int%u_t' */];
   unsigned int dec = 0;
   type_kind_t tk = tk_integral;
 
@@ -3969,7 +4101,7 @@ do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
   string_append (result, "&");
 
   /* Now recursively demangle the literal name */
-  recurse = (char *) xmalloc (literal_len + 1);
+  recurse = XNEWVEC (char, literal_len + 1);
   memcpy (recurse, *mangled, literal_len);
   recurse[literal_len] = '\000';
 
@@ -4071,7 +4203,7 @@ do_arg (struct work_stuff *work, const char **mangled, string *result)
   if (work->previous_argument)
     string_delete (work->previous_argument);
   else
-    work->previous_argument = (string*) xmalloc (sizeof (string));
+    work->previous_argument = XNEW (string);
 
   if (!do_type (work, mangled, work->previous_argument))
     return 0;
@@ -4095,18 +4227,16 @@ remember_type (struct work_stuff *work, const char *start, int len)
       if (work -> typevec_size == 0)
        {
          work -> typevec_size = 3;
-         work -> typevec
-           = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
+         work -> typevec = XNEWVEC (char *, work->typevec_size);
        }
       else
        {
          work -> typevec_size *= 2;
          work -> typevec
-           = (char **) xrealloc ((char *)work -> typevec,
-                                 sizeof (char *) * work -> typevec_size);
+           = XRESIZEVEC (char *, work->typevec, work->typevec_size);
        }
     }
-  tem = xmalloc (len + 1);
+  tem = XNEWVEC (char, len + 1);
   memcpy (tem, start, len);
   tem[len] = '\0';
   work -> typevec[work -> ntypes++] = tem;
@@ -4124,18 +4254,16 @@ remember_Ktype (struct work_stuff *work, const char *start, int len)
       if (work -> ksize == 0)
        {
          work -> ksize = 5;
-         work -> ktypevec
-           = (char **) xmalloc (sizeof (char *) * work -> ksize);
+         work -> ktypevec = XNEWVEC (char *, work->ksize);
        }
       else
        {
          work -> ksize *= 2;
          work -> ktypevec
-           = (char **) xrealloc ((char *)work -> ktypevec,
-                                 sizeof (char *) * work -> ksize);
+           = XRESIZEVEC (char *, work->ktypevec, work->ksize);
        }
     }
-  tem = xmalloc (len + 1);
+  tem = XNEWVEC (char, len + 1);
   memcpy (tem, start, len);
   tem[len] = '\0';
   work -> ktypevec[work -> numk++] = tem;
@@ -4155,15 +4283,13 @@ register_Btype (struct work_stuff *work)
       if (work -> bsize == 0)
        {
          work -> bsize = 5;
-         work -> btypevec
-           = (char **) xmalloc (sizeof (char *) * work -> bsize);
+         work -> btypevec = XNEWVEC (char *, work->bsize);
        }
       else
        {
          work -> bsize *= 2;
          work -> btypevec
-           = (char **) xrealloc ((char *)work -> btypevec,
-                                 sizeof (char *) * work -> bsize);
+           = XRESIZEVEC (char *, work->btypevec, work->bsize);
        }
     }
   ret = work -> numb++;
@@ -4179,7 +4305,7 @@ remember_Btype (struct work_stuff *work, const char *start,
 {
   char *tem;
 
-  tem = xmalloc (len + 1);
+  tem = XNEWVEC (char, len + 1);
   memcpy (tem, start, len);
   tem[len] = '\0';
   work -> btypevec[index] = tem;
@@ -4431,7 +4557,9 @@ demangle_nested_args (struct work_stuff *work, const char **mangled,
   return result;
 }
 
-static void
+/* Returns 1 if a valid function name was found or 0 otherwise.  */
+
+static int 
 demangle_function_name (struct work_stuff *work, const char **mangled,
                         string *declp, const char *scan)
 {
@@ -4471,13 +4599,13 @@ demangle_function_name (struct work_stuff *work, const char **mangled,
        {
          work -> constructor += 1;
          string_clear (declp);
-         return;
+         return 1;
        }
       else if (strcmp (declp -> b, "__dt") == 0)
        {
          work -> destructor += 1;
          string_clear (declp);
-         return;
+         return 1;
        }
     }
 
@@ -4585,6 +4713,13 @@ demangle_function_name (struct work_stuff *work, const char **mangled,
            }
        }
     }
+
+  /* If a function name was obtained but it's not valid, we were not
+     successful.  */
+  if (LEN_STRING (declp) == 1 && declp->b[0] == '.')
+    return 0;
+  else
+    return 1;
 }
 
 /* a mini string-handling package */
@@ -4600,7 +4735,7 @@ string_need (string *s, int n)
        {
          n = 32;
        }
-      s->p = s->b = xmalloc (n);
+      s->p = s->b = XNEWVEC (char, n);
       s->e = s->b + n;
     }
   else if (s->e - s->p < n)
@@ -4608,7 +4743,7 @@ string_need (string *s, int n)
       tem = s->p - s->b;
       n += tem;
       n *= 2;
-      s->b = xrealloc (s->b, n);
+      s->b = XRESIZEVEC (char, s->b, n);
       s->p = s->b + tem;
       s->e = s->b + n;
     }