diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs index 885fbee631..435789e0f2 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArraySubscriptingExpression.cs @@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public ArraySubscriptingExpression(BaseNode LeftNode, BaseNode Subscript) : base(NodeType.ArraySubscriptingExpression) { - this.LeftNode = LeftNode; + this.LeftNode = LeftNode; this.Subscript = Subscript; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs index 430832773e..1679736072 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ArrayType.cs @@ -6,17 +6,17 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { private BaseNode Base; private BaseNode DimensionExpression; - private string DimensionString; + private string DimensionString; public ArrayType(BaseNode Base, BaseNode DimensionExpression = null) : base(NodeType.ArrayType) { - this.Base = Base; + this.Base = Base; this.DimensionExpression = DimensionExpression; } public ArrayType(BaseNode Base, string DimensionString) : base(NodeType.ArrayType) { - this.Base = Base; + this.Base = Base; this.DimensionString = DimensionString; } @@ -39,14 +39,21 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { // FIXME: detect if previous char was a ]. Writer.Write(" "); - Writer.Write("["); - if (DimensionString != null) - Writer.Write(DimensionString); - else if (DimensionExpression != null) - DimensionExpression.Print(Writer); - Writer.Write("]"); - Base.PrintRight(Writer); + Writer.Write("["); + + if (DimensionString != null) + { + Writer.Write(DimensionString); + } + else if (DimensionExpression != null) + { + DimensionExpression.Print(Writer); + } + + Writer.Write("]"); + + Base.PrintRight(Writer); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs index b13c663dd9..870758462e 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BaseNode.cs @@ -70,8 +70,11 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public virtual void Print(TextWriter Writer) { PrintLeft(Writer); + if (HasRightPart()) + { PrintRight(Writer); + } } public abstract void PrintLeft(TextWriter Writer); @@ -101,7 +104,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override string ToString() { StringWriter Writer = new StringWriter(); + Print(Writer); + return Writer.ToString(); } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs index 227f577e2d..9cd1dd779a 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BinaryExpression.cs @@ -5,32 +5,37 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class BinaryExpression : BaseNode { private BaseNode LeftPart; - private string Name; + private string Name; private BaseNode RightPart; public BinaryExpression(BaseNode LeftPart, string Name, BaseNode RightPart) : base(NodeType.BinaryExpression) { - this.LeftPart = LeftPart; - this.Name = Name; + this.LeftPart = LeftPart; + this.Name = Name; this.RightPart = RightPart; } public override void PrintLeft(TextWriter Writer) { if (Name.Equals(">")) + { Writer.Write("("); + } Writer.Write("("); LeftPart.Print(Writer); Writer.Write(") "); + Writer.Write(Name); + Writer.Write(" ("); RightPart.Print(Writer); Writer.Write(")"); - if (Name.Equals(">")) + { Writer.Write(")"); + } } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs index fc14df46c9..0421cb07cc 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedExpression.cs @@ -6,12 +6,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { private BaseNode Element; private BaseNode Expression; - private bool IsArrayExpression; + private bool IsArrayExpression; public BracedExpression(BaseNode Element, BaseNode Expression, bool IsArrayExpression) : base(NodeType.BracedExpression) { - this.Element = Element; - this.Expression = Expression; + this.Element = Element; + this.Expression = Expression; this.IsArrayExpression = IsArrayExpression; } @@ -33,7 +33,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { Writer.Write(" = "); } + Expression.Print(Writer); + } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs index 5fc7b4d615..e9a3ba9e2e 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/BracedRangeExpression.cs @@ -10,8 +10,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public BracedRangeExpression(BaseNode FirstNode, BaseNode LastNode, BaseNode Expression) : base(NodeType.BracedRangeExpression) { - this.FirstNode = FirstNode; - this.LastNode = LastNode; + this.FirstNode = FirstNode; + this.LastNode = LastNode; this.Expression = Expression; } @@ -27,6 +27,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { Writer.Write(" = "); } + Expression.Print(Writer); } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs index 9c1ae569e7..7e59ab09df 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CallExpression.cs @@ -16,6 +16,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintLeft(TextWriter Writer) { Callee.Print(Writer); + Writer.Write("("); Writer.Write(string.Join(", ", Nodes.ToArray())); Writer.Write(")"); diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CasExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CasExpression.cs index 10e8420148..2415c6c000 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CasExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CasExpression.cs @@ -6,14 +6,14 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class CastExpression : BaseNode { - private string Kind; + private string Kind; private BaseNode To; private BaseNode From; public CastExpression(string Kind, BaseNode To, BaseNode From) : base(NodeType.CastExpression) { this.Kind = Kind; - this.To = To; + this.To = To; this.From = From; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs index 49ddcba445..17ac7c1a20 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConditionalExpression.cs @@ -10,9 +10,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public ConditionalExpression(BaseNode ConditionNode, BaseNode ThenNode, BaseNode ElseNode) : base(NodeType.ConditionalExpression) { - this.ThenNode = ThenNode; + this.ThenNode = ThenNode; this.ConditionNode = ConditionNode; - this.ElseNode = ElseNode; + this.ElseNode = ElseNode; } public override void PrintLeft(TextWriter Writer) diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs index ea453b9e35..7c5d35d810 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionExpression.cs @@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public ConversionExpression(BaseNode TypeNode, BaseNode Expressions) : base(NodeType.ConversionExpression) { - this.TypeNode = TypeNode; + this.TypeNode = TypeNode; this.Expressions = Expressions; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs index ff564d0f4f..55d4eecab9 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ConversionOperatorType.cs @@ -4,10 +4,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class ConversionOperatorType : ParentNode { - public ConversionOperatorType(BaseNode Child) : base(NodeType.ConversionOperatorType, Child) - { - - } + public ConversionOperatorType(BaseNode Child) : base(NodeType.ConversionOperatorType, Child) { } public override void PrintLeft(TextWriter Writer) { diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs index b6fe47c302..49ed386d08 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorDtorNameType.cs @@ -4,7 +4,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class CtorDtorNameType : ParentNode { - bool IsDestructor; + private bool IsDestructor; + public CtorDtorNameType(BaseNode Name, bool IsDestructor) : base(NodeType.CtorDtorNameType, Name) { this.IsDestructor = IsDestructor; @@ -13,7 +14,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintLeft(TextWriter Writer) { if (IsDestructor) + { Writer.Write("~"); + } + Writer.Write(Child.GetName()); } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs index 8914de684b..7630dbe570 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/CtorVtableSpecialName.cs @@ -9,7 +9,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public CtorVtableSpecialName(BaseNode FirstType, BaseNode SecondType) : base(NodeType.CtorVtableSpecialName) { - this.FirstType = FirstType; + this.FirstType = FirstType; this.SecondType = SecondType; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs index e89c6399b5..22c34c4219 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DeleteExpression.cs @@ -9,17 +9,24 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public DeleteExpression(BaseNode Child, bool IsGlobal, bool IsArrayExpression) : base(NodeType.DeleteExpression, Child) { - this.IsGlobal = IsGlobal; + this.IsGlobal = IsGlobal; this.IsArrayExpression = IsArrayExpression; } public override void PrintLeft(TextWriter Writer) { if (IsGlobal) + { Writer.Write("::"); + } + Writer.Write("delete"); + if (IsArrayExpression) + { Writer.Write("[] "); + } + Child.Print(Writer); } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs index 0f171a2188..c65c4cfb3a 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DtorName.cs @@ -4,9 +4,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class DtorName : ParentNode { - public DtorName(BaseNode Name) : base(NodeType.DtOrName, Name) - { - } + public DtorName(BaseNode Name) : base(NodeType.DtOrName, Name) { } public override void PrintLeft(TextWriter Writer) { diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs index 63ebe5cf2f..dca5f0dfd0 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/DynamicExceptionSpec.cs @@ -4,9 +4,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class DynamicExceptionSpec : ParentNode { - public DynamicExceptionSpec(BaseNode Child) : base(NodeType.DynamicExceptionSpec, Child) - { - } + public DynamicExceptionSpec(BaseNode Child) : base(NodeType.DynamicExceptionSpec, Child) { } public override void PrintLeft(TextWriter Writer) { diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs index 59c09ae0a7..11f89c8d33 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ElaboratedType.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class ElaboratedType : ParentNode { private string Elaborated; + public ElaboratedType(string Elaborated, BaseNode Type) : base(NodeType.ElaboratedType, Type) { this.Elaborated = Elaborated; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs index 4670d050e8..dc991aa09c 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EnclosedExpression.cs @@ -4,15 +4,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class EnclosedExpression : BaseNode { - private string Prefix; + private string Prefix; private BaseNode Expression; - private string Postfix; + private string Postfix; public EnclosedExpression(string Prefix, BaseNode Expression, string Postfix) : base(NodeType.EnclosedExpression) { - this.Prefix = Prefix; + this.Prefix = Prefix; this.Expression = Expression; - this.Postfix = Postfix; + this.Postfix = Postfix; } public override void PrintLeft(TextWriter Writer) diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs index c370f941f1..37a9a7afe0 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/EncodedFunction.cs @@ -10,14 +10,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast private BaseNode Ref; private BaseNode Attrs; private BaseNode Ret; + public EncodedFunction(BaseNode Name, BaseNode Params, BaseNode CV, BaseNode Ref, BaseNode Attrs, BaseNode Ret) : base(NodeType.NameType) { - this.Name = Name; + this.Name = Name; this.Params = Params; - this.CV = CV; - this.Ref = Ref; - this.Attrs = Attrs; - this.Ret = Ret; + this.CV = CV; + this.Ref = Ref; + this.Attrs = Attrs; + this.Ret = Ret; } public override void PrintLeft(TextWriter Writer) @@ -25,10 +26,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast if (Ret != null) { Ret.PrintLeft(Writer); + if (!Ret.HasRightPart()) + { Writer.Write(" "); + } } + Name.Print(Writer); + } public override bool HasRightPart() @@ -39,21 +45,33 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintRight(TextWriter Writer) { Writer.Write("("); + if (Params != null) + { Params.Print(Writer); + } + Writer.Write(")"); if (Ret != null) + { Ret.PrintRight(Writer); - + } + if (CV != null) + { CV.Print(Writer); + } if (Ref != null) + { Ref.Print(Writer); + } if (Attrs != null) + { Attrs.Print(Writer); + } } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs index 0c76c9b706..e015299846 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FoldExpression.cs @@ -4,18 +4,17 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class FoldExpression : BaseNode { - private bool IsLeftFold; - - private string OperatorName; + private bool IsLeftFold; + private string OperatorName; private BaseNode Expression; private BaseNode Initializer; public FoldExpression(bool IsLeftFold, string OperatorName, BaseNode Expression, BaseNode Initializer) : base(NodeType.FunctionParameter) { - this.IsLeftFold = IsLeftFold; + this.IsLeftFold = IsLeftFold; this.OperatorName = OperatorName; - this.Expression = Expression; - this.Initializer = Initializer; + this.Expression = Expression; + this.Initializer = Initializer; } public override void PrintLeft(TextWriter Writer) diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs index 47604b74c2..bc7d21fd09 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ForwardTemplateReference.cs @@ -4,11 +4,11 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class ForwardTemplateReference : BaseNode { - private int Index; - - // TOOD: Compute inside the Demangler + // TODO: Compute inside the Demangler public BaseNode Reference; + private int Index; + public ForwardTemplateReference(int Index) : base(NodeType.ForwardTemplateReference) { this.Index = Index; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs index 02b8209f72..5a1ca61d55 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionParameter.cs @@ -14,8 +14,11 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintLeft(TextWriter Writer) { Writer.Write("fp "); + if (Number != null) + { Writer.Write(Number); + } } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs index 2a41ef0c03..c727eab9c5 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/FunctionType.cs @@ -4,18 +4,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class FunctionType : BaseNode { - private BaseNode ReturnType; - private BaseNode Params; - private BaseNode CVQualifier; + private BaseNode ReturnType; + private BaseNode Params; + private BaseNode CVQualifier; private SimpleReferenceType ReferenceQualifier; - private BaseNode ExceptionSpec; + private BaseNode ExceptionSpec; + public FunctionType(BaseNode ReturnType, BaseNode Params, BaseNode CVQualifier, SimpleReferenceType ReferenceQualifier, BaseNode ExceptionSpec) : base(NodeType.FunctionType) { - this.ReturnType = ReturnType; - this.Params = Params; - this.CVQualifier = CVQualifier; + this.ReturnType = ReturnType; + this.Params = Params; + this.CVQualifier = CVQualifier; this.ReferenceQualifier = ReferenceQualifier; - this.ExceptionSpec = ExceptionSpec; + this.ExceptionSpec = ExceptionSpec; } public override void PrintLeft(TextWriter Writer) @@ -29,8 +30,11 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast Writer.Write("("); Params.Print(Writer); Writer.Write(")"); + ReturnType.PrintRight(Writer); + CVQualifier.Print(Writer); + if (ReferenceQualifier.Qualifier != Reference.None) { Writer.Write(" "); diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs index 9b286d5427..cd534590b9 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/InitListExpression.cs @@ -6,19 +6,22 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class InitListExpression : BaseNode { - private BaseNode TypeNode; + private BaseNode TypeNode; private List Nodes; public InitListExpression(BaseNode TypeNode, List Nodes) : base(NodeType.InitListExpression) { this.TypeNode = TypeNode; - this.Nodes = Nodes; + this.Nodes = Nodes; } public override void PrintLeft(TextWriter Writer) { if (TypeNode != null) + { TypeNode.Print(Writer); + } + Writer.Write("{"); Writer.Write(string.Join(", ", Nodes.ToArray())); Writer.Write("}"); diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs index 197f6f153b..984c9aefb0 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerCastExpression.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class IntegerCastExpression : ParentNode { private string Number; + public IntegerCastExpression(BaseNode Type, string Number) : base(NodeType.IntegerCastExpression, Type) { this.Number = Number; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs index ec9219387f..215cf6dce5 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/IntegerLiteral.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public IntegerLiteral(string LitteralName, string LitteralValue) : base(NodeType.IntegerLiteral) { this.LitteralValue = LitteralValue; - this.LitteralName = LitteralName; + this.LitteralName = LitteralName; } public override void PrintLeft(TextWriter Writer) diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs index f2f40488ce..f9bd4a6ef5 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LiteralOperator.cs @@ -4,10 +4,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class LiteralOperator : ParentNode { - public LiteralOperator(BaseNode Child) : base(NodeType.LiteralOperator, Child) - { - - } + public LiteralOperator(BaseNode Child) : base(NodeType.LiteralOperator, Child) { } public override void PrintLeft(TextWriter Writer) { diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs index 06be9e9fee..44c216289c 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/LocalName.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public LocalName(BaseNode Encoding, BaseNode Entity) : base(NodeType.LocalName) { this.Encoding = Encoding; - this.Entity = Entity; + this.Entity = Entity; } public override void PrintLeft(TextWriter Writer) diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs index 49871b8414..dd3d02dbd1 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/MemberExpression.cs @@ -5,14 +5,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class MemberExpression : BaseNode { private BaseNode LeftNode; + private string Kind; private BaseNode RightNode; - private string Kind; - public MemberExpression(BaseNode LeftNode, string Kind, BaseNode RightNode) : base(NodeType.MemberExpression) { - this.LeftNode = LeftNode; - this.Kind = Kind; + this.LeftNode = LeftNode; + this.Kind = Kind; this.RightNode = RightNode; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs index d858779526..029440cb77 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameType.cs @@ -10,6 +10,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { this.NameValue = NameValue; } + public NameType(string NameValue) : base(NodeType.NameType) { this.NameValue = NameValue; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs index 3c2ecbe828..e16bd1508b 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NameTypeWithTemplateArguments.cs @@ -6,9 +6,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { private BaseNode Prev; private BaseNode TemplateArgument; + public NameTypeWithTemplateArguments(BaseNode Prev, BaseNode TemplateArgument) : base(NodeType.NameTypeWithTemplateArguments) { - this.Prev = Prev; + this.Prev = Prev; this.TemplateArgument = TemplateArgument; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs index cc6e72dbc3..0ec6d98299 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NestedName.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class NestedName : ParentNode { private BaseNode Name; + public NestedName(BaseNode Name, BaseNode Type) : base(NodeType.NestedName, Type) { this.Name = Name; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs index 16b96c00cd..5cc14ad9f8 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/NewExpression.cs @@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class NewExpression : BaseNode { private NodeArray Expressions; - private BaseNode TypeNode; + private BaseNode TypeNode; private NodeArray Initializers; private bool IsGlobal; @@ -13,21 +13,27 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public NewExpression(NodeArray Expressions, BaseNode TypeNode, NodeArray Initializers, bool IsGlobal, bool IsArrayExpression) : base(NodeType.NewExpression) { - this.Expressions = Expressions; - this.TypeNode = TypeNode; - this.Initializers = Initializers; - this.IsGlobal = IsGlobal; + this.Expressions = Expressions; + this.TypeNode = TypeNode; + this.Initializers = Initializers; + + this.IsGlobal = IsGlobal; this.IsArrayExpression = IsArrayExpression; } public override void PrintLeft(TextWriter Writer) { if (IsGlobal) + { Writer.Write("::operator "); - + } + Writer.Write("new "); + if (IsArrayExpression) + { Writer.Write("[] "); + } if (Expressions.Nodes.Count != 0) { diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs index f285c6d064..66ad112277 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameter.cs @@ -5,10 +5,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class PackedTemplateParameter : NodeArray { - public PackedTemplateParameter(List Nodes) : base(Nodes, NodeType.PackedTemplateParameter) - { + public PackedTemplateParameter(List Nodes) : base(Nodes, NodeType.PackedTemplateParameter) { } - } public override void PrintLeft(TextWriter Writer) { foreach (BaseNode Node in Nodes) @@ -34,6 +32,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast return true; } } + return false; } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs index 7aba6c056b..ce9fa4a3ba 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PackedTemplateParameterExpansion.cs @@ -4,10 +4,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class PackedTemplateParameterExpansion : ParentNode { - public PackedTemplateParameterExpansion(BaseNode Child) : base(NodeType.PackedTemplateParameterExpansion, Child) - { - - } + public PackedTemplateParameterExpansion(BaseNode Child) : base(NodeType.PackedTemplateParameterExpansion, Child) {} public override void PrintLeft(TextWriter Writer) { diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs index 14463e7507..f1c2834739 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ParentNode.cs @@ -3,6 +3,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public abstract class ParentNode : BaseNode { public BaseNode Child { get; private set; } + public ParentNode(NodeType Type, BaseNode Child) : base(Type) { this.Child = Child; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs index 93066d9751..a60776a272 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PointerType.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class PointerType : BaseNode { private BaseNode Child; + public PointerType(BaseNode Child) : base(NodeType.PointerType) { this.Child = Child; @@ -19,15 +20,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { Child.PrintLeft(Writer); if (Child.IsArray()) + { Writer.Write(" "); + } + if (Child.IsArray() || Child.HasFunctions()) + { Writer.Write("("); + } + Writer.Write("*"); } + public override void PrintRight(TextWriter Writer) { if (Child.IsArray() || Child.HasFunctions()) + { Writer.Write(")"); + } + Child.PrintRight(Writer); } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs index 35b8b40c00..021f2de820 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixExpression.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class PostfixExpression : ParentNode { private string Operator; + public PostfixExpression(BaseNode Type, string Operator) : base(NodeType.PostfixExpression, Type) { this.Operator = Operator; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs index b8767ffa37..465450d3f2 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/PostfixQualifiedType.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class PostfixQualifiedType : ParentNode { private string PostfixQualifier; + public PostfixQualifiedType(string PostfixQualifier, BaseNode Type) : base(NodeType.PostfixQualifiedType, Type) { this.PostfixQualifier = PostfixQualifier; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs index 7c720ee00c..ce356e1628 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/QualifiedName.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public QualifiedName(BaseNode Qualifier, BaseNode Name) : base(NodeType.QualifiedName) { this.Qualifier = Qualifier; - this.Name = Name; + this.Name = Name; } public override void PrintLeft(TextWriter Writer) diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs index 502062dc8b..3721b8dee3 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/Qualifier.cs @@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast Const, Volatile, Restricted = 4 - }; + } public enum Reference { @@ -32,10 +32,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { Writer.Write(" const"); } + if ((Qualifier & CV.Volatile) != 0) { Writer.Write(" volatile"); } + if ((Qualifier & CV.Restricted) != 0) { Writer.Write(" restrict"); @@ -45,7 +47,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintLeft(TextWriter Writer) { if (Child != null) + { Child.PrintLeft(Writer); + } + PrintQualifier(Writer); } @@ -57,7 +62,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintRight(TextWriter Writer) { if (Child != null) + { Child.PrintRight(Writer); + } } } @@ -76,6 +83,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { Writer.Write("&"); } + if ((Qualifier & Reference.RValue) != 0) { Writer.Write("&&"); @@ -85,9 +93,14 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintLeft(TextWriter Writer) { if (Child != null) + { Child.PrintLeft(Writer); + } else if (Qualifier != Reference.None) + { Writer.Write(" "); + } + PrintQualifier(Writer); } @@ -99,7 +112,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintRight(TextWriter Writer) { if (Child != null) + { Child.PrintRight(Writer); + } } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs index a9b25f9b2d..602814afb3 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/ReferenceType.cs @@ -4,13 +4,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class ReferenceType : BaseNode { - private string Reference; + private string Reference; private BaseNode Child; public ReferenceType(string Reference, BaseNode Child) : base(NodeType.ReferenceType) { this.Reference = Reference; - this.Child = Child; + this.Child = Child; } public override bool HasRightPart() @@ -21,16 +21,26 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public override void PrintLeft(TextWriter Writer) { Child.PrintLeft(Writer); + if (Child.IsArray()) + { Writer.Write(" "); + } + if (Child.IsArray() || Child.HasFunctions()) + { Writer.Write("("); + } + Writer.Write(Reference); } public override void PrintRight(TextWriter Writer) { if (Child.IsArray() || Child.HasFunctions()) + { Writer.Write(")"); + } + Child.PrintRight(Writer); } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs index 6cabe47f9d..1a299af4d2 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialName.cs @@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast public class SpecialName : ParentNode { private string SpecialValue; + public SpecialName(string SpecialValue, BaseNode Type) : base(NodeType.SpecialName, Type) { this.SpecialValue = SpecialValue; diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs index c8bc941060..f4e9a14a12 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/SpecialSubstitution.cs @@ -12,8 +12,8 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast IStream, OStream, IOStream, - } + private SpecialType SpecialSubstitutionKey; public SpecialSubstitution(SpecialType SpecialSubstitutionKey) : base(NodeType.SpecialSubstitution) @@ -36,7 +36,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast return "basic_string"; case SpecialType.String: if (Type == NodeType.ExpandedSpecialSubstitution) + { return "basic_string"; + } + return "string"; case SpecialType.IStream: return "istream"; @@ -45,6 +48,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast case SpecialType.IOStream: return "iostream"; } + return null; } @@ -65,6 +69,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast case SpecialType.IOStream: return "std::basic_iostream >"; } + return null; } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs index 433f6b38ff..27ef1a11af 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Ast/TemplateArguments.cs @@ -6,17 +6,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler.Ast { public class TemplateArguments : NodeArray { - public TemplateArguments(List Nodes) : base(Nodes, NodeType.TemplateArguments) - { - - } + public TemplateArguments(List Nodes) : base(Nodes, NodeType.TemplateArguments) { } public override void PrintLeft(TextWriter Writer) { string Params = string.Join(", ", Nodes.ToArray()); + Writer.Write("<"); + Writer.Write(Params); + if (Params.EndsWith(">")) + { Writer.Write(" "); + } + Writer.Write(">"); } } diff --git a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs index 67feaf00b9..d8e6135be2 100644 --- a/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs +++ b/Ryujinx.HLE/HOS/Diagnostics/Demangler/Demangler.cs @@ -8,32 +8,36 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { class Demangler { - private static readonly string BASE_36 = "0123456789abcdefghijklmnopqrstuvwxyz"; - private List SubstitutionList = new List(); + private static readonly string BASE_36 = "0123456789abcdefghijklmnopqrstuvwxyz"; + private List SubstitutionList = new List(); private List TemplateParamList = new List(); + private List ForwardTemplateReferenceList = new List(); public string Mangled { get; private set; } - private int Pos; + private int Position; private int Length; private bool CanForwardTemplateReference; private bool CanParseTemplateArgs; + public Demangler(string Mangled) { - this.Mangled = Mangled; - Pos = 0; - Length = Mangled.Length; + this.Mangled = Mangled; + Position = 0; + Length = Mangled.Length; CanParseTemplateArgs = true; } private bool ConsumeIf(string ToConsume) { - string MangledPart = Mangled.Substring(Pos); + string MangledPart = Mangled.Substring(Position); + if (MangledPart.StartsWith(ToConsume)) { - Pos += ToConsume.Length; + Position += ToConsume.Length; + return true; } @@ -42,57 +46,74 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private string PeekString(int Offset = 0, int Length = 1) { - if (Pos + Offset >= Length) + if (Position + Offset >= Length) + { return null; - return Mangled.Substring(Pos + Offset, Length); + } + + return Mangled.Substring(Position + Offset, Length); } + private char Peek(int Offset = 0) { - if (Pos + Offset >= Length) + if (Position + Offset >= Length) + { return '\0'; - return Mangled[Pos + Offset]; + } + + return Mangled[Position + Offset]; } private char Consume() { - if (Pos < Length) + if (Position < Length) { - return Mangled[Pos++]; + return Mangled[Position++]; } + return '\0'; } private int Count() { - return Length - Pos; + return Length - Position; } - private static int FromBase36(string encoded) + private static int FromBase36(string Encoded) { - char[] reversedEncoded = encoded.ToLower().ToCharArray().Reverse().ToArray(); - int result = 0; - for (int i = 0; i < reversedEncoded.Length; i++) + char[] ReversedEncoded = Encoded.ToLower().ToCharArray().Reverse().ToArray(); + + int Result = 0; + + for (int i = 0; i < ReversedEncoded.Length; i++) { - char c = reversedEncoded[i]; - int value = BASE_36.IndexOf(c); - if (value == -1) + int Value = BASE_36.IndexOf(ReversedEncoded[i]); + if (Value == -1) + { return -1; - result += value * (int)Math.Pow(36, i); + } + + Result += Value * (int)Math.Pow(36, i); } - return result; + + return Result; } private int ParseSeqId() { - string Part = Mangled.Substring(Pos); + string Part = Mangled.Substring(Position); + int SeqIdLen = 0; - int SeqIdLen; - for (SeqIdLen = 0; SeqIdLen < Part.Length; SeqIdLen++) + for (; SeqIdLen < Part.Length; SeqIdLen++) { if (!char.IsLetterOrDigit(Part[SeqIdLen])) + { break; + } } - Pos += SeqIdLen; + + Position += SeqIdLen; + return FromBase36(Part.Substring(0, SeqIdLen)); } @@ -108,29 +129,32 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseSubstitution() { if (!ConsumeIf("S")) - return null; - char C = Peek(); - if (char.IsLower(C)) { - switch (C) + return null; + } + + char SubstitutionSecondChar = Peek(); + if (char.IsLower(SubstitutionSecondChar)) + { + switch (SubstitutionSecondChar) { case 'a': - Pos++; + Position++; return new SpecialSubstitution(SpecialSubstitution.SpecialType.Allocator); case 'b': - Pos++; + Position++; return new SpecialSubstitution(SpecialSubstitution.SpecialType.BasicString); case 's': - Pos++; + Position++; return new SpecialSubstitution(SpecialSubstitution.SpecialType.String); case 'i': - Pos++; + Position++; return new SpecialSubstitution(SpecialSubstitution.SpecialType.IStream); case 'o': - Pos++; + Position++; return new SpecialSubstitution(SpecialSubstitution.SpecialType.OStream); case 'd': - Pos++; + Position++; return new SpecialSubstitution(SpecialSubstitution.SpecialType.IOStream); default: return null; @@ -141,17 +165,27 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler if (ConsumeIf("_")) { if (SubstitutionList.Count != 0) + { return SubstitutionList[0]; + } + return null; } // ::= S _ int SeqId = ParseSeqId(); if (SeqId < 0) + { return null; + } + SeqId++; + if (!ConsumeIf("_") || SeqId >= SubstitutionList.Count) + { return null; + } + return SubstitutionList[SeqId]; } @@ -172,6 +206,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return ParseNumber(true).Length == 0 || !ConsumeIf("_") || ParseNumber(true).Length == 0 || !ConsumeIf("_"); } + return true; } @@ -183,17 +218,31 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseClassEnumType() { string ElaboratedType = null; + if (ConsumeIf("Ts")) + { ElaboratedType = "struct"; + } else if (ConsumeIf("Tu")) + { ElaboratedType = "union"; + } else if (ConsumeIf("Te")) + { ElaboratedType = "enum"; + } + BaseNode Name = ParseName(); if (Name == null) + { return null; + } + if (ElaboratedType == null) + { return Name; + } + return new ElaboratedType(ElaboratedType, Name); } @@ -208,6 +257,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler CV CVQualifiers = ParseCVQualifiers(); BaseNode ExceptionSpec = null; + if (ConsumeIf("Do")) { ExceptionSpec = new NameType("noexcept"); @@ -216,17 +266,24 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Expression = ParseExpression(); if (Expression == null || !ConsumeIf("E")) + { return null; + } + ExceptionSpec = new NoexceptSpec(Expression); } else if (ConsumeIf("Dw")) { List Types = new List(); + while (!ConsumeIf("E")) { BaseNode Type = ParseType(); if (Type == null) + { return null; + } + Types.Add(Type); } @@ -235,23 +292,36 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // We don't need the transaction ConsumeIf("Dx"); + if (!ConsumeIf("F")) + { return null; + } // extern "C" ConsumeIf("Y"); + BaseNode ReturnType = ParseType(); if (ReturnType == null) + { return null; + } Reference ReferenceQualifier = Reference.None; List Params = new List(); + while (true) { if (ConsumeIf("E")) + { break; + } + if (ConsumeIf("v")) + { continue; + } + if (ConsumeIf("RE")) { ReferenceQualifier = Reference.LValue; @@ -265,9 +335,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler BaseNode Type = ParseType(); if (Type == null) + { return null; + } + Params.Add(Type); } + return new FunctionType(ReturnType, new NodeArray(Params), new CVType(CVQualifiers, null), new SimpleReferenceType(ReferenceQualifier, null), ExceptionSpec); } @@ -276,16 +350,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseArrayType() { if (!ConsumeIf("A")) + { return null; + } + BaseNode ElementType; if (char.IsDigit(Peek())) { string Dimension = ParseNumber(); if (Dimension.Length == 0 || !ConsumeIf("_")) + { return null; + } + ElementType = ParseType(); if (ElementType == null) + { return null; + } + return new ArrayType(ElementType, Dimension); } @@ -293,15 +376,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode DimensionExpression = ParseExpression(); if (DimensionExpression == null || !ConsumeIf("_")) + { return null; + } + ElementType = ParseType(); if (ElementType == null) + { return null; + } + return new ArrayType(ElementType, DimensionExpression); } + ElementType = ParseType(); if (ElementType == null) + { return null; + } + return new ArrayType(ElementType); } @@ -324,239 +417,291 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { // Temporary context if (Context == null) + { Context = new NameParserContext(); + } - BaseNode Res = null; + BaseNode Result = null; switch (Peek()) { case 'r': case 'V': case 'K': int TypePos = 0; + if (Peek(TypePos) == 'r') + { TypePos++; + } + if (Peek(TypePos) == 'V') + { TypePos++; + } + if (Peek(TypePos) == 'K') + { TypePos++; + } + if (Peek(TypePos) == 'F' || (Peek(TypePos) == 'D' && (Peek(TypePos + 1) == 'o' || Peek(TypePos + 1) == 'O' || Peek(TypePos + 1) == 'w' || Peek(TypePos + 1) == 'x'))) { - Res = ParseFunctionType(); + Result = ParseFunctionType(); break; } + CV CV = ParseCVQualifiers(); - Res = ParseType(Context); - if (Res == null) + + Result = ParseType(Context); + + if (Result == null) + { return null; - Res = new CVType(CV, Res); + } + + Result = new CVType(CV, Result); break; case 'U': // TODO: return null; case 'v': - Pos++; + Position++; return new NameType("void"); case 'w': - Pos++; + Position++; return new NameType("wchar_t"); case 'b': - Pos++; + Position++; return new NameType("bool"); case 'c': - Pos++; + Position++; return new NameType("char"); case 'a': - Pos++; + Position++; return new NameType("signed char"); case 'h': - Pos++; + Position++; return new NameType("unsigned char"); case 's': - Pos++; + Position++; return new NameType("short"); case 't': - Pos++; + Position++; return new NameType("unsigned short"); case 'i': - Pos++; + Position++; return new NameType("int"); case 'j': - Pos++; + Position++; return new NameType("unsigned int"); case 'l': - Pos++; + Position++; return new NameType("long"); case 'm': - Pos++; + Position++; return new NameType("unsigned long"); case 'x': - Pos++; + Position++; return new NameType("long long"); case 'y': - Pos++; + Position++; return new NameType("unsigned long long"); case 'n': - Pos++; + Position++; return new NameType("__int128"); case 'o': - Pos++; + Position++; return new NameType("unsigned __int128"); case 'f': - Pos++; + Position++; return new NameType("float"); case 'd': - Pos++; + Position++; return new NameType("double"); case 'e': - Pos++; + Position++; return new NameType("long double"); case 'g': - Pos++; + Position++; return new NameType("__float128"); case 'z': - Pos++; + Position++; return new NameType("..."); case 'u': - Pos++; + Position++; return ParseSourceName(); case 'D': switch (Peek(1)) { case 'd': - Pos += 2; + Position += 2; return new NameType("decimal64"); case 'e': - Pos += 2; + Position += 2; return new NameType("decimal128"); case 'f': - Pos += 2; + Position += 2; return new NameType("decimal32"); case 'h': - Pos += 2; - //return new NameType("decimal16"); + Position += 2; // FIXME: GNU c++flit returns this but that is not what is supposed to be returned. return new NameType("half"); + //return new NameType("decimal16"); case 'i': - Pos += 2; + Position += 2; return new NameType("char32_t"); case 's': - Pos += 2; + Position += 2; return new NameType("char16_t"); case 'a': - Pos += 2; + Position += 2; return new NameType("decltype(auto)"); case 'n': - Pos += 2; - //return new NameType("std::nullptr_t"); + Position += 2; // FIXME: GNU c++flit returns this but that is not what is supposed to be returned. return new NameType("decltype(nullptr)"); + //return new NameType("std::nullptr_t"); case 't': case 'T': - Pos += 2; - Res = ParseDecltype(); + Position += 2; + Result = ParseDecltype(); break; case 'o': case 'O': case 'w': case 'x': - Res = ParseFunctionType(); + Result = ParseFunctionType(); break; default: return null; } break; case 'F': - Res = ParseFunctionType(); + Result = ParseFunctionType(); break; case 'A': - // TODO: return ParseArrayType(); case 'M': // TODO: - Pos++; + Position++; return null; case 'T': // might just be a class enum type if (Peek(1) == 's' || Peek(1) == 'u' || Peek(1) == 'e') { - Res = ParseClassEnumType(); + Result = ParseClassEnumType(); break; } - Res = ParseTemplateParam(); - if (Res == null) + + Result = ParseTemplateParam(); + if (Result == null) + { return null; + } if (CanParseTemplateArgs && Peek() == 'I') { BaseNode TemplateArguments = ParseTemplateArguments(); if (TemplateArguments == null) + { return null; - Res = new NameTypeWithTemplateArguments(Res, TemplateArguments); + } + + Result = new NameTypeWithTemplateArguments(Result, TemplateArguments); } break; case 'P': - Pos++; - Res = ParseType(Context); - if (Res == null) + Position++; + Result = ParseType(Context); + + if (Result == null) + { return null; - Res = new PointerType(Res); + } + + Result = new PointerType(Result); break; case 'R': - Pos++; - Res = ParseType(Context); - if (Res == null) + Position++; + Result = ParseType(Context); + + if (Result == null) + { return null; - Res = new ReferenceType("&", Res); + } + + Result = new ReferenceType("&", Result); break; case 'O': - Pos++; - Res = ParseType(Context); - if (Res == null) + Position++; + Result = ParseType(Context); + + if (Result == null) + { return null; - Res = new ReferenceType("&&", Res); + } + + Result = new ReferenceType("&&", Result); break; case 'C': - Pos++; - Res = ParseType(Context); - if (Res == null) + Position++; + Result = ParseType(Context); + + if (Result == null) + { return null; - Res = new PostfixQualifiedType(" complex", Res); + } + + Result = new PostfixQualifiedType(" complex", Result); break; case 'G': - Pos++; - Res = ParseType(Context); - if (Res == null) + Position++; + Result = ParseType(Context); + + if (Result == null) + { return null; - Res = new PostfixQualifiedType(" imaginary", Res); + } + + Result = new PostfixQualifiedType(" imaginary", Result); break; case 'S': if (Peek(1) != 't') { BaseNode Substitution = ParseSubstitution(); if (Substitution == null) + { return null; + } + if (CanParseTemplateArgs && Peek() == 'I') { BaseNode TemplateArgument = ParseTemplateArgument(); if (TemplateArgument == null) + { return null; - Res = new NameTypeWithTemplateArguments(Substitution, TemplateArgument); + } + + Result = new NameTypeWithTemplateArguments(Substitution, TemplateArgument); break; } return Substitution; } else { - Res = ParseClassEnumType(); + Result = ParseClassEnumType(); break; } default: - Res = ParseClassEnumType(); + Result = ParseClassEnumType(); break; } - if (Res != null) - SubstitutionList.Add(Res); - return Res; + if (Result != null) + { + SubstitutionList.Add(Result); + } + + return Result; } // ::= TV # virtual table @@ -577,7 +722,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Name = ParseName(); if (Name == null) + { return null; + } + return new SpecialName("guard variable for ", Name); } return null; @@ -588,73 +736,110 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { // ::= TV # virtual table case 'V': - Pos += 2; + Position += 2; Node = ParseType(Context); if (Node == null) + { return null; + } + return new SpecialName("vtable for ", Node); // ::= TT # VTT structure (construction vtable index) case 'T': - Pos += 2; + Position += 2; Node = ParseType(Context); if (Node == null) + { return null; + } + return new SpecialName("VTT for ", Node); // ::= TI # typeinfo structure case 'I': - Pos += 2; + Position += 2; Node = ParseType(Context); if (Node == null) + { return null; + } + return new SpecialName("typeinfo for ", Node); // ::= TS # typeinfo name (null-terminated byte string) case 'S': - Pos += 2; + Position += 2; Node = ParseType(Context); if (Node == null) + { return null; + } + return new SpecialName("typeinfo name for ", Node); // ::= Tc case 'c': - Pos += 2; + Position += 2; if (ParseCallOffset() || ParseCallOffset()) + { return null; + } + Node = ParseEncoding(); if (Node == null) + { return null; + } + return new SpecialName("covariant return thunk to ", Node); // extension ::= TC _ case 'C': - Pos += 2; + Position += 2; BaseNode FirstType = ParseType(); if (FirstType == null || ParseNumber(true).Length == 0 || !ConsumeIf("_")) + { return null; + } + BaseNode SecondType = ParseType(); + return new CtorVtableSpecialName(SecondType, FirstType); // ::= TH # Thread-local initialization case 'H': - Pos += 2; + Position += 2; Node = ParseName(); if (Node == null) + { return null; + } + return new SpecialName("thread-local initialization routine for ", Node); // ::= TW # Thread-local wrapper case 'W': - Pos += 2; + Position += 2; Node = ParseName(); if (Node == null) + { return null; + } + return new SpecialName("thread-local wrapper routine for ", Node); default: - Pos++; + Position++; bool IsVirtual = Peek() == 'v'; if (ParseCallOffset()) + { return null; + } + Node = ParseEncoding(); if (Node == null) + { return null; + } + if (IsVirtual) + { return new SpecialName("virtual thunk to ", Node); + } + return new SpecialName("non-virtual thunk to ", Node); } } @@ -663,6 +848,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private CV ParseCVQualifiers() { CV Qualifiers = CV.None; + if (ConsumeIf("r")) { Qualifiers |= CV.Restricted; @@ -675,6 +861,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { Qualifiers |= CV.Const; } + return Qualifiers; } @@ -683,58 +870,83 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= O # && ref-qualifier private SimpleReferenceType ParseRefQualifiers() { - Reference Res = Reference.None; + Reference Result = Reference.None; if (ConsumeIf("O")) { - Res = Reference.RValue; + Result = Reference.RValue; } else if (ConsumeIf("R")) { - Res = Reference.LValue; + Result = Reference.LValue; } - return new SimpleReferenceType(Res, null); + return new SimpleReferenceType(Result, null); } private BaseNode CreateNameNode(BaseNode Prev, BaseNode Name, NameParserContext Context) { - BaseNode Res = Name; + BaseNode Result = Name; if (Prev != null) - Res = new NestedName(Name, Prev); + { + Result = new NestedName(Name, Prev); + } + if (Context != null) + { Context.FinishWithTemplateArguments = false; - return Res; + } + + return Result; } private int ParsePositiveNumber() { - string Part = Mangled.Substring(Pos); - int NumberLen; - for (NumberLen = 0; NumberLen < Part.Length; NumberLen++) + string Part = Mangled.Substring(Position); + int NumberLength = 0; + + for (; NumberLength < Part.Length; NumberLength++) { - if (!char.IsDigit(Part[NumberLen])) + if (!char.IsDigit(Part[NumberLength])) + { break; + } } - Pos += NumberLen; - if (NumberLen == 0) + + Position += NumberLength; + + if (NumberLength == 0) + { return -1; - return int.Parse(Part.Substring(0, NumberLen)); + } + + return int.Parse(Part.Substring(0, NumberLength)); } private string ParseNumber(bool IsSigned = false) { if (IsSigned) - ConsumeIf("n"); - if (Count() == 0 || !char.IsDigit(Mangled[Pos])) - return null; - string Part = Mangled.Substring(Pos); - int NumberLen; - for (NumberLen = 0; NumberLen < Part.Length; NumberLen++) { - if (!char.IsDigit(Part[NumberLen])) - break; + ConsumeIf("n"); } - Pos += NumberLen; - return Part.Substring(0, NumberLen); + + if (Count() == 0 || !char.IsDigit(Mangled[Position])) + { + return null; + } + + string Part = Mangled.Substring(Position); + int NumberLength = 0; + + for (; NumberLength < Part.Length; NumberLength++) + { + if (!char.IsDigit(Part[NumberLength])) + { + break; + } + } + + Position += NumberLength; + + return Part.Substring(0, NumberLength); } // ::= @@ -742,11 +954,17 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { int Length = ParsePositiveNumber(); if (Count() < Length || Length <= 0) + { return null; - string Name = Mangled.Substring(Pos, Length); - Pos += Length; + } + + string Name = Mangled.Substring(Position, Length); + Position += Length; if (Name.StartsWith("_GLOBAL__N")) + { return new NameType("(anonymous namespace)"); + } + return new NameType(Name); } @@ -809,17 +1027,17 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'a': - Pos += 2; + Position += 2; return new NameType("operator&&"); case 'd': case 'n': - Pos += 2; + Position += 2; return new NameType("operator&"); case 'N': - Pos += 2; + Position += 2; return new NameType("operator&="); case 'S': - Pos += 2; + Position += 2; return new NameType("operator="); default: return null; @@ -828,29 +1046,38 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'l': - Pos += 2; + Position += 2; return new NameType("operator()"); case 'm': - Pos += 2; + Position += 2; return new NameType("operator,"); case 'o': - Pos += 2; + Position += 2; return new NameType("operator~"); case 'v': - Pos += 2; - bool CanParseTemplateArgsBackup = CanParseTemplateArgs; + Position += 2; + + bool CanParseTemplateArgsBackup = CanParseTemplateArgs; bool CanForwardTemplateReferenceBackup = CanForwardTemplateReference; - CanParseTemplateArgs = false; + + CanParseTemplateArgs = false; CanForwardTemplateReference = CanForwardTemplateReferenceBackup || Context != null; BaseNode Type = ParseType(); - CanParseTemplateArgs = CanParseTemplateArgsBackup; + CanParseTemplateArgs = CanParseTemplateArgsBackup; CanForwardTemplateReference = CanForwardTemplateReferenceBackup; + if (Type == null) + { return null; + } + if (Context != null) + { Context.CtorDtorConversion = true; + } + return new ConversionOperatorType(Type); default: return null; @@ -859,19 +1086,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'a': - Pos += 2; + Position += 2; return new NameType("operator delete[]"); case 'e': - Pos += 2; + Position += 2; return new NameType("operator*"); case 'l': - Pos += 2; + Position += 2; return new NameType("operator delete"); case 'v': - Pos += 2; + Position += 2; return new NameType("operator/"); case 'V': - Pos += 2; + Position += 2; return new NameType("operator/="); default: return null; @@ -880,13 +1107,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'o': - Pos += 2; + Position += 2; return new NameType("operator^"); case 'O': - Pos += 2; + Position += 2; return new NameType("operator^="); case 'q': - Pos += 2; + Position += 2; return new NameType("operator=="); default: return null; @@ -895,10 +1122,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'e': - Pos += 2; + Position += 2; return new NameType("operator>="); case 't': - Pos += 2; + Position += 2; return new NameType("operator>"); default: return null; @@ -906,7 +1133,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'i': if (Peek(1) == 'x') { - Pos += 2; + Position += 2; return new NameType("operator[]"); } return null; @@ -914,22 +1141,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'e': - Pos += 2; + Position += 2; return new NameType("operator<="); case 'i': - Pos += 2; + Position += 2; BaseNode SourceName = ParseSourceName(); if (SourceName == null) + { return null; + } + return new LiteralOperator(SourceName); case 's': - Pos += 2; + Position += 2; return new NameType("operator<<"); case 'S': - Pos += 2; + Position += 2; return new NameType("operator<<="); case 't': - Pos += 2; + Position += 2; return new NameType("operator<"); default: return null; @@ -938,19 +1168,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'i': - Pos += 2; + Position += 2; return new NameType("operator-"); case 'I': - Pos += 2; + Position += 2; return new NameType("operator-="); case 'l': - Pos += 2; + Position += 2; return new NameType("operator*"); case 'L': - Pos += 2; + Position += 2; return new NameType("operator*="); case 'm': - Pos += 2; + Position += 2; return new NameType("operator--"); default: return null; @@ -959,19 +1189,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'a': - Pos += 2; + Position += 2; return new NameType("operator new[]"); case 'e': - Pos += 2; + Position += 2; return new NameType("operator!="); case 'g': - Pos += 2; + Position += 2; return new NameType("operator-"); case 't': - Pos += 2; + Position += 2; return new NameType("operator!"); case 'w': - Pos += 2; + Position += 2; return new NameType("operator new"); default: return null; @@ -980,13 +1210,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'o': - Pos += 2; + Position += 2; return new NameType("operator||"); case 'r': - Pos += 2; + Position += 2; return new NameType("operator|"); case 'R': - Pos += 2; + Position += 2; return new NameType("operator|="); default: return null; @@ -995,20 +1225,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'm': - Pos += 2; + Position += 2; return new NameType("operator->*"); case 's': case 'l': - Pos += 2; + Position += 2; return new NameType("operator+"); case 'L': - Pos += 2; + Position += 2; return new NameType("operator+="); case 'p': - Pos += 2; + Position += 2; return new NameType("operator++"); case 't': - Pos += 2; + Position += 2; return new NameType("operator->"); default: return null; @@ -1016,7 +1246,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'q': if (Peek(1) == 'u') { - Pos += 2; + Position += 2; return new NameType("operator?"); } return null; @@ -1024,16 +1254,16 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'm': - Pos += 2; + Position += 2; return new NameType("operator%"); case 'M': - Pos += 2; + Position += 2; return new NameType("operator%="); case 's': - Pos += 2; + Position += 2; return new NameType("operator>>"); case 'S': - Pos += 2; + Position += 2; return new NameType("operator>>="); default: return null; @@ -1041,7 +1271,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 's': if (Peek(1) == 's') { - Pos += 2; + Position += 2; return new NameType("operator<=>"); } return null; @@ -1060,7 +1290,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= DC + E # structured binding declaration (TODO) private BaseNode ParseUnqualifiedName(NameParserContext Context) { - BaseNode Res = null; + BaseNode Result = null; char C = Peek(); if (C == 'U') { @@ -1069,7 +1299,7 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } else if (char.IsDigit(C)) { - Res = ParseSourceName(); + Result = ParseSourceName(); } else if (ConsumeIf("DC")) { @@ -1078,15 +1308,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler } else { - Res = ParseOperatorName(Context); + Result = ParseOperatorName(Context); } - if (Res != null) + if (Result != null) { // TODO: ABI Tags //throw new Exception("ABI Tags not implemented"); } - return Res; + return Result; } // ::= C1 # complete object constructor @@ -1104,16 +1334,26 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler if (ConsumeIf("C")) { - bool IsInherited = ConsumeIf("I"); - char C = Peek(); + bool IsInherited = ConsumeIf("I"); - if (C != '1' && C != '2' && C != '3') + char CtorDtorType = Peek(); + if (CtorDtorType != '1' && CtorDtorType != '2' && CtorDtorType != '3') + { return null; - Pos++; + } + + Position++; + if (Context != null) + { Context.CtorDtorConversion = true; + } + if (IsInherited && ParseName(Context) == null) + { return null; + } + return new CtorDtorNameType(Prev, false); } @@ -1121,12 +1361,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { char C = Peek(); if (C != '0' && C != '1' && C != '2') + { return null; - Pos++; + } + + Position++; + if (Context != null) + { Context.CtorDtorConversion = true; + } + return new CtorDtorNameType(Prev, true); } + return null; } @@ -1140,24 +1388,38 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { // ignored ParseCVQualifiers(); + if (!ConsumeIf("_")) + { return null; + } + return new FunctionParameter(ParseNumber()); } else if (ConsumeIf("fL")) { string L1Number = ParseNumber(); if (L1Number == null || L1Number.Length == 0) + { return null; + } + if (!ConsumeIf("p")) + { return null; + } + // ignored ParseCVQualifiers(); - if (!ConsumeIf("_")) - return null; - return new FunctionParameter(ParseNumber()); + if (!ConsumeIf("_")) + { + return null; + } + + return new FunctionParameter(ParseNumber()); } + return null; } @@ -1168,14 +1430,20 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseFoldExpression() { if (!ConsumeIf("f")) + { return null; - char FoldKind = Peek(); + } + + char FoldKind = Peek(); bool HasInitializer = FoldKind == 'L' || FoldKind == 'R'; - bool IsLeftFold = FoldKind == 'l' || FoldKind == 'L'; + bool IsLeftFold = FoldKind == 'l' || FoldKind == 'L'; if (!IsLeftFold && !(FoldKind == 'r' || FoldKind == 'R')) + { return null; - Pos++; + } + + Position++; string OperatorName = null; @@ -1277,24 +1545,33 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler default: return null; } - Pos += 2; + + Position += 2; BaseNode Expression = ParseExpression(); - BaseNode Initializer = null; if (Expression == null) + { return null; + } + + BaseNode Initializer = null; + if (HasInitializer) { Initializer = ParseExpression(); if (Initializer == null) + { return null; + } } + if (IsLeftFold && Initializer != null) { BaseNode Temp = Expression; - Expression = Initializer; - Initializer = Temp; + Expression = Initializer; + Initializer = Temp; } + return new FoldExpression(IsLeftFold, OperatorName, new PackedTemplateParameterExpansion(Expression), Initializer); } @@ -1304,15 +1581,19 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseConversionExpression() { if (!ConsumeIf("cv")) + { return null; + } bool CanParseTemplateArgsBackup = CanParseTemplateArgs; - CanParseTemplateArgs = false; - BaseNode Type = ParseType(); - CanParseTemplateArgs = CanParseTemplateArgsBackup; + CanParseTemplateArgs = false; + BaseNode Type = ParseType(); + CanParseTemplateArgs = CanParseTemplateArgsBackup; if (Type == null) + { return null; + } List Expressions = new List(); if (ConsumeIf("_")) @@ -1321,7 +1602,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Expression = ParseExpression(); if (Expression == null) + { return null; + } Expressions.Add(Expression); } @@ -1330,7 +1613,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Expression = ParseExpression(); if (Expression == null) + { return null; + } Expressions.Add(Expression); } @@ -1342,11 +1627,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode LeftPart = ParseExpression(); if (LeftPart == null) + { return null; + } BaseNode RightPart = ParseExpression(); if (RightPart == null) + { return null; + } return new BinaryExpression(LeftPart, Name, RightPart); } @@ -1355,7 +1644,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Expression = ParseExpression(); if (Expression == null) + { return null; + } return new PrefixExpression(Name, Expression); } @@ -1374,38 +1665,59 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'i': - Pos += 2; + Position += 2; BaseNode Field = ParseSourceName(); if (Field == null) + { return null; + } + BracedExpressionNode = ParseBracedExpression(); if (BracedExpressionNode == null) + { return null; + } + return new BracedExpression(Field, BracedExpressionNode, false); case 'x': - Pos += 2; + Position += 2; BaseNode Index = ParseExpression(); if (Index == null) + { return null; + } + BracedExpressionNode = ParseBracedExpression(); if (BracedExpressionNode == null) + { return null; + } + return new BracedExpression(Index, BracedExpressionNode, true); case 'X': - Pos += 2; + Position += 2; BaseNode RangeBeginExpression = ParseExpression(); if (RangeBeginExpression == null) + { return null; + } BaseNode RangeEndExpression = ParseExpression(); if (RangeEndExpression == null) + { return null; + } + BracedExpressionNode = ParseBracedExpression(); if (BracedExpressionNode == null) + { return null; + } + return new BracedRangeExpression(RangeBeginExpression, RangeEndExpression, BracedExpressionNode); } } + return ParseExpression(); } @@ -1418,36 +1730,50 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseNewExpression() { bool IsGlobal = ConsumeIf("gs"); - bool IsArray = Peek(1) == 'a'; + bool IsArray = Peek(1) == 'a'; if (!ConsumeIf("nw") || !ConsumeIf("na")) + { return null; + } - List Expressions = new List(); + List Expressions = new List(); List Initializers = new List(); while (!ConsumeIf("_")) { BaseNode Expression = ParseExpression(); if (Expression == null) + { return null; + } + Expressions.Add(Expression); } + BaseNode TypeNode = ParseType(); if (TypeNode == null) + { return null; + } + if (ConsumeIf("pi")) { while (!ConsumeIf("E")) { BaseNode Initializer = ParseExpression(); if (Initializer == null) + { return null; + } + Initializers.Add(Initializer); } } else if (!ConsumeIf("E")) + { return null; + } return new NewExpression(new NodeArray(Expressions), TypeNode, new NodeArray(Initializers), IsGlobal, IsArray); } @@ -1500,7 +1826,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler bool IsGlobal = ConsumeIf("gs"); BaseNode Expression = null; if (Count() < 2) + { return null; + } switch (Peek()) { @@ -1511,35 +1839,44 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'f': char C = Peek(1); if (C == 'p' || (C == 'L' && char.IsDigit(Peek(2)))) + { return ParseFunctionParameter(); + } + return ParseFoldExpression(); case 'a': switch (Peek(1)) { case 'a': - Pos += 2; + Position += 2; return ParseBinaryExpression("&&"); case 'd': case 'n': - Pos += 2; + Position += 2; return ParseBinaryExpression("&"); case 'N': - Pos += 2; + Position += 2; return ParseBinaryExpression("&="); case 'S': - Pos += 2; + Position += 2; return ParseBinaryExpression("="); case 't': - Pos += 2; + Position += 2; BaseNode Type = ParseType(); if (Type == null) + { return null; + } + return new EnclosedExpression("alignof (", Type, ")"); case 'z': - Pos += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new EnclosedExpression("alignof (", Expression, ")"); } return null; @@ -1547,33 +1884,45 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'c': - Pos += 2; + Position += 2; BaseNode To = ParseType(); if (To == null) + { return null; + } + BaseNode From = ParseExpression(); if (From == null) + { return null; + } + return new CastExpression("const_cast", To, From); case 'l': - Pos += 2; + Position += 2; BaseNode Callee = ParseExpression(); if (Callee == null) + { return null; + } + List Names = new List(); while (!ConsumeIf("E")) { Expression = ParseExpression(); if (Expression == null) + { return null; + } + Names.Add(Expression); } return new CallExpression(Callee, Names); case 'm': - Pos += 2; + Position += 2; return ParseBinaryExpression(","); case 'o': - Pos += 2; + Position += 2; return ParsePrefixExpression("~"); case 'v': return ParseConversionExpression(); @@ -1585,54 +1934,78 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'a': - Pos += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return Expression; + } + return new DeleteExpression(Expression, IsGlobal, true); case 'c': - Pos += 2; + Position += 2; BaseNode Type = ParseType(); if (Type == null) + { return null; + } + Expression = ParseExpression(); if (Expression == null) + { return Expression; + } + return new CastExpression("dynamic_cast", Type, Expression); case 'e': - Pos += 2; + Position += 2; return ParsePrefixExpression("*"); case 'l': - Pos += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new DeleteExpression(Expression, IsGlobal, false); case 'n': return ParseUnresolvedName(); case 's': - Pos += 2; + Position += 2; LeftNode = ParseExpression(); if (LeftNode == null) + { return null; + } + RightNode = ParseExpression(); if (RightNode == null) + { return null; + } + return new MemberExpression(LeftNode, ".*", RightNode); case 't': - Pos += 2; + Position += 2; LeftNode = ParseExpression(); if (LeftNode == null) + { return null; + } + RightNode = ParseExpression(); if (RightNode == null) + { return null; + } + return new MemberExpression(LeftNode, ".", RightNode); case 'v': - Pos += 2; + Position += 2; return ParseBinaryExpression("/"); case 'V': - Pos += 2; + Position += 2; return ParseBinaryExpression("/="); } return null; @@ -1640,13 +2013,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'o': - Pos += 2; + Position += 2; return ParseBinaryExpression("^"); case 'O': - Pos += 2; + Position += 2; return ParseBinaryExpression("^="); case 'q': - Pos += 2; + Position += 2; return ParseBinaryExpression("=="); } return null; @@ -1654,10 +2027,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'e': - Pos += 2; + Position += 2; return ParseBinaryExpression(">="); case 't': - Pos += 2; + Position += 2; return ParseBinaryExpression(">"); } return null; @@ -1665,23 +2038,32 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'x': - Pos += 2; + Position += 2; BaseNode Base = ParseExpression(); if (Base == null) + { return null; + } + BaseNode Subscript = ParseExpression(); if (Base == null) + { return null; + } + return new ArraySubscriptingExpression(Base, Subscript); case 'l': - Pos += 2; + Position += 2; List BracedExpressions = new List(); while (!ConsumeIf("E")) { Expression = ParseBracedExpression(); if (Expression == null) + { return null; + } + BracedExpressions.Add(Expression); } return new InitListExpression(null, BracedExpressions); @@ -1691,16 +2073,16 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'e': - Pos += 2; + Position += 2; return ParseBinaryExpression("<="); case 's': - Pos += 2; + Position += 2; return ParseBinaryExpression("<<"); case 'S': - Pos += 2; + Position += 2; return ParseBinaryExpression("<<="); case 't': - Pos += 2; + Position += 2; return ParseBinaryExpression("<"); } return null; @@ -1708,24 +2090,30 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'i': - Pos += 2; + Position += 2; return ParseBinaryExpression("-"); case 'I': - Pos += 2; + Position += 2; return ParseBinaryExpression("-="); case 'l': - Pos += 2; + Position += 2; return ParseBinaryExpression("*"); case 'L': - Pos += 2; + Position += 2; return ParseBinaryExpression("*="); case 'm': - Pos += 2; + Position += 2; if (ConsumeIf("_")) + { return ParsePrefixExpression("--"); + } + Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new PostfixExpression(Expression, "--"); } return null; @@ -1734,23 +2122,26 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { case 'a': case 'w': - Pos += 2; + Position += 2; return ParseNewExpression(); case 'e': - Pos += 2; + Position += 2; return ParseBinaryExpression("!="); case 'g': - Pos += 2; + Position += 2; return ParsePrefixExpression("-"); case 't': - Pos += 2; + Position += 2; return ParsePrefixExpression("!"); case 'x': - Pos += 2; - Pos += 2; + Position += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new EnclosedExpression("noexcept (", Expression, ")"); } return null; @@ -1760,13 +2151,13 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'n': return ParseUnresolvedName(); case 'o': - Pos += 2; + Position += 2; return ParseBinaryExpression("||"); case 'r': - Pos += 2; + Position += 2; return ParseBinaryExpression("|"); case 'R': - Pos += 2; + Position += 2; return ParseBinaryExpression("|="); } return null; @@ -1774,47 +2165,68 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'm': - Pos += 2; + Position += 2; return ParseBinaryExpression("->*"); case 'l': case 's': - Pos += 2; + Position += 2; return ParseBinaryExpression("+"); case 'L': - Pos += 2; + Position += 2; return ParseBinaryExpression("+="); case 'p': - Pos += 2; + Position += 2; if (ConsumeIf("_")) + { return ParsePrefixExpression("++"); + } + Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new PostfixExpression(Expression, "++"); case 't': - Pos += 2; + Position += 2; LeftNode = ParseExpression(); if (LeftNode == null) + { return null; + } + RightNode = ParseExpression(); if (RightNode == null) + { return null; + } + return new MemberExpression(LeftNode, "->", RightNode); } return null; case 'q': if (Peek(1) == 'u') { - Pos += 2; + Position += 2; BaseNode Condition = ParseExpression(); if (Condition == null) + { return null; + } + LeftNode = ParseExpression(); if (LeftNode == null) + { return null; + } + RightNode = ParseExpression(); if (RightNode == null) + { return null; + } + return new ConditionalExpression(Condition, LeftNode, RightNode); } return null; @@ -1822,25 +2234,31 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'c': - Pos += 2; + Position += 2; BaseNode To = ParseType(); if (To == null) + { return null; + } + BaseNode From = ParseExpression(); if (From == null) + { return null; + } + return new CastExpression("reinterpret_cast", To, From); case 'm': - Pos += 2; + Position += 2; return ParseBinaryExpression("%"); case 'M': - Pos += 2; + Position += 2; return ParseBinaryExpression("%"); case 's': - Pos += 2; + Position += 2; return ParseBinaryExpression(">>"); case 'S': - Pos += 2; + Position += 2; return ParseBinaryExpression(">>="); } return null; @@ -1848,36 +2266,51 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler switch (Peek(1)) { case 'c': - Pos += 2; + Position += 2; BaseNode To = ParseType(); if (To == null) + { return null; + } + BaseNode From = ParseExpression(); if (From == null) + { return null; + } + return new CastExpression("static_cast", To, From); case 'p': - Pos += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new PackedTemplateParameterExpansion(Expression); case 'r': return ParseUnresolvedName(); case 't': - Pos += 2; + Position += 2; BaseNode EnclosedType = ParseType(); if (EnclosedType == null) + { return null; + } + return new EnclosedExpression("sizeof (", EnclosedType, ")"); case 'z': - Pos += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new EnclosedExpression("sizeof (", Expression, ")"); case 'Z': - Pos += 2; + Position += 2; BaseNode SizeofParamNode = null; switch (Peek()) { @@ -1885,23 +2318,32 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // FIXME: ??? Not entire sure if it's right SizeofParamNode = ParseFunctionParameter(); if (SizeofParamNode == null) + { return null; + } + return new EnclosedExpression("sizeof...(", new PackedTemplateParameterExpansion(SizeofParamNode), ")"); case 'f': SizeofParamNode = ParseFunctionParameter(); if (SizeofParamNode == null) + { return null; + } + return new EnclosedExpression("sizeof...(", SizeofParamNode, ")"); } return null; case 'P': - Pos += 2; + Position += 2; List Arguments = new List(); while (!ConsumeIf("E")) { BaseNode Argument = ParseTemplateArgument(); if (Argument == null) + { return null; + } + Arguments.Add(Argument); } return new EnclosedExpression("sizeof...(", new NodeArray(Arguments), ")"); @@ -1913,42 +2355,60 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler case 'e': Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new EnclosedExpression("typeid (", Expression, ")"); case 't': BaseNode EnclosedType = ParseExpression(); if (EnclosedType == null) + { return null; + } + return new EnclosedExpression("typeid (", EnclosedType, ")"); case 'l': - Pos += 2; + Position += 2; BaseNode TypeNode = ParseType(); if (TypeNode == null) + { return null; + } + List BracedExpressions = new List(); while (!ConsumeIf("E")) { Expression = ParseBracedExpression(); if (Expression == null) + { return null; + } + BracedExpressions.Add(Expression); } return new InitListExpression(TypeNode, BracedExpressions); case 'r': - Pos += 2; + Position += 2; return new NameType("throw"); case 'w': - Pos += 2; + Position += 2; Expression = ParseExpression(); if (Expression == null) + { return null; + } + return new ThrowExpression(Expression); } return null; } if (char.IsDigit(Peek())) + { return ParseUnresolvedName(); + } + return null; } @@ -1956,7 +2416,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { string Number = ParseNumber(true); if (Number == null || Number.Length == 0 || !ConsumeIf("E")) + { return null; + } + return new IntegerLiteral(LiteralName, Number); } @@ -1970,56 +2433,65 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseExpressionPrimary() { if (!ConsumeIf("L")) + { return null; + } + switch (Peek()) { case 'w': - Pos++; + Position++; return ParseIntegerLiteral("wchar_t"); case 'b': if (ConsumeIf("b0E")) + { return new NameType("false", NodeType.BooleanExpression); + } + if (ConsumeIf("b1E")) + { return new NameType("true", NodeType.BooleanExpression); + } + return null; case 'c': - Pos++; + Position++; return ParseIntegerLiteral("char"); case 'a': - Pos++; + Position++; return ParseIntegerLiteral("signed char"); case 'h': - Pos++; + Position++; return ParseIntegerLiteral("unsigned char"); case 's': - Pos++; + Position++; return ParseIntegerLiteral("short"); case 't': - Pos++; + Position++; return ParseIntegerLiteral("unsigned short"); case 'i': - Pos++; + Position++; return ParseIntegerLiteral(""); case 'j': - Pos++; + Position++; return ParseIntegerLiteral("u"); case 'l': - Pos++; + Position++; return ParseIntegerLiteral("l"); case 'm': - Pos++; + Position++; return ParseIntegerLiteral("ul"); case 'x': - Pos++; + Position++; return ParseIntegerLiteral("ll"); case 'y': - Pos++; + Position++; return ParseIntegerLiteral("ull"); case 'n': - Pos++; + Position++; return ParseIntegerLiteral("__int128"); case 'o': - Pos++; + Position++; return ParseIntegerLiteral("unsigned __int128"); case 'd': case 'e': @@ -2031,7 +2503,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Encoding = ParseEncoding(); if (Encoding != null && ConsumeIf("E")) + { return Encoding; + } } return null; case 'T': @@ -2039,10 +2513,16 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler default: BaseNode Type = ParseType(); if (Type == null) + { return null; + } + string Number = ParseNumber(); if (Number == null || Number.Length == 0 || !ConsumeIf("E")) + { return null; + } + return new IntegerCastExpression(Type, Number); } } @@ -2052,12 +2532,21 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseDecltype() { if (!ConsumeIf("D") || (!ConsumeIf("t") && !ConsumeIf("T"))) + { return null; + } + BaseNode Expression = ParseExpression(); if (Expression == null) + { return null; + } + if (!ConsumeIf("E")) + { return null; + } + return new EnclosedExpression("decltype(", Expression, ")"); } @@ -2068,16 +2557,24 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseTemplateParam() { if (!ConsumeIf("T")) + { return null; + } + int Index = 0; if (!ConsumeIf("_")) { Index = ParsePositiveNumber(); if (Index < 0) + { return null; + } + Index++; if (!ConsumeIf("_")) + { return null; + } } // 5.1.8: TODO: lambda? @@ -2091,7 +2588,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler return ForwardTemplateReference; } if (Index >= TemplateParamList.Count) + { return null; + } + return TemplateParamList[Index]; } @@ -2099,9 +2599,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseTemplateArguments(bool HasContext = false) { if (!ConsumeIf("I")) + { return null; + } + if (HasContext) + { TemplateParamList.Clear(); + } + List Args = new List(); while (!ConsumeIf("E")) { @@ -2111,7 +2617,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler BaseNode TemplateArgument = ParseTemplateArgument(); TemplateParamList = TemplateParamListTemp; if (TemplateArgument == null) + { return null; + } + Args.Add(TemplateArgument); if (TemplateArgument.GetType().Equals(NodeType.PackedTemplateArgument)) { @@ -2123,7 +2632,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode TemplateArgument = ParseTemplateArgument(); if (TemplateArgument == null) + { return null; + } + Args.Add(TemplateArgument); } } @@ -2141,23 +2653,29 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { // X E case 'X': - Pos++; + Position++; BaseNode Expression = ParseExpression(); if (Expression == null || !ConsumeIf("E")) + { return null; + } + return Expression; // case 'L': return ParseExpressionPrimary(); // J * E case 'J': - Pos++; + Position++; List TemplateArguments = new List(); while (!ConsumeIf("E")) { BaseNode TemplateArgument = ParseTemplateArgument(); if (TemplateArgument == null) + { return null; + } + TemplateArguments.Add(TemplateArgument); } return new NodeArray(TemplateArguments, NodeType.PackedTemplateArgument); @@ -2185,7 +2703,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode TemplateParam = ParseTemplateParam(); if (TemplateParam == null) + { return null; + } + SubstitutionList.Add(TemplateParam); return TemplateParam; } @@ -2193,7 +2714,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode DeclType = ParseDecltype(); if (DeclType == null) + { return null; + } + SubstitutionList.Add(DeclType); return DeclType; } @@ -2205,12 +2729,18 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode SourceName = ParseSourceName(); if (SourceName == null) + { return null; + } + if (Peek() == 'I') { BaseNode TemplateArguments = ParseTemplateArguments(); if (TemplateArguments == null) + { return null; + } + return new NameTypeWithTemplateArguments(SourceName, TemplateArguments); } return SourceName; @@ -2230,7 +2760,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler Node = ParseUnresolvedType(); } if (Node == null) + { return null; + } + return new DtorName(Node); } @@ -2244,18 +2777,29 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseBaseUnresolvedName() { if (char.IsDigit(Peek())) + { return ParseSimpleId(); + } else if (ConsumeIf("dn")) + { return ParseDestructorName(); + } + ConsumeIf("on"); BaseNode OperatorName = ParseOperatorName(null); if (OperatorName == null) + { return null; + } + if (Peek() == 'I') { BaseNode TemplateArguments = ParseTemplateArguments(); if (TemplateArguments == null) + { return null; + } + return new NameTypeWithTemplateArguments(OperatorName, TemplateArguments); } return OperatorName; @@ -2269,38 +2813,52 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // # A::x, N::y, A::z; "gs" means leading "::" private BaseNode ParseUnresolvedName(NameParserContext Context = null) { - BaseNode Res = null; + BaseNode Result = null; if (ConsumeIf("srN")) { - Res = ParseUnresolvedType(); - if (Res == null) + Result = ParseUnresolvedType(); + if (Result == null) + { return null; + } if (Peek() == 'I') { BaseNode TemplateArguments = ParseTemplateArguments(); if (TemplateArguments == null) + { return null; - Res = new NameTypeWithTemplateArguments(Res, TemplateArguments); - if (Res == null) + } + + Result = new NameTypeWithTemplateArguments(Result, TemplateArguments); + if (Result == null) + { return null; + } } while (!ConsumeIf("E")) { BaseNode SimpleId = ParseSimpleId(); if (SimpleId == null) + { return null; - Res = new QualifiedName(Res, SimpleId); - if (Res == null) - return null; + } + Result = new QualifiedName(Result, SimpleId); + if (Result == null) + { + return null; + } } BaseNode BaseName = ParseBaseUnresolvedName(); if (BaseName == null) + { return null; - return new QualifiedName(Res, BaseName); + } + + return new QualifiedName(Result, BaseName); } bool IsGlobal = ConsumeIf("gs"); @@ -2308,12 +2866,18 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler // ::= [gs] # x or (with "gs") ::x if (!ConsumeIf("sr")) { - Res = ParseBaseUnresolvedName(); - if (Res == null) + Result = ParseBaseUnresolvedName(); + if (Result == null) + { return null; + } + if (IsGlobal) - Res = new GlobalQualifiedName(Res); - return Res; + { + Result = new GlobalQualifiedName(Result); + } + + return Result; } // ::= [gs] sr + E @@ -2323,43 +2887,66 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Qualifier = ParseSimpleId(); if (Qualifier == null) + { return null; - if (Res != null) - Res = new QualifiedName(Res, Qualifier); + } + + if (Result != null) + { + Result = new QualifiedName(Result, Qualifier); + } else if (IsGlobal) - Res = new GlobalQualifiedName(Qualifier); + { + Result = new GlobalQualifiedName(Qualifier); + } else - Res = Qualifier; - if (Res == null) + { + Result = Qualifier; + } + + if (Result == null) + { return null; + } } while (!ConsumeIf("E")); } // ::= sr [tempate-args] # T::x / decltype(p)::x else { - Res = ParseUnresolvedType(); - if (Res == null) + Result = ParseUnresolvedType(); + if (Result == null) + { return null; + } if (Peek() == 'I') { BaseNode TemplateArguments = ParseTemplateArguments(); if (TemplateArguments == null) + { return null; - Res = new NameTypeWithTemplateArguments(Res, TemplateArguments); - if (Res == null) + } + + Result = new NameTypeWithTemplateArguments(Result, TemplateArguments); + if (Result == null) + { return null; + } } } - if (Res == null) + if (Result == null) + { return null; + } BaseNode BaseUnresolvedName = ParseBaseUnresolvedName(); if (BaseUnresolvedName == null) + { return null; + } - return new QualifiedName(Res, BaseUnresolvedName); + return new QualifiedName(Result, BaseUnresolvedName); } // ::= @@ -2370,7 +2957,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode UnresolvedName = ParseUnresolvedName(Context); if (UnresolvedName == null) + { return null; + } + return new StdQualifiedName(UnresolvedName); } return ParseUnresolvedName(Context); @@ -2382,25 +2972,38 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { // Impossible in theory if (Consume() != 'N') + { return null; - BaseNode Res = null; + } + + BaseNode Result = null; CVType CV = new CVType(ParseCVQualifiers(), null); if (Context != null) + { Context.CV = CV; + } + SimpleReferenceType Ref = ParseRefQualifiers(); if (Context != null) + { Context.Ref = Ref; + } if (ConsumeIf("St")) - Res = new NameType("std"); + { + Result = new NameType("std"); + } while (!ConsumeIf("E")) { // end if (ConsumeIf("M")) { - if (Res == null) + if (Result == null) + { return null; + } + continue; } char C = Peek(); @@ -2410,9 +3013,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode TemplateParam = ParseTemplateParam(); if (TemplateParam == null) + { return null; - Res = CreateNameNode(Res, TemplateParam, Context); - SubstitutionList.Add(Res); + } + + Result = CreateNameNode(Result, TemplateParam, Context); + SubstitutionList.Add(Result); continue; } @@ -2420,12 +3026,18 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler if (C == 'I') { BaseNode TemplateArgument = ParseTemplateArguments(Context != null); - if (TemplateArgument == null || Res == null) + if (TemplateArgument == null || Result == null) + { return null; - Res = new NameTypeWithTemplateArguments(Res, TemplateArgument); + } + + Result = new NameTypeWithTemplateArguments(Result, TemplateArgument); if (Context != null) + { Context.FinishWithTemplateArguments = true; - SubstitutionList.Add(Res); + } + + SubstitutionList.Add(Result); continue; } @@ -2434,9 +3046,12 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Decltype = ParseDecltype(); if (Decltype == null) + { return null; - Res = CreateNameNode(Res, Decltype, Context); - SubstitutionList.Add(Res); + } + + Result = CreateNameNode(Result, Decltype, Context); + SubstitutionList.Add(Result); continue; } @@ -2445,10 +3060,16 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Substitution = ParseSubstitution(); if (Substitution == null) + { return null; - Res = CreateNameNode(Res, Substitution, Context); - if (Res != Substitution) + } + + Result = CreateNameNode(Result, Substitution, Context); + if (Result != Substitution) + { SubstitutionList.Add(Substitution); + } + continue; } @@ -2456,19 +3077,27 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler if (C == 'C' || (C == 'D' && Peek(1) != 'C')) { // We cannot have nothing before this - if (Res == null) + if (Result == null) + { return null; - BaseNode CtOrDtorName = ParseCtorDtorName(Context, Res); + } + + BaseNode CtOrDtorName = ParseCtorDtorName(Context, Result); if (CtOrDtorName == null) + { return null; - Res = CreateNameNode(Res, CtOrDtorName, Context); + } + + Result = CreateNameNode(Result, CtOrDtorName, Context); // TODO: ABI Tags (before) - if (Res == null) + if (Result == null) + { return null; + } - SubstitutionList.Add(Res); + SubstitutionList.Add(Result); continue; } @@ -2477,15 +3106,17 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { return null; } - Res = CreateNameNode(Res, UnqualifiedName, Context); + Result = CreateNameNode(Result, UnqualifiedName, Context); - SubstitutionList.Add(Res); + SubstitutionList.Add(Result); } - if (Res == null || SubstitutionList.Count == 0) + if (Result == null || SubstitutionList.Count == 0) + { return null; + } SubstitutionList.RemoveAt(SubstitutionList.Count - 1); - return Res; + return Result; } // ::= _ # when number < 10 @@ -2493,7 +3124,9 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private void ParseDiscriminator() { if (Count() == 0) + { return; + } // We ignore the discriminator, we don't need it. if (ConsumeIf("_")) { @@ -2512,10 +3145,16 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler private BaseNode ParseLocalName(NameParserContext Context) { if (!ConsumeIf("Z")) + { return null; + } + BaseNode Encoding = ParseEncoding(); if (Encoding == null || !ConsumeIf("E")) + { return null; + } + BaseNode EntityName; if (ConsumeIf("s")) { @@ -2526,16 +3165,25 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { ParseNumber(true); if (!ConsumeIf("_")) + { return null; + } + EntityName = ParseName(Context); if (EntityName == null) + { return null; + } + return new LocalName(Encoding, EntityName); } EntityName = ParseName(Context); if (EntityName == null) + { return null; + } + ParseDiscriminator(); return new LocalName(Encoding, EntityName); } @@ -2549,42 +3197,66 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler ConsumeIf("L"); if (Peek() == 'N') + { return ParseNestedName(Context); + } if (Peek() == 'Z') + { return ParseLocalName(Context); + } if (Peek() == 'S' && Peek(1) != 't') { BaseNode Substitution = ParseSubstitution(); if (Substitution == null) + { return null; + } + if (Peek() != 'I') + { return null; + } + BaseNode TemplateArguments = ParseTemplateArguments(Context != null); if (TemplateArguments == null) + { return null; + } + if (Context != null) + { Context.FinishWithTemplateArguments = true; + } + return new NameTypeWithTemplateArguments(Substitution, TemplateArguments); } - BaseNode Res = ParseUnscopedName(Context); - if (Res == null) + BaseNode Result = ParseUnscopedName(Context); + if (Result == null) + { return null; + } if (Peek() == 'I') { - SubstitutionList.Add(Res); + SubstitutionList.Add(Result); BaseNode TemplateArguments = ParseTemplateArguments(Context != null); if (TemplateArguments == null) + { return null; + } + if (Context != null) + { Context.FinishWithTemplateArguments = true; - return new NameTypeWithTemplateArguments(Res, TemplateArguments); + } + + return new NameTypeWithTemplateArguments(Result, TemplateArguments); } - return Res; + return Result; } private bool IsEncodingEnd() @@ -2600,15 +3272,22 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { NameParserContext Context = new NameParserContext(); if (Peek() == 'T' || (Peek() == 'G' && Peek(1) == 'V')) + { return ParseSpecialName(Context); + } + BaseNode Name = ParseName(Context); if (Name == null) + { return null; + } // TODO: compute template refs here if (IsEncodingEnd()) + { return Name; + } // TODO: Ua9enable_ifI @@ -2617,11 +3296,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { ReturnType = ParseType(); if (ReturnType == null) + { return null; + } } if (ConsumeIf("v")) + { return new EncodedFunction(Name, null, Context.CV, Context.Ref, null, ReturnType); + } List Params = new List(); @@ -2633,7 +3316,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler { BaseNode Param = ParseType(); if (Param == null) + { return null; + } + Params.Add(Param); } @@ -2667,13 +3353,15 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler public static string Parse(string OriginalMangled) { Demangler Instance = new Demangler(OriginalMangled); - BaseNode ResNode = Instance.Parse(); + BaseNode ResNode = Instance.Parse(); + if (ResNode != null) { StringWriter Writer = new StringWriter(); ResNode.Print(Writer); return Writer.ToString(); } + return OriginalMangled; } }