aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs230
1 files changed, 124 insertions, 106 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index af324bf..89211a5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -79,12 +79,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
79 79
80 private List<string> m_warnings = new List<string>(); 80 private List<string> m_warnings = new List<string>();
81 81
82 // private object m_syncy = new object();
83
84 private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
85 private static VBCodeProvider VBcodeProvider = new VBCodeProvider();
86
87 // private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files
88 private static UInt64 scriptCompileCounter = 0; // And a counter 82 private static UInt64 scriptCompileCounter = 0; // And a counter
89 83
90 public IScriptEngine m_scriptEngine; 84 public IScriptEngine m_scriptEngine;
@@ -119,7 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
119 { 113 {
120 in_startup = false; 114 in_startup = false;
121 CheckOrCreateScriptsDirectory(); 115 CheckOrCreateScriptsDirectory();
122 116
123 // First time we start? Delete old files 117 // First time we start? Delete old files
124 if (DeleteScriptsOnStartup) 118 if (DeleteScriptsOnStartup)
125 DeleteOldFiles(); 119 DeleteOldFiles();
@@ -251,23 +245,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
251 } 245 }
252 } 246 }
253 247
254 ////private ICodeCompiler icc = codeProvider.CreateCompiler();
255 //public string CompileFromFile(string LSOFileName)
256 //{
257 // switch (Path.GetExtension(LSOFileName).ToLower())
258 // {
259 // case ".txt":
260 // case ".lsl":
261 // Common.ScriptEngineBase.Shared.SendToDebug("Source code is LSL, converting to CS");
262 // return CompileFromLSLText(File.ReadAllText(LSOFileName));
263 // case ".cs":
264 // Common.ScriptEngineBase.Shared.SendToDebug("Source code is CS");
265 // return CompileFromCSText(File.ReadAllText(LSOFileName));
266 // default:
267 // throw new Exception("Unknown script type.");
268 // }
269 //}
270
271 public string GetCompilerOutput(string assetID) 248 public string GetCompilerOutput(string assetID)
272 { 249 {
273 return Path.Combine(ScriptEnginesPath, Path.Combine( 250 return Path.Combine(ScriptEnginesPath, Path.Combine(
@@ -310,9 +287,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
310 { 287 {
311// m_log.DebugFormat("[Compiler]: Found existing assembly {0} for asset {1} in {2}", assembly, asset, m_scriptEngine.World.Name); 288// m_log.DebugFormat("[Compiler]: Found existing assembly {0} for asset {1} in {2}", assembly, asset, m_scriptEngine.World.Name);
312 289
313 // If we have already read this linemap file, then it will be in our dictionary. 290 // If we have already read this linemap file, then it will be in our dictionary.
314 // Don't build another copy of the dictionary (saves memory) and certainly 291 // Don't build another copy of the dictionary (saves memory) and certainly
315 // don't keep reading the same file from disk multiple times. 292 // don't keep reading the same file from disk multiple times.
316 if (!m_lineMaps.ContainsKey(assembly)) 293 if (!m_lineMaps.ContainsKey(assembly))
317 m_lineMaps[assembly] = ReadMapFile(assembly + ".map"); 294 m_lineMaps[assembly] = ReadMapFile(assembly + ".map");
318 linemap = m_lineMaps[assembly]; 295 linemap = m_lineMaps[assembly];
@@ -356,14 +333,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
356 throw new Exception(errtext); 333 throw new Exception(errtext);
357 } 334 }
358 335
359 string compileScript = source; 336 string compileScript = string.Empty;
360 337
361 if (language == enumCompileType.lsl) 338 if (language == enumCompileType.lsl)
362 { 339 {
363 // Its LSL, convert it to C# 340 // Its LSL, convert it to C#
364 LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
365 compileScript = LSL_Converter.Convert(source);
366 341
342 StringBuilder sb = new StringBuilder(16394);
343
344 LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
345 AddCSScriptHeader(
346 m_scriptEngine.ScriptClassName,
347 m_scriptEngine.ScriptBaseClassName,
348 m_scriptEngine.ScriptBaseClassParameters,
349 sb);
350
351 LSL_Converter.Convert(source,sb);
352 AddCSScriptTail(sb);
353 compileScript = sb.ToString();
367 // copy converter warnings into our warnings. 354 // copy converter warnings into our warnings.
368 foreach (string warning in LSL_Converter.GetWarnings()) 355 foreach (string warning in LSL_Converter.GetWarnings())
369 { 356 {
@@ -371,25 +358,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
371 } 358 }
372 359
373 linemap = ((CSCodeGenerator)LSL_Converter).PositionMap; 360 linemap = ((CSCodeGenerator)LSL_Converter).PositionMap;
374 // Write the linemap to a file and save it in our dictionary for next time. 361 // Write the linemap to a file and save it in our dictionary for next time.
375 m_lineMaps[assembly] = linemap; 362 m_lineMaps[assembly] = linemap;
376 WriteMapFile(assembly + ".map", linemap); 363 WriteMapFile(assembly + ".map", linemap);
364 LSL_Converter.Clear();
377 } 365 }
378 366 else
379 switch (language)
380 { 367 {
381 case enumCompileType.cs: 368 switch (language)
382 case enumCompileType.lsl: 369 {
383 compileScript = CreateCSCompilerScript( 370 case enumCompileType.cs:
384 compileScript, 371 compileScript = CreateCSCompilerScript(
385 m_scriptEngine.ScriptClassName, 372 source,
386 m_scriptEngine.ScriptBaseClassName, 373 m_scriptEngine.ScriptClassName,
387 m_scriptEngine.ScriptBaseClassParameters); 374 m_scriptEngine.ScriptBaseClassName,
388 break; 375 m_scriptEngine.ScriptBaseClassParameters);
389 case enumCompileType.vb: 376 break;
390 compileScript = CreateVBCompilerScript( 377 case enumCompileType.vb:
391 compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName); 378 compileScript = CreateVBCompilerScript(
392 break; 379 source, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName);
380 break;
381 }
393 } 382 }
394 383
395 assembly = CompileFromDotNetText(compileScript, language, asset, assembly); 384 assembly = CompileFromDotNetText(compileScript, language, asset, assembly);
@@ -419,29 +408,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
419// return compileScript; 408// return compileScript;
420// } 409// }
421 410
411 public static void AddCSScriptHeader(string className, string baseClassName, ParameterInfo[] constructorParameters, StringBuilder sb)
412 {
413 sb.Append(string.Format(
414@"using OpenSim.Region.ScriptEngine.Shared;
415using System.Collections.Generic;
416
417namespace SecondLife
418{{
419 public class {0} : {1}
420 {{
421 public {0}({2}) : base({3}) {{}}
422",
423 className,
424 baseClassName,
425 constructorParameters != null
426 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.ToString()))
427 : "",
428 constructorParameters != null
429 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.Name))
430 : ""
431 ));
432 }
433
434 public static void AddCSScriptTail(StringBuilder sb)
435 {
436 sb.Append(string.Format(" }}\n}}\n"));
437 }
438
422 public static string CreateCSCompilerScript( 439 public static string CreateCSCompilerScript(
423 string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters) 440 string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters)
424 { 441 {
425 compileScript = string.Format( 442 compileScript = string.Format(
426@"using OpenSim.Region.ScriptEngine.Shared; 443@"using OpenSim.Region.ScriptEngine.Shared;
427using System.Collections.Generic; 444using System.Collections.Generic;
428 445
429namespace SecondLife 446namespace SecondLife
430{{ 447{{
431 public class {0} : {1} 448 public class {0} : {1}
432 {{ 449 {{
433 public {0}({2}) : base({3}) {{}} 450 public {0}({2}) : base({3}) {{}}
434{4} 451{4}
435 }} 452 }}
436}}", 453}}",
437 className, 454 className,
438 baseClassName, 455 baseClassName,
439 constructorParameters != null 456 constructorParameters != null
440 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.ToString())) 457 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.ToString()))
441 : "", 458 : "",
442 constructorParameters != null 459 constructorParameters != null
443 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.Name)) 460 ? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.Name))
444 : "", 461 : "",
445 compileScript); 462 compileScript);
446 463
447 return compileScript; 464 return compileScript;
@@ -468,7 +485,7 @@ namespace SecondLife
468 internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset, string assembly) 485 internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset, string assembly)
469 { 486 {
470// m_log.DebugFormat("[Compiler]: Compiling to assembly\n{0}", Script); 487// m_log.DebugFormat("[Compiler]: Compiling to assembly\n{0}", Script);
471 488
472 string ext = "." + lang.ToString(); 489 string ext = "." + lang.ToString();
473 490
474 // Output assembly name 491 // Output assembly name
@@ -511,8 +528,6 @@ namespace SecondLife
511 // Do actual compile 528 // Do actual compile
512 CompilerParameters parameters = new CompilerParameters(); 529 CompilerParameters parameters = new CompilerParameters();
513 530
514 parameters.IncludeDebugInformation = true;
515
516 string rootPath = AppDomain.CurrentDomain.BaseDirectory; 531 string rootPath = AppDomain.CurrentDomain.BaseDirectory;
517 532
518 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 533 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
@@ -524,7 +539,7 @@ namespace SecondLife
524 539
525 if (m_scriptEngine.ScriptReferencedAssemblies != null) 540 if (m_scriptEngine.ScriptReferencedAssemblies != null)
526 Array.ForEach<string>( 541 Array.ForEach<string>(
527 m_scriptEngine.ScriptReferencedAssemblies, 542 m_scriptEngine.ScriptReferencedAssemblies,
528 a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a))); 543 a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a)));
529 544
530 parameters.GenerateExecutable = false; 545 parameters.GenerateExecutable = false;
@@ -532,62 +547,62 @@ namespace SecondLife
532 parameters.IncludeDebugInformation = CompileWithDebugInformation; 547 parameters.IncludeDebugInformation = CompileWithDebugInformation;
533 //parameters.WarningLevel = 1; // Should be 4? 548 //parameters.WarningLevel = 1; // Should be 4?
534 parameters.TreatWarningsAsErrors = false; 549 parameters.TreatWarningsAsErrors = false;
550 parameters.GenerateInMemory = false;
551
552// this seems to cause issues on some windows servers
553// parameters.TempFiles = new TempFileCollection(Path.Combine(ScriptEnginesPath,
554// m_scriptEngine.World.RegionInfo.RegionID.ToString()), CompileWithDebugInformation);
535 555
536 CompilerResults results; 556 CompilerResults results;
557
558 CodeDomProvider provider;
537 switch (lang) 559 switch (lang)
538 { 560 {
539 case enumCompileType.vb: 561 case enumCompileType.vb:
540 results = VBcodeProvider.CompileAssemblyFromSource( 562 provider = CodeDomProvider.CreateProvider("VisualBasic");
541 parameters, Script);
542 break; 563 break;
543 case enumCompileType.cs: 564 case enumCompileType.cs:
544 case enumCompileType.lsl: 565 case enumCompileType.lsl:
545 bool complete = false; 566 provider = CodeDomProvider.CreateProvider("CSharp");
546 bool retried = false;
547 do
548 {
549 lock (CScodeProvider)
550 {
551 results = CScodeProvider.CompileAssemblyFromSource(
552 parameters, Script);
553 }
554
555 // Deal with an occasional segv in the compiler.
556 // Rarely, if ever, occurs twice in succession.
557 // Line # == 0 and no file name are indications that
558 // this is a native stack trace rather than a normal
559 // error log.
560 if (results.Errors.Count > 0)
561 {
562 if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) &&
563 results.Errors[0].Line == 0)
564 {
565 // System.Console.WriteLine("retrying failed compilation");
566 retried = true;
567 }
568 else
569 {
570 complete = true;
571 }
572 }
573 else
574 {
575 complete = true;
576 }
577 } while (!complete);
578 break; 567 break;
579 default: 568 default:
580 throw new Exception("Compiler is not able to recongnize " + 569 throw new Exception("Compiler is not able to recongnize " +
581 "language type \"" + lang.ToString() + "\""); 570 "language type \"" + lang.ToString() + "\"");
582 } 571 }
583 572
584// foreach (Type type in results.CompiledAssembly.GetTypes()) 573 if(provider == null)
585// { 574 throw new Exception("Compiler failed to load ");
586// foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) 575
587// { 576 bool complete = false;
588// m_log.DebugFormat("[COMPILER]: {0}.{1}", type.FullName, method.Name); 577 bool retried = false;
589// } 578
590// } 579 do
580 {
581 results = provider.CompileAssemblyFromSource(
582 parameters, Script);
583 // Deal with an occasional segv in the compiler.
584 // Rarely, if ever, occurs twice in succession.
585 // Line # == 0 and no file name are indications that
586 // this is a native stack trace rather than a normal
587 // error log.
588 if (results.Errors.Count > 0)
589 {
590 if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) &&
591 results.Errors[0].Line == 0)
592 {
593 // System.Console.WriteLine("retrying failed compilation");
594 retried = true;
595 }
596 else
597 {
598 complete = true;
599 }
600 }
601 else
602 {
603 complete = true;
604 }
605 } while (!complete);
591 606
592 // 607 //
593 // WARNINGS AND ERRORS 608 // WARNINGS AND ERRORS
@@ -628,13 +643,15 @@ namespace SecondLife
628 } 643 }
629 } 644 }
630 645
646 provider.Dispose();
647
631 if (hadErrors) 648 if (hadErrors)
632 { 649 {
633 throw new Exception(errtext); 650 throw new Exception(errtext);
634 } 651 }
635 652
636 // On today's highly asynchronous systems, the result of 653 // On today's highly asynchronous systems, the result of
637 // the compile may not be immediately apparent. Wait a 654 // the compile may not be immediately apparent. Wait a
638 // reasonable amount of time before giving up on it. 655 // reasonable amount of time before giving up on it.
639 656
640 if (!File.Exists(assembly)) 657 if (!File.Exists(assembly))
@@ -785,15 +802,16 @@ namespace SecondLife
785 802
786 private static void WriteMapFile(string filename, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap) 803 private static void WriteMapFile(string filename, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap)
787 { 804 {
788 string mapstring = String.Empty; 805 StringBuilder mapbuilder = new StringBuilder(1024);
806
789 foreach (KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> kvp in linemap) 807 foreach (KeyValuePair<KeyValuePair<int, int>, KeyValuePair<int, int>> kvp in linemap)
790 { 808 {
791 KeyValuePair<int, int> k = kvp.Key; 809 KeyValuePair<int, int> k = kvp.Key;
792 KeyValuePair<int, int> v = kvp.Value; 810 KeyValuePair<int, int> v = kvp.Value;
793 mapstring += String.Format("{0},{1},{2},{3}\n", k.Key, k.Value, v.Key, v.Value); 811 mapbuilder.Append(String.Format("{0},{1},{2},{3}\n", k.Key, k.Value, v.Key, v.Value));
794 } 812 }
795 813
796 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring); 814 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapbuilder.ToString());
797 815
798 using (FileStream mfs = File.Create(filename)) 816 using (FileStream mfs = File.Create(filename))
799 mfs.Write(mapbytes, 0, mapbytes.Length); 817 mfs.Write(mapbytes, 0, mapbytes.Length);