diff options
author | Charles Krinke | 2009-02-23 02:43:51 +0000 |
---|---|---|
committer | Charles Krinke | 2009-02-23 02:43:51 +0000 |
commit | 08c76989a719803e4cb7c5391bc864046bba31f2 (patch) | |
tree | b62e6288ba9ce024a5020d0f302a059e44ba457e | |
parent | A little bit more tweaking with appearance. Now passing both the wearables an... (diff) | |
download | opensim-SC_OLD-08c76989a719803e4cb7c5391bc864046bba31f2.zip opensim-SC_OLD-08c76989a719803e4cb7c5391bc864046bba31f2.tar.gz opensim-SC_OLD-08c76989a719803e4cb7c5391bc864046bba31f2.tar.bz2 opensim-SC_OLD-08c76989a719803e4cb7c5391bc864046bba31f2.tar.xz |
Mantis#3187. Thank you kindly, DoranZemlja for a patch that:
Adds a warning for an LSL construct that exploits a
popular list memory saving hack.
6 files changed, 169 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs index 4ede7f1..32eb200 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs | |||
@@ -218,6 +218,43 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
218 | localID, itemID, "on_rez", new DetectParams[0], | 218 | localID, itemID, "on_rez", new DetectParams[0], |
219 | new object[] { new LSL_Types.LSLInteger(startParam) }); | 219 | new object[] { new LSL_Types.LSLInteger(startParam) }); |
220 | } | 220 | } |
221 | |||
222 | string[] warnings = LSLCompiler.GetWarnings(); | ||
223 | |||
224 | if (warnings != null && warnings.Length != 0) | ||
225 | { | ||
226 | if (presence != null && (!postOnRez)) | ||
227 | presence.ControllingClient.SendAgentAlertMessage( | ||
228 | "Script saved with warnings, check debug window!", | ||
229 | false); | ||
230 | |||
231 | foreach (string warning in warnings) | ||
232 | { | ||
233 | try | ||
234 | { | ||
235 | // DISPLAY WARNING INWORLD | ||
236 | string text = "Warning:\n" + warning; | ||
237 | if (text.Length > 1100) | ||
238 | text = text.Substring(0, 1099); | ||
239 | |||
240 | World.SimChat(Utils.StringToBytes(text), | ||
241 | ChatTypeEnum.DebugChannel, 2147483647, | ||
242 | m_host.AbsolutePosition, m_host.Name, m_host.UUID, | ||
243 | false); | ||
244 | } | ||
245 | catch (Exception e2) // LEGIT: User Scripting | ||
246 | { | ||
247 | m_log.Error("[" + | ||
248 | m_scriptEngine.ScriptEngineName + | ||
249 | "]: Error displaying warning in-world: " + | ||
250 | e2.ToString()); | ||
251 | m_log.Error("[" + | ||
252 | m_scriptEngine.ScriptEngineName + "]: " + | ||
253 | "Warning:\r\n" + | ||
254 | warning); | ||
255 | } | ||
256 | } | ||
257 | } | ||
221 | } | 258 | } |
222 | catch (Exception e) // LEGIT: User Scripting | 259 | catch (Exception e) // LEGIT: User Scripting |
223 | { | 260 | { |
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs b/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs index 6273da9..d11abbc 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs | |||
@@ -34,6 +34,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces | |||
34 | public interface ICompiler | 34 | public interface ICompiler |
35 | { | 35 | { |
36 | string PerformScriptCompile(string source, string asset); | 36 | string PerformScriptCompile(string source, string asset); |
37 | string[] GetWarnings(); | ||
37 | Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> | 38 | Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> |
38 | LineMap(); | 39 | LineMap(); |
39 | } | 40 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index 71e88e3..880ba4a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs | |||
@@ -40,6 +40,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
40 | private int m_braceCount; // for indentation | 40 | private int m_braceCount; // for indentation |
41 | private int m_CSharpLine; // the current line of generated C# code | 41 | private int m_CSharpLine; // the current line of generated C# code |
42 | private int m_CSharpCol; // the current column of generated C# code | 42 | private int m_CSharpCol; // the current column of generated C# code |
43 | private List<string> m_warnings = new List<string>(); | ||
43 | 44 | ||
44 | /// <summary> | 45 | /// <summary> |
45 | /// Creates an 'empty' CSCodeGenerator instance. | 46 | /// Creates an 'empty' CSCodeGenerator instance. |
@@ -153,6 +154,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
153 | } | 154 | } |
154 | 155 | ||
155 | /// <summary> | 156 | /// <summary> |
157 | /// Get the set of warnings generated during compilation. | ||
158 | /// </summary> | ||
159 | /// <returns></returns> | ||
160 | public string[] GetWarnings() | ||
161 | { | ||
162 | return m_warnings.ToArray(); | ||
163 | } | ||
164 | |||
165 | private void AddWarning(string warning) | ||
166 | { | ||
167 | if (!m_warnings.Contains(warning)) | ||
168 | { | ||
169 | m_warnings.Add(warning); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /// <summary> | ||
156 | /// Recursively called to generate each type of node. Will generate this | 174 | /// Recursively called to generate each type of node. Will generate this |
157 | /// node, then all it's children. | 175 | /// node, then all it's children. |
158 | /// </summary> | 176 | /// </summary> |
@@ -446,6 +464,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
446 | { | 464 | { |
447 | string retstr = String.Empty; | 465 | string retstr = String.Empty; |
448 | 466 | ||
467 | List<string> identifiers = new List<string>(); | ||
468 | checkForMultipleAssignments(identifiers, a); | ||
469 | |||
449 | retstr += GenerateNode((SYMBOL) a.kids.Pop()); | 470 | retstr += GenerateNode((SYMBOL) a.kids.Pop()); |
450 | retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); | 471 | retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); |
451 | foreach (SYMBOL kid in a.kids) | 472 | foreach (SYMBOL kid in a.kids) |
@@ -454,6 +475,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
454 | return retstr; | 475 | return retstr; |
455 | } | 476 | } |
456 | 477 | ||
478 | // This code checks for LSL of the following forms, and generates a | ||
479 | // warning if it finds them. | ||
480 | // | ||
481 | // list l = [ "foo" ]; | ||
482 | // l = (l=[]) + l + ["bar"]; | ||
483 | // (produces l=["foo","bar"] in SL but l=["bar"] in OS) | ||
484 | // | ||
485 | // integer i; | ||
486 | // integer j; | ||
487 | // i = (j = 3) + (j = 4) + (j = 5); | ||
488 | // (produces j=3 in SL but j=5 in OS) | ||
489 | // | ||
490 | // Without this check, that code passes compilation, but does not do what | ||
491 | // the end user expects, because LSL in SL evaluates right to left instead | ||
492 | // of left to right. | ||
493 | // | ||
494 | // The theory here is that producing an error and alerting the end user that | ||
495 | // something needs to change is better than silently generating incorrect code. | ||
496 | private void checkForMultipleAssignments(List<string> identifiers, SYMBOL s) | ||
497 | { | ||
498 | if (s is Assignment) | ||
499 | { | ||
500 | Assignment a = (Assignment)s; | ||
501 | string newident = null; | ||
502 | |||
503 | if (a.kids[0] is Declaration) | ||
504 | { | ||
505 | newident = ((Declaration)a.kids[0]).Id; | ||
506 | } | ||
507 | else if (a.kids[0] is IDENT) | ||
508 | { | ||
509 | newident = ((IDENT)a.kids[0]).yytext; | ||
510 | } | ||
511 | else if (a.kids[0] is IdentDotExpression) | ||
512 | { | ||
513 | newident = ((IdentDotExpression)a.kids[0]).Name; // +"." + ((IdentDotExpression)a.kids[0]).Member; | ||
514 | } | ||
515 | else | ||
516 | { | ||
517 | AddWarning(String.Format("Multiple assignments checker internal error '{0}' at line {1} column {2}.", a.kids[0].GetType(), ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position)); | ||
518 | } | ||
519 | |||
520 | if (identifiers.Contains(newident)) | ||
521 | { | ||
522 | AddWarning(String.Format("Multiple assignments to '{0}' at line {1} column {2}; results may differ between LSL and OSSL.", newident, ((SYMBOL)a.kids[0]).Line - 1, ((SYMBOL)a.kids[0]).Position)); | ||
523 | } | ||
524 | identifiers.Add(newident); | ||
525 | } | ||
526 | |||
527 | int index; | ||
528 | for (index = 0; index < s.kids.Count; index++) | ||
529 | { | ||
530 | checkForMultipleAssignments(identifiers, (SYMBOL) s.kids[index]); | ||
531 | } | ||
532 | } | ||
533 | |||
457 | /// <summary> | 534 | /// <summary> |
458 | /// Generates the code for a ReturnStatement node. | 535 | /// Generates the code for a ReturnStatement node. |
459 | /// </summary> | 536 | /// </summary> |
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 03b2ab3..59d862d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs | |||
@@ -76,6 +76,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
76 | private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap; | 76 | private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap; |
77 | private ICodeConverter LSL_Converter; | 77 | private ICodeConverter LSL_Converter; |
78 | 78 | ||
79 | private List<string> m_warnings = new List<string>(); | ||
80 | |||
79 | // private object m_syncy = new object(); | 81 | // private object m_syncy = new object(); |
80 | 82 | ||
81 | private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); | 83 | private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); |
@@ -336,6 +338,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
336 | LSL_Converter = (ICodeConverter)new CSCodeGenerator(); | 338 | LSL_Converter = (ICodeConverter)new CSCodeGenerator(); |
337 | compileScript = LSL_Converter.Convert(Script); | 339 | compileScript = LSL_Converter.Convert(Script); |
338 | 340 | ||
341 | // copy converter warnings into our warnings. | ||
342 | foreach(string warning in LSL_Converter.GetWarnings()) | ||
343 | { | ||
344 | AddWarning(warning); | ||
345 | } | ||
346 | |||
339 | m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap; | 347 | m_positionMap = ((CSCodeGenerator) LSL_Converter).PositionMap; |
340 | } | 348 | } |
341 | 349 | ||
@@ -373,6 +381,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
373 | return CompileFromDotNetText(compileScript, l, asset); | 381 | return CompileFromDotNetText(compileScript, l, asset); |
374 | } | 382 | } |
375 | 383 | ||
384 | public string[] GetWarnings() | ||
385 | { | ||
386 | return m_warnings.ToArray(); | ||
387 | } | ||
388 | |||
389 | private void AddWarning(string warning) | ||
390 | { | ||
391 | if (!m_warnings.Contains(warning)) | ||
392 | { | ||
393 | m_warnings.Add(warning); | ||
394 | } | ||
395 | } | ||
396 | |||
376 | private static string CreateJSCompilerScript(string compileScript) | 397 | private static string CreateJSCompilerScript(string compileScript) |
377 | { | 398 | { |
378 | compileScript = String.Empty + | 399 | compileScript = String.Empty + |
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/ICodeConverter.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/ICodeConverter.cs index 28e42da..917000e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/ICodeConverter.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/ICodeConverter.cs | |||
@@ -33,5 +33,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools | |||
33 | public interface ICodeConverter | 33 | public interface ICodeConverter |
34 | { | 34 | { |
35 | string Convert(string script); | 35 | string Convert(string script); |
36 | string[] GetWarnings(); | ||
36 | } | 37 | } |
37 | } | 38 | } |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 75d0bec..40a6dd1 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -516,6 +516,38 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
516 | m_AddingAssemblies[assembly]++; | 516 | m_AddingAssemblies[assembly]++; |
517 | } | 517 | } |
518 | } | 518 | } |
519 | |||
520 | string[] warnings = m_Compiler.GetWarnings(); | ||
521 | |||
522 | if (warnings != null && warnings.Length != 0) | ||
523 | { | ||
524 | if (presence != null && (!postOnRez)) | ||
525 | presence.ControllingClient.SendAgentAlertMessage("Script saved with warnings, check debug window!", false); | ||
526 | |||
527 | foreach (string warning in warnings) | ||
528 | { | ||
529 | try | ||
530 | { | ||
531 | // DISPLAY WARNING INWORLD | ||
532 | string text = "Warning:\n" + warning; | ||
533 | if (text.Length > 1000) | ||
534 | text = text.Substring(0, 1000); | ||
535 | World.SimChat(Utils.StringToBytes(text), | ||
536 | ChatTypeEnum.DebugChannel, 2147483647, | ||
537 | part.AbsolutePosition, | ||
538 | part.Name, part.UUID, false); | ||
539 | } | ||
540 | catch (Exception e2) // LEGIT: User Scripting | ||
541 | { | ||
542 | m_log.Error("[XEngine]: " + | ||
543 | "Error displaying warning in-world: " + | ||
544 | e2.ToString()); | ||
545 | m_log.Error("[XEngine]: " + | ||
546 | "Warning:\r\n" + | ||
547 | warning); | ||
548 | } | ||
549 | } | ||
550 | } | ||
519 | } | 551 | } |
520 | catch (Exception e) | 552 | catch (Exception e) |
521 | { | 553 | { |