Added OpenSim.32BitLaunch.exe that can be used on 64-bit systems to run OpenSim in 32-bit mode.

Added VISUAL BASIC.NET-support
//cs, //lsl and //vb as first characters of script will determine what compiler is used.
Compile warnings are no longer treated as errors. Script will still run.
Added a few useless and useful config options:
Write script source to harddisk for debug, Default compile language, Allowed compilers (languages), compile in release or debug mode, clean up old scripts on startup
Loads of warnings for incorrect config
ThreadPoolClientBranch
Tedd Hansen 2008-02-02 02:35:56 +00:00
parent 667197f24d
commit 8ccc12d642
4 changed files with 256 additions and 38 deletions

View File

@ -58,6 +58,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// </summary>
private void StopMaintenanceThread()
{
#if DEBUG
m_ScriptEngine.Log.Debug(m_ScriptEngine.ScriptEngineName, "StopMaintenanceThread() called");
#endif
PleaseShutdown = true;
Thread.Sleep(100);
try
{
if (MaintenanceThreadThread != null)
@ -70,7 +75,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
}
catch (Exception ex)
{
m_ScriptEngine.Log.Error("EventQueueManager", "Exception stopping maintenence thread: " + ex.ToString());
m_ScriptEngine.Log.Error(m_ScriptEngine.ScriptEngineName, "Exception stopping maintenence thread: " + ex.ToString());
}
}

View File

