1 /*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2021, Jerome Duval, jerome.duval@gmail.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7 #include <ctype.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include <new>
14
15 #include <TypeConstants.h>
16
17 #ifdef _KERNEL_MODE
18 # include <debug_heap.h>
19 #endif
20
21 #include "demangle.h"
22
23
24 // C++ ABI: https://itanium-cxx-abi.github.io/cxx-abi/abi.html
25
26
27 //#define TRACE_GCC3_DEMANGLER
28 #ifdef TRACE_GCC3_DEMANGLER
29 # define TRACE(x...) PRINT(x)
30 # define DEBUG_SCOPE(name) DebugScope debug(name, fInput.String())
31 #else
32 # define TRACE(x...) ;
33 # define DEBUG_SCOPE(name) do {} while (false)
34 #endif
35
36 #ifdef _KERNEL_MODE
37 # define PRINT(format...) kprintf(format)
38 # define VPRINT(format, args) PRINT("%s", format)
39 // no vkprintf()
40 # define NEW(constructor) new(kdebug_alloc) constructor
41 # define DELETE(object) DebugAlloc::destroy(object)
42 #else
43 # define PRINT(format...) printf(format)
44 # define VPRINT(format, args) vprintf(format, args)
45 # define NEW(constructor) new(std::nothrow) constructor
46 # define DELETE(object) delete object
47 #endif
48
49
50 typedef long number_type;
51
52 enum {
53 ERROR_OK = 0,
54 ERROR_NOT_MANGLED,
55 ERROR_UNSUPPORTED,
56 ERROR_INVALID,
57 ERROR_BUFFER_TOO_SMALL,
58 ERROR_NO_MEMORY,
59 ERROR_INTERNAL,
60 ERROR_INVALID_PARAMETER_INDEX
61 };
62
63 // object classification
64 enum object_type {
65 OBJECT_TYPE_UNKNOWN,
66 OBJECT_TYPE_DATA,
67 OBJECT_TYPE_FUNCTION,
68 OBJECT_TYPE_METHOD_CLASS,
69 OBJECT_TYPE_METHOD_OBJECT,
70 OBJECT_TYPE_METHOD_UNKNOWN
71 };
72
73 // prefix classification
74 enum prefix_type {
75 PREFIX_NONE,
76 PREFIX_NAMESPACE,
77 PREFIX_CLASS,
78 PREFIX_UNKNOWN
79 };
80
81 // type classification
82 enum type_type {
83 TYPE_ELLIPSIS,
84 TYPE_VOID,
85 TYPE_WCHAR_T,
86 TYPE_BOOL,
87 TYPE_CHAR,
88 TYPE_SIGNED_CHAR,
89 TYPE_UNSIGNED_CHAR,
90 TYPE_SHORT,
91 TYPE_UNSIGNED_SHORT,
92 TYPE_INT,
93 TYPE_UNSIGNED_INT,
94 TYPE_LONG,
95 TYPE_UNSIGNED_LONG,
96 TYPE_LONG_LONG,
97 TYPE_UNSIGNED_LONG_LONG,
98 TYPE_INT128,
99 TYPE_UNSIGNED_INT128,
100 TYPE_FLOAT,
101 TYPE_DOUBLE,
102 TYPE_LONG_DOUBLE,
103 TYPE_FLOAT128,
104 TYPE_DFLOAT16,
105 TYPE_DFLOAT32,
106 TYPE_DFLOAT64,
107 TYPE_DFLOAT128,
108 TYPE_CHAR16_T,
109 TYPE_CHAR32_T,
110
111 TYPE_UNKNOWN,
112 TYPE_CONST_CHAR_POINTER,
113 TYPE_POINTER,
114 TYPE_REFERENCE
115 };
116
117 const char* const kTypeNames[] = {
118 "...",
119 "void",
120 "wchar_t",
121 "bool",
122 "char",
123 "signed char",
124 "unsigned char",
125 "short",
126 "unsigned short",
127 "int",
128 "unsigned int",
129 "long",
130 "unsigned long",
131 "long long",
132 "unsigned long long",
133 "__int128",
134 "unsigned __int128",
135 "float",
136 "double",
137 "long double",
138 "__float128",
139 "__dfloat16", // TODO: Official names for the __dfloat*!
140 "__dfloat32",
141 "__dfloat64",
142 "__dfloat64",
143 "char16_t",
144 "char32_t",
145
146 "?",
147 "char const*",
148 "void*",
149 "void&"
150 };
151
152
153 // CV qualifier flags
154 enum {
155 CV_QUALIFIER_RESTRICT = 0x1,
156 CV_QUALIFIER_VOLATILE = 0x2,
157 CV_QUALIFIER_CONST = 0x4
158 };
159
160 enum type_modifier {
161 TYPE_QUALIFIER_POINTER = 0,
162 TYPE_QUALIFIER_REFERENCE,
163 TYPE_QUALIFIER_RVALUE_REFERENCE,
164 TYPE_QUALIFIER_COMPLEX,
165 TYPE_QUALIFIER_IMAGINARY
166 };
167
168 static const char* const kTypeModifierSuffixes[] = {
169 "*",
170 "&",
171 "&&",
172 " complex",
173 " imaginary"
174 };
175
176 struct operator_info {
177 const char* mangled_name;
178 const char* name;
179 int argument_count;
180 int flags;
181 };
182
183 // operator flags
184 enum {
185 OPERATOR_TYPE_PARAM = 0x01,
186 OPERATOR_IS_MEMBER = 0x02
187 };
188
189
190 static const operator_info kOperatorInfos[] = {
191 { "nw", "new", -1, OPERATOR_IS_MEMBER },
192 { "na", "new[]", -1, OPERATOR_IS_MEMBER },
193 { "dl", "delete", -1, OPERATOR_IS_MEMBER },
194 { "da", "delete[]", -1, OPERATOR_IS_MEMBER },
195 { "ps", "+", 1, 0 }, // unary
196 { "ng", "-", 1, 0 }, // unary
197 { "ad", "&", 1, 0 }, // unary
198 { "de", "*", 1, 0 }, // unary
199 { "co", "~", 1, 0 },
200 { "pl", "+", 2, 0 },
201 { "mi", "-", 2, 0 },
202 { "ml", "*", 2, 0 },
203 { "dv", "/", 2, 0 },
204 { "rm", "%", 2, 0 },
205 { "an", "&", 2, 0 },
206 { "or", "|", 2, 0 },
207 { "eo", "^", 2, 0 },
208 { "aS", "=", 2, 0 },
209 { "pL", "+=", 2, 0 },
210 { "mI", "-=", 2, 0 },
211 { "mL", "*=", 2, 0 },
212 { "dV", "/=", 2, 0 },
213 { "rM", "%=", 2, 0 },
214 { "aN", "&=", 2, 0 },
215 { "oR", "|=", 2, 0 },
216 { "eO", "^=", 2, 0 },
217 { "ls", "<<", 2, 0 },
218 { "rs", ">>", 2, 0 },
219 { "lS", "<<=", 2, 0 },
220 { "rS", ">>=", 2, 0 },
221 { "eq", "==", 2, 0 },
222 { "ne", "!=", 2, 0 },
223 { "lt", "<", 2, 0 },
224 { "gt", ">", 2, 0 },
225 { "le", "<=", 2, 0 },
226 { "ge", ">=", 2, 0 },
227 { "nt", "!", 1, 0 },
228 { "aa", "&&", 2, 0 },
229 { "oo", "||", 2, 0 },
230 { "pp", "++", 1, 0 },
231 { "mm", "--", 1, 0 },
232 { "cm", ",", -1, 0 },
233 { "pm", "->*", 2, 0 },
234 { "pt", "->", 2, 0 },
235 { "cl", "()", -1, 0 },
236 { "ix", "[]", -1, 0 },
237 { "qu", "?", 3, 0 },
238 { "st", "sizeof", 1, OPERATOR_TYPE_PARAM }, // type
239 { "sz", "sizeof", 1, 0 }, // expression
240 { "at", "alignof", 1, OPERATOR_TYPE_PARAM }, // type
241 { "az", "alignof", 1, 0 }, // expression
242 {}
243 };
244
245
246 #ifdef TRACE_GCC3_DEMANGLER
247
248 struct DebugScope {
DebugScopeDebugScope249 DebugScope(const char* functionName, const char* remainingString = NULL)
250 :
251 fParent(sGlobalScope),
252 fFunctionName(functionName),
253 fLevel(fParent != NULL ? fParent->fLevel + 1 : 0)
254 {
255 sGlobalScope = this;
256 if (remainingString != NULL) {
257 PRINT("%*s%s(): \"%s\"\n", fLevel * 2, "", fFunctionName,
258 remainingString);
259 } else
260 PRINT("%*s%s()\n", fLevel * 2, "", fFunctionName);
261 }
262
~DebugScopeDebugScope263 ~DebugScope()
264 {
265 sGlobalScope = fParent;
266 PRINT("%*s%s() done\n", fLevel * 2, "", fFunctionName);
267 }
268
PrintDebugScope269 static void Print(const char* format,...)
270 {
271 int level = sGlobalScope != NULL ? sGlobalScope->fLevel : 0;
272
273 va_list args;
274 va_start(args, format);
275 PRINT("%*s", (level + 1) * 2, "");
276 VPRINT(format, args);
277 va_end(args);
278 }
279
280 private:
281 DebugScope* fParent;
282 const char* fFunctionName;
283 int fLevel;
284
285 static DebugScope* sGlobalScope;
286 };
287
288 DebugScope* DebugScope::sGlobalScope = NULL;
289
290 #endif // TRACE_GCC3_DEMANGLER
291
292
293 class Input {
294 public:
Input()295 Input()
296 :
297 fString(NULL),
298 fLength(0)
299 {
300 }
301
SetTo(const char * string,size_t length)302 void SetTo(const char* string, size_t length)
303 {
304 fString = string;
305 fLength = length;
306 }
307
String() const308 const char* String() const
309 {
310 return fString;
311 }
312
CharsRemaining() const313 int CharsRemaining() const
314 {
315 return fLength;
316 }
317
Skip(size_t count)318 void Skip(size_t count)
319 {
320 if (count > fLength) {
321 PRINT("Input::Skip(): fOffset > fLength\n");
322 return;
323 }
324
325 fString += count;
326 fLength -= count;
327 }
328
HasPrefix(char prefix) const329 bool HasPrefix(char prefix) const
330 {
331 return fLength > 0 && fString[0] == prefix;
332 }
333
HasPrefix(const char * prefix) const334 bool HasPrefix(const char* prefix) const
335 {
336 size_t prefixLen = strlen(prefix);
337 return prefixLen <= fLength
338 && strncmp(fString, prefix, strlen(prefix)) == 0;
339 }
340
SkipPrefix(char prefix)341 bool SkipPrefix(char prefix)
342 {
343 if (!HasPrefix(prefix))
344 return false;
345
346 fString++;
347 fLength--;
348 return true;
349 }
350
SkipPrefix(const char * prefix)351 bool SkipPrefix(const char* prefix)
352 {
353 size_t prefixLen = strlen(prefix);
354 if (prefixLen <= fLength && strncmp(fString, prefix, prefixLen) != 0)
355 return false;
356
357 fString += prefixLen;
358 fLength -= prefixLen;
359 return true;
360 }
361
operator [](size_t index) const362 char operator[](size_t index) const
363 {
364 if (index >= fLength) {
365 PRINT("Input::operator[](): fOffset + index >= fLength\n");
366 return '\0';
367 }
368
369 return fString[index];
370 }
371
372 private:
373 const char* fString;
374 size_t fLength;
375 };
376
377
378 class NameBuffer {
379 public:
NameBuffer(char * buffer,size_t size)380 NameBuffer(char* buffer, size_t size)
381 :
382 fBuffer(buffer),
383 fSize(size),
384 fLength(0),
385 fOverflow(false)
386 {
387 }
388
IsEmpty() const389 bool IsEmpty() const
390 {
391 return fLength == 0;
392 }
393
LastChar() const394 char LastChar() const
395 {
396 return fLength > 0 ? fBuffer[fLength - 1] : '\0';
397 }
398
HadOverflow() const399 bool HadOverflow() const
400 {
401 return fOverflow;
402 }
403
Terminate()404 char* Terminate()
405 {
406 fBuffer[fLength] = '\0';
407 return fBuffer;
408 }
409
Append(const char * string,size_t length)410 bool Append(const char* string, size_t length)
411 {
412 if (fLength + length >= fSize) {
413 fOverflow = true;
414 return false;
415 }
416
417 memcpy(fBuffer + fLength, string, length);
418 fLength += length;
419 return true;
420 }
421
Append(const char * string)422 bool Append(const char* string)
423 {
424 return Append(string, strlen(string));
425 }
426
427 private:
428 char* fBuffer;
429 size_t fSize;
430 size_t fLength;
431 bool fOverflow;
432 };
433
434
435 struct TypeInfo {
436 type_type type;
437 int cvQualifiers;
438
TypeInfoTypeInfo439 TypeInfo()
440 :
441 type(TYPE_UNKNOWN),
442 cvQualifiers(0)
443 {
444 }
445
TypeInfoTypeInfo446 TypeInfo(type_type type)
447 :
448 type(type),
449 cvQualifiers(0)
450 {
451 }
452
TypeInfoTypeInfo453 TypeInfo(const TypeInfo& other, int cvQualifiers = 0)
454 :
455 type(other.type),
456 cvQualifiers(other.cvQualifiers | cvQualifiers)
457 {
458 }
459
operator =TypeInfo460 TypeInfo& operator=(const TypeInfo& other)
461 {
462 type = other.type;
463 cvQualifiers = other.cvQualifiers;
464 return *this;
465 }
466 };
467
468
469 struct DemanglingParameters {
470 bool objectNameOnly;
471
DemanglingParametersDemanglingParameters472 DemanglingParameters(bool objectNameOnly)
473 :
474 objectNameOnly(objectNameOnly)
475 {
476 }
477 };
478
479
480 struct DemanglingInfo : DemanglingParameters {
481 object_type objectType;
482
DemanglingInfoDemanglingInfo483 DemanglingInfo(bool objectNameOnly)
484 :
485 DemanglingParameters(objectNameOnly),
486 objectType(OBJECT_TYPE_UNKNOWN)
487 {
488 }
489 };
490
491
492 struct ParameterInfo {
493 TypeInfo type;
494
ParameterInfoParameterInfo495 ParameterInfo()
496 {
497 }
498 };
499
500
501 class Node;
502
503 struct NameDecorationInfo {
504 const Node* firstDecorator;
505 const Node* closestCVDecoratorList;
506
NameDecorationInfoNameDecorationInfo507 NameDecorationInfo(const Node* decorator)
508 :
509 firstDecorator(decorator),
510 closestCVDecoratorList(NULL)
511 {
512 }
513 };
514
515 struct CVQualifierInfo {
516 const Node* firstCVQualifier;
517 const Node* firstNonCVQualifier;
518
CVQualifierInfoCVQualifierInfo519 CVQualifierInfo()
520 :
521 firstCVQualifier(NULL),
522 firstNonCVQualifier(NULL)
523 {
524 }
525 };
526
527
528 class Node {
529 public:
Node()530 Node()
531 :
532 fNextAllocated(NULL),
533 fParent(NULL),
534 fNext(NULL),
535 fNextReferenceable(NULL),
536 fReferenceable(true)
537 {
538 }
539
~Node()540 virtual ~Node()
541 {
542 }
543
NextAllocated() const544 Node* NextAllocated() const { return fNextAllocated; }
SetNextAllocated(Node * node)545 void SetNextAllocated(Node* node) { fNextAllocated = node; }
546
Parent() const547 Node* Parent() const { return fParent; }
SetParent(Node * node)548 virtual void SetParent(Node* node) { fParent = node; }
549
Next() const550 Node* Next() const { return fNext; }
SetNext(Node * node)551 void SetNext(Node* node) { fNext = node; }
552
IsReferenceable() const553 bool IsReferenceable() const { return fReferenceable; }
SetReferenceable(bool flag)554 void SetReferenceable(bool flag) { fReferenceable = flag; }
555
NextReferenceable() const556 Node* NextReferenceable() const { return fNextReferenceable; }
SetNextReferenceable(Node * node)557 void SetNextReferenceable(Node* node) { fNextReferenceable = node; }
558
559 virtual bool GetName(NameBuffer& buffer) const = 0;
560
GetDecoratedName(NameBuffer & buffer,NameDecorationInfo & decorationInfo) const561 virtual bool GetDecoratedName(NameBuffer& buffer,
562 NameDecorationInfo& decorationInfo) const
563 {
564 if (!GetName(buffer))
565 return false;
566
567 return decorationInfo.firstDecorator == NULL
568 || decorationInfo.firstDecorator->AddDecoration(buffer, NULL);
569 }
570
AddDecoration(NameBuffer & buffer,const Node * stopDecorator) const571 virtual bool AddDecoration(NameBuffer& buffer,
572 const Node* stopDecorator) const
573 {
574 return true;
575 }
576
GetCVQualifierInfo(CVQualifierInfo & info) const577 virtual void GetCVQualifierInfo(CVQualifierInfo& info) const
578 {
579 info.firstNonCVQualifier = this;
580 }
581
GetUnqualifiedNode(Node * beforeNode)582 virtual Node* GetUnqualifiedNode(Node* beforeNode)
583 {
584 return this;
585 }
586
IsTemplatized() const587 virtual bool IsTemplatized() const
588 {
589 return false;
590 }
591
TemplateParameterAt(int index) const592 virtual Node* TemplateParameterAt(int index) const
593 {
594 return NULL;
595 }
596
IsNoReturnValueFunction() const597 virtual bool IsNoReturnValueFunction() const
598 {
599 return false;
600 }
601
IsTypeName(const char * name,size_t length) const602 virtual bool IsTypeName(const char* name, size_t length) const
603 {
604 return false;
605 }
606
ObjectType() const607 virtual object_type ObjectType() const
608 {
609 return OBJECT_TYPE_UNKNOWN;
610 }
611
PrefixType() const612 virtual prefix_type PrefixType() const
613 {
614 return PREFIX_NONE;
615 }
616
Type() const617 virtual TypeInfo Type() const
618 {
619 return TypeInfo();
620 }
621
622 private:
623 Node* fNextAllocated;
624 Node* fParent;
625 Node* fNext;
626 Node* fNextReferenceable;
627 bool fReferenceable;
628 };
629
630
631 class NamedTypeNode : public Node {
632 public:
NamedTypeNode(Node * name)633 NamedTypeNode(Node* name)
634 :
635 fName(name)
636 {
637 if (fName != NULL)
638 fName->SetParent(this);
639 }
640
GetName(NameBuffer & buffer) const641 virtual bool GetName(NameBuffer& buffer) const
642 {
643 return fName == NULL || fName->GetName(buffer);
644 }
645
IsNoReturnValueFunction() const646 virtual bool IsNoReturnValueFunction() const
647 {
648 return fName != NULL && fName->IsNoReturnValueFunction();
649 }
650
Type() const651 virtual TypeInfo Type() const
652 {
653 return fName != NULL ? fName->Type() : TypeInfo();
654 }
655
656 protected:
657 Node* fName;
658 };
659
660
661 class SubstitutionNode : public Node {
662 public:
SubstitutionNode(Node * node)663 SubstitutionNode(Node* node)
664 :
665 fNode(node)
666 {
667 }
668
GetName(NameBuffer & buffer) const669 virtual bool GetName(NameBuffer& buffer) const
670 {
671 return fNode->GetName(buffer);
672 }
673
GetDecoratedName(NameBuffer & buffer,NameDecorationInfo & decorationInfo) const674 virtual bool GetDecoratedName(NameBuffer& buffer,
675 NameDecorationInfo& decorationInfo) const
676 {
677 return fNode->GetDecoratedName(buffer, decorationInfo);
678 }
679
AddDecoration(NameBuffer & buffer,const Node * stopDecorator) const680 virtual bool AddDecoration(NameBuffer& buffer,
681 const Node* stopDecorator) const
682 {
683 return fNode->AddDecoration(buffer, stopDecorator);
684 }
685
GetCVQualifierInfo(CVQualifierInfo & info) const686 virtual void GetCVQualifierInfo(CVQualifierInfo& info) const
687 {
688 fNode->GetCVQualifierInfo(info);
689 }
690
IsTemplatized() const691 virtual bool IsTemplatized() const
692 {
693 return fNode->IsTemplatized();
694 }
695
TemplateParameterAt(int index) const696 virtual Node* TemplateParameterAt(int index) const
697 {
698 return fNode->TemplateParameterAt(index);
699 }
700
IsNoReturnValueFunction() const701 virtual bool IsNoReturnValueFunction() const
702 {
703 return fNode->IsNoReturnValueFunction();
704 }
705
IsTypeName(const char * name,size_t length) const706 virtual bool IsTypeName(const char* name, size_t length) const
707 {
708 return fNode->IsTypeName(name, length);
709 }
710
ObjectType() const711 virtual object_type ObjectType() const
712 {
713 return fNode->ObjectType();
714 }
715
PrefixType() const716 virtual prefix_type PrefixType() const
717 {
718 return fNode->PrefixType();
719 }
720
Type() const721 virtual TypeInfo Type() const
722 {
723 return fNode->Type();
724 }
725
726 private:
727 Node* fNode;
728 };
729
730
731 class ArrayNode : public NamedTypeNode {
732 public:
ArrayNode(Node * type,int dimension)733 ArrayNode(Node* type, int dimension)
734 :
735 NamedTypeNode(type),
736 fDimensionExpression(NULL),
737 fDimensionNumber(dimension)
738 {
739 }
740
ArrayNode(Node * type,Node * dimension)741 ArrayNode(Node* type, Node* dimension)
742 :
743 NamedTypeNode(type),
744 fDimensionExpression(dimension),
745 fDimensionNumber(0)
746 {
747 fDimensionExpression->SetParent(this);
748 }
749
GetName(NameBuffer & buffer) const750 virtual bool GetName(NameBuffer& buffer) const
751 {
752 if (!fName->GetName(buffer))
753 return false;
754
755 buffer.Append("[", 1);
756
757 if (fDimensionExpression != NULL) {
758 if (!fDimensionExpression->GetName(buffer))
759 return false;
760 } else {
761 char stringBuffer[16];
762 snprintf(stringBuffer, sizeof(stringBuffer), "%d",
763 fDimensionNumber);
764 buffer.Append(stringBuffer);
765 }
766
767 return buffer.Append("]", 1);
768 }
769
ObjectType() const770 virtual object_type ObjectType() const
771 {
772 return OBJECT_TYPE_DATA;
773 }
774
Type() const775 virtual TypeInfo Type() const
776 {
777 // TODO: Check!
778 return TypeInfo(TYPE_POINTER);
779 }
780
781
782 private:
783 Node* fDimensionExpression;
784 int fDimensionNumber;
785 };
786
787
788 class ObjectNode : public NamedTypeNode {
789 public:
ObjectNode(Node * name)790 ObjectNode(Node* name)
791 :
792 NamedTypeNode(name)
793 {
794 }
795
GetObjectName(NameBuffer & buffer,const DemanglingParameters & parameters)796 virtual bool GetObjectName(NameBuffer& buffer,
797 const DemanglingParameters& parameters)
798 {
799 if (parameters.objectNameOnly)
800 return fName != NULL ? fName->GetName(buffer) : true;
801
802 return GetName(buffer);
803 }
804
ObjectType() const805 virtual object_type ObjectType() const
806 {
807 return OBJECT_TYPE_DATA;
808 }
809
ParameterAt(uint32 index) const810 virtual Node* ParameterAt(uint32 index) const
811 {
812 return NULL;
813 }
814 };
815
816
817 class SimpleNameNode : public Node {
818 public:
SimpleNameNode(const char * name)819 SimpleNameNode(const char* name)
820 :
821 fName(name),
822 fLength(strlen(name))
823 {
824 }
825
SimpleNameNode(const char * name,size_t length)826 SimpleNameNode(const char* name, size_t length)
827 :
828 fName(name),
829 fLength(length)
830 {
831 }
832
GetName(NameBuffer & buffer) const833 virtual bool GetName(NameBuffer& buffer) const
834 {
835 return buffer.Append(fName, fLength);
836 }
837
838 protected:
839 const char* fName;
840 size_t fLength;
841 };
842
843
844 class SimpleTypeNode : public SimpleNameNode {
845 public:
SimpleTypeNode(const char * name)846 SimpleTypeNode(const char* name)
847 :
848 SimpleNameNode(name),
849 fType(TYPE_UNKNOWN)
850 {
851 }
852
SimpleTypeNode(type_type type)853 SimpleTypeNode(type_type type)
854 :
855 SimpleNameNode(kTypeNames[type]),
856 fType(type)
857 {
858 }
859
IsTypeName(const char * name,size_t length) const860 virtual bool IsTypeName(const char* name, size_t length) const
861 {
862 return fLength == length && strcmp(fName, name) == 0;
863 }
864
ObjectType() const865 virtual object_type ObjectType() const
866 {
867 return OBJECT_TYPE_DATA;
868 }
869
Type() const870 virtual TypeInfo Type() const
871 {
872 return TypeInfo(fType);
873 }
874
875 private:
876 type_type fType;
877 };
878
879
880 class TypedNumberLiteralNode : public Node {
881 public:
TypedNumberLiteralNode(Node * type,const char * number,size_t length)882 TypedNumberLiteralNode(Node* type, const char* number, size_t length)
883 :
884 fType(type),
885 fNumber(number),
886 fLength(length)
887 {
888 fType->SetParent(this);
889 }
890
GetName(NameBuffer & buffer) const891 virtual bool GetName(NameBuffer& buffer) const
892 {
893 // If the type is bool and the number is 0 or 1, we use "false" or
894 // "true" respectively.
895 if (fType->IsTypeName("bool", 4) && fLength == 1
896 && (fNumber[0] == '0' || fNumber[0] == '1')) {
897 return buffer.Append(fNumber[0] == '0' ? "false" : "true");
898 }
899
900 // Add the type in parentheses. The GNU demangler omits "int", so do we.
901 if (!fType->IsTypeName("int", 3)) {
902 buffer.Append("(");
903 if (!fType->GetName(buffer))
904 return false;
905 buffer.Append(")");
906 }
907
908 // add the number -- replace a leading 'n' by '-', if necessary
909 if (fLength > 0 && fNumber[0] == 'n') {
910 buffer.Append("-");
911 return buffer.Append(fNumber + 1, fLength - 1);
912 }
913
914 return buffer.Append(fNumber, fLength);
915 }
916
ObjectType() const917 virtual object_type ObjectType() const
918 {
919 return OBJECT_TYPE_DATA;
920 }
921
922 private:
923 Node* fType;
924 const char* fNumber;
925 size_t fLength;
926 };
927
928
929 class XtructorNode : public Node {
930 public:
XtructorNode(bool constructor,char type)931 XtructorNode(bool constructor, char type)
932 :
933 fConstructor(constructor),
934 fType(type)
935 {
936 }
937
SetParent(Node * node)938 virtual void SetParent(Node* node)
939 {
940 fUnqualifiedNode = node->GetUnqualifiedNode(this);
941 Node::SetParent(node);
942 }
943
GetName(NameBuffer & buffer) const944 virtual bool GetName(NameBuffer& buffer) const
945 {
946 if (fUnqualifiedNode == NULL)
947 return false;
948
949 if (!fConstructor)
950 buffer.Append("~");
951
952 return fUnqualifiedNode->GetName(buffer);
953 }
954
IsNoReturnValueFunction() const955 virtual bool IsNoReturnValueFunction() const
956 {
957 return true;
958 }
959
ObjectType() const960 virtual object_type ObjectType() const
961 {
962 return OBJECT_TYPE_METHOD_CLASS;
963 }
964
965 private:
966 bool fConstructor;
967 char fType;
968 Node* fUnqualifiedNode;
969 };
970
971
972 class SpecialNameNode : public Node {
973 public:
SpecialNameNode(const char * name,Node * child)974 SpecialNameNode(const char* name, Node* child)
975 :
976 fName(name),
977 fChild(child)
978 {
979 fChild->SetParent(this);
980 }
981
GetName(NameBuffer & buffer) const982 virtual bool GetName(NameBuffer& buffer) const
983 {
984 return buffer.Append(fName) && fChild->GetName(buffer);
985 }
986
987 protected:
988 const char* fName;
989 Node* fChild;
990 };
991
992
993 class DecoratingNode : public Node {
994 public:
DecoratingNode(Node * child)995 DecoratingNode(Node* child)
996 :
997 fChildNode(child)
998 {
999 fChildNode->SetParent(this);
1000 }
1001
GetName(NameBuffer & buffer) const1002 virtual bool GetName(NameBuffer& buffer) const
1003 {
1004 NameDecorationInfo decorationInfo(this);
1005 return fChildNode->GetDecoratedName(buffer, decorationInfo);
1006 }
1007
GetDecoratedName(NameBuffer & buffer,NameDecorationInfo & decorationInfo) const1008 virtual bool GetDecoratedName(NameBuffer& buffer,
1009 NameDecorationInfo& decorationInfo) const
1010 {
1011 decorationInfo.closestCVDecoratorList = NULL;
1012 return fChildNode->GetDecoratedName(buffer, decorationInfo);
1013 }
1014
1015 protected:
1016 Node* fChildNode;
1017 };
1018
1019
1020 class CVQualifiersNode : public DecoratingNode {
1021 public:
CVQualifiersNode(int qualifiers,Node * child)1022 CVQualifiersNode(int qualifiers, Node* child)
1023 :
1024 DecoratingNode(child),
1025 fCVQualifiers(qualifiers)
1026 {
1027 }
1028
GetDecoratedName(NameBuffer & buffer,NameDecorationInfo & decorationInfo) const1029 virtual bool GetDecoratedName(NameBuffer& buffer,
1030 NameDecorationInfo& decorationInfo) const
1031 {
1032 if (decorationInfo.closestCVDecoratorList == NULL)
1033 decorationInfo.closestCVDecoratorList = this;
1034 return fChildNode->GetDecoratedName(buffer, decorationInfo);
1035 }
1036
AddDecoration(NameBuffer & buffer,const Node * stopDecorator) const1037 virtual bool AddDecoration(NameBuffer& buffer,
1038 const Node* stopDecorator) const
1039 {
1040 if (this == stopDecorator)
1041 return true;
1042
1043 if (!fChildNode->AddDecoration(buffer, stopDecorator))
1044 return false;
1045
1046 if ((fCVQualifiers & CV_QUALIFIER_RESTRICT) != 0)
1047 buffer.Append(" restrict");
1048 if ((fCVQualifiers & CV_QUALIFIER_VOLATILE) != 0)
1049 buffer.Append(" volatile");
1050 if ((fCVQualifiers & CV_QUALIFIER_CONST) != 0)
1051 buffer.Append(" const");
1052
1053 return true;
1054 }
1055
GetCVQualifierInfo(CVQualifierInfo & info) const1056 virtual void GetCVQualifierInfo(CVQualifierInfo& info) const
1057 {
1058 if (info.firstCVQualifier == NULL)
1059 info.firstCVQualifier = this;
1060 fChildNode->GetCVQualifierInfo(info);
1061 }
1062
IsTemplatized() const1063 virtual bool IsTemplatized() const
1064 {
1065 return fChildNode->IsTemplatized();
1066 }
1067
TemplateParameterAt(int index) const1068 virtual Node* TemplateParameterAt(int index) const
1069 {
1070 return fChildNode->TemplateParameterAt(index);
1071 }
1072
IsNoReturnValueFunction() const1073 virtual bool IsNoReturnValueFunction() const
1074 {
1075 return fChildNode->IsNoReturnValueFunction();
1076 }
1077
ObjectType() const1078 virtual object_type ObjectType() const
1079 {
1080 return fChildNode->ObjectType();
1081 }
1082
PrefixType() const1083 virtual prefix_type PrefixType() const
1084 {
1085 return fChildNode->PrefixType();
1086 }
1087
Type() const1088 virtual TypeInfo Type() const
1089 {
1090 return TypeInfo(fChildNode->Type(), fCVQualifiers);
1091 }
1092
1093 private:
1094 int fCVQualifiers;
1095 };
1096
1097
1098 class TypeModifierNode : public DecoratingNode {
1099 public:
TypeModifierNode(type_modifier modifier,Node * child)1100 TypeModifierNode(type_modifier modifier, Node* child)
1101 :
1102 DecoratingNode(child),
1103 fModifier(modifier)
1104 {
1105 }
1106
AddDecoration(NameBuffer & buffer,const Node * stopDecorator) const1107 virtual bool AddDecoration(NameBuffer& buffer,
1108 const Node* stopDecorator) const
1109 {
1110 if (this == stopDecorator)
1111 return true;
1112
1113 return fChildNode->AddDecoration(buffer, stopDecorator)
1114 && buffer.Append(kTypeModifierSuffixes[fModifier]);
1115 }
1116
ObjectType() const1117 virtual object_type ObjectType() const
1118 {
1119 return OBJECT_TYPE_DATA;
1120 }
1121
Type() const1122 virtual TypeInfo Type() const
1123 {
1124 TypeInfo type = fChildNode->Type();
1125 if (type.type == TYPE_CHAR
1126 && (type.cvQualifiers & CV_QUALIFIER_CONST) != 0) {
1127 return TypeInfo(TYPE_CONST_CHAR_POINTER);
1128 }
1129
1130 switch (fModifier) {
1131 case TYPE_QUALIFIER_POINTER:
1132 return TypeInfo(TYPE_POINTER);
1133 case TYPE_QUALIFIER_REFERENCE:
1134 return TypeInfo(TYPE_REFERENCE);
1135 default:
1136 return TypeInfo();
1137 }
1138 }
1139
1140 private:
1141 type_modifier fModifier;
1142 };
1143
1144
1145 class VendorTypeModifierNode : public DecoratingNode {
1146 public:
VendorTypeModifierNode(Node * name,Node * child)1147 VendorTypeModifierNode(Node* name, Node* child)
1148 :
1149 DecoratingNode(child),
1150 fName(name)
1151 {
1152 fName->SetParent(this);
1153 }
1154
AddDecoration(NameBuffer & buffer,const Node * stopDecorator) const1155 virtual bool AddDecoration(NameBuffer& buffer,
1156 const Node* stopDecorator) const
1157 {
1158 if (this == stopDecorator)
1159 return true;
1160
1161 return fChildNode->AddDecoration(buffer, stopDecorator)
1162 && buffer.Append(" ")
1163 && fName->GetName(buffer);
1164 }
1165
ObjectType() const1166 virtual object_type ObjectType() const
1167 {
1168 return OBJECT_TYPE_DATA;
1169 }
1170
1171 private:
1172 Node* fName;
1173 };
1174
1175
1176 class OperatorNode : public Node {
1177 public:
OperatorNode(const operator_info * info)1178 OperatorNode(const operator_info* info)
1179 :
1180 fInfo(info)
1181 {
1182 SetReferenceable(false);
1183 }
1184
GetName(NameBuffer & buffer) const1185 virtual bool GetName(NameBuffer& buffer) const
1186 {
1187 return buffer.Append(
1188 isalpha(fInfo->name[0]) ? "operator " : "operator")
1189 && buffer.Append(fInfo->name);
1190 }
1191
ObjectType() const1192 virtual object_type ObjectType() const
1193 {
1194 return (fInfo->flags & OPERATOR_IS_MEMBER) != 0
1195 ? OBJECT_TYPE_METHOD_CLASS : OBJECT_TYPE_UNKNOWN;
1196 }
1197
1198 private:
1199 const operator_info* fInfo;
1200 };
1201
1202
1203 class VendorOperatorNode : public Node {
1204 public:
VendorOperatorNode(Node * name)1205 VendorOperatorNode(Node* name)
1206 :
1207 fName(name)
1208 {
1209 fName->SetParent(this);
1210 SetReferenceable(false);
1211 }
1212
GetName(NameBuffer & buffer) const1213 virtual bool GetName(NameBuffer& buffer) const
1214 {
1215 return buffer.Append("operator ")
1216 && fName->GetName(buffer);
1217 }
1218
1219 private:
1220 Node* fName;
1221 };
1222
1223
1224 class CastOperatorNode : public Node {
1225 public:
CastOperatorNode(Node * child)1226 CastOperatorNode(Node* child)
1227 :
1228 fChildNode(child)
1229 {
1230 fChildNode->SetParent(this);
1231 }
1232
GetName(NameBuffer & buffer) const1233 virtual bool GetName(NameBuffer& buffer) const
1234 {
1235 return buffer.Append("operator ") && fChildNode->GetName(buffer);
1236 }
1237
IsNoReturnValueFunction() const1238 virtual bool IsNoReturnValueFunction() const
1239 {
1240 return true;
1241 }
1242
ObjectType() const1243 virtual object_type ObjectType() const
1244 {
1245 return OBJECT_TYPE_METHOD_OBJECT;
1246 }
1247
1248 private:
1249 Node* fChildNode;
1250 };
1251
1252
1253 class PrefixedNode : public Node {
1254 public:
PrefixedNode(Node * prefix,Node * node)1255 PrefixedNode(Node* prefix, Node* node)
1256 :
1257 fPrefixNode(prefix),
1258 fNode(node)
1259 {
1260 fPrefixNode->SetParent(this);
1261 fNode->SetParent(this);
1262 }
1263
GetName(NameBuffer & buffer) const1264 virtual bool GetName(NameBuffer& buffer) const
1265 {
1266 if (!fPrefixNode->GetName(buffer))
1267 return false;
1268
1269 buffer.Append("::");
1270 return fNode->GetName(buffer);
1271 }
1272
GetUnqualifiedNode(Node * beforeNode)1273 virtual Node* GetUnqualifiedNode(Node* beforeNode)
1274 {
1275 return beforeNode == fNode
1276 ? fPrefixNode->GetUnqualifiedNode(beforeNode)
1277 : fNode->GetUnqualifiedNode(beforeNode);
1278 }
1279
IsNoReturnValueFunction() const1280 virtual bool IsNoReturnValueFunction() const
1281 {
1282 return fNode->IsNoReturnValueFunction();
1283 }
1284
ObjectType() const1285 virtual object_type ObjectType() const
1286 {
1287 return fNode->ObjectType();
1288 }
1289
PrefixType() const1290 virtual prefix_type PrefixType() const
1291 {
1292 return PREFIX_UNKNOWN;
1293 }
1294
1295 private:
1296 Node* fPrefixNode;
1297 Node* fNode;
1298 };
1299
1300
1301 class ClonedNode : public ObjectNode {
1302 public:
ClonedNode(Node * clone,ObjectNode * node)1303 ClonedNode(Node* clone, ObjectNode* node)
1304 :
1305 ObjectNode(NULL),
1306 fNode(node),
1307 fCloneNode(clone)
1308 {
1309 fNode->SetParent(this);
1310 fCloneNode->SetParent(this);
1311 }
1312
GetName(NameBuffer & buffer) const1313 virtual bool GetName(NameBuffer& buffer) const
1314 {
1315 if (!fNode->GetName(buffer))
1316 return false;
1317 buffer.Append(" ", 1);
1318 return _AppendCloneName(buffer);
1319 }
1320
GetObjectName(NameBuffer & buffer,const DemanglingParameters & parameters)1321 virtual bool GetObjectName(NameBuffer& buffer,
1322 const DemanglingParameters& parameters)
1323 {
1324 if (parameters.objectNameOnly) {
1325 if (!fNode->GetObjectName(buffer, parameters))
1326 return false;
1327 if (!_AppendCloneName(buffer))
1328 return false;
1329 return buffer.Append(" ", 1);
1330 }
1331
1332 return ObjectNode::GetObjectName(buffer, parameters);
1333 }
1334
GetUnqualifiedNode(Node * beforeNode)1335 virtual Node* GetUnqualifiedNode(Node* beforeNode)
1336 {
1337 return beforeNode == fCloneNode
1338 ? fNode->GetUnqualifiedNode(beforeNode)
1339 : fCloneNode->GetUnqualifiedNode(beforeNode);
1340 }
1341
IsNoReturnValueFunction() const1342 virtual bool IsNoReturnValueFunction() const
1343 {
1344 return fNode->IsNoReturnValueFunction();
1345 }
1346
ObjectType() const1347 virtual object_type ObjectType() const
1348 {
1349 return fNode->ObjectType();
1350 }
1351
PrefixType() const1352 virtual prefix_type PrefixType() const
1353 {
1354 return PREFIX_UNKNOWN;
1355 }
1356
ParameterAt(uint32 index) const1357 virtual Node* ParameterAt(uint32 index) const
1358 {
1359 return fNode->ParameterAt(index);
1360 }
1361
1362 private:
_AppendCloneName(NameBuffer & buffer) const1363 bool _AppendCloneName(NameBuffer& buffer) const
1364 {
1365 buffer.Append("[clone ");
1366 if (!fCloneNode->GetName(buffer))
1367 return false;
1368 buffer.Append("]");
1369 return true;
1370 }
1371
1372 private:
1373 ObjectNode* fNode;
1374 Node* fCloneNode;
1375 };
1376
1377
1378 typedef PrefixedNode DependentNameNode;
1379
1380
1381 class TemplateNode : public Node {
1382 public:
TemplateNode(Node * base)1383 TemplateNode(Node* base)
1384 :
1385 fBase(base),
1386 fFirstArgument(NULL),
1387 fLastArgument(NULL)
1388 {
1389 fBase->SetParent(this);
1390 }
1391
AddArgument(Node * child)1392 void AddArgument(Node* child)
1393 {
1394 child->SetParent(this);
1395
1396 if (fLastArgument != NULL) {
1397 fLastArgument->SetNext(child);
1398 fLastArgument = child;
1399 } else {
1400 fFirstArgument = child;
1401 fLastArgument = child;
1402 }
1403 }
1404
GetName(NameBuffer & buffer) const1405 virtual bool GetName(NameBuffer& buffer) const
1406 {
1407 if (!fBase->GetName(buffer))
1408 return false;
1409
1410 buffer.Append("<");
1411
1412 Node* child = fFirstArgument;
1413 while (child != NULL) {
1414 if (child != fFirstArgument)
1415 buffer.Append(", ");
1416
1417 if (!child->GetName(buffer))
1418 return false;
1419
1420 child = child->Next();
1421 }
1422
1423 // add a space between consecutive '>'
1424 if (buffer.LastChar() == '>')
1425 buffer.Append(" ");
1426
1427 return buffer.Append(">");
1428 }
1429
GetUnqualifiedNode(Node * beforeNode)1430 virtual Node* GetUnqualifiedNode(Node* beforeNode)
1431 {
1432 return fBase != beforeNode
1433 ? fBase->GetUnqualifiedNode(beforeNode) : this;
1434 }
1435
IsTemplatized() const1436 virtual bool IsTemplatized() const
1437 {
1438 return true;
1439 }
1440
TemplateParameterAt(int index) const1441 virtual Node* TemplateParameterAt(int index) const
1442 {
1443 Node* child = fFirstArgument;
1444 while (child != NULL) {
1445 if (index == 0)
1446 return child;
1447 index--;
1448 child = child->Next();
1449 }
1450
1451 return NULL;
1452 }
1453
IsNoReturnValueFunction() const1454 virtual bool IsNoReturnValueFunction() const
1455 {
1456 return fBase->IsNoReturnValueFunction();
1457 }
1458
ObjectType() const1459 virtual object_type ObjectType() const
1460 {
1461 return fBase->ObjectType();
1462 }
1463
PrefixType() const1464 virtual prefix_type PrefixType() const
1465 {
1466 return fBase->PrefixType();
1467 }
1468
1469 protected:
1470 Node* fBase;
1471 Node* fFirstArgument;
1472 Node* fLastArgument;
1473 };
1474
1475
1476 class MultiSubExpressionsNode : public Node {
1477 public:
MultiSubExpressionsNode()1478 MultiSubExpressionsNode()
1479 :
1480 fFirstSubExpression(NULL),
1481 fLastSubExpression(NULL)
1482 {
1483 }
1484
AddSubExpression(Node * child)1485 void AddSubExpression(Node* child)
1486 {
1487 child->SetParent(this);
1488
1489 if (fLastSubExpression != NULL) {
1490 fLastSubExpression->SetNext(child);
1491 fLastSubExpression = child;
1492 } else {
1493 fFirstSubExpression = child;
1494 fLastSubExpression = child;
1495 }
1496 }
1497
1498 protected:
1499 Node* fFirstSubExpression;
1500 Node* fLastSubExpression;
1501 };
1502
1503
1504 class CallNode : public MultiSubExpressionsNode {
1505 public:
CallNode()1506 CallNode()
1507 {
1508 }
1509
GetName(NameBuffer & buffer) const1510 virtual bool GetName(NameBuffer& buffer) const
1511 {
1512 // TODO: Use the real syntax!
1513 buffer.Append("call(");
1514
1515 Node* child = fFirstSubExpression;
1516 while (child != NULL) {
1517 if (child != fFirstSubExpression)
1518 buffer.Append(", ");
1519
1520 if (!child->GetName(buffer))
1521 return false;
1522
1523 child = child->Next();
1524 }
1525
1526 buffer.Append(")");
1527
1528 return true;
1529 }
1530 };
1531
1532
1533 class OperatorExpressionNode : public MultiSubExpressionsNode {
1534 public:
OperatorExpressionNode(const operator_info * info)1535 OperatorExpressionNode(const operator_info* info)
1536 :
1537 fInfo(info)
1538 {
1539 }
1540
GetName(NameBuffer & buffer) const1541 virtual bool GetName(NameBuffer& buffer) const
1542 {
1543 bool isIdentifier = isalpha(fInfo->name[0]) || fInfo->name[0] == '_';
1544
1545 if (fInfo->argument_count == 1 || isIdentifier
1546 || fInfo->argument_count > 3
1547 || (fInfo->argument_count == 3 && strcmp(fInfo->name, "?") != 0)) {
1548 // prefix operator
1549 buffer.Append(fInfo->name);
1550
1551 if (isIdentifier)
1552 buffer.Append("(");
1553
1554 Node* child = fFirstSubExpression;
1555 while (child != NULL) {
1556 if (child != fFirstSubExpression)
1557 buffer.Append(", ");
1558
1559 if (!child->GetName(buffer))
1560 return false;
1561
1562 child = child->Next();
1563 }
1564
1565 if (isIdentifier)
1566 buffer.Append(")");
1567
1568 return true;
1569 }
1570
1571 Node* arg1 = fFirstSubExpression;
1572 Node* arg2 = arg1->Next();
1573
1574 buffer.Append("(");
1575
1576 if (fInfo->argument_count == 2) {
1577 // binary infix operator
1578 if (!arg1->GetName(buffer))
1579 return false;
1580
1581 buffer.Append(" ");
1582 buffer.Append(fInfo->name);
1583 buffer.Append(" ");
1584
1585 if (!arg2->GetName(buffer))
1586 return false;
1587
1588 return buffer.Append(")");
1589 }
1590
1591 Node* arg3 = arg2->Next();
1592
1593 if (fInfo->argument_count == 2) {
1594 // trinary operator "... ? ... : ..."
1595 if (!arg1->GetName(buffer))
1596 return false;
1597
1598 buffer.Append(" ? ");
1599
1600 if (!arg2->GetName(buffer))
1601 return false;
1602
1603 buffer.Append(" : ");
1604
1605 if (!arg3->GetName(buffer))
1606 return false;
1607
1608 return buffer.Append(")");
1609 }
1610
1611 return false;
1612 }
1613
1614 private:
1615 const operator_info* fInfo;
1616 };
1617
1618
1619 class ConversionExpressionNode : public MultiSubExpressionsNode {
1620 public:
ConversionExpressionNode(Node * type)1621 ConversionExpressionNode(Node* type)
1622 :
1623 fType(type)
1624 {
1625 fType->SetParent(this);
1626 }
1627
GetName(NameBuffer & buffer) const1628 virtual bool GetName(NameBuffer& buffer) const
1629 {
1630 buffer.Append("(");
1631
1632 if (!fType->GetName(buffer))
1633 return false;
1634
1635 buffer.Append(")(");
1636
1637 Node* child = fFirstSubExpression;
1638 while (child != NULL) {
1639 if (child != fFirstSubExpression)
1640 buffer.Append(", ");
1641
1642 if (!child->GetName(buffer))
1643 return false;
1644
1645 child = child->Next();
1646 }
1647
1648 return buffer.Append(")");
1649 }
1650
1651 private:
1652 Node* fType;
1653 };
1654
1655
1656 class PointerToMemberNode : public DecoratingNode {
1657 public:
PointerToMemberNode(Node * classType,Node * memberType)1658 PointerToMemberNode(Node* classType, Node* memberType)
1659 :
1660 DecoratingNode(memberType),
1661 fClassType(classType)
1662 {
1663 fClassType->SetParent(this);
1664 }
1665
AddDecoration(NameBuffer & buffer,const Node * stopDecorator) const1666 virtual bool AddDecoration(NameBuffer& buffer,
1667 const Node* stopDecorator) const
1668 {
1669 if (this == stopDecorator)
1670 return true;
1671
1672 if (!fChildNode->AddDecoration(buffer, stopDecorator))
1673 return false;
1674
1675 // In most cases we need a space before the name. In some it is
1676 // superfluous, though.
1677 if (!buffer.IsEmpty() && buffer.LastChar() != '(')
1678 buffer.Append(" ");
1679
1680 if (!fClassType->GetName(buffer))
1681 return false;
1682
1683 return buffer.Append("::*");
1684 }
1685
ObjectType() const1686 virtual object_type ObjectType() const
1687 {
1688 return OBJECT_TYPE_DATA;
1689 }
1690
Type() const1691 virtual TypeInfo Type() const
1692 {
1693 // TODO: Method pointers aren't ordinary pointers. Though we might not
1694 // be able to determine the difference.
1695 return TypeInfo(TYPE_POINTER);
1696 }
1697
1698
1699 private:
1700 Node* fClassType;
1701 };
1702
1703
1704 class FunctionNode : public ObjectNode {
1705 public:
FunctionNode(Node * nameNode,bool hasReturnType,bool isExternC)1706 FunctionNode(Node* nameNode, bool hasReturnType, bool isExternC)
1707 :
1708 ObjectNode(nameNode),
1709 fFirstTypeNode(NULL),
1710 fLastTypeNode(NULL),
1711 fHasReturnType(hasReturnType),
1712 fIsExternC(isExternC)
1713 {
1714 }
1715
AddType(Node * child)1716 void AddType(Node* child)
1717 {
1718 child->SetParent(this);
1719
1720 if (fLastTypeNode != NULL) {
1721 fLastTypeNode->SetNext(child);
1722 fLastTypeNode = child;
1723 } else {
1724 fFirstTypeNode = child;
1725 fLastTypeNode = child;
1726 }
1727 }
1728
GetName(NameBuffer & buffer) const1729 virtual bool GetName(NameBuffer& buffer) const
1730 {
1731 NameDecorationInfo decorationInfo(NULL);
1732 return GetDecoratedName(buffer, decorationInfo);
1733 }
1734
GetDecoratedName(NameBuffer & buffer,NameDecorationInfo & decorationInfo) const1735 virtual bool GetDecoratedName(NameBuffer& buffer,
1736 NameDecorationInfo& decorationInfo) const
1737 {
1738 // write 'extern "C"'
1739 // if (fIsExternC)
1740 // buffer.Append("extern \"C\"");
1741
1742 // write the return type
1743 Node* child = fFirstTypeNode;
1744 if (_HasReturnType() && child != NULL) {
1745 if (!child->GetName(buffer))
1746 return false;
1747 child = child->Next();
1748
1749 buffer.Append(" ", 1);
1750 }
1751
1752 // write the function name
1753 if (fName == NULL)
1754 buffer.Append("(", 1);
1755
1756 CVQualifierInfo info;
1757 if (fName != NULL) {
1758 // skip CV qualifiers on our name -- we'll add them later
1759 fName->GetCVQualifierInfo(info);
1760 if (info.firstNonCVQualifier != NULL
1761 && !info.firstNonCVQualifier->GetName(buffer)) {
1762 return false;
1763 }
1764 }
1765
1766 // add non-CV qualifier decorations
1767 if (decorationInfo.firstDecorator != NULL) {
1768 if (!decorationInfo.firstDecorator->AddDecoration(buffer,
1769 decorationInfo.closestCVDecoratorList)) {
1770 return false;
1771 }
1772 }
1773
1774 if (fName == NULL)
1775 buffer.Append(")", 1);
1776
1777 // add the parameter types
1778 buffer.Append("(");
1779
1780 // don't add a single "void" parameter
1781 if (child != NULL && child->Next() == NULL
1782 && child->IsTypeName("void", 4)) {
1783 child = NULL;
1784 }
1785
1786 Node* firstParam = child;
1787 while (child != NULL) {
1788 if (child != firstParam)
1789 buffer.Append(", ");
1790
1791 if (!child->GetName(buffer))
1792 return false;
1793
1794 child = child->Next();
1795 }
1796
1797 buffer.Append(")");
1798
1799 // add CV qualifiers on our name
1800 if (info.firstCVQualifier != NULL) {
1801 if (!info.firstCVQualifier->AddDecoration(buffer,
1802 info.firstNonCVQualifier)) {
1803 return false;
1804 }
1805 }
1806
1807 // add CV qualifiers on us
1808 if (decorationInfo.closestCVDecoratorList != NULL)
1809 decorationInfo.closestCVDecoratorList->AddDecoration(buffer, NULL);
1810
1811 return true;
1812 }
1813
ObjectType() const1814 virtual object_type ObjectType() const
1815 {
1816 // no name, no fun
1817 if (fName == NULL)
1818 return OBJECT_TYPE_FUNCTION;
1819
1820 // check our name's prefix
1821 switch (fName->PrefixType()) {
1822 case PREFIX_NONE:
1823 case PREFIX_NAMESPACE:
1824 return OBJECT_TYPE_FUNCTION;
1825 case PREFIX_CLASS:
1826 case PREFIX_UNKNOWN:
1827 break;
1828 }
1829
1830 // Our name has a prefix, but we don't know, whether it is a class or
1831 // namespace. Let's ask our name what it thinks it is.
1832 object_type type = fName->ObjectType();
1833 switch (type) {
1834 case OBJECT_TYPE_FUNCTION:
1835 case OBJECT_TYPE_METHOD_CLASS:
1836 case OBJECT_TYPE_METHOD_OBJECT:
1837 case OBJECT_TYPE_METHOD_UNKNOWN:
1838 // That's as good as it gets.
1839 return type;
1840 case OBJECT_TYPE_UNKNOWN:
1841 case OBJECT_TYPE_DATA:
1842 default:
1843 // Obviously our name doesn't have a clue.
1844 return OBJECT_TYPE_METHOD_UNKNOWN;
1845 }
1846 }
1847
ParameterAt(uint32 index) const1848 virtual Node* ParameterAt(uint32 index) const
1849 {
1850 // skip return type
1851 Node* child = fFirstTypeNode;
1852 if (_HasReturnType() && child != NULL)
1853 child = child->Next();
1854
1855 // ignore a single "void" parameter
1856 if (child != NULL && child->Next() == NULL
1857 && child->IsTypeName("void", 4)) {
1858 return NULL;
1859 }
1860
1861 // get the type at the index
1862 while (child != NULL && index > 0) {
1863 child = child->Next();
1864 index--;
1865 }
1866
1867 return child;
1868 }
1869
1870 private:
_HasReturnType() const1871 bool _HasReturnType() const
1872 {
1873 return fHasReturnType
1874 || fName == NULL
1875 || (fName->IsTemplatized() && !fName->IsNoReturnValueFunction());
1876 }
1877
1878 private:
1879 Node* fFirstTypeNode;
1880 Node* fLastTypeNode;
1881 bool fHasReturnType;
1882 bool fIsExternC;
1883 };
1884
1885
1886 // #pragma mark - Demangler
1887
1888
1889 class Demangler {
1890 public:
1891 Demangler();
1892
1893 int Demangle(const char* mangledName, char* buffer,
1894 size_t size,
1895 DemanglingInfo& demanglingInfo);
1896 int GetParameterInfo(const char* mangledName,
1897 uint32 index, char* buffer, size_t size,
1898 ParameterInfo& info);
1899
1900 // actually private, but public to make gcc 2 happy
1901 inline bool _SetError(int error);
1902 inline void _AddAllocatedNode(Node* node);
1903
1904 private:
1905 template<typename NodeType> struct NodeCreator;
1906
1907 inline bool _SkipExpected(char c);
1908 inline bool _SkipExpected(const char* string);
1909
1910 void _Init();
1911 void _Cleanup();
1912
1913 int _Demangle(const char* mangledName, char* buffer,
1914 size_t size,
1915 DemanglingInfo& demanglingInfo);
1916 int _GetParameterInfo(const char* mangledName,
1917 uint32 index, char* buffer, size_t size,
1918 ParameterInfo& info);
1919
1920 int _Parse(const char* mangledName,
1921 const char*& versionSuffix,
1922 ObjectNode*& _node);
1923
1924 bool _ParseClone(ObjectNode*& _node);
1925 bool _ParseEncoding(ObjectNode*& _node);
1926 bool _ParseSpecialName(Node*& _node);
1927 bool _ParseCallOffset(bool& nonVirtual,
1928 number_type& offset1, number_type& offset2);
1929 bool _ParseName(Node*& _node);
1930 bool _ParseNestedName(Node*& _node);
1931 bool _ParseNestedNameInternal(Node*& _node);
1932 bool _ParseLocalName(Node*& _node);
1933 bool _ParseUnqualifiedName(Node*& _node);
1934 bool _ParseSourceName(Node*& _node);
1935 bool _ParseOperatorName(Node*& _node);
1936 bool _ParseType(Node*& _node);
1937 bool _ParseTypeInternal(Node*& _node);
1938 void _ParseCVQualifiers(int& qualifiers);
1939 bool _ParseTypeWithModifier(type_modifier modifier,
1940 int toSkip, Node*& _node);
1941 bool _TryParseBuiltinType(Node*& _node);
1942 bool _ParseFunctionType(FunctionNode*& _node);;
1943 bool _ParseArrayType(Node*& _node);
1944 bool _ParsePointerToMemberType(Node*& _node);
1945 bool _ParseTemplateParam(Node*& _node);
1946 bool _ParseSubstitution(Node*& _node);
1947 bool _ParseSubstitutionInternal(Node*& _node);
1948 bool _ParseBareFunctionType(FunctionNode* node);
1949 bool _ParseTemplateArgs(Node* node, Node*& _node);
1950 bool _ParseTemplateArg(Node*& _node);
1951 bool _ParseExpression(Node*& _node);
1952 bool _ParseExpressionPrimary(Node*& _node);
1953 bool _ParseNumber(number_type& number);
1954
1955 bool _CreateNodeAndSkip(const char* name,
1956 size_t length, int toSkip, Node*& _node);
1957 bool _CreateNodeAndSkip(const char* name, int toSkip,
1958 Node*& _node);
1959 bool _CreateTypeNodeAndSkip(type_type type,
1960 int toSkip, Node*& _node);
1961 bool _CreateTypeNodeAndSkip(const char* name,
1962 const char* prefix,
1963 const char* templateArgs, int toSkip,
1964 Node*& _node);
1965
1966 void _RegisterReferenceableNode(Node* node);
1967 bool _CreateSubstitutionNode(int index,
1968 Node*& _node);
1969
1970 private:
1971 Input fInput;
1972 int fError;
1973 Node* fAllocatedNodes;
1974 Node* fFirstReferenceableNode;
1975 Node* fLastReferenceableNode;
1976 Node* fTemplatizedNode;
1977 };
1978
1979
1980 template<typename NodeType>
1981 struct Demangler::NodeCreator {
NodeCreatorDemangler::NodeCreator1982 NodeCreator(Demangler* demangler)
1983 :
1984 fDemangler(demangler)
1985 {
1986 }
1987
1988 template<typename ReturnType>
operator ()Demangler::NodeCreator1989 inline bool operator()(ReturnType*& _node) const
1990 {
1991 _node = NEW(NodeType);
1992 if (_node == NULL)
1993 return fDemangler->_SetError(ERROR_NO_MEMORY);
1994
1995 fDemangler->_AddAllocatedNode(_node);
1996 return true;
1997 }
1998
1999 template<typename ParameterType1, typename ReturnType>
operator ()Demangler::NodeCreator2000 inline bool operator()(ParameterType1 arg1, ReturnType*& _node) const
2001 {
2002 _node = NEW(NodeType(arg1));
2003 if (_node == NULL)
2004 return fDemangler->_SetError(ERROR_NO_MEMORY);
2005
2006 fDemangler->_AddAllocatedNode(_node);
2007 return true;
2008 }
2009
2010 template<typename ParameterType1, typename ParameterType2,
2011 typename ReturnType>
operator ()Demangler::NodeCreator2012 inline bool operator()(ParameterType1 arg1, ParameterType2 arg2,
2013 ReturnType*& _node) const
2014 {
2015 _node = NEW(NodeType(arg1, arg2));
2016 if (_node == NULL)
2017 return fDemangler->_SetError(ERROR_NO_MEMORY);
2018
2019 fDemangler->_AddAllocatedNode(_node);
2020 return true;
2021 }
2022
2023 template<typename ParameterType1, typename ParameterType2,
2024 typename ParameterType3, typename ReturnType>
operator ()Demangler::NodeCreator2025 inline bool operator()(ParameterType1 arg1, ParameterType2 arg2,
2026 ParameterType3 arg3, ReturnType*& _node) const
2027 {
2028 _node = NEW(NodeType(arg1, arg2, arg3));
2029 if (_node == NULL)
2030 return fDemangler->_SetError(ERROR_NO_MEMORY);
2031
2032 fDemangler->_AddAllocatedNode(_node);
2033 return true;
2034 }
2035
2036 private:
2037 Demangler* fDemangler;
2038 };
2039
2040
2041 inline bool
_SetError(int error)2042 Demangler::_SetError(int error)
2043 {
2044 if (fError == ERROR_OK) {
2045 fError = error;
2046 #ifdef TRACE_GCC3_DEMANGLER
2047 DebugScope::Print("_SetError(): %d, remaining input: \"%s\"\n",
2048 error, fInput.String());
2049 #endif
2050 }
2051 return false;
2052 }
2053
2054
2055 inline void
_AddAllocatedNode(Node * node)2056 Demangler::_AddAllocatedNode(Node* node)
2057 {
2058 node->SetNextAllocated(fAllocatedNodes);
2059 fAllocatedNodes = node;
2060 }
2061
2062
2063 inline bool
_SkipExpected(char c)2064 Demangler::_SkipExpected(char c)
2065 {
2066 return fInput.SkipPrefix(c) || _SetError(ERROR_INVALID);
2067 }
2068
2069
2070 inline bool
_SkipExpected(const char * string)2071 Demangler::_SkipExpected(const char* string)
2072 {
2073 return fInput.SkipPrefix(string) || _SetError(ERROR_INVALID);
2074 }
2075
2076
Demangler()2077 Demangler::Demangler()
2078 :
2079 fInput(),
2080 fAllocatedNodes(NULL)
2081 {
2082 }
2083
2084
2085 int
Demangle(const char * mangledName,char * buffer,size_t size,DemanglingInfo & demanglingInfo)2086 Demangler::Demangle(const char* mangledName, char* buffer, size_t size,
2087 DemanglingInfo& demanglingInfo)
2088 {
2089 DEBUG_SCOPE("Demangle");
2090
2091 _Init();
2092
2093 int result = _Demangle(mangledName, buffer, size, demanglingInfo);
2094
2095 _Cleanup();
2096
2097 return result;
2098 }
2099
2100
2101 int
GetParameterInfo(const char * mangledName,uint32 index,char * buffer,size_t size,ParameterInfo & info)2102 Demangler::GetParameterInfo(const char* mangledName, uint32 index, char* buffer,
2103 size_t size, ParameterInfo& info)
2104 {
2105 DEBUG_SCOPE("GetParameterInfo");
2106
2107 _Init();
2108
2109 int result = _GetParameterInfo(mangledName, index, buffer, size, info);
2110
2111 _Cleanup();
2112
2113 return result;
2114 }
2115
2116
2117 void
_Init()2118 Demangler::_Init()
2119 {
2120 fError = ERROR_OK;
2121
2122 fFirstReferenceableNode = NULL;
2123 fLastReferenceableNode = NULL;
2124 fAllocatedNodes = NULL;
2125 fTemplatizedNode = NULL;
2126 }
2127
2128
2129 void
_Cleanup()2130 Demangler::_Cleanup()
2131 {
2132 while (fAllocatedNodes != NULL) {
2133 Node* node = fAllocatedNodes;
2134 fAllocatedNodes = node->NextAllocated();
2135 DELETE(node);
2136 }
2137 }
2138
2139
2140 int
_Demangle(const char * mangledName,char * buffer,size_t size,DemanglingInfo & demanglingInfo)2141 Demangler::_Demangle(const char* mangledName, char* buffer, size_t size,
2142 DemanglingInfo& demanglingInfo)
2143 {
2144 // parse the name
2145 const char* versionSuffix;
2146 ObjectNode* node;
2147 int error = _Parse(mangledName, versionSuffix, node);
2148 if (error != ERROR_OK)
2149 return error;
2150
2151 NameBuffer nameBuffer(buffer, size);
2152 bool success = node->GetObjectName(nameBuffer, demanglingInfo);
2153
2154 // If versioned, append the unmodified version string
2155 if (success && versionSuffix != NULL)
2156 nameBuffer.Append(versionSuffix);
2157
2158 if (nameBuffer.HadOverflow())
2159 return ERROR_BUFFER_TOO_SMALL;
2160
2161 if (!success)
2162 return ERROR_INTERNAL;
2163
2164 demanglingInfo.objectType = node->ObjectType();
2165
2166 nameBuffer.Terminate();
2167 return ERROR_OK;
2168 }
2169
2170
2171 int
_GetParameterInfo(const char * mangledName,uint32 index,char * buffer,size_t size,ParameterInfo & info)2172 Demangler::_GetParameterInfo(const char* mangledName, uint32 index,
2173 char* buffer, size_t size, ParameterInfo& info)
2174 {
2175 // parse the name
2176 const char* versionSuffix;
2177 ObjectNode* node;
2178 int error = _Parse(mangledName, versionSuffix, node);
2179 if (error != ERROR_OK)
2180 return error;
2181
2182 // get the parameter node
2183 Node* parameter = node->ParameterAt(index);
2184 if (parameter == NULL)
2185 return ERROR_INVALID_PARAMETER_INDEX;
2186
2187 // get the parameter name
2188 NameBuffer nameBuffer(buffer, size);
2189 bool success = parameter->GetName(nameBuffer);
2190
2191 if (nameBuffer.HadOverflow())
2192 return ERROR_BUFFER_TOO_SMALL;
2193
2194 if (!success)
2195 return ERROR_INTERNAL;
2196
2197 nameBuffer.Terminate();
2198
2199 // get the type
2200 info.type = parameter->Type();
2201
2202 return ERROR_OK;
2203 }
2204
2205
2206 int
_Parse(const char * mangledName,const char * & versionSuffix,ObjectNode * & _node)2207 Demangler::_Parse(const char* mangledName, const char*& versionSuffix,
2208 ObjectNode*& _node)
2209 {
2210 // To support versioned symbols, we ignore the version suffix when
2211 // demangling.
2212 versionSuffix = strchr(mangledName, '@');
2213 fInput.SetTo(mangledName,
2214 versionSuffix != NULL
2215 ? versionSuffix - mangledName : strlen(mangledName));
2216
2217 // <mangled-name> ::= _Z <encoding> [<clone-suffix>]*
2218
2219 if (!fInput.SkipPrefix("_Z"))
2220 return ERROR_NOT_MANGLED;
2221
2222 if (!_ParseEncoding(_node) || !_ParseClone(_node))
2223 return fError;
2224
2225 if (fInput.CharsRemaining() != 0) {
2226 // bogus at end of input
2227 return ERROR_INVALID;
2228 }
2229
2230 return ERROR_OK;
2231 }
2232
2233
2234 bool
_ParseClone(ObjectNode * & _node)2235 Demangler::_ParseClone(ObjectNode*& _node)
2236 {
2237 DEBUG_SCOPE("_ParseClone");
2238
2239 while (fInput.HasPrefix('.')) {
2240 int count = fInput.CharsRemaining();
2241 int i = 1;
2242 while (true) {
2243 for (; i < count && fInput[i] != '.'; i++)
2244 ;
2245 if (i + 1 >= count || fInput[i + 1] < '0' || fInput[i + 1] > '9')
2246 break;
2247 i++;
2248 }
2249 if (i == 1)
2250 break;
2251 Node* clone;
2252 if (!_CreateNodeAndSkip(fInput.String(), i, i, clone))
2253 return false;
2254
2255 if (!NodeCreator<ClonedNode>(this)(clone, _node, _node))
2256 return false;
2257 }
2258 return true;
2259 }
2260
2261
2262 bool
_ParseEncoding(ObjectNode * & _node)2263 Demangler::_ParseEncoding(ObjectNode*& _node)
2264 {
2265 DEBUG_SCOPE("_ParseEncoding");
2266
2267 // <encoding> ::= <function name> <bare-function-type>
2268 // ::= <data name>
2269 // ::= <special-name>
2270
2271 // NOTE: This is not in the specs: Local entities seem to be prefixed
2272 // by an 'L'.
2273 fInput.SkipPrefix('L');
2274
2275 // parse <special-name>, if it is one
2276 Node* name;
2277 if (fInput.HasPrefix('T') || fInput.HasPrefix("GV")) {
2278 return _ParseSpecialName(name)
2279 && NodeCreator<ObjectNode>(this)(name, _node);
2280 }
2281
2282 // either <data name> or <function name>
2283 if (!_ParseName(name))
2284 return false;
2285
2286 if (fInput.CharsRemaining() == 0 || fInput.HasPrefix('E')
2287 || fInput.HasPrefix('.')) {
2288 // <data name>
2289 return NodeCreator<ObjectNode>(this)(name, _node);
2290 }
2291
2292 // <function name> -- parse remaining <bare-function-type>
2293 FunctionNode* functionNode;
2294 if (!NodeCreator<FunctionNode>(this)(name, false, false, functionNode))
2295 return false;
2296 _node = functionNode;
2297
2298 // If our name is templatized, we push it onto the templatized node
2299 // stack while parsing the function parameters.
2300 Node* previousTemplatizedNode = fTemplatizedNode;
2301 if (name->IsTemplatized())
2302 fTemplatizedNode = name;
2303
2304 if (!_ParseBareFunctionType(functionNode))
2305 return false;
2306
2307 fTemplatizedNode = previousTemplatizedNode;
2308
2309 return true;
2310 }
2311
2312
2313 bool
_ParseSpecialName(Node * & _node)2314 Demangler::_ParseSpecialName(Node*& _node)
2315 {
2316 DEBUG_SCOPE("_ParseSpecialName");
2317
2318 if (fInput.CharsRemaining() == 0)
2319 return _SetError(ERROR_INVALID);
2320
2321 // <special-name> ::= GV <object name> # Guard variable for one-time
2322 // # initialization
2323 // # No <type>
2324 if (!fInput.SkipPrefix('T')) {
2325 Node* name;
2326 return _SkipExpected("GV")
2327 && _ParseName(name)
2328 && NodeCreator<SpecialNameNode>(this)("guard variable for ",
2329 name, _node);
2330 }
2331
2332 // <special-name> ::= TV <type> # virtual table
2333 // ::= TT <type> # VTT structure (construction vtable
2334 // # index)
2335 // ::= TI <type> # typeinfo structure
2336 // ::= TS <type> # typeinfo name (null-terminated byte
2337 // # string)
2338 const char* prefix = NULL;
2339 switch (fInput[0]) {
2340 case 'V':
2341 prefix = "vtable for ";
2342 break;
2343 case 'T':
2344 prefix = "VTT for ";
2345 break;
2346 case 'I':
2347 prefix = "typeinfo for ";
2348 break;
2349 case 'S':
2350 prefix = "typeinfo name for ";
2351 break;
2352 }
2353
2354 if (prefix != NULL) {
2355 fInput.Skip(1);
2356 Node* type;
2357 return _ParseType(type)
2358 && NodeCreator<SpecialNameNode>(this)(prefix, type, _node);
2359 }
2360
2361 // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
2362 // # base is the nominal target function of thunk
2363 // # first call-offset is 'this' adjustment
2364 // # second call-offset is result adjustment
2365 if (fInput.SkipPrefix('c')) {
2366 bool nonVirtual;
2367 number_type offset1;
2368 number_type offset2;
2369 ObjectNode* name;
2370 return _ParseCallOffset(nonVirtual, offset1, offset2)
2371 && _ParseCallOffset(nonVirtual, offset1, offset2)
2372 && _ParseEncoding(name)
2373 && NodeCreator<SpecialNameNode>(this)(
2374 "covariant return thunk to ", name, _node);
2375 }
2376
2377 // <special-name> ::= T <call-offset> <base encoding>
2378 // # base is the nominal target function of thunk
2379 bool nonVirtual;
2380 number_type offset1;
2381 number_type offset2;
2382 ObjectNode* name;
2383 return _ParseCallOffset(nonVirtual, offset1, offset2)
2384 && _ParseEncoding(name)
2385 && NodeCreator<SpecialNameNode>(this)(
2386 nonVirtual ? "non-virtual thunk to " : "virtual thunk to ",
2387 name, _node);
2388 }
2389
2390
2391 bool
_ParseCallOffset(bool & nonVirtual,number_type & offset1,number_type & offset2)2392 Demangler::_ParseCallOffset(bool& nonVirtual, number_type& offset1,
2393 number_type& offset2)
2394 {
2395 // <call-offset> ::= h <nv-offset> _
2396 // ::= v <v-offset> _
2397 // <nv-offset> ::= <offset number>
2398 // # non-virtual base override
2399 // <v-offset> ::= <offset number> _ <virtual offset number>
2400 // # virtual base override, with vcall offset
2401
2402 // non-virtual
2403 if (fInput.SkipPrefix('h')) {
2404 nonVirtual = true;
2405 return _ParseNumber(offset1) && _SkipExpected('_');
2406 }
2407
2408 // virtual
2409 nonVirtual = false;
2410 return _SkipExpected('v')
2411 && _ParseNumber(offset1)
2412 && _SkipExpected('_')
2413 && _ParseNumber(offset2)
2414 && _SkipExpected('_');
2415 }
2416
2417 bool
_ParseName(Node * & _node)2418 Demangler::_ParseName(Node*& _node)
2419 {
2420 DEBUG_SCOPE("_ParseName");
2421
2422 if (fInput.CharsRemaining() == 0)
2423 return _SetError(ERROR_INVALID);
2424
2425 // <name> ::= <nested-name>
2426 // ::= <unscoped-name>
2427 // ::= <unscoped-template-name> <template-args>
2428 // ::= <local-name> # See Scope Encoding below
2429 //
2430 // <unscoped-name> ::= <unqualified-name>
2431 // ::= St <unqualified-name> # ::std::
2432 //
2433 // <unscoped-template-name> ::= <unscoped-name>
2434 // ::= <substitution>
2435
2436 switch (fInput[0]) {
2437 case 'N':
2438 // <nested-name>
2439 return _ParseNestedName(_node);
2440 case 'Z':
2441 // <local-name>
2442 return _ParseLocalName(_node);
2443 case 'S':
2444 {
2445 // <substitution>
2446 if (!fInput.HasPrefix("St")) {
2447 if (!_ParseSubstitution(_node))
2448 return false;
2449 break;
2450 }
2451
2452 // std:: namespace
2453 fInput.Skip(2);
2454
2455 Node* prefix;
2456 if (!NodeCreator<SimpleNameNode>(this)("std", prefix))
2457 return false;
2458
2459 // <unqualified-name>
2460 Node* node;
2461 if (!_ParseUnqualifiedName(node)
2462 || !NodeCreator<PrefixedNode>(this)(prefix, node, _node)) {
2463 return false;
2464 }
2465
2466 break;
2467 }
2468 default:
2469 // <unqualified-name>
2470 if (!_ParseUnqualifiedName(_node))
2471 return false;
2472 break;
2473 }
2474
2475 // We get here for the names that might be an <unscoped-template-name>.
2476 // Check whether <template-args> are following.
2477 if (!fInput.HasPrefix('I'))
2478 return true;
2479
2480 // <unscoped-template-name> is referenceable
2481 _RegisterReferenceableNode(_node);
2482
2483 return _ParseTemplateArgs(_node, _node);
2484 }
2485
2486
2487 bool
_ParseNestedName(Node * & _node)2488 Demangler::_ParseNestedName(Node*& _node)
2489 {
2490 DEBUG_SCOPE("_ParseNestedName");
2491
2492 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
2493 // ::= N [<CV-qualifiers>] <template-prefix>
2494 // <template-args> E
2495 //
2496 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
2497 //
2498 // <prefix> ::= <prefix> <unqualified-name>
2499 // ::= <template-prefix> <template-args>
2500 // ::= <template-param>
2501 // ::= # empty
2502 // ::= <substitution>
2503 //
2504 // <template-prefix> ::= <prefix> <template unqualified-name>
2505 // ::= <template-param>
2506 // ::= <substitution>
2507
2508 if (!_SkipExpected('N'))
2509 return false;
2510
2511 // parse CV qualifiers
2512 int qualifiers;
2513 _ParseCVQualifiers(qualifiers);
2514
2515 // parse the main part
2516 if (!_ParseNestedNameInternal(_node))
2517 return false;
2518
2519 // create a CV qualifiers wrapper node, if necessary
2520 if (qualifiers != 0) {
2521 return NodeCreator<CVQualifiersNode>(this)(qualifiers, _node,
2522 _node);
2523 }
2524
2525 return true;
2526 }
2527
2528
2529 bool
_ParseNestedNameInternal(Node * & _node)2530 Demangler::_ParseNestedNameInternal(Node*& _node)
2531 {
2532 DEBUG_SCOPE("_ParseNestedNameMain");
2533
2534 if (fInput.CharsRemaining() == 0)
2535 return _SetError(ERROR_INVALID);
2536
2537 // the initial prefix might be a template param or a substitution
2538 Node* initialPrefixNode = NULL;
2539 Node* prefixNode = NULL;
2540 switch (fInput[0]) {
2541 case 'T': // <template-param>
2542 if (!_ParseTemplateParam(initialPrefixNode))
2543 return false;
2544
2545 // a <prefix> or <template-prefix> and as such referenceable
2546 _RegisterReferenceableNode(initialPrefixNode);
2547 break;
2548
2549 case 'S': // <substitution>
2550 if (!_ParseSubstitution(initialPrefixNode))
2551 return false;
2552 break;
2553 }
2554
2555 while (true) {
2556 bool canTerminate = false;
2557 Node* node;
2558
2559 if (initialPrefixNode != NULL) {
2560 node = initialPrefixNode;
2561 initialPrefixNode = NULL;
2562 } else {
2563 if (!_ParseUnqualifiedName(node))
2564 return false;
2565 canTerminate = true;
2566 }
2567
2568 // join prefix and the new node
2569 if (prefixNode != NULL) {
2570 if (!NodeCreator<PrefixedNode>(this)(prefixNode, node, node))
2571 return false;
2572 }
2573
2574 // template arguments?
2575 if (fInput.HasPrefix('I')) {
2576 // <template-prefix> is referenceable
2577 _RegisterReferenceableNode(node);
2578
2579 // parse the template arguments
2580 if (!_ParseTemplateArgs(node, node))
2581 return false;
2582 canTerminate = true;
2583 }
2584
2585 if (fInput.CharsRemaining() == 0)
2586 return _SetError(ERROR_INVALID);
2587
2588 // end of nested name?
2589 if (fInput.SkipPrefix('E')) {
2590 // If it doesn't have template args, it must end in an
2591 // unqualified name.
2592 if (!canTerminate)
2593 return _SetError(ERROR_INVALID);
2594
2595 _node = node;
2596 return true;
2597 }
2598
2599 // The fun continues, so this is a <prefix> or <template-prefix>
2600 // and as such referenceable.
2601 prefixNode = node;
2602 _RegisterReferenceableNode(node);
2603 }
2604 }
2605
2606
2607 bool
_ParseLocalName(Node * & _node)2608 Demangler::_ParseLocalName(Node*& _node)
2609 {
2610 DEBUG_SCOPE("_ParseLocalName");
2611
2612 // <local-name> := Z <function encoding> E <entity name>
2613 // [<discriminator>]
2614 // := Z <function encoding> E s [<discriminator>]
2615 // <discriminator> := _ <non-negative number>
2616
2617 // parse the function name
2618 ObjectNode* functionName;
2619 if (!_SkipExpected('Z')
2620 || !_ParseEncoding(functionName)
2621 || !_SkipExpected('E')) {
2622 return false;
2623 }
2624
2625 Node* entityName;
2626 if (fInput.SkipPrefix('s')) {
2627 // string literal
2628 if (!NodeCreator<SimpleNameNode>(this)("string literal",
2629 entityName)) {
2630 return false;
2631 }
2632 } else {
2633 // local type or object
2634 if (!_ParseName(entityName))
2635 return false;
2636 }
2637
2638 // parse discriminator
2639 number_type discriminator = 0;
2640 if (fInput.SkipPrefix('_')) {
2641 if (!_ParseNumber(discriminator))
2642 return false;
2643 if (discriminator < 0)
2644 return _SetError(ERROR_INVALID);
2645 discriminator++;
2646 }
2647
2648 return NodeCreator<PrefixedNode>(this)(functionName, entityName, _node);
2649 }
2650
2651
2652 bool
_ParseUnqualifiedName(Node * & _node)2653 Demangler::_ParseUnqualifiedName(Node*& _node)
2654 {
2655 DEBUG_SCOPE("_ParseUnqualifiedName");
2656
2657 // <unqualified-name> ::= <operator-name>
2658 // ::= <ctor-dtor-name>
2659 // ::= <source-name>
2660 //
2661 // <source-name> ::= <positive length number> <identifier>
2662 // <number> ::= [n] <non-negative decimal integer>
2663 // <identifier> ::= <unqualified source code identifier>
2664 //
2665 // <ctor-dtor-name> ::= C1 # complete object constructor
2666 // ::= C2 # base object constructor
2667 // ::= C3 # complete object allocating constructor
2668 // ::= D0 # deleting destructor
2669 // ::= D1 # complete object destructor
2670 // ::= D2 # base object destructor
2671
2672 // we need at least 2 chars
2673 if (fInput.CharsRemaining() < 2)
2674 return _SetError(ERROR_INVALID);
2675
2676 if (isdigit(fInput[0]) || (fInput[0] == 'n' && isdigit(fInput[1]))) {
2677 // <source-name>
2678 return _ParseSourceName(_node);
2679 }
2680
2681 if (fInput[0] == 'C') {
2682 // <ctor-dtor-name> -- constructors
2683 switch (fInput[1]) {
2684 case '1':
2685 case '2':
2686 case '3':
2687 if (!NodeCreator<XtructorNode>(this)(true, fInput[1] - '1',
2688 _node)) {
2689 return false;
2690 }
2691
2692 fInput.Skip(2);
2693 return true;
2694 default:
2695 return _SetError(ERROR_INVALID);
2696 }
2697 }
2698
2699 if (fInput[0] == 'D') {
2700 // <ctor-dtor-name> -- destructors
2701 switch (fInput[1]) {
2702 case '0':
2703 case '1':
2704 case '2':
2705 if (!NodeCreator<XtructorNode>(this)(false, fInput[1] - '0',
2706 _node)) {
2707 return false;
2708 }
2709
2710 fInput.Skip(2);
2711 return true;
2712 default:
2713 return _SetError(ERROR_INVALID);
2714 }
2715 }
2716
2717 // must be an <operator-name>
2718 return _ParseOperatorName(_node);
2719 }
2720
2721
2722 bool
_ParseSourceName(Node * & _node)2723 Demangler::_ParseSourceName(Node*& _node)
2724 {
2725 DEBUG_SCOPE("_ParseSourceName");
2726
2727 if (fInput.CharsRemaining() == 0)
2728 return _SetError(ERROR_INVALID);
2729
2730 number_type number;
2731 if (!_ParseNumber(number))
2732 return false;
2733
2734 if (number <= 0 || number > fInput.CharsRemaining())
2735 return _SetError(ERROR_INVALID);
2736
2737 return _CreateNodeAndSkip(fInput.String(), number, number, _node);
2738 }
2739
2740
2741 bool
_ParseOperatorName(Node * & _node)2742 Demangler::_ParseOperatorName(Node*& _node)
2743 {
2744 DEBUG_SCOPE("_ParseOperatorName");
2745
2746 if (fInput.CharsRemaining() < 2)
2747 return _SetError(ERROR_INVALID);
2748
2749 const operator_info* info = NULL;
2750 for (int i = 0; kOperatorInfos[i].name != NULL; i++) {
2751 if (fInput.SkipPrefix(kOperatorInfos[i].mangled_name)) {
2752 info = &kOperatorInfos[i];
2753 break;
2754 }
2755 }
2756
2757 if (info != NULL)
2758 return NodeCreator<OperatorNode>(this)(info, _node);
2759
2760 // <operator-name> ::= cv <type> # (cast)
2761 if (fInput.SkipPrefix("cv")) {
2762 Node* typeNode;
2763 if (!_ParseType(typeNode))
2764 return false;
2765
2766 return NodeCreator<CastOperatorNode>(this)(typeNode, _node);
2767 }
2768
2769 // <operator-name> ::= v <digit> <source-name> # vendor extended
2770 // operator
2771 if (fInput.SkipPrefix('v')) {
2772 if (fInput.CharsRemaining() == 0 || !isdigit(fInput[0]))
2773 return _SetError(ERROR_INVALID);
2774 fInput.Skip(1);
2775
2776 Node* name;
2777 return _ParseSourceName(name)
2778 && NodeCreator<VendorOperatorNode>(this)(name, _node);
2779 }
2780
2781 return _SetError(ERROR_INVALID);
2782 }
2783
2784
2785 bool
_ParseType(Node * & _node)2786 Demangler::_ParseType(Node*& _node)
2787 {
2788 DEBUG_SCOPE("_ParseType");
2789
2790 if (!_ParseTypeInternal(_node))
2791 return false;
2792
2793 _RegisterReferenceableNode(_node);
2794 return true;
2795 }
2796
2797
2798 bool
_ParseTypeInternal(Node * & _node)2799 Demangler::_ParseTypeInternal(Node*& _node)
2800 {
2801 DEBUG_SCOPE("_ParseTypeInternal");
2802
2803 // <type> ::= <builtin-type>
2804 // ::= <function-type>
2805 // ::= <class-enum-type>
2806 // ::= <array-type>
2807 // ::= <pointer-to-member-type>
2808 // ::= <template-param>
2809 // ::= <template-template-param> <template-args>
2810 // ::= <substitution> # See Compression below
2811 //
2812 // <template-template-param> ::= <template-param>
2813 // ::= <substitution>
2814 //
2815 // <type> ::= <CV-qualifiers> <type>
2816 // ::= P <type> # pointer-to
2817 // ::= R <type> # reference-to
2818 // ::= O <type> # rvalue reference-to (C++0x)
2819 // ::= C <type> # complex pair (C 2000)
2820 // ::= G <type> # imaginary (C 2000)
2821 // ::= U <source-name> <type> # vendor extended type qualifier
2822 //
2823 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
2824 //
2825 // <type> ::= Dp <type> # pack expansion of (C++0x)
2826 // ::= Dt <expression> E # decltype of an id-expression or
2827 // # class member access (C++0x)
2828 // ::= DT <expression> E # decltype of an expression (C++0x)
2829
2830 if (_TryParseBuiltinType(_node)) {
2831 _node->SetReferenceable(false);
2832 return true;
2833 }
2834 if (fError != ERROR_OK)
2835 return false;
2836
2837 if (fInput.CharsRemaining() == 0)
2838 return _SetError(ERROR_INVALID);
2839
2840 switch (fInput[0]) {
2841 // function type
2842 case 'F':
2843 {
2844 FunctionNode* functionNode;
2845 if (!_ParseFunctionType(functionNode))
2846 return false;
2847 _node = functionNode;
2848 return true;
2849 }
2850
2851 // array type
2852 case 'A':
2853 return _ParseArrayType(_node);
2854
2855 // pointer to member type
2856 case 'M':
2857 return _ParsePointerToMemberType(_node);
2858
2859 // template param
2860 case 'T':
2861 if (!_ParseTemplateParam(_node))
2862 return false;
2863 break;
2864
2865 // CV qualifiers
2866 case 'r':
2867 case 'V':
2868 case 'K':
2869 {
2870 // parse CV qualifiers
2871 int qualifiers;
2872 _ParseCVQualifiers(qualifiers);
2873
2874 // parse the type
2875 if (!_ParseType(_node))
2876 return false;
2877
2878 // create the wrapper node
2879 return NodeCreator<CVQualifiersNode>(this)(qualifiers, _node,
2880 _node);
2881 }
2882
2883 // pointer, reference, etc.
2884 case 'P':
2885 return _ParseTypeWithModifier(TYPE_QUALIFIER_POINTER, 1, _node);
2886 case 'R':
2887 return _ParseTypeWithModifier(TYPE_QUALIFIER_REFERENCE, 1,
2888 _node);
2889 case 'O':
2890 return _ParseTypeWithModifier(
2891 TYPE_QUALIFIER_RVALUE_REFERENCE, 1, _node);
2892 case 'C':
2893 return _ParseTypeWithModifier(TYPE_QUALIFIER_COMPLEX, 1, _node);
2894 case 'G':
2895 return _ParseTypeWithModifier(TYPE_QUALIFIER_IMAGINARY, 1,
2896 _node);
2897
2898 // pack and decltype
2899 case 'D':
2900 #if 0
2901 if (fInput.CharsRemaining() < 2)
2902 return _SetError(ERROR_INVALID);
2903
2904 switch(fInput[1]) {
2905 case 'p':
2906 fInput.Skip(2);
2907 return _ParseType(_node);
2908 case 't':
2909 case 'T':
2910 {
2911 fInput.Skip(2);
2912 Node* nameNode;
2913 if (!_ParseExpression(nameNode))
2914 return false;
2915 if (!fInput.SkipPrefix('E'))
2916 return ERROR_INVALID;
2917 }
2918 }
2919 #endif
2920 // NOTE: Unsupported by the GNU demangler.
2921 return _SetError(ERROR_UNSUPPORTED);
2922
2923 // vendor extended type qualifier
2924 case 'U':
2925 fInput.Skip(1);
2926 Node* name;
2927 Node* type;
2928 return _ParseSourceName(name) && _ParseType(type)
2929 && NodeCreator<VendorTypeModifierNode>(this)(name, type,
2930 _node);
2931
2932 // substitution
2933 case 'S':
2934 if (!fInput.HasPrefix("St")) {
2935 if (!_ParseSubstitution(_node))
2936 return false;
2937 break;
2938 }
2939
2940 // "St" -- the "std" namespace. The grammar is ambiguous here,
2941 // since we could parse that as <substitution> or as
2942 // <class-enum-type>. We assume the latter and fall through.
2943
2944 default:
2945 {
2946 // <class-enum-type> ::= <name>
2947 Node* nameNode;
2948 return _ParseName(nameNode)
2949 && NodeCreator<NamedTypeNode>(this)(nameNode, _node);
2950 }
2951 }
2952
2953 // We get here for the types that might be a <template-template-param>.
2954 // Check whether <template-args> are following.
2955 if (!fInput.HasPrefix('I'))
2956 return true;
2957
2958 // <template-template-param> is referenceable
2959 _RegisterReferenceableNode(_node);
2960
2961 return _ParseTemplateArgs(_node, _node);
2962 }
2963
2964
2965 void
_ParseCVQualifiers(int & qualifiers)2966 Demangler::_ParseCVQualifiers(int& qualifiers)
2967 {
2968 qualifiers = 0;
2969
2970 if (fInput.SkipPrefix('r'))
2971 qualifiers |= CV_QUALIFIER_RESTRICT;
2972 if (fInput.SkipPrefix('V'))
2973 qualifiers |= CV_QUALIFIER_VOLATILE;
2974 if (fInput.SkipPrefix('K'))
2975 qualifiers |= CV_QUALIFIER_CONST;
2976 }
2977
2978
2979 bool
_ParseTypeWithModifier(type_modifier modifier,int toSkip,Node * & _node)2980 Demangler::_ParseTypeWithModifier(type_modifier modifier, int toSkip,
2981 Node*& _node)
2982 {
2983 if (toSkip > 0)
2984 fInput.Skip(toSkip);
2985
2986 Node* node;
2987 if (!_ParseType(node))
2988 return false;
2989
2990 return NodeCreator<TypeModifierNode>(this)(modifier, node, _node);
2991 }
2992
2993
2994 bool
_TryParseBuiltinType(Node * & _node)2995 Demangler::_TryParseBuiltinType(Node*& _node)
2996 {
2997 DEBUG_SCOPE("_TryParseBuiltinType");
2998
2999 // <builtin-type> ::= v # void
3000 // ::= w # wchar_t
3001 // ::= b # bool
3002 // ::= c # char
3003 // ::= a # signed char
3004 // ::= h # unsigned char
3005 // ::= s # short
3006 // ::= t # unsigned short
3007 // ::= i # int
3008 // ::= j # unsigned int
3009 // ::= l # long
3010 // ::= m # unsigned long
3011 // ::= x # long long, __int64
3012 // ::= y # unsigned long long, __int64
3013 // ::= n # __int128
3014 // ::= o # unsigned __int128
3015 // ::= f # float
3016 // ::= d # double
3017 // ::= e # long double, __float80
3018 // ::= g # __float128
3019 // ::= z # ellipsis
3020 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3021 // ::= De # IEEE 754r decimal floating point (128 bits)
3022 // ::= Df # IEEE 754r decimal floating point (32 bits)
3023 // ::= Dh # IEEE 754r half-precision floating point
3024 // # (16 bits)
3025 // ::= Di # char32_t
3026 // ::= Ds # char16_t
3027 // ::= u <source-name> # vendor extended type
3028
3029 if (fInput.CharsRemaining() == 0)
3030 return false;
3031
3032 switch (fInput[0]) {
3033 case 'v':
3034 return _CreateTypeNodeAndSkip(TYPE_VOID, 1, _node);
3035 case 'w':
3036 return _CreateTypeNodeAndSkip(TYPE_WCHAR_T, 1, _node);
3037 case 'b':
3038 return _CreateTypeNodeAndSkip(TYPE_BOOL, 1, _node);
3039 case 'c':
3040 return _CreateTypeNodeAndSkip(TYPE_CHAR, 1, _node);
3041 case 'a':
3042 return _CreateTypeNodeAndSkip(TYPE_SIGNED_CHAR, 1, _node);
3043 case 'h':
3044 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_CHAR, 1, _node);
3045 case 's':
3046 return _CreateTypeNodeAndSkip(TYPE_SHORT, 1, _node);
3047 case 't':
3048 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_SHORT, 1,
3049 _node);
3050 case 'i':
3051 return _CreateTypeNodeAndSkip(TYPE_INT, 1, _node);
3052 case 'j':
3053 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_INT, 1, _node);
3054 case 'l':
3055 return _CreateTypeNodeAndSkip(TYPE_LONG, 1, _node);
3056 case 'm':
3057 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_LONG, 1, _node);
3058 case 'x':
3059 return _CreateTypeNodeAndSkip(TYPE_LONG_LONG, 1, _node);
3060 case 'y':
3061 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_LONG_LONG, 1, _node);
3062 case 'n':
3063 return _CreateTypeNodeAndSkip(TYPE_INT128, 1, _node);
3064 case 'o':
3065 return _CreateTypeNodeAndSkip(TYPE_UNSIGNED_INT128, 1, _node);
3066 case 'f':
3067 return _CreateTypeNodeAndSkip(TYPE_FLOAT, 1, _node);
3068 case 'd':
3069 return _CreateTypeNodeAndSkip(TYPE_DOUBLE, 1, _node);
3070 case 'e':
3071 return _CreateTypeNodeAndSkip(TYPE_LONG_DOUBLE, 1, _node);
3072 case 'g':
3073 return _CreateTypeNodeAndSkip(TYPE_FLOAT128, 1, _node);
3074 case 'z':
3075 return _CreateTypeNodeAndSkip(TYPE_ELLIPSIS, 1, _node);
3076
3077 case 'D':
3078 if (fInput.CharsRemaining() < 2)
3079 return false;
3080
3081 // TODO: Official names for the __dfloat*!
3082 switch (fInput[1]) {
3083 case 'd':
3084 return _CreateTypeNodeAndSkip(TYPE_DFLOAT64, 2, _node);
3085 case 'e':
3086 return _CreateTypeNodeAndSkip(TYPE_DFLOAT128, 2, _node);
3087 case 'f':
3088 return _CreateTypeNodeAndSkip(TYPE_DFLOAT32, 2, _node);
3089 case 'h':
3090 return _CreateTypeNodeAndSkip(TYPE_DFLOAT16, 2, _node);
3091 case 'i':
3092 return _CreateTypeNodeAndSkip(TYPE_CHAR16_T, 2, _node);
3093 case 's':
3094 return _CreateTypeNodeAndSkip(TYPE_CHAR32_T, 2, _node);
3095 default:
3096 return false;
3097 }
3098
3099 case 'u':
3100 {
3101 fInput.Skip(1);
3102 Node* nameNode;
3103 return _ParseSourceName(nameNode)
3104 && NodeCreator<NamedTypeNode>(this)(nameNode, _node);
3105 }
3106
3107 default:
3108 return false;
3109 }
3110 }
3111
3112
3113 bool
_ParseFunctionType(FunctionNode * & _node)3114 Demangler::_ParseFunctionType(FunctionNode*& _node)
3115 {
3116 DEBUG_SCOPE("_ParseFunctionType");
3117
3118 // <function-type> ::= F [Y] <bare-function-type> E
3119
3120 if (!_SkipExpected('F'))
3121 return false;
3122
3123 // is 'extern "C"'?
3124 bool isExternC = fInput.SkipPrefix('Y');
3125
3126 // create function and parse function type
3127 if (!NodeCreator<FunctionNode>(this)((Node*)NULL, true, isExternC,
3128 _node)
3129 || !_ParseBareFunctionType(_node)) {
3130 return false;
3131 }
3132
3133 // skip terminating 'E'
3134 return _SkipExpected('E');
3135 }
3136
3137
3138 bool
_ParseArrayType(Node * & _node)3139 Demangler::_ParseArrayType(Node*& _node)
3140 {
3141 DEBUG_SCOPE("_ParseArrayType");
3142
3143 // <array-type> ::= A <positive dimension number> _ <element type>
3144 // ::= A [<dimension expression>] _ <element type>
3145
3146 if (fInput.CharsRemaining() < 2 || !fInput.SkipPrefix('A'))
3147 return _SetError(ERROR_INVALID);
3148
3149 number_type dimensionNumber;
3150 Node* dimensionExpression = NULL;
3151
3152 // If it looks like a number, it must be the first production, otherwise
3153 // the second one.
3154 if (isdigit(fInput[0])
3155 || (fInput[0] == 'n' && fInput.CharsRemaining() >= 2
3156 && isdigit(fInput[1]))) {
3157 if (!_ParseNumber(dimensionNumber))
3158 return false;
3159 } else {
3160 if (!_ParseExpression(dimensionExpression))
3161 return false;
3162 }
3163
3164 // parse the type
3165 Node* type;
3166 if (!_SkipExpected('_') || !_ParseType(type))
3167 return false;
3168
3169 // create the array node
3170 return dimensionExpression != NULL
3171 ? NodeCreator<ArrayNode>(this)(type, dimensionExpression, _node)
3172 : NodeCreator<ArrayNode>(this)(type, dimensionNumber, _node);
3173 }
3174
3175
3176 bool
_ParsePointerToMemberType(Node * & _node)3177 Demangler::_ParsePointerToMemberType(Node*& _node)
3178 {
3179 DEBUG_SCOPE("_ParsePointerToMemberType");
3180
3181 // <pointer-to-member-type> ::= M <class type> <member type>
3182 Node* classType;
3183 Node* memberType;
3184 return _SkipExpected('M')
3185 && _ParseType(classType)
3186 && _ParseType(memberType)
3187 && NodeCreator<PointerToMemberNode>(this)(classType, memberType,
3188 _node);
3189 }
3190
3191
3192 bool
_ParseTemplateParam(Node * & _node)3193 Demangler::_ParseTemplateParam(Node*& _node)
3194 {
3195 DEBUG_SCOPE("_ParseTemplateParam");
3196
3197 // <template-param> ::= T_ # first template parameter
3198 // ::= T <parameter-2 non-negative number> _
3199
3200 if (!_SkipExpected('T'))
3201 return false;
3202 if (fTemplatizedNode == NULL)
3203 return _SetError(ERROR_INVALID);
3204
3205 // get the index;
3206 number_type index = 0;
3207 if (!fInput.HasPrefix('_')) {
3208 if (!_ParseNumber(index))
3209 return false;
3210
3211 if (index < 0)
3212 return _SetError(ERROR_INVALID);
3213 index++;
3214 }
3215
3216 if (!_SkipExpected('_'))
3217 return false;
3218
3219 // get the parameter
3220 Node* parameter = fTemplatizedNode->TemplateParameterAt(index);
3221 if (parameter == NULL)
3222 return _SetError(ERROR_INVALID);
3223
3224 // create a substitution node
3225 return NodeCreator<SubstitutionNode>(this)(parameter, _node);
3226 }
3227
3228
3229 bool
_ParseSubstitution(Node * & _node)3230 Demangler::_ParseSubstitution(Node*& _node)
3231 {
3232 DEBUG_SCOPE("_ParseSubstitution");
3233
3234 if (!_ParseSubstitutionInternal(_node))
3235 return false;
3236
3237 // substitutions are never referenceable
3238 _node->SetReferenceable(false);
3239
3240 return true;
3241 }
3242
3243
3244 bool
_ParseSubstitutionInternal(Node * & _node)3245 Demangler::_ParseSubstitutionInternal(Node*& _node)
3246 {
3247 DEBUG_SCOPE("_ParseSubstitutionInternal");
3248
3249 // <substitution> ::= S <seq-id> _
3250 // ::= S_
3251 //
3252 // <substitution> ::= St # ::std::
3253 // <substitution> ::= Sa # ::std::allocator
3254 // <substitution> ::= Sb # ::std::basic_string
3255 // <substitution> ::= Ss # ::std::basic_string < char,
3256 // ::std::char_traits<char>,
3257 // ::std::allocator<char> >
3258 // <substitution> ::= Si # ::std::basic_istream<char,
3259 // std::char_traits<char> >
3260 // <substitution> ::= So # ::std::basic_ostream<char,
3261 // std::char_traits<char> >
3262 // <substitution> ::= Sd # ::std::basic_iostream<char,
3263 // std::char_traits<char> >
3264
3265 if (fInput.CharsRemaining() < 2 || !fInput.SkipPrefix('S'))
3266 return _SetError(ERROR_INVALID);
3267
3268 switch (fInput[0]) {
3269 case 't':
3270 return _CreateNodeAndSkip("std", 1, _node);
3271 case 'a':
3272 return _CreateTypeNodeAndSkip("allocator", "std", NULL, 1,
3273 _node);
3274 case 'b':
3275 return _CreateTypeNodeAndSkip("basic_string", "std", NULL, 1,
3276 _node);
3277 case 's':
3278 return _CreateTypeNodeAndSkip("basic_string", "std",
3279 "char, std::char_traits<char>, std::allocator<char>", 1,
3280 _node);
3281 case 'i':
3282 return _CreateTypeNodeAndSkip("basic_istream", "std",
3283 "char, std::char_traits<char>", 1, _node);
3284 case 'o':
3285 return _CreateTypeNodeAndSkip("basic_ostream", "std",
3286 "char, std::char_traits<char>", 1, _node);
3287 case 'd':
3288 return _CreateTypeNodeAndSkip("basic_iostream", "std",
3289 "char, std::char_traits<char>", 1, _node);
3290 case '_':
3291 fInput.Skip(1);
3292 return _CreateSubstitutionNode(0, _node);
3293 }
3294
3295 // parse <seq-id>
3296 int seqID = 0;
3297 int count = fInput.CharsRemaining();
3298 int i = 0;
3299 for (; i < count && fInput[i] != '_'; i++) {
3300 char c = fInput[i];
3301 if (isdigit(c))
3302 seqID = seqID * 36 + (c - '0');
3303 else if (c >= 'A' && c <= 'Z')
3304 seqID = seqID * 36 + 10 + (c - 'A');
3305 else
3306 return _SetError(ERROR_INVALID);
3307 }
3308
3309 if (i == count)
3310 return _SetError(ERROR_INVALID);
3311
3312 // skip digits and '_'
3313 fInput.Skip(i + 1);
3314
3315 return _CreateSubstitutionNode(seqID + 1, _node);
3316 }
3317
3318
3319 bool
_ParseBareFunctionType(FunctionNode * node)3320 Demangler::_ParseBareFunctionType(FunctionNode* node)
3321 {
3322 DEBUG_SCOPE("_ParseBareFunctionType");
3323
3324 // <bare-function-type> ::= <signature type>+
3325 // # types are possible return type, then parameter types
3326
3327 if (fInput.CharsRemaining() == 0)
3328 return _SetError(ERROR_INVALID);
3329
3330 do {
3331 Node* typeNode;
3332 if (!_ParseType(typeNode))
3333 return false;
3334
3335 node->AddType(typeNode);
3336 } while (fInput.CharsRemaining() > 0 && fInput[0] != 'E'
3337 && fInput[0] != '.');
3338 // 'E' und '.' delimit <function-type>
3339
3340 return true;
3341 }
3342
3343
3344 bool
_ParseTemplateArgs(Node * node,Node * & _node)3345 Demangler::_ParseTemplateArgs(Node* node, Node*& _node)
3346 {
3347 DEBUG_SCOPE("_ParseTemplateArgs");
3348
3349 // <template-args> ::= I <template-arg>+ E
3350
3351 if (!_SkipExpected('I'))
3352 return false;
3353
3354 // we need at least one <template-arg>
3355 if (fInput.CharsRemaining() == 0 || fInput[0] == 'E')
3356 return _SetError(ERROR_INVALID);
3357
3358 // create the node
3359 TemplateNode* templateNode;
3360 if (!NodeCreator<TemplateNode>(this)(node, templateNode))
3361 return false;
3362 _node = templateNode;
3363
3364 // parse the args
3365 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3366 Node* arg;
3367 if (!_ParseTemplateArg(arg))
3368 return false;
3369 templateNode->AddArgument(arg);
3370 }
3371
3372 // skip the trailing 'E'
3373 return _SkipExpected('E');
3374 }
3375
3376
3377 bool
_ParseTemplateArg(Node * & _node)3378 Demangler::_ParseTemplateArg(Node*& _node)
3379 {
3380 DEBUG_SCOPE("_ParseTemplateArg");
3381
3382 // <template-arg> ::= <type> # type or template
3383 // ::= X <expression> E # expression
3384 // ::= <expr-primary> # simple expressions
3385 // ::= I <template-arg>* E # argument pack
3386 // ::= sp <expression> # pack expansion of (C++0x)
3387
3388 if (fInput.CharsRemaining() == 0)
3389 return _SetError(ERROR_INVALID);
3390
3391 switch (fInput[0]) {
3392 case 'X': // X <expression> E
3393 fInput.Skip(1);
3394 return _ParseExpression(_node) && _SkipExpected('E');
3395
3396 case 'L': // <expr-primary>
3397 return _ParseExpressionPrimary(_node);
3398
3399 case 'I': // I <template-arg>* E
3400 {
3401 #if 0
3402 fInput.Skip(1);
3403
3404 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3405 Node* arg;
3406 if (!_ParseTemplateArg(arg))
3407 return false;
3408 }
3409
3410 if (!fInput.SkipPrefix('E'))
3411 return _SetError(ERROR_INVALID);
3412 return true;
3413 #endif
3414 // NOTE: Unsupported by the GNU demangler.
3415 return _SetError(ERROR_UNSUPPORTED);
3416 }
3417
3418 case 's':
3419 if (fInput.SkipPrefix("sp")) {
3420 // sp <expression>
3421 #if 0
3422 return _ParseExpression(_node);
3423 #endif
3424 // NOTE: Unsupported by the GNU demangler.
3425 return _SetError(ERROR_UNSUPPORTED);
3426 }
3427
3428 // fall through...
3429
3430 default: // <type>
3431 return _ParseType(_node);
3432 }
3433 }
3434
3435
3436 bool
_ParseExpression(Node * & _node)3437 Demangler::_ParseExpression(Node*& _node)
3438 {
3439 DEBUG_SCOPE("_ParseExpression");
3440
3441 // <expression> ::= <unary operator-name> <expression>
3442 // ::= <binary operator-name> <expression> <expression>
3443 // ::= <trinary operator-name> <expression> <expression>
3444 // <expression>
3445 // ::= cl <expression>* E # call
3446 // ::= cv <type> expression # conversion with one
3447 // argument
3448 // ::= cv <type> _ <expression>* E # conversion with a
3449 // different number of
3450 // arguments
3451 // ::= st <type> # sizeof (a type)
3452 // ::= at <type> # alignof (a type)
3453 // ::= <template-param>
3454 // ::= <function-param>
3455 // ::= sr <type> <unqualified-name>
3456 // # dependent name
3457 // ::= sr <type> <unqualified-name> <template-args>
3458 // # dependent template-id
3459 // ::= sZ <template-param>
3460 // # size of a parameter pack
3461 // ::= <expr-primary>
3462 //
3463 // <expr-primary> ::= L <type> <value number> E # integer literal
3464 // ::= L <type <value float> E # floating literal
3465 // ::= L <mangled-name> E # external name
3466
3467 if (fInput.CharsRemaining() == 0)
3468 return _SetError(ERROR_INVALID);
3469
3470 switch (fInput[0]) {
3471 case 'L':
3472 return _ParseExpressionPrimary(_node);
3473 case 'T':
3474 return _ParseTemplateParam(_node);
3475 // NOTE: <function-param> is not defined in the specs!
3476 }
3477
3478 // must be an operator
3479 if (fInput.CharsRemaining() < 2)
3480 return _SetError(ERROR_INVALID);
3481
3482 // some operators need special handling
3483
3484 if (fInput.SkipPrefix("cl")) {
3485 // cl <expression>* E # call
3486 CallNode* callNode;
3487 if (!NodeCreator<CallNode>(this)(callNode))
3488 return false;
3489
3490 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3491 Node* subExpression;
3492 if (!_ParseExpression(subExpression))
3493 return false;
3494 callNode->AddSubExpression(subExpression);
3495 }
3496
3497 _node = callNode;
3498 return _SkipExpected('E');
3499 }
3500
3501 if (fInput.SkipPrefix("cv")) {
3502 // cv <type> expression # conversion with one argument
3503 // cv <type> _ <expression>* E # conversion with a different number
3504 // of arguments
3505
3506 // parse the type
3507 Node* type;
3508 if (!_ParseType(type))
3509 return false;
3510
3511 // create a conversion expression node
3512 ConversionExpressionNode* expression;
3513 if (!NodeCreator<ConversionExpressionNode>(this)(type, expression))
3514 return false;
3515 _node = expression;
3516
3517 if (fInput.SkipPrefix('_')) {
3518 // multi argument conversion
3519 while (fInput.CharsRemaining() > 0 && fInput[0] != 'E') {
3520 Node* subExpression;
3521 if (!_ParseExpression(subExpression))
3522 return false;
3523 expression->AddSubExpression(subExpression);
3524 }
3525
3526 return _SkipExpected('E');
3527 }
3528
3529 // single argument conversion
3530 Node* subExpression;
3531 if (!_ParseExpression(subExpression))
3532 return false;
3533 expression->AddSubExpression(subExpression);
3534
3535 return true;
3536 }
3537
3538 if (fInput.SkipPrefix("sr")) {
3539 // sr <type> <unqualified-name>
3540 // sr <type> <unqualified-name> <template-args>
3541
3542 // parse type and unqualified name and create the node
3543 Node* type;
3544 Node* name;
3545 if (!_ParseType(type) || !_ParseUnqualifiedName(name)
3546 || !NodeCreator<DependentNameNode>(this)(type, name, _node)) {
3547 return false;
3548 }
3549
3550 // If there are template arguments left, add them.
3551 if (!fInput.HasPrefix('I'))
3552 return true;
3553
3554 return _ParseTemplateArgs(_node, _node);
3555 }
3556
3557 if (fInput.SkipPrefix("sZ")) {
3558 // sZ <template-param>
3559
3560 // NOTE: Unsupported by the GNU demangler.
3561 return _SetError(ERROR_UNSUPPORTED);
3562 }
3563
3564 // no special operator, so have a look for the others
3565
3566 const operator_info* info = NULL;
3567 for (int i = 0; kOperatorInfos[i].name != NULL; i++) {
3568 if (fInput.SkipPrefix(kOperatorInfos[i].mangled_name)) {
3569 info = &kOperatorInfos[i];
3570 break;
3571 }
3572 }
3573
3574 // We can only deal with operators with a fixed argument count at this
3575 // point.
3576 if (info == NULL || info->argument_count < 0)
3577 return _SetError(ERROR_INVALID);
3578
3579 // create an operator node
3580 OperatorExpressionNode* operatorNode;
3581 if (!NodeCreator<OperatorExpressionNode>(this)(info, operatorNode))
3582 return false;
3583
3584 // parse the arguments
3585 int i = 0;
3586
3587 // the first one might be a type
3588 if ((info->flags & OPERATOR_TYPE_PARAM) != 0) {
3589 Node* type;
3590 if (!_ParseType(type))
3591 return false;
3592
3593 operatorNode->AddSubExpression(type);
3594 i++;
3595 }
3596
3597 // the others are expressions
3598 for (; i < info->argument_count; i++) {
3599 Node* subExpression;
3600 if (!_ParseExpression(subExpression))
3601 return false;
3602 operatorNode->AddSubExpression(subExpression);
3603 }
3604
3605 _node = operatorNode;
3606 return true;
3607 }
3608
3609
3610 bool
_ParseExpressionPrimary(Node * & _node)3611 Demangler::_ParseExpressionPrimary(Node*& _node)
3612 {
3613 DEBUG_SCOPE("_ParseExpressionPrimary");
3614
3615 // <expr-primary> ::= L <type> <value number> E # integer literal
3616 // ::= L <type <value float> E # floating literal
3617 // ::= L <mangled-name> E # external name
3618
3619 if (!_SkipExpected('L'))
3620 return false;
3621
3622 if (fInput.SkipPrefix("_Z")) {
3623 ObjectNode* node;
3624 if (!_ParseEncoding(node))
3625 return false;
3626 _node = node;
3627 } else {
3628 // number or float literal
3629 Node* type;
3630 if (!_ParseType(type))
3631 return false;
3632
3633 // GNU's demangler doesn't really seem to parse the integer/float,
3634 // but only replaces a leading 'n' by '-'. Good enough for us, too.
3635
3636 // determine the length
3637 int maxLength = fInput.CharsRemaining();
3638 int length = 0;
3639 while (length < maxLength && fInput[length] != 'E')
3640 length++;
3641
3642 if (length == 0)
3643 return _SetError(ERROR_INVALID);
3644
3645 if (!NodeCreator<TypedNumberLiteralNode>(this)(type,
3646 fInput.String(), length, _node)) {
3647 return false;
3648 }
3649
3650 fInput.Skip(length);
3651 }
3652
3653 return _SkipExpected('E');
3654 }
3655
3656
3657 bool
_ParseNumber(number_type & number)3658 Demangler::_ParseNumber(number_type& number)
3659 {
3660 DEBUG_SCOPE("_ParseNumber");
3661
3662 bool negative = fInput.SkipPrefix('n');
3663
3664 if (fInput.CharsRemaining() == 0)
3665 return _SetError(ERROR_INVALID);
3666
3667 number = 0;
3668 int count = fInput.CharsRemaining();
3669 int i = 0;
3670 for (; i < count && isdigit(fInput[i]); i++)
3671 number = number * 10 + (fInput[i] - '0');
3672
3673 fInput.Skip(i);
3674
3675 if (negative)
3676 number =-number;
3677 return true;
3678 }
3679
3680
3681 bool
_CreateNodeAndSkip(const char * name,size_t length,int toSkip,Node * & _node)3682 Demangler::_CreateNodeAndSkip(const char* name, size_t length, int toSkip,
3683 Node*& _node)
3684 {
3685 if (toSkip > 0)
3686 fInput.Skip(toSkip);
3687
3688 return NodeCreator<SimpleNameNode>(this)(name, length, _node);
3689 }
3690
3691
3692 bool
_CreateNodeAndSkip(const char * name,int toSkip,Node * & _node)3693 Demangler::_CreateNodeAndSkip(const char* name, int toSkip, Node*& _node)
3694 {
3695 return _CreateNodeAndSkip(name, strlen(name), toSkip, _node);
3696 }
3697
3698
3699 bool
_CreateTypeNodeAndSkip(type_type type,int toSkip,Node * & _node)3700 Demangler::_CreateTypeNodeAndSkip(type_type type, int toSkip, Node*& _node)
3701 {
3702 if (toSkip > 0)
3703 fInput.Skip(toSkip);
3704
3705 return NodeCreator<SimpleTypeNode>(this)(type, _node);
3706 }
3707
3708
3709 bool
_CreateTypeNodeAndSkip(const char * name,const char * prefix,const char * templateArgs,int toSkip,Node * & _node)3710 Demangler::_CreateTypeNodeAndSkip(const char* name, const char* prefix,
3711 const char* templateArgs, int toSkip, Node*& _node)
3712 {
3713 if (toSkip > 0)
3714 fInput.Skip(toSkip);
3715
3716 // create the name node
3717 if (!NodeCreator<SimpleTypeNode>(this)(name, _node))
3718 return false;
3719
3720 // add the prefix
3721 if (prefix != NULL) {
3722 Node* prefixNode;
3723 if (!NodeCreator<SimpleTypeNode>(this)(prefix, prefixNode)
3724 || !NodeCreator<PrefixedNode>(this)(prefixNode, _node, _node)) {
3725 return false;
3726 }
3727 }
3728
3729 // wrap the node to add the template args
3730 if (templateArgs != NULL) {
3731 TemplateNode* templateNode;
3732 Node* argsNode;
3733 if (!NodeCreator<TemplateNode>(this)(_node, templateNode)
3734 || !NodeCreator<SimpleTypeNode>(this)(templateArgs, argsNode)) {
3735 return false;
3736 }
3737 templateNode->AddArgument(argsNode);
3738 _node = templateNode;
3739 }
3740
3741 return true;
3742 }
3743
3744
3745 void
_RegisterReferenceableNode(Node * node)3746 Demangler::_RegisterReferenceableNode(Node* node)
3747 {
3748 // check, if not referenceable or already registered
3749 if (!node->IsReferenceable() || node == fLastReferenceableNode
3750 || node->NextReferenceable() != NULL) {
3751 return;
3752 }
3753
3754 if (fFirstReferenceableNode == NULL) {
3755 fFirstReferenceableNode = node;
3756 fLastReferenceableNode = node;
3757 } else {
3758 fLastReferenceableNode->SetNextReferenceable(node);
3759 fLastReferenceableNode = node;
3760 }
3761 }
3762
3763
3764 bool
_CreateSubstitutionNode(int index,Node * & _node)3765 Demangler::_CreateSubstitutionNode(int index, Node*& _node)
3766 {
3767 Node* node = fFirstReferenceableNode;
3768 while (node != NULL && index > 0) {
3769 node = node->NextReferenceable();
3770 index--;
3771 }
3772
3773 if (node == NULL)
3774 return _SetError(ERROR_INVALID);
3775
3776 // create a substitution node
3777 return NodeCreator<SubstitutionNode>(this)(node, _node);
3778 }
3779
3780
3781 // #pragma mark -
3782
3783
3784 const char*
demangle_symbol_gcc3(const char * mangledName,char * buffer,size_t bufferSize,bool * _isObjectMethod)3785 demangle_symbol_gcc3(const char* mangledName, char* buffer, size_t bufferSize,
3786 bool* _isObjectMethod)
3787 {
3788 bool isObjectMethod;
3789 if (_isObjectMethod == NULL)
3790 _isObjectMethod = &isObjectMethod;
3791
3792 Demangler demangler;
3793 DemanglingInfo info(true);
3794 if (demangler.Demangle(mangledName, buffer, bufferSize, info) != ERROR_OK)
3795 return NULL;
3796
3797 // Set the object method return value. Unless we know for sure that it isn't
3798 // an object method, we assume that it is.
3799 switch (info.objectType) {
3800 case OBJECT_TYPE_DATA:
3801 case OBJECT_TYPE_FUNCTION:
3802 case OBJECT_TYPE_METHOD_CLASS:
3803 *_isObjectMethod = false;
3804 break;
3805 case OBJECT_TYPE_METHOD_OBJECT:
3806 *_isObjectMethod = true;
3807 break;
3808 case OBJECT_TYPE_UNKNOWN:
3809 case OBJECT_TYPE_METHOD_UNKNOWN:
3810 *_isObjectMethod = strstr(buffer, "::") != NULL;
3811 break;
3812 }
3813
3814 return buffer;
3815 }
3816
3817
3818 status_t
get_next_argument_gcc3(uint32 * _cookie,const char * mangledName,char * name,size_t nameSize,int32 * _type,size_t * _argumentLength)3819 get_next_argument_gcc3(uint32* _cookie, const char* mangledName, char* name,
3820 size_t nameSize, int32* _type, size_t* _argumentLength)
3821 {
3822 Demangler demangler;
3823 ParameterInfo info;
3824 int result = demangler.GetParameterInfo(mangledName, *_cookie, name,
3825 nameSize, info);
3826 if (result != ERROR_OK) {
3827 switch (result) {
3828 case ERROR_NOT_MANGLED:
3829 return B_BAD_VALUE;
3830 case ERROR_UNSUPPORTED:
3831 return B_BAD_VALUE;
3832 case ERROR_INVALID:
3833 return B_BAD_VALUE;
3834 case ERROR_BUFFER_TOO_SMALL:
3835 return B_BUFFER_OVERFLOW;
3836 case ERROR_NO_MEMORY:
3837 return B_NO_MEMORY;
3838 case ERROR_INVALID_PARAMETER_INDEX:
3839 return B_BAD_INDEX;
3840 case ERROR_INTERNAL:
3841 default:
3842 return B_ERROR;
3843 }
3844 }
3845
3846 // translate the type
3847 switch (info.type.type) {
3848 case TYPE_BOOL:
3849 *_type = B_BOOL_TYPE;
3850 *_argumentLength = 1;
3851 break;
3852
3853 case TYPE_CHAR:
3854 *_type = B_CHAR_TYPE;
3855 *_argumentLength = 1;
3856 break;
3857
3858 case TYPE_SIGNED_CHAR:
3859 *_type = B_INT8_TYPE;
3860 *_argumentLength = 1;
3861 break;
3862 case TYPE_UNSIGNED_CHAR:
3863 *_type = B_UINT8_TYPE;
3864 *_argumentLength = 1;
3865 break;
3866
3867 case TYPE_SHORT:
3868 *_type = B_INT16_TYPE;
3869 *_argumentLength = 2;
3870 break;
3871 case TYPE_UNSIGNED_SHORT:
3872 *_type = B_UINT16_TYPE;
3873 *_argumentLength = 2;
3874 break;
3875
3876 case TYPE_INT:
3877 *_type = B_INT32_TYPE;
3878 *_argumentLength = 4;
3879 break;
3880 case TYPE_UNSIGNED_INT:
3881 *_type = B_UINT32_TYPE;
3882 *_argumentLength = 4;
3883 break;
3884
3885 case TYPE_LONG:
3886 *_type = sizeof(long) == 4 ? B_INT32_TYPE : B_INT64_TYPE;
3887 *_argumentLength = sizeof(long);
3888 break;
3889 case TYPE_UNSIGNED_LONG:
3890 *_type = sizeof(long) == 4 ? B_UINT32_TYPE : B_UINT64_TYPE;
3891 *_argumentLength = sizeof(long);
3892 break;
3893
3894 case TYPE_LONG_LONG:
3895 *_type = B_INT64_TYPE;
3896 *_argumentLength = 8;
3897 break;
3898 case TYPE_UNSIGNED_LONG_LONG:
3899 *_type = B_INT64_TYPE;
3900 *_argumentLength = 8;
3901 break;
3902
3903 case TYPE_INT128:
3904 *_type = 0;
3905 *_argumentLength = 16;
3906 break;
3907 case TYPE_UNSIGNED_INT128:
3908 *_type = 0;
3909 *_argumentLength = 16;
3910 break;
3911
3912 case TYPE_FLOAT:
3913 *_type = B_FLOAT_TYPE;
3914 *_argumentLength = sizeof(float);
3915 break;
3916 case TYPE_DOUBLE:
3917 *_type = B_DOUBLE_TYPE;
3918 *_argumentLength = sizeof(double);
3919 break;
3920
3921 case TYPE_LONG_DOUBLE:
3922 *_type = 0;
3923 *_argumentLength = sizeof(long double);
3924 break;
3925
3926 case TYPE_FLOAT128:
3927 *_type = 0;
3928 *_argumentLength = 16;
3929 break;
3930
3931 case TYPE_DFLOAT16:
3932 *_argumentLength = 2;
3933 case TYPE_DFLOAT32:
3934 *_argumentLength *= 2;
3935 case TYPE_DFLOAT64:
3936 *_argumentLength *= 2;
3937 case TYPE_DFLOAT128:
3938 *_argumentLength *= 2;
3939 *_type = 0;
3940 break;
3941
3942 case TYPE_CHAR16_T:
3943 *_type = B_UINT16_TYPE;
3944 *_argumentLength = 2;
3945 break;
3946
3947 case TYPE_CHAR32_T:
3948 *_type = B_UINT32_TYPE;
3949 *_argumentLength = 2;
3950 break;
3951
3952 case TYPE_CONST_CHAR_POINTER:
3953 *_type = B_STRING_TYPE;
3954 *_argumentLength = sizeof(void*);
3955 break;
3956
3957 case TYPE_POINTER:
3958 *_type = B_POINTER_TYPE;
3959 *_argumentLength = sizeof(void*);
3960 break;
3961
3962 case TYPE_REFERENCE:
3963 *_type = B_REF_TYPE;
3964 // TODO: That's actually entry_ref!
3965 *_argumentLength = sizeof(void*);
3966 break;
3967
3968 case TYPE_WCHAR_T:
3969 // TODO: Type/size might change!
3970 *_type = B_UINT16_TYPE;
3971 *_argumentLength = 2;
3972 break;
3973
3974 case TYPE_UNKNOWN:
3975 case TYPE_ELLIPSIS:
3976 case TYPE_VOID:
3977 default:
3978 // Well, tell our caller *something*.
3979 *_type = 0;
3980 *_argumentLength = sizeof(int);
3981 }
3982
3983 // assume sizeof(int) argument alignment
3984 if (*_argumentLength < sizeof(int))
3985 *_argumentLength = sizeof(int);
3986
3987 ++*_cookie;
3988 return B_OK;
3989 }
3990
3991
3992 #ifndef _KERNEL_MODE
3993
3994 const char*
demangle_name_gcc3(const char * mangledName,char * buffer,size_t bufferSize)3995 demangle_name_gcc3(const char* mangledName, char* buffer, size_t bufferSize)
3996 {
3997 Demangler demangler;
3998 DemanglingInfo info(false);
3999 if (demangler.Demangle(mangledName, buffer, bufferSize, info) != ERROR_OK)
4000 return NULL;
4001 return buffer;
4002 }
4003
4004 #endif
4005