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>
|
||||
</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 -->
|
||||
<Project frameworkVersion="v3_5" name="OpenSim.TestSuite" path="OpenSim/TestSuite" type="Exe">
|
||||
<Configuration name="Debug">
|
||||
|
|
Loading…
Reference in New Issue