home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / gcc-2.4.5 / cp-dem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-01  |  26.4 KB  |  1,362 lines

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