From 2a0e157985d790e6cbd83d61690da2709dfab9dd Mon Sep 17 00:00:00 2001 From: Tedd Hansen Date: Wed, 8 Aug 2007 14:05:13 +0000 Subject: [PATCH] Added ScriptEngine.DotNetEngine --- .../DotNetEngine.Compiler.LSL/Common.cs | 84 + .../DotNetEngine.Compiler.LSL/Engine.cs | 300 ++ .../IL_common_functions.cs | 56 + .../LSL_BaseClass.cs | 58 + .../LSL_BaseClass_Builtins.cs | 373 ++ .../LSL_BaseClass_OPCODES.cs | 342 ++ .../LSL_CLRInterface.cs | 79 + .../LSL_OPCODE_IL_processor.cs | 435 +++ .../DotNetEngine.Compiler.LSL/LSO_Enums.cs | 557 +++ .../DotNetEngine.Compiler.LSL/LSO_Parser.cs | 722 ++++ .../DotNetEngine.Compiler.LSL/LSO_Struct.cs | 135 + .../DotNetEngine.Compiler.LSL/LSOdoc.htm | 9 + .../DotNetEngine.Compiler.LSL/OPCODES.txt | 142 + ...iptEngine.DotNetEngine.Compiler.LSL.csproj | 63 + ...ScriptEngine.DotNetEngine.Compiler.LSL.suo | Bin 0 -> 7680 bytes .../Properties/AssemblyInfo.cs | 35 + .../LSL_BuiltIn_Commands_Interface.cs | 368 ++ ...LSL_BuiltIn_Commands_TestImplementation.cs | 386 ++ .../DotNetEngine.Compiler.LSL/temp_rc.cs | 3293 +++++++++++++++++ .../ScriptEngine/DotNetEngine/Common.cs | 58 + .../ScriptEngine/DotNetEngine/EventManager.cs | 99 + .../DotNetEngine/EventQueueManager.cs | 136 + ...im.Region.ScriptEngine.DotNetEngine.csproj | 59 + ...enSim.Region.ScriptEngine.DotNetEngine.suo | Bin 0 -> 5120 bytes .../DotNetEngine/Properties/AssemblyInfo.cs | 35 + .../ScriptEngine/DotNetEngine/ScriptEngine.cs | 77 + .../DotNetEngine/ScriptEngineInterface.cs | 40 + .../DotNetEngine/ScriptManager.cs | 232 ++ .../DotNetEngine/TempWorldInterface.cs | 15 + 29 files changed, 8188 insertions(+) create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Common.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Engine.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/IL_common_functions.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_Builtins.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_OPCODES.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_CLRInterface.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_OPCODE_IL_processor.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Enums.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Parser.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Struct.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSOdoc.htm create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OPCODES.txt create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.csproj create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.suo create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Server API/LSL_BuiltIn_Commands_Interface.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Server API/LSL_BuiltIn_Commands_TestImplementation.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/temp_rc.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.csproj create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.suo create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngineInterface.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs create mode 100644 OpenSim/Region/ScriptEngine/DotNetEngine/TempWorldInterface.cs diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Common.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Common.cs new file mode 100644 index 0000000000..1f24d9bebd --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Common.cs @@ -0,0 +1,84 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public static class Common + { + static public bool Debug = true; + static public bool IL_UseTryCatch = true; + static public bool IL_CreateConstructor = true; + static public bool IL_CreateFunctionList = true; + static public bool IL_ProcessCodeChunks = true; + + public delegate void SendToDebugEventDelegate(string Message); + public delegate void SendToLogEventDelegate(string Message); + static public event SendToDebugEventDelegate SendToDebugEvent; + static public event SendToLogEventDelegate SendToLogEvent; + + static public void SendToDebug(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:Debug: " + Message); + SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + static public void SendToLog(string Message) + { + //if (Debug == true) + Console.WriteLine("COMPILER:LOG: " + Message); + SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } + + // TEMPORARY TEST THINGIES + public static class IL_Helper + { + public static string ReverseFormatString(string text1, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1); + } + public static string ReverseFormatString(string text1, UInt32 text2, string format) + { + Common.SendToDebug("ReverseFormatString text1: " + text1); + Common.SendToDebug("ReverseFormatString text2: " + text2.ToString()); + Common.SendToDebug("ReverseFormatString format: " + format); + return string.Format(format, text1, text2.ToString()); + } + public static string Cast_ToString(object obj) + { + Common.SendToDebug("OBJECT TO BE CASTED: " + obj.GetType().ToString()); + return "ABCDEFGIHJKLMNOPQ123"; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Engine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Engine.cs new file mode 100644 index 0000000000..80394b1bd9 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/Engine.cs @@ -0,0 +1,300 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Threading; +using System.Windows.Forms; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + + + public class Engine + { + //private string LSO_FileName = @"LSO\AdditionTest.lso"; + private string LSO_FileName;// = @"LSO\CloseToDefault.lso"; + AppDomain appDomain; + + public string Compile(string LSOFileName) + { + LSO_FileName = LSOFileName; + + + //appDomain = AppDomain.CreateDomain("AlternateAppDomain"); + appDomain = Thread.GetDomain(); + + // Create Assembly Name + AssemblyName asmName = new AssemblyName(); + asmName.Name = System.IO.Path.GetFileNameWithoutExtension(LSO_FileName); + //asmName.Name = "TestAssembly"; + + string DLL_FileName = asmName.Name + ".dll"; + string DLL_FileName_WithPath = System.IO.Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName; + + Common.SendToLog("LSO File Name: " + System.IO.Path.GetFileName(LSO_FileName)); + Common.SendToLog("Assembly name: " + asmName.Name); + Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll"); + Common.SendToLog("Starting processing of LSL ByteCode..."); + Common.SendToLog(""); + + + + // Create Assembly + AssemblyBuilder asmBuilder = appDomain.DefineDynamicAssembly( + asmName, + AssemblyBuilderAccess.RunAndSave + ); + //// Create Assembly + //AssemblyBuilder asmBuilder = + // Thread.GetDomain().DefineDynamicAssembly + //(asmName, AssemblyBuilderAccess.RunAndSave); + + // Create a module (and save to disk) + ModuleBuilder modBuilder = asmBuilder.DefineDynamicModule + (asmName.Name, + DLL_FileName); + + //Common.SendToDebug("asmName.Name is still \"" + asmName.Name + "\""); + // Create a Class (/Type) + TypeBuilder typeBuilder = modBuilder.DefineType( + "LSL_ScriptObject", + TypeAttributes.Public | TypeAttributes.BeforeFieldInit, + typeof(OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass)); + //, + // typeof()); + //, typeof(LSL_BuiltIn_Commands_Interface)); + //, + // typeof(object), + // new Type[] { typeof(LSL_CLRInterface.LSLScript) }); + + + + /* + * Generate the IL itself + */ + + LSO_Parser LSOP = new LSO_Parser(LSO_FileName, typeBuilder); + LSOP.OpenFile(); + LSOP.Parse(); + + // Constructor has to be created AFTER LSO_Parser because of accumulated variables + if (Common.IL_CreateConstructor) + IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP); + + LSOP.CloseFile(); + /* + * Done generating. Create a type and run it. + */ + + + Common.SendToLog("Attempting to compile assembly..."); + // Compile it + Type type = typeBuilder.CreateType(); + Common.SendToLog("Compilation successful!"); + + Common.SendToLog("Saving assembly: " + DLL_FileName); + asmBuilder.Save(DLL_FileName); + + Common.SendToLog("Returning assembly filename: " + DLL_FileName); + + + return DLL_FileName; + + + //Common.SendToLog("Creating an instance of new assembly..."); + //// Create an instance we can play with + ////LSLScript hello = (LSLScript)Activator.CreateInstance(type); + ////LSL_CLRInterface.LSLScript MyScript = (LSL_CLRInterface.LSLScript)Activator.CreateInstance(type); + //object MyScript = (object)Activator.CreateInstance(type); + + + + + + //System.Reflection.MemberInfo[] Members = type.GetMembers(); + + //Common.SendToLog("Members of assembly " + type.ToString() + ":"); + //foreach (MemberInfo member in Members) + // Common.SendToLog(member.ToString()); + + + //// Play with it + ////MyScript.event_state_entry("Test"); + //object[] args = { null }; + ////System.Collections.Generic.List Functions = (System.Collections.Generic.List)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //string[] ret = { }; + //if (Common.IL_CreateFunctionList) + // ret = (string[])type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, MyScript, null); + + //foreach (string s in ret) + //{ + // Common.SendToLog(""); + // Common.SendToLog("*** Executing LSL Server Event: " + s); + // //object test = type.GetMember(s); + // //object runner = type.InvokeMember(s, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, MyScript, args); + // //runner(); + // //objBooks_Late = type.InvokeMember(s, BindingFlags.CreateInstance, null, objApp_Late, null); + // type.InvokeMember(s, BindingFlags.InvokeMethod, null, MyScript, new object[] { "Test" }); + + //} + + + } + + + private static void IL_CREATE_CONSTRUCTOR(TypeBuilder typeBuilder, LSO_Parser LSOP) + { + + + Common.SendToDebug("IL_CREATE_CONSTRUCTOR()"); + //ConstructorBuilder constructor = typeBuilder.DefineConstructor( + // MethodAttributes.Public, + // CallingConventions.Standard, + // new Type[0]); + ConstructorBuilder constructor = typeBuilder.DefineConstructor( + MethodAttributes.Public | + MethodAttributes.SpecialName | + MethodAttributes.RTSpecialName, + CallingConventions.Standard, + new Type[0]); + + //Define the reflection ConstructorInfor for System.Object + ConstructorInfo conObj = typeof(LSL_BaseClass).GetConstructor(new Type[0]); + + //call constructor of base object + ILGenerator il = constructor.GetILGenerator(); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, conObj); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: UInt32 State = 0;"); + //string FieldName; + //// Create state object + //FieldName = "State"; + //FieldBuilder State_fb = typeBuilder.DefineField( + // FieldName, + // typeof(UInt32), + // FieldAttributes.Public); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldc_I4, 0); + //il.Emit(OpCodes.Stfld, State_fb); + + + //Common.SendToDebug("IL_CREATE_CONSTRUCTOR: Creating global: LSL_BuiltIn_Commands_TestImplementation LSL_BuiltIns = New LSL_BuiltIn_Commands_TestImplementation();"); + ////Type objType1 = typeof(object); + //Type objType1 = typeof(LSL_BuiltIn_Commands_TestImplementation); + + //FieldName = "LSL_BuiltIns"; + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField( + // FieldName, + // objType1, + // FieldAttributes.Public); + + ////LSL_BuiltIn_Commands_TestImplementation _ti = new LSL_BuiltIn_Commands_TestImplementation(); + //il.Emit(OpCodes.Ldarg_0); + ////il.Emit(OpCodes.Ldstr, "Test 123"); + //il.Emit(OpCodes.Newobj, objType1.GetConstructor(new Type[] { })); + //il.Emit(OpCodes.Stfld, LSL_BuiltIns_fb); + + foreach (UInt32 pos in LSOP.StaticBlocks.Keys) + { + LSO_Struct.StaticBlock sb; + LSOP.StaticBlocks.TryGetValue(pos, out sb); + + if (sb.ObjectType > 0 && sb.ObjectType < 8) { // We don't want void or null's + + il.Emit(OpCodes.Ldarg_0); + // Push position to stack + il.Emit(OpCodes.Ldc_I4, pos); + //il.Emit(OpCodes.Box, typeof(UInt32)); + + + Type datatype = null; + + // Push data to stack + Common.SendToDebug("Adding to static (" + pos + ") type: " + ((LSO_Enums.Variable_Type_Codes)sb.ObjectType).ToString() + " (" + sb.ObjectType + ")"); + switch ((LSO_Enums.Variable_Type_Codes)sb.ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.Integer: + //UInt32 + il.Emit(OpCodes.Ldc_I4, BitConverter.ToUInt32(sb.BlockVariable, 0)); + datatype = typeof(UInt32); + il.Emit(OpCodes.Box, datatype); + break; + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + //String + LSO_Struct.HeapBlock hb = LSOP.GetHeap(LSOP.myHeader.HR + BitConverter.ToUInt32(sb.BlockVariable, 0) - 1); + il.Emit(OpCodes.Ldstr, System.Text.Encoding.UTF8.GetString(hb.Data)); + datatype = typeof(string); + break; + case LSO_Enums.Variable_Type_Codes.Vector: + datatype = typeof(LSO_Enums.Vector); + //TODO: Not implemented + break; + case LSO_Enums.Variable_Type_Codes.Rotation: + //Object + //TODO: Not implemented + datatype = typeof(LSO_Enums.Rotation); + break; + default: + datatype = typeof(object); + break; + } + + + // Make call + il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("AddToStatic", new Type[] { typeof(UInt32), datatype })); + } + + } + + + + + ////il.Emit(OpCodes.Newobj, typeof(UInt32)); + //il.Emit(OpCodes.Starg_0); + //// Create LSL function library + //FieldBuilder LSL_BuiltIns_fb = typeBuilder.DefineField("LSL_BuiltIns", typeof(LSL_BuiltIn_Commands_Interface), FieldAttributes.Public); + //il.Emit(OpCodes.Newobj, typeof(LSL_BuiltIn_Commands_Interface)); + //il.Emit(OpCodes.Stloc_1); + + il.Emit(OpCodes.Ret); + } + + + + + // End of class + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/IL_common_functions.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/IL_common_functions.cs new file mode 100644 index 0000000000..76738b8437 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/IL_common_functions.cs @@ -0,0 +1,56 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Reflection.Emit; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + partial class LSO_Parser + { + private static TypeBuilder CreateType(ModuleBuilder modBuilder, string typeName) + { + TypeBuilder typeBuilder = modBuilder.DefineType(typeName, + TypeAttributes.Public | + TypeAttributes.Class | + TypeAttributes.AutoClass | + TypeAttributes.AnsiClass | + TypeAttributes.BeforeFieldInit | + TypeAttributes.AutoLayout, + typeof(object), + new Type[] { typeof(object) }); + return typeBuilder; + + } + + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass.cs new file mode 100644 index 0000000000..b88a905a9a --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public partial class LSL_BaseClass + { + //public MemoryStream LSLStack = new MemoryStream(); + public Stack LSLStack = new Stack(); + public Dictionary StaticVariables = new Dictionary(); + public Dictionary GlobalVariables = new Dictionary(); + public Dictionary LocalVariables = new Dictionary(); + //public System.Collections.Generic.List FunctionList = new System.Collections.Generic.List(); + //public void AddFunction(String x) { + // FunctionList.Add(x); + //} + //public Stack LSLStack = new Stack; + //public struct StackItemStruct + //{ + // public LSO_Enums.Variable_Type_Codes ItemType; + // public object Data; + //} + public UInt32 State = 0; + public LSL_BuiltIn_Commands_Interface LSL_Builtins; + public LSL_BuiltIn_Commands_Interface GetLSL_BuiltIn() + { + return LSL_Builtins; + } + + + public LSL_BaseClass() { } + + + public virtual int OverrideMe() + { + return 0; + } + public void Start(LSL_BuiltIn_Commands_Interface LSLBuiltins) + { + LSL_Builtins = LSLBuiltins; + + Common.SendToLog("OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass.Start() called"); + //LSL_Builtins.llSay(0, "Test"); + return; + } + + public void AddToStatic(UInt32 index, object obj) + { + Common.SendToDebug("AddToStatic: " + index + " type: " + obj.GetType()); + StaticVariables.Add(index, obj); + } + + + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_Builtins.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_Builtins.cs new file mode 100644 index 0000000000..d6f9a88b4d --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_Builtins.cs @@ -0,0 +1,373 @@ +//using System; +//using System.Collections.Generic; +//using System.Text; + +//namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +//{ +// public partial class LSL_BaseClass +// { + + +// public float llSin() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llSin(f); +// } +// public float llCos() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llCos(f); +// } +// public float llTan() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llTan(f); +// } +// public float llAtan2() { +// float x = (float)LSLStack.Pop(); +// float y = (float)LSLStack.Pop(); +// return LSL_Builtins.llAtan2(x, y); +// } +// public float llSqrt() { +// float f = (float)LSLStack.Pop(); +// return LSL_Builtins.llSqrt(f); +// } +// float llPow() +// { +// float fexponent = (float)LSLStack.Pop(); +// float fbase = (float)LSLStack.Pop(); +// return LSL_Builtins.llPow(fbase, fexponent); +// } +// //UInt32 llAbs(UInt32 i){ return; } +// //float llFabs(float f){ return; } +// //float llFrand(float mag){ return; } +// //UInt32 llFloor(float f){ return; } +// //UInt32 llCeil(float f){ return; } +// //UInt32 llRound(float f){ return; } +// //float llVecMag(LSO_Enums.Vector v){ return; } +// //LSO_Enums.Vector llVecNorm(LSO_Enums.Vector v){ return; } +// //float llVecDist(LSO_Enums.Vector a, LSO_Enums.Vector b){ return; } +// //LSO_Enums.Vector llRot2Euler(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Rotation llEuler2Rot(LSO_Enums.Vector v){ return; } +// //LSO_Enums.Rotation llAxes2Rot(LSO_Enums.Vector fwd, LSO_Enums.Vector left, LSO_Enums.Vector up){ return; } +// //LSO_Enums.Vector llRot2Fwd(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Vector llRot2Left(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Vector llRot2Up(LSO_Enums.Rotation r){ return; } +// //LSO_Enums.Rotation llRotBetween(LSO_Enums.Vector start, LSO_Enums.Vector end){ return; } +// public void llWhisper() +// { +// UInt16 i = (UInt16)LSLStack.Pop(); +// string s = (string)LSLStack.Pop(); +// LSL_Builtins.llWhisper(i, s); +// } +// public void llSay() +// { +// UInt16 i = (UInt16)LSLStack.Pop(); +// string s = (string)LSLStack.Pop(); +// LSL_Builtins.llSay(i, s); +// } +// //void llShout(UInt16 channelID, string text); +// //UInt32 llListen(UInt16 channelID, string name, LSO_Enums.Key ID, string msg); +// //void llListenControl(UInt32 number, UInt32 active); +// //void llListenRemove(UInt32 number); +// //void llSensor(string name, LSO_Enums.Key id, UInt32 type, float range, float arc); +// //void llSensorRepeat(string name, LSO_Enums.Key id, UInt32 type, float range, float arc, float rate); +// //void llSensorRemove(); +// //string llDetectedName(UInt32 number); +// //LSO_Enums.Key llDetectedKey(UInt32 number); +// //LSO_Enums.Key llDetectedOwner(UInt32 number); +// //UInt32 llDetectedType(UInt32 number); +// //LSO_Enums.Vector llDetectedPos(UInt32 number); +// //LSO_Enums.Vector llDetectedVel(UInt32 number); +// //LSO_Enums.Vector llDetectedGrab(UInt32 number); +// //LSO_Enums.Rotation llDetectedRot(UInt32 number); +// //UInt32 llDetectedGroup(UInt32 number); +// //UInt32 llDetectedLinkNumber(UInt32 number); +// //void llDie(); +// //float llGround(LSO_Enums.Vector offset); +// //float llCloud(LSO_Enums.Vector offset); +// //LSO_Enums.Vector llWind(LSO_Enums.Vector offset); +// //void llSetStatus(UInt32 status, UInt32 value); +// //UInt32 llGetStatus(UInt32 status); +// //void llSetScale(LSO_Enums.Vector scale); +// //LSO_Enums.Vector llGetScale(); +// //void llSetColor(); +// //float llGetAlpha(); +// //void llSetAlpha(); +// //LSO_Enums.Vector llGetColor(); +// //void llSetTexture(); +// //void llScaleTexture(); +// //void llOffsetTexture(); +// //void llRotateTexture(); +// //string llGetTexture(); +// //void llSetPos(); + +// public void llGetPos() { } +// public void llGetLocalPos() { } +// public void llSetRot() { } +// public void llGetRot() { } +// public void llGetLocalRot() { } +// public void llSetForce() { } +// public void llGetForce() { } +// public void llTarget() { } +// public void llTargetRemove() { } +// public void llRotTarget() { } +// public void llRotTargetRemove() { } +// public void llMoveToTarget() { } +// public void llStopMoveToTarget() { } +// public void llApplyImpulse() { } +// public void llApplyRotationalImpulse() { } +// public void llSetTorque() { } +// public void llGetTorque() { } +// public void llSetForceAndTorque() { } +// public void llGetVel() { } +// public void llGetAccel() { } +// public void llGetOmega() { } +// public void llGetTimeOfDay() { } +// public void llGetWallclock() { } +// public void llGetTime() { } +// public void llResetTime() { } +// public void llGetAndResetTime() { } +// public void llSound() { } +// public void llPlaySound() { } +// public void llLoopSound() { } +// public void llLoopSoundMaster() { } +// public void llLoopSoundSlave() { } +// public void llPlaySoundSlave() { } +// public void llTriggerSound() { } +// public void llStopSound() { } +// public void llPreloadSound() { } +// public void llGetSubString() { } +// public void llDeleteSubString() { } +// public void llInsertString() { } +// public void llToUpper() { } +// public void llToLower() { } +// public void llGiveMoney() { } +// public void llMakeExplosion() { } +// public void llMakeFountain() { } +// public void llMakeSmoke() { } +// public void llMakeFire() { } +// public void llRezObject() { } +// public void llLookAt() { } +// public void llStopLookAt() { } +// public void llSetTimerEvent() { } +// public void llSleep() { } +// public void llGetMass() { } +// public void llCollisionFilter() { } +// public void llTakeControls() { } +// public void llReleaseControls() { } +// public void llAttachToAvatar() { } +// public void llDetachFromAvatar() { } +// public void llTakeCamera() { } +// public void llReleaseCamera() { } +// public void llGetOwner() { } +// public void llInstantMessage() { } +// public void llEmail() { } +// public void llGetNextEmail() { } +// public void llGetKey() { } +// public void llSetBuoyancy() { } +// public void llSetHoverHeight() { } +// public void llStopHover() { } +// public void llMinEventDelay() { } +// public void llSoundPreload() { } +// public void llRotLookAt() { } +// public void llStringLength() { } +// public void llStartAnimation() { } +// public void llStopAnimation() { } +// public void llPointAt() { } +// public void llStopPointAt() { } +// public void llTargetOmega() { } +// public void llGetStartParameter() { } +// public void llGodLikeRezObject() { } +// public void llRequestPermissions() { } +// public void llGetPermissionsKey() { } +// public void llGetPermissions() { } +// public void llGetLinkNumber() { } +// public void llSetLinkColor() { } +// public void llCreateLink() { } +// public void llBreakLink() { } +// public void llBreakAllLinks() { } +// public void llGetLinkKey() { } +// public void llGetLinkName() { } +// public void llGetInventoryNumber() { } +// public void llGetInventoryName() { } +// public void llSetScriptState() { } +// public void llGetEnergy() { } +// public void llGiveInventory() { } +// public void llRemoveInventory() { } +// public void llSetText() { } +// public void llWater() { } +// public void llPassTouches() { } +// public void llRequestAgentData() { } +// public void llRequestInventoryData() { } +// public void llSetDamage() { } +// public void llTeleportAgentHome() { } +// public void llModifyLand() { } +// public void llCollisionSound() { } +// public void llCollisionSprite() { } +// public void llGetAnimation() { } +// public void llResetScript() { } +// public void llMessageLinked() { } +// public void llPushObject() { } +// public void llPassCollisions() { } +// public void llGetScriptName() { } +// public void llGetNumberOfSides() { } +// public void llAxisAngle2Rot() { } +// public void llRot2Axis() { } +// public void llRot2Angle() { } +// public void llAcos() { } +// public void llAsin() { } +// public void llAngleBetween() { } +// public void llGetInventoryKey() { } +// public void llAllowInventoryDrop() { } +// public void llGetSunDirection() { } +// public void llGetTextureOffset() { } +// public void llGetTextureScale() { } +// public void llGetTextureRot() { } +// public void llSubStringIndex() { } +// public void llGetOwnerKey() { } +// public void llGetCenterOfMass() { } +// public void llListSort() { } +// public void llGetListLength() { } +// public void llList2Integer() { } +// public void llList2Float() { } +// public void llList2String() { } +// public void llList2Key() { } +// public void llList2Vector() { } +// public void llList2Rot() { } +// public void llList2List() { } +// public void llDeleteSubList() { } +// public void llGetListEntryType() { } +// public void llList2CSV() { } +// public void llCSV2List() { } +// public void llListRandomize() { } +// public void llList2ListStrided() { } +// public void llGetRegionCorner() { } +// public void llListInsertList() { } +// public void llListFindList() { } +// public void llGetObjectName() { } +// public void llSetObjectName() { } +// public void llGetDate() { } +// public void llEdgeOfWorld() { } +// public void llGetAgentInfo() { } +// public void llAdjustSoundVolume() { } +// public void llSetSoundQueueing() { } +// public void llSetSoundRadius() { } +// public void llKey2Name() { } +// public void llSetTextureAnim() { } +// public void llTriggerSoundLimited() { } +// public void llEjectFromLand() { } +// public void llParseString2List() { } +// public void llOverMyLand() { } +// public void llGetLandOwnerAt() { } +// public void llGetNotecardLine() { } +// public void llGetAgentSize() { } +// public void llSameGroup() { } +// public void llUnSit() { } +// public void llGroundSlope() { } +// public void llGroundNormal() { } +// public void llGroundContour() { } +// public void llGetAttached() { } +// public void llGetFreeMemory() { } +// public void llGetRegionName() { } +// public void llGetRegionTimeDilation() { } +// public void llGetRegionFPS() { } +// public void llParticleSystem() { } +// public void llGroundRepel() { } +// public void llGiveInventoryList() { } +// public void llSetVehicleType() { } +// public void llSetVehicleFloatParam() { } +// public void llSetVehicleVectorParam() { } +// public void llSetVehicleRotationParam() { } +// public void llSetVehicleFlags() { } +// public void llRemoveVehicleFlags() { } +// public void llSitTarget() { } +// public void llAvatarOnSitTarget() { } +// public void llAddToLandPassList() { } +// public void llSetTouchText() { } +// public void llSetSitText() { } +// public void llSetCameraEyeOffset() { } +// public void llSetCameraAtOffset() { } +// public void llDumpList2String() { } +// public void llScriptDanger() { } +// public void llDialog() { } +// public void llVolumeDetect() { } +// public void llResetOtherScript() { } +// public void llGetScriptState() { } +// public void llRemoteLoadScript() { } +// public void llSetRemoteScriptAccessPin() { } +// public void llRemoteLoadScriptPin() { } +// public void llOpenRemoteDataChannel() { } +// public void llSendRemoteData() { } +// public void llRemoteDataReply() { } +// public void llCloseRemoteDataChannel() { } +// public void llMD5String() { } +// public void llSetPrimitiveParams() { } +// public void llStringToBase64() { } +// public void llBase64ToString() { } +// public void llXorBase64Strings() { } +// public void llRemoteDataSetRegion() { } +// public void llLog10() { } +// public void llLog() { } +// public void llGetAnimationList() { } +// public void llSetParcelMusicURL() { } +// public void llGetRootPosition() { } +// public void llGetRootRotation() { } +// public void llGetObjectDesc() { } +// public void llSetObjectDesc() { } +// public void llGetCreator() { } +// public void llGetTimestamp() { } +// public void llSetLinkAlpha() { } +// public void llGetNumberOfPrims() { } +// public void llGetNumberOfNotecardLines() { } +// public void llGetBoundingBox() { } +// public void llGetGeometricCenter() { } +// public void llGetPrimitiveParams() { } +// public void llIntegerToBase64() { } +// public void llBase64ToInteger() { } +// public void llGetGMTclock() { } +// public void llGetSimulatorHostname() { } +// public void llSetLocalRot() { } +// public void llParseStringKeepNulls() { } +// public void llRezAtRoot() { } +// public void llGetObjectPermMask() { } +// public void llSetObjectPermMask() { } +// public void llGetInventoryPermMask() { } +// public void llSetInventoryPermMask() { } +// public void llGetInventoryCreator() { } +// public void llOwnerSay() { } +// public void llRequestSimulatorData() { } +// public void llForceMouselook() { } +// public void llGetObjectMass() { } +// public void llListReplaceList() { } +// public void llLoadURL() { } +// public void llParcelMediaCommandList() { } +// public void llParcelMediaQuery() { } +// public void llModPow() { } +// public void llGetInventoryType() { } +// public void llSetPayPrice() { } +// public void llGetCameraPos() { } +// public void llGetCameraRot() { } +// public void llSetPrimURL() { } +// public void llRefreshPrimURL() { } +// public void llEscapeURL() { } +// public void llUnescapeURL() { } +// public void llMapDestination() { } +// public void llAddToLandBanList() { } +// public void llRemoveFromLandPassList() { } +// public void llRemoveFromLandBanList() { } +// public void llSetCameraParams() { } +// public void llClearCameraParams() { } +// public void llListStatistics() { } +// public void llGetUnixTime() { } +// public void llGetParcelFlags() { } +// public void llGetRegionFlags() { } +// public void llXorBase64StringsCorrect() { } +// public void llHTTPRequest() { } +// public void llResetLandBanList() { } +// public void llResetLandPassList() { } +// public void llGetParcelPrimCount() { } +// public void llGetParcelPrimOwners() { } +// public void llGetObjectPrimCount() { } +// public void llGetParcelMaxPrims() { } +// public void llGetParcelDetails() { } + +// } +//} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_OPCODES.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_OPCODES.cs new file mode 100644 index 0000000000..b7716781e0 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_BaseClass_OPCODES.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public partial class LSL_BaseClass + { + + + + public void StoreToLocal(UInt32 index) + { + // TODO: How to determine local? + Common.SendToDebug("::StoreToLocal " + index); + if (LocalVariables.ContainsKey(index)) + LocalVariables.Remove(index); + LocalVariables.Add(index, LSLStack.Peek()); + } + public void StoreToGlobal(UInt32 index) + { + Common.SendToDebug("::StoreToGlobal " + index); + if (GlobalVariables.ContainsKey(index)) + GlobalVariables.Remove(index); + GlobalVariables.Add(index, LSLStack.Peek()); + } + public void StoreToStatic(UInt32 index) + { + Common.SendToDebug("::StoreToStatic " + index); + //if (StaticVariables.ContainsKey(index)) + // StaticVariables.Remove(index); + StaticVariables.Add(index, LSLStack.Peek()); + } + public void GetFromLocal(UInt32 index) + { + // TODO: How to determine local? + Common.SendToDebug("::GetFromLocal " + index); + object ret; + LocalVariables.TryGetValue(index, out ret); + LSLStack.Push(ret); + //return ret; + } + public void GetFromGlobal(UInt32 index) + { + Common.SendToDebug("::GetFromGlobal " + index); + object ret; + GlobalVariables.TryGetValue(index, out ret); + LSLStack.Push(ret); + //return ret; + } + public void GetFromStatic(UInt32 index) + { + Common.SendToDebug("::GetFromStatic " + index); + object ret; + StaticVariables.TryGetValue(index, out ret); + Common.SendToDebug("::GetFromStatic - ObjectType: " + ret.GetType().ToString()); + LSLStack.Push(ret); + //return ret; + } + + public object POPToStack() + { + Common.SendToDebug("::POPToStack"); + //return LSLStack.Pop(); + object p = LSLStack.Pop(); + if (p.GetType() == typeof(UInt32)) + return (UInt32)p; + if (p.GetType() == typeof(string)) + return (string)p; + if (p.GetType() == typeof(Int32)) + return (Int32)p; + if (p.GetType() == typeof(UInt16)) + return (UInt16)p; + if (p.GetType() == typeof(float)) + return (float)p; + if (p.GetType() == typeof(LSO_Enums.Vector)) + return (LSO_Enums.Vector)p; + if (p.GetType() == typeof(LSO_Enums.Rotation)) + return (LSO_Enums.Rotation)p; + if (p.GetType() == typeof(LSO_Enums.Key)) + return (LSO_Enums.Key)p; + + return p; + } + + //public object POPToStack(UInt32 count) + //{ + // // POP NUMBER FROM TOP OF STACK + // //LSLStack.SetLength(LSLStack.Length - 4); + // Common.SendToDebug("::POPToStack " + count); + // if (count < 2) + // return LSLStack.Pop(); + + // Stack s = new Stack(); + // for (int i = 0; i < count; i++) + // { + // s.Push(LSLStack.Pop); + + // } + + //} + + public void POP() + { + // POP NUMBER FROM TOP OF STACK + //LSLStack.SetLength(LSLStack.Length - 4); + Common.SendToDebug("::POP"); + if (LSLStack.Count < 1) + { + //TODO: Temporary fix + Common.SendToDebug("ERROR: TRYING TO POP EMPTY STACK!"); + } + else + { + LSLStack.Pop(); + } + } + public void PUSH(object Param) + { + if (Param == null) + { + Common.SendToDebug("::PUSH: "); + } + else + { + + //Common.SendToDebug("::PUSH: " + Param.GetType()); + } + + LSLStack.Push(Param); + } + public void ADD(UInt32 Param) + { + Common.SendToDebug("::ADD: " + Param); + object o2 = LSLStack.Pop(); + object o1 = LSLStack.Pop(); + Common.SendToDebug("::ADD: Debug: o1: " + o1.GetType() + " (" + o1.ToString() + "), o2: " + o2.GetType() + " (" + o2.ToString() + ")"); + if (o2.GetType() == typeof(string)) + { + LSLStack.Push((string)o1 + (string)o2); + return; + } + if (o2.GetType() == typeof(UInt32)) + { + LSLStack.Push((UInt32)o1 + (UInt32)o2); + return; + } + + } + public void SUB(UInt32 Param) + { + Common.SendToDebug("::SUB: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 - i2)); + } + public void MUL(UInt32 Param) + { + Common.SendToDebug("::SUB: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 * i2)); + } + public void DIV(UInt32 Param) + { + Common.SendToDebug("::DIV: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 / i2)); + } + + + public void MOD(UInt32 Param) + { + Common.SendToDebug("::MOD: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 % i2)); + } + public void EQ(UInt32 Param) + { + Common.SendToDebug("::EQ: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + if (i1 == i2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + public void NEQ(UInt32 Param) + { + Common.SendToDebug("::NEQ: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + if (i1 != i2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + public void LEQ(UInt32 Param) + { + Common.SendToDebug("::LEQ: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + if (i1 <= i2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + public void GEQ(UInt32 Param) + { + Common.SendToDebug("::GEQ: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + if (i1 >= i2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + public void LESS(UInt32 Param) + { + Common.SendToDebug("::LESS: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + if (i1 < i2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + public void GREATER(UInt32 Param) + { + Common.SendToDebug("::GREATER: " + Param); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + if (i1 > i2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + + + + public void BITAND() + { + Common.SendToDebug("::BITAND"); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 & i2)); + } + public void BITOR() + { + Common.SendToDebug("::BITOR"); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 | i2)); + } + public void BITXOR() + { + Common.SendToDebug("::BITXOR"); + UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 ^ i2)); + } + public void BOOLAND() + { + Common.SendToDebug("::BOOLAND"); + bool b2 = bool.Parse((string)LSLStack.Pop()); + bool b1 = bool.Parse((string)LSLStack.Pop()); + if (b1 && b2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + } + public void BOOLOR() + { + Common.SendToDebug("::BOOLOR"); + bool b2 = bool.Parse((string)LSLStack.Pop()); + bool b1 = bool.Parse((string)LSLStack.Pop()); + + if (b1 || b2) + { + LSLStack.Push((UInt32)1); + } + else + { + LSLStack.Push((UInt32)0); + } + + } + public void NEG(UInt32 Param) + { + Common.SendToDebug("::NEG: " + Param); + //UInt32 i2 = (UInt32)LSLStack.Pop(); + UInt32 i1 = (UInt32)LSLStack.Pop(); + LSLStack.Push((UInt32)(i1 * -1)); + } + public void BITNOT() + { + //Common.SendToDebug("::BITNOT"); + //UInt32 i2 = (UInt32)LSLStack.Pop(); + //UInt32 i1 = (UInt32)LSLStack.Pop(); + //LSLStack.Push((UInt32)(i1 / i2)); + } + public void BOOLNOT() + { + //Common.SendToDebug("::BOOLNOT"); + ////UInt32 i2 = (UInt32)LSLStack.Pop(); + //UInt32 i1 = (UInt32)LSLStack.Pop(); + //LSLStack.Push((UInt32)(i1)); + } + + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_CLRInterface.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_CLRInterface.cs new file mode 100644 index 0000000000..84cb20c1a8 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_CLRInterface.cs @@ -0,0 +1,79 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public class LSL_CLRInterface + { + public interface LSLScript + { + //public virtual void Run(object arg) + //{ + //} + //void Run(object arg); + + //void event_state_entry(object arg); + //void event_state_exit(); + //void event_touch_start(object arg); + //void event_touch(); + //void event_touch_end(); + //void event_collision_start(); + //void event_collision(); + //void event_collision_end(); + //void event_land_collision_start(); + //void event_land_collision(); + //void event_land_collision_end(); + //void event_timer(); + //void event_listen(); + //void event_on_rez(); + //void event_sensor(); + //void event_no_sensor(); + //void event_control(); + //void event_money(); + //void event_email(); + //void event_at_target(); + //void event_not_at_target(); + //void event_at_rot_target(); + //void event_not_at_rot_target(); + //void event_run_time_permissions(); + //void event_changed(); + //void event_attach(); + //void event_dataserver(); + //void event_link_message(); + //void event_moving_start(); + //void event_moving_end(); + //void event_object_rez(); + //void event_remote_data(); + //void event_http_response(); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_OPCODE_IL_processor.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_OPCODE_IL_processor.cs new file mode 100644 index 0000000000..8836195450 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSL_OPCODE_IL_processor.cs @@ -0,0 +1,435 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Reflection.Emit; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + partial class LSO_Parser + { + //internal Stack ILStack = new Stack(); + //LSO_Enums MyLSO_Enums = new LSO_Enums(); + + internal bool LSL_PROCESS_OPCODE(ILGenerator il) + { + + byte bp1; + UInt32 u32p1; + float fp1; + UInt16 opcode = br_read(1)[0]; + Common.SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table)opcode).ToString()); + string idesc = ((LSO_Enums.Operation_Table)opcode).ToString(); + switch ((LSO_Enums.Operation_Table)opcode) + { + + /*************** + * IMPLEMENTED * + ***************/ + case LSO_Enums.Operation_Table.NOOP: + break; + case LSO_Enums.Operation_Table.PUSHSP: + // Push Stack Top (Memory Address) to stack + Common.SendToDebug("Instruction " + idesc); + Common.SendToDebug("Instruction " + idesc + ": Description: Pushing Stack Top (Memory Address from header) to stack"); + IL_Push(il, (UInt32)myHeader.SP); + break; + // BYTE + case LSO_Enums.Operation_Table.PUSHARGB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + // INTEGER + case LSO_Enums.Operation_Table.PUSHARGI: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + u32p1); + IL_Push(il, u32p1); + break; + // FLOAT + case LSO_Enums.Operation_Table.PUSHARGF: + fp1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + fp1); + IL_Push(il, fp1); + break; + // STRING + case LSO_Enums.Operation_Table.PUSHARGS: + string s = Read_String(); + Common.SendToDebug("Instruction " + idesc + ", Param1: " + s); + IL_Debug(il, "OPCODE: " + idesc + ":" + s); + IL_Push(il, s); + break; + // VECTOR z,y,x + case LSO_Enums.Operation_Table.PUSHARGV: + LSO_Enums.Vector v = new LSO_Enums.Vector(); + v.Z = BitConverter.ToUInt32(br_read(4), 0); + v.Y = BitConverter.ToUInt32(br_read(4), 0); + v.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 Z: " + v.Z); + Common.SendToDebug("Param1 Y: " + v.Y); + Common.SendToDebug("Param1 X: " + v.X); + IL_Push(il, v); + break; + // ROTATION s,z,y,x + case LSO_Enums.Operation_Table.PUSHARGQ: + LSO_Enums.Rotation r = new LSO_Enums.Rotation(); + r.S = BitConverter.ToUInt32(br_read(4), 0); + r.Z = BitConverter.ToUInt32(br_read(4), 0); + r.Y = BitConverter.ToUInt32(br_read(4), 0); + r.X = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1 S: " + r.S); + Common.SendToDebug("Param1 Z: " + r.Z); + Common.SendToDebug("Param1 Y: " + r.Y); + Common.SendToDebug("Param1 X: " + r.X); + IL_Push(il, r); + break; + + case LSO_Enums.Operation_Table.PUSHE: + IL_Push(il, (UInt32)0); + break; + + case LSO_Enums.Operation_Table.PUSHARGE: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1); + //IL_Push(il, new string(" ".ToCharArray()[0], Convert.ToInt32(u32p1))); + IL_Push(il, u32p1); + break; + // BYTE + case LSO_Enums.Operation_Table.ADD: + case LSO_Enums.Operation_Table.SUB: + case LSO_Enums.Operation_Table.MUL: + case LSO_Enums.Operation_Table.DIV: + case LSO_Enums.Operation_Table.EQ: + case LSO_Enums.Operation_Table.NEQ: + case LSO_Enums.Operation_Table.LEQ: + case LSO_Enums.Operation_Table.GEQ: + case LSO_Enums.Operation_Table.LESS: + case LSO_Enums.Operation_Table.GREATER: + case LSO_Enums.Operation_Table.NEG: + case LSO_Enums.Operation_Table.MOD: + bp1 = br_read(1)[0]; + Common.SendToDebug("Param1: " + bp1); + IL_CallBaseFunction(il, idesc, (UInt32)bp1); + break; + + // NO ARGUMENTS + case LSO_Enums.Operation_Table.BITAND: + case LSO_Enums.Operation_Table.BITOR: + case LSO_Enums.Operation_Table.BITXOR: + case LSO_Enums.Operation_Table.BOOLAND: + case LSO_Enums.Operation_Table.BOOLOR: + case LSO_Enums.Operation_Table.BITNOT: + case LSO_Enums.Operation_Table.BOOLNOT: + IL_CallBaseFunction(il, idesc); + break; + // SHORT + case LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE: + // TODO: What is size of short? + UInt16 U16p1 = BitConverter.ToUInt16(br_read(2), 0); + Common.SendToDebug("Instruction " + idesc + ": Builtin Command: " + ((LSO_Enums.BuiltIn_Functions)U16p1).ToString()); + //Common.SendToDebug("Param1: " + U16p1); + string fname = ((LSO_Enums.BuiltIn_Functions)U16p1).ToString(); + + bool cmdFound = false; + foreach (MethodInfo mi in typeof(LSL_BuiltIn_Commands_Interface).GetMethods()) + { + // Found command + if (mi.Name == fname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("GetLSL_BuiltIn", new Type[] { })); + // Pop required number of items from my stack to .Net stack + IL_PopToStack(il, mi.GetParameters().Length); + il.Emit(OpCodes.Callvirt, mi); + cmdFound = true; + break; + } + } + if (cmdFound == false) + { + Common.SendToDebug("ERROR: UNABLE TO LOCATE OPCODE " + idesc + " IN BASECLASS"); + } + + break; + + // RETURN + case LSO_Enums.Operation_Table.RETURN: + + Common.SendToDebug("OPCODE: RETURN"); + return true; + + case LSO_Enums.Operation_Table.POP: + case LSO_Enums.Operation_Table.POPS: + case LSO_Enums.Operation_Table.POPL: + case LSO_Enums.Operation_Table.POPV: + case LSO_Enums.Operation_Table.POPQ: + // Pops a specific datatype from the stack + // We just ignore the datatype for now + IL_Pop(il); + break; + + // LONG + case LSO_Enums.Operation_Table.STORE: + case LSO_Enums.Operation_Table.STORES: + case LSO_Enums.Operation_Table.STOREL: + case LSO_Enums.Operation_Table.STOREV: + case LSO_Enums.Operation_Table.STOREQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + break; + + case LSO_Enums.Operation_Table.STOREG: + case LSO_Enums.Operation_Table.STOREGS: + case LSO_Enums.Operation_Table.STOREGL: + case LSO_Enums.Operation_Table.STOREGV: + case LSO_Enums.Operation_Table.STOREGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToGlobal", u32p1); + break; + + case LSO_Enums.Operation_Table.LOADP: + case LSO_Enums.Operation_Table.LOADSP: + case LSO_Enums.Operation_Table.LOADLP: + case LSO_Enums.Operation_Table.LOADVP: + case LSO_Enums.Operation_Table.LOADQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToLocal", u32p1); + IL_Pop(il); + break; + + case LSO_Enums.Operation_Table.LOADGP: + case LSO_Enums.Operation_Table.LOADGSP: + case LSO_Enums.Operation_Table.LOADGLP: + case LSO_Enums.Operation_Table.LOADGVP: + case LSO_Enums.Operation_Table.LOADGQP: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "StoreToStatic", u32p1 - 6 + myHeader.GVR); + IL_Pop(il); + break; + + // PUSH FROM LOCAL FRAME + case LSO_Enums.Operation_Table.PUSH: + case LSO_Enums.Operation_Table.PUSHS: + case LSO_Enums.Operation_Table.PUSHL: + case LSO_Enums.Operation_Table.PUSHV: + case LSO_Enums.Operation_Table.PUSHQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromLocal", u32p1); + + break; + + // PUSH FROM STATIC FRAME + case LSO_Enums.Operation_Table.PUSHG: + case LSO_Enums.Operation_Table.PUSHGS: + case LSO_Enums.Operation_Table.PUSHGL: + case LSO_Enums.Operation_Table.PUSHGV: + case LSO_Enums.Operation_Table.PUSHGQ: + u32p1 = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Param1: " + u32p1.ToString()); + IL_CallBaseFunction(il, "GetFromStatic", u32p1 - 6 + myHeader.GVR); + break; + + + /*********************** + * NOT IMPLEMENTED YET * + ***********************/ + + + + case LSO_Enums.Operation_Table.POPIP: + case LSO_Enums.Operation_Table.POPSP: + case LSO_Enums.Operation_Table.POPSLR: + case LSO_Enums.Operation_Table.POPARG: + case LSO_Enums.Operation_Table.POPBP: + //Common.SendToDebug("Instruction " + idesc + ": Ignored"); + Common.SendToDebug("Instruction " + idesc + ": Description: Drop x bytes from the stack (TODO: Only popping 1)"); + //Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + IL_Pop(il); + break; + + + + // None + case LSO_Enums.Operation_Table.PUSHIP: + // PUSH INSTRUCTION POINTER + break; + case LSO_Enums.Operation_Table.PUSHBP: + + case LSO_Enums.Operation_Table.PUSHEV: + break; + case LSO_Enums.Operation_Table.PUSHEQ: + break; + + + // LONG + case LSO_Enums.Operation_Table.JUMP: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE, LONG + case LSO_Enums.Operation_Table.JUMPIF: + case LSO_Enums.Operation_Table.JUMPNIF: + Common.SendToDebug("Param1: " + br_read(1)[0]); + Common.SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // LONG + case LSO_Enums.Operation_Table.STATE: + bp1 = br_read(1)[0]; + //il.Emit(OpCodes.Ld); // Load local variable 0 onto stack + //il.Emit(OpCodes.Ldc_I4, 0); // Push index position + //il.Emit(OpCodes.Ldstr, EventList[p1]); // Push value + //il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + break; + case LSO_Enums.Operation_Table.CALL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + Common.SendToDebug("ERROR: Function CALL not implemented yet."); + break; + // BYTE + case LSO_Enums.Operation_Table.CAST: + bp1 = br_read(1)[0]; + Common.SendToDebug("Instruction " + idesc + ": Cast to type: " + ((LSO_Enums.OpCode_Cast_TypeDefs)bp1)); + Common.SendToDebug("Param1: " + bp1); + switch ((LSO_Enums.OpCode_Cast_TypeDefs)bp1) + { + case LSO_Enums.OpCode_Cast_TypeDefs.String: + Common.SendToDebug("Instruction " + idesc + ": il.Emit(OpCodes.Box, ILStack.Pop());"); + break; + default: + Common.SendToDebug("Instruction " + idesc + ": Unknown cast type!"); + break; + } + break; + // LONG + case LSO_Enums.Operation_Table.STACKTOS: + case LSO_Enums.Operation_Table.STACKTOL: + Common.SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4), 0)); + break; + // BYTE + case LSO_Enums.Operation_Table.PRINT: + case LSO_Enums.Operation_Table.CALLLIB: + Common.SendToDebug("Param1: " + br_read(1)[0]); + break; + } + return false; + } + + private void IL_PopToStack(ILGenerator il) + { + IL_PopToStack(il, 1); + } + private void IL_PopToStack(ILGenerator il, int count) + { + Common.SendToDebug("IL_PopToStack();"); + for (int i = 0; i < count; i++) + { + IL_CallBaseFunction(il, "POPToStack"); + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Call, + // typeof(LSL_BaseClass).GetMethod("POPToStack", + // new Type[] { })); + } + } + private void IL_Pop(ILGenerator il) + { + Common.SendToDebug("IL_Pop();"); + IL_CallBaseFunction(il, "POP"); + } + private void IL_Debug(ILGenerator il, string text) + { + il.Emit(OpCodes.Ldstr, text); + il.Emit(OpCodes.Call, typeof(Common).GetMethod("SendToDebug", + new Type[] { typeof(string) } + )); + } + private void IL_CallBaseFunction(ILGenerator il, string methodname) + { + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod(methodname, new Type[] { })); + } + private void IL_CallBaseFunction(ILGenerator il, string methodname, object data) + { + il.Emit(OpCodes.Ldarg_0); + if (data.GetType() == typeof(string)) + il.Emit(OpCodes.Ldstr, (string)data); + if (data.GetType() == typeof(UInt32)) + il.Emit(OpCodes.Ldc_I4, (UInt32)data); + il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod(methodname, new Type[] { data.GetType() })); + } + + private void IL_Push(ILGenerator il, object data) + { + il.Emit(OpCodes.Ldarg_0); + Common.SendToDebug("PUSH datatype: " + data.GetType()); + + IL_PushDataTypeToILStack(il, data); + + il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("PUSH", new Type[] { data.GetType() })); + + } + + private void IL_PushDataTypeToILStack(ILGenerator il, object data) + { + if (data.GetType() == typeof(UInt16)) + { + il.Emit(OpCodes.Ldc_I4, (UInt16)data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof(UInt32)) + { + il.Emit(OpCodes.Ldc_I4, (UInt32)data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof(Int32)) + { + il.Emit(OpCodes.Ldc_I4, (Int32)data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof(float)) + { + il.Emit(OpCodes.Ldc_I4, (float)data); + il.Emit(OpCodes.Box, data.GetType()); + } + if (data.GetType() == typeof(string)) + il.Emit(OpCodes.Ldstr, (string)data); + //if (data.GetType() == typeof(LSO_Enums.Rotation)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Rotation)data); + //if (data.GetType() == typeof(LSO_Enums.Vector)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Vector)data); + //if (data.GetType() == typeof(LSO_Enums.Key)) + // il.Emit(OpCodes.Ldobj, (LSO_Enums.Key)data); + + } + + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Enums.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Enums.cs new file mode 100644 index 0000000000..f3eef3dbc9 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Enums.cs @@ -0,0 +1,557 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + public static class LSO_Enums + { + //public System.Collections.Generic.Dictionary OpCode_Add_Types; + + //LSO_Enums() { + // OpCode_Add_Types.Add(51, typeof(String)); + // OpCode_Add_Types.Add(17, typeof(UInt32)); + //} + + [Serializable] + public enum OpCode_Add_TypeDefs + { + String = 51, + UInt32 = 17 + } + [Serializable] + public enum OpCode_Cast_TypeDefs + { + String = 19 + } + + [Serializable] + public struct Key + { + public string KeyString; + } + + [Serializable] + public struct Vector + { + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + [Serializable] + public struct Rotation + { + public UInt32 S; + public UInt32 Z; + public UInt32 Y; + public UInt32 X; + } + [Serializable] + public enum Variable_Type_Codes + { + Void = 0, + Integer = 1, + Float = 2, + String = 3, + Key = 4, + Vector = 5, + Rotation = 6, + List = 7, + Null = 8 + } + [Serializable] + public enum Event_Mask_Values + { + state_entry = 0, + state_exit = 1, + touch_start = 2, + touch = 3, + touch_end = 4, + collision_start = 5, + collision = 6, + collision_end = 7, + land_collision_start = 8, + land_collision = 9, + land_collision_end = 10, + timer = 11, + listen = 12, + on_rez = 13, + sensor = 14, + no_sensor = 15, + control = 16, + money = 17, + email = 18, + at_target = 19, + not_at_target = 20, + at_rot_target = 21, + not_at_rot_target = 22, + run_time_permissions = 23, + changed = 24, + attach = 25, + dataserver = 26, + link_message = 27, + moving_start = 28, + moving_end = 29, + object_rez = 30, + remote_data = 31, + http_response = 32 + } + [Serializable] + public enum Operation_Table + { + NOOP = 0x0, + POP = 0x1, + POPS = 0x2, + POPL = 0x3, + POPV = 0x4, + POPQ = 0x5, + POPARG = 0x6, + POPIP = 0x7, + POPBP = 0x8, + POPSP = 0x9, + POPSLR = 0xa, + DUP = 0x20, + DUPS = 0x21, + DUPL = 0x22, + DUPV = 0x23, + DUPQ = 0x24, + STORE = 0x30, + STORES = 0x31, + STOREL = 0x32, + STOREV = 0x33, + STOREQ = 0x34, + STOREG = 0x35, + STOREGS = 0x36, + STOREGL = 0x37, + STOREGV = 0x38, + STOREGQ = 0x39, + LOADP = 0x3a, + LOADSP = 0x3b, + LOADLP = 0x3c, + LOADVP = 0x3d, + LOADQP = 0x3e, + LOADGP = 0x3f, + LOADGSP = 0x40, + LOADGLP = 0x41, + LOADGVP = 0x42, + LOADGQP = 0x43, + PUSH = 0x50, + PUSHS = 0x51, + PUSHL = 0x52, + PUSHV = 0x53, + PUSHQ = 0x54, + PUSHG = 0x55, + PUSHGS = 0x56, + PUSHGL = 0x57, + PUSHGV = 0x58, + PUSHGQ = 0x59, + PUSHIP = 0x5a, + PUSHBP = 0x5b, + PUSHSP = 0x5c, + PUSHARGB = 0x5d, + PUSHARGI = 0x5e, + PUSHARGF = 0x5f, + PUSHARGS = 0x60, + PUSHARGV = 0x61, + PUSHARGQ = 0x62, + PUSHE = 0x63, + PUSHEV = 0x64, + PUSHEQ = 0x65, + PUSHARGE = 0x66, + ADD = 0x70, + SUB = 0x71, + MUL = 0x72, + DIV = 0x73, + MOD = 0x74, + EQ = 0x75, + NEQ = 0x76, + LEQ = 0x77, + GEQ = 0x78, + LESS = 0x79, + GREATER = 0x7a, + BITAND = 0x7b, + BITOR = 0x7c, + BITXOR = 0x7d, + BOOLAND = 0x7e, + BOOLOR = 0x7f, + NEG = 0x80, + BITNOT = 0x81, + BOOLNOT = 0x82, + JUMP = 0x90, + JUMPIF = 0x91, + JUMPNIF = 0x92, + STATE = 0x93, + CALL = 0x94, + RETURN = 0x95, + CAST = 0xa0, + STACKTOS = 0xb0, + STACKTOL = 0xb1, + PRINT = 0xc0, + CALLLIB = 0xd0, + CALLLIB_TWO_BYTE = 0xd1, + SHL = 0xe0, + SHR = 0xe1 + } + [Serializable] + public enum BuiltIn_Functions + { + llSin = 0, + llCos = 1, + llTan = 2, + llAtan2 = 3, + llSqrt = 4, + llPow = 5, + llAbs = 6, + llFabs = 7, + llFrand = 8, + llFloor = 9, + llCeil = 10, + llRound = 11, + llVecMag = 12, + llVecNorm = 13, + llVecDist = 14, + llRot2Euler = 15, + llEuler2Rot = 16, + llAxes2Rot = 17, + llRot2Fwd = 18, + llRot2Left = 19, + llRot2Up = 20, + llRotBetween = 21, + llWhisper = 22, + llSay = 23, + llShout = 24, + llListen = 25, + llListenControl = 26, + llListenRemove = 27, + llSensor = 28, + llSensorRepeat = 29, + llSensorRemove = 30, + llDetectedName = 31, + llDetectedKey = 32, + llDetectedOwner = 33, + llDetectedType = 34, + llDetectedPos = 35, + llDetectedVel = 36, + llDetectedGrab = 37, + llDetectedRot = 38, + llDetectedGroup = 39, + llDetectedLinkNumber = 40, + llDie = 41, + llGround = 42, + llCloud = 43, + llWind = 44, + llSetStatus = 45, + llGetStatus = 46, + llSetScale = 47, + llGetScale = 48, + llSetColor = 49, + llGetAlpha = 50, + llSetAlpha = 51, + llGetColor = 52, + llSetTexture = 53, + llScaleTexture = 54, + llOffsetTexture = 55, + llRotateTexture = 56, + llGetTexture = 57, + llSetPos = 58, + llGetPos = 59, + llGetLocalPos = 60, + llSetRot = 61, + llGetRot = 62, + llGetLocalRot = 63, + llSetForce = 64, + llGetForce = 65, + llTarget = 66, + llTargetRemove = 67, + llRotTarget = 68, + llRotTargetRemove = 69, + llMoveToTarget = 70, + llStopMoveToTarget = 71, + llApplyImpulse = 72, + llApplyRotationalImpulse = 73, + llSetTorque = 74, + llGetTorque = 75, + llSetForceAndTorque = 76, + llGetVel = 77, + llGetAccel = 78, + llGetOmega = 79, + llGetTimeOfDay = 80, + llGetWallclock = 81, + llGetTime = 82, + llResetTime = 83, + llGetAndResetTime = 84, + llSound = 85, + llPlaySound = 86, + llLoopSound = 87, + llLoopSoundMaster = 88, + llLoopSoundSlave = 89, + llPlaySoundSlave = 90, + llTriggerSound = 91, + llStopSound = 92, + llPreloadSound = 93, + llGetSubString = 94, + llDeleteSubString = 95, + llInsertString = 96, + llToUpper = 97, + llToLower = 98, + llGiveMoney = 99, + llMakeExplosion = 100, + llMakeFountain = 101, + llMakeSmoke = 102, + llMakeFire = 103, + llRezObject = 104, + llLookAt = 105, + llStopLookAt = 106, + llSetTimerEvent = 107, + llSleep = 108, + llGetMass = 109, + llCollisionFilter = 110, + llTakeControls = 111, + llReleaseControls = 112, + llAttachToAvatar = 113, + llDetachFromAvatar = 114, + llTakeCamera = 115, + llReleaseCamera = 116, + llGetOwner = 117, + llInstantMessage = 118, + llEmail = 119, + llGetNextEmail = 120, + llGetKey = 121, + llSetBuoyancy = 122, + llSetHoverHeight = 123, + llStopHover = 124, + llMinEventDelay = 125, + llSoundPreload = 126, + llRotLookAt = 127, + llStringLength = 128, + llStartAnimation = 129, + llStopAnimation = 130, + llPointAt = 131, + llStopPointAt = 132, + llTargetOmega = 133, + llGetStartParameter = 134, + llGodLikeRezObject = 135, + llRequestPermissions = 136, + llGetPermissionsKey = 137, + llGetPermissions = 138, + llGetLinkNumber = 139, + llSetLinkColor = 140, + llCreateLink = 141, + llBreakLink = 142, + llBreakAllLinks = 143, + llGetLinkKey = 144, + llGetLinkName = 145, + llGetInventoryNumber = 146, + llGetInventoryName = 147, + llSetScriptState = 148, + llGetEnergy = 149, + llGiveInventory = 150, + llRemoveInventory = 151, + llSetText = 152, + llWater = 153, + llPassTouches = 154, + llRequestAgentData = 155, + llRequestInventoryData = 156, + llSetDamage = 157, + llTeleportAgentHome = 158, + llModifyLand = 159, + llCollisionSound = 160, + llCollisionSprite = 161, + llGetAnimation = 162, + llResetScript = 163, + llMessageLinked = 164, + llPushObject = 165, + llPassCollisions = 166, + llGetScriptName = 167, + llGetNumberOfSides = 168, + llAxisAngle2Rot = 169, + llRot2Axis = 170, + llRot2Angle = 171, + llAcos = 172, + llAsin = 173, + llAngleBetween = 174, + llGetInventoryKey = 175, + llAllowInventoryDrop = 176, + llGetSunDirection = 177, + llGetTextureOffset = 178, + llGetTextureScale = 179, + llGetTextureRot = 180, + llSubStringIndex = 181, + llGetOwnerKey = 182, + llGetCenterOfMass = 183, + llListSort = 184, + llGetListLength = 185, + llList2Integer = 186, + llList2Float = 187, + llList2String = 188, + llList2Key = 189, + llList2Vector = 190, + llList2Rot = 191, + llList2List = 192, + llDeleteSubList = 193, + llGetListEntryType = 194, + llList2CSV = 195, + llCSV2List = 196, + llListRandomize = 197, + llList2ListStrided = 198, + llGetRegionCorner = 199, + llListInsertList = 200, + llListFindList = 201, + llGetObjectName = 202, + llSetObjectName = 203, + llGetDate = 204, + llEdgeOfWorld = 205, + llGetAgentInfo = 206, + llAdjustSoundVolume = 207, + llSetSoundQueueing = 208, + llSetSoundRadius = 209, + llKey2Name = 210, + llSetTextureAnim = 211, + llTriggerSoundLimited = 212, + llEjectFromLand = 213, + llParseString2List = 214, + llOverMyLand = 215, + llGetLandOwnerAt = 216, + llGetNotecardLine = 217, + llGetAgentSize = 218, + llSameGroup = 219, + llUnSit = 220, + llGroundSlope = 221, + llGroundNormal = 222, + llGroundContour = 223, + llGetAttached = 224, + llGetFreeMemory = 225, + llGetRegionName = 226, + llGetRegionTimeDilation = 227, + llGetRegionFPS = 228, + llParticleSystem = 229, + llGroundRepel = 230, + llGiveInventoryList = 231, + llSetVehicleType = 232, + llSetVehicleFloatParam = 233, + llSetVehicleVectorParam = 234, + llSetVehicleRotationParam = 235, + llSetVehicleFlags = 236, + llRemoveVehicleFlags = 237, + llSitTarget = 238, + llAvatarOnSitTarget = 239, + llAddToLandPassList = 240, + llSetTouchText = 241, + llSetSitText = 242, + llSetCameraEyeOffset = 243, + llSetCameraAtOffset = 244, + llDumpList2String = 245, + llScriptDanger = 246, + llDialog = 247, + llVolumeDetect = 248, + llResetOtherScript = 249, + llGetScriptState = 250, + llRemoteLoadScript = 251, + llSetRemoteScriptAccessPin = 252, + llRemoteLoadScriptPin = 253, + llOpenRemoteDataChannel = 254, + llSendRemoteData = 255, + llRemoteDataReply = 256, + llCloseRemoteDataChannel = 257, + llMD5String = 258, + llSetPrimitiveParams = 259, + llStringToBase64 = 260, + llBase64ToString = 261, + llXorBase64Strings = 262, + llRemoteDataSetRegion = 263, + llLog10 = 264, + llLog = 265, + llGetAnimationList = 266, + llSetParcelMusicURL = 267, + llGetRootPosition = 268, + llGetRootRotation = 269, + llGetObjectDesc = 270, + llSetObjectDesc = 271, + llGetCreator = 272, + llGetTimestamp = 273, + llSetLinkAlpha = 274, + llGetNumberOfPrims = 275, + llGetNumberOfNotecardLines = 276, + llGetBoundingBox = 277, + llGetGeometricCenter = 278, + llGetPrimitiveParams = 279, + llIntegerToBase64 = 280, + llBase64ToInteger = 281, + llGetGMTclock = 282, + llGetSimulatorHostname = 283, + llSetLocalRot = 284, + llParseStringKeepNulls = 285, + llRezAtRoot = 286, + llGetObjectPermMask = 287, + llSetObjectPermMask = 288, + llGetInventoryPermMask = 289, + llSetInventoryPermMask = 290, + llGetInventoryCreator = 291, + llOwnerSay = 292, + llRequestSimulatorData = 293, + llForceMouselook = 294, + llGetObjectMass = 295, + llListReplaceList = 296, + llLoadURL = 297, + llParcelMediaCommandList = 298, + llParcelMediaQuery = 299, + llModPow = 300, + llGetInventoryType = 301, + llSetPayPrice = 302, + llGetCameraPos = 303, + llGetCameraRot = 304, + llSetPrimURL = 305, + llRefreshPrimURL = 306, + llEscapeURL = 307, + llUnescapeURL = 308, + llMapDestination = 309, + llAddToLandBanList = 310, + llRemoveFromLandPassList = 311, + llRemoveFromLandBanList = 312, + llSetCameraParams = 313, + llClearCameraParams = 314, + llListStatistics = 315, + llGetUnixTime = 316, + llGetParcelFlags = 317, + llGetRegionFlags = 318, + llXorBase64StringsCorrect = 319, + llHTTPRequest = 320, + llResetLandBanList = 321, + llResetLandPassList = 322, + llGetParcelPrimCount = 323, + llGetParcelPrimOwners = 324, + llGetObjectPrimCount = 325, + llGetParcelMaxPrims = 326, + llGetParcelDetails = 327 + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Parser.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Parser.cs new file mode 100644 index 0000000000..b486c46bc0 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Parser.cs @@ -0,0 +1,722 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + partial class LSO_Parser + { + private string FileName; + private FileStream fs; + private BinaryReader br; + internal LSO_Struct.Header myHeader; + internal Dictionary StaticBlocks = new Dictionary(); + //private System.Collections.Hashtable StaticBlocks = new System.Collections.Hashtable(); + + private TypeBuilder typeBuilder; + private System.Collections.Generic.List EventList = new System.Collections.Generic.List(); + + public LSO_Parser(string _FileName, TypeBuilder _typeBuilder) + { + FileName = _FileName; + typeBuilder = _typeBuilder; + } + + internal void OpenFile() + { + // Open + Common.SendToDebug("Opening filename: " + FileName); + fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); + br = new BinaryReader(fs, Encoding.BigEndianUnicode); + + } + internal void CloseFile() + { + + // Close + br.Close(); + fs.Close(); + } + + + /// + /// Parse LSO file. + /// + public void Parse() + { + + + + // The LSO Format consist of 6 major blocks: header, statics, functions, states, heap, and stack. + + + // HEADER BLOCK + Common.SendToDebug("Reading HEADER BLOCK at: 0"); + fs.Seek(0, SeekOrigin.Begin); + myHeader = new LSO_Struct.Header(); + myHeader.TM = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.VN = BitConverter.ToUInt32(br_read(4), 0); + myHeader.BP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.HP = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NS = BitConverter.ToUInt32(br_read(4), 0); + myHeader.CE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.IE = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ER = BitConverter.ToUInt32(br_read(4), 0); + myHeader.FR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SLR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GVR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.GFR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.PR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.ESR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.SR = BitConverter.ToUInt32(br_read(4), 0); + myHeader.NCE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NIE = BitConverter.ToUInt64(br_read(8), 0); + myHeader.NER = BitConverter.ToUInt64(br_read(8), 0); + + // Print Header Block to debug + Common.SendToDebug("TM - Top of memory (size): " + myHeader.TM); + Common.SendToDebug("IP - Instruction Pointer (0=not running): " + myHeader.IP); + Common.SendToDebug("VN - Version number: " + myHeader.VN); + Common.SendToDebug("BP - Local Frame Pointer: " + myHeader.BP); + Common.SendToDebug("SP - Stack Pointer: " + myHeader.SP); + Common.SendToDebug("HR - Heap Register: " + myHeader.HR); + Common.SendToDebug("HP - Heap Pointer: " + myHeader.HP); + Common.SendToDebug("CS - Current State: " + myHeader.CS); + Common.SendToDebug("NS - Next State: " + myHeader.NS); + Common.SendToDebug("CE - Current Events: " + myHeader.CE); + Common.SendToDebug("IE - In Event: " + myHeader.IE); + Common.SendToDebug("ER - Event Register: " + myHeader.ER); + Common.SendToDebug("FR - Fault Register: " + myHeader.FR); + Common.SendToDebug("SLR - Sleep Register: " + myHeader.SLR); + Common.SendToDebug("GVR - Global Variable Register: " + myHeader.GVR); + Common.SendToDebug("GFR - Global Function Register: " + myHeader.GFR); + Common.SendToDebug("PR - Parameter Register: " + myHeader.PR); + Common.SendToDebug("ESR - Energy Supply Register: " + myHeader.ESR); + Common.SendToDebug("SR - State Register: " + myHeader.SR); + Common.SendToDebug("NCE - 64-bit Current Events: " + myHeader.NCE); + Common.SendToDebug("NIE - 64-bit In Events: " + myHeader.NIE); + Common.SendToDebug("NER - 64-bit Event Register: " + myHeader.NER); + Common.SendToDebug("Read position when exiting HEADER BLOCK: " + fs.Position); + + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + myHeader.GVR); + fs.Seek(myHeader.GVR, SeekOrigin.Begin); + int StaticBlockCount = 0; + // Read function blocks until we hit GFR + while (fs.Position < myHeader.GFR) + { + StaticBlockCount++; + long startReadPos = fs.Position; + Common.SendToDebug("Reading Static Block " + StaticBlockCount + " at: " + startReadPos); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + ((LSO_Enums.Variable_Type_Codes)myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies -- what about strings? + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add((UInt32)startReadPos, myStaticBlock); + + } + Common.SendToDebug("Number of Static Blocks read: " + StaticBlockCount); + + + // FUNCTION BLOCK + // Always right after STATIC BLOCK + LSO_Struct.FunctionBlock myFunctionBlock = new LSO_Struct.FunctionBlock(); + if (myHeader.GFR == myHeader.SR) + { + // If GFR and SR are at same position then there is no fuction block + Common.SendToDebug("No FUNCTION BLOCK found"); + } + else + { + Common.SendToDebug("Reading FUNCTION BLOCK at: " + myHeader.GFR); + fs.Seek(myHeader.GFR, SeekOrigin.Begin); + myFunctionBlock.FunctionCount = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Number of functions in Fuction Block: " + myFunctionBlock.FunctionCount); + if (myFunctionBlock.FunctionCount > 0) + { + myFunctionBlock.CodeChunkPointer = new UInt32[myFunctionBlock.FunctionCount]; + for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + { + Common.SendToDebug("Reading function " + i + " at: " + fs.Position); + // TODO: ADD TO FUNCTION LIST (How do we identify it later?) + // Note! Absolute position + myFunctionBlock.CodeChunkPointer[i] = BitConverter.ToUInt32(br_read(4), 0) + myHeader.GFR; + Common.SendToDebug("Fuction " + i + " code chunk position: " + myFunctionBlock.CodeChunkPointer[i]); + } + } + } + + + // STATE FRAME BLOCK + // Always right after FUNCTION BLOCK + Common.SendToDebug("Reading STATE BLOCK at: " + myHeader.SR); + fs.Seek(myHeader.SR, SeekOrigin.Begin); + LSO_Struct.StateFrameBlock myStateFrameBlock = new LSO_Struct.StateFrameBlock(); + myStateFrameBlock.StateCount = BitConverter.ToUInt32(br_read(4), 0); + if (myStateFrameBlock.StateCount > 0) + { + // Initialize array + myStateFrameBlock.StatePointer = new LSO_Struct.StatePointerBlock[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + Common.SendToDebug("Reading STATE POINTER BLOCK " + (i + 1) + " at: " + fs.Position); + // Position is relative to state frame + myStateFrameBlock.StatePointer[i].Location = myHeader.SR + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].EventMask = new System.Collections.BitArray(br_read(8)); + Common.SendToDebug("Pointer: " + myStateFrameBlock.StatePointer[i].Location); + Common.SendToDebug("Total potential EventMask bits: " + myStateFrameBlock.StatePointer[i].EventMask.Count); + + //// Read STATE BLOCK + //long CurPos = fs.Position; + //fs.Seek(CurPos, SeekOrigin.Begin); + + } + } + + + // STATE BLOCK + // For each StateFrameBlock there is one StateBlock with multiple event handlers + + if (myStateFrameBlock.StateCount > 0) + { + // Go through all State Frame Pointers found + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + + fs.Seek(myStateFrameBlock.StatePointer[i].Location, SeekOrigin.Begin); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " at: " + fs.Position); + + // READ: STATE BLOCK HEADER + myStateFrameBlock.StatePointer[i].StateBlock = new LSO_Struct.StateBlock(); + myStateFrameBlock.StatePointer[i].StateBlock.StartPos = (UInt32)fs.Position; // Note + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize = BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.Unknown = br_read(1)[0]; + myStateFrameBlock.StatePointer[i].StateBlock.EndPos = (UInt32)fs.Position; // Note + Common.SendToDebug("State block Start Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.StartPos); + Common.SendToDebug("State block Header Size: " + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize); + Common.SendToDebug("State block Header End Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.EndPos); + + // We need to count number of bits flagged in EventMask? + + + // for each bit in myStateFrameBlock.StatePointer[i].EventMask + + // ADDING TO ALL RIGHT NOW, SHOULD LIMIT TO ONLY THE ONES IN USE + //TODO: Create event hooks + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers = new LSO_Struct.StateBlockHandler[myStateFrameBlock.StatePointer[i].EventMask.Count - 1]; + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + + if (myStateFrameBlock.StatePointer[i].EventMask.Get(ii) == true) + { + // We got an event + // READ: STATE BLOCK HANDLER + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER matching EVENT MASK " + ii + " (" + ((LSO_Enums.Event_Mask_Values)ii).ToString() + ") at: " + fs.Position); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer = myStateFrameBlock.StatePointer[i].StateBlock.EndPos + BitConverter.ToUInt32(br_read(4), 0); + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + ((LSO_Enums.Event_Mask_Values)ii).ToString() + ") Code Chunk Pointer: " + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer); + Common.SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + ((LSO_Enums.Event_Mask_Values)ii).ToString() + ") Call Frame Size: " + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize); + } + } + } + } + + + + + //// READ FUNCTION CODE CHUNKS + //// Functions + Function start pos (GFR) + //// TODO: Somehow be able to identify and reference this + //LSO_Struct.CodeChunk[] myFunctionCodeChunk; + //if (myFunctionBlock.FunctionCount > 0) + //{ + // myFunctionCodeChunk = new LSO_Struct.CodeChunk[myFunctionBlock.FunctionCount]; + // for (int i = 0; i < myFunctionBlock.FunctionCount; i++) + // { + // Common.SendToDebug("Reading Function Code Chunk " + i); + // myFunctionCodeChunk[i] = GetCodeChunk((UInt32)myFunctionBlock.CodeChunkPointer[i]); + // } + + //} + // READ EVENT CODE CHUNKS + LSO_Struct.CodeChunk[] myEventCodeChunk; + if (myStateFrameBlock.StateCount > 0) + { + myEventCodeChunk = new LSO_Struct.CodeChunk[myStateFrameBlock.StateCount]; + for (int i = 0; i < myStateFrameBlock.StateCount; i++) + { + // TODO: Somehow organize events and functions so they can be found again, + // two level search ain't no good + for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) + { + + + if (myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer > 0) + { + Common.SendToDebug("Reading Event Code Chunk state " + i + ", event " + (LSO_Enums.Event_Mask_Values)ii); + + + // Override a Method / Function + string eventname = i + "_event_" + (LSO_Enums.Event_Mask_Values)ii; + Common.SendToDebug("Event Name: " + eventname); + if (Common.IL_ProcessCodeChunks) + { + EventList.Add(eventname); + + // JUMP TO CODE PROCESSOR + ProcessCodeChunk(myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer, typeBuilder, eventname); + } + } + + } + + } + + } + + + + + if (Common.IL_CreateFunctionList) + IL_INSERT_FUNCTIONLIST(); + + } + + internal LSO_Struct.HeapBlock GetHeap(UInt32 pos) + { + // HEAP BLOCK + // TODO:? Special read for strings/keys (null terminated) and lists (pointers to other HEAP entries) + Common.SendToDebug("Reading HEAP BLOCK at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + + LSO_Struct.HeapBlock myHeapBlock = new LSO_Struct.HeapBlock(); + myHeapBlock.DataBlockSize = BitConverter.ToInt32(br_read(4), 0); + myHeapBlock.ObjectType = br_read(1)[0]; + myHeapBlock.ReferenceCount = BitConverter.ToUInt16(br_read(2), 0); + //myHeapBlock.Data = br_read(getObjectSize(myHeapBlock.ObjectType)); + // Don't read it reversed + myHeapBlock.Data = new byte[myHeapBlock.DataBlockSize - 1]; + br.Read(myHeapBlock.Data, 0, myHeapBlock.DataBlockSize - 1); + + + Common.SendToDebug("Heap Block Data Block Size: " + myHeapBlock.DataBlockSize); + Common.SendToDebug("Heap Block ObjectType: " + ((LSO_Enums.Variable_Type_Codes)myHeapBlock.ObjectType).ToString()); + Common.SendToDebug("Heap Block Reference Count: " + myHeapBlock.ReferenceCount); + + return myHeapBlock; + } + private byte[] br_read(int len) + { + if (len <= 0) + return null; + + try + { + byte[] bytes = new byte[len]; + for (int i = len - 1; i > -1; i--) + bytes[i] = br.ReadByte(); + return bytes; + } + catch (Exception e) + { + Common.SendToDebug("Exception: " + e.ToString()); + throw (e); + } + } + //private byte[] br_read_smallendian(int len) + //{ + // byte[] bytes = new byte[len]; + // br.Read(bytes,0, len); + // return bytes; + //} + private Type getLLObjectType(byte objectCode) + { + switch ((LSO_Enums.Variable_Type_Codes)objectCode) + { + case LSO_Enums.Variable_Type_Codes.Void: return typeof(void); + case LSO_Enums.Variable_Type_Codes.Integer: return typeof(UInt32); + case LSO_Enums.Variable_Type_Codes.Float: return typeof(float); + case LSO_Enums.Variable_Type_Codes.String: return typeof(string); + case LSO_Enums.Variable_Type_Codes.Key: return typeof(string); + case LSO_Enums.Variable_Type_Codes.Vector: return typeof(LSO_Enums.Vector); + case LSO_Enums.Variable_Type_Codes.Rotation: return typeof(LSO_Enums.Rotation); + case LSO_Enums.Variable_Type_Codes.List: + Common.SendToDebug("TODO: List datatype not implemented yet!"); + return typeof(System.Collections.ArrayList); + case LSO_Enums.Variable_Type_Codes.Null: + Common.SendToDebug("TODO: Datatype null is not implemented, using string instead.!"); + return typeof(string); + default: + Common.SendToDebug("Lookup of LSL datatype " + objectCode + " to .Net datatype failed: Unknown LSL datatype. Defaulting to object."); + return typeof(object); + } + } + private int getObjectSize(byte ObjectType) + { + switch ((LSO_Enums.Variable_Type_Codes)ObjectType) + { + case LSO_Enums.Variable_Type_Codes.Integer: + case LSO_Enums.Variable_Type_Codes.Float: + case LSO_Enums.Variable_Type_Codes.String: + case LSO_Enums.Variable_Type_Codes.Key: + case LSO_Enums.Variable_Type_Codes.List: + return 4; + case LSO_Enums.Variable_Type_Codes.Vector: + return 12; + case LSO_Enums.Variable_Type_Codes.Rotation: + return 16; + default: + return 0; + } + } + private string Read_String() + { + string ret = ""; + byte reader = br_read(1)[0]; + while (reader != 0x000) + { + ret += (char)reader; + reader = br_read(1)[0]; + } + return ret; + } + + /// + /// Reads a code chunk and creates IL + /// + /// Absolute position in file. REMEMBER TO ADD myHeader.GFR! + /// TypeBuilder for assembly + /// Name of event (function) to generate + private void ProcessCodeChunk(UInt32 pos, TypeBuilder typeBuilder, string eventname) + { + + LSO_Struct.CodeChunk myCodeChunk = new LSO_Struct.CodeChunk(); + + Common.SendToDebug("Reading Function Code Chunk at: " + pos); + fs.Seek(pos, SeekOrigin.Begin); + myCodeChunk.CodeChunkHeaderSize = BitConverter.ToUInt32(br_read(4), 0); + Common.SendToDebug("CodeChunk Header Size: " + myCodeChunk.CodeChunkHeaderSize); + // Read until null + myCodeChunk.Comment = Read_String(); + Common.SendToDebug("Function comment: " + myCodeChunk.Comment); + myCodeChunk.ReturnTypePos = br_read(1)[0]; + myCodeChunk.ReturnType = GetStaticBlock((long)myCodeChunk.ReturnTypePos + (long)myHeader.GVR); + Common.SendToDebug("Return type #" + myCodeChunk.ReturnType.ObjectType + ": " + ((LSO_Enums.Variable_Type_Codes)myCodeChunk.ReturnType.ObjectType).ToString()); + + + // TODO: How to determine number of codechunks -- does this method work? + myCodeChunk.CodeChunkArguments = new System.Collections.Generic.List(); + byte reader = br_read(1)[0]; + reader = br_read(1)[0]; + + // NOTE ON CODE CHUNK ARGUMENTS + // This determins type definition + int ccount = 0; + while (reader != 0x000) + { + ccount++; + Common.SendToDebug("Reading Code Chunk Argument " + ccount); + LSO_Struct.CodeChunkArgument CCA = new LSO_Struct.CodeChunkArgument(); + CCA.FunctionReturnTypePos = reader; + reader = br_read(1)[0]; + CCA.NullString = reader; + CCA.FunctionReturnType = GetStaticBlock(CCA.FunctionReturnTypePos + myHeader.GVR); + myCodeChunk.CodeChunkArguments.Add(CCA); + Common.SendToDebug("Code Chunk Argument " + ccount + " type #" + CCA.FunctionReturnType.ObjectType + ": " + (LSO_Enums.Variable_Type_Codes)CCA.FunctionReturnType.ObjectType); + } + // Create string array + Type[] MethodArgs = new Type[myCodeChunk.CodeChunkArguments.Count]; + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + MethodArgs[_ic] = getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType); + Common.SendToDebug("Method argument " + _ic + ": " + getLLObjectType(myCodeChunk.CodeChunkArguments[_ic].FunctionReturnType.ObjectType).ToString()); + } + // End marker is 0x000 + myCodeChunk.EndMarker = reader; + + + // + // Emit: START OF METHOD (FUNCTION) + // + + Common.SendToDebug("CLR:" + eventname + ":MethodBuilder methodBuilder = typeBuilder.DefineMethod..."); + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof(void), + new Type[] { typeof(object) }); + //MethodArgs); + //typeof(void), //getLLObjectType(myCodeChunk.ReturnType), + // new Type[] { typeof(object) }, //); + + //Common.SendToDebug("CLR:" + eventname + ":typeBuilder.DefineMethodOverride(methodBuilder..."); + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + // Create the IL generator + + Common.SendToDebug("CLR:" + eventname + ":ILGenerator il = methodBuilder.GetILGenerator();"); + ILGenerator il = methodBuilder.GetILGenerator(); + + + if (Common.IL_UseTryCatch) + IL_INSERT_TRY(il, eventname); + + + + // Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //Common.SendToDebug("STARTUP: il.Emit(OpCodes.Ldc_I4_S, 0);"); + + //il.Emit(OpCodes.Ldc_I4_S, 0); + for (int _ic = 0; _ic < myCodeChunk.CodeChunkArguments.Count; _ic++) + { + Common.SendToDebug("PARAMS: il.Emit(OpCodes.Ldarg, " + _ic + ");"); + il.Emit(OpCodes.Ldarg, _ic); + } + + + + // + // CALLING OPCODE PROCESSOR, one command at the time TO GENERATE IL + // + bool FoundRet = false; + while (FoundRet == false) + { + FoundRet = LSL_PROCESS_OPCODE(il); + } + + + if (Common.IL_UseTryCatch) + IL_INSERT_END_TRY(il, eventname); + + // Emit: RETURN FROM METHOD + il.Emit(OpCodes.Ret); + + return; + + } + + private void IL_INSERT_FUNCTIONLIST() + { + + Common.SendToDebug("Creating function list"); + + + string eventname = "GetFunctions"; + + Common.SendToDebug("Creating IL " + eventname); + // Define a private String field. + //FieldBuilder myField = myTypeBuilder.DefineField("EventList", typeof(String[]), FieldAttributes.Public); + + + //FieldBuilder mem = typeBuilder.DefineField("mem", typeof(Array), FieldAttributes.Private); + + + + MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, + MethodAttributes.Public, + typeof(string[]), + null); + + //typeBuilder.DefineMethodOverride(methodBuilder, + // typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); + + ILGenerator il = methodBuilder.GetILGenerator(); + + + + + // IL_INSERT_TRY(il, eventname); + + // // Push string to stack + // il.Emit(OpCodes.Ldstr, "Inside " + eventname); + + //// Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); + //il.Emit(OpCodes.Call, typeof(Console).GetMethod + // ("WriteLine", new Type[] { typeof(string) })); + + //initIL.Emit(OpCodes.Newobj, typeof(string[])); + + //string[] MyArray = new string[2] { "TestItem1" , "TestItem2" }; + + ////il.Emit(OpCodes.Ldarg_0); + + il.DeclareLocal(typeof(string[])); + + ////il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldc_I4, EventList.Count); // Specify array length + il.Emit(OpCodes.Newarr, typeof(String)); // create new string array + il.Emit(OpCodes.Stloc_0); // Store array as local variable 0 in stack + ////SetFunctionList + + for (int lv = 0; lv < EventList.Count; lv++) + { + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + il.Emit(OpCodes.Ldc_I4, lv); // Push index position + il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + il.Emit(OpCodes.Stelem_Ref); // Perform array[index] = value + + //il.Emit(OpCodes.Ldarg_0); + //il.Emit(OpCodes.Ldstr, EventList[lv]); // Push value + //il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("AddFunction", new Type[] { typeof(string) })); + + } + + + + // IL_INSERT_END_TRY(il, eventname); + + + il.Emit(OpCodes.Ldloc_0); // Load local variable 0 onto stack + // il.Emit(OpCodes.Call, typeof(LSL_BaseClass).GetMethod("SetFunctionList", new Type[] { typeof(Array) })); + + il.Emit(OpCodes.Ret); // Return + + } + + + private void IL_INSERT_TRY(ILGenerator il, string eventname) + { + /* + * CLR TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.BeginExceptionBlock()"); + il.BeginExceptionBlock(); + + // Push "Hello World!" string to stack + //Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + //il.Emit(OpCodes.Ldstr, "Starting CLR dynamic execution of: " + eventname); + + } + + private void IL_INSERT_END_TRY(ILGenerator il, string eventname) + { + /* + * CATCH + */ + Common.SendToDebug("CLR:" + eventname + ":il.BeginCatchBlock(typeof(Exception));"); + il.BeginCatchBlock(typeof(Exception)); + + // Push "Hello World!" string to stack + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); + il.Emit(OpCodes.Ldstr, "Execption executing dynamic CLR function " + eventname + ": "); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof(Console).GetMethod + ("Write", new Type[] { typeof(string) })); + + //callvirt instance string [mscorlib]System.Exception::get_Message() + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Callvirt..."); + il.Emit(OpCodes.Callvirt, typeof(Exception).GetMethod + ("get_Message")); + + //call void [mscorlib]System.Console::WriteLine(string) + Common.SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); + il.Emit(OpCodes.Call, typeof(Console).GetMethod + ("WriteLine", new Type[] { typeof(string) })); + + /* + * CLR END TRY + */ + //Common.SendToDebug("CLR:" + eventname + ":il.EndExceptionBlock();"); + il.EndExceptionBlock(); + } + + private LSO_Struct.StaticBlock GetStaticBlock(long pos) + { + long FirstPos = fs.Position; + try + { + UInt32 position = (UInt32)pos; + // STATIC BLOCK + Common.SendToDebug("Reading STATIC BLOCK at: " + position); + fs.Seek(position, SeekOrigin.Begin); + + if (StaticBlocks.ContainsKey(position) == true) + { + Common.SendToDebug("Found cached STATIC BLOCK"); + + + + return StaticBlocks[pos]; + } + + //int StaticBlockCount = 0; + // Read function blocks until we hit GFR + //while (fs.Position < myHeader.GFR) + //{ + //StaticBlockCount++; + + //Common.SendToDebug("Reading Static Block at: " + position); + + //fs.Seek(myHeader.GVR, SeekOrigin.Begin); + LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); + myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); + myStaticBlock.ObjectType = br_read(1)[0]; + Common.SendToDebug("Static Block ObjectType: " + ((LSO_Enums.Variable_Type_Codes)myStaticBlock.ObjectType).ToString()); + myStaticBlock.Unknown = br_read(1)[0]; + // Size of datatype varies + if (myStaticBlock.ObjectType != 0) + myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); + + StaticBlocks.Add(position, myStaticBlock); + //} + Common.SendToDebug("Done reading Static Block."); + return myStaticBlock; + } + finally + { + // Go back to original read pos + fs.Seek(FirstPos, SeekOrigin.Begin); + } + + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Struct.cs b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Struct.cs new file mode 100644 index 0000000000..8ea618c83b --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSO_Struct.cs @@ -0,0 +1,135 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL +{ + static class LSO_Struct + { + + public struct Header + { + public UInt32 TM; + public UInt32 IP; + public UInt32 VN; + public UInt32 BP; + public UInt32 SP; + public UInt32 HR; + public UInt32 HP; + public UInt32 CS; + public UInt32 NS; + public UInt32 CE; + public UInt32 IE; + public UInt32 ER; + public UInt32 FR; + public UInt32 SLR; + public UInt32 GVR; + public UInt32 GFR; + public UInt32 PR; + public UInt32 ESR; + public UInt32 SR; + public UInt64 NCE; + public UInt64 NIE; + public UInt64 NER; + } + + public struct StaticBlock + { + public UInt32 Static_Chunk_Header_Size; + public byte ObjectType; + public byte Unknown; + public byte[] BlockVariable; + } + /* Not actually a structure + public struct StaticBlockVariable + { + public UInt32 Integer1; + public UInt32 Float1; + public UInt32 HeapPointer_String; + public UInt32 HeapPointer_Key; + public byte[] Vector_12; + public byte[] Rotation_16; + public UInt32 Pointer_List_Structure; + } */ + public struct HeapBlock + { + public Int32 DataBlockSize; + public byte ObjectType; + public UInt16 ReferenceCount; + public byte[] Data; + } + public struct StateFrameBlock + { + public UInt32 StateCount; + public StatePointerBlock[] StatePointer; + } + public struct StatePointerBlock + { + public UInt32 Location; + public System.Collections.BitArray EventMask; + public StateBlock StateBlock; + } + public struct StateBlock + { + public UInt32 StartPos; + public UInt32 EndPos; + public UInt32 HeaderSize; + public byte Unknown; + public StateBlockHandler[] StateBlockHandlers; + } + public struct StateBlockHandler + { + public UInt32 CodeChunkPointer; + public UInt32 CallFrameSize; + } + public struct FunctionBlock + { + public UInt32 FunctionCount; + public UInt32[] CodeChunkPointer; + } + public struct CodeChunk + { + public UInt32 CodeChunkHeaderSize; + public string Comment; + public System.Collections.Generic.List CodeChunkArguments; + public byte EndMarker; + public byte ReturnTypePos; + public StaticBlock ReturnType; + } + public struct CodeChunkArgument + { + public byte FunctionReturnTypePos; + public byte NullString; + public StaticBlock FunctionReturnType; + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSOdoc.htm b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSOdoc.htm new file mode 100644 index 0000000000..1f70524870 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/LSOdoc.htm @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OPCODES.txt b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OPCODES.txt new file mode 100644 index 0000000000..50fb26c41c --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OPCODES.txt @@ -0,0 +1,142 @@ +OPCODE IL_Processor Implemented +======================================================== +NOOP * * +POP * * +POPS * * +POPL * * +POPV * * +POPQ * * +POPARG * * +POPIP +POPBP +POPSP +POPSLR +DUP +DUPS +DUPL +DUPV +DUPQ +STORE * * +STORES * * +STOREL * * +STOREV * * +STOREQ * * +STOREG * * +STOREGS * * +STOREGL * * +STOREGV * * +STOREGQ * * +LOADP * * +LOADSP * * +LOADLP * * +LOADVP * * +LOADQP * * +LOADGP * * +LOADGSP * * +LOADGLP * * +LOADGVP * * +LOADGQP * * +PUSH * * +PUSHS * * +PUSHL * * +PUSHV * * +PUSHQ * * +PUSHG * * +PUSHGS * * +PUSHGL * * +PUSHGV * * +PUSHGQ * * +PUSHIP +PUSHBP +PUSHSP * * +PUSHARGB +PUSHARGI * * +PUSHARGF * * +PUSHARGS * * +PUSHARGV +PUSHARGQ +PUSHE * * +PUSHEV +PUSHEQ +PUSHARGE * +ADD * * +SUB * * +MUL * * +DIV * * +MOD * * +EQ * * +NEQ * * +LEQ * * +GEQ * * +LESS * * +GREATER * * +BITAND * * +BITOR * * +BITXOR * * +BOOLAND * * +BOOLOR * * +NEG * * +BITNOT * +BOOLNOT * +JUMP +JUMPIF +JUMPNIF +STATE +CALL +RETURN * * +CAST +STACKTOS +STACKTOL +PRINT +CALLLIB +CALLLIB_TWO_BYTE * * +SHL +SHR + + + + + + + +IN USE: + + + Implemented +NOOP * +26 +ADD * +BITAND * +CALL +CALLLIB_TWO_BYTE +CAST +DUP +EQ * +JUMPNIF +LOADLP +LOADSP +NEQ * +NOOP +POP * +POPBP +POPL +POPS +POPV +PUSH +PUSHARGB +PUSHARGE +PUSHARGF * +PUSHARGI * +PUSHARGS * +PUSHBP +PUSHE +PUSHG +PUSHGS +PUSHL +PUSHS +PUSHSP +RETURN * +STACKTOL +STOREG +STOREGS +STOREL diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.csproj b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.csproj new file mode 100644 index 0000000000..872ca92020 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.csproj @@ -0,0 +1,63 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {E56CB0C4-DBE8-4169-AC21-B6A2E8235A82} + Library + Properties + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.suo b/OpenSim/Region/ScriptEngine/DotNetEngine.Compiler.LSL/OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL.suo new file mode 100644 index 0000000000000000000000000000000000000000..eab36abd86d6edc3d913de3cf4454f2661612d46 GIT binary patch literal 7680 zcmeHM%WsTP6hBjM#-kqfsv7TiX}!A;?X(dI+RRusnbfFinO0_|qUq9KpoB!Mg9Sp;fxn~#q)ytA#-$4@?4C+wM9Sy6XH2y9O85SIuO9e@ zq0`+7cFzV#?2tCu4(a=ltCJ(9A#&PEfI^w-<#fnX0r;}0UOJ)mL1~42a*KpfZUQ$; zg;eJGI$b?qihT4N>cn}ZTk_|KnE?f)X8CLL529KqpK>Rn>{dQ~{D=CUK203w{Hce= z0+#MQ;T zB2`|3bSZe5Dz8Ag61+;4S0h~mu25xKY8`mJDsM!(3A`CxrRr#(A}<+DjPEu3*_h3Bjl)WQ9i@@qaM*srP>a(9gzl zqN|O7PoCfS#xsChdpz>6|MSG$3A{_Bv=5yL`neizwHNUs{@Zah0t{@x>eWjvVlt!R z4*VX%j_9yrBBMbEN_uDXEIes>UbbysdvyJ&YY-ZT45xt=S1*3$Svy-}RAkVH0_$(W zpA8xF%$FtpX#JSx>z7$S3x&_B!X%$(cqgKK-cz)lo%*xA4E#-XG|A`v!HFP0wZ3lk zpN~PmtAS1Od7p72>d!lwUIVB8Y+nrSQymA3|J?sIz<-|jf;jIn$Fp%JCWKSIzwPaT zssJSB&hle{_y51vKYe@P4J92J`o5gHnS1&bdGTNAudzP5>2iWznY-R<+oh6T59)76 zI^K3;_~Q*Vf}0?3vb+h{ch>aE-`e?Zfu +// +// Copyright (c) 2002 Microsoft Corporation. All rights reserved. +// +// The use and distribution terms for this software are contained in the file +// named license.txt, which can be found in the root of this distribution. +// By using this software in any fashion, you are agreeing to be bound by the +// terms of this license. +// +// You must not remove this notice, or any other, from this software. +// +// +//------------------------------------------------------------------------------ + +// The RegexCompiler class is internal to the Regex package. +// It translates a block of RegexCode to MSIL, and creates a +// subclass of the RegexRunner type. +// +#define ECMA + +namespace System.Text.RegularExpressions +{ + + using System.Collections; + using System.Threading; + using System.Reflection; + using System.Reflection.Emit; + using System.Security; + using System.Security.Permissions; + using System.Diagnostics; + using System.Globalization; + + // RegexDynamicModule + // + // Because dynamic modules are expensive and not thread-safe, we create + // one dynamic module per-thread, and cache as much information about it + // as we can. + // + // While we're at it, we just create one RegexCompiler per thread + // as well, and have RegexCompiler inherit from RegexDynamicModule. + internal class RegexDynamicModule + { + internal AssemblyBuilder _assembly; + internal ModuleBuilder _module; + + // fields that never change (making them saves about 6% overall running time) + + internal static FieldInfo _textbegF; + internal static FieldInfo _textendF; + internal static FieldInfo _textstartF; + internal static FieldInfo _textposF; + internal static FieldInfo _textF; + internal static FieldInfo _trackposF; + internal static FieldInfo _trackF; + internal static FieldInfo _stackposF; + internal static FieldInfo _stackF; + internal static FieldInfo _crawlposF; + internal static FieldInfo _crawlF; + internal static FieldInfo _matchF; + internal static FieldInfo _trackcountF; + + // note some methods + + internal static MethodInfo _ensurestorageM; + internal static MethodInfo _captureM; + internal static MethodInfo _transferM; + internal static MethodInfo _uncaptureM; + internal static MethodInfo _ismatchedM; + internal static MethodInfo _matchlengthM; + internal static MethodInfo _matchindexM; + internal static MethodInfo _isboundaryM; + internal static MethodInfo _isECMABoundaryM; + internal static MethodInfo _chartolowerM; + internal static MethodInfo _getcharM; + internal static MethodInfo _crawlposM; + internal static MethodInfo _charInSetM; + internal static MethodInfo _getCurrentCulture; + internal static MethodInfo _getInvariantCulture; +#if DBG + internal static MethodInfo _dumpstateM; +#endif + + + protected RegexDynamicModule(int moduleNum, AssemblyName an, CustomAttributeBuilder[] attribs, String resourceFile) + { + new ReflectionPermission(PermissionState.Unrestricted).Assert(); + try + { + if (an == null) + { + an = new AssemblyName(); + an.Name = "RegexAssembly" + AppDomain.CurrentDomain.GetHashCode().ToString() + "_" + moduleNum.ToString(); + _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); + } + else + { + _assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave); + } + + _module = _assembly.DefineDynamicModule(an.Name + ".dll"); + + if (attribs != null) + { + for (int i = 0; i < attribs.Length; i++) + { + _assembly.SetCustomAttribute(attribs[i]); + } + } + + if (resourceFile != null) + { + // unmanaged resources are not supported + throw new ArgumentOutOfRangeException("resourceFile"); + } + } + finally + { + CodeAccessPermission.RevertAssert(); + } + } + + static RegexDynamicModule() + { + + new ReflectionPermission(PermissionState.Unrestricted).Assert(); + try + { + // note some fields + _textbegF = RegexRunnerField("runtextbeg"); + _textendF = RegexRunnerField("runtextend"); + _textstartF = RegexRunnerField("runtextstart"); + _textposF = RegexRunnerField("runtextpos"); + _textF = RegexRunnerField("runtext"); + _trackposF = RegexRunnerField("runtrackpos"); + _trackF = RegexRunnerField("runtrack"); + _stackposF = RegexRunnerField("runstackpos"); + _stackF = RegexRunnerField("runstack"); + _crawlposF = RegexRunnerField("runcrawlpos"); + _crawlF = RegexRunnerField("runcrawl"); + _matchF = RegexRunnerField("runmatch"); + _trackcountF = RegexRunnerField("runtrackcount"); + + // note some methods + _ensurestorageM = RegexRunnerMethod("EnsureStorage"); + _captureM = RegexRunnerMethod("Capture"); + _transferM = RegexRunnerMethod("TransferCapture"); + _uncaptureM = RegexRunnerMethod("Uncapture"); + _ismatchedM = RegexRunnerMethod("IsMatched"); + _matchlengthM = RegexRunnerMethod("MatchLength"); + _matchindexM = RegexRunnerMethod("MatchIndex"); + _isboundaryM = RegexRunnerMethod("IsBoundary"); + _charInSetM = RegexRunnerMethod("CharInSet"); + _isECMABoundaryM = RegexRunnerMethod("IsECMABoundary"); + _crawlposM = RegexRunnerMethod("Crawlpos"); + + _chartolowerM = typeof(Char).GetMethod("ToLower", new Type[] { typeof(Char), typeof(CultureInfo) }); + _getcharM = typeof(String).GetMethod("get_Chars", new Type[] { typeof(int) }); + _getCurrentCulture = typeof(CultureInfo).GetMethod("get_CurrentCulture"); + _getInvariantCulture = typeof(CultureInfo).GetMethod("get_InvariantCulture"); + + +#if DBG + _dumpstateM = RegexRunnerMethod("DumpState"); +#endif + } + finally + { + CodeAccessPermission.RevertAssert(); + } + } + + private static FieldInfo RegexRunnerField(String fieldname) + { + return typeof(RegexRunner).GetField(fieldname, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + + private static MethodInfo RegexRunnerMethod(String methname) + { + return typeof(RegexRunner).GetMethod(methname, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + } + } + + + internal sealed class RegexCompiler : RegexDynamicModule + { + internal static Object _syncObject = new Object(); + internal static int _typeCount = 0; + internal static int _moduleCount = 0; + internal static LocalDataStoreSlot _moduleSlot = Thread.AllocateDataSlot(); + + // state of the type builder + internal TypeBuilder _typebuilder; + internal MethodBuilder _methbuilder; + internal ILGenerator _ilg; + + // tokens representing local variables + internal LocalBuilder _textstartV; + internal LocalBuilder _textbegV; + internal LocalBuilder _textendV; + internal LocalBuilder _textposV; + internal LocalBuilder _textV; + internal LocalBuilder _trackposV; + internal LocalBuilder _trackV; + internal LocalBuilder _stackposV; + internal LocalBuilder _stackV; + internal LocalBuilder _tempV; + internal LocalBuilder _temp2V; + internal LocalBuilder _temp3V; + + + internal RegexCode _code; // the RegexCode object (used for debugging only) + internal int[] _codes; // the RegexCodes being translated + internal String[] _strings; // the stringtable associated with the RegexCodes + internal RegexPrefix _fcPrefix; // the possible first chars computed by RegexFCD + internal RegexPrefix _scPrefix; // the set of eaten prefix chars + internal RegexBoyerMoore _bmPrefix; // a prefix as a boyer-moore machine + internal int _anchors; // the set of anchors + + internal Label[] _labels; // a label for every operation in _codes + internal BacktrackNote[] _notes; // a list of the backtracking states to be generated + internal int _notecount; // true count of _notes (allocation grows exponentially) + internal int _trackcount; // count of backtracking states (used to reduce allocations) + + internal Label _backtrack; // label for backtracking + + + internal int _regexopcode; // the current opcode being processed + internal int _codepos; // the current code being translated + internal int _backpos; // the current backtrack-note being translated + + internal RegexOptions _options; // options + + internal const int infinite = RegexNode.infinite; // an infinity + + // special code fragments + internal int[] _uniquenote; // _notes indices for code that should be emitted <= once + internal int[] _goto; // indices for forward-jumps-through-switch (for allocations) + + // indices for unique code fragments + internal const int stackpop = 0; // pop one + internal const int stackpop2 = 1; // pop two + internal const int stackpop3 = 2; // pop three + internal const int capback = 3; // uncapture + internal const int capback2 = 4; // uncapture 2 + internal const int branchmarkback2 = 5; // back2 part of branchmark + internal const int lazybranchmarkback2 = 6; // back2 part of lazybranchmark + internal const int branchcountback2 = 7; // back2 part of branchcount + internal const int lazybranchcountback2 = 8; // back2 part of lazybranchcount + internal const int forejumpback = 9; // back part of forejump + internal const int uniquecount = 10; + + + private RegexCompiler(int moduleNum) + : base(moduleNum, null, null, null) + { + } + + private RegexCompiler(int moduleNum, AssemblyName an, CustomAttributeBuilder[] attribs, String resourceFile) + : base(moduleNum, an, attribs, resourceFile) + { + } + + // Entry point to dynamically compile a regular expression. The expression is compiled to + // an in memory assembly. + internal static RegexRunnerFactory Compile(RegexCode code, RegexOptions options) + { + RegexCompiler c; + + c = GetThreadCompiler(); + + Type factory; + RegexRunnerFactory rrf; + + new ReflectionPermission(PermissionState.Unrestricted).Assert(); + try + { + factory = c.FactoryFromCode(code, options, "Regex"); + rrf = (RegexRunnerFactory)(Activator.CreateInstance(factory, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null)); + } + finally + { + CodeAccessPermission.RevertAssert(); + } + return rrf; + } + + // Compile regular expressions into an assembly on disk. + internal static void CompileToAssembly(RegexCompilationInfo[] regexes, AssemblyName an, CustomAttributeBuilder[] attribs, String resourceFile) + { + RegexCompiler c = new RegexCompiler(0, an, attribs, resourceFile); + + for (int i = 0; i < regexes.Length; i++) + { + String pattern = regexes[i].Pattern; + RegexOptions options = regexes[i].Options; + String fullname = regexes[i].Namespace + "." + regexes[i].Name; + + RegexTree tree = RegexParser.Parse(pattern, options); + RegexCode code = RegexWriter.Write(tree); + + Type factory; + + new ReflectionPermission(PermissionState.Unrestricted).Assert(); + try + { + factory = c.FactoryFromCode(code, options, fullname); + c.GenerateRegexType(pattern, options, fullname, regexes[i].IsPublic, code, tree, factory); + } + finally + { + CodeAccessPermission.RevertAssert(); + } + } + + c.Save(); + } + + // The top-level driver. Initializes everything then calls the Generate* methods. + internal Type FactoryFromCode(RegexCode code, RegexOptions options, String typeprefix) + { + String runnertypename; + String runnerfactoryname; + Type runnertype; + Type factory; + + _code = code; + _codes = code._codes; + _strings = code._strings; + _fcPrefix = code._fcPrefix; + _scPrefix = code._scPrefix; + _bmPrefix = code._bmPrefix; + _anchors = code._anchors; + _trackcount = code._trackcount; + _options = options; + + // pick a name for the class + + lock (_syncObject) + { + + // Note: Class names must be unique within assemblies, not just + // within modules. We append the modulename to the runner name + // to make our name unique across the assembly + + runnertypename = typeprefix + "Runner" + _typeCount.ToString(); + runnerfactoryname = typeprefix + "Factory" + _typeCount.ToString(); + _typeCount++; + } + + // Generate a RegexRunner class + // (blocks are simply illustrative) + + DefineType(runnertypename, false, typeof(RegexRunner)); + { + DefineMethod("Go", null); + { + GenerateGo(); + BakeMethod(); + } + + DefineMethod("FindFirstChar", typeof(bool)); + { + GenerateFindFirstChar(); + BakeMethod(); + } + + DefineMethod("InitTrackCount", null); + { + GenerateInitTrackCount(); + BakeMethod(); + } + + runnertype = BakeType(); + } + + // Generate a RegexRunnerFactory class + + DefineType(runnerfactoryname, false, typeof(RegexRunnerFactory)); + { + DefineMethod("CreateInstance", typeof(RegexRunner)); + { + GenerateCreateInstance(runnertype); + BakeMethod(); + } + + factory = BakeType(); + } + + return factory; + } + + + internal void GenerateRegexType(String pattern, RegexOptions opts, String name, bool ispublic, RegexCode code, RegexTree tree, Type factory) + { + FieldInfo patternF = RegexField("pattern"); + FieldInfo optionsF = RegexField("roptions"); + FieldInfo factoryF = RegexField("factory"); + FieldInfo capsF = RegexField("caps"); + FieldInfo capnamesF = RegexField("capnames"); + FieldInfo capslistF = RegexField("capslist"); + FieldInfo capsizeF = RegexField("capsize"); + Type[] noTypeArray = new Type[0]; + ConstructorBuilder cbuilder; + + DefineType(name, ispublic, typeof(Regex)); + { + // define constructor + _methbuilder = null; + MethodAttributes ma = System.Reflection.MethodAttributes.Public; + cbuilder = _typebuilder.DefineConstructor(ma, CallingConventions.Standard, noTypeArray); + _ilg = cbuilder.GetILGenerator(); + { + // call base constructor + Ldthis(); + _ilg.Emit(OpCodes.Call, typeof(Regex).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, + null, new Type[0], new ParameterModifier[0])); + // set pattern + Ldthis(); + Ldstr(pattern); + Stfld(patternF); + + // set options + Ldthis(); + Ldc((int)opts); + Stfld(optionsF); + + // set factory + Ldthis(); + Newobj(factory.GetConstructor(noTypeArray)); + Stfld(factoryF); + + // set caps + if (code._caps != null) + GenerateCreateHashtable(capsF, code._caps); + + // set capnames + if (tree._capnames != null) + GenerateCreateHashtable(capnamesF, tree._capnames); + + // set capslist + if (tree._capslist != null) + { + Ldthis(); + Ldc(tree._capslist.Length); + _ilg.Emit(OpCodes.Newarr, typeof(String)); // create new string array + Stfld(capslistF); + + for (int i = 0; i < tree._capslist.Length; i++) + { + Ldthisfld(capslistF); + + Ldc(i); + Ldstr(tree._capslist[i]); + _ilg.Emit(OpCodes.Stelem_Ref); + } + } + + // set capsize + Ldthis(); + Ldc(code._capsize); + Stfld(capsizeF); + + // set runnerref and replref by calling InitializeReferences() + Ldthis(); + Call(typeof(Regex).GetMethod("InitializeReferences", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)); + + + Ret(); + } + } + + // bake the constructor and type, then save the assembly + cbuilder = null; + _typebuilder.CreateType(); + _ilg = null; + _typebuilder = null; + } + + internal void GenerateCreateHashtable(FieldInfo field, Hashtable ht) + { + MethodInfo addMethod = typeof(Hashtable).GetMethod("Add", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + + Ldthis(); + Newobj(typeof(Hashtable).GetConstructor(new Type[0])); + Stfld(field); + + IDictionaryEnumerator en = ht.GetEnumerator(); + while (en.MoveNext()) + { + Ldthisfld(field); + + if (en.Key is int) + { + Ldc((int)en.Key); + _ilg.Emit(OpCodes.Box, typeof(Int32)); + } + else + Ldstr((String)en.Key); + + Ldc((int)en.Value); + _ilg.Emit(OpCodes.Box, typeof(Int32)); + Callvirt(addMethod); + } + } + + private FieldInfo RegexField(String fieldname) + { + return typeof(Regex).GetField(fieldname, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); + } + + internal void Save() + { + _assembly.Save(_assembly.GetName().Name + ".dll"); + } + + // Keeps track of an operation that needs to be referenced in the backtrack-jump + // switch table, and that needs backtracking code to be emitted (if flags != 0) + internal sealed class BacktrackNote + { + internal BacktrackNote(int flags, Label label, int codepos) + { + _codepos = codepos; + _flags = flags; + _label = label; + } + + internal int _codepos; + internal int _flags; + internal Label _label; + } + + // Adds a backtrack note to the list of them, and returns the index of the new + // note (which is also the index for the jump used by the switch table) + internal int AddBacktrackNote(int flags, Label l, int codepos) + { + if (_notes == null || _notecount >= _notes.Length) + { + BacktrackNote[] newnotes = new BacktrackNote[_notes == null ? 16 : _notes.Length * 2]; + if (_notes != null) + System.Array.Copy(_notes, 0, newnotes, 0, _notecount); + _notes = newnotes; + } + + _notes[_notecount] = new BacktrackNote(flags, l, codepos); + + return _notecount++; + } + + // Adds a backtrack note for the current operation; creates a new label for + // where the code will be, and returns the switch index. + internal int AddTrack() + { + return AddTrack(RegexCode.Back); + } + + // Adds a backtrack note for the current operation; creates a new label for + // where the code will be, and returns the switch index. + internal int AddTrack(int flags) + { + return AddBacktrackNote(flags, DefineLabel(), _codepos); + } + + // Adds a switchtable entry for the specified position (for the forward + // logic; does not cause backtracking logic to be generated) + internal int AddGoto(int destpos) + { + if (_goto[destpos] == -1) + _goto[destpos] = AddBacktrackNote(0, _labels[destpos], destpos); + + return _goto[destpos]; + } + + // Adds a note for backtracking code that only needs to be generated once; + // if it's already marked to be generated, returns the switch index + // for the unique piece of code. + internal int AddUniqueTrack(int i) + { + return AddUniqueTrack(i, RegexCode.Back); + } + + // Adds a note for backtracking code that only needs to be generated once; + // if it's already marked to be generated, returns the switch index + // for the unique piece of code. + internal int AddUniqueTrack(int i, int flags) + { + if (_uniquenote[i] == -1) + _uniquenote[i] = AddTrack(flags); + + return _uniquenote[i]; + } + + // A macro for _ilg.DefineLabel + internal Label DefineLabel() + { + return _ilg.DefineLabel(); + } + + // A macro for _ilg.MarkLabel + internal void MarkLabel(Label l) + { + _ilg.MarkLabel(l); + } + + // Returns the ith operand of the current operation + internal int Operand(int i) + { + return _codes[_codepos + i + 1]; + } + + // True if the current operation is marked for the leftward direction + internal bool IsRtl() + { + return (_regexopcode & RegexCode.Rtl) != 0; + } + + // True if the current operation is marked for the leftward direction + internal bool IsCi() + { + return (_regexopcode & RegexCode.Ci) != 0; + } + +#if DBG + // True if we need to do the backtrack logic for the current operation + internal bool IsBack() { + return(_regexopcode & RegexCode.Back) != 0; + } + + // True if we need to do the second-backtrack logic for the current operation + internal bool IsBack2() { + return(_regexopcode & RegexCode.Back2) != 0; + } +#endif + + // Returns the raw regex opcode (masking out Back and Rtl) + internal int Code() + { + return _regexopcode & RegexCode.Mask; + } + + internal void Ldstr(string str) + { + _ilg.Emit(OpCodes.Ldstr, str); + } + + // A macro for the various forms of Ldc + internal void Ldc(int i) + { + if (i <= 127 && i >= -128) + _ilg.Emit(OpCodes.Ldc_I4_S, (byte)i); + else + _ilg.Emit(OpCodes.Ldc_I4, i); + } + + // A macro for _ilg.Emit(OpCodes.Dup) + internal void Dup() + { + _ilg.Emit(OpCodes.Dup); + } + + // A macro for _ilg.Emit(OpCodes.Ret) + internal void Ret() + { + _ilg.Emit(OpCodes.Ret); + } + + // A macro for _ilg.Emit(OpCodes.Pop) + internal void Pop() + { + _ilg.Emit(OpCodes.Pop); + } + + // A macro for _ilg.Emit(OpCodes.Add) + internal void Add() + { + _ilg.Emit(OpCodes.Add); + } + + // A macro for _ilg.Emit(OpCodes.Add); a true flag can turn it into a Sub + internal void Add(bool negate) + { + if (negate) + _ilg.Emit(OpCodes.Sub); + else + _ilg.Emit(OpCodes.Add); + } + + // A macro for _ilg.Emit(OpCodes.Sub) + internal void Sub() + { + _ilg.Emit(OpCodes.Sub); + } + + // A macro for _ilg.Emit(OpCodes.Sub); a true flag can turn it into a Add + internal void Sub(bool negate) + { + if (negate) + _ilg.Emit(OpCodes.Add); + else + _ilg.Emit(OpCodes.Sub); + } + + // A macro for _ilg.Emit(OpCodes.Ldloc); + internal void Ldloc(LocalBuilder lt) + { + _ilg.Emit(OpCodes.Ldloc_S, lt); + } + + // A macro for _ilg.Emit(OpCodes.Stloc); + internal void Stloc(LocalBuilder lt) + { + _ilg.Emit(OpCodes.Stloc_S, lt); + } + + // A macro for _ilg.Emit(OpCodes.Ldarg_0); + internal void Ldthis() + { + _ilg.Emit(OpCodes.Ldarg_0); + } + + // A macro for Ldthis(); Ldfld(); + internal void Ldthisfld(FieldInfo ft) + { + Ldthis(); + _ilg.Emit(OpCodes.Ldfld, ft); + } + + // A macro for Ldthis(); Ldfld(); Stloc(); + internal void Mvfldloc(FieldInfo ft, LocalBuilder lt) + { + Ldthisfld(ft); + Stloc(lt); + } + + // A macro for Ldthis(); Ldthisfld(); Stloc(); + internal void Mvlocfld(LocalBuilder lt, FieldInfo ft) + { + Ldthis(); + Ldloc(lt); + Stfld(ft); + } + + // A macro for _ilg.Emit(OpCodes.Stfld); + internal void Stfld(FieldInfo ft) + { + _ilg.Emit(OpCodes.Stfld, ft); + } + + // A macro for _ilg.Emit(OpCodes.Callvirt); + internal void Callvirt(MethodInfo mt) + { + _ilg.Emit(OpCodes.Callvirt, mt); + } + + // A macro for _ilg.Emit(OpCodes.Call); + internal void Call(MethodInfo mt) + { + _ilg.Emit(OpCodes.Call, mt); + } + + // A macro for _ilg.Emit(OpCodes.Newobj); + internal void Newobj(ConstructorInfo ct) + { + _ilg.Emit(OpCodes.Newobj, ct); + } + + // A macro for _ilg.Emit(OpCodes.Brfalse) (long form) + internal void BrfalseFar(Label l) + { + _ilg.Emit(OpCodes.Brfalse, l); + } + + // A macro for _ilg.Emit(OpCodes.Brtrue) (long form) + internal void BrtrueFar(Label l) + { + _ilg.Emit(OpCodes.Brtrue, l); + } + + // A macro for _ilg.Emit(OpCodes.Br) (long form) + internal void BrFar(Label l) + { + _ilg.Emit(OpCodes.Br, l); + } + + // A macro for _ilg.Emit(OpCodes.Ble) (long form) + internal void BleFar(Label l) + { + _ilg.Emit(OpCodes.Ble, l); + } + + // A macro for _ilg.Emit(OpCodes.Blt) (long form) + internal void BltFar(Label l) + { + _ilg.Emit(OpCodes.Blt, l); + } + + // A macro for _ilg.Emit(OpCodes.Bge) (long form) + internal void BgeFar(Label l) + { + _ilg.Emit(OpCodes.Bge, l); + } + + // A macro for _ilg.Emit(OpCodes.Bgt) (long form) + internal void BgtFar(Label l) + { + _ilg.Emit(OpCodes.Bgt, l); + } + + // A macro for _ilg.Emit(OpCodes.Bne) (long form) + internal void BneFar(Label l) + { + _ilg.Emit(OpCodes.Bne_Un, l); + } + + // A macro for _ilg.Emit(OpCodes.Beq) (long form) + internal void BeqFar(Label l) + { + _ilg.Emit(OpCodes.Beq, l); + } + + // A macro for _ilg.Emit(OpCodes.Brfalse_S) (short jump) + internal void Brfalse(Label l) + { + _ilg.Emit(OpCodes.Brfalse_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Br_S) (short jump) + internal void Br(Label l) + { + _ilg.Emit(OpCodes.Br_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Ble_S) (short jump) + internal void Ble(Label l) + { + _ilg.Emit(OpCodes.Ble_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Blt_S) (short jump) + internal void Blt(Label l) + { + _ilg.Emit(OpCodes.Blt_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Bge_S) (short jump) + internal void Bge(Label l) + { + _ilg.Emit(OpCodes.Bge_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Bgt_S) (short jump) + internal void Bgt(Label l) + { + _ilg.Emit(OpCodes.Bgt_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Bleun_S) (short jump) + internal void Bgtun(Label l) + { + _ilg.Emit(OpCodes.Bgt_Un_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Bne_S) (short jump) + internal void Bne(Label l) + { + _ilg.Emit(OpCodes.Bne_Un_S, l); + } + + // A macro for _ilg.Emit(OpCodes.Beq_S) (short jump) + internal void Beq(Label l) + { + _ilg.Emit(OpCodes.Beq_S, l); + } + + // A macro for the Ldlen instruction + internal void Ldlen() + { + _ilg.Emit(OpCodes.Ldlen); + } + + // Loads the char to the right of the current position + internal void Rightchar() + { + Ldloc(_textV); + Ldloc(_textposV); + Callvirt(_getcharM); + } + + // Loads the char to the right of the current position and advances the current position + internal void Rightcharnext() + { + Ldloc(_textV); + Ldloc(_textposV); + Dup(); + Ldc(1); + Add(); + Stloc(_textposV); + Callvirt(_getcharM); + } + + // Loads the char to the left of the current position + internal void Leftchar() + { + Ldloc(_textV); + Ldloc(_textposV); + Ldc(1); + Sub(); + Callvirt(_getcharM); + } + + // Loads the char to the left of the current position and advances (leftward) + internal void Leftcharnext() + { + Ldloc(_textV); + Ldloc(_textposV); + Ldc(1); + Sub(); + Dup(); + Stloc(_textposV); + Callvirt(_getcharM); + } + + // Creates a backtrack note and pushes the switch index it on the tracking stack + internal void Track() + { + ReadyPushTrack(); + Ldc(AddTrack()); + DoPush(); + } + + // Pushes the current switch index on the tracking stack so the backtracking + // logic will be repeated again next time we backtrack here. + // + internal void Trackagain() + { + ReadyPushTrack(); + Ldc(_backpos); + DoPush(); + } + + // Saves the value of a local variable on the tracking stack + internal void PushTrack(LocalBuilder lt) + { + ReadyPushTrack(); + Ldloc(lt); + DoPush(); + } + + // Creates a backtrack note for a piece of code that should only be generated once, + // and emits code that pushes the switch index on the backtracking stack. + internal void TrackUnique(int i) + { + ReadyPushTrack(); + Ldc(AddUniqueTrack(i)); + DoPush(); + } + + // Creates a second-backtrack note for a piece of code that should only be + // generated once, and emits code that pushes the switch index on the + // backtracking stack. + internal void TrackUnique2(int i) + { + ReadyPushTrack(); + Ldc(AddUniqueTrack(i, RegexCode.Back2)); + DoPush(); + } + + // Prologue to code that will push an element on the tracking stack + internal void ReadyPushTrack() + { + _ilg.Emit(OpCodes.Ldloc_S, _trackV); + _ilg.Emit(OpCodes.Ldloc_S, _trackposV); + _ilg.Emit(OpCodes.Ldc_I4_1); + _ilg.Emit(OpCodes.Sub); + _ilg.Emit(OpCodes.Dup); + _ilg.Emit(OpCodes.Stloc_S, _trackposV); + } + + // Pops an element off the tracking stack (leave it on the operand stack) + internal void PopTrack() + { + _ilg.Emit(OpCodes.Ldloc_S, _trackV); + _ilg.Emit(OpCodes.Ldloc_S, _trackposV); + _ilg.Emit(OpCodes.Dup); + _ilg.Emit(OpCodes.Ldc_I4_1); + _ilg.Emit(OpCodes.Add); + _ilg.Emit(OpCodes.Stloc_S, _trackposV); + _ilg.Emit(OpCodes.Ldelem_I4); + } + + // Retrieves the top entry on the tracking stack without popping + internal void TopTrack() + { + _ilg.Emit(OpCodes.Ldloc_S, _trackV); + _ilg.Emit(OpCodes.Ldloc_S, _trackposV); + _ilg.Emit(OpCodes.Ldelem_I4); + } + + // Saves the value of a local variable on the grouping stack + internal void PushStack(LocalBuilder lt) + { + ReadyPushStack(); + _ilg.Emit(OpCodes.Ldloc_S, lt); + DoPush(); + } + + // Prologue to code that will replace the ith element on the grouping stack + internal void ReadyReplaceStack(int i) + { + _ilg.Emit(OpCodes.Ldloc_S, _stackV); + _ilg.Emit(OpCodes.Ldloc_S, _stackposV); + if (i != 0) + { + Ldc(i); + _ilg.Emit(OpCodes.Add); + } + } + + // Prologue to code that will push an element on the grouping stack + internal void ReadyPushStack() + { + _ilg.Emit(OpCodes.Ldloc_S, _stackV); + _ilg.Emit(OpCodes.Ldloc_S, _stackposV); + _ilg.Emit(OpCodes.Ldc_I4_1); + _ilg.Emit(OpCodes.Sub); + _ilg.Emit(OpCodes.Dup); + _ilg.Emit(OpCodes.Stloc_S, _stackposV); + } + + // Retrieves the top entry on the stack without popping + internal void TopStack() + { + _ilg.Emit(OpCodes.Ldloc_S, _stackV); + _ilg.Emit(OpCodes.Ldloc_S, _stackposV); + _ilg.Emit(OpCodes.Ldelem_I4); + } + + // Pops an element off the grouping stack (leave it on the operand stack) + internal void PopStack() + { + _ilg.Emit(OpCodes.Ldloc_S, _stackV); + _ilg.Emit(OpCodes.Ldloc_S, _stackposV); + _ilg.Emit(OpCodes.Dup); + _ilg.Emit(OpCodes.Ldc_I4_1); + _ilg.Emit(OpCodes.Add); + _ilg.Emit(OpCodes.Stloc_S, _stackposV); + _ilg.Emit(OpCodes.Ldelem_I4); + } + + // Pops 1 element off the grouping stack and discards it + internal void PopDiscardStack() + { + PopDiscardStack(1); + } + + // Pops i elements off the grouping stack and discards them + internal void PopDiscardStack(int i) + { + _ilg.Emit(OpCodes.Ldloc_S, _stackposV); + Ldc(i); + _ilg.Emit(OpCodes.Add); + _ilg.Emit(OpCodes.Stloc_S, _stackposV); + } + + // Epilogue to code that will replace an element on a stack (use Ld* in between) + internal void DoReplace() + { + _ilg.Emit(OpCodes.Stelem_I4); + } + + // Epilogue to code that will push an element on a stack (use Ld* in between) + internal void DoPush() + { + _ilg.Emit(OpCodes.Stelem_I4); + } + + // Jump to the backtracking switch + internal void Back() + { + _ilg.Emit(OpCodes.Br, _backtrack); + } + + // Branch to the MSIL corresponding to the regex code at i + // + // A trick: since track and stack space is gobbled up unboundedly + // only as a result of branching backwards, this is where we check + // for sufficient space and trigger reallocations. + // + // If the "goto" is backwards, we generate code that checks + // available space against the amount of space that would be needed + // in the worst case by code that will only go forward; if there's + // not enough, we push the destination on the tracking stack, then + // we jump to the place where we invoke the allocator. + // + // Since forward gotos pose no threat, they just turn into a Br. + internal void Goto(int i) + { + if (i < _codepos) + { + Label l1 = DefineLabel(); + + // When going backwards, ensure enough space. + Ldloc(_trackposV); + Ldc(_trackcount * 4); + Ble(l1); + Ldloc(_stackposV); + Ldc(_trackcount * 3); + BgtFar(_labels[i]); + MarkLabel(l1); + ReadyPushTrack(); + Ldc(AddGoto(i)); + DoPush(); + BrFar(_backtrack); + } + else + { + BrFar(_labels[i]); + } + } + + // Returns the position of the next operation in the regex code, taking + // into account the different numbers of arguments taken by operations + internal int NextCodepos() + { + return _codepos + RegexCode.OpcodeSize(_codes[_codepos]); + } + + // The label for the next (forward) operation + internal Label AdvanceLabel() + { + return _labels[NextCodepos()]; + } + + // Goto the next (forward) operation + internal void Advance() + { + _ilg.Emit(OpCodes.Br, AdvanceLabel()); + } + + internal void CallToLower() + { + if ((_options & RegexOptions.CultureInvariant) != 0) + Call(_getInvariantCulture); + else + Call(_getCurrentCulture); + + Call(_chartolowerM); + } + + // Generates the first section of the MSIL. This section contains all + // the forward logic, and corresponds directly to the regex codes. + // + // In the absence of backtracking, this is all we would need. + internal void GenerateForwardSection() + { + int codepos; + + _labels = new Label[_codes.Length]; + _goto = new int[_codes.Length]; + + // initialize + + for (codepos = 0; codepos < _codes.Length; codepos += RegexCode.OpcodeSize(_codes[codepos])) + { + _goto[codepos] = -1; + _labels[codepos] = _ilg.DefineLabel(); + } + + _uniquenote = new int[uniquecount]; + for (int i = 0; i < uniquecount; i++) + _uniquenote[i] = -1; + + // emit variable initializers + + Mvfldloc(_textF, _textV); + Mvfldloc(_textstartF, _textstartV); + Mvfldloc(_textbegF, _textbegV); + Mvfldloc(_textendF, _textendV); + Mvfldloc(_textposF, _textposV); + Mvfldloc(_trackF, _trackV); + Mvfldloc(_trackposF, _trackposV); + Mvfldloc(_stackF, _stackV); + Mvfldloc(_stackposF, _stackposV); + + _backpos = -1; + + for (codepos = 0; codepos < _codes.Length; codepos += RegexCode.OpcodeSize(_codes[codepos])) + { + MarkLabel(_labels[codepos]); + _codepos = codepos; + _regexopcode = _codes[codepos]; + GenerateOneCode(); + } + } + + // Generates the middle section of the MSIL. This section contains the + // big switch jump that allows us to simulate a stack of addresses, + // and it also contains the calls that expand the tracking and the + // grouping stack when they get too full. + internal void GenerateMiddleSection() + { + Label l1 = DefineLabel(); + Label[] table; + int i; + + // Backtrack switch + MarkLabel(_backtrack); + + // first call EnsureStorage + Mvlocfld(_trackposV, _trackposF); + Mvlocfld(_stackposV, _stackposF); + Ldthis(); + Callvirt(_ensurestorageM); + Mvfldloc(_trackposF, _trackposV); + Mvfldloc(_stackposF, _stackposV); + Mvfldloc(_trackF, _trackV); + Mvfldloc(_stackF, _stackV); + + + PopTrack(); + + table = new Label[_notecount]; + for (i = 0; i < _notecount; i++) + table[i] = _notes[i]._label; + + _ilg.Emit(OpCodes.Switch, table); + + } + + // Generates the last section of the MSIL. This section contains all of + // the backtracking logic. + internal void GenerateBacktrackSection() + { + int i; + + for (i = 0; i < _notecount; i++) + { + BacktrackNote n = _notes[i]; + if (n._flags != 0) + { + _ilg.MarkLabel(n._label); + _codepos = n._codepos; + _backpos = i; + _regexopcode = _codes[n._codepos] | n._flags; + GenerateOneCode(); + } + } + } + + // Generates FindFirstChar + internal void GenerateFindFirstChar() + { + _textposV = DeclareInt(); + _textV = DeclareString(); + _tempV = DeclareInt(); + _temp2V = DeclareInt(); + + if (0 != (_anchors & (RegexFCD.Beginning | RegexFCD.Start | RegexFCD.EndZ | RegexFCD.End))) + { + if (!_code._rightToLeft) + { + if (0 != (_anchors & RegexFCD.Beginning)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textbegF); + Ble(l1); + Ldthis(); + Ldthisfld(_textendF); + Stfld(_textposF); + Ldc(0); + Ret(); + MarkLabel(l1); + } + + if (0 != (_anchors & RegexFCD.Start)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textstartF); + Ble(l1); + Ldthis(); + Ldthisfld(_textendF); + Stfld(_textposF); + Ldc(0); + Ret(); + MarkLabel(l1); + } + + if (0 != (_anchors & RegexFCD.EndZ)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textendF); + Ldc(1); + Sub(); + Bge(l1); + Ldthis(); + Ldthisfld(_textendF); + Ldc(1); + Sub(); + Stfld(_textposF); + MarkLabel(l1); + } + + if (0 != (_anchors & RegexFCD.End)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textendF); + Bge(l1); + Ldthis(); + Ldthisfld(_textendF); + Stfld(_textposF); + MarkLabel(l1); + } + } + else + { + if (0 != (_anchors & RegexFCD.End)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textendF); + Bge(l1); + Ldthis(); + Ldthisfld(_textbegF); + Stfld(_textposF); + Ldc(0); + Ret(); + MarkLabel(l1); + } + + if (0 != (_anchors & RegexFCD.EndZ)) + { + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textendF); + Ldc(1); + Sub(); + Blt(l1); + Ldthisfld(_textposF); + Ldthisfld(_textendF); + Beq(l2); + Ldthisfld(_textF); + Ldthisfld(_textposF); + Callvirt(_getcharM); + Ldc((int)'\n'); + Beq(l2); + MarkLabel(l1); + Ldthis(); + Ldthisfld(_textbegF); + Stfld(_textposF); + Ldc(0); + Ret(); + MarkLabel(l2); + } + + if (0 != (_anchors & RegexFCD.Start)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textstartF); + Bge(l1); + Ldthis(); + Ldthisfld(_textbegF); + Stfld(_textposF); + Ldc(0); + Ret(); + MarkLabel(l1); + } + + if (0 != (_anchors & RegexFCD.Beginning)) + { + Label l1 = DefineLabel(); + Ldthisfld(_textposF); + Ldthisfld(_textbegF); + Ble(l1); + Ldthis(); + Ldthisfld(_textbegF); + Stfld(_textposF); + MarkLabel(l1); + } + } + + + Ldc(1); + Ret(); + } + else if (_bmPrefix != null && _bmPrefix._negativeUnicode == null) + { + // Compiled Boyer-Moore string matching + + LocalBuilder chV = _tempV; + LocalBuilder testV = _tempV; + LocalBuilder limitV = _temp2V; + Label lDefaultAdvance = DefineLabel(); + Label lAdvance = DefineLabel(); + Label lFail = DefineLabel(); + Label lStart = DefineLabel(); + Label lOutOfRange = DefineLabel(); + Label lPartialMatch = DefineLabel(); + + + int chLast; + int i; + int beforefirst; + int last; + Label[] table; + + if (!_code._rightToLeft) + { + beforefirst = -1; + last = _bmPrefix._pattern.Length - 1; + } + else + { + beforefirst = _bmPrefix._pattern.Length; + last = 0; + } + + chLast = _bmPrefix._pattern[last]; + + Mvfldloc(_textF, _textV); + if (!_code._rightToLeft) + Ldthisfld(_textendF); + else + Ldthisfld(_textbegF); + Stloc(limitV); + + Ldthisfld(_textposF); + if (!_code._rightToLeft) + { + Ldc(_bmPrefix._pattern.Length - 1); + Add(); + } + else + { + Ldc(_bmPrefix._pattern.Length); + Sub(); + } + Stloc(_textposV); + Br(lStart); + + MarkLabel(lDefaultAdvance); + + if (!_code._rightToLeft) + Ldc(_bmPrefix._pattern.Length); + else + Ldc(-_bmPrefix._pattern.Length); + + MarkLabel(lAdvance); + + Ldloc(_textposV); + Add(); + Stloc(_textposV); + + MarkLabel(lStart); + + Ldloc(_textposV); + Ldloc(limitV); + if (!_code._rightToLeft) + BgeFar(lFail); + else + BltFar(lFail); + + Rightchar(); + if (_bmPrefix._caseInsensitive) + CallToLower(); + + Dup(); + Stloc(chV); + Ldc(chLast); + BeqFar(lPartialMatch); + + Ldloc(chV); + Ldc(_bmPrefix._lowASCII); + Sub(); + Dup(); + Stloc(chV); + Ldc(_bmPrefix._highASCII - _bmPrefix._lowASCII); + Bgtun(lDefaultAdvance); + + table = new Label[_bmPrefix._highASCII - _bmPrefix._lowASCII + 1]; + + for (i = _bmPrefix._lowASCII; i <= _bmPrefix._highASCII; i++) + { + if (_bmPrefix._negativeASCII[i] == beforefirst) + table[i - _bmPrefix._lowASCII] = lDefaultAdvance; + else + table[i - _bmPrefix._lowASCII] = DefineLabel(); + } + + Ldloc(chV); + _ilg.Emit(OpCodes.Switch, table); + + for (i = _bmPrefix._lowASCII; i <= _bmPrefix._highASCII; i++) + { + if (_bmPrefix._negativeASCII[i] == beforefirst) + continue; + + MarkLabel(table[i - _bmPrefix._lowASCII]); + + Ldc(_bmPrefix._negativeASCII[i]); + BrFar(lAdvance); + } + + MarkLabel(lPartialMatch); + + Ldloc(_textposV); + Stloc(testV); + + for (i = _bmPrefix._pattern.Length - 2; i >= 0; i--) + { + Label lNext = DefineLabel(); + int charindex; + + if (!_code._rightToLeft) + charindex = i; + else + charindex = _bmPrefix._pattern.Length - 1 - i; + + Ldloc(_textV); + Ldloc(testV); + Ldc(1); + Sub(_code._rightToLeft); + Dup(); + Stloc(testV); + Callvirt(_getcharM); + if (_bmPrefix._caseInsensitive) + CallToLower(); + + Ldc(_bmPrefix._pattern[charindex]); + Beq(lNext); + Ldc(_bmPrefix._positive[charindex]); + BrFar(lAdvance); + + MarkLabel(lNext); + + } + + Ldthis(); + Ldloc(testV); + if (_code._rightToLeft) + { + Ldc(1); + Add(); + } + Stfld(_textposF); + Ldc(1); + Ret(); + + MarkLabel(lFail); + + Ldthis(); + if (!_code._rightToLeft) + Ldthisfld(_textendF); + else + Ldthisfld(_textbegF); + Stfld(_textposF); + Ldc(0); + Ret(); + } + else if (_fcPrefix == null) + { + Ldc(1); + Ret(); + } + else + { + LocalBuilder cV = _temp2V; + LocalBuilder chV = _tempV; + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + Label l3 = DefineLabel(); + Label l4 = DefineLabel(); + Label l5 = DefineLabel(); + + Mvfldloc(_textposF, _textposV); + Mvfldloc(_textF, _textV); + + if (!_code._rightToLeft) + { + Ldthisfld(_textendF); + Ldloc(_textposV); + } + else + { + Ldloc(_textposV); + Ldthisfld(_textbegF); + } + Sub(); + Stloc(cV); + + Ldloc(cV); + Ldc(0); + BleFar(l4); + + MarkLabel(l1); + + Ldloc(cV); + Ldc(1); + Sub(); + Stloc(cV); + + if (_code._rightToLeft) + Leftcharnext(); + else + Rightcharnext(); + + if (_fcPrefix.CaseInsensitive) + CallToLower(); + + if (!RegexCharClass.IsSingleton(_fcPrefix.Prefix)) + { + Ldstr(_fcPrefix.Prefix); + Ldstr(String.Empty); + Call(_charInSetM); + + BrtrueFar(l2); + } + else + { + Ldc(RegexCharClass.SingletonChar(_fcPrefix.Prefix)); + Beq(l2); + } + + MarkLabel(l5); + + Ldloc(cV); + Ldc(0); + if (!RegexCharClass.IsSingleton(_fcPrefix.Prefix)) + BgtFar(l1); + else + Bgt(l1); + + Ldc(0); + BrFar(l3); + + MarkLabel(l2); + + /* // CURRENTLY DISABLED + // If for some reason we have a prefix we didn't use, use it now. + + if (_bmPrefix != null) { + if (!_code._rightToLeft) { + Ldthisfld(_textendF); + Ldloc(_textposV); + } + else { + Ldloc(_textposV); + Ldthisfld(_textbegF); + } + Sub(); + Ldc(_bmPrefix._pattern.Length - 1); + BltFar(l5); + + for (int i = 1; i < _bmPrefix._pattern.Length; i++) { + Ldloc(_textV); + Ldloc(_textposV); + if (!_code._rightToLeft) { + Ldc(i - 1); + Add(); + } + else { + Ldc(i); + Sub(); + } + Callvirt(_getcharM); + if (!_code._rightToLeft) + Ldc(_bmPrefix._pattern[i]); + else + Ldc(_bmPrefix._pattern[_bmPrefix._pattern.Length - 1 - i]); + BneFar(l5); + } + } + */ + + Ldloc(_textposV); + Ldc(1); + Sub(_code._rightToLeft); + Stloc(_textposV); + Ldc(1); + + MarkLabel(l3); + + Mvlocfld(_textposV, _textposF); + Ret(); + + MarkLabel(l4); + Ldc(0); + Ret(); + } + + } + + // Generates a very simple method that sets the _trackcount field. + internal void GenerateInitTrackCount() + { + Ldthis(); + Ldc(_trackcount); + Stfld(_trackcountF); + Ret(); + } + + // Generates a very simple factory method. + internal void GenerateCreateInstance(Type newtype) + { + Newobj(newtype.GetConstructor(new Type[0])); + Ret(); + } + + // Gets the unique-for-regex dynamic module for this thread + internal static RegexCompiler GetThreadCompiler() + { + RegexCompiler compiler = (RegexCompiler)Thread.GetData(_moduleSlot); + + if (compiler == null) + { + int moduleNum; + + lock (_syncObject) + { + moduleNum = _moduleCount++; + } + + compiler = new RegexCompiler(moduleNum); + Thread.SetData(_moduleSlot, compiler); + } + + return compiler; + } + + // Begins the definition of a new type with a specified base class + internal void DefineType(String typename, bool ispublic, Type inheritfromclass) + { + if (ispublic) + _typebuilder = _module.DefineType(typename, TypeAttributes.Class | TypeAttributes.Public, inheritfromclass); + else + _typebuilder = _module.DefineType(typename, TypeAttributes.Class | TypeAttributes.NotPublic, inheritfromclass); + + } + + // Begins the definition of a new method (no args) with a specified return value + internal void DefineMethod(String methname, Type returntype) + { + MethodAttributes ma = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Virtual; + + _methbuilder = _typebuilder.DefineMethod(methname, ma, returntype, null); + _ilg = _methbuilder.GetILGenerator(); + } + + // Ends the definition of a method + internal void BakeMethod() + { + _methbuilder = null; + } + + // Ends the definition of a class and returns the type + internal Type BakeType() + { + Type retval = _typebuilder.CreateType(); + _typebuilder = null; + + return retval; + } + + // Declares a local int + internal LocalBuilder DeclareInt() + { + return _ilg.DeclareLocal(typeof(int)); + } + + // Declares a local int array + internal LocalBuilder DeclareIntArray() + { + return _ilg.DeclareLocal(typeof(int[])); + } + + // Declares a local char array + internal LocalBuilder DeclareCharArray() + { + return _ilg.DeclareLocal(typeof(char[])); + } + + // Declares a local string + internal LocalBuilder DeclareString() + { + return _ilg.DeclareLocal(typeof(string)); + } + + // Generates the code for "RegexRunner.Go" + internal void GenerateGo() + { + // declare some locals + + _textposV = DeclareInt(); + _textV = DeclareString(); + _trackposV = DeclareInt(); + _trackV = DeclareIntArray(); + _stackposV = DeclareInt(); + _stackV = DeclareIntArray(); + _tempV = DeclareInt(); + _temp2V = DeclareInt(); + _temp3V = DeclareInt(); + _textbegV = DeclareInt(); + _textendV = DeclareInt(); + _textstartV = DeclareInt(); + + // clear some tables + + _labels = null; + _notes = null; + _notecount = 0; + + // globally used labels + + _backtrack = DefineLabel(); + + // emit the code! + + GenerateForwardSection(); + GenerateMiddleSection(); + GenerateBacktrackSection(); + } + +#if DBG + // Some simple debugging stuff + internal static char[] Hex = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + internal static MethodInfo _debugWriteLine = typeof(Debug).GetMethod("WriteLine", new Type[] {typeof(string)}); + + internal static String BaDescription(byte[] ba) { + StringBuilder sb = new StringBuilder(); + + sb.Append("Length " + ba.Length.ToString() + "\n"); + + for (int i = 0; i < ba.Length; i++) { + sb.Append(Hex[ba[i] >> 4]); + sb.Append(Hex[ba[i] & 0xF]); + sb.Append(' '); + } + return sb.ToString(); + } + + // Debug only: emit code to print out a message + internal void Message(String str) { + Ldstr(str); + Call(_debugWriteLine); + } + +#endif + + // The main translation function. It translates the logic for a single opcode at + // the current position. The structure of this function exactly mirrors + // the structure of the inner loop of RegexInterpreter.Go(). + // + // The C# code from RegexInterpreter.Go() that corresponds to each case is + // included as a comment. + // + // Note that since we're generating code, we can collapse many cases that are + // dealt with one-at-a-time in RegexIntepreter. We can also unroll loops that + // iterate over constant strings or sets. + internal void GenerateOneCode() + { +#if DBG + if ((_options & RegexOptions.Debug) != 0) { + Mvlocfld(_textposV, _textposF); + Mvlocfld(_trackposV, _trackposF); + Mvlocfld(_stackposV, _stackposF); + Ldthis(); + Callvirt(_dumpstateM); + StringBuilder sb = new StringBuilder(); + if (_backpos > 0) + sb.AppendFormat("{0:D6} ", _backpos); + else + sb.Append(" "); + sb.Append(_code.OpcodeDescription(_codepos)); + if (IsBack()) + sb.Append(" Back"); + if (IsBack2()) + sb.Append(" Back2"); + Message(sb.ToString()); + } +#endif + + switch (_regexopcode) + { + case RegexCode.Stop: + //: return; + Mvlocfld(_textposV, _textposF); // update _textpos + Ret(); + break; + + case RegexCode.Nothing: + //: break Backward; + Back(); + break; + + case RegexCode.Goto: + //: Goto(Operand(0)); + Goto(Operand(0)); + break; + + case RegexCode.Testref: + //: if (!_match.IsMatched(Operand(0))) + //: break Backward; + Ldthis(); + Ldc(Operand(0)); + Callvirt(_ismatchedM); + BrfalseFar(_backtrack); + break; + + case RegexCode.Lazybranch: + //: Track(Textpos()); + PushTrack(_textposV); + Track(); + break; + + case RegexCode.Lazybranch | RegexCode.Back: + //: Trackframe(1); + //: Textto(Tracked(0)); + //: Goto(Operand(0)); + PopTrack(); + Stloc(_textposV); + Goto(Operand(0)); + break; + + case RegexCode.Nullmark: + //: Stack(-1); + //: Track(); + ReadyPushStack(); + Ldc(-1); + DoPush(); + TrackUnique(stackpop); + break; + + case RegexCode.Setmark: + //: Stack(Textpos()); + //: Track(); + PushStack(_textposV); + TrackUnique(stackpop); + break; + + case RegexCode.Nullmark | RegexCode.Back: + case RegexCode.Setmark | RegexCode.Back: + //: Stackframe(1); + //: break Backward; + PopDiscardStack(); + Back(); + break; + + case RegexCode.Getmark: + //: Stackframe(1); + //: Track(Stacked(0)); + //: Textto(Stacked(0)); + ReadyPushTrack(); + PopStack(); + Dup(); + Stloc(_textposV); + DoPush(); + + Track(); + break; + + case RegexCode.Getmark | RegexCode.Back: + //: Trackframe(1); + //: Stack(Tracked(0)); + //: break Backward; + ReadyPushStack(); + PopTrack(); + DoPush(); + Back(); + break; + + case RegexCode.Capturemark: + //: if (!IsMatched(Operand(1))) + //: break Backward; + //: Stackframe(1); + //: if (Operand(1) != -1) + //: TransferCapture(Operand(0), Operand(1), Stacked(0), Textpos()); + //: else + //: Capture(Operand(0), Stacked(0), Textpos()); + //: Track(Stacked(0)); + + //: Stackframe(1); + //: Capture(Operand(0), Stacked(0), Textpos()); + //: Track(Stacked(0)); + + if (Operand(1) != -1) + { + Ldthis(); + Ldc(Operand(1)); + Callvirt(_ismatchedM); + BrfalseFar(_backtrack); + } + + PopStack(); + Stloc(_tempV); + + if (Operand(1) != -1) + { + Ldthis(); + Ldc(Operand(0)); + Ldc(Operand(1)); + Ldloc(_tempV); + Ldloc(_textposV); + Callvirt(_transferM); + } + else + { + Ldthis(); + Ldc(Operand(0)); + Ldloc(_tempV); + Ldloc(_textposV); + Callvirt(_captureM); + } + + PushTrack(_tempV); + + if (Operand(0) != -1 && Operand(1) != -1) + TrackUnique(capback2); + else + TrackUnique(capback); + + break; + + + case RegexCode.Capturemark | RegexCode.Back: + //: Trackframe(1); + //: Stack(Tracked(0)); + //: Uncapture(); + //: if (Operand(0) != -1 && Operand(1) != -1) + //: Uncapture(); + //: break Backward; + ReadyPushStack(); + PopTrack(); + DoPush(); + Ldthis(); + Callvirt(_uncaptureM); + if (Operand(0) != -1 && Operand(1) != -1) + { + Ldthis(); + Callvirt(_uncaptureM); + } + Back(); + break; + + case RegexCode.Branchmark: + //: Stackframe(1); + //: + //: if (Textpos() != Stacked(0)) + //: { // Nonempty match -> loop now + //: Track(Stacked(0), Textpos()); // Save old mark, textpos + //: Stack(Textpos()); // Make new mark + //: Goto(Operand(0)); // Loop + //: } + //: else + //: { // Empty match -> straight now + //: Track2(Stacked(0)); // Save old mark + //: Advance(1); // Straight + //: } + //: continue Forward; + { + LocalBuilder mark = _tempV; + Label l1 = DefineLabel(); + + PopStack(); + Dup(); + Stloc(mark); // Stacked(0) -> temp + PushTrack(mark); + Ldloc(_textposV); + Beq(l1); // mark == textpos -> branch + + // (matched != 0) + + PushTrack(_textposV); + PushStack(_textposV); + Track(); + Goto(Operand(0)); // Goto(Operand(0)) + + // else + + MarkLabel(l1); + TrackUnique2(branchmarkback2); + break; + } + + case RegexCode.Branchmark | RegexCode.Back: + //: Trackframe(2); + //: Stackframe(1); + //: Textto(Tracked(1)); // Recall position + //: Track2(Tracked(0)); // Save old mark + //: Advance(1); + PopTrack(); + Stloc(_textposV); + PopStack(); + Pop(); + // track spot 0 is already in place + TrackUnique2(branchmarkback2); + Advance(); + break; + + case RegexCode.Branchmark | RegexCode.Back2: + //: Trackframe(1); + //: Stack(Tracked(0)); // Recall old mark + //: break Backward; // Backtrack + ReadyPushStack(); + PopTrack(); + DoPush(); + Back(); + break; + + + case RegexCode.Lazybranchmark: + //: Stackframe(1); + //: + //: if (Textpos() != Stacked(0)) + //: { // Nonempty match -> next loop + //: Track(Stacked(0), Textpos()); // Save old mark, textpos + //: } + //: else + //: { // Empty match -> no loop + //: Track2(Stacked(0)); // Save old mark + //: } + //: Advance(1); + //: continue Forward; + { + LocalBuilder mark = _tempV; + Label l1 = DefineLabel(); + + PopStack(); + Dup(); + Stloc(mark); // Stacked(0) -> temp + PushTrack(mark); + Ldloc(_textposV); + Beq(l1); // mark == textpos -> branch + + // (matched != 0) + + PushTrack(_textposV); + Track(); + Br(AdvanceLabel()); // Advance (near) + + // else + + MarkLabel(l1); + TrackUnique2(lazybranchmarkback2); + break; + } + + case RegexCode.Lazybranchmark | RegexCode.Back: + //: Trackframe(2); + //: Track2(Tracked(0)); // Save old mark + //: Stack(Textpos()); // Make new mark + //: Textto(Tracked(1)); // Recall position + //: Goto(Operand(0)); // Loop + + PopTrack(); + Stloc(_textposV); + PushStack(_textposV); + TrackUnique2(lazybranchmarkback2); + Goto(Operand(0)); + break; + + case RegexCode.Lazybranchmark | RegexCode.Back2: + //: Stackframe(1); + //: Trackframe(1); + //: Stack(Tracked(0)); // Recall old mark + //: break Backward; + ReadyReplaceStack(0); + PopTrack(); + DoReplace(); + Back(); + break; + + case RegexCode.Nullcount: + //: Stack(-1, Operand(0)); + //: Track(); + ReadyPushStack(); + Ldc(-1); + DoPush(); + ReadyPushStack(); + Ldc(Operand(0)); + DoPush(); + TrackUnique(stackpop2); + break; + + case RegexCode.Setcount: + //: Stack(Textpos(), Operand(0)); + //: Track(); + PushStack(_textposV); + ReadyPushStack(); + Ldc(Operand(0)); + DoPush(); + TrackUnique(stackpop2); + break; + + + case RegexCode.Nullcount | RegexCode.Back: + case RegexCode.Setcount | RegexCode.Back: + //: Stackframe(2); + //: break Backward; + PopDiscardStack(2); + Back(); + break; + + + case RegexCode.Branchcount: + //: Stackframe(2); + //: int mark = Stacked(0); + //: int count = Stacked(1); + //: + //: if (count >= Operand(1) || Textpos() == mark && count >= 0) + //: { // Max loops or empty match -> straight now + //: Track2(mark, count); // Save old mark, count + //: Advance(2); // Straight + //: } + //: else + //: { // Nonempty match -> count+loop now + //: Track(mark); // remember mark + //: Stack(Textpos(), count + 1); // Make new mark, incr count + //: Goto(Operand(0)); // Loop + //: } + //: continue Forward; + { + LocalBuilder count = _tempV; + LocalBuilder mark = _temp2V; + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + + PopStack(); + Stloc(count); // count -> temp + PopStack(); + Dup(); + Stloc(mark); // mark -> temp2 + PushTrack(mark); + + Ldloc(_textposV); + Bne(l1); // mark != textpos -> l1 + Ldloc(count); + Ldc(0); + Bge(l2); // count >= 0 && mark == textpos -> l2 + + MarkLabel(l1); + Ldloc(count); + Ldc(Operand(1)); + Bge(l2); // count >= Operand(1) -> l2 + + // else + PushStack(_textposV); + ReadyPushStack(); + Ldloc(count); // mark already on track + Ldc(1); + Add(); + DoPush(); + Track(); + Goto(Operand(0)); + + // if (count >= Operand(1) || Textpos() == mark) + MarkLabel(l2); + PushTrack(count); // mark already on track + TrackUnique2(branchcountback2); + break; + } + + case RegexCode.Branchcount | RegexCode.Back: + //: Trackframe(1); + //: Stackframe(2); + //: if (Stacked(1) > 0) // Positive -> can go straight + //: { + //: Textto(Stacked(0)); // Zap to mark + //: Track2(Tracked(0), Stacked(1) - 1); // Save old mark, old count + //: Advance(2); // Straight + //: continue Forward; + //: } + //: Stack(Tracked(0), Stacked(1) - 1); // recall old mark, old count + //: break Backward; + { + + LocalBuilder count = _tempV; + Label l1 = DefineLabel(); + PopStack(); + Ldc(1); + Sub(); + Dup(); + Stloc(count); + Ldc(0); + Blt(l1); + + // if (count >= 0) + PopStack(); + Stloc(_textposV); + PushTrack(count); // Tracked(0) is alredy on the track + TrackUnique2(branchcountback2); + Advance(); + + // else + MarkLabel(l1); + ReadyReplaceStack(0); + PopTrack(); + DoReplace(); + PushStack(count); + Back(); + break; + } + + case RegexCode.Branchcount | RegexCode.Back2: + //: Trackframe(2); + //: Stack(Tracked(0), Tracked(1)); // Recall old mark, old count + //: break Backward; // Backtrack + + PopTrack(); + Stloc(_tempV); + ReadyPushStack(); + PopTrack(); + DoPush(); + PushStack(_tempV); + Back(); + break; + + case RegexCode.Lazybranchcount: + //: Stackframe(2); + //: int mark = Stacked(0); + //: int count = Stacked(1); + //: + //: if (count < 0) + //: { // Negative count -> loop now + //: Track2(mark); // Save old mark + //: Stack(Textpos(), count + 1); // Make new mark, incr count + //: Goto(Operand(0)); // Loop + //: } + //: else + //: { // Nonneg count or empty match -> straight now + //: Track(mark, count, Textpos()); // Save mark, count, position + //: } + { + LocalBuilder count = _tempV; + LocalBuilder mark = _temp2V; + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + Label l3 = _labels[NextCodepos()]; + + PopStack(); + Stloc(count); // count -> temp + PopStack(); + Stloc(mark); // mark -> temp2 + + Ldloc(count); + Ldc(0); + Bge(l1); // count >= 0 -> l1 + + // if (count < 0) + PushTrack(mark); + PushStack(_textposV); + ReadyPushStack(); + Ldloc(count); + Ldc(1); + Add(); + DoPush(); + TrackUnique2(lazybranchcountback2); + Goto(Operand(0)); + + // else + MarkLabel(l1); + PushTrack(mark); + PushTrack(count); + PushTrack(_textposV); + Track(); + break; + } + + case RegexCode.Lazybranchcount | RegexCode.Back: + //: Trackframe(3); + //: int mark = Tracked(0); + //: int textpos = Tracked(2); + //: if (Tracked(1) <= Operand(1) && textpos != mark) + //: { + //: Textto(Tracked(2)); // Recall position + //: Stack(Textpos(), Tracked(1) + 1); // Make new mark, incr count + //: Track2(Tracked(0)); // Save old mark + //: Goto(Operand(0)); // Loop + //: continue Forward; + //: } + //: else + //: { + //: Stack(Tracked(0), Tracked(1)); // Recall old mark, count + //: break Backward; // backtrack + //: } + { + Label l1 = DefineLabel(); + LocalBuilder cV = _tempV; + PopTrack(); + Stloc(_textposV); + PopTrack(); + Dup(); + Stloc(cV); + Ldc(Operand(1)); + Bgt(l1); // Tracked(1) > Operand(1) -> l1 + + Ldloc(_textposV); + TopTrack(); + Beq(l1); // textpos == mark -> l1 + + PushStack(_textposV); + ReadyPushStack(); + Ldloc(cV); + Ldc(1); + Add(); + DoPush(); + TrackUnique2(lazybranchcountback2); + Goto(Operand(0)); + + MarkLabel(l1); + ReadyPushStack(); + PopTrack(); + DoPush(); + PushStack(cV); + Back(); + break; + } + + case RegexCode.Lazybranchcount | RegexCode.Back2: + //: Trackframe(1); + //: Stackframe(2); + //: Stack(Tracked(0), Stacked(1) - 1); // Recall old mark, count + //: break Backward; // Backtrack + + ReadyReplaceStack(1); + PopTrack(); + DoReplace(); + ReadyReplaceStack(0); + TopStack(); + Ldc(1); + Sub(); + DoReplace(); + Back(); + break; + + + case RegexCode.Setjump: + //: Stack(Trackpos(), Crawlpos()); + //: Track(); + ReadyPushStack(); + Ldthisfld(_trackF); + Ldlen(); + Ldloc(_trackposV); + Sub(); + DoPush(); + ReadyPushStack(); + Ldthis(); + Callvirt(_crawlposM); + DoPush(); + TrackUnique(stackpop2); + break; + + case RegexCode.Setjump | RegexCode.Back: + //: Stackframe(2); + PopDiscardStack(2); + Back(); + break; + + + case RegexCode.Backjump: + //: Stackframe(2); + //: Trackto(Stacked(0)); + //: while (Crawlpos() != Stacked(1)) + //: Uncapture(); + //: break Backward; + { + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + + PopStack(); + Ldthisfld(_trackF); + Ldlen(); + PopStack(); + Sub(); + Stloc(_trackposV); + Dup(); + Ldthis(); + Callvirt(_crawlposM); + Beq(l2); + + MarkLabel(l1); + Ldthis(); + Callvirt(_uncaptureM); + Dup(); + Ldthis(); + Callvirt(_crawlposM); + Bne(l1); + + MarkLabel(l2); + Pop(); + Back(); + break; + } + + case RegexCode.Forejump: + //: Stackframe(2); + //: Trackto(Stacked(0)); + //: Track(Stacked(1)); + PopStack(); + Stloc(_tempV); + Ldthisfld(_trackF); + Ldlen(); + PopStack(); + Sub(); + Stloc(_trackposV); + PushTrack(_tempV); + TrackUnique(forejumpback); + break; + + case RegexCode.Forejump | RegexCode.Back: + //: Trackframe(1); + //: while (Crawlpos() != Tracked(0)) + //: Uncapture(); + //: break Backward; + { + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + + PopTrack(); + + Dup(); + Ldthis(); + Callvirt(_crawlposM); + Beq(l2); + + MarkLabel(l1); + Ldthis(); + Callvirt(_uncaptureM); + Dup(); + Ldthis(); + Callvirt(_crawlposM); + Bne(l1); + + MarkLabel(l2); + Pop(); + Back(); + break; + } + + case RegexCode.Bol: + //: if (Leftchars() > 0 && CharAt(Textpos() - 1) != '\n') + //: break Backward; + { + Label l1 = _labels[NextCodepos()]; + Ldloc(_textposV); + Ldloc(_textbegV); + Ble(l1); + Leftchar(); + Ldc((int)'\n'); + BneFar(_backtrack); + break; + } + + case RegexCode.Eol: + //: if (Rightchars() > 0 && CharAt(Textpos()) != '\n') + //: break Backward; + { + Label l1 = _labels[NextCodepos()]; + Ldloc(_textposV); + Ldloc(_textendV); + Bge(l1); + Rightchar(); + Ldc((int)'\n'); + BneFar(_backtrack); + break; + } + + case RegexCode.Boundary: + case RegexCode.Nonboundary: + //: if (!IsBoundary(Textpos(), _textbeg, _textend)) + //: break Backward; + Ldthis(); + Ldloc(_textposV); + Ldloc(_textbegV); + Ldloc(_textendV); + Callvirt(_isboundaryM); + if (Code() == RegexCode.Boundary) + BrfalseFar(_backtrack); + else + BrtrueFar(_backtrack); + break; + + case RegexCode.ECMABoundary: + case RegexCode.NonECMABoundary: + //: if (!IsECMABoundary(Textpos(), _textbeg, _textend)) + //: break Backward; + Ldthis(); + Ldloc(_textposV); + Ldloc(_textbegV); + Ldloc(_textendV); + Callvirt(_isECMABoundaryM); + if (Code() == RegexCode.ECMABoundary) + BrfalseFar(_backtrack); + else + BrtrueFar(_backtrack); + break; + + case RegexCode.Beginning: + //: if (Leftchars() > 0) + //: break Backward; + Ldloc(_textposV); + Ldloc(_textbegV); + BgtFar(_backtrack); + break; + + case RegexCode.Start: + //: if (Textpos() != Textstart()) + //: break Backward; + Ldloc(_textposV); + Ldthisfld(_textstartF); + BneFar(_backtrack); + break; + + case RegexCode.EndZ: + //: if (Rightchars() > 1 || Rightchars() == 1 && CharAt(Textpos()) != '\n') + //: break Backward; + Ldloc(_textposV); + Ldloc(_textendV); + Ldc(1); + Sub(); + BltFar(_backtrack); + Ldloc(_textposV); + Ldloc(_textendV); + Bge(_labels[NextCodepos()]); + Rightchar(); + Ldc((int)'\n'); + BneFar(_backtrack); + break; + + case RegexCode.End: + //: if (Rightchars() > 0) + //: break Backward; + Ldloc(_textposV); + Ldloc(_textendV); + BltFar(_backtrack); + break; + + case RegexCode.One: + case RegexCode.Notone: + case RegexCode.Set: + case RegexCode.One | RegexCode.Rtl: + case RegexCode.Notone | RegexCode.Rtl: + case RegexCode.Set | RegexCode.Rtl: + case RegexCode.One | RegexCode.Ci: + case RegexCode.Notone | RegexCode.Ci: + case RegexCode.Set | RegexCode.Ci: + case RegexCode.One | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Notone | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Set | RegexCode.Ci | RegexCode.Rtl: + + //: if (Rightchars() < 1 || Rightcharnext() != (char)Operand(0)) + //: break Backward; + Ldloc(_textposV); + + if (!IsRtl()) + { + Ldloc(_textendV); + BgeFar(_backtrack); + Rightcharnext(); + } + else + { + Ldloc(_textbegV); + BleFar(_backtrack); + Leftcharnext(); + } + + if (IsCi()) + CallToLower(); + + if (Code() == RegexCode.Set) + { + + Ldstr(_strings[Operand(0)]); + Ldstr(_strings[Operand(1)]); + Call(_charInSetM); + + BrfalseFar(_backtrack); + } + else + { + Ldc(Operand(0)); + if (Code() == RegexCode.One) + BneFar(_backtrack); + else + BeqFar(_backtrack); + } + break; + + case RegexCode.Multi: + case RegexCode.Multi | RegexCode.Ci: + // + // + + //: String Str = _strings[Operand(0)]; + //: int i, c; + //: if (Rightchars() < (c = Str.Length)) + //: break Backward; + //: for (i = 0; c > 0; i++, c--) + //: if (Str[i] != Rightcharnext()) + //: break Backward; + { + int i; + String str; + + str = _strings[Operand(0)]; + + Ldc(str.Length); + Ldloc(_textendV); + Ldloc(_textposV); + Sub(); + BgtFar(_backtrack); + + // unroll the string + for (i = 0; i < str.Length; i++) + { + Ldloc(_textV); + Ldloc(_textposV); + if (i != 0) + { + Ldc(i); + Add(); + } + Callvirt(_getcharM); + if (IsCi()) + CallToLower(); + + Ldc((int)str[i]); + BneFar(_backtrack); + } + + Ldloc(_textposV); + Ldc(str.Length); + Add(); + Stloc(_textposV); + break; + } + + + case RegexCode.Multi | RegexCode.Rtl: + case RegexCode.Multi | RegexCode.Ci | RegexCode.Rtl: + //: String Str = _strings[Operand(0)]; + //: int c; + //: if (Leftchars() < (c = Str.Length)) + //: break Backward; + //: while (c > 0) + //: if (Str[--c] != Leftcharnext()) + //: break Backward; + { + int i; + String str; + + str = _strings[Operand(0)]; + + Ldc(str.Length); + Ldloc(_textposV); + Ldloc(_textbegV); + Sub(); + BgtFar(_backtrack); + + // unroll the string + for (i = str.Length; i > 0; ) + { + i--; + Ldloc(_textV); + Ldloc(_textposV); + Ldc(str.Length - i); + Sub(); + Callvirt(_getcharM); + if (IsCi()) + { + CallToLower(); + } + Ldc((int)str[i]); + BneFar(_backtrack); + } + + Ldloc(_textposV); + Ldc(str.Length); + Sub(); + Stloc(_textposV); + + break; + } + + case RegexCode.Ref: + case RegexCode.Ref | RegexCode.Rtl: + case RegexCode.Ref | RegexCode.Ci: + case RegexCode.Ref | RegexCode.Ci | RegexCode.Rtl: + //: int capnum = Operand(0); + //: int j, c; + //: if (!_match.IsMatched(capnum)) { + //: #if ECMA + //: if (!RegexOptions.ECMAScript) + //: #endif + //: break Backward; + //: } else { + //: if (Rightchars() < (c = _match.MatchLength(capnum))) + //: break Backward; + //: for (j = _match.MatchIndex(capnum); c > 0; j++, c--) + //: if (CharAt(j) != Rightcharnext()) + //: break Backward; + //: } + { + LocalBuilder lenV = _tempV; + LocalBuilder indexV = _temp2V; + Label l1 = DefineLabel(); + + Ldthis(); + Ldc(Operand(0)); + Callvirt(_ismatchedM); + if ((_options & RegexOptions.ECMAScript) != 0) + Brfalse(AdvanceLabel()); + else + BrfalseFar(_backtrack); // !IsMatched() -> back + + Ldthis(); + Ldc(Operand(0)); + Callvirt(_matchlengthM); + Dup(); + Stloc(lenV); + if (!IsRtl()) + { + Ldloc(_textendV); + Ldloc(_textposV); + } + else + { + Ldloc(_textposV); + Ldloc(_textbegV); + } + Sub(); + BgtFar(_backtrack); // Matchlength() > Rightchars() -> back + + Ldthis(); + Ldc(Operand(0)); + Callvirt(_matchindexM); + if (!IsRtl()) + { + Ldloc(lenV); + Add(IsRtl()); + } + Stloc(indexV); // index += len + + Ldloc(_textposV); + Ldloc(lenV); + Add(IsRtl()); + Stloc(_textposV); // texpos += len + + MarkLabel(l1); + Ldloc(lenV); + Ldc(0); + Ble(AdvanceLabel()); + Ldloc(_textV); + Ldloc(indexV); + Ldloc(lenV); + if (IsRtl()) + { + Ldc(1); + Sub(); + Dup(); + Stloc(lenV); + } + Sub(IsRtl()); + Callvirt(_getcharM); + if (IsCi()) + CallToLower(); + + Ldloc(_textV); + Ldloc(_textposV); + Ldloc(lenV); + if (!IsRtl()) + { + Dup(); + Ldc(1); + Sub(); + Stloc(lenV); + } + Sub(IsRtl()); + Callvirt(_getcharM); + if (IsCi()) + CallToLower(); + + Beq(l1); + Back(); + break; + } + + + case RegexCode.Onerep: + case RegexCode.Notonerep: + case RegexCode.Setrep: + case RegexCode.Onerep | RegexCode.Rtl: + case RegexCode.Notonerep | RegexCode.Rtl: + case RegexCode.Setrep | RegexCode.Rtl: + case RegexCode.Onerep | RegexCode.Ci: + case RegexCode.Notonerep | RegexCode.Ci: + case RegexCode.Setrep | RegexCode.Ci: + case RegexCode.Onerep | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Notonerep | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Setrep | RegexCode.Ci | RegexCode.Rtl: + //: int c = Operand(1); + //: if (Rightchars() < c) + //: break Backward; + //: char ch = (char)Operand(0); + //: while (c-- > 0) + //: if (Rightcharnext() != ch) + //: break Backward; + { + LocalBuilder lenV = _tempV; + Label l1 = DefineLabel(); + + int c = (Code() == RegexCode.Setrep) ? Operand(2) : Operand(1); + + if (c == 0) + break; + + Ldc(c); + if (!IsRtl()) + { + Ldloc(_textendV); + Ldloc(_textposV); + } + else + { + Ldloc(_textposV); + Ldloc(_textbegV); + } + Sub(); + BgtFar(_backtrack); // Matchlength() > Rightchars() -> back + + Ldloc(_textposV); + Ldc(c); + Add(IsRtl()); + Stloc(_textposV); // texpos += len + + Ldc(c); + Stloc(lenV); + + MarkLabel(l1); + Ldloc(_textV); + Ldloc(_textposV); + Ldloc(lenV); + if (IsRtl()) + { + Ldc(1); + Sub(); + Dup(); + Stloc(lenV); + Add(); + } + else + { + Dup(); + Ldc(1); + Sub(); + Stloc(lenV); + Sub(); + } + Callvirt(_getcharM); + if (IsCi()) + CallToLower(); + + if (Code() == RegexCode.Setrep) + { + Ldstr(_strings[Operand(0)]); + Ldstr(_strings[Operand(1)]); + Call(_charInSetM); + + BrfalseFar(_backtrack); + } + else + { + Ldc(Operand(0)); + if (Code() == RegexCode.Onerep) + BneFar(_backtrack); + else + BeqFar(_backtrack); + } + Ldloc(lenV); + Ldc(0); + if (Code() == RegexCode.Setrep) + BgtFar(l1); + else + Bgt(l1); + break; + } + + + case RegexCode.Oneloop: + case RegexCode.Notoneloop: + case RegexCode.Setloop: + case RegexCode.Oneloop | RegexCode.Rtl: + case RegexCode.Notoneloop | RegexCode.Rtl: + case RegexCode.Setloop | RegexCode.Rtl: + case RegexCode.Oneloop | RegexCode.Ci: + case RegexCode.Notoneloop | RegexCode.Ci: + case RegexCode.Setloop | RegexCode.Ci: + case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl: + //: int c = Operand(1); + //: if (c > Rightchars()) + //: c = Rightchars(); + //: char ch = (char)Operand(0); + //: int i; + //: for (i = c; i > 0; i--) + //: { + //: if (Rightcharnext() != ch) + //: { + //: Leftnext(); + //: break; + //: } + //: } + //: if (c > i) + //: Track(c - i - 1, Textpos() - 1); + { + LocalBuilder cV = _tempV; + LocalBuilder lenV = _temp2V; + Label l1 = DefineLabel(); + Label l2 = DefineLabel(); + + int c = (Code() == RegexCode.Setloop) ? Operand(2) : Operand(1); + + if (c == 0) + break; + if (!IsRtl()) + { + Ldloc(_textendV); + Ldloc(_textposV); + } + else + { + Ldloc(_textposV); + Ldloc(_textbegV); + } + Sub(); + if (c != infinite) + { + Label l4 = DefineLabel(); + Dup(); + Ldc(c); + Blt(l4); + Pop(); + Ldc(c); + MarkLabel(l4); + } + Dup(); + Stloc(lenV); + Ldc(1); + Add(); + Stloc(cV); + + MarkLabel(l1); + Ldloc(cV); + Ldc(1); + Sub(); + Dup(); + Stloc(cV); + Ldc(0); + if (Code() == RegexCode.Setloop) + BleFar(l2); + else + Ble(l2); + + if (IsRtl()) + Leftcharnext(); + else + Rightcharnext(); + if (IsCi()) + CallToLower(); + + if (Code() == RegexCode.Setloop) + { + Ldstr(_strings[Operand(0)]); + Ldstr(_strings[Operand(1)]); + Call(_charInSetM); + + BrtrueFar(l1); + } + else + { + Ldc(Operand(0)); + if (Code() == RegexCode.Oneloop) + Beq(l1); + else + Bne(l1); + } + + Ldloc(_textposV); + Ldc(1); + Sub(IsRtl()); + Stloc(_textposV); + + MarkLabel(l2); + Ldloc(lenV); + Ldloc(cV); + Ble(AdvanceLabel()); + + ReadyPushTrack(); + Ldloc(lenV); + Ldloc(cV); + Sub(); + Ldc(1); + Sub(); + DoPush(); + + ReadyPushTrack(); + Ldloc(_textposV); + Ldc(1); + Sub(IsRtl()); + DoPush(); + + Track(); + break; + } + + case RegexCode.Oneloop | RegexCode.Back: + case RegexCode.Notoneloop | RegexCode.Back: + case RegexCode.Setloop | RegexCode.Back: + case RegexCode.Oneloop | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Notoneloop | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Setloop | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Back: + case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Back: + case RegexCode.Setloop | RegexCode.Ci | RegexCode.Back: + case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back: + //: Trackframe(2); + //: int i = Tracked(0); + //: int pos = Tracked(1); + //: Textto(pos); + //: if (i > 0) + //: Track(i - 1, pos - 1); + //: Advance(2); + PopTrack(); + Stloc(_textposV); + PopTrack(); + Stloc(_tempV); + Ldloc(_tempV); + Ldc(0); + BleFar(AdvanceLabel()); + ReadyPushTrack(); + Ldloc(_tempV); + Ldc(1); + Sub(); + DoPush(); + ReadyPushTrack(); + Ldloc(_textposV); + Ldc(1); + Sub(IsRtl()); + DoPush(); + Trackagain(); + Advance(); + break; + + case RegexCode.Onelazy: + case RegexCode.Notonelazy: + case RegexCode.Setlazy: + case RegexCode.Onelazy | RegexCode.Rtl: + case RegexCode.Notonelazy | RegexCode.Rtl: + case RegexCode.Setlazy | RegexCode.Rtl: + case RegexCode.Onelazy | RegexCode.Ci: + case RegexCode.Notonelazy | RegexCode.Ci: + case RegexCode.Setlazy | RegexCode.Ci: + case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl: + case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl: + //: int c = Operand(1); + //: if (c > Rightchars()) + //: c = Rightchars(); + //: if (c > 0) + //: Track(c - 1, Textpos()); + { + LocalBuilder cV = _tempV; + + int c = (Code() == RegexCode.Setlazy) ? Operand(2) : Operand(1); + + if (c == 0) + break; + + if (!IsRtl()) + { + Ldloc(_textendV); + Ldloc(_textposV); + } + else + { + Ldloc(_textposV); + Ldloc(_textbegV); + } + Sub(); + if (c != infinite) + { + Label l4 = DefineLabel(); + Dup(); + Ldc(c); + Blt(l4); + Pop(); + Ldc(c); + MarkLabel(l4); + } + Dup(); + Stloc(cV); + Ldc(0); + Ble(AdvanceLabel()); + ReadyPushTrack(); + Ldloc(cV); + Ldc(1); + Sub(); + DoPush(); + PushTrack(_textposV); + Track(); + break; + } + + case RegexCode.Onelazy | RegexCode.Back: + case RegexCode.Notonelazy | RegexCode.Back: + case RegexCode.Setlazy | RegexCode.Back: + case RegexCode.Onelazy | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Notonelazy | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Setlazy | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Back: + case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Back: + case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Back: + case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back: + case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back: + //: Trackframe(2); + //: int pos = Tracked(1); + //: Textto(pos); + //: if (Rightcharnext() != (char)Operand(0)) + //: break Backward; + //: int i = Tracked(0); + //: if (i > 0) + //: Track(i - 1, pos + 1); + + PopTrack(); + Stloc(_textposV); + PopTrack(); + Stloc(_temp2V); + + if (!IsRtl()) + Rightcharnext(); + else + Leftcharnext(); + + if (IsCi()) + CallToLower(); + + if (Code() == RegexCode.Setlazy) + { + Ldstr(_strings[Operand(0)]); + Ldstr(_strings[Operand(1)]); + Call(_charInSetM); + + BrfalseFar(_backtrack); + } + else + { + Ldc(Operand(0)); + if (Code() == RegexCode.Onelazy) + BneFar(_backtrack); + else + BeqFar(_backtrack); + } + + Ldloc(_temp2V); + Ldc(0); + BleFar(AdvanceLabel()); + ReadyPushTrack(); + Ldloc(_temp2V); + Ldc(1); + Sub(); + DoPush(); + PushTrack(_textposV); + Trackagain(); + Advance(); + break; + + default: + throw new NotImplementedException(SR.GetString(SR.UnimplementedState)); + } + } + } + +} + diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs new file mode 100644 index 0000000000..e95d1bb966 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Common.cs @@ -0,0 +1,58 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + public static class Common + { + static public bool Debug = true; + + public delegate void SendToDebugEventDelegate(string Message); + public delegate void SendToLogEventDelegate(string Message); + static public event SendToDebugEventDelegate SendToDebugEvent; + static public event SendToLogEventDelegate SendToLogEvent; + + static public void SendToDebug(string Message) + { + //if (Debug == true) + Console.WriteLine("SE:Debug: " + Message); + //SendToDebugEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + static public void SendToLog(string Message) + { + //if (Debug == true) + Console.WriteLine("SE:LOG: " + Message); + //SendToLogEvent("\r\n" + DateTime.Now.ToString("[HH:mm:ss] ") + Message); + } + } + +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs new file mode 100644 index 0000000000..46b898a37f --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs @@ -0,0 +1,99 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + /// + /// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it. + /// + class EventManager + { + private ScriptEngine myScriptEngine; + public EventManager(ScriptEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + // TODO: HOOK EVENTS UP TO SERVER! + Common.SendToDebug("EventManager Start"); + + // Hook up a test event to our test form + Common.SendToDebug("EventManager Hooking up dummy-event: touch_start"); + myScriptEngine.World.touch_start += new TempWorldInterfaceEventDelegates.touch_start(touch_start); + } + + public void touch_start(string ObjectID) + { + // Add to queue for all scripts in ObjectID object + Common.SendToDebug("EventManager Event: touch_start"); + myScriptEngine.myEventQueueManager.AddToObjectQueue(ObjectID, "touch_start", new object[] { (UInt32)0 }); + } + + + // TODO: Replace placeholders below + // These needs to be hooked up to OpenSim during init of this class + // then queued in EventQueueManager. + // When queued in EventQueueManager they need to be LSL compatible (name and params) + public void state_entry() { } + public void state_exit() { } + //public void touch_start() { } + public void touch() { } + public void touch_end() { } + public void collision_start() { } + public void collision() { } + public void collision_end() { } + public void land_collision_start() { } + public void land_collision() { } + public void land_collision_end() { } + public void timer() { } + public void listen() { } + public void on_rez() { } + public void sensor() { } + public void no_sensor() { } + public void control() { } + public void money() { } + public void email() { } + public void at_target() { } + public void not_at_target() { } + public void at_rot_target() { } + public void not_at_rot_target() { } + public void run_time_permissions() { } + public void changed() { } + public void attach() { } + public void dataserver() { } + public void link_message() { } + public void moving_start() { } + public void moving_end() { } + public void object_rez() { } + public void remote_data() { } + public void http_response() { } + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs new file mode 100644 index 0000000000..59f669be7c --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs @@ -0,0 +1,136 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Reflection; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + class EventQueueManager + { + private Thread EventQueueThread; + private int NothingToDoSleepms = 200; + private Queue EventQueue = new Queue(); + private struct QueueItemStruct + { + public string ObjectID; + public string ScriptID; + public string FunctionName; + public object[] param; + } + + private ScriptEngine myScriptEngine; + public EventQueueManager(ScriptEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + Common.SendToDebug("EventQueueManager Start"); + // Start worker thread + EventQueueThread = new Thread(EventQueueThreadLoop); + EventQueueThread.IsBackground = true; + EventQueueThread.Name = "EventQueueManagerThread"; + EventQueueThread.Start(); + } + ~EventQueueManager() + { + // Kill worker thread + if (EventQueueThread != null && EventQueueThread.IsAlive == true) + { + try + { + EventQueueThread.Abort(); + EventQueueThread.Join(); + } + catch (Exception e) + { + Common.SendToDebug("EventQueueManager Exception killing worker thread: " + e.ToString()); + } + } + // Todo: Clean up our queues + + } + + private void EventQueueThreadLoop() + { + Common.SendToDebug("EventQueueManager Worker thread spawned"); + try + { + while (true) + { + if (EventQueue.Count == 0) + { + // Nothing to do? Sleep a bit waiting for something to do + Thread.Sleep(NothingToDoSleepms); + } + else + { + // Something in queue, process + QueueItemStruct QIS = EventQueue.Dequeue(); + Common.SendToDebug("Processing event for ObjectID: " + QIS.ObjectID + ", ScriptID: " + QIS.ScriptID + ", FunctionName: " + QIS.FunctionName); + // TODO: Execute function + myScriptEngine.myScriptManager.ExecuteFunction(QIS.ObjectID, QIS.ScriptID, QIS.FunctionName, QIS.param); + } + } + } + catch (ThreadAbortException tae) + { + Common.SendToDebug("EventQueueManager Worker thread killed: " + tae.Message); + } + } + + public void AddToObjectQueue(string ObjectID, string FunctionName, object[] param) + { + // Determine all scripts in Object and add to their queue + Common.SendToDebug("EventQueueManager Adding ObjectID: " + ObjectID + ", FunctionName: " + FunctionName); + + foreach (string ScriptID in myScriptEngine.myScriptManager.GetScriptKeys(ObjectID)) + { + // Add to each script in that object + // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? + + // Create a structure and add data + QueueItemStruct QIS = new QueueItemStruct(); + QIS.ObjectID = ObjectID; + QIS.ScriptID = ScriptID; + QIS.FunctionName = FunctionName; + QIS.param = param; + + // Add it to queue + EventQueue.Enqueue(QIS); + + } + } + //public void AddToScriptQueue(string ObjectID, string FunctionName, object[] param) + //{ + // // Add to script queue + //} + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.csproj b/OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.csproj new file mode 100644 index 0000000000..b9ea871bae --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.csproj @@ -0,0 +1,59 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {8D47DF28-AAC4-47AB-9A6D-9A104A115817} + Library + Properties + OpenSim.Region.ScriptEngine.DotNetEngine + OpenSim.Region.ScriptEngine.DotNetEngine + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + {E56CB0C4-DBE8-4169-AC21-B6A2E8235A82} + OpenSim.ScriptEngine.DotNetEngine.Compiler.LSL + + + + + \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.suo b/OpenSim/Region/ScriptEngine/DotNetEngine/OpenSim.Region.ScriptEngine.DotNetEngine.suo new file mode 100644 index 0000000000000000000000000000000000000000..58ef5c2c5d66d629c7605686e07710b23d5ce63b GIT binary patch literal 5120 zcmeHKOKVe65S}zv?Mqu9QERQ;xe>uvEiQyovkna2#O041QkIMsgH$J1kw5jTnjdS-?{fRA-TDpviF^e^Q%ypOuS@()6h667vu!A zPoNi-tImR98$lH+j*j6rLHSZJAXBjVlBA)Zn35rkW5A^J7zpc^am*UP{AY+bZUk)tHoM~upc{eoA=fv7 zZU$~~#}UwN!0qn19dxJL-v!zU-0hCBy$1i#1I@Rs#@I*cy>shc=a<({8M>B z8AH}2C64^fNCLIwBywp2Gh;F!mq9bqkCu6L1=N(t3O0*SYbLYQ6Ay)!DCO{%HQ^aJ7}Y{9eoj)_&(@W%k*KcN#Q{ zOzK6;?6YJXIWdj=to;5RDmS-mhVKvG3cerAo-ziH33~mlJMX9eu*crgDeBi*YpTBm zLKY14A1qboF32yx>*zaxi?9847Z_aY8 zE_h%zu<`H1t+w#v7le-V{p;sLI#Zl%c@o(37r)=$5xhGZ|G@9?l|<05{_Zb?xnhs? xrsc7Xr@ literal 0 HcmV?d00001 diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..aa76b6a691 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.DotNetEngine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenSim.Region.ScriptEngine.DotNetEngine")] +[assembly: AssemblyCopyright("Copyright © 2007")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2842257e-6fde-4460-9368-4cde57fa9cc4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs new file mode 100644 index 0000000000..35afaf7f70 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs @@ -0,0 +1,77 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + public class ScriptEngine : ScriptEngineInterface + { + // + // This is the root object for ScriptEngine + // + + internal TempWorldInterface World; + internal EventManager myEventManager; // Handles and queues incoming events from OpenSim + internal EventQueueManager myEventQueueManager; // Executes events + internal ScriptManager myScriptManager; // Load, unload and execute scripts + + public ScriptEngine() + { + Common.SendToDebug("ScriptEngine Object Initialized"); + } + + public void InitializeEngine(TempWorldInterface Sceneworld) + { + World = Sceneworld; + Common.SendToDebug("ScriptEngine InitializeEngine()"); + + // Create all objects we'll be using + myEventQueueManager = new EventQueueManager(this); + myEventManager = new EventManager(this); + myScriptManager = new ScriptManager(this); + + // Should we iterate the region for scripts that needs starting? + // Or can we assume we are loaded before anything else so we can use proper events? + } + public void Shutdown() + { + // We are shutting down + } + + // !!!FOR DEBUGGING ONLY!!! (for executing script directly from test app) + [Obsolete("!!!FOR DEBUGGING ONLY!!!")] + public void StartScript(string ScriptID, string ObjectID) + { + Common.SendToDebug("ScriptEngine DEBUG: StartScript: " + ScriptID); + myScriptManager.StartScript(ScriptID, ObjectID); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngineInterface.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngineInterface.cs new file mode 100644 index 0000000000..c561523b41 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngineInterface.cs @@ -0,0 +1,40 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + interface ScriptEngineInterface + { + void InitializeEngine(TempWorldInterface Sceneworld); + void Shutdown(); + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs new file mode 100644 index 0000000000..f2080ebb84 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs @@ -0,0 +1,232 @@ +/* +* Copyright (c) Contributors, http://www.openmetaverse.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +/* Original code: Tedd Hansen */ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Reflection; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + class ScriptManager + { + + private ScriptEngine myScriptEngine; + public ScriptManager(ScriptEngine _ScriptEngine) + { + myScriptEngine = _ScriptEngine; + Common.SendToDebug("ScriptManager Start"); + } + + + // Object> + internal Dictionary> Scripts = new Dictionary>(); + + + internal Dictionary.KeyCollection GetScriptKeys(string ObjectID) + { + if (Scripts.ContainsKey(ObjectID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(ObjectID, out Obj); + + return Obj.Keys; + + } + + internal OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass GetScript(string ObjectID, string ScriptID) + { + if (Scripts.ContainsKey(ObjectID) == false) + return null; + + Dictionary Obj; + Scripts.TryGetValue(ObjectID, out Obj); + if (Obj.ContainsKey(ScriptID) == false) + return null; + + // Get script + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script; + Obj.TryGetValue(ScriptID, out Script); + + return Script; + + } + internal void SetScript(string ObjectID, string ScriptID, OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script) + { + // Create object if it doesn't exist + if (Scripts.ContainsKey(ObjectID) == false) + Scripts.Add(ObjectID, new Dictionary()); + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(ObjectID, out Obj); + if (Obj.ContainsKey(ScriptID) == true) + Obj.Remove(ScriptID); + + // Add to object + Obj.Add(ScriptID, Script); + + } + + /// + /// Fetches, loads and hooks up a script to an objects events + /// + /// + /// + public void StartScript(string ScriptID, string ObjectID) + { + Common.SendToDebug("ScriptManager StartScript: ScriptID: " + ScriptID + ", ObjectID: " + ObjectID); + + // We will initialize and start the script. + // It will be up to the script itself to hook up the correct events. + string FileName; + + // * Fetch script from server + // DEBUG - ScriptID is an actual filename during debug + // (therefore we can also check type by looking at extension) + FileName = ScriptID; + + // * Does script need compile? Send it to LSL compiler first. (TODO: Use (and clean) compiler cache) + if (FileName.ToLower().EndsWith(".lso")) + { + Common.SendToDebug("ScriptManager Script is LSO, compiling to .Net Assembly"); + // Create a new instance of the compiler (currently we don't want reuse) + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Engine LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Engine(); + // Compile + FileName = LSLCompiler.Compile(FileName); + } + + // * Insert yield into code + FileName = ProcessYield(FileName); + + // * Find next available AppDomain to put it in + AppDomain FreeAppDomain = GetFreeAppDomain(); + + // * Load and start script + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName); + string FullScriptID = ScriptID + "." + ObjectID; + // Add it to our temporary active script keeper + //Scripts.Add(FullScriptID, Script); + SetScript(ObjectID, ScriptID, Script); + // We need to give (untrusted) assembly a private instance of BuiltIns + // this private copy will contain Read-Only FullScriptID so that it can bring that on to the server whenever needed. + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BuiltIn_Commands_Interface LSLB = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BuiltIn_Commands_TestImplementation(FullScriptID); + // Start the script - giving it BuiltIns + Common.SendToDebug("ScriptManager initializing script, handing over private builtin command interface"); + Script.Start(LSLB); + + + } + private string ProcessYield(string FileName) + { + // TODO: Create a new assembly and copy old but insert Yield Code + return FileName; + } + + private AppDomain GetFreeAppDomain() + { + // TODO: Find an available AppDomain - if none, create one and add default security + return Thread.GetDomain(); + } + + /// + /// Does actual loading and initialization of script Assembly + /// + /// AppDomain to load script into + /// FileName of script assembly (.dll) + /// + private OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass LoadAndInitAssembly(AppDomain FreeAppDomain, string FileName) + { + Common.SendToDebug("ScriptManager Loading Assembly " + FileName); + // Load .Net Assembly (.dll) + // Initialize and return it + + // TODO: Add error handling + // Script might not follow our rules since users can upload -anything- + + Assembly a; + //try + //{ + + + // Load to default appdomain (temporary) + a = Assembly.LoadFrom(FileName); + // Load to specified appdomain + // TODO: Insert security + //a = FreeAppDomain.Load(FileName); + //} + //catch (Exception e) + //{ + //} + + + foreach (Type _t in a.GetTypes()) + { + Console.WriteLine("Type: " + _t.ToString()); + } + + Type t; + //try + //{ + t = a.GetType("LSL_ScriptObject", true); + //} + //catch (Exception e) + //{ + //} + + return (OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass)Activator.CreateInstance(t); + + + } + + internal void ExecuteFunction(string ObjectID, string ScriptID, string FunctionName, object[] args) + { + Common.SendToDebug("Executing Function ObjectID: " + ObjectID + ", ScriptID: " + ScriptID + ", FunctionName: " + FunctionName); + OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = myScriptEngine.myScriptManager.GetScript(ObjectID, ScriptID); + + Type type = Script.GetType(); + //object o = (object)Script; + + //System.Collections.Generic.List Functions = (System.Collections.Generic.List) + //Type type = typeof(OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass); + Common.SendToDebug("Invoke: \"" + Script.State + "_event_" + FunctionName + "\""); + type.InvokeMember(Script.State + "_event_" + FunctionName, BindingFlags.InvokeMethod, null, Script, args); + //System.Collections.Generic.List Functions = (System.Collections.Generic.List)type.InvokeMember("GetFunctions", BindingFlags.InvokeMethod, null, Script, null); + + + //foreach (MemberInfo mi in type.GetMembers()) + //{ + // Common.SendToDebug("Member found: " + mi.ToString()); + //} + + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/TempWorldInterface.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/TempWorldInterface.cs new file mode 100644 index 0000000000..6ba6c07b71 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/TempWorldInterface.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.Region.ScriptEngine.DotNetEngine +{ + public class TempWorldInterfaceEventDelegates + { + public delegate void touch_start(string ObjectID); + } + public interface TempWorldInterface + { + event TempWorldInterfaceEventDelegates.touch_start touch_start; + } +}