2008-12-09 20:55:34 +00:00
|
|
|
|
#region CPL License
|
|
|
|
|
/*
|
|
|
|
|
Nuclex Framework
|
2009-01-07 19:05:29 +00:00
|
|
|
|
Copyright (C) 2002-2009 Nuclex Development Labs
|
2008-12-09 20:55:34 +00:00
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the IBM Common Public License as
|
|
|
|
|
published by the IBM Corporation; either version 1.0 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
IBM Common Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the IBM Common Public
|
|
|
|
|
License along with this library
|
|
|
|
|
*/
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
using System.Diagnostics;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
using System.IO;
|
2008-12-09 20:55:34 +00:00
|
|
|
|
|
|
|
|
|
namespace Nuclex.Support.Parsing {
|
|
|
|
|
|
|
|
|
|
partial class CommandLine {
|
|
|
|
|
|
|
|
|
|
/// <summary>Parses command line strings</summary>
|
2008-12-10 19:26:25 +00:00
|
|
|
|
private class Parser {
|
|
|
|
|
|
|
|
|
|
/// <summary>Initializes a new command line parser</summary>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
/// <param name="windowsMode">Whether the / character initiates an argument</param>
|
|
|
|
|
private Parser(bool windowsMode) {
|
|
|
|
|
this.windowsMode = windowsMode;
|
2009-04-15 19:54:01 +00:00
|
|
|
|
this.arguments = new List<CommandLine.Argument>();
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
2008-12-09 20:55:34 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>Parses a string containing command line arguments</summary>
|
|
|
|
|
/// <param name="commandLineString">String that will be parsed</param>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
/// <param name="windowsMode">Whether the / character initiates an argument</param>
|
2008-12-09 20:55:34 +00:00
|
|
|
|
/// <returns>The parsed command line arguments from the string</returns>
|
2009-04-15 19:54:01 +00:00
|
|
|
|
public static List<CommandLine.Argument> Parse(
|
|
|
|
|
string commandLineString, bool windowsMode
|
|
|
|
|
) {
|
2008-12-11 20:15:21 +00:00
|
|
|
|
Parser theParser = new Parser(windowsMode);
|
|
|
|
|
theParser.parseFullCommandLine(commandLineString);
|
2009-04-15 19:54:01 +00:00
|
|
|
|
return theParser.arguments;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if ENABLE_TOKENIZED_COMMAND_LINE_PARSING // don't enable, it's broken!
|
|
|
|
|
/// <summary>Parses a string containing command line arguments</summary>
|
|
|
|
|
/// <param name="commandLineArguments">Command line tokens that will be parsed</param>
|
|
|
|
|
/// <param name="windowsMode">Whether the / character initiates an argument</param>
|
|
|
|
|
/// <returns>The parsed command line arguments from the string</returns>
|
|
|
|
|
public static List<CommandLine.Argument> Parse(
|
|
|
|
|
string[] commandLineArguments, bool windowsMode
|
|
|
|
|
) {
|
|
|
|
|
Parser theParser = new Parser(windowsMode);
|
|
|
|
|
theParser.parseSplitCommandLine(commandLineArguments);
|
|
|
|
|
return theParser.arguments;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
2009-04-15 19:54:01 +00:00
|
|
|
|
#endif // ENABLE_TOKENIZED_COMMAND_LINE_PARSING
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses the provided string and adds the parameters found to
|
|
|
|
|
/// the command line representation
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="commandLineString">
|
|
|
|
|
/// String containing the command line arguments that will be parsed
|
|
|
|
|
/// </param>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
private void parseFullCommandLine(string commandLineString) {
|
2008-12-09 20:55:34 +00:00
|
|
|
|
if(commandLineString == null) {
|
2008-12-10 19:26:25 +00:00
|
|
|
|
return;
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
// Walk through the command line character by character and gather
|
|
|
|
|
// the parameters and values to build the command line representation from
|
2008-12-09 20:55:34 +00:00
|
|
|
|
for(int index = 0; index < commandLineString.Length; ) {
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
// Look for the next non-whitespace character
|
|
|
|
|
index = StringHelper.IndexNotOfAny(
|
|
|
|
|
commandLineString, WhitespaceCharacters, index
|
|
|
|
|
);
|
|
|
|
|
if(index == -1) {
|
|
|
|
|
break;
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
// Parse the chunk of characters at this location and advance the index
|
|
|
|
|
// to the next location after the chunk of characters
|
2008-12-11 20:15:21 +00:00
|
|
|
|
parseChunk(commandLineString, ref index);
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-15 19:54:01 +00:00
|
|
|
|
#if ENABLE_TOKENIZED_COMMAND_LINE_PARSING // don't enable, it's broken!
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses the command line from a series pre-split argument tokens
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="commandLineParts">Split argument tokens that will be parsed</param>
|
|
|
|
|
private void parseSplitCommandLine(string[] commandLineParts) {
|
|
|
|
|
if(commandLineParts == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Walk through the command line character by character and gather
|
|
|
|
|
// the parameters and values to build the command line representation from
|
|
|
|
|
for(int index = 0; index < commandLineParts.Length; ++index) {
|
|
|
|
|
|
|
|
|
|
if(commandLineParts[index] != null) {
|
|
|
|
|
int characterIndex = 0;
|
|
|
|
|
parseChunk(commandLineParts[index], ref characterIndex);
|
|
|
|
|
|
|
|
|
|
Debug.Assert(characterIndex == commandLineParts[index].Length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif // ENABLE_TOKENIZED_COMMAND_LINE_PARSING
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Parses a chunk of characters and adds it as an option or a loose value to
|
|
|
|
|
/// the command line representation we're building
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="commandLineString">
|
|
|
|
|
/// String containing the chunk of characters that will be parsed
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="index">Index in the string at which to begin parsing</param>
|
|
|
|
|
/// <returns>The number of characters that were consumed</returns>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
private void parseChunk(string commandLineString, ref int index) {
|
2008-12-10 19:26:25 +00:00
|
|
|
|
int startIndex = index;
|
|
|
|
|
|
|
|
|
|
char currentCharacter = commandLineString[index];
|
|
|
|
|
switch(currentCharacter) {
|
|
|
|
|
|
|
|
|
|
// Unix style argument using either '-' or "--" as its initiator
|
|
|
|
|
case '-': {
|
|
|
|
|
++index;
|
|
|
|
|
|
|
|
|
|
// Does the string end here? Stop parsing.
|
|
|
|
|
if(index >= commandLineString.Length) {
|
2009-04-15 19:54:01 +00:00
|
|
|
|
addValue(new StringSegment(commandLineString, startIndex, 1));
|
2008-12-09 20:55:34 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
|
|
|
|
// Does another '-' follow? Might be a unix style option or a loose "--"
|
|
|
|
|
if(commandLineString[index] == '-') {
|
|
|
|
|
++index;
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
parsePotentialOption(commandLineString, startIndex, ref index);
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Windows style argument using '/' as its initiator
|
|
|
|
|
case '/': {
|
2008-12-11 20:15:21 +00:00
|
|
|
|
// The '/ character is only used to initiate argument on windows and can be
|
2009-04-14 20:25:56 +00:00
|
|
|
|
// toggled off. The application decides whether this is done depending on the
|
2008-12-11 20:15:21 +00:00
|
|
|
|
// operating system or whether uniform behavior across platforms is desired.
|
|
|
|
|
if(!this.windowsMode) {
|
|
|
|
|
goto default;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
++index;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
parsePotentialOption(commandLineString, startIndex, ref index);
|
2008-12-10 19:26:25 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Quoted loose value
|
|
|
|
|
case '"': {
|
2008-12-11 20:15:21 +00:00
|
|
|
|
parseQuotedValue(commandLineString, ref index);
|
2008-12-10 19:26:25 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unquoted loose value
|
|
|
|
|
default: {
|
2008-12-11 20:15:21 +00:00
|
|
|
|
parseNakedValue(commandLineString, ref index);
|
2008-12-10 19:26:25 +00:00
|
|
|
|
break;
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
/// <summary>Parses a potential command line option</summary>
|
|
|
|
|
/// <param name="commandLineString">String containing the command line arguments</param>
|
|
|
|
|
/// <param name="initiatorStartIndex">
|
|
|
|
|
/// Index of the option's initiator ('-' or '--' or '/')
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="index">
|
|
|
|
|
/// Index at which the option name is supposed start (if it's an actual option)
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns>The number of characters consumed</returns>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
private void parsePotentialOption(
|
2009-04-15 19:54:01 +00:00
|
|
|
|
string commandLineString, int initiatorStartIndex, ref int index
|
2008-12-09 20:55:34 +00:00
|
|
|
|
) {
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
|
|
|
|
// If the string ends here this can only be considered as a loose value
|
2008-12-11 20:15:21 +00:00
|
|
|
|
if(index == commandLineString.Length) {
|
2009-04-15 19:54:01 +00:00
|
|
|
|
addValue(
|
2008-12-11 20:15:21 +00:00
|
|
|
|
new StringSegment(
|
|
|
|
|
commandLineString,
|
|
|
|
|
initiatorStartIndex,
|
|
|
|
|
commandLineString.Length - initiatorStartIndex
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
return;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
int nameStartIndex = index;
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
// Look for the first character that ends the option. If it is not an actual option,
|
|
|
|
|
// the very first character might be the end
|
2009-04-14 20:25:56 +00:00
|
|
|
|
if(commandLineString[index] != commandLineString[initiatorStartIndex]) {
|
|
|
|
|
index = commandLineString.IndexOfAny(NameEndingCharacters, nameStartIndex);
|
|
|
|
|
if(index == -1) {
|
|
|
|
|
index = commandLineString.Length;
|
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
|
|
|
|
// If the first character of the supposed option is not valid for an option name,
|
2008-12-10 19:26:25 +00:00
|
|
|
|
// we have to consider this to be a loose value
|
2009-04-14 20:25:56 +00:00
|
|
|
|
if((index == nameStartIndex)/* && !isAssignmentCharacter(commandLineString[index])*/) {
|
2008-12-11 20:15:21 +00:00
|
|
|
|
index = commandLineString.IndexOfAny(WhitespaceCharacters, index);
|
|
|
|
|
if(index == -1) {
|
|
|
|
|
index = commandLineString.Length;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
2009-04-15 19:54:01 +00:00
|
|
|
|
addValue(
|
2008-12-11 20:15:21 +00:00
|
|
|
|
new StringSegment(
|
|
|
|
|
commandLineString, initiatorStartIndex, index - initiatorStartIndex
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
return;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
2009-04-14 20:25:56 +00:00
|
|
|
|
parsePotentialOptionAssignment(
|
2008-12-11 20:15:21 +00:00
|
|
|
|
commandLineString, initiatorStartIndex, nameStartIndex, ref index
|
2008-12-10 19:26:25 +00:00
|
|
|
|
);
|
2009-04-14 20:25:56 +00:00
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
/// <summary>Parses the value assignment in a command line option</summary>
|
|
|
|
|
/// <param name="commandLineString">String containing the command line arguments</param>
|
|
|
|
|
/// <param name="initiatorStartIndex">
|
|
|
|
|
/// Position of the character that started the option
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="nameStartIndex">
|
|
|
|
|
/// Position of the first character in the option's name
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="index">Index at which the option name ended</param>
|
2009-04-14 20:25:56 +00:00
|
|
|
|
private void parsePotentialOptionAssignment(
|
2009-04-15 19:54:01 +00:00
|
|
|
|
string commandLineString, int initiatorStartIndex, int nameStartIndex, ref int index
|
2008-12-11 20:15:21 +00:00
|
|
|
|
) {
|
|
|
|
|
int nameEndIndex = index;
|
|
|
|
|
int valueStartIndex;
|
|
|
|
|
int valueEndIndex;
|
|
|
|
|
|
2009-04-14 20:25:56 +00:00
|
|
|
|
// See if this is an assignment character. If it is, the assigned value
|
|
|
|
|
// should follow to the right.
|
|
|
|
|
bool isAssignment =
|
|
|
|
|
(index < commandLineString.Length) &&
|
|
|
|
|
isAssignmentCharacter(commandLineString[index]);
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
2009-04-14 20:25:56 +00:00
|
|
|
|
// If it's an assignment, we can proceed parsing the assigned value
|
|
|
|
|
if(isAssignment) {
|
|
|
|
|
++index;
|
|
|
|
|
parseOptionValue(commandLineString, initiatorStartIndex, nameStartIndex, ref index);
|
|
|
|
|
return;
|
|
|
|
|
} else { // No, it's an option name without an assignment
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
2009-04-14 20:25:56 +00:00
|
|
|
|
bool isModifier =
|
|
|
|
|
(commandLineString[index - 1] == '+') ||
|
|
|
|
|
(commandLineString[index - 1] == '-');
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
2009-04-14 20:25:56 +00:00
|
|
|
|
if(isModifier) {
|
|
|
|
|
valueStartIndex = index - 1;
|
|
|
|
|
valueEndIndex = index;
|
|
|
|
|
--nameEndIndex;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
} else {
|
2009-04-14 20:25:56 +00:00
|
|
|
|
valueStartIndex = -1;
|
|
|
|
|
valueEndIndex = -1;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int argumentLength = index - initiatorStartIndex;
|
2009-04-15 19:54:01 +00:00
|
|
|
|
this.arguments.Add(
|
2009-04-14 20:25:56 +00:00
|
|
|
|
new Argument(
|
2008-12-11 20:15:21 +00:00
|
|
|
|
new StringSegment(commandLineString, initiatorStartIndex, argumentLength),
|
|
|
|
|
nameStartIndex, nameEndIndex - nameStartIndex,
|
|
|
|
|
valueStartIndex, valueEndIndex - valueStartIndex
|
|
|
|
|
)
|
|
|
|
|
);
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
/// <summary>Parses the value assignment in a command line option</summary>
|
|
|
|
|
/// <param name="commandLineString">String containing the command line arguments</param>
|
|
|
|
|
/// <param name="initiatorStartIndex">
|
|
|
|
|
/// Position of the character that started the option
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="nameStartIndex">
|
|
|
|
|
/// Position of the first character in the option's name
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <param name="index">Index at which the option name ended</param>
|
|
|
|
|
private void parseOptionValue(
|
2009-04-15 19:54:01 +00:00
|
|
|
|
string commandLineString, int initiatorStartIndex, int nameStartIndex, ref int index
|
2008-12-11 20:15:21 +00:00
|
|
|
|
) {
|
2009-04-14 20:25:56 +00:00
|
|
|
|
int nameEndIndex = index - 1;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
int valueStartIndex, valueEndIndex;
|
|
|
|
|
|
|
|
|
|
// Does the string end after the suspected assignment character?
|
2009-04-14 20:25:56 +00:00
|
|
|
|
bool argumentEndReached = (index == commandLineString.Length);
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
|
|
|
|
if(argumentEndReached) {
|
|
|
|
|
valueStartIndex = -1;
|
|
|
|
|
valueEndIndex = -1;
|
|
|
|
|
} else {
|
2009-04-14 20:25:56 +00:00
|
|
|
|
char nextCharacter = commandLineString[index];
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
|
|
|
|
// Is this a quoted assignment
|
|
|
|
|
if(nextCharacter == '"') {
|
2009-04-14 20:25:56 +00:00
|
|
|
|
++index;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
valueStartIndex = index;
|
|
|
|
|
index = commandLineString.IndexOf('"', index);
|
|
|
|
|
if(index == -1) {
|
|
|
|
|
index = commandLineString.Length;
|
|
|
|
|
valueEndIndex = index;
|
|
|
|
|
} else {
|
|
|
|
|
valueEndIndex = index;
|
|
|
|
|
++index;
|
|
|
|
|
}
|
|
|
|
|
} else { // Nope, assuming unquoted assignment or empty assignment
|
|
|
|
|
valueStartIndex = index;
|
|
|
|
|
index = commandLineString.IndexOfAny(WhitespaceCharacters, index);
|
|
|
|
|
if(index == -1) {
|
|
|
|
|
index = commandLineString.Length;
|
|
|
|
|
valueEndIndex = index;
|
|
|
|
|
} else {
|
|
|
|
|
if(index == valueStartIndex) {
|
|
|
|
|
valueStartIndex = -1;
|
|
|
|
|
valueEndIndex = -1;
|
|
|
|
|
} else {
|
|
|
|
|
valueEndIndex = index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int argumentLength = index - initiatorStartIndex;
|
2009-04-15 19:54:01 +00:00
|
|
|
|
this.arguments.Add(
|
2009-04-14 20:25:56 +00:00
|
|
|
|
new Argument(
|
2008-12-11 20:15:21 +00:00
|
|
|
|
new StringSegment(commandLineString, initiatorStartIndex, argumentLength),
|
|
|
|
|
nameStartIndex, nameEndIndex - nameStartIndex,
|
|
|
|
|
valueStartIndex, valueEndIndex - valueStartIndex
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>Parses a quoted value from the input string</summary>
|
|
|
|
|
/// <param name="commandLineString">String the quoted value is parsed from</param>
|
|
|
|
|
/// <param name="index">Index at which the quoted value begins</param>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
private void parseQuotedValue(string commandLineString, ref int index) {
|
2009-04-14 20:25:56 +00:00
|
|
|
|
int startIndex = index;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
char quoteCharacter = commandLineString[index];
|
2009-04-14 20:25:56 +00:00
|
|
|
|
int valueIndex = startIndex + 1;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
|
|
|
|
|
// Search for the closing quote
|
2009-04-14 20:25:56 +00:00
|
|
|
|
index = commandLineString.IndexOf(quoteCharacter, valueIndex);
|
2008-12-11 20:15:21 +00:00
|
|
|
|
if(index == -1) {
|
|
|
|
|
index = commandLineString.Length; // value ends at string end
|
2009-04-15 19:54:01 +00:00
|
|
|
|
this.arguments.Add(
|
2009-04-14 20:25:56 +00:00
|
|
|
|
Argument.ValueOnly(
|
|
|
|
|
new StringSegment(commandLineString, startIndex, index - startIndex),
|
|
|
|
|
valueIndex, index - valueIndex
|
|
|
|
|
)
|
2008-12-11 20:15:21 +00:00
|
|
|
|
);
|
|
|
|
|
} else { // A closing quote was found
|
2009-04-15 19:54:01 +00:00
|
|
|
|
this.arguments.Add(
|
2009-04-14 20:25:56 +00:00
|
|
|
|
Argument.ValueOnly(
|
|
|
|
|
new StringSegment(commandLineString, startIndex, index - startIndex + 1),
|
|
|
|
|
valueIndex, index - valueIndex
|
|
|
|
|
)
|
2008-12-11 20:15:21 +00:00
|
|
|
|
);
|
|
|
|
|
++index; // Skip the closing quote
|
2008-12-10 19:26:25 +00:00
|
|
|
|
}
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-12-10 19:26:25 +00:00
|
|
|
|
/// <summary>Parses a plain, unquoted value from the input string</summary>
|
|
|
|
|
/// <param name="commandLineString">String containing the value to be parsed</param>
|
|
|
|
|
/// <param name="index">Index at which the value begins</param>
|
2008-12-11 20:15:21 +00:00
|
|
|
|
private void parseNakedValue(string commandLineString, ref int index) {
|
|
|
|
|
int startIndex = index;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
index = commandLineString.IndexOfAny(WhitespaceCharacters, index);
|
|
|
|
|
if(index == -1) {
|
|
|
|
|
index = commandLineString.Length;
|
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2009-04-15 19:54:01 +00:00
|
|
|
|
addValue(new StringSegment(commandLineString, startIndex, index - startIndex));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>Adds a loose value to the command line</summary>
|
|
|
|
|
/// <param name="value">Value taht will be added</param>
|
|
|
|
|
private void addValue(StringSegment value) {
|
|
|
|
|
this.arguments.Add(
|
|
|
|
|
Argument.ValueOnly(value, value.Offset, value.Count)
|
2008-12-11 20:15:21 +00:00
|
|
|
|
);
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2009-04-14 20:25:56 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Determines whether the specified character indicates an assignment
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="character">
|
|
|
|
|
/// Character that will be checked for being an assignemnt
|
|
|
|
|
/// </param>
|
|
|
|
|
/// <returns>
|
|
|
|
|
/// True if the specified character indicated an assignment, otherwise false
|
|
|
|
|
/// </returns>
|
|
|
|
|
private static bool isAssignmentCharacter(char character) {
|
|
|
|
|
return (character == ':') || (character == '=');
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-11 20:15:21 +00:00
|
|
|
|
/// <summary>Characters which end an option name when they are encountered</summary>
|
2009-04-14 20:25:56 +00:00
|
|
|
|
private static readonly char[] NameEndingCharacters = new char[] {
|
|
|
|
|
' ', '\t', '=', ':', '"'
|
2008-12-11 20:15:21 +00:00
|
|
|
|
};
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>Characters the parser considers to be whitespace</summary>
|
2008-12-09 20:55:34 +00:00
|
|
|
|
private static readonly char[] WhitespaceCharacters = new char[] { ' ', '\t' };
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2009-04-15 19:54:01 +00:00
|
|
|
|
/// <summary>Argument list being filled by the parser</summary>
|
|
|
|
|
private List<CommandLine.Argument> arguments;
|
2008-12-11 20:15:21 +00:00
|
|
|
|
/// <summary>Whether the '/' character initiates an argument</summary>
|
|
|
|
|
private bool windowsMode;
|
2008-12-10 19:26:25 +00:00
|
|
|
|
|
2008-12-09 20:55:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Nuclex.Support.Parsing
|