wined3d: Add D3DSTENCILOP to the WINED3D namespace.
[wine] / dlls / msvcrt / undname.c
1 /*
2  *  Demangle VC++ symbols into C function prototypes
3  *
4  *  Copyright 2000 Jon Griffiths
5  *            2004 Eric Pouech
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdio.h>
27 #include "msvcrt.h"
28
29 #include "wine/debug.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
32
33 /* TODO:
34  * - document a bit (grammar + functions)
35  * - back-port this new code into tools/winedump/msmangle.c
36  */
37
38 #define UNDNAME_COMPLETE                 (0x0000)
39 #define UNDNAME_NO_LEADING_UNDERSCORES   (0x0001) /* Don't show __ in calling convention */
40 #define UNDNAME_NO_MS_KEYWORDS           (0x0002) /* Don't show calling convention at all */
41 #define UNDNAME_NO_FUNCTION_RETURNS      (0x0004) /* Don't show function/method return value */
42 #define UNDNAME_NO_ALLOCATION_MODEL      (0x0008)
43 #define UNDNAME_NO_ALLOCATION_LANGUAGE   (0x0010)
44 #define UNDNAME_NO_MS_THISTYPE           (0x0020)
45 #define UNDNAME_NO_CV_THISTYPE           (0x0040)
46 #define UNDNAME_NO_THISTYPE              (0x0060)
47 #define UNDNAME_NO_ACCESS_SPECIFIERS     (0x0080) /* Don't show access specifier (public/protected/private) */
48 #define UNDNAME_NO_THROW_SIGNATURES      (0x0100)
49 #define UNDNAME_NO_MEMBER_TYPE           (0x0200) /* Don't show static/virtual specifier */
50 #define UNDNAME_NO_RETURN_UDT_MODEL      (0x0400)
51 #define UNDNAME_32_BIT_DECODE            (0x0800)
52 #define UNDNAME_NAME_ONLY                (0x1000) /* Only report the variable/method name */
53 #define UNDNAME_NO_ARGUMENTS             (0x2000) /* Don't show method arguments */
54 #define UNDNAME_NO_SPECIAL_SYMS          (0x4000)
55 #define UNDNAME_NO_COMPLEX_TYPE          (0x8000)
56
57 /* How data types modifiers are stored:
58  * M (in the following definitions) is defined for 
59  * 'A', 'B', 'C' and 'D' as follows
60  *      {<A>}:  ""
61  *      {<B>}:  "const "
62  *      {<C>}:  "volatile "
63  *      {<D>}:  "const volatile "
64  *
65  *      in arguments:
66  *              P<M>x   {<M>}x*
67  *              Q<M>x   {<M>}x* const
68  *              A<M>x   {<M>}x&
69  *      in data fields:
70  *              same as for arguments and also the following
71  *              ?<M>x   {<M>}x
72  *              
73  */
74
75 #define MAX_ARRAY_ELTS  32
76 struct array
77 {
78     unsigned            start;          /* first valid reference in array */
79     unsigned            num;            /* total number of used elts */
80     unsigned            max;
81     char*               elts[MAX_ARRAY_ELTS];
82 };
83
84 /* Structure holding a parsed symbol */
85 struct parsed_symbol
86 {
87     unsigned            flags;          /* the UNDNAME_ flags used for demangling */
88     malloc_func_t       mem_alloc_ptr;  /* internal allocator */
89     free_func_t         mem_free_ptr;   /* internal deallocator */
90
91     const char*         current;        /* pointer in input (mangled) string */
92     char*               result;         /* demangled string */
93
94     struct array        names;          /* array of names for back reference */
95     struct array        stack;          /* stack of parsed strings */
96
97     void*               alloc_list;     /* linked list of allocated blocks */
98     unsigned            avail_in_first; /* number of available bytes in head block */
99 };
100
101 /* Type for parsing mangled types */
102 struct datatype_t
103 {
104     const char*         left;
105     const char*         right;
106 };
107
108 /******************************************************************
109  *              und_alloc
110  *
111  * Internal allocator. Uses a simple linked list of large blocks
112  * where we use a poor-man allocator. It's fast, and since all
113  * allocation is pool, memory management is easy (esp. freeing).
114  */
115 static void*    und_alloc(struct parsed_symbol* sym, size_t len)
116 {
117     void*       ptr;
118
119 #define BLOCK_SIZE      1024
120 #define AVAIL_SIZE      (1024 - sizeof(void*))
121
122     if (len > AVAIL_SIZE)
123     {
124         /* allocate a specific block */
125         ptr = sym->mem_alloc_ptr(sizeof(void*) + len);
126         if (!ptr) return NULL;
127         *(void**)ptr = sym->alloc_list;
128         sym->alloc_list = ptr;
129         sym->avail_in_first = 0;
130         ptr = (char*)sym->alloc_list + sizeof(void*);
131     }
132     else 
133     {
134         if (len > sym->avail_in_first)
135         {
136             /* add a new block */
137             ptr = sym->mem_alloc_ptr(BLOCK_SIZE);
138             if (!ptr) return NULL;
139             *(void**)ptr = sym->alloc_list;
140             sym->alloc_list = ptr;
141             sym->avail_in_first = AVAIL_SIZE;
142         }
143         /* grab memory from head block */
144         ptr = (char*)sym->alloc_list + BLOCK_SIZE - sym->avail_in_first;
145         sym->avail_in_first -= len;
146     }
147     return ptr;
148 #undef BLOCK_SIZE
149 #undef AVAIL_SIZE
150 }
151
152 /******************************************************************
153  *              und_free
154  * Frees all the blocks in the list of large blocks allocated by
155  * und_alloc.
156  */
157 static void und_free_all(struct parsed_symbol* sym)
158 {
159     void*       next;
160
161     while (sym->alloc_list)
162     {
163         next = *(void**)sym->alloc_list;
164         if(sym->mem_free_ptr) sym->mem_free_ptr(sym->alloc_list);
165         sym->alloc_list = next;
166     }
167     sym->avail_in_first = 0;
168 }
169
170 /******************************************************************
171  *              str_array_init
172  * Initialises an array of strings
173  */
174 static void str_array_init(struct array* a)
175 {
176     a->start = a->num = a->max = 0;
177 }
178
179 /******************************************************************
180  *              str_array_push
181  * Adding a new string to an array
182  */
183 static void str_array_push(struct parsed_symbol* sym, const char* ptr, size_t len, 
184                            struct array* a)
185 {
186     assert(ptr);
187     assert(a);
188     assert(a->num < MAX_ARRAY_ELTS);
189     if (len == -1) len = strlen(ptr);
190     a->elts[a->num] = und_alloc(sym, len + 1);
191     assert(a->elts[a->num]);
192     memcpy(a->elts[a->num], ptr, len);
193     a->elts[a->num][len] = '\0'; 
194     if (++a->num >= a->max) a->max = a->num;
195     {
196         int i;
197         char c;
198
199         for (i = a->max - 1; i >= 0; i--)
200         {
201             c = '>';
202             if (i < a->start) c = '-';
203             else if (i >= a->num) c = '}';
204             TRACE("%p\t%d%c %s\n", a, i, c, a->elts[i]);
205         }
206     }
207 }
208
209 /******************************************************************
210  *              str_array_get_ref
211  * Extracts a reference from an existing array (doing proper type
212  * checking)
213  */
214 static char* str_array_get_ref(struct array* cref, unsigned idx)
215 {
216     assert(cref);
217     if (cref->start + idx >= cref->max)
218     {
219         WARN("Out of bounds: %p %d + %d >= %d\n", 
220               cref, cref->start, idx, cref->max);
221         return NULL;
222     }
223     TRACE("Returning %p[%d] => %s\n", 
224           cref, idx, cref->elts[cref->start + idx]);
225     return cref->elts[cref->start + idx];
226 }
227
228 /******************************************************************
229  *              str_printf
230  * Helper for printf type of command (only %s and %c are implemented) 
231  * while dynamically allocating the buffer
232  */
233 static char* str_printf(struct parsed_symbol* sym, const char* format, ...)
234 {
235     va_list     args;
236     size_t      len = 1, i, sz;
237     char*       tmp;
238     char*       p;
239     char*       t;
240
241     va_start(args, format);
242     for (i = 0; format[i]; i++)
243     {
244         if (format[i] == '%')
245         {
246             switch (format[++i])
247             {
248             case 's': t = va_arg(args, char*); if (t) len += strlen(t); break;
249             case 'c': (void)va_arg(args, int); len++; break;
250             default: i--; /* fall thru */
251             case '%': len++; break;
252             }
253         }
254         else len++;
255     }
256     va_end(args);
257     if (!(tmp = (char*)und_alloc(sym, len))) return NULL;
258     va_start(args, format);
259     for (p = tmp, i = 0; format[i]; i++)
260     {
261         if (format[i] == '%')
262         {
263             switch (format[++i])
264             {
265             case 's':
266                 t = va_arg(args, char*);
267                 if (t)
268                 {
269                     sz = strlen(t);
270                     memcpy(p, t, sz);
271                     p += sz;
272                 }
273                 break;
274             case 'c':
275                 *p++ = (char)va_arg(args, int);
276                 break;
277             default: i--; /* fall thru */
278             case '%': *p++ = '%'; break;
279             }
280         }
281         else *p++ = format[i];
282     }
283     va_end(args);
284     *p = '\0';
285     return tmp;
286 }
287
288 /* forward declaration */
289 static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
290                               struct array* pmt, BOOL in_args);
291
292 /******************************************************************
293  *              get_args
294  * Parses a list of function/method arguments, creates a string corresponding
295  * to the arguments' list.
296  */
297 static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_term, 
298                       char open_char, char close_char)
299
300 {
301     struct datatype_t   ct;
302     struct array        arg_collect;
303     char*               args_str = NULL;
304     int                 i;
305
306     str_array_init(&arg_collect);
307
308     /* Now come the function arguments */
309     while (*sym->current)
310     {
311         /* Decode each data type and append it to the argument list */
312         if (*sym->current == '@')
313         {
314             sym->current++;
315             break;
316         }
317         if (!demangle_datatype(sym, &ct, pmt_ref, TRUE))
318             return NULL;
319         /* 'void' terminates an argument list */
320         if (!strcmp(ct.left, "void"))
321         {
322             if (!z_term && *sym->current == '@') sym->current++;
323             break;
324         }
325         str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1, 
326                        &arg_collect);
327         if (!strcmp(ct.left, "...")) break;
328     }
329     /* Functions are always terminated by 'Z'. If we made it this far and
330      * don't find it, we have incorrectly identified a data type.
331      */
332     if (z_term && *sym->current++ != 'Z') return NULL;
333
334     if (arg_collect.num == 0 || 
335         (arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void")))        
336         return str_printf(sym, "%cvoid%c", open_char, close_char);
337     for (i = 1; i < arg_collect.num; i++)
338     {
339         args_str = str_printf(sym, "%s,%s", args_str, arg_collect.elts[i]);
340     }
341
342     if (close_char == '>' && args_str && args_str[strlen(args_str) - 1] == '>')
343         args_str = str_printf(sym, "%c%s%s %c", 
344                               open_char, arg_collect.elts[0], args_str, close_char);
345     else
346         args_str = str_printf(sym, "%c%s%s%c", 
347                               open_char, arg_collect.elts[0], args_str, close_char);
348     
349     return args_str;
350 }
351
352 /******************************************************************
353  *              get_modifier
354  * Parses the type modifier. Always returns a static string
355  */
356 static BOOL get_modifier(char ch, const char** ret)
357 {
358     switch (ch)
359     {
360     case 'A': *ret = NULL; break;
361     case 'B': *ret = "const"; break;
362     case 'C': *ret = "volatile"; break;
363     case 'D': *ret = "const volatile"; break;
364     default: return FALSE;
365     }
366     return TRUE;
367 }
368
369 static const char* get_modified_type(struct parsed_symbol* sym, char modif)
370 {
371     const char* modifier;
372     const char* ret = NULL;
373     const char* str_modif;
374
375     switch (modif)
376     {
377     case 'A': str_modif = " &"; break;
378     case 'B': str_modif = " & volatile"; break;
379     case 'P': str_modif = " *"; break;
380     case 'Q': str_modif = " * const"; break;
381     case 'R': str_modif = " * volatile"; break;
382     case 'S': str_modif = " * const volatile"; break;
383     case '?': str_modif = ""; break;
384     default: return NULL;
385     }
386
387     if (get_modifier(*sym->current++, &modifier))
388     {
389         unsigned            mark = sym->stack.num;
390         struct datatype_t   sub_ct;
391
392         /* Recurse to get the referred-to type */
393         if (!demangle_datatype(sym, &sub_ct, NULL, FALSE))
394             return NULL;
395         ret = str_printf(sym, "%s%s%s%s%s", 
396                          sub_ct.left, sub_ct.left && modifier ? " " : NULL, 
397                          modifier, sub_ct.right, str_modif);
398         sym->stack.num = mark;
399     }
400     return ret;
401 }
402
403 /******************************************************************
404  *             get_literal_string
405  * Gets the literal name from the current position in the mangled
406  * symbol to the first '@' character. It pushes the parsed name to
407  * the symbol names stack and returns a pointer to it or NULL in
408  * case of an error.
409  */
410 static char* get_literal_string(struct parsed_symbol* sym)
411 {
412     const char *ptr = sym->current;
413
414     do {
415         if (!((*sym->current >= 'A' && *sym->current <= 'Z') ||
416               (*sym->current >= 'a' && *sym->current <= 'z') ||
417               (*sym->current >= '0' && *sym->current <= '9') ||
418               *sym->current == '_' || *sym->current == '$')) {
419             TRACE("Failed at '%c' in %s\n", *sym->current, ptr);
420             return NULL;
421         }
422     } while (*++sym->current != '@');
423     sym->current++;
424     str_array_push(sym, ptr, sym->current - 1 - ptr, &sym->names);
425
426     return str_array_get_ref(&sym->names, sym->names.num - sym->names.start - 1);
427 }
428
429 /******************************************************************
430  *              get_class
431  * Parses class as a list of parent-classes, terminated by '@' and stores the
432  * result in 'a' array. Each parent-classes, as well as the inner element
433  * (either field/method name or class name), are represented in the mangled
434  * name by a literal name ([a-zA-Z0-9_]+ terminated by '@') or a back reference
435  * ([0-9]) or a name with template arguments ('?$' literal name followed by the
436  * template argument list). The class name components appear in the reverse
437  * order in the mangled name, e.g aaa@bbb@ccc@@ will be demangled to
438  * ccc::bbb::aaa
439  * For each of this class name componets a string will be allocated in the
440  * array.
441  */
442 static BOOL get_class(struct parsed_symbol* sym)
443 {
444     const char* name = NULL;
445
446     while (*sym->current != '@')
447     {
448         switch (*sym->current)
449         {
450         case '\0': return FALSE;
451
452         case '0': case '1': case '2': case '3':
453         case '4': case '5': case '6': case '7':
454         case '8': case '9':
455             name = str_array_get_ref(&sym->names, *sym->current++ - '0');
456             break;
457         case '?':
458             if (*++sym->current == '$') 
459             {
460                 /* In a template argument list the back reference to names
461                    table is separately created. '0' points to the class
462                    component name with the template arguments. We use the same
463                    stack array to hold the names but save/restore the stack
464                    state before/after parsing the template argument list. */
465                 char*           args = NULL;
466                 unsigned        num_mark = sym->names.num;
467                 unsigned        start_mark = sym->names.start;
468                 unsigned        stack_mark = sym->stack.num;
469
470                 sym->names.start = sym->names.num;
471                 sym->current++;
472                 if (!(name = get_literal_string(sym)))
473                     return FALSE;
474                 args = get_args(sym, NULL, FALSE, '<', '>');
475                 if (args != NULL)
476                     name = str_printf(sym, "%s%s", name, args);
477                 sym->names.num = num_mark;
478                 sym->names.start = start_mark;
479                 sym->stack.num = stack_mark;
480                 /* Now that we are back to the standard name scope push
481                    the class component with all its template arguments
482                    to the names array for back reference. */
483                 str_array_push(sym, name, -1, &sym->names);
484             }
485             break;
486         default:
487             name = get_literal_string(sym);
488             break;
489         }
490         if (!name)
491             return FALSE;
492         str_array_push(sym, name, -1, &sym->stack);
493     }
494     sym->current++;
495     return TRUE;
496 }
497
498 /******************************************************************
499  *              get_class_string
500  * From an array collected by get_class in sym->stack, constructs the
501  * corresponding (allocated) string
502  */
503 static char* get_class_string(struct parsed_symbol* sym, int start)
504 {
505     int         i;
506     size_t      len, sz;
507     char*       ret;
508     struct array *a = &sym->stack;
509
510     for (len = 0, i = start; i < a->num; i++)
511     {
512         assert(a->elts[i]);
513         len += 2 + strlen(a->elts[i]);
514     }
515     if (!(ret = und_alloc(sym, len - 1))) return NULL;
516     for (len = 0, i = a->num - 1; i >= start; i--)
517     {
518         sz = strlen(a->elts[i]);
519         memcpy(ret + len, a->elts[i], sz);
520         len += sz;
521         if (i > start)
522         {
523             ret[len++] = ':';
524             ret[len++] = ':';
525         }
526     }
527     ret[len] = '\0';
528     return ret;
529 }
530
531 /******************************************************************
532  *            get_class_name
533  * Wrapper around get_class and get_class_string.
534  */
535 static char* get_class_name(struct parsed_symbol* sym)
536 {
537     unsigned    mark = sym->stack.num;
538     char*       s = NULL;
539
540     if (get_class(sym))
541         s = get_class_string(sym, mark);
542     sym->stack.num = mark;
543     return s;
544 }
545
546 /******************************************************************
547  *              get_calling_convention
548  * Returns a static string corresponding to the calling convention described
549  * by char 'ch'. Sets export to TRUE iff the calling convention is exported.
550  */
551 static BOOL get_calling_convention(char ch, const char** call_conv,
552                                    const char** exported, unsigned flags)
553 {
554     *call_conv = *exported = NULL;
555
556     if (!(flags & (UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ALLOCATION_LANGUAGE)))
557     {
558         if (flags & UNDNAME_NO_LEADING_UNDERSCORES)
559         {
560             if (((ch - 'A') % 2) == 1) *exported = "dll_export ";
561             switch (ch)
562             {
563             case 'A': case 'B': *call_conv = "cdecl"; break;
564             case 'C': case 'D': *call_conv = "pascal"; break;
565             case 'E': case 'F': *call_conv = "thiscall"; break;
566             case 'G': case 'H': *call_conv = "stdcall"; break;
567             case 'I': case 'J': *call_conv = "fastcall"; break;
568             case 'K': break;
569             default: ERR("Unknown calling convention %c\n", ch); return FALSE;
570             }
571         }
572         else
573         {
574             if (((ch - 'A') % 2) == 1) *exported = "__dll_export ";
575             switch (ch)
576             {
577             case 'A': case 'B': *call_conv = "__cdecl"; break;
578             case 'C': case 'D': *call_conv = "__pascal"; break;
579             case 'E': case 'F': *call_conv = "__thiscall"; break;
580             case 'G': case 'H': *call_conv = "__stdcall"; break;
581             case 'I': case 'J': *call_conv = "__fastcall"; break;
582             case 'K': break;
583             default: ERR("Unknown calling convention %c\n", ch); return FALSE;
584             }
585         }
586     }
587     return TRUE;
588 }
589
590 /*******************************************************************
591  *         get_simple_type
592  * Return a string containing an allocated string for a simple data type
593  */
594 static const char* get_simple_type(char c)
595 {
596     const char* type_string;
597     
598     switch (c)
599     {
600     case 'C': type_string = "signed char"; break;
601     case 'D': type_string = "char"; break;
602     case 'E': type_string = "unsigned char"; break;
603     case 'F': type_string = "short"; break;
604     case 'G': type_string = "unsigned short"; break;
605     case 'H': type_string = "int"; break;
606     case 'I': type_string = "unsigned int"; break;
607     case 'J': type_string = "long"; break;
608     case 'K': type_string = "unsigned long"; break;
609     case 'M': type_string = "float"; break;
610     case 'N': type_string = "double"; break;
611     case 'O': type_string = "long double"; break;
612     case 'X': type_string = "void"; break;
613     case 'Z': type_string = "..."; break;
614     default:  type_string = NULL; break;
615     }
616     return type_string;
617 }
618
619 /*******************************************************************
620  *         get_extented_type
621  * Return a string containing an allocated string for a simple data type
622  */
623 static const char* get_extended_type(char c)
624 {
625     const char* type_string;
626     
627     switch (c)
628     {
629     case 'D': type_string = "__int8"; break;
630     case 'E': type_string = "unsigned __int8"; break;
631     case 'F': type_string = "__int16"; break;
632     case 'G': type_string = "unsigned __int16"; break;
633     case 'H': type_string = "__int32"; break;
634     case 'I': type_string = "unsigned __int32"; break;
635     case 'J': type_string = "__int64"; break;
636     case 'K': type_string = "unsigned __int64"; break;
637     case 'L': type_string = "__int128"; break;
638     case 'M': type_string = "unsigned __int128"; break;
639     case 'N': type_string = "bool"; break;
640     case 'W': type_string = "wchar_t"; break;
641     default:  type_string = NULL; break;
642     }
643     return type_string;
644 }
645
646 /*******************************************************************
647  *         demangle_datatype
648  *
649  * Attempt to demangle a C++ data type, which may be datatype.
650  * a datatype type is made up of a number of simple types. e.g:
651  * char** = (pointer to (pointer to (char)))
652  */
653 static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
654                               struct array* pmt_ref, BOOL in_args)
655 {
656     char                dt;
657     BOOL                add_pmt = TRUE;
658     int                 num_args=0;
659
660     assert(ct);
661     ct->left = ct->right = NULL;
662     
663     switch (dt = *sym->current++)
664     {
665     case '_':
666         /* MS type: __int8,__int16 etc */
667         ct->left = get_extended_type(*sym->current++);
668         break;
669     case 'C': case 'D': case 'E': case 'F': case 'G':
670     case 'H': case 'I': case 'J': case 'K': case 'M':
671     case 'N': case 'O': case 'X': case 'Z':
672         /* Simple data types */
673         ct->left = get_simple_type(dt);
674         add_pmt = FALSE;
675         break;
676     case 'T': /* union */
677     case 'U': /* struct */
678     case 'V': /* class */
679         /* Class/struct/union */
680         {
681             const char* struct_name = NULL;
682             const char* type_name = NULL;
683
684             if (!(struct_name = get_class_name(sym)))
685                 goto done;
686             if (!(sym->flags & UNDNAME_NO_COMPLEX_TYPE)) 
687             {
688                 switch (dt)
689                 {
690                 case 'T': type_name = "union ";  break;
691                 case 'U': type_name = "struct "; break;
692                 case 'V': type_name = "class ";  break;
693                 }
694             }
695             ct->left = str_printf(sym, "%s%s", type_name, struct_name);
696         }
697         break;
698     case '?':
699         /* not all the time is seems */
700         if (!(ct->left = get_modified_type(sym, '?'))) goto done;
701         break;
702     case 'A': /* reference */
703     case 'B': /* volatile reference */
704         if (!(ct->left = get_modified_type(sym, dt))) goto done;
705         break;
706     case 'Q': /* const pointer */
707     case 'R': /* volatile pointer */
708     case 'S': /* const volatile pointer */
709         if (!(ct->left = get_modified_type(sym, in_args ? dt : 'P'))) goto done;
710         break;
711     case 'P': /* Pointer */
712         if (isdigit(*sym->current))
713         {
714             /* FIXME: P6 = Function pointer, others who knows.. */
715             if (*sym->current++ == '6')
716             {
717                 char*                   args = NULL;
718                 const char*             call_conv;
719                 const char*             exported;
720                 struct datatype_t       sub_ct;
721                 unsigned                mark = sym->stack.num;
722
723                 if (!get_calling_convention(*sym->current++,
724                                             &call_conv, &exported, 
725                                             sym->flags & ~UNDNAME_NO_ALLOCATION_LANGUAGE) ||
726                     !demangle_datatype(sym, &sub_ct, pmt_ref, FALSE))
727                     goto done;
728
729                 args = get_args(sym, pmt_ref, TRUE, '(', ')');
730                 if (!args) goto done;
731                 sym->stack.num = mark;
732
733                 ct->left  = str_printf(sym, "%s%s (%s*", 
734                                        sub_ct.left, sub_ct.right, call_conv);
735                 ct->right = str_printf(sym, ")%s", args);
736             }
737             else goto done;
738         }
739         else if (!(ct->left = get_modified_type(sym, 'P'))) goto done;
740         break;
741     case 'W':
742         if (*sym->current == '4')
743         {
744             char*               enum_name;
745             sym->current++;
746             if (!(enum_name = get_class_name(sym)))
747                 goto done;
748             if (sym->flags & UNDNAME_NO_COMPLEX_TYPE)
749                 ct->left = enum_name;
750             else
751                 ct->left = str_printf(sym, "enum %s", enum_name);
752         }
753         else goto done;
754         break;
755     case '0': case '1': case '2': case '3': case '4':
756     case '5': case '6': case '7': case '8': case '9':
757         /* Referring back to previously parsed type */
758         ct->left = str_array_get_ref(pmt_ref, dt - '0');
759         if (!ct->left) goto done;
760         add_pmt = FALSE;
761         break;
762     case '$':
763         if (sym->current[0] != '0') goto done;
764         if (sym->current[1] >= '0' && sym->current[1] <= '9')
765         {
766             char*       ptr;
767             ptr = und_alloc(sym, 2);
768             ptr[0] = sym->current[1] + 1;
769             ptr[1] = 0;
770             ct->left = ptr;
771             sym->current += 2;
772         }
773         else if (sym->current[1] >= 'A' && sym->current[1] <= 'P')
774         {
775             while (sym->current[1] >= 'A' && sym->current[1] <= 'P')
776             {
777                 num_args *= 16;
778                 num_args += sym->current[1] - 'A';
779                 sym->current += 1;
780             }
781             if(sym->current[1] == '@')
782             {
783                 char *ptr;
784                 ptr = und_alloc(sym, 17);
785                 sprintf(ptr,"%d",num_args);
786                 ct->left = ptr;
787                 sym->current += 1;
788             }
789         }
790         else goto done;
791         break;
792     default :
793         ERR("Unknown type %c\n", dt);
794         break;
795     }
796     if (add_pmt && pmt_ref && in_args)
797         str_array_push(sym, str_printf(sym, "%s%s", ct->left, ct->right), 
798                        -1, pmt_ref);
799 done:
800     
801     return ct->left != NULL;
802 }
803
804 /******************************************************************
805  *              handle_data
806  * Does the final parsing and handling for a variable or a field in
807  * a class.
808  */
809 static BOOL handle_data(struct parsed_symbol* sym)
810 {
811     const char*         access = NULL;
812     const char*         member_type = NULL;
813     const char*         modifier = NULL;
814     struct datatype_t   ct;
815     char*               name = NULL;
816     BOOL                ret = FALSE;
817     char                dt;
818
819     /* 0 private static
820      * 1 protected static
821      * 2 public static
822      * 3 private non-static
823      * 4 protected non-static
824      * 5 public non-static
825      * 6 ?? static
826      * 7 ?? static
827      */
828
829     if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS))
830     {
831         /* we only print the access for static members */
832         switch (*sym->current)
833         {
834         case '0': access = "private: "; break;
835         case '1': access = "protected: "; break;
836         case '2': access = "public: "; break;
837         } 
838     }
839
840     if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE))
841     {
842         if (*sym->current >= '0' && *sym->current <= '2')
843             member_type = "static ";
844     }
845
846     name = get_class_string(sym, 0);
847
848     switch (dt = *sym->current++)
849     {
850     case '0': case '1': case '2':
851     case '3': case '4': case '5':
852         {
853             unsigned mark = sym->stack.num;
854             struct array pmt;
855
856             str_array_init(&pmt);
857
858             if (!demangle_datatype(sym, &ct, &pmt, FALSE)) goto done;
859             if (!get_modifier(*sym->current++, &modifier)) goto done;
860             sym->stack.num = mark;
861         }
862         break;
863     case '6' : /* compiler generated static */
864     case '7' : /* compiler generated static */
865         ct.left = ct.right = NULL;
866         if (!get_modifier(*sym->current++, &modifier)) goto done;
867         if (*sym->current != '@')
868         {
869             char*       cls = NULL;
870
871             if (!(cls = get_class_name(sym)))
872                 goto done;
873             ct.right = str_printf(sym, "{for `%s'}", cls);
874         }
875         break;
876     default: goto done;
877     }
878     if (sym->flags & UNDNAME_NAME_ONLY) ct.left = ct.right = modifier = NULL;
879     sym->result = str_printf(sym, "%s%s%s%s%s%s%s%s", access,
880                              member_type, ct.left, 
881                              modifier && ct.left ? " " : NULL, modifier, 
882                              modifier || ct.left ? " " : NULL, name, ct.right);
883     ret = TRUE;
884 done:
885     return ret;
886 }
887
888 /******************************************************************
889  *              handle_method
890  * Does the final parsing and handling for a function or a method in
891  * a class.
892  */
893 static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
894 {
895     const char*         access = NULL;
896     const char*         member_type = NULL;
897     struct datatype_t   ct_ret;
898     const char*         call_conv;
899     const char*         modifier = NULL;
900     const char*         exported;
901     const char*         args_str = NULL;
902     const char*         name = NULL;
903     BOOL                ret = FALSE;
904     unsigned            mark;
905     struct array        array_pmt;
906
907     /* FIXME: why 2 possible letters for each option?
908      * 'A' private:
909      * 'B' private:
910      * 'C' private: static
911      * 'D' private: static
912      * 'E' private: virtual
913      * 'F' private: virtual
914      * 'G' private: thunk
915      * 'H' private: thunk
916      * 'I' protected:
917      * 'J' protected:
918      * 'K' protected: static
919      * 'L' protected: static
920      * 'M' protected: virtual
921      * 'N' protected: virtual
922      * 'O' protected: thunk
923      * 'P' protected: thunk
924      * 'Q' public:
925      * 'R' public:
926      * 'S' public: static
927      * 'T' public: static
928      * 'U' public: virtual
929      * 'V' public: virtual
930      * 'W' public: thunk
931      * 'X' public: thunk
932      * 'Y'
933      * 'Z'
934      */
935
936     if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS))
937     {
938         switch ((*sym->current - 'A') / 8)
939         {
940         case 0: access = "private: "; break;
941         case 1: access = "protected: "; break;
942         case 2: access = "public: "; break;
943         }
944     }
945     if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE))
946     {
947         if (*sym->current >= 'A' && *sym->current <= 'X')
948         {
949             switch ((*sym->current - 'A') % 8)
950             {
951             case 2: case 3: member_type = "static "; break;
952             case 4: case 5: member_type = "virtual "; break;
953             case 6: case 7: member_type = "thunk "; break;
954             }
955         }
956     }
957
958     if (*sym->current >= 'A' && *sym->current <= 'X')
959     {
960         if (!((*sym->current - 'A') & 2))
961         {
962             /* Implicit 'this' pointer */
963             /* If there is an implicit this pointer, const modifier follows */
964             if (!get_modifier(*++sym->current, &modifier)) goto done;
965         }
966     }
967     else if (*sym->current < 'A' || *sym->current > 'Z') goto done;
968     sym->current++;
969
970     name = get_class_string(sym, 0);
971   
972     if (!get_calling_convention(*sym->current++, &call_conv, &exported,
973                                 sym->flags))
974         goto done;
975
976     str_array_init(&array_pmt);
977
978     /* Return type, or @ if 'void' */
979     if (*sym->current == '@')
980     {
981         ct_ret.left = "void";
982         ct_ret.right = NULL;
983         sym->current++;
984     }
985     else
986     {
987         if (!demangle_datatype(sym, &ct_ret, &array_pmt, FALSE))
988             goto done;
989     }
990     if (sym->flags & UNDNAME_NO_FUNCTION_RETURNS)
991         ct_ret.left = ct_ret.right = NULL;
992     if (cast_op)
993     {
994         name = str_printf(sym, "%s%s%s", name, ct_ret.left, ct_ret.right);
995         ct_ret.left = ct_ret.right = NULL;
996     }
997
998     mark = sym->stack.num;
999     if (!(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done;
1000     if (sym->flags & UNDNAME_NAME_ONLY) args_str = modifier = NULL;
1001     sym->stack.num = mark;
1002
1003     /* Note: '()' after 'Z' means 'throws', but we don't care here
1004      * Yet!!! FIXME
1005      */
1006     sym->result = str_printf(sym, "%s%s%s%s%s%s%s%s%s%s%s%s",
1007                              access, member_type, ct_ret.left, 
1008                              (ct_ret.left && !ct_ret.right) ? " " : NULL,
1009                              call_conv, call_conv ? " " : NULL, exported,
1010                              name, args_str, modifier, 
1011                              modifier ? " " : NULL, ct_ret.right);
1012     ret = TRUE;
1013 done:
1014     return ret;
1015 }
1016
1017 /*******************************************************************
1018  *         symbol_demangle
1019  * Demangle a C++ linker symbol
1020  */
1021 static BOOL symbol_demangle(struct parsed_symbol* sym)
1022 {
1023     BOOL                ret = FALSE;
1024     unsigned            do_after = 0;
1025     static CHAR         dashed_null[] = "--null--";
1026
1027     /* FIXME seems wrong as name, as it demangles a simple data type */
1028     if (sym->flags & UNDNAME_NO_ARGUMENTS)
1029     {
1030         struct datatype_t   ct;
1031
1032         if (demangle_datatype(sym, &ct, NULL, FALSE))
1033         {
1034             sym->result = str_printf(sym, "%s%s", ct.left, ct.right);
1035             ret = TRUE;
1036         }
1037         goto done;
1038     }
1039
1040     /* MS mangled names always begin with '?' */
1041     if (*sym->current != '?') return FALSE;
1042     str_array_init(&sym->names);
1043     str_array_init(&sym->stack);
1044     sym->current++;
1045
1046     /* Then function name or operator code */
1047     if (*sym->current == '?' && sym->current[1] != '$')
1048     {
1049         const char* function_name = NULL;
1050
1051         /* C++ operator code (one character, or two if the first is '_') */
1052         switch (*++sym->current)
1053         {
1054         case '0': do_after = 1; break;
1055         case '1': do_after = 2; break;
1056         case '2': function_name = "operator new"; break;
1057         case '3': function_name = "operator delete"; break;
1058         case '4': function_name = "operator="; break;
1059         case '5': function_name = "operator>>"; break;
1060         case '6': function_name = "operator<<"; break;
1061         case '7': function_name = "operator!"; break;
1062         case '8': function_name = "operator=="; break;
1063         case '9': function_name = "operator!="; break;
1064         case 'A': function_name = "operator[]"; break;
1065         case 'B': function_name = "operator "; do_after = 3; break;
1066         case 'C': function_name = "operator->"; break;
1067         case 'D': function_name = "operator*"; break;
1068         case 'E': function_name = "operator++"; break;
1069         case 'F': function_name = "operator--"; break;
1070         case 'G': function_name = "operator-"; break;
1071         case 'H': function_name = "operator+"; break;
1072         case 'I': function_name = "operator&"; break;
1073         case 'J': function_name = "operator->*"; break;
1074         case 'K': function_name = "operator/"; break;
1075         case 'L': function_name = "operator%"; break;
1076         case 'M': function_name = "operator<"; break;
1077         case 'N': function_name = "operator<="; break;
1078         case 'O': function_name = "operator>"; break;
1079         case 'P': function_name = "operator>="; break;
1080         case 'Q': function_name = "operator,"; break;
1081         case 'R': function_name = "operator()"; break;
1082         case 'S': function_name = "operator~"; break;
1083         case 'T': function_name = "operator^"; break;
1084         case 'U': function_name = "operator|"; break;
1085         case 'V': function_name = "operator&&"; break;
1086         case 'W': function_name = "operator||"; break;
1087         case 'X': function_name = "operator*="; break;
1088         case 'Y': function_name = "operator+="; break;
1089         case 'Z': function_name = "operator-="; break;
1090         case '_':
1091             switch (*++sym->current)
1092             {
1093             case '0': function_name = "operator/="; break;
1094             case '1': function_name = "operator%="; break;
1095             case '2': function_name = "operator>>="; break;
1096             case '3': function_name = "operator<<="; break;
1097             case '4': function_name = "operator&="; break;
1098             case '5': function_name = "operator|="; break;
1099             case '6': function_name = "operator^="; break;
1100             case '7': function_name = "`vftable'"; break;
1101             case '8': function_name = "`vbtable'"; break;
1102             case '9': function_name = "`vcall'"; break;
1103             case 'A': function_name = "`typeof'"; break;
1104             case 'B': function_name = "`local static guard'"; break;
1105             case 'C': function_name = "`string'"; do_after = 4; break;
1106             case 'D': function_name = "`vbase destructor'"; break;
1107             case 'E': function_name = "`vector deleting destructor'"; break;
1108             case 'F': function_name = "`default constructor closure'"; break;
1109             case 'G': function_name = "`scalar deleting destructor'"; break;
1110             case 'H': function_name = "`vector constructor iterator'"; break;
1111             case 'I': function_name = "`vector destructor iterator'"; break;
1112             case 'J': function_name = "`vector vbase constructor iterator'"; break;
1113             case 'K': function_name = "`virtual displacement map'"; break;
1114             case 'L': function_name = "`eh vector constructor iterator'"; break;
1115             case 'M': function_name = "`eh vector destructor iterator'"; break;
1116             case 'N': function_name = "`eh vector vbase constructor iterator'"; break;
1117             case 'O': function_name = "`copy constructor closure'"; break;
1118             case 'S': function_name = "`local vftable'"; break;
1119             case 'T': function_name = "`local vftable constructor closure'"; break;
1120             case 'U': function_name = "operator new[]"; break;
1121             case 'V': function_name = "operator delete[]"; break;
1122             case 'X': function_name = "`placement delete closure'"; break;
1123             case 'Y': function_name = "`placement delete[] closure'"; break;
1124             default:
1125                 ERR("Unknown operator: _%c\n", *sym->current);
1126                 return FALSE;
1127             }
1128             break;
1129         default:
1130             /* FIXME: Other operators */
1131             ERR("Unknown operator: %c\n", *sym->current);
1132             return FALSE;
1133         }
1134         sym->current++;
1135         switch (do_after)
1136         {
1137         case 1: case 2:
1138             sym->stack.num = sym->stack.max = 1;
1139             sym->stack.elts[0] = dashed_null;
1140             break;
1141         case 4:
1142             sym->result = (char*)function_name;
1143             ret = TRUE;
1144             goto done;
1145         default:
1146             str_array_push(sym, function_name, -1, &sym->stack);
1147             break;
1148         }
1149         sym->stack.start = 1;
1150     }
1151
1152     /* Either a class name, or '@' if the symbol is not a class member */
1153     if (*sym->current != '@')
1154     {
1155         /* Class the function is associated with, terminated by '@@' */
1156         if (!get_class(sym)) goto done;
1157     }
1158     else sym->current++;
1159
1160     switch (do_after)
1161     {
1162     case 0: default: break;
1163     case 1: case 2:
1164         /* it's time to set the member name for ctor & dtor */
1165         if (sym->stack.num <= 1) goto done;
1166         if (do_after == 1)
1167             sym->stack.elts[0] = sym->stack.elts[1];
1168         else
1169             sym->stack.elts[0] = str_printf(sym, "~%s", sym->stack.elts[1]);
1170         /* ctors and dtors don't have return type */
1171         sym->flags |= UNDNAME_NO_FUNCTION_RETURNS;
1172         break;
1173     case 3:
1174         sym->flags &= ~UNDNAME_NO_FUNCTION_RETURNS;
1175         break;
1176     }
1177
1178     /* Function/Data type and access level */
1179     if (*sym->current >= '0' && *sym->current <= '7')
1180         ret = handle_data(sym);
1181     else if (*sym->current >= 'A' && *sym->current <= 'Z')
1182         ret = handle_method(sym, do_after == 3);
1183     else ret = FALSE;
1184 done:
1185     if (ret) assert(sym->result);
1186     else WARN("Failed at %s\n", sym->current);
1187
1188     return ret;
1189 }
1190
1191 /*********************************************************************
1192  *              __unDNameEx (MSVCRT.@)
1193  *
1194  * Demangle a C++ identifier.
1195  *
1196  * PARAMS
1197  *  buffer   [O] If not NULL, the place to put the demangled string
1198  *  mangled  [I] Mangled name of the function
1199  *  buflen   [I] Length of buffer
1200  *  memget   [I] Function to allocate memory with
1201  *  memfree  [I] Function to free memory with
1202  *  unknown  [?] Unknown, possibly a call back
1203  *  flags    [I] Flags determining demangled format
1204  *
1205  * RETURNS
1206  *  Success: A string pointing to the unmangled name, allocated with memget.
1207  *  Failure: NULL.
1208  */
1209 char* CDECL __unDNameEx(char* buffer, const char* mangled, int buflen,
1210                         malloc_func_t memget, free_func_t memfree,
1211                         void* unknown, unsigned short int flags)
1212 {
1213     struct parsed_symbol        sym;
1214     const char*                 result;
1215
1216     TRACE("(%p,%s,%d,%p,%p,%p,%x)\n",
1217           buffer, mangled, buflen, memget, memfree, unknown, flags);
1218     
1219     /* The flags details is not documented by MS. However, it looks exactly
1220      * like the UNDNAME_ manifest constants from imagehlp.h and dbghelp.h
1221      * So, we copied those (on top of the file)
1222      */
1223     memset(&sym, 0, sizeof(struct parsed_symbol));
1224     if (flags & UNDNAME_NAME_ONLY)
1225         flags |= UNDNAME_NO_FUNCTION_RETURNS | UNDNAME_NO_ACCESS_SPECIFIERS |
1226             UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_ALLOCATION_LANGUAGE |
1227             UNDNAME_NO_COMPLEX_TYPE;
1228
1229     sym.flags         = flags;
1230     sym.mem_alloc_ptr = memget;
1231     sym.mem_free_ptr  = memfree;
1232     sym.current       = mangled;
1233
1234     result = symbol_demangle(&sym) ? sym.result : mangled;
1235     if (buffer && buflen)
1236     {
1237         lstrcpynA( buffer, result, buflen);
1238     }
1239     else
1240     {
1241         buffer = memget(strlen(result) + 1);
1242         if (buffer) strcpy(buffer, result);
1243     }
1244
1245     und_free_all(&sym);
1246
1247     return buffer;
1248 }
1249
1250
1251 /*********************************************************************
1252  *              __unDName (MSVCRT.@)
1253  */
1254 char* CDECL __unDName(char* buffer, const char* mangled, int buflen,
1255                       malloc_func_t memget, free_func_t memfree,
1256                       unsigned short int flags)
1257 {
1258     return __unDNameEx(buffer, mangled, buflen, memget, memfree, NULL, flags);
1259 }