コード例 #1
0
        public override void Execute(SharedObjects shared)
        {
            string pathString = PopValueAssert(shared, true).ToString();
            string toAppend   = PopValueAssert(shared).ToString();

            AssertArgBottomAndConsume(shared);

            if (shared.VolumeMgr != null)
            {
                GlobalPath path   = shared.VolumeMgr.GlobalPathFromObject(pathString);
                Volume     volume = shared.VolumeMgr.GetVolumeFromPath(path);

                VolumeItem volumeItem = volume.Open(path) as VolumeFile;
                VolumeFile volumeFile = null;

                if (volumeItem == null)
                {
                    volumeFile = volume.CreateFile(path);
                }
                else if (volumeItem is VolumeDirectory)
                {
                    throw new KOSFileException("Can't append to file: path points to a directory");
                }
                else
                {
                    volumeFile = volumeItem as VolumeFile;
                }

                if (!volumeFile.WriteLn(toAppend))
                {
                    throw new KOSFileException("Can't append to file: not enough space or access forbidden");
                }
            }
        }
コード例 #2
0
        public override void Execute(SharedObjects shared)
        {
            string fileName         = PopValueAssert(shared, true).ToString();
            string expressionResult = PopValueAssert(shared).ToString();

            AssertArgBottomAndConsume(shared);

            if (shared.VolumeMgr != null)
            {
                Volume volume = shared.VolumeMgr.CurrentVolume;
                if (volume != null)
                {
                    VolumeFile volumeFile = volume.OpenOrCreate(fileName);

                    if (volumeFile == null || !volumeFile.WriteLn(expressionResult))
                    {
                        throw new KOSFileException("Can't append to file: not enough space or access forbidden");
                    }
                }
                else
                {
                    throw new KOSFileException("Volume not found");
                }
            }
        }
コード例 #3
0
ファイル: YieldFinishedCompile.cs プロジェクト: wanyoungj/KOS
        public override void ThreadFinish()
        {
            switch (compileMode)
            {
            case CompileMode.RUN:
                programContext.AddParts(codeParts);
                shared.Cpu.StopCompileStopwatch();
                break;

            case CompileMode.LOAD:
                int programAddress = programContext.AddObjectParts(codeParts, path.ToString());
                // push the entry point address of the new program onto the stack
                shared.Cpu.PushStack(programAddress);
                shared.Cpu.PushStack(BooleanValue.False);
                break;

            case CompileMode.FILE:
                VolumeFile written = volume.SaveFile(outPath, new FileContent(codeParts));
                if (written == null)
                {
                    throw new KOSFileException("Can't save compiled file: not enough space or access forbidden");
                }
                break;

            default:
                break;
            }
        }
コード例 #4
0
ファイル: VolumeTest.cs プロジェクト: stephengeorgewest/KOS-1
        public void CanReadAndWriteFiles()
        {
            string dir           = "/content_parent/content_test";
            string content       = "some test content!@#$;\n\rtaenstałąż";
            int    contentLength = Encoding.UTF8.GetBytes(content).Length;

            VolumeFile volumeFile = TestVolume.CreateFile(VolumePath.FromString(dir));

            Assert.AreEqual(0, volumeFile.ReadAll().Bytes.Length);
            Assert.AreEqual("", volumeFile.ReadAll().String);

            Assert.IsTrue(volumeFile.Write(content));
            Assert.AreEqual(FileCategory.ASCII, volumeFile.ReadAll().Category);

            Assert.AreEqual(contentLength, TestVolume.Size);

            if (ExpectedCapacity != Volume.INFINITE_CAPACITY)
            {
                Assert.AreEqual(ExpectedCapacity - contentLength, TestVolume.FreeSpace);
            }
            else
            {
                Assert.AreEqual(Volume.INFINITE_CAPACITY, TestVolume.FreeSpace);
            }

            Assert.AreEqual(contentLength, volumeFile.Size);
            Assert.AreEqual(content, volumeFile.ReadAll().String);

            // we should be able to save the same file again
            Assert.IsTrue(TestVolume.SaveFile(volumeFile) != null);
        }
