diff options
author | Atsushi Kanamori <AtsushiKan@users.noreply.github.com> | 2017-06-15 17:19:25 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-15 17:19:25 +0300 |
commit | 3805f6558511e79f9367723147f1aeff1be4cc20 (patch) | |
tree | 36123bbeff11043c65bd0014033edb7d65d8d856 | |
parent | f60512cb5616edd1ed31ec5316c342655b5f8bae (diff) |
Make Environment.GetCommandLineArgs() work on Project N. (#3894)
3 files changed, 57 insertions, 34 deletions
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.ProjectN.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.ProjectN.cs index f0fbc7b20..f49f9cf92 100644 --- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.ProjectN.cs +++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.ProjectN.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Runtime; namespace Internal.Runtime.Augments { @@ -15,9 +16,6 @@ namespace Internal.Runtime.Augments throw new PlatformNotSupportedException(); } - public static string[] GetCommandLineArgs() - { - throw new PlatformNotSupportedException(SR.PlatformNotSupported_GetCommandLineArgs); - } + public static string[] GetCommandLineArgs() => CommandLine.InternalCreateCommandLine(includeArg0: true); } } diff --git a/src/System.Private.CoreLib/src/Resources/Strings.resx b/src/System.Private.CoreLib/src/Resources/Strings.resx index 9e8c957ee..53a8ed147 100644 --- a/src/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/System.Private.CoreLib/src/Resources/Strings.resx @@ -2449,7 +2449,4 @@ <data name="Arg_OpenType" xml:space="preserve"> <value>Cannot create an instance of {0} as it is an open type.</value> </data> - <data name="PlatformNotSupported_GetCommandLineArgs" xml:space="preserve"> - <value>Environment.GetCommandLineArgs() is not supported on this platform.</value> - </data> </root> diff --git a/src/System.Private.CoreLib/src/System/Runtime/CommandLine.Windows.cs b/src/System.Private.CoreLib/src/System/Runtime/CommandLine.Windows.cs index 73ffd6af6..6b018375e 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CommandLine.Windows.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CommandLine.Windows.cs @@ -20,16 +20,17 @@ namespace System.Runtime string[] commandLine = InternalCreateCommandLine(); return RawCalliHelper.Call<int>(pfnUserMain, commandLine); } - + [RuntimeExport("CreateCommandLine")] - public static unsafe string[] InternalCreateCommandLine() - { - char * pCmdLine = Interop.mincore.GetCommandLine(); + public static string[] InternalCreateCommandLine() => InternalCreateCommandLine(includeArg0: false); - int nArgs = SegmentCommandLine(pCmdLine, null); + internal static unsafe string[] InternalCreateCommandLine(bool includeArg0) + { + char* pCmdLine = Interop.mincore.GetCommandLine(); + int nArgs = SegmentCommandLine(pCmdLine, null, includeArg0); string[] argArray = new string[nArgs]; - SegmentCommandLine(pCmdLine, argArray); + SegmentCommandLine(pCmdLine, argArray, includeArg0); return argArray; } @@ -40,37 +41,32 @@ namespace System.Runtime // // This functions interface mimics the CommandLineToArgvW api. // - private static unsafe int SegmentCommandLine(char * pCmdLine, string[] argArray) + private static unsafe int SegmentCommandLine(char * pCmdLine, string[] argArray, bool includeArg0) { int nArgs = 0; - char c; - bool inquote; - - // First, parse the program name (argv[0]). Argv[0] is parsed under special rules. Anything up to - // the first whitespace outside a quoted subtring is accepted. Backslashes are treated as normal - // characters. char* psrc = pCmdLine; - inquote = false; - do { - if (*psrc == '"') + // First, parse the program name (argv[0]). Argv[0] is parsed under special rules. Anything up to + // the first whitespace outside a quoted subtring is accepted. Backslashes are treated as normal + // characters. + char* psrcOrig = psrc; + + int arg0Len = ScanArgument0(ref psrc, null); + if (includeArg0) { - inquote = !inquote; - c = *psrc++; - continue; + if (argArray != null) + { + char[] arg0 = new char[arg0Len]; + ScanArgument0(ref psrcOrig, arg0); + argArray[nArgs] = new string(arg0); + } + nArgs++; } - - c = *psrc++; - } while ((c != '\0' && (inquote || (c != ' ' && c != '\t')))); - - if (c == '\0') - { - psrc--; } - inquote = false; + bool inquote = false; // loop on each argument for (;;) @@ -106,6 +102,38 @@ namespace System.Runtime return nArgs; } + private static unsafe int ScanArgument0(ref char* psrc, char[] arg) + { + // Argv[0] is parsed under special rules. Anything up to + // the first whitespace outside a quoted subtring is accepted. Backslashes are treated as normal + // characters. + int charIdx = 0; + bool inquote = false; + for (;;) + { + char c = *psrc++; + if (c == '"') + { + inquote = !inquote; + continue; + } + + if (c == '\0' || (!inquote && (c == ' ' || c == '\t'))) + { + psrc--; + break; + } + + if (arg != null) + { + arg[charIdx] = c; + } + charIdx++; + } + + return charIdx; + } + private static unsafe int ScanArgument(ref char* psrc, ref bool inquote, char[] arg) { int charIdx = 0; |