diff options
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/br.rs | 85 |
1 files changed, 62 insertions, 23 deletions
diff --git a/src/bin/br.rs b/src/bin/br.rs index bf3befe..e96df54 100644 --- a/src/bin/br.rs +++ b/src/bin/br.rs @@ -43,13 +43,18 @@ fn main_run(args: Run) { unsafe { VERBOSE = true; } } - let bytecode = load_bytecode(args.program.as_ref().map(|p| p.as_path())); + let program_path = args.program.as_ref().map(|p| p.as_path()); + let Bytecode { bytes: bytecode, path } = load_bytecode(program_path); + let symbols_path = path.as_ref().map(|p| { + let mut path = p.to_path_buf(); + path.set_extension("br.sym"); + path + }); + let metadata = parse_metadata(&bytecode); if metadata.is_none() { verbose!("Could not read program metadata"); } - // TODO: Load and parse symbols file into debug state, use nearest symbol - // path when debugging. let mut config = EmulatorConfig { dimensions: ScreenDimensions::ZERO, @@ -60,6 +65,7 @@ fn main_run(args: Run) { initial_transmission: None, decode_stdin: args.decode_stdin, encode_stdout: args.encode_stdout, + symbols_path, }; let phosphor = Phosphor::new(); @@ -106,14 +112,18 @@ fn main_run(args: Run) { std::process::exit(0); } -fn load_bytecode(path: Option<&Path>) -> Vec<u8> { +fn load_bytecode(path: Option<&Path>) -> Bytecode { // TODO: Etch file location into bytecode. if let Some(path) = path { if let Ok(bytecode) = load_bytecode_from_file(path) { - verbose!("Loaded program from {path:?} ({} bytes)", bytecode.len()); + let length = bytecode.bytes.len(); + let path = bytecode.path(); + verbose!("Loaded program from {path:?} ({length} bytes)"); return bytecode; - } else if let Some((bytecode, path)) = load_bytecode_from_bedrock_path(path) { - verbose!("Loaded program from {path:?} ({} bytes)", bytecode.len()); + } else if let Some(bytecode) = load_bytecode_from_bedrock_path(path) { + let length = bytecode.bytes.len(); + let path = bytecode.path(); + verbose!("Loaded program from {path:?} ({length} bytes)"); return bytecode; } else { eprintln!("Could not read program from {path:?}, exiting"); @@ -122,7 +132,8 @@ fn load_bytecode(path: Option<&Path>) -> Vec<u8> { } else { verbose!("Reading program from standard input..."); if let Ok(bytecode) = load_bytecode_from_stdin() { - verbose!("Loaded program from standard input ({} bytes)", bytecode.len()); + let length = bytecode.bytes.len(); + verbose!("Loaded program from standard input ({length} bytes)"); return bytecode; } else { eprintln!("Could not read program from standard input, exiting"); @@ -131,13 +142,8 @@ fn load_bytecode(path: Option<&Path>) -> Vec<u8> { } } -/// Attempt to load bytecode from a file path. -fn load_bytecode_from_file(path: &Path) -> Result<Vec<u8>, std::io::Error> { - load_bytecode_from_readable_source(std::fs::File::open(path)?) -} - /// Attempt to load bytecode from a directory in the BEDROCK_PATH environment variable. -fn load_bytecode_from_bedrock_path(path: &Path) -> Option<(Vec<u8>, PathBuf)> { +fn load_bytecode_from_bedrock_path(path: &Path) -> Option<Bytecode> { if path.is_relative() && path.components().count() == 1 { for base_path in std::env::var("BEDROCK_PATH").ok()?.split(':') { let mut base_path = PathBuf::from(base_path); @@ -145,29 +151,48 @@ fn load_bytecode_from_bedrock_path(path: &Path) -> Option<(Vec<u8>, PathBuf)> { base_path.push(path); verbose!("Attempting to load program from {base_path:?}"); if let Ok(bytecode) = load_bytecode_from_file(&base_path) { - return Some((bytecode, base_path)); + return Some(bytecode); } if path.extension().is_some() { continue; } base_path.set_extension("br"); verbose!("Attempting to load program from {base_path:?}"); if let Ok(bytecode) = load_bytecode_from_file(&base_path) { - return Some((bytecode, base_path)); + return Some(bytecode); } } } return None; } +/// Attempt to load bytecode from a file path. +fn load_bytecode_from_file(path: &Path) -> Result<Bytecode, std::io::Error> { + load_bytecode_from_readable_source(std::fs::File::open(path)?, Some(path)) +} + /// Attempt to load bytecode from standard input. -fn load_bytecode_from_stdin() -> Result<Vec<u8>, std::io::Error> { - load_bytecode_from_readable_source(std::io::stdin()) +fn load_bytecode_from_stdin() -> Result<Bytecode, std::io::Error> { + load_bytecode_from_readable_source(std::io::stdin(), None) } /// Attempt to load bytecode from a source that implements std::io::Read. -fn load_bytecode_from_readable_source(source: impl Read) -> Result<Vec<u8>, std::io::Error> { - let mut bytecode = Vec::<u8>::new(); - source.take(65536).read_to_end(&mut bytecode)?; - return Ok(bytecode); +fn load_bytecode_from_readable_source(source: impl Read, path: Option<&Path>) -> Result<Bytecode, std::io::Error> { + let mut bytes = Vec::<u8>::new(); + source.take(65536).read_to_end(&mut bytes)?; + return Ok(Bytecode { bytes, path: path.map(|p| p.to_path_buf()) }); +} + +struct Bytecode { + bytes: Vec<u8>, + path: Option<PathBuf>, +} + +impl Bytecode { + fn path(&self) -> String { + match &self.path { + Some(path) => path.as_os_str().to_string_lossy().to_string(), + None => String::from("<unknown>"), + } + } } @@ -248,7 +273,19 @@ fn main_asm(args: Asm) { // ----------------------------------------------------------------------- // GENERATE symbols file and bytecode let bytecode = generate_bytecode(&mut semantic_tokens); - // let symbols = generate_symbols_file(&semantic_tokens); + + if args.symbols && !args.check { + if let Some(path) = &args.output { + let mut symbols_path = path.to_path_buf(); + symbols_path.set_extension("br.sym"); + let symbols = generate_symbols_file(&semantic_tokens); + if let Err(err) = std::fs::write(&symbols_path, symbols) { + verbose!("Could not write to symbols path {symbols_path:?}: ({err:?})."); + } else { + verbose!("Saved debug symbols to {symbols_path:?}"); + } + } + } let length = bytecode.len(); let percentage = (length as f32 / 65536.0 * 100.0).round() as u16; @@ -361,6 +398,8 @@ xflags::xflags! { optional --check /// Only return resolved source code. optional --resolve + /// Generate debug symbols with file extension '.br.sym' + optional --symbols } } } |