Beispiel #1
0
        /// <summary>
        /// Runs the specified command in a separate project
        /// </summary>
        /// <param name="type">Command type</param>
        /// <param name="command">Command to run</param>
        private Task <string> RunCommand(string type, string command)
        {
            var pane = OutputWindow.GetPane <Z80AssemblerOutputPane>();

            pane.WriteLine($"Running {type}:");
            pane.WriteLine(command);
            var tcs        = new TaskCompletionSource <string>();
            var cmdProcess = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName               = "cmd.exe",
                    Arguments              = $"/C {command}",
                    CreateNoWindow         = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    UseShellExecute        = false,
                    WorkingDirectory       = SpectNetPackage.Default.ActiveProject.ProjectDir
                }
            };

            Task.Factory.StartNew(() =>
            {
                try
                {
                    cmdProcess.Start();

                    // --- Wait up to 5 minutes to run the process
                    cmdProcess.WaitForExit(300000);
                    if (!cmdProcess.HasExited)
                    {
                        cmdProcess.Kill();
                        tcs.SetException(new InvalidOperationException("Task did not complete within timeout."));
                    }
                    else
                    {
                        var exitCode = cmdProcess.ExitCode;
                        var output   = cmdProcess.StandardError.ReadToEnd();
                        if (!string.IsNullOrWhiteSpace(output))
                        {
                            pane.Write(output);
                        }

                        pane.WriteLine($"Executing {type} completed with exit code {exitCode}.");
                        tcs.SetResult(output.Length == 0 ? null : output);
                    }
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
                finally
                {
                    cmdProcess.Dispose();
                }
            });
            return(tcs.Task);
        }
Beispiel #2
0
 /// <summary>
 /// Gets the active project's configuration
 /// </summary>
 /// <returns>
 /// Configuration information
 /// </returns>
 public SpectrumProjectConfiguration GetSpectrumProjectConfiguration()
 {
     try
     {
         var configFileName = Path.Combine(SpectNetPackage.Default.ActiveProject.ProjectDir,
                                           SpectrumProject.PROJECT_CONFIG_FILE);
         if (!File.Exists(configFileName))
         {
             return(null);
         }
         var configContents = File.ReadAllText(configFileName);
         return(JsonConvert.DeserializeObject <SpectrumProjectConfiguration>(configContents));
     }
     catch (Exception ex)
     {
         var pane = OutputWindow.GetPane <Z80AssemblerOutputPane>();
         pane.WriteLine($"Cannot obtain ZX Spectrum project configuration: {ex.Message}");
         return(null);
     }
 }
