Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Verbose mode prints command line, temp file name

  • Loading branch information...
commit 0e70e41e13772a14e12835cbeabec377c63688ba 1 parent c3d04d5
damageboy authored
1  .gitignore
@@ -2,3 +2,4 @@ Daemaged.InlineIL/bin
2 2 Daemaged.InlineIL/obj
3 3 *.suo
4 4 *.user
  5 +*.suo
100 Daemaged.InlineIL.Demos/Filter_CSharp.cs
... ... @@ -1,51 +1,51 @@
1   -using System;
2   -class Foo
3   -{
4   - static void ThrowMe()
5   - {
6   - throw new ArgumentException();
7   - }
8   -
9   - static void Main()
10   - {
11   - string x;
12   - object ex = null;
13   -#if IL
14   - // declare a new local.
15   - .locals init (int32 ghi)
16   -
17   - .try
18   - {
19   -#endif
20   - x = "a";
21   - ThrowMe();
22   -
23   -#if IL
24   - leave.s IL_ExitTryCatch
25   - } // end try block
26   - filter
27   - {
28   - // Exception object is on the stack.
29   - stloc ex
30   -#endif
31   - Console.WriteLine("Inside Filter. Object=" + ex);
32   - x += "b";
33   -
34   -#if IL
35   - ldc.i4.1 // true - execute handler
36   - endfilter
37   - } // end filter
38   - { // begin handler
39   -#endif
40   - Console.WriteLine("Yow! In handler now!");
41   - x += "c";
42   -#if IL
43   - leave.s IL_ExitTryCatch
44   - } // end handler
45   - IL_ExitTryCatch: nop
46   -#endif
47   -
48   - Console.WriteLine("Back in C#");
49   - Console.WriteLine(x);
50   - } // end Main
  1 +using System;
  2 +class Foo
  3 +{
  4 + static void ThrowMe()
  5 + {
  6 + throw new ArgumentException();
  7 + }
  8 +
  9 + static void Main()
  10 + {
  11 + string x;
  12 + object ex = null;
  13 +#if IL
  14 + // declare a new local.
  15 + .locals init (int32 ghi)
  16 +
  17 + .try
  18 + {
  19 +#endif
  20 + x = "a";
  21 + ThrowMe();
  22 +
  23 +#if IL
  24 + leave.s IL_ExitTryCatch
  25 + } // end try block
  26 + filter
  27 + {
  28 + // Exception object is on the stack.
  29 + stloc ex
  30 +#endif
  31 + Console.WriteLine("Inside Filter. Object=" + ex);
  32 + x += "b";
  33 +
  34 +#if IL
  35 + ldc.i4.1 // true - execute handler
  36 + endfilter
  37 + } // end filter
  38 + { // begin handler
  39 +#endif
  40 + Console.WriteLine("Yow! In handler now!");
  41 + x += "c";
  42 +#if IL
  43 + leave.s IL_ExitTryCatch
  44 + } // end handler
  45 + IL_ExitTryCatch: nop
  46 +#endif
  47 +
  48 + Console.WriteLine("Back in C#");
  49 + Console.WriteLine(x);
  50 + } // end Main
51 51 } // end Class Foo
40 Daemaged.InlineIL.Demos/Simple_CSharp.cs
... ... @@ -1,21 +1,21 @@
1   -using System;
2   -class Program
3   -{
4   - static void Main()
5   - {
6   - int x = 3;
7   - int y = 4;
8   - int z = 5;
9   -
10   - // Here's some inline IL
11   -#if IL
12   - ldloc x
13   - ldloc y
14   - add
15   - ldloc z
16   - add
17   - stloc x
18   -#endif
19   - Console.WriteLine(x);
20   - }
  1 +using System;
  2 +class Program
  3 +{
  4 + static void Main()
  5 + {
  6 + int x = 3;
  7 + int y = 4;
  8 + int z = 5;
  9 +
  10 + // Here's some inline IL
  11 +#if IL
  12 + ldloc x
  13 + ldloc y
  14 + add
  15 + ldloc z
  16 + add
  17 + stloc x
  18 +#endif
  19 + Console.WriteLine(x);
  20 + }
21 21 }
40 Daemaged.InlineIL.sln
... ... @@ -1,20 +1,20 @@
1   -
2   -Microsoft Visual Studio Solution File, Format Version 11.00
3   -# Visual Studio 2010
4   -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daemaged.InlineIL", "Daemaged.InlineIL\Daemaged.InlineIL.csproj", "{DD22CE04-2896-4430-8D16-CD7FB06BABD4}"
5   -EndProject
6   -Global
7   - GlobalSection(SolutionConfigurationPlatforms) = preSolution
8   - Debug|Any CPU = Debug|Any CPU
9   - Release|Any CPU = Release|Any CPU
10   - EndGlobalSection
11   - GlobalSection(ProjectConfigurationPlatforms) = postSolution
12   - {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13   - {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
14   - {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
15   - {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Release|Any CPU.Build.0 = Release|Any CPU
16   - EndGlobalSection
17   - GlobalSection(SolutionProperties) = preSolution
18   - HideSolutionNode = FALSE
19   - EndGlobalSection
20   -EndGlobal
  1 +
  2 +Microsoft Visual Studio Solution File, Format Version 11.00
  3 +# Visual Studio 2010
  4 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Daemaged.InlineIL", "Daemaged.InlineIL\Daemaged.InlineIL.csproj", "{DD22CE04-2896-4430-8D16-CD7FB06BABD4}"
  5 +EndProject
  6 +Global
  7 + GlobalSection(SolutionConfigurationPlatforms) = preSolution
  8 + Debug|Any CPU = Debug|Any CPU
  9 + Release|Any CPU = Release|Any CPU
  10 + EndGlobalSection
  11 + GlobalSection(ProjectConfigurationPlatforms) = postSolution
  12 + {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  13 + {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
  14 + {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
  15 + {DD22CE04-2896-4430-8D16-CD7FB06BABD4}.Release|Any CPU.Build.0 = Release|Any CPU
  16 + EndGlobalSection
  17 + GlobalSection(SolutionProperties) = preSolution
  18 + HideSolutionNode = FALSE
  19 + EndGlobalSection
  20 +EndGlobal
162 Daemaged.InlineIL/Daemaged.InlineIL.csproj
... ... @@ -1,82 +1,82 @@
1   -<?xml version="1.0" encoding="utf-8"?>
2   -<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3   - <PropertyGroup>
4   - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5   - <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
6   - <ProductVersion>8.0.30703</ProductVersion>
7   - <SchemaVersion>2.0</SchemaVersion>
8   - <ProjectGuid>{DD22CE04-2896-4430-8D16-CD7FB06BABD4}</ProjectGuid>
9   - <OutputType>Exe</OutputType>
10   - <AppDesignerFolder>Properties</AppDesignerFolder>
11   - <RootNamespace>Daemaged.InlineIL</RootNamespace>
12   - <AssemblyName>Daemaged.InlineIL</AssemblyName>
13   - <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
14   - <TargetFrameworkProfile>Client</TargetFrameworkProfile>
15   - <FileAlignment>512</FileAlignment>
16   - </PropertyGroup>
17   - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
18   - <DebugSymbols>true</DebugSymbols>
19   - <OutputPath>bin\Debug\</OutputPath>
20   - <DefineConstants>DEBUG;TRACE</DefineConstants>
21   - <DebugType>full</DebugType>
22   - <PlatformTarget>AnyCPU</PlatformTarget>
23   - <CodeAnalysisLogFile>bin\Debug\Daemaged.InlineIL.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
24   - <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
25   - <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
26   - <ErrorReport>prompt</ErrorReport>
27   - <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
28   - <CodeAnalysisRuleSetDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
29   - <CodeAnalysisRuleDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
30   - <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
31   - </PropertyGroup>
32   - <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
33   - <OutputPath>bin\Release\</OutputPath>
34   - <DefineConstants>TRACE</DefineConstants>
35   - <Optimize>true</Optimize>
36   - <DebugType>pdbonly</DebugType>
37   - <PlatformTarget>AnyCPU</PlatformTarget>
38   - <CodeAnalysisLogFile>bin\Release\Daemaged.InlineIL.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
39   - <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
40   - <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
41   - <ErrorReport>prompt</ErrorReport>
42   - <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
43   - <CodeAnalysisRuleSetDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
44   - <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
45   - <CodeAnalysisRuleDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
46   - <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
47   - </PropertyGroup>
48   - <PropertyGroup>
49   - <SignAssembly>true</SignAssembly>
50   - </PropertyGroup>
51   - <PropertyGroup>
52   - <AssemblyOriginatorKeyFile>Daemaged.InlineIL.snk</AssemblyOriginatorKeyFile>
53   - </PropertyGroup>
54   - <ItemGroup>
55   - <Reference Include="System" />
56   - <Reference Include="System.Core" />
57   - <Reference Include="System.Xml.Linq" />
58   - <Reference Include="System.Data.DataSetExtensions" />
59   - <Reference Include="Microsoft.CSharp" />
60   - <Reference Include="System.Data" />
61   - <Reference Include="System.Xml" />
62   - </ItemGroup>
63   - <ItemGroup>
64   - <Compile Include="ILanguage.cs" />
65   - <Compile Include="ILDocument.cs" />
66   - <Compile Include="InlineILSnippet.cs" />
67   - <Compile Include="Options.cs" />
68   - <Compile Include="Program.cs" />
69   - <Compile Include="Properties\AssemblyInfo.cs" />
70   - </ItemGroup>
71   - <ItemGroup>
72   - <None Include="Daemaged.InlineIL.snk" />
73   - </ItemGroup>
74   - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
75   - <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
76   - Other similar extension points exist, see Microsoft.Common.targets.
77   - <Target Name="BeforeBuild">
78   - </Target>
79   - <Target Name="AfterBuild">
80   - </Target>
81   - -->
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  3 + <PropertyGroup>
  4 + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
  5 + <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
  6 + <ProductVersion>8.0.30703</ProductVersion>
  7 + <SchemaVersion>2.0</SchemaVersion>
  8 + <ProjectGuid>{DD22CE04-2896-4430-8D16-CD7FB06BABD4}</ProjectGuid>
  9 + <OutputType>Exe</OutputType>
  10 + <AppDesignerFolder>Properties</AppDesignerFolder>
  11 + <RootNamespace>Daemaged.InlineIL</RootNamespace>
  12 + <AssemblyName>Daemaged.InlineIL</AssemblyName>
  13 + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
  14 + <TargetFrameworkProfile>Client</TargetFrameworkProfile>
  15 + <FileAlignment>512</FileAlignment>
  16 + </PropertyGroup>
  17 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
  18 + <DebugSymbols>true</DebugSymbols>
  19 + <OutputPath>bin\Debug\</OutputPath>
  20 + <DefineConstants>DEBUG;TRACE</DefineConstants>
  21 + <DebugType>full</DebugType>
  22 + <PlatformTarget>AnyCPU</PlatformTarget>
  23 + <CodeAnalysisLogFile>bin\Debug\Daemaged.InlineIL.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
  24 + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
  25 + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
  26 + <ErrorReport>prompt</ErrorReport>
  27 + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
  28 + <CodeAnalysisRuleSetDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
  29 + <CodeAnalysisRuleDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
  30 + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
  31 + </PropertyGroup>
  32 + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
  33 + <OutputPath>bin\Release\</OutputPath>
  34 + <DefineConstants>TRACE</DefineConstants>
  35 + <Optimize>true</Optimize>
  36 + <DebugType>pdbonly</DebugType>
  37 + <PlatformTarget>AnyCPU</PlatformTarget>
  38 + <CodeAnalysisLogFile>bin\Release\Daemaged.InlineIL.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
  39 + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
  40 + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
  41 + <ErrorReport>prompt</ErrorReport>
  42 + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
  43 + <CodeAnalysisRuleSetDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
  44 + <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
  45 + <CodeAnalysisRuleDirectories>;C:\dev\vs10\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
  46 + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
  47 + </PropertyGroup>
  48 + <PropertyGroup>
  49 + <SignAssembly>true</SignAssembly>
  50 + </PropertyGroup>
  51 + <PropertyGroup>
  52 + <AssemblyOriginatorKeyFile>Daemaged.InlineIL.snk</AssemblyOriginatorKeyFile>
  53 + </PropertyGroup>
  54 + <ItemGroup>
  55 + <Reference Include="System" />
  56 + <Reference Include="System.Core" />
  57 + <Reference Include="System.Xml.Linq" />
  58 + <Reference Include="System.Data.DataSetExtensions" />
  59 + <Reference Include="Microsoft.CSharp" />
  60 + <Reference Include="System.Data" />
  61 + <Reference Include="System.Xml" />
  62 + </ItemGroup>
  63 + <ItemGroup>
  64 + <Compile Include="ILanguage.cs" />
  65 + <Compile Include="ILDocument.cs" />
  66 + <Compile Include="InlineILSnippet.cs" />
  67 + <Compile Include="Options.cs" />
  68 + <Compile Include="Program.cs" />
  69 + <Compile Include="Properties\AssemblyInfo.cs" />
  70 + </ItemGroup>
  71 + <ItemGroup>
  72 + <None Include="Daemaged.InlineIL.snk" />
  73 + </ItemGroup>
  74 + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  75 + <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
  76 + Other similar extension points exist, see Microsoft.Common.targets.
  77 + <Target Name="BeforeBuild">
  78 + </Target>
  79 + <Target Name="AfterBuild">
  80 + </Target>
  81 + -->
82 82 </Project>
0  Daemaged.InlineIL/Daemaged.InlineIL.snk 100755 → 100644
File mode changed
417 Daemaged.InlineIL/ILDocument.cs
... ... @@ -1,205 +1,214 @@
1   -using System;
2   -using System.Collections.Generic;
3   -using System.Collections.Specialized;
4   -using System.IO;
5   -using System.Linq;
6   -using System.Runtime.InteropServices;
7   -using System.Text.RegularExpressions;
8   -
9   -namespace InlineIL
10   -{
11   - class ILDocument
12   - {
13   - // We represent the ILasm document as a set of lines. This makes it easier to manipulate it
14   - // (particularly to inject snippets)
15   -
16   - // Create a new ildocument for the given module.
17   - public ILDocument(string pathModule)
18   - {
19   - // ILDasm the file to produce a textual IL file.
20   - // /linenum tells ildasm to preserve line-number information. This is needed so that we don't lose
21   - // the source-info when we round-trip the il.
22   -
23   - var pathTempIl = Path.GetTempFileName();
24   -
25   - // We need to invoke ildasm, which is in the sdk.
26   - var pathIldasm = Program.SdkDir + "ildasm.exe";
27   -
28   - // We'd like to use File.Exists to make sure ildasm is available, but that function appears broken.
29   - // It doesn't allow spaces in the filenam, even if quoted. Perhaps just a beta 1 bug.
30   -
31   - Util.Run(pathIldasm, "\"" + pathModule + "\" /linenum /text /nobar /out=\"" + pathTempIl + "\"");
32   -
33   -
34   - // Now read the temporary file into a string list.
35   - var temp = new StringCollection();
36   - using (TextReader reader = new StreamReader(new FileStream(pathTempIl, FileMode.Open)))
37   - {
38   - string line;
39   - while ((line = reader.ReadLine()) != null) {
40   - // Remove .maxstack since the inline IL will very likely increase stack size.
41   - if (line.Trim().StartsWith(".maxstack"))
42   - line = "// removed .maxstack declaration";
43   -
44   - temp.Add(line);
45   - }
46   - }
47   - Lines = new string[temp.Count];
48   - temp.CopyTo(Lines, 0);
49   - }
50   -
51   - public string[] Lines { get; set; }
52   -
53   - // Save the IL document back out to a file.
54   - public void EmitToFile(string pathOutputModule, string outputType, string keyFile)
55   - {
56   - var pathTempIl = Path.GetTempFileName();
57   -
58   - // Dump to file.
59   - using (TextWriter writer = new StreamWriter(new FileStream(pathTempIl, FileMode.Create)))
60   - {
61   - foreach (var line in Lines)
62   - {
63   - var x = line;
64   - // ilasm thinks different casings are different source files.
65   - if (line.Trim().StartsWith(".line"))
66   - x = line.ToLower();
67   - writer.WriteLine(x);
68   - }
69   - }
70   -
71   - var pathIlasm = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "ilasm.exe");
72   -
73   - // Run ilasm to re-emit it. It will look something like this:
74   - // ilasm t.il /output=t2.exe /optimize /debug
75   - // /optimize tells ilasm to convert long instructions to short forms (eg "ldarg 0 --> ldarg.0")
76   - // /debug (instead of /debug=impl) tells the runtime to use explicit sequence points
77   - // (which are necessary to single-step the IL instructions that we're inlining)
78   - var keyArg = !String.IsNullOrEmpty(keyFile) ? string.Format("/KEY={0}", keyFile) : "";
79   - Util.Run(pathIlasm, string.Format("\"{0}\" /output=\"{1}\" /optimize /debug /{2} {3} /nologo /quiet",
80   - pathTempIl, pathOutputModule, outputType, keyArg));
81   - }
82   -
83   - // Insert a snippet of IL into the document.
84   - public int FindSnippetLocation(InlineILSnippet snippet)
85   - {
86   - var snippetStart = snippet.StartLine;
87   - var snippetEnd = snippet.EndLine;
88   -
89   - // We need to find where to place the IL snippet in our ildasm output.
90   - // If the IL snippet is at source line (f, g) (inclusive), the ildasm should contain
91   - // consecutive .line directives such '.line x' and '.line y' such that (x > f) && (g > y).
92   - // Once we find such a pair, we can inject the ilasm snippet into the ilasm document at
93   - // the line before the one containing '.line y'.
94   -
95   - // intentionally pick MaxValue so that (idxLast < idxStartLine) is false until we initialize idxLast
96   - var lastKnownLine = int.MaxValue;
97   -
98   - var idxInsertAt = -1;
99   - var idxIlasmLine = 1; // source files are 1-based.
100   - var fileName = String.Empty;
101   - foreach (var line in Lines) {
102   - //Console.WriteLine(line);
103   - Match m;
104   - if ((m = _lineFileRegex.Match(line)).Success) {
105   - fileName = m.Groups["filename"].Value;
106   - //Console.WriteLine("Switching to {0} @ line {1}", fileName, idxIlasmLine);
107   - }
108   -
109   - if (fileName != snippet.Sourcefile) {
110   - idxIlasmLine++;
111   - continue;
112   - }
113   -
114   - var idxCurrent = GetLineMarker(line);
115   - if (idxCurrent != 0) {
116   - if ((lastKnownLine < snippetStart) && (snippetEnd < idxCurrent)) {
117   - // What if there are multiple such values of (x,y)?
118   - // Probably should inject at each spot. - which means we may need a while-loop here instead of foreach
119   - if (idxInsertAt != -1)
120   - throw new Exception("ILAsm snippet needs to be inserted at multiple spots.");
121   -
122   - // Found snippets location! Insert before ilasm source line idxIlasmLine
123   - // (which is index idxIlasmLine-1, since the array is 0-based)
124   - //Console.WriteLine("Found possible snippet {0}:{1}-{2} location @ line {3}",
125   - // snippet.Sourcefile, snippet.StartLine, snippet.EndLine, idxIlasmLine);
126   - idxInsertAt = idxIlasmLine - 1;
127   - }
128   -
129   - lastKnownLine = idxCurrent;
130   - }
131   -
132   - idxIlasmLine++;
133   - }
134   -
135   - if (idxInsertAt == -1)
136   - {
137   - throw new ArgumentException("Can't find where to place " + snippet);
138   - }
139   - //Console.WriteLine("Inserting to .il file @ {0}", idxInsertAt);
140   - //Lines = Util.InsertArrayIntoArray(Lines, snippet.Lines, idxInsertAt);
141   - return idxInsertAt;
142   - }
143   -
144   - #region IL Text parsing Utility
145   - // Is this a line number marker? ".line #,"
146   - // Returns 0 if this isn't a line marker.
147   - // Note that this does not work with multiple source files.
148   - private static readonly Regex _reLine = new Regex(@"\s*\.line (\d+),");
149   - private static readonly Regex _lineFileRegex = new Regex(@"line \d+,\d+ : \d+,\d+ '(?'filename'[^']+)'");
150   -
151   - static int GetLineMarker(string line)
152   - {
153   - var i = 0;
154   - var m = _reLine.Match(line);
155   - if (m.Success)
156   - {
157   - var val = m.Groups[1].Value;
158   - if (int.TryParse(val, out i))
159   - // Protect for hidden lines (0xFeeFee)
160   - // http://blogs.msdn.com/b/jmstall/archive/2005/06/19/feefee-sequencepoints.aspx
161   - return i == 0xFEEFEE ? 0 : i;
162   - }
163   - return 0;
164   - }
165   -
166   - // Get a ILasm string for a sequence point marker. Eg, should look something like:
167   - // .line 7,7 : 2,6 'c:\\temp\\t.cs'
168   - public static string CreateILSequenceMarker(string pathSourceFile, int idxLineStart, int idxLineEnd, int idxColStart, int idxColEnd)
169   - {
170   - var pathEscapedSourceFile = pathSourceFile.Replace(@"\", @"\\");
171   - return ".line " + idxLineStart + "," + idxLineEnd + " : " + idxColStart + "," + idxColEnd + " '" + pathEscapedSourceFile + "'";
172   - }
173   -
174   - // Given a line of IL, determine if it's a statement.
175   - // We can't add markers to none-statement lines.
176   - static public bool IsStatement(string line)
177   - {
178   - // Parsing the ilasm text lines seems very hacky here. This is one place it would be great if we had
179   - // a codedom for ilasm.
180   - // It would be best to run this through a compiled regular expression instead of the adhoc string operations.
181   - var t = line.Trim();
182   -
183   - // skip blank lines and comments.
184   - if (t.Length <= 1) return false;
185   - if (t.StartsWith("//")) return false;
186   -
187   - // The '.' includes all sorts of metacommands that we wan't to skip.
188   - var ch = t[0];
189   - if (ch == '.' || ch == '{' || ch == '}') return false;
190   -
191   - return !t.StartsWith("catch") && !t.StartsWith("filter");
192   - }
193   -
194   - #endregion IL Text parsing Utility
195   -
196   - //.line 27,27 : 5,44 'c:\Path\To\File.cs'
197   - //.line 27,27 : 5,44 ''
198   -
199   -
200   - public IList<string> GetSourceFiles()
201   - {
202   - return Lines.Select(l => _lineFileRegex.Match(l)).Where(m => m.Success).Select(m => m.Groups["filename"].Value).Distinct().ToList();
203   - }
204   - }
  1 +using System;
  2 +using System.Collections.Generic;
  3 +using System.Collections.Specialized;
  4 +using System.IO;
  5 +using System.Linq;
  6 +using System.Runtime.InteropServices;
  7 +using System.Text.RegularExpressions;
  8 +
  9 +namespace InlineIL
  10 +{
  11 + class ILDocument
  12 + {
  13 + // We represent the ILasm document as a set of lines. This makes it easier to manipulate it
  14 + // (particularly to inject snippets)
  15 +
  16 + // Create a new ildocument for the given module.
  17 + public ILDocument(string pathModule)
  18 + {
  19 + // ILDasm the file to produce a textual IL file.
  20 + // /linenum tells ildasm to preserve line-number information. This is needed so that we don't lose
  21 + // the source-info when we round-trip the il.
  22 +
  23 + var pathTempIl = Path.GetTempFileName();
  24 +
  25 + // We need to invoke ildasm, which is in the sdk.
  26 + var pathIldasm = Program.SdkDir + "ildasm.exe";
  27 +
  28 + // We'd like to use File.Exists to make sure ildasm is available, but that function appears broken.
  29 + // It doesn't allow spaces in the filenam, even if quoted. Perhaps just a beta 1 bug.
  30 +
  31 + Util.Run(pathIldasm, "\"" + pathModule + "\" /linenum /text /nobar /out=\"" + pathTempIl + "\"");
  32 +
  33 +
  34 + // Now read the temporary file into a string list.
  35 + var temp = new StringCollection();
  36 + using (TextReader reader = new StreamReader(new FileStream(pathTempIl, FileMode.Open)))
  37 + {
  38 + string line;
  39 + while ((line = reader.ReadLine()) != null) {
  40 + // Remove .maxstack since the inline IL will very likely increase stack size.
  41 + if (line.Trim().StartsWith(".maxstack"))
  42 + line = "// removed .maxstack declaration";
  43 +
  44 + temp.Add(line);
  45 + }
  46 + }
  47 + Lines = new string[temp.Count];
  48 + temp.CopyTo(Lines, 0);
  49 + }
  50 +
  51 + public string[] Lines { get; set; }
  52 +
  53 + // Save the IL document back out to a file.
  54 + public void EmitToFile(string pathOutputModule, string outputType, string keyFile, bool verbose)
  55 + {
  56 +
  57 + var pathTempIl = Path.GetTempFileName();
  58 +
  59 + if (verbose)
  60 + Console.WriteLine("Emitting temp MSIL to {0}", pathTempIl);
  61 +
  62 + // Dump to file.);
  63 + using (TextWriter writer = new StreamWriter(new FileStream(pathTempIl, FileMode.Create)))
  64 + {
  65 + foreach (var line in Lines)
  66 + {
  67 + var x = line;
  68 + // ilasm thinks different casings are different source files.
  69 + if (line.Trim().StartsWith(".line"))
  70 + x = line.ToLower();
  71 + writer.WriteLine(x);
  72 + }
  73 + }
  74 +
  75 + var pathIlasm = Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "ilasm.exe");
  76 +
  77 + // Run ilasm to re-emit it. It will look something like this:
  78 + // ilasm t.il /output=t2.exe /optimize /debug
  79 + // /optimize tells ilasm to convert long instructions to short forms (eg "ldarg 0 --> ldarg.0")
  80 + // /debug (instead of /debug=impl) tells the runtime to use explicit sequence points
  81 + // (which are necessary to single-step the IL instructions that we're inlining)
  82 + var keyArg = !String.IsNullOrEmpty(keyFile) ? string.Format("/KEY={0}", keyFile) : "";
  83 +
  84 + var cmdArgs = string.Format("\"{0}\" /output=\"{1}\" /optimize /debug /{2} {3} /nologo /quiet",
  85 + pathTempIl, pathOutputModule, outputType, keyArg);
  86 + if (verbose)
  87 + Console.WriteLine("Running {0} {1}", pathIlasm, cmdArgs);
  88 +
  89 + Util.Run(pathIlasm, cmdArgs);
  90 + }
  91 +
  92 + // Insert a snippet of IL into the document.
  93 + public int FindSnippetLocation(InlineILSnippet snippet)
  94 + {
  95 + var snippetStart = snippet.StartLine;
  96 + var snippetEnd = snippet.EndLine;
  97 +
  98 + // We need to find where to place the IL snippet in our ildasm output.
  99 + // If the IL snippet is at source line (f, g) (inclusive), the ildasm should contain
  100 + // consecutive .line directives such '.line x' and '.line y' such that (x > f) && (g > y).
  101 + // Once we find such a pair, we can inject the ilasm snippet into the ilasm document at
  102 + // the line before the one containing '.line y'.
  103 +
  104 + // intentionally pick MaxValue so that (idxLast < idxStartLine) is false until we initialize idxLast
  105 + var lastKnownLine = int.MaxValue;
  106 +
  107 + var idxInsertAt = -1;
  108 + var idxIlasmLine = 1; // source files are 1-based.
  109 + var fileName = String.Empty;
  110 + foreach (var line in Lines) {
  111 + //Console.WriteLine(line);
  112 + Match m;
  113 + if ((m = _lineFileRegex.Match(line)).Success) {
  114 + fileName = m.Groups["filename"].Value;
  115 + //Console.WriteLine("Switching to {0} @ line {1}", fileName, idxIlasmLine);
  116 + }
  117 +
  118 + if (fileName != snippet.Sourcefile) {
  119 + idxIlasmLine++;
  120 + continue;
  121 + }
  122 +
  123 + var idxCurrent = GetLineMarker(line);
  124 + if (idxCurrent != 0) {
  125 + if ((lastKnownLine < snippetStart) && (snippetEnd < idxCurrent)) {
  126 + // What if there are multiple such values of (x,y)?
  127 + // Probably should inject at each spot. - which means we may need a while-loop here instead of foreach
  128 + if (idxInsertAt != -1)
  129 + throw new Exception("ILAsm snippet needs to be inserted at multiple spots.");
  130 +
  131 + // Found snippets location! Insert before ilasm source line idxIlasmLine
  132 + // (which is index idxIlasmLine-1, since the array is 0-based)
  133 + //Console.WriteLine("Found possible snippet {0}:{1}-{2} location @ line {3}",
  134 + // snippet.Sourcefile, snippet.StartLine, snippet.EndLine, idxIlasmLine);
  135 + idxInsertAt = idxIlasmLine - 1;
  136 + }
  137 +
  138 + lastKnownLine = idxCurrent;
  139 + }
  140 +
  141 + idxIlasmLine++;
  142 + }
  143 +
  144 + if (idxInsertAt == -1)
  145 + {
  146 + throw new ArgumentException("Can't find where to place " + snippet);
  147 + }
  148 + //Console.WriteLine("Inserting to .il file @ {0}", idxInsertAt);
  149 + //Lines = Util.InsertArrayIntoArray(Lines, snippet.Lines, idxInsertAt);
  150 + return idxInsertAt;
  151 + }
  152 +
  153 + #region IL Text parsing Utility
  154 + // Is this a line number marker? ".line #,"
  155 + // Returns 0 if this isn't a line marker.
  156 + // Note that this does not work with multiple source files.
  157 + private static readonly Regex _reLine = new Regex(@"\s*\.line (\d+),");
  158 + private static readonly Regex _lineFileRegex = new Regex(@"line \d+,\d+ : \d+,\d+ '(?'filename'[^']+)'");
  159 +
  160 + static int GetLineMarker(string line)
  161 + {
  162 + var i = 0;
  163 + var m = _reLine.Match(line);
  164 + if (m.Success)
  165 + {
  166 + var val = m.Groups[1].Value;
  167 + if (int.TryParse(val, out i))
  168 + // Protect for hidden lines (0xFeeFee)
  169 + // http://blogs.msdn.com/b/jmstall/archive/2005/06/19/feefee-sequencepoints.aspx
  170 + return i == 0xFEEFEE ? 0 : i;
  171 + }
  172 + return 0;
  173 + }
  174 +
  175 + // Get a ILasm string for a sequence point marker. Eg, should look something like:
  176 + // .line 7,7 : 2,6 'c:\\temp\\t.cs'
  177 + public static string CreateILSequenceMarker(string pathSourceFile, int idxLineStart, int idxLineEnd, int idxColStart, int idxColEnd)
  178 + {
  179 + var pathEscapedSourceFile = pathSourceFile.Replace(@"\", @"\\");
  180 + return ".line " + idxLineStart + "," + idxLineEnd + " : " + idxColStart + "," + idxColEnd + " '" + pathEscapedSourceFile + "'";
  181 + }
  182 +
  183 + // Given a line of IL, determine if it's a statement.
  184 + // We can't add markers to none-statement lines.
  185 + static public bool IsStatement(string line)
  186 + {
  187 + // Parsing the ilasm text lines seems very hacky here. This is one place it would be great if we had
  188 + // a codedom for ilasm.
  189 + // It would be best to run this through a compiled regular expression instead of the adhoc string operations.
  190 + var t = line.Trim();
  191 +
  192 + // skip blank lines and comments.
  193 + if (t.Length <= 1) return false;
  194 + if (t.StartsWith("//")) return false;
  195 +
  196 + // The '.' includes all sorts of metacommands that we wan't to skip.
  197 + var ch = t[0];
  198 + if (ch == '.' || ch == '{' || ch == '}') return false;
  199 +
  200 + return !t.StartsWith("catch") && !t.StartsWith("filter");
  201 + }
  202 +
  203 + #endregion IL Text parsing Utility
  204 +
  205 + //.line 27,27 : 5,44 'c:\Path\To\File.cs'
  206 + //.line 27,27 : 5,44 ''
  207 +
  208 +
  209 + public IList<string> GetSourceFiles()
  210 + {
  211 + return Lines.Select(l => _lineFileRegex.Match(l)).Where(m => m.Success).Select(m => m.Groups["filename"].Value).Distinct().ToList();
  212 + }
  213 + }
205 214 }
86 Daemaged.InlineIL/ILanguage.cs
... ... @@ -1,43 +1,43 @@
1   -using System;
2   -using System.Collections.Generic;
3   -using System.Linq;
4   -using System.Text;
5   -
6   -namespace InlineIL
7   -{
8   - // Abstraction for different languages.
9   - interface ILanguage
10   - {
11   - // Source line that indicates an inline IL snippet is starting.
12   - string StartMarker { get; }
13   -
14   - // Source line that ends an inline IL snippet. Must match with StartMarker.
15   - string EndMarker { get; }
16   - }
17   -
18   - // Language service for the VB.Net compiler.
19   - class VisualBasicLanguage : ILanguage
20   - {
21   - public string StartMarker
22   - {
23   - get { return "#If IL Then"; }
24   - }
25   - public string EndMarker
26   - {
27   - get { return "#End If"; }
28   - }
29   - }
30   -
31   - // Language service for the C# compiler.
32   - class CSharpLanguage : ILanguage
33   - {
34   - public string StartMarker
35   - {
36   - get { return "#if IL"; }
37   - }
38   - public string EndMarker
39   - {
40   - get { return "#endif"; }
41   - }
42   - }
43   -}
  1 +using System;
  2 +using System.Collections.Generic;
  3 +using System.Linq;
  4 +using System.Text;
  5 +
  6 +namespace InlineIL
  7 +{
  8 + // Abstraction for different languages.
  9 + interface ILanguage
  10 + {
  11 + // Source line that indicates an inline IL snippet is starting.
  12 + string StartMarker { get; }
  13 +
  14 + // Source line that ends an inline IL snippet. Must match with StartMarker.
  15 + string EndMarker { get; }
  16 + }
  17 +
  18 + // Language service for the VB.Net compiler.
  19 + class VisualBasicLanguage : ILanguage
  20 + {
  21 + public string StartMarker
  22 + {
  23 + get { return "#If IL Then"; }
  24 + }
  25 + public string EndMarker
  26 + {
  27 + get { return "#End If"; }
  28 + }
  29 + }
  30 +
  31 + // Language service for the C# compiler.
  32 + class CSharpLanguage : ILanguage
  33 + {
  34 + public string StartMarker
  35 + {
  36 + get { return "#if IL"; }
  37 + }
  38 + public string EndMarker
  39 + {
  40 + get { return "#endif"; }
  41 + }
  42 + }
  43 +}
126 Daemaged.InlineIL/InlineILSnippet.cs
... ... @@ -1,64 +1,64 @@
1   -using System;
2   -using System.Collections.Specialized;
3   -using System.Diagnostics;
4   -
5   -namespace InlineIL
6   -{
7   - class InlineILSnippet
8   - {
9   - // Create an IL snippet that matches the given range (startLine to endLine, inclusive) in the
10   - // given source file.
11   - // Although we could compute the lines collection from the other 3 parameters, we pass it in for perf reasons
12   - // since we already have it available.
13   - public InlineILSnippet(string pathSourceFile, int idxStartLine, int idxEndLine, StringCollection lines)
14   - {
15   - Sourcefile = pathSourceFile;
16   - StartLine = idxStartLine;
17   - EndLine = idxEndLine;
18   -
19   - // This assert would be false if the incoming lines collection has been preprocessed (Eg, if the caller
20   - // already inject .line directives to map back to the source).
21   - Debug.Assert(idxEndLine - idxStartLine + 1 == lines.Count);
22   -
23   - // Marshal into an array. Since we're already copying, we'll also inject the sequence point info.
24   - Lines = new string[(lines.Count * 2)+1];
25   - Lines[0] = string.Format("// Snippet from {0}:{1}", pathSourceFile, idxStartLine);
26   -
27   -
28   - for (var i = 0; i < lines.Count; i++)
29   - {
30   - var idxSourceLine = idxStartLine + i;
31   -
32   - // ILAsm only lets us add sequence points to statements.
33   - var sequenceMarker = ILDocument.IsStatement(lines[i]) ?
34   - ILDocument.CreateILSequenceMarker(pathSourceFile, idxSourceLine, idxSourceLine, 1, lines[i].Length + 1) :
35   - "// skip sequence marker";
36   -
37   - Lines[2 * i + 1] = sequenceMarker;
38   - Lines[2 * i + 2] = lines[i];
39   - }
40   - }
41   -
42   - public override string ToString()
43   - { return "Snippet in file '" + Sourcefile + "' at range (" + StartLine + "," + EndLine + ")"; }
44   -
45   -
46   - #region Properties
47   - // First line of the IL snippet within the source document.
48   - public int StartLine { get; private set; }
49   -
50   - // Last line (inclusive) of the IL snippet in the source document.
51   - // Total number of lines in IL snippet is (EndLine - StartLine + 1)
52   - public int EndLine { get; private set; }
53   -
54   - // Path to source file that IL snippet originally occured in.
55   - // This can be used to generate sequence points from the snippet back to the original source file.
56   - public string Sourcefile { get; private set; }
57   -
58   - public string[] Lines { get; private set; }
59   - public int InsertLocation { get; set; }
60   -
61   - #endregion Properties
62   -
63   - }
  1 +using System;
  2 +using System.Collections.Specialized;
  3 +using System.Diagnostics;
  4 +
  5 +namespace InlineIL
  6 +{
  7 + class InlineILSnippet
  8 + {
  9 + // Create an IL snippet that matches the given range (startLine to endLine, inclusive) in the
  10 + // given source file.
  11 + // Although we could compute the lines collection from the other 3 parameters, we pass it in for perf reasons
  12 + // since we already have it available.
  13 + public InlineILSnippet(string pathSourceFile, int idxStartLine, int idxEndLine, StringCollection lines)
  14 + {
  15 + Sourcefile = pathSourceFile;
  16 + StartLine = idxStartLine;
  17 + EndLine = idxEndLine;
  18 +
  19 + // This assert would be false if the incoming lines collection has been preprocessed (Eg, if the caller
  20 + // already inject .line directives to map back to the source).
  21 + Debug.Assert(idxEndLine - idxStartLine + 1 == lines.Count);
  22 +
  23 + // Marshal into an array. Since we're already copying, we'll also inject the sequence point info.
  24 + Lines = new string[(lines.Count * 2)+1];
  25 + Lines[0] = string.Format("// Snippet from {0}:{1}", pathSourceFile, idxStartLine);
  26 +
  27 +
  28 + for (var i = 0; i < lines.Count; i++)
  29 + {
  30 + var idxSourceLine = idxStartLine + i;
  31 +
  32 + // ILAsm only lets us add sequence points to statements.
  33 + var sequenceMarker = ILDocument.IsStatement(lines[i]) ?
  34 + ILDocument.CreateILSequenceMarker(pathSourceFile, idxSourceLine, idxSourceLine, 1, lines[i].Length + 1) :
  35 + "// skip sequence marker";
  36 +
  37 + Lines[2 * i + 1] = sequenceMarker;
  38 + Lines[2 * i + 2] = lines[i];
  39 + }
  40 + }
  41 +
  42 + public override string ToString()
  43 + { return "Snippet in file '" + Sourcefile + "' at range (" + StartLine + "," + EndLine + ")"; }
  44 +
  45 +
  46 + #region Properties
  47 + // First line of the IL snippet within the source document.
  48 + public int StartLine { get; private set; }
  49 +
  50 + // Last line (inclusive) of the IL snippet in the source document.
  51 + // Total number of lines in IL snippet is (EndLine - StartLine + 1)
  52 + public int EndLine { get; private set; }
  53 +
  54 + // Path to source file that IL snippet originally occured in.
  55 + // This can be used to generate sequence points from the snippet back to the original source file.
  56 + public string Sourcefile { get; private set; }
  57 +
  58 + public string[] Lines { get; private set; }
  59 + public int InsertLocation { get; set; }
  60 +
  61 + #endregion Properties
  62 +
  63 + }
64 64 }
2,438 Daemaged.InlineIL/Options.cs
... ... @@ -1,1219 +1,1219 @@
1   -//
2   -// Options.cs
3   -//
4   -// Authors:
5   -// Jonathan Pryor <jpryor@novell.com>
6   -// Federico Di Gregorio <fog@initd.org>
7   -//
8   -// Copyright (C) 2008 Novell (http://www.novell.com)
9   -// Copyright (C) 2009 Federico Di Gregorio.
10   -//
11   -// Permission is hereby granted, free of charge, to any person obtaining
12   -// a copy of this software and associated documentation files (the
13   -// "Software"), to deal in the Software without restriction, including
14   -// without limitation the rights to use, copy, modify, merge, publish,
15   -// distribute, sublicense, and/or sell copies of the Software, and to
16   -// permit persons to whom the Software is furnished to do so, subject to
17   -// the following conditions:
18   -//
19   -// The above copyright notice and this permission notice shall be
20   -// included in all copies or substantial portions of the Software.
21   -//
22   -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23   -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24   -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25   -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26   -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27   -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28   -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29   -//
30   -
31   -// Compile With:
32   -// gmcs -debug+ -r:System.Core Options.cs -o:NDesk.Options.dll
33   -// gmcs -debug+ -d:LINQ -r:System.Core Options.cs -o:NDesk.Options.dll
34   -//
35   -// The LINQ version just changes the implementation of
36   -// OptionSet.Parse(IEnumerable<string>), and confers no semantic changes.
37   -
38   -//
39   -// A Getopt::Long-inspired option parsing library for C#.
40   -//
41   -// NDesk.Options.OptionSet is built upon a key/value table, where the
42   -// key is a option format string and the value is a delegate that is
43   -// invoked when the format string is matched.
44   -//
45   -// Option format strings:
46   -// Regex-like BNF Grammar:
47   -// name: .+
48   -// type: [=:]
49   -// sep: ( [^{}]+ | '{' .+ '}' )?
50   -// aliases: ( name type sep ) ( '|' name type sep )*
51   -//
52   -// Each '|'-delimited name is an alias for the associated action. If the
53   -// format string ends in a '=', it has a required value. If the format
54   -// string ends in a ':', it has an optional value. If neither '=' or ':'
55   -// is present, no value is supported. `=' or `:' need only be defined on one
56   -// alias, but if they are provided on more than one they must be consistent.
57   -//
58   -// Each alias portion may also end with a "key/value separator", which is used
59   -// to split option values if the option accepts > 1 value. If not specified,
60   -// it defaults to '=' and ':'. If specified, it can be any character except
61   -// '{' and '}' OR the *string* between '{' and '}'. If no separator should be
62   -// used (i.e. the separate values should be distinct arguments), then "{}"
63   -// should be used as the separator.
64   -//
65   -// Options are extracted either from the current option by looking for
66   -// the option name followed by an '=' or ':', or is taken from the
67   -// following option IFF:
68   -// - The current option does not contain a '=' or a ':'
69   -// - The current option requires a value (i.e. not a Option type of ':')
70   -//
71   -// The `name' used in the option format string does NOT include any leading
72   -// option indicator, such as '-', '--', or '/'. All three of these are
73   -// permitted/required on any named option.
74   -//
75   -// Option bundling is permitted so long as:
76   -// - '-' is used to start the option group
77   -// - all of the bundled options are a single character
78   -// - at most one of the bundled options accepts a value, and the value
79   -// provided starts from the next character to the end of the string.
80   -//
81   -// This allows specifying '-a -b -c' as '-abc', and specifying '-D name=value'
82   -// as '-Dname=value'.
83   -//
84   -// Option processing is disabled by specifying "--". All options after "--"
85   -// are returned by OptionSet.Parse() unchanged and unprocessed.
86   -//
87   -// Unprocessed options are returned from OptionSet.Parse().
88   -//
89   -// Examples:
90   -// int verbose = 0;
91   -// OptionSet p = new OptionSet ()
92   -// .Add ("v", v => ++verbose)
93   -// .Add ("name=|value=", v => Console.WriteLine (v));
94   -// p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"});
95   -//
96   -// The above would parse the argument string array, and would invoke the
97   -// lambda expression three times, setting `verbose' to 3 when complete.
98   -// It would also print out "A" and "B" to standard output.
99   -// The returned array would contain the string "extra".
100   -//
101   -// C# 3.0 collection initializers are supported and encouraged:
102   -// var p = new OptionSet () {
103   -// { "h|?|help", v => ShowHelp () },
104   -// };
105   -//
106   -// System.ComponentModel.TypeConverter is also supported, allowing the use of
107   -// custom data types in the callback type; TypeConverter.ConvertFromString()
108   -// is used to convert the value option to an instance of the specified
109   -// type:
110   -//
111   -// var p = new OptionSet () {
112   -// { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) },
113   -// };
114   -//
115   -// Random other tidbits:
116   -// - Boolean options (those w/o '=' or ':' in the option format string)
117   -// are explicitly enabled if they are followed with '+', and explicitly
118   -// disabled if they are followed with '-':
119   -// string a = null;
120   -// var p = new OptionSet () {
121   -// { "a", s => a = s },
122   -// };
123   -// p.Parse (new string[]{"-a"}); // sets v != null
124   -// p.Parse (new string[]{"-a+"}); // sets v != null
125   -// p.Parse (new string[]{"-a-"}); // sets v == null
126   -//
127   -
128   -using System;
129   -using System.Collections;
130   -using System.Collections.Generic;
131   -using System.Collections.ObjectModel;
132   -using System.ComponentModel;
133   -using System.Globalization;
134   -using System.IO;
135   -using System.Runtime.Serialization;
136   -using System.Security.Permissions;
137   -using System.Text;
138   -using System.Text.RegularExpressions;
139   -
140   -#if LINQ
141   -using System.Linq;
142   -#endif
143   -
144   -#if TEST
145   -using NDesk.Options;