use std::{ fmt::Display, io::ErrorKind, path::{Path, PathBuf}, }; use crate::{ common::{Output, Relocatable}, error::Error, }; pub struct Linker where R: Relocatable, O: Output, { relocatables: Vec, output: O, } impl Linker where R: Relocatable, O: Output, { pub fn new(output: O) -> Self { Self { relocatables: Vec::new(), output, } } pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> { self.relocatables .push(R::new(origin, self.relocatables.len())?); Ok(()) } pub fn link(mut self) -> Result { for r in self.relocatables.iter() { for s in r.sections() { self.output.process_section(s?)?; } } self.output.finalize(&self.relocatables) } pub fn object_path(origin: &Path) -> Result { let mut dest = std::fs::canonicalize(origin)?; if !dest.pop() { let err = std::io::Error::new(ErrorKind::Other, "Destination path invalid"); Err(Error::IOError(Box::new(err))) } else { dest.push("rld.out"); Ok(dest) } } } impl Display for Linker where R: Relocatable, O: Output, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "===Relocatables===")?; for r in self.relocatables.iter() { write!(f, "{}", r)?; } Ok(()) } }