Beispiel #3
0
        /// <summary>
        /// Compiles the program code
        /// </summary>
        /// <returns>True, if compilation successful; otherwise, false</returns>
        public async Task <bool> CompileCode()
        {
            // --- Execute pre-build event
            var codeManager = SpectNetPackage.Default.CodeManager;

            PrebuildError   = null;
            PostbuildError  = null;
            CleanupError    = null;
            PreexportError  = null;
            PostexportError = null;
            var eventOutput = await codeManager.RunPreBuildEvent(ItemFullPath);

            if (eventOutput != null)
            {
                PrebuildError = eventOutput;
                CleanupError  = await codeManager.RunBuildErrorEvent(ItemFullPath);

                DisplayBuildErrors();
                return(false);
            }

            var start = DateTime.Now;
            var pane  = OutputWindow.GetPane <Z80AssemblerOutputPane>();
            await pane.WriteLineAsync(_compiler.ServiceName);

            var output = await _compiler.CompileDocument(ItemFullPath, PrepareAssemblerOptions());

            var duration = (DateTime.Now - start).TotalMilliseconds;
            await pane.WriteLineAsync($"Compile time: {duration}ms");

            var compiled = output != null;

            if (compiled)
            {
                // --- Sign that compilation was successful
                HostPackage.DebugInfoProvider.CompiledOutput = Output = output;
                CreateCompilationListFile(_hierarchy, _itemId);
            }
            HostPackage.CodeManager.RaiseCompilationCompleted(output);

            // --- Execute post-build event
            if (compiled && output.Errors.Count == 0)
            {
                // --- Export if required
                if (!string.IsNullOrEmpty(SpectNetPackage.Default.Options.ExportOnCompile))
                {
                    var parts = SpectNetPackage.Default.Options.ExportOnCompile.Split(';');
                    var name  = Path.GetFileNameWithoutExtension(ItemPath) ?? "MyCode";
                    var vm    = new ExportZ80ProgramViewModel
                    {
                        Name     = name,
                        Filename = Path.Combine(Path.GetDirectoryName(SpectNetPackage.Default.ActiveProject.Root.FullName),
                                                EXPORT_PATH, name)
                    };
                    if (parts.Length > 0)
                    {
                        // --- Validate format
                        var format = parts[0].Trim().ToLower();
                        if (format == "tap")
                        {
                            vm.Format = ExportFormat.Tap;
                        }
                        else if (format == "tzx")
                        {
                            vm.Format = ExportFormat.Tzx;
                        }
                        else if (format == "hex")
                        {
                            vm.Format = ExportFormat.IntelHex;
                        }
                        else
                        {
                            PostbuildError = $"Invalid export format: {parts[0]}";
                        }
                    }

                    if (PostbuildError == null && parts.Length > 1)
                    {
                        var flag = parts[1].Trim();
                        if (flag == "" || flag == "1")
                        {
                            vm.AutoStart = true;
                        }
                        else if (flag == "0")
                        {
                            vm.AutoStart = false;
                        }
                        else
                        {
                            PostbuildError = $"Invalid export Auto-Start flag (use 0 or 1): {parts[1]}";
                        }
                    }

                    if (PostbuildError == null && parts.Length > 2)
                    {
                        var flag = parts[2].Trim();
                        if (flag == "" || flag == "1")
                        {
                            vm.ApplyClear = true;
                        }
                        else if (flag == "0")
                        {
                            vm.ApplyClear = false;
                        }
                        else
                        {
                            PostbuildError = $"Invalid export Apply CLEAR flag (use 0 or 1): {parts[2]}";
                        }
                    }

                    vm.SingleBlock  = true;
                    vm.AddToProject = false;

                    if (PostbuildError == null && parts.Length > 3)
                    {
                        var flag = parts[3].Trim();
                        if (flag == "" || flag == "0")
                        {
                            vm.AddPause0 = false;
                        }
                        else if (flag == "1")
                        {
                            vm.AddPause0 = true;
                        }
                        else
                        {
                            PostbuildError = $"Invalid export Add PAUSE flag (use 0 or 1): {parts[3]}";
                        }
                    }

                    if (PostbuildError == null && parts.Length > 4 && parts[4].Trim() != "")
                    {
                        if (ushort.TryParse(parts[4], out var startAddr))
                        {
                            vm.StartAddress = startAddr.ToString();
                        }
                        else
                        {
                            PostbuildError = $"Invalid Start Address (use 0-65535): {parts[4]}";
                        }
                    }

                    if (PostbuildError == null && parts.Length > 5 && parts[5].Trim() != "")
                    {
                        if (ushort.TryParse(parts[5], out var border))
                        {
                            if (border >= 0 && border <= 7)
                            {
                                vm.Border = border.ToString();
                            }
                            else
                            {
                                PostbuildError = $"Invalid Border value (use 0-7): {parts[5]}";
                            }
                        }
                        else
                        {
                            PostbuildError = $"Invalid Border value (use 0-7): {parts[5]}";
                        }
                    }

                    if (PostbuildError == null && parts.Length > 6)
                    {
                        vm.ScreenFile = parts[6];
                    }

                    if (PostbuildError == null)
                    {
                        ExportProgramCommand.ExportCompiledCode(Output, vm);
                    }
                }

                // --- Run post-build tasks
                eventOutput = await codeManager.RunPostBuildEvent(ItemFullPath);

                if (eventOutput != null)
                {
                    PostbuildError = eventOutput;
                    CleanupError   = await codeManager.RunBuildErrorEvent(ItemFullPath);

                    DisplayBuildErrors();
                    return(false);
                }
            }
            else
            {
                CleanupError = await codeManager.RunBuildErrorEvent(ItemFullPath);

                DisplayBuildErrors();
            }
            return(compiled);
        }
        /// <summary>
        /// Compiles the program code
        /// </summary>
        /// <returns>True, if compilation successful; otherwise, false</returns>
        public async Task <bool> CompileCode()
        {
            // --- Execute pre-build event
            var codeManager = SpectNetPackage.Default.CodeManager;

            PrebuildError   = null;
            PostbuildError  = null;
            CleanupError    = null;
            PreexportError  = null;
            PostexportError = null;
            var eventOutput = await codeManager.RunPreBuildEvent(ItemFullPath);

            if (eventOutput != null)
            {
                PrebuildError = eventOutput;
                CleanupError  = await codeManager.RunBuildErrorEvent(ItemFullPath);

                DisplayBuildErrors();
                return(false);
            }

            var start = DateTime.Now;
            var pane  = OutputWindow.GetPane <Z80AssemblerOutputPane>();
            await pane.WriteLineAsync(_compiler.ServiceName);

            var output = await _compiler.CompileDocument(ItemFullPath, PrepareAssemblerOptions());

            var duration = (DateTime.Now - start).TotalMilliseconds;
            await pane.WriteLineAsync($"Compile time: {duration}ms");

            var compiled = output != null;

            if (compiled)
            {
                // --- Sign that compilation was successful
                HostPackage.DebugInfoProvider.CompiledOutput = Output = output;
                CreateCompilationListFile(_hierarchy, _itemId);
            }
            HostPackage.CodeManager.RaiseCompilationCompleted(output);

            // --- Execute post-build event
            if (compiled && output.Errors.Count == 0)
            {
                eventOutput = await codeManager.RunPostBuildEvent(ItemFullPath);

                if (eventOutput != null)
                {
                    PostbuildError = eventOutput;
                    CleanupError   = await codeManager.RunBuildErrorEvent(ItemFullPath);

                    DisplayBuildErrors();
                    return(false);
                }
            }
            else
            {
                CleanupError = await codeManager.RunBuildErrorEvent(ItemFullPath);

                DisplayBuildErrors();
            }
            return(compiled);
        }
