// 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();
}
}
}