コード例 #5
0
        public override void Execute(SharedObjects shared)
        {
            string fileName = PopValueAssert(shared, true).ToString();

            AssertArgBottomAndConsume(shared);

            VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Create(fileName);

            ReturnValue = volumeFile;
        }
コード例 #6
0
        public void CanCopyFileToRootDirectory()
        {
            GlobalPath targetPath = GlobalPath.FromString("1:");

            Assert.IsTrue(volumeManager.Copy(subsubdir1File1Path, targetPath));

            Assert.AreEqual(1, TargetVolume.Root.List().Count);
            VolumeFile file = (TargetVolume.Open(file1) as VolumeFile);

            Assert.AreEqual("subsubdir1File1\n", file.ReadAll().String);
        }
コード例 #7
0
        public override void Execute(SharedObjects shared)
        {
            object volumeId  = PopValueAssert(shared, true);
            string direction = PopValueAssert(shared).ToString();
            string fileName  = PopValueAssert(shared, true).ToString();

            AssertArgBottomAndConsume(shared);

            SafeHouse.Logger.Log(string.Format("FunctionCopy: Volume: {0} Direction: {1} Filename: {2}", volumeId, direction, fileName));

            if (shared.VolumeMgr != null)
            {
                Volume origin;
                Volume destination;

                if (direction == "from")
                {
                    origin      = volumeId is Volume ? volumeId as Volume : shared.VolumeMgr.GetVolume(volumeId);
                    destination = shared.VolumeMgr.CurrentVolume;
                }
                else
                {
                    origin      = shared.VolumeMgr.CurrentVolume;
                    destination = volumeId is Volume ? volumeId as Volume : shared.VolumeMgr.GetVolume(volumeId);
                }

                if (origin != null && destination != null)
                {
                    if (origin == destination)
                    {
                        throw new Exception("Cannot copy from a volume to the same volume.");
                    }

                    VolumeFile file = origin.Open(fileName);
                    if (file != null)
                    {
                        if (destination.Save(file.Name, file.ReadAll()) == null)
                        {
                            throw new Exception("File copy failed");
                        }
                    }
                    else
                    {
                        throw new Exception(string.Format("File '{0}' not found", fileName));
                    }
                }
                else
                {
                    throw new Exception(string.Format("Volume {0} not found", volumeId));
                }
            }
        }
コード例 #8
0
        public override void Execute(SafeSharedObjects shared)
        {
            object pathObject = PopValueAssert(shared, true);

            AssertArgBottomAndConsume(shared);

            GlobalPath path   = shared.VolumeMgr.GlobalPathFromObject(pathObject);
            Volume     volume = shared.VolumeMgr.GetVolumeFromPath(path);

            VolumeFile volumeFile = volume.CreateFile(path);

            ReturnValue = volumeFile;
        }
コード例 #9
0
        public override void Execute(SharedObjects shared)
        {
            string fileName = PopValueAssert(shared, true).ToString();

            AssertArgBottomAndConsume(shared);

            VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Open(fileName);

            if (volumeFile == null)
            {
                throw new KOSException("File does not exist: " + fileName);
            }

            ReturnValue = volumeFile;
        }
コード例 #10
0
        protected static void DelegateLoadContents(KOSTextEditPopup me)
        {
            me.volume   = me.loadingVolume;
            me.fileName = me.loadingFileName;
            VolumeFile file = me.volume.Open(me.fileName);

            if (file == null)
            {
                me.term.Print("[New File]");
                me.contents = "";
            }
            else
            {
                me.contents = file.ReadAll().String;
            }
            me.isDirty = false;
        }
