home *** CD-ROM | disk | FTP | other *** search
/ M.u.C.S. Disc 2000 / MUCS2000.iso / gnuc / util-41s.lzh / util-41 / cplusdem.c < prev    next >
C/C++ Source or Header  |  1998-09-12  |  29KB  |  1,450 lines

  1. /* Demangler for GNU C++ 
  2.    Copyright (C) 1989, 1992 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.    Modified for g++ 1.95.03 (November 13 verison).  */
  27.  
  28. /* This file exports one function
  29.  
  30.    char *cplus_demangle (const char *name)
  31.  
  32.    If NAME is a mangled function name produced by GNU C++, then
  33.    a pointer to a malloced string giving a C++ representation
  34.    of the name will be returned; otherwise NULL will be returned.
  35.    It is the caller's responsibility to free the string which
  36.    is returned.
  37.  
  38.    For example,
  39.    
  40.    cplus_demangle ("_foo__1Ai")
  41.    
  42.    returns
  43.  
  44.    "A::foo(int)"
  45.  
  46.    This file imports xmalloc and xrealloc, which are like malloc and
  47.    realloc except that they generate a fatal error if there is no
  48.    available memory. */
  49.  
  50. /* #define nounderscore 1 *//* define this is names don't start with _ */
  51.  
  52. #include <stdio.h>
  53. #include <ctype.h>
  54.  
  55. #ifdef USG
  56. #include <memory.h>
  57. #include <string.h>
  58. #else
  59. #include <strings.h>
  60. #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
  61. #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
  62. #define strchr index 
  63. #define strrchr rindex
  64. #endif
  65.  
  66. /* This is '$' on systems where the assembler can deal with that.
  67.    Where the assembler can't, it's '.' (but on many systems '.' is
  68.    used for other things).  */
  69. #if !defined (CPLUS_MARKER)
  70. #define CPLUS_MARKER '$'
  71. #endif
  72.  
  73. #ifndef __STDC__
  74. #define const
  75. #endif
  76.  
  77. #ifdef __STDC__
  78. extern char *cplus_demangle (const char *type);
  79. #else
  80. extern char *cplus_demangle ();
  81. #endif
  82.  
  83. #ifdef __STDC__
  84. extern char *xmalloc (int);
  85. extern char *xrealloc (char *, int);
  86. extern void free (char *);
  87. #else
  88. extern char *xmalloc ();
  89. extern char *xrealloc ();
  90. extern void free ();
  91. #endif
  92.  
  93. static char **typevec = 0;
  94. static int ntypes = 0;
  95. static int typevec_size = 0;
  96.  
  97. static struct {
  98.   const char *in;
  99.   const char *out;
  100. } optable[] = {
  101.   "nw", " new",            /* new (1.92, ansi) */
  102.   "dl", " delete",        /* new (1.92, ansi) */
  103.   "new", " new",        /* old (1.91) */
  104.   "delete", " delete",        /* old (1.91) */
  105.   "ne", "!=",            /* old, ansi */
  106.   "eq", "==",            /* old, ansi */
  107.   "ge", ">=",            /* old, ansi */
  108.   "gt", ">",            /* old, ansi */
  109.   "le", "<=",            /* old, ansi */
  110.   "lt", "<",            /* old, ansi */
  111.   "plus", "+",            /* old */
  112.   "pl", "+",            /* ansi */
  113.   "apl", "+=",            /* ansi */
  114.   "minus", "-",            /* old */
  115.   "mi", "-",            /* ansi */
  116.   "ami", "-=",            /* ansi */
  117.   "mult", "*",            /* old */
  118.   "ml", "*",            /* ansi */
  119.   "aml", "*=",            /* ansi */
  120.   "convert", "+",        /* old (unary +) */
  121.   "negate", "-",        /* old (unary -) */
  122.   "trunc_mod", "%",        /* old */
  123.   "md", "%",            /* ansi */
  124.   "amd", "%=",            /* ansi */
  125.   "trunc_div", "/",        /* old */
  126.   "dv", "/",            /* ansi */
  127.   "adv", "/=",            /* ansi */
  128.   "truth_andif", "&&",        /* old */
  129.   "aa", "&&",            /* ansi */
  130.   "truth_orif", "||",        /* old */
  131.   "oo", "||",            /* ansi */
  132.   "truth_not", "!",        /* old */
  133.   "nt", "!",            /* ansi */
  134.   "postincrement", "++",    /* old */
  135.   "pp", "++",            /* ansi */
  136.   "postdecrement", "--",    /* old */
  137.   "mm", "--",            /* ansi */
  138.   "bit_ior", "|",        /* old */
  139.   "or", "|",            /* ansi */
  140.   "aor", "|=",            /* ansi */
  141.   "bit_xor", "^",        /* old */
  142.   "er", "^",            /* ansi */
  143.   "aer", "^=",            /* ansi */
  144.   "bit_and", "&",        /* old */
  145.   "ad", "&",            /* ansi */
  146.   "aad", "&=",            /* ansi */
  147.   "bit_not", "~",        /* old */
  148.   "co", "~",            /* ansi */
  149.   "call", "()",            /* old */
  150.   "cl", "()",            /* ansi */
  151.   "alshift", "<<",        /* old */
  152.   "ls", "<<",            /* ansi */
  153.   "als", "<<=",            /* ansi */
  154.   "arshift", ">>",        /* old */
  155.   "rs", ">>",            /* ansi */
  156.   "ars", ">>=",            /* ansi */
  157.   "component", "->",        /* old */
  158.   "rf", "->",            /* ansi */
  159.   "indirect", "*",        /* old */
  160.   "method_call", "->()",    /* old */
  161.   "addr", "&",            /* old (unary &) */
  162.   "array", "[]",        /* old */
  163.   "vc", "[]",            /* ansi */
  164.   "compound", ",",        /* old */
  165.   "cm", ",",            /* ansi */
  166.   "nop", "",            /* old (for operator=) */
  167.   "as", "=",            /* ansi */
  168.   "cond", "?:",            /* old */
  169.   "cn", "?:",            /* psuedo-ansi */
  170.   "max", ">?",            /* old */
  171.   "mx", ">?",            /* psuedo-ansi */
  172.   "min", "<?",            /* old */
  173.   "mn", "<?",            /* psuedo-ansi */
  174. };
  175.  
  176. /* Beware: these aren't '\0' terminated. */
  177.  
  178. typedef struct {
  179.   char *b;            /* pointer to start of string */
  180.   char *p;            /* pointer after last character */
  181.   char *e;            /* pointer after end of allocated space */
  182. } string;
  183.  
  184. #ifdef __STDC__
  185. static void string_need (string *s, int n);
  186. static void string_delete (string *s);
  187. static void string_init (string *s);
  188. static void string_clear (string *s);
  189. static int string_empty (string *s);
  190. static void string_append (string *p, const char *s);
  191. static void string_appends (string *p, string *s);
  192. static void string_appendn (string *p, const char *s, int n);
  193. static void string_prepend (string *p, const char *s);
  194. static void string_prepends (string *p, string *s);
  195. static void string_prependn (string *p, const char *s, int n);
  196. static int get_count (const char **type, int *count);
  197. static int do_args (const char **type, string *decl);
  198. static int do_type (const char **type, string *result);
  199. static int do_arg (const char **type, string *result);
  200. static int do_args (const char **type, string *decl);
  201. static int do_cuv_prefix (const char **type, string *result, int *non_empty);
  202. static int do_builtin_type (const char **type, string *result, int *non_empty);
  203. static int do_template_args (const char **type, string *result);
  204. static void munge_function_name (string *name);
  205. static void remember_type (const char *type, int len);
  206. #else
  207. static void string_need ();
  208. static void string_delete ();
  209. static void string_init ();
  210. static void string_clear ();
  211. static int string_empty ();
  212. static void string_append ();
  213. static void string_appends ();
  214. static void string_appendn ();
  215. static void string_prepend ();
  216. static void string_prepends ();
  217. static void string_prependn ();
  218. static int get_count ();
  219. static int do_args ();
  220. static int do_type ();
  221. static int do_arg ();
  222. static int do_args ();
  223. static int do_cuv_prefix ();
  224. static int do_builtin_type ();
  225. static int do_template_args ();
  226. static void munge_function_name ();
  227. static void remember_type ();
  228. #endif
  229.  
  230. int
  231. get_simple_count (type, res)
  232.      char **type;
  233.      int *res;
  234. {
  235.   int n = 0, success = 1;;
  236.   
  237.   if (!isdigit (**type))
  238.     return 0;
  239.   do
  240.     {
  241.       n *= 10;
  242.       n += **type - '0';
  243.       *type += 1;
  244.     } 
  245.   while (isdigit (**type));
  246.   if (strlen (*type) < n)
  247.     {
  248.       success = 0;
  249.     }
  250.  
  251.   *res = n;
  252.   return success;
  253. }
  254.  
  255. char *
  256. cplus_demangle (type)
  257.      const char *type;
  258. {
  259.   string decl;
  260.   int n;
  261.   int success = 0;
  262.   int constructor = 0;
  263.   int destructor = 0;
  264.   int static_type = 0;
  265.   int const_flag = 0;
  266.   int i;
  267.   const char *p;
  268. #ifndef LONGERNAMES
  269.   const char *premangle;
  270. #endif
  271.  
  272.   if (type == NULL || *type == '\0')
  273.     return NULL;
  274. #ifndef nounderscore
  275.   if (*type++ != '_')
  276.     return NULL;
  277. #endif
  278.   p = type;
  279.   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  280.     p++;
  281.   if (*p == '\0')
  282.     {
  283.       /* destructor */
  284.       if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
  285.     {
  286.       destructor = 1;
  287.       p = type;
  288.     }
  289.       /* virtual table "_vt$"  */
  290.       else if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
  291.     {
  292.       if (isdigit (type[4]))
  293.         {
  294.           int n;
  295.           string_init (&decl);
  296.           type += 4;
  297.           while (get_simple_count (&type, &n))
  298.         {
  299.           string_appendn (&decl, type, n);
  300.           type += n;
  301.           if (*type == '\0')
  302.             {
  303.               string_appendn (&decl, " virtual table", 15);
  304.               return decl.b;
  305.             }
  306.           if (*type++ != CPLUS_MARKER)
  307.             break;
  308.           string_append (&decl, "::");
  309.         }
  310.           string_delete (&decl);
  311.           return NULL;
  312.         }
  313.       else
  314.         {
  315.           int n = strlen (type + 4) + 14 + 1;
  316.           char *tem = (char *) xmalloc (n);
  317.           strcpy (tem, type + 4);
  318.           strcat (tem, " virtual table");
  319.           return tem;
  320.         }
  321.     }
  322.       /* static data member */
  323.       else if (type[0] == '_' && strchr ("0123456789Qt", type[1]) != NULL
  324.            && strchr (type, CPLUS_MARKER) != NULL)
  325.     {
  326.       static_type = 1;
  327.       p = type + 1;
  328.     }
  329.       else return NULL;
  330.     }
  331.  
  332.   string_init (&decl);
  333.  
  334.   if (static_type)
  335.     {
  336.       if (!isdigit (p[0]) && ('t' != p[0]))
  337.     {
  338.       string_delete (&decl);
  339.       return NULL;
  340.     }
  341.     }
  342.   else if (destructor)
  343.     {
  344.       if (!isdigit (p[3])&& ('t' != p[3]))
  345.     {
  346.       string_delete (&decl);
  347.       return NULL;
  348.     }
  349.       p += 3;
  350.     }
  351.   else if (p == type)
  352.     {
  353.       if (!isdigit (p[2]) && ('t' != p[2]))
  354.     {
  355.       p += 1;
  356.       while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  357.         p++;
  358.       string_appendn (&decl, type, p - type);      
  359.       string_appendn (&decl, "", 1);
  360.       munge_function_name (&decl);
  361.       if (decl.b[0] == '_')
  362.         decl.p--;
  363.       p += 2;
  364.     }
  365.       else
  366.     {
  367.       constructor = 1;
  368.       p += 2;
  369.     }
  370.     }
  371.   else
  372.     {
  373.       string_appendn (&decl, type, p - type);
  374.       decl.p[0] = '\0';
  375.       munge_function_name (&decl);
  376.       p += 2;
  377.     }
  378.  
  379. #ifndef LONGERNAMES
  380.   premangle = p;
  381. #endif
  382.   switch (*p)
  383.     {
  384.     case 'C':
  385.       /* a const member function */
  386.       p += 1;
  387.       const_flag = 1;
  388.       if (*p == 't')
  389.     goto template;
  390.       if (!isdigit (*p))
  391.     {
  392.       string_delete (&decl);
  393.       return NULL;
  394.     }
  395.       /* fall through */
  396.     case '0':
  397.     case '1':
  398.     case '2':
  399.     case '3':
  400.     case '4':
  401.     case '5':
  402.     case '6':
  403.     case '7':
  404.     case '8':
  405.     case '9':
  406.       n = 0;
  407.       do
  408.     {
  409.       n *= 10;
  410.       n += *p - '0';
  411.       p += 1;
  412.     }
  413.       while (isdigit (*p));
  414.       if (strlen (p) < n)
  415.     {
  416.       string_delete (&decl);
  417.       return NULL;
  418.     }
  419.       if (constructor || destructor)
  420.     {
  421.       string_appendn (&decl, p, n);
  422.       string_append (&decl, "::");
  423.       if (destructor)
  424.         string_append(&decl, "~");
  425.       string_appendn (&decl, p, n);
  426.     }
  427.       else
  428.     {
  429.       string_prepend (&decl, "::");
  430.       string_prependn (&decl, p, n);
  431.     }
  432.       p += n;
  433. #ifndef LONGERNAMES
  434.       remember_type (premangle, p - premangle);
  435. #endif
  436.       if (static_type)
  437.     {
  438.       string_append(&decl, p+1);
  439.       p += strlen(p);
  440.       success = 1;
  441.     }
  442.       else
  443.     success = do_args (&p, &decl);
  444.       if (const_flag)
  445.     string_append (&decl, " const");
  446.       break;
  447.     case 'F':
  448.       p += 1;
  449.       success = do_args (&p, &decl);
  450.       break;
  451.     /* template additions */
  452.     case 't':
  453.     template:
  454.       p += 1;
  455.       {
  456.     int r;
  457.     string tname;
  458.     string trawname;
  459.     
  460.     string_init(&tname);
  461.     string_init(&trawname);
  462.  
  463.     /* get template name */
  464.     if (!get_simple_count (&p, &r))
  465.       {
  466.         success = 0;
  467.         break;
  468.       }
  469.     string_appendn (&tname, p, r);
  470.     string_appendn (&trawname, p, r);
  471.     p += r;
  472.     string_append (&tname, "<");
  473.     success = do_template_args (&p, &tname);
  474.     if (!success)
  475.       {
  476.         string_delete (&tname);
  477.         string_delete (&trawname);
  478.         break;
  479.       }
  480.     if (tname.p[-1] == '>')
  481.       string_append (&tname, " ");
  482.     string_append (&tname, ">::");
  483.     if (destructor)
  484.       string_append(&tname, "~");
  485.     if (constructor || destructor)
  486.       string_appends (&tname, &trawname);
  487.     string_delete(&trawname);
  488.  
  489.     if (!success) {
  490.       string_delete(&tname);
  491.       return 0;
  492.     }
  493.     string_prepends (&decl, &tname);
  494.     string_delete (&tname);
  495.  
  496.     if (static_type)
  497.       {
  498.         string_append (&decl, p+1);
  499.         p += strlen (p);
  500.         success = 1;
  501.       }
  502.     else
  503.       success = do_args (&p, &decl);
  504.     if (const_flag)
  505.       string_append (&decl, " const");
  506.       }
  507.       break;
  508.     }
  509.  
  510.   for (i = 0; i < ntypes; i++)
  511.     if (typevec[i] != NULL)
  512.       free (typevec[i]);
  513.   ntypes = 0;
  514.   if (typevec != NULL)
  515.     {
  516.       free ((char *)typevec);
  517.       typevec = NULL;
  518.       typevec_size = 0;
  519.     }
  520.  
  521.   if (success)
  522.     {
  523.       string_appendn (&decl, "", 1);
  524.       return decl.b;
  525.     }
  526.   else
  527.     {
  528.       string_delete (&decl);
  529.       return NULL;
  530.     }
  531. }
  532.  
  533. static int
  534. get_count (type, count)
  535.      const char **type;
  536.      int *count;
  537. {
  538.   if (!isdigit (**type))
  539.     return 0;
  540.   *count = **type - '0';
  541.   *type += 1;
  542.   /* see flush_repeats in cp-method.c */
  543.   if (isdigit (**type))
  544.     {
  545.       const char *p = *type;
  546.       int n = *count;
  547.       do 
  548.     {
  549.       n *= 10;
  550.       n += *p - '0';
  551.       p += 1;
  552.     } 
  553.       while (isdigit (*p));
  554.       if (*p == '_')
  555.     {
  556.       *type = p + 1;
  557.       *count = n;
  558.     }
  559.     }
  560.   return 1;
  561. }
  562.  
  563. /* result will be initialised here; it will be freed on failure */
  564.  
  565. static int
  566. do_type (type, result)
  567.      const char **type;
  568.      string *result;
  569. {
  570.   int n;
  571.   int done;
  572.   int non_empty = 0;
  573.   int success;
  574.   string decl;
  575.   const char *remembered_type;
  576.  
  577.   string_init (&decl);
  578.   string_init (result);
  579.  
  580.   done = 0;
  581.   success = 1;
  582.   while (success && !done)
  583.     {
  584.       int member;
  585.       switch (**type)
  586.     {
  587.     case 'P':
  588.       *type += 1;
  589.       string_prepend (&decl, "*");
  590.       break;
  591.  
  592.     case 'R':
  593.       *type += 1;
  594.       string_prepend (&decl, "&");
  595.       break;
  596.  
  597.     case 'T':
  598.       *type += 1;
  599.       if (!get_count (type, &n) || n >= ntypes)
  600.         success = 0;
  601.       else
  602.         {
  603.           remembered_type = typevec[n];
  604.           type = &remembered_type;
  605.         }
  606.       break;
  607.  
  608.     case 'F':
  609.       *type += 1;
  610.       if (!string_empty (&decl) && decl.b[0] == '*')
  611.         {
  612.           string_prepend (&decl, "(");
  613.           string_append (&decl, ")");
  614.         }
  615.       if (!do_args (type, &decl) || **type != '_')
  616.         success = 0;
  617.       else
  618.         *type += 1;
  619.       break;
  620.  
  621.     case 'M':
  622.     case 'O':
  623.       {
  624.         int constp = 0;
  625.         int volatilep = 0;
  626.  
  627.         member = **type == 'M';
  628.         *type += 1;
  629.         if (!get_simple_count (type, &n))
  630.           {
  631.         success = 0;
  632.         break;
  633.           }
  634.         string_append (&decl, ")");
  635.         string_prepend (&decl, "::");
  636.         string_prependn (&decl, *type, n);
  637.         string_prepend (&decl, "(");
  638.         *type += n;
  639.         if (member)
  640.           {
  641.         if (**type == 'C')
  642.           {
  643.             *type += 1;
  644.             constp = 1;
  645.           }
  646.         if (**type == 'V')
  647.           {
  648.             *type += 1;
  649.             volatilep = 1;
  650.           }
  651.         if (*(*type)++ != 'F')
  652.           {
  653.             success = 0;
  654.             break;
  655.           }
  656.           }
  657.         if ((member && !do_args (type, &decl)) || **type != '_')
  658.           {
  659.         success = 0;
  660.         break;
  661.           }
  662.         *type += 1;
  663.         if (constp)
  664.           {
  665.         if (non_empty)
  666.           string_append (&decl, " ");
  667.         else
  668.           non_empty = 1;
  669.         string_append (&decl, "const");
  670.           }
  671.         if (volatilep)
  672.           {
  673.         if (non_empty)
  674.           string_append (&decl, " ");
  675.         else
  676.           non_empty = 1;
  677.         string_append (&decl, "volatile");
  678.           }
  679.         break;
  680.       }
  681.  
  682.     case 'C':
  683.       if ((*type)[1] == 'P')
  684.         {
  685.           *type += 1;
  686.           if (!string_empty (&decl))
  687.         string_prepend (&decl, " ");
  688.           string_prepend (&decl, "const");
  689.           break;
  690.         }
  691.  
  692.       /* fall through */
  693.     default:
  694.       done = 1;
  695.       break;
  696.     }
  697.     }
  698.  
  699.   non_empty = 0;
  700.   if (success)
  701.     success = do_cuv_prefix (type, result, &non_empty);
  702.  
  703.   if (success)
  704.     success = do_builtin_type(type, result, &non_empty);
  705.   
  706.   if (success)
  707.     {
  708.       if (!string_empty (&decl))
  709.     {
  710.       string_append (result, " ");
  711.       string_appends (result, &decl);
  712.     }
  713.       string_delete (&decl);
  714.       return 1;
  715.     }
  716.   else
  717.     {
  718.       string_delete (&decl);
  719.       string_delete (result);
  720.       return 0;
  721.     }
  722. }
  723.  
  724. static int
  725. do_cuv_prefix (type, result, non_empty)
  726.      const char **type;
  727.      string* result;
  728.      int* non_empty;
  729. {
  730.   int success = 1;
  731.   int done = 0;
  732.   
  733.   while (success && !done)
  734.     {
  735.       switch (**type)
  736.     {
  737.     case 'C':
  738.       *type += 1;
  739.       if (*non_empty)
  740.         string_append (result, " ");
  741.       else
  742.         *non_empty = 1;
  743.       string_append (result, "const");
  744.       break;
  745.     case 'U':
  746.       *type += 1;
  747.       if (*non_empty)
  748.         string_append (result, " ");
  749.       else
  750.         *non_empty = 1;
  751.       string_append (result, "unsigned");
  752.       break;
  753.     case 'S':
  754.       *type += 1;
  755.       if (*non_empty)
  756.         string_append (result, " ");
  757.       else
  758.         *non_empty = 1;
  759.       string_append (result, "signed");
  760.       break;
  761.     case 'V':
  762.       *type += 1;
  763.       if (*non_empty)
  764.         string_append (result, " ");
  765.       else
  766.         *non_empty = 1;
  767.       string_append (result, "volatile");
  768.       break;
  769.     default:
  770.       done = 1;
  771.       break;
  772.     }
  773.     }
  774.   return success;
  775. }
  776.  
  777. static int
  778. do_builtin_type (type, result, non_empty)
  779.      const char **type;
  780.      string* result;
  781.      int *non_empty;
  782. {
  783.   int success = 1;
  784.   int n;
  785.   
  786.   switch (**type)
  787.     {
  788.     case '\0':
  789.     case '_':
  790.       break;
  791.     case 'v':
  792.       *type += 1;
  793.       if (*non_empty)
  794.     string_append (result, " ");
  795.       string_append (result, "void");
  796.       break;
  797.     case 'x':
  798.       *type += 1;
  799.       if (*non_empty)
  800.     string_append (result, " ");
  801.       string_append (result, "long long");
  802.       break;
  803.     case 'l':
  804.       *type += 1;
  805.       if (*non_empty)
  806.     string_append (result, " ");
  807.       string_append (result, "long");
  808.       break;
  809.     case 'i':
  810.       *type += 1;
  811.       if (*non_empty)
  812.     string_append (result, " ");
  813.       string_append (result, "int");
  814.       break;
  815.     case 's':
  816.       *type += 1;
  817.       if (*non_empty)
  818.     string_append (result, " ");
  819.       string_append (result, "short");
  820.       break;
  821.     case 'c':
  822.       *type += 1;
  823.       if (*non_empty)
  824.     string_append (result, " ");
  825.       string_append (result, "char");
  826.       break;
  827.     case 'w':
  828.       *type += 1;
  829.       if (*non_empty)
  830.     string_append (result, " ");
  831.       string_append (result, "wchar_t");
  832.       break;
  833.     case 'r':
  834.       *type += 1;
  835.       if (*non_empty)
  836.     string_append (result, " ");
  837.       string_append (result, "long double");
  838.       break;
  839.     case 'd':
  840.       *type += 1;
  841.       if (*non_empty)
  842.     string_append (result, " ");
  843.       string_append (result, "double");
  844.       break;
  845.     case 'f':
  846.       *type += 1;
  847.       if (*non_empty)
  848.     string_append (result, " ");
  849.       string_append (result, "float");
  850.       break;
  851.     case 'G':
  852.       *type += 1;
  853.       if (!isdigit (**type))
  854.     {
  855.       success = 0;
  856.       break;
  857.     }
  858.       /* fall through */
  859.     case '0':
  860.     case '1':
  861.     case '2':
  862.     case '3':
  863.     case '4':
  864.     case '5':
  865.     case '6':
  866.     case '7':
  867.     case '8':
  868.     case '9':
  869.       n = 0;
  870.       do
  871.     {
  872.       n *= 10;
  873.       n += **type - '0';
  874.       *type += 1;
  875.     }
  876.       while (isdigit (**type));
  877.       if (strlen (*type) < n)
  878.     {
  879.       success = 0;
  880.       break;
  881.     }
  882.       if (*non_empty)
  883.     string_append (result, " ");
  884.       string_appendn (result, *type, n);
  885.       *type += n;
  886.       break;
  887.     case 't':
  888.       *type += 1;
  889.       /* get template name */
  890.       if (!get_simple_count (type, &n))
  891.     {
  892.       success = 0;
  893.       break;
  894.     }
  895.       if (*non_empty)
  896.     string_append (result, " ");
  897.       string_appendn (result, *type, n);
  898.       *type += n;
  899.       string_append (result, "<");
  900.       if (!do_template_args (type, result))
  901.     success = 0;
  902.       else
  903.     {
  904.       if (result->p[-1] == '>')
  905.         string_append (result, " ");
  906.       string_append (result, ">");
  907.     }
  908.       break;
  909.     case 'Q':
  910.       n = (*type)[1] - '0';
  911.       if (n < 0 || n > 9)
  912.     {
  913.       success = 0;
  914.       break;
  915.     }
  916.       *type += 2;
  917.       if (n > 0)
  918.     {
  919.       string temp;
  920.       if (!do_type (type, &temp))
  921.         {
  922.           success = 0;
  923.           break;
  924.         }
  925.       if (*non_empty)
  926.         string_append (result, " ");
  927.       string_appends (result, &temp);
  928.       string_delete (&temp);
  929.       while (--n > 0)
  930.         {
  931.           if (!do_type (type, &temp))
  932.         {
  933.           success = 0;
  934.           break;
  935.         }
  936.           string_append (result, "::");
  937.           string_appends (result, &temp);
  938.           string_delete (&temp);
  939.         }
  940.     }
  941.       break;
  942.       
  943.     default:
  944.       success = 0;
  945.       break;
  946.     }
  947.   return success;
  948. }
  949.  
  950. static int
  951. do_template_args (type, result)
  952.      const char **type;
  953.      string *result;
  954. {
  955.   int r, i;
  956.  
  957.   string temp;
  958.   int need_comma = 0;
  959.   int success;
  960.  
  961.   /* get size of template parameter list */
  962.   if (!get_count (type, &r))
  963.     return 0;
  964.   success = 1;
  965.   for (i = 0; i < r; i++)
  966.     {
  967.       if (need_comma)
  968.     string_append (result, ", ");
  969.       /* Z for type parameters */
  970.       if (**type == 'Z')
  971.     {
  972.       *type += 1;
  973.  
  974.       success = do_arg (type, &temp);
  975.       if (success)
  976.         string_appends (result, &temp);
  977.       string_delete(&temp);
  978.       if (!success)
  979.         break;
  980.     }
  981.       /* otherwise, value parameter */
  982.       else
  983.     {
  984.       const char *old_p  = *type;
  985.       int is_pointer = 0;
  986.       int is_real = 0;
  987.       int is_integral = 0;
  988.       int done = 0;
  989.  
  990.       success = do_arg (type, &temp);
  991.       if (success)
  992.         string_appends (result, &temp);
  993.       string_delete(&temp);
  994.       if (!success)
  995.         break;
  996.       string_append (result, "=");
  997.       while (*old_p && !done)
  998.         {    
  999.           switch (*old_p)
  1000.         {
  1001.         case 'P':
  1002.         case 'R':
  1003.           done = is_pointer = 1;
  1004.           break;
  1005.         case 'C':    /* const */
  1006.         case 'U':    /* unsigned */
  1007.         case 'V':    /* volatile */
  1008.         case 'F':    /* function */
  1009.         case 'M':    /* member function */
  1010.         case 'O':    /* ??? */
  1011.           old_p++;
  1012.           continue;
  1013.         case 'Q':    /* repetition of following */
  1014.         case 'T':    /* remembered type */
  1015.           abort();
  1016.           break;
  1017.         case 'v':    /* void */
  1018.           abort();
  1019.           break;
  1020.         case 'x':    /* long long */
  1021.         case 'l':    /* long */
  1022.         case 'i':    /* int */
  1023.         case 's':    /* short */
  1024.         case 'c':    /* char */
  1025.         case 'w': /* wchar_t */
  1026.           done = is_integral = 1;
  1027.           break;
  1028.         case 'r':    /* long double */
  1029.         case 'd':    /* double */
  1030.         case 'f':    /* float */
  1031.           done = is_real = 1;
  1032.           break;
  1033.         default:
  1034.           abort();
  1035.         }
  1036.         }
  1037.       if (is_integral)
  1038.         {
  1039.           if (**type == 'm')
  1040.         {
  1041.           string_appendn (result, "-", 1);
  1042.           (*type)++;
  1043.         }
  1044.           while (isdigit (**type))    
  1045.         {
  1046.           string_appendn (result, *type, 1);
  1047.           (*type)++;
  1048.         }
  1049.         }
  1050.       else if (is_real)
  1051.         {
  1052.           if (**type == 'm')
  1053.         {
  1054.           string_appendn (result, "-", 1);
  1055.           (*type)++;
  1056.         }
  1057.           while (isdigit (**type))    
  1058.         {
  1059.           string_appendn (result, *type, 1);
  1060.           (*type)++;
  1061.         }
  1062.           if (**type == '.')    /* fraction */
  1063.         {
  1064.           string_appendn (result, ".", 1);
  1065.           (*type)++;
  1066.           while (isdigit (**type))    
  1067.             {
  1068.               string_appendn (result, *type, 1);
  1069.               (*type)++;
  1070.             }
  1071.         }
  1072.           if (**type == 'e')    /* exponent */
  1073.         {
  1074.           string_appendn (result, "e", 1);
  1075.           (*type)++;
  1076.           while (isdigit (**type))    
  1077.             {
  1078.               string_appendn (result, *type, 1);
  1079.               (*type)++;
  1080.             }
  1081.         }
  1082.         }
  1083.       else if (is_pointer)
  1084.         {
  1085.           int symbol_len;
  1086.  
  1087.           if (!get_count (type, &symbol_len))
  1088.         {
  1089.           success = 0;
  1090.           break;
  1091.         }
  1092.           string_appendn (result, *type, symbol_len);
  1093.           *type += symbol_len;
  1094.         }
  1095.     }
  1096.       need_comma = 1;
  1097.     }
  1098.     return success;
  1099.  
  1100. }
  1101.  
  1102. /* `result' will be initialised in do_type; it will be freed on failure */
  1103.  
  1104. static int
  1105. do_arg (type, result)
  1106.      const char **type;
  1107.      string *result;
  1108. {
  1109.   const char *start = *type;
  1110.  
  1111.   if (!do_type (type, result))
  1112.     return 0;
  1113.   remember_type (start, *type - start);
  1114.   return 1;
  1115. }
  1116.  
  1117. static void
  1118. remember_type (start, len)
  1119.      const char *start;
  1120.      int len;
  1121. {
  1122.   char *tem;
  1123.  
  1124.   if (ntypes >= typevec_size)
  1125.     {
  1126.       if (typevec_size == 0)
  1127.     {
  1128.       typevec_size = 3;
  1129.       typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
  1130.     }
  1131.       else
  1132.     {
  1133.       typevec_size *= 2;
  1134.       typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
  1135.     }
  1136.     }
  1137.   tem = (char *) xmalloc (len + 1);
  1138.   memcpy (tem, start, len);
  1139.   tem[len] = '\0';
  1140.   typevec[ntypes++] = tem;
  1141. }
  1142.  
  1143. /* `decl' must be already initialised, usually non-empty;
  1144.    it won't be freed on failure */
  1145.  
  1146. static int
  1147. do_args (type, decl)
  1148.      const char **type;
  1149.      string *decl;
  1150. {
  1151.   string arg;
  1152.   int need_comma = 0;
  1153.  
  1154.   string_append (decl, "(");
  1155.  
  1156.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  1157.     {
  1158.       if (**type == 'N')
  1159.     {
  1160.       int r;
  1161.       int t;
  1162.       *type += 1;
  1163.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  1164.         return 0;
  1165.       while (--r >= 0)
  1166.         {
  1167.           const char *tem = typevec[t];
  1168.           if (need_comma)
  1169.         string_append (decl, ", ");
  1170.           if (!do_arg (&tem, &arg))
  1171.         return 0;
  1172.           string_appends (decl, &arg);
  1173.           string_delete (&arg);
  1174.           need_comma = 1;
  1175.         }
  1176.     }
  1177.       else
  1178.     {
  1179.       if (need_comma)
  1180.         string_append (decl, ", ");
  1181.       if (!do_arg (type, &arg))
  1182.         return 0;
  1183.       string_appends (decl, &arg);
  1184.       string_delete (&arg);
  1185.       need_comma = 1;
  1186.     }
  1187.     }
  1188.  
  1189.   if (**type == 'v')
  1190.     *type += 1;
  1191.   else if (**type == 'e')
  1192.     {
  1193.       *type += 1;
  1194.       if (need_comma)
  1195.     string_append (decl, ",");
  1196.       string_append (decl, "...");
  1197.     }
  1198.  
  1199.   string_append (decl, ")");
  1200.   return 1;
  1201. }
  1202.  
  1203. static void
  1204. munge_function_name (name)
  1205.      string *name;
  1206. {
  1207.   if (string_empty (name))
  1208.     return;
  1209.  
  1210.   if (name->p - name->b >= 3 
  1211.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
  1212.     {
  1213.       int i;
  1214.       /* see if it's an assignment expression */
  1215.       if (name->p - name->b >= 10 /* op$assign_ */
  1216.       && memcmp (name->b + 3, "assign_", 7) == 0)
  1217.     {
  1218.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1219.         {
  1220.           int len = name->p - name->b - 10;
  1221.           if (strlen (optable[i].in) == len
  1222.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  1223.         {
  1224.           string_clear (name);
  1225.           string_append (name, "operator");
  1226.           string_append (name, optable[i].out);
  1227.           string_append (name, "=");
  1228.           return;
  1229.         }
  1230.         }
  1231.     }
  1232.       else
  1233.     {
  1234.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1235.         {
  1236.           int len = name->p - name->b - 3;
  1237.           if (strlen (optable[i].in) == len 
  1238.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  1239.         {
  1240.           string_clear (name);
  1241.           string_append (name, "operator");
  1242.           string_append (name, optable[i].out);
  1243.           return;
  1244.         }
  1245.         }
  1246.     }
  1247.       return;
  1248.     }
  1249.   else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0)
  1250.     {
  1251.       /* type conversion operator */
  1252.       string type;
  1253.       const char *tem = name->b + 5;
  1254.       if (do_type (&tem, &type))
  1255.     {
  1256.       string_clear (name);
  1257.       string_append (name, "operator ");
  1258.       string_appends (name, &type);
  1259.       string_delete (&type);
  1260.       return;
  1261.     }
  1262.     }
  1263.   /* ANSI.  */
  1264.   else if (name->b[2] == 'o' && name->b[3] == 'p')
  1265.     {
  1266.       /* type conversion operator.  */
  1267.       string type;
  1268.       const char *tem = name->b + 4;
  1269.       if (do_type (&tem, &type))
  1270.     {
  1271.       string_clear (name);
  1272.       string_append (name, "operator ");
  1273.       string_appends (name, &type);
  1274.       string_delete (&type);
  1275.       return;
  1276.     }
  1277.     }
  1278.   else if (name->b[2] >= 'a' && name->b[2] <= 'z'
  1279.        && name->b[3] >= 'a' && name->b[3] <= 'z')
  1280.     {
  1281.       int i;
  1282.  
  1283.       if (name->b[4] == '\0')
  1284.     {
  1285.       /* Operator.  */
  1286.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1287.         {
  1288.           if (strlen (optable[i].in) == 2
  1289.           && memcmp (optable[i].in, name->b + 2, 2) == 0)
  1290.         {
  1291.           string_clear (name);
  1292.           string_append (name, "operator");
  1293.           string_append (name, optable[i].out);
  1294.           return;
  1295.         }
  1296.         }
  1297.     }
  1298.       else
  1299.     {
  1300.       if (name->b[2] != 'a' || name->b[5] != '\0')
  1301.         return;
  1302.       /* Assignment.  */
  1303.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  1304.         {
  1305.           if (strlen (optable[i].in) == 3
  1306.           && memcmp (optable[i].in, name->b + 2, 3) == 0)
  1307.         {
  1308.           string_clear (name);
  1309.           string_append (name, "operator");
  1310.           string_append (name, optable[i].out);
  1311.           return;
  1312.         }
  1313.         }
  1314.     }
  1315.     }
  1316. }
  1317.  
  1318. /* a mini string-handling package */
  1319.  
  1320. static void
  1321. string_need (s, n)
  1322.      string *s;
  1323.      int n;
  1324. {
  1325.   if (s->b == NULL)
  1326.     {
  1327.       if (n < 32)
  1328.     n = 32;
  1329.       s->p = s->b = (char *) xmalloc (n);
  1330.       s->e = s->b + n;
  1331.     }
  1332.   else if (s->e - s->p < n)
  1333.     {
  1334.       int tem = s->p - s->b;
  1335.       n += tem;
  1336.       n *= 2;
  1337.       s->b = (char *) xrealloc (s->b, n);
  1338.       s->p = s->b + tem;
  1339.       s->e = s->b + n;
  1340.     }
  1341. }
  1342.  
  1343. static void
  1344. string_delete (s)
  1345.      string *s;
  1346. {
  1347.   if (s->b != NULL)
  1348.     {
  1349.       free (s->b);
  1350.       s->b = s->e = s->p = NULL;
  1351.     }
  1352. }
  1353.  
  1354. static void
  1355. string_init (s)
  1356.      string *s;
  1357. {
  1358.   s->b = s->p = s->e = NULL;
  1359. }
  1360.  
  1361. static void 
  1362. string_clear (s)
  1363.      string *s;
  1364. {
  1365.   s->p = s->b;
  1366. }
  1367.  
  1368. static int
  1369. string_empty (s)
  1370.      string *s;
  1371. {
  1372.   return s->b == s->p;
  1373. }
  1374.  
  1375. static void
  1376. string_append (p, s)
  1377.      string *p;
  1378.      const char *s;
  1379. {
  1380.   int n;
  1381.   if (s == NULL || *s == '\0')
  1382.     return;
  1383.   n = strlen (s);
  1384.   string_need (p, n);
  1385.   memcpy (p->p, s, n);
  1386.   p->p += n;
  1387. }
  1388.  
  1389. static void
  1390. string_appends (p, s)
  1391.      string *p, *s;
  1392. {
  1393.   int n;
  1394.   if (s->b == s->p)
  1395.     return;
  1396.   n = s->p - s->b;
  1397.   string_need (p, n);
  1398.   memcpy (p->p, s->b, n);
  1399.   p->p += n;
  1400. }
  1401.  
  1402. static void
  1403. string_appendn (p, s, n)
  1404.      string *p;
  1405.      const char *s;
  1406.      int n;
  1407. {
  1408.   if (n == 0)
  1409.     return;
  1410.   string_need (p, n);
  1411.   memcpy (p->p, s, n);
  1412.   p->p += n;
  1413. }
  1414.  
  1415. static void
  1416. string_prepend (p, s)
  1417.      string *p;
  1418.      const char *s;
  1419. {
  1420.   if (s == NULL || *s == '\0')
  1421.     return;
  1422.   string_prependn (p, s, strlen (s));
  1423. }
  1424.  
  1425. static void
  1426. string_prepends (p, s)
  1427.      string *p, *s;
  1428. {
  1429.   if (s->b == s->p)
  1430.     return;
  1431.   string_prependn (p, s->b, s->p - s->b);
  1432. }
  1433.  
  1434. static void
  1435. string_prependn (p, s, n)
  1436.      string *p;
  1437.      const char *s;
  1438.      int n;
  1439. {
  1440.   char *q;
  1441.  
  1442.   if (n == 0)
  1443.     return;
  1444.   string_need (p, n);
  1445.   for (q = p->p - 1; q >= p->b; q--)
  1446.     q[n] = q[0];
  1447.   memcpy (p->b, s, n);
  1448.   p->p += n;
  1449. }
  1450.