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