コード例 #11
0
ファイル: KSPLogger.cs プロジェクト: stephengeorgewest/KOS-1
        private string GetSourceLine(GlobalPath path, int line)
        {
            string returnVal = "(Can't show source line)";

            if (line < 0)
            {
                // Special exception - if line number is negative then this isn't from any
                // line of user's code but from the system itself (like the triggers the compiler builds
                // to recalculate LOCK THROTTLE and LOCK STEERING each time there's an Update).
                return("<<System Built-In Flight Control Updater>>");
            }

            if (path is InternalPath)
            {
                return((path as InternalPath).Line(line));
            }

            Volume vol;

            try
            {
                vol = Shared.VolumeMgr.GetVolumeFromPath(path);
            }
            catch (KOSPersistenceException)
            {
                return(returnVal);
            }

            VolumeFile file = vol.Open(path) as VolumeFile;

            if (file != null)
            {
                if (file.ReadAll().Category == FileCategory.KSM)
                {
                    return("<<machine language file: can't show source line>>");
                }

                string[] splitLines = file.ReadAll().String.Split('\n');
                if (splitLines.Length >= line)
                {
                    returnVal = splitLines[line - 1];
                }
            }

            return(returnVal);
        }
コード例 #12
0
        public override void Execute(SharedObjects shared)
        {
            string fileName = PopValueAssert(shared, true).ToString();

            AssertArgBottomAndConsume(shared);

            VolumeFile volumeFile = shared.VolumeMgr.CurrentVolume.Open(fileName);

            if (volumeFile == null)
            {
                throw new KOSException("File does not exist: " + fileName);
            }

            object read = new SerializationMgr(shared).Deserialize(volumeFile.ReadAll().String, JsonFormatter.ReaderInstance);

            ReturnValue = read;
        }
コード例 #13
0
        public override void Execute(SafeSharedObjects shared)
        {
            object pathObject = PopValueAssert(shared, true);

            AssertArgBottomAndConsume(shared);

            GlobalPath path   = shared.VolumeMgr.GlobalPathFromObject(pathObject);
            Volume     volume = shared.VolumeMgr.GetVolumeFromPath(path);

            VolumeFile volumeFile = volume.Open(path) as VolumeFile;

            if (volumeFile == null)
            {
                throw new KOSException("File does not exist: " + path);
            }

            Structure read = new SafeSerializationMgr(shared).Deserialize(volumeFile.ReadAll().String, JsonFormatter.ReaderInstance) as SerializableStructure;

            ReturnValue = read;
        }
コード例 #14
0
        private void CompareDirectories(GlobalPath dir1Path, GlobalPath dir2Path)
        {
            Volume dir1Volume = volumeManager.GetVolumeFromPath(dir1Path);
            Volume dir2Volume = volumeManager.GetVolumeFromPath(dir2Path);

            VolumeDirectory dir1 = dir1Volume.Open(dir1Path) as VolumeDirectory;
            VolumeDirectory dir2 = dir2Volume.Open(dir2Path) as VolumeDirectory;

            Assert.NotNull(dir1);
            Assert.NotNull(dir2);

            int dir1Count = dir1.List().Count;
            int dir2Count = dir2.List().Count;

            if (dir1Count != dir2Count)
            {
                Assert.Fail("Item count not equal: " + dir1Count + " != " + dir2Count);
            }

            foreach (KeyValuePair <string, VolumeItem> pair in dir1.List())
            {
                VolumeItem dir2Item = dir2Volume.Open(dir2Path.Combine(pair.Key));

                if (pair.Value is VolumeDirectory && dir2Item is VolumeDirectory)
                {
                    CompareDirectories(dir1Path.Combine(pair.Key), dir2Path.Combine(pair.Key));
                }
                else if (pair.Value is VolumeFile && dir2Item is VolumeFile)
                {
                    VolumeFile file1 = pair.Value as VolumeFile;
                    VolumeFile file2 = dir2Item as VolumeFile;

                    Assert.AreEqual(file1.ReadAll(), file2.ReadAll());
                }
                else
                {
                    Assert.Fail("Items are not of the same type: " + dir1Path.Combine(pair.Key) + ", " + dir2Path.Combine(pair.Key));
                }
            }
        }
