Beispiel #1
0
        /// <summary>
        /// Compile .NET script to .Net assembly (.dll)
        /// </summary>
        /// <param name="Script">CS script</param>
        /// <returns>Filename to .dll assembly</returns>
        internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset, string assembly)
        {
            //            m_log.DebugFormat("[Compiler]: Compiling to assembly\n{0}", Script);

            string ext = "." + lang.ToString();

            // Output assembly name
            scriptCompileCounter++;
            try
            {
                File.Delete(assembly);
            }
            catch (Exception e) // NOTLEGIT - Should be just FileIOException
            {
                throw new Exception("Unable to delete old existing " +
                                    "script-file before writing new. Compile aborted: " +
                                    e.ToString());
            }

            // DEBUG - write source to disk
            if (WriteScriptSourceToDebugFile)
            {
                string srcFileName = FilePrefix + "_source_" +
                                     Path.GetFileNameWithoutExtension(assembly) + ext;
                try
                {
                    File.WriteAllText(Path.Combine(Path.Combine(
                                                       ScriptEnginesPath,
                                                       m_scriptEngine.World.RegionInfo.RegionID.ToString()),
                                                   srcFileName), Script);
                }
                catch (Exception ex) //NOTLEGIT - Should be just FileIOException
                {
                    m_log.Error("[Compiler]: Exception while " +
                                "trying to write script source to file \"" +
                                srcFileName + "\": " + ex.ToString());
                }
            }

            // Do actual compile
            CompilerParameters parameters = new CompilerParameters();

            parameters.IncludeDebugInformation = true;

            string rootPath = AppDomain.CurrentDomain.BaseDirectory;

            parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                             "OpenSim.Region.ScriptEngine.Shared.dll"));
            parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                             "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
            parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                             "OpenMetaverseTypes.dll"));

            if (m_scriptEngine.ScriptReferencedAssemblies != null)
            {
                Array.ForEach <string>(
                    m_scriptEngine.ScriptReferencedAssemblies,
                    a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a)));
            }

            if (lang == enumCompileType.yp)
            {
                parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                                 "OpenSim.Region.ScriptEngine.Shared.YieldProlog.dll"));
            }

            parameters.GenerateExecutable      = false;
            parameters.OutputAssembly          = assembly;
            parameters.IncludeDebugInformation = CompileWithDebugInformation;
            //parameters.WarningLevel = 1; // Should be 4?
            parameters.TreatWarningsAsErrors = false;

            CompilerResults results;

            switch (lang)
            {
            case enumCompileType.vb:
                results = VBcodeProvider.CompileAssemblyFromSource(
                    parameters, Script);
                break;

            case enumCompileType.cs:
            case enumCompileType.lsl:
                bool complete = false;
                bool retried  = false;
                do
                {
                    lock (CScodeProvider)
                    {
                        results = CScodeProvider.CompileAssemblyFromSource(
                            parameters, Script);
                    }

                    // Deal with an occasional segv in the compiler.
                    // Rarely, if ever, occurs twice in succession.
                    // Line # == 0 and no file name are indications that
                    // this is a native stack trace rather than a normal
                    // error log.
                    if (results.Errors.Count > 0)
                    {
                        if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) &&
                            results.Errors[0].Line == 0)
                        {
                            // System.Console.WriteLine("retrying failed compilation");
                            retried = true;
                        }
                        else
                        {
                            complete = true;
                        }
                    }
                    else
                    {
                        complete = true;
                    }
                } while (!complete);
                break;

            default:
                throw new Exception("Compiler is not able to recongnize " +
                                    "language type \"" + lang.ToString() + "\"");
            }

            //            foreach (Type type in results.CompiledAssembly.GetTypes())
            //            {
            //                foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
            //                {
            //                    m_log.DebugFormat("[COMPILER]: {0}.{1}", type.FullName, method.Name);
            //                }
            //            }

            //
            // WARNINGS AND ERRORS
            //
            bool   hadErrors = false;
            string errtext   = String.Empty;

            if (results.Errors.Count > 0)
            {
                foreach (CompilerError CompErr in results.Errors)
                {
                    string severity = CompErr.IsWarning ? "Warning" : "Error";

                    KeyValuePair <int, int> errorPos;

                    // Show 5 errors max, but check entire list for errors

                    if (severity == "Error")
                    {
                        // C# scripts will not have a linemap since theres no line translation involved.
                        if (!m_lineMaps.ContainsKey(assembly))
                        {
                            errorPos = new KeyValuePair <int, int>(CompErr.Line, CompErr.Column);
                        }
                        else
                        {
                            errorPos = FindErrorPosition(CompErr.Line, CompErr.Column, m_lineMaps[assembly]);
                        }

                        string text = CompErr.ErrorText;

                        // Use LSL type names
                        if (lang == enumCompileType.lsl)
                        {
                            text = ReplaceTypes(CompErr.ErrorText);
                        }

                        // The Second Life viewer's script editor begins
                        // countingn lines and columns at 0, so we subtract 1.
                        errtext += String.Format("({0},{1}): {4} {2}: {3}\n",
                                                 errorPos.Key - 1, errorPos.Value - 1,
                                                 CompErr.ErrorNumber, text, severity);
                        hadErrors = true;
                    }
                }
            }

            if (hadErrors)
            {
                throw new Exception(errtext);
            }

            //  On today's highly asynchronous systems, the result of
            //  the compile may not be immediately apparent. Wait a
            //  reasonable amount of time before giving up on it.

            if (!File.Exists(assembly))
            {
                for (int i = 0; i < 20 && !File.Exists(assembly); i++)
                {
                    System.Threading.Thread.Sleep(250);
                }
                // One final chance...
                if (!File.Exists(assembly))
                {
                    errtext  = String.Empty;
                    errtext += "No compile error. But not able to locate compiled file.";
                    throw new Exception(errtext);
                }
            }

            //            m_log.DebugFormat("[Compiler] Compiled new assembly "+
            //                    "for {0}", asset);

            // Because windows likes to perform exclusive locks, we simply
            // write out a textual representation of the file here
            //
            // Read the binary file into a buffer
            //
            FileInfo fi = new FileInfo(assembly);

            if (fi == null)
            {
                errtext  = String.Empty;
                errtext += "No compile error. But not able to stat file.";
                throw new Exception(errtext);
            }

            Byte[] data = new Byte[fi.Length];

            try
            {
                FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read);
                fs.Read(data, 0, data.Length);
                fs.Close();
            }
            catch (Exception)
            {
                errtext  = String.Empty;
                errtext += "No compile error. But not able to open file.";
                throw new Exception(errtext);
            }

            // Convert to base64
            //
            string filetext = System.Convert.ToBase64String(data);

            Byte[] buf = Encoding.ASCII.GetBytes(filetext);

            FileStream sfs = File.Create(assembly + ".text");

            sfs.Write(buf, 0, buf.Length);
            sfs.Close();

            return(assembly);
        }
