home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / gdb / cplus-dem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-08  |  19.2 KB  |  997 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 mode)
  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 MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
  35.    Otherwise they are not.
  36.    If MODE >= 0, parameters are emitted; otherwise not.
  37.  
  38.    For example,
  39.    
  40.    cplus_demangle ("foo__1Ai",  0)    => "A::foo(int)"
  41.    cplus_demangle ("foo__1Ai",  1)    => "A::foo(int)"
  42.    cplus_demangle ("foo__1Ai", -1)    => "A::foo"
  43.  
  44.    cplus_demangle ("foo__1Afe",  0)    => "A::foo(float,...)"
  45.    cplus_demangle ("foo__1Afe",  1)    => "A::foo(float,...)"
  46.    cplus_demangle ("foo__1Afe", -1)    => "A::foo"
  47.  
  48.    This file imports xmalloc and xrealloc, which are like malloc and
  49.    realloc except that they generate a fatal error if there is no
  50.    available memory. */
  51.  
  52. /* #define nounderscore 1 /* define this is names don't start with _ */
  53.  
  54. #include <stdio.h>
  55. #include <ctype.h>
  56.  
  57. #ifdef USG
  58. #include <memory.h>
  59. #include <string.h>
  60. #else
  61. #include <strings.h>
  62. #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
  63. #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
  64. #define strchr index 
  65. #define strrchr rindex
  66. #endif
  67.  
  68. #ifndef __STDC__
  69. #define const
  70. #endif
  71.  
  72. #ifdef __STDC__
  73. extern char *cplus_demangle (const char *type, int mode);
  74. #else
  75. extern char *cplus_demangle ();
  76. #endif
  77.  
  78. #ifdef __STDC__
  79. extern char *xmalloc (int);
  80. extern char *xrealloc (char *, int);
  81. #else
  82. extern char *xmalloc ();
  83. extern char *xrealloc ();
  84. #endif
  85.  
  86. static char **typevec = 0;
  87. static int ntypes = 0;
  88. static int typevec_size = 0;
  89.  
  90. static struct {
  91.   const char *in;
  92.   const char *out;
  93. } optable[] = {
  94.   "new", " new",
  95.   "delete", " delete",
  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.   "nop", "",            /* for operator= */
  128. };
  129.  
  130. /* Beware: these aren't '\0' terminated. */
  131.  
  132. typedef struct {
  133.   char *b;            /* pointer to start of string */
  134.   char *p;            /* pointer after last character */
  135.   char *e;            /* pointer after end of allocated space */
  136. } string;
  137.  
  138. #ifdef __STDC__
  139. static void string_need (string *s, int n);
  140. static void string_delete (string *s);
  141. static void string_init (string *s);
  142. static void string_clear (string *s);
  143. static int string_empty (string *s);
  144. static void string_append (string *p, const char *s);
  145. static void string_appends (string *p, string *s);
  146. static void string_appendn (string *p, const char *s, int n);
  147. static void string_prepend (string *p, const char *s);
  148. #if 0
  149. static void string_prepends (string *p, string *s);
  150. #endif
  151. static void string_prependn (string *p, const char *s, int n);
  152. static int get_count (const char **type, int *count);
  153. static int do_args (const char **type, string *decl, int arg_mode);
  154. static int do_type (const char **type, string *result, int arg_mode);
  155. static int do_arg (const char **type, string *result, int arg_mode);
  156. static void munge_function_name (string *name, int arg_mode);
  157. static void remember_type (const char *type, int len);
  158. #else
  159. static void string_need ();
  160. static void string_delete ();
  161. static void string_init ();
  162. static void string_clear ();
  163. static int string_empty ();
  164. static void string_append ();
  165. static void string_appends ();
  166. static void string_appendn ();
  167. static void string_prepend ();
  168. static void string_prepends ();
  169. static void string_prependn ();
  170. static int get_count ();
  171. static int do_args ();
  172. static int do_type ();
  173. static int do_arg ();
  174. static int do_args ();
  175. static void munge_function_name ();
  176. static void remember_type ();
  177. #endif
  178.  
  179. char *
  180. cplus_demangle (type, arg_mode)
  181.      const char *type;
  182.      int arg_mode;
  183. {
  184.   string decl;
  185.   int n;
  186.   int success = 0;
  187.   int constructor = 0;
  188.   int const_flag = 0;
  189.   int i;
  190.   const char *p;
  191. #ifndef LONGERNAMES
  192.   const char *premangle;
  193. #endif
  194.  
  195. # define print_ansi_qualifiers (arg_mode >  0)
  196. # define print_arg_types       (arg_mode >= 0)
  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 "_vt$" */
  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, arg_mode);
  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, arg_mode);
  314.       if (const_flag && print_arg_types)
  315.     string_append (&decl, " const");
  316.       break;
  317.     case 'F':
  318.       p += 1;
  319.       success = do_args (&p, &decl, arg_mode);
  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, arg_mode)
  380.      const char **type;
  381.      string *result;
  382.      int arg_mode;
  383. {
  384.   int n;
  385.   int done;
  386.   int non_empty = 0;
  387.   int success;
  388.   string decl;
  389.   const char *remembered_type;
  390.  
  391.   string_init (&decl);
  392.   string_init (result);
  393.  
  394.   done = 0;
  395.   success = 1;
  396.   while (success && !done)
  397.     {
  398.       int member;
  399.       switch (**type)
  400.     {
  401.     case 'P':
  402.       *type += 1;
  403.       string_prepend (&decl, "*");
  404.       break;
  405.  
  406.     case 'R':
  407.       *type += 1;
  408.       string_prepend (&decl, "&");
  409.       break;
  410.  
  411.     case 'T':
  412.       *type += 1;
  413.       if (!get_count (type, &n) || n >= ntypes)
  414.         success = 0;
  415.       else
  416.         {
  417.           remembered_type = typevec[n];
  418.           type = &remembered_type;
  419.         }
  420.       break;
  421.  
  422.     case 'F':
  423.       *type += 1;
  424.       if (!string_empty (&decl) && decl.b[0] == '*')
  425.         {
  426.           string_prepend (&decl, "(");
  427.           string_append (&decl, ")");
  428.         }
  429.       if (!do_args (type, &decl, arg_mode) || **type != '_')
  430.         success = 0;
  431.       else
  432.         *type += 1;
  433.       break;
  434.  
  435.     case 'M':
  436.     case 'O':
  437.       {
  438.         int constp = 0;
  439.         int volatilep = 0;
  440.  
  441.         member = **type == 'M';
  442.         *type += 1;
  443.         if (!isdigit (**type))
  444.           {
  445.         success = 0;
  446.         break;
  447.           }
  448.         n = 0;
  449.         do
  450.           {
  451.         n *= 10;
  452.         n += **type - '0';
  453.         *type += 1;
  454.           } 
  455.         while (isdigit (**type));
  456.         if (strlen (*type) < n)
  457.           {
  458.         success = 0;
  459.         break;
  460.           }
  461.         string_append (&decl, ")");
  462.         string_prepend (&decl, "::");
  463.         string_prependn (&decl, *type, n);
  464.         string_prepend (&decl, "(");
  465.         *type += n;
  466.         if (member)
  467.           {
  468.         if (**type == 'C')
  469.           {
  470.             *type += 1;
  471.             constp = 1;
  472.           }
  473.         if (**type == 'V')
  474.           {
  475.             *type += 1;
  476.             volatilep = 1;
  477.           }
  478.         if (*(*type)++ != 'F')
  479.           {
  480.             success = 0;
  481.             break;
  482.           }
  483.           }
  484.         if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
  485.           {
  486.         success = 0;
  487.         break;
  488.           }
  489.         *type += 1;
  490.         if (! print_ansi_qualifiers)
  491.           break;
  492.         if (constp)
  493.           {
  494.         if (non_empty)
  495.           string_append (&decl, " ");
  496.         else
  497.           non_empty = 1;
  498.         string_append (&decl, "const");
  499.           }
  500.         if (volatilep)
  501.           {
  502.         if (non_empty)
  503.           string_append (&decl, " ");
  504.         else
  505.           non_empty = 1;
  506.         string_append (&decl, "volatile");
  507.           }
  508.         break;
  509.       }
  510.  
  511.     case 'C':
  512.       if ((*type)[1] == 'P')
  513.         {
  514.           *type += 1;
  515.           if (print_ansi_qualifiers)
  516.         {
  517.           if (!string_empty (&decl))
  518.             string_prepend (&decl, " ");
  519.           string_prepend (&decl, "const");
  520.         }
  521.           break;
  522.         }
  523.  
  524.       /* fall through */
  525.     default:
  526.       done = 1;
  527.       break;
  528.     }
  529.     }
  530.  
  531.   done = 0;
  532.   non_empty = 0;
  533.   while (success && !done)
  534.     {
  535.       switch (**type)
  536.     {
  537.     case 'C':
  538.       *type += 1;
  539.       if (print_ansi_qualifiers)
  540.         {
  541.           if (non_empty)
  542.         string_append (result, " ");
  543.           else
  544.         non_empty = 1;
  545.           string_append (result, "const");
  546.         }
  547.       break;
  548.     case 'U':
  549.       *type += 1;
  550.       if (non_empty)
  551.         string_append (result, " ");
  552.       else
  553.         non_empty = 1;
  554.       string_append (result, "unsigned");
  555.       break;
  556.     case 'V':
  557.       *type += 1;
  558.       if (print_ansi_qualifiers)
  559.         {
  560.           if (non_empty)
  561.         string_append (result, " ");
  562.           else
  563.         non_empty = 1;
  564.           string_append (result, "volatile");
  565.         }
  566.       break;
  567.     default:
  568.       done = 1;
  569.       break;
  570.     }
  571.     }
  572.  
  573.   if (success)
  574.     switch (**type)
  575.       {
  576.       case '\0':
  577.       case '_':
  578.     break;
  579.       case 'v':
  580.     *type += 1;
  581.     if (non_empty)
  582.       string_append (result, " ");
  583.     string_append (result, "void");
  584.     break;
  585.       case 'x':
  586.     *type += 1;
  587.     if (non_empty)
  588.       string_append (result, " ");
  589.     string_append (result, "long long");
  590.     break;
  591.       case 'l':
  592.     *type += 1;
  593.     if (non_empty)
  594.       string_append (result, " ");
  595.     string_append (result, "long");
  596.     break;
  597.       case 'i':
  598.     *type += 1;
  599.     if (non_empty)
  600.       string_append (result, " ");
  601.     string_append (result, "int");
  602.     break;
  603.       case 's':
  604.     *type += 1;
  605.     if (non_empty)
  606.       string_append (result, " ");
  607.     string_append (result, "short");
  608.     break;
  609.       case 'c':
  610.     *type += 1;
  611.     if (non_empty)
  612.       string_append (result, " ");
  613.     string_append (result, "char");
  614.     break;
  615.       case 'r':
  616.     *type += 1;
  617.     if (non_empty)
  618.       string_append (result, " ");
  619.     string_append (result, "long double");
  620.     break;
  621.       case 'd':
  622.     *type += 1;
  623.     if (non_empty)
  624.       string_append (result, " ");
  625.     string_append (result, "double");
  626.     break;
  627.       case 'f':
  628.     *type += 1;
  629.     if (non_empty)
  630.       string_append (result, " ");
  631.     string_append (result, "float");
  632.     break;
  633.       case 'G':
  634.     *type += 1;
  635.     if (!isdigit (**type))
  636.       {
  637.         success = 0;
  638.         break;
  639.       }
  640.     /* fall through */
  641.       case '0':
  642.       case '1':
  643.       case '2':
  644.       case '3':
  645.       case '4':
  646.       case '5':
  647.       case '6':
  648.       case '7':
  649.       case '8':
  650.       case '9':
  651.     n = 0;
  652.     do
  653.       {
  654.         n *= 10;
  655.         n += **type - '0';
  656.         *type += 1;
  657.       }
  658.     while (isdigit (**type));
  659.     if (strlen (*type) < n)
  660.       {
  661.         success = 0;
  662.         break;
  663.       }
  664.     if (non_empty)
  665.       string_append (result, " ");
  666.     string_appendn (result, *type, n);
  667.     *type += n;
  668.     break;
  669.       default:
  670.     success = 0;
  671.     break;
  672.       }
  673.  
  674.   if (success)
  675.     {
  676.       if (!string_empty (&decl))
  677.     {
  678.       string_append (result, " ");
  679.       string_appends (result, &decl);
  680.     }
  681.       string_delete (&decl);
  682.       return 1;
  683.     }
  684.   else
  685.     {
  686.       string_delete (&decl);
  687.       string_delete (result);
  688.       return 0;
  689.     }
  690. }
  691.  
  692. /* `result' will be initialised in do_type; it will be freed on failure */
  693.  
  694. static int
  695. do_arg (type, result, arg_mode)
  696.      const char **type;
  697.      string *result;
  698.      int arg_mode;
  699. {
  700.   const char *start = *type;
  701.  
  702.   if (!do_type (type, result, arg_mode))
  703.     return 0;
  704.   remember_type (start, *type - start);
  705.   return 1;
  706. }
  707.  
  708. static void
  709. remember_type (start, len)
  710.      const char *start;
  711.      int len;
  712. {
  713.   char *tem;
  714.  
  715.   if (ntypes >= typevec_size)
  716.     {
  717.       if (typevec_size == 0)
  718.     {
  719.       typevec_size = 3;
  720.       typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
  721.     }
  722.       else
  723.     {
  724.       typevec_size *= 2;
  725.       typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
  726.     }
  727.     }
  728.   tem = (char *) xmalloc (len + 1);
  729.   memcpy (tem, start, len);
  730.   tem[len] = '\0';
  731.   typevec[ntypes++] = tem;
  732. }
  733.  
  734. /* `decl' must be already initialised, usually non-empty;
  735.    it won't be freed on failure */
  736.  
  737. static int
  738. do_args (type, decl, arg_mode)
  739.      const char **type;
  740.      string *decl;
  741.      int arg_mode;
  742. {
  743.   string arg;
  744.   int need_comma = 0;
  745.  
  746.   if (print_arg_types)
  747.     string_append (decl, "(");
  748.  
  749.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  750.     {
  751.       if (**type == 'N')
  752.     {
  753.       int r;
  754.       int t;
  755.       *type += 1;
  756.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  757.         return 0;
  758.       while (--r >= 0)
  759.         {
  760.           const char *tem = typevec[t];
  761.           if (need_comma && print_arg_types)
  762.         string_append (decl, ", ");
  763.           if (!do_arg (&tem, &arg, arg_mode))
  764.         return 0;
  765.           if (print_arg_types)
  766.         string_appends (decl, &arg);
  767.           string_delete (&arg);
  768.           need_comma = 1;
  769.         }
  770.     }
  771.       else
  772.     {
  773.       if (need_comma & print_arg_types)
  774.         string_append (decl, ", ");
  775.       if (!do_arg (type, &arg, arg_mode))
  776.         return 0;
  777.       if (print_arg_types)
  778.         string_appends (decl, &arg);
  779.       string_delete (&arg);
  780.       need_comma = 1;
  781.     }
  782.     }
  783.  
  784.   if (**type == 'v')
  785.     *type += 1;
  786.   else if (**type == 'e')
  787.     {
  788.       *type += 1;
  789.       if (print_arg_types)
  790.     {
  791.       if (need_comma)
  792.         string_append (decl, ",");
  793.       string_append (decl, "...");
  794.     }
  795.     }
  796.  
  797.   if (print_arg_types)
  798.     string_append (decl, ")");
  799.   return 1;
  800. }
  801.  
  802. static void
  803. munge_function_name (name, arg_mode)
  804.      string *name;
  805.      int arg_mode;
  806. {
  807.   if (!string_empty (name) && name->p - name->b >= 3 
  808.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
  809.     {
  810.       int i;
  811.       /* see if it's an assignment expression */
  812.       if (name->p - name->b >= 10 /* op$assign_ */
  813.       && memcmp (name->b + 3, "assign_", 7) == 0)
  814.     {
  815.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  816.         {
  817.           int len = name->p - name->b - 10;
  818.           if (strlen (optable[i].in) == len
  819.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  820.         {
  821.           string_clear (name);
  822.           string_append (name, "operator");
  823.           string_append (name, optable[i].out);
  824.           string_append (name, "=");
  825.           return;
  826.         }
  827.         }
  828.     }
  829.       else
  830.     {
  831.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  832.         {
  833.           int len = name->p - name->b - 3;
  834.           if (strlen (optable[i].in) == len 
  835.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  836.         {
  837.           string_clear (name);
  838.           string_append (name, "operator");
  839.           string_append (name, optable[i].out);
  840.           return;
  841.         }
  842.         }
  843.     }
  844.       return;
  845.     }
  846.   else if (!string_empty (name) && name->p - name->b >= 5
  847.        && memcmp (name->b, "type$", 5) == 0)
  848.     {
  849.       /* type conversion operator */
  850.       string type;
  851.       const char *tem = name->b + 5;
  852.       if (do_type (&tem, &type, arg_mode))
  853.     {
  854.       string_clear (name);
  855.       string_append (name, "operator ");
  856.       string_appends (name, &type);
  857.       string_delete (&type);
  858.       return;
  859.     }
  860.     }
  861. }
  862.  
  863. /* a mini string-handling package */
  864.  
  865. static void
  866. string_need (s, n)
  867.      string *s;
  868.      int n;
  869. {
  870.   if (s->b == NULL)
  871.     {
  872.       if (n < 32)
  873.     n = 32;
  874.       s->p = s->b = (char *) xmalloc (n);
  875.       s->e = s->b + n;
  876.     }
  877.   else if (s->e - s->p < n)
  878.     {
  879.       int tem = s->p - s->b;
  880.       n += tem;
  881.       n *= 2;
  882.       s->b = (char *) xrealloc (s->b, n);
  883.       s->p = s->b + tem;
  884.       s->e = s->b + n;
  885.     }
  886. }
  887.  
  888. static void
  889. string_delete (s)
  890.      string *s;
  891. {
  892.   if (s->b != NULL)
  893.     {
  894.       free (s->b);
  895.       s->b = s->e = s->p = NULL;
  896.     }
  897. }
  898.  
  899. static void
  900. string_init (s)
  901.      string *s;
  902. {
  903.   s->b = s->p = s->e = NULL;
  904. }
  905.  
  906. static void 
  907. string_clear (s)
  908.      string *s;
  909. {
  910.   s->p = s->b;
  911. }
  912.  
  913. static int
  914. string_empty (s)
  915.      string *s;
  916. {
  917.   return s->b == s->p;
  918. }
  919.  
  920. static void
  921. string_append (p, s)
  922.      string *p;
  923.      const char *s;
  924. {
  925.   int n;
  926.   if (s == NULL || *s == '\0')
  927.     return;
  928.   n = strlen (s);
  929.   string_need (p, n);
  930.   memcpy (p->p, s, n);
  931.   p->p += n;
  932. }
  933.  
  934. static void
  935. string_appends (p, s)
  936.      string *p, *s;
  937. {
  938.   int n;
  939.   if (s->b == s->p)
  940.     return;
  941.   n = s->p - s->b;
  942.   string_need (p, n);
  943.   memcpy (p->p, s->b, n);
  944.   p->p += n;
  945. }
  946.  
  947. static void
  948. string_appendn (p, s, n)
  949.      string *p;
  950.      const char *s;
  951.      int n;
  952. {
  953.   if (n == 0)
  954.     return;
  955.   string_need (p, n);
  956.   memcpy (p->p, s, n);
  957.   p->p += n;
  958. }
  959.  
  960. static void
  961. string_prepend (p, s)
  962.      string *p;
  963.      const char *s;
  964. {
  965.   if (s == NULL || *s == '\0')
  966.     return;
  967.   string_prependn (p, s, strlen (s));
  968. }
  969.  
  970. #if 0
  971. static void
  972. string_prepends (p, s)
  973.      string *p, *s;
  974. {
  975.   if (s->b == s->p)
  976.     return;
  977.   string_prependn (p, s->b, s->p - s->b);
  978. }
  979. #endif
  980.  
  981. static void
  982. string_prependn (p, s, n)
  983.      string *p;
  984.      const char *s;
  985.      int n;
  986. {
  987.   char *q;
  988.  
  989.   if (n == 0)
  990.     return;
  991.   string_need (p, n);
  992.   for (q = p->p - 1; q >= p->b; q--)
  993.     q[n] = q[0];
  994.   memcpy (p->b, s, n);
  995.   p->p += n;
  996. }
  997.