private List<Replacement> BuildReplacementList(string input)
{
var index = 0;
var replacements = new List<Replacement>();
do
{
var tokenStart = input.IndexOf("%", index, StringComparison.InvariantCulture);
if (tokenStart == -1)
break;
var tokenEnd = input.IndexOf("%", tokenStart + 1, StringComparison.InvariantCulture);
if (tokenEnd == -1)
break;
var tokenLength = tokenEnd - tokenStart + 1;
var variableNameStart = tokenStart + 1;
var variableNameLength = tokenLength - 2;
var isEnvironmentVariable = false;
var variableName = "";
if (tokenStart > 0)
{
var tokenStartPrefix = input.Substring(tokenStart - 1, 1).ToCharArray()[0];
var tokenEndPrefix = input.Substring(tokenEnd - 1, 1).ToCharArray()[0];
if (tokenStartPrefix == '\\' && tokenEndPrefix == '\\')
{
isEnvironmentVariable = true;
// Add the first backslash to the token
tokenStart--;
tokenLength++;
// Remove the last backslash from the name
variableNameLength--;
}
else if (tokenStartPrefix == '^' && tokenEndPrefix == '^')
{
// Add the first caret to the token
tokenStart--;
tokenLength++;
// Remove the last caret from the name
variableNameLength--;
variableName = input.Substring(variableNameStart, variableNameLength);
replacements.Add(new Replacement(tokenStart, tokenLength, $"%{variableName}%"));
index = tokenEnd;
continue;
}
}
var token = input.Substring(tokenStart, tokenLength);
var escape = DetermineEscapeType(token);
if (escape != EscapeType.All)
{
// Remove the escape character from the name
variableNameStart++;
variableNameLength--;
}
if (variableNameLength == 0)
{
index = tokenEnd;
continue;
}
variableName = input.Substring(variableNameStart, variableNameLength);
var replacementValue = token;
if (!isEnvironmentVariable)
{
replacementValue = GetVariableReplacement(variableName, token);
}
var haveReplacement = false;
if (replacementValue != token)
{
haveReplacement = true;
}
else
{
replacementValue = Environment.GetEnvironmentVariable(variableName);
if (replacementValue != null)
haveReplacement = true;
}
if (haveReplacement)
{
var trailing = tokenEnd + 2 <= input.Length ? input.Substring(tokenEnd + 1, 1).ToCharArray()[0] : '\0';
if (escape == EscapeType.All)
{
replacementValue = CommandLineArguments.EscapeBackslashes(replacementValue);
if (trailing == '\'')
replacementValue = CommandLineArguments.EscapeBackslashesForTrailingQuote(replacementValue);
}
if (escape == EscapeType.All || escape == EscapeType.ShellMetacharacters)
replacementValue = CommandLineArguments.EscapeShellMetacharacters(replacementValue);
replacements.Add(new Replacement(tokenStart, tokenLength, replacementValue));
index = tokenEnd + 1;
}
else
{
index = tokenEnd;
}
} while (true);
return replacements;
}