Beispiel #2
0
        /// <summary>
        /// Compile .NET script to .Net assembly (.dll)
        /// </summary>
        /// <param name="Script">CS script</param>
        /// <returns>Filename to .dll assembly</returns>
        internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset)
        {
            string ext = "." + lang.ToString();

            // Output assembly name
            scriptCompileCounter++;
            string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
                                              m_scriptEngine.World.RegionInfo.RegionID.ToString(),
                                              FilePrefix + "_compiled_" + asset + ".dll"));

            try
            {
                File.Delete(OutFile);
            }
            catch (Exception e) // NOTLEGIT - Should be just FileIOException
            {
                throw new Exception("Unable to delete old existing " +
                                    "script-file before writing new. Compile aborted: " +
                                    e.ToString());
            }

            // DEBUG - write source to disk
            if (WriteScriptSourceToDebugFile)
            {
                string srcFileName = FilePrefix + "_source_" +
                                     Path.GetFileNameWithoutExtension(OutFile) + ext;
                try
                {
                    File.WriteAllText(Path.Combine(Path.Combine(
                                                       ScriptEnginesPath,
                                                       m_scriptEngine.World.RegionInfo.RegionID.ToString()),
                                                   srcFileName), Script);
                }
                catch (Exception ex) //NOTLEGIT - Should be just FileIOException
                {
                    m_log.Error("[Compiler]: Exception while " +
                                "trying to write script source to file \"" +
                                srcFileName + "\": " + ex.ToString());
                }
            }

            // Do actual compile
            CompilerParameters parameters = new CompilerParameters();

            parameters.IncludeDebugInformation = true;

            string rootPath =
                Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);

            parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                             "OpenSim.Region.ScriptEngine.Shared.dll"));
            parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                             "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));

            if (lang == enumCompileType.yp)
            {
                parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                                                                 "OpenSim.Region.ScriptEngine.Shared.YieldProlog.dll"));
            }

            parameters.GenerateExecutable      = false;
            parameters.OutputAssembly          = OutFile;
            parameters.IncludeDebugInformation = CompileWithDebugInformation;
            //parameters.WarningLevel = 1; // Should be 4?
            parameters.TreatWarningsAsErrors = false;

            CompilerResults results;

            switch (lang)
            {
            case enumCompileType.vb:
                results = VBcodeProvider.CompileAssemblyFromSource(
                    parameters, Script);
                break;

            case enumCompileType.cs:
            case enumCompileType.lsl:
                lock (CScodeProvider)
                {
                    results = CScodeProvider.CompileAssemblyFromSource(
                        parameters, Script);
                }
                break;

            case enumCompileType.js:
                results = JScodeProvider.CompileAssemblyFromSource(
                    parameters, Script);
                break;

            case enumCompileType.yp:
                results = YPcodeProvider.CompileAssemblyFromSource(
                    parameters, Script);
                break;

            default:
                throw new Exception("Compiler is not able to recongnize " +
                                    "language type \"" + lang.ToString() + "\"");
            }

            // Check result
            // Go through errors

            //
            // WARNINGS AND ERRORS
            //
            int display = 5;

            if (results.Errors.Count > 0)
            {
                string errtext = String.Empty;
                foreach (CompilerError CompErr in results.Errors)
                {
                    // Show 5 errors max
                    //
                    if (display <= 0)
                    {
                        break;
                    }
                    display--;

                    string severity = "Error";
                    if (CompErr.IsWarning)
                    {
                        severity = "Warning";
                    }

                    KeyValuePair <int, int> lslPos;

                    lslPos = FindErrorPosition(CompErr.Line, CompErr.Column);

                    string text = CompErr.ErrorText;

                    // Use LSL type names
                    if (lang == enumCompileType.lsl)
                    {
                        text = ReplaceTypes(CompErr.ErrorText);
                    }

                    // The Second Life viewer's script editor begins
                    // countingn lines and columns at 0, so we subtract 1.
                    errtext += String.Format("Line ({0},{1}): {4} {2}: {3}\n",
                                             lslPos.Key - 1, lslPos.Value - 1,
                                             CompErr.ErrorNumber, text, severity);
                }

                if (!File.Exists(OutFile))
                {
                    throw new Exception(errtext);
                }
            }

            //
            // NO ERRORS, BUT NO COMPILED FILE
            //
            if (!File.Exists(OutFile))
            {
                string errtext = String.Empty;
                errtext += "No compile error. But not able to locate compiled file.";
                throw new Exception(errtext);
            }