コード例 #15
0
ファイル: KOSTextEditPopup.cs プロジェクト: vincentBenet/KOS
        protected static void DelegateLoadContents(KOSTextEditPopup me)
        {
            VolumeItem item = me.loadingVolume.Open(me.loadingPath);

            if (item == null)
            {
                me.term.Print("[New File]");
                me.contents = "";
            }
            else if (item is VolumeFile)
            {
                VolumeFile file = item as VolumeFile;
                me.loadingPath = GlobalPath.FromVolumePath(item.Path, me.loadingPath.VolumeId);
                me.contents    = file.ReadAll().String;
            }
            else
            {
                throw new KOSPersistenceException("Path '" + me.loadingPath + "' points to a directory");
            }

            me.volume  = me.loadingVolume;
            me.isDirty = false;
        }
コード例 #16
0
ファイル: Reader.cs プロジェクト: mnadareski/UnshieldSharp
 /// <summary>
 /// Dispose of the current object
 /// </summary>
 public void Dispose()
 {
     VolumeFile?.Close();
 }
コード例 #17
0
ファイル: Volume.cs プロジェクト: KSP-KOS/KOS
 public VolumeFile SaveFile(VolumeFile volumeFile)
 {
     return SaveFile(volumeFile.Path, volumeFile.ReadAll());
 }
コード例 #18
0
        public override void Execute(SharedObjects shared)
        {
            bool   defaultOutput = false;
            bool   justCompiling = false;                        // is this load() happening to compile, or to run?
            string fileNameOut   = null;
            object topStack      = PopValueAssert(shared, true); // null if there's no output file (output file means compile, not run).

            if (topStack != null)
            {
                justCompiling = true;
                string outputArg = topStack.ToString();
                if (outputArg.Equals("-default-compile-out-"))
                {
                    defaultOutput = true;
                }
                else
                {
                    fileNameOut = PersistenceUtilities.CookedFilename(outputArg, Volume.KOS_MACHINELANGUAGE_EXTENSION);
                }
            }

            string fileName = null;

            topStack = PopValueAssert(shared, true);
            if (topStack != null)
            {
                fileName = topStack.ToString();
            }

            AssertArgBottomAndConsume(shared);

            if (fileName == null)
            {
                throw new KOSFileException("No filename to load was given.");
            }

            VolumeFile file = shared.VolumeMgr.CurrentVolume.Open(fileName, !justCompiling); // if running, look for KSM first.  If compiling look for KS first.

            if (file == null)
            {
                throw new KOSFileException(string.Format("Can't find file '{0}'.", fileName));
            }
            fileName = file.Name; // just in case GetByName picked an extension that changed it.
            FileContent fileContent = file.ReadAll();

            // filename is now guaranteed to have an extension.  To make default output name, replace the extension with KSM:
            if (defaultOutput)
            {
                fileNameOut = fileName.Substring(0, fileName.LastIndexOf('.')) + "." + Volume.KOS_MACHINELANGUAGE_EXTENSION;
            }

            if (fileNameOut != null && fileName == fileNameOut)
            {
                throw new KOSFileException("Input and output filenames must differ.");
            }

            if (shared.VolumeMgr == null)
            {
                return;
            }
            if (shared.VolumeMgr.CurrentVolume == null)
            {
                throw new KOSFileException("Volume not found");
            }

            if (shared.ScriptHandler != null)
            {
                shared.Cpu.StartCompileStopwatch();
                var options = new CompilerOptions {
                    LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager
                };
                string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName;
                // add this program to the address space of the parent program,
                // or to a file to save:
                if (justCompiling)
                {
                    List <CodePart> compileParts = shared.ScriptHandler.Compile(filePath, 1, fileContent.String, string.Empty, options);
                    VolumeFile      volumeFile   = shared.VolumeMgr.CurrentVolume.Save(fileNameOut, new FileContent(compileParts));
                    if (volumeFile == null)
                    {
                        throw new KOSFileException("Can't save compiled file: not enough space or access forbidden");
                    }
                }
                else
                {
                    var             programContext = ((CPU)shared.Cpu).SwitchToProgramContext();
                    List <CodePart> parts;
                    if (fileContent.Category == FileCategory.KSM)
                    {
                        string prefix = programContext.Program.Count.ToString();
                        parts = fileContent.AsParts(filePath, prefix);
                    }
                    else
                    {
                        parts = shared.ScriptHandler.Compile(filePath, 1, fileContent.String, "program", options);
                    }
                    int programAddress = programContext.AddObjectParts(parts);
                    // push the entry point address of the new program onto the stack
                    shared.Cpu.PushStack(programAddress);
                }
                shared.Cpu.StopCompileStopwatch();
            }
        }
