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