//            m_log.DebugFormat("[Compiler] Compiled new assembly "+
//                    "for {0}", asset);

            // Because windows likes to perform exclusive locks, we simply
            // write out a textual representation of the file here
            //
            // Read the binary file into a buffer
            //
            FileInfo fi = new FileInfo(OutFile);

            if (fi == null)
            {
                string errtext = String.Empty;
                errtext += "No compile error. But not able to stat file.";
                throw new Exception(errtext);
            }

            Byte[] data = new Byte[fi.Length];

            try
            {
                FileStream fs = File.Open(OutFile, FileMode.Open, FileAccess.Read);
                fs.Read(data, 0, data.Length);
                fs.Close();
            }
            catch (Exception)
            {
                string errtext = String.Empty;
                errtext += "No compile error. But not able to open file.";
                throw new Exception(errtext);
            }

            // Convert to base64
            //
            string filetext = System.Convert.ToBase64String(data);

            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();

            Byte[] buf = enc.GetBytes(filetext);

            FileStream sfs = File.Create(OutFile + ".text");

            sfs.Write(buf, 0, buf.Length);
            sfs.Close();

            string posmap = String.Empty;

            if (m_positionMap != null)
            {
                foreach (KeyValuePair <KeyValuePair <int, int>, KeyValuePair <int, int> > kvp in m_positionMap)
                {
                    KeyValuePair <int, int> k = kvp.Key;
                    KeyValuePair <int, int> v = kvp.Value;
                    posmap += String.Format("{0},{1},{2},{3}\n",
                                            k.Key, k.Value, v.Key, v.Value);
                }
            }

            buf = enc.GetBytes(posmap);

            FileStream mfs = File.Create(OutFile + ".map");

            mfs.Write(buf, 0, buf.Length);
            mfs.Close();

            return(OutFile);
        }
