This fix adds a stand-alone compilation environment
for OpenSIm scripts. It makes it very easy to address coding issues before going in-world to try a script out. This is a HUGE time saver if you're doing anything significant with scripts. Signed-off-by: dr scofield (aka dirk husemann) <drscofield@xyzzyxyzzy.net>remotes/origin/0.6.7-post-fixes
parent
3b1ef2bfd2
commit
d4c98ddffc
|
@ -0,0 +1,287 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.CSharp;
|
||||||
|
using OpenSim.Region.ScriptEngine.Shared.CodeTools;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace OpenSim.Tools.LSL.Compiler
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
|
||||||
|
private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
string source = null;
|
||||||
|
|
||||||
|
if(args.Length == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("No input file specified");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!File.Exists(args[0]))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Input file does not exist");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ICodeConverter cvt = (ICodeConverter) new CSCodeGenerator();
|
||||||
|
source = cvt.Convert(File.ReadAllText(args[0]));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Conversion failed:\n"+e.Message);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
source = CreateCSCompilerScript(source);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine(CompileFromDotNetText(source,"a.out"));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Conversion failed: "+e.Message);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateCSCompilerScript(string compileScript)
|
||||||
|
{
|
||||||
|
compileScript = String.Empty +
|
||||||
|
"using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
|
||||||
|
String.Empty + "namespace SecondLife { " +
|
||||||
|
String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
|
||||||
|
@"public Script() { } " +
|
||||||
|
compileScript +
|
||||||
|
"} }\r\n";
|
||||||
|
return compileScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CompileFromDotNetText(string Script, string asset)
|
||||||
|
{
|
||||||
|
|
||||||
|
string OutFile = asset;
|
||||||
|
string disp ="OK";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(OutFile);
|
||||||
|
}
|
||||||
|
catch (Exception e) // NOTLEGIT - Should be just FileIOException
|
||||||
|
{
|
||||||
|
throw new Exception("Unable to delete old existing "+
|
||||||
|
"script-file before writing new. Compile aborted: " +
|
||||||
|
e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do actual compile
|
||||||
|
CompilerParameters parameters = new CompilerParameters();
|
||||||
|
|
||||||
|
parameters.IncludeDebugInformation = true;
|
||||||
|
|
||||||
|
string rootPath =
|
||||||
|
Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
|
||||||
|
|
||||||
|
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
|
||||||
|
"OpenSim.Region.ScriptEngine.Shared.dll"));
|
||||||
|
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
|
||||||
|
"OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
|
||||||
|
|
||||||
|
parameters.GenerateExecutable = false;
|
||||||
|
parameters.OutputAssembly = OutFile;
|
||||||
|
parameters.IncludeDebugInformation = true;
|
||||||
|
parameters.WarningLevel = 1;
|
||||||
|
parameters.TreatWarningsAsErrors = false;
|
||||||
|
|
||||||
|
CompilerResults results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
|
||||||
|
|
||||||
|
if (results.Errors.Count > 0)
|
||||||
|
{
|
||||||
|
string errtext = String.Empty;
|
||||||
|
foreach (CompilerError CompErr in results.Errors)
|
||||||
|
{
|
||||||
|
string severity = "Error";
|
||||||
|
if ( CompErr.IsWarning )
|
||||||
|
{
|
||||||
|
severity = "Warning";
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyValuePair<int, int> lslPos;
|
||||||
|
|
||||||
|
lslPos = FindErrorPosition(CompErr.Line, CompErr.Column);
|
||||||
|
|
||||||
|
string text = CompErr.ErrorText;
|
||||||
|
|
||||||
|
text = ReplaceTypes(CompErr.ErrorText);
|
||||||
|
|
||||||
|
// The Second Life viewer's script editor begins
|
||||||
|
// countingn lines and columns at 0, so we subtract 1.
|
||||||
|
errtext += String.Format("Line ({0},{1}): {4} {2}: {3}\n",
|
||||||
|
lslPos.Key - 1, lslPos.Value - 1,
|
||||||
|
CompErr.ErrorNumber, text, severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
disp = "Completed with errors";
|
||||||
|
|
||||||
|
if (!File.Exists(OutFile))
|
||||||
|
{
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(OutFile))
|
||||||
|
{
|
||||||
|
string errtext = String.Empty;
|
||||||
|
errtext += "No compile error. But not able to locate compiled file.";
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because windows likes to perform exclusive locks, we simply
|
||||||
|
// write out a textual representation of the file here
|
||||||
|
//
|
||||||
|
// Read the binary file into a buffer
|
||||||
|
//
|
||||||
|
FileInfo fi = new FileInfo(OutFile);
|
||||||
|
|
||||||
|
if (fi == null)
|
||||||
|
{
|
||||||
|
string errtext = String.Empty;
|
||||||
|
errtext += "No compile error. But not able to stat file.";
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte[] data = new Byte[fi.Length];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileStream fs = File.Open(OutFile, FileMode.Open, FileAccess.Read);
|
||||||
|
fs.Read(data, 0, data.Length);
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
string errtext = String.Empty;
|
||||||
|
errtext += "No compile error. But not able to open file.";
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to base64
|
||||||
|
//
|
||||||
|
string filetext = System.Convert.ToBase64String(data);
|
||||||
|
|
||||||
|
System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
|
||||||
|
|
||||||
|
Byte[] buf = enc.GetBytes(filetext);
|
||||||
|
|
||||||
|
FileStream sfs = File.Create(OutFile+".text");
|
||||||
|
sfs.Write(buf, 0, buf.Length);
|
||||||
|
sfs.Close();
|
||||||
|
|
||||||
|
string posmap = String.Empty;
|
||||||
|
if (m_positionMap != null)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> kvp in m_positionMap)
|
||||||
|
{
|
||||||
|
KeyValuePair<int, int> k = kvp.Key;
|
||||||
|
KeyValuePair<int, int> v = kvp.Value;
|
||||||
|
posmap += String.Format("{0},{1},{2},{3}\n",
|
||||||
|
k.Key, k.Value, v.Key, v.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = enc.GetBytes(posmap);
|
||||||
|
|
||||||
|
FileStream mfs = File.Create(OutFile+".map");
|
||||||
|
mfs.Write(buf, 0, buf.Length);
|
||||||
|
mfs.Close();
|
||||||
|
|
||||||
|
return disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ReplaceTypes(string message)
|
||||||
|
{
|
||||||
|
message = message.Replace(
|
||||||
|
"OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString",
|
||||||
|
"string");
|
||||||
|
|
||||||
|
message = message.Replace(
|
||||||
|
"OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger",
|
||||||
|
"integer");
|
||||||
|
|
||||||
|
message = message.Replace(
|
||||||
|
"OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat",
|
||||||
|
"float");
|
||||||
|
|
||||||
|
message = message.Replace(
|
||||||
|
"OpenSim.Region.ScriptEngine.Shared.LSL_Types.list",
|
||||||
|
"list");
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KeyValuePair<int, int> FindErrorPosition(int line, int col)
|
||||||
|
{
|
||||||
|
return FindErrorPosition(line, col, m_positionMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class kvpSorter : IComparer<KeyValuePair<int,int>>
|
||||||
|
{
|
||||||
|
public int Compare(KeyValuePair<int,int> a,
|
||||||
|
KeyValuePair<int,int> b)
|
||||||
|
{
|
||||||
|
return a.Key.CompareTo(b.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static KeyValuePair<int, int> FindErrorPosition(int line,
|
||||||
|
int col, Dictionary<KeyValuePair<int, int>,
|
||||||
|
KeyValuePair<int, int>> positionMap)
|
||||||
|
{
|
||||||
|
if (positionMap == null || positionMap.Count == 0)
|
||||||
|
return new KeyValuePair<int, int>(line, col);
|
||||||
|
|
||||||
|
KeyValuePair<int, int> ret = new KeyValuePair<int, int>();
|
||||||
|
|
||||||
|
if (positionMap.TryGetValue(new KeyValuePair<int, int>(line, col),
|
||||||
|
out ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
List<KeyValuePair<int,int>> sorted =
|
||||||
|
new List<KeyValuePair<int,int>>(positionMap.Keys);
|
||||||
|
|
||||||
|
sorted.Sort(new kvpSorter());
|
||||||
|
|
||||||
|
int l = 1;
|
||||||
|
int c = 1;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<int, int> cspos in sorted)
|
||||||
|
{
|
||||||
|
if (cspos.Key >= line)
|
||||||
|
{
|
||||||
|
if (cspos.Key > line)
|
||||||
|
return new KeyValuePair<int, int>(l, c);
|
||||||
|
if (cspos.Value > col)
|
||||||
|
return new KeyValuePair<int, int>(l, c);
|
||||||
|
c = cspos.Value;
|
||||||
|
if (c == 0)
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l = cspos.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new KeyValuePair<int, int>(l, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
prebuild.xml
27
prebuild.xml
|
@ -3196,6 +3196,33 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project name="lslc" path="OpenSim/Tools/Compiler" type="Exe">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../../bin/</ReferencePath>
|
||||||
|
<Reference name="System"/>
|
||||||
|
<Reference name="OpenMetaverseTypes.dll"/>
|
||||||
|
<Reference name="OpenMetaverse.dll"/>
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Region.ScriptEngine.Shared.CodeTools"/>
|
||||||
|
<Reference name="Nini.dll" />
|
||||||
|
<Reference name="log4net.dll"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
<!-- Test Suite -->
|
<!-- Test Suite -->
|
||||||
<Project frameworkVersion="v3_5" name="OpenSim.TestSuite" path="OpenSim/TestSuite" type="Exe">
|
<Project frameworkVersion="v3_5" name="OpenSim.TestSuite" path="OpenSim/TestSuite" type="Exe">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
|
|
Loading…
Reference in New Issue