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