Beispiel #5
0
        /// <summary>
        /// Logs a message to the SpectNetIDE output pane
        /// </summary>
        /// <param name="message">Message to log</param>
        public static void Log(string message)
        {
            var pane = OutputWindow.GetPane <SpectNetIdeOutputPane>();

            pane.WriteLine(message);
        }
Beispiel #6
0
        public Task <ZxbResult> RunAsync(ZxbOptions options, bool log = false)
        {
            var tcs        = new TaskCompletionSource <ZxbResult>();
            var zxbProcess = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName               = Path.Combine(_zxbPath ?? string.Empty, "zxb.exe"),
                    Arguments              = options.ToString(),
                    CreateNoWindow         = true,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    UseShellExecute        = false
                }
            };

            _ = Task.Factory.StartNew(() =>
            {
                try
                {
                    if (log)
                    {
                        var pane = OutputWindow.GetPane <Z80AssemblerOutputPane>();
                        pane.WriteLine($"Starting ZXB with: {zxbProcess.StartInfo.Arguments}");
                    }

                    var output = new StringBuilder();
                    var error  = new StringBuilder();

                    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                        using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                        {
                            zxbProcess.OutputDataReceived += (sender, e) => {
                                if (e.Data == null)
                                {
                                    outputWaitHandle.Set();
                                }
                                else
                                {
                                    output.AppendLine(e.Data);
                                }
                            };
                            zxbProcess.ErrorDataReceived += (sender, e) =>
                            {
                                if (e.Data == null)
                                {
                                    errorWaitHandle.Set();
                                }
                                else
                                {
                                    error.AppendLine(e.Data);
                                }
                            };

                            zxbProcess.Start();

                            zxbProcess.BeginOutputReadLine();
                            zxbProcess.BeginErrorReadLine();

                            if (zxbProcess.WaitForExit(_timeOut) &&
                                outputWaitHandle.WaitOne(_timeOut) &&
                                errorWaitHandle.WaitOne(_timeOut))
                            {
                                var exitCode = zxbProcess.ExitCode;
                                tcs.SetResult(new ZxbResult(exitCode, error.ToString()));
                            }
                            else
                            {
                                zxbProcess.Kill();
                                tcs.SetException(new InvalidOperationException("ZXB task did not complete within timeout."));
                            }
                        }
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
                finally
                {
                    zxbProcess.Dispose();
                }
            });
            return(tcs.Task);
        }
        /// <summary>
        /// Responds to the event when the Z80 assembler releases a message
        /// </summary>
        private void OnAssemblerMessage(object sender, AssemblerMessageArgs e)
        {
            var pane = OutputWindow.GetPane <Z80AssemblerOutputPane>();

            pane.WriteLine(e.Message);
        }