BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / debugger / demangle / gcc3+.cpp
blob46419a7714b5b9b2229929e2aa96f5c8fe0e23b0
1 /*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <ctype.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include <new>
14 #include <TypeConstants.h>
16 #ifdef _KERNEL_MODE
17 # include <debug_heap.h>
18 #endif
20 #include "demangle.h"
23 // C++ ABI: http://www.codesourcery.com/public/cxx-abi/abi.html
26 //#define TRACE_GCC3_DEMANGLER
27 #ifdef TRACE_GCC3_DEMANGLER
28 # define TRACE(x...) PRINT(x)
29 # define DEBUG_SCOPE(name) DebugScope debug(name, fInput.String())
30 #else
31 # define TRACE(x...) ;
32 # define DEBUG_SCOPE(name) do {} while (false)
33 #endif
35 #ifdef _KERNEL_MODE
36 # define PRINT(format...) kprintf(format)
37 # define VPRINT(format, args) PRINT("%s", format)
38 // no vkprintf()
39 # define NEW(constructor) new(kdebug_alloc) constructor
40 # define DELETE(object) DebugAlloc::destroy(object)
41 #else
42 # define PRINT(format...) printf(format)
43 # define VPRINT(format, args) vprintf(format, args)
44 # define NEW(constructor) new(std::nothrow) constructor
45 # define DELETE(object) delete object
46 #endif
49 typedef long number_type;
51 enum {
52 ERROR_OK = 0,
53 ERROR_NOT_MANGLED,
54 ERROR_UNSUPPORTED,
55 ERROR_INVALID,
56 ERROR_BUFFER_TOO_SMALL,
57 ERROR_NO_MEMORY,
58 ERROR_INTERNAL,
59 ERROR_INVALID_PARAMETER_INDEX
62 // object classification
63 enum object_type {
64 OBJECT_TYPE_UNKNOWN,
65 OBJECT_TYPE_DATA,
66 OBJECT_TYPE_FUNCTION,
67 OBJECT_TYPE_METHOD_CLASS,
68 OBJECT_TYPE_METHOD_OBJECT,
69 OBJECT_TYPE_METHOD_UNKNOWN
72 // prefix classification
73 enum prefix_type {
74 PREFIX_NONE,
75 PREFIX_NAMESPACE,
76 PREFIX_CLASS,
77 PREFIX_UNKNOWN
80 // type classification
81 enum type_type {
82 TYPE_ELLIPSIS,
83 TYPE_VOID,
84 TYPE_WCHAR_T,
85 TYPE_BOOL,
86 TYPE_CHAR,
87 TYPE_SIGNED_CHAR,
88 TYPE_UNSIGNED_CHAR,
89 TYPE_SHORT,
90 TYPE_UNSIGNED_SHORT,
91 TYPE_INT,
92 TYPE_UNSIGNED_INT,
93 TYPE_LONG,
94 TYPE_UNSIGNED_LONG,
95 TYPE_LONG_LONG,
96 TYPE_UNSIGNED_LONG_LONG,
97 TYPE_INT128,
98 TYPE_UNSIGNED_INT128,
99 TYPE_FLOAT,
100 TYPE_DOUBLE,
101 TYPE_LONG_DOUBLE,
102 TYPE_FLOAT128,
103 TYPE_DFLOAT16,
104 TYPE_DFLOAT32,
105 TYPE_DFLOAT64,
106 TYPE_DFLOAT128,
107 TYPE_CHAR16_T,
108 TYPE_CHAR32_T,
110 TYPE_UNKNOWN,
111 TYPE_CONST_CHAR_POINTER,
112 TYPE_POINTER,
113 TYPE_REFERENCE
116 const char* const kTypeNames[] = {
117 "...",
118 "void",
119 "wchar_t",
120 "bool",
121 "char",
122 "signed char",
123 "unsigned char",
124 "short",
125 "unsigned short",
126 "int",
127 "unsigned int",
128 "long",
129 "unsigned long",
130 "long long",
131 "unsigned long long",
132 "__int128",
133 "unsigned __int128",
134 "float",
135 "double",
136 "long double",
137 "__float128",
138 "__dfloat16", // TODO: Official names for the __dfloat*!
139 "__dfloat32",
140 "__dfloat64",
141 "__dfloat64",
142 "char16_t",
143 "char32_t",
145 "?",
146 "char const*",
147 "void*",
148 "void&"
152 // CV qualifier flags
153 enum {
154 CV_QUALIFIER_RESTRICT = 0x1,
155 CV_QUALIFIER_VOLATILE = 0x2,
156 CV_QUALIFIER_CONST = 0x4
159 enum type_modifier {
160 TYPE_QUALIFIER_POINTER = 0,
161 TYPE_QUALIFIER_REFERENCE,
162 TYPE_QUALIFIER_RVALUE_REFERENCE,
163 TYPE_QUALIFIER_COMPLEX,
164 TYPE_QUALIFIER_IMAGINARY
167 static const char* const kTypeModifierSuffixes[] = {
168 "*",
169 "&",
170 "&&",
171 " complex",
172 " imaginary"
175 struct operator_info {
176 const char* mangled_name;
177 const char* name;
178 int argument_count;
179 int flags;
182 // operator flags
183 enum {
184 OPERATOR_TYPE_PARAM = 0x01,
185 OPERATOR_IS_MEMBER = 0x02
189 static const operator_info kOperatorInfos[] = {
190 { "nw", "new", -1, OPERATOR_IS_MEMBER },
191 { "na", "new[]", -1, OPERATOR_IS_MEMBER },
192 { "dl", "delete", -1, OPERATOR_IS_MEMBER },
193 { "da", "delete[]", -1, OPERATOR_IS_MEMBER },
194 { "ps", "+", 1, 0 }, // unary
195 { "ng", "-", 1, 0 }, // unary
196 { "ad", "&", 1, 0 }, // unary
197 { "de", "*", 1, 0 }, // unary
198 { "co", "~", 1, 0 },
199 { "pl", "+", 2, 0 },
200 { "mi", "-", 2, 0 },
201 { "ml", "*", 2, 0 },
202 { "dv", "/", 2, 0 },
203 { "rm", "%", 2, 0 },
204 { "an", "&", 2, 0 },
205 { "or", "|", 2, 0 },
206 { "eo", "^", 2, 0 },
207 { "aS", "=", 2, 0 },
208 { "pL", "+=", 2, 0 },
209 { "mI", "-=", 2, 0 },
210 { "mL", "*=", 2, 0 },
211 { "dV", "/=", 2, 0 },
212 { "rM", "%=", 2, 0 },
213 { "aN", "&=", 2, 0 },
214 { "oR", "|=", 2, 0 },
215 { "eO", "^=", 2, 0 },
216 { "ls", "<<", 2, 0 },
217 { "rs", ">>", 2, 0 },
218 { "lS", "<<=", 2, 0 },
219 { "rS", ">>=", 2, 0 },
220 { "eq", "==", 2, 0 },
221 { "ne", "!=", 2, 0 },
222 { "lt", "<", 2, 0 },
223 { "gt", ">", 2, 0 },
224 { "le", "<=", 2, 0 },
225 { "ge", ">=", 2, 0 },
226 { "nt", "!", 1, 0 },
227 { "aa", "&&", 2, 0 },
228 { "oo", "||", 2, 0 },
229 { "pp", "++", 1, 0 },
230 { "mm", "--", 1, 0 },
231 { "cm", ",", -1, 0 },
232 { "pm", "->*", 2, 0 },
233 { "pt", "->", 2, 0 },
234 { "cl", "()", -1, 0 },
235 { "ix", "[]", -1, 0 },
236 { "qu", "?", 3, 0 },
237 { "st", "sizeof", 1, OPERATOR_TYPE_PARAM }, // type
238 { "sz", "sizeof", 1, 0 }, // expression
239 { "at", "alignof", 1, OPERATOR_TYPE_PARAM }, // type
240 { "az", "alignof", 1, 0 }, // expression
245 #ifdef TRACE_GCC3_DEMANGLER
247 struct DebugScope {
248 DebugScope(const char* functionName, const char* remainingString = NULL)
250 fParent(sGlobalScope),
251 fFunctionName(functionName),
252 fLevel(fParent != NULL ? fParent->fLevel + 1 : 0)
254 sGlobalScope = this;
255 if (remainingString != NULL) {
256 PRINT("%*s%s(): \"%s\"\n", fLevel * 2, "", fFunctionName,
257 remainingString);
258 } else
259 PRINT("%*s%s()\n", fLevel * 2, "", fFunctionName);
262 ~DebugScope()
264 sGlobalScope = fParent;
265 PRINT("%*s%s() done\n", fLevel * 2, "", fFunctionName);
268 static void Print(const char* format,...)
270 int level = sGlobalScope != NULL ? sGlobalScope->fLevel : 0;
272 va_list args;
273 va_start(args, format);
274 PRINT("%*s", (level + 1) * 2, "");
275 VPRINT(format, args);
276 va_end(args);
279 private:
280 DebugScope* fParent;
281 const char* fFunctionName;
282 int fLevel;
284 static DebugScope* sGlobalScope;
287 DebugScope* DebugScope::sGlobalScope = NULL;
289 #endif // TRACE_GCC3_DEMANGLER
292 class Input {
293 public:
294 Input()
296 fString(NULL),
297 fLength(0)
301 void SetTo(const char* string, size_t length)
303 fString = string;
304 fLength = length;
307 const char* String() const
309 return fString;
312 int CharsRemaining() const
314 return fLength;
317 void Skip(size_t count)
319 if (count > fLength) {
320 PRINT("Input::Skip(): fOffset > fLength\n");
321 return;
324 fString += count;
325 fLength -= count;
328 bool HasPrefix(char prefix) const
330 return fLength > 0 && fString[0] == prefix;
333 bool HasPrefix(const char* prefix) const
335 size_t prefixLen = strlen(prefix);
336 return prefixLen <= fLength
337 && strncmp(fString, prefix, strlen(prefix)) == 0;
340 bool SkipPrefix(char prefix)
342 if (!HasPrefix(prefix))
343 return false;
345 fString++;
346 fLength--;
347 return true;
350 bool SkipPrefix(const char* prefix)
352 size_t prefixLen = strlen(prefix);
353 if (prefixLen <= fLength && strncmp(fString, prefix, prefixLen) != 0)
354 return false;
356 fString += prefixLen;
357 fLength -= prefixLen;
358 return true;
361 char operator[](size_t index) const
363 if (index >= fLength) {
364 PRINT("Input::operator[](): fOffset + index >= fLength\n");
365 return '\0';
368 return fString[index];
371 private:
372 const char* fString;
373 size_t fLength;
377 class NameBuffer {
378 public:
379 NameBuffer(char* buffer, size_t size)
381 fBuffer(buffer),
382 fSize(size),
383 fLength(0),
384 fOverflow(false)
388 bool IsEmpty() const
390 return fLength == 0;
393 char LastChar() const
395 return fLength > 0 ? fBuffer[fLength - 1] : '\0';
398 bool HadOverflow() const
400 return fOverflow;
403 char* Terminate()
405 fBuffer[fLength] = '\0';
406 return fBuffer;
409 bool Append(const char* string, size_t length)
411 if (fLength + length >= fSize) {
412 fOverflow = true;
413 return false;
416 memcpy(fBuffer + fLength, string, length);
417 fLength += length;
418 return true;
421 bool Append(const char* string)
423 return Append(string, strlen(string));
426 private:
427 char* fBuffer;
428 size_t fSize;
429 size_t fLength;
430 bool fOverflow;
434 struct TypeInfo {
435 type_type type;
436 int cvQualifiers;
438 TypeInfo()
440 type(TYPE_UNKNOWN),
441 cvQualifiers(0)
445 TypeInfo(type_type type)
447 type(type),
448 cvQualifiers(0)
452 TypeInfo(const TypeInfo& other, int cvQualifiers = 0)
454 type(other.type),
455 cvQualifiers(other.cvQualifiers | cvQualifiers)
459 TypeInfo& operator=(const TypeInfo& other)
461 type = other.type;
462 cvQualifiers = other.cvQualifiers;
463 return *this;
468 struct DemanglingParameters {
469 bool objectNameOnly;
471 DemanglingParameters(bool objectNameOnly)
473 objectNameOnly(objectNameOnly)
479 struct DemanglingInfo : DemanglingParameters {
480 object_type objectType;
482 DemanglingInfo(bool objectNameOnly)
484 DemanglingParameters(objectNameOnly),
485 objectType(OBJECT_TYPE_UNKNOWN)
491 struct ParameterInfo {
492 TypeInfo type;
494 ParameterInfo()
500 class Node;
502 struct NameDecorationInfo {
503 const Node* firstDecorator;
504 const Node* closestCVDecoratorList;
506 NameDecorationInfo(const Node* decorator)
508 firstDecorator(decorator),
509 closestCVDecoratorList(NULL)
514 struct CVQualifierInfo {
515 const Node* firstCVQualifier;
516 const Node* firstNonCVQualifier;
518 CVQualifierInfo()
520 firstCVQualifier(NULL),
521 firstNonCVQualifier(NULL)
527 class Node {
528 public:
529 Node()
531 fNextAllocated(NULL),
532 fParent(NULL),
533 fNext(NULL),
534 fNextReferenceable(NULL),
535 fReferenceable(true)
539 virtual ~Node()
543 Node* NextAllocated() const { return fNextAllocated; }
544 void SetNextAllocated(Node* node) { fNextAllocated = node; }
546 Node* Parent() const { return fParent; }
547 virtual void SetParent(Node* node) { fParent = node; }
549 Node* Next() const { return fNext; }
550 void SetNext(Node* node) { fNext = node; }
552 bool IsReferenceable() const { return fReferenceable; }
553 void SetReferenceable(bool flag) { fReferenceable = flag; }
555 Node* NextReferenceable() const { return fNextReferenceable; }
556 void SetNextReferenceable(Node* node) { fNextReferenceable = node; }
558 virtual bool GetName(NameBuffer& buffer) const = 0;
560 virtual bool GetDecoratedName(NameBuffer& buffer,
561 NameDecorationInfo& decorationInfo) const
563 if (!GetName(buffer))
564 return false;
566 return decorationInfo.firstDecorator == NULL
567 || decorationInfo.firstDecorator->AddDecoration(buffer, NULL);
570 virtual bool AddDecoration(NameBuffer& buffer,
571 const Node* stopDecorator) const
573 return true;
576 virtual void GetCVQualifierInfo(CVQualifierInfo& info) const
578 info.firstNonCVQualifier = this;
581 virtual Node* GetUnqualifiedNode(Node* beforeNode)
583 return this;
586 virtual bool IsTemplatized() const
588 return false;
591 virtual Node* TemplateParameterAt(int index) const
593 return NULL;
596 virtual bool IsNoReturnValueFunction() const
598 return false;
601 virtual bool IsTypeName(const char* name, size_t length) const
603 return false;
606 virtual object_type ObjectType() const
608 return OBJECT_TYPE_UNKNOWN;
611 virtual prefix_type PrefixType() const
613 return PREFIX_NONE;
616 virtual TypeInfo Type() const
618 return TypeInfo();
621 private:
622 Node* fNextAllocated;
623 Node* fParent;
624 Node* fNext;
625 Node* fNextReferenceable;
626 bool fReferenceable;
630 class NamedTypeNode : public Node {
631 public:
632 NamedTypeNode(Node* name)
634 fName(name)
636 if (fName != NULL)
637 fName->SetParent(this);
640 virtual bool GetName(NameBuffer& buffer) const
642 return fName == NULL || fName->GetName(buffer);
645 virtual bool IsNoReturnValueFunction() const
647 return fName != NULL && fName->IsNoReturnValueFunction();
650 virtual TypeInfo Type() const
652 return fName != NULL ? fName->Type() : TypeInfo();
655 protected:
656 Node* fName;
660 class SubstitutionNode : public Node {
661 public:
662 SubstitutionNode(Node* node)
664 fNode(node)
668 virtual bool GetName(NameBuffer& buffer) const
670 return fNode->GetName(buffer);
673 virtual bool GetDecoratedName(NameBuffer& buffer,
674 NameDecorationInfo& decorationInfo) const
676 return fNode->GetDecoratedName(buffer, decorationInfo);
679 virtual bool AddDecoration(NameBuffer& buffer,
680 const Node* stopDecorator) const
682 return fNode->AddDecoration(buffer, stopDecorator);
685 virtual void GetCVQualifierInfo(CVQualifierInfo& info) const
687 fNode->GetCVQualifierInfo(info);
690 virtual bool IsTemplatized() const
692 return fNode->IsTemplatized();
695 virtual Node* TemplateParameterAt(int index) const
697 return fNode->TemplateParameterAt(index);
700 virtual bool IsNoReturnValueFunction() const
702 return fNode->IsNoReturnValueFunction();
705 virtual bool IsTypeName(const char* name, size_t length) const
707 return fNode->IsTypeName(name, length);
710 virtual object_type ObjectType() const
712 return fNode->ObjectType();
715 virtual prefix_type PrefixType() const
717 return fNode->PrefixType();
720 virtual TypeInfo Type() const
722 return fNode->Type();
725 private:
726 Node* fNode;
730 class ArrayNode : public NamedTypeNode {
731 public:
732 ArrayNode(Node* type, int dimension)
734 NamedTypeNode(type),
735 fDimensionExpression(NULL),
736 fDimensionNumber(dimension)
740 ArrayNode(Node* type, Node* dimension)
742 NamedTypeNode(type),
743 fDimensionExpression(dimension),
744 fDimensionNumber(0)
746 fDimensionExpression->SetParent(this);
749 virtual bool GetName(NameBuffer& buffer) const
751 if (!fName->GetName(buffer))
752 return false;
754 buffer.Append("[", 1);
756 if (fDimensionExpression != NULL) {
757 if (!fDimensionExpression->GetName(buffer))
758 return false;
759 } else {
760 char stringBuffer[16];
761 snprintf(stringBuffer, sizeof(stringBuffer), "%d",
762 fDimensionNumber);
763 buffer.Append(stringBuffer);
766 return buffer.Append("]", 1);
769 virtual object_type ObjectType() const
771 return OBJECT_TYPE_DATA;
774 virtual TypeInfo Type() const
776 // TODO: Check!
777 return TypeInfo(TYPE_POINTER);
781 private:
782 Node* fDimensionExpression;
783 int fDimensionNumber;
787 class ObjectNode : public NamedTypeNode {
788 public:
789 ObjectNode(Node* name)
791 NamedTypeNode(name)
795 virtual bool GetObjectName(NameBuffer& buffer,
796 const DemanglingParameters& parameters)
798 if (parameters.objectNameOnly)
799 return fName != NULL ? fName->GetName(buffer) : true;
801 return GetName(buffer);
804 virtual object_type ObjectType() const
806 return OBJECT_TYPE_DATA;
809 virtual Node* ParameterAt(uint32 index) const
811 return NULL;
816 class SimpleNameNode : public Node {
817 public:
818 SimpleNameNode(const char* name)
820 fName(name),
821 fLength(strlen(name))
825 SimpleNameNode(const char* name, size_t length)
827 fName(name),
828 fLength(length)
832 virtual bool GetName(NameBuffer& buffer) const
834 return buffer.Append(fName, fLength);
837 protected:
838 const char* fName;
839 size_t fLength;
843 class SimpleTypeNode : public SimpleNameNode {
844 public:
845 SimpleTypeNode(const char* name)
847 SimpleNameNode(name),
848 fType(TYPE_UNKNOWN)
852 SimpleTypeNode(type_type type)
854 SimpleNameNode(kTypeNames[type]),
855 fType(type)
859 virtual bool IsTypeName(const char* name, size_t length) const
861 return fLength == length && strcmp(fName, name) == 0;
864 virtual object_type ObjectType() const
866 return OBJECT_TYPE_DATA;
869 virtual TypeInfo Type() const
871 return TypeInfo(fType);
874 private:
875 type_type fType;
879 class TypedNumberLiteralNode : public Node {
880 public:
881 TypedNumberLiteralNode(Node* type, const char* number, size_t length)
883 fType(type),
884 fNumber(number),
885 fLength(length)
887 fType->SetParent(this);
890 virtual bool GetName(NameBuffer& buffer) const
892 // If the type is bool and the number is 0 or 1, we use "false" or
893 // "true" respectively.
894 if (fType->IsTypeName("bool", 4) && fLength == 1
895 && (fNumber[0] == '0' || fNumber[0] == '1')) {
896 return buffer.Append(fNumber[0] == '0' ? "false" : "true");
899 // Add the type in parentheses. The GNU demangler omits "int", so do we.
900 if (!fType->IsTypeName("int", 3)) {
901 buffer.Append("(");
902 if (!fType->GetName(buffer))
903 return false;
904 buffer.Append(")");
907 // add the number -- replace a leading 'n' by '-', if necessary
908 if (fLength > 0 && fNumber[0] == 'n') {
909 buffer.Append("-");
910 return buffer.Append(fNumber + 1, fLength - 1);
913 return buffer.Append(fNumber, fLength);
916 virtual object_type ObjectType() const
918 return OBJECT_TYPE_DATA;
921 private:
922 Node* fType;
923 const char* fNumber;
924 size_t fLength;
928 class XtructorNode : public Node {
929 public:
930 XtructorNode(bool constructor, char type)
932 fConstructor(constructor),
933 fType(type)
937 virtual void SetParent(Node* node)
939 fUnqualifiedNode = node->GetUnqualifiedNode(this);
940 Node::SetParent(node);
943 virtual bool GetName(NameBuffer& buffer) const
945 if (fUnqualifiedNode == NULL)
946 return false;
948 if (!fConstructor)
949 buffer.Append("~");
951 return fUnqualifiedNode->GetName(buffer);
954 virtual bool IsNoReturnValueFunction() const
956 return true;
959 virtual object_type ObjectType() const
961 return OBJECT_TYPE_METHOD_CLASS;
964 private:
965 bool fConstructor;
966 char fType;
967 Node* fUnqualifiedNode;
971 class SpecialNameNode : public Node {
972 public:
973 SpecialNameNode(const char* name, Node* child)
975 fName(name),
976 fChild(child)
978 fChild->SetParent(this);
981 virtual bool GetName(NameBuffer& buffer) const
983 return buffer.Append(fName) && fChild->GetName(buffer);
986 protected:
987 const char* fName;
988 Node* fChild;
992 class DecoratingNode : public Node {
993 public:
994 DecoratingNode(Node* child)
996 fChildNode(child)
998 fChildNode->SetParent(this);
1001 virtual bool GetName(NameBuffer& buffer) const
1003 NameDecorationInfo decorationInfo(this);
1004 return fChildNode->GetDecoratedName(buffer, decorationInfo);
1007 virtual bool GetDecoratedName(NameBuffer& buffer,
1008 NameDecorationInfo& decorationInfo) const
1010 decorationInfo.closestCVDecoratorList = NULL;
1011 return fChildNode->GetDecoratedName(buffer, decorationInfo);
1014 protected:
1015 Node* fChildNode;
1019 class CVQualifiersNode : public DecoratingNode {
1020 public:
1021 CVQualifiersNode(int qualifiers, Node* child)
1023 DecoratingNode(child),
1024 fCVQualifiers(qualifiers)
1028 virtual bool GetDecoratedName(NameBuffer& buffer,
1029 NameDecorationInfo& decorationInfo) const
1031 if (decorationInfo.closestCVDecoratorList == NULL)
1032 decorationInfo.closestCVDecoratorList = this;
1033 return fChildNode->GetDecoratedName(buffer, decorationInfo);
1036 virtual bool AddDecoration(NameBuffer& buffer,
1037 const Node* stopDecorator) const
1039 if (this == stopDecorator)
1040 return true;
1042 if (!fChildNode->AddDecoration(buffer, stopDecorator))
1043 return false;
1045 if ((fCVQualifiers & CV_QUALIFIER_RESTRICT) != 0)
1046 buffer.Append(" restrict");
1047 if ((fCVQualifiers & CV_QUALIFIER_VOLATILE) != 0)
1048 buffer.Append(" volatile");
1049 if ((fCVQualifiers & CV_QUALIFIER_CONST) != 0)
1050 buffer.Append(" const");
1052 return true;
1055 virtual void GetCVQualifierInfo(CVQualifierInfo& info) const
1057 if (info.firstCVQualifier == NULL)
1058 info.firstCVQualifier = this;
1059 fChildNode->GetCVQualifierInfo(info);
1062 virtual bool IsTemplatized() const
1064 return fChildNode->IsTemplatized();
1067 virtual Node* TemplateParameterAt(int index) const
1069 return fChildNode->TemplateParameterAt(index);
1072 virtual bool IsNoReturnValueFunction() const
1074 return fChildNode->IsNoReturnValueFunction();
1077 virtual object_type ObjectType() const
1079 return fChildNode->ObjectType();
1082 virtual prefix_type PrefixType() const
1084 return fChildNode->PrefixType();
1087 virtual TypeInfo Type() const
1089 return TypeInfo(fChildNode->Type(), fCVQualifiers);
1092 private:
1093 int fCVQualifiers;
1097 class TypeModifierNode : public DecoratingNode {
1098 public:
1099 TypeModifierNode(type_modifier modifier, Node* child)
1101 DecoratingNode(child),
1102 fModifier(modifier)
1106 virtual bool AddDecoration(NameBuffer& buffer,
1107 const Node* stopDecorator) const
1109 if (this == stopDecorator)
1110 return true;
1112 return fChildNode->AddDecoration(buffer, stopDecorator)
1113 && buffer.Append(kTypeModifierSuffixes[fModifier]);
1116 virtual object_type ObjectType() const
1118 return OBJECT_TYPE_DATA;
1121 virtual TypeInfo Type() const
1123 TypeInfo type = fChildNode->Type();
1124 if (type.type == TYPE_CHAR
1125 && (type.cvQualifiers & CV_QUALIFIER_CONST) != 0) {
1126 return TypeInfo(TYPE_CONST_CHAR_POINTER);
1129 switch (fModifier) {
1130 case TYPE_QUALIFIER_POINTER:
1131 return TypeInfo(TYPE_POINTER);
1132 case TYPE_QUALIFIER_REFERENCE:
1133 return TypeInfo(TYPE_REFERENCE);
1134 default:
1135 return TypeInfo();
1139 private:
1140 type_modifier fModifier;
1144 class VendorTypeModifierNode : public DecoratingNode {
1145 public:
1146 VendorTypeModifierNode(Node* name, Node* child)
1148 DecoratingNode(child),
1149 fName(name)
1151 fName->SetParent(this);
1154 virtual bool AddDecoration(NameBuffer& buffer,
1155 const Node* stopDecorator) const
1157 if (this == stopDecorator)
1158 return true;
1160 return fChildNode->AddDecoration(buffer, stopDecorator)
1161 && buffer.Append(" ")
1162 && fName->GetName(buffer);
1165 virtual object_type ObjectType() const
1167 return OBJECT_TYPE_DATA;
1170 private:
1171 Node* fName;
1175 class OperatorNode : public Node {
1176 public:
1177 OperatorNode(const operator_info* info)
1179 fInfo(info)
1181 SetReferenceable(false);
1184 virtual bool GetName(NameBuffer& buffer) const
1186 return buffer.Append(
1187 isalpha(fInfo->name[0]) ? "operator " : "operator")
1188 && buffer.Append(fInfo->name);
1191 virtual object_type ObjectType() const
1193 return (fInfo->flags & OPERATOR_IS_MEMBER) != 0
1194 ? OBJECT_TYPE_METHOD_CLASS : OBJECT_TYPE_UNKNOWN;
1197 private:
1198 const operator_info* fInfo;
1202 class VendorOperatorNode : public Node {
1203 public:
1204 VendorOperatorNode(Node* name)
1206 fName(name)
1208 fName->SetParent(this);
1209 SetReferenceable(false);
1212 virtual bool GetName(NameBuffer& buffer) const
1214 return buffer.Append("operator ")
1215 && fName->GetName(buffer);
1218 private:
1219 Node* fName;
1223 class CastOperatorNode : public Node {
1224 public:
1225 CastOperatorNode(Node* child)
1227 fChildNode(child)
1229 fChildNode->SetParent(this);
1232 virtual bool GetName(NameBuffer& buffer) const
1234 return buffer.Append("operator ") && fChildNode->GetName(buffer);
1237 virtual bool IsNoReturnValueFunction() const
1239 return true;
1242 virtual object_type ObjectType() const
1244 return OBJECT_TYPE_METHOD_OBJECT;
1247 private:
1248 Node* fChildNode;
1252 class PrefixedNode : public Node {
1253 public:
1254 PrefixedNode(Node* prefix, Node* node)
1256 fPrefixNode(prefix),
1257 fNode(node)
1259 fPrefixNode->SetParent(this);
1260 fNode->SetParent(this);
1263 virtual bool GetName(NameBuffer& buffer) const
1265 if (!fPrefixNode->GetName(buffer))
1266 return false;
1268 buffer.Append("::");
1269 return fNode->GetName(buffer);
1272 virtual Node* GetUnqualifiedNode(Node* beforeNode)
1274 return beforeNode == fNode
1275 ? fPrefixNode->GetUnqualifiedNode(beforeNode)
1276 : fNode->GetUnqualifiedNode(beforeNode);
1279 virtual bool IsNoReturnValueFunction() const
1281 return fNode->IsNoReturnValueFunction();
1284 virtual object_type ObjectType() const
1286 return fNode->ObjectType();
1289 virtual prefix_type PrefixType() const
1291 return PREFIX_UNKNOWN;
1294 private:
1295 Node* fPrefixNode;
1296 Node* fNode;
1300 typedef PrefixedNode DependentNameNode;
1303 class TemplateNode : public Node {
1304 public:
1305 TemplateNode(Node* base)
1307 fBase(base),
1308 fFirstArgument(NULL),
1309 fLastArgument(NULL)
1311 fBase->SetParent(this);
1314 void AddArgument(Node* child)
1316 child->SetParent(this);
1318 if (fLastArgument != NULL) {
1319 fLastArgument->SetNext(child);
1320 fLastArgument = child;
1321 } else {
1322 fFirstArgument = child;
1323 fLastArgument = child;
1327 virtual bool GetName(NameBuffer& buffer) const
1329 if (!fBase->GetName(buffer))
1330 return false;
1332 buffer.Append("<");
1334 Node* child = fFirstArgument;
1335 while (child != NULL) {
1336 if (child != fFirstArgument)
1337 buffer.Append(", ");
1339 if (!child->GetName(buffer))
1340 return false;
1342 child = child->Next();
1345 // add a space between consecutive '>'
1346 if (buffer.LastChar() == '>')
1347 buffer.Append(" ");
1349 return buffer.Append(">");
1352 virtual Node* GetUnqualifiedNode(Node* beforeNode)
1354 return fBase != beforeNode
1355 ? fBase->GetUnqualifiedNode(beforeNode) : this;
1358 virtual bool IsTemplatized() const
1360 return true;
1363 virtual Node* TemplateParameterAt(int index) const
1365 Node* child = fFirstArgument;
1366 while (child != NULL) {
1367 if (index == 0)
1368 return child;
1369 index--;
1370 child = child->Next();
1373 return NULL;
1376 virtual bool IsNoReturnValueFunction() const
1378 return fBase->IsNoReturnValueFunction();
1381 virtual object_type ObjectType() const
1383 return fBase->ObjectType();
1386 virtual prefix_type PrefixType() const
1388 return fBase->PrefixType();
1391 protected:
1392 Node* fBase;
1393 Node* fFirstArgument;
1394 Node* fLastArgument;
1398 class MultiSubExpressionsNode : public Node {
1399 public:
1400 MultiSubExpressionsNode()
1402 fFirstSubExpression(NULL),
1403 fLastSubExpression(NULL)
1407 void AddSubExpression(Node* child)
1409 child->SetParent(this);
1411 if (fLastSubExpression != NULL) {
1412 fLastSubExpression->SetNext(child);
1413 fLastSubExpression = child;
1414 } else {
1415 fFirstSubExpression = child;
1416 fLastSubExpression = child;
1420 protected:
1421 Node* fFirstSubExpression;
1422 Node* fLastSubExpression;
1426 class CallNode : public MultiSubExpressionsNode {
1427 public:
1428 CallNode()
1432 virtual bool GetName(NameBuffer& buffer) const
1434 // TODO: Use the real syntax!
1435 buffer.Append("call(");
1437 Node* child = fFirstSubExpression;
1438 while (child != NULL) {
1439 if (child != fFirstSubExpression)
1440 buffer.Append(", ");
1442 if (!child->GetName(buffer))
1443 return false;
1445 child = child->Next();
1448 buffer.Append(")");
1450 return true;
1455 class OperatorExpressionNode : public MultiSubExpressionsNode {
1456 public:
1457 OperatorExpressionNode(const operator_info* info)
1459 fInfo(info)
1463 virtual bool GetName(NameBuffer& buffer) const
1465 bool isIdentifier = isalpha(fInfo->name[0]) || fInfo->name[0] == '_';
1467 if (fInfo->argument_count == 1 || isIdentifier
1468 || fInfo->argument_count > 3
1469 || (fInfo->argument_count == 3 && strcmp(fInfo->name, "?") != 0)) {
1470 // prefix operator
1471 buffer.Append(fInfo->name);
1473 if (isIdentifier)
1474 buffer.Append("(");
1476 Node* child = fFirstSubExpression;
1477 while (child != NULL) {
1478 if (child != fFirstSubExpression)
1479 buffer.Append(", ");
1481 if (!child->GetName(buffer))
1482 return false;
1484 child = child->Next();
1487 if (isIdentifier)
1488 buffer.Append(")");
1490 return true;
1493 Node* arg1 = fFirstSubExpression;
1494 Node* arg2 = arg1->Next();
1496 buffer.Append("(");
1498 if (fInfo->argument_count == 2) {
1499 // binary infix operator
1500 if (!arg1->GetName(buffer))
1501 return false;
1503 buffer.Append(" ");
1504 buffer.Append(fInfo->name);
1505 buffer.Append(" ");
1507 if (!arg2->GetName(buffer))
1508 return false;
1510 return buffer.Append(")");
1513 Node* arg3 = arg2->Next();
1515 if (fInfo->argument_count == 2) {
1516 // trinary operator "... ? ... : ..."
1517 if (!arg1->GetName(buffer))
1518 return false;
1520 buffer.Append(" ? ");
1522 if (!arg2->GetName(buffer))
1523 return false;
1525 buffer.Append(" : ");
1527 if (!arg3->GetName(buffer))
1528 return false;
1530 return buffer.Append(")");
1533 return false;
1536 private:
1537 const operator_info* fInfo;
1541 class ConversionExpressionNode : public MultiSubExpressionsNode {
1542 public:
1543 ConversionExpressionNode(Node* type)
1545 fType(type)
1547 fType->SetParent(this);
1550 virtual bool GetName(NameBuffer& buffer) const
1552 buffer.Append("(");
1554 if (!fType->GetName(buffer))
1555 return false;
1557 buffer.Append(")(");
1559 Node* child = fFirstSubExpression;
1560 while (child != NULL) {
1561 if (child != fFirstSubExpression)
1562 buffer.Append(", ");
1564 if (!child->GetName(buffer))
1565 return false;
1567 child = child->Next();
1570 return buffer.Append(")");
1573 private:
1574 Node* fType;
1578 class PointerToMemberNode : public DecoratingNode {
1579 public:
1580 PointerToMemberNode(Node* classType, Node* memberType)
1582 DecoratingNode(memberType),
1583 fClassType(classType)
1585 fClassType->SetParent(this);
1588 virtual bool AddDecoration(NameBuffer& buffer,
1589 const Node* stopDecorator) const
1591 if (this == stopDecorator)
1592 return true;
1594 if (!fChildNode->AddDecoration(buffer, stopDecorator))
1595 return false;
1597 // In most cases we need a space before the name. In some it is
1598 // superfluous, though.
1599 if (!buffer.IsEmpty() && buffer.LastChar() != '(')
1600 buffer.Append(" ");
1602 if (!fClassType->GetName(buffer))
1603 return false;
1605 return buffer.Append("::*");
1608 virtual object_type ObjectType() const
1610 return OBJECT_TYPE_DATA;
1613 virtual TypeInfo Type() const
1615 // TODO: Method pointers aren't ordinary pointers. Though we might not
1616 // be able to determine the difference.
1617 return TypeInfo(TYPE_POINTER);
1621 private:
1622 Node* fClassType;
1626 class FunctionNode : public ObjectNode {
1627 public:
1628 FunctionNode(Node* nameNode, bool hasReturnType, bool isExternC)
1630 ObjectNode(nameNode),
1631 fFirstTypeNode(NULL),
1632 fLastTypeNode(NULL),
1633 fHasReturnType(hasReturnType),
1634 fIsExternC(isExternC)
1638 void AddType(Node* child)
1640 child->SetParent(this);
1642 if (fLastTypeNode != NULL) {
1643 fLastTypeNode->SetNext(child);
1644 fLastTypeNode = child;
1645 } else {
1646 fFirstTypeNode = child;
1647 fLastTypeNode = child;
1651 virtual bool GetName(NameBuffer& buffer) const
1653 NameDecorationInfo decorationInfo(NULL);
1654 return GetDecoratedName(buffer, decorationInfo);
1657 virtual bool GetDecoratedName(NameBuffer& buffer,
1658 NameDecorationInfo& decorationInfo) const
1660 // write 'extern "C"'
1661 // if (fIsExternC)
1662 // buffer.Append("extern \"C\"");
1664 // write the return type
1665 Node* child = fFirstTypeNode;
1666 if (_HasReturnType() && child != NULL) {
1667 if (!child->GetName(buffer))
1668 return false;
1669 child = child->Next();
1671 buffer.Append(" ", 1);
1674 // write the function name
1675 if (fName == NULL)
1676 buffer.Append("(", 1);
1678 CVQualifierInfo info;
1679 if (fName != NULL) {
1680 // skip CV qualifiers on our name -- we'll add them later
1681 fName->GetCVQualifierInfo(info);
1682 if (info.firstNonCVQualifier != NULL
1683 && !info.firstNonCVQualifier->GetName(buffer)) {
1684 return false;
1688 // add non-CV qualifier decorations
1689 if (decorationInfo.firstDecorator != NULL) {
1690 if (!decorationInfo.firstDecorator->AddDecoration(buffer,
1691 decorationInfo.closestCVDecoratorList)) {
1692 return false;
1696 if (fName == NULL)
1697 buffer.Append(")", 1);
1699 // add the parameter types
1700 buffer.Append("(");
1702 // don't add a single "void" parameter
1703 if (child != NULL && child->Next() == NULL
1704 && child->IsTypeName("void", 4)) {
1705 child = NULL;
1708 Node* firstParam = child;
1709 while (child != NULL) {
1710 if (child != firstParam)
1711 buffer.Append(", ");
1713 if (!child->GetName(buffer))
1714 return false;
1716 child = child->Next();
1719 buffer.Append(")");
1721 // add CV qualifiers on our name
1722 if (info.firstCVQualifier != NULL) {
1723 if (!info.firstCVQualifier->AddDecoration(buffer,
1724 info.firstNonCVQualifier)) {
1725 return false;
1729 // add CV qualifiers on us
1730 if (decorationInfo.closestCVDecoratorList != NULL)
1731 decorationInfo.closestCVDecoratorList->AddDecoration(buffer, NULL);
1733 return true;
1736 virtual object_type ObjectType() const
1738 // no name, no fun
1739 if (fName == NULL)
1740 return OBJECT_TYPE_FUNCTION;
1742 // check our name's prefix
1743 switch (fName->PrefixType()) {
1744 case PREFIX_NONE:
1745 case PREFIX_NAMESPACE:
1746 return OBJECT_TYPE_FUNCTION;
1747 case PREFIX_CLASS:
1748 case PREFIX_UNKNOWN:
1749 break;
1752 // Our name has a prefix, but we don't know, whether it is a class or
1753 // namespace. Let's ask our name what it thinks it is.
1754 object_type type = fName->ObjectType();
1755 switch (type) {
1756 case OBJECT_TYPE_FUNCTION:
1757 case OBJECT_TYPE_METHOD_CLASS:
1758 case OBJECT_TYPE_METHOD_OBJECT:
1759 case OBJECT_TYPE_METHOD_UNKNOWN:
1760 // That's as good as it gets.
1761 return type;
1762 case OBJECT_TYPE_UNKNOWN:
1763 case OBJECT_TYPE_DATA:
1764 default:
1765 // Obviously our name doesn't have a clue.
1766 return OBJECT_TYPE_METHOD_UNKNOWN;
1770 virtual Node* ParameterAt(uint32 index) const
1772 // skip return type
1773 Node* child = fFirstTypeNode;
1774 if (_HasReturnType() && child != NULL)
1775 child = child->Next();
1777 // ignore a single "void" parameter
1778 if (child != NULL && child->Next() == NULL
1779 && child->IsTypeName("void", 4)) {
1780 return NULL;
1783 // get the type at the index
1784 while (child != NULL && index > 0) {
1785 child = child->Next();
1786 index--;
1789 return child;
1792 private:
1793 bool _HasReturnType() const
1795 return fHasReturnType
1796 || fName == NULL
1797 || (fName->IsTemplatized() && !fName->IsNoReturnValueFunction());
1800 private:
1801 Node* fFirstTypeNode;
1802 Node* fLastTypeNode;
1803 bool fHasReturnType;
1804 bool fIsExternC;
1808 // #pragma mark - Demangler
1811 class Demangler {
1812 public:
1813 Demangler();
1815 int Demangle(const char* mangledName, char* buffer,
1816 size_t size,
1817 DemanglingInfo& demanglingInfo);
1818 int GetParameterInfo(const char* mangledName,
1819 uint32 index, char* buffer, size_t size,
1820 ParameterInfo& info);
1822 // actually private, but public to make gcc 2 happy
1823 inline bool _SetError(int error);
1824 inline void _AddAllocatedNode(Node* node);
1826 private:
1827 template<typename NodeType> struct NodeCreator;
1829 inline bool _SkipExpected(char c);
1830 inline bool _SkipExpected(const char* string);
1832 void _Init();
1833 void _Cleanup();
1835 int _Demangle(const char* mangledName, char* buffer,
1836 size_t size,
1837 DemanglingInfo& demanglingInfo);
1838 int _GetParameterInfo(const char* mangledName,
1839 uint32 index, char* buffer, size_t size,
1840 ParameterInfo& info);
1842 int _Parse(const char* mangledName,
1843 const char*& versionSuffix,
1844 ObjectNode*& _node);
1846 bool _ParseEncoding(ObjectNode*& _node);
1847 bool _ParseSpecialName(Node*& _node);
1848 bool _ParseCallOffset(bool& nonVirtual,
1849 number_type& offset1, number_type& offset2);
1850 bool _ParseName(Node*& _node);
1851 bool _ParseNestedName(Node*& _node);
1852 bool _ParseNestedNameInternal(Node*& _node);
1853 bool _ParseLocalName(Node*& _node);
1854 bool _ParseUnqualifiedName(Node*& _node);
1855 bool _ParseSourceName(Node*& _node);
1856 bool _ParseOperatorName(Node*& _node);
1857 bool _ParseType(Node*& _node);
1858 bool _ParseTypeInternal(Node*& _node);
1859 void _ParseCVQualifiers(int& qualifiers);
1860 bool _ParseTypeWithModifier(type_modifier modifier,
1861 int toSkip, Node*& _node);
1862 bool _TryParseBuiltinType(Node*& _node);
1863 bool _ParseFunctionType(FunctionNode*& _node);;
1864 bool _ParseArrayType(Node*& _node);
1865 bool _ParsePointerToMemberType(Node*& _node);
1866 bool _ParseTemplateParam(Node*& _node);
1867 bool _ParseSubstitution(Node*& _node);
1868 bool _ParseSubstitutionInternal(Node*& _node);
1869 bool _ParseBareFunctionType(FunctionNode* node);
1870 bool _ParseTemplateArgs(Node* node, Node*& _node);
1871 bool _ParseTemplateArg(Node*& _node);
1872 bool _ParseExpression(Node*& _node);
1873 bool _ParseExpressionPrimary(Node*& _node);
1874 bool _ParseNumber(number_type& number);
1876 bool _CreateNodeAndSkip(const char* name,
1877 size_t length, int toSkip, Node*& _node);
1878 bool _CreateNodeAndSkip(const char* name, int toSkip,
1879 Node*& _node);
1880 bool _CreateTypeNodeAndSkip(type_type type,
1881 int toSkip, Node*& _node);
1882 bool _CreateTypeNodeAndSkip(const char* name,
1883 const char* prefix,
1884 const char* templateArgs, int toSkip,
1885 Node*& _node);
1887 void _RegisterReferenceableNode(Node* node);
1888 bool _CreateSubstitutionNode(int index,
1889 Node*& _node);
1891 private:
1892 Input fInput;
1893 int fError;
1894 Node* fAllocatedNodes;
1895 Node* fFirstReferenceableNode;
1896 Node* fLastReferenceableNode;
1897 Node* fTemplatizedNode;
1901 template<typename NodeType>
1902 struct Demangler::NodeCreator {
1903 NodeCreator(Demangler* demangler)
1905 fDemangler(demangler)
1909 template<typename ReturnType>
1910 inline bool operator()(ReturnType*& _node) const
1912 _node = NEW(NodeType);
1913 if (_node == NULL)
1914 return fDemangler->_SetError(ERROR_NO_MEMORY);
1916 fDemangler->_AddAllocatedNode(_node);
1917 return true;
1920 template<typename ParameterType1, typename ReturnType>
1921 inline bool operator()(ParameterType1 arg1, ReturnType*& _node) const
1923 _node = NEW(NodeType(arg1));
1924 if (_node == NULL)
1925 return fDemangler->_SetError(ERROR_NO_MEMORY);
1927 fDemangler->_AddAllocatedNode(_node);
1928 return true;
1931 template<typename ParameterType1, typename ParameterType2,
1932 typename ReturnType>
1933 inline bool operator()(ParameterType1 arg1, ParameterType2 arg2,
1934 ReturnType*& _node) const
1936 _node = NEW(NodeType(arg1, arg2));
1937 if (_node == NULL)
1938 return fDemangler->_SetError(ERROR_NO_MEMORY);
1940 fDemangler->_AddAllocatedNode(_node);
1941 return true;
1944 template<typename ParameterType1, typename ParameterType2,
1945 typename ParameterType3, typename ReturnType>
1946 inline bool operator()(ParameterType1 arg1, ParameterType2 arg2,
1947 ParameterType3 arg3, ReturnType*& _node) const
1949 _node = NEW(NodeType(arg1, arg2, arg3));
1950 if (_node == NULL)
1951 return fDemangler->_SetError(ERROR_NO_MEMORY);
1953 fDemangler->_AddAllocatedNode(_node);
1954 return true;
1957 private:
1958 Demangler* fDemangler;
1962 inline bool
1963 Demangler::_SetError(int error)
1965 if (fError == ERROR_OK) {
1966 fError = error;
1967 #ifdef TRACE_GCC3_DEMANGLER
1968 DebugScope::Print("_SetError(): %d, remaining input: \"%s\"\n",
1969 error, fInput.String());
1970 #endif
1972 return false;
1976 inline void
1977 Demangler::_AddAllocatedNode(Node* node)
1979 node->SetNextAllocated(fAllocatedNodes);
1980 fAllocatedNodes = node;
1984 inline bool
1985 Demangler::_SkipExpected(char c)
1987 return fInput.SkipPrefix(c) || _SetError(ERROR_INVALID);
1991 inline bool
1992 Demangler::_SkipExpected(const char* string)
1994 return fInput.SkipPrefix(string) || _SetError(ERROR_INVALID);
1998 Demangler::Demangler()
2000 fInput(),
2001 fAllocatedNodes(NULL)
2007 Demangler::Demangle(const char* mangledName, char* buffer, size_t size,
2008 DemanglingInfo& demanglingInfo)
2010 DEBUG_SCOPE("Demangle");
2012 _Init();
2014 int result = _Demangle(mangledName, buffer, size, demanglingInfo);
2016 _Cleanup();
2018 return result;
2023 Demangler::GetParameterInfo(const char* mangledName, uint32 index, char* buffer,
2024 size_t size, ParameterInfo& info)
2026 DEBUG_SCOPE("GetParameterInfo");
2028 _Init();
2030 int result = _GetParameterInfo(mangledName, index, buffer, size, info);
2032 _Cleanup();
2034 return result;
2038 void
2039 Demangler::_Init()
2041 fError = ERROR_OK;
2043 fFirstReferenceableNode = NULL;
2044 fLastReferenceableNode = NULL;
2045 fAllocatedNodes = NULL;
2046 fTemplatizedNode = NULL;
2050 void
2051 Demangler::_Cleanup()
2053 while (fAllocatedNodes != NULL) {
2054 Node* node = fAllocatedNodes;
2055 fAllocatedNodes = node->NextAllocated();
2056 DELETE(node);
2062 Demangler::_Demangle(const char* mangledName, char* buffer, size_t size,
2063 DemanglingInfo& demanglingInfo)
2065 // parse the name
2066 const char* versionSuffix;
2067 ObjectNode* node;
2068 int error = _Parse(mangledName, versionSuffix, node);
2069 if (error != ERROR_OK)
2070 return error;
2072 NameBuffer nameBuffer(buffer, size);
2073 bool success = node->GetObjectName(nameBuffer, demanglingInfo);
2075 // If versioned, append the unmodified version string
2076 if (success && versionSuffix != NULL)
2077 nameBuffer.Append(versionSuffix);
2079 if (nameBuffer.HadOverflow())
2080 return ERROR_BUFFER_TOO_SMALL;
2082 if (!success)
2083 return ERROR_INTERNAL;
2085 demanglingInfo.objectType = node->ObjectType();
2087 nameBuffer.Terminate();
2088 return ERROR_OK;
2093 Demangler::_GetParameterInfo(const char* mangledName, uint32 index,
2094 char* buffer, size_t size, ParameterInfo& info)
2096 // parse the name
2097 const char* versionSuffix;
2098 ObjectNode* node;
2099 int error = _Parse(mangledName, versionSuffix, node);
2100 if (error != ERROR_OK)
2101 return error;
2103 // get the parameter node
2104 Node* parameter = node->ParameterAt(index);
2105 if (parameter == NULL)
2106 return ERROR_INVALID_PARAMETER_INDEX;
2108 // get the parameter name
2109 NameBuffer nameBuffer(buffer, size);
2110 bool success = parameter->GetName(nameBuffer);
2112 if (nameBuffer.HadOverflow())
2113 return ERROR_BUFFER_TOO_SMALL;
2115 if (!success)
2116 return ERROR_INTERNAL;
2118 nameBuffer.Terminate();
2120 // get the type
2121 info.type = parameter->Type();
2123 return ERROR_OK;
2128 Demangler::_Parse(const char* mangledName, const char*& versionSuffix,
2129 ObjectNode*& _node)
2131 // To support versioned symbols, we ignore the version suffix when
2132 // demangling.
2133 versionSuffix = strchr(mangledName, '@');
2134 fInput.SetTo(mangledName,
2135 versionSuffix != NULL
2136 ? versionSuffix - mangledName : strlen(mangledName));
2138 // <mangled-name> ::= _Z <encoding>
2140 if (!fInput.SkipPrefix("_Z"))
2141 return ERROR_NOT_MANGLED;
2143 if (!_ParseEncoding(_node))
2144 return fError;
2146 if (fInput.CharsRemaining() != 0) {
2147 // bogus at end of input
2148 return ERROR_INVALID;
2151 return ERROR_OK;
2155 bool
2156 Demangler::_ParseEncoding(ObjectNode*& _node)
2158 DEBUG_SCOPE("_ParseEncoding");
2160 // <encoding> ::= <function name> <bare-function-type>
2161 // ::= <data name>
2162 // ::= <special-name>
2164 // NOTE: This is not in the specs: Local entities seem to be prefixed
2165 // by an 'L'.
2166 fInput.SkipPrefix('L');
2168 // parse <special-name>, if it is one
2169 Node* name;
2170 if (fInput.HasPrefix('T') || fInput.HasPrefix("GV")) {
2171 return _ParseSpecialName(name)
2172 && NodeCreator<ObjectNode>(this)(name, _node);
2175 // either <data name> or <function name>
2176 if (!_ParseName(name))
2177 return false;
2179 if (fInput.CharsRemaining() == 0 || fInput.HasPrefix('E')) {
2180 // <data name>
2181 return NodeCreator<ObjectNode>(this)(name, _node);
2184 // <function name> -- parse remaining <bare-function-type>
2185 FunctionNode* functionNode;
2186 if (!NodeCreator<FunctionNode>(this)(name, false, false, functionNode))
2187 return false;
2188 _node = functionNode;
2190 // If our name is templatized, we push it onto the templatized node
2191 // stack while parsing the function parameters.
2192 Node* previousTemplatizedNode = fTemplatizedNode;
2193 if (name->IsTemplatized())
2194 fTemplatizedNode = name;
2196 if (!_ParseBareFunctionType(functionNode))
2197 return false;
2199 fTemplatizedNode = previousTemplatizedNode;
2201 return true;
2205 bool
2206 Demangler::_ParseSpecialName(Node*& _node)
2208 DEBUG_SCOPE("_ParseSpecialName");
2210 if (fInput.CharsRemaining() == 0)
2211 return _SetError(ERROR_INVALID);
2213 // <special-name> ::= GV <object name> # Guard variable for one-time
2214 // # initialization
2215 // # No <type>
2216 if (!fInput.SkipPrefix('T')) {
2217 Node* name;
2218 return _SkipExpected("GV")
2219 && _ParseName(name)
2220 && NodeCreator<SpecialNameNode>(this)("guard variable for ",
2221 name, _node);
2224 // <special-name> ::= TV <type> # virtual table
2225 // ::= TT <type> # VTT structure (construction vtable
2226 // # index)
2227 // ::= TI <type> # typeinfo structure
2228 // ::= TS <type> # typeinfo name (null-terminated byte
2229 // # string)
2230 const char* prefix = NULL;
2231 switch (fInput[0]) {
2232 case 'V':
2233 prefix = "vtable for ";
2234 break;
2235 case 'T':
2236 prefix = "VTT for ";
2237 break;
2238 case 'I':
2239 prefix = "typeinfo for ";
2240 break;
2241 case 'S':
2242 prefix = "typeinfo name for ";
2243 break;
2246 if (prefix != NULL) {
2247 fInput.Skip(1);
2248 Node* type;
2249 return _ParseType(type)
2250 && NodeCreator<SpecialNameNode>(this)(prefix, type, _node);
2253 // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
2254 // # base is the nominal target function of thunk
2255 // # first call-offset is 'this' adjustment
2256 // # second call-offset is result adjustment
2257 if (fInput.SkipPrefix('c')) {
2258 bool nonVirtual;
2259 number_type offset1;
2260 number_type offset2;
2261 ObjectNode* name;
2262 return _ParseCallOffset(nonVirtual, offset1, offset2)
2263 && _ParseCallOffset(nonVirtual, offset1, offset2)
2264 && _ParseEncoding(name)
2265 && NodeCreator<SpecialNameNode>(this)(
2266 "covariant return thunk to ", name, _node);
2269 // <special-name> ::= T <call-offset> <base encoding>
2270 // # base is the nominal target function of thunk
2271 bool nonVirtual;
2272 number_type offset1;
2273 number_type offset2;
2274 ObjectNode* name;
2275 return _ParseCallOffset(nonVirtual, offset1, offset2)
2276 && _ParseEncoding(name)
2277 && NodeCreator<SpecialNameNode>(this)(
2278 nonVirtual ? "non-virtual thunk to " : "virtual thunk to ",
2279 name, _node);
2283 bool
2284 Demangler::_ParseCallOffset(bool& nonVirtual, number_type& offset1,
2285 number_type& offset2)
2287 // <call-offset> ::= h <nv-offset> _
2288 // ::= v <v-offset> _
2289 // <nv-offset> ::= <offset number>
2290 // # non-virtual base override
2291 // <v-offset> ::= <offset number> _ <virtual offset number>
2292 // # virtual base override, with vcall offset
2294 // non-virtual
2295 if (fInput.SkipPrefix('h')) {
2296 nonVirtual = true;
2297 return _ParseNumber(offset1) && _SkipExpected('_');
2300 // virtual
2301 nonVirtual = false;
2302 return _SkipExpected('v')
2303 && _ParseNumber(offset1)
2304 && _SkipExpected('_')
2305 && _ParseNumber(offset2)
2306 && _SkipExpected('_');
2309 bool
2310 Demangler::_ParseName(Node*& _node)
2312 DEBUG_SCOPE("_ParseName");
2314 if (fInput.CharsRemaining() == 0)
2315 return _SetError(ERROR_INVALID);
2317 // <name> ::= <nested-name>
2318 // ::= <unscoped-name>
2319 // ::= <unscoped-template-name> <template-args>
2320 // ::= <local-name> # See Scope Encoding below
2322 // <unscoped-name> ::= <unqualified-name>
2323 // ::= St <unqualified-name> # ::std::
2325 // <unscoped-template-name> ::= <unscoped-name>
2326 // ::= <substitution>
2328 switch (fInput[0]) {
2329 case 'N':
2330 // <nested-name>
2331 return _ParseNestedName(_node);
2332 case 'Z':
2333 // <local-name>
2334 return _ParseLocalName(_node);
2335 case 'S':
2337 // <substitution>
2338 if (!fInput.HasPrefix("St")) {
2339 if (!_ParseSubstitution(_node))
2340 return false;
2341 break;
2344 // std:: namespace
2345 fInput.Skip(2);
2347 Node* prefix;
2348 if (!NodeCreator<SimpleNameNode>(this)("std", prefix))
2349 return false;
2351 // <unqualified-name>
2352 Node* node;
2353 if (!_ParseUnqualifiedName(node)
2354 || !NodeCreator<PrefixedNode>(this)(prefix, node, _node)) {
2355 return false;
2358 break;
2360 default:
2361 // <unqualified-name>
2362 if (!_ParseUnqualifiedName(_node))
2363 return false;
2364 break;
2367 // We get here for the names that might be an <unscoped-template-name>.
2368 // Check whether <template-args> are following.
2369 if (!fInput.HasPrefix('I'))
2370 return true;
2372 // <unscoped-template-name> is referenceable
2373 _RegisterReferenceableNode(_node);
2375 return _ParseTemplateArgs(_node, _node);
2379 bool
2380 Demangler::_ParseNestedName(Node*& _node)
2382 DEBUG_SCOPE("_ParseNestedName");
2384 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
2385 // ::= N [<CV-qualifiers>] <template-prefix>
2386 // <template-args> E
2388 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
2390 // <prefix> ::= <prefix> <unqualified-name>
2391 // ::= <template-prefix> <template-args>
2392 // ::= <template-param>
2393 // ::= # empty
2394 // ::= <substitution>
2396 // <template-prefix> ::= <prefix> <template unqualified-name>
2397 // ::= <template-param>
2398 // ::= <substitution>
2400 if (!_SkipExpected('N'))
2401 return false;
2403 // parse CV qualifiers
2404 int qualifiers;
2405 _ParseCVQualifiers(qualifiers);
2407 // parse the main part
2408 if (!_ParseNestedNameInternal(_node))
2409 return false;
2411 // create a CV qualifiers wrapper node, if necessary
2412 if (qualifiers != 0) {
2413 return NodeCreator<CVQualifiersNode>(this)(qualifiers, _node,
2414 _node);
2417 return true;
2421 bool
2422 Demangler::_ParseNestedNameInternal(Node*& _node)
2424 DEBUG_SCOPE("_ParseNestedNameMain");
2426 if (fInput.CharsRemaining() == 0)
2427 return _SetError(ERROR_INVALID);
2429 // the initial prefix might be a template param or a substitution
2430 Node* initialPrefixNode = NULL;
2431 Node* prefixNode = NULL;
2432 switch (fInput[0]) {
2433 case 'T': // <template-param>
2434 if (!_ParseTemplateParam(initialPrefixNode))
2435 return false;
2437 // a <prefix> or <template-prefix> and as such referenceable
2438 _RegisterReferenceableNode(initialPrefixNode);
2439 break;
2441 case 'S': // <substitution>
2442 if (!_ParseSubstitution(initialPrefixNode))
2443 return false;
2444 break;
2447 while (true) {
2448 bool canTerminate = false;
2449 Node* node;
2451 if (initialPrefixNode != NULL) {
2452 node = initialPrefixNode;
2453 initialPrefixNode = NULL;
2454 } else {
2455 if (!_ParseUnqualifiedName(node))
2456 return false;
2457 canTerminate = true;
2460 // join prefix and the new node
2461 if (prefixNode != NULL) {
2462 if (!NodeCreator<PrefixedNode>(this)(prefixNode, node, node))
2463 return false;
2466 // template arguments?
2467 if (fInput.HasPrefix('I')) {
2468 // <template-prefix> is referenceable
2469 _RegisterReferenceableNode(node);
2471 // parse the template arguments
2472 if (!_ParseTemplateArgs(node, node))
2473 return false;
2474 canTerminate = true;
2477 if (fInput.CharsRemaining() == 0)
2478 return _SetError(ERROR_INVALID);
2480 // end of nested name?
2481 if (fInput.SkipPrefix('E')) {
2482 // If it doesn't have template args, it must end in an
2483 // unqualified name.
2484 if (!canTerminate)
2485 return _SetError(ERROR_INVALID);
2487 _node = node;
2488 return true;
2491 // The fun continues, so this is a <prefix> or <template-prefix>
2492 // and as such referenceable.
2493 prefixNode = node;
2494 _RegisterReferenceableNode(node);
2499 bool
2500 Demangler::_ParseLocalName(Node*& _node)
2502 DEBUG_SCOPE("_ParseLocalName");
2504 // <local-name> := Z <function encoding> E <entity name>
2505 // [<discriminator>]
2506 // := Z <function encoding> E s [<discriminator>]
2507 // <discriminator> := _ <non-negative number>
2509 // parse the function name
2510 ObjectNode* functionName;
2511 if (!_SkipExpected('Z')
2512 || !_ParseEncoding(functionName)
2513 || !_SkipExpected('E')) {
2514 return false;
2517 Node* entityName;
2518 if (fInput.SkipPrefix('s')) {
2519 // string literal
2520 if (!NodeCreator<SimpleNameNode>(this)("string literal",
2521 entityName)) {
2522 return false;
2524 } else {
2525 // local type or object
2526 if (!_ParseName(entityName))
2527 return false;
2530 // parse discriminator
2531 number_type discriminator = 0;
2532 if (fInput.SkipPrefix('_')) {
2533 if (!_ParseNumber(discriminator))
2534 return false;
2535 if (discriminator < 0)
2536 return _SetError(ERROR_INVALID);
2537 discriminator++;
2540 return NodeCreator<PrefixedNode>(this)(functionName, entityName, _node);
2544 bool
2545 Demangler::_ParseUnqualifiedName(Node*& _node)
2547 DEBUG_SCOPE("_ParseUnqualifiedName");
2549 // <unqualified-name> ::= <operator-name>
2550 // ::= <ctor-dtor-name>
2551 // ::= <source-name>
2553 // <source-name> ::= <positive length number> <identifier>
2554 // <number> ::= [n] <non-negative decimal integer>
2555 // <identifier> ::= <unqualified source code identifier>
2557 // <ctor-dtor-name> ::= C1 # complete object constructor
2558 // ::= C2 # base object constructor
2559 // ::= C3 # complete object allocating constructor
2560 // ::= D0 # deleting destructor
2561 // ::= D1 # complete object destructor
2562 // ::= D2 # base object destructor
2564 // we need at least 2 chars
2565 if (fInput.CharsRemaining() < 2)
2566 return _SetError(ERROR_INVALID);
2568 if (isdigit(fInput[0]) || (fInput[0] == 'n' && isdigit(fInput[1]))) {
2569 // <source-name>
2570 return _ParseSourceName(_node);
2573 if (fInput[0] == 'C') {
2574 // <ctor-dtor-name> -- constructors
2575 switch (fInput[1]) {
2576 case '1':
2577 case '2':
2578 case '3':
2579 if (!NodeCreator<XtructorNode>(this)(true, fInput[1] - '1',
2580 _node)) {
2581 return false;
2584 fInput.Skip(2);
2585 return true;
2586 default:
2587 return _SetError(ERROR_INVALID);
2591 if (fInput[0] == 'D') {
2592 // <ctor-dtor-name> -- destructors
2593 switch (fInput[1]) {
2594 case '0':
2595 case '1':
2596 case '2':
2597 if (!NodeCreator<XtructorNode>(this)(false, fInput[1] - '0',
2598 _node)) {
2599 return false;
2602 fInput.Skip(2);
2603 return true;
2604 default:
2605 return _SetError(ERROR_INVALID);
2609 // must be an <operator-name>
2610 return _ParseOperatorName(_node);
2614 bool
2615 Demangler::_ParseSourceName(Node*& _node)
2617 DEBUG_SCOPE("_ParseSourceName");
2619 if (fInput.CharsRemaining() == 0)
2620 return _SetError(ERROR_INVALID);
2622 number_type number;
2623 if (!_ParseNumber(number))
2624 return false;
2626 if (number <= 0 || number > fInput.CharsRemaining())
2627 return _SetError(ERROR_INVALID);
2629 return _CreateNodeAndSkip(fInput.String(), number, number, _node);
2633 bool
2634 Demangler::_ParseOperatorName(Node*& _node)
2636 DEBUG_SCOPE("_ParseOperatorName");
2638 if (fInput.CharsRemaining() < 2)
2639 return _SetError(ERROR_INVALID);
2641 const operator_info* info = NULL;
2642 for (int i = 0; kOperatorInfos[i].name != NULL; i++) {
2643 if (fInput.SkipPrefix(kOperatorInfos[i].mangled_name)) {
2644 info = &kOperatorInfos[i];
2645 break;
2649 if (info != NULL)
2650 return NodeCreator<OperatorNode>(this)(info, _node);
2652 // <operator-name> ::= cv <type> # (cast)
2653 if (fInput.SkipPrefix("cv")) {
2654 Node* typeNode;
2655 if (!_ParseType(typeNode))
2656 return false;
2658 return NodeCreator<CastOperatorNode>(this)(typeNode, _node);
2661 // <operator-name> ::= v <digit> <source-name> # vendor extended
2662 // operator
2663 if (fInput.SkipPrefix('v')) {
2664 if (fInput.CharsRemaining() == 0 || !isdigit(fInput[0]))
2665 return _SetError(ERROR_INVALID);
2666 fInput.Skip(1);
2668 Node* name;
2669 return _ParseSourceName(name)
2670 && NodeCreator<VendorOperatorNode>(this)(name, _node);
2673 return _SetError(ERROR_INVALID);
2677 bool
2678 Demangler::_ParseType(Node*& _node)
2680 DEBUG_SCOPE("_ParseType");
2682 if (!_ParseTypeInternal(_node))
2683 return false;
2685 _RegisterReferenceableNode(_node);
2686 return true;
2690 bool
2691 Demangler::_ParseTypeInternal(Node*& _node)
2693 DEBUG_SCOPE("_ParseTypeInternal");
2695 // <type> ::= <builtin-type>
2696 // ::= <function-type>
2697 // ::= <class-enum-type>
2698 // ::= <array-type>
2699 // ::= <pointer-to-member-type>
2700 // ::= <template-param>
2701 // ::= <template-template-param> <template-args>
2702 // ::= <substitution> # See Compression below
2704 // <template-template-param> ::= <template-param>
2705 // ::= <substitution>
2707 // <type> ::= <CV-qualifiers> <type>
2708 // ::= P <type> # pointer-to
2709 // ::= R <type> # reference-to
2710 // ::= O <type> # rvalue reference-to (C++0x)
2711 // ::= C <type> # complex pair (C 2000)
2712 // ::= G <type> # imaginary (C 2000)
2713 // ::= U <source-name> <type> # vendor extended type qualifier
2715 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
2717 // <type> ::= Dp <type> # pack expansion of (C++0x)
2718 // ::= Dt <expression> E # decltype of an id-expression or
2719 // # class member access (C++0x)
2720 // ::= DT <expression> E # decltype of an expression (C++0x)
2722 if (_TryParseBuiltinType(_node)) {
2723 _node->SetReferenceable(false);
2724 return true;
2726 if (fError != ERROR_OK)
2727 return false;
2729 if (fInput.CharsRemaining() == 0)
2730 return _SetError(ERROR_INVALID);
2732 switch (fInput[0]) {
2733 // function type
2734 case 'F':
2736 FunctionNode* functionNode;
2737 if (!_ParseFunctionType(functionNode))
2738 return false;
2739 _node = functionNode;
2740 return true;
2743 // array type
2744 case 'A':
2745 return _ParseArrayType(_node);
2747 // pointer to member type
2748 case 'M':
2749 return _ParsePointerToMemberType(_node);
2751 // template param
2752 case 'T':
2753 if (!_ParseTemplateParam(_node))
2754 return false;
2755 break;
2757 // CV qualifiers
2758 case 'r':
2759 case 'V':
2760 case 'K':
2762 // parse CV qualifiers
2763 int qualifiers;
2764 _ParseCVQualifiers(qualifiers);
2766 // parse the type
2767 if (!_ParseType(_node))
2768 return false;
2770 // create the wrapper node
2771 return NodeCreator<CVQualifiersNode>(this)(qualifiers, _node,
2772 _node);
2775 // pointer, reference, etc.
2776 case 'P':
2777 return _ParseTypeWithModifier(TYPE_QUALIFIER_POINTER, 1, _node);
2778 case 'R':
2779 return _ParseTypeWithModifier(TYPE_QUALIFIER_REFERENCE, 1,
2780 _node);
2781 case 'O':
2782 return _ParseTypeWithModifier(
2783 TYPE_QUALIFIER_RVALUE_REFERENCE, 1, _node);
2784 case 'C':
2785 return _ParseTypeWithModifier(TYPE_QUALIFIER_COMPLEX, 1, _node);
2786 case 'G':
2787 return _ParseTypeWithModifier(TYPE_QUALIFIER_IMAGINARY, 1,
2788 _node);
2790 // pack and decltype
2791 case 'D':
2792 #if 0
2793 if (fInput.CharsRemaining() < 2)
2794 return _SetError(ERROR_INVALID);
2796 switch(fInput[1]) {
2797 case 'p':
2798 fInput.Skip(2);
2799 return _ParseType(_node);
2800 case 't':
2801 case 'T':
2803 fInput.Skip(2);
2804 Node* nameNode;
2805 if (!_ParseExpression(nameNode))
2806 return false;
2807 if (!fInput.SkipPrefix('E'))
2808 return ERROR_INVALID;
2811 #endif
2812 // NOTE: Unsupported by the GNU demangler.
2813 return _SetError(ERROR_UNSUPPORTED);
2815 // vendor extended type qualifier
2816 case 'U':
2817 fInput.Skip(1);
2818 Node* name;
2819 Node* type;
2820 return _ParseSourceName(name) && _ParseType(type)
2821 && NodeCreator<VendorTypeModifierNode>(this)(name, type,
2822 _node);
2824 // substitution
2825 case 'S':
2826 if (!fInput.HasPrefix("St")) {
2827 if (!_ParseSubstitution(_node))
2828 return false;
2829 break;
2832 // "St" -- the "std" namespace. The grammar is ambiguous here,
2833 // since we could parse that as <substitution> or as
2834 // <class-enum-type>. We assume the latter and fall through.
2836 default:
2838 // <class-enum-type> ::= <name>
2839 Node* nameNode;
2840 return _ParseName(nameNode)
2841 && NodeCreator<NamedTypeNode>(this)(nameNode, _node);
2845 // We get here for the types that might be a <template-template-param>.
2846 // Check whether <template-args> are following.
2847 if (!fInput.HasPrefix('I'))
2848 return true;
2850 // <template-template-param> is referenceable
2851 _RegisterReferenceableNode(_node);
2853 return _ParseTemplateArgs(_node, _node);
2857 void
2858 Demangler::_ParseCVQualifiers(int& qualifiers)
2860 qualifiers = 0;
2862 if (fInput.SkipPrefix('r'))
2863 qualifiers |= CV_QUALIFIER_RESTRICT;
2864 if (fInput.SkipPrefix('V'))
2865 qualifiers |= CV_QUALIFIER_VOLATILE;
2866 if (fInput.SkipPrefix('K'))
2867 qualifiers |= CV_QUALIFIER_CONST;
2871 bool
2872 Demangler::_ParseTypeWithModifier(type_modifier modifier, int toSkip,
2873 Node*& _node)
2875 if (toSkip > 0)
2876 fInput.Skip(toSkip);
2878 Node* node;
2879 if (!_ParseType(node))
2880 return false;
2882 return NodeCreator<TypeModifierNode>(this)(modifier, node, _node);
2886 bool
2887 Demangler::_TryParseBuiltinType(Node*& _node)
2889 DEBUG_SCOPE("_TryParseBuiltinType");
2891 // <builtin-type> ::= v # void
2892 // ::= w # wchar_t
2893 // ::= b # bool
2894 // ::= c # char
2895 // ::= a # signed char
2896 // ::= h # unsigned char
2897 // ::= s # short
2898 // ::= t # unsigned short
2899 // ::= i # int
2900 // ::= j # unsigned int
2901 // ::= l # long
2902 // ::= m # unsigned long
2903 // ::= x # long long, __int64
2904 // ::= y # unsigned long long, __int64
2905 // ::= n # __int128
2906 // ::= o # unsigned __int128
2907 // ::= f # float
2908 // ::= d # double
2909 // ::= e # long double, __float80
2910 // ::= g # __float128
2911 // ::= z # ellipsis
2912 // ::= Dd # IEEE 754r decimal floating point (64 bits)
2913 // ::= De # IEEE 754r decimal floating point (128 bits)
2914 // ::= Df # IEEE 754r decimal floating point (32 bits)
2915 // ::= Dh # IEEE 754r half-precision floating point
2916 // # (16 bits)
2917 // ::= Di # char32_t
2918 // ::= Ds # char16_t
2919 // ::= u <source-name> # vendor extended type
2921 if (fInput.CharsRemaining() == 0)
2922 return false;
2924 switch (fInput[0]) {
2925 case 'v':
2926 return _CreateTypeNodeAndSkip(TYPE_VOID, 1, _node);
2927 case 'w':
2928 return _CreateTypeNodeAndSkip(TYPE_WCHAR_T, 1, _node);
2929 case 'b':
2930 return _CreateTypeNodeAndSkip(TYPE_BOOL, 1, _node);
2931 case 'c':
2932 return _CreateTypeNodeAndSkip(TYPE_CHAR, 1, _node);
2933 case 'a':
2934 return _CreateTypeNodeAndSkip(TYPE_SIGNED_CHAR, 1, _node);
2935 case 'h':
2936 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_CHAR, 1, _node);
2937 case 's':
2938 return _CreateTypeNodeAndSkip(TYPE_SHORT, 1, _node);
2939 case 't':
2940 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_SHORT, 1,
2941 _node);
2942 case 'i':
2943 return _CreateTypeNodeAndSkip(TYPE_INT, 1, _node);
2944 case 'j':
2945 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_INT, 1, _node);
2946 case 'l':
2947 return _CreateTypeNodeAndSkip(TYPE_LONG, 1, _node);
2948 case 'm':
2949 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_LONG, 1, _node);
2950 case 'x':
2951 return _CreateTypeNodeAndSkip(TYPE_LONG_LONG, 1, _node);
2952 case 'y':
2953 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_LONG_LONG, 1, _node);
2954 case 'n':
2955 return _CreateTypeNodeAndSkip(TYPE_INT128, 1, _node);
2956 case 'o':
2957 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_INT128, 1, _node);
2958 case 'f':
2959 return _CreateTypeNodeAndSkip(TYPE_FLOAT, 1, _node);
2960 case 'd':
2961 return _CreateTypeNodeAndSkip(TYPE_DOUBLE, 1, _node);
2962 case 'e':
2963 return _CreateTypeNodeAndSkip(TYPE_LONG_DOUBLE, 1, _node);
2964 case 'g':
2965 return _CreateTypeNodeAndSkip(TYPE_FLOAT128, 1, _node);
2966 case 'z':
2967 return _CreateTypeNodeAndSkip(TYPE_ELLIPSIS, 1, _node);
2969 case 'D':
2970 if (fInput.CharsRemaining() < 2)
2971 return false;
2973 // TODO: Official names for the __dfloat*!
2974 switch (fInput[1]) {
2975 case 'd':
2976 return _CreateTypeNodeAndSkip(TYPE_DFLOAT64, 2, _node);
2977 case 'e':
2978 return _CreateTypeNodeAndSkip(TYPE_DFLOAT128, 2, _node);
2979 case 'f':
2980 return _CreateTypeNodeAndSkip(TYPE_DFLOAT32, 2, _node);
2981 case 'h':
2982 return _CreateTypeNodeAndSkip(TYPE_DFLOAT16, 2, _node);
2983 case 'i':
2984 return _CreateTypeNodeAndSkip(TYPE_CHAR16_T, 2, _node);
2985 case 's':
2986 return _CreateTypeNodeAndSkip(TYPE_CHAR32_T, 2, _node);
2987 default:
2988 return false;
2991 case 'u':
2993 fInput.Skip(1);
2994 Node* nameNode;
2995 return _ParseSourceName(nameNode)
2996 && NodeCreator<NamedTypeNode>(this)(nameNode, _node);
2999 default:
3000 return false;
3005 bool
3006 Demangler::_ParseFunctionType(FunctionNode*& _node)
3008 DEBUG_SCOPE("_ParseFunctionType");
3010 // <function-type> ::= F [Y] <bare-function-type> E
3012 if (!_SkipExpected('F'))
3013 return false;
3015 // is 'extern "C"'?
3016 bool isExternC = fInput.SkipPrefix('Y');
3018 // create function and parse function type
3019 if (!NodeCreator<FunctionNode>(this)((Node*)NULL, true, isExternC,
3020 _node)
3021 || !_ParseBareFunctionType(_node)) {
3022 return false;
3025 // skip terminating 'E'
3026 return _SkipExpected('E');
3030 bool
3031 Demangler::_ParseArrayType(Node*& _node)
3033 DEBUG_SCOPE("_ParseArrayType");
3035 // <array-type> ::= A <positive dimension number> _ <element type>
3036 // ::= A [<dimension expression>] _ <element type>
3038 if (fInput.CharsRemaining() < 2 || !fInput.SkipPrefix('A'))
3039 return _SetError(ERROR_INVALID);
3041 number_type dimensionNumber;
3042 Node* dimensionExpression = NULL;
3044 // If it looks like a number, it must be the first production, otherwise
3045 // the second one.
3046 if (isdigit(fInput[0])
3047 || (fInput[0] == 'n' && fInput.CharsRemaining() >= 2
3048 && isdigit(fInput[1]))) {
3049 if (!_ParseNumber(dimensionNumber))
3050 return false;
3051 } else {
3052 if (!_ParseExpression(dimensionExpression))
3053 return false;
3056 // parse the type
3057 Node* type;
3058 if (!_SkipExpected('_') || !_ParseType(type))
3059 return false;
3061 // create the array node
3062 return dimensionExpression != NULL
3063 ? NodeCreator<ArrayNode>(this)(type, dimensionExpression, _node)
3064 : NodeCreator<ArrayNode>(this)(type, dimensionNumber, _node);
3068 bool
3069 Demangler::_ParsePointerToMemberType(Node*& _node)
3071 DEBUG_SCOPE("_ParsePointerToMemberType");
3073 // <pointer-to-member-type> ::= M <class type> <member type>
3074 Node* classType;
3075 Node* memberType;
3076 return _SkipExpected('M')
3077 && _ParseType(classType)
3078 && _ParseType(memberType)
3079 && NodeCreator<PointerToMemberNode>(this)(classType, memberType,
3080 _node);
3084 bool
3085 Demangler::_ParseTemplateParam(Node*& _node)
3087 DEBUG_SCOPE("_ParseTemplateParam");
3089 // <template-param> ::= T_ # first template parameter
3090 // ::= T <parameter-2 non-negative number> _
3092 if (!_SkipExpected('T'))
3093 return false;
3094 if (fTemplatizedNode == NULL)
3095 return _SetError(ERROR_INVALID);
3097 // get the index;
3098 number_type index = 0;
3099 if (!fInput.HasPrefix('_')) {
3100 if (!_ParseNumber(index))
3101 return false;
3103 if (index < 0)
3104 return _SetError(ERROR_INVALID);
3105 index++;
3108 if (!_SkipExpected('_'))
3109 return false;
3111 // get the parameter
3112 Node* parameter = fTemplatizedNode->TemplateParameterAt(index);
3113 if (parameter == NULL)
3114 return _SetError(ERROR_INVALID);
3116 // create a substitution node
3117 return NodeCreator<SubstitutionNode>(this)(parameter, _node);
3121 bool
3122 Demangler::_ParseSubstitution(Node*& _node)
3124 DEBUG_SCOPE("_ParseSubstitution");
3126 if (!_ParseSubstitutionInternal(_node))
3127 return false;
3129 // substitutions are never referenceable
3130 _node->SetReferenceable(false);
3132 return true;
3136 bool
3137 Demangler::_ParseSubstitutionInternal(Node*& _node)
3139 DEBUG_SCOPE("_ParseSubstitutionInternal");
3141 // <substitution> ::= S <seq-id> _
3142 // ::= S_
3144 // <substitution> ::= St # ::std::
3145 // <substitution> ::= Sa # ::std::allocator
3146 // <substitution> ::= Sb # ::std::basic_string
3147 // <substitution> ::= Ss # ::std::basic_string < char,
3148 // ::std::char_traits<char>,
3149 // ::std::allocator<char> >
3150 // <substitution> ::= Si # ::std::basic_istream<char,
3151 // std::char_traits<char> >
3152 // <substitution> ::= So # ::std::basic_ostream<char,
3153 // std::char_traits<char> >
3154 // <substitution> ::= Sd # ::std::basic_iostream<char,
3155 // std::char_traits<char> >
3157 if (fInput.CharsRemaining() < 2 || !fInput.SkipPrefix('S'))
3158 return _SetError(ERROR_INVALID);
3160 switch (fInput[0]) {
3161 case 't':
3162 return _CreateNodeAndSkip("std", 1, _node);
3163 case 'a':
3164 return _CreateTypeNodeAndSkip("allocator", "std", NULL, 1,
3165 _node);
3166 case 'b':
3167 return _CreateTypeNodeAndSkip("basic_string", "std", NULL, 1,
3168 _node);
3169 case 's':
3170 return _CreateTypeNodeAndSkip("basic_string", "std",
3171 "char, std::char_traits<char>, std::allocator<char>", 1,
3172 _node);
3173 case 'i':
3174 return _CreateTypeNodeAndSkip("basic_istream", "std",
3175 "char, std::char_traits<char>", 1, _node);
3176 case 'o':
3177 return _CreateTypeNodeAndSkip("basic_ostream", "std",
3178 "char, std::char_traits<char>", 1, _node);
3179 case 'd':
3180 return _CreateTypeNodeAndSkip("basic_iostream", "std",
3181 "char, std::char_traits<char>", 1, _node);
3182 case '_':
3183 fInput.Skip(1);
3184 return _CreateSubstitutionNode(0, _node);
3187 // parse <seq-id>
3188 int seqID = 0;
3189 int count = fInput.CharsRemaining();
3190 int i = 0;
3191 for (; i < count && fInput[i] != '_'; i++) {
3192 char c = fInput[i];
3193 if (isdigit(c))
3194 seqID = seqID * 36 + (c - '0');
3195 else if (c >= 'A' && c <= 'Z')
3196 seqID = seqID * 36 + 10 + (c - 'A');
3197 else
3198 return _SetError(ERROR_INVALID);
3201 if (i == count)
3202 return _SetError(ERROR_INVALID);
3204 // skip digits and '_'
3205 fInput.Skip(i + 1);
3207 return _CreateSubstitutionNode(seqID + 1, _node);
3211 bool
3212 Demangler::_ParseBareFunctionType(FunctionNode* node)
3214 DEBUG_SCOPE("_ParseBareFunctionType");
3216 // <bare-function-type> ::= <signature type>+
3217 // # types are possible return type, then parameter types
3219 if (fInput.CharsRemaining() == 0)
3220 return _SetError(ERROR_INVALID);
3222 do {
3223 Node* typeNode;
3224 if (!_ParseType(typeNode))
3225 return false;
3227 node->AddType(typeNode);
3228 } while (fInput.CharsRemaining() > 0 && fInput[0] != 'E');
3229 // 'E' delimits <function-type>
3231 return true;
3235 bool
3236 Demangler::_ParseTemplateArgs(Node* node, Node*& _node)
3238 DEBUG_SCOPE("_ParseTemplateArgs");
3240 // <template-args> ::= I <template-arg>+ E
3242 if (!_SkipExpected('I'))
3243 return false;
3245 // we need at least one <template-arg>
3246 if (fInput.CharsRemaining() == 0 || fInput[0] == 'E')
3247 return _SetError(ERROR_INVALID);
3249 // create the node
3250 TemplateNode* templateNode;
3251 if (!NodeCreator<TemplateNode>(this)(node, templateNode))
3252 return false;
3253 _node = templateNode;
3255 // parse the args
3256 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3257 Node* arg;
3258 if (!_ParseTemplateArg(arg))
3259 return false;
3260 templateNode->AddArgument(arg);
3263 // skip the trailing 'E'
3264 return _SkipExpected('E');
3268 bool
3269 Demangler::_ParseTemplateArg(Node*& _node)
3271 DEBUG_SCOPE("_ParseTemplateArg");
3273 // <template-arg> ::= <type> # type or template
3274 // ::= X <expression> E # expression
3275 // ::= <expr-primary> # simple expressions
3276 // ::= I <template-arg>* E # argument pack
3277 // ::= sp <expression> # pack expansion of (C++0x)
3279 if (fInput.CharsRemaining() == 0)
3280 return _SetError(ERROR_INVALID);
3282 switch (fInput[0]) {
3283 case 'X': // X <expression> E
3284 fInput.Skip(1);
3285 return _ParseExpression(_node) && _SkipExpected('E');
3287 case 'L': // <expr-primary>
3288 return _ParseExpressionPrimary(_node);
3290 case 'I': // I <template-arg>* E
3292 #if 0
3293 fInput.Skip(1);
3295 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3296 Node* arg;
3297 if (!_ParseTemplateArg(arg))
3298 return false;
3301 if (!fInput.SkipPrefix('E'))
3302 return _SetError(ERROR_INVALID);
3303 return true;
3304 #endif
3305 // NOTE: Unsupported by the GNU demangler.
3306 return _SetError(ERROR_UNSUPPORTED);
3309 case 's':
3310 if (fInput.SkipPrefix("sp")) {
3311 // sp <expression>
3312 #if 0
3313 return _ParseExpression(_node);
3314 #endif
3315 // NOTE: Unsupported by the GNU demangler.
3316 return _SetError(ERROR_UNSUPPORTED);
3319 // fall through...
3321 default: // <type>
3322 return _ParseType(_node);
3327 bool
3328 Demangler::_ParseExpression(Node*& _node)
3330 DEBUG_SCOPE("_ParseExpression");
3332 // <expression> ::= <unary operator-name> <expression>
3333 // ::= <binary operator-name> <expression> <expression>
3334 // ::= <trinary operator-name> <expression> <expression>
3335 // <expression>
3336 // ::= cl <expression>* E # call
3337 // ::= cv <type> expression # conversion with one
3338 // argument
3339 // ::= cv <type> _ <expression>* E # conversion with a
3340 // different number of
3341 // arguments
3342 // ::= st <type> # sizeof (a type)
3343 // ::= at <type> # alignof (a type)
3344 // ::= <template-param>
3345 // ::= <function-param>
3346 // ::= sr <type> <unqualified-name>
3347 // # dependent name
3348 // ::= sr <type> <unqualified-name> <template-args>
3349 // # dependent template-id
3350 // ::= sZ <template-param>
3351 // # size of a parameter pack
3352 // ::= <expr-primary>
3354 // <expr-primary> ::= L <type> <value number> E # integer literal
3355 // ::= L <type <value float> E # floating literal
3356 // ::= L <mangled-name> E # external name
3358 if (fInput.CharsRemaining() == 0)
3359 return _SetError(ERROR_INVALID);
3361 switch (fInput[0]) {
3362 case 'L':
3363 return _ParseExpressionPrimary(_node);
3364 case 'T':
3365 return _ParseTemplateParam(_node);
3366 // NOTE: <function-param> is not defined in the specs!
3369 // must be an operator
3370 if (fInput.CharsRemaining() < 2)
3371 return _SetError(ERROR_INVALID);
3373 // some operators need special handling
3375 if (fInput.SkipPrefix("cl")) {
3376 // cl <expression>* E # call
3377 CallNode* callNode;
3378 if (!NodeCreator<CallNode>(this)(callNode))
3379 return false;
3381 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3382 Node* subExpression;
3383 if (!_ParseExpression(subExpression))
3384 return false;
3385 callNode->AddSubExpression(subExpression);
3388 _node = callNode;
3389 return _SkipExpected('E');
3392 if (fInput.SkipPrefix("cv")) {
3393 // cv <type> expression # conversion with one argument
3394 // cv <type> _ <expression>* E # conversion with a different number
3395 // of arguments
3397 // parse the type
3398 Node* type;
3399 if (!_ParseType(type))
3400 return false;
3402 // create a conversion expression node
3403 ConversionExpressionNode* expression;
3404 if (!NodeCreator<ConversionExpressionNode>(this)(type, expression))
3405 return false;
3406 _node = expression;
3408 if (fInput.SkipPrefix('_')) {
3409 // multi argument conversion
3410 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3411 Node* subExpression;
3412 if (!_ParseExpression(subExpression))
3413 return false;
3414 expression->AddSubExpression(subExpression);
3417 return _SkipExpected('E');
3420 // single argument conversion
3421 Node* subExpression;
3422 if (!_ParseExpression(subExpression))
3423 return false;
3424 expression->AddSubExpression(subExpression);
3426 return true;
3429 if (fInput.SkipPrefix("sr")) {
3430 // sr <type> <unqualified-name>
3431 // sr <type> <unqualified-name> <template-args>
3433 // parse type and unqualified name and create the node
3434 Node* type;
3435 Node* name;
3436 if (!_ParseType(type) || !_ParseUnqualifiedName(name)
3437 || !NodeCreator<DependentNameNode>(this)(type, name, _node)) {
3438 return false;
3441 // If there are template arguments left, add them.
3442 if (!fInput.HasPrefix('I'))
3443 return true;
3445 return _ParseTemplateArgs(_node, _node);
3448 if (fInput.SkipPrefix("sZ")) {
3449 // sZ <template-param>
3451 // NOTE: Unsupported by the GNU demangler.
3452 return _SetError(ERROR_UNSUPPORTED);
3455 // no special operator, so have a look for the others
3457 const operator_info* info = NULL;
3458 for (int i = 0; kOperatorInfos[i].name != NULL; i++) {
3459 if (fInput.SkipPrefix(kOperatorInfos[i].mangled_name)) {
3460 info = &kOperatorInfos[i];
3461 break;
3465 // We can only deal with operators with a fixed argument count at this
3466 // point.
3467 if (info == NULL || info->argument_count < 0)
3468 return _SetError(ERROR_INVALID);
3470 // create an operator node
3471 OperatorExpressionNode* operatorNode;
3472 if (!NodeCreator<OperatorExpressionNode>(this)(info, operatorNode))
3473 return false;
3475 // parse the arguments
3476 int i = 0;
3478 // the first one might be a type
3479 if ((info->flags & OPERATOR_TYPE_PARAM) != 0) {
3480 Node* type;
3481 if (!_ParseType(type))
3482 return false;
3484 operatorNode->AddSubExpression(type);
3485 i++;
3488 // the others are expressions
3489 for (; i < info->argument_count; i++) {
3490 Node* subExpression;
3491 if (!_ParseExpression(subExpression))
3492 return false;
3493 operatorNode->AddSubExpression(subExpression);
3496 _node = operatorNode;
3497 return true;
3501 bool
3502 Demangler::_ParseExpressionPrimary(Node*& _node)
3504 DEBUG_SCOPE("_ParseExpressionPrimary");
3506 // <expr-primary> ::= L <type> <value number> E # integer literal
3507 // ::= L <type <value float> E # floating literal
3508 // ::= L <mangled-name> E # external name
3510 if (!_SkipExpected('L'))
3511 return false;
3513 if (fInput.SkipPrefix("_Z")) {
3514 ObjectNode* node;
3515 if (!_ParseEncoding(node))
3516 return false;
3517 _node = node;
3518 } else {
3519 // number or float literal
3520 Node* type;
3521 if (!_ParseType(type))
3522 return false;
3524 // GNU's demangler doesn't really seem to parse the integer/float,
3525 // but only replaces a leading 'n' by '-'. Good enough for us, too.
3527 // determine the length
3528 int maxLength = fInput.CharsRemaining();
3529 int length = 0;
3530 while (length < maxLength && fInput[length] != 'E')
3531 length++;
3533 if (length == 0)
3534 return _SetError(ERROR_INVALID);
3536 if (!NodeCreator<TypedNumberLiteralNode>(this)(type,
3537 fInput.String(), length, _node)) {
3538 return false;
3541 fInput.Skip(length);
3544 return _SkipExpected('E');
3548 bool
3549 Demangler::_ParseNumber(number_type& number)
3551 DEBUG_SCOPE("_ParseNumber");
3553 bool negative = fInput.SkipPrefix('n');
3555 if (fInput.CharsRemaining() == 0)
3556 return _SetError(ERROR_INVALID);
3558 number = 0;
3559 int count = fInput.CharsRemaining();
3560 int i = 0;
3561 for (; i < count && isdigit(fInput[i]); i++)
3562 number = number * 10 + (fInput[i] - '0');
3564 fInput.Skip(i);
3566 if (negative)
3567 number =-number;
3568 return true;
3572 bool
3573 Demangler::_CreateNodeAndSkip(const char* name, size_t length, int toSkip,
3574 Node*& _node)
3576 if (toSkip > 0)
3577 fInput.Skip(toSkip);
3579 return NodeCreator<SimpleNameNode>(this)(name, length, _node);
3583 bool
3584 Demangler::_CreateNodeAndSkip(const char* name, int toSkip, Node*& _node)
3586 return _CreateNodeAndSkip(name, strlen(name), toSkip, _node);
3590 bool
3591 Demangler::_CreateTypeNodeAndSkip(type_type type, int toSkip, Node*& _node)
3593 if (toSkip > 0)
3594 fInput.Skip(toSkip);
3596 return NodeCreator<SimpleTypeNode>(this)(type, _node);
3600 bool
3601 Demangler::_CreateTypeNodeAndSkip(const char* name, const char* prefix,
3602 const char* templateArgs, int toSkip, Node*& _node)
3604 if (toSkip > 0)
3605 fInput.Skip(toSkip);
3607 // create the name node
3608 if (!NodeCreator<SimpleTypeNode>(this)(name, _node))
3609 return false;
3611 // add the prefix
3612 if (prefix != NULL) {
3613 Node* prefixNode;
3614 if (!NodeCreator<SimpleTypeNode>(this)(prefix, prefixNode)
3615 || !NodeCreator<PrefixedNode>(this)(prefixNode, _node, _node)) {
3616 return false;
3620 // wrap the node to add the template args
3621 if (templateArgs != NULL) {
3622 TemplateNode* templateNode;
3623 Node* argsNode;
3624 if (!NodeCreator<TemplateNode>(this)(_node, templateNode)
3625 || !NodeCreator<SimpleTypeNode>(this)(templateArgs, argsNode)) {
3626 return false;
3628 templateNode->AddArgument(argsNode);
3629 _node = templateNode;
3632 return true;
3636 void
3637 Demangler::_RegisterReferenceableNode(Node* node)
3639 // check, if not referenceable or already registered
3640 if (!node->IsReferenceable() || node == fLastReferenceableNode
3641 || node->NextReferenceable() != NULL) {
3642 return;
3645 if (fFirstReferenceableNode == NULL) {
3646 fFirstReferenceableNode = node;
3647 fLastReferenceableNode = node;
3648 } else {
3649 fLastReferenceableNode->SetNextReferenceable(node);
3650 fLastReferenceableNode = node;
3655 bool
3656 Demangler::_CreateSubstitutionNode(int index, Node*& _node)
3658 Node* node = fFirstReferenceableNode;
3659 while (node != NULL && index > 0) {
3660 node = node->NextReferenceable();
3661 index--;
3664 if (node == NULL)
3665 return _SetError(ERROR_INVALID);
3667 // create a substitution node
3668 return NodeCreator<SubstitutionNode>(this)(node, _node);
3672 // #pragma mark -
3675 const char*
3676 demangle_symbol_gcc3(const char* mangledName, char* buffer, size_t bufferSize,
3677 bool* _isObjectMethod)
3679 bool isObjectMethod;
3680 if (_isObjectMethod == NULL)
3681 _isObjectMethod = &isObjectMethod;
3683 Demangler demangler;
3684 DemanglingInfo info(true);
3685 if (demangler.Demangle(mangledName, buffer, bufferSize, info) != ERROR_OK)
3686 return NULL;
3688 // Set the object method return value. Unless we know for sure that it isn't
3689 // an object method, we assume that it is.
3690 switch (info.objectType) {
3691 case OBJECT_TYPE_DATA:
3692 case OBJECT_TYPE_FUNCTION:
3693 case OBJECT_TYPE_METHOD_CLASS:
3694 *_isObjectMethod = false;
3695 break;
3696 case OBJECT_TYPE_METHOD_OBJECT:
3697 *_isObjectMethod = true;
3698 break;
3699 case OBJECT_TYPE_UNKNOWN:
3700 case OBJECT_TYPE_METHOD_UNKNOWN:
3701 *_isObjectMethod = strstr(buffer, "::") != NULL;
3702 break;
3705 return buffer;
3709 status_t
3710 get_next_argument_gcc3(uint32* _cookie, const char* mangledName, char* name,
3711 size_t nameSize, int32* _type, size_t* _argumentLength)
3713 Demangler demangler;
3714 ParameterInfo info;
3715 int result = demangler.GetParameterInfo(mangledName, *_cookie, name,
3716 nameSize, info);
3717 if (result != ERROR_OK) {
3718 switch (result) {
3719 case ERROR_NOT_MANGLED:
3720 return B_BAD_VALUE;
3721 case ERROR_UNSUPPORTED:
3722 return B_BAD_VALUE;
3723 case ERROR_INVALID:
3724 return B_BAD_VALUE;
3725 case ERROR_BUFFER_TOO_SMALL:
3726 return B_BUFFER_OVERFLOW;
3727 case ERROR_NO_MEMORY:
3728 return B_NO_MEMORY;
3729 case ERROR_INTERNAL:
3730 default:
3731 return B_ERROR;
3735 // translate the type
3736 switch (info.type.type) {
3737 case TYPE_BOOL:
3738 *_type = B_BOOL_TYPE;
3739 *_argumentLength = 1;
3740 break;
3742 case TYPE_CHAR:
3743 *_type = B_CHAR_TYPE;
3744 *_argumentLength = 1;
3745 break;
3747 case TYPE_SIGNED_CHAR:
3748 *_type = B_INT8_TYPE;
3749 *_argumentLength = 1;
3750 break;
3751 case TYPE_UNSIGNED_CHAR:
3752 *_type = B_UINT8_TYPE;
3753 *_argumentLength = 1;
3754 break;
3756 case TYPE_SHORT:
3757 *_type = B_INT16_TYPE;
3758 *_argumentLength = 2;
3759 break;
3760 case TYPE_UNSIGNED_SHORT:
3761 *_type = B_UINT16_TYPE;
3762 *_argumentLength = 2;
3763 break;
3765 case TYPE_INT:
3766 *_type = B_INT32_TYPE;
3767 *_argumentLength = 4;
3768 break;
3769 case TYPE_UNSIGNED_INT:
3770 *_type = B_UINT32_TYPE;
3771 *_argumentLength = 4;
3772 break;
3774 case TYPE_LONG:
3775 *_type = sizeof(long) == 4 ? B_INT32_TYPE : B_INT64_TYPE;
3776 *_argumentLength = sizeof(long);
3777 break;
3778 case TYPE_UNSIGNED_LONG:
3779 *_type = sizeof(long) == 4 ? B_UINT32_TYPE : B_UINT64_TYPE;
3780 *_argumentLength = sizeof(long);
3781 break;
3783 case TYPE_LONG_LONG:
3784 *_type = B_INT64_TYPE;
3785 *_argumentLength = 8;
3786 break;
3787 case TYPE_UNSIGNED_LONG_LONG:
3788 *_type = B_INT64_TYPE;
3789 *_argumentLength = 8;
3790 break;
3792 case TYPE_INT128:
3793 *_type = 0;
3794 *_argumentLength = 16;
3795 break;
3796 case TYPE_UNSIGNED_INT128:
3797 *_type = 0;
3798 *_argumentLength = 16;
3799 break;
3801 case TYPE_FLOAT:
3802 *_type = B_FLOAT_TYPE;
3803 *_argumentLength = sizeof(float);
3804 break;
3805 case TYPE_DOUBLE:
3806 *_type = B_DOUBLE_TYPE;
3807 *_argumentLength = sizeof(double);
3808 break;
3810 case TYPE_LONG_DOUBLE:
3811 *_type = 0;
3812 *_argumentLength = sizeof(long double);
3813 break;
3815 case TYPE_FLOAT128:
3816 *_type = 0;
3817 *_argumentLength = 16;
3818 break;
3820 case TYPE_DFLOAT16:
3821 *_argumentLength = 2;
3822 case TYPE_DFLOAT32:
3823 *_argumentLength *= 2;
3824 case TYPE_DFLOAT64:
3825 *_argumentLength *= 2;
3826 case TYPE_DFLOAT128:
3827 *_argumentLength *= 2;
3828 *_type = 0;
3829 break;
3831 case TYPE_CHAR16_T:
3832 *_type = B_UINT16_TYPE;
3833 *_argumentLength = 2;
3834 break;
3836 case TYPE_CHAR32_T:
3837 *_type = B_UINT32_TYPE;
3838 *_argumentLength = 2;
3839 break;
3841 case TYPE_CONST_CHAR_POINTER:
3842 *_type = B_STRING_TYPE;
3843 *_argumentLength = sizeof(void*);
3844 break;
3846 case TYPE_POINTER:
3847 *_type = B_POINTER_TYPE;
3848 *_argumentLength = sizeof(void*);
3849 break;
3851 case TYPE_REFERENCE:
3852 *_type = B_REF_TYPE;
3853 // TODO: That's actually entry_ref!
3854 *_argumentLength = sizeof(void*);
3855 break;
3857 case TYPE_WCHAR_T:
3858 // TODO: Type/size might change!
3859 *_type = B_UINT16_TYPE;
3860 *_argumentLength = 2;
3861 break;
3863 case TYPE_UNKNOWN:
3864 case TYPE_ELLIPSIS:
3865 case TYPE_VOID:
3866 default:
3867 // Well, tell our caller *something*.
3868 *_type = 0;
3869 *_argumentLength = sizeof(int);
3872 // assume sizeof(int) argument alignment
3873 if (*_argumentLength < sizeof(int))
3874 *_argumentLength = sizeof(int);
3876 ++*_cookie;
3877 return B_OK;
3881 #ifndef _KERNEL_MODE
3883 const char*
3884 demangle_name_gcc3(const char* mangledName, char* buffer, size_t bufferSize)
3887 Demangler demangler;
3888 DemanglingInfo info(false);
3889 if (demangler.Demangle(mangledName, buffer, bufferSize, info) != ERROR_OK)
3890 return NULL;
3891 return buffer;
3894 #endif