コード例 #19
0
ファイル: Volume.cs プロジェクト: CalebJ2/KOS
 //public abstract bool AppendToFile(string name, string textToAppend);
 //public abstract bool AppendToFile(string name, byte[] bytesToAppend);
 public VolumeFile Save(VolumeFile volumeFile)
 {
     return Save(volumeFile.Name, volumeFile.ReadAll());
 }
コード例 #20
0
ファイル: Volume.cs プロジェクト: CalebJ2/KOS
 private int FileInfoComparer(VolumeFile a, VolumeFile b)
 {
     return string.CompareOrdinal(a.Name, b.Name);
 }
コード例 #21
0
        public override void Execute(SharedObjects shared)
        {
            // run() is strange.  It needs two levels of args - the args to itself, and the args it is meant to
            // pass on to the program it's invoking.  First, these are the args to run itself:
            object volumeId = PopValueAssert(shared, true);
            string fileName = PopValueAssert(shared, true).ToString();

            AssertArgBottomAndConsume(shared);

            // Now the args it is going to be passing on to the program:
            var progArgs = new List <object>();
            int argc     = CountRemainingArgs(shared);

            for (int i = 0; i < argc; ++i)
            {
                progArgs.Add(PopValueAssert(shared, true));
            }
            AssertArgBottomAndConsume(shared);

            if (shared.VolumeMgr == null)
            {
                return;
            }
            if (shared.VolumeMgr.CurrentVolume == null)
            {
                throw new Exception("Volume not found");
            }

            VolumeFile file = shared.VolumeMgr.CurrentVolume.Open(fileName, true);

            if (file == null)
            {
                throw new Exception(string.Format("File '{0}' not found", fileName));
            }
            if (shared.ScriptHandler == null)
            {
                return;
            }

            if (volumeId != null)
            {
                Volume targetVolume = shared.VolumeMgr.GetVolume(volumeId);
                if (targetVolume != null)
                {
                    if (shared.ProcessorMgr != null)
                    {
                        string filePath = string.Format("{0}/{1}", shared.VolumeMgr.GetVolumeRawIdentifier(targetVolume), fileName);
                        var    options  = new CompilerOptions {
                            LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager
                        };
                        List <CodePart> parts   = shared.ScriptHandler.Compile(filePath, 1, file.ReadAll().String, "program", options);
                        var             builder = new ProgramBuilder();
                        builder.AddRange(parts);
                        List <Opcode> program = builder.BuildProgram();
                        shared.ProcessorMgr.RunProgramOn(program, targetVolume);
                    }
                }
                else
                {
                    throw new KOSFileException("Volume not found");
                }
            }
            else
            {
                // clear the "program" compilation context
                shared.Cpu.StartCompileStopwatch();
                shared.ScriptHandler.ClearContext("program");
                string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName;
                var    options  = new CompilerOptions {
                    LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager
                };
                var programContext = ((CPU)shared.Cpu).SwitchToProgramContext();

                List <CodePart> codeParts;
                FileContent     content = file.ReadAll();
                if (content.Category == FileCategory.KSM)
                {
                    string prefix = programContext.Program.Count.ToString();
                    codeParts = content.AsParts(fileName, prefix);
                }
                else
                {
                    try
                    {
                        codeParts = shared.ScriptHandler.Compile(filePath, 1, content.String, "program", options);
                    }
                    catch (Exception)
                    {
                        // If it died due to a compile error, then we won't really be able to switch to program context
                        // as was implied by calling Cpu.SwitchToProgramContext() up above.  The CPU needs to be
                        // told that it's still in interpreter context, or else it fails to advance the interpreter's
                        // instruction pointer and it will just try the "call run()" instruction again:
                        shared.Cpu.BreakExecution(false);
                        throw;
                    }
                }
                programContext.AddParts(codeParts);
                shared.Cpu.StopCompileStopwatch();
            }

            // Because run() returns FIRST, and THEN the CPU jumps to the new program's first instruction that it set up,
            // it needs to put the return stack in a weird order.  Its return value needs to be buried UNDER the args to the
            // program it's calling:
            UsesAutoReturn = false;

            shared.Cpu.PushStack(0); // dummy return that all functions have.

            // Put the args for the program being called back on in the same order they were in before (so read the list backward):
            shared.Cpu.PushStack(new KOSArgMarkerType());
            for (int i = argc - 1; i >= 0; --i)
            {
                shared.Cpu.PushStack(progArgs[i]);
            }
        }
