Vasm cli wrapper will now export a symbol table

This commit is contained in:
2023-01-07 02:09:27 -06:00
parent 3e6a33899a
commit 11f0760b01
5 changed files with 58 additions and 15 deletions
Generated
+24
View File
@@ -592,6 +592,12 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "itoa"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]] [[package]]
name = "jni-sys" name = "jni-sys"
version = "0.3.0" version = "0.3.0"
@@ -1203,6 +1209,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]] [[package]]
name = "safe_arch" name = "safe_arch"
version = "0.5.2" version = "0.5.2"
@@ -1230,6 +1242,17 @@ version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
[[package]]
name = "serde_json"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.8.2" version = "0.8.2"
@@ -1386,6 +1409,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"regex", "regex",
"serde_json",
"vasm_core", "vasm_core",
] ]
+2 -1
View File
@@ -8,4 +8,5 @@ edition = "2021"
[dependencies] [dependencies]
vasm_core = { path = "../vasm_core" } vasm_core = { path = "../vasm_core" }
clap = { version = "3.1.18", features = ["derive"] } clap = { version = "3.1.18", features = ["derive"] }
regex = "1.7.0" regex = "1.7.0"
serde_json = "1.0.91"
+21 -3
View File
@@ -1,8 +1,10 @@
use std::collections::BTreeMap;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use clap::lazy_static::lazy_static; use clap::lazy_static::lazy_static;
use clap::Parser; use clap::Parser;
use regex::Regex; use regex::Regex;
use serde_json::json;
/// Vulcan Assembler /// Vulcan Assembler
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@@ -12,6 +14,10 @@ struct Args {
#[clap(short, long)] #[clap(short, long)]
output: Option<String>, output: Option<String>,
/// Whether to generate a JSON file containing the symbol table
#[clap(short, long)]
symbols: bool,
/// Input file /// Input file
#[clap()] #[clap()]
file: String, file: String,
@@ -51,10 +57,22 @@ fn main() {
args.deduce(); args.deduce();
match vasm_core::assemble_file(args.file.as_str()) { match vasm_core::assemble_file(args.file.as_str()) {
Ok(bytes) => { Ok((bytes, scope)) => {
//println!("We got some bytes... {} of them", bytes.len()); let mut outfile = File::create(args.output.as_ref().unwrap()).expect("Failed to open output file");
let mut outfile = File::create(args.output.unwrap()).expect("Failed to open output file");
outfile.write(bytes.as_slice()).expect("Failed to write to output file"); outfile.write(bytes.as_slice()).expect("Failed to write to output file");
if args.symbols {
let mut important_symbols : BTreeMap<String, i32> = BTreeMap::new();
for (sym, addr) in scope {
if !sym.starts_with("__gensym") {
important_symbols.insert(sym, addr);
}
}
let mut symfile = File::create(format!("{}.sym", args.output.unwrap())).expect("Failed to open symbol file");
let json = json!(important_symbols).to_string();
symfile.write(json.as_bytes()).expect("Failed to write to symbol file");
}
} }
Err(error) => { Err(error) => {
println!("{}", error) println!("{}", error)
+10 -10
View File
@@ -179,11 +179,11 @@ pub fn assemble_snippet<T: IntoIterator<Item = String>>(
}) })
.collect(); .collect();
assemble_line_results(line_results) assemble_line_results(line_results).map(|(bytes, _)| { bytes })
} }
/// Assemble a file from the filesystem, opening other files as it includes them. /// Assemble a file from the filesystem, opening other files as it includes them.
pub fn assemble_file(filename: &str) -> Result<Vec<u8>, AssembleError> { pub fn assemble_file(filename: &str) -> Result<(Vec<u8>, Scope), AssembleError> {
let lines = lines_from_file(filename)?; let lines = lines_from_file(filename)?;
let line_results: Vec<Result<Line, AssembleError>> = LineSource::new(filename, lines, |file| { let line_results: Vec<Result<Line, AssembleError>> = LineSource::new(filename, lines, |file| {
lines_from_file(file.as_str()) lines_from_file(file.as_str())
@@ -195,7 +195,7 @@ pub fn assemble_file(filename: &str) -> Result<Vec<u8>, AssembleError> {
fn assemble_line_results( fn assemble_line_results(
mut line_results: Vec<Result<Line, AssembleError>>, mut line_results: Vec<Result<Line, AssembleError>>,
) -> Result<Vec<u8>, AssembleError> { ) -> Result<(Vec<u8>, Scope), AssembleError> {
if let Some(Err(error)) = line_results.iter().find(|line| line.is_err()) { if let Some(Err(error)) = line_results.iter().find(|line| line.is_err()) {
Err(error.clone()) Err(error.clone())
} else { } else {
@@ -224,7 +224,7 @@ fn lines_from_file(filename: &str) -> Result<Vec<String>, AssembleError> {
/// ///
/// Vulcan is a little-endian architecture: multi-byte arguments / .dbs will store the /// Vulcan is a little-endian architecture: multi-byte arguments / .dbs will store the
/// least-significant byte at the lowest address, then the more significant bytes following. /// least-significant byte at the lowest address, then the more significant bytes following.
fn generate_code<T: IntoIterator<Item = Line>>(lines: T) -> Result<Vec<u8>, AssembleError> { fn generate_code<T: IntoIterator<Item = Line>>(lines: T) -> Result<(Vec<u8>, Scope), AssembleError> {
let lines: Vec<Line> = lines.into_iter().collect(); let lines: Vec<Line> = lines.into_iter().collect();
let scope = solve_equs(&lines)?; let scope = solve_equs(&lines)?;
let line_lengths = measure_instructions(&lines, &scope); let line_lengths = measure_instructions(&lines, &scope);
@@ -276,7 +276,7 @@ fn generate_code<T: IntoIterator<Item = Line>>(lines: T) -> Result<Vec<u8>, Asse
} }
} }
Ok(code) Ok((code, scope))
} }
#[cfg(test)] #[cfg(test)]
@@ -485,13 +485,13 @@ mod test {
#[test] #[test]
fn test_generate_code() { fn test_generate_code() {
assert_eq!(generate_code(parse(["add"])), Ok(vec![4])); assert_eq!(generate_code(parse(["add"])).unwrap().0, vec![4]);
assert_eq!( assert_eq!(
generate_code(parse([".org 0x400", "add 7"])), generate_code(parse([".org 0x400", "add 7"])).unwrap().0,
Ok(vec![5, 7]) vec![5, 7]
); );
assert_eq!(generate_code(parse([".db 57"])), Ok(vec![57, 0, 0])); assert_eq!(generate_code(parse([".db 57"])).unwrap().0, vec![57, 0, 0]);
assert_eq!(generate_code(parse([".db \"AZ\0\""])), Ok(vec![65, 90, 0])); assert_eq!(generate_code(parse([".db \"AZ\0\""])).unwrap().0, vec![65, 90, 0]);
} }
#[test] #[test]
+1 -1
View File
@@ -1 +1 @@
{"$BRNZ":28,"$BRZ":27,"$CALL":25,"$JMP":23,"$JMPR":24,"$PUSH":0,"$RET":26,"$SWAP":20,"$end":4617,"$start":1024,"advance_entry":1141,"backslash":3276,"close_paren":3267,"close_paren_stub":3275,"compare":1414,"compile_dict_start":3429,"compile_dictionary":4222,"compile_handleword":3150,"compile_instruction":1537,"compile_instruction_arg":1511,"compile_tick":1196,"cr":1067,"cursor":4210,"data_start":3340,"dict_start":3588,"dictionary":4219,"does_at_runtime":2225,"does_word":2196,"dupnz":1074,"dupnz_done":1080,"emit":1025,"emit_cursor":1042,"emit_hook":4228,"end0_pop1":1093,"end0_pop2":1092,"end1_pop2":1096,"eval":1773,"eval_word_buffer":4487,"expected_word_err":3388,"find_in_dict":1149,"find_in_dict_next":1179,"find_word":2584,"handleword_hook":4198,"heap":4195,"heap_start":4618,"hex_is_number":1280,"hex_itoa":1701,"immediate_handleword":3113,"input_number":1595,"invalid_mnemonic":3293,"invalid_mnemonic_str":3353,"is_digit":1084,"is_number":1205,"is_number_hook":4201,"itoa":1618,"itoa_hook":4204,"itoa_loop":1648,"itoa_pos":1637,"itoa_print_loop":1685,"lambda_nesting_level":4216,"lambda_start_ptr":4213,"line_len":4207,"linecomment":3209,"missing_word":3301,"missing_word_str":3340,"mnemonics":2258,"mnemonics_end":2469,"new_dict":1451,"new_dict_error":1497,"nova_asm_to":2563,"nova_bracket_tick":2634,"nova_char":2689,"nova_close_brace":3049,"nova_close_bracket":1998,"nova_colon":2146,"nova_comma":2133,"nova_compile_dotquote":2877,"nova_compile_opcode":2555,"nova_compile_open_brace":3024,"nova_compile_squote":2810,"nova_continue":2007,"nova_create":1946,"nova_dec":2660,"nova_dotquote":2856,"nova_emit":3007,"nova_exit":2099,"nova_here":2579,"nova_hex":2672,"nova_immediate":2105,"nova_immediate_open_brace":3012,"nova_literal":2654,"nova_number":1932,"nova_opcode":2550,"nova_opcode_for_word":2469,"nova_open_bracket":1990,"nova_peekr":2961,"nova_popr":2994,"nova_postpone":2017,"nova_print_stack":2907,"nova_pushr":2981,"nova_quote_string_to":2715,"nova_resolve":1568,"nova_rpick":2969,"nova_safe_opcode":2529,"nova_semicolon":2154,"nova_squote":2780,"nova_tick":2613,"nova_word":1852,"nova_word_to":1902,"nova_word_to_pad":2164,"open_paren":3250,"pad":4231,"parencomment":3211,"parse_hex_digit":1326,"pos_is_number":1234,"pos_is_number_bad":1271,"pos_is_number_done":1276,"pos_is_number_loop":1236,"print":1045,"print_number":1613,"print_stack_end":3426,"print_stack_start":3422,"push_jump":1552,"quit":3317,"quit_vector":4225,"r_stack":4522,"r_stack_ptr":4519,"skip_nonword":1388,"skip_word":1371,"stop":1024,"tick":1187,"unclosed_error":3372,"word_char":1081,"wordeq":1100} {"$BRNZ":28,"$BRZ":27,"$CALL":25,"$JMP":23,"$JMPR":24,"$PUSH":0,"$RET":26,"$SWAP":20,"advance_entry":1141,"backslash":3276,"close_paren":3267,"close_paren_stub":3275,"compare":1414,"compile_dict_start":3429,"compile_dictionary":4222,"compile_handleword":3150,"compile_instruction":1537,"compile_instruction_arg":1511,"compile_tick":1196,"cr":1067,"cursor":4210,"data_start":3340,"dict_start":3588,"dictionary":4219,"does_at_runtime":2225,"does_word":2196,"dupnz":1074,"dupnz_done":1080,"emit":1025,"emit_cursor":1042,"emit_hook":4228,"end0_pop1":1093,"end0_pop2":1092,"end1_pop2":1096,"eval":1773,"eval_word_buffer":4487,"expected_word_err":3388,"find_in_dict":1149,"find_in_dict_next":1179,"find_word":2584,"handleword_hook":4198,"heap":4195,"heap_start":4618,"hex_is_number":1280,"hex_itoa":1701,"immediate_handleword":3113,"input_number":1595,"invalid_mnemonic":3293,"invalid_mnemonic_str":3353,"is_digit":1084,"is_number":1205,"is_number_hook":4201,"itoa":1618,"itoa_hook":4204,"itoa_loop":1648,"itoa_pos":1637,"itoa_print_loop":1685,"lambda_nesting_level":4216,"lambda_start_ptr":4213,"line_len":4207,"linecomment":3209,"missing_word":3301,"missing_word_str":3340,"mnemonics":2258,"mnemonics_end":2469,"new_dict":1451,"new_dict_error":1497,"nova_asm_to":2563,"nova_bracket_tick":2634,"nova_char":2689,"nova_close_brace":3049,"nova_close_bracket":1998,"nova_colon":2146,"nova_comma":2133,"nova_compile_dotquote":2877,"nova_compile_opcode":2555,"nova_compile_open_brace":3024,"nova_compile_squote":2810,"nova_continue":2007,"nova_create":1946,"nova_dec":2660,"nova_dotquote":2856,"nova_emit":3007,"nova_exit":2099,"nova_here":2579,"nova_hex":2672,"nova_immediate":2105,"nova_immediate_open_brace":3012,"nova_literal":2654,"nova_number":1932,"nova_opcode":2550,"nova_opcode_for_word":2469,"nova_open_bracket":1990,"nova_peekr":2961,"nova_popr":2994,"nova_postpone":2017,"nova_print_stack":2907,"nova_pushr":2981,"nova_quote_string_to":2715,"nova_resolve":1568,"nova_rpick":2969,"nova_safe_opcode":2529,"nova_semicolon":2154,"nova_squote":2780,"nova_tick":2613,"nova_word":1852,"nova_word_to":1902,"nova_word_to_pad":2164,"open_paren":3250,"pad":4231,"parencomment":3211,"parse_hex_digit":1326,"pos_is_number":1234,"pos_is_number_bad":1271,"pos_is_number_done":1276,"pos_is_number_loop":1236,"print":1045,"print_number":1613,"print_stack_end":3426,"print_stack_start":3422,"push_jump":1552,"quit":3317,"quit_vector":4225,"r_stack":4522,"r_stack_ptr":4519,"skip_nonword":1388,"skip_word":1371,"stop":1024,"tick":1187,"unclosed_error":3372,"word_char":1081,"wordeq":1100}