@ -28,9 +28,12 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
{
@ -44,45 +47,192 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
// Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details.
//
private LSL2CSConverter LSL_Converter = new LSL2CSConverter();
private CSharpCodeProvider codeProvider = new CSharpCodeProvider();
internal enum enumCompileType
{
lsl = 0,
cs = 1,
vb = 2
}
private enumCompileType DefaultCompileLanguage;
private bool WriteScriptSourceToDebugFile;
private bool CompileWithDebugInformation;
private bool CleanUpOldScriptsOnStartup;
private System.Collections.Generic.Dictionary<string, Boolean> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
private System.Collections.Generic.Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
private string FilePrefix;
private string ScriptEnginesPath = "ScriptEngines";
private static LSL2CSConverter LSL_Converter = new LSL2CSConverter();
private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
private static VBCodeProvider VBcodeProvider = new VBCodeProvider();
private static UInt64 scriptCompileCounter = 0;
private static int instanceID = new Random().Next(0, int.MaxValue);
// Implemented due to peer preassure --- will cause garbage in ScriptEngines folder ;)
// Implemented due to peer preassure --- will cause garbage in ScriptEngines folder ;)
//private ICodeCompiler icc = codeProvider.CreateCompiler();
public string CompileFromFile(string LSOFileName)
public Common.ScriptEngineBase.ScriptEngine m_scriptEngine;
public Compiler(Common.ScriptEngineBase.ScriptEngine scriptEngine)
{
switch (Path.GetExtension(LSOFileName).ToLower())
{
case ".txt":
case ".lsl":
Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS");
return CompileFromLSLText(File.ReadAllText(LSOFileName));
case ".cs":
Common.ScriptEngineBase.Common.SendToDebug("Source code is CS");
return CompileFromCSText(File.ReadAllText(LSOFileName));
default:
throw new Exception("Unknown script type.");
}
m_scriptEngine = scriptEngine;
ReadConfig();
}
public bool in_startup = true;
public void ReadConfig()
{
WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true);
CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true);
CleanUpOldScriptsOnStartup = m_scriptEngine.ScriptConfigSource.GetBoolean("CleanUpOldScriptsOnStartup", true);
// Get file prefix from scriptengine name and make it file system safe:
FilePrefix = m_scriptEngine.ScriptEngineName;
foreach (char c in Path.GetInvalidFileNameChars())
{
FilePrefix = FilePrefix.Replace(c, '_');
}
// First time we start?
if (in_startup)
{
in_startup = false;
DeleteOldFiles();
}
LanguageMapping.Add("cs", enumCompileType.cs);
LanguageMapping.Add("vb", enumCompileType.lsl);
LanguageMapping.Add("lsl", enumCompileType.vb);
// Allowed compilers
string allowedCompilers = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl;cs;vb");
AllowedCompilers.Clear();
foreach (string strl in allowedCompilers.Split(';'))
{
string strlan = strl.Trim(" \t".ToCharArray()).ToLower();
if (!LanguageMapping.ContainsKey(strlan))
{
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Config error. Compiler is unable to recongnize language type \"" + strl + "\" specified in \"AllowedCompilers\".");
}
AllowedCompilers.Add(strlan, true);
}
if (AllowedCompilers.Count == 0)
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!");
// Default language
string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower();
// Is this language recognized at all?
if (!LanguageMapping.ContainsKey(defaultCompileLanguage))
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Config error. Default language specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Scripts may not be executed!");
// Is this language in allow-list?
if (!AllowedCompilers.ContainsKey(defaultCompileLanguage))
{
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName,
"Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!");
}
else
{
// LANGUAGE IS IN ALLOW-LIST
DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage];
}
// We now have an allow-list, a mapping list, and a default language
}
private void DeleteOldFiles()
{
// CREATE FOLDER IF IT DOESNT EXIST
if (!Directory.Exists(ScriptEnginesPath))
{
try
{
Directory.CreateDirectory(ScriptEnginesPath);
}
catch (Exception ex)
{
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString());
}
}
foreach (string file in Directory.GetFiles(ScriptEnginesPath))
{
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "FILE FOUND: " + file);
if (file.ToLower().StartsWith(FilePrefix + "_compiled_") ||
file.ToLower().StartsWith(FilePrefix + "_source_"))
{
try
{
File.Delete(file);
}
catch (Exception ex)
{
m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Exception trying delete old script file \"" + file + "\": " + ex.ToString());
}
}
}
}
////private ICodeCompiler icc = codeProvider.CreateCompiler();
//public string CompileFromFile(string LSOFileName)
//{
// switch (Path.GetExtension(LSOFileName).ToLower())
// {
// case ".txt":
// case ".lsl":
// Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS");
// return CompileFromLSLText(File.ReadAllText(LSOFileName));
// case ".cs":
// Common.ScriptEngineBase.Common.SendToDebug("Source code is CS");
// return CompileFromCSText(File.ReadAllText(LSOFileName));
// default:
// throw new Exception("Unknown script type.");
// }
//}
/// <summary>
/// Converts script from LSL to CS and calls CompileFromCSText
/// </summary>
/// <param name="Script">LSL script</param>
/// <returns>Filename to .dll assembly</returns>
public string CompileFromLSLText(string Script)
public string PerformScriptCompile(string Script)
{
if (Script.Substring(0, 4).ToLower() == "//c#")
enumCompileType l = DefaultCompileLanguage;
if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
l = enumCompileType.cs;
if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
l = enumCompileType.vb;
if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
l = enumCompileType.lsl;
if (!AllowedCompilers.ContainsKey(l.ToString()))
{
return CompileFromCSText(Script);
// Not allowed to compile to this language!
string errtext = String.Empty;
errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!";
throw new Exception(errtext);
}
string compileScript;
if (l == enumCompileType.lsl)
{
// Its LSL, convert it to C#
compileScript = LSL_Converter.Convert(Script);
l = enumCompileType.cs;
}
else
{
return CompileFromCSText(LSL_Converter.Convert(Script));
// We don't need to convert
compileScript = Script;
}
return CompileFromCSorVBText(Script, l);
}
/// <summary>
@ -90,36 +240,45 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
/// </summary>
/// <param name="Script">CS script</param>
/// <returns>Filename to .dll assembly</returns>
public string CompileFromCSText(string Script)
internal string CompileFromCSorVBText(string Script, enumCompileType lang)
{
string ext = "." + lang.ToString();
// Output assembly name
scriptCompileCounter++;
string OutFile =
Path.Combine("ScriptEngines",
"DotNetScript_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll");
FilePrefix + "_compiled_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll");
try
{
File.Delete(OutFile);
}
catch (Exception e)
{
Console.WriteLine("Exception attempting to delete old compiled script: " + e.ToString());
//m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
}
//string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
// DEBUG - write source to disk
try
{
File.WriteAllText(
Path.Combine("ScriptEngines", "debug_" + Path.GetFileNameWithoutExtension(OutFile) + ".cs"), Script);
}
catch
if (WriteScriptSourceToDebugFile)
{
try
{
File.WriteAllText(
Path.Combine("ScriptEngines", FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext),
Script);
}
catch
{
}
}
// Do actual compile
CompilerParameters parameters = new CompilerParameters();
parameters.IncludeDebugInformation = true;
// Add all available assemblies
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
@ -136,11 +295,29 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
//parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment");
parameters.GenerateExecutable = false;
parameters.OutputAssembly = OutFile;
parameters.IncludeDebugInformation = false;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Script);
parameters.IncludeDebugInformation = CompileWithDebugInformation;
parameters.WarningLevel = 4;
parameters.TreatWarningsAsErrors = false;
CompilerResults results;
switch (lang)
{
case enumCompileType.vb:
results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script);
break;
case enumCompileType.cs:
results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
break;
default:
throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\"");
}
// Check result
// Go through errors
// TODO: Return errors to user somehow
//
// WARNINGS AND ERRORS
//
if (results.Errors.Count > 0)
{
string errtext = String.Empty;
@ -150,10 +327,22 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + "'\r\n";
}
throw new Exception(errtext);
if (!File.Exists(OutFile))
{
throw new Exception(errtext);
}
}
//
// NO ERRORS, BUT NO COMPILED FILE
//
if (!File.Exists(OutFile))
{
string errtext = String.Empty;
errtext += "No compile error. But not able to locate compiled file.";
throw new Exception(errtext);
}
return OutFile;
}
}

