aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-27 05:31:43 +0000
committerMelanie Thielker2008-09-27 05:31:43 +0000
commit85068dae60db02b168a29ffd75e1408e30d279e1 (patch)
tree8389c246a6e9891eb1bf310b85cba19a1668d790 /OpenSim/Region/ScriptEngine/Shared
parentMantis #2277 (diff)
downloadopensim-SC-85068dae60db02b168a29ffd75e1408e30d279e1.zip
opensim-SC-85068dae60db02b168a29ffd75e1408e30d279e1.tar.gz
opensim-SC-85068dae60db02b168a29ffd75e1408e30d279e1.tar.bz2
opensim-SC-85068dae60db02b168a29ffd75e1408e30d279e1.tar.xz
Add friendly error messages to both engines.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs225
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs51
3 files changed, 220 insertions, 75 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 86d6188..e8f2b71 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -89,7 +89,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
89 ResetCounters(); 89 ResetCounters();
90 Parser p = new LSLSyntax(new yyLSLSyntax(), new ErrorHandler(true)); 90 Parser p = new LSLSyntax(new yyLSLSyntax(), new ErrorHandler(true));
91 // Obviously this needs to be in a try/except block. 91 // Obviously this needs to be in a try/except block.
92 LSL2CSCodeTransformer codeTransformer = new LSL2CSCodeTransformer(p.Parse(script)); 92 LSL2CSCodeTransformer codeTransformer;
93 try
94 {
95 codeTransformer = new LSL2CSCodeTransformer(p.Parse(script));
96 }
97 catch (CSToolsException e)
98 {
99 string message;
100
101 // LL start numbering lines at 0 - geeks!
102 //
103 message = String.Format("Line ({0},{1}) {2}",
104 e.slInfo.lineNumber - 1,
105 e.slInfo.charPosition - 1, e.Message);
106
107 throw new Exception(message);
108 }
109
93 m_astRoot = codeTransformer.Transform(); 110 m_astRoot = codeTransformer.Transform();
94 111
95 string retstr = String.Empty; 112 string retstr = String.Empty;
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index ec864e1..c6026fb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -38,7 +38,7 @@ using OpenSim.Region.ScriptEngine.Interfaces;
38 38
39namespace OpenSim.Region.ScriptEngine.Shared.CodeTools 39namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
40{ 40{
41 public class Compiler 41 public class Compiler : ICompiler
42 { 42 {
43 // private static readonly log4net.ILog m_log 43 // private static readonly log4net.ILog m_log
44 // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 44 // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@@ -255,18 +255,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
255 /// <returns>Filename to .dll assembly</returns> 255 /// <returns>Filename to .dll assembly</returns>
256 public string PerformScriptCompile(string Script, string asset) 256 public string PerformScriptCompile(string Script, string asset)
257 { 257 {
258 m_positionMap = null;
259
258 string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( 260 string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
259 m_scriptEngine.World.RegionInfo.RegionID.ToString(), 261 m_scriptEngine.World.RegionInfo.RegionID.ToString(),
260 FilePrefix + "_compiled_" + asset + ".dll")); 262 FilePrefix + "_compiled_" + asset + ".dll"));
261// string OutFile = Path.Combine(ScriptEnginesPath, 263// string OutFile = Path.Combine(ScriptEnginesPath,
262// FilePrefix + "_compiled_" + asset + ".dll"); 264// FilePrefix + "_compiled_" + asset + ".dll");
263 265
264 if (File.Exists(OutFile))
265 {
266 m_scriptEngine.Log.DebugFormat("[Compiler] Returning existing assembly for {0}", asset);
267 return OutFile;
268 }
269
270 if (!Directory.Exists(ScriptEnginesPath)) 266 if (!Directory.Exists(ScriptEnginesPath))
271 { 267 {
272 try 268 try
@@ -327,38 +323,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
327 compileScript = LSL_Converter.Convert(Script); 323 compileScript = LSL_Converter.Convert(Script);
328 324
329 m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap; 325 m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap;
326 }
330 327
331 l = enumCompileType.cs; 328 // Check this late so the map is generated on sim start
329 //
330 if (File.Exists(OutFile))
331 {
332 m_scriptEngine.Log.DebugFormat("[Compiler] Returning existing assembly for {0}", asset);
333 return OutFile;
332 } 334 }
333 335
334 if (l == enumCompileType.yp) 336 if (l == enumCompileType.yp)
335 { 337 {
336 // Its YP, convert it to C# 338 // Its YP, convert it to C#
337 compileScript = YP_Converter.Convert(Script); 339 compileScript = YP_Converter.Convert(Script);
338 // We have our own processor now
339 //l = enumCompileType.cs;
340 }
341
342 // Insert additional assemblies here
343
344 //ADAM: Disabled for the moment until it's working right.
345 bool enableCommanderLSL = false;
346
347 if (enableCommanderLSL == true && ((l == enumCompileType.cs) || (l == enumCompileType.yp)))
348 {
349 foreach (KeyValuePair<string,
350 ICommander> com
351 in m_scriptEngine.World.GetCommanders())
352 {
353 compileScript = com.Value.GenerateRuntimeAPI() + compileScript;
354 }
355 } 340 }
356 341
357 // End of insert
358
359 switch (l) 342 switch (l)
360 { 343 {
361 case enumCompileType.cs: 344 case enumCompileType.cs:
345 case enumCompileType.lsl:
362 compileScript = CreateCSCompilerScript(compileScript); 346 compileScript = CreateCSCompilerScript(compileScript);
363 break; 347 break;
364 case enumCompileType.vb: 348 case enumCompileType.vb:
@@ -372,10 +356,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
372 break; 356 break;
373 } 357 }
374 358
375// m_log.Debug("[ScriptEngine.DotNetEngine]: Preparing to compile the following LSL to C# translated code");
376// m_log.Debug("");
377// m_log.Debug(compileScript);
378
379 return CompileFromDotNetText(compileScript, l, asset); 359 return CompileFromDotNetText(compileScript, l, asset);
380 } 360 }
381 361
@@ -442,26 +422,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
442 // Output assembly name 422 // Output assembly name
443 scriptCompileCounter++; 423 scriptCompileCounter++;
444 string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine( 424 string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
445 m_scriptEngine.World.RegionInfo.RegionID.ToString(), 425 m_scriptEngine.World.RegionInfo.RegionID.ToString(),
446 FilePrefix + "_compiled_" + asset + ".dll")); 426 FilePrefix + "_compiled_" + asset + ".dll"));
447#if DEBUG
448// m_scriptEngine.Log.Debug("[Compiler]: Starting compile of \"" + OutFile + "\".");
449#endif
450 try 427 try
451 { 428 {
452 File.Delete(OutFile); 429 File.Delete(OutFile);
453 } 430 }
454 catch (Exception e) // NOTLEGIT - Should be just catching FileIOException 431 catch (Exception e) // NOTLEGIT - Should be just FileIOException
455 { 432 {
456 //m_scriptEngine.Log.Error("[Compiler]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); 433 throw new Exception("Unable to delete old existing "+
457 throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString()); 434 "script-file before writing new. Compile aborted: " +
435 e.ToString());
458 } 436 }
459 //string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
460 437
461 // DEBUG - write source to disk 438 // DEBUG - write source to disk
462 if (WriteScriptSourceToDebugFile) 439 if (WriteScriptSourceToDebugFile)
463 { 440 {
464 string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext; 441 string srcFileName = FilePrefix + "_source_" +
442 Path.GetFileNameWithoutExtension(OutFile) + ext;
465 try 443 try
466 { 444 {
467 File.WriteAllText(Path.Combine(Path.Combine( 445 File.WriteAllText(Path.Combine(Path.Combine(
@@ -469,9 +447,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
469 m_scriptEngine.World.RegionInfo.RegionID.ToString()), 447 m_scriptEngine.World.RegionInfo.RegionID.ToString()),
470 srcFileName), Script); 448 srcFileName), Script);
471 } 449 }
472 catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException 450 catch (Exception ex) //NOTLEGIT - Should be just FileIOException
473 { 451 {
474 m_scriptEngine.Log.Error("[Compiler]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString()); 452 m_scriptEngine.Log.Error("[Compiler]: Exception while "+
453 "trying to write script source to file \"" +
454 srcFileName + "\": " + ex.ToString());
475 } 455 }
476 } 456 }
477 457
@@ -480,22 +460,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
480 460
481 parameters.IncludeDebugInformation = true; 461 parameters.IncludeDebugInformation = true;
482 462
483 // Add all available assemblies 463 string rootPath =
484// foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) 464 Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
485// {
486// Console.WriteLine("Adding assembly: " + asm.Location);
487// parameters.ReferencedAssemblies.Add(asm.Location);
488// }
489 465
490 string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory); 466 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
491 // string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location); 467 "OpenSim.Region.ScriptEngine.Shared.dll"));
492 //Console.WriteLine("Assembly location: " + rootPath); 468 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
493 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.dll")); 469 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
494 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
495 470
496 if (lang == enumCompileType.yp) 471 if (lang == enumCompileType.yp)
497 { 472 {
498 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.YieldProlog.dll")); 473 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
474 "OpenSim.Region.ScriptEngine.Shared.YieldProlog.dll"));
499 } 475 }
500 476
501 parameters.GenerateExecutable = false; 477 parameters.GenerateExecutable = false;
@@ -504,24 +480,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
504 //parameters.WarningLevel = 1; // Should be 4? 480 //parameters.WarningLevel = 1; // Should be 4?
505 parameters.TreatWarningsAsErrors = false; 481 parameters.TreatWarningsAsErrors = false;
506 482
507//Console.WriteLine(Script);
508 CompilerResults results; 483 CompilerResults results;
509 switch (lang) 484 switch (lang)
510 { 485 {
511 case enumCompileType.vb: 486 case enumCompileType.vb:
512 results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script); 487 results = VBcodeProvider.CompileAssemblyFromSource(
488 parameters, Script);
513 break; 489 break;
514 case enumCompileType.cs: 490 case enumCompileType.cs:
515 results = CScodeProvider.CompileAssemblyFromSource(parameters, Script); 491 case enumCompileType.lsl:
492 results = CScodeProvider.CompileAssemblyFromSource(
493 parameters, Script);
516 break; 494 break;
517 case enumCompileType.js: 495 case enumCompileType.js:
518 results = JScodeProvider.CompileAssemblyFromSource(parameters, Script); 496 results = JScodeProvider.CompileAssemblyFromSource(
497 parameters, Script);
519 break; 498 break;
520 case enumCompileType.yp: 499 case enumCompileType.yp:
521 results = YPcodeProvider.CompileAssemblyFromSource(parameters, Script); 500 results = YPcodeProvider.CompileAssemblyFromSource(
501 parameters, Script);
522 break; 502 break;
523 default: 503 default:
524 throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\""); 504 throw new Exception("Compiler is not able to recongnize "+
505 "language type \"" + lang.ToString() + "\"");
525 } 506 }
526 507
527 // Check result 508 // Check result
@@ -530,11 +511,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
530 // 511 //
531 // WARNINGS AND ERRORS 512 // WARNINGS AND ERRORS
532 // 513 //
514 int display = 5;
533 if (results.Errors.Count > 0) 515 if (results.Errors.Count > 0)
534 { 516 {
535 string errtext = String.Empty; 517 string errtext = String.Empty;
536 foreach (CompilerError CompErr in results.Errors) 518 foreach (CompilerError CompErr in results.Errors)
537 { 519 {
520 // Show 5 errors max
521 //
522 if (display <= 0)
523 break;
524 display--;
525
538 string severity = "Error"; 526 string severity = "Error";
539 if ( CompErr.IsWarning ) 527 if ( CompErr.IsWarning )
540 { 528 {
@@ -543,22 +531,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
543 531
544 KeyValuePair<int, int> lslPos; 532 KeyValuePair<int, int> lslPos;
545 533
546 try 534 lslPos = FindErrorPosition(CompErr.Line, CompErr.Column);
547 { 535
548 lslPos = m_positionMap[new KeyValuePair<int, int>(CompErr.Line, CompErr.Column)]; 536 string text = CompErr.ErrorText;
549 } 537
550 catch (KeyNotFoundException) // we don't have this line/column mapped 538 // Use LSL type names
551 { 539 if (lang == enumCompileType.lsl)
552 m_scriptEngine.Log.Debug(String.Format("[Compiler]: Lookup of C# line {0}, column {1} failed.", CompErr.Line, CompErr.Column)); 540 text = ReplaceTypes(CompErr.ErrorText);
553 lslPos = new KeyValuePair<int, int>(-CompErr.Line, -CompErr.Column);
554 }
555 541
556 // The Second Life viewer's script editor begins 542 // The Second Life viewer's script editor begins
557 // countingn lines and columns at 0, so we subtract 1. 543 // countingn lines and columns at 0, so we subtract 1.
558 errtext += String.Format("Line {0}, column {1}, {4} Number: {2}, '{3}'\r\n", lslPos.Key - 1, lslPos.Value - 1, CompErr.ErrorNumber, CompErr.ErrorText, severity); 544 errtext += String.Format("Line ({0},{1}): {4} {2}: {3}\n",
545 lslPos.Key - 1, lslPos.Value - 1,
546 CompErr.ErrorNumber, text, severity);
559 } 547 }
560 548
561 Console.WriteLine("[COMPILER MESSAGES]: " + errtext);
562 if (!File.Exists(OutFile)) 549 if (!File.Exists(OutFile))
563 { 550 {
564 throw new Exception(errtext); 551 throw new Exception(errtext);
@@ -574,8 +561,100 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
574 errtext += "No compile error. But not able to locate compiled file."; 561 errtext += "No compile error. But not able to locate compiled file.";
575 throw new Exception(errtext); 562 throw new Exception(errtext);
576 } 563 }
577 m_scriptEngine.Log.DebugFormat("[Compiler] Compiled new assembly for {0}", asset); 564 m_scriptEngine.Log.DebugFormat("[Compiler] Compiled new assembly "+
565 "for {0}", asset);
578 return OutFile; 566 return OutFile;
579 } 567 }
568
569 public KeyValuePair<int, int> FindErrorPosition(int line, int col)
570 {
571 return FindErrorPosition(line, col, m_positionMap);
572 }
573
574 private class kvpSorter : IComparer<KeyValuePair<int,int>>
575 {
576 public int Compare(KeyValuePair<int,int> a,
577 KeyValuePair<int,int> b)
578 {
579 return a.Key.CompareTo(b.Key);
580 }
581 }
582
583 public static KeyValuePair<int, int> FindErrorPosition(int line,
584 int col, Dictionary<KeyValuePair<int, int>,
585 KeyValuePair<int, int>> positionMap)
586 {
587 if (positionMap == null || positionMap.Count == 0)
588 return new KeyValuePair<int, int>(line, col);
589
590 KeyValuePair<int, int> ret = new KeyValuePair<int, int>();
591
592 if (positionMap.TryGetValue(new KeyValuePair<int, int>(line, col),
593 out ret))
594 return ret;
595
596 List<KeyValuePair<int,int>> sorted =
597 new List<KeyValuePair<int,int>>(positionMap.Keys);
598
599 sorted.Sort(new kvpSorter());
600
601 int l = 1;
602 int c = 1;
603
604 foreach (KeyValuePair<int, int> cspos in sorted)
605 {
606 if (cspos.Key >= line)
607 {
608 if (cspos.Key > line)
609 return new KeyValuePair<int, int>(l, c);
610 if (cspos.Value > col)
611 return new KeyValuePair<int, int>(l, c);
612 c = cspos.Value;
613 if (c == 0)
614 c++;
615 }
616 else
617 {
618 l = cspos.Key;
619 }
620 }
621 return new KeyValuePair<int, int>(l, c);
622 }
623
624 string ReplaceTypes(string message)
625 {
626 message = message.Replace(
627 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString",
628 "string");
629
630 message = message.Replace(
631 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger",
632 "integer");
633
634 message = message.Replace(
635 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat",
636 "float");
637
638 message = message.Replace(
639 "OpenSim.Region.ScriptEngine.Shared.LSL_Types.list",
640 "list");
641
642 return message;
643 }
644
645 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>
646 LineMap()
647 {
648 if (m_positionMap == null)
649 return null;
650
651 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> ret =
652 new Dictionary<KeyValuePair<int,int>, KeyValuePair<int, int>>();
653
654 foreach (KeyValuePair<int, int> kvp in m_positionMap.Keys)
655 ret.Add(kvp, m_positionMap[kvp]);
656
657 return ret;
658 }
580 } 659 }
581} 660}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index c8d60af..aa9ace4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -80,6 +80,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
80 private int m_ControlEventsInQueue = 0; 80 private int m_ControlEventsInQueue = 0;
81 private int m_LastControlLevel = 0; 81 private int m_LastControlLevel = 0;
82 private bool m_CollisionInQueue = false; 82 private bool m_CollisionInQueue = false;
83 private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>
84 m_LineMap;
85
86 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>
87 LineMap
88 {
89 get { return m_LineMap; }
90 set { m_LineMap = value; }
91 }
83 92
84 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); 93 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
85 94
@@ -628,7 +637,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
628 try 637 try
629 { 638 {
630 // DISPLAY ERROR INWORLD 639 // DISPLAY ERROR INWORLD
631 string text = "Runtime error:\n" + e.InnerException.ToString(); 640 string text = FormatException(e);
641
632 if (text.Length > 1000) 642 if (text.Length > 1000)
633 text = text.Substring(0, 1000); 643 text = text.Substring(0, 1000);
634 m_Engine.World.SimChat(Utils.StringToBytes(text), 644 m_Engine.World.SimChat(Utils.StringToBytes(text),
@@ -812,5 +822,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
812 { 822 {
813 return String.Format("{0} {1} on {2}", m_ScriptName, m_ItemID, m_PrimName); 823 return String.Format("{0} {1} on {2}", m_ScriptName, m_ItemID, m_PrimName);
814 } 824 }
825
826 string FormatException(Exception e)
827 {
828 string message = "Runtime error:\n" + e.InnerException.StackTrace;
829 string[] lines = message.Split(new char[] {'\n'});
830
831 foreach (string line in lines)
832 {
833 if (line.Contains("SecondLife.Script"))
834 {
835 int idx = line.IndexOf(':');
836 if (idx != -1)
837 {
838 string val = line.Substring(idx+1);
839 int lineNum = 0;
840 if (int.TryParse(val, out lineNum))
841 {
842 KeyValuePair<int, int> pos =
843 Compiler.FindErrorPosition(
844 lineNum, 0, LineMap);
845
846 int scriptLine = pos.Key;
847 int col = pos.Value;
848 if (scriptLine == 0)
849 scriptLine++;
850 if (col == 0)
851 col++;
852 message = string.Format("Runtime error:\n" +
853 "Line ({0}): {1}", scriptLine - 1,
854 e.InnerException.Message);
855
856 return message;
857 }
858 }
859 }
860 }
861
862 return message;
863 }
815 } 864 }
816} 865}