From 08c76989a719803e4cb7c5391bc864046bba31f2 Mon Sep 17 00:00:00 2001 From: Charles Krinke Date: Mon, 23 Feb 2009 02:43:51 +0000 Subject: 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. --- .../Shared/CodeTools/CSCodeGenerator.cs | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs') 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 private int m_braceCount; // for indentation private int m_CSharpLine; // the current line of generated C# code private int m_CSharpCol; // the current column of generated C# code + private List m_warnings = new List(); /// /// Creates an 'empty' CSCodeGenerator instance. @@ -153,6 +154,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } /// + /// Get the set of warnings generated during compilation. + /// + /// + public string[] GetWarnings() + { + return m_warnings.ToArray(); + } + + private void AddWarning(string warning) + { + if (!m_warnings.Contains(warning)) + { + m_warnings.Add(warning); + } + } + + /// /// Recursively called to generate each type of node. Will generate this /// node, then all it's children. /// @@ -446,6 +464,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools { string retstr = String.Empty; + List identifiers = new List(); + checkForMultipleAssignments(identifiers, a); + retstr += GenerateNode((SYMBOL) a.kids.Pop()); retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); foreach (SYMBOL kid in a.kids) @@ -454,6 +475,62 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools return retstr; } + // This code checks for LSL of the following forms, and generates a + // warning if it finds them. + // + // list l = [ "foo" ]; + // l = (l=[]) + l + ["bar"]; + // (produces l=["foo","bar"] in SL but l=["bar"] in OS) + // + // integer i; + // integer j; + // i = (j = 3) + (j = 4) + (j = 5); + // (produces j=3 in SL but j=5 in OS) + // + // Without this check, that code passes compilation, but does not do what + // the end user expects, because LSL in SL evaluates right to left instead + // of left to right. + // + // The theory here is that producing an error and alerting the end user that + // something needs to change is better than silently generating incorrect code. + private void checkForMultipleAssignments(List identifiers, SYMBOL s) + { + if (s is Assignment) + { + Assignment a = (Assignment)s; + string newident = null; + + if (a.kids[0] is Declaration) + { + newident = ((Declaration)a.kids[0]).Id; + } + else if (a.kids[0] is IDENT) + { + newident = ((IDENT)a.kids[0]).yytext; + } + else if (a.kids[0] is IdentDotExpression) + { + newident = ((IdentDotExpression)a.kids[0]).Name; // +"." + ((IdentDotExpression)a.kids[0]).Member; + } + else + { + 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)); + } + + if (identifiers.Contains(newident)) + { + 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)); + } + identifiers.Add(newident); + } + + int index; + for (index = 0; index < s.kids.Count; index++) + { + checkForMultipleAssignments(identifiers, (SYMBOL) s.kids[index]); + } + } + /// /// Generates the code for a ReturnStatement node. /// -- cgit v1.1