/// <summary> /// /// </summary> /// <param name="Texts"></param> /// <returns></returns> private string Expand(string Text, Dictionary <string, string> Locals = null, HashSet <string> Used = null) { if (Used == null) { Used = new HashSet <string>(); } string Output = ""; var Tokens = new CTokenReader(new CTokenizer(Text, TokenizeSpaces: true).Tokenize()); Tokens.MoveNextSpace(); while (Tokens.HasMore) { bool Stringify = false; if (Locals != null && Tokens.Current.Raw == "##") { Tokens.MoveNextSpace(); } if (Tokens.Current.Raw == "#") { Tokens.MoveNextSpace(); if (Tokens.Current.Type == CTokenType.Identifier) { Stringify = true; } else { Stringify = false; Output += "#"; } } if (Tokens.Current.Type == CTokenType.Identifier) { var CurrentIdentifier = Tokens.Current.Raw; var UpdatedIdentifier = ReplaceSimpleVariable(CurrentIdentifier); if (UpdatedIdentifier != CurrentIdentifier) { Output += UpdatedIdentifier; Tokens.MoveNextSpace(); continue; } switch (CurrentIdentifier) { case "__VA_ARGS__": CurrentIdentifier = "..."; break; } if (Locals != null && Locals.ContainsKey(CurrentIdentifier)) { CurrentIdentifier = Locals[CurrentIdentifier]; if (Stringify) { CurrentIdentifier = CToken.Stringify(CurrentIdentifier); } Output += CurrentIdentifier; Tokens.MoveNextSpace(); } else if (!Used.Contains(CurrentIdentifier) && Context.Macros.ContainsKey(CurrentIdentifier)) { var Macro = Context.Macros[CurrentIdentifier]; // Constant if (Macro is MacroConstant) { Output += Expand(Macro.Replacement, null, new HashSet <string>(Used.Concat(new[] { CurrentIdentifier }))); Tokens.MoveNextSpace(); } // Function else { Tokens.MoveNextNoSpace(); Tokens.ExpectCurrent("("); var MacroFunction = Context.Macros[CurrentIdentifier] as MacroFunction; if (MacroFunction == null) { throw (new Exception("Trying to call a non-function macro")); } //Console.WriteLine(":: {0} :: ", Text); var Parameters = ParseParameterList(Tokens, JustIdentifiers: false); for (int n = 0; n < Parameters.Length; n++) { //Console.WriteLine(" {0}", Parameters[n]); Parameters[n] = Expand(Parameters[n], Locals, Used); //Console.WriteLine(" -> {0}", Parameters[n]); } var Map = MapFunctionParameters(MacroFunction.Parameters, Parameters); //foreach (var Item in Map) Console.WriteLine("{0} -> {1}", Item.Key, Item.Value); Output += Expand(MacroFunction.Replacement, Map, new HashSet <string>(new[] { CurrentIdentifier })); } } else { Output += CurrentIdentifier; Tokens.MoveNextSpace(); } } else { Output += Tokens.Current.Raw; Tokens.MoveNextSpace(); } } return(Output); }