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