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