View File

@ -49,13 +49,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
// UNLOAD SCRIPT
// PROVIDE SCRIPT WITH ITS INTERFACE TO OpenSim
private Compiler.LSL.Compiler LSLCompiler = new Compiler.LSL.Compiler();
private Compiler.LSL.Compiler LSLCompiler;
public override void _StartScript(uint localID, LLUUID itemID, string Script)
{
//IScriptHost root = host.GetRoot();
m_scriptEngine.Log.Debug(m_scriptEngine.ScriptEngineName, "ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID);
// First time start? Lets fire up our compiler...
if (LSLCompiler == null)
LSLCompiler = new Compiler.LSL.Compiler(m_scriptEngine);
//IScriptHost root = host.GetRoot();
// We will initialize and start the script.
// It will be up to the script itself to hook up the correct events.
string ScriptSource = String.Empty;
@ -65,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
try
{
// Compile (We assume LSL)
ScriptSource = LSLCompiler.CompileFromLSLText(Script);
ScriptSource = LSLCompiler.PerformScriptCompile(Script);
#if DEBUG
long before;

View File

@ -200,3 +200,22 @@ ScriptLoadUnloadLoopms=30
; Async LL commands are LSL-commands that causes an event to be fired back with result
AsyncLLCommandLoopms=50
; When script is converted from LSL to C#, or just plain compiled, a copy of the script source will be put in the ScriptEngine folder
WriteScriptSourceToDebugFile=true
; Specify default script compiler
; If you do not specify //cs, //vb or //lsl tag as the first characters of your script then the default compiler will be chosen
; Valid languages are: lsl, cs and vb
DefaultCompileLanguage=lsl
; Specify what compilers are allowed to be used
; Valid languages are: lsl, cs and vb
AllowedCompilers=lsl;cs;vb
; Compile scripts with debugging
; Probably a thousand times slower, but gives you a line number when something goes wrong.
CompileWithDebugInformation=true
; Remove old scripts on next startup
CleanUpOldScriptsOnStartup=true