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