wined3d: Add UpdatOverlayZOrder.
[wine.git] / dlls / msvcrt / undname.c
bloba775e72d0c541ef8dc05c40dbb3f57bbe3b0ebf9
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 "config.h"
23 #include "wine/port.h"
25 #include <assert.h>
26 #include <stdio.h>
27 #include "msvcrt.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
33 /* TODO:
34 * - document a bit (grammar + functions)
35 * - back-port this new code into tools/winedump/msmangle.c
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)
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 "
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
75 #define MAX_ARRAY_ELTS 32
76 struct array
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];
84 /* Structure holding a parsed symbol */
85 struct parsed_symbol
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 */
91 const char* current; /* pointer in input (mangled) string */
92 char* result; /* demangled string */
94 struct array names; /* array of names for back reference */
95 struct array stack; /* stack of parsed strings */
97 void* alloc_list; /* linked list of allocated blocks */
98 unsigned avail_in_first; /* number of available bytes in head block */
101 /* Type for parsing mangled types */
102 struct datatype_t
104 const char* left;
105 const char* right;
108 /******************************************************************
109 * und_alloc
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).
115 static void* und_alloc(struct parsed_symbol* sym, size_t len)
117 void* ptr;
119 #define BLOCK_SIZE 1024
120 #define AVAIL_SIZE (1024 - sizeof(void*))
122 if (len > AVAIL_SIZE)
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*);
132 else
134 if (len > sym->avail_in_first)
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;
143 /* grab memory from head block */
144 ptr = (char*)sym->alloc_list + BLOCK_SIZE - sym->avail_in_first;
145 sym->avail_in_first -= len;
147 return ptr;
148 #undef BLOCK_SIZE
149 #undef AVAIL_SIZE
152 /******************************************************************
153 * und_free
154 * Frees all the blocks in the list of large blocks allocated by
155 * und_alloc.
157 static void und_free_all(struct parsed_symbol* sym)
159 void* next;
161 while (sym->alloc_list)
163 next = *(void**)sym->alloc_list;
164 if(sym->mem_free_ptr) sym->mem_free_ptr(sym->alloc_list);
165 sym->alloc_list = next;
167 sym->avail_in_first = 0;
170 /******************************************************************
171 * str_array_init
172 * Initialises an array of strings
174 static void str_array_init(struct array* a)
176 a->start = a->num = a->max = 0;
179 /******************************************************************
180 * str_array_push
181 * Adding a new string to an array
183 static void str_array_push(struct parsed_symbol* sym, const char* ptr, size_t len,
184 struct array* a)
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;
196 int i;
197 char c;
199 for (i = a->max - 1; i >= 0; i--)
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]);
209 /******************************************************************
210 * str_array_get_ref
211 * Extracts a reference from an existing array (doing proper type
212 * checking)
214 static char* str_array_get_ref(struct array* cref, unsigned idx)
216 assert(cref);
217 if (cref->start + idx >= cref->max)
219 WARN("Out of bounds: %p %d + %d >= %d\n",
220 cref, cref->start, idx, cref->max);
221 return NULL;
223 TRACE("Returning %p[%d] => %s\n",
224 cref, idx, cref->elts[cref->start + idx]);
225 return cref->elts[cref->start + idx];
228 /******************************************************************
229 * str_printf
230 * Helper for printf type of command (only %s and %c are implemented)
231 * while dynamically allocating the buffer
233 static char* str_printf(struct parsed_symbol* sym, const char* format, ...)
235 va_list args;
236 size_t len = 1, i, sz;
237 char* tmp;
238 char* p;
239 char* t;
241 va_start(args, format);
242 for (i = 0; format[i]; i++)
244 if (format[i] == '%')
246 switch (format[++i])
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;
254 else len++;
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++)
261 if (format[i] == '%')
263 switch (format[++i])
265 case 's':
266 t = va_arg(args, char*);
267 if (t)
269 sz = strlen(t);
270 memcpy(p, t, sz);
271 p += sz;
273 break;
274 case 'c':
275 *p++ = (char)va_arg(args, int);
276 break;
277 default: i--; /* fall thru */
278 case '%': *p++ = '%'; break;
281 else *p++ = format[i];
283 va_end(args);
284 *p = '\0';
285 return tmp;
288 /* forward declaration */
289 static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
290 struct array* pmt, BOOL in_args);
292 /******************************************************************
293 * get_args
294 * Parses a list of function/method arguments, creates a string corresponding
295 * to the arguments' list.
297 static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_term,
298 char open_char, char close_char)
301 struct datatype_t ct;
302 struct array arg_collect;
303 char* args_str = NULL;
304 int i;
306 str_array_init(&arg_collect);
308 /* Now come the function arguments */
309 while (*sym->current)
311 /* Decode each data type and append it to the argument list */
312 if (*sym->current == '@')
314 sym->current++;
315 break;
317 if (!demangle_datatype(sym, &ct, pmt_ref, TRUE))
318 return NULL;
319 /* 'void' terminates an argument list */
320 if (!strcmp(ct.left, "void"))
322 if (!z_term && *sym->current == '@') sym->current++;
323 break;
325 str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1,
326 &arg_collect);
327 if (!strcmp(ct.left, "...")) break;
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.
332 if (z_term && *sym->current++ != 'Z') return NULL;
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++)
339 args_str = str_printf(sym, "%s,%s", args_str, arg_collect.elts[i]);
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);
349 return args_str;
352 /******************************************************************
353 * get_modifier
354 * Parses the type modifier. Always returns a static string
356 static BOOL get_modifier(char ch, const char** ret)
358 switch (ch)
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;
366 return TRUE;
369 static const char* get_modified_type(struct parsed_symbol* sym, char modif)
371 const char* modifier;
372 const char* ret = NULL;
373 const char* str_modif;
375 switch (modif)
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;
387 if (get_modifier(*sym->current++, &modifier))
389 unsigned mark = sym->stack.num;
390 struct datatype_t sub_ct;
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;
400 return ret;
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.
410 static char* get_literal_string(struct parsed_symbol* sym)
412 const char *ptr = sym->current;
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;
422 } while (*++sym->current != '@');
423 sym->current++;
424 str_array_push(sym, ptr, sym->current - 1 - ptr, &sym->names);
426 return str_array_get_ref(&sym->names, sym->names.num - sym->names.start - 1);
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.
442 static BOOL get_class(struct parsed_symbol* sym)
444 const char* name = NULL;
446 while (*sym->current != '@')
448 switch (*sym->current)
450 case '\0': return FALSE;
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 == '$')
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;
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);
485 break;
486 default:
487 name = get_literal_string(sym);
488 break;
490 if (!name)
491 return FALSE;
492 str_array_push(sym, name, -1, &sym->stack);
494 sym->current++;
495 return TRUE;
498 /******************************************************************
499 * get_class_string
500 * From an array collected by get_class in sym->stack, constructs the
501 * corresponding (allocated) string
503 static char* get_class_string(struct parsed_symbol* sym, int start)
505 int i;
506 size_t len, sz;
507 char* ret;
508 struct array *a = &sym->stack;
510 for (len = 0, i = start; i < a->num; i++)
512 assert(a->elts[i]);
513 len += 2 + strlen(a->elts[i]);
515 if (!(ret = und_alloc(sym, len - 1))) return NULL;
516 for (len = 0, i = a->num - 1; i >= start; i--)
518 sz = strlen(a->elts[i]);
519 memcpy(ret + len, a->elts[i], sz);
520 len += sz;
521 if (i > start)
523 ret[len++] = ':';
524 ret[len++] = ':';
527 ret[len] = '\0';
528 return ret;
531 /******************************************************************
532 * get_class_name
533 * Wrapper around get_class and get_class_string.
535 static char* get_class_name(struct parsed_symbol* sym)
537 unsigned mark = sym->stack.num;
538 char* s = NULL;
540 if (get_class(sym))
541 s = get_class_string(sym, mark);
542 sym->stack.num = mark;
543 return s;
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.
551 static BOOL get_calling_convention(char ch, const char** call_conv,
552 const char** exported, unsigned flags)
554 *call_conv = *exported = NULL;
556 if (!(flags & (UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_ALLOCATION_LANGUAGE)))
558 if (flags & UNDNAME_NO_LEADING_UNDERSCORES)
560 if (((ch - 'A') % 2) == 1) *exported = "dll_export ";
561 switch (ch)
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;
572 else
574 if (((ch - 'A') % 2) == 1) *exported = "__dll_export ";
575 switch (ch)
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;
587 return TRUE;
590 /*******************************************************************
591 * get_simple_type
592 * Return a string containing an allocated string for a simple data type
594 static const char* get_simple_type(char c)
596 const char* type_string;
598 switch (c)
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;
616 return type_string;
619 /*******************************************************************
620 * get_extented_type
621 * Return a string containing an allocated string for a simple data type
623 static const char* get_extended_type(char c)
625 const char* type_string;
627 switch (c)
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;
643 return type_string;
646 /*******************************************************************
647 * demangle_datatype
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)))
653 static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
654 struct array* pmt_ref, BOOL in_args)
656 char dt;
657 BOOL add_pmt = TRUE;
658 int num_args=0;
660 assert(ct);
661 ct->left = ct->right = NULL;
663 switch (dt = *sym->current++)
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 */
681 const char* struct_name = NULL;
682 const char* type_name = NULL;
684 if (!(struct_name = get_class_name(sym)))
685 goto done;
686 if (!(sym->flags & UNDNAME_NO_COMPLEX_TYPE))
688 switch (dt)
690 case 'T': type_name = "union "; break;
691 case 'U': type_name = "struct "; break;
692 case 'V': type_name = "class "; break;
695 ct->left = str_printf(sym, "%s%s", type_name, struct_name);
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))
714 /* FIXME: P6 = Function pointer, others who knows.. */
715 if (*sym->current++ == '6')
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;
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;
729 args = get_args(sym, pmt_ref, TRUE, '(', ')');
730 if (!args) goto done;
731 sym->stack.num = mark;
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);
737 else goto done;
739 else if (!(ct->left = get_modified_type(sym, 'P'))) goto done;
740 break;
741 case 'W':
742 if (*sym->current == '4')
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);
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')
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;
773 else if (sym->current[1] >= 'A' && sym->current[1] <= 'P')
775 while (sym->current[1] >= 'A' && sym->current[1] <= 'P')
777 num_args *= 16;
778 num_args += sym->current[1] - 'A';
779 sym->current += 1;
781 if(sym->current[1] == '@')
783 char *ptr;
784 ptr = und_alloc(sym, 17);
785 sprintf(ptr,"%d",num_args);
786 ct->left = ptr;
787 sym->current += 1;
790 else goto done;
791 break;
792 default :
793 ERR("Unknown type %c\n", dt);
794 break;
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:
801 return ct->left != NULL;
804 /******************************************************************
805 * handle_data
806 * Does the final parsing and handling for a variable or a field in
807 * a class.
809 static BOOL handle_data(struct parsed_symbol* sym)
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;
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
829 if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS))
831 /* we only print the access for static members */
832 switch (*sym->current)
834 case '0': access = "private: "; break;
835 case '1': access = "protected: "; break;
836 case '2': access = "public: "; break;
840 if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE))
842 if (*sym->current >= '0' && *sym->current <= '2')
843 member_type = "static ";
846 name = get_class_string(sym, 0);
848 switch (dt = *sym->current++)
850 case '0': case '1': case '2':
851 case '3': case '4': case '5':
853 unsigned mark = sym->stack.num;
854 struct array pmt;
856 str_array_init(&pmt);
858 if (!demangle_datatype(sym, &ct, &pmt, FALSE)) goto done;
859 if (!get_modifier(*sym->current++, &modifier)) goto done;
860 sym->stack.num = mark;
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 != '@')
869 char* cls = NULL;
871 if (!(cls = get_class_name(sym)))
872 goto done;
873 ct.right = str_printf(sym, "{for `%s'}", cls);
875 break;
876 default: goto done;
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;
888 /******************************************************************
889 * handle_method
890 * Does the final parsing and handling for a function or a method in
891 * a class.
893 static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
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;
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'
936 if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS))
938 switch ((*sym->current - 'A') / 8)
940 case 0: access = "private: "; break;
941 case 1: access = "protected: "; break;
942 case 2: access = "public: "; break;
945 if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE))
947 if (*sym->current >= 'A' && *sym->current <= 'X')
949 switch ((*sym->current - 'A') % 8)
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;
958 if (*sym->current >= 'A' && *sym->current <= 'X')
960 if (!((*sym->current - 'A') & 2))
962 /* Implicit 'this' pointer */
963 /* If there is an implicit this pointer, const modifier follows */
964 if (!get_modifier(*++sym->current, &modifier)) goto done;
967 else if (*sym->current < 'A' || *sym->current > 'Z') goto done;
968 sym->current++;
970 name = get_class_string(sym, 0);
972 if (!get_calling_convention(*sym->current++, &call_conv, &exported,
973 sym->flags))
974 goto done;
976 str_array_init(&array_pmt);
978 /* Return type, or @ if 'void' */
979 if (*sym->current == '@')
981 ct_ret.left = "void";
982 ct_ret.right = NULL;
983 sym->current++;
985 else
987 if (!demangle_datatype(sym, &ct_ret, &array_pmt, FALSE))
988 goto done;
990 if (sym->flags & UNDNAME_NO_FUNCTION_RETURNS)
991 ct_ret.left = ct_ret.right = NULL;
992 if (cast_op)
994 name = str_printf(sym, "%s%s%s", name, ct_ret.left, ct_ret.right);
995 ct_ret.left = ct_ret.right = NULL;
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;
1003 /* Note: '()' after 'Z' means 'throws', but we don't care here
1004 * Yet!!! FIXME
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;
1017 /*******************************************************************
1018 * symbol_demangle
1019 * Demangle a C++ linker symbol
1021 static BOOL symbol_demangle(struct parsed_symbol* sym)
1023 BOOL ret = FALSE;
1024 unsigned do_after = 0;
1025 static CHAR dashed_null[] = "--null--";
1027 /* FIXME seems wrong as name, as it demangles a simple data type */
1028 if (sym->flags & UNDNAME_NO_ARGUMENTS)
1030 struct datatype_t ct;
1032 if (demangle_datatype(sym, &ct, NULL, FALSE))
1034 sym->result = str_printf(sym, "%s%s", ct.left, ct.right);
1035 ret = TRUE;
1037 goto done;
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++;
1046 /* Then function name or operator code */
1047 if (*sym->current == '?' && sym->current[1] != '$')
1049 const char* function_name = NULL;
1051 /* C++ operator code (one character, or two if the first is '_') */
1052 switch (*++sym->current)
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)
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;
1128 break;
1129 default:
1130 /* FIXME: Other operators */
1131 ERR("Unknown operator: %c\n", *sym->current);
1132 return FALSE;
1134 sym->current++;
1135 switch (do_after)
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;
1149 sym->stack.start = 1;
1152 /* Either a class name, or '@' if the symbol is not a class member */
1153 if (*sym->current != '@')
1155 /* Class the function is associated with, terminated by '@@' */
1156 if (!get_class(sym)) goto done;
1158 else sym->current++;
1160 switch (do_after)
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;
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);
1188 return ret;
1191 /*********************************************************************
1192 * __unDNameEx (MSVCRT.@)
1194 * Demangle a C++ identifier.
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
1205 * RETURNS
1206 * Success: A string pointing to the unmangled name, allocated with memget.
1207 * Failure: NULL.
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)
1213 struct parsed_symbol sym;
1214 const char* result;
1216 TRACE("(%p,%s,%d,%p,%p,%p,%x)\n",
1217 buffer, mangled, buflen, memget, memfree, unknown, flags);
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)
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;
1229 sym.flags = flags;
1230 sym.mem_alloc_ptr = memget;
1231 sym.mem_free_ptr = memfree;
1232 sym.current = mangled;
1234 result = symbol_demangle(&sym) ? sym.result : mangled;
1235 if (buffer && buflen)
1237 lstrcpynA( buffer, result, buflen);
1239 else
1241 buffer = memget(strlen(result) + 1);
1242 if (buffer) strcpy(buffer, result);
1245 und_free_all(&sym);
1247 return buffer;
1251 /*********************************************************************
1252 * __unDName (MSVCRT.@)
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)
1258 return __unDNameEx(buffer, mangled, buflen, memget, memfree, NULL, flags);