The Labs \ Source Viewer \ SSCLI \ System.Text.RegularExpressions \ RegexTypeCompiler

  1. //------------------------------------------------------------------------------
  2. // <copyright file="RegexCompiler.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. // The RegexCompiler class is internal to the Regex package.
  16. // It translates a block of RegexCode to MSIL, and creates a
  17. // subclass of the RegexRunner type.
  18. namespace System.Text.RegularExpressions
  19. {
  20.    
  21.     using System.Collections;
  22.     using System.Threading;
  23.     using System.Reflection;
  24.     using System.Reflection.Emit;
  25.     using System.Security;
  26.     using System.Security.Policy;
  27.     using System.Security.Permissions;
  28.     using System.Diagnostics;
  29.     using System.Globalization;
  30.     using System.Runtime.Versioning;
  31.    
  32. /*
  33.     * RegexDynamicModule
  34.     *
  35.     * Because dynamic modules are expensive and not thread-safe, we create
  36.     * one dynamic module per-thread, and cache as much information about it
  37.     * as we can.
  38.     *
  39.     * While we're at it, we just create one RegexCompiler per thread
  40.     * as well, and have RegexCompiler inherit from RegexDynamicModule.
  41.     */   
  42.     internal abstract class RegexCompiler
  43.     {
  44.         // fields that never change (making them saves about 6% overall running time)
  45.        
  46.         static internal FieldInfo _textbegF;
  47.         static internal FieldInfo _textendF;
  48.         static internal FieldInfo _textstartF;
  49.         static internal FieldInfo _textposF;
  50.         static internal FieldInfo _textF;
  51.         static internal FieldInfo _trackposF;
  52.         static internal FieldInfo _trackF;
  53.         static internal FieldInfo _stackposF;
  54.         static internal FieldInfo _stackF;
  55.         static internal FieldInfo _trackcountF;
  56.        
  57.         // note some methods
  58.        
  59.         static internal MethodInfo _ensurestorageM;
  60.         static internal MethodInfo _captureM;
  61.         static internal MethodInfo _transferM;
  62.         static internal MethodInfo _uncaptureM;
  63.         static internal MethodInfo _ismatchedM;
  64.         static internal MethodInfo _matchlengthM;
  65.         static internal MethodInfo _matchindexM;
  66.         static internal MethodInfo _isboundaryM;
  67.         static internal MethodInfo _isECMABoundaryM;
  68.         static internal MethodInfo _chartolowerM;
  69.         static internal MethodInfo _getcharM;
  70.         static internal MethodInfo _crawlposM;
  71.         static internal MethodInfo _charInSetM;
  72.         static internal MethodInfo _getCurrentCulture;
  73.         static internal MethodInfo _getInvariantCulture;
  74.         #if DBG
  75.         static internal MethodInfo _dumpstateM;
  76.         #endif
  77.        
  78.         internal ILGenerator _ilg;
  79.        
  80.         // tokens representing local variables
  81.         internal LocalBuilder _textstartV;
  82.         internal LocalBuilder _textbegV;
  83.         internal LocalBuilder _textendV;
  84.         internal LocalBuilder _textposV;
  85.         internal LocalBuilder _textV;
  86.         internal LocalBuilder _trackposV;
  87.         internal LocalBuilder _trackV;
  88.         internal LocalBuilder _stackposV;
  89.         internal LocalBuilder _stackV;
  90.         internal LocalBuilder _tempV;
  91.         internal LocalBuilder _temp2V;
  92.         internal LocalBuilder _temp3V;
  93.        
  94.        
  95.         internal RegexCode _code;
  96.         // the RegexCode object (used for debugging only)
  97.         internal int[] _codes;
  98.         // the RegexCodes being translated
  99.         internal string[] _strings;
  100.         // the stringtable associated with the RegexCodes
  101.         internal RegexPrefix _fcPrefix;
  102.         // the possible first chars computed by RegexFCD
  103.         internal RegexBoyerMoore _bmPrefix;
  104.         // a prefix as a boyer-moore machine
  105.         internal int _anchors;
  106.         // the set of anchors
  107.         internal Label[] _labels;
  108.         // a label for every operation in _codes
  109.         internal BacktrackNote[] _notes;
  110.         // a list of the backtracking states to be generated
  111.         internal int _notecount;
  112.         // true count of _notes (allocation grows exponentially)
  113.         internal int _trackcount;
  114.         // count of backtracking states (used to reduce allocations)
  115.         internal Label _backtrack;
  116.         // label for backtracking
  117.        
  118.         internal int _regexopcode;
  119.         // the current opcode being processed
  120.         internal int _codepos;
  121.         // the current code being translated
  122.         internal int _backpos;
  123.         // the current backtrack-note being translated
  124.         internal RegexOptions _options;
  125.         // options
  126.         // special code fragments
  127.         internal int[] _uniquenote;
  128.         // _notes indices for code that should be emitted <= once
  129.         internal int[] _goto;
  130.         // indices for forward-jumps-through-switch (for allocations)
  131.         // indices for unique code fragments
  132.         internal const int stackpop = 0;
  133.         // pop one
  134.         internal const int stackpop2 = 1;
  135.         // pop two
  136.         internal const int stackpop3 = 2;
  137.         // pop three
  138.         internal const int capback = 3;
  139.         // uncapture
  140.         internal const int capback2 = 4;
  141.         // uncapture 2
  142.         internal const int branchmarkback2 = 5;
  143.         // back2 part of branchmark
  144.         internal const int lazybranchmarkback2 = 6;
  145.         // back2 part of lazybranchmark
  146.         internal const int branchcountback2 = 7;
  147.         // back2 part of branchcount
  148.         internal const int lazybranchcountback2 = 8;
  149.         // back2 part of lazybranchcount
  150.         internal const int forejumpback = 9;
  151.         // back part of forejump
  152.         internal const int uniquecount = 10;
  153.        
  154.         static RegexCompiler()
  155.         {
  156.            
  157.             new ReflectionPermission(PermissionState.Unrestricted).Assert();
  158.             try {
  159.                 // note some fields
  160.                 _textbegF = RegexRunnerField("runtextbeg");
  161.                 _textendF = RegexRunnerField("runtextend");
  162.                 _textstartF = RegexRunnerField("runtextstart");
  163.                 _textposF = RegexRunnerField("runtextpos");
  164.                 _textF = RegexRunnerField("runtext");
  165.                 _trackposF = RegexRunnerField("runtrackpos");
  166.                 _trackF = RegexRunnerField("runtrack");
  167.                 _stackposF = RegexRunnerField("runstackpos");
  168.                 _stackF = RegexRunnerField("runstack");
  169.                 _trackcountF = RegexRunnerField("runtrackcount");
  170.                
  171.                 // note some methods
  172.                 _ensurestorageM = RegexRunnerMethod("EnsureStorage");
  173.                 _captureM = RegexRunnerMethod("Capture");
  174.                 _transferM = RegexRunnerMethod("TransferCapture");
  175.                 _uncaptureM = RegexRunnerMethod("Uncapture");
  176.                 _ismatchedM = RegexRunnerMethod("IsMatched");
  177.                 _matchlengthM = RegexRunnerMethod("MatchLength");
  178.                 _matchindexM = RegexRunnerMethod("MatchIndex");
  179.                 _isboundaryM = RegexRunnerMethod("IsBoundary");
  180.                 _charInSetM = RegexRunnerMethod("CharInClass");
  181.                 _isECMABoundaryM = RegexRunnerMethod("IsECMABoundary");
  182.                 _crawlposM = RegexRunnerMethod("Crawlpos");
  183.                
  184.                 _chartolowerM = typeof(char).GetMethod("ToLower", new Type[] {typeof(char), typeof(CultureInfo)});
  185.                 _getcharM = typeof(string).GetMethod("get_Chars", new Type[] {typeof(int)});
  186.                 _getCurrentCulture = typeof(CultureInfo).GetMethod("get_CurrentCulture");
  187.                 _getInvariantCulture = typeof(CultureInfo).GetMethod("get_InvariantCulture");
  188.                
  189.                
  190.                 #if DBG
  191.                 _dumpstateM = RegexRunnerMethod("DumpState");
  192.                 #endif
  193.             }
  194.             finally {
  195.                 CodeAccessPermission.RevertAssert();
  196.             }
  197.         }
  198.        
  199.         private static FieldInfo RegexRunnerField(string fieldname)
  200.         {
  201.             return typeof(RegexRunner).GetField(fieldname, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  202.         }
  203.        
  204.         private static MethodInfo RegexRunnerMethod(string methname)
  205.         {
  206.             return typeof(RegexRunner).GetMethod(methname, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
  207.         }
  208.        
  209.        
  210. /*
  211.         * Entry point to dynamically compile a regular expression.  The expression is compiled to
  212.         * an in memory assembly.
  213.         */       
  214.         static internal RegexRunnerFactory Compile(RegexCode code, RegexOptions options)
  215.         {
  216.             RegexLWCGCompiler c = new RegexLWCGCompiler();
  217.             RegexRunnerFactory factory;
  218.            
  219.             new ReflectionPermission(PermissionState.Unrestricted).Assert();
  220.             try {
  221.                 factory = c.FactoryInstanceFromCode(code, options);
  222.             }
  223.             finally {
  224.                 CodeAccessPermission.RevertAssert();
  225.             }
  226.             return factory;
  227.         }
  228.        
  229. /*
  230.         * Compile regular expressions into an assembly on disk.
  231.         */       
  232.         [ResourceExposure(ResourceScope.Machine)]
  233.         [ResourceConsumption(ResourceScope.Machine)]
  234.         static internal void CompileToAssembly(RegexCompilationInfo[] regexes, AssemblyName an, CustomAttributeBuilder[] attribs, string resourceFile, Evidence evidence)
  235.         {
  236.             RegexTypeCompiler c = new RegexTypeCompiler(an, attribs, resourceFile, evidence);
  237.            
  238.             for (int i = 0; i < regexes.Length; i++) {
  239.                 string pattern = regexes[i].Pattern;
  240.                 RegexOptions options = regexes[i].Options;
  241.                 string fullname;
  242.                 if (regexes[i].Namespace.Length == 0)
  243.                     fullname = regexes[i].Name;
  244.                 else
  245.                     fullname = regexes[i].Namespace + "." + regexes[i].Name;
  246.                
  247.                 RegexTree tree = RegexParser.Parse(pattern, options);
  248.                 RegexCode code = RegexWriter.Write(tree);
  249.                
  250.                 Type factory;
  251.                
  252.                 new ReflectionPermission(PermissionState.Unrestricted).Assert();
  253.                 try {
  254.                     factory = c.FactoryTypeFromCode(code, options, fullname);
  255.                     c.GenerateRegexType(pattern, options, fullname, regexes[i].IsPublic, code, tree, factory);
  256.                 }
  257.                 finally {
  258.                     CodeAccessPermission.RevertAssert();
  259.                 }
  260.             }
  261.            
  262.             c.Save();
  263.         }
  264.        
  265.        
  266. /*
  267.         * Keeps track of an operation that needs to be referenced in the backtrack-jump
  268.         * switch table, and that needs backtracking code to be emitted (if flags != 0)
  269.         */       
  270.         internal sealed class BacktrackNote
  271.         {
  272.             internal BacktrackNote(int flags, Label label, int codepos)
  273.             {
  274.                 _codepos = codepos;
  275.                 _flags = flags;
  276.                 _label = label;
  277.             }
  278.            
  279.             internal int _codepos;
  280.             internal int _flags;
  281.             internal Label _label;
  282.         }
  283.        
  284. /*
  285.         * Adds a backtrack note to the list of them, and returns the index of the new
  286.         * note (which is also the index for the jump used by the switch table)
  287.         */       
  288.         internal int AddBacktrackNote(int flags, Label l, int codepos)
  289.         {
  290.             if (_notes == null || _notecount >= _notes.Length) {
  291.                 BacktrackNote[] newnotes = new BacktrackNote[_notes == null ? 16 : _notes.Length * 2];
  292.                 if (_notes != null)
  293.                     System.Array.Copy(_notes, 0, newnotes, 0, _notecount);
  294.                 _notes = newnotes;
  295.             }
  296.            
  297.             _notes[_notecount] = new BacktrackNote(flags, l, codepos);
  298.            
  299.             return _notecount++;
  300.         }
  301.        
  302. /*
  303.         * Adds a backtrack note for the current operation; creates a new label for
  304.         * where the code will be, and returns the switch index.
  305.         */       
  306.         internal int AddTrack()
  307.         {
  308.             return AddTrack(RegexCode.Back);
  309.         }
  310.        
  311. /*
  312.         * Adds a backtrack note for the current operation; creates a new label for
  313.         * where the code will be, and returns the switch index.
  314.         */       
  315.         internal int AddTrack(int flags)
  316.         {
  317.             return AddBacktrackNote(flags, DefineLabel(), _codepos);
  318.         }
  319.        
  320. /*
  321.         * Adds a switchtable entry for the specified position (for the forward
  322.         * logic; does not cause backtracking logic to be generated)
  323.         */       
  324.         internal int AddGoto(int destpos)
  325.         {
  326.             if (_goto[destpos] == -1)
  327.                 _goto[destpos] = AddBacktrackNote(0, _labels[destpos], destpos);
  328.            
  329.             return _goto[destpos];
  330.         }
  331.        
  332. /*
  333.         * Adds a note for backtracking code that only needs to be generated once;
  334.         * if it's already marked to be generated, returns the switch index
  335.         * for the unique piece of code.
  336.         */       
  337.         internal int AddUniqueTrack(int i)
  338.         {
  339.             return AddUniqueTrack(i, RegexCode.Back);
  340.         }
  341.        
  342. /*
  343.         * Adds a note for backtracking code that only needs to be generated once;
  344.         * if it's already marked to be generated, returns the switch index
  345.         * for the unique piece of code.
  346.         */       
  347.         internal int AddUniqueTrack(int i, int flags)
  348.         {
  349.             if (_uniquenote[i] == -1)
  350.                 _uniquenote[i] = AddTrack(flags);
  351.            
  352.             return _uniquenote[i];
  353.         }
  354.        
  355. /*
  356.         * A macro for _ilg.DefineLabel
  357.         */       
  358.         internal Label DefineLabel()
  359.         {
  360.             return _ilg.DefineLabel();
  361.         }
  362.        
  363. /*
  364.         * A macro for _ilg.MarkLabel
  365.         */       
  366.         internal void MarkLabel(Label l)
  367.         {
  368.             _ilg.MarkLabel(l);
  369.         }
  370.        
  371. /*
  372.         * Returns the ith operand of the current operation
  373.         */       
  374.         internal int Operand(int i)
  375.         {
  376.             return _codes[_codepos + i + 1];
  377.         }
  378.        
  379. /*
  380.         * True if the current operation is marked for the leftward direction
  381.         */       
  382.         internal bool IsRtl()
  383.         {
  384.             return (_regexopcode & RegexCode.Rtl) != 0;
  385.         }
  386.        
  387. /*
  388.         * True if the current operation is marked for the leftward direction
  389.         */       
  390.         internal bool IsCi()
  391.         {
  392.             return (_regexopcode & RegexCode.Ci) != 0;
  393.         }
  394.        
  395.         #if DBG
  396. /*
  397.         * True if we need to do the backtrack logic for the current operation
  398.         */       
  399.         internal bool IsBack()
  400.         {
  401.             return (_regexopcode & RegexCode.Back) != 0;
  402.         }
  403.        
  404. /*
  405.         * True if we need to do the second-backtrack logic for the current operation
  406.         */       
  407.         internal bool IsBack2()
  408.         {
  409.             return (_regexopcode & RegexCode.Back2) != 0;
  410.         }
  411.         #endif
  412.        
  413. /*
  414.         * Returns the raw regex opcode (masking out Back and Rtl)
  415.         */       
  416.         internal int Code()
  417.         {
  418.             return _regexopcode & RegexCode.Mask;
  419.         }
  420.        
  421.         internal void Ldstr(string str)
  422.         {
  423.             _ilg.Emit(OpCodes.Ldstr, str);
  424.         }
  425.        
  426. /*
  427.         * A macro for the various forms of Ldc
  428.         */       
  429.         internal void Ldc(int i)
  430.         {
  431.             if (i <= 127 && i >= -128)
  432.                 _ilg.Emit(OpCodes.Ldc_I4_S, (byte)i);
  433.             else
  434.                 _ilg.Emit(OpCodes.Ldc_I4, i);
  435.         }
  436.        
  437. /*
  438.         * A macro for _ilg.Emit(OpCodes.Dup)
  439.         */       
  440.         internal void Dup()
  441.         {
  442.             _ilg.Emit(OpCodes.Dup);
  443.         }
  444.        
  445. /*
  446.         * A macro for _ilg.Emit(OpCodes.Ret)
  447.         */       
  448.         internal void Ret()
  449.         {
  450.             _ilg.Emit(OpCodes.Ret);
  451.         }
  452.        
  453. /*
  454.         * A macro for _ilg.Emit(OpCodes.Pop)
  455.         */       
  456.         internal void Pop()
  457.         {
  458.             _ilg.Emit(OpCodes.Pop);
  459.         }
  460.        
  461. /*
  462.         * A macro for _ilg.Emit(OpCodes.Add)
  463.         */       
  464.         internal void Add()
  465.         {
  466.             _ilg.Emit(OpCodes.Add);
  467.         }
  468.        
  469. /*
  470.         * A macro for _ilg.Emit(OpCodes.Add); a true flag can turn it into a Sub
  471.         */       
  472.         internal void Add(bool negate)
  473.         {
  474.             if (negate)
  475.                 _ilg.Emit(OpCodes.Sub);
  476.             else
  477.                 _ilg.Emit(OpCodes.Add);
  478.         }
  479.        
  480. /*
  481.         * A macro for _ilg.Emit(OpCodes.Sub)
  482.         */       
  483.         internal void Sub()
  484.         {
  485.             _ilg.Emit(OpCodes.Sub);
  486.         }
  487.        
  488. /*
  489.         * A macro for _ilg.Emit(OpCodes.Sub); a true flag can turn it into a Add
  490.         */       
  491.         internal void Sub(bool negate)
  492.         {
  493.             if (negate)
  494.                 _ilg.Emit(OpCodes.Add);
  495.             else
  496.                 _ilg.Emit(OpCodes.Sub);
  497.         }
  498.        
  499. /*
  500.         * A macro for _ilg.Emit(OpCodes.Ldloc);
  501.         */       
  502.         internal void Ldloc(LocalBuilder lt)
  503.         {
  504.             _ilg.Emit(OpCodes.Ldloc_S, lt);
  505.         }
  506.        
  507. /*
  508.         * A macro for _ilg.Emit(OpCodes.Stloc);
  509.         */       
  510.         internal void Stloc(LocalBuilder lt)
  511.         {
  512.             _ilg.Emit(OpCodes.Stloc_S, lt);
  513.         }
  514.        
  515. /*
  516.         * A macro for _ilg.Emit(OpCodes.Ldarg_0);
  517.         */       
  518.         internal void Ldthis()
  519.         {
  520.             _ilg.Emit(OpCodes.Ldarg_0);
  521.         }
  522.        
  523. /*
  524.         * A macro for Ldthis(); Ldfld();
  525.         */       
  526.         internal void Ldthisfld(FieldInfo ft)
  527.         {
  528.             Ldthis();
  529.             _ilg.Emit(OpCodes.Ldfld, ft);
  530.         }
  531.        
  532. /*
  533.         * A macro for Ldthis(); Ldfld(); Stloc();
  534.         */       
  535.         internal void Mvfldloc(FieldInfo ft, LocalBuilder lt)
  536.         {
  537.             Ldthisfld(ft);
  538.             Stloc(lt);
  539.         }
  540.        
  541. /*
  542.         * A macro for Ldthis(); Ldthisfld(); Stloc();
  543.         */       
  544.         internal void Mvlocfld(LocalBuilder lt, FieldInfo ft)
  545.         {
  546.             Ldthis();
  547.             Ldloc(lt);
  548.             Stfld(ft);
  549.         }
  550.        
  551. /*
  552.         * A macro for _ilg.Emit(OpCodes.Stfld);
  553.         */       
  554.         internal void Stfld(FieldInfo ft)
  555.         {
  556.             _ilg.Emit(OpCodes.Stfld, ft);
  557.         }
  558.        
  559. /*
  560.         * A macro for _ilg.Emit(OpCodes.Callvirt);
  561.         */       
  562.         internal void Callvirt(MethodInfo mt)
  563.         {
  564.             _ilg.Emit(OpCodes.Callvirt, mt);
  565.         }
  566.        
  567. /*
  568.         * A macro for _ilg.Emit(OpCodes.Call);
  569.         */       
  570.         internal void Call(MethodInfo mt)
  571.         {
  572.             _ilg.Emit(OpCodes.Call, mt);
  573.         }
  574.        
  575. /*
  576.         * A macro for _ilg.Emit(OpCodes.Newobj);
  577.         */       
  578.         internal void Newobj(ConstructorInfo ct)
  579.         {
  580.             _ilg.Emit(OpCodes.Newobj, ct);
  581.         }
  582.        
  583. /*
  584.         * A macro for _ilg.Emit(OpCodes.Brfalse) (long form)
  585.         */       
  586.         internal void BrfalseFar(Label l)
  587.         {
  588.             _ilg.Emit(OpCodes.Brfalse, l);
  589.         }
  590.        
  591. /*
  592.         * A macro for _ilg.Emit(OpCodes.Brtrue) (long form)
  593.         */       
  594.         internal void BrtrueFar(Label l)
  595.         {
  596.             _ilg.Emit(OpCodes.Brtrue, l);
  597.         }
  598.        
  599. /*
  600.         * A macro for _ilg.Emit(OpCodes.Br) (long form)
  601.         */       
  602.         internal void BrFar(Label l)
  603.         {
  604.             _ilg.Emit(OpCodes.Br, l);
  605.         }
  606.        
  607. /*
  608.         * A macro for _ilg.Emit(OpCodes.Ble) (long form)
  609.         */       
  610.         internal void BleFar(Label l)
  611.         {
  612.             _ilg.Emit(OpCodes.Ble, l);
  613.         }
  614.        
  615. /*
  616.         * A macro for _ilg.Emit(OpCodes.Blt) (long form)
  617.         */       
  618.         internal void BltFar(Label l)
  619.         {
  620.             _ilg.Emit(OpCodes.Blt, l);
  621.         }
  622.        
  623. /*
  624.         * A macro for _ilg.Emit(OpCodes.Bge) (long form)
  625.         */       
  626.         internal void BgeFar(Label l)
  627.         {
  628.             _ilg.Emit(OpCodes.Bge, l);
  629.         }
  630.        
  631. /*
  632.         * A macro for _ilg.Emit(OpCodes.Bgt) (long form)
  633.         */       
  634.         internal void BgtFar(Label l)
  635.         {
  636.             _ilg.Emit(OpCodes.Bgt, l);
  637.         }
  638.        
  639. /*
  640.         * A macro for _ilg.Emit(OpCodes.Bne) (long form)
  641.         */       
  642.         internal void BneFar(Label l)
  643.         {
  644.             _ilg.Emit(OpCodes.Bne_Un, l);
  645.         }
  646.        
  647. /*
  648.         * A macro for _ilg.Emit(OpCodes.Beq) (long form)
  649.         */       
  650.         internal void BeqFar(Label l)
  651.         {
  652.             _ilg.Emit(OpCodes.Beq, l);
  653.         }
  654.        
  655. /*
  656.         * A macro for _ilg.Emit(OpCodes.Brfalse_S) (short jump)
  657.         */       
  658.         internal void Brfalse(Label l)
  659.         {
  660.             _ilg.Emit(OpCodes.Brfalse_S, l);
  661.         }
  662.        
  663. /*
  664.         * A macro for _ilg.Emit(OpCodes.Br_S) (short jump)
  665.         */       
  666.         internal void Br(Label l)
  667.         {
  668.             _ilg.Emit(OpCodes.Br_S, l);
  669.         }
  670.        
  671. /*
  672.         * A macro for _ilg.Emit(OpCodes.Ble_S) (short jump)
  673.         */       
  674.         internal void Ble(Label l)
  675.         {
  676.             _ilg.Emit(OpCodes.Ble_S, l);
  677.         }
  678.        
  679. /*
  680.         * A macro for _ilg.Emit(OpCodes.Blt_S) (short jump)
  681.         */       
  682.         internal void Blt(Label l)
  683.         {
  684.             _ilg.Emit(OpCodes.Blt_S, l);
  685.         }
  686.        
  687. /*
  688.         * A macro for _ilg.Emit(OpCodes.Bge_S) (short jump)
  689.         */       
  690.         internal void Bge(Label l)
  691.         {
  692.             _ilg.Emit(OpCodes.Bge_S, l);
  693.         }
  694.        
  695. /*
  696.         * A macro for _ilg.Emit(OpCodes.Bgt_S) (short jump)
  697.         */       
  698.         internal void Bgt(Label l)
  699.         {
  700.             _ilg.Emit(OpCodes.Bgt_S, l);
  701.         }
  702.        
  703. /*
  704.         * A macro for _ilg.Emit(OpCodes.Bleun_S) (short jump)
  705.         */       
  706.         internal void Bgtun(Label l)
  707.         {
  708.             _ilg.Emit(OpCodes.Bgt_Un_S, l);
  709.         }
  710.        
  711. /*
  712.         * A macro for _ilg.Emit(OpCodes.Bne_S) (short jump)
  713.         */       
  714.         internal void Bne(Label l)
  715.         {
  716.             _ilg.Emit(OpCodes.Bne_Un_S, l);
  717.         }
  718.        
  719. /*
  720.         * A macro for _ilg.Emit(OpCodes.Beq_S) (short jump)
  721.         */       
  722.         internal void Beq(Label l)
  723.         {
  724.             _ilg.Emit(OpCodes.Beq_S, l);
  725.         }
  726.        
  727. /*
  728.         * A macro for the Ldlen instruction
  729.         */       
  730.         internal void Ldlen()
  731.         {
  732.             _ilg.Emit(OpCodes.Ldlen);
  733.         }
  734.        
  735. /*
  736.         * Loads the char to the right of the current position
  737.         */       
  738.         internal void Rightchar()
  739.         {
  740.             Ldloc(_textV);
  741.             Ldloc(_textposV);
  742.             Callvirt(_getcharM);
  743.         }
  744.        
  745. /*
  746.         * Loads the char to the right of the current position and advances the current position
  747.         */       
  748.         internal void Rightcharnext()
  749.         {
  750.             Ldloc(_textV);
  751.             Ldloc(_textposV);
  752.             Dup();
  753.             Ldc(1);
  754.             Add();
  755.             Stloc(_textposV);
  756.             Callvirt(_getcharM);
  757.         }
  758.        
  759. /*
  760.         * Loads the char to the left of the current position
  761.         */       
  762.         internal void Leftchar()
  763.         {
  764.             Ldloc(_textV);
  765.             Ldloc(_textposV);
  766.             Ldc(1);
  767.             Sub();
  768.             Callvirt(_getcharM);
  769.         }
  770.        
  771. /*
  772.         * Loads the char to the left of the current position and advances (leftward)
  773.         */       
  774.         internal void Leftcharnext()
  775.         {
  776.             Ldloc(_textV);
  777.             Ldloc(_textposV);
  778.             Ldc(1);
  779.             Sub();
  780.             Dup();
  781.             Stloc(_textposV);
  782.             Callvirt(_getcharM);
  783.         }
  784.        
  785. /*
  786.         * Creates a backtrack note and pushes the switch index it on the tracking stack
  787.         */       
  788.         internal void Track()
  789.         {
  790.             ReadyPushTrack();
  791.             Ldc(AddTrack());
  792.             DoPush();
  793.         }
  794.        
  795. /*
  796.         * Pushes the current switch index on the tracking stack so the backtracking
  797.         * logic will be repeated again next time we backtrack here.
  798.         *
  799.         * <CONSIDER>perhaps we can just "unpop" the tracking stack because _backpos
  800.         * should aways be there already?</CONSIDER>
  801.         */       
  802.         internal void Trackagain()
  803.         {
  804.             ReadyPushTrack();
  805.             Ldc(_backpos);
  806.             DoPush();
  807.         }
  808.        
  809. /*
  810.         * Saves the value of a local variable on the tracking stack
  811.         */       
  812.         internal void PushTrack(LocalBuilder lt)
  813.         {
  814.             ReadyPushTrack();
  815.             Ldloc(lt);
  816.             DoPush();
  817.         }
  818.        
  819. /*
  820.         * Creates a backtrack note for a piece of code that should only be generated once,
  821.         * and emits code that pushes the switch index on the backtracking stack.
  822.         */       
  823.         internal void TrackUnique(int i)
  824.         {
  825.             ReadyPushTrack();
  826.             Ldc(AddUniqueTrack(i));
  827.             DoPush();
  828.         }
  829.        
  830. /*
  831.         * Creates a second-backtrack note for a piece of code that should only be
  832.         * generated once, and emits code that pushes the switch index on the
  833.         * backtracking stack.
  834.         */       
  835.         internal void TrackUnique2(int i)
  836.         {
  837.             ReadyPushTrack();
  838.             Ldc(AddUniqueTrack(i, RegexCode.Back2));
  839.             DoPush();
  840.         }
  841.        
  842. /*
  843.         * Prologue to code that will push an element on the tracking stack
  844.         */       
  845.         internal void ReadyPushTrack()
  846.         {
  847.             _ilg.Emit(OpCodes.Ldloc_S, _trackV);
  848.             _ilg.Emit(OpCodes.Ldloc_S, _trackposV);
  849.             _ilg.Emit(OpCodes.Ldc_I4_1);
  850.             _ilg.Emit(OpCodes.Sub);
  851.             _ilg.Emit(OpCodes.Dup);
  852.             _ilg.Emit(OpCodes.Stloc_S, _trackposV);
  853.         }
  854.        
  855. /*
  856.         * Pops an element off the tracking stack (leave it on the operand stack)
  857.         */       
  858.         internal void PopTrack()
  859.         {
  860.             _ilg.Emit(OpCodes.Ldloc_S, _trackV);
  861.             _ilg.Emit(OpCodes.Ldloc_S, _trackposV);
  862.             _ilg.Emit(OpCodes.Dup);
  863.             _ilg.Emit(OpCodes.Ldc_I4_1);
  864.             _ilg.Emit(OpCodes.Add);
  865.             _ilg.Emit(OpCodes.Stloc_S, _trackposV);
  866.             _ilg.Emit(OpCodes.Ldelem_I4);
  867.         }
  868.        
  869. /*
  870.         * Retrieves the top entry on the tracking stack without popping
  871.         */       
  872.         internal void TopTrack()
  873.         {
  874.             _ilg.Emit(OpCodes.Ldloc_S, _trackV);
  875.             _ilg.Emit(OpCodes.Ldloc_S, _trackposV);
  876.             _ilg.Emit(OpCodes.Ldelem_I4);
  877.         }
  878.        
  879. /*
  880.         * Saves the value of a local variable on the grouping stack
  881.         */       
  882.         internal void PushStack(LocalBuilder lt)
  883.         {
  884.             ReadyPushStack();
  885.             _ilg.Emit(OpCodes.Ldloc_S, lt);
  886.             DoPush();
  887.         }
  888.        
  889. /*
  890.         * Prologue to code that will replace the ith element on the grouping stack
  891.         */       
  892.         internal void ReadyReplaceStack(int i)
  893.         {
  894.             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
  895.             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
  896.             if (i != 0) {
  897.                 Ldc(i);
  898.                 _ilg.Emit(OpCodes.Add);
  899.             }
  900.         }
  901.        
  902. /*
  903.         * Prologue to code that will push an element on the grouping stack
  904.         */       
  905.         internal void ReadyPushStack()
  906.         {
  907.             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
  908.             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
  909.             _ilg.Emit(OpCodes.Ldc_I4_1);
  910.             _ilg.Emit(OpCodes.Sub);
  911.             _ilg.Emit(OpCodes.Dup);
  912.             _ilg.Emit(OpCodes.Stloc_S, _stackposV);
  913.         }
  914.        
  915. /*
  916.         * Retrieves the top entry on the stack without popping
  917.         */       
  918.         internal void TopStack()
  919.         {
  920.             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
  921.             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
  922.             _ilg.Emit(OpCodes.Ldelem_I4);
  923.         }
  924.        
  925. /*
  926.         * Pops an element off the grouping stack (leave it on the operand stack)
  927.         */       
  928.         internal void PopStack()
  929.         {
  930.             _ilg.Emit(OpCodes.Ldloc_S, _stackV);
  931.             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
  932.             _ilg.Emit(OpCodes.Dup);
  933.             _ilg.Emit(OpCodes.Ldc_I4_1);
  934.             _ilg.Emit(OpCodes.Add);
  935.             _ilg.Emit(OpCodes.Stloc_S, _stackposV);
  936.             _ilg.Emit(OpCodes.Ldelem_I4);
  937.         }
  938.        
  939. /*
  940.         * Pops 1 element off the grouping stack and discards it
  941.         */       
  942.         internal void PopDiscardStack()
  943.         {
  944.             PopDiscardStack(1);
  945.         }
  946.        
  947. /*
  948.         * Pops i elements off the grouping stack and discards them
  949.         */       
  950.         internal void PopDiscardStack(int i)
  951.         {
  952.             _ilg.Emit(OpCodes.Ldloc_S, _stackposV);
  953.             Ldc(i);
  954.             _ilg.Emit(OpCodes.Add);
  955.             _ilg.Emit(OpCodes.Stloc_S, _stackposV);
  956.         }
  957.        
  958. /*
  959.         * Epilogue to code that will replace an element on a stack (use Ld* in between)
  960.         */       
  961.         internal void DoReplace()
  962.         {
  963.             _ilg.Emit(OpCodes.Stelem_I4);
  964.         }
  965.        
  966. /*
  967.         * Epilogue to code that will push an element on a stack (use Ld* in between)
  968.         */       
  969.         internal void DoPush()
  970.         {
  971.             _ilg.Emit(OpCodes.Stelem_I4);
  972.         }
  973.        
  974. /*
  975.         * Jump to the backtracking switch
  976.         */       
  977.         internal void Back()
  978.         {
  979.             _ilg.Emit(OpCodes.Br, _backtrack);
  980.         }
  981.        
  982. /*
  983.         * Branch to the MSIL corresponding to the regex code at i
  984.         *
  985.         * A trick: since track and stack space is gobbled up unboundedly
  986.         * only as a result of branching backwards, this is where we check
  987.         * for sufficient space and trigger reallocations.
  988.         *
  989.         * If the "goto" is backwards, we generate code that checks
  990.         * available space against the amount of space that would be needed
  991.         * in the worst case by code that will only go forward; if there's
  992.         * not enough, we push the destination on the tracking stack, then
  993.         * we jump to the place where we invoke the allocator.
  994.         *
  995.         * Since forward gotos pose no threat, they just turn into a Br.
  996.         */       
  997.         internal void Goto(int i)
  998.         {
  999.             if (i < _codepos) {
  1000.                 Label l1 = DefineLabel();
  1001.                
  1002.                 // When going backwards, ensure enough space.
  1003.                 Ldloc(_trackposV);
  1004.                 Ldc(_trackcount * 4);
  1005.                 Ble(l1);
  1006.                 Ldloc(_stackposV);
  1007.                 Ldc(_trackcount * 3);
  1008.                 BgtFar(_labels[i]);
  1009.                 MarkLabel(l1);
  1010.                 ReadyPushTrack();
  1011.                 Ldc(AddGoto(i));
  1012.                 DoPush();
  1013.                 BrFar(_backtrack);
  1014.             }
  1015.             else {
  1016.                 BrFar(_labels[i]);
  1017.             }
  1018.         }
  1019.        
  1020. /*
  1021.         * Returns the position of the next operation in the regex code, taking
  1022.         * into account the different numbers of arguments taken by operations
  1023.         */       
  1024.         internal int NextCodepos()
  1025.         {
  1026.             return _codepos + RegexCode.OpcodeSize(_codes[_codepos]);
  1027.         }
  1028.        
  1029. /*
  1030.         * The label for the next (forward) operation
  1031.         */       
  1032.         internal Label AdvanceLabel()
  1033.         {
  1034.             return _labels[NextCodepos()];
  1035.         }
  1036.        
  1037. /*
  1038.         * Goto the next (forward) operation
  1039.         */       
  1040.         internal void Advance()
  1041.         {
  1042.             _ilg.Emit(OpCodes.Br, AdvanceLabel());
  1043.         }
  1044.        
  1045.         internal void CallToLower()
  1046.         {
  1047.             if ((_options & RegexOptions.CultureInvariant) != 0)
  1048.                 Call(_getInvariantCulture);
  1049.             else
  1050.                 Call(_getCurrentCulture);
  1051.            
  1052.             Call(_chartolowerM);
  1053.         }
  1054.        
  1055. /*
  1056.         * Generates the first section of the MSIL. This section contains all
  1057.         * the forward logic, and corresponds directly to the regex codes.
  1058.         *
  1059.         * In the absence of backtracking, this is all we would need.
  1060.         */       
  1061.         internal void GenerateForwardSection()
  1062.         {
  1063.             int codepos;
  1064.            
  1065.             _labels = new Label[_codes.Length];
  1066.             _goto = new int[_codes.Length];
  1067.            
  1068.             // initialize
  1069.            
  1070.             for (codepos = 0; codepos < _codes.Length; codepos += RegexCode.OpcodeSize(_codes[codepos])) {
  1071.                 _goto[codepos] = -1;
  1072.                 _labels[codepos] = _ilg.DefineLabel();
  1073.             }
  1074.            
  1075.             _uniquenote = new int[uniquecount];
  1076.             for (int i = 0; i < uniquecount; i++)
  1077.                 _uniquenote[i] = -1;
  1078.            
  1079.             // emit variable initializers
  1080.            
  1081.             Mvfldloc(_textF, _textV);
  1082.             Mvfldloc(_textstartF, _textstartV);
  1083.             Mvfldloc(_textbegF, _textbegV);
  1084.             Mvfldloc(_textendF, _textendV);
  1085.             Mvfldloc(_textposF, _textposV);
  1086.             Mvfldloc(_trackF, _trackV);
  1087.             Mvfldloc(_trackposF, _trackposV);
  1088.             Mvfldloc(_stackF, _stackV);
  1089.             Mvfldloc(_stackposF, _stackposV);
  1090.            
  1091.             _backpos = -1;
  1092.            
  1093.             for (codepos = 0; codepos < _codes.Length; codepos += RegexCode.OpcodeSize(_codes[codepos])) {
  1094.                 MarkLabel(_labels[codepos]);
  1095.                 _codepos = codepos;
  1096.                 _regexopcode = _codes[codepos];
  1097.                 GenerateOneCode();
  1098.             }
  1099.         }
  1100.        
  1101. /*
  1102.         * Generates the middle section of the MSIL. This section contains the
  1103.         * big switch jump that allows us to simulate a stack of addresses,
  1104.         * and it also contains the calls that expand the tracking and the
  1105.         * grouping stack when they get too full.
  1106.         */       
  1107.         internal void GenerateMiddleSection()
  1108.         {
  1109.             Label l1 = DefineLabel();
  1110.             Label[] table;
  1111.             int i;
  1112.            
  1113.             // Backtrack switch
  1114.             MarkLabel(_backtrack);
  1115.            
  1116.             // first call EnsureStorage
  1117.             Mvlocfld(_trackposV, _trackposF);
  1118.             Mvlocfld(_stackposV, _stackposF);
  1119.             Ldthis();
  1120.             Callvirt(_ensurestorageM);
  1121.             Mvfldloc(_trackposF, _trackposV);
  1122.             Mvfldloc(_stackposF, _stackposV);
  1123.             Mvfldloc(_trackF, _trackV);
  1124.             Mvfldloc(_stackF, _stackV);
  1125.            
  1126.            
  1127.             PopTrack();
  1128.            
  1129.             table = new Label[_notecount];
  1130.             for (i = 0; i < _notecount; i++)
  1131.                 table[i] = _notes[i]._label;
  1132.            
  1133.             _ilg.Emit(OpCodes.Switch, table);
  1134.            
  1135.         }
  1136.        
  1137. /*
  1138.         * Generates the last section of the MSIL. This section contains all of
  1139.         * the backtracking logic.
  1140.         */       
  1141.         internal void GenerateBacktrackSection()
  1142.         {
  1143.             int i;
  1144.            
  1145.             for (i = 0; i < _notecount; i++) {
  1146.                 BacktrackNote n = _notes[i];
  1147.                 if (n._flags != 0) {
  1148.                     _ilg.MarkLabel(n._label);
  1149.                     _codepos = n._codepos;
  1150.                     _backpos = i;
  1151.                     _regexopcode = _codes[n._codepos] | n._flags;
  1152.                     GenerateOneCode();
  1153.                 }
  1154.             }
  1155.         }
  1156.        
  1157. /*
  1158.         * Generates FindFirstChar
  1159.         */       
  1160.         internal void GenerateFindFirstChar()
  1161.         {
  1162.             _textposV = DeclareInt();
  1163.             _textV = DeclareString();
  1164.             _tempV = DeclareInt();
  1165.             _temp2V = DeclareInt();
  1166.            
  1167.             if (0 != (_anchors & (RegexFCD.Beginning | RegexFCD.Start | RegexFCD.EndZ | RegexFCD.End))) {
  1168.                 if (!_code._rightToLeft) {
  1169.                     if (0 != (_anchors & RegexFCD.Beginning)) {
  1170.                         Label l1 = DefineLabel();
  1171.                         Ldthisfld(_textposF);
  1172.                         Ldthisfld(_textbegF);
  1173.                         Ble(l1);
  1174.                         Ldthis();
  1175.                         Ldthisfld(_textendF);
  1176.                         Stfld(_textposF);
  1177.                         Ldc(0);
  1178.                         Ret();
  1179.                         MarkLabel(l1);
  1180.                     }
  1181.                    
  1182.                     if (0 != (_anchors & RegexFCD.Start)) {
  1183.                         Label l1 = DefineLabel();
  1184.                         Ldthisfld(_textposF);
  1185.                         Ldthisfld(_textstartF);
  1186.                         Ble(l1);
  1187.                         Ldthis();
  1188.                         Ldthisfld(_textendF);
  1189.                         Stfld(_textposF);
  1190.                         Ldc(0);
  1191.                         Ret();
  1192.                         MarkLabel(l1);
  1193.                     }
  1194.                    
  1195.                     if (0 != (_anchors & RegexFCD.EndZ)) {
  1196.                         Label l1 = DefineLabel();
  1197.                         Ldthisfld(_textposF);
  1198.                         Ldthisfld(_textendF);
  1199.                         Ldc(1);
  1200.                         Sub();
  1201.                         Bge(l1);
  1202.                         Ldthis();
  1203.                         Ldthisfld(_textendF);
  1204.                         Ldc(1);
  1205.                         Sub();
  1206.                         Stfld(_textposF);
  1207.                         MarkLabel(l1);
  1208.                     }
  1209.                    
  1210.                     if (0 != (_anchors & RegexFCD.End)) {
  1211.                         Label l1 = DefineLabel();
  1212.                         Ldthisfld(_textposF);
  1213.                         Ldthisfld(_textendF);
  1214.                         Bge(l1);
  1215.                         Ldthis();
  1216.                         Ldthisfld(_textendF);
  1217.                         Stfld(_textposF);
  1218.                         MarkLabel(l1);
  1219.                     }
  1220.                 }
  1221.                 else {
  1222.                     if (0 != (_anchors & RegexFCD.End)) {
  1223.                         Label l1 = DefineLabel();
  1224.                         Ldthisfld(_textposF);
  1225.                         Ldthisfld(_textendF);
  1226.                         Bge(l1);
  1227.                         Ldthis();
  1228.                         Ldthisfld(_textbegF);
  1229.                         Stfld(_textposF);
  1230.                         Ldc(0);
  1231.                         Ret();
  1232.                         MarkLabel(l1);
  1233.                     }
  1234.                    
  1235.                     if (0 != (_anchors & RegexFCD.EndZ)) {
  1236.                         Label l1 = DefineLabel();
  1237.                         Label l2 = DefineLabel();
  1238.                         Ldthisfld(_textposF);
  1239.                         Ldthisfld(_textendF);
  1240.                         Ldc(1);
  1241.                         Sub();
  1242.                         Blt(l1);
  1243.                         Ldthisfld(_textposF);
  1244.                         Ldthisfld(_textendF);
  1245.                         Beq(l2);
  1246.                         Ldthisfld(_textF);
  1247.                         Ldthisfld(_textposF);
  1248.                         Callvirt(_getcharM);
  1249.                         Ldc((int)'\n');
  1250.                         Beq(l2);
  1251.                         MarkLabel(l1);
  1252.                         Ldthis();
  1253.                         Ldthisfld(_textbegF);
  1254.                         Stfld(_textposF);
  1255.                         Ldc(0);
  1256.                         Ret();
  1257.                         MarkLabel(l2);
  1258.                     }
  1259.                    
  1260.                     if (0 != (_anchors & RegexFCD.Start)) {
  1261.                         Label l1 = DefineLabel();
  1262.                         Ldthisfld(_textposF);
  1263.                         Ldthisfld(_textstartF);
  1264.                         Bge(l1);
  1265.                         Ldthis();
  1266.                         Ldthisfld(_textbegF);
  1267.                         Stfld(_textposF);
  1268.                         Ldc(0);
  1269.                         Ret();
  1270.                         MarkLabel(l1);
  1271.                     }
  1272.                    
  1273.                     if (0 != (_anchors & RegexFCD.Beginning)) {
  1274.                         Label l1 = DefineLabel();
  1275.                         Ldthisfld(_textposF);
  1276.                         Ldthisfld(_textbegF);
  1277.                         Ble(l1);
  1278.                         Ldthis();
  1279.                         Ldthisfld(_textbegF);
  1280.                         Stfld(_textposF);
  1281.                         MarkLabel(l1);
  1282.                     }
  1283.                 }
  1284.                
  1285.                
  1286.                 Ldc(1);
  1287.                 Ret();
  1288.             }
  1289.             else if (_bmPrefix != null && _bmPrefix._negativeUnicode == null) {
  1290.                
  1291.                 LocalBuilder chV = _tempV;
  1292.                 LocalBuilder testV = _tempV;
  1293.                 LocalBuilder limitV = _temp2V;
  1294.                 Label lDefaultAdvance = DefineLabel();
  1295.                 Label lAdvance = DefineLabel();
  1296.                 Label lFail = DefineLabel();
  1297.                 Label lStart = DefineLabel();
  1298.                 Label lOutOfRange = DefineLabel();
  1299.                 Label lPartialMatch = DefineLabel();
  1300.                
  1301.                
  1302.                 int chLast;
  1303.                 int i;
  1304.                 int beforefirst;
  1305.                 int last;
  1306.                 Label[] table;
  1307.                
  1308.                 if (!_code._rightToLeft) {
  1309.                     beforefirst = -1;
  1310.                     last = _bmPrefix._pattern.Length - 1;
  1311.                 }
  1312.                 else {
  1313.                     beforefirst = _bmPrefix._pattern.Length;
  1314.                     last = 0;
  1315.                 }
  1316.                
  1317.                 chLast = _bmPrefix._pattern[last];
  1318.                
  1319.                 Mvfldloc(_textF, _textV);
  1320.                 if (!_code._rightToLeft)
  1321.                     Ldthisfld(_textendF);
  1322.                 else
  1323.                     Ldthisfld(_textbegF);
  1324.                 Stloc(limitV);
  1325.                
  1326.                 Ldthisfld(_textposF);
  1327.                 if (!_code._rightToLeft) {
  1328.                     Ldc(_bmPrefix._pattern.Length - 1);
  1329.                     Add();
  1330.                 }
  1331.                 else {
  1332.                     Ldc(_bmPrefix._pattern.Length);
  1333.                     Sub();
  1334.                 }
  1335.                 Stloc(_textposV);
  1336.                 Br(lStart);
  1337.                
  1338.                 MarkLabel(lDefaultAdvance);
  1339.                
  1340.                 if (!_code._rightToLeft)
  1341.                     Ldc(_bmPrefix._pattern.Length);
  1342.                 else
  1343.                     Ldc(-_bmPrefix._pattern.Length);
  1344.                
  1345.                 MarkLabel(lAdvance);
  1346.                
  1347.                 Ldloc(_textposV);
  1348.                 Add();
  1349.                 Stloc(_textposV);
  1350.                
  1351.                 MarkLabel(lStart);
  1352.                
  1353.                 Ldloc(_textposV);
  1354.                 Ldloc(limitV);
  1355.                 if (!_code._rightToLeft)
  1356.                     BgeFar(lFail);
  1357.                 else
  1358.                     BltFar(lFail);
  1359.                
  1360.                 Rightchar();
  1361.                 if (_bmPrefix._caseInsensitive)
  1362.                     CallToLower();
  1363.                
  1364.                 Dup();
  1365.                 Stloc(chV);
  1366.                 Ldc(chLast);
  1367.                 BeqFar(lPartialMatch);
  1368.                
  1369.                 Ldloc(chV);
  1370.                 Ldc(_bmPrefix._lowASCII);
  1371.                 Sub();
  1372.                 Dup();
  1373.                 Stloc(chV);
  1374.                 Ldc(_bmPrefix._highASCII - _bmPrefix._lowASCII);
  1375.                 Bgtun(lDefaultAdvance);
  1376.                
  1377.                 table = new Label[_bmPrefix._highASCII - _bmPrefix._lowASCII + 1];
  1378.                
  1379.                 for (i = _bmPrefix._lowASCII; i <= _bmPrefix._highASCII; i++) {
  1380.                     if (_bmPrefix._negativeASCII[i] == beforefirst)
  1381.                         table[i - _bmPrefix._lowASCII] = lDefaultAdvance;
  1382.                     else
  1383.                         table[i - _bmPrefix._lowASCII] = DefineLabel();
  1384.                 }
  1385.                
  1386.                 Ldloc(chV);
  1387.                 _ilg.Emit(OpCodes.Switch, table);
  1388.                
  1389.                 for (i = _bmPrefix._lowASCII; i <= _bmPrefix._highASCII; i++) {
  1390.                     if (_bmPrefix._negativeASCII[i] == beforefirst)
  1391.                         continue;
  1392.                    
  1393.                     MarkLabel(table[i - _bmPrefix._lowASCII]);
  1394.                    
  1395.                     Ldc(_bmPrefix._negativeASCII[i]);
  1396.                     BrFar(lAdvance);
  1397.                 }
  1398.                
  1399.                 MarkLabel(lPartialMatch);
  1400.                
  1401.                 Ldloc(_textposV);
  1402.                 Stloc(testV);
  1403.                
  1404.                 for (i = _bmPrefix._pattern.Length - 2; i >= 0; i--) {
  1405.                     Label lNext = DefineLabel();
  1406.                     int charindex;
  1407.                    
  1408.                     if (!_code._rightToLeft)
  1409.                         charindex = i;
  1410.                     else
  1411.                         charindex = _bmPrefix._pattern.Length - 1 - i;
  1412.                    
  1413.                     Ldloc(_textV);
  1414.                     Ldloc(testV);
  1415.                     Ldc(1);
  1416.                     Sub(_code._rightToLeft);
  1417.                     Dup();
  1418.                     Stloc(testV);
  1419.                     Callvirt(_getcharM);
  1420.                     if (_bmPrefix._caseInsensitive)
  1421.                         CallToLower();
  1422.                    
  1423.                     Ldc(_bmPrefix._pattern[charindex]);
  1424.                     Beq(lNext);
  1425.                     Ldc(_bmPrefix._positive[charindex]);
  1426.                     BrFar(lAdvance);
  1427.                    
  1428.                     MarkLabel(lNext);
  1429.                    
  1430.                 }
  1431.                
  1432.                 Ldthis();
  1433.                 Ldloc(testV);
  1434.                 if (_code._rightToLeft) {
  1435.                     Ldc(1);
  1436.                     Add();
  1437.                 }
  1438.                 Stfld(_textposF);
  1439.                 Ldc(1);
  1440.                 Ret();
  1441.                
  1442.                 MarkLabel(lFail);
  1443.                
  1444.                 Ldthis();
  1445.                 if (!_code._rightToLeft)
  1446.                     Ldthisfld(_textendF);
  1447.                 else
  1448.                     Ldthisfld(_textbegF);
  1449.                 Stfld(_textposF);
  1450.                 Ldc(0);
  1451.                 Ret();
  1452.             }
  1453.             else if (_fcPrefix == null) {
  1454.                 Ldc(1);
  1455.                 Ret();
  1456.             }
  1457.             else {
  1458.                 LocalBuilder cV = _temp2V;
  1459.                 LocalBuilder chV = _tempV;
  1460.                 Label l1 = DefineLabel();
  1461.                 Label l2 = DefineLabel();
  1462.                 Label l3 = DefineLabel();
  1463.                 Label l4 = DefineLabel();
  1464.                 Label l5 = DefineLabel();
  1465.                
  1466.                 Mvfldloc(_textposF, _textposV);
  1467.                 Mvfldloc(_textF, _textV);
  1468.                
  1469.                 if (!_code._rightToLeft) {
  1470.                     Ldthisfld(_textendF);
  1471.                     Ldloc(_textposV);
  1472.                 }
  1473.                 else {
  1474.                     Ldloc(_textposV);
  1475.                     Ldthisfld(_textbegF);
  1476.                 }
  1477.                 Sub();
  1478.                 Stloc(cV);
  1479.                
  1480.                 Ldloc(cV);
  1481.                 Ldc(0);
  1482.                 BleFar(l4);
  1483.                
  1484.                 MarkLabel(l1);
  1485.                
  1486.                 Ldloc(cV);
  1487.                 Ldc(1);
  1488.                 Sub();
  1489.                 Stloc(cV);
  1490.                
  1491.                 if (_code._rightToLeft)
  1492.                     Leftcharnext();
  1493.                 else
  1494.                     Rightcharnext();
  1495.                
  1496.                 if (_fcPrefix.CaseInsensitive)
  1497.                     CallToLower();
  1498.                
  1499.                 if (!RegexCharClass.IsSingleton(_fcPrefix.Prefix)) {
  1500.                     Ldstr(_fcPrefix.Prefix);
  1501.                     Call(_charInSetM);
  1502.                    
  1503.                     BrtrueFar(l2);
  1504.                 }
  1505.                 else {
  1506.                     Ldc(RegexCharClass.SingletonChar(_fcPrefix.Prefix));
  1507.                     Beq(l2);
  1508.                 }
  1509.                
  1510.                 MarkLabel(l5);
  1511.                
  1512.                 Ldloc(cV);
  1513.                 Ldc(0);
  1514.                 if (!RegexCharClass.IsSingleton(_fcPrefix.Prefix))
  1515.                     BgtFar(l1);
  1516.                 else
  1517.                     Bgt(l1);
  1518.                
  1519.                 Ldc(0);
  1520.                 BrFar(l3);
  1521.                
  1522.                 MarkLabel(l2);
  1523.                
  1524.                 /*         
  1525.                             // CURRENTLY DISABLED
  1526.                             // If for some reason we have a prefix we didn't use, use it now.
  1527.                
  1528.                             if (_bmPrefix != null) {
  1529.                                 if (!_code._rightToLeft) {
  1530.                                     Ldthisfld(_textendF);
  1531.                                     Ldloc(_textposV);
  1532.                                 }
  1533.                                 else {
  1534.                                     Ldloc(_textposV);
  1535.                                     Ldthisfld(_textbegF);
  1536.                                 }
  1537.                                 Sub();
  1538.                                 Ldc(_bmPrefix._pattern.Length - 1);
  1539.                                 BltFar(l5);
  1540.                                
  1541.                                 for (int i = 1; i < _bmPrefix._pattern.Length; i++) {
  1542.                                     Ldloc(_textV);
  1543.                                     Ldloc(_textposV);
  1544.                                     if (!_code._rightToLeft) {
  1545.                                         Ldc(i - 1);
  1546.                                         Add();
  1547.                                     }
  1548.                                     else {
  1549.                                         Ldc(i);
  1550.                                         Sub();
  1551.                                     }
  1552.                                     Callvirt(_getcharM);
  1553.                                     if (!_code._rightToLeft)
  1554.                                         Ldc(_bmPrefix._pattern[i]);
  1555.                                     else
  1556.                                         Ldc(_bmPrefix._pattern[_bmPrefix._pattern.Length - 1 - i]);
  1557.                                     BneFar(l5);
  1558.                                 }
  1559.                             }
  1560.                 */               
  1561.                
  1562. Ldloc(_textposV);
  1563.                 Ldc(1);
  1564.                 Sub(_code._rightToLeft);
  1565.                 Stloc(_textposV);
  1566.                 Ldc(1);
  1567.                
  1568.                 MarkLabel(l3);
  1569.                
  1570.                 Mvlocfld(_textposV, _textposF);
  1571.                 Ret();
  1572.                
  1573.                 MarkLabel(l4);
  1574.                 Ldc(0);
  1575.                 Ret();
  1576.             }
  1577.            
  1578.         }
  1579.        
  1580. /*
  1581.         * Generates a very simple method that sets the _trackcount field.
  1582.         */       
  1583.         internal void GenerateInitTrackCount()
  1584.         {
  1585.             Ldthis();
  1586.             Ldc(_trackcount);
  1587.             Stfld(_trackcountF);
  1588.             Ret();
  1589.         }
  1590.        
  1591. /*
  1592.         * Declares a local int
  1593.         */       
  1594.         internal LocalBuilder DeclareInt()
  1595.         {
  1596.             return _ilg.DeclareLocal(typeof(int));
  1597.         }
  1598.        
  1599. /*
  1600.         * Declares a local int array
  1601.         */       
  1602.         internal LocalBuilder DeclareIntArray()
  1603.         {
  1604.             return _ilg.DeclareLocal(typeof(int[]));
  1605.         }
  1606.        
  1607. /*
  1608.         * Declares a local string
  1609.         */       
  1610.         internal LocalBuilder DeclareString()
  1611.         {
  1612.             return _ilg.DeclareLocal(typeof(string));
  1613.         }
  1614.        
  1615. /*
  1616.         * Generates the code for "RegexRunner.Go"
  1617.         */       
  1618.         internal void GenerateGo()
  1619.         {
  1620.             // declare some locals
  1621.            
  1622.             _textposV = DeclareInt();
  1623.             _textV = DeclareString();
  1624.             _trackposV = DeclareInt();
  1625.             _trackV = DeclareIntArray();
  1626.             _stackposV = DeclareInt();
  1627.             _stackV = DeclareIntArray();
  1628.             _tempV = DeclareInt();
  1629.             _temp2V = DeclareInt();
  1630.             _temp3V = DeclareInt();
  1631.             _textbegV = DeclareInt();
  1632.             _textendV = DeclareInt();
  1633.             _textstartV = DeclareInt();
  1634.            
  1635.             // clear some tables
  1636.            
  1637.             _labels = null;
  1638.             _notes = null;
  1639.             _notecount = 0;
  1640.            
  1641.             // globally used labels
  1642.            
  1643.             _backtrack = DefineLabel();
  1644.            
  1645.             // emit the code!
  1646.            
  1647.             GenerateForwardSection();
  1648.             GenerateMiddleSection();
  1649.             GenerateBacktrackSection();
  1650.         }
  1651.        
  1652.         #if DBG
  1653. /*
  1654.         * Some simple debugging stuff
  1655.         */       
  1656.         static internal MethodInfo _debugWriteLine = typeof(Debug).GetMethod("WriteLine", new Type[] {typeof(string)});
  1657.        
  1658. /*
  1659.         * Debug only: emit code to print out a message
  1660.         */       
  1661.         internal void Message(string str)
  1662.         {
  1663.             Ldstr(str);
  1664.             Call(_debugWriteLine);
  1665.         }
  1666.        
  1667.         #endif
  1668.        
  1669. /*
  1670.         * The main translation function. It translates the logic for a single opcode at
  1671.         * the current position. The structure of this function exactly mirrors
  1672.         * the structure of the inner loop of RegexInterpreter.Go().
  1673.         *
  1674.         * The C# code from RegexInterpreter.Go() that corresponds to each case is
  1675.         * included as a comment.
  1676.         *
  1677.         * Note that since we're generating code, we can collapse many cases that are
  1678.         * dealt with one-at-a-time in RegexIntepreter. We can also unroll loops that
  1679.         * iterate over constant strings or sets.
  1680.         */       
  1681.         internal void GenerateOneCode()
  1682.         {
  1683.             #if DBG
  1684.             if ((_options & RegexOptions.Debug) != 0) {
  1685.                 Mvlocfld(_textposV, _textposF);
  1686.                 Mvlocfld(_trackposV, _trackposF);
  1687.                 Mvlocfld(_stackposV, _stackposF);
  1688.                 Ldthis();
  1689.                 Callvirt(_dumpstateM);
  1690.                 StringBuilder sb = new StringBuilder();
  1691.                 if (_backpos > 0)
  1692.                     sb.AppendFormat("{0:D6} ", _backpos);
  1693.                 else
  1694.                     sb.Append(" ");
  1695.                 sb.Append(_code.OpcodeDescription(_codepos));
  1696.                 if (IsBack())
  1697.                     sb.Append(" Back");
  1698.                 if (IsBack2())
  1699.                     sb.Append(" Back2");
  1700.                 Message(sb.ToString());
  1701.             }
  1702.             #endif
  1703.            
  1704.             switch (_regexopcode) {
  1705.                 case RegexCode.Stop:
  1706.                     //: return;
  1707.                     Mvlocfld(_textposV, _textposF);
  1708.                     // update _textpos
  1709.                     Ret();
  1710.                     break;
  1711.                 case RegexCode.Nothing:
  1712.                    
  1713.                     //: break Backward;
  1714.                     Back();
  1715.                     break;
  1716.                 case RegexCode.Goto:
  1717.                    
  1718.                     //: Goto(Operand(0));
  1719.                     Goto(Operand(0));
  1720.                     break;
  1721.                 case RegexCode.Testref:
  1722.                    
  1723.                     //: if (!_match.IsMatched(Operand(0)))
  1724.                     //: break Backward;
  1725.                     Ldthis();
  1726.                     Ldc(Operand(0));
  1727.                     Callvirt(_ismatchedM);
  1728.                     BrfalseFar(_backtrack);
  1729.                     break;
  1730.                 case RegexCode.Lazybranch:
  1731.                    
  1732.                     //: Track(Textpos());
  1733.                     PushTrack(_textposV);
  1734.                     Track();
  1735.                     break;
  1736.                 case RegexCode.Lazybranch | RegexCode.Back:
  1737.                    
  1738.                     //: Trackframe(1);
  1739.                     //: Textto(Tracked(0));
  1740.                     //: Goto(Operand(0));
  1741.                     PopTrack();
  1742.                     Stloc(_textposV);
  1743.                     Goto(Operand(0));
  1744.                     break;
  1745.                 case RegexCode.Nullmark:
  1746.                    
  1747.                     //: Stack(-1);
  1748.                     //: Track();
  1749.                     ReadyPushStack();
  1750.                     Ldc(-1);
  1751.                     DoPush();
  1752.                     TrackUnique(stackpop);
  1753.                     break;
  1754.                 case RegexCode.Setmark:
  1755.                    
  1756.                     //: Stack(Textpos());
  1757.                     //: Track();
  1758.                     PushStack(_textposV);
  1759.                     TrackUnique(stackpop);
  1760.                     break;
  1761.                 case RegexCode.Nullmark | RegexCode.Back:
  1762.                 case RegexCode.Setmark | RegexCode.Back:
  1763.                    
  1764.                     //: Stackframe(1);
  1765.                     //: break Backward;
  1766.                     PopDiscardStack();
  1767.                     Back();
  1768.                     break;
  1769.                 case RegexCode.Getmark:
  1770.                    
  1771.                     //: Stackframe(1);
  1772.                     //: Track(Stacked(0));
  1773.                     //: Textto(Stacked(0));
  1774.                     ReadyPushTrack();
  1775.                     PopStack();
  1776.                     Dup();
  1777.                     Stloc(_textposV);
  1778.                     DoPush();
  1779.                    
  1780.                     Track();
  1781.                     break;
  1782.                 case RegexCode.Getmark | RegexCode.Back:
  1783.                    
  1784.                     //: Trackframe(1);
  1785.                     //: Stack(Tracked(0));
  1786.                     //: break Backward;
  1787.                     ReadyPushStack();
  1788.                     PopTrack();
  1789.                     DoPush();
  1790.                     Back();
  1791.                     break;
  1792.                 case RegexCode.Capturemark:
  1793.                    
  1794.                     //: if (!IsMatched(Operand(1)))
  1795.                     //: break Backward;
  1796.                     //: Stackframe(1);
  1797.                     //: if (Operand(1) != -1)
  1798.                     //: TransferCapture(Operand(0), Operand(1), Stacked(0), Textpos());
  1799.                     //: else
  1800.                     //: Capture(Operand(0), Stacked(0), Textpos());
  1801.                     //: Track(Stacked(0));
  1802.                    
  1803.                     //: Stackframe(1);
  1804.                     //: Capture(Operand(0), Stacked(0), Textpos());
  1805.                     //: Track(Stacked(0));
  1806.                    
  1807.                     if (Operand(1) != -1) {
  1808.                         Ldthis();
  1809.                         Ldc(Operand(1));
  1810.                         Callvirt(_ismatchedM);
  1811.                         BrfalseFar(_backtrack);
  1812.                     }
  1813.                    
  1814.                     PopStack();
  1815.                     Stloc(_tempV);
  1816.                    
  1817.                     if (Operand(1) != -1) {
  1818.                         Ldthis();
  1819.                         Ldc(Operand(0));
  1820.                         Ldc(Operand(1));
  1821.                         Ldloc(_tempV);
  1822.                         Ldloc(_textposV);
  1823.                         Callvirt(_transferM);
  1824.                     }
  1825.                     else {
  1826.                         Ldthis();
  1827.                         Ldc(Operand(0));
  1828.                         Ldloc(_tempV);
  1829.                         Ldloc(_textposV);
  1830.                         Callvirt(_captureM);
  1831.                     }
  1832.                    
  1833.                     PushTrack(_tempV);
  1834.                    
  1835.                     if (Operand(0) != -1 && Operand(1) != -1)
  1836.                         TrackUnique(capback2);
  1837.                     else
  1838.                         TrackUnique(capback);
  1839.                    
  1840.                     break;
  1841.                 case RegexCode.Capturemark | RegexCode.Back:
  1842.                    
  1843.                    
  1844.                     //: Trackframe(1);
  1845.                     //: Stack(Tracked(0));
  1846.                     //: Uncapture();
  1847.                     //: if (Operand(0) != -1 && Operand(1) != -1)
  1848.                     //: Uncapture();
  1849.                     //: break Backward;
  1850.                     ReadyPushStack();
  1851.                     PopTrack();
  1852.                     DoPush();
  1853.                     Ldthis();
  1854.                     Callvirt(_uncaptureM);
  1855.                     if (Operand(0) != -1 && Operand(1) != -1) {
  1856.                         Ldthis();
  1857.                         Callvirt(_uncaptureM);
  1858.                     }
  1859.                     Back();
  1860.                     break;
  1861.                 case RegexCode.Branchmark:
  1862.                    
  1863.                     //: Stackframe(1);
  1864.                     //:
  1865.                     //: if (Textpos() != Stacked(0))
  1866.                     //: { // Nonempty match -> loop now
  1867.                     //: Track(Stacked(0), Textpos()); // Save old mark, textpos
  1868.                     //: Stack(Textpos()); // Make new mark
  1869.                     //: Goto(Operand(0)); // Loop
  1870.                     //: }
  1871.                     //: else
  1872.                     //: { // Empty match -> straight now
  1873.                     //: Track2(Stacked(0)); // Save old mark
  1874.                     //: Advance(1); // Straight
  1875.                     //: }
  1876.                     //: continue Forward;
  1877.                    
  1878.                     {
  1879.                         LocalBuilder mark = _tempV;
  1880.                         Label l1 = DefineLabel();
  1881.                        
  1882.                         PopStack();
  1883.                         Dup();
  1884.                         Stloc(mark);
  1885.                         // Stacked(0) -> temp
  1886.                         PushTrack(mark);
  1887.                         Ldloc(_textposV);
  1888.                         Beq(l1);
  1889.                         // mark == textpos -> branch
  1890.                         // (matched != 0)
  1891.                        
  1892.                         PushTrack(_textposV);
  1893.                         PushStack(_textposV);
  1894.                         Track();
  1895.                         Goto(Operand(0));
  1896.                         // Goto(Operand(0))
  1897.                         // else
  1898.                        
  1899.                         MarkLabel(l1);
  1900.                         TrackUnique2(branchmarkback2);
  1901.                         break;
  1902.                     }
  1903.                     break;
  1904.                 case RegexCode.Branchmark | RegexCode.Back:
  1905.                    
  1906.                     //: Trackframe(2);
  1907.                     //: Stackframe(1);
  1908.                     //: Textto(Tracked(1)); // Recall position
  1909.                     //: Track2(Tracked(0)); // Save old mark
  1910.                     //: Advance(1);
  1911.                     PopTrack();
  1912.                     Stloc(_textposV);
  1913.                     PopStack();
  1914.                     Pop();
  1915.                     // track spot 0 is already in place
  1916.                     TrackUnique2(branchmarkback2);
  1917.                     Advance();
  1918.                     break;
  1919.                 case RegexCode.Branchmark | RegexCode.Back2:
  1920.                    
  1921.                     //: Trackframe(1);
  1922.                     //: Stack(Tracked(0)); // Recall old mark
  1923.                     //: break Backward; // Backtrack
  1924.                     ReadyPushStack();
  1925.                     PopTrack();
  1926.                     DoPush();
  1927.                     Back();
  1928.                     break;
  1929.                 case RegexCode.Lazybranchmark:
  1930.                    
  1931.                    
  1932.                     //: StackPop();
  1933.                     //: int oldMarkPos = StackPeek();
  1934.                     //:
  1935.                     //: if (Textpos() != oldMarkPos) { // Nonempty match -> next loop
  1936.                     //: { // Nonempty match -> next loop
  1937.                     //: if (oldMarkPos != -1)
  1938.                     //: Track(Stacked(0), Textpos()); // Save old mark, textpos
  1939.                     //: else
  1940.                     //: TrackPush(Textpos(), Textpos());
  1941.                     //: }
  1942.                     //: else
  1943.                     //: { // Empty match -> no loop
  1944.                     //: Track2(Stacked(0)); // Save old mark
  1945.                     //: }
  1946.                     //: Advance(1);
  1947.                     //: continue Forward;
  1948.                    
  1949.                     {
  1950.                         LocalBuilder mark = _tempV;
  1951.                         Label l1 = DefineLabel();
  1952.                         Label l2 = DefineLabel();
  1953.                         Label l3 = DefineLabel();
  1954.                        
  1955.                         PopStack();
  1956.                         Dup();
  1957.                         Stloc(mark);
  1958.                         // Stacked(0) -> temp
  1959.                         // if (oldMarkPos != -1)
  1960.                         Ldloc(mark);
  1961.                         Ldc(-1);
  1962.                         Beq(l2);
  1963.                         // mark == -1 -> branch
  1964.                         PushTrack(mark);
  1965.                         Br(l3);
  1966.                         // else
  1967.                         MarkLabel(l2);
  1968.                         PushTrack(_textposV);
  1969.                         MarkLabel(l3);
  1970.                        
  1971.                         // if (Textpos() != mark)
  1972.                         Ldloc(_textposV);
  1973.                         Beq(l1);
  1974.                         // mark == textpos -> branch
  1975.                         PushTrack(_textposV);
  1976.                         Track();
  1977.                         Br(AdvanceLabel());
  1978.                         // Advance (near)
  1979.                         // else
  1980.                         MarkLabel(l1);
  1981.                         ReadyPushStack();
  1982.                         // push the current textPos on the stack.
  1983.                         // May be ignored by 'back2' or used by a true empty match.
  1984.                         Ldloc(mark);
  1985.                        
  1986.                         DoPush();
  1987.                         TrackUnique2(lazybranchmarkback2);
  1988.                        
  1989.                         break;
  1990.                     }
  1991.                     break;
  1992.                 case RegexCode.Lazybranchmark | RegexCode.Back:
  1993.                    
  1994.                     //: Trackframe(2);
  1995.                     //: Track2(Tracked(0)); // Save old mark
  1996.                     //: Stack(Textpos()); // Make new mark
  1997.                     //: Textto(Tracked(1)); // Recall position
  1998.                     //: Goto(Operand(0)); // Loop
  1999.                    
  2000.                     PopTrack();
  2001.                     Stloc(_textposV);
  2002.                     PushStack(_textposV);
  2003.                     TrackUnique2(lazybranchmarkback2);
  2004.                     Goto(Operand(0));
  2005.                     break;
  2006.                 case RegexCode.Lazybranchmark | RegexCode.Back2:
  2007.                    
  2008.                     //: Stackframe(1);
  2009.                     //: Trackframe(1);
  2010.                     //: Stack(Tracked(0)); // Recall old mark
  2011.                     //: break Backward;
  2012.                     ReadyReplaceStack(0);
  2013.                     PopTrack();
  2014.                     DoReplace();
  2015.                     Back();
  2016.                     break;
  2017.                 case RegexCode.Nullcount:
  2018.                    
  2019.                     //: Stack(-1, Operand(0));
  2020.                     //: Track();
  2021.                     ReadyPushStack();
  2022.                     Ldc(-1);
  2023.                     DoPush();
  2024.                     ReadyPushStack();
  2025.                     Ldc(Operand(0));
  2026.                     DoPush();
  2027.                     TrackUnique(stackpop2);
  2028.                     break;
  2029.                 case RegexCode.Setcount:
  2030.                    
  2031.                     //: Stack(Textpos(), Operand(0));
  2032.                     //: Track();
  2033.                     PushStack(_textposV);
  2034.                     ReadyPushStack();
  2035.                     Ldc(Operand(0));
  2036.                     DoPush();
  2037.                     TrackUnique(stackpop2);
  2038.                     break;
  2039.                 case RegexCode.Nullcount | RegexCode.Back:
  2040.                 case RegexCode.Setcount | RegexCode.Back:
  2041.                    
  2042.                    
  2043.                     //: Stackframe(2);
  2044.                     //: break Backward;
  2045.                     PopDiscardStack(2);
  2046.                     Back();
  2047.                     break;
  2048.                 case RegexCode.Branchcount:
  2049.                    
  2050.                    
  2051.                     //: Stackframe(2);
  2052.                     //: int mark = Stacked(0);
  2053.                     //: int count = Stacked(1);
  2054.                     //:
  2055.                     //: if (count >= Operand(1) || Textpos() == mark && count >= 0)
  2056.                     //: { // Max loops or empty match -> straight now
  2057.                     //: Track2(mark, count); // Save old mark, count
  2058.                     //: Advance(2); // Straight
  2059.                     //: }
  2060.                     //: else
  2061.                     //: { // Nonempty match -> count+loop now
  2062.                     //: Track(mark); // remember mark
  2063.                     //: Stack(Textpos(), count + 1); // Make new mark, incr count
  2064.                     //: Goto(Operand(0)); // Loop
  2065.                     //: }
  2066.                     //: continue Forward;
  2067.                    
  2068.                     {
  2069.                         LocalBuilder count = _tempV;
  2070.                         LocalBuilder mark = _temp2V;
  2071.                         Label l1 = DefineLabel();
  2072.                         Label l2 = DefineLabel();
  2073.                        
  2074.                         PopStack();
  2075.                         Stloc(count);
  2076.                         // count -> temp
  2077.                         PopStack();
  2078.                         Dup();
  2079.                         Stloc(mark);
  2080.                         // mark -> temp2
  2081.                         PushTrack(mark);
  2082.                        
  2083.                         Ldloc(_textposV);
  2084.                         Bne(l1);
  2085.                         // mark != textpos -> l1
  2086.                         Ldloc(count);
  2087.                         Ldc(0);
  2088.                         Bge(l2);
  2089.                         // count >= 0 && mark == textpos -> l2
  2090.                         MarkLabel(l1);
  2091.                         Ldloc(count);
  2092.                         Ldc(Operand(1));
  2093.                         Bge(l2);
  2094.                         // count >= Operand(1) -> l2
  2095.                         // else
  2096.                         PushStack(_textposV);
  2097.                         ReadyPushStack();
  2098.                         Ldloc(count);
  2099.                         // mark already on track
  2100.                         Ldc(1);
  2101.                         Add();
  2102.                         DoPush();
  2103.                         Track();
  2104.                         Goto(Operand(0));
  2105.                        
  2106.                         // if (count >= Operand(1) || Textpos() == mark)
  2107.                         MarkLabel(l2);
  2108.                         PushTrack(count);
  2109.                         // mark already on track
  2110.                         TrackUnique2(branchcountback2);
  2111.                         break;
  2112.                     }
  2113.                     break;
  2114.                 case RegexCode.Branchcount | RegexCode.Back:
  2115.                    
  2116.                     //: Trackframe(1);
  2117.                     //: Stackframe(2);
  2118.                     //: if (Stacked(1) > 0) // Positive -> can go straight
  2119.                     //: {
  2120.                     //: Textto(Stacked(0)); // Zap to mark
  2121.                     //: Track2(Tracked(0), Stacked(1) - 1); // Save old mark, old count
  2122.                     //: Advance(2); // Straight
  2123.                     //: continue Forward;
  2124.                     //: }
  2125.                     //: Stack(Tracked(0), Stacked(1) - 1); // recall old mark, old count
  2126.                     //: break Backward;
  2127.                    
  2128.                     {
  2129.                        
  2130.                         LocalBuilder count = _tempV;
  2131.                         Label l1 = DefineLabel();
  2132.                         PopStack();
  2133.                         Ldc(1);
  2134.                         Sub();
  2135.                         Dup();
  2136.                         Stloc(count);
  2137.                         Ldc(0);
  2138.                         Blt(l1);
  2139.                        
  2140.                         // if (count >= 0)
  2141.                         PopStack();
  2142.                         Stloc(_textposV);
  2143.                         PushTrack(count);
  2144.                         // Tracked(0) is alredy on the track
  2145.                         TrackUnique2(branchcountback2);
  2146.                         Advance();
  2147.                        
  2148.                         // else
  2149.                         MarkLabel(l1);
  2150.                         ReadyReplaceStack(0);
  2151.                         PopTrack();
  2152.                         DoReplace();
  2153.                         PushStack(count);
  2154.                         Back();
  2155.                         break;
  2156.                     }
  2157.                     break;
  2158.                 case RegexCode.Branchcount | RegexCode.Back2:
  2159.                    
  2160.                     //: Trackframe(2);
  2161.                     //: Stack(Tracked(0), Tracked(1)); // Recall old mark, old count
  2162.                     //: break Backward; // Backtrack
  2163.                    
  2164.                     PopTrack();
  2165.                     Stloc(_tempV);
  2166.                     ReadyPushStack();
  2167.                     PopTrack();
  2168.                     DoPush();
  2169.                     PushStack(_tempV);
  2170.                     Back();
  2171.                     break;
  2172.                 case RegexCode.Lazybranchcount:
  2173.                    
  2174.                     //: Stackframe(2);
  2175.                     //: int mark = Stacked(0);
  2176.                     //: int count = Stacked(1);
  2177.                     //:
  2178.                     //: if (count < 0)
  2179.                     //: { // Negative count -> loop now
  2180.                     //: Track2(mark); // Save old mark
  2181.                     //: Stack(Textpos(), count + 1); // Make new mark, incr count
  2182.                     //: Goto(Operand(0)); // Loop
  2183.                     //: }
  2184.                     //: else
  2185.                     //: { // Nonneg count or empty match -> straight now
  2186.                     //: Track(mark, count, Textpos()); // Save mark, count, position
  2187.                     //: }
  2188.                    
  2189.                     {
  2190.                         LocalBuilder count = _tempV;
  2191.                         LocalBuilder mark = _temp2V;
  2192.                         Label l1 = DefineLabel();
  2193.                         Label l2 = DefineLabel();
  2194.                         Label l3 = _labels[NextCodepos()];
  2195.                        
  2196.                         PopStack();
  2197.                         Stloc(count);
  2198.                         // count -> temp
  2199.                         PopStack();
  2200.                         Stloc(mark);
  2201.                         // mark -> temp2
  2202.                         Ldloc(count);
  2203.                         Ldc(0);
  2204.                         Bge(l1);
  2205.                         // count >= 0 -> l1
  2206.                         // if (count < 0)
  2207.                         PushTrack(mark);
  2208.                         PushStack(_textposV);
  2209.                         ReadyPushStack();
  2210.                         Ldloc(count);
  2211.                         Ldc(1);
  2212.                         Add();
  2213.                         DoPush();
  2214.                         TrackUnique2(lazybranchcountback2);
  2215.                         Goto(Operand(0));
  2216.                        
  2217.                         // else
  2218.                         MarkLabel(l1);
  2219.                         PushTrack(mark);
  2220.                         PushTrack(count);
  2221.                         PushTrack(_textposV);
  2222.                         Track();
  2223.                         break;
  2224.                     }
  2225.                     break;
  2226.                 case RegexCode.Lazybranchcount | RegexCode.Back:
  2227.                    
  2228.                     //: Trackframe(3);
  2229.                     //: int mark = Tracked(0);
  2230.                     //: int textpos = Tracked(2);
  2231.                     //: if (Tracked(1) <= Operand(1) && textpos != mark)
  2232.                     //: {
  2233.                     //: Textto(Tracked(2)); // Recall position
  2234.                     //: Stack(Textpos(), Tracked(1) + 1); // Make new mark, incr count
  2235.                     //: Track2(Tracked(0)); // Save old mark
  2236.                     //: Goto(Operand(0)); // Loop
  2237.                     //: continue Forward;
  2238.                     //: }
  2239.                     //: else
  2240.                     //: {
  2241.                     //: Stack(Tracked(0), Tracked(1)); // Recall old mark, count
  2242.                     //: break Backward; // backtrack
  2243.                     //: }
  2244.                    
  2245.                     {
  2246.                         Label l1 = DefineLabel();
  2247.                         LocalBuilder cV = _tempV;
  2248.                         PopTrack();
  2249.                         Stloc(_textposV);
  2250.                         PopTrack();
  2251.                         Dup();
  2252.                         Stloc(cV);
  2253.                         Ldc(Operand(1));
  2254.                         Bgt(l1);
  2255.                         // Tracked(1) > Operand(1) -> l1
  2256.                         Ldloc(_textposV);
  2257.                         TopTrack();
  2258.                         Beq(l1);
  2259.                         // textpos == mark -> l1
  2260.                         PushStack(_textposV);
  2261.                         ReadyPushStack();
  2262.                         Ldloc(cV);
  2263.                         Ldc(1);
  2264.                         Add();
  2265.                         DoPush();
  2266.                         TrackUnique2(lazybranchcountback2);
  2267.                         Goto(Operand(0));
  2268.                        
  2269.                         MarkLabel(l1);
  2270.                         ReadyPushStack();
  2271.                         PopTrack();
  2272.                         DoPush();
  2273.                         PushStack(cV);
  2274.                         Back();
  2275.                         break;
  2276.                     }
  2277.                     break;
  2278.                 case RegexCode.Lazybranchcount | RegexCode.Back2:
  2279.                    
  2280.                    
  2281.                     ReadyReplaceStack(1);
  2282.                     PopTrack();
  2283.                     DoReplace();
  2284.                     ReadyReplaceStack(0);
  2285.                     TopStack();
  2286.                     Ldc(1);
  2287.                     Sub();
  2288.                     DoReplace();
  2289.                     Back();
  2290.                     break;
  2291.                 case RegexCode.Setjump:
  2292.                    
  2293.                    
  2294.                     //: Stack(Trackpos(), Crawlpos());
  2295.                     //: Track();
  2296.                     ReadyPushStack();
  2297.                     Ldthisfld(_trackF);
  2298.                     Ldlen();
  2299.                     Ldloc(_trackposV);
  2300.                     Sub();
  2301.                     DoPush();
  2302.                     ReadyPushStack();
  2303.                     Ldthis();
  2304.                     Callvirt(_crawlposM);
  2305.                     DoPush();
  2306.                     TrackUnique(stackpop2);
  2307.                     break;
  2308.                 case RegexCode.Setjump | RegexCode.Back:
  2309.                    
  2310.                     //: Stackframe(2);
  2311.                     PopDiscardStack(2);
  2312.                     Back();
  2313.                     break;
  2314.                 case RegexCode.Backjump:
  2315.                    
  2316.                    
  2317.                     //: Stackframe(2);
  2318.                     //: Trackto(Stacked(0));
  2319.                     //: while (Crawlpos() != Stacked(1))
  2320.                     //: Uncapture();
  2321.                     //: break Backward;
  2322.                    
  2323.                     {
  2324.                         Label l1 = DefineLabel();
  2325.                         Label l2 = DefineLabel();
  2326.                        
  2327.                         PopStack();
  2328.                         Ldthisfld(_trackF);
  2329.                         Ldlen();
  2330.                         PopStack();
  2331.                         Sub();
  2332.                         Stloc(_trackposV);
  2333.                         Dup();
  2334.                         Ldthis();
  2335.                         Callvirt(_crawlposM);
  2336.                         Beq(l2);
  2337.                        
  2338.                         MarkLabel(l1);
  2339.                         Ldthis();
  2340.                         Callvirt(_uncaptureM);
  2341.                         Dup();
  2342.                         Ldthis();
  2343.                         Callvirt(_crawlposM);
  2344.                         Bne(l1);
  2345.                        
  2346.                         MarkLabel(l2);
  2347.                         Pop();
  2348.                         Back();
  2349.                         break;
  2350.                     }
  2351.                     break;
  2352.                 case RegexCode.Forejump:
  2353.                    
  2354.                     //: Stackframe(2);
  2355.                     //: Trackto(Stacked(0));
  2356.                     //: Track(Stacked(1));
  2357.                     PopStack();
  2358.                     Stloc(_tempV);
  2359.                     Ldthisfld(_trackF);
  2360.                     Ldlen();
  2361.                     PopStack();
  2362.                     Sub();
  2363.                     Stloc(_trackposV);
  2364.                     PushTrack(_tempV);
  2365.                     TrackUnique(forejumpback);
  2366.                     break;
  2367.                 case RegexCode.Forejump | RegexCode.Back:
  2368.                    
  2369.                     //: Trackframe(1);
  2370.                     //: while (Crawlpos() != Tracked(0))
  2371.                     //: Uncapture();
  2372.                     //: break Backward;
  2373.                    
  2374.                     {
  2375.                         Label l1 = DefineLabel();
  2376.                         Label l2 = DefineLabel();
  2377.                        
  2378.                         PopTrack();
  2379.                        
  2380.                         Dup();
  2381.                         Ldthis();
  2382.                         Callvirt(_crawlposM);
  2383.                         Beq(l2);
  2384.                        
  2385.                         MarkLabel(l1);
  2386.                         Ldthis();
  2387.                         Callvirt(_uncaptureM);
  2388.                         Dup();
  2389.                         Ldthis();
  2390.                         Callvirt(_crawlposM);
  2391.                         Bne(l1);
  2392.                        
  2393.                         MarkLabel(l2);
  2394.                         Pop();
  2395.                         Back();
  2396.                         break;
  2397.                     }
  2398.                     break;
  2399.                 case RegexCode.Bol:
  2400.                    
  2401.                     //: if (Leftchars() > 0 && CharAt(Textpos() - 1) != '\n')
  2402.                     //: break Backward;
  2403.                    
  2404.                     {
  2405.                         Label l1 = _labels[NextCodepos()];
  2406.                         Ldloc(_textposV);
  2407.                         Ldloc(_textbegV);
  2408.                         Ble(l1);
  2409.                         Leftchar();
  2410.                         Ldc((int)'\n');
  2411.                         BneFar(_backtrack);
  2412.                         break;
  2413.                     }
  2414.                     break;
  2415.                 case RegexCode.Eol:
  2416.                    
  2417.                     //: if (Rightchars() > 0 && CharAt(Textpos()) != '\n')
  2418.                     //: break Backward;
  2419.                    
  2420.                     {
  2421.                         Label l1 = _labels[NextCodepos()];
  2422.                         Ldloc(_textposV);
  2423.                         Ldloc(_textendV);
  2424.                         Bge(l1);
  2425.                         Rightchar();
  2426.                         Ldc((int)'\n');
  2427.                         BneFar(_backtrack);
  2428.                         break;
  2429.                     }
  2430.                     break;
  2431.                 case RegexCode.Boundary:
  2432.                 case RegexCode.Nonboundary:
  2433.                    
  2434.                     //: if (!IsBoundary(Textpos(), _textbeg, _textend))
  2435.                     //: break Backward;
  2436.                     Ldthis();
  2437.                     Ldloc(_textposV);
  2438.                     Ldloc(_textbegV);
  2439.                     Ldloc(_textendV);
  2440.                     Callvirt(_isboundaryM);
  2441.                     if (Code() == RegexCode.Boundary)
  2442.                         BrfalseFar(_backtrack);
  2443.                     else
  2444.                         BrtrueFar(_backtrack);
  2445.                     break;
  2446.                 case RegexCode.ECMABoundary:
  2447.                 case RegexCode.NonECMABoundary:
  2448.                    
  2449.                     //: if (!IsECMABoundary(Textpos(), _textbeg, _textend))
  2450.                     //: break Backward;
  2451.                     Ldthis();
  2452.                     Ldloc(_textposV);
  2453.                     Ldloc(_textbegV);
  2454.                     Ldloc(_textendV);
  2455.                     Callvirt(_isECMABoundaryM);
  2456.                     if (Code() == RegexCode.ECMABoundary)
  2457.                         BrfalseFar(_backtrack);
  2458.                     else
  2459.                         BrtrueFar(_backtrack);
  2460.                     break;
  2461.                 case RegexCode.Beginning:
  2462.                    
  2463.                     //: if (Leftchars() > 0)
  2464.                     //: break Backward;
  2465.                     Ldloc(_textposV);
  2466.                     Ldloc(_textbegV);
  2467.                     BgtFar(_backtrack);
  2468.                     break;
  2469.                 case RegexCode.Start:
  2470.                    
  2471.                     //: if (Textpos() != Textstart())
  2472.                     //: break Backward;
  2473.                     Ldloc(_textposV);
  2474.                     Ldthisfld(_textstartF);
  2475.                     BneFar(_backtrack);
  2476.                     break;
  2477.                 case RegexCode.EndZ:
  2478.                    
  2479.                     //: if (Rightchars() > 1 || Rightchars() == 1 && CharAt(Textpos()) != '\n')
  2480.                     //: break Backward;
  2481.                     Ldloc(_textposV);
  2482.                     Ldloc(_textendV);
  2483.                     Ldc(1);
  2484.                     Sub();
  2485.                     BltFar(_backtrack);
  2486.                     Ldloc(_textposV);
  2487.                     Ldloc(_textendV);
  2488.                     Bge(_labels[NextCodepos()]);
  2489.                     Rightchar();
  2490.                     Ldc((int)'\n');
  2491.                     BneFar(_backtrack);
  2492.                     break;
  2493.                 case RegexCode.End:
  2494.                    
  2495.                     //: if (Rightchars() > 0)
  2496.                     //: break Backward;
  2497.                     Ldloc(_textposV);
  2498.                     Ldloc(_textendV);
  2499.                     BltFar(_backtrack);
  2500.                     break;
  2501.                 case RegexCode.One:
  2502.                 case RegexCode.Notone:
  2503.                 case RegexCode.Set:
  2504.                 case RegexCode.One | RegexCode.Rtl:
  2505.                 case RegexCode.Notone | RegexCode.Rtl:
  2506.                 case RegexCode.Set | RegexCode.Rtl:
  2507.                 case RegexCode.One | RegexCode.Ci:
  2508.                 case RegexCode.Notone | RegexCode.Ci:
  2509.                 case RegexCode.Set | RegexCode.Ci:
  2510.                 case RegexCode.One | RegexCode.Ci | RegexCode.Rtl:
  2511.                 case RegexCode.Notone | RegexCode.Ci | RegexCode.Rtl:
  2512.                 case RegexCode.Set | RegexCode.Ci | RegexCode.Rtl:
  2513.                    
  2514.                    
  2515.                     //: if (Rightchars() < 1 || Rightcharnext() != (char)Operand(0))
  2516.                     //: break Backward;
  2517.                     Ldloc(_textposV);
  2518.                    
  2519.                     if (!IsRtl()) {
  2520.                         Ldloc(_textendV);
  2521.                         BgeFar(_backtrack);
  2522.                         Rightcharnext();
  2523.                     }
  2524.                     else {
  2525.                         Ldloc(_textbegV);
  2526.                         BleFar(_backtrack);
  2527.                         Leftcharnext();
  2528.                     }
  2529.                    
  2530.                     if (IsCi())
  2531.                         CallToLower();
  2532.                    
  2533.                     if (Code() == RegexCode.Set) {
  2534.                        
  2535.                         Ldstr(_strings[Operand(0)]);
  2536.                         Call(_charInSetM);
  2537.                        
  2538.                         BrfalseFar(_backtrack);
  2539.                     }
  2540.                     else {
  2541.                         Ldc(Operand(0));
  2542.                         if (Code() == RegexCode.One)
  2543.                             BneFar(_backtrack);
  2544.                         else
  2545.                             BeqFar(_backtrack);
  2546.                     }
  2547.                     break;
  2548.                 case RegexCode.Multi:
  2549.                 case RegexCode.Multi | RegexCode.Ci:
  2550.                    
  2551.                     //
  2552.                    
  2553.                    
  2554.                     {
  2555.                         int i;
  2556.                         string str;
  2557.                        
  2558.                         str = _strings[Operand(0)];
  2559.                        
  2560.                         Ldc(str.Length);
  2561.                         Ldloc(_textendV);
  2562.                         Ldloc(_textposV);
  2563.                         Sub();
  2564.                         BgtFar(_backtrack);
  2565.                        
  2566.                         // unroll the string
  2567.                         for (i = 0; i < str.Length; i++) {
  2568.                             Ldloc(_textV);
  2569.                             Ldloc(_textposV);
  2570.                             if (i != 0) {
  2571.                                 Ldc(i);
  2572.                                 Add();
  2573.                             }
  2574.                             Callvirt(_getcharM);
  2575.                             if (IsCi())
  2576.                                 CallToLower();
  2577.                            
  2578.                             Ldc((int)str[i]);
  2579.                             BneFar(_backtrack);
  2580.                         }
  2581.                        
  2582.                         Ldloc(_textposV);
  2583.                         Ldc(str.Length);
  2584.                         Add();
  2585.                         Stloc(_textposV);
  2586.                         break;
  2587.                     }
  2588.                     break;
  2589.                 case RegexCode.Multi | RegexCode.Rtl:
  2590.                 case RegexCode.Multi | RegexCode.Ci | RegexCode.Rtl:
  2591.                    
  2592.                    
  2593.                     //: String Str = _strings[Operand(0)];
  2594.                     //: int c;
  2595.                     //: if (Leftchars() < (c = Str.Length))
  2596.                     //: break Backward;
  2597.                     //: while (c > 0)
  2598.                     //: if (Str[--c] != Leftcharnext())
  2599.                     //: break Backward;
  2600.                    
  2601.                     {
  2602.                         int i;
  2603.                         string str;
  2604.                        
  2605.                         str = _strings[Operand(0)];
  2606.                        
  2607.                         Ldc(str.Length);
  2608.                         Ldloc(_textposV);
  2609.                         Ldloc(_textbegV);
  2610.                         Sub();
  2611.                         BgtFar(_backtrack);
  2612.                        
  2613.                         // unroll the string
  2614.                         for (i = str.Length; i > 0;) {
  2615.                             i--;
  2616.                             Ldloc(_textV);
  2617.                             Ldloc(_textposV);
  2618.                             Ldc(str.Length - i);
  2619.                             Sub();
  2620.                             Callvirt(_getcharM);
  2621.                             if (IsCi()) {
  2622.                                 CallToLower();
  2623.                             }
  2624.                             Ldc((int)str[i]);
  2625.                             BneFar(_backtrack);
  2626.                         }
  2627.                        
  2628.                         Ldloc(_textposV);
  2629.                         Ldc(str.Length);
  2630.                         Sub();
  2631.                         Stloc(_textposV);
  2632.                        
  2633.                         break;
  2634.                     }
  2635.                     break;
  2636.                 case RegexCode.Ref:
  2637.                 case RegexCode.Ref | RegexCode.Rtl:
  2638.                 case RegexCode.Ref | RegexCode.Ci:
  2639.                 case RegexCode.Ref | RegexCode.Ci | RegexCode.Rtl:
  2640.                    
  2641.                     //: int capnum = Operand(0);
  2642.                     //: int j, c;
  2643.                     //: if (!_match.IsMatched(capnum)) {
  2644.                     //: if (!RegexOptions.ECMAScript)
  2645.                     //: break Backward;
  2646.                     //: } else {
  2647.                     //: if (Rightchars() < (c = _match.MatchLength(capnum)))
  2648.                     //: break Backward;
  2649.                     //: for (j = _match.MatchIndex(capnum); c > 0; j++, c--)
  2650.                     //: if (CharAt(j) != Rightcharnext())
  2651.                     //: break Backward;
  2652.                     //: }
  2653.                    
  2654.                     {
  2655.                         LocalBuilder lenV = _tempV;
  2656.                         LocalBuilder indexV = _temp2V;
  2657.                         Label l1 = DefineLabel();
  2658.                        
  2659.                         Ldthis();
  2660.                         Ldc(Operand(0));
  2661.                         Callvirt(_ismatchedM);
  2662.                         if ((_options & RegexOptions.ECMAScript) != 0)
  2663.                             Brfalse(AdvanceLabel());
  2664.                         else
  2665.                             BrfalseFar(_backtrack);
  2666.                         // !IsMatched() -> back
  2667.                         Ldthis();
  2668.                         Ldc(Operand(0));
  2669.                         Callvirt(_matchlengthM);
  2670.                         Dup();
  2671.                         Stloc(lenV);
  2672.                         if (!IsRtl()) {
  2673.                             Ldloc(_textendV);
  2674.                             Ldloc(_textposV);
  2675.                         }
  2676.                         else {
  2677.                             Ldloc(_textposV);
  2678.                             Ldloc(_textbegV);
  2679.                         }
  2680.                         Sub();
  2681.                         BgtFar(_backtrack);
  2682.                         // Matchlength() > Rightchars() -> back
  2683.                         Ldthis();
  2684.                         Ldc(Operand(0));
  2685.                         Callvirt(_matchindexM);
  2686.                         if (!IsRtl()) {
  2687.                             Ldloc(lenV);
  2688.                             Add(IsRtl());
  2689.                         }
  2690.                         Stloc(indexV);
  2691.                         // index += len
  2692.                         Ldloc(_textposV);
  2693.                         Ldloc(lenV);
  2694.                         Add(IsRtl());
  2695.                         Stloc(_textposV);
  2696.                         // texpos += len
  2697.                         MarkLabel(l1);
  2698.                         Ldloc(lenV);
  2699.                         Ldc(0);
  2700.                         Ble(AdvanceLabel());
  2701.                         Ldloc(_textV);
  2702.                         Ldloc(indexV);
  2703.                         Ldloc(lenV);
  2704.                         if (IsRtl()) {
  2705.                             Ldc(1);
  2706.                             Sub();
  2707.                             Dup();
  2708.                             Stloc(lenV);
  2709.                         }
  2710.                         Sub(IsRtl());
  2711.                         Callvirt(_getcharM);
  2712.                         if (IsCi())
  2713.                             CallToLower();
  2714.                        
  2715.                         Ldloc(_textV);
  2716.                         Ldloc(_textposV);
  2717.                         Ldloc(lenV);
  2718.                         if (!IsRtl()) {
  2719.                             Dup();
  2720.                             Ldc(1);
  2721.                             Sub();
  2722.                             Stloc(lenV);
  2723.                         }
  2724.                         Sub(IsRtl());
  2725.                         Callvirt(_getcharM);
  2726.                         if (IsCi())
  2727.                             CallToLower();
  2728.                        
  2729.                         Beq(l1);
  2730.                         Back();
  2731.                         break;
  2732.                     }
  2733.                     break;
  2734.                 case RegexCode.Onerep:
  2735.                 case RegexCode.Notonerep:
  2736.                 case RegexCode.Setrep:
  2737.                 case RegexCode.Onerep | RegexCode.Rtl:
  2738.                 case RegexCode.Notonerep | RegexCode.Rtl:
  2739.                 case RegexCode.Setrep | RegexCode.Rtl:
  2740.                 case RegexCode.Onerep | RegexCode.Ci:
  2741.                 case RegexCode.Notonerep | RegexCode.Ci:
  2742.                 case RegexCode.Setrep | RegexCode.Ci:
  2743.                 case RegexCode.Onerep | RegexCode.Ci | RegexCode.Rtl:
  2744.                 case RegexCode.Notonerep | RegexCode.Ci | RegexCode.Rtl:
  2745.                 case RegexCode.Setrep | RegexCode.Ci | RegexCode.Rtl:
  2746.                    
  2747.                    
  2748.                     //: int c = Operand(1);
  2749.                     //: if (Rightchars() < c)
  2750.                     //: break Backward;
  2751.                     //: char ch = (char)Operand(0);
  2752.                     //: while (c-- > 0)
  2753.                     //: if (Rightcharnext() != ch)
  2754.                     //: break Backward;
  2755.                    
  2756.                     {
  2757.                         LocalBuilder lenV = _tempV;
  2758.                         Label l1 = DefineLabel();
  2759.                        
  2760.                         int c = Operand(1);
  2761.                        
  2762.                         if (c == 0)
  2763.                             break;
  2764.                        
  2765.                         Ldc(c);
  2766.                         if (!IsRtl()) {
  2767.                             Ldloc(_textendV);
  2768.                             Ldloc(_textposV);
  2769.                         }
  2770.                         else {
  2771.                             Ldloc(_textposV);
  2772.                             Ldloc(_textbegV);
  2773.                         }
  2774.                         Sub();
  2775.                         BgtFar(_backtrack);
  2776.                         // Matchlength() > Rightchars() -> back
  2777.                         Ldloc(_textposV);
  2778.                         Ldc(c);
  2779.                         Add(IsRtl());
  2780.                         Stloc(_textposV);
  2781.                         // texpos += len
  2782.                         Ldc(c);
  2783.                         Stloc(lenV);
  2784.                        
  2785.                         MarkLabel(l1);
  2786.                         Ldloc(_textV);
  2787.                         Ldloc(_textposV);
  2788.                         Ldloc(lenV);
  2789.                         if (IsRtl()) {
  2790.                             Ldc(1);
  2791.                             Sub();
  2792.                             Dup();
  2793.                             Stloc(lenV);
  2794.                             Add();
  2795.                         }
  2796.                         else {
  2797.                             Dup();
  2798.                             Ldc(1);
  2799.                             Sub();
  2800.                             Stloc(lenV);
  2801.                             Sub();
  2802.                         }
  2803.                         Callvirt(_getcharM);
  2804.                         if (IsCi())
  2805.                             CallToLower();
  2806.                        
  2807.                         if (Code() == RegexCode.Setrep) {
  2808.                             Ldstr(_strings[Operand(0)]);
  2809.                             Call(_charInSetM);
  2810.                            
  2811.                             BrfalseFar(_backtrack);
  2812.                         }
  2813.                         else {
  2814.                             Ldc(Operand(0));
  2815.                             if (Code() == RegexCode.Onerep)
  2816.                                 BneFar(_backtrack);
  2817.                             else
  2818.                                 BeqFar(_backtrack);
  2819.                         }
  2820.                         Ldloc(lenV);
  2821.                         Ldc(0);
  2822.                         if (Code() == RegexCode.Setrep)
  2823.                             BgtFar(l1);
  2824.                         else
  2825.                             Bgt(l1);
  2826.                         break;
  2827.                     }
  2828.                     break;
  2829.                 case RegexCode.Oneloop:
  2830.                 case RegexCode.Notoneloop:
  2831.                 case RegexCode.Setloop:
  2832.                 case RegexCode.Oneloop | RegexCode.Rtl:
  2833.                 case RegexCode.Notoneloop | RegexCode.Rtl:
  2834.                 case RegexCode.Setloop | RegexCode.Rtl:
  2835.                 case RegexCode.Oneloop | RegexCode.Ci:
  2836.                 case RegexCode.Notoneloop | RegexCode.Ci:
  2837.                 case RegexCode.Setloop | RegexCode.Ci:
  2838.                 case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl:
  2839.                 case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl:
  2840.                 case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl:
  2841.                    
  2842.                    
  2843.                     //: int c = Operand(1);
  2844.                     //: if (c > Rightchars())
  2845.                     //: c = Rightchars();
  2846.                     //: char ch = (char)Operand(0);
  2847.                     //: int i;
  2848.                     //: for (i = c; i > 0; i--)
  2849.                     //: {
  2850.                     //: if (Rightcharnext() != ch)
  2851.                     //: {
  2852.                     //: Leftnext();
  2853.                     //: break;
  2854.                     //: }
  2855.                     //: }
  2856.                     //: if (c > i)
  2857.                     //: Track(c - i - 1, Textpos() - 1);
  2858.                    
  2859.                    
  2860.                     {
  2861.                         LocalBuilder cV = _tempV;
  2862.                         LocalBuilder lenV = _temp2V;
  2863.                         Label l1 = DefineLabel();
  2864.                         Label l2 = DefineLabel();
  2865.                        
  2866.                         int c = Operand(1);
  2867.                        
  2868.                         if (c == 0)
  2869.                             break;
  2870.                         if (!IsRtl()) {
  2871.                             Ldloc(_textendV);
  2872.                             Ldloc(_textposV);
  2873.                         }
  2874.                         else {
  2875.                             Ldloc(_textposV);
  2876.                             Ldloc(_textbegV);
  2877.                         }
  2878.                         Sub();
  2879.                         if (c != Int32.MaxValue) {
  2880.                             Label l4 = DefineLabel();
  2881.                             Dup();
  2882.                             Ldc(c);
  2883.                             Blt(l4);
  2884.                             Pop();
  2885.                             Ldc(c);
  2886.                             MarkLabel(l4);
  2887.                         }
  2888.                         Dup();
  2889.                         Stloc(lenV);
  2890.                         Ldc(1);
  2891.                         Add();
  2892.                         Stloc(cV);
  2893.                        
  2894.                         MarkLabel(l1);
  2895.                         Ldloc(cV);
  2896.                         Ldc(1);
  2897.                         Sub();
  2898.                         Dup();
  2899.                         Stloc(cV);
  2900.                         Ldc(0);
  2901.                         if (Code() == RegexCode.Setloop)
  2902.                             BleFar(l2);
  2903.                         else
  2904.                             Ble(l2);
  2905.                        
  2906.                         if (IsRtl())
  2907.                             Leftcharnext();
  2908.                         else
  2909.                             Rightcharnext();
  2910.                         if (IsCi())
  2911.                             CallToLower();
  2912.                        
  2913.                         if (Code() == RegexCode.Setloop) {
  2914.                             Ldstr(_strings[Operand(0)]);
  2915.                             Call(_charInSetM);
  2916.                            
  2917.                             BrtrueFar(l1);
  2918.                         }
  2919.                         else {
  2920.                             Ldc(Operand(0));
  2921.                             if (Code() == RegexCode.Oneloop)
  2922.                                 Beq(l1);
  2923.                             else
  2924.                                 Bne(l1);
  2925.                         }
  2926.                        
  2927.                         Ldloc(_textposV);
  2928.                         Ldc(1);
  2929.                         Sub(IsRtl());
  2930.                         Stloc(_textposV);
  2931.                        
  2932.                         MarkLabel(l2);
  2933.                         Ldloc(lenV);
  2934.                         Ldloc(cV);
  2935.                         Ble(AdvanceLabel());
  2936.                        
  2937.                         ReadyPushTrack();
  2938.                         Ldloc(lenV);
  2939.                         Ldloc(cV);
  2940.                         Sub();
  2941.                         Ldc(1);
  2942.                         Sub();
  2943.                         DoPush();
  2944.                        
  2945.                         ReadyPushTrack();
  2946.                         Ldloc(_textposV);
  2947.                         Ldc(1);
  2948.                         Sub(IsRtl());
  2949.                         DoPush();
  2950.                        
  2951.                         Track();
  2952.                         break;
  2953.                     }
  2954.                     break;
  2955.                 case RegexCode.Oneloop | RegexCode.Back:
  2956.                 case RegexCode.Notoneloop | RegexCode.Back:
  2957.                 case RegexCode.Setloop | RegexCode.Back:
  2958.                 case RegexCode.Oneloop | RegexCode.Rtl | RegexCode.Back:
  2959.                 case RegexCode.Notoneloop | RegexCode.Rtl | RegexCode.Back:
  2960.                 case RegexCode.Setloop | RegexCode.Rtl | RegexCode.Back:
  2961.                 case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Back:
  2962.                 case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Back:
  2963.                 case RegexCode.Setloop | RegexCode.Ci | RegexCode.Back:
  2964.                 case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
  2965.                 case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
  2966.                 case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
  2967.                    
  2968.                     //: Trackframe(2);
  2969.                     //: int i = Tracked(0);
  2970.                     //: int pos = Tracked(1);
  2971.                     //: Textto(pos);
  2972.                     //: if (i > 0)
  2973.                     //: Track(i - 1, pos - 1);
  2974.                     //: Advance(2);
  2975.                     PopTrack();
  2976.                     Stloc(_textposV);
  2977.                     PopTrack();
  2978.                     Stloc(_tempV);
  2979.                     Ldloc(_tempV);
  2980.                     Ldc(0);
  2981.                     BleFar(AdvanceLabel());
  2982.                     ReadyPushTrack();
  2983.                     Ldloc(_tempV);
  2984.                     Ldc(1);
  2985.                     Sub();
  2986.                     DoPush();
  2987.                     ReadyPushTrack();
  2988.                     Ldloc(_textposV);
  2989.                     Ldc(1);
  2990.                     Sub(IsRtl());
  2991.                     DoPush();
  2992.                     Trackagain();
  2993.                     Advance();
  2994.                     break;
  2995.                 case RegexCode.Onelazy:
  2996.                 case RegexCode.Notonelazy:
  2997.                 case RegexCode.Setlazy:
  2998.                 case RegexCode.Onelazy | RegexCode.Rtl:
  2999.                 case RegexCode.Notonelazy | RegexCode.Rtl:
  3000.                 case RegexCode.Setlazy | RegexCode.Rtl:
  3001.                 case RegexCode.Onelazy | RegexCode.Ci:
  3002.                 case RegexCode.Notonelazy | RegexCode.Ci:
  3003.                 case RegexCode.Setlazy | RegexCode.Ci:
  3004.                 case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl:
  3005.                 case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl:
  3006.                 case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl:
  3007.                    
  3008.                     //: int c = Operand(1);
  3009.                     //: if (c > Rightchars())
  3010.                     //: c = Rightchars();
  3011.                     //: if (c > 0)
  3012.                     //: Track(c - 1, Textpos());
  3013.                    
  3014.                     {
  3015.                         LocalBuilder cV = _tempV;
  3016.                        
  3017.                         int c = Operand(1);
  3018.                        
  3019.                         if (c == 0)
  3020.                             break;
  3021.                        
  3022.                         if (!IsRtl()) {
  3023.                             Ldloc(_textendV);
  3024.                             Ldloc(_textposV);
  3025.                         }
  3026.                         else {
  3027.                             Ldloc(_textposV);
  3028.                             Ldloc(_textbegV);
  3029.                         }
  3030.                         Sub();
  3031.                         if (c != Int32.MaxValue) {
  3032.                             Label l4 = DefineLabel();
  3033.                             Dup();
  3034.                             Ldc(c);
  3035.                             Blt(l4);
  3036.                             Pop();
  3037.                             Ldc(c);
  3038.                             MarkLabel(l4);
  3039.                         }
  3040.                         Dup();
  3041.                         Stloc(cV);
  3042.                         Ldc(0);
  3043.                         Ble(AdvanceLabel());
  3044.                         ReadyPushTrack();
  3045.                         Ldloc(cV);
  3046.                         Ldc(1);
  3047.                         Sub();
  3048.                         DoPush();
  3049.                         PushTrack(_textposV);
  3050.                         Track();
  3051.                         break;
  3052.                     }
  3053.                     break;
  3054.                 case RegexCode.Onelazy | RegexCode.Back:
  3055.                 case RegexCode.Notonelazy | RegexCode.Back:
  3056.                 case RegexCode.Setlazy | RegexCode.Back:
  3057.                 case RegexCode.Onelazy | RegexCode.Rtl | RegexCode.Back:
  3058.                 case RegexCode.Notonelazy | RegexCode.Rtl | RegexCode.Back:
  3059.                 case RegexCode.Setlazy | RegexCode.Rtl | RegexCode.Back:
  3060.                 case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Back:
  3061.                 case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Back:
  3062.                 case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Back:
  3063.                 case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
  3064.                 case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
  3065.                 case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
  3066.                    
  3067.                     //: Trackframe(2);
  3068.                     //: int pos = Tracked(1);
  3069.                     //: Textto(pos);
  3070.                     //: if (Rightcharnext() != (char)Operand(0))
  3071.                     //: break Backward;
  3072.                     //: int i = Tracked(0);
  3073.                     //: if (i > 0)
  3074.                     //: Track(i - 1, pos + 1);
  3075.                    
  3076.                     PopTrack();
  3077.                     Stloc(_textposV);
  3078.                     PopTrack();
  3079.                     Stloc(_temp2V);
  3080.                    
  3081.                     if (!IsRtl())
  3082.                         Rightcharnext();
  3083.                     else
  3084.                         Leftcharnext();
  3085.                    
  3086.                     if (IsCi())
  3087.                         CallToLower();
  3088.                    
  3089.                     if (Code() == RegexCode.Setlazy) {
  3090.                         Ldstr(_strings[Operand(0)]);
  3091.                         Call(_charInSetM);
  3092.                        
  3093.                         BrfalseFar(_backtrack);
  3094.                     }
  3095.                     else {
  3096.                         Ldc(Operand(0));
  3097.                         if (Code() == RegexCode.Onelazy)
  3098.                             BneFar(_backtrack);
  3099.                         else
  3100.                             BeqFar(_backtrack);
  3101.                     }
  3102.                    
  3103.                     Ldloc(_temp2V);
  3104.                     Ldc(0);
  3105.                     BleFar(AdvanceLabel());
  3106.                     ReadyPushTrack();
  3107.                     Ldloc(_temp2V);
  3108.                     Ldc(1);
  3109.                     Sub();
  3110.                     DoPush();
  3111.                     PushTrack(_textposV);
  3112.                     Trackagain();
  3113.                     Advance();
  3114.                     break;
  3115.                 default:
  3116.                    
  3117.                     throw new NotImplementedException(SR.GetString(SR.UnimplementedState));
  3118.                     break;
  3119.             }
  3120.         }
  3121.     }
  3122.    
  3123.     internal class RegexTypeCompiler : RegexCompiler
  3124.     {
  3125.         private static int _typeCount = 0;
  3126.         private static LocalDataStoreSlot _moduleSlot = Thread.AllocateDataSlot();
  3127.        
  3128.         private AssemblyBuilder _assembly;
  3129.         private ModuleBuilder _module;
  3130.        
  3131.         // state of the type builder
  3132.         private TypeBuilder _typebuilder;
  3133.         private MethodBuilder _methbuilder;
  3134.        
  3135.         [ResourceExposure(ResourceScope.Machine)]
  3136.         [ResourceConsumption(ResourceScope.Machine)]
  3137.         internal RegexTypeCompiler(AssemblyName an, CustomAttributeBuilder[] attribs, string resourceFile, Evidence evidence)
  3138.         {
  3139.             new ReflectionPermission(PermissionState.Unrestricted).Assert();
  3140.             try {
  3141.                 Debug.Assert(an != null, "AssemblyName should not be null");
  3142.                 _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave, evidence);
  3143.                 _module = _assembly.DefineDynamicModule(an.Name + ".dll");
  3144.                
  3145.                 if (attribs != null) {
  3146.                     for (int i = 0; i < attribs.Length; i++) {
  3147.                         _assembly.SetCustomAttribute(attribs[i]);
  3148.                     }
  3149.                 }
  3150.                
  3151.                 if (resourceFile != null) {
  3152.                     // unmanaged resources are not supported
  3153.                     throw new ArgumentOutOfRangeException("resourceFile");
  3154.                 }
  3155.             }
  3156.             finally {
  3157.                 CodeAccessPermission.RevertAssert();
  3158.             }
  3159.         }
  3160.        
  3161. /*
  3162.         * The top-level driver. Initializes everything then calls the Generate* methods.
  3163.         */       
  3164.         internal Type FactoryTypeFromCode(RegexCode code, RegexOptions options, string typeprefix)
  3165.         {
  3166.             string runnertypename;
  3167.             string runnerfactoryname;
  3168.             Type runnertype;
  3169.             Type factory;
  3170.            
  3171.             _code = code;
  3172.             _codes = code._codes;
  3173.             _strings = code._strings;
  3174.             _fcPrefix = code._fcPrefix;
  3175.             _bmPrefix = code._bmPrefix;
  3176.             _anchors = code._anchors;
  3177.             _trackcount = code._trackcount;
  3178.             _options = options;
  3179.            
  3180.             // pick a name for the class
  3181.             int typenum = Interlocked.Increment(ref _typeCount);
  3182.             string typenumString = typenum.ToString(CultureInfo.InvariantCulture);
  3183.             runnertypename = typeprefix + "Runner" + typenumString;
  3184.             runnerfactoryname = typeprefix + "Factory" + typenumString;
  3185.            
  3186.             // Generate a RegexRunner class
  3187.             // (blocks are simply illustrative)
  3188.            
  3189.             DefineType(runnertypename, false, typeof(RegexRunner));
  3190.             {
  3191.                 DefineMethod("Go", null);
  3192.                 {
  3193.                     GenerateGo();
  3194.                     BakeMethod();
  3195.                 }
  3196.                
  3197.                 DefineMethod("FindFirstChar", typeof(bool));
  3198.                 {
  3199.                     GenerateFindFirstChar();
  3200.                     BakeMethod();
  3201.                 }
  3202.                
  3203.                 DefineMethod("InitTrackCount", null);
  3204.                 {
  3205.                     GenerateInitTrackCount();
  3206.                     BakeMethod();
  3207.                 }
  3208.                
  3209.                 runnertype = BakeType();
  3210.             }
  3211.            
  3212.             // Generate a RegexRunnerFactory class
  3213.            
  3214.             DefineType(runnerfactoryname, false, typeof(RegexRunnerFactory));
  3215.             {
  3216.                 DefineMethod("CreateInstance", typeof(RegexRunner));
  3217.                 {
  3218.                     GenerateCreateInstance(runnertype);
  3219.                     BakeMethod();
  3220.                 }
  3221.                
  3222.                 factory = BakeType();
  3223.             }
  3224.            
  3225.             return factory;
  3226.         }
  3227.        
  3228.         internal void GenerateRegexType(string pattern, RegexOptions opts, string name, bool ispublic, RegexCode code, RegexTree tree, Type factory)
  3229.         {
  3230.             FieldInfo patternF = RegexField("pattern");
  3231.             FieldInfo optionsF = RegexField("roptions");
  3232.             FieldInfo factoryF = RegexField("factory");
  3233.             FieldInfo capsF = RegexField("caps");
  3234.             FieldInfo capnamesF = RegexField("capnames");
  3235.             FieldInfo capslistF = RegexField("capslist");
  3236.             FieldInfo capsizeF = RegexField("capsize");
  3237.             Type[] noTypeArray = new Type[0];
  3238.             ConstructorBuilder cbuilder;
  3239.            
  3240.             DefineType(name, ispublic, typeof(Regex));
  3241.             {
  3242.                 // define constructor
  3243.                 _methbuilder = null;
  3244.                 MethodAttributes ma = System.Reflection.MethodAttributes.Public;
  3245.                 cbuilder = _typebuilder.DefineConstructor(ma, CallingConventions.Standard, noTypeArray);
  3246.                 _ilg = cbuilder.GetILGenerator();
  3247.                 {
  3248.                     // call base constructor
  3249.                     Ldthis();
  3250.                     _ilg.Emit(OpCodes.Call, typeof(Regex).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], new ParameterModifier[0]));
  3251.                     // set pattern
  3252.                     Ldthis();
  3253.                     Ldstr(pattern);
  3254.                     Stfld(patternF);
  3255.                    
  3256.                     // set options
  3257.                     Ldthis();
  3258.                     Ldc((int)opts);
  3259.                     Stfld(optionsF);
  3260.                    
  3261.                     // set factory
  3262.                     Ldthis();
  3263.                     Newobj(factory.GetConstructor(noTypeArray));
  3264.                     Stfld(factoryF);
  3265.                    
  3266.                     // set caps
  3267.                     if (code._caps != null)
  3268.                         GenerateCreateHashtable(capsF, code._caps);
  3269.                    
  3270.                     // set capnames
  3271.                     if (tree._capnames != null)
  3272.                         GenerateCreateHashtable(capnamesF, tree._capnames);
  3273.                    
  3274.                     // set capslist
  3275.                     if (tree._capslist != null) {
  3276.                         Ldthis();
  3277.                         Ldc(tree._capslist.Length);
  3278.                         _ilg.Emit(OpCodes.Newarr, typeof(string));
  3279.                         // create new string array
  3280.                         Stfld(capslistF);
  3281.                        
  3282.                         for (int i = 0; i < tree._capslist.Length; i++) {
  3283.                             Ldthisfld(capslistF);
  3284.                            
  3285.                             Ldc(i);
  3286.                             Ldstr(tree._capslist[i]);
  3287.                             _ilg.Emit(OpCodes.Stelem_Ref);
  3288.                         }
  3289.                     }
  3290.                    
  3291.                     // set capsize
  3292.                     Ldthis();
  3293.                     Ldc(code._capsize);
  3294.                     Stfld(capsizeF);
  3295.                    
  3296.                     // set runnerref and replref by calling InitializeReferences()
  3297.                     Ldthis();
  3298.                     Call(typeof(Regex).GetMethod("InitializeReferences", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
  3299.                    
  3300.                    
  3301.                     Ret();
  3302.                 }
  3303.             }
  3304.            
  3305.             // bake the constructor and type, then save the assembly
  3306.             cbuilder = null;
  3307.             _typebuilder.CreateType();
  3308.             _ilg = null;
  3309.             _typebuilder = null;
  3310.         }
  3311.        
  3312.         internal void GenerateCreateHashtable(FieldInfo field, Hashtable ht)
  3313.         {
  3314.             MethodInfo addMethod = typeof(Hashtable).GetMethod("Add", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  3315.            
  3316.             Ldthis();
  3317.             Newobj(typeof(Hashtable).GetConstructor(new Type[0]));
  3318.             Stfld(field);
  3319.            
  3320.             IDictionaryEnumerator en = ht.GetEnumerator();
  3321.             while (en.MoveNext()) {
  3322.                 Ldthisfld(field);
  3323.                
  3324.                 if (en.Key is int) {
  3325.                     Ldc((int)en.Key);
  3326.                     _ilg.Emit(OpCodes.Box, typeof(Int32));
  3327.                 }
  3328.                 else
  3329.                     Ldstr((string)en.Key);
  3330.                
  3331.                 Ldc((int)en.Value);
  3332.                 _ilg.Emit(OpCodes.Box, typeof(Int32));
  3333.                 Callvirt(addMethod);
  3334.             }
  3335.         }
  3336.        
  3337.         private FieldInfo RegexField(string fieldname)
  3338.         {
  3339.             return typeof(Regex).GetField(fieldname, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
  3340.         }
  3341.        
  3342.         [ResourceExposure(ResourceScope.None)]
  3343.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Private)]
  3344.         internal void Save()
  3345.         {
  3346.             _assembly.Save(_assembly.GetName().Name + ".dll");
  3347.         }
  3348.        
  3349. /*
  3350.         * Generates a very simple factory method.
  3351.         */       
  3352.         internal void GenerateCreateInstance(Type newtype)
  3353.         {
  3354.             Newobj(newtype.GetConstructor(new Type[0]));
  3355.             Ret();
  3356.         }
  3357.        
  3358. /*
  3359.         * Begins the definition of a new type with a specified base class
  3360.         */       
  3361.         internal void DefineType(string typename, bool ispublic, Type inheritfromclass)
  3362.         {
  3363.             if (ispublic)
  3364.                 _typebuilder = _module.DefineType(typename, TypeAttributes.Class | TypeAttributes.Public, inheritfromclass);
  3365.             else
  3366.                 _typebuilder = _module.DefineType(typename, TypeAttributes.Class | TypeAttributes.NotPublic, inheritfromclass);
  3367.            
  3368.         }
  3369.        
  3370. /*
  3371.         * Begins the definition of a new method (no args) with a specified return value
  3372.         */       
  3373.         internal void DefineMethod(string methname, Type returntype)
  3374.         {
  3375.             MethodAttributes ma = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Virtual;
  3376.            
  3377.             _methbuilder = _typebuilder.DefineMethod(methname, ma, returntype, null);
  3378.             _ilg = _methbuilder.GetILGenerator();
  3379.         }
  3380.        
  3381. /*
  3382.         * Ends the definition of a method
  3383.         */       
  3384.         internal void BakeMethod()
  3385.         {
  3386.             _methbuilder = null;
  3387.         }
  3388.        
  3389. /*
  3390.         * Ends the definition of a class and returns the type
  3391.         */       
  3392.         internal Type BakeType()
  3393.         {
  3394.             Type retval = _typebuilder.CreateType();
  3395.             _typebuilder = null;
  3396.            
  3397.             return retval;
  3398.         }
  3399.        
  3400.     }
  3401.    
  3402.     internal class RegexLWCGCompiler : RegexCompiler
  3403.     {
  3404.         private static int _regexCount = 0;
  3405.         private static Type[] _paramTypes = new Type[] {typeof(RegexRunner)};
  3406.        
  3407.         internal RegexLWCGCompiler()
  3408.         {
  3409.         }
  3410.        
  3411. /*
  3412.         * The top-level driver. Initializes everything then calls the Generate* methods.
  3413.         */       
  3414.         internal RegexRunnerFactory FactoryInstanceFromCode(RegexCode code, RegexOptions options)
  3415.         {
  3416.             _code = code;
  3417.             _codes = code._codes;
  3418.             _strings = code._strings;
  3419.             _fcPrefix = code._fcPrefix;
  3420.             _bmPrefix = code._bmPrefix;
  3421.             _anchors = code._anchors;
  3422.             _trackcount = code._trackcount;
  3423.             _options = options;
  3424.            
  3425.             // pick a unique number for the methods we generate
  3426.             int regexnum = Interlocked.Increment(ref _regexCount);
  3427.             string regexnumString = regexnum.ToString(CultureInfo.InvariantCulture);
  3428.            
  3429.             DynamicMethod goMethod = DefineDynamicMethod("Go" + regexnumString, null, typeof(CompiledRegexRunner));
  3430.             GenerateGo();
  3431.            
  3432.             DynamicMethod firstCharMethod = DefineDynamicMethod("FindFirstChar" + regexnumString, typeof(bool), typeof(CompiledRegexRunner));
  3433.             GenerateFindFirstChar();
  3434.            
  3435.             DynamicMethod trackCountMethod = DefineDynamicMethod("InitTrackCount" + regexnumString, null, typeof(CompiledRegexRunner));
  3436.             GenerateInitTrackCount();
  3437.            
  3438.             return new CompiledRegexRunnerFactory(goMethod, firstCharMethod, trackCountMethod);
  3439.         }
  3440.        
  3441. /*
  3442.         * Begins the definition of a new method (no args) with a specified return value
  3443.         */       
  3444.         internal DynamicMethod DefineDynamicMethod(string methname, Type returntype, Type hostType)
  3445.         {
  3446.             // We're claiming that these are static methods, but really they are instance methods.
  3447.             // By giving them a parameter which represents "this", we're tricking them into
  3448.             // being instance methods.
  3449.            
  3450.             MethodAttributes attribs = MethodAttributes.Public | MethodAttributes.Static;
  3451.             CallingConventions conventions = CallingConventions.Standard;
  3452.            
  3453.                 /*skipVisibility*/            DynamicMethod dm = new DynamicMethod(methname, attribs, conventions, returntype, _paramTypes, hostType, false);
  3454.             _ilg = dm.GetILGenerator();
  3455.             return dm;
  3456.         }
  3457.        
  3458.     }
  3459.    
  3460. }

Developer Fusion