Beispiel #3
0
        /// <summary>
        /// Converts script from LSL to CS and calls CompileFromCSText
        /// </summary>
        /// <param name="Script">LSL script</param>
        /// <returns>Filename to .dll assembly</returns>
        public void PerformScriptCompile(string Script, string asset, UUID ownerUUID,
                                         out string assembly, out Dictionary <KeyValuePair <int, int>, KeyValuePair <int, int> > linemap)
        {
            //            m_log.DebugFormat("[Compiler]: Compiling script\n{0}", Script);

            IScriptModuleComms comms = m_scriptEngine.World.RequestModuleInterface <IScriptModuleComms>();

            linemap = null;
            m_warnings.Clear();

            assembly = GetCompilerOutput(asset);

            if (!Directory.Exists(ScriptEnginesPath))
            {
                try
                {
                    Directory.CreateDirectory(ScriptEnginesPath);
                }
                catch (Exception)
                {
                }
            }

            if (!Directory.Exists(Path.Combine(ScriptEnginesPath,
                                               m_scriptEngine.World.RegionInfo.RegionID.ToString())))
            {
                try
                {
                    Directory.CreateDirectory(ScriptEnginesPath);
                }
                catch (Exception)
                {
                }
            }

            // Don't recompile if we already have it
            // Performing 3 file exists tests for every script can still be slow
            if (File.Exists(assembly) && File.Exists(assembly + ".text") && File.Exists(assembly + ".map"))
            {
                // If we have already read this linemap file, then it will be in our dictionary.
                // Don't build another copy of the dictionary (saves memory) and certainly
                // don't keep reading the same file from disk multiple times.
                if (!m_lineMaps.ContainsKey(assembly))
                {
                    m_lineMaps[assembly] = ReadMapFile(assembly + ".map");
                }
                linemap = m_lineMaps[assembly];
                return;
            }

            if (Script == String.Empty)
            {
                throw new Exception("Cannot find script assembly and no script text present");
            }

            enumCompileType language = DefaultCompileLanguage;

            if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
            {
                language = enumCompileType.cs;
            }
            if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
            {
                language = enumCompileType.vb;
                // We need to remove //vb, it won't compile with that

                Script = Script.Substring(4, Script.Length - 4);
            }
            if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
            {
                language = enumCompileType.lsl;
            }

            if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture))
            {
                language = enumCompileType.js;
            }

            if (Script.StartsWith("//yp", true, CultureInfo.InvariantCulture))
            {
                language = enumCompileType.yp;
            }

            //            m_log.DebugFormat("[Compiler]: Compile language is {0}", language);

            if (!AllowedCompilers.ContainsKey(language.ToString()))
            {
                // Not allowed to compile to this language!
                string errtext = String.Empty;
                errtext += "The compiler for language \"" + language.ToString() + "\" is not in list of allowed compilers. Script will not be executed!";
                throw new Exception(errtext);
            }

            if (m_scriptEngine.World.Permissions.CanCompileScript(ownerUUID, (int)language) == false)
            {
                // Not allowed to compile to this language!
                string errtext = String.Empty;
                errtext += ownerUUID + " is not in list of allowed users for this scripting language. Script will not be executed!";
                throw new Exception(errtext);
            }

            string compileScript = Script;

            if (language == enumCompileType.lsl)
            {
                // Its LSL, convert it to C#
                LSL_Converter = (ICodeConverter) new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
                compileScript = LSL_Converter.Convert(Script);

                // copy converter warnings into our warnings.
                foreach (string warning in LSL_Converter.GetWarnings())
                {
                    AddWarning(warning);
                }

                linemap = ((CSCodeGenerator)LSL_Converter).PositionMap;
                // Write the linemap to a file and save it in our dictionary for next time.
                m_lineMaps[assembly] = linemap;
                WriteMapFile(assembly + ".map", linemap);
            }

            switch (language)
            {
            case enumCompileType.cs:
            case enumCompileType.lsl:
                compileScript = CreateCSCompilerScript(
                    compileScript,
                    m_scriptEngine.ScriptClassName,
                    m_scriptEngine.ScriptBaseClassName,
                    m_scriptEngine.ScriptBaseClassParameters);
                break;

            case enumCompileType.vb:
                compileScript = CreateVBCompilerScript(
                    compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName);
                break;
            }

            assembly = CompileFromDotNetText(compileScript, language, asset, assembly);
        }
