// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EpicGames.Core; namespace UnrealBuildTool { /// /// Stores information about a defined preprocessor macro /// class PreprocessorMacro { /// /// Name of the macro /// public Identifier Name; /// /// Parameter names for the macro. The '...' placeholder is represented by the __VA_ARGS__ string. /// public List? Parameters; /// /// Raw list of tokens for this macro /// public List Tokens; /// /// Construct a preprocessor macro /// /// Name of the macro /// Parameter list for the macro. Should be null for object macros. Ownership of this list is transferred. /// Tokens for the macro. Ownership of this list is transferred. public PreprocessorMacro(Identifier Name, List? Parameters, List Tokens) { this.Name = Name; this.Parameters = Parameters; this.Tokens = Tokens; } /// /// Read a macro from a binary archive /// /// Reader to serialize from public PreprocessorMacro(BinaryArchiveReader Reader) { Name = Reader.ReadIdentifier(); Parameters = Reader.ReadList(() => Reader.ReadIdentifier()); Tokens = Reader.ReadList(() => Reader.ReadToken()); } /// /// Write a macro to a binary archive /// /// Writer to serialize to public void Write(BinaryArchiveWriter Writer) { Writer.WriteIdentifier(Name); Writer.WriteList(Parameters, x => Writer.WriteIdentifier(x)); Writer.WriteList(Tokens, x => Writer.WriteToken(x)); } /// /// Finds the index of a parameter in the parameter list /// /// Parameter name to look for /// Index of the parameter, or -1 if it's not found. public int FindParameterIndex(Identifier Parameter) { for (int Idx = 0; Idx < Parameters!.Count; Idx++) { if (Parameters[Idx] == Parameter) { return Idx; } } return -1; } /// /// Checks whether this macro definition is equivalent to another macro definition /// /// The macro definition to compare against /// True if the macro definitions are equivalent public bool IsEquivalentTo(PreprocessorMacro Other) { if(this != Other) { if(Name != Other.Name || Tokens.Count != Other.Tokens.Count) { return false; } if(Parameters != null) { if(Other.Parameters == null || Other.Parameters.Count != Parameters.Count || !Enumerable.SequenceEqual(Parameters, Other.Parameters)) { return false; } } else { if(Other.Parameters != null) { return false; } } if(!Enumerable.SequenceEqual(Tokens, Other.Tokens)) { return false; } } return true; } /// /// True if the macro is an object macro /// public bool IsObjectMacro { get { return Parameters == null; } } /// /// True if the macro is a function macro /// public bool IsFunctionMacro { get { return Parameters != null; } } /// /// The number of required parameters. For variadic macros, the last parameter is optional. /// public int MinRequiredParameters { get { return HasVariableArgumentList? (Parameters!.Count - 1) : Parameters!.Count; } } /// /// True if the macro has a variable argument list /// public bool HasVariableArgumentList { get { return Parameters!.Count > 0 && Parameters[Parameters.Count - 1] == Identifiers.__VA_ARGS__; } } /// /// Converts this macro to a string for debugging /// /// The tokens in this macro public override string ToString() { StringBuilder Result = new StringBuilder(Name.ToString()); if (Parameters != null) { Result.AppendFormat("({0})", String.Join(", ", Parameters)); } Result.Append("="); if (Tokens.Count > 0) { Result.Append(Tokens[0].Text); for (int Idx = 1; Idx < Tokens.Count; Idx++) { if(Tokens[Idx].HasLeadingSpace) { Result.Append(" "); } Result.Append(Tokens[Idx].Text); } } return Result.ToString(); } } }