From 44852158f23d25ea56bcf24a0f09175e21838802 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 1 Nov 2008 23:50:19 +0000 Subject: [PATCH] Mantis #2518 Thank you, idb, for a patch that fixes the conflicts of lsl identifiers with c# keywords --- .../Shared/CodeTools/CSCodeGenerator.cs | 39 ++++++-- .../Shared/CodeTools/CSReservedWords.cs | 91 +++++++++++++++++++ 2 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/Shared/CodeTools/CSReservedWords.cs diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index a825eff646..5100f2379a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs @@ -214,11 +214,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools else if (s is Constant) retstr += GenerateConstant((Constant) s); else if (s is IdentDotExpression) - retstr += Generate(((IdentDotExpression) s).Name + "." + ((IdentDotExpression) s).Member, s); + retstr += Generate(CheckName(((IdentDotExpression) s).Name) + "." + ((IdentDotExpression) s).Member, s); else if (s is IdentExpression) - retstr += Generate(((IdentExpression) s).Name, s); + retstr += Generate(CheckName(((IdentExpression) s).Name), s); else if (s is IDENT) - retstr += Generate(((TOKEN) s).yytext, s); + retstr += Generate(CheckName(((TOKEN) s).yytext), s); else { foreach (SYMBOL kid in s.kids) @@ -247,7 +247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools else remainingKids.Add(kid); - retstr += GenerateIndented(String.Format("{0} {1}(", gf.ReturnType, gf.Name), gf); + retstr += GenerateIndented(String.Format("{0} {1}(", gf.ReturnType, CheckName(gf.Name)), gf); // print the state arguments, if any foreach (SYMBOL kid in argumentDeclarationListKids) @@ -344,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools foreach (Declaration d in adl.kids) { - retstr += Generate(String.Format("{0} {1}", d.Datatype, d.Id), d); + retstr += Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d); if (0 < comma--) retstr += Generate(", "); } @@ -403,7 +403,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools /// String containing C# code for Declaration d. private string GenerateDeclaration(Declaration d) { - return Generate(String.Format("{0} {1}", d.Datatype, d.Id), d); + return Generate(String.Format("{0} {1}", d.Datatype, CheckName(d.Id)), d); } /// @@ -694,10 +694,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools if (0 < ide.kids.Count) { IdentDotExpression dot = (IdentDotExpression) ide.kids.Top; - retstr += Generate(String.Format("{0}", ide.PostOperation ? dot.Name + "." + dot.Member + ide.Operation : ide.Operation + dot.Name + "." + dot.Member), ide); + retstr += Generate(String.Format("{0}", ide.PostOperation ? CheckName(dot.Name) + "." + dot.Member + ide.Operation : ide.Operation + CheckName(dot.Name) + "." + dot.Member), ide); } else - retstr += Generate(String.Format("{0}", ide.PostOperation ? ide.Name + ide.Operation : ide.Operation + ide.Name), ide); + retstr += Generate(String.Format("{0}", ide.PostOperation ? CheckName(ide.Name) + ide.Operation : ide.Operation + CheckName(ide.Name)), ide); return retstr; } @@ -728,7 +728,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools { string retstr = String.Empty; - retstr += Generate(String.Format("{0}(", fc.Id), fc); + retstr += Generate(String.Format("{0}(", CheckName(fc.Id)), fc); foreach (SYMBOL kid in fc.kids) retstr += GenerateNode(kid); @@ -968,5 +968,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools return retstr; } + + /// + /// Returns the passed name with an underscore prepended if that name is a reserved word in C# + /// and not resevered in LSL otherwise it just returns the passed name. + /// + /// This makes no attempt to cache the results to minimise future lookups. For a non trivial + /// scripts the number of unique identifiers could easily grow to the size of the reserved word + /// list so maintaining a list or dictionary and doing the lookup there firstwould probably not + /// give any real speed advantage. + /// + /// I believe there is a class Microsoft.CSharp.CSharpCodeProvider that has a function + /// CreateValidIdentifier(str) that will return either the value of str if it is not a C# + /// key word or "_"+str if it is. But availability under Mono? + /// + private string CheckName(string s) + { + if (CSReservedWords.IsReservedWord(s)) + return "_" + s; + else + return s; + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSReservedWords.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSReservedWords.cs new file mode 100644 index 0000000000..bd758d6ae0 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSReservedWords.cs @@ -0,0 +1,91 @@ +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; + +namespace OpenSim.Region.ScriptEngine.Shared.CodeTools +{ + /// + /// A container for all of the reserved C# words that are not also reserved words in LSL. + /// The words must be maintained in alphabetical order. + /// The words that are key words in lsl are picked up by the lsl compiler as errors. + /// The LSL reserved words have been left in the list as comments for completeness + /// + internal class CSReservedWords + { + private static List reservedWords = new List(new string[] { + "abstract","as", + "base","bool","break","byte", + "case","catch","char","checked","class","const","continue", + "decimal","default","delegate", + //"do", + "double", + //"else", + "enum", + //"event", + "explicit","extern", + "false","finally","fixed", + //"float","for", + "foreach", + "goto", + //"if", + "implicit","in","int","interface","internal","is", + "lock","long", + "namespace","new","null", + "object","operator","out","override", + "params","private","protected","public", + "readonly","ref", + //"return", + "sbyte","sealed","short","sizeof","stackalloc","static", + //"string", + "struct","switch", + "this","throw","true","try","typeof", + "uint","ulong","unchecked","unsafe","ushort","using", + "virtual","void","volatile", + //"while" + }); + + /// + /// Returns true if the passed string is in the list of reserved words with + /// a little simple pre-filtering. + /// + internal static bool IsReservedWord(string word) + { + // A couple of quick filters to weed out single characters, ll functions and + // anything that starts with an uppercase letter + if (String.IsNullOrEmpty(word)) return false; + if (word.Length < 2) return false; + if (word.StartsWith("ll")) return false; + char first = word.ToCharArray(0,1)[0]; + if (first >= 'A' && first <= 'Z') return false; + + return (reservedWords.BinarySearch(word) >= 0); + } + } +}