293 lines
12 KiB
C#
293 lines
12 KiB
C#
/*
|
|
* 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.IO;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using OpenSim.Region.ScriptEngine.Common;
|
|
using OpenSim.Region.ScriptEngine.LSOEngine.LSO;
|
|
|
|
namespace OpenSim.Region.ScriptEngine.LSOEngine.LSO
|
|
{
|
|
public class Engine
|
|
{
|
|
//private string LSO_FileName = @"LSO\AdditionTest.lso";
|
|
private string LSO_FileName; // = @"LSO\CloseToDefault.lso";
|
|
private 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 = Path.GetFileNameWithoutExtension(LSO_FileName);
|
|
//asmName.Name = "TestAssembly";
|
|
|
|
string DLL_FileName = asmName.Name + ".dll";
|
|
string DLL_FileName_WithPath = Path.GetDirectoryName(LSO_FileName) + @"\" + DLL_FileName;
|
|
|
|
LSOEngine.LSO.Common.SendToLog("LSO File Name: " + Path.GetFileName(LSO_FileName));
|
|
LSOEngine.LSO.Common.SendToLog("Assembly name: " + asmName.Name);
|
|
LSOEngine.LSO.Common.SendToLog("Assembly File Name: " + asmName.Name + ".dll");
|
|
LSOEngine.LSO.Common.SendToLog("Starting processing of LSL ByteCode...");
|
|
LSOEngine.LSO.Common.SendToLog(String.Empty);
|
|
|
|
|
|
// 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 \String.Empty + asmName.Name + "\String.Empty);
|
|
// Create a Class (/Type)
|
|
TypeBuilder typeBuilder = modBuilder.DefineType(
|
|
"LSL_ScriptObject",
|
|
TypeAttributes.Public | TypeAttributes.BeforeFieldInit,
|
|
typeof (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 (LSOEngine.LSO.Common.IL_CreateConstructor)
|
|
IL_CREATE_CONSTRUCTOR(typeBuilder, LSOP);
|
|
|
|
LSOP.CloseFile();
|
|
/*
|
|
* Done generating. Create a type and run it.
|
|
*/
|
|
|
|
|
|
LSOEngine.LSO.Common.SendToLog("Attempting to compile assembly...");
|
|
// Compile it
|
|
Type type = typeBuilder.CreateType();
|
|
LSOEngine.LSO.Common.SendToLog("Compilation successful!");
|
|
|
|
LSOEngine.LSO.Common.SendToLog("Saving assembly: " + DLL_FileName);
|
|
asmBuilder.Save(DLL_FileName);
|
|
|
|
LSOEngine.LSO.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<string> Functions = (System.Collections.Generic.List<string>)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(String.Empty);
|
|
// 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)
|
|
{
|
|
LSOEngine.LSO.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
|
|
LSOEngine.LSO.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, 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
|
|
}
|
|
} |