/* * Copyright (c) Contributors, http://opensimulator.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; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Text; namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSO { internal 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 List EventList = new 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 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 (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 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); } } } }