Beispiel #4
0
        ////private ICodeCompiler icc = codeProvider.CreateCompiler();
        //public string CompileFromFile(string LSOFileName)
        //{
        //    switch (Path.GetExtension(LSOFileName).ToLower())
        //    {
        //        case ".txt":
        //        case ".lsl":
        //            Common.ScriptEngineBase.Shared.SendToDebug("Source code is LSL, converting to CS");
        //            return CompileFromLSLText(File.ReadAllText(LSOFileName));
        //        case ".cs":
        //            Common.ScriptEngineBase.Shared.SendToDebug("Source code is CS");
        //            return CompileFromCSText(File.ReadAllText(LSOFileName));
        //        default:
        //            throw new Exception("Unknown script type.");
        //    }
        //}

        /// <summary>
        /// Converts script from LSL to CS and calls CompileFromCSText
        /// </summary>
        /// <param name="Script">LSL script</param>
        /// <returns>Filename to .dll assembly</returns>
        public string PerformScriptCompile(string Script, string asset)
        {
            m_positionMap = null;
            m_warnings.Clear();

            string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
                                              m_scriptEngine.World.RegionInfo.RegionID.ToString(),
                                              FilePrefix + "_compiled_" + asset + ".dll"));

//            string OutFile = Path.Combine(ScriptEnginesPath,
//                    FilePrefix + "_compiled_" + asset + ".dll");

            if (!Directory.Exists(ScriptEnginesPath))
            {
                try
                {
                    Directory.CreateDirectory(ScriptEnginesPath);
                }
                catch (Exception)
                {
                }
            }

            if (!Directory.Exists(Path.Combine(ScriptEnginesPath,
                                               m_scriptEngine.World.RegionInfo.RegionID.ToString())))
            {
                try
                {
                    Directory.CreateDirectory(ScriptEnginesPath);
                }
                catch (Exception)
                {
                }
            }

            if (Script == String.Empty)
            {
                if (File.Exists(OutFile))
                {
                    return(OutFile);
                }

                throw new Exception("Cannot find script assembly and no script text present");
            }

            // Don't recompile if we already have it
            //
            if (File.Exists(OutFile) && File.Exists(OutFile + ".text") && File.Exists(OutFile + ".map"))
            {
                ReadMapFile(OutFile + ".map");
                return(OutFile);
            }

            enumCompileType l = DefaultCompileLanguage;

            if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
            {
                l = enumCompileType.cs;
            }
            if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
            {
                l = enumCompileType.vb;
                // We need to remove //vb, it won't compile with that

                Script = Script.Substring(4, Script.Length - 4);
            }
            if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
            {
                l = enumCompileType.lsl;
            }

            if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture))
            {
                l = enumCompileType.js;
            }

            if (Script.StartsWith("//yp", true, CultureInfo.InvariantCulture))
            {
                l = enumCompileType.yp;
            }

            if (!AllowedCompilers.ContainsKey(l.ToString()))
            {
                // Not allowed to compile to this language!
                string errtext = String.Empty;
                errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!";
                throw new Exception(errtext);
            }

            string compileScript = Script;

            if (l == enumCompileType.lsl)
            {
                // Its LSL, convert it to C#
                LSL_Converter = (ICodeConverter) new CSCodeGenerator();
                compileScript = LSL_Converter.Convert(Script);

                // copy converter warnings into our warnings.
                foreach (string warning in LSL_Converter.GetWarnings())
                {
                    AddWarning(warning);
                }

                m_positionMap = ((CSCodeGenerator)LSL_Converter).PositionMap;
            }

            if (l == enumCompileType.yp)
            {
                // Its YP, convert it to C#
                compileScript = YP_Converter.Convert(Script);
            }

            switch (l)
            {
            case enumCompileType.cs:
            case enumCompileType.lsl:
                compileScript = CreateCSCompilerScript(compileScript);
                break;

            case enumCompileType.vb:
                compileScript = CreateVBCompilerScript(compileScript);
                break;

            case enumCompileType.js:
                compileScript = CreateJSCompilerScript(compileScript);
                break;

            case enumCompileType.yp:
                compileScript = CreateYPCompilerScript(compileScript);
                break;
            }

            return(CompileFromDotNetText(compileScript, l, asset));
        }