home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Atari / Gnu / gdb36p4s.zoo / cplus-dem.c < prev    next >
C/C++ Source or Header  |  1990-06-29  |  19KB  |  986 lines

  1. /* Demangler for GNU C++ 
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.    written by James Clark (jjc@jclark.uucp)
  4.    
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 1, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* This is for g++ 1.36.1 (November 6 version). It will probably
  20.    require changes for any other version.
  21.  
  22.    Modified for g++ 1.36.2 (November 18 version).  */
  23.  
  24. /* This file exports one function
  25.  
  26.    char *cplus_demangle (const char *name, int ansi)
  27.    
  28.    If NAME is a mangled function name produced by GNU C++, then
  29.    a pointer to a malloced string giving a C++ representation
  30.    of the name will be returned; otherwise NULL will be returned.
  31.    It is the caller's responsibility to free the string which
  32.    is returned.
  33.  
  34.    If ANSI is non-zero, then ANSI qualifiers such as `const',
  35.    `void', and the ellipses operator `...' are output.  Otherwise
  36.    they are not.
  37.  
  38.    For example,
  39.    
  40.    cplus_demangle ("_foo__1Ai")
  41.    
  42.    returns
  43.  
  44.    "A::foo(int)"
  45.  
  46.    This file imports xmalloc and xrealloc, which are like malloc and
  47.    realloc except that they generate a fatal error if there is no
  48.    available memory. */
  49.  
  50. /* #define nounderscore 1 /* define this is names don't start with _ */
  51.  
  52. #include <stdio.h>
  53. #include <ctype.h>
  54.  
  55. #ifdef USG
  56. #include <memory.h>
  57. #include <string.h>
  58. #else
  59. #include <strings.h>
  60. #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
  61. #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
  62. #define strchr index 
  63. #define strrchr rindex
  64. #endif
  65.  
  66. #ifndef __STDC__
  67. #define const
  68. #endif
  69.  
  70. #ifdef __STDC__
  71. extern char *cplus_demangle (const char *type, int ansi);
  72. #else
  73. extern char *cplus_demangle ();
  74. #endif
  75.  
  76. #ifdef __STDC__
  77. extern char *xmalloc (int);
  78. extern char *xrealloc (char *, int);
  79. #else
  80. extern char *xmalloc ();
  81. extern char *xrealloc ();
  82. #endif
  83.  
  84. static char **typevec = 0;
  85. static int ntypes = 0;
  86. static int typevec_size = 0;
  87.  
  88. static struct {
  89.   const char *in;
  90.   const char *out;
  91. } optable[] = {
  92.   "new", " new",
  93.   "delete", " delete",
  94.   "ne", "!=",
  95.   "eq", "==",
  96.   "ge", ">=",
  97.   "gt", ">",
  98.   "le", "<=",
  99.   "lt", "<",
  100.   "plus", "+",
  101.   "minus", "-",
  102.   "mult", "*",
  103.   "convert", "+",    /* unary + */
  104.   "negate", "-",    /* unary - */
  105.   "trunc_mod", "%",
  106.   "trunc_div", "/",
  107.   "truth_andif", "&&",
  108.   "truth_orif", "||",
  109.   "truth_not", "!",
  110.   "postincrement", "++",
  111.   "postdecrement", "--",
  112.   "bit_ior", "|",
  113.   "bit_xor", "^",
  114.   "bit_and", "&",
  115.   "bit_not", "~",
  116.   "call", "()",
  117.   "cond", "?:",
  118.   "alshift", "<<",
  119.   "arshift", ">>",
  120.   "component", "->",
  121.   "indirect", "*",
  122.   "method_call", "->()",
  123.   "addr", "&",        /* unary & */
  124.   "array", "[]",
  125.   "nop", "",            /* for operator= */
  126. };
  127.  
  128. /* Beware: these aren't '\0' terminated. */
  129.  
  130. typedef struct {
  131.   char *b;            /* pointer to start of string */
  132.   char *p;            /* pointer after last character */
  133.   char *e;            /* pointer after end of allocated space */
  134. } string;
  135.  
  136. #ifdef __STDC__
  137. static void string_need (string *s, int n);
  138. static void string_delete (string *s);
  139. static void string_init (string *s);
  140. static void string_clear (string *s);
  141. static int string_empty (string *s);
  142. static void string_append (string *p, const char *s);
  143. static void string_appends (string *p, string *s);
  144. static void string_appendn (string *p, const char *s, int n);
  145. static void string_prepend (string *p, const char *s);
  146. #if 0
  147. static void string_prepends (string *p, string *s);
  148. #endif
  149. static void string_prependn (string *p, const char *s, int n);
  150. static int get_count (const char **type, int *count);
  151. static int do_args (const char **type, string *decl);
  152. static int do_type (const char **type, string *result);
  153. static int do_arg (const char **type, string *result);
  154. static int do_args (const char **type, string *decl);
  155. static void munge_function_name (string *name);
  156. static void remember_type (const char *type, int len);
  157. #else
  158. static void string_need ();
  159. static void string_delete ();
  160. static void string_init ();
  161. static void string_clear ();
  162. static int string_empty ();
  163. static void string_append ();
  164. static void string_appends ();
  165. static void string_appendn ();
  166. static void string_prepend ();
  167. static void string_prepends ();
  168. static void string_prependn ();
  169. static int get_count ();
  170. static int do_args ();
  171. static int do_type ();
  172. static int do_arg ();
  173. static int do_args ();
  174. static void munge_function_name ();
  175. static void remember_type ();
  176. #endif
  177.  
  178. static int print_ansi_qualifiers;
  179.  
  180. char *
  181. cplus_demangle (type, ansi)
  182.      const char *type;
  183.      int ansi;
  184. {
  185.   string decl;
  186.   int n;
  187.   int success = 0;
  188.   int constructor = 0;
  189.   int const_flag = 0;
  190.   int i;
  191.   const char *p;
  192. #ifndef LONGERNAMES
  193.   const char *premangle;
  194. #endif
  195.  
  196.   print_ansi_qualifiers = ansi;
  197.  
  198.   if (type == NULL || *type == '\0')
  199.     return NULL;
  200. #ifndef nounderscore
  201.   if (*type++ != '_')
  202.     return NULL;
  203. #endif
  204.   p = type;
  205.   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  206.     p++;
  207.   if (*p == '\0')
  208.     {
  209.       /* destructor */
  210.       if (type[0] == '_' && type[1] == '$' && type[2] == '_')
  211.     {
  212.       int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
  213.       char *tem = (char *) xmalloc (n);
  214.       strcpy (tem, type + 3);
  215.       strcat (tem, "::~");
  216.       strcat (tem, type + 3);
  217.       strcat (tem, "()");
  218.       return tem;
  219.     }
  220.       /* static data member */
  221.       if (*type != '_' && (p = strchr (type, '$')) != NULL)
  222.     {
  223.       int n = strlen (type) + 2;
  224.       char *tem = (char *) xmalloc (n);
  225.       memcpy (tem, type, p - type);
  226.       strcpy (tem + (p - type), "::");
  227.       strcpy (tem + (p - type) + 2, p + 1);
  228.       return tem;
  229.     }
  230.       /* virtual table */
  231.       if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
  232.     {
  233.       int n = strlen (type + 4) + 14 + 1;
  234.       char *tem = (char *) xmalloc (n);
  235.       strcpy (tem, type + 4);
  236.       strcat (tem, " virtual table");
  237.       return tem;
  238.     }
  239.       return NULL;
  240.     }
  241.  
  242.   string_init (&decl);
  243.  
  244.   if (p == type)
  245.     {
  246.       if (!isdigit (p[2]))
  247.     {
  248.       string_delete (&decl);
  249.       return NULL;
  250.     }
  251.       constructor = 1;
  252.     }
  253.   else
  254.     {
  255.       string_appendn (&decl, type, p - type);
  256.       munge_function_name (&decl);
  257.     }
  258.   p += 2;
  259.  
  260. #ifndef LONGERNAMES
  261.   premangle = p;
  262. #endif
  263.   switch (*p)
  264.     {
  265.     case 'C':
  266.       /* a const member function */
  267.       if (!isdigit (p[1]))
  268.     {
  269.       string_delete (&decl);
  270.       return NULL;
  271.     }
  272.       p += 1;
  273.       const_flag = 1;
  274.       /* fall through */
  275.     case '0':
  276.     case '1':
  277.     case '2':
  278.     case '3':
  279.     case '4':
  280.     case '5':
  281.     case '6':
  282.     case '7':
  283.     case '8':
  284.     case '9':
  285.       n = 0;
  286.       do
  287.     {
  288.       n *= 10;
  289.       n += *p - '0';
  290.       p += 1;
  291.     }
  292.       while (isdigit (*p));
  293.       if (strlen (p) < n)
  294.     {
  295.       string_delete (&decl);
  296.       return NULL;
  297.     }
  298.       if (constructor)
  299.     {
  300.       string_appendn (&decl, p, n);
  301.       string_append (&decl, "::");
  302.       string_appendn (&decl, p, n);
  303.     }
  304.       else
  305.     {
  306.       string_prepend (&decl, "::");
  307.       string_prependn (&decl, p, n);
  308.     }
  309.       p += n;
  310. #ifndef LONGERNAMES
  311.       remember_type (premangle, p - premangle);
  312. #endif
  313.       success = do_args (&p, &decl);
  314.       if (const_flag)
  315.     string_append (&decl, " const");
  316.       break;
  317.     case 'F':
  318.       p += 1;
  319.       success = do_args (&p, &decl);
  320.       break;
  321.     }
  322.  
  323.   for (i = 0; i < ntypes; i++)
  324.     if (typevec[i] != NULL)
  325.       free (typevec[i]);
  326.   ntypes = 0;
  327.   if (typevec != NULL)
  328.     {
  329.       free ((char *)typevec);
  330.       typevec = NULL;
  331.       typevec_size = 0;
  332.     }
  333.  
  334.   if (success)
  335.     {
  336.       string_appendn (&decl, "", 1);
  337.       return decl.b;
  338.     }
  339.   else
  340.     {
  341.       string_delete (&decl);
  342.       return NULL;
  343.     }
  344. }
  345.  
  346. static int
  347. get_count (type, count)
  348.      const char **type;
  349.      int *count;
  350. {
  351.   if (!isdigit (**type))
  352.     return 0;
  353.   *count = **type - '0';
  354.   *type += 1;
  355.   /* see flush_repeats in cplus-method.c */
  356.   if (isdigit (**type))
  357.     {
  358.       const char *p = *type;
  359.       int n = *count;
  360.       do 
  361.     {
  362.       n *= 10;
  363.       n += *p - '0';
  364.       p += 1;
  365.     } 
  366.       while (isdigit (*p));
  367.       if (*p == '_')
  368.     {
  369.       *type = p + 1;
  370.       *count = n;
  371.     }
  372.     }
  373.   return 1;
  374. }
  375.  
  376. /* result will be initialised here; it will be freed on failure */
  377.  
  378. static int
  379. do_type (type, result)
  380.      const char **type;
  381.      string *result;
  382. {
  383.   int n;
  384.   int done;
  385.   int non_empty = 0;
  386.   int success;
  387.   string decl;
  388.   const char *remembered_type;
  389.  
  390.   string_init (&decl);
  391.   string_init (result);
  392.  
  393.   done = 0;
  394.   success = 1;
  395.   while (success && !done)
  396.     {
  397.       int member;
  398.       switch (**type)
  399.     {
  400.     case 'P':
  401.       *type += 1;
  402.       string_prepend (&decl, "*");
  403.       break;
  404.  
  405.     case 'R':
  406.       *type += 1;
  407.       string_prepend (&decl, "&");
  408.       break;
  409.  
  410.     case 'T':
  411.       *type += 1;
  412.       if (!get_count (type, &n) || n >= ntypes)
  413.         success = 0;
  414.       else
  415.         {
  416.           remembered_type = typevec[n];
  417.           type = &remembered_type;
  418.         }
  419.       break;
  420.  
  421.     case 'F':
  422.       *type += 1;
  423.       if (!string_empty (&decl) && decl.b[0] == '*')
  424.         {
  425.           string_prepend (&decl, "(");
  426.           string_append (&decl, ")");
  427.         }
  428.       if (!do_args (type, &decl) || **type != '_')
  429.         success = 0;
  430.       else
  431.         *type += 1;
  432.       break;
  433.  
  434.     case 'M':
  435.     case 'O':
  436.       {
  437.         int constp = 0;
  438.         int volatilep = 0;
  439.  
  440.         member = **type == 'M';
  441.         *type += 1;
  442.         if (!isdigit (**type))
  443.           {
  444.         success = 0;
  445.         break;
  446.           }
  447.         n = 0;
  448.         do
  449.           {
  450.         n *= 10;
  451.         n += **type - '0';
  452.         *type += 1;
  453.           } 
  454.         while (isdigit (**type));
  455.         if (strlen (*type) < n)
  456.           {
  457.         success = 0;
  458.         break;
  459.           }
  460.         string_append (&decl, ")");
  461.         string_prepend (&decl, "::");
  462.         string_prependn (&decl, *type, n);
  463.         string_prepend (&decl, "(");
  464.         *type += n;
  465.         if (member)
  466.           {
  467.         if (**type == 'C')
  468.           {
  469.             *type += 1;
  470.             constp = 1;
  471.           }
  472.         if (**type == 'V')
  473.           {
  474.             *type += 1;
  475.             volatilep = 1;
  476.           }
  477.         if (*(*type)++ != 'F')
  478.           {
  479.             success = 0;
  480.             break;
  481.           }
  482.           }
  483.         if ((member && !do_args (type, &decl)) || **type != '_')
  484.           {
  485.         success = 0;
  486.         break;
  487.           }
  488.         *type += 1;
  489.         if (! print_ansi_qualifiers)
  490.           break;
  491.         if (constp)
  492.           {
  493.         if (non_empty)
  494.           string_append (&decl, " ");
  495.         else
  496.           non_empty = 1;
  497.         string_append (&decl, "const");
  498.           }
  499.         if (volatilep)
  500.           {
  501.         if (non_empty)
  502.           string_append (&decl, " ");
  503.         else
  504.           non_empty = 1;
  505.         string_append (&decl, "volatilep");
  506.           }
  507.         break;
  508.       }
  509.  
  510.     case 'C':
  511.       if ((*type)[1] == 'P')
  512.         {
  513.           *type += 1;
  514.           if (print_ansi_qualifiers)
  515.         {
  516.           if (!string_empty (&decl))
  517.             string_prepend (&decl, " ");
  518.           string_prepend (&decl, "const");
  519.         }
  520.           break;
  521.         }
  522.  
  523.       /* fall through */
  524.     default:
  525.       done = 1;
  526.       break;
  527.     }
  528.     }
  529.  
  530.   done = 0;
  531.   non_empty = 0;
  532.   while (success && !done)
  533.     {
  534.       switch (**type)
  535.     {
  536.     case 'C':
  537.       *type += 1;
  538.       if (print_ansi_qualifiers)
  539.         {
  540.           if (non_empty)
  541.         string_append (result, " ");
  542.           else
  543.         non_empty = 1;
  544.           string_append (result, "const");
  545.         }
  546.       break;
  547.     case 'U':
  548.       *type += 1;
  549.       if (non_empty)
  550.         string_append (result, " ");
  551.       else
  552.         non_empty = 1;
  553.       string_append (result, "unsigned");
  554.       break;
  555.     case 'V':
  556.       *type += 1;
  557.       if (print_ansi_qualifiers)
  558.         {
  559.           if (non_empty)
  560.         string_append (result, " ");
  561.           else
  562.         non_empty = 1;
  563.           string_append (result, "volatile");
  564.         }
  565.       break;
  566.     default:
  567.       done = 1;
  568.       break;
  569.     }
  570.     }
  571.  
  572.   if (success)
  573.     switch (**type)
  574.       {
  575.       case '\0':
  576.       case '_':
  577.     break;
  578.       case 'v':
  579.     *type += 1;
  580.     if (non_empty)
  581.       string_append (result, " ");
  582.     string_append (result, "void");
  583.     break;
  584.       case 'x':
  585.     *type += 1;
  586.     if (non_empty)
  587.       string_append (result, " ");
  588.     string_append (result, "long long");
  589.     break;
  590.       case 'l':
  591.     *type += 1;
  592.     if (non_empty)
  593.       string_append (result, " ");
  594.     string_append (result, "long");
  595.     break;
  596.       case 'i':
  597.     *type += 1;
  598.     if (non_empty)
  599.       string_append (result, " ");
  600.     string_append (result, "int");
  601.     break;
  602.       case 's':
  603.     *type += 1;
  604.     if (non_empty)
  605.       string_append (result, " ");
  606.     string_append (result, "short");
  607.     break;
  608.       case 'c':
  609.     *type += 1;
  610.     if (non_empty)
  611.       string_append (result, " ");
  612.     string_append (result, "char");
  613.     break;
  614.       case 'r':
  615.     *type += 1;
  616.     if (non_empty)
  617.       string_append (result, " ");
  618.     string_append (result, "long double");
  619.     break;
  620.       case 'd':
  621.     *type += 1;
  622.     if (non_empty)
  623.       string_append (result, " ");
  624.     string_append (result, "double");
  625.     break;
  626.       case 'f':
  627.     *type += 1;
  628.     if (non_empty)
  629.       string_append (result, " ");
  630.     string_append (result, "float");
  631.     break;
  632.       case 'G':
  633.     *type += 1;
  634.     if (!isdigit (**type))
  635.       {
  636.         success = 0;
  637.         break;
  638.       }
  639.     /* fall through */
  640.       case '0':
  641.       case '1':
  642.       case '2':
  643.       case '3':
  644.       case '4':
  645.       case '5':
  646.       case '6':
  647.       case '7':
  648.       case '8':
  649.       case '9':
  650.     n = 0;
  651.     do
  652.       {
  653.         n *= 10;
  654.         n += **type - '0';
  655.         *type += 1;
  656.       }
  657.     while (isdigit (**type));
  658.     if (strlen (*type) < n)
  659.       {
  660.         success = 0;
  661.         break;
  662.       }
  663.     if (non_empty)
  664.       string_append (result, " ");
  665.     string_appendn (result, *type, n);
  666.     *type += n;
  667.     break;
  668.       default:
  669.     success = 0;
  670.     break;
  671.       }
  672.  
  673.   if (success)
  674.     {
  675.       if (!string_empty (&decl))
  676.     {
  677.       string_append (result, " ");
  678.       string_appends (result, &decl);
  679.     }
  680.       string_delete (&decl);
  681.       return 1;
  682.     }
  683.   else
  684.     {
  685.       string_delete (&decl);
  686.       string_delete (result);
  687.       return 0;
  688.     }
  689. }
  690.  
  691. /* `result' will be initialised in do_type; it will be freed on failure */
  692.  
  693. static int
  694. do_arg (type, result)
  695.      const char **type;
  696.      string *result;
  697. {
  698.   const char *start = *type;
  699.  
  700.   if (!do_type (type, result))
  701.     return 0;
  702.   remember_type (start, *type - start);
  703.   return 1;
  704. }
  705.  
  706. static void
  707. remember_type (start, len)
  708.      const char *start;
  709.      int len;
  710. {
  711.   char *tem;
  712.  
  713.   if (ntypes >= typevec_size)
  714.     {
  715.       if (typevec_size == 0)
  716.     {
  717.       typevec_size = 3;
  718.       typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
  719.     }
  720.       else
  721.     {
  722.       typevec_size *= 2;
  723.       typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
  724.     }
  725.     }
  726.   tem = (char *) xmalloc (len + 1);
  727.   memcpy (tem, start, len);
  728.   tem[len] = '\0';
  729.   typevec[ntypes++] = tem;
  730. }
  731.  
  732. /* `decl' must be already initialised, usually non-empty;
  733.    it won't be freed on failure */
  734.  
  735. static int
  736. do_args (type, decl)
  737.      const char **type;
  738.      string *decl;
  739. {
  740.   string arg;
  741.   int need_comma = 0;
  742.  
  743.   string_append (decl, "(");
  744.  
  745.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  746.     {
  747.       if (**type == 'N')
  748.     {
  749.       int r;
  750.       int t;
  751.       *type += 1;
  752.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  753.         return 0;
  754.       while (--r >= 0)
  755.         {
  756.           const char *tem = typevec[t];
  757.           if (need_comma)
  758.         string_append (decl, ", ");
  759.           if (!do_arg (&tem, &arg))
  760.         return 0;
  761.           string_appends (decl, &arg);
  762.           string_delete (&arg);
  763.           need_comma = 1;
  764.         }
  765.     }
  766.       else
  767.     {
  768.       if (need_comma)
  769.         string_append (decl, ", ");
  770.       if (!do_arg (type, &arg))
  771.         return 0;
  772.       string_appends (decl, &arg);
  773.       string_delete (&arg);
  774.       need_comma = 1;
  775.     }
  776.     }
  777.  
  778.   if (**type == 'v')
  779.     *type += 1;
  780.   else if (**type == 'e')
  781.     {
  782.       *type += 1;
  783.       if (need_comma)
  784.     string_append (decl, ",");
  785.       string_append (decl, "...");
  786.     }
  787.  
  788.   string_append (decl, ")");
  789.   return 1;
  790. }
  791.  
  792. static void
  793. munge_function_name (name)
  794.      string *name;
  795. {
  796.   if (!string_empty (name) && name->p - name->b >= 3 
  797.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
  798.     {
  799.       int i;
  800.       /* see if it's an assignment expression */
  801.       if (name->p - name->b >= 10 /* op$assign_ */
  802.       && memcmp (name->b + 3, "assign_", 7) == 0)
  803.     {
  804.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  805.         {
  806.           int len = name->p - name->b - 10;
  807.           if (strlen (optable[i].in) == len
  808.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  809.         {
  810.           string_clear (name);
  811.           string_append (name, "operator");
  812.           string_append (name, optable[i].out);
  813.           string_append (name, "=");
  814.           return;
  815.         }
  816.         }
  817.     }
  818.       else
  819.     {
  820.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  821.         {
  822.           int len = name->p - name->b - 3;
  823.           if (strlen (optable[i].in) == len 
  824.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  825.         {
  826.           string_clear (name);
  827.           string_append (name, "operator");
  828.           string_append (name, optable[i].out);
  829.           return;
  830.         }
  831.         }
  832.     }
  833.       return;
  834.     }
  835.   else if (!string_empty (name) && name->p - name->b >= 5
  836.        && memcmp (name->b, "type$", 5) == 0)
  837.     {
  838.       /* type conversion operator */
  839.       string type;
  840.       const char *tem = name->b + 5;
  841.       if (do_type (&tem, &type))
  842.     {
  843.       string_clear (name);
  844.       string_append (name, "operator ");
  845.       string_appends (name, &type);
  846.       string_delete (&type);
  847.       return;
  848.     }
  849.     }
  850. }
  851.  
  852. /* a mini string-handling package */
  853.  
  854. static void
  855. string_need (s, n)
  856.      string *s;
  857.      int n;
  858. {
  859.   if (s->b == NULL)
  860.     {
  861.       if (n < 32)
  862.     n = 32;
  863.       s->p = s->b = (char *) xmalloc (n);
  864.       s->e = s->b + n;
  865.     }
  866.   else if (s->e - s->p < n)
  867.     {
  868.       int tem = s->p - s->b;
  869.       n += tem;
  870.       n *= 2;
  871.       s->b = (char *) xrealloc (s->b, n);
  872.       s->p = s->b + tem;
  873.       s->e = s->b + n;
  874.     }
  875. }
  876.  
  877. static void
  878. string_delete (s)
  879.      string *s;
  880. {
  881.   if (s->b != NULL)
  882.     {
  883.       free (s->b);
  884.       s->b = s->e = s->p = NULL;
  885.     }
  886. }
  887.  
  888. static void
  889. string_init (s)
  890.      string *s;
  891. {
  892.   s->b = s->p = s->e = NULL;
  893. }
  894.  
  895. static void 
  896. string_clear (s)
  897.      string *s;
  898. {
  899.   s->p = s->b;
  900. }
  901.  
  902. static int
  903. string_empty (s)
  904.      string *s;
  905. {
  906.   return s->b == s->p;
  907. }
  908.  
  909. static void
  910. string_append (p, s)
  911.      string *p;
  912.      const char *s;
  913. {
  914.   int n;
  915.   if (s == NULL || *s == '\0')
  916.     return;
  917.   n = strlen (s);
  918.   string_need (p, n);
  919.   memcpy (p->p, s, n);
  920.   p->p += n;
  921. }
  922.  
  923. static void
  924. string_appends (p, s)
  925.      string *p, *s;
  926. {
  927.   int n;
  928.   if (s->b == s->p)
  929.     return;
  930.   n = s->p - s->b;
  931.   string_need (p, n);
  932.   memcpy (p->p, s->b, n);
  933.   p->p += n;
  934. }
  935.  
  936. static void
  937. string_appendn (p, s, n)
  938.      string *p;
  939.      const char *s;
  940.      int n;
  941. {
  942.   if (n == 0)
  943.     return;
  944.   string_need (p, n);
  945.   memcpy (p->p, s, n);
  946.   p->p += n;
  947. }
  948.  
  949. static void
  950. string_prepend (p, s)
  951.      string *p;
  952.      const char *s;
  953. {
  954.   if (s == NULL || *s == '\0')
  955.     return;
  956.   string_prependn (p, s, strlen (s));
  957. }
  958.  
  959. #if 0
  960. static void
  961. string_prepends (p, s)
  962.      string *p, *s;
  963. {
  964.   if (s->b == s->p)
  965.     return;
  966.   string_prependn (p, s->b, s->p - s->b);
  967. }
  968. #endif
  969.  
  970. static void
  971. string_prependn (p, s, n)
  972.      string *p;
  973.      const char *s;
  974.      int n;
  975. {
  976.   char *q;
  977.  
  978.   if (n == 0)
  979.     return;
  980.   string_need (p, n);
  981.   for (q = p->p - 1; q >= p->b; q--)
  982.     q[n] = q[0];
  983.   memcpy (p->b, s, n);
  984.   p->p += n;
  985. }
  986.