コード例 #22
0
ファイル: KSPLogger.cs プロジェクト: jonored/KOS
        private string GetSourceLine(string filePath, int line)
        {
            string returnVal = "(Can't show source line)";

            if (line < 0 && string.IsNullOrEmpty(filePath))
            {
                // Special exception - if line number is negative then this isn't from any
                // line of user's code but from the system itself (like the triggers the compiler builds
                // to recalculate LOCK THROTTLE and LOCK STEERING each time there's an Update).
                return("<<System Built-In Flight Control Updater>>");
            }

            if (string.IsNullOrEmpty(filePath))
            {
                return("<<Probably internal error within kOS C# code>>");
            }
            string[] pathParts = filePath.Split('/');
            string   fileName  = pathParts.Last();
            Volume   vol;

            if (pathParts.Length > 1)
            {
                string volName = pathParts.First();
                if (Regex.IsMatch(volName, @"^\d+$"))
                {
                    // If the volume is a number, then get the volume by integer id.
                    int volNum;
                    int.TryParse(volName, out volNum);
                    vol = Shared.VolumeMgr.GetVolume(volNum);
                }
                else
                {
                    // If the volume is not a number, then get the volume by name string.
                    vol = Shared.VolumeMgr.GetVolume(volName);
                }
            }
            else
            {
                vol = Shared.VolumeMgr.CurrentVolume;
            }

            if (fileName == "interpreter history")
            {
                return(Shared.Interpreter.GetCommandHistoryAbsolute(line));
            }

            VolumeFile file = vol.Open(fileName);

            if (file != null)
            {
                if (file.ReadAll().Category == FileCategory.KSM)
                {
                    return("<<machine language file: can't show source line>>");
                }

                string[] splitLines = file.ReadAll().String.Split('\n');
                if (splitLines.Length >= line)
                {
                    returnVal = splitLines[line - 1];
                }
            }
            return(returnVal);
        }
コード例 #23
0
ファイル: VolumeManager.cs プロジェクト: KSP-KOS/KOS
 protected bool CopyFileToDirectory(VolumeFile volumeFile, VolumeDirectory volumeDirectory,
     bool verifyFreeSpace)
 {
     return volumeDirectory.Volume.SaveFile(volumeDirectory.Path.Combine(volumeFile.Name), volumeFile.ReadAll(),
         verifyFreeSpace) != null;
 }
コード例 #24
0
ファイル: VolumeManager.cs プロジェクト: KSP-KOS/KOS
 protected bool CopyFile(VolumeFile volumeFile, GlobalPath destinationPath, Volume targetVolume,
     bool verifyFreeSpace)
 {
     return targetVolume.SaveFile(destinationPath, volumeFile.ReadAll(), verifyFreeSpace) != null;
 }
