public Task <ZxbResult> RunAsync(ZxbOptions options) { 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 { zxbProcess.Start(); // --- Wait up to 10 seconds to run the process zxbProcess.WaitForExit(_timeOut); if (!zxbProcess.HasExited) { zxbProcess.Kill(); tcs.SetException(new InvalidOperationException("ZXB task did not complete within timeout.")); } else { var exitCode = zxbProcess.ExitCode; var output = zxbProcess.StandardError.ReadToEnd(); tcs.SetResult(new ZxbResult(exitCode, output)); } } catch (Exception ex) { tcs.SetException(ex); } finally { zxbProcess.Dispose(); } }); return(tcs.Task); }
/// <summary> /// Prepares the ZXB options to run /// </summary> /// <returns>Options to use when compiling ZX BASIC project</returns> private ZxbOptions PrepareZxbOptions(string documentPath, bool addToProject) { // --- Try to find options declaration in the source file var contents = File.ReadAllText(documentPath); var commentRegExp = new Regex("\\s*(rem|REM)\\s*(@options|@OPTIONS)\\s*(.*)"); var match = commentRegExp.Match(contents); var rawArgs = match.Success ? match.Groups[3].Value : null; var outputBase = addToProject ? documentPath : Path.Combine(SpectNetPackage.Default.Solution.SolutionDir, SolutionStructure.PRIVATE_FOLDER, ZXBASIC_TEMP_FOLDER, Path.GetFileName(documentPath)); var outDir = Path.GetDirectoryName(outputBase); if (!Directory.Exists(outDir)) { Directory.CreateDirectory(outDir); } var outputFile = Path.ChangeExtension(outputBase, ".zxbas.z80asm"); var packageOptions = SpectNetPackage.Default.Options; var options = new ZxbOptions { RawArgs = rawArgs, ProgramFilename = documentPath, OutputFilename = outputFile, Optimize = packageOptions.Optimize, OrgValue = packageOptions.OrgValue, ArrayBaseOne = packageOptions.ArrayBaseOne, StringBaseOne = packageOptions.StringBaseOne, SinclairFlag = packageOptions.SinclairFlag, HeapSize = packageOptions.HeapSize, DebugMemory = packageOptions.DebugMemory, DebugArray = packageOptions.DebugArray, StrictBool = packageOptions.StrictBool, EnableBreak = packageOptions.EnableBreak, ExplicitDim = packageOptions.ExplicitDim, StrictTypes = packageOptions.StrictTypes }; return(options); }
/// <summary> /// Prepares the ZXB options to run /// </summary> /// <returns></returns> private ZxbOptions PrepareZxbOptions(string documentPath) { var outputBase = Path.Combine(SpectNetPackage.Default.Solution.SolutionDir, SolutionStructure.PRIVATE_FOLDER, ZXBASIC_TEMP_FOLDER, Path.GetFileName(documentPath)); var outDir = Path.GetDirectoryName(outputBase); if (!Directory.Exists(outDir)) { Directory.CreateDirectory(outDir); } var outputFile = Path.ChangeExtension(outputBase, ".z80asm"); var packageOptions = SpectNetPackage.Default.Options; var options = new ZxbOptions { ProgramFilename = documentPath, OutputFilename = outputFile, AsmFormat = true, Optimize = packageOptions.Optimize, OrgValue = packageOptions.OrgValue, ArrayBaseOne = packageOptions.ArrayBaseOne, StringBaseOne = packageOptions.StringBaseOne, SinclairFlag = packageOptions.SinclairFlag, HeapSize = packageOptions.HeapSize, DebugMemory = packageOptions.DebugMemory, DebugArray = packageOptions.DebugArray, StrictBool = packageOptions.StrictBool, EnableBreak = packageOptions.EnableBreak, ExplicitDim = packageOptions.ExplicitDim, StrictTypes = packageOptions.StrictTypes }; return(options); }
/// <summary> /// Parses the source code and merges options from head comment /// </summary> /// <param name="options"></param> private void MergeOptionsFromSource(ZxbOptions options) { }
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); }