2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
14 #include <TypeConstants.h>
17 # include <debug_heap.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())
31 # define TRACE(x...) ;
32 # define DEBUG_SCOPE(name) do {} while (false)
36 # define PRINT(format...) kprintf(format)
37 # define VPRINT(format, args) PRINT("%s", format)
39 # define NEW(constructor) new(kdebug_alloc) constructor
40 # define DELETE(object) DebugAlloc::destroy(object)
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
49 typedef long number_type
;
56 ERROR_BUFFER_TOO_SMALL
,
59 ERROR_INVALID_PARAMETER_INDEX
62 // object classification
67 OBJECT_TYPE_METHOD_CLASS
,
68 OBJECT_TYPE_METHOD_OBJECT
,
69 OBJECT_TYPE_METHOD_UNKNOWN
72 // prefix classification
80 // type classification
96 TYPE_UNSIGNED_LONG_LONG
,
111 TYPE_CONST_CHAR_POINTER
,
116 const char* const kTypeNames
[] = {
131 "unsigned long long",
138 "__dfloat16", // TODO: Official names for the __dfloat*!
152 // CV qualifier flags
154 CV_QUALIFIER_RESTRICT
= 0x1,
155 CV_QUALIFIER_VOLATILE
= 0x2,
156 CV_QUALIFIER_CONST
= 0x4
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
[] = {
175 struct operator_info
{
176 const char* mangled_name
;
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
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 },
224 { "le", "<=", 2, 0 },
225 { "ge", ">=", 2, 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 },
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
248 DebugScope(const char* functionName
, const char* remainingString
= NULL
)
250 fParent(sGlobalScope
),
251 fFunctionName(functionName
),
252 fLevel(fParent
!= NULL
? fParent
->fLevel
+ 1 : 0)
255 if (remainingString
!= NULL
) {
256 PRINT("%*s%s(): \"%s\"\n", fLevel
* 2, "", fFunctionName
,
259 PRINT("%*s%s()\n", fLevel
* 2, "", fFunctionName
);
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;
273 va_start(args
, format
);
274 PRINT("%*s", (level
+ 1) * 2, "");
275 VPRINT(format
, args
);
281 const char* fFunctionName
;
284 static DebugScope
* sGlobalScope
;
287 DebugScope
* DebugScope::sGlobalScope
= NULL
;
289 #endif // TRACE_GCC3_DEMANGLER
301 void SetTo(const char* string
, size_t length
)
307 const char* String() const
312 int CharsRemaining() const
317 void Skip(size_t count
)
319 if (count
> fLength
) {
320 PRINT("Input::Skip(): fOffset > fLength\n");
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
))
350 bool SkipPrefix(const char* prefix
)
352 size_t prefixLen
= strlen(prefix
);
353 if (prefixLen
<= fLength
&& strncmp(fString
, prefix
, prefixLen
) != 0)
356 fString
+= prefixLen
;
357 fLength
-= prefixLen
;
361 char operator[](size_t index
) const
363 if (index
>= fLength
) {
364 PRINT("Input::operator[](): fOffset + index >= fLength\n");
368 return fString
[index
];
379 NameBuffer(char* buffer
, size_t size
)
393 char LastChar() const
395 return fLength
> 0 ? fBuffer
[fLength
- 1] : '\0';
398 bool HadOverflow() const
405 fBuffer
[fLength
] = '\0';
409 bool Append(const char* string
, size_t length
)
411 if (fLength
+ length
>= fSize
) {
416 memcpy(fBuffer
+ fLength
, string
, length
);
421 bool Append(const char* string
)
423 return Append(string
, strlen(string
));
445 TypeInfo(type_type type
)
452 TypeInfo(const TypeInfo
& other
, int cvQualifiers
= 0)
455 cvQualifiers(other
.cvQualifiers
| cvQualifiers
)
459 TypeInfo
& operator=(const TypeInfo
& other
)
462 cvQualifiers
= other
.cvQualifiers
;
468 struct DemanglingParameters
{
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
{
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
;
520 firstCVQualifier(NULL
),
521 firstNonCVQualifier(NULL
)
531 fNextAllocated(NULL
),
534 fNextReferenceable(NULL
),
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
))
566 return decorationInfo
.firstDecorator
== NULL
567 || decorationInfo
.firstDecorator
->AddDecoration(buffer
, NULL
);
570 virtual bool AddDecoration(NameBuffer
& buffer
,
571 const Node
* stopDecorator
) const
576 virtual void GetCVQualifierInfo(CVQualifierInfo
& info
) const
578 info
.firstNonCVQualifier
= this;
581 virtual Node
* GetUnqualifiedNode(Node
* beforeNode
)
586 virtual bool IsTemplatized() const
591 virtual Node
* TemplateParameterAt(int index
) const
596 virtual bool IsNoReturnValueFunction() const
601 virtual bool IsTypeName(const char* name
, size_t length
) const
606 virtual object_type
ObjectType() const
608 return OBJECT_TYPE_UNKNOWN
;
611 virtual prefix_type
PrefixType() const
616 virtual TypeInfo
Type() const
622 Node
* fNextAllocated
;
625 Node
* fNextReferenceable
;
630 class NamedTypeNode
: public Node
{
632 NamedTypeNode(Node
* name
)
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();
660 class SubstitutionNode
: public Node
{
662 SubstitutionNode(Node
* 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();
730 class ArrayNode
: public NamedTypeNode
{
732 ArrayNode(Node
* type
, int dimension
)
735 fDimensionExpression(NULL
),
736 fDimensionNumber(dimension
)
740 ArrayNode(Node
* type
, Node
* dimension
)
743 fDimensionExpression(dimension
),
746 fDimensionExpression
->SetParent(this);
749 virtual bool GetName(NameBuffer
& buffer
) const
751 if (!fName
->GetName(buffer
))
754 buffer
.Append("[", 1);
756 if (fDimensionExpression
!= NULL
) {
757 if (!fDimensionExpression
->GetName(buffer
))
760 char stringBuffer
[16];
761 snprintf(stringBuffer
, sizeof(stringBuffer
), "%d",
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
777 return TypeInfo(TYPE_POINTER
);
782 Node
* fDimensionExpression
;
783 int fDimensionNumber
;
787 class ObjectNode
: public NamedTypeNode
{
789 ObjectNode(Node
* 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
816 class SimpleNameNode
: public Node
{
818 SimpleNameNode(const char* name
)
821 fLength(strlen(name
))
825 SimpleNameNode(const char* name
, size_t length
)
832 virtual bool GetName(NameBuffer
& buffer
) const
834 return buffer
.Append(fName
, fLength
);
843 class SimpleTypeNode
: public SimpleNameNode
{
845 SimpleTypeNode(const char* name
)
847 SimpleNameNode(name
),
852 SimpleTypeNode(type_type type
)
854 SimpleNameNode(kTypeNames
[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
);
879 class TypedNumberLiteralNode
: public Node
{
881 TypedNumberLiteralNode(Node
* type
, const char* number
, size_t 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)) {
902 if (!fType
->GetName(buffer
))
907 // add the number -- replace a leading 'n' by '-', if necessary
908 if (fLength
> 0 && fNumber
[0] == 'n') {
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
;
928 class XtructorNode
: public Node
{
930 XtructorNode(bool constructor
, char type
)
932 fConstructor(constructor
),
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
)
951 return fUnqualifiedNode
->GetName(buffer
);
954 virtual bool IsNoReturnValueFunction() const
959 virtual object_type
ObjectType() const
961 return OBJECT_TYPE_METHOD_CLASS
;
967 Node
* fUnqualifiedNode
;
971 class SpecialNameNode
: public Node
{
973 SpecialNameNode(const char* name
, Node
* child
)
978 fChild
->SetParent(this);
981 virtual bool GetName(NameBuffer
& buffer
) const
983 return buffer
.Append(fName
) && fChild
->GetName(buffer
);
992 class DecoratingNode
: public Node
{
994 DecoratingNode(Node
* 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
);
1019 class CVQualifiersNode
: public DecoratingNode
{
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
)
1042 if (!fChildNode
->AddDecoration(buffer
, stopDecorator
))
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");
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
);
1097 class TypeModifierNode
: public DecoratingNode
{
1099 TypeModifierNode(type_modifier modifier
, Node
* child
)
1101 DecoratingNode(child
),
1106 virtual bool AddDecoration(NameBuffer
& buffer
,
1107 const Node
* stopDecorator
) const
1109 if (this == stopDecorator
)
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
);
1140 type_modifier fModifier
;
1144 class VendorTypeModifierNode
: public DecoratingNode
{
1146 VendorTypeModifierNode(Node
* name
, Node
* child
)
1148 DecoratingNode(child
),
1151 fName
->SetParent(this);
1154 virtual bool AddDecoration(NameBuffer
& buffer
,
1155 const Node
* stopDecorator
) const
1157 if (this == stopDecorator
)
1160 return fChildNode
->AddDecoration(buffer
, stopDecorator
)
1161 && buffer
.Append(" ")
1162 && fName
->GetName(buffer
);
1165 virtual object_type
ObjectType() const
1167 return OBJECT_TYPE_DATA
;
1175 class OperatorNode
: public Node
{
1177 OperatorNode(const operator_info
* 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
;
1198 const operator_info
* fInfo
;
1202 class VendorOperatorNode
: public Node
{
1204 VendorOperatorNode(Node
* name
)
1208 fName
->SetParent(this);
1209 SetReferenceable(false);
1212 virtual bool GetName(NameBuffer
& buffer
) const
1214 return buffer
.Append("operator ")
1215 && fName
->GetName(buffer
);
1223 class CastOperatorNode
: public Node
{
1225 CastOperatorNode(Node
* 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
1242 virtual object_type
ObjectType() const
1244 return OBJECT_TYPE_METHOD_OBJECT
;
1252 class PrefixedNode
: public Node
{
1254 PrefixedNode(Node
* prefix
, Node
* node
)
1256 fPrefixNode(prefix
),
1259 fPrefixNode
->SetParent(this);
1260 fNode
->SetParent(this);
1263 virtual bool GetName(NameBuffer
& buffer
) const
1265 if (!fPrefixNode
->GetName(buffer
))
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
;
1300 typedef PrefixedNode DependentNameNode
;
1303 class TemplateNode
: public Node
{
1305 TemplateNode(Node
* base
)
1308 fFirstArgument(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
;
1322 fFirstArgument
= child
;
1323 fLastArgument
= child
;
1327 virtual bool GetName(NameBuffer
& buffer
) const
1329 if (!fBase
->GetName(buffer
))
1334 Node
* child
= fFirstArgument
;
1335 while (child
!= NULL
) {
1336 if (child
!= fFirstArgument
)
1337 buffer
.Append(", ");
1339 if (!child
->GetName(buffer
))
1342 child
= child
->Next();
1345 // add a space between consecutive '>'
1346 if (buffer
.LastChar() == '>')
1349 return buffer
.Append(">");
1352 virtual Node
* GetUnqualifiedNode(Node
* beforeNode
)
1354 return fBase
!= beforeNode
1355 ? fBase
->GetUnqualifiedNode(beforeNode
) : this;
1358 virtual bool IsTemplatized() const
1363 virtual Node
* TemplateParameterAt(int index
) const
1365 Node
* child
= fFirstArgument
;
1366 while (child
!= NULL
) {
1370 child
= child
->Next();
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();
1393 Node
* fFirstArgument
;
1394 Node
* fLastArgument
;
1398 class MultiSubExpressionsNode
: public Node
{
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
;
1415 fFirstSubExpression
= child
;
1416 fLastSubExpression
= child
;
1421 Node
* fFirstSubExpression
;
1422 Node
* fLastSubExpression
;
1426 class CallNode
: public MultiSubExpressionsNode
{
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
))
1445 child
= child
->Next();
1455 class OperatorExpressionNode
: public MultiSubExpressionsNode
{
1457 OperatorExpressionNode(const operator_info
* 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)) {
1471 buffer
.Append(fInfo
->name
);
1476 Node
* child
= fFirstSubExpression
;
1477 while (child
!= NULL
) {
1478 if (child
!= fFirstSubExpression
)
1479 buffer
.Append(", ");
1481 if (!child
->GetName(buffer
))
1484 child
= child
->Next();
1493 Node
* arg1
= fFirstSubExpression
;
1494 Node
* arg2
= arg1
->Next();
1498 if (fInfo
->argument_count
== 2) {
1499 // binary infix operator
1500 if (!arg1
->GetName(buffer
))
1504 buffer
.Append(fInfo
->name
);
1507 if (!arg2
->GetName(buffer
))
1510 return buffer
.Append(")");
1513 Node
* arg3
= arg2
->Next();
1515 if (fInfo
->argument_count
== 2) {
1516 // trinary operator "... ? ... : ..."
1517 if (!arg1
->GetName(buffer
))
1520 buffer
.Append(" ? ");
1522 if (!arg2
->GetName(buffer
))
1525 buffer
.Append(" : ");
1527 if (!arg3
->GetName(buffer
))
1530 return buffer
.Append(")");
1537 const operator_info
* fInfo
;
1541 class ConversionExpressionNode
: public MultiSubExpressionsNode
{
1543 ConversionExpressionNode(Node
* type
)
1547 fType
->SetParent(this);
1550 virtual bool GetName(NameBuffer
& buffer
) const
1554 if (!fType
->GetName(buffer
))
1557 buffer
.Append(")(");
1559 Node
* child
= fFirstSubExpression
;
1560 while (child
!= NULL
) {
1561 if (child
!= fFirstSubExpression
)
1562 buffer
.Append(", ");
1564 if (!child
->GetName(buffer
))
1567 child
= child
->Next();
1570 return buffer
.Append(")");
1578 class PointerToMemberNode
: public DecoratingNode
{
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
)
1594 if (!fChildNode
->AddDecoration(buffer
, stopDecorator
))
1597 // In most cases we need a space before the name. In some it is
1598 // superfluous, though.
1599 if (!buffer
.IsEmpty() && buffer
.LastChar() != '(')
1602 if (!fClassType
->GetName(buffer
))
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
);
1626 class FunctionNode
: public ObjectNode
{
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
;
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"'
1662 // buffer.Append("extern \"C\"");
1664 // write the return type
1665 Node
* child
= fFirstTypeNode
;
1666 if (_HasReturnType() && child
!= NULL
) {
1667 if (!child
->GetName(buffer
))
1669 child
= child
->Next();
1671 buffer
.Append(" ", 1);
1674 // write the function name
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
)) {
1688 // add non-CV qualifier decorations
1689 if (decorationInfo
.firstDecorator
!= NULL
) {
1690 if (!decorationInfo
.firstDecorator
->AddDecoration(buffer
,
1691 decorationInfo
.closestCVDecoratorList
)) {
1697 buffer
.Append(")", 1);
1699 // add the parameter types
1702 // don't add a single "void" parameter
1703 if (child
!= NULL
&& child
->Next() == NULL
1704 && child
->IsTypeName("void", 4)) {
1708 Node
* firstParam
= child
;
1709 while (child
!= NULL
) {
1710 if (child
!= firstParam
)
1711 buffer
.Append(", ");
1713 if (!child
->GetName(buffer
))
1716 child
= child
->Next();
1721 // add CV qualifiers on our name
1722 if (info
.firstCVQualifier
!= NULL
) {
1723 if (!info
.firstCVQualifier
->AddDecoration(buffer
,
1724 info
.firstNonCVQualifier
)) {
1729 // add CV qualifiers on us
1730 if (decorationInfo
.closestCVDecoratorList
!= NULL
)
1731 decorationInfo
.closestCVDecoratorList
->AddDecoration(buffer
, NULL
);
1736 virtual object_type
ObjectType() const
1740 return OBJECT_TYPE_FUNCTION
;
1742 // check our name's prefix
1743 switch (fName
->PrefixType()) {
1745 case PREFIX_NAMESPACE
:
1746 return OBJECT_TYPE_FUNCTION
;
1748 case PREFIX_UNKNOWN
:
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();
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.
1762 case OBJECT_TYPE_UNKNOWN
:
1763 case OBJECT_TYPE_DATA
:
1765 // Obviously our name doesn't have a clue.
1766 return OBJECT_TYPE_METHOD_UNKNOWN
;
1770 virtual Node
* ParameterAt(uint32 index
) const
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)) {
1783 // get the type at the index
1784 while (child
!= NULL
&& index
> 0) {
1785 child
= child
->Next();
1793 bool _HasReturnType() const
1795 return fHasReturnType
1797 || (fName
->IsTemplatized() && !fName
->IsNoReturnValueFunction());
1801 Node
* fFirstTypeNode
;
1802 Node
* fLastTypeNode
;
1803 bool fHasReturnType
;
1808 // #pragma mark - Demangler
1815 int Demangle(const char* mangledName
, char* buffer
,
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
);
1827 template<typename NodeType
> struct NodeCreator
;
1829 inline bool _SkipExpected(char c
);
1830 inline bool _SkipExpected(const char* string
);
1835 int _Demangle(const char* mangledName
, char* buffer
,
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
,
1880 bool _CreateTypeNodeAndSkip(type_type type
,
1881 int toSkip
, Node
*& _node
);
1882 bool _CreateTypeNodeAndSkip(const char* name
,
1884 const char* templateArgs
, int toSkip
,
1887 void _RegisterReferenceableNode(Node
* node
);
1888 bool _CreateSubstitutionNode(int index
,
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
);
1914 return fDemangler
->_SetError(ERROR_NO_MEMORY
);
1916 fDemangler
->_AddAllocatedNode(_node
);
1920 template<typename ParameterType1
, typename ReturnType
>
1921 inline bool operator()(ParameterType1 arg1
, ReturnType
*& _node
) const
1923 _node
= NEW(NodeType(arg1
));
1925 return fDemangler
->_SetError(ERROR_NO_MEMORY
);
1927 fDemangler
->_AddAllocatedNode(_node
);
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
));
1938 return fDemangler
->_SetError(ERROR_NO_MEMORY
);
1940 fDemangler
->_AddAllocatedNode(_node
);
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
));
1951 return fDemangler
->_SetError(ERROR_NO_MEMORY
);
1953 fDemangler
->_AddAllocatedNode(_node
);
1958 Demangler
* fDemangler
;
1963 Demangler::_SetError(int error
)
1965 if (fError
== ERROR_OK
) {
1967 #ifdef TRACE_GCC3_DEMANGLER
1968 DebugScope::Print("_SetError(): %d, remaining input: \"%s\"\n",
1969 error
, fInput
.String());
1977 Demangler::_AddAllocatedNode(Node
* node
)
1979 node
->SetNextAllocated(fAllocatedNodes
);
1980 fAllocatedNodes
= node
;
1985 Demangler::_SkipExpected(char c
)
1987 return fInput
.SkipPrefix(c
) || _SetError(ERROR_INVALID
);
1992 Demangler::_SkipExpected(const char* string
)
1994 return fInput
.SkipPrefix(string
) || _SetError(ERROR_INVALID
);
1998 Demangler::Demangler()
2001 fAllocatedNodes(NULL
)
2007 Demangler::Demangle(const char* mangledName
, char* buffer
, size_t size
,
2008 DemanglingInfo
& demanglingInfo
)
2010 DEBUG_SCOPE("Demangle");
2014 int result
= _Demangle(mangledName
, buffer
, size
, demanglingInfo
);
2023 Demangler::GetParameterInfo(const char* mangledName
, uint32 index
, char* buffer
,
2024 size_t size
, ParameterInfo
& info
)
2026 DEBUG_SCOPE("GetParameterInfo");
2030 int result
= _GetParameterInfo(mangledName
, index
, buffer
, size
, info
);
2043 fFirstReferenceableNode
= NULL
;
2044 fLastReferenceableNode
= NULL
;
2045 fAllocatedNodes
= NULL
;
2046 fTemplatizedNode
= NULL
;
2051 Demangler::_Cleanup()
2053 while (fAllocatedNodes
!= NULL
) {
2054 Node
* node
= fAllocatedNodes
;
2055 fAllocatedNodes
= node
->NextAllocated();
2062 Demangler::_Demangle(const char* mangledName
, char* buffer
, size_t size
,
2063 DemanglingInfo
& demanglingInfo
)
2066 const char* versionSuffix
;
2068 int error
= _Parse(mangledName
, versionSuffix
, node
);
2069 if (error
!= ERROR_OK
)
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
;
2083 return ERROR_INTERNAL
;
2085 demanglingInfo
.objectType
= node
->ObjectType();
2087 nameBuffer
.Terminate();
2093 Demangler::_GetParameterInfo(const char* mangledName
, uint32 index
,
2094 char* buffer
, size_t size
, ParameterInfo
& info
)
2097 const char* versionSuffix
;
2099 int error
= _Parse(mangledName
, versionSuffix
, node
);
2100 if (error
!= ERROR_OK
)
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
;
2116 return ERROR_INTERNAL
;
2118 nameBuffer
.Terminate();
2121 info
.type
= parameter
->Type();
2128 Demangler::_Parse(const char* mangledName
, const char*& versionSuffix
,
2131 // To support versioned symbols, we ignore the version suffix when
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
))
2146 if (fInput
.CharsRemaining() != 0) {
2147 // bogus at end of input
2148 return ERROR_INVALID
;
2156 Demangler::_ParseEncoding(ObjectNode
*& _node
)
2158 DEBUG_SCOPE("_ParseEncoding");
2160 // <encoding> ::= <function name> <bare-function-type>
2162 // ::= <special-name>
2164 // NOTE: This is not in the specs: Local entities seem to be prefixed
2166 fInput
.SkipPrefix('L');
2168 // parse <special-name>, if it is one
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
))
2179 if (fInput
.CharsRemaining() == 0 || fInput
.HasPrefix('E')) {
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
))
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
))
2199 fTemplatizedNode
= previousTemplatizedNode
;
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
2216 if (!fInput
.SkipPrefix('T')) {
2218 return _SkipExpected("GV")
2220 && NodeCreator
<SpecialNameNode
>(this)("guard variable for ",
2224 // <special-name> ::= TV <type> # virtual table
2225 // ::= TT <type> # VTT structure (construction vtable
2227 // ::= TI <type> # typeinfo structure
2228 // ::= TS <type> # typeinfo name (null-terminated byte
2230 const char* prefix
= NULL
;
2231 switch (fInput
[0]) {
2233 prefix
= "vtable for ";
2236 prefix
= "VTT for ";
2239 prefix
= "typeinfo for ";
2242 prefix
= "typeinfo name for ";
2246 if (prefix
!= NULL
) {
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')) {
2259 number_type offset1
;
2260 number_type offset2
;
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
2272 number_type offset1
;
2273 number_type offset2
;
2275 return _ParseCallOffset(nonVirtual
, offset1
, offset2
)
2276 && _ParseEncoding(name
)
2277 && NodeCreator
<SpecialNameNode
>(this)(
2278 nonVirtual
? "non-virtual thunk to " : "virtual thunk to ",
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
2295 if (fInput
.SkipPrefix('h')) {
2297 return _ParseNumber(offset1
) && _SkipExpected('_');
2302 return _SkipExpected('v')
2303 && _ParseNumber(offset1
)
2304 && _SkipExpected('_')
2305 && _ParseNumber(offset2
)
2306 && _SkipExpected('_');
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]) {
2331 return _ParseNestedName(_node
);
2334 return _ParseLocalName(_node
);
2338 if (!fInput
.HasPrefix("St")) {
2339 if (!_ParseSubstitution(_node
))
2348 if (!NodeCreator
<SimpleNameNode
>(this)("std", prefix
))
2351 // <unqualified-name>
2353 if (!_ParseUnqualifiedName(node
)
2354 || !NodeCreator
<PrefixedNode
>(this)(prefix
, node
, _node
)) {
2361 // <unqualified-name>
2362 if (!_ParseUnqualifiedName(_node
))
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'))
2372 // <unscoped-template-name> is referenceable
2373 _RegisterReferenceableNode(_node
);
2375 return _ParseTemplateArgs(_node
, _node
);
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>
2394 // ::= <substitution>
2396 // <template-prefix> ::= <prefix> <template unqualified-name>
2397 // ::= <template-param>
2398 // ::= <substitution>
2400 if (!_SkipExpected('N'))
2403 // parse CV qualifiers
2405 _ParseCVQualifiers(qualifiers
);
2407 // parse the main part
2408 if (!_ParseNestedNameInternal(_node
))
2411 // create a CV qualifiers wrapper node, if necessary
2412 if (qualifiers
!= 0) {
2413 return NodeCreator
<CVQualifiersNode
>(this)(qualifiers
, _node
,
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
))
2437 // a <prefix> or <template-prefix> and as such referenceable
2438 _RegisterReferenceableNode(initialPrefixNode
);
2441 case 'S': // <substitution>
2442 if (!_ParseSubstitution(initialPrefixNode
))
2448 bool canTerminate
= false;
2451 if (initialPrefixNode
!= NULL
) {
2452 node
= initialPrefixNode
;
2453 initialPrefixNode
= NULL
;
2455 if (!_ParseUnqualifiedName(node
))
2457 canTerminate
= true;
2460 // join prefix and the new node
2461 if (prefixNode
!= NULL
) {
2462 if (!NodeCreator
<PrefixedNode
>(this)(prefixNode
, node
, node
))
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
))
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.
2485 return _SetError(ERROR_INVALID
);
2491 // The fun continues, so this is a <prefix> or <template-prefix>
2492 // and as such referenceable.
2494 _RegisterReferenceableNode(node
);
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')) {
2518 if (fInput
.SkipPrefix('s')) {
2520 if (!NodeCreator
<SimpleNameNode
>(this)("string literal",
2525 // local type or object
2526 if (!_ParseName(entityName
))
2530 // parse discriminator
2531 number_type discriminator
= 0;
2532 if (fInput
.SkipPrefix('_')) {
2533 if (!_ParseNumber(discriminator
))
2535 if (discriminator
< 0)
2536 return _SetError(ERROR_INVALID
);
2540 return NodeCreator
<PrefixedNode
>(this)(functionName
, entityName
, _node
);
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]))) {
2570 return _ParseSourceName(_node
);
2573 if (fInput
[0] == 'C') {
2574 // <ctor-dtor-name> -- constructors
2575 switch (fInput
[1]) {
2579 if (!NodeCreator
<XtructorNode
>(this)(true, fInput
[1] - '1',
2587 return _SetError(ERROR_INVALID
);
2591 if (fInput
[0] == 'D') {
2592 // <ctor-dtor-name> -- destructors
2593 switch (fInput
[1]) {
2597 if (!NodeCreator
<XtructorNode
>(this)(false, fInput
[1] - '0',
2605 return _SetError(ERROR_INVALID
);
2609 // must be an <operator-name>
2610 return _ParseOperatorName(_node
);
2615 Demangler::_ParseSourceName(Node
*& _node
)
2617 DEBUG_SCOPE("_ParseSourceName");
2619 if (fInput
.CharsRemaining() == 0)
2620 return _SetError(ERROR_INVALID
);
2623 if (!_ParseNumber(number
))
2626 if (number
<= 0 || number
> fInput
.CharsRemaining())
2627 return _SetError(ERROR_INVALID
);
2629 return _CreateNodeAndSkip(fInput
.String(), number
, number
, _node
);
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
];
2650 return NodeCreator
<OperatorNode
>(this)(info
, _node
);
2652 // <operator-name> ::= cv <type> # (cast)
2653 if (fInput
.SkipPrefix("cv")) {
2655 if (!_ParseType(typeNode
))
2658 return NodeCreator
<CastOperatorNode
>(this)(typeNode
, _node
);
2661 // <operator-name> ::= v <digit> <source-name> # vendor extended
2663 if (fInput
.SkipPrefix('v')) {
2664 if (fInput
.CharsRemaining() == 0 || !isdigit(fInput
[0]))
2665 return _SetError(ERROR_INVALID
);
2669 return _ParseSourceName(name
)
2670 && NodeCreator
<VendorOperatorNode
>(this)(name
, _node
);
2673 return _SetError(ERROR_INVALID
);
2678 Demangler::_ParseType(Node
*& _node
)
2680 DEBUG_SCOPE("_ParseType");
2682 if (!_ParseTypeInternal(_node
))
2685 _RegisterReferenceableNode(_node
);
2691 Demangler::_ParseTypeInternal(Node
*& _node
)
2693 DEBUG_SCOPE("_ParseTypeInternal");
2695 // <type> ::= <builtin-type>
2696 // ::= <function-type>
2697 // ::= <class-enum-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);
2726 if (fError
!= ERROR_OK
)
2729 if (fInput
.CharsRemaining() == 0)
2730 return _SetError(ERROR_INVALID
);
2732 switch (fInput
[0]) {
2736 FunctionNode
* functionNode
;
2737 if (!_ParseFunctionType(functionNode
))
2739 _node
= functionNode
;
2745 return _ParseArrayType(_node
);
2747 // pointer to member type
2749 return _ParsePointerToMemberType(_node
);
2753 if (!_ParseTemplateParam(_node
))
2762 // parse CV qualifiers
2764 _ParseCVQualifiers(qualifiers
);
2767 if (!_ParseType(_node
))
2770 // create the wrapper node
2771 return NodeCreator
<CVQualifiersNode
>(this)(qualifiers
, _node
,
2775 // pointer, reference, etc.
2777 return _ParseTypeWithModifier(TYPE_QUALIFIER_POINTER
, 1, _node
);
2779 return _ParseTypeWithModifier(TYPE_QUALIFIER_REFERENCE
, 1,
2782 return _ParseTypeWithModifier(
2783 TYPE_QUALIFIER_RVALUE_REFERENCE
, 1, _node
);
2785 return _ParseTypeWithModifier(TYPE_QUALIFIER_COMPLEX
, 1, _node
);
2787 return _ParseTypeWithModifier(TYPE_QUALIFIER_IMAGINARY
, 1,
2790 // pack and decltype
2793 if (fInput
.CharsRemaining() < 2)
2794 return _SetError(ERROR_INVALID
);
2799 return _ParseType(_node
);
2805 if (!_ParseExpression(nameNode
))
2807 if (!fInput
.SkipPrefix('E'))
2808 return ERROR_INVALID
;
2812 // NOTE: Unsupported by the GNU demangler.
2813 return _SetError(ERROR_UNSUPPORTED
);
2815 // vendor extended type qualifier
2820 return _ParseSourceName(name
) && _ParseType(type
)
2821 && NodeCreator
<VendorTypeModifierNode
>(this)(name
, type
,
2826 if (!fInput
.HasPrefix("St")) {
2827 if (!_ParseSubstitution(_node
))
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.
2838 // <class-enum-type> ::= <name>
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'))
2850 // <template-template-param> is referenceable
2851 _RegisterReferenceableNode(_node
);
2853 return _ParseTemplateArgs(_node
, _node
);
2858 Demangler::_ParseCVQualifiers(int& qualifiers
)
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
;
2872 Demangler::_ParseTypeWithModifier(type_modifier modifier
, int toSkip
,
2876 fInput
.Skip(toSkip
);
2879 if (!_ParseType(node
))
2882 return NodeCreator
<TypeModifierNode
>(this)(modifier
, node
, _node
);
2887 Demangler::_TryParseBuiltinType(Node
*& _node
)
2889 DEBUG_SCOPE("_TryParseBuiltinType");
2891 // <builtin-type> ::= v # void
2895 // ::= a # signed char
2896 // ::= h # unsigned char
2898 // ::= t # unsigned short
2900 // ::= j # unsigned int
2902 // ::= m # unsigned long
2903 // ::= x # long long, __int64
2904 // ::= y # unsigned long long, __int64
2906 // ::= o # unsigned __int128
2909 // ::= e # long double, __float80
2910 // ::= g # __float128
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
2917 // ::= Di # char32_t
2918 // ::= Ds # char16_t
2919 // ::= u <source-name> # vendor extended type
2921 if (fInput
.CharsRemaining() == 0)
2924 switch (fInput
[0]) {
2926 return _CreateTypeNodeAndSkip(TYPE_VOID
, 1, _node
);
2928 return _CreateTypeNodeAndSkip(TYPE_WCHAR_T
, 1, _node
);
2930 return _CreateTypeNodeAndSkip(TYPE_BOOL
, 1, _node
);
2932 return _CreateTypeNodeAndSkip(TYPE_CHAR
, 1, _node
);
2934 return _CreateTypeNodeAndSkip(TYPE_SIGNED_CHAR
, 1, _node
);
2936 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_CHAR
, 1, _node
);
2938 return _CreateTypeNodeAndSkip(TYPE_SHORT
, 1, _node
);
2940 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_SHORT
, 1,
2943 return _CreateTypeNodeAndSkip(TYPE_INT
, 1, _node
);
2945 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_INT
, 1, _node
);
2947 return _CreateTypeNodeAndSkip(TYPE_LONG
, 1, _node
);
2949 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_LONG
, 1, _node
);
2951 return _CreateTypeNodeAndSkip(TYPE_LONG_LONG
, 1, _node
);
2953 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_LONG_LONG
, 1, _node
);
2955 return _CreateTypeNodeAndSkip(TYPE_INT128
, 1, _node
);
2957 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_INT128
, 1, _node
);
2959 return _CreateTypeNodeAndSkip(TYPE_FLOAT
, 1, _node
);
2961 return _CreateTypeNodeAndSkip(TYPE_DOUBLE
, 1, _node
);
2963 return _CreateTypeNodeAndSkip(TYPE_LONG_DOUBLE
, 1, _node
);
2965 return _CreateTypeNodeAndSkip(TYPE_FLOAT128
, 1, _node
);
2967 return _CreateTypeNodeAndSkip(TYPE_ELLIPSIS
, 1, _node
);
2970 if (fInput
.CharsRemaining() < 2)
2973 // TODO: Official names for the __dfloat*!
2974 switch (fInput
[1]) {
2976 return _CreateTypeNodeAndSkip(TYPE_DFLOAT64
, 2, _node
);
2978 return _CreateTypeNodeAndSkip(TYPE_DFLOAT128
, 2, _node
);
2980 return _CreateTypeNodeAndSkip(TYPE_DFLOAT32
, 2, _node
);
2982 return _CreateTypeNodeAndSkip(TYPE_DFLOAT16
, 2, _node
);
2984 return _CreateTypeNodeAndSkip(TYPE_CHAR16_T
, 2, _node
);
2986 return _CreateTypeNodeAndSkip(TYPE_CHAR32_T
, 2, _node
);
2995 return _ParseSourceName(nameNode
)
2996 && NodeCreator
<NamedTypeNode
>(this)(nameNode
, _node
);
3006 Demangler::_ParseFunctionType(FunctionNode
*& _node
)
3008 DEBUG_SCOPE("_ParseFunctionType");
3010 // <function-type> ::= F [Y] <bare-function-type> E
3012 if (!_SkipExpected('F'))
3016 bool isExternC
= fInput
.SkipPrefix('Y');
3018 // create function and parse function type
3019 if (!NodeCreator
<FunctionNode
>(this)((Node
*)NULL
, true, isExternC
,
3021 || !_ParseBareFunctionType(_node
)) {
3025 // skip terminating 'E'
3026 return _SkipExpected('E');
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
3046 if (isdigit(fInput
[0])
3047 || (fInput
[0] == 'n' && fInput
.CharsRemaining() >= 2
3048 && isdigit(fInput
[1]))) {
3049 if (!_ParseNumber(dimensionNumber
))
3052 if (!_ParseExpression(dimensionExpression
))
3058 if (!_SkipExpected('_') || !_ParseType(type
))
3061 // create the array node
3062 return dimensionExpression
!= NULL
3063 ? NodeCreator
<ArrayNode
>(this)(type
, dimensionExpression
, _node
)
3064 : NodeCreator
<ArrayNode
>(this)(type
, dimensionNumber
, _node
);
3069 Demangler::_ParsePointerToMemberType(Node
*& _node
)
3071 DEBUG_SCOPE("_ParsePointerToMemberType");
3073 // <pointer-to-member-type> ::= M <class type> <member type>
3076 return _SkipExpected('M')
3077 && _ParseType(classType
)
3078 && _ParseType(memberType
)
3079 && NodeCreator
<PointerToMemberNode
>(this)(classType
, memberType
,
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'))
3094 if (fTemplatizedNode
== NULL
)
3095 return _SetError(ERROR_INVALID
);
3098 number_type index
= 0;
3099 if (!fInput
.HasPrefix('_')) {
3100 if (!_ParseNumber(index
))
3104 return _SetError(ERROR_INVALID
);
3108 if (!_SkipExpected('_'))
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
);
3122 Demangler::_ParseSubstitution(Node
*& _node
)
3124 DEBUG_SCOPE("_ParseSubstitution");
3126 if (!_ParseSubstitutionInternal(_node
))
3129 // substitutions are never referenceable
3130 _node
->SetReferenceable(false);
3137 Demangler::_ParseSubstitutionInternal(Node
*& _node
)
3139 DEBUG_SCOPE("_ParseSubstitutionInternal");
3141 // <substitution> ::= S <seq-id> _
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]) {
3162 return _CreateNodeAndSkip("std", 1, _node
);
3164 return _CreateTypeNodeAndSkip("allocator", "std", NULL
, 1,
3167 return _CreateTypeNodeAndSkip("basic_string", "std", NULL
, 1,
3170 return _CreateTypeNodeAndSkip("basic_string", "std",
3171 "char, std::char_traits<char>, std::allocator<char>", 1,
3174 return _CreateTypeNodeAndSkip("basic_istream", "std",
3175 "char, std::char_traits<char>", 1, _node
);
3177 return _CreateTypeNodeAndSkip("basic_ostream", "std",
3178 "char, std::char_traits<char>", 1, _node
);
3180 return _CreateTypeNodeAndSkip("basic_iostream", "std",
3181 "char, std::char_traits<char>", 1, _node
);
3184 return _CreateSubstitutionNode(0, _node
);
3189 int count
= fInput
.CharsRemaining();
3191 for (; i
< count
&& fInput
[i
] != '_'; i
++) {
3194 seqID
= seqID
* 36 + (c
- '0');
3195 else if (c
>= 'A' && c
<= 'Z')
3196 seqID
= seqID
* 36 + 10 + (c
- 'A');
3198 return _SetError(ERROR_INVALID
);
3202 return _SetError(ERROR_INVALID
);
3204 // skip digits and '_'
3207 return _CreateSubstitutionNode(seqID
+ 1, _node
);
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
);
3224 if (!_ParseType(typeNode
))
3227 node
->AddType(typeNode
);
3228 } while (fInput
.CharsRemaining() > 0 && fInput
[0] != 'E');
3229 // 'E' delimits <function-type>
3236 Demangler::_ParseTemplateArgs(Node
* node
, Node
*& _node
)
3238 DEBUG_SCOPE("_ParseTemplateArgs");
3240 // <template-args> ::= I <template-arg>+ E
3242 if (!_SkipExpected('I'))
3245 // we need at least one <template-arg>
3246 if (fInput
.CharsRemaining() == 0 || fInput
[0] == 'E')
3247 return _SetError(ERROR_INVALID
);
3250 TemplateNode
* templateNode
;
3251 if (!NodeCreator
<TemplateNode
>(this)(node
, templateNode
))
3253 _node
= templateNode
;
3256 while (fInput
.CharsRemaining() > 0 && fInput
[0] != 'E') {
3258 if (!_ParseTemplateArg(arg
))
3260 templateNode
->AddArgument(arg
);
3263 // skip the trailing 'E'
3264 return _SkipExpected('E');
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
3285 return _ParseExpression(_node
) && _SkipExpected('E');
3287 case 'L': // <expr-primary>
3288 return _ParseExpressionPrimary(_node
);
3290 case 'I': // I <template-arg>* E
3295 while (fInput
.CharsRemaining() > 0 && fInput
[0] != 'E') {
3297 if (!_ParseTemplateArg(arg
))
3301 if (!fInput
.SkipPrefix('E'))
3302 return _SetError(ERROR_INVALID
);
3305 // NOTE: Unsupported by the GNU demangler.
3306 return _SetError(ERROR_UNSUPPORTED
);
3310 if (fInput
.SkipPrefix("sp")) {
3313 return _ParseExpression(_node
);
3315 // NOTE: Unsupported by the GNU demangler.
3316 return _SetError(ERROR_UNSUPPORTED
);
3322 return _ParseType(_node
);
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>
3336 // ::= cl <expression>* E # call
3337 // ::= cv <type> expression # conversion with one
3339 // ::= cv <type> _ <expression>* E # conversion with a
3340 // different number of
3342 // ::= st <type> # sizeof (a type)
3343 // ::= at <type> # alignof (a type)
3344 // ::= <template-param>
3345 // ::= <function-param>
3346 // ::= sr <type> <unqualified-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]) {
3363 return _ParseExpressionPrimary(_node
);
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
3378 if (!NodeCreator
<CallNode
>(this)(callNode
))
3381 while (fInput
.CharsRemaining() > 0 && fInput
[0] != 'E') {
3382 Node
* subExpression
;
3383 if (!_ParseExpression(subExpression
))
3385 callNode
->AddSubExpression(subExpression
);
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
3399 if (!_ParseType(type
))
3402 // create a conversion expression node
3403 ConversionExpressionNode
* expression
;
3404 if (!NodeCreator
<ConversionExpressionNode
>(this)(type
, expression
))
3408 if (fInput
.SkipPrefix('_')) {
3409 // multi argument conversion
3410 while (fInput
.CharsRemaining() > 0 && fInput
[0] != 'E') {
3411 Node
* subExpression
;
3412 if (!_ParseExpression(subExpression
))
3414 expression
->AddSubExpression(subExpression
);
3417 return _SkipExpected('E');
3420 // single argument conversion
3421 Node
* subExpression
;
3422 if (!_ParseExpression(subExpression
))
3424 expression
->AddSubExpression(subExpression
);
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
3436 if (!_ParseType(type
) || !_ParseUnqualifiedName(name
)
3437 || !NodeCreator
<DependentNameNode
>(this)(type
, name
, _node
)) {
3441 // If there are template arguments left, add them.
3442 if (!fInput
.HasPrefix('I'))
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
];
3465 // We can only deal with operators with a fixed argument count at this
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
))
3475 // parse the arguments
3478 // the first one might be a type
3479 if ((info
->flags
& OPERATOR_TYPE_PARAM
) != 0) {
3481 if (!_ParseType(type
))
3484 operatorNode
->AddSubExpression(type
);
3488 // the others are expressions
3489 for (; i
< info
->argument_count
; i
++) {
3490 Node
* subExpression
;
3491 if (!_ParseExpression(subExpression
))
3493 operatorNode
->AddSubExpression(subExpression
);
3496 _node
= operatorNode
;
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'))
3513 if (fInput
.SkipPrefix("_Z")) {
3515 if (!_ParseEncoding(node
))
3519 // number or float literal
3521 if (!_ParseType(type
))
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();
3530 while (length
< maxLength
&& fInput
[length
] != 'E')
3534 return _SetError(ERROR_INVALID
);
3536 if (!NodeCreator
<TypedNumberLiteralNode
>(this)(type
,
3537 fInput
.String(), length
, _node
)) {
3541 fInput
.Skip(length
);
3544 return _SkipExpected('E');
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
);
3559 int count
= fInput
.CharsRemaining();
3561 for (; i
< count
&& isdigit(fInput
[i
]); i
++)
3562 number
= number
* 10 + (fInput
[i
] - '0');
3573 Demangler::_CreateNodeAndSkip(const char* name
, size_t length
, int toSkip
,
3577 fInput
.Skip(toSkip
);
3579 return NodeCreator
<SimpleNameNode
>(this)(name
, length
, _node
);
3584 Demangler::_CreateNodeAndSkip(const char* name
, int toSkip
, Node
*& _node
)
3586 return _CreateNodeAndSkip(name
, strlen(name
), toSkip
, _node
);
3591 Demangler::_CreateTypeNodeAndSkip(type_type type
, int toSkip
, Node
*& _node
)
3594 fInput
.Skip(toSkip
);
3596 return NodeCreator
<SimpleTypeNode
>(this)(type
, _node
);
3601 Demangler::_CreateTypeNodeAndSkip(const char* name
, const char* prefix
,
3602 const char* templateArgs
, int toSkip
, Node
*& _node
)
3605 fInput
.Skip(toSkip
);
3607 // create the name node
3608 if (!NodeCreator
<SimpleTypeNode
>(this)(name
, _node
))
3612 if (prefix
!= NULL
) {
3614 if (!NodeCreator
<SimpleTypeNode
>(this)(prefix
, prefixNode
)
3615 || !NodeCreator
<PrefixedNode
>(this)(prefixNode
, _node
, _node
)) {
3620 // wrap the node to add the template args
3621 if (templateArgs
!= NULL
) {
3622 TemplateNode
* templateNode
;
3624 if (!NodeCreator
<TemplateNode
>(this)(_node
, templateNode
)
3625 || !NodeCreator
<SimpleTypeNode
>(this)(templateArgs
, argsNode
)) {
3628 templateNode
->AddArgument(argsNode
);
3629 _node
= templateNode
;
3637 Demangler::_RegisterReferenceableNode(Node
* node
)
3639 // check, if not referenceable or already registered
3640 if (!node
->IsReferenceable() || node
== fLastReferenceableNode
3641 || node
->NextReferenceable() != NULL
) {
3645 if (fFirstReferenceableNode
== NULL
) {
3646 fFirstReferenceableNode
= node
;
3647 fLastReferenceableNode
= node
;
3649 fLastReferenceableNode
->SetNextReferenceable(node
);
3650 fLastReferenceableNode
= node
;
3656 Demangler::_CreateSubstitutionNode(int index
, Node
*& _node
)
3658 Node
* node
= fFirstReferenceableNode
;
3659 while (node
!= NULL
&& index
> 0) {
3660 node
= node
->NextReferenceable();
3665 return _SetError(ERROR_INVALID
);
3667 // create a substitution node
3668 return NodeCreator
<SubstitutionNode
>(this)(node
, _node
);
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
)
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;
3696 case OBJECT_TYPE_METHOD_OBJECT
:
3697 *_isObjectMethod
= true;
3699 case OBJECT_TYPE_UNKNOWN
:
3700 case OBJECT_TYPE_METHOD_UNKNOWN
:
3701 *_isObjectMethod
= strstr(buffer
, "::") != NULL
;
3710 get_next_argument_gcc3(uint32
* _cookie
, const char* mangledName
, char* name
,
3711 size_t nameSize
, int32
* _type
, size_t* _argumentLength
)
3713 Demangler demangler
;
3715 int result
= demangler
.GetParameterInfo(mangledName
, *_cookie
, name
,
3717 if (result
!= ERROR_OK
) {
3719 case ERROR_NOT_MANGLED
:
3721 case ERROR_UNSUPPORTED
:
3725 case ERROR_BUFFER_TOO_SMALL
:
3726 return B_BUFFER_OVERFLOW
;
3727 case ERROR_NO_MEMORY
:
3729 case ERROR_INTERNAL
:
3735 // translate the type
3736 switch (info
.type
.type
) {
3738 *_type
= B_BOOL_TYPE
;
3739 *_argumentLength
= 1;
3743 *_type
= B_CHAR_TYPE
;
3744 *_argumentLength
= 1;
3747 case TYPE_SIGNED_CHAR
:
3748 *_type
= B_INT8_TYPE
;
3749 *_argumentLength
= 1;
3751 case TYPE_UNSIGNED_CHAR
:
3752 *_type
= B_UINT8_TYPE
;
3753 *_argumentLength
= 1;
3757 *_type
= B_INT16_TYPE
;
3758 *_argumentLength
= 2;
3760 case TYPE_UNSIGNED_SHORT
:
3761 *_type
= B_UINT16_TYPE
;
3762 *_argumentLength
= 2;
3766 *_type
= B_INT32_TYPE
;
3767 *_argumentLength
= 4;
3769 case TYPE_UNSIGNED_INT
:
3770 *_type
= B_UINT32_TYPE
;
3771 *_argumentLength
= 4;
3775 *_type
= sizeof(long) == 4 ? B_INT32_TYPE
: B_INT64_TYPE
;
3776 *_argumentLength
= sizeof(long);
3778 case TYPE_UNSIGNED_LONG
:
3779 *_type
= sizeof(long) == 4 ? B_UINT32_TYPE
: B_UINT64_TYPE
;
3780 *_argumentLength
= sizeof(long);
3783 case TYPE_LONG_LONG
:
3784 *_type
= B_INT64_TYPE
;
3785 *_argumentLength
= 8;
3787 case TYPE_UNSIGNED_LONG_LONG
:
3788 *_type
= B_INT64_TYPE
;
3789 *_argumentLength
= 8;
3794 *_argumentLength
= 16;
3796 case TYPE_UNSIGNED_INT128
:
3798 *_argumentLength
= 16;
3802 *_type
= B_FLOAT_TYPE
;
3803 *_argumentLength
= sizeof(float);
3806 *_type
= B_DOUBLE_TYPE
;
3807 *_argumentLength
= sizeof(double);
3810 case TYPE_LONG_DOUBLE
:
3812 *_argumentLength
= sizeof(long double);
3817 *_argumentLength
= 16;
3821 *_argumentLength
= 2;
3823 *_argumentLength
*= 2;
3825 *_argumentLength
*= 2;
3826 case TYPE_DFLOAT128
:
3827 *_argumentLength
*= 2;
3832 *_type
= B_UINT16_TYPE
;
3833 *_argumentLength
= 2;
3837 *_type
= B_UINT32_TYPE
;
3838 *_argumentLength
= 2;
3841 case TYPE_CONST_CHAR_POINTER
:
3842 *_type
= B_STRING_TYPE
;
3843 *_argumentLength
= sizeof(void*);
3847 *_type
= B_POINTER_TYPE
;
3848 *_argumentLength
= sizeof(void*);
3851 case TYPE_REFERENCE
:
3852 *_type
= B_REF_TYPE
;
3853 // TODO: That's actually entry_ref!
3854 *_argumentLength
= sizeof(void*);
3858 // TODO: Type/size might change!
3859 *_type
= B_UINT16_TYPE
;
3860 *_argumentLength
= 2;
3867 // Well, tell our caller *something*.
3869 *_argumentLength
= sizeof(int);
3872 // assume sizeof(int) argument alignment
3873 if (*_argumentLength
< sizeof(int))
3874 *_argumentLength
= sizeof(int);
3881 #ifndef _KERNEL_MODE
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
)