diff options
author | Tedd Hansen | 2008-02-02 02:35:56 +0000 |
---|---|---|
committer | Tedd Hansen | 2008-02-02 02:35:56 +0000 |
commit | 8ccc12d642d1104bf4c1249a02a82d8af5d6efe0 (patch) | |
tree | f3691396c5649dbfc393b289cf7b5224cb251c85 /OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs | |
parent | Added OpenSim.32BitLaunch.exe that can be used on 64-bit systems to run OpenS... (diff) | |
download | opensim-SC-8ccc12d642d1104bf4c1249a02a82d8af5d6efe0.zip opensim-SC-8ccc12d642d1104bf4c1249a02a82d8af5d6efe0.tar.gz opensim-SC-8ccc12d642d1104bf4c1249a02a82d8af5d6efe0.tar.bz2 opensim-SC-8ccc12d642d1104bf4c1249a02a82d8af5d6efe0.tar.xz |
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
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs | 255 |
1 files changed, 222 insertions, 33 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs index 2adc060..d3f2873 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/Compiler.cs | |||
@@ -28,9 +28,12 @@ | |||
28 | 28 | ||
29 | using System; | 29 | using System; |
30 | using System.CodeDom.Compiler; | 30 | using System.CodeDom.Compiler; |
31 | using System.Collections.Generic; | ||
32 | using System.Globalization; | ||
31 | using System.IO; | 33 | using System.IO; |
32 | using System.Reflection; | 34 | using System.Reflection; |
33 | using Microsoft.CSharp; | 35 | using Microsoft.CSharp; |
36 | using Microsoft.VisualBasic; | ||
34 | 37 | ||
35 | namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | 38 | namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL |
36 | { | 39 | { |
@@ -44,45 +47,192 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | |||
44 | // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. | 47 | // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. |
45 | // | 48 | // |
46 | 49 | ||
47 | private LSL2CSConverter LSL_Converter = new LSL2CSConverter(); | 50 | internal enum enumCompileType |
48 | private CSharpCodeProvider codeProvider = new CSharpCodeProvider(); | 51 | { |
52 | lsl = 0, | ||
53 | cs = 1, | ||
54 | vb = 2 | ||
55 | } | ||
56 | private enumCompileType DefaultCompileLanguage; | ||
57 | private bool WriteScriptSourceToDebugFile; | ||
58 | private bool CompileWithDebugInformation; | ||
59 | private bool CleanUpOldScriptsOnStartup; | ||
60 | private System.Collections.Generic.Dictionary<string, Boolean> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase); | ||
61 | private System.Collections.Generic.Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase); | ||
62 | |||
63 | private string FilePrefix; | ||
64 | private string ScriptEnginesPath = "ScriptEngines"; | ||
65 | |||
66 | private static LSL2CSConverter LSL_Converter = new LSL2CSConverter(); | ||
67 | private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); | ||
68 | private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); | ||
69 | |||
49 | private static UInt64 scriptCompileCounter = 0; | 70 | private static UInt64 scriptCompileCounter = 0; |
50 | 71 | ||
51 | private static int instanceID = new Random().Next(0, int.MaxValue); | 72 | private static int instanceID = new Random().Next(0, int.MaxValue); |
52 | // Implemented due to peer preassure --- will cause garbage in ScriptEngines folder ;) | 73 | // Implemented due to peer preassure --- will cause garbage in ScriptEngines folder ;) |
53 | 74 | ||
54 | //private ICodeCompiler icc = codeProvider.CreateCompiler(); | 75 | public Common.ScriptEngineBase.ScriptEngine m_scriptEngine; |
55 | public string CompileFromFile(string LSOFileName) | 76 | public Compiler(Common.ScriptEngineBase.ScriptEngine scriptEngine) |
56 | { | 77 | { |
57 | switch (Path.GetExtension(LSOFileName).ToLower()) | 78 | m_scriptEngine = scriptEngine; |
58 | { | 79 | ReadConfig(); |
59 | case ".txt": | 80 | } |
60 | case ".lsl": | 81 | public bool in_startup = true; |
61 | Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS"); | 82 | public void ReadConfig() |
62 | return CompileFromLSLText(File.ReadAllText(LSOFileName)); | 83 | { |
63 | case ".cs": | 84 | WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true); |
64 | Common.ScriptEngineBase.Common.SendToDebug("Source code is CS"); | 85 | CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true); |
65 | return CompileFromCSText(File.ReadAllText(LSOFileName)); | 86 | CleanUpOldScriptsOnStartup = m_scriptEngine.ScriptConfigSource.GetBoolean("CleanUpOldScriptsOnStartup", true); |
66 | default: | 87 | |
67 | throw new Exception("Unknown script type."); | 88 | // Get file prefix from scriptengine name and make it file system safe: |
89 | FilePrefix = m_scriptEngine.ScriptEngineName; | ||
90 | foreach (char c in Path.GetInvalidFileNameChars()) | ||
91 | { | ||
92 | FilePrefix = FilePrefix.Replace(c, '_'); | ||
93 | } | ||
94 | // First time we start? | ||
95 | if (in_startup) | ||
96 | { | ||
97 | in_startup = false; | ||
98 | DeleteOldFiles(); | ||
99 | } | ||
100 | |||
101 | LanguageMapping.Add("cs", enumCompileType.cs); | ||
102 | LanguageMapping.Add("vb", enumCompileType.lsl); | ||
103 | LanguageMapping.Add("lsl", enumCompileType.vb); | ||
104 | |||
105 | // Allowed compilers | ||
106 | string allowedCompilers = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl;cs;vb"); | ||
107 | AllowedCompilers.Clear(); | ||
108 | foreach (string strl in allowedCompilers.Split(';')) | ||
109 | { | ||
110 | string strlan = strl.Trim(" \t".ToCharArray()).ToLower(); | ||
111 | if (!LanguageMapping.ContainsKey(strlan)) | ||
112 | { | ||
113 | m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Config error. Compiler is unable to recongnize language type \"" + strl + "\" specified in \"AllowedCompilers\"."); | ||
114 | } | ||
115 | AllowedCompilers.Add(strlan, true); | ||
116 | } | ||
117 | if (AllowedCompilers.Count == 0) | ||
118 | m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!"); | ||
119 | |||
120 | // Default language | ||
121 | string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower(); | ||
122 | |||
123 | // Is this language recognized at all? | ||
124 | if (!LanguageMapping.ContainsKey(defaultCompileLanguage)) | ||
125 | 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!"); | ||
126 | |||
127 | // Is this language in allow-list? | ||
128 | if (!AllowedCompilers.ContainsKey(defaultCompileLanguage)) | ||
129 | { | ||
130 | m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, | ||
131 | "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!"); | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | // LANGUAGE IS IN ALLOW-LIST | ||
136 | DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage]; | ||
137 | } | ||
138 | |||
139 | // We now have an allow-list, a mapping list, and a default language | ||
140 | |||
141 | } | ||
142 | |||
143 | private void DeleteOldFiles() | ||
144 | { | ||
145 | |||
146 | // CREATE FOLDER IF IT DOESNT EXIST | ||
147 | if (!Directory.Exists(ScriptEnginesPath)) | ||
148 | { | ||
149 | try | ||
150 | { | ||
151 | Directory.CreateDirectory(ScriptEnginesPath); | ||
152 | } | ||
153 | catch (Exception ex) | ||
154 | { | ||
155 | m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString()); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | foreach (string file in Directory.GetFiles(ScriptEnginesPath)) | ||
160 | { | ||
161 | m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "FILE FOUND: " + file); | ||
162 | |||
163 | if (file.ToLower().StartsWith(FilePrefix + "_compiled_") || | ||
164 | file.ToLower().StartsWith(FilePrefix + "_source_")) | ||
165 | { | ||
166 | try | ||
167 | { | ||
168 | File.Delete(file); | ||
169 | } | ||
170 | catch (Exception ex) | ||
171 | { | ||
172 | m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Exception trying delete old script file \"" + file + "\": " + ex.ToString()); | ||
173 | } | ||
174 | |||
175 | } | ||
68 | } | 176 | } |
177 | |||
69 | } | 178 | } |
70 | 179 | ||
180 | ////private ICodeCompiler icc = codeProvider.CreateCompiler(); | ||
181 | //public string CompileFromFile(string LSOFileName) | ||
182 | //{ | ||
183 | // switch (Path.GetExtension(LSOFileName).ToLower()) | ||
184 | // { | ||
185 | // case ".txt": | ||
186 | // case ".lsl": | ||
187 | // Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS"); | ||
188 | // return CompileFromLSLText(File.ReadAllText(LSOFileName)); | ||
189 | // case ".cs": | ||
190 | // Common.ScriptEngineBase.Common.SendToDebug("Source code is CS"); | ||
191 | // return CompileFromCSText(File.ReadAllText(LSOFileName)); | ||
192 | // default: | ||
193 | // throw new Exception("Unknown script type."); | ||
194 | // } | ||
195 | //} | ||
196 | |||
71 | /// <summary> | 197 | /// <summary> |
72 | /// Converts script from LSL to CS and calls CompileFromCSText | 198 | /// Converts script from LSL to CS and calls CompileFromCSText |
73 | /// </summary> | 199 | /// </summary> |
74 | /// <param name="Script">LSL script</param> | 200 | /// <param name="Script">LSL script</param> |
75 | /// <returns>Filename to .dll assembly</returns> | 201 | /// <returns>Filename to .dll assembly</returns> |
76 | public string CompileFromLSLText(string Script) | 202 | public string PerformScriptCompile(string Script) |
77 | { | 203 | { |
78 | if (Script.Substring(0, 4).ToLower() == "//c#") | 204 | enumCompileType l = DefaultCompileLanguage; |
205 | |||
206 | |||
207 | if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture)) | ||
208 | l = enumCompileType.cs; | ||
209 | if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture)) | ||
210 | l = enumCompileType.vb; | ||
211 | if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture)) | ||
212 | l = enumCompileType.lsl; | ||
213 | |||
214 | if (!AllowedCompilers.ContainsKey(l.ToString())) | ||
215 | { | ||
216 | // Not allowed to compile to this language! | ||
217 | string errtext = String.Empty; | ||
218 | errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; | ||
219 | throw new Exception(errtext); | ||
220 | } | ||
221 | |||
222 | string compileScript; | ||
223 | |||
224 | if (l == enumCompileType.lsl) | ||
79 | { | 225 | { |
80 | return CompileFromCSText(Script); | 226 | // Its LSL, convert it to C# |
227 | compileScript = LSL_Converter.Convert(Script); | ||
228 | l = enumCompileType.cs; | ||
81 | } | 229 | } |
82 | else | 230 | else |
83 | { | 231 | { |
84 | return CompileFromCSText(LSL_Converter.Convert(Script)); | 232 | // We don't need to convert |
233 | compileScript = Script; | ||
85 | } | 234 | } |
235 | return CompileFromCSorVBText(Script, l); | ||
86 | } | 236 | } |
87 | 237 | ||
88 | /// <summary> | 238 | /// <summary> |
@@ -90,36 +240,45 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | |||
90 | /// </summary> | 240 | /// </summary> |
91 | /// <param name="Script">CS script</param> | 241 | /// <param name="Script">CS script</param> |
92 | /// <returns>Filename to .dll assembly</returns> | 242 | /// <returns>Filename to .dll assembly</returns> |
93 | public string CompileFromCSText(string Script) | 243 | internal string CompileFromCSorVBText(string Script, enumCompileType lang) |
94 | { | 244 | { |
245 | string ext = "." + lang.ToString(); | ||
246 | |||
95 | // Output assembly name | 247 | // Output assembly name |
96 | scriptCompileCounter++; | 248 | scriptCompileCounter++; |
97 | string OutFile = | 249 | string OutFile = |
98 | Path.Combine("ScriptEngines", | 250 | Path.Combine("ScriptEngines", |
99 | "DotNetScript_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll"); | 251 | FilePrefix + "_compiled_" + instanceID.ToString() + "_" + scriptCompileCounter.ToString() + ".dll"); |
100 | try | 252 | try |
101 | { | 253 | { |
102 | File.Delete(OutFile); | 254 | File.Delete(OutFile); |
103 | } | 255 | } |
104 | catch (Exception e) | 256 | catch (Exception e) |
105 | { | 257 | { |
106 | Console.WriteLine("Exception attempting to delete old compiled script: " + e.ToString()); | 258 | //m_scriptEngine.Log.Error(m_scriptEngine.ScriptEngineName, "Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); |
259 | throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); | ||
107 | } | 260 | } |
108 | //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); | 261 | //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); |
109 | 262 | ||
110 | // DEBUG - write source to disk | 263 | // DEBUG - write source to disk |
111 | try | 264 | if (WriteScriptSourceToDebugFile) |
112 | { | ||
113 | File.WriteAllText( | ||
114 | Path.Combine("ScriptEngines", "debug_" + Path.GetFileNameWithoutExtension(OutFile) + ".cs"), Script); | ||
115 | } | ||
116 | catch | ||
117 | { | 265 | { |
266 | try | ||
267 | { | ||
268 | File.WriteAllText( | ||
269 | Path.Combine("ScriptEngines", FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext), | ||
270 | Script); | ||
271 | } | ||
272 | catch | ||
273 | { | ||
274 | } | ||
118 | } | 275 | } |
119 | 276 | ||
120 | // Do actual compile | 277 | // Do actual compile |
121 | CompilerParameters parameters = new CompilerParameters(); | 278 | CompilerParameters parameters = new CompilerParameters(); |
279 | |||
122 | parameters.IncludeDebugInformation = true; | 280 | parameters.IncludeDebugInformation = true; |
281 | |||
123 | // Add all available assemblies | 282 | // Add all available assemblies |
124 | foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) | 283 | foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) |
125 | { | 284 | { |
@@ -136,11 +295,29 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | |||
136 | //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); | 295 | //parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment"); |
137 | parameters.GenerateExecutable = false; | 296 | parameters.GenerateExecutable = false; |
138 | parameters.OutputAssembly = OutFile; | 297 | parameters.OutputAssembly = OutFile; |
139 | parameters.IncludeDebugInformation = false; | 298 | parameters.IncludeDebugInformation = CompileWithDebugInformation; |
140 | CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, Script); | 299 | parameters.WarningLevel = 4; |
300 | parameters.TreatWarningsAsErrors = false; | ||
141 | 301 | ||
302 | CompilerResults results; | ||
303 | switch (lang) | ||
304 | { | ||
305 | case enumCompileType.vb: | ||
306 | results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script); | ||
307 | break; | ||
308 | case enumCompileType.cs: | ||
309 | results = CScodeProvider.CompileAssemblyFromSource(parameters, Script); | ||
310 | break; | ||
311 | default: | ||
312 | throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\""); | ||
313 | } | ||
314 | |||
315 | // Check result | ||
142 | // Go through errors | 316 | // Go through errors |
143 | // TODO: Return errors to user somehow | 317 | |
318 | // | ||
319 | // WARNINGS AND ERRORS | ||
320 | // | ||
144 | if (results.Errors.Count > 0) | 321 | if (results.Errors.Count > 0) |
145 | { | 322 | { |
146 | string errtext = String.Empty; | 323 | string errtext = String.Empty; |
@@ -150,10 +327,22 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | |||
150 | ", Error Number: " + CompErr.ErrorNumber + | 327 | ", Error Number: " + CompErr.ErrorNumber + |
151 | ", '" + CompErr.ErrorText + "'\r\n"; | 328 | ", '" + CompErr.ErrorText + "'\r\n"; |
152 | } | 329 | } |
153 | throw new Exception(errtext); | 330 | if (!File.Exists(OutFile)) |
331 | { | ||
332 | throw new Exception(errtext); | ||
333 | } | ||
154 | } | 334 | } |
155 | 335 | ||
156 | 336 | ||
337 | // | ||
338 | // NO ERRORS, BUT NO COMPILED FILE | ||
339 | // | ||
340 | if (!File.Exists(OutFile)) | ||
341 | { | ||
342 | string errtext = String.Empty; | ||
343 | errtext += "No compile error. But not able to locate compiled file."; | ||
344 | throw new Exception(errtext); | ||
345 | } | ||
157 | return OutFile; | 346 | return OutFile; |
158 | } | 347 | } |
159 | } | 348 | } |