diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/CodeTools')
3 files changed, 997 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs new file mode 100644 index 0000000..2edcee0 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs | |||
@@ -0,0 +1,515 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.CodeDom.Compiler; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Globalization; | ||
32 | using System.IO; | ||
33 | using Microsoft.CSharp; | ||
34 | using Microsoft.JScript; | ||
35 | using Microsoft.VisualBasic; | ||
36 | using OpenSim.Region.Environment.Interfaces; | ||
37 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
38 | |||
39 | namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | ||
40 | { | ||
41 | public class Compiler | ||
42 | { | ||
43 | private static readonly log4net.ILog m_log | ||
44 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
45 | |||
46 | // * Uses "LSL2Converter" to convert LSL to C# if necessary. | ||
47 | // * Compiles C#-code into an assembly | ||
48 | // * Returns assembly name ready for AppDomain load. | ||
49 | // | ||
50 | // Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details. | ||
51 | // | ||
52 | |||
53 | internal enum enumCompileType | ||
54 | { | ||
55 | lsl = 0, | ||
56 | cs = 1, | ||
57 | vb = 2, | ||
58 | js = 3 | ||
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 Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase); | ||
69 | private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase); | ||
70 | |||
71 | private string FilePrefix; | ||
72 | private string ScriptEnginesPath = "ScriptEngines"; | ||
73 | |||
74 | private static LSL2CSConverter LSL_Converter = new LSL2CSConverter(); | ||
75 | private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); | ||
76 | private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); | ||
77 | private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider(); | ||
78 | |||
79 | private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files | ||
80 | private static UInt64 scriptCompileCounter = 0; // And a counter | ||
81 | |||
82 | public IScriptEngine m_scriptEngine; | ||
83 | public Compiler(IScriptEngine scriptEngine) | ||
84 | { | ||
85 | m_scriptEngine = scriptEngine; | ||
86 | ReadConfig(); | ||
87 | } | ||
88 | public bool in_startup = true; | ||
89 | public void ReadConfig() | ||
90 | { | ||
91 | |||
92 | // Get some config | ||
93 | WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", true); | ||
94 | CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true); | ||
95 | |||
96 | // Get file prefix from scriptengine name and make it file system safe: | ||
97 | FilePrefix = "CommonCompiler"; | ||
98 | foreach (char c in Path.GetInvalidFileNameChars()) | ||
99 | { | ||
100 | FilePrefix = FilePrefix.Replace(c, '_'); | ||
101 | } | ||
102 | |||
103 | // First time we start? Delete old files | ||
104 | if (in_startup) | ||
105 | { | ||
106 | in_startup = false; | ||
107 | DeleteOldFiles(); | ||
108 | } | ||
109 | |||
110 | // Map name and enum type of our supported languages | ||
111 | LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs); | ||
112 | LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb); | ||
113 | LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl); | ||
114 | LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js); | ||
115 | |||
116 | // Allowed compilers | ||
117 | string allowComp = m_scriptEngine.Config.GetString("AllowedCompilers", "lsl,cs,vb,js"); | ||
118 | AllowedCompilers.Clear(); | ||
119 | |||
120 | #if DEBUG | ||
121 | m_scriptEngine.Log.Debug("[Compiler]: Allowed languages: " + allowComp); | ||
122 | #endif | ||
123 | |||
124 | |||
125 | foreach (string strl in allowComp.Split(',')) | ||
126 | { | ||
127 | string strlan = strl.Trim(" \t".ToCharArray()).ToLower(); | ||
128 | if (!LanguageMapping.ContainsKey(strlan)) | ||
129 | { | ||
130 | m_scriptEngine.Log.Error("[Compiler]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | #if DEBUG | ||
135 | //m_scriptEngine.Log.Debug("[Compiler]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\"."); | ||
136 | #endif | ||
137 | } | ||
138 | AllowedCompilers.Add(strlan, true); | ||
139 | } | ||
140 | if (AllowedCompilers.Count == 0) | ||
141 | m_scriptEngine.Log.Error("[Compiler]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!"); | ||
142 | |||
143 | // Default language | ||
144 | string defaultCompileLanguage = m_scriptEngine.Config.GetString("DefaultCompileLanguage", "lsl").ToLower(); | ||
145 | |||
146 | // Is this language recognized at all? | ||
147 | if (!LanguageMapping.ContainsKey(defaultCompileLanguage)) | ||
148 | { | ||
149 | m_scriptEngine.Log.Error("[Compiler]: " + | ||
150 | "Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\"."); | ||
151 | defaultCompileLanguage = "lsl"; | ||
152 | } | ||
153 | |||
154 | // Is this language in allow-list? | ||
155 | if (!AllowedCompilers.ContainsKey(defaultCompileLanguage)) | ||
156 | { | ||
157 | m_scriptEngine.Log.Error("[Compiler]: " + | ||
158 | "Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!"); | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | #if DEBUG | ||
163 | // m_scriptEngine.Log.Debug("[Compiler]: " + | ||
164 | // "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language."); | ||
165 | #endif | ||
166 | // LANGUAGE IS IN ALLOW-LIST | ||
167 | DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage]; | ||
168 | } | ||
169 | |||
170 | // We now have an allow-list, a mapping list, and a default language | ||
171 | |||
172 | } | ||
173 | |||
174 | /// <summary> | ||
175 | /// Delete old script files | ||
176 | /// </summary> | ||
177 | private void DeleteOldFiles() | ||
178 | { | ||
179 | |||
180 | // CREATE FOLDER IF IT DOESNT EXIST | ||
181 | if (!Directory.Exists(ScriptEnginesPath)) | ||
182 | { | ||
183 | try | ||
184 | { | ||
185 | Directory.CreateDirectory(ScriptEnginesPath); | ||
186 | } | ||
187 | catch (Exception ex) | ||
188 | { | ||
189 | m_scriptEngine.Log.Error("[Compiler]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString()); | ||
190 | } | ||
191 | } | ||
192 | |||
193 | if (!Directory.Exists(Path.Combine(ScriptEnginesPath, | ||
194 | m_scriptEngine.World.RegionInfo.RegionID.ToString()))) | ||
195 | { | ||
196 | try | ||
197 | { | ||
198 | Directory.CreateDirectory(Path.Combine(ScriptEnginesPath, | ||
199 | m_scriptEngine.World.RegionInfo.RegionID.ToString())); | ||
200 | } | ||
201 | catch (Exception ex) | ||
202 | { | ||
203 | m_scriptEngine.Log.Error("[Compiler]: Exception trying to create ScriptEngine directory \"" + Path.Combine(ScriptEnginesPath, | ||
204 | m_scriptEngine.World.RegionInfo.RegionID.ToString())+ "\": " + ex.ToString()); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | foreach (string file in Directory.GetFiles(Path.Combine(ScriptEnginesPath, | ||
209 | m_scriptEngine.World.RegionInfo.RegionID.ToString()))) | ||
210 | { | ||
211 | //m_scriptEngine.Log.Error("[Compiler]: FILE FOUND: " + file); | ||
212 | |||
213 | if (file.ToLower().StartsWith(FilePrefix + "_compiled_") || | ||
214 | file.ToLower().StartsWith(FilePrefix + "_source_")) | ||
215 | { | ||
216 | try | ||
217 | { | ||
218 | File.Delete(file); | ||
219 | } | ||
220 | catch (Exception ex) | ||
221 | { | ||
222 | m_scriptEngine.Log.Error("[Compiler]: Exception trying delete old script file \"" + file + "\": " + ex.ToString()); | ||
223 | } | ||
224 | |||
225 | } | ||
226 | } | ||
227 | |||
228 | } | ||
229 | |||
230 | ////private ICodeCompiler icc = codeProvider.CreateCompiler(); | ||
231 | //public string CompileFromFile(string LSOFileName) | ||
232 | //{ | ||
233 | // switch (Path.GetExtension(LSOFileName).ToLower()) | ||
234 | // { | ||
235 | // case ".txt": | ||
236 | // case ".lsl": | ||
237 | // Common.ScriptEngineBase.Shared.SendToDebug("Source code is LSL, converting to CS"); | ||
238 | // return CompileFromLSLText(File.ReadAllText(LSOFileName)); | ||
239 | // case ".cs": | ||
240 | // Common.ScriptEngineBase.Shared.SendToDebug("Source code is CS"); | ||
241 | // return CompileFromCSText(File.ReadAllText(LSOFileName)); | ||
242 | // default: | ||
243 | // throw new Exception("Unknown script type."); | ||
244 | // } | ||
245 | //} | ||
246 | |||
247 | /// <summary> | ||
248 | /// Converts script from LSL to CS and calls CompileFromCSText | ||
249 | /// </summary> | ||
250 | /// <param name="Script">LSL script</param> | ||
251 | /// <returns>Filename to .dll assembly</returns> | ||
252 | public string PerformScriptCompile(string Script, string asset) | ||
253 | { | ||
254 | string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( | ||
255 | m_scriptEngine.World.RegionInfo.RegionID.ToString(), | ||
256 | FilePrefix + "_compiled_" + asset + ".dll")); | ||
257 | // string OutFile = Path.Combine(ScriptEnginesPath, | ||
258 | // FilePrefix + "_compiled_" + asset + ".dll"); | ||
259 | |||
260 | if (File.Exists(OutFile)) | ||
261 | { | ||
262 | m_scriptEngine.Log.DebugFormat("[Compiler] Returning existing assembly for {0}", asset); | ||
263 | return OutFile; | ||
264 | } | ||
265 | |||
266 | if (!Directory.Exists(ScriptEnginesPath)) | ||
267 | { | ||
268 | try | ||
269 | { | ||
270 | Directory.CreateDirectory(ScriptEnginesPath); | ||
271 | } | ||
272 | catch (Exception ex) | ||
273 | { | ||
274 | } | ||
275 | } | ||
276 | |||
277 | if (!Directory.Exists(Path.Combine(ScriptEnginesPath, | ||
278 | m_scriptEngine.World.RegionInfo.RegionID.ToString()))) | ||
279 | { | ||
280 | try | ||
281 | { | ||
282 | Directory.CreateDirectory(ScriptEnginesPath); | ||
283 | } | ||
284 | catch (Exception ex) | ||
285 | { | ||
286 | } | ||
287 | } | ||
288 | |||
289 | enumCompileType l = DefaultCompileLanguage; | ||
290 | |||
291 | if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture)) | ||
292 | l = enumCompileType.cs; | ||
293 | if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture)) | ||
294 | { | ||
295 | l = enumCompileType.vb; | ||
296 | // We need to remove //vb, it won't compile with that | ||
297 | |||
298 | Script = Script.Substring(4, Script.Length - 4); | ||
299 | } | ||
300 | if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture)) | ||
301 | l = enumCompileType.lsl; | ||
302 | |||
303 | if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture)) | ||
304 | l = enumCompileType.js; | ||
305 | |||
306 | if (!AllowedCompilers.ContainsKey(l.ToString())) | ||
307 | { | ||
308 | // Not allowed to compile to this language! | ||
309 | string errtext = String.Empty; | ||
310 | errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!"; | ||
311 | throw new Exception(errtext); | ||
312 | } | ||
313 | |||
314 | string compileScript = Script; | ||
315 | |||
316 | if (l == enumCompileType.lsl) | ||
317 | { | ||
318 | // Its LSL, convert it to C# | ||
319 | compileScript = LSL_Converter.Convert(Script); | ||
320 | l = enumCompileType.cs; | ||
321 | } | ||
322 | |||
323 | // Insert additional assemblies here | ||
324 | |||
325 | //ADAM: Disabled for the moment until it's working right. | ||
326 | bool enableCommanderLSL = false; | ||
327 | |||
328 | if (enableCommanderLSL == true && l == enumCompileType.cs) | ||
329 | { | ||
330 | foreach (KeyValuePair<string, | ||
331 | ICommander> com | ||
332 | in m_scriptEngine.World.GetCommanders()) | ||
333 | { | ||
334 | compileScript = com.Value.GenerateRuntimeAPI() + compileScript; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | // End of insert | ||
339 | |||
340 | switch (l) | ||
341 | { | ||
342 | case enumCompileType.cs: | ||
343 | compileScript = CreateCSCompilerScript(compileScript); | ||
344 | break; | ||
345 | case enumCompileType.vb: | ||
346 | compileScript = CreateVBCompilerScript(compileScript); | ||
347 | break; | ||
348 | case enumCompileType.js: | ||
349 | compileScript = CreateJSCompilerScript(compileScript); | ||
350 | break; | ||
351 | } | ||
352 | |||
353 | // m_log.Debug("[ScriptEngine.DotNetEngine]: Preparing to compile the following LSL to C# translated code"); | ||
354 | // m_log.Debug(""); | ||
355 | // m_log.Debug(compileScript); | ||
356 | |||
357 | return CompileFromDotNetText(compileScript, l, asset); | ||
358 | } | ||
359 | |||
360 | private static string CreateJSCompilerScript(string compileScript) | ||
361 | { | ||
362 | compileScript = String.Empty + | ||
363 | "import OpenSim.Region.ScriptEngine.Shared; import System.Collections.Generic;\r\n" + | ||
364 | "package SecondLife {\r\n" + | ||
365 | "class Script extends OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + | ||
366 | compileScript + | ||
367 | "} }\r\n"; | ||
368 | return compileScript; | ||
369 | } | ||
370 | |||
371 | private static string CreateCSCompilerScript(string compileScript) | ||
372 | { | ||
373 | compileScript = String.Empty + | ||
374 | "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + | ||
375 | String.Empty + "namespace SecondLife { " + | ||
376 | String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + | ||
377 | @"public Script() { } " + | ||
378 | compileScript + | ||
379 | "} }\r\n"; | ||
380 | return compileScript; | ||
381 | } | ||
382 | |||
383 | private static string CreateVBCompilerScript(string compileScript) | ||
384 | { | ||
385 | compileScript = String.Empty + | ||
386 | "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " + | ||
387 | String.Empty + "NameSpace SecondLife:" + | ||
388 | String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass: " + | ||
389 | "\r\nPublic Sub New()\r\nEnd Sub: " + | ||
390 | compileScript + | ||
391 | ":End Class :End Namespace\r\n"; | ||
392 | return compileScript; | ||
393 | } | ||
394 | |||
395 | /// <summary> | ||
396 | /// Compile .NET script to .Net assembly (.dll) | ||
397 | /// </summary> | ||
398 | /// <param name="Script">CS script</param> | ||
399 | /// <returns>Filename to .dll assembly</returns> | ||
400 | internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset) | ||
401 | { | ||
402 | string ext = "." + lang.ToString(); | ||
403 | |||
404 | // Output assembly name | ||
405 | scriptCompileCounter++; | ||
406 | string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( | ||
407 | m_scriptEngine.World.RegionInfo.RegionID.ToString(), | ||
408 | FilePrefix + "_compiled_" + asset + ".dll")); | ||
409 | #if DEBUG | ||
410 | // m_scriptEngine.Log.Debug("[Compiler]: Starting compile of \"" + OutFile + "\"."); | ||
411 | #endif | ||
412 | try | ||
413 | { | ||
414 | File.Delete(OutFile); | ||
415 | } | ||
416 | catch (Exception e) // NOTLEGIT - Should be just catching FileIOException | ||
417 | { | ||
418 | //m_scriptEngine.Log.Error("[Compiler]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); | ||
419 | throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); | ||
420 | } | ||
421 | //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll"); | ||
422 | |||
423 | // DEBUG - write source to disk | ||
424 | if (WriteScriptSourceToDebugFile) | ||
425 | { | ||
426 | string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext; | ||
427 | try | ||
428 | { | ||
429 | File.WriteAllText(Path.Combine(Path.Combine( | ||
430 | ScriptEnginesPath, | ||
431 | m_scriptEngine.World.RegionInfo.RegionID.ToString()), | ||
432 | srcFileName), Script); | ||
433 | } | ||
434 | catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException | ||
435 | { | ||
436 | m_scriptEngine.Log.Error("[Compiler]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString()); | ||
437 | } | ||
438 | } | ||
439 | |||
440 | // Do actual compile | ||
441 | CompilerParameters parameters = new CompilerParameters(); | ||
442 | |||
443 | parameters.IncludeDebugInformation = true; | ||
444 | |||
445 | // Add all available assemblies | ||
446 | // foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) | ||
447 | // { | ||
448 | // Console.WriteLine("Adding assembly: " + asm.Location); | ||
449 | // parameters.ReferencedAssemblies.Add(asm.Location); | ||
450 | // } | ||
451 | |||
452 | string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); | ||
453 | string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); | ||
454 | //Console.WriteLine("Assembly location: " + rootPath); | ||
455 | parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.dll")); | ||
456 | parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); | ||
457 | |||
458 | parameters.GenerateExecutable = false; | ||
459 | parameters.OutputAssembly = OutFile; | ||
460 | parameters.IncludeDebugInformation = CompileWithDebugInformation; | ||
461 | //parameters.WarningLevel = 1; // Should be 4? | ||
462 | parameters.TreatWarningsAsErrors = false; | ||
463 | |||
464 | //Console.WriteLine(Script); | ||
465 | CompilerResults results; | ||
466 | switch (lang) | ||
467 | { | ||
468 | case enumCompileType.vb: | ||
469 | results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script); | ||
470 | break; | ||
471 | case enumCompileType.cs: | ||
472 | results = CScodeProvider.CompileAssemblyFromSource(parameters, Script); | ||
473 | break; | ||
474 | case enumCompileType.js: | ||
475 | results = JScodeProvider.CompileAssemblyFromSource(parameters, Script); | ||
476 | break; | ||
477 | default: | ||
478 | throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\""); | ||
479 | } | ||
480 | |||
481 | // Check result | ||
482 | // Go through errors | ||
483 | |||
484 | // | ||
485 | // WARNINGS AND ERRORS | ||
486 | // | ||
487 | if (results.Errors.Count > 0) | ||
488 | { | ||
489 | string errtext = String.Empty; | ||
490 | foreach (CompilerError CompErr in results.Errors) | ||
491 | { | ||
492 | errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) + | ||
493 | ", Error Number: " + CompErr.ErrorNumber + | ||
494 | ", '" + CompErr.ErrorText + "'\r\n"; | ||
495 | } | ||
496 | if (!File.Exists(OutFile)) | ||
497 | { | ||
498 | throw new Exception(errtext); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | // | ||
503 | // NO ERRORS, BUT NO COMPILED FILE | ||
504 | // | ||
505 | if (!File.Exists(OutFile)) | ||
506 | { | ||
507 | string errtext = String.Empty; | ||
508 | errtext += "No compile error. But not able to locate compiled file."; | ||
509 | throw new Exception(errtext); | ||
510 | } | ||
511 | m_scriptEngine.Log.DebugFormat("[Compiler] Compiled new assembly for {0}", asset); | ||
512 | return OutFile; | ||
513 | } | ||
514 | } | ||
515 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSConverter.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSConverter.cs new file mode 100644 index 0000000..380686e --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSConverter.cs | |||
@@ -0,0 +1,374 @@ | |||
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 | */ | ||
28 | |||
29 | using System; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Text.RegularExpressions; | ||
32 | |||
33 | namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | ||
34 | { | ||
35 | public class LSL2CSConverter | ||
36 | { | ||
37 | // Uses regex to convert LSL code to C# code. | ||
38 | |||
39 | //private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled); | ||
40 | private Dictionary<string, string> dataTypes = new Dictionary<string, string>(); | ||
41 | private Dictionary<string, string> quotes = new Dictionary<string, string>(); | ||
42 | // c Style | ||
43 | private Regex cstylecomments = new Regex(@"/\*(.|[\r\n])*?\*/", RegexOptions.Compiled | RegexOptions.Multiline); | ||
44 | // c# one liners | ||
45 | private Regex nonCommentFwsl = new Regex("\"[a-zA-Z0-9.,:/\\n ]+//[^\"+]+([\\\\\\\"+]+)?(\\s+)?[\"+](\\s+)?(;)?", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
46 | private Regex conelinecomments = new Regex(@"[^:].?([\/]{2}[^\n]*)|([\n]{1,}[\/]{2}[^\n]*)", RegexOptions.Compiled | RegexOptions.Multiline); | ||
47 | // ([^\"])((?:[a-zA-Z])\.[a-zA-Z].?)([^\"]) | ||
48 | |||
49 | // value we're looking for: (?:[a-zA-Z])\.[a-zA-Z] | ||
50 | public LSL2CSConverter() | ||
51 | { | ||
52 | // Only the types we need to convert | ||
53 | dataTypes.Add("void", "void"); | ||
54 | dataTypes.Add("integer", "LSL_Types.LSLInteger"); | ||
55 | dataTypes.Add("float", "LSL_Types.LSLFloat"); | ||
56 | dataTypes.Add("string", "LSL_Types.LSLString"); | ||
57 | dataTypes.Add("key", "LSL_Types.LSLString"); | ||
58 | dataTypes.Add("vector", "LSL_Types.Vector3"); | ||
59 | dataTypes.Add("rotation", "LSL_Types.Quaternion"); | ||
60 | dataTypes.Add("list", "LSL_Types.list"); | ||
61 | dataTypes.Add("null", "null"); | ||
62 | } | ||
63 | |||
64 | public string Convert(string Script) | ||
65 | { | ||
66 | quotes.Clear(); | ||
67 | string Return = String.Empty; | ||
68 | Script = " \r\n" + Script; | ||
69 | |||
70 | // | ||
71 | // Prepare script for processing | ||
72 | // | ||
73 | |||
74 | // Clean up linebreaks | ||
75 | Script = Regex.Replace(Script, @"\r\n", "\n"); | ||
76 | Script = Regex.Replace(Script, @"\n", "\r\n"); | ||
77 | |||
78 | // QUOTE REPLACEMENT | ||
79 | // temporarily replace quotes so we can work our magic on the script without | ||
80 | // always considering if we are inside our outside quotes's | ||
81 | // TODO: Does this work on half-quotes in strings? ;) | ||
82 | string _Script = String.Empty; | ||
83 | string C; | ||
84 | bool in_quote = false; | ||
85 | bool quote_replaced = false; | ||
86 | string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_"; | ||
87 | string quote = String.Empty; | ||
88 | bool last_was_escape = false; | ||
89 | int quote_replaced_count = 0; | ||
90 | |||
91 | string removefwnoncomments = nonCommentFwsl.Replace(Script, "\"\";"); | ||
92 | |||
93 | string removecomments = conelinecomments.Replace(removefwnoncomments, ""); | ||
94 | removecomments = cstylecomments.Replace(removecomments, ""); | ||
95 | string[] localscript = removecomments.Split('"'); | ||
96 | string checkscript = String.Empty; | ||
97 | bool flip = true; | ||
98 | |||
99 | for (int p = 0; p < localscript.Length; p++) | ||
100 | { | ||
101 | //if (localscript[p].Length >= 1) | ||
102 | //{ | ||
103 | if (!localscript[p].EndsWith(@"\")) | ||
104 | { | ||
105 | flip = !flip; | ||
106 | //System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p] + " ! " + localscript[p].EndsWith(@"\").ToString()); | ||
107 | } | ||
108 | //} | ||
109 | //else | ||
110 | //{ | ||
111 | // flip = !flip; | ||
112 | // System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p]); | ||
113 | //} | ||
114 | if (!flip) | ||
115 | checkscript += localscript[p]; | ||
116 | } | ||
117 | |||
118 | //System.Console.WriteLine("SCRIPT:" + checkscript); | ||
119 | |||
120 | // checks for alpha.alpha way of referring to objects in C# | ||
121 | // ignores alpha.x alpha.y, alpha.z for refering to vector components | ||
122 | Match SecurityM; | ||
123 | |||
124 | // BROKEN: this check is very wrong. It block's any url in strings. | ||
125 | SecurityM = Regex.Match(checkscript, @"(?:[a-zA-Z])\.(?:[a-wA-Z]|[a-zA-Z][a-zA-Z])", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
126 | |||
127 | if (SecurityM.Success) | ||
128 | throw new Exception("CS0103: 'The . symbol cannot be used in LSL except in float values or vector components'. Detected around: " + SecurityM.Captures[0].Value); | ||
129 | |||
130 | SecurityM = Regex.Match(checkscript, @"typeof\s", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
131 | if (SecurityM.Success) | ||
132 | throw new Exception("CS0103: 'The object.typeof method isn't allowed in LSL'"); | ||
133 | |||
134 | SecurityM = Regex.Match(checkscript, @"GetType\(", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
135 | if (SecurityM.Success) | ||
136 | throw new Exception("CS0103: 'The object.GetType method isn't allowed in LSL'"); | ||
137 | |||
138 | for (int p = 0; p < Script.Length; p++) | ||
139 | { | ||
140 | C = Script.Substring(p, 1); | ||
141 | while (true) | ||
142 | { | ||
143 | // found " and last was not \ so this is not an escaped \" | ||
144 | if (C == "\"" && last_was_escape == false) | ||
145 | { | ||
146 | // Toggle inside/outside quote | ||
147 | in_quote = !in_quote; | ||
148 | if (in_quote) | ||
149 | { | ||
150 | quote_replaced_count++; | ||
151 | } | ||
152 | else | ||
153 | { | ||
154 | if (quote == String.Empty) | ||
155 | { | ||
156 | // We didn't replace quote, probably because of empty string? | ||
157 | _Script += quote_replacement_string + | ||
158 | quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); | ||
159 | } | ||
160 | // We just left a quote | ||
161 | quotes.Add( | ||
162 | quote_replacement_string + | ||
163 | quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote); | ||
164 | quote = String.Empty; | ||
165 | } | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | if (!in_quote) | ||
170 | { | ||
171 | // We are not inside a quote | ||
172 | quote_replaced = false; | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | // We are inside a quote | ||
177 | if (!quote_replaced) | ||
178 | { | ||
179 | // Replace quote | ||
180 | _Script += quote_replacement_string + | ||
181 | quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]); | ||
182 | quote_replaced = true; | ||
183 | } | ||
184 | quote += C; | ||
185 | break; | ||
186 | } | ||
187 | _Script += C; | ||
188 | break; | ||
189 | } | ||
190 | last_was_escape = false; | ||
191 | if (C == @"\") | ||
192 | { | ||
193 | last_was_escape = true; | ||
194 | } | ||
195 | } | ||
196 | Script = _Script; | ||
197 | // | ||
198 | // END OF QUOTE REPLACEMENT | ||
199 | // | ||
200 | |||
201 | // | ||
202 | // PROCESS STATES | ||
203 | // Remove state definitions and add state names to start of each event within state | ||
204 | // | ||
205 | int ilevel = 0; | ||
206 | int lastlevel = 0; | ||
207 | string ret = String.Empty; | ||
208 | string cache = String.Empty; | ||
209 | bool in_state = false; | ||
210 | string current_statename = String.Empty; | ||
211 | for (int p = 0; p < Script.Length; p++) | ||
212 | { | ||
213 | C = Script.Substring(p, 1); | ||
214 | while (true) | ||
215 | { | ||
216 | // inc / dec level | ||
217 | if (C == @"{") | ||
218 | ilevel++; | ||
219 | if (C == @"}") | ||
220 | ilevel--; | ||
221 | if (ilevel < 0) | ||
222 | ilevel = 0; | ||
223 | cache += C; | ||
224 | |||
225 | // if level == 0, add to return | ||
226 | if (ilevel == 1 && lastlevel == 0) | ||
227 | { | ||
228 | // 0 => 1: Get last | ||
229 | Match m = | ||
230 | //Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{", | ||
231 | Regex.Match(cache, @"(?![a-zA-Z_]+)\s*(state\s+)?(?<statename>[a-zA-Z_][a-zA-Z_0-9]*)[^a-zA-Z_0-9\(\)]*{", | ||
232 | |||
233 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
234 | |||
235 | in_state = false; | ||
236 | if (m.Success) | ||
237 | { | ||
238 | // Go back to level 0, this is not a state | ||
239 | in_state = true; | ||
240 | current_statename = m.Groups["statename"].Captures[0].Value; | ||
241 | //Console.WriteLine("Current statename: " + current_statename); | ||
242 | cache = | ||
243 | //@"(?<s1>(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?<s2>[^a-zA-Z_\(\)]*){", | ||
244 | Regex.Replace(cache, | ||
245 | @"(?<s1>(?![a-zA-Z_]+)\s*)" + @"(state\s+)?([a-zA-Z_][a-zA-Z_0-9]*)(?<s2>[^a-zA-Z_0-9\(\)]*){", | ||
246 | "${s1}${s2}", | ||
247 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); | ||
248 | } | ||
249 | ret += cache; | ||
250 | cache = String.Empty; | ||
251 | } | ||
252 | if (ilevel == 0 && lastlevel == 1) | ||
253 | { | ||
254 | // 1 => 0: Remove last } | ||
255 | if (in_state == true) | ||
256 | { | ||
257 | cache = cache.Remove(cache.Length - 1, 1); | ||
258 | //cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline); | ||
259 | |||
260 | //Replace function names | ||
261 | // void dataserver(key query_id, string data) { | ||
262 | //cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "<STATE>" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
263 | //Console.WriteLine("Replacing using statename: " + current_statename); | ||
264 | cache = | ||
265 | Regex.Replace(cache, | ||
266 | @"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", | ||
267 | @"$1public " + current_statename + "_event_$2", | ||
268 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); | ||
269 | } | ||
270 | |||
271 | ret += cache; | ||
272 | cache = String.Empty; | ||
273 | in_state = true; | ||
274 | current_statename = String.Empty; | ||
275 | } | ||
276 | |||
277 | break; | ||
278 | } | ||
279 | lastlevel = ilevel; | ||
280 | } | ||
281 | ret += cache; | ||
282 | cache = String.Empty; | ||
283 | |||
284 | Script = ret; | ||
285 | ret = String.Empty; | ||
286 | |||
287 | foreach (string key in dataTypes.Keys) | ||
288 | { | ||
289 | string val; | ||
290 | dataTypes.TryGetValue(key, out val); | ||
291 | |||
292 | // Replace CAST - (integer) with (int) | ||
293 | Script = | ||
294 | Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")", | ||
295 | RegexOptions.Compiled | RegexOptions.Multiline); | ||
296 | // Replace return types and function variables - integer a() and f(integer a, integer a) | ||
297 | Script = | ||
298 | Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3", | ||
299 | RegexOptions.Compiled | RegexOptions.Multiline); | ||
300 | Script = | ||
301 | Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,", | ||
302 | RegexOptions.Compiled | RegexOptions.Multiline); | ||
303 | } | ||
304 | |||
305 | // Change jumps into goto's and prefix its label | ||
306 | Script = | ||
307 | Regex.Replace(Script, | ||
308 | @"(\W)jump\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*;", | ||
309 | @"$1goto label_$2;", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
310 | // and prefix labels so the do not clash with C#'s reserved words | ||
311 | Script = | ||
312 | Regex.Replace(Script, | ||
313 | @"@([a-zA-Z_][a-zA-Z_0-9]*)\s*;", | ||
314 | @"label_$1: ;", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
315 | |||
316 | // Add "void" in front of functions that needs it | ||
317 | Script = | ||
318 | Regex.Replace(Script, | ||
319 | @"^(\s*public\s+)?((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)", | ||
320 | @"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
321 | |||
322 | // Replace <x,y,z> and <x,y,z,r> | ||
323 | Script = | ||
324 | Regex.Replace(Script, @"<([^,>;]*,[^,>;]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Quaternion($1)", | ||
325 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
326 | Script = | ||
327 | Regex.Replace(Script, @"<([^,>;)]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Vector3($1)", | ||
328 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
329 | |||
330 | // Replace List []'s | ||
331 | Script = | ||
332 | Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)", | ||
333 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
334 | |||
335 | // Replace (string) to .ToString() // | ||
336 | Script = | ||
337 | Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.ToString()", | ||
338 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
339 | Script = | ||
340 | Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)", | ||
341 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline); | ||
342 | |||
343 | // Replace "state STATENAME" with "state("statename")" | ||
344 | Script = | ||
345 | Regex.Replace(Script, @"(state)\s+([^;\n\r]+)(;[\r\n\s])", "$1(\"$2\")$3", | ||
346 | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase); | ||
347 | |||
348 | // REPLACE BACK QUOTES | ||
349 | foreach (string key in quotes.Keys) | ||
350 | { | ||
351 | string val; | ||
352 | quotes.TryGetValue(key, out val); | ||
353 | Script = Script.Replace(key, "\"" + val + "\""); | ||
354 | } | ||
355 | |||
356 | //System.Console.WriteLine(Script); | ||
357 | Return = String.Empty;// + | ||
358 | //"using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;"; | ||
359 | |||
360 | //Return += String.Empty + | ||
361 | // "namespace SecondLife { "; | ||
362 | //Return += String.Empty + | ||
363 | // //"[Serializable] " + | ||
364 | // "public class Script : OpenSim.Region.ScriptEngine.Shared.LSL_BaseClass { "; | ||
365 | //Return += @"public Script() { } "; | ||
366 | Return += Script; | ||
367 | //Return += "} }\r\n"; | ||
368 | |||
369 | quotes.Clear(); | ||
370 | |||
371 | return Return; | ||
372 | } | ||
373 | } | ||
374 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/YP2CSConverter.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/YP2CSConverter.cs new file mode 100644 index 0000000..54b4861 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/YP2CSConverter.cs | |||
@@ -0,0 +1,108 @@ | |||
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 | */ | ||
28 | |||
29 | using System; | ||
30 | using System.IO; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Text; | ||
33 | using System.Text.RegularExpressions; | ||
34 | using OpenSim.Region.ScriptEngine.Shared.YieldProlog; | ||
35 | |||
36 | namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | ||
37 | { | ||
38 | public class YP2CSConverter | ||
39 | { | ||
40 | public YP2CSConverter() | ||
41 | { | ||
42 | } | ||
43 | |||
44 | public string Convert(string Script) | ||
45 | { | ||
46 | string CS_code = GenCode(Script); | ||
47 | return CS_code; | ||
48 | } | ||
49 | |||
50 | static string GenCode(string myCode) | ||
51 | { | ||
52 | Variable TermList = new Variable(); | ||
53 | Variable FunctionCode = new Variable(); | ||
54 | |||
55 | string CS_code = ""; | ||
56 | |||
57 | int cs_pointer = myCode.IndexOf("\n//cs"); | ||
58 | if (cs_pointer > 0) | ||
59 | { | ||
60 | CS_code = myCode.Substring(cs_pointer); // CS code comes after | ||
61 | myCode = myCode.Substring(0, cs_pointer); | ||
62 | } | ||
63 | myCode.Replace("//yp", "%YPCode"); | ||
64 | |||
65 | StringWriter myCS_SW = new StringWriter(); | ||
66 | StringReader myCode_SR = new StringReader(" yp_nop_header_nop. \n "+myCode + "\n"); | ||
67 | |||
68 | YP.see(myCode_SR); | ||
69 | YP.tell(myCS_SW); | ||
70 | |||
71 | //Console.WriteLine("Mycode\n ===================================\n" + myCode+"\n"); | ||
72 | foreach (bool l1 in Parser.parseInput(TermList)) | ||
73 | { | ||
74 | foreach (bool l2 in YPCompiler.makeFunctionPseudoCode(TermList, FunctionCode)) | ||
75 | { | ||
76 | ListPair VFC = new ListPair(FunctionCode, new Variable()); | ||
77 | //Console.WriteLine("-------------------------") | ||
78 | //Console.WriteLine(FunctionCode.ToString()) | ||
79 | //Console.WriteLine("-------------------------") | ||
80 | YPCompiler.convertFunctionCSharp(FunctionCode); | ||
81 | //YPCompiler.convertStringCodesCSharp(VFC); | ||
82 | } | ||
83 | } | ||
84 | YP.seen(); | ||
85 | myCS_SW.Close(); | ||
86 | YP.told(); | ||
87 | StringBuilder bu = myCS_SW.GetStringBuilder(); | ||
88 | string finalcode = "//YPEncoded\n" + bu.ToString(); | ||
89 | // FIX script events (we're in the same script) | ||
90 | // 'YP.script_event(Atom.a(@"sayit"),' ==> 'sayit(' | ||
91 | finalcode = Regex.Replace(finalcode, | ||
92 | @"YP.script_event\(Atom.a\(\@\""(.*?)""\)\,", | ||
93 | @"this.$1(", | ||
94 | RegexOptions.Compiled | RegexOptions.Singleline); | ||
95 | finalcode = Regex.Replace(finalcode, | ||
96 | @" static ", | ||
97 | @" ", | ||
98 | RegexOptions.Compiled | RegexOptions.Singleline); | ||
99 | |||
100 | finalcode = CS_code+"\n\r"+ finalcode; | ||
101 | finalcode = Regex.Replace(finalcode, | ||
102 | @"PrologCallback", | ||
103 | @"public IEnumerable<bool> ", | ||
104 | RegexOptions.Compiled | RegexOptions.Singleline); | ||
105 | return finalcode; | ||
106 | } | ||
107 | } | ||
108 | } | ||