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