string_appendn (tname, *mangled, symbol_len);
if (symbol_len == 0) string_appendn (tname, "0", 1); else { char *p = xmalloc (symbol_len + 1), *q; strncpy (p, *mangled, symbol_len); p [symbol_len] = '\0'; q = cplus_demangle (p, work->options); string_appendn (tname, "&", 1); if (q) { string_append (tname, q); free (q); } else string_append (tname, p); free (p); }
demangle_template (work, mangled, tname, trawname)     struct work_stuff *work;     const char **mangled;     string *tname;     string *trawname;{  int i;  int is_pointer;  int is_real;  int is_integral;  int is_char;  int is_bool;  int r;  int need_comma = 0;  int success = 0;  int done;  const char *old_p;  const char *start;  int symbol_len;  string temp;  (*mangled)++;  start = *mangled;  /* get template name */  if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)    {      return (0);    }  if (trawname)    string_appendn (trawname, *mangled, r);  string_appendn (tname, *mangled, r);  *mangled += r;  string_append (tname, "<");  /* get size of template parameter list */  if (!get_count (mangled, &r))    {      return (0);    }  for (i = 0; i < r; i++)    {      if (need_comma)	{	  string_append (tname, ", ");	}      /* Z for type parameters */      if (**mangled == 'Z')	{	  (*mangled)++;	  /* temp is initialized in do_type */	  success = do_type (work, mangled, &temp);	  if (success)	    {	      string_appends (tname, &temp);	    }	  string_delete(&temp);	  if (!success)	    {	      break;	    }	}      else	{	  /* otherwise, value parameter */	  old_p  = *mangled;	  is_pointer = 0;	  is_real = 0;	  is_integral = 0;          is_char = 0;	  done = 0;	  /* temp is initialized in do_type */	  success = do_type (work, mangled, &temp);/*	  if (success)	    {	      string_appends (tname, &temp);	    }*/	  string_delete(&temp);	  if (!success)	    {	      break;	    }/*	  string_append (tname, "=");*/	  while (*old_p && !done)	    {		      switch (*old_p)		{		  case 'P':		  case 'p':		  case 'R':		    done = is_pointer = 1;		    break;		  case 'C':	/* const */		  case 'S':	/* explicitly signed [char] */		  case 'U':	/* unsigned */		  case 'V':	/* volatile */		  case 'F':	/* function */		  case 'M':	/* member function */		  case 'O':	/* ??? */		    old_p++;		    continue;		  case 'Q':	/* qualified name */                    done = is_integral = 1;                    break;		  case 'T':	/* remembered type */		    abort ();		    break;		  case 'v':	/* void */		    abort ();		    break;		  case 'x':	/* long long */		  case 'l':	/* long */		  case 'i':	/* int */		  case 's':	/* short */		  case 'w':	/* wchar_t */		    done = is_integral = 1;		    break;		  case 'b':	/* bool */		    done = is_bool = 1;		    break;		  case 'c':	/* char */		    done = is_char = 1;		    break;		  case 'r':	/* long double */		  case 'd':	/* double */		  case 'f':	/* float */		    done = is_real = 1;		    break;		  default:		    /* it's probably user defined type, let's assume		       it's integral, it seems hard to figure out		       what it really is */		    done = is_integral = 1;		}	    }	  if (is_integral)	    {	      if (**mangled == 'm')		{		  string_appendn (tname, "-", 1);		  (*mangled)++;		}	      while (isdigit (**mangled))			{		  string_appendn (tname, *mangled, 1);		  (*mangled)++;		}	    }	  else if (is_char)	    {            char tmp[2];            int val;              if (**mangled == 'm')                {                  string_appendn (tname, "-", 1);                  (*mangled)++;                }	      string_appendn (tname, "'", 1);              val = consume_count(mangled);	      if (val == 0)		{		  success = 0;		  break;                }              tmp[0] = (char)val;              tmp[1] = '\0';              string_appendn (tname, &tmp[0], 1);	      string_appendn (tname, "'", 1);	    }	  else if (is_bool)	    {	      int val = consume_count (mangled);	      if (val == 0)		string_appendn (tname, "false", 5);	      else if (val == 1)		string_appendn (tname, "true", 4);	      else		success = 0;	    }	  else if (is_real)	    {	      if (**mangled == 'm')		{		  string_appendn (tname, "-", 1);		  (*mangled)++;		}	      while (isdigit (**mangled))			{		  string_appendn (tname, *mangled, 1);		  (*mangled)++;		}	      if (**mangled == '.') /* fraction */		{		  string_appendn (tname, ".", 1);		  (*mangled)++;		  while (isdigit (**mangled))			    {		      string_appendn (tname, *mangled, 1);		      (*mangled)++;		    }		}	      if (**mangled == 'e') /* exponent */		{		  string_appendn (tname, "e", 1);		  (*mangled)++;		  while (isdigit (**mangled))			    {		      string_appendn (tname, *mangled, 1);		      (*mangled)++;		    }		}	    }	  else if (is_pointer)	    {	      if (!get_count (mangled, &symbol_len))		{		  success = 0;		  break;		}	      string_appendn (tname, *mangled, symbol_len);	      *mangled += symbol_len;	    }	}      need_comma = 1;    }  if (tname->p[-1] == '>')    string_append (tname, " ");  string_append (tname, ">");  /*      if (work -> static_type)	{	  string_append (declp, *mangled + 1);	  *mangled += strlen (*mangled);	  success = 1;	}      else	{	  success = demangle_args (work, mangled, declp);	}    }*/  return (success);}