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