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