msvcrt: Use the public definitions for the UNDNAME_ flags.
[wine.git] / dlls / msvcrt / undname.c
blob89052d433b02a5422a774497e572d796542c51bc
1 /*
2 * Demangle VC++ symbols into C function prototypes
4 * Copyright 2000 Jon Griffiths
5 * 2004 Eric Pouech
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.
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.
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
22 #include <assert.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include "msvcrt.h"
26 #include "winver.h"
27 #include "imagehlp.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
33 /* How data types qualifiers are stored:
34 * M (in the following definitions) is defined for
35 * 'A', 'B', 'C' and 'D' as follows
36 * {<A>}: ""
37 * {<B>}: "const "
38 * {<C>}: "volatile "
39 * {<D>}: "const volatile "
41 * in arguments:
42 * P<M>x {<M>}x*
43 * Q<M>x {<M>}x* const
44 * A<M>x {<M>}x&
45 * in data fields:
46 * same as for arguments and also the following
47 * ?<M>x {<M>}x
51 #define UNDNAME_NO_COMPLEX_TYPE (0x8000)
53 struct array
55 unsigned start; /* first valid reference in array */
56 unsigned num; /* total number of used elts */
57 unsigned max;
58 unsigned alloc;
59 char** elts;
62 /* Structure holding a parsed symbol */
63 struct parsed_symbol
65 unsigned flags; /* the UNDNAME_ flags used for demangling */
66 malloc_func_t mem_alloc_ptr; /* internal allocator */
67 free_func_t mem_free_ptr; /* internal deallocator */
69 const char* current; /* pointer in input (mangled) string */
70 char* result; /* demangled string */
72 struct array names; /* array of names for back reference */
73 struct array stack; /* stack of parsed strings */
75 void* alloc_list; /* linked list of allocated blocks */
76 unsigned avail_in_first; /* number of available bytes in head block */
79 enum datatype_e
81 DT_NO_LEADING_WS = 0x01,
82 DT_NO_LRSEP_WS = 0x02,
85 /* Type for parsing mangled types */
86 struct datatype_t
88 const char* left;
89 const char* right;
90 enum datatype_e flags;
93 static BOOL symbol_demangle(struct parsed_symbol* sym);
94 static char* get_class_name(struct parsed_symbol* sym);
96 /******************************************************************
97 * und_alloc
99 * Internal allocator. Uses a simple linked list of large blocks
100 * where we use a poor-man allocator. It's fast, and since all
101 * allocation is pool, memory management is easy (esp. freeing).
103 static void* und_alloc(struct parsed_symbol* sym, unsigned int len)
105 void* ptr;
107 #define BLOCK_SIZE 1024
108 #define AVAIL_SIZE (1024 - sizeof(void*))
110 if (len > AVAIL_SIZE)
112 /* allocate a specific block */
113 ptr = sym->mem_alloc_ptr(sizeof(void*) + len);
114 if (!ptr) return NULL;
115 *(void**)ptr = sym->alloc_list;
116 sym->alloc_list = ptr;
117 sym->avail_in_first = 0;
118 ptr = (char*)sym->alloc_list + sizeof(void*);
120 else
122 if (len > sym->avail_in_first)
124 /* add a new block */
125 ptr = sym->mem_alloc_ptr(BLOCK_SIZE);
126 if (!ptr) return NULL;
127 *(void**)ptr = sym->alloc_list;
128 sym->alloc_list = ptr;
129 sym->avail_in_first = AVAIL_SIZE;
131 /* grab memory from head block */
132 ptr = (char*)sym->alloc_list + BLOCK_SIZE - sym->avail_in_first;
133 sym->avail_in_first -= len;
135 return ptr;
136 #undef BLOCK_SIZE
137 #undef AVAIL_SIZE
140 /******************************************************************
141 * und_free
142 * Frees all the blocks in the list of large blocks allocated by
143 * und_alloc.
145 static void und_free_all(struct parsed_symbol* sym)
147 void* next;
149 while (sym->alloc_list)
151 next = *(void**)sym->alloc_list;
152 if(sym->mem_free_ptr) sym->mem_free_ptr(sym->alloc_list);
153 sym->alloc_list = next;
155 sym->avail_in_first = 0;
158 /******************************************************************
159 * str_array_init
160 * Initialises an array of strings
162 static void str_array_init(struct array* a)
164 a->start = a->num = a->max = a->alloc = 0;
165 a->elts = NULL;
168 /******************************************************************
169 * str_array_push
170 * Adding a new string to an array
172 static BOOL str_array_push(struct parsed_symbol* sym, const char* ptr, int len,
173 struct array* a)
175 char** new;
177 assert(ptr);
178 assert(a);
180 if (!a->alloc)
182 new = und_alloc(sym, (a->alloc = 32) * sizeof(a->elts[0]));
183 if (!new) return FALSE;
184 a->elts = new;
186 else if (a->max >= a->alloc)
188 new = und_alloc(sym, (a->alloc * 2) * sizeof(a->elts[0]));
189 if (!new) return FALSE;
190 memcpy(new, a->elts, a->alloc * sizeof(a->elts[0]));
191 a->alloc *= 2;
192 a->elts = new;
194 if (len == -1) len = strlen(ptr);
195 a->elts[a->num] = und_alloc(sym, len + 1);
196 assert(a->elts[a->num]);
197 memcpy(a->elts[a->num], ptr, len);
198 a->elts[a->num][len] = '\0';
199 if (++a->num >= a->max) a->max = a->num;
201 int i;
202 char c;
204 for (i = a->max - 1; i >= 0; i--)
206 c = '>';
207 if (i < a->start) c = '-';
208 else if (i >= a->num) c = '}';
209 TRACE("%p\t%d%c %s\n", a, i, c, debugstr_a(a->elts[i]));
213 return TRUE;
216 /******************************************************************
217 * str_array_get_ref
218 * Extracts a reference from an existing array (doing proper type
219 * checking)
221 static char* str_array_get_ref(struct array* cref, unsigned idx)
223 assert(cref);
224 if (cref->start + idx >= cref->max)
226 WARN("Out of bounds: %p %d + %d >= %d\n",
227 cref, cref->start, idx, cref->max);
228 return NULL;
230 TRACE("Returning %p[%d] => %s\n",
231 cref, idx, debugstr_a(cref->elts[cref->start + idx]));
232 return cref->elts[cref->start + idx];
235 /******************************************************************
236 * str_printf
237 * Helper for printf type of command (only %s and %c are implemented)
238 * while dynamically allocating the buffer
240 static char* WINAPIV str_printf(struct parsed_symbol* sym, const char* format, ...)
242 va_list args;
243 unsigned int len = 1, i, sz;
244 char* tmp;
245 char* p;
246 char* t;
248 va_start(args, format);
249 for (i = 0; format[i]; i++)
251 if (format[i] == '%')
253 switch (format[++i])
255 case 's': t = va_arg(args, char*); if (t) len += strlen(t); break;
256 case 'c': (void)va_arg(args, int); len++; break;
257 default: i--; /* fall through */
258 case '%': len++; break;
261 else len++;
263 va_end(args);
264 if (!(tmp = und_alloc(sym, len))) return NULL;
265 va_start(args, format);
266 for (p = tmp, i = 0; format[i]; i++)
268 if (format[i] == '%')
270 switch (format[++i])
272 case 's':
273 t = va_arg(args, char*);
274 if (t)
276 sz = strlen(t);
277 memcpy(p, t, sz);
278 p += sz;
280 break;
281 case 'c':
282 *p++ = (char)va_arg(args, int);
283 break;
284 default: i--; /* fall through */
285 case '%': *p++ = '%'; break;
288 else *p++ = format[i];
290 va_end(args);
291 *p = '\0';
292 return tmp;
295 enum datatype_flags
297 IN_ARGS = 0x01,
298 WS_AFTER_QUAL_IF = 0x02,
301 /* forward declaration */
302 static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
303 struct array* pmt, enum datatype_flags flags);
305 static const char* get_number(struct parsed_symbol* sym)
307 char* ptr;
308 BOOL sgn = FALSE;
310 if (*sym->current == '?')
312 sgn = TRUE;
313 sym->current++;
315 if (*sym->current >= '0' && *sym->current <= '8')
317 ptr = und_alloc(sym, 3);
318 if (sgn) ptr[0] = '-';
319 ptr[sgn ? 1 : 0] = *sym->current + 1;
320 ptr[sgn ? 2 : 1] = '\0';
321 sym->current++;
323 else if (*sym->current == '9')
325 ptr = und_alloc(sym, 4);
326 if (sgn) ptr[0] = '-';
327 ptr[sgn ? 1 : 0] = '1';
328 ptr[sgn ? 2 : 1] = '0';
329 ptr[sgn ? 3 : 2] = '\0';
330 sym->current++;
332 else if (*sym->current >= 'A' && *sym->current <= 'P')
334 int ret = 0;
336 while (*sym->current >= 'A' && *sym->current <= 'P')
338 ret *= 16;
339 ret += *sym->current++ - 'A';
341 if (*sym->current != '@') return NULL;
343 ptr = und_alloc(sym, 17);
344 sprintf(ptr, "%s%u", sgn ? "-" : "", ret);
345 sym->current++;
347 else return NULL;
348 return ptr;
351 /******************************************************************
352 * get_args
353 * Parses a list of function/method arguments, creates a string corresponding
354 * to the arguments' list.
356 static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_term,
357 char open_char, char close_char)
360 struct datatype_t ct;
361 struct array arg_collect;
362 char* args_str = NULL;
363 char* last;
364 unsigned int i;
366 str_array_init(&arg_collect);
368 /* Now come the function arguments */
369 while (*sym->current)
371 /* Decode each data type and append it to the argument list */
372 if (*sym->current == '@')
374 sym->current++;
375 break;
377 if (!demangle_datatype(sym, &ct, pmt_ref, IN_ARGS))
378 return NULL;
379 /* 'void' terminates an argument list in a function */
380 if (z_term && !strcmp(ct.left, "void")) break;
381 if (!str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1,
382 &arg_collect))
383 return NULL;
384 if (!strcmp(ct.left, "...")) break;
386 /* Functions are always terminated by 'Z'. If we made it this far and
387 * don't find it, we have incorrectly identified a data type.
389 if (z_term && *sym->current++ != 'Z') return NULL;
391 if (arg_collect.num == 0 ||
392 (arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void")))
393 return str_printf(sym, "%cvoid%c", open_char, close_char);
394 for (i = 1; i < arg_collect.num; i++)
396 args_str = str_printf(sym, "%s,%s", args_str, arg_collect.elts[i]);
399 last = args_str ? args_str : arg_collect.elts[0];
400 if (close_char == '>' && last[strlen(last) - 1] == '>')
401 args_str = str_printf(sym, "%c%s%s %c",
402 open_char, arg_collect.elts[0], args_str, close_char);
403 else
404 args_str = str_printf(sym, "%c%s%s%c",
405 open_char, arg_collect.elts[0], args_str, close_char);
407 return args_str;
410 static void append_extended_qualifier(struct parsed_symbol *sym, const char **where,
411 const char *str, BOOL is_ms_keyword)
413 if (!is_ms_keyword || !(sym->flags & UNDNAME_NO_MS_KEYWORDS))
415 if (is_ms_keyword && (sym->flags & UNDNAME_NO_LEADING_UNDERSCORES))
416 str += 2;
417 *where = *where ? str_printf(sym, "%s%s%s%s", *where, is_ms_keyword ? " " : "", str, is_ms_keyword ? "" : " ") :
418 str_printf(sym, "%s%s", str, is_ms_keyword ? "" : " ");
422 static void get_extended_qualifier(struct parsed_symbol *sym, struct datatype_t *xdt)
424 unsigned fl = 0;
425 xdt->left = xdt->right = NULL;
426 xdt->flags = 0;
427 for (;;)
429 switch (*sym->current)
431 case 'E': append_extended_qualifier(sym, &xdt->right, "__ptr64", TRUE); fl |= 2; break;
432 case 'F': append_extended_qualifier(sym, &xdt->left, "__unaligned", TRUE); fl |= 2; break;
433 #ifdef _UCRT
434 case 'G': append_extended_qualifier(sym, &xdt->right, "&", FALSE); fl |= 1; break;
435 case 'H': append_extended_qualifier(sym, &xdt->right, "&&", FALSE); fl |= 1; break;
436 #endif
437 case 'I': append_extended_qualifier(sym, &xdt->right, "__restrict", TRUE); fl |= 2; break;
438 default: if (fl == 1 || (fl == 3 && (sym->flags & UNDNAME_NO_MS_KEYWORDS))) xdt->flags = DT_NO_LRSEP_WS; return;
440 sym->current++;
444 /******************************************************************
445 * get_qualifier
446 * Parses the type qualifier. Always returns static strings.
448 static BOOL get_qualifier(struct parsed_symbol *sym, struct datatype_t *xdt, const char** pclass)
450 char ch;
451 const char* qualif;
453 get_extended_qualifier(sym, xdt);
454 switch (ch = *sym->current++)
456 case 'A': qualif = NULL; break;
457 case 'B': qualif = "const"; break;
458 case 'C': qualif = "volatile"; break;
459 case 'D': qualif = "const volatile"; break;
460 case 'Q': qualif = NULL; break;
461 case 'R': qualif = "const"; break;
462 case 'S': qualif = "volatile"; break;
463 case 'T': qualif = "const volatile"; break;
464 default: return FALSE;
466 if (qualif)
468 xdt->flags &= ~DT_NO_LRSEP_WS;
469 xdt->left = xdt->left ? str_printf(sym, "%s %s", qualif, xdt->left) : qualif;
471 if (ch >= 'Q' && ch <= 'T') /* pointer to member, fetch class */
473 const char* class = get_class_name(sym);
474 if (!class) return FALSE;
475 if (!pclass)
477 FIXME("Got pointer to class %s member without storage\n", class);
478 return FALSE;
480 *pclass = class;
482 else if (pclass) *pclass = NULL;
483 return TRUE;
486 static BOOL get_function_qualifier(struct parsed_symbol *sym, const char** qualif)
488 struct datatype_t xdt;
490 if (!get_qualifier(sym, &xdt, NULL)) return FALSE;
491 *qualif = (xdt.left || xdt.right) ?
492 str_printf(sym, "%s%s%s", xdt.left, (xdt.flags & DT_NO_LRSEP_WS) ? "" : " ", xdt.right) : NULL;
493 return TRUE;
496 static BOOL get_qualified_type(struct datatype_t *ct, struct parsed_symbol* sym,
497 struct array *pmt_ref, char qualif, enum datatype_flags flags)
499 struct datatype_t xdt1;
500 struct datatype_t xdt2;
501 const char* ref;
502 const char* str_qualif;
503 const char* class;
505 get_extended_qualifier(sym, &xdt1);
507 switch (qualif)
509 case 'A': ref = " &"; str_qualif = NULL; break;
510 case 'B': ref = " &"; str_qualif = " volatile"; break;
511 case 'P': ref = " *"; str_qualif = NULL; break;
512 case 'Q': ref = " *"; str_qualif = " const"; break;
513 case 'R': ref = " *"; str_qualif = " volatile"; break;
514 case 'S': ref = " *"; str_qualif = " const volatile"; break;
515 case '?': ref = NULL; str_qualif = NULL; break;
516 case '$': ref = " &&"; str_qualif = NULL; break;
517 default: return FALSE;
519 ct->right = NULL;
520 ct->flags = 0;
522 if (get_qualifier(sym, &xdt2, &class))
524 unsigned mark = sym->stack.num;
525 struct datatype_t sub_ct;
527 if (ref || str_qualif || xdt1.left || xdt1.right)
529 if (class)
530 ct->left = str_printf(sym, "%s%s%s%s::%s%s%s",
531 xdt1.left ? " " : NULL, xdt1.left,
532 class ? " " : NULL, class, ref ? ref + 1 : NULL,
533 xdt1.right ? " " : NULL, xdt1.right, str_qualif);
534 else
535 ct->left = str_printf(sym, "%s%s%s%s%s%s",
536 xdt1.left ? " " : NULL, xdt1.left, ref,
537 xdt1.right ? " " : NULL, xdt1.right, str_qualif);
539 else
540 ct->left = NULL;
541 /* multidimensional arrays */
542 if (*sym->current == 'Y')
544 const char* n1;
545 int num;
547 sym->current++;
548 if (!(n1 = get_number(sym))) return FALSE;
549 num = atoi(n1);
551 ct->left = str_printf(sym, " (%s%s", xdt2.left, ct->left && !xdt2.left ? ct->left + 1 : ct->left);
552 ct->right = ")";
553 xdt2.left = NULL;
555 while (num--)
556 ct->right = str_printf(sym, "%s[%s]", ct->right, get_number(sym));
559 /* Recurse to get the referred-to type */
560 if (!demangle_datatype(sym, &sub_ct, pmt_ref, 0))
561 return FALSE;
562 if (sub_ct.flags & DT_NO_LEADING_WS)
563 ct->left++;
564 ct->left = str_printf(sym, "%s%s%s%s%s", sub_ct.left, xdt2.left ? " " : NULL,
565 xdt2.left, ct->left,
566 ((xdt2.left || str_qualif) && (flags & WS_AFTER_QUAL_IF)) ? " " : NULL);
567 if (sub_ct.right) ct->right = str_printf(sym, "%s%s", ct->right, sub_ct.right);
568 sym->stack.num = mark;
570 else if (ref || str_qualif || xdt1.left || xdt1.right)
571 ct->left = str_printf(sym, "%s%s%s%s%s%s",
572 xdt1.left ? " " : NULL, xdt1.left, ref,
573 xdt1.right ? " " : NULL, xdt1.right, str_qualif);
574 else
575 ct->left = NULL;
576 return TRUE;
579 /******************************************************************
580 * get_literal_string
581 * Gets the literal name from the current position in the mangled
582 * symbol to the first '@' character. It pushes the parsed name to
583 * the symbol names stack and returns a pointer to it or NULL in
584 * case of an error.
586 static char* get_literal_string(struct parsed_symbol* sym)
588 const char *ptr = sym->current;
590 do {
591 if (!((*sym->current >= 'A' && *sym->current <= 'Z') ||
592 (*sym->current >= 'a' && *sym->current <= 'z') ||
593 (*sym->current >= '0' && *sym->current <= '9') ||
594 *sym->current == '_' || *sym->current == '$')) {
595 TRACE("Failed at '%c' in %s\n", *sym->current, debugstr_a(ptr));
596 return NULL;
598 } while (*++sym->current != '@');
599 sym->current++;
600 if (!str_array_push(sym, ptr, sym->current - 1 - ptr, &sym->names))
601 return NULL;
603 return str_array_get_ref(&sym->names, sym->names.num - sym->names.start - 1);
606 /******************************************************************
607 * get_template_name
608 * Parses a name with a template argument list and returns it as
609 * a string.
610 * In a template argument list the back reference to the names
611 * table is separately created. '0' points to the class component
612 * name with the template arguments. We use the same stack array
613 * to hold the names but save/restore the stack state before/after
614 * parsing the template argument list.
616 static char* get_template_name(struct parsed_symbol* sym)
618 char *name, *args;
619 unsigned num_mark = sym->names.num;
620 unsigned start_mark = sym->names.start;
621 unsigned stack_mark = sym->stack.num;
622 struct array array_pmt;
624 sym->names.start = sym->names.num;
625 if (!(name = get_literal_string(sym))) {
626 sym->names.start = start_mark;
627 return FALSE;
629 str_array_init(&array_pmt);
630 args = get_args(sym, &array_pmt, FALSE, '<', '>');
631 if (args != NULL)
632 name = str_printf(sym, "%s%s", name, args);
633 sym->names.num = num_mark;
634 sym->names.start = start_mark;
635 sym->stack.num = stack_mark;
636 return name;
639 /******************************************************************
640 * get_class
641 * Parses class as a list of parent-classes, terminated by '@' and stores the
642 * result in 'a' array. Each parent-classes, as well as the inner element
643 * (either field/method name or class name), are represented in the mangled
644 * name by a literal name ([a-zA-Z0-9_]+ terminated by '@') or a back reference
645 * ([0-9]) or a name with template arguments ('?$' literal name followed by the
646 * template argument list). The class name components appear in the reverse
647 * order in the mangled name, e.g aaa@bbb@ccc@@ will be demangled to
648 * ccc::bbb::aaa
649 * For each of these class name components a string will be allocated in the
650 * array.
652 static BOOL get_class(struct parsed_symbol* sym)
654 const char* name = NULL;
656 while (*sym->current != '@')
658 switch (*sym->current)
660 case '\0': return FALSE;
662 case '0': case '1': case '2': case '3':
663 case '4': case '5': case '6': case '7':
664 case '8': case '9':
665 name = str_array_get_ref(&sym->names, *sym->current++ - '0');
666 break;
667 case '?':
668 switch (*++sym->current)
670 case '$':
671 sym->current++;
672 if ((name = get_template_name(sym)) &&
673 !str_array_push(sym, name, -1, &sym->names))
674 return FALSE;
675 break;
676 case '?':
678 struct array stack = sym->stack;
679 unsigned int start = sym->names.start;
680 unsigned int num = sym->names.num;
682 str_array_init( &sym->stack );
683 if (symbol_demangle( sym )) name = str_printf( sym, "`%s'", sym->result );
684 sym->names.start = start;
685 sym->names.num = num;
686 sym->stack = stack;
688 break;
689 default:
690 if (!(name = get_number( sym ))) return FALSE;
691 name = str_printf( sym, "`%s'", name );
692 break;
694 break;
695 default:
696 name = get_literal_string(sym);
697 break;
699 if (!name || !str_array_push(sym, name, -1, &sym->stack))
700 return FALSE;
702 sym->current++;
703 return TRUE;
706 /******************************************************************
707 * get_class_string
708 * From an array collected by get_class in sym->stack, constructs the
709 * corresponding (allocated) string
711 static char* get_class_string(struct parsed_symbol* sym, int start)
713 int i;
714 unsigned int len, sz;
715 char* ret;
716 struct array *a = &sym->stack;
718 for (len = 0, i = start; i < a->num; i++)
720 assert(a->elts[i]);
721 len += 2 + strlen(a->elts[i]);
723 if (!(ret = und_alloc(sym, len - 1))) return NULL;
724 for (len = 0, i = a->num - 1; i >= start; i--)
726 sz = strlen(a->elts[i]);
727 memcpy(ret + len, a->elts[i], sz);
728 len += sz;
729 if (i > start)
731 ret[len++] = ':';
732 ret[len++] = ':';
735 ret[len] = '\0';
736 return ret;
739 /******************************************************************
740 * get_class_name
741 * Wrapper around get_class and get_class_string.
743 static char* get_class_name(struct parsed_symbol* sym)
745 unsigned mark = sym->stack.num;
746 char* s = NULL;
748 if (get_class(sym))
749 s = get_class_string(sym, mark);
750 sym->stack.num = mark;
751 return s;
754 /******************************************************************
755 * get_calling_convention
756 * Returns a static string corresponding to the calling convention described
757 * by char 'ch'. Sets export to TRUE iff the calling convention is exported.
759 static BOOL get_calling_convention(char ch, const char** call_conv,
760 const char** exported, unsigned flags)
762 *call_conv = *exported = NULL;
764 if (!(flags & (UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ALLOCATION_LANGUAGE)))
766 if (flags & UNDNAME_NO_LEADING_UNDERSCORES)
768 if (((ch - 'A') % 2) == 1) *exported = "dll_export ";
769 switch (ch)
771 case 'A': case 'B': *call_conv = "cdecl"; break;
772 case 'C': case 'D': *call_conv = "pascal"; break;
773 case 'E': case 'F': *call_conv = "thiscall"; break;
774 case 'G': case 'H': *call_conv = "stdcall"; break;
775 case 'I': case 'J': *call_conv = "fastcall"; break;
776 case 'K': case 'L': break;
777 case 'M': *call_conv = "clrcall"; break;
778 default: ERR("Unknown calling convention %c\n", ch); return FALSE;
781 else
783 if (((ch - 'A') % 2) == 1) *exported = "__dll_export ";
784 switch (ch)
786 case 'A': case 'B': *call_conv = "__cdecl"; break;
787 case 'C': case 'D': *call_conv = "__pascal"; break;
788 case 'E': case 'F': *call_conv = "__thiscall"; break;
789 case 'G': case 'H': *call_conv = "__stdcall"; break;
790 case 'I': case 'J': *call_conv = "__fastcall"; break;
791 case 'K': case 'L': break;
792 case 'M': *call_conv = "__clrcall"; break;
793 default: ERR("Unknown calling convention %c\n", ch); return FALSE;
797 return TRUE;
800 /*******************************************************************
801 * get_simple_type
802 * Return a string containing an allocated string for a simple data type
804 static const char* get_simple_type(char c)
806 const char* type_string;
808 switch (c)
810 case 'C': type_string = "signed char"; break;
811 case 'D': type_string = "char"; break;
812 case 'E': type_string = "unsigned char"; break;
813 case 'F': type_string = "short"; break;
814 case 'G': type_string = "unsigned short"; break;
815 case 'H': type_string = "int"; break;
816 case 'I': type_string = "unsigned int"; break;
817 case 'J': type_string = "long"; break;
818 case 'K': type_string = "unsigned long"; break;
819 case 'M': type_string = "float"; break;
820 case 'N': type_string = "double"; break;
821 case 'O': type_string = "long double"; break;
822 case 'X': type_string = "void"; break;
823 case 'Z': type_string = "..."; break;
824 default: type_string = NULL; break;
826 return type_string;
829 /*******************************************************************
830 * get_extended_type
831 * Return a string containing an allocated string for a simple data type
833 static const char* get_extended_type(char c)
835 const char* type_string;
837 switch (c)
839 case 'D': type_string = "__int8"; break;
840 case 'E': type_string = "unsigned __int8"; break;
841 case 'F': type_string = "__int16"; break;
842 case 'G': type_string = "unsigned __int16"; break;
843 case 'H': type_string = "__int32"; break;
844 case 'I': type_string = "unsigned __int32"; break;
845 case 'J': type_string = "__int64"; break;
846 case 'K': type_string = "unsigned __int64"; break;
847 case 'L': type_string = "__int128"; break;
848 case 'M': type_string = "unsigned __int128"; break;
849 case 'N': type_string = "bool"; break;
850 case 'Q': type_string = "char8_t"; break;
851 case 'S': type_string = "char16_t"; break;
852 case 'U': type_string = "char32_t"; break;
853 case 'W': type_string = "wchar_t"; break;
854 default: type_string = NULL; break;
856 return type_string;
859 struct function_signature
861 const char* call_conv;
862 const char* exported;
863 struct datatype_t return_ct;
864 const char* arguments;
867 static BOOL get_function_signature(struct parsed_symbol* sym, struct array* pmt_ref,
868 struct function_signature* fs)
870 unsigned mark = sym->stack.num;
872 if (!get_calling_convention(*sym->current++,
873 &fs->call_conv, &fs->exported,
874 sym->flags & ~UNDNAME_NO_ALLOCATION_LANGUAGE) ||
875 !demangle_datatype(sym, &fs->return_ct, pmt_ref, FALSE))
876 return FALSE;
878 if (!(fs->arguments = get_args(sym, pmt_ref, TRUE, '(', ')')))
879 return FALSE;
880 sym->stack.num = mark;
882 return TRUE;
885 /*******************************************************************
886 * demangle_datatype
888 * Attempt to demangle a C++ data type, which may be datatype.
889 * a datatype type is made up of a number of simple types. e.g:
890 * char** = (pointer to (pointer to (char)))
892 static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
893 struct array* pmt_ref, enum datatype_flags flags)
895 char dt;
896 BOOL add_pmt = TRUE;
898 assert(ct);
899 ct->left = ct->right = NULL;
900 ct->flags = 0;
902 switch (dt = *sym->current++)
904 case '_':
905 /* MS type: __int8,__int16 etc */
906 ct->left = get_extended_type(*sym->current++);
907 break;
908 case 'C': case 'D': case 'E': case 'F': case 'G':
909 case 'H': case 'I': case 'J': case 'K': case 'M':
910 case 'N': case 'O': case 'X': case 'Z':
911 /* Simple data types */
912 ct->left = get_simple_type(dt);
913 add_pmt = FALSE;
914 break;
915 case 'T': /* union */
916 case 'U': /* struct */
917 case 'V': /* class */
918 case 'Y': /* cointerface */
919 /* Class/struct/union/cointerface */
921 const char* struct_name = NULL;
922 const char* type_name = NULL;
924 if (!(struct_name = get_class_name(sym)))
925 goto done;
926 if (!(sym->flags & UNDNAME_NO_COMPLEX_TYPE))
928 switch (dt)
930 case 'T': type_name = "union "; break;
931 case 'U': type_name = "struct "; break;
932 case 'V': type_name = "class "; break;
933 case 'Y': type_name = "cointerface "; break;
936 ct->left = str_printf(sym, "%s%s", type_name, struct_name);
938 break;
939 case '?':
940 /* not all the time is seems */
941 if (flags & IN_ARGS)
943 const char* ptr;
944 if (!(ptr = get_number(sym))) goto done;
945 ct->left = str_printf(sym, "`template-parameter-%s'", ptr);
947 else
949 if (!get_qualified_type(ct, sym, pmt_ref, '?', flags)) goto done;
951 break;
952 case 'A': /* reference */
953 case 'B': /* volatile reference */
954 if (!get_qualified_type(ct, sym, pmt_ref, dt, flags)) goto done;
955 break;
956 case 'Q': /* const pointer */
957 case 'R': /* volatile pointer */
958 case 'S': /* const volatile pointer */
959 if (!get_qualified_type(ct, sym, pmt_ref, (flags & IN_ARGS) ? dt : 'P', flags)) goto done;
960 break;
961 case 'P': /* Pointer */
962 if (isdigit(*sym->current))
964 /* FIXME:
965 * P6 = Function pointer
966 * P8 = Member function pointer
967 * others who knows.. */
968 if (*sym->current == '8')
970 struct function_signature fs;
971 const char* class;
972 const char* function_qualifier;
974 sym->current++;
976 if (!(class = get_class_name(sym)))
977 goto done;
978 if (!get_function_qualifier(sym, &function_qualifier))
979 goto done;
980 if (!get_function_signature(sym, pmt_ref, &fs))
981 goto done;
983 ct->left = str_printf(sym, "%s%s (%s %s::*",
984 fs.return_ct.left, fs.return_ct.right, fs.call_conv, class);
985 ct->right = str_printf(sym, ")%s%s", fs.arguments, function_qualifier);
987 else if (*sym->current == '6')
989 struct function_signature fs;
991 sym->current++;
993 if (!get_function_signature(sym, pmt_ref, &fs))
994 goto done;
996 ct->left = str_printf(sym, "%s%s (%s*",
997 fs.return_ct.left, fs.return_ct.right, fs.call_conv);
998 ct->flags = DT_NO_LEADING_WS;
999 ct->right = str_printf(sym, ")%s", fs.arguments);
1001 else goto done;
1003 else if (!get_qualified_type(ct, sym, pmt_ref, 'P', flags)) goto done;
1004 break;
1005 case 'W':
1006 if (*sym->current == '4')
1008 char* enum_name;
1009 sym->current++;
1010 if (!(enum_name = get_class_name(sym)))
1011 goto done;
1012 if (sym->flags & UNDNAME_NO_COMPLEX_TYPE)
1013 ct->left = enum_name;
1014 else
1015 ct->left = str_printf(sym, "enum %s", enum_name);
1017 else goto done;
1018 break;
1019 case '0': case '1': case '2': case '3': case '4':
1020 case '5': case '6': case '7': case '8': case '9':
1021 /* Referring back to previously parsed type */
1022 /* left and right are pushed as two separate strings */
1023 if (!pmt_ref) goto done;
1024 ct->left = str_array_get_ref(pmt_ref, (dt - '0') * 2);
1025 ct->right = str_array_get_ref(pmt_ref, (dt - '0') * 2 + 1);
1026 if (!ct->left) goto done;
1027 add_pmt = FALSE;
1028 break;
1029 case '$':
1030 switch (*sym->current++)
1032 case '0':
1033 if (!(ct->left = get_number(sym))) goto done;
1034 break;
1035 case 'D':
1037 const char* ptr;
1038 if (!(ptr = get_number(sym))) goto done;
1039 ct->left = str_printf(sym, "`template-parameter%s'", ptr);
1041 break;
1042 case 'F':
1044 const char* p1;
1045 const char* p2;
1046 if (!(p1 = get_number(sym))) goto done;
1047 if (!(p2 = get_number(sym))) goto done;
1048 ct->left = str_printf(sym, "{%s,%s}", p1, p2);
1050 break;
1051 case 'G':
1053 const char* p1;
1054 const char* p2;
1055 const char* p3;
1056 if (!(p1 = get_number(sym))) goto done;
1057 if (!(p2 = get_number(sym))) goto done;
1058 if (!(p3 = get_number(sym))) goto done;
1059 ct->left = str_printf(sym, "{%s,%s,%s}", p1, p2, p3);
1061 break;
1062 case 'Q':
1064 const char* ptr;
1065 if (!(ptr = get_number(sym))) goto done;
1066 ct->left = str_printf(sym, "`non-type-template-parameter%s'", ptr);
1068 break;
1069 case '$':
1070 if (*sym->current == 'A')
1072 sym->current++;
1073 if (*sym->current == '6')
1075 struct function_signature fs;
1077 sym->current++;
1079 if (!get_function_signature(sym, pmt_ref, &fs))
1080 goto done;
1081 ct->left = str_printf(sym, "%s%s %s%s",
1082 fs.return_ct.left, fs.return_ct.right, fs.call_conv, fs.arguments);
1085 else if (*sym->current == 'B')
1087 unsigned mark = sym->stack.num;
1088 struct datatype_t sub_ct;
1089 const char* arr = NULL;
1090 sym->current++;
1092 /* multidimensional arrays */
1093 if (*sym->current == 'Y')
1095 const char* n1;
1096 int num;
1098 sym->current++;
1099 if (!(n1 = get_number(sym))) goto done;
1100 num = atoi(n1);
1102 while (num--)
1103 arr = str_printf(sym, "%s[%s]", arr, get_number(sym));
1106 if (!demangle_datatype(sym, &sub_ct, pmt_ref, 0)) goto done;
1108 if (arr)
1109 ct->left = str_printf(sym, "%s %s", sub_ct.left, arr);
1110 else
1111 ct->left = sub_ct.left;
1112 ct->right = sub_ct.right;
1113 sym->stack.num = mark;
1115 else if (*sym->current == 'C')
1117 struct datatype_t xdt;
1119 sym->current++;
1120 if (!get_qualifier(sym, &xdt, NULL)) goto done;
1121 if (!demangle_datatype(sym, ct, pmt_ref, flags)) goto done;
1122 ct->left = str_printf(sym, "%s %s", ct->left, xdt.left);
1124 else if (*sym->current == 'Q')
1126 sym->current++;
1127 if (!get_qualified_type(ct, sym, pmt_ref, '$', flags)) goto done;
1129 break;
1131 break;
1132 default :
1133 ERR("Unknown type %c\n", dt);
1134 break;
1136 if (add_pmt && pmt_ref && (flags & IN_ARGS))
1138 /* left and right are pushed as two separate strings */
1139 if (!str_array_push(sym, ct->left ? ct->left : "", -1, pmt_ref) ||
1140 !str_array_push(sym, ct->right ? ct->right : "", -1, pmt_ref))
1141 return FALSE;
1143 done:
1145 return ct->left != NULL;
1148 /******************************************************************
1149 * handle_data
1150 * Does the final parsing and handling for a variable or a field in
1151 * a class.
1153 static BOOL handle_data(struct parsed_symbol* sym)
1155 const char* access = NULL;
1156 const char* member_type = NULL;
1157 struct datatype_t xdt = {NULL};
1158 struct datatype_t ct;
1159 char* name = NULL;
1160 BOOL ret = FALSE;
1162 /* 0 private static
1163 * 1 protected static
1164 * 2 public static
1165 * 3 private non-static
1166 * 4 protected non-static
1167 * 5 public non-static
1168 * 6 ?? static
1169 * 7 ?? static
1172 if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS))
1174 /* we only print the access for static members */
1175 switch (*sym->current)
1177 case '0': access = "private: "; break;
1178 case '1': access = "protected: "; break;
1179 case '2': access = "public: "; break;
1183 if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE))
1185 if (*sym->current >= '0' && *sym->current <= '2')
1186 member_type = "static ";
1189 name = get_class_string(sym, 0);
1191 switch (*sym->current++)
1193 case '0': case '1': case '2':
1194 case '3': case '4': case '5':
1196 unsigned mark = sym->stack.num;
1197 struct array pmt;
1198 const char* class;
1200 str_array_init(&pmt);
1202 if (!demangle_datatype(sym, &ct, &pmt, 0)) goto done;
1203 if (!get_qualifier(sym, &xdt, &class)) goto done; /* class doesn't seem to be displayed */
1204 if (xdt.left && xdt.right) xdt.left = str_printf(sym, "%s %s", xdt.left, xdt.right);
1205 else if (!xdt.left) xdt.left = xdt.right;
1206 sym->stack.num = mark;
1208 break;
1209 case '6' : /* compiler generated static */
1210 case '7' : /* compiler generated static */
1211 ct.left = ct.right = NULL;
1212 if (!get_qualifier(sym, &xdt, NULL)) goto done;
1213 if (*sym->current != '@')
1215 char* cls = NULL;
1217 if (!(cls = get_class_name(sym)))
1218 goto done;
1219 ct.right = str_printf(sym, "{for `%s'}", cls);
1221 break;
1222 case '8':
1223 case '9':
1224 xdt.left = ct.left = ct.right = NULL;
1225 break;
1226 default: goto done;
1228 if (sym->flags & UNDNAME_NAME_ONLY) ct.left = ct.right = xdt.left = NULL;
1230 sym->result = str_printf(sym, "%s%s%s%s%s%s%s%s", access,
1231 member_type, ct.left,
1232 xdt.left && ct.left ? " " : NULL, xdt.left,
1233 xdt.left || ct.left ? " " : NULL, name, ct.right);
1234 ret = TRUE;
1235 done:
1236 return ret;
1239 /******************************************************************
1240 * handle_method
1241 * Does the final parsing and handling for a function or a method in
1242 * a class.
1244 static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
1246 char accmem;
1247 const char* access = NULL;
1248 int access_id = -1;
1249 const char* member_type = NULL;
1250 struct datatype_t ct_ret;
1251 const char* call_conv;
1252 const char* function_qualifier = NULL;
1253 const char* exported;
1254 const char* args_str = NULL;
1255 const char* name = NULL;
1256 BOOL ret = FALSE, has_args = TRUE, has_ret = TRUE;
1257 unsigned mark;
1258 struct array array_pmt;
1260 /* FIXME: why 2 possible letters for each option?
1261 * 'A' private:
1262 * 'B' private:
1263 * 'C' private: static
1264 * 'D' private: static
1265 * 'E' private: virtual
1266 * 'F' private: virtual
1267 * 'G' private: thunk
1268 * 'H' private: thunk
1269 * 'I' protected:
1270 * 'J' protected:
1271 * 'K' protected: static
1272 * 'L' protected: static
1273 * 'M' protected: virtual
1274 * 'N' protected: virtual
1275 * 'O' protected: thunk
1276 * 'P' protected: thunk
1277 * 'Q' public:
1278 * 'R' public:
1279 * 'S' public: static
1280 * 'T' public: static
1281 * 'U' public: virtual
1282 * 'V' public: virtual
1283 * 'W' public: thunk
1284 * 'X' public: thunk
1285 * 'Y'
1286 * 'Z'
1287 * "$0" private: thunk vtordisp
1288 * "$1" private: thunk vtordisp
1289 * "$2" protected: thunk vtordisp
1290 * "$3" protected: thunk vtordisp
1291 * "$4" public: thunk vtordisp
1292 * "$5" public: thunk vtordisp
1293 * "$B" vcall thunk
1294 * "$R" thunk vtordispex
1296 accmem = *sym->current++;
1297 if (accmem == '$')
1299 if (*sym->current >= '0' && *sym->current <= '5')
1300 access_id = (*sym->current - '0') / 2;
1301 else if (*sym->current == 'R')
1302 access_id = (sym->current[1] - '0') / 2;
1303 else if (*sym->current != 'B')
1304 goto done;
1306 else if (accmem >= 'A' && accmem <= 'Z')
1307 access_id = (accmem - 'A') / 8;
1308 else
1309 goto done;
1311 switch (access_id)
1313 case 0: access = "private: "; break;
1314 case 1: access = "protected: "; break;
1315 case 2: access = "public: "; break;
1317 if (accmem == '$' || (accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7)
1318 access = str_printf(sym, "[thunk]:%s", access ? access : " ");
1320 if (accmem == '$' && *sym->current != 'B')
1321 member_type = "virtual ";
1322 else if (accmem <= 'X')
1324 switch ((accmem - 'A') % 8)
1326 case 2: case 3: member_type = "static "; break;
1327 case 4: case 5: case 6: case 7: member_type = "virtual "; break;
1331 if (sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS)
1332 access = NULL;
1333 if (sym->flags & UNDNAME_NO_MEMBER_TYPE)
1334 member_type = NULL;
1336 name = get_class_string(sym, 0);
1338 if (accmem == '$' && *sym->current == 'B') /* vcall thunk */
1340 const char *n;
1342 sym->current++;
1343 n = get_number(sym);
1345 if(!n || *sym->current++ != 'A') goto done;
1346 name = str_printf(sym, "%s{%s,{flat}}' }'", name, n);
1347 has_args = FALSE;
1348 has_ret = FALSE;
1350 else if (accmem == '$' && *sym->current == 'R') /* vtordispex thunk */
1352 const char *n1, *n2, *n3, *n4;
1354 sym->current += 2;
1355 n1 = get_number(sym);
1356 n2 = get_number(sym);
1357 n3 = get_number(sym);
1358 n4 = get_number(sym);
1360 if(!n1 || !n2 || !n3 || !n4) goto done;
1361 name = str_printf(sym, "%s`vtordispex{%s,%s,%s,%s}' ", name, n1, n2, n3, n4);
1363 else if (accmem == '$') /* vtordisp thunk */
1365 const char *n1, *n2;
1367 sym->current++;
1368 n1 = get_number(sym);
1369 n2 = get_number(sym);
1371 if (!n1 || !n2) goto done;
1372 name = str_printf(sym, "%s`vtordisp{%s,%s}' ", name, n1, n2);
1374 else if ((accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) /* a thunk */
1375 name = str_printf(sym, "%s`adjustor{%s}' ", name, get_number(sym));
1377 if (has_args && (accmem == '$' ||
1378 (accmem <= 'X' && (accmem - 'A') % 8 != 2 && (accmem - 'A') % 8 != 3)))
1380 /* Implicit 'this' pointer */
1381 if (!get_function_qualifier(sym, &function_qualifier)) goto done;
1384 if (!get_calling_convention(*sym->current++, &call_conv, &exported,
1385 sym->flags))
1386 goto done;
1388 str_array_init(&array_pmt);
1390 /* Return type, or @ if 'void' */
1391 if (has_ret && *sym->current == '@')
1393 ct_ret.left = "void";
1394 ct_ret.right = NULL;
1395 sym->current++;
1397 else if (has_ret)
1399 if (!demangle_datatype(sym, &ct_ret, &array_pmt, cast_op ? WS_AFTER_QUAL_IF : 0))
1400 goto done;
1402 if (!has_ret || sym->flags & UNDNAME_NO_FUNCTION_RETURNS)
1403 ct_ret.left = ct_ret.right = NULL;
1404 if (cast_op)
1406 name = str_printf(sym, "%s %s%s", name, ct_ret.left, ct_ret.right);
1407 ct_ret.left = ct_ret.right = NULL;
1410 mark = sym->stack.num;
1411 if (has_args && !(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done;
1412 if (sym->flags & UNDNAME_NAME_ONLY) args_str = function_qualifier = NULL;
1413 if (sym->flags & UNDNAME_NO_THISTYPE) function_qualifier = NULL;
1414 sym->stack.num = mark;
1416 /* Note: '()' after 'Z' means 'throws', but we don't care here
1417 * Yet!!! FIXME
1419 sym->result = str_printf(sym, "%s%s%s%s%s%s%s%s%s%s%s",
1420 access, member_type, ct_ret.left,
1421 (ct_ret.left && !ct_ret.right) ? " " : NULL,
1422 call_conv, call_conv ? " " : NULL, exported,
1423 name, args_str, function_qualifier, ct_ret.right);
1424 ret = TRUE;
1425 done:
1426 return ret;
1429 /*******************************************************************
1430 * symbol_demangle
1431 * Demangle a C++ linker symbol
1433 static BOOL symbol_demangle(struct parsed_symbol* sym)
1435 BOOL ret = FALSE;
1436 enum {
1437 PP_NONE,
1438 PP_CONSTRUCTOR,
1439 PP_DESTRUCTOR,
1440 PP_CAST_OPERATOR,
1441 } post_process = PP_NONE;
1443 /* FIXME seems wrong as name, as it demangles a simple data type */
1444 if (sym->flags & UNDNAME_NO_ARGUMENTS)
1446 struct datatype_t ct;
1448 if (demangle_datatype(sym, &ct, NULL, 0))
1450 sym->result = str_printf(sym, "%s%s", ct.left, ct.right);
1451 ret = TRUE;
1453 goto done;
1456 /* MS mangled names always begin with '?' */
1457 if (*sym->current != '?') return FALSE;
1458 sym->current++;
1460 /* Then function name or operator code */
1461 if (*sym->current == '?')
1463 const char* function_name = NULL;
1464 BOOL in_template = FALSE;
1466 if (sym->current[1] == '$' && sym->current[2] == '?')
1468 in_template = TRUE;
1469 sym->current += 2;
1472 /* C++ operator code (one character, or two if the first is '_') */
1473 switch (*++sym->current)
1475 case '0': function_name = ""; post_process = PP_CONSTRUCTOR; break;
1476 case '1': function_name = ""; post_process = PP_DESTRUCTOR; break;
1477 case '2': function_name = "operator new"; break;
1478 case '3': function_name = "operator delete"; break;
1479 case '4': function_name = "operator="; break;
1480 case '5': function_name = "operator>>"; break;
1481 case '6': function_name = "operator<<"; break;
1482 case '7': function_name = "operator!"; break;
1483 case '8': function_name = "operator=="; break;
1484 case '9': function_name = "operator!="; break;
1485 case 'A': function_name = "operator[]"; break;
1486 case 'B': function_name = "operator"; post_process = PP_CAST_OPERATOR; break;
1487 case 'C': function_name = "operator->"; break;
1488 case 'D': function_name = "operator*"; break;
1489 case 'E': function_name = "operator++"; break;
1490 case 'F': function_name = "operator--"; break;
1491 case 'G': function_name = "operator-"; break;
1492 case 'H': function_name = "operator+"; break;
1493 case 'I': function_name = "operator&"; break;
1494 case 'J': function_name = "operator->*"; break;
1495 case 'K': function_name = "operator/"; break;
1496 case 'L': function_name = "operator%"; break;
1497 case 'M': function_name = "operator<"; break;
1498 case 'N': function_name = "operator<="; break;
1499 case 'O': function_name = "operator>"; break;
1500 case 'P': function_name = "operator>="; break;
1501 case 'Q': function_name = "operator,"; break;
1502 case 'R': function_name = "operator()"; break;
1503 case 'S': function_name = "operator~"; break;
1504 case 'T': function_name = "operator^"; break;
1505 case 'U': function_name = "operator|"; break;
1506 case 'V': function_name = "operator&&"; break;
1507 case 'W': function_name = "operator||"; break;
1508 case 'X': function_name = "operator*="; break;
1509 case 'Y': function_name = "operator+="; break;
1510 case 'Z': function_name = "operator-="; break;
1511 case '_':
1512 switch (*++sym->current)
1514 case '0': function_name = "operator/="; break;
1515 case '1': function_name = "operator%="; break;
1516 case '2': function_name = "operator>>="; break;
1517 case '3': function_name = "operator<<="; break;
1518 case '4': function_name = "operator&="; break;
1519 case '5': function_name = "operator|="; break;
1520 case '6': function_name = "operator^="; break;
1521 case '7': function_name = "`vftable'"; break;
1522 case '8': function_name = "`vbtable'"; break;
1523 case '9': function_name = "`vcall'"; break;
1524 case 'A': function_name = "`typeof'"; break;
1525 case 'B': function_name = "`local static guard'"; break;
1526 case 'C': sym->result = (char*)"`string'"; /* string literal: followed by string encoding (native never undecode it) */
1527 /* FIXME: should unmangle the whole string for error reporting */
1528 if (*sym->current && sym->current[strlen(sym->current) - 1] == '@') ret = TRUE;
1529 goto done;
1530 case 'D': function_name = "`vbase destructor'"; break;
1531 case 'E': function_name = "`vector deleting destructor'"; break;
1532 case 'F': function_name = "`default constructor closure'"; break;
1533 case 'G': function_name = "`scalar deleting destructor'"; break;
1534 case 'H': function_name = "`vector constructor iterator'"; break;
1535 case 'I': function_name = "`vector destructor iterator'"; break;
1536 case 'J': function_name = "`vector vbase constructor iterator'"; break;
1537 case 'K': function_name = "`virtual displacement map'"; break;
1538 case 'L': function_name = "`eh vector constructor iterator'"; break;
1539 case 'M': function_name = "`eh vector destructor iterator'"; break;
1540 case 'N': function_name = "`eh vector vbase constructor iterator'"; break;
1541 case 'O': function_name = "`copy constructor closure'"; break;
1542 case 'R':
1543 sym->flags |= UNDNAME_NO_FUNCTION_RETURNS;
1544 switch (*++sym->current)
1546 case '0':
1548 struct datatype_t ct;
1550 sym->current++;
1551 if (!demangle_datatype(sym, &ct, NULL, 0))
1552 goto done;
1553 function_name = str_printf(sym, "%s%s `RTTI Type Descriptor'",
1554 ct.left, ct.right);
1555 sym->current--;
1557 break;
1558 case '1':
1560 const char* n1, *n2, *n3, *n4;
1561 sym->current++;
1562 n1 = get_number(sym);
1563 n2 = get_number(sym);
1564 n3 = get_number(sym);
1565 n4 = get_number(sym);
1566 sym->current--;
1567 function_name = str_printf(sym, "`RTTI Base Class Descriptor at (%s,%s,%s,%s)'",
1568 n1, n2, n3, n4);
1570 break;
1571 case '2': function_name = "`RTTI Base Class Array'"; break;
1572 case '3': function_name = "`RTTI Class Hierarchy Descriptor'"; break;
1573 case '4': function_name = "`RTTI Complete Object Locator'"; break;
1574 default:
1575 ERR("Unknown RTTI operator: _R%c\n", *sym->current);
1576 break;
1578 break;
1579 case 'S': function_name = "`local vftable'"; break;
1580 case 'T': function_name = "`local vftable constructor closure'"; break;
1581 case 'U': function_name = "operator new[]"; break;
1582 case 'V': function_name = "operator delete[]"; break;
1583 case 'X': function_name = "`placement delete closure'"; break;
1584 case 'Y': function_name = "`placement delete[] closure'"; break;
1585 case '_':
1586 switch (*++sym->current)
1588 case 'K':
1589 sym->current++;
1590 function_name = str_printf(sym, "operator \"\" %s", get_literal_string(sym));
1591 --sym->current;
1592 break;
1593 default:
1594 FIXME("Unknown operator: __%c\n", *sym->current);
1595 return FALSE;
1597 break;
1598 default:
1599 ERR("Unknown operator: _%c\n", *sym->current);
1600 return FALSE;
1602 break;
1603 case '$':
1604 sym->current++;
1605 if (!(function_name = get_template_name(sym))) goto done;
1606 --sym->current;
1607 break;
1608 default:
1609 /* FIXME: Other operators */
1610 ERR("Unknown operator: %c\n", *sym->current);
1611 return FALSE;
1613 sym->current++;
1614 if (in_template)
1616 const char *args;
1617 struct array array_pmt;
1619 str_array_init(&array_pmt);
1620 args = get_args(sym, &array_pmt, FALSE, '<', '>');
1621 if (args) function_name = function_name ? str_printf(sym, "%s%s", function_name, args) : args;
1622 sym->names.num = 0;
1624 if (!str_array_push(sym, function_name, -1, &sym->stack))
1625 return FALSE;
1627 else if (*sym->current == '$')
1629 /* Strange construct, it's a name with a template argument list
1630 and that's all. */
1631 sym->current++;
1632 ret = (sym->result = get_template_name(sym)) != NULL;
1633 goto done;
1636 /* Either a class name, or '@' if the symbol is not a class member */
1637 switch (*sym->current)
1639 case '@': sym->current++; break;
1640 case '$': break;
1641 default:
1642 /* Class the function is associated with, terminated by '@@' */
1643 if (!get_class(sym)) goto done;
1644 break;
1647 switch (post_process)
1649 case PP_NONE: default: break;
1650 case PP_CONSTRUCTOR: case PP_DESTRUCTOR:
1651 /* it's time to set the member name for ctor & dtor */
1652 if (sym->stack.num <= 1) goto done;
1653 sym->stack.elts[0] = str_printf(sym, "%s%s%s", post_process == PP_DESTRUCTOR ? "~" : NULL,
1654 sym->stack.elts[1], sym->stack.elts[0]);
1655 /* ctors and dtors don't have return type */
1656 sym->flags |= UNDNAME_NO_FUNCTION_RETURNS;
1657 break;
1658 case PP_CAST_OPERATOR:
1659 sym->flags &= ~UNDNAME_NO_FUNCTION_RETURNS;
1660 break;
1663 /* Function/Data type and access level */
1664 if (*sym->current >= '0' && *sym->current <= '9')
1665 ret = handle_data(sym);
1666 else if ((*sym->current >= 'A' && *sym->current <= 'Z') || *sym->current == '$')
1667 ret = handle_method(sym, post_process == PP_CAST_OPERATOR);
1668 else ret = FALSE;
1669 done:
1670 if (ret) assert(sym->result);
1671 else WARN("Failed at %s\n", debugstr_a(sym->current));
1673 return ret;
1676 /*********************************************************************
1677 * __unDNameEx (MSVCRT.@)
1679 * Demangle a C++ identifier.
1681 * PARAMS
1682 * buffer [O] If not NULL, the place to put the demangled string
1683 * mangled [I] Mangled name of the function
1684 * buflen [I] Length of buffer
1685 * memget [I] Function to allocate memory with
1686 * memfree [I] Function to free memory with
1687 * unknown [?] Unknown, possibly a call back
1688 * flags [I] Flags determining demangled format
1690 * RETURNS
1691 * Success: A string pointing to the unmangled name, allocated with memget.
1692 * Failure: NULL.
1694 char* CDECL __unDNameEx(char* buffer, const char* mangled, int buflen,
1695 malloc_func_t memget, free_func_t memfree,
1696 void* unknown, unsigned short int flags)
1698 struct parsed_symbol sym;
1699 const char* result;
1701 TRACE("(%p,%s,%d,%p,%p,%p,%x)\n",
1702 buffer, debugstr_a(mangled), buflen, memget, memfree, unknown, flags);
1704 /* The flags details is not documented by MS. However, it looks exactly
1705 * like the UNDNAME_ manifest constants from imagehlp.h and dbghelp.h
1706 * So, we copied those (on top of the file)
1708 memset(&sym, 0, sizeof(struct parsed_symbol));
1709 if (flags & UNDNAME_NAME_ONLY)
1710 flags |= UNDNAME_NO_FUNCTION_RETURNS | UNDNAME_NO_ACCESS_SPECIFIERS |
1711 UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_ALLOCATION_LANGUAGE |
1712 UNDNAME_NO_COMPLEX_TYPE;
1714 sym.flags = flags;
1715 sym.mem_alloc_ptr = memget;
1716 sym.mem_free_ptr = memfree;
1717 sym.current = mangled;
1718 str_array_init( &sym.names );
1719 str_array_init( &sym.stack );
1721 result = symbol_demangle(&sym) ? sym.result : mangled;
1722 if (buffer && buflen)
1724 lstrcpynA( buffer, result, buflen);
1726 else
1728 buffer = memget(strlen(result) + 1);
1729 if (buffer) strcpy(buffer, result);
1732 und_free_all(&sym);
1734 return buffer;
1738 /*********************************************************************
1739 * __unDName (MSVCRT.@)
1741 char* CDECL __unDName(char* buffer, const char* mangled, int buflen,
1742 malloc_func_t memget, free_func_t memfree,
1743 unsigned short int flags)
1745 return __unDNameEx(buffer, mangled, buflen, memget, memfree, NULL, flags);