コード例 #25
0
        public override void Execute(SharedObjects shared)
        {
            // run() is strange.  It needs two levels of args - the args to itself, and the args it is meant to
            // pass on to the program it's invoking.  First, these are the args to run itself:
            object volumeId   = PopValueAssert(shared, true);
            object pathObject = PopValueAssert(shared, true);

            AssertArgBottomAndConsume(shared);

            // Now the args it is going to be passing on to the program:
            var progArgs = new List <object>();
            int argc     = CountRemainingArgs(shared);

            for (int i = 0; i < argc; ++i)
            {
                progArgs.Add(PopValueAssert(shared, true));
            }
            AssertArgBottomAndConsume(shared);

            if (shared.VolumeMgr == null)
            {
                return;
            }

            GlobalPath path       = shared.VolumeMgr.GlobalPathFromObject(pathObject);
            Volume     volume     = shared.VolumeMgr.GetVolumeFromPath(path);
            VolumeFile volumeFile = volume.Open(path) as VolumeFile;

            FileContent content = volumeFile != null?volumeFile.ReadAll() : null;

            if (content == null)
            {
                throw new Exception(string.Format("File '{0}' not found", path));
            }

            if (shared.ScriptHandler == null)
            {
                return;
            }

            if (volumeId != null)
            {
                throw new KOSObsoletionException("v1.0.2", "run [file] on [volume]", "None", "");
            }
            else
            {
                // clear the "program" compilation context
                shared.Cpu.StartCompileStopwatch();
                shared.ScriptHandler.ClearContext("program");
                //string filePath = shared.VolumeMgr.GetVolumeRawIdentifier(shared.VolumeMgr.CurrentVolume) + "/" + fileName;
                var options = new CompilerOptions {
                    LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager
                };
                var programContext = shared.Cpu.SwitchToProgramContext();

                List <CodePart> codeParts;
                if (content.Category == FileCategory.KSM)
                {
                    string prefix = programContext.Program.Count.ToString();
                    codeParts = content.AsParts(path, prefix);
                    programContext.AddParts(codeParts);
                    shared.Cpu.StopCompileStopwatch();
                }
                else
                {
                    shared.Cpu.YieldProgram(YieldFinishedCompile.RunScript(path, 1, content.String, "program", options));
                }
            }

            // Because run() returns FIRST, and THEN the CPU jumps to the new program's first instruction that it set up,
            // it needs to put the return stack in a weird order.  Its return value needs to be buried UNDER the args to the
            // program it's calling:
            UsesAutoReturn = false;

            shared.Cpu.PushStack(0); // dummy return that all functions have.

            // Put the args for the program being called back on in the same order they were in before (so read the list backward):
            shared.Cpu.PushStack(new KOSArgMarkerType());
            for (int i = argc - 1; i >= 0; --i)
            {
                shared.Cpu.PushStack(progArgs[i]);
            }
        }
