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