/** * @brief Compile a script to produce a ScriptObjCode object * @returns object code pointer or null if compile error * also can throw compile error exception */ public ScriptObjCode Compile() { Stream objFileStream = null; StreamWriter asmFileWriter = null; string sourceHash = null; TextWriter saveSource = null; string objFileName = GetScriptFileName(m_ScriptObjCodeKey + ".yobj"); string tmpFileName = GetScriptFileName(m_ScriptObjCodeKey + ".ytmp"); // If we already have an object file, don't bother compiling. if (!m_ForceRecomp && File.Exists(objFileName)) { objFileStream = File.OpenRead(objFileName); } else { // If source file empty, try to read from asset server. if (EmptySource(m_SourceCode)) { m_SourceCode = FetchSource(m_CameFrom); } // Maybe write script source to a file for debugging. if (m_Engine.m_ScriptDebugSaveSource) { string lslFileName = GetScriptFileName(m_ScriptObjCodeKey + ".lsl"); // m_log.Debug ("[YEngine]: MMRScriptCompileSaveSource: saving to " + lslFileName); saveSource = File.CreateText(lslFileName); } // Parse source string into tokens. TokenBegin tokenBegin; try { tokenBegin = TokenBegin.Construct(m_CameFrom, saveSource, ErrorHandler, m_SourceCode, out sourceHash); } finally { if (saveSource != null) { saveSource.Close(); } } if (tokenBegin == null) { m_log.Debug("[YEngine]: parsing errors on " + m_ScriptObjCodeKey); return(null); } // Create object file one way or another. try { // Create abstract syntax tree from raw tokens. TokenScript tokenScript = ScriptReduce.Reduce(tokenBegin); if (tokenScript == null) { m_log.Warn("[YEngine]: reduction errors on " + m_ScriptObjCodeKey + " (" + m_CameFrom + ")"); PrintCompilerErrors(); return(null); } // Compile abstract syntax tree to write object file. using (BinaryWriter objFileWriter = new BinaryWriter(File.Create(tmpFileName))) { bool ok = ScriptCodeGen.CodeGen(tokenScript, objFileWriter, sourceHash); if (!ok) { m_log.Warn("[YEngine]: compile error on " + m_ScriptObjCodeKey + " (" + m_CameFrom + ")"); PrintCompilerErrors(); return(null); } } // File has been completely written. // If there is an old one laying around, delete it now. // Then re-open the new file for reading from the beginning. if (File.Exists(objFileName)) { File.Replace(tmpFileName, objFileName, null); } else { File.Move(tmpFileName, objFileName); } objFileStream = File.OpenRead(objFileName); } finally { // In case something went wrong writing temp file, delete it. File.Delete(tmpFileName); } // Since we just wrote the .xmrobj file, maybe save disassembly. if (m_Engine.m_ScriptDebugSaveIL) { string asmFileName = GetScriptFileName(m_ScriptObjCodeKey + ".yasm"); // m_log.Debug ("[YEngine]: MMRScriptCompileSaveILGen: saving to " + asmFileName); asmFileWriter = File.CreateText(asmFileName); } } // Read object file to create ScriptObjCode object. // Maybe also write disassembly to a file for debugging. BinaryReader objFileReader = new BinaryReader(objFileStream); ScriptObjCode scriptObjCode = null; try { scriptObjCode = new ScriptObjCode(objFileReader, asmFileWriter, null); } finally { objFileReader.Close(); if (asmFileWriter != null) { asmFileWriter.Flush(); asmFileWriter.Close(); } } return(scriptObjCode); }
/** * @brief Compile a script to produce a ScriptObjCode object * @returns object code pointer or null if compile error * also can throw compile error exception */ public ScriptObjCode Compile() { bool oldObjFile = false; Stream objFileStream = null; StreamWriter asmFileWriter = null; string envar = null; string sourceHash = null; TextWriter saveSource = null; string asmFileName = GetScriptFileName(m_ScriptObjCodeKey + ".xmrasm"); string lslFileName = GetScriptFileName(m_ScriptObjCodeKey + ".lsl"); string objFileName = GetScriptFileName(m_ScriptObjCodeKey + ".xmrobj"); string tmpFileName = GetScriptFileName(m_ScriptObjCodeKey + ".xmrtmp"); /* * If we already have an object file, don't bother compiling. */ if (!m_ForceRecomp && File.Exists(objFileName)) { objFileStream = File.OpenRead(objFileName); oldObjFile = true; } else { /* * If source file empty, try to read from asset server. */ if (EmptySource(m_SourceCode)) { m_SourceCode = FetchSource(m_CameFrom); } /* * Maybe write script source to a file for debugging. */ envar = Environment.GetEnvironmentVariable("MMRScriptCompileSaveSource"); if ((envar != null) && ((envar[0] & 1) != 0)) { m_log.Debug("[XMREngine]: MMRScriptCompileSaveSource: saving to " + lslFileName); saveSource = File.CreateText(lslFileName); } /* * Parse source string into tokens. */ TokenBegin tokenBegin; try { tokenBegin = TokenBegin.Construct(m_CameFrom, saveSource, ErrorHandler, m_SourceCode, out sourceHash); } finally { if (saveSource != null) { saveSource.Close(); } } if (tokenBegin == null) { m_log.Debug("[XMREngine]: parsing errors on " + m_ScriptObjCodeKey); return(null); } /* * Create object file one way or another. */ try { objFileStream = File.Create(tmpFileName); /* * Create abstract syntax tree from raw tokens. */ TokenScript tokenScript = ScriptReduce.Reduce(tokenBegin); if (tokenScript == null) { m_log.Warn("[XMREngine]: reduction errors on " + m_ScriptObjCodeKey + " (" + m_CameFrom + ")"); PrintCompilerErrors(); return(null); } /* * Compile abstract syntax tree to write object file. */ BinaryWriter objFileWriter = new BinaryWriter(objFileStream); bool ok = ScriptCodeGen.CodeGen(tokenScript, objFileWriter, sourceHash); if (!ok) { m_log.Warn("[XMREngine]: compile error on " + m_ScriptObjCodeKey + " (" + m_CameFrom + ")"); PrintCompilerErrors(); objFileStream.Close(); return(null); } objFileStream.Close(); /* * File has been completely written. * If there is an old one laying around, delete it now. * Then re-open the new file for reading from the beginning. */ if (File.Exists(objFileName)) { File.Replace(tmpFileName, objFileName, null); } else { File.Move(tmpFileName, objFileName); } objFileStream = File.OpenRead(objFileName); } finally { /* * In case something went wrong writing temp file, delete it. */ try { File.Delete(tmpFileName); } catch { } } /* * Since we just wrote the .xmrobj file, maybe save disassembly. */ envar = Environment.GetEnvironmentVariable("MMRScriptCompileSaveILGen"); if ((envar != null) && ((envar[0] & 1) != 0)) { m_log.Debug("[XMREngine]: MMRScriptCompileSaveILGen: saving to " + asmFileName); asmFileWriter = File.CreateText(asmFileName); } } /* * Read object file to create ScriptObjCode object. * Maybe also write disassembly to a file for debugging. */ BinaryReader objFileReader = new BinaryReader(objFileStream); ScriptObjCode scriptObjCode = null; try { scriptObjCode = new ScriptObjCode(objFileReader, asmFileWriter, null); if (scriptObjCode != null) { scriptObjCode.fileDateUtc = File.GetLastWriteTimeUtc(objFileName); } } finally { objFileReader.Close(); if (asmFileWriter != null) { asmFileWriter.Flush(); asmFileWriter.Close(); } } /* * Maybe an old object file has reached its expiration date. */ if (oldObjFile && (scriptObjCode != null) && scriptObjCode.IsExpired()) { m_log.Debug("[XMREngine]: expiration reached on " + m_ScriptObjCodeKey + ", reloading"); m_ForceRecomp = true; scriptObjCode = Compile(); } return(scriptObjCode); }