aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Tools
diff options
context:
space:
mode:
authorAlan M Webb2009-09-16 10:00:00 -0400
committerdr scofield (aka dirk husemann)2009-09-16 16:43:51 +0200
commitd4c98ddffc7b6ac25cd08f57f9f67a33bff91683 (patch)
treed30710d0b87a035fea6cef4a1f79007643f0801d /OpenSim/Tools
parent This fixes a boundary case error in the strided list (diff)
downloadopensim-SC-d4c98ddffc7b6ac25cd08f57f9f67a33bff91683.zip
opensim-SC-d4c98ddffc7b6ac25cd08f57f9f67a33bff91683.tar.gz
opensim-SC-d4c98ddffc7b6ac25cd08f57f9f67a33bff91683.tar.bz2
opensim-SC-d4c98ddffc7b6ac25cd08f57f9f67a33bff91683.tar.xz
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>
Diffstat (limited to 'OpenSim/Tools')
-rw-r--r--OpenSim/Tools/Compiler/Program.cs287
1 files changed, 287 insertions, 0 deletions
diff --git a/OpenSim/Tools/Compiler/Program.cs b/OpenSim/Tools/Compiler/Program.cs
new file mode 100644
index 0000000..0141f48
--- /dev/null
+++ b/OpenSim/Tools/Compiler/Program.cs
@@ -0,0 +1,287 @@
1
2using System;
3using System.Collections.Generic;
4using System.IO;
5using Microsoft.CSharp;
6using OpenSim.Region.ScriptEngine.Shared.CodeTools;
7using System.CodeDom.Compiler;
8
9namespace OpenSim.Tools.LSL.Compiler
10{
11 class Program
12 {
13 private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
14 private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
15
16 static void Main(string[] args)
17 {
18 string source = null;
19
20 if(args.Length == 0)
21 {
22 Console.WriteLine("No input file specified");
23 Environment.Exit(1);
24 }
25
26 if(!File.Exists(args[0]))
27 {
28 Console.WriteLine("Input file does not exist");
29 Environment.Exit(1);
30 }
31
32 try
33 {
34 ICodeConverter cvt = (ICodeConverter) new CSCodeGenerator();
35 source = cvt.Convert(File.ReadAllText(args[0]));
36 }
37 catch(Exception e)
38 {
39 Console.WriteLine("Conversion failed:\n"+e.Message);
40 Environment.Exit(1);
41 }
42
43 source = CreateCSCompilerScript(source);
44
45 try
46 {
47 Console.WriteLine(CompileFromDotNetText(source,"a.out"));
48 }
49 catch(Exception e)
50 {
51 Console.WriteLine("Conversion failed: "+e.Message);
52 Environment.Exit(1);
53 }
54
55 Environment.Exit(0);
56 }
57
58 private static string CreateCSCompilerScript(string compileScript)
59 {
60 compileScript = String.Empty +
61 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
62 String.Empty + "namespace SecondLife { " +
63 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
64 @"public Script() { } " +
65 compileScript +
66 "} }\r\n";
67 return compileScript;
68 }
69
70 private static string CompileFromDotNetText(string Script, string asset)
71 {
72
73 string OutFile = asset;
74 string disp ="OK";
75
76 try
77 {
78 File.Delete(OutFile);
79 }
80 catch (Exception e) // NOTLEGIT - Should be just FileIOException
81 {
82 throw new Exception("Unable to delete old existing "+
83 "script-file before writing new. Compile aborted: " +
84 e.ToString());
85 }
86
87 // Do actual compile
88 CompilerParameters parameters = new CompilerParameters();
89
90 parameters.IncludeDebugInformation = true;
91
92 string rootPath =
93 Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
94
95 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
96 "OpenSim.Region.ScriptEngine.Shared.dll"));
97 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
98 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
99
100 parameters.GenerateExecutable = false;
101 parameters.OutputAssembly = OutFile;
102 parameters.IncludeDebugInformation = true;
103 parameters.WarningLevel = 1;
104 parameters.TreatWarningsAsErrors = false;
105
106 CompilerResults results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
107
108 if (results.Errors.Count > 0)
109 {
110 string errtext = String.Empty;
111 foreach (CompilerError CompErr in results.Errors)
112 {
113 string severity = "Error";
114 if ( CompErr.IsWarning )
115 {
116 severity = "Warning";
117 }
118
119 KeyValuePair<int, int> lslPos;
120
121 lslPos = FindErrorPosition(CompErr.Line, CompErr.Column);
122
123 string text = CompErr.ErrorText;
124
125 text = ReplaceTypes(CompErr.ErrorText);
126
127 // The Second Life viewer's script editor begins
128 // countingn lines and columns at 0, so we subtract 1.
129 errtext += String.Format("Line ({0},{1}): {4} {2}: {3}\n",
130 lslPos.Key - 1, lslPos.Value - 1,
131 CompErr.ErrorNumber, text, severity);
132 }
133
134 disp = "Completed with errors";
135
136 if (!File.Exists(OutFile))
137 {
138 throw new Exception(errtext);
139 }
140 }
141
142 if (!File.Exists(OutFile))
143 {
144 string errtext = String.Empty;
145 errtext += "No compile error. But not able to locate compiled file.";
146 throw new Exception(errtext);
147 }
148
149 // Because windows likes to perform exclusive locks, we simply
150 // write out a textual representation of the file here
151 //
152 // Read the binary file into a buffer
153 //
154 FileInfo fi = new FileInfo(OutFile);
155
156 if (fi == null)
157 {
158 string errtext = String.Empty;
159 errtext += "No compile error. But not able to stat file.";
160 throw new Exception(errtext);
161 }
162
163 Byte[] data = new Byte[fi.Length];
164
165 try
166 {
167 FileStream fs = File.Open(OutFile, FileMode.Open, FileAccess.Read);
168 fs.Read(data, 0, data.Length);
169 fs.Close();
170 }
171 catch (Exception)
172 {
173 string errtext = String.Empty;
174 errtext += "No compile error. But not able to open file.";
175 throw new Exception(errtext);
176 }
177
178 // Convert to base64
179 //
180 string filetext = System.Convert.ToBase64String(data);
181
182 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
183
184 Byte[] buf = enc.GetBytes(filetext);
185
186 FileStream sfs = File.Create(OutFile+".text");
187 sfs.Write(buf, 0, buf.Length);
188 sfs.Close();
189
190 string posmap = String.Empty;
191 if (m_positionMap != null)
192 {
193 foreach (KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> kvp in m_positionMap)
194 {
195 KeyValuePair<int, int> k = kvp.Key;
196 KeyValuePair<int, int> v = kvp.Value;
197 posmap += String.Format("{0},{1},{2},{3}\n",
198 k.Key, k.Value, v.Key, v.Value);
199 }
200 }
201
202 buf = enc.GetBytes(posmap);
203
204 FileStream mfs = File.Create(OutFile+".map");
205 mfs.Write(buf, 0, buf.Length);
206 mfs.Close();
207
208 return disp;
209 }
210
211 private static string ReplaceTypes(string message)
212 {
213 message = message.Replace(
214 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString",
215 "string");
216
217 message = message.Replace(
218 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger",
219 "integer");
220
221 message = message.Replace(
222 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat",
223 "float");
224
225 message = message.Replace(
226 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.list",
227 "list");
228
229 return message;
230 }
231
232 private static KeyValuePair<int, int> FindErrorPosition(int line, int col)
233 {
234 return FindErrorPosition(line, col, m_positionMap);
235 }
236
237 private class kvpSorter : IComparer<KeyValuePair<int,int>>
238 {
239 public int Compare(KeyValuePair<int,int> a,
240 KeyValuePair<int,int> b)
241 {
242 return a.Key.CompareTo(b.Key);
243 }
244 }
245
246 public static KeyValuePair<int, int> FindErrorPosition(int line,
247 int col, Dictionary<KeyValuePair<int, int>,
248 KeyValuePair<int, int>> positionMap)
249 {
250 if (positionMap == null || positionMap.Count == 0)
251 return new KeyValuePair<int, int>(line, col);
252
253 KeyValuePair<int, int> ret = new KeyValuePair<int, int>();
254
255 if (positionMap.TryGetValue(new KeyValuePair<int, int>(line, col),
256 out ret))
257 return ret;
258
259 List<KeyValuePair<int,int>> sorted =
260 new List<KeyValuePair<int,int>>(positionMap.Keys);
261
262 sorted.Sort(new kvpSorter());
263
264 int l = 1;
265 int c = 1;
266
267 foreach (KeyValuePair<int, int> cspos in sorted)
268 {
269 if (cspos.Key >= line)
270 {
271 if (cspos.Key > line)
272 return new KeyValuePair<int, int>(l, c);
273 if (cspos.Value > col)
274 return new KeyValuePair<int, int>(l, c);
275 c = cspos.Value;
276 if (c == 0)
277 c++;
278 }
279 else
280 {
281 l = cspos.Key;
282 }
283 }
284 return new KeyValuePair<int, int>(l, c);
285 }
286 }
287}