public Job(CommandLine commandLine) { commandLine.ApplyTo(this); // Build input file list _inputFiles = new List <FileInfo>(commandLine.PositionalArguments.Count + (_interactive ? 1 : 0)); foreach (string filePath in commandLine.PositionalArguments) { FileInfo tmpFile = new FileInfo(filePath); if (!tmpFile.Exists) { Diagnostics.Report(Diagnostics.Severity.Error, $"{filePath} does not exist"); } else if (tmpFile.Kind == FileType.Kind.UNCLASSIFIED) { Diagnostics.Report(Diagnostics.Severity.Error, $"{filePath} is of unknown type"); } else if (tmpFile.Kind == FileType.Kind.TARGET_ASSEMBLY || tmpFile.Kind == FileType.Kind.TARGET_OBJECT) { Diagnostics.Report(Diagnostics.Severity.Error, "MonC cannot load target assembly or object files. External tools must be used for these."); } else { _inputFiles.Add(tmpFile); } } // Additional interactive input file if requested if (_interactive) { _inputFiles.Add(FileInfo.Interactive); } Diagnostics.ThrowIfErrors(); // Skip run is implied when output path is provided if (_outputPath != null) { _skipRun = true; } // VM is implied for debugger if (_debugger) { _skipRun = false; } if (_asm) { // Relocatable processing is implied for assembly output _reloc = true; } // Relocatable output always skips VM and may only accept one input file if (_reloc) { _skipRun = true; if (_inputFiles.Count > 1) { throw Diagnostics.ThrowError("-c or -S flag may only be set for one input file"); } } // Set output file if provided and not using VM _outputFile = _outputPath != null ? new FileInfo(_outputPath) : null; // Assembly output defaults to stdout if not specified if (_asm && _outputFile == null) { _outputFile = FileInfo.StdIo; } // Select toolchain by user request or input files / output file _toolChainSelection = SelectToolChain(); // Construct toolchain _toolChain = (ToolChain)Activator.CreateInstance(_toolChainSelection.Value); commandLine.ApplyTo(_toolChain); // Determine target phase based on output file (if provided) and command line flags _targetPhase = SelectTargetPhase(); if (_reloc && _inputFiles.Count > 1) { throw Diagnostics.ThrowError("relocatable output only works with one input file"); } // Initialize module phase open set with pre-link phases up to target PhaseSet modulePhaseOpenSet = _toolChain.FilterPhases( PhaseSet.AllPhasesTo((Phase)Math.Min((int)_targetPhase, (int)Phase.Link - 1))); // Visit JobActions for each file; building a chain of tools _moduleFileTools = new List <IModuleTool>(_inputFiles.Count); foreach (FileInfo inputFile in _inputFiles) { if (inputFile.IsLinkerInput) { _moduleFileTools.Add(_toolChain.BuildLinkerInputFileTool(this, inputFile)); continue; } ITool tool = null; foreach (Phase phase in inputFile.PossiblePhases& modulePhaseOpenSet) { tool = IJobAction.FromPhase(phase) .Accept(_toolChain, this, tool != null ? (IInput)tool : inputFile); commandLine.ApplyTo(tool); } if (tool is IModuleTool moduleTool) { _moduleFileTools.Add(moduleTool); } else { throw new InvalidOperationException("toolchain did not produce a module input file tool"); } } // Set up link and subsequent tools if (_targetPhase >= Phase.Link) { PhaseSet linkPhaseOpenSet = _toolChain.FilterPhases(PhaseSet.AllPhasesTo(_targetPhase) & PhaseSet.AllPhasesFrom(Phase.Link)); ITool tool = null; foreach (Phase phase in linkPhaseOpenSet) { tool = IJobAction.FromPhase(phase) .Accept(_toolChain, this, tool != null ? (IInput)tool : this); commandLine.ApplyTo(tool); } if (tool is IExecutableTool executableTool) { _executableTool = executableTool; } else { throw new InvalidOperationException("toolchain did not produce an executable tool"); } } }
public virtual PhaseSet FilterPhases(PhaseSet phases) => phases;