1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
extern crate pir_8_emu; use std::io::{self, Write, Read, stdout, stdin}; use std::process::exit; use std::borrow::Cow; use std::fs::File; fn main() { let result = actual_main().err().unwrap_or(0); exit(result); } fn actual_main() -> Result<(), i32> { let mut opts = pir_8_emu::options::DisassemblerOptions::parse(); let registers = opts.register_lettters .take() .map(|ll| pir_8_emu::isa::GeneralPurposeRegister::from_letters(&ll).unwrap()) .unwrap_or_else(pir_8_emu::isa::GeneralPurposeRegister::defaults); let mut output = stdout(); let (mut input, input_name): (Box<dyn Read>, Cow<'static, str>) = match opts.input.take() { Some((name, path)) => { (Box::new(File::open(path).map_err(|err| { eprintln!("Couldn't open input file \"{}\": {}", name, err); 3 })?), name.into()) } None => (Box::new(stdin()), "<stdin>".into()), }; if opts.skip != 0 { io::copy(&mut (&mut input).take(opts.skip as u64), &mut io::sink()).map_err(|err| { eprintln!("Failed to skip {} header bytes of file {}: {}", opts.skip, input_name, err); 5 })?; } let mut data_buf = 0u16; let mut data_remaining = 0; let mut last_instruction = pir_8_emu::isa::instruction::Instruction::Reserved(0); let mut bytes_to_keep = 0; let mut bb = input.bytes().enumerate(); while let Some((byte_idx, byte)) = bb.next() { let byte = byte.map_err(|err| { eprintln!("Failed to read byte {:#0w$X} of file {}: {}", byte_idx, input_name, err, w = 2 + pir_8_emu::util::min_byte_width(byte_idx) as usize * 2); 5 })?; if bytes_to_keep == 0 { if let Some(&(_, length)) = opts.keep.iter().find(|(s, l)| *l != 0 && *s == byte_idx) { bytes_to_keep = length; writeln!(output, "{:08X} S skipping {:#0w$X} bytes", byte_idx, length, w = 2 + pir_8_emu::util::min_byte_width(length) as usize * 2).map_err(|err| { eprintln!("Failed to write skip message ({:08X}, {:#04X}) from {}: {}", byte_idx, length, input_name, err); 4 })?; } } if bytes_to_keep != 0 { bytes_to_keep -= 1; continue; } if data_remaining != 0 { data_buf = (data_buf << 8) | (byte as u16); data_remaining -= 1; if data_remaining == 0 { let len = last_instruction.data_length(); writeln!(output, "{:08X} {}{d:0w$X} D {d:#0w_x$X}", byte_idx, if len == 1 { " " } else { "" }, d = data_buf, w = len * 2, w_x = len * 2 + 2).map_err(|err| { eprintln!("Failed to write instruction data {:#0w_x$X} for {} from {}:{:#10X}: {}", data_buf, last_instruction.display(®isters), input_name, byte_idx, err, w_x = len * 2 + 2); 4 })?; data_buf = 0; } } else { last_instruction = pir_8_emu::isa::instruction::Instruction::from(byte); data_remaining = last_instruction.data_length(); writeln!(output, "{:08X} {:02X} {} {}", byte_idx, byte, if last_instruction.is_valid() { ' ' } else { '!' }, last_instruction.display(®isters)).map_err(|err| { eprintln!("Failed to write instruction {} ({:#04X}) from {}:{:#10X}: {}", last_instruction.display(®isters), byte, input_name, byte_idx, err); 4 })?; } } if data_remaining != 0 { let len = last_instruction.data_length(); eprintln!("Insufficient data for instruction {}: have {}/{} at {:#0w$X}", last_instruction.display(®isters), len - data_remaining, len, data_buf, w = 2 + len * 2); return Err(7); } Ok(()) }