aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-26 16:11:53 +0000
committerMelanie Thielker2008-09-26 16:11:53 +0000
commitd8c470343e50b342024491219bd43678a24b4a03 (patch)
tree2ee37a53c9d976e4b88706a1634c5ffdb69b0aae /OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
parentAfter the last commit, the old Common assembly was still being loaded. (diff)
downloadopensim-SC_OLD-d8c470343e50b342024491219bd43678a24b4a03.zip
opensim-SC_OLD-d8c470343e50b342024491219bd43678a24b4a03.tar.gz
opensim-SC_OLD-d8c470343e50b342024491219bd43678a24b4a03.tar.bz2
opensim-SC_OLD-d8c470343e50b342024491219bd43678a24b4a03.tar.xz
Compiler Connection! One world, one compiler!
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs509
1 files changed, 0 insertions, 509 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
deleted file mode 100644
index 4adedc3..0000000
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs
+++ /dev/null
@@ -1,509 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.CodeDom.Compiler;
30using System.Collections.Generic;
31using System.Globalization;
32using System.IO;
33using Microsoft.CSharp;
34using Microsoft.JScript;
35using Microsoft.VisualBasic;
36using OpenSim.Region.Environment.Interfaces;
37
38namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL
39{
40 public class Compiler
41 {
42 private static readonly log4net.ILog m_log
43 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44
45 // * Uses "LSL2Converter" to convert LSL to C# if necessary.
46 // * Compiles C#-code into an assembly
47 // * Returns assembly name ready for AppDomain load.
48 //
49 // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details.
50 //
51
52 internal enum enumCompileType
53 {
54 lsl = 0,
55 cs = 1,
56 vb = 2,
57 js = 3,
58 yp = 4
59 }
60
61 /// <summary>
62 /// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs.
63 /// </summary>
64 public int LinesToRemoveOnError = 3;
65 private enumCompileType DefaultCompileLanguage;
66 private bool WriteScriptSourceToDebugFile;
67 private bool CompileWithDebugInformation;
68 // private bool CleanUpOldScriptsOnStartup;
69 private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
70 private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
71
72 private string FilePrefix;
73 private string ScriptEnginesPath = "ScriptEngines";
74
75 private static CSCodeGenerator LSL_Converter = new CSCodeGenerator();
76 private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap; // mapping between LSL and C# line/column numbers
77 private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
78 private static VBCodeProvider VBcodeProvider = new VBCodeProvider();
79 private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider();
80 private static CSharpCodeProvider YPcodeProvider = new CSharpCodeProvider(); // YP is translated into CSharp
81 private static YP2CSConverter YP_Converter = new YP2CSConverter();
82
83 private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files
84 private static UInt64 scriptCompileCounter = 0; // And a counter
85
86 public ScriptEngine m_scriptEngine;
87 public Compiler(ScriptEngine scriptEngine)
88 {
89 m_scriptEngine = scriptEngine;
90 ReadConfig();
91 }
92 public bool in_startup = true;
93 public void ReadConfig()
94 {
95
96 // Get some config
97 WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true);
98 CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true);
99 // CleanUpOldScriptsOnStartup = m_scriptEngine.ScriptConfigSource.GetBoolean("CleanUpOldScriptsOnStartup", true);
100
101 // Get file prefix from scriptengine name and make it file system safe:
102 FilePrefix = m_scriptEngine.ScriptEngineName;
103 foreach (char c in Path.GetInvalidFileNameChars())
104 {
105 FilePrefix = FilePrefix.Replace(c, '_');
106 }
107
108 // First time we start? Delete old files
109 if (in_startup)
110 {
111 in_startup = false;
112 DeleteOldFiles();
113 }
114
115 // Map name and enum type of our supported languages
116 LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs);
117 LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb);
118 LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl);
119 LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js);
120 LanguageMapping.Add(enumCompileType.yp.ToString(), enumCompileType.yp);
121
122 // Allowed compilers
123 string allowComp = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl,cs,vb,js,yp");
124 AllowedCompilers.Clear();
125
126#if DEBUG
127 m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Allowed languages: " + allowComp);
128#endif
129
130
131 foreach (string strl in allowComp.Split(','))
132 {
133 string strlan = strl.Trim(" \t".ToCharArray()).ToLower();
134 if (!LanguageMapping.ContainsKey(strlan))
135 {
136 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\".");
137 }
138 else
139 {
140#if DEBUG
141 //m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\".");
142#endif
143 }
144 AllowedCompilers.Add(strlan, true);
145 }
146 if (AllowedCompilers.Count == 0)
147 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!");
148
149 // Default language
150 string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower();
151
152 // Is this language recognized at all?
153 if (!LanguageMapping.ContainsKey(defaultCompileLanguage))
154 {
155 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " +
156 "Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\".");
157 defaultCompileLanguage = "lsl";
158 }
159
160 // Is this language in allow-list?
161 if (!AllowedCompilers.ContainsKey(defaultCompileLanguage))
162 {
163 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " +
164 "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!");
165 }
166 else
167 {
168#if DEBUG
169// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: " +
170// "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language.");
171#endif
172 // LANGUAGE IS IN ALLOW-LIST
173 DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage];
174 }
175
176 // We now have an allow-list, a mapping list, and a default language
177
178 }
179
180 /// <summary>
181 /// Delete old script files
182 /// </summary>
183 private void DeleteOldFiles()
184 {
185
186 // CREATE FOLDER IF IT DOESNT EXIST
187 if (!Directory.Exists(ScriptEnginesPath))
188 {
189 try
190 {
191 Directory.CreateDirectory(ScriptEnginesPath);
192 }
193 catch (Exception ex)
194 {
195 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString());
196 }
197 }
198
199 foreach (string file in Directory.GetFiles(ScriptEnginesPath))
200 {
201 //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: FILE FOUND: " + file);
202
203 if (file.ToLower().StartsWith(FilePrefix + "_compiled_") ||
204 file.ToLower().StartsWith(FilePrefix + "_source_"))
205 {
206 try
207 {
208 File.Delete(file);
209 }
210 catch (Exception ex)
211 {
212 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying delete old script file \"" + file + "\": " + ex.ToString());
213 }
214
215 }
216 }
217
218 }
219
220 /// <summary>
221 /// Converts script from LSL to CS and calls CompileFromCSText
222 /// </summary>
223 /// <param name="Script">LSL script</param>
224 /// <returns>Filename to .dll assembly</returns>
225 public string PerformScriptCompile(string Script)
226 {
227 enumCompileType l = DefaultCompileLanguage;
228
229
230 if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
231 l = enumCompileType.cs;
232 if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
233 {
234 l = enumCompileType.vb;
235 // We need to remove //vb, it won't compile with that
236
237 Script = Script.Substring(4, Script.Length - 4);
238 }
239 if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
240 l = enumCompileType.lsl;
241
242 if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture))
243 l = enumCompileType.js;
244
245 if (Script.StartsWith("//yp", true, CultureInfo.InvariantCulture))
246 l = enumCompileType.yp;
247
248 if (!AllowedCompilers.ContainsKey(l.ToString()))
249 {
250 // Not allowed to compile to this language!
251 string errtext = String.Empty;
252 errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!";
253 throw new Exception(errtext);
254 }
255
256 string compileScript = Script;
257
258 if (l == enumCompileType.lsl)
259 {
260 // Its LSL, convert it to C#
261 compileScript = LSL_Converter.Convert(Script);
262 m_positionMap = LSL_Converter.PositionMap;
263 l = enumCompileType.cs;
264 }
265
266 if (l == enumCompileType.yp)
267 {
268 // Its YP, convert it to C#
269 compileScript = YP_Converter.Convert(Script);
270 // We have our own processor now
271 //l = enumCompileType.cs;
272 }
273
274 // Insert additional assemblies here
275
276 //ADAM: Disabled for the moment until it's working right.
277 bool enableCommanderLSL = false;
278
279 if (enableCommanderLSL == true && ((l == enumCompileType.cs) || (l == enumCompileType.yp)))
280 {
281 foreach (KeyValuePair<string,
282 ICommander> com
283 in m_scriptEngine.World.GetCommanders())
284 {
285 compileScript = com.Value.GenerateRuntimeAPI() + compileScript;
286 }
287 }
288
289 // End of insert
290
291
292 switch (l)
293 {
294 case enumCompileType.cs:
295 compileScript = CreateCSCompilerScript(compileScript);
296 break;
297 case enumCompileType.vb:
298 compileScript = CreateVBCompilerScript(compileScript);
299 break;
300 case enumCompileType.js:
301 compileScript = CreateJSCompilerScript(compileScript);
302 break;
303 case enumCompileType.yp:
304 compileScript = CreateYPCompilerScript(compileScript);
305 break;
306 }
307
308 m_log.Debug("[ScriptEngine.DotNetEngine]: Preparing to compile the following LSL to C# translated code");
309 m_log.Debug("");
310 m_log.Debug(compileScript);
311
312 return CompileFromDotNetText(compileScript, l);
313 }
314
315 private static string CreateJSCompilerScript(string compileScript)
316 {
317 compileScript = String.Empty +
318 "import OpenSim.Region.ScriptEngine.Shared; import System.Collections.Generic;\r\n" +
319 "package SecondLife {\r\n" +
320 "class Script extends OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
321 compileScript +
322 "} }\r\n";
323 return compileScript;
324 }
325
326 private static string CreateCSCompilerScript(string compileScript)
327 {
328 compileScript = String.Empty +
329 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
330 String.Empty + "namespace SecondLife { " +
331 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
332 @"public Script() { } " +
333 compileScript +
334 "} }\r\n";
335 return compileScript;
336 }
337
338 private static string CreateYPCompilerScript(string compileScript)
339 {
340 compileScript = String.Empty +
341 "using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog; " +
342 "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
343 String.Empty + "namespace SecondLife { " +
344 String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
345 //@"public Script() { } " +
346 @"static OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog.YP YP=null; " +
347 @"public Script() { YP= new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.YieldProlog.YP(); } "+
348
349 compileScript +
350 "} }\r\n";
351 return compileScript;
352 }
353
354 private static string CreateVBCompilerScript(string compileScript)
355 {
356 compileScript = String.Empty +
357 "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " +
358 String.Empty + "NameSpace SecondLife:" +
359 String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass: " +
360 "\r\nPublic Sub New()\r\nEnd Sub: " +
361 compileScript +
362 ":End Class :End Namespace\r\n";
363 return compileScript;
364 }
365
366 /// <summary>
367 /// Compile .NET script to .Net assembly (.dll)
368 /// </summary>
369 /// <param name="Script">CS script</param>
370 /// <returns>Filename to .dll assembly</returns>
371 internal string CompileFromDotNetText(string Script, enumCompileType lang)
372 {
373 string ext = "." + lang.ToString();
374
375 // Output assembly name
376 scriptCompileCounter++;
377 string OutFile =
378 Path.Combine("ScriptEngines",
379 FilePrefix + "_compiled_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll");
380#if DEBUG
381 m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Starting compile of \"" + OutFile + "\".");
382#endif
383 try
384 {
385 File.Delete(OutFile);
386 }
387 catch (Exception e) // NOTLEGIT - Should be just catching FileIOException
388 {
389 //m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
390 throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
391 }
392 //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
393
394 // DEBUG - write source to disk
395 if (WriteScriptSourceToDebugFile)
396 {
397 string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext;
398 try
399 {
400 File.WriteAllText(
401 Path.Combine("ScriptEngines", srcFileName),
402 Script);
403 }
404 catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException
405 {
406 m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString());
407 }
408 }
409
410 // Do actual compile
411 CompilerParameters parameters = new CompilerParameters();
412
413 parameters.IncludeDebugInformation = true;
414
415 // Add all available assemblies
416// foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
417// {
418// Console.WriteLine("Adding assembly: " + asm.Location);
419// parameters.ReferencedAssemblies.Add(asm.Location);
420// }
421
422 string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
423 string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location);
424 //Console.WriteLine("Assembly location: " + rootPath);
425 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.dll"));
426 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
427
428 if (lang == enumCompileType.yp)
429 {
430 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.YieldProlog.dll"));
431 }
432
433 //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment");
434 parameters.GenerateExecutable = false;
435 parameters.OutputAssembly = OutFile;
436 parameters.IncludeDebugInformation = CompileWithDebugInformation;
437 //parameters.WarningLevel = 1; // Should be 4?
438 parameters.TreatWarningsAsErrors = false;
439
440 CompilerResults results;
441 switch (lang)
442 {
443 case enumCompileType.vb:
444 results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script);
445 break;
446 case enumCompileType.cs:
447 results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
448 break;
449 case enumCompileType.js:
450 results = JScodeProvider.CompileAssemblyFromSource(parameters, Script);
451 break;
452 case enumCompileType.yp:
453 results = YPcodeProvider.CompileAssemblyFromSource(parameters, Script);
454 break;
455 default:
456 throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\"");
457 }
458
459 // Check result
460 // Go through errors
461
462 //
463 // WARNINGS AND ERRORS
464 //
465 if (results.Errors.Count > 0)
466 {
467 string errtext = String.Empty;
468 foreach (CompilerError CompErr in results.Errors)
469 {
470 KeyValuePair<int, int> lslPos;
471
472 try
473 {
474 lslPos = m_positionMap[new KeyValuePair<int, int>(CompErr.Line, CompErr.Column)];
475 }
476 catch (KeyNotFoundException) // we don't have this line/column mapped
477 {
478 m_scriptEngine.Log.Debug(String.Format("[{0}]: Lookup of C# line {1}, column {2} failed.", m_scriptEngine.ScriptEngineName, CompErr.Line, CompErr.Column));
479 lslPos = new KeyValuePair<int, int>(-CompErr.Line, -CompErr.Column);
480 }
481
482 // The Second Life viewer's script editor begins
483 // countingn lines and columns at 0, so we subtract 1.
484 errtext += String.Format("Line {0}, column {1}, Error Number: {2}, '{3}'\r\n", lslPos.Key - 1, lslPos.Value - 1, CompErr.ErrorNumber, CompErr.ErrorText);
485 //errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) +
486 // ", Error Number: " + CompErr.ErrorNumber +
487 // ", '" + CompErr.ErrorText + "'\r\n";
488 }
489 Console.WriteLine("[COMPILER ERROR]:" + errtext);
490 if (!File.Exists(OutFile))
491 {
492 throw new Exception(errtext);
493 }
494 }
495
496
497 //
498 // NO ERRORS, BUT NO COMPILED FILE
499 //
500 if (!File.Exists(OutFile))
501 {
502 string errtext = String.Empty;
503 errtext += "No compile error. But not able to locate compiled file.";
504 throw new Exception(errtext);
505 }
506 return OutFile;
507 }
508 }
509}