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
use std::borrow::Cow;
use std::fs::File;
use std::path::Path;
use clap::ArgMatches;
use emulator::Instruction;
use emulator::parse::read_reachable_program;
static TEMPLATE: &'static str = include_str!("latex.tex");
pub fn main(args: &ArgMatches<'_>) -> Result<(), i32> {
let programs = args.values_of("2i-programm").unwrap().map(|arg| {
let program_path = Path::new(arg);
let program_file = File::open(program_path).map_err(|e| {
println!("Die angegebene Datei konnte nicht geöffnet werden: {}", e);
2
})?;
let program = read_reachable_program(&program_file).map_err(|e| {
println!("Das Mikroprogramm konnte nicht geladen werden: {}", e);
3
})?;
Ok((program_path.to_owned(), program))
}).collect::<Result<Vec<_>,i32>>()?;
let mut template = TEMPLATE.split("#split#");
let author = if let Some(authors) = args.values_of("autor") {
let prefix = "\\indent -- ".to_owned();
Cow::Owned(prefix + &authors.collect::<Vec<_>>().join(", "))
} else {
"".into()
};
let header = template.next().unwrap();
print!("{}", header.replace("#author#", &author));
let page_separator = template.next().unwrap();
let mut lines_remaining = 37;
for (path, program) in programs {
if lines_remaining < program.len() + 2 {
print!("{}", page_separator);
lines_remaining = 40;
}
lines_remaining -= program.len() + 2;
print_program(&path.to_string_lossy(), &program);
}
print!("{}", template.next().unwrap());
Ok(())
}
fn print_program(filename: &str, program: &Vec<(u8, Instruction)>) {
println!();
println!(" % Generated from {}", filename);
println!(" \\multicolumn{{15}}{{l}}{{}}\\\\\\multicolumn{{15}}{{l}}{{\\textbf{{{}}}}}\\\\\\hline", escape_latex(filename));
for &(addr, inst) in program.iter() {
println!(" {}&\\verb|{}|&{:05b}&{:02b}&{:05b}&{:01b}&{:01b}&{:03b}&{:04b}&{:01b}&{:01b}&{:01b}&{:01b}&{:04b}&{:01b}\\\\\\hline",
addr,
inst.to_mnemonic(Some(addr as usize)),
addr,
inst.get_address_control(),
inst.get_next_instruction_address(),
inst.is_bus_writable() as u8,
inst.is_bus_enabled() as u8,
inst.get_register_address_a(),
inst.get_constant_input() & 0b1111,
inst.should_write_register_b() as u8,
inst.should_write_register() as u8,
inst.is_alu_input_a_bus() as u8,
inst.is_alu_input_b_const() as u8,
inst.get_alu_instruction(),
inst.should_store_flags() as u8);
}
}
fn escape_latex(string: &str) -> String {
let mut result = String::with_capacity(string.len());
for char in string.chars() {
match char {
'&' => result.push_str("\\&"),
'%' => result.push_str("\\%"),
'$' => result.push_str("\\$"),
'#' => result.push_str("\\#"),
'_' => result.push_str("\\_"),
'{' => result.push_str("\\{"),
'}' => result.push_str("\\}"),
'~' => result.push_str("\\textasciitilde{}"),
'^' => result.push_str("\\textasciicircum{}"),
'\\' => result.push_str("\\textbackslash{}"),
_ => result.push(char),
}
}
result
}