コード例 #26
0
        public override void Execute(SharedObjects shared)
        {
            // NOTE: The built-in load() function actually ends up returning
            // two things on the stack: on top is a boolean for whether the program
            // was already loaded, and under that is an integer for where to jump to
            // to call it.  The load() function is NOT meant to be called directly from
            // a user script.
            // (unless it's being called in compile-only mode, in which case it
            // returns the default dummy zero on the stack like everything else does).

            bool       defaultOutput = false;
            bool       justCompiling = false;                        // is this load() happening to compile, or to run?
            GlobalPath outPath       = null;
            object     topStack      = PopValueAssert(shared, true); // null if there's no output file (output file means compile, not run).

            if (topStack != null)
            {
                justCompiling = true;
                string outputArg = topStack.ToString();
                if (outputArg.Equals("-default-compile-out-"))
                {
                    defaultOutput = true;
                }
                else
                {
                    outPath = shared.VolumeMgr.GlobalPathFromObject(outputArg);
                }
            }

            object skipAlreadyObject     = PopValueAssert(shared, false);
            bool   skipIfAlreadyCompiled = (skipAlreadyObject is bool) ? (bool)skipAlreadyObject : false;

            object pathObject = PopValueAssert(shared, true);

            AssertArgBottomAndConsume(shared);

            if (pathObject == null)
            {
                throw new KOSFileException("No filename to load was given.");
            }

            GlobalPath path   = shared.VolumeMgr.GlobalPathFromObject(pathObject);
            Volume     volume = shared.VolumeMgr.GetVolumeFromPath(path);

            VolumeFile file = volume.Open(path, !justCompiling) as VolumeFile; // if running, look for KSM first.  If compiling look for KS first.

            if (file == null)
            {
                throw new KOSFileException(string.Format("Can't find file '{0}'.", path));
            }
            path = GlobalPath.FromVolumePath(file.Path, shared.VolumeMgr.GetVolumeId(volume));

            if (skipIfAlreadyCompiled && !justCompiling)
            {
                var programContext = ((CPU)shared.Cpu).SwitchToProgramContext();
                int programAddress = programContext.GetAlreadyCompiledEntryPoint(path.ToString());
                if (programAddress >= 0)
                {
                    // TODO - The check could also have some dependancy on whether the file content changed on
                    //     disk since last time, but that would also mean having to have a way to clear out the old
                    //     copy of the compiled file from the program context, which right now doesn't exist. (Without
                    //     that, doing something like a loop that re-wrote a file and re-ran it 100 times would leave
                    //     100 old dead copies of the compiled opcodes in memory, only the lastmost copy being really used.)

                    // We're done here.  Skip the compile.  Point the caller at the already-compiled version.
                    shared.Cpu.PushStack(programAddress);
                    this.ReturnValue = true; // tell caller that it already existed.
                    return;
                }
            }

            FileContent fileContent = file.ReadAll();

            // filename is now guaranteed to have an extension.  To make default output name, replace the extension with KSM:
            if (defaultOutput)
            {
                outPath = path.ChangeExtension(Volume.KOS_MACHINELANGUAGE_EXTENSION);
            }

            if (path.Equals(outPath))
            {
                throw new KOSFileException("Input and output paths must differ.");
            }

            if (shared.VolumeMgr == null)
            {
                return;
            }
            if (shared.VolumeMgr.CurrentVolume == null)
            {
                throw new KOSFileException("Volume not found");
            }

            if (shared.ScriptHandler != null)
            {
                shared.Cpu.StartCompileStopwatch();
                var options = new CompilerOptions {
                    LoadProgramsInSameAddressSpace = true, FuncManager = shared.FunctionManager
                };
                // add this program to the address space of the parent program,
                // or to a file to save:
                if (justCompiling)
                {
                    // since we've already read the file content, use the volume from outPath instead of the source path
                    volume = shared.VolumeMgr.GetVolumeFromPath(outPath);
                    List <CodePart> compileParts = shared.ScriptHandler.Compile(path, 1, fileContent.String, string.Empty, options);
                    VolumeFile      written      = volume.SaveFile(outPath, new FileContent(compileParts));
                    if (written == null)
                    {
                        throw new KOSFileException("Can't save compiled file: not enough space or access forbidden");
                    }
                }
                else
                {
                    var             programContext = ((CPU)shared.Cpu).SwitchToProgramContext();
                    List <CodePart> parts;
                    if (fileContent.Category == FileCategory.KSM)
                    {
                        string prefix = programContext.Program.Count.ToString();
                        parts = fileContent.AsParts(path, prefix);
                    }
                    else
                    {
                        parts = shared.ScriptHandler.Compile(path, 1, fileContent.String, "program", options);
                    }
                    int programAddress = programContext.AddObjectParts(parts, path.ToString());
                    // push the entry point address of the new program onto the stack
                    shared.Cpu.PushStack(programAddress);
                    this.ReturnValue = false; // did not already exist.
                }
                shared.Cpu.StopCompileStopwatch();
            }
        }