diff --git a/Cargo.lock b/Cargo.lock index 293883f..61698a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -22,9 +22,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" [[package]] name = "arrayvec" @@ -38,7 +38,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -69,15 +69,24 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "card_macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "cc" -version = "1.0.76" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cfg-if" @@ -109,7 +118,7 @@ dependencies = [ "atty", "bitflags", "clap_derive", - "clap_lex", + "clap_lex 0.2.4", "indexmap", "once_cell", "strsim", @@ -117,6 +126,19 @@ dependencies = [ "textwrap", ] +[[package]] +name = "clap" +version = "4.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" +dependencies = [ + "bitflags", + "clap_lex 0.3.1", + "is-terminal", + "strsim", + "termcolor", +] + [[package]] name = "clap_derive" version = "3.2.18" @@ -139,6 +161,15 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -157,9 +188,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crossterm" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +checksum = "ab9f7409c70a38a56216480fba371ee460207dd8926ccf5b4160591759559170" dependencies = [ "bitflags", "crossterm_winapi", @@ -172,6 +203,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "crossterm" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm_winapi" version = "0.9.0" @@ -193,9 +240,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.82" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8" dependencies = [ "cc", "cxxbridge-flags", @@ -205,9 +252,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.82" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8" dependencies = [ "cc", "codespan-reporting", @@ -220,15 +267,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.82" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" +checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971" [[package]] name = "cxxbridge-macro" -version = "1.0.82" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e" dependencies = [ "proc-macro2", "quote", @@ -248,15 +295,15 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "elf" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6de42b0529467fc9a2692fd91585c84dd255fb15b0df0f80299724a9456986c6" +checksum = "2ace2c81c1832d02208b8317b90b2de5b3b4f55024b86d3f2ae800353e348fd7" [[package]] name = "errno" @@ -281,9 +328,9 @@ dependencies = [ [[package]] name = "fd-lock" -version = "3.0.8" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27" +checksum = "28c0190ff0bd3b28bfdd4d0cf9f92faa12880fb0b8ae2054723dd6c76a4efd42" dependencies = [ "cfg-if", "rustix", @@ -298,9 +345,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "ghost" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a" +checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3" dependencies = [ "proc-macro2", "quote", @@ -328,6 +375,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "human-repr" version = "1.0.1" @@ -370,9 +426,9 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21e0a36a4dc4b469422ee17f715e8313f4a637675656d6a13637954278c6f55" +checksum = "16fe3b35d64bd1f72917f06425e7573a2f63f74f42c8f56e53ea6826dde3a2b5" dependencies = [ "ctor", "ghost", @@ -380,14 +436,26 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87" +checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" dependencies = [ "libc", "windows-sys", ] +[[package]] +name = "is-terminal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +dependencies = [ + "hermit-abi 0.2.6", + "io-lifetimes", + "rustix", + "windows-sys", +] + [[package]] name = "itertools" version = "0.10.5" @@ -408,24 +476,24 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] [[package]] name = "linux-raw-sys" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb68f22743a3fb35785f1e7f844ca5a3de2dde5bd0c0ef5b372065814699b121" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "lock_api" @@ -453,7 +521,8 @@ dependencies = [ "anyhow", "bitflags", "bitvec", - "clap", + "card_macro", + "clap 3.2.23", "derive-try-from-primitive", "elf", "human-repr", @@ -496,9 +565,9 @@ checksum = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" [[package]] name = "nu-ansi-term" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7bca0d33a384280d1563b97f49cb95303df9fa22588739a04b7d8015c1ccd50" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", "winapi", @@ -531,15 +600,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "os_str_bytes" -version = "6.4.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "overload" @@ -559,9 +628,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" dependencies = [ "cfg-if", "libc", @@ -605,18 +674,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] @@ -638,30 +707,32 @@ dependencies = [ [[package]] name = "reedline" -version = "0.6.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422f144c06f679da4ab4f082a6d1d43e28bfabb68d009100e6e5520728f99fec" +checksum = "555a4285d183a94d140d749712a6600b10e70d7cd6aef91e3cfb65ba09b1d75e" dependencies = [ "chrono", - "crossterm", + "crossterm 0.24.0", "fd-lock", + "itertools", "nu-ansi-term", "serde", "strip-ansi-escapes", "strum", "strum_macros", + "thiserror", "unicode-segmentation", "unicode-width", ] [[package]] name = "reedline-repl-rs" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a82ee3209046ff272bd79fe1311ed82823102f741f3130be9dc82ef77d492b3" +checksum = "9431c30dcf1210814a728e1ceedf8070a6589cd15d80717f313f92c4d2f73469" dependencies = [ - "clap", - "crossterm", + "clap 4.1.4", + "crossterm 0.25.0", "nu-ansi-term", "reedline", "regex", @@ -671,9 +742,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -688,9 +759,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "rustix" -version = "0.36.1" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812a2ec2043c4d6bc6482f5be2ab8244613cac2493d128d36c0759e52a626ab3" +checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" dependencies = [ "bitflags", "errno", @@ -702,9 +773,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "scopeguard" @@ -714,24 +785,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -810,9 +881,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -827,9 +898,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -842,18 +913,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", @@ -862,9 +933,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -873,18 +944,18 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-segmentation" @@ -1045,45 +1116,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "wyz" diff --git a/Cargo.toml b/Cargo.toml index 8415e5b..648a0e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" anyhow = "1.0.66" bitflags = "1.3.2" bitvec = "1.0.0" +card_macro = { version = "0.1.0", path = "card_macro" } clap = { version = "3.2.23", features = ["clap_derive", "derive"] } derive-try-from-primitive = "1.0.0" elf = "0.7.0" diff --git a/src/main.rs b/src/main.rs index 48a54d3..25649b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,402 +97,401 @@ fn main() -> Result<(), anyhow::Error> { return Ok(()); } Repl::<_, anyhow::Error>::new(state) - .with_name("68KEmu") - .with_version("0.1.0") - .with_banner("68K Backplane Computer Emulator") - .with_description("68K Backplane Computer Emulator") - .with_command( - Command::new("card") - .trailing_var_arg(true) + .with_name("68KEmu") + .with_version("0.1.0") + .with_banner("68K Backplane Computer Emulator") + .with_description("68K Backplane Computer Emulator") + .with_command( + Command::new("card") .arg( Arg::new("num") - .required(true) - .help("The card number to send the command to"), + .required(true) + .help("The card number to send the command to"), ) .arg( Arg::new("cmd") - .required(true) - .multiple_values(true) - .takes_value(true) - .help("The command to send"), + .trailing_var_arg(true) + .num_args(1..) + .required(true) + .help("The command to send"), ) .about("Send a command to a card"), - |args, state| { - let num = args.get_one::("num").unwrap().parse::()?; - state.cpu.bus_mut().card_cmd( - num, - &args + |args, state| { + let num = args.get_one::("num").unwrap().parse::()?; + state.cpu.bus_mut().card_cmd( + num, + &args .get_many::("cmd") .unwrap() .map(String::as_str) .collect_vec(), - )?; - Ok(None) - }, - ) - .with_command( - Command::new("ls").about("List the cards in the system"), - |_, state| Ok(Some(state.cpu.bus_mut().to_string())), - ) - .with_command( - Command::new("regs").about("Show CPU registers"), - |_, state| Ok(Some(format!("{}", state.cpu))), - ) - .with_command( - Command::new("step") - .arg( - Arg::new("count") - .takes_value(true) - .help("Count of instructions to step by. Defaults to 1"), - ) - .arg( - Arg::new("print_ins") - .long("print_ins") - .short('i') - .action(ArgAction::SetTrue) - .help("Print instructions"), - ) - .arg( - Arg::new("print_regs") - .long("print_regs") - .short('r') - .action(ArgAction::SetTrue) - .help("Print ending registers"), - ) - .about("Step the CPU"), - |args, state| { - let count = parse::(args.get_one::("count").map_or("1", String::as_str))?; - let mut out = String::new(); - for _ in 0..count { - if state.cpu.stopped { - out += &format!("CPU stopped at PC {:#x}\n", state.cpu.pc()); - break; - } - if args.get_flag("print_ins") { - let pc = state.cpu.pc(); - out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0; - } - state.cpu.step(); - } - if args.get_flag("print_regs") { - out += &format!("{}\n", state.cpu); - } - if out.is_empty() { + )?; Ok(None) - } else { - out.pop(); // Remove trailing newline - Ok(Some(out)) - } - }, - ) - .with_command( - Command::new("run") - .arg(Arg::new("stop_addr").takes_value(true).help( - "Optional address to stop execution at. Works as a breakpoint only for this run", - )) - .arg( - Arg::new("print_ins") - .long("print_ins") - .short('p') - .action(ArgAction::SetTrue) - .help("Print all executed instructions"), + }, ) - .about("Run the CPU"), - |args, state| { - let mut out = String::new(); - while !state.cpu.stopped { - let stop_addr = args - .get_one::("stop_addr") - .map(|s| state.symbol_tables.parse_location_address(s)) - .transpose()?; - if stop_addr.map_or(false, |a| state.cpu.pc() == a) - || state.symbol_tables.breakpoint_set_at(state.cpu.pc()) - || state.address_breakpoints.contains(&state.cpu.pc()) - { - break; - } - if args.get_flag("print_ins") { - let pc = state.cpu.pc(); - out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0; - } - state.cpu.step(); - } - out += &format!("{}\n", state.cpu); - let pc = state.cpu.pc(); - out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0; - out.pop(); // Remove trailing newline - Ok(Some(out)) - }, + .with_command( + Command::new("ls").about("List the cards in the system"), + |_, state| Ok(Some(state.cpu.bus_mut().to_string())), + ) + .with_command( + Command::new("regs").about("Show CPU registers"), + |_, state| Ok(Some(format!("{}", state.cpu))), + ) + .with_command( + Command::new("step") + .arg( + Arg::new("count") + + .help("Count of instructions to step by. Defaults to 1"), + ) + .arg( + Arg::new("print_ins") + .long("print_ins") + .short('i') + .action(ArgAction::SetTrue) + .help("Print instructions"), + ) + .arg( + Arg::new("print_regs") + .long("print_regs") + .short('r') + .action(ArgAction::SetTrue) + .help("Print ending registers"), + ) + .about("Step the CPU"), + |args, state| { + let count = parse::(args.get_one::("count").map_or("1", String::as_str))?; + let mut out = String::new(); + for _ in 0..count { + if state.cpu.stopped { + out += &format!("CPU stopped at PC {:#x}\n", state.cpu.pc()); + break; + } + if args.get_flag("print_ins") { + let pc = state.cpu.pc(); + out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0; + } + state.cpu.step(); + } + if args.get_flag("print_regs") { + out += &format!("{}\n", state.cpu); + } + if out.is_empty() { + Ok(None) + } else { + out.pop(); // Remove trailing newline + Ok(Some(out)) + } + }, + ) + .with_command( + Command::new("run") + .arg(Arg::new("stop_addr").help( + "Optional address to stop execution at. Works as a breakpoint only for this run", + )) + .arg( + Arg::new("print_ins") + .long("print_ins") + .short('p') + .action(ArgAction::SetTrue) + .help("Print all executed instructions"), + ) + .about("Run the CPU"), + |args, state| { + let mut out = String::new(); + while !state.cpu.stopped { + let stop_addr = args + .get_one::("stop_addr") + .map(|s| state.symbol_tables.parse_location_address(s)) + .transpose()?; + if stop_addr.map_or(false, |a| state.cpu.pc() == a) + || state.symbol_tables.breakpoint_set_at(state.cpu.pc()) + || state.address_breakpoints.contains(&state.cpu.pc()) + { + break; + } + if args.get_flag("print_ins") { + let pc = state.cpu.pc(); + out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0; + } + state.cpu.step(); + } + out += &format!("{}\n", state.cpu); + let pc = state.cpu.pc(); + out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0; + out.pop(); // Remove trailing newline + Ok(Some(out)) + }, + ) + .with_command( + Command::new("reset").about("Reset the cards and CPU, in that order"), + |_, state| { + state.cpu.bus_mut().reset(); + state.cpu.reset(); + Ok(None) + }, + ) + .with_command( + Command::new("peek") + .arg( + Arg::new("count") + .short('c') + + .help("The count of values to print"), + ) + .arg( + Arg::new("fmt") + .short('f') + + .help("The format to print the values in ()"), + ) + .arg(Arg::new("addr").required(true)) + .about("Peek a memory address"), + |args, state| { + let (fmt, size) = if let Some(fmt_str) = args.get_one::("fmt") { + if fmt_str.len() != 2 { + return Err(anyhow!("Peek format length must be 2")); + } + let fmt = peek::Format::try_from(fmt_str.chars().next().unwrap())?; + let size = peek::Size::try_from(fmt_str.chars().nth(1).unwrap())?; + state.last_peek_format = (fmt, size); + (fmt, size) + } else { + state.last_peek_format + }; + let count = parse::(args.get_one::("count").map_or("1", String::as_str))?; + let addr = state + .symbol_tables + .parse_location_address(args.get_one::("addr").unwrap())?; + if (size != peek::Size::Byte) & ((addr & 0x1) != 0) { + return Err(anyhow!("Cannot peek words from a non-aligned address")); + } + let mut data = Vec::new(); + let bus = state.cpu.bus_mut(); + for i in 0..count { + match size { + peek::Size::Byte => data.push(bus.read_byte(addr + i)? as u32), + peek::Size::Word => data.push(bus.read_word(addr + (i * 2))? as u32), + peek::Size::LongWord => data.push( + (bus.read_word(addr + (i * 4))? as u32) << 16 + | (bus.read_word(addr + (i * 4) + 2)? as u32), + ), + } + } + Ok(Some( + data.chunks(size.chunk_size()) + .enumerate() + .map(|(i, c)| { + format!( + "0x{:x}: ", + addr + (size.chunk_size() * size.byte_count() * i) as u32 + ) + &c.iter().map(|d| fmt.format(*d, size)).join(" ") + }) + .join("\n"), + )) + }, + ) + .with_command( + Command::new("poke") + .arg(Arg::new("address").help("The address to write to").required(true)) + .arg(Arg::new("data").help("The data to write").required(true)) + .arg( + Arg::new("word") + .long("word") + .short('w') + .action(ArgAction::SetTrue) + .help("Write a word instead of a byte"), + ) + .about("Write to a memory address"), + |args, state| { + let address = parse::(args.get_one::("address").unwrap())?; + if args.get_flag("word") { + if (address & 0x1) != 0 { + return Err(anyhow!("Cannot poke a word to a non-aligned address")); + } + let data = parse::(args.get_one::("data").unwrap())?; + state.cpu.bus_mut().write_word(address, data)?; + } else { + let data = parse::(args.get_one::("data").unwrap())?; + state.cpu.bus_mut().write_byte(address, data as u8)?; + } + Ok(None) + } ) - .with_command( - Command::new("reset").about("Reset the cards and CPU, in that order"), - |_, state| { - state.cpu.bus_mut().reset(); - state.cpu.reset(); - Ok(None) - }, - ) - .with_command( - Command::new("peek") - .arg( - Arg::new("count") - .short('c') - .takes_value(true) - .help("The count of values to print"), - ) - .arg( - Arg::new("fmt") - .short('f') - .takes_value(true) - .help("The format to print the values in ()"), - ) - .arg(Arg::new("addr").required(true)) - .about("Peek a memory address"), - |args, state| { - let (fmt, size) = if let Some(fmt_str) = args.get_one::("fmt") { - if fmt_str.len() != 2 { - return Err(anyhow!("Peek format length must be 2")); - } - let fmt = peek::Format::try_from(fmt_str.chars().next().unwrap())?; - let size = peek::Size::try_from(fmt_str.chars().nth(1).unwrap())?; - state.last_peek_format = (fmt, size); - (fmt, size) - } else { - state.last_peek_format - }; - let count = parse::(args.get_one::("count").map_or("1", String::as_str))?; - let addr = state - .symbol_tables - .parse_location_address(args.get_one::("addr").unwrap())?; - if (size != peek::Size::Byte) & ((addr & 0x1) != 0) { - return Err(anyhow!("Cannot peek words from a non-aligned address")); - } - let mut data = Vec::new(); - let bus = state.cpu.bus_mut(); - for i in 0..count { - match size { - peek::Size::Byte => data.push(bus.read_byte(addr + i)? as u32), - peek::Size::Word => data.push(bus.read_word(addr + (i * 2))? as u32), - peek::Size::LongWord => data.push( - (bus.read_word(addr + (i * 4))? as u32) << 16 - | (bus.read_word(addr + (i * 4) + 2)? as u32), - ), - } - } - Ok(Some( - data.chunks(size.chunk_size()) - .enumerate() - .map(|(i, c)| { - format!( - "0x{:x}: ", - addr + (size.chunk_size() * size.byte_count() * i) as u32 - ) + &c.iter().map(|d| fmt.format(*d, size)).join(" ") - }) - .join("\n"), - )) - }, - ) - .with_command( - Command::new("poke") - .arg(Arg::new("address").help("The address to write to").required(true)) - .arg(Arg::new("data").help("The data to write").required(true)) - .arg( - Arg::new("word") - .long("word") - .short('w') - .action(ArgAction::SetTrue) - .help("Write a word instead of a byte"), - ) - .about("Write to a memory address"), - |args, state| { - let address = parse::(args.get_one::("address").unwrap())?; - if args.get_flag("word") { - if (address & 0x1) != 0 { - return Err(anyhow!("Cannot poke a word to a non-aligned address")); - } - let data = parse::(args.get_one::("data").unwrap())?; - state.cpu.bus_mut().write_word(address, data)?; - } else { - let data = parse::(args.get_one::("data").unwrap())?; - state.cpu.bus_mut().write_byte(address, data as u8)?; - } - Ok(None) - } - ) - .with_command( - Command::new("disas") + .with_command( + Command::new("disas") .arg(Arg::new("addr").help("Address to start disassembly at. Defaults to current PC")) .arg( Arg::new("count") - .short('c') - .takes_value(true) - .help("Count of instructions to disassemble. Defaults to 1"), + .short('c') + + .help("Count of instructions to disassemble. Defaults to 1"), ) .about("Disassemble a region of memory"), - |args, state| { - let mut addr = args - .get_one::("addr") - .map_or(Ok(state.cpu.pc()), |s| { - state.symbol_tables.parse_location_address(s) - })?; - let count = parse::(args.get_one::("count").map_or("1", String::as_str))?; - let mut out = String::new(); - for _ in 0..count { - let (fmt, res) = disas_fmt(&mut state.cpu, addr, &state.symbol_tables); - out += &fmt; - match res { - Ok(new_addr) => { - addr = new_addr; - } - Err(_) => { - break; - } - } - } - out.pop(); // Remove trailing newline - Ok(Some(out)) - }, - ) - .with_command( - Command::new("sym") - .arg(Arg::new("file").help("The ELF file to load symbols from")) - .arg( - Arg::new("append") - .long("append") - .short('a') - .action(ArgAction::SetTrue) - .requires("file") - .conflicts_with_all(&["delete", "set-active"]) - .help("Append the file's symbols to the loaded list of symbols"), - ) - .arg( - Arg::new("delete") - .long("delete") - .short('d') - .action(ArgAction::SetTrue) - .requires("file") - .conflicts_with_all(&["append", "set-active"]) - .help("Delete the symbol table instead of loading it"), - ) - .arg( - Arg::new("set-active") - .long("set-active") - .short('c') - .takes_value(true) - .value_parser(BoolishValueParser::new()) - .requires("file") - .conflicts_with_all(&["append", "delete"]) - .help("Set whether the symbol table is active or not"), - ) - .about("Load symbols from an ELF file, or list symbols if no file provided"), - |args, state| { - if let Some(file_path) = args.get_one::("file") { - let table_name = Path::new(&file_path).file_name().unwrap().to_str().unwrap(); - if args.get_flag("delete") { - state.symbol_tables.delete(table_name)?; - } else if let Some(&active) = args.get_one::("set-active") { - state.symbol_tables.set_active(table_name, active)?; - } else { - state - .symbol_tables - .load_table(file_path, args.get_flag("append"))?; - } - Ok(None) - } else if state.symbol_tables.is_empty() { - Ok(Some("No symbols".to_string())) - } else { - Ok(Some(format!("{}", state.symbol_tables.symbol_displayer()))) - } - }, - ) - .with_command( - Command::new("resolve") - .arg( - Arg::new("location") - .help("The location to resolve") - .required(true), - ) - .about("Resolve a location to an address"), - |args, state| { - let location = args.get_one::("location").unwrap(); - Ok(Some(format!( - "{}", - state - .symbol_tables - .parse_location(location)? - .displayer(&state.symbol_tables) - ))) - }, - ) - .with_command( - Command::new("bp") - .arg(Arg::new("location").help("The location to set a breakpoint at")) - .arg( - Arg::new("delete") - .long("delete") - .short('d') - .action(ArgAction::SetTrue) - .requires("location") - .help("Delete the breakpoint instead of setting it"), - ) - .about("Set a breakpoint or list current breakpoints"), - |args, state| { - if let Some(location) = args.get_one::("location") { - let location = state.symbol_tables.parse_location(location)?; - if args.get_flag("delete") { - let deleted = match location { - Location::Symbol((table, symbol)) => { - state.symbol_tables.delete_breakpoint(&table, &symbol)? - } - Location::Address(address) => { - state.address_breakpoints.shift_remove(&address) - } - }; - if deleted { - Ok(None) - } else { - Ok(Some("No such breakpoint".to_string())) - } - } else { - match location { - Location::Symbol((table, symbol)) => { - state.symbol_tables.set_breakpoint(&table, symbol)?; - } - Location::Address(address) => { - state.address_breakpoints.insert(address); - } - }; - Ok(None) - } - } else { + |args, state| { + let mut addr = args + .get_one::("addr") + .map_or(Ok(state.cpu.pc()), |s| { + state.symbol_tables.parse_location_address(s) + })?; + let count = parse::(args.get_one::("count").map_or("1", String::as_str))?; let mut out = String::new(); - out += &format!("{}", state.symbol_tables.breakpoint_displayer()); - if !state.address_breakpoints.is_empty() { - if !out.is_empty() { - out += "\n"; - } - out += "Address breakpoints:\n"; - out += &format!("{}", state.address_breakpoints.iter().format("\n")); + for _ in 0..count { + let (fmt, res) = disas_fmt(&mut state.cpu, addr, &state.symbol_tables); + out += &fmt; + match res { + Ok(new_addr) => { + addr = new_addr; + } + Err(_) => { + break; + } + } } - if out.is_empty() { - Ok(Some("No breakpoints".to_string())) - } else { - Ok(Some(out)) - } - } - }, - ) - .with_command( - Command::new("quit") - .visible_alias("q") - .visible_alias("exit") - .about("Quit"), - |_, _| process::exit(0), - ) - // Visible aliases don't actually work, so fake it with hidden subcommands - .with_command(Command::new("q").hide(true), |_, _| process::exit(0)) - .with_command(Command::new("exit").hide(true), |_, _| process::exit(0)) - .run()?; + out.pop(); // Remove trailing newline + Ok(Some(out)) + }, + ) + .with_command( + Command::new("sym") + .arg(Arg::new("file").help("The ELF file to load symbols from")) + .arg( + Arg::new("append") + .long("append") + .short('a') + .action(ArgAction::SetTrue) + .requires("file") + .conflicts_with_all(&["delete", "set-active"]) + .help("Append the file's symbols to the loaded list of symbols"), + ) + .arg( + Arg::new("delete") + .long("delete") + .short('d') + .action(ArgAction::SetTrue) + .requires("file") + .conflicts_with_all(&["append", "set-active"]) + .help("Delete the symbol table instead of loading it"), + ) + .arg( + Arg::new("set-active") + .long("set-active") + .short('c') + + .value_parser(BoolishValueParser::new()) + .requires("file") + .conflicts_with_all(&["append", "delete"]) + .help("Set whether the symbol table is active or not"), + ) + .about("Load symbols from an ELF file, or list symbols if no file provided"), + |args, state| { + if let Some(file_path) = args.get_one::("file") { + let table_name = Path::new(&file_path).file_name().unwrap().to_str().unwrap(); + if args.get_flag("delete") { + state.symbol_tables.delete(table_name)?; + } else if let Some(&active) = args.get_one::("set-active") { + state.symbol_tables.set_active(table_name, active)?; + } else { + state + .symbol_tables + .load_table(file_path, args.get_flag("append"))?; + } + Ok(None) + } else if state.symbol_tables.is_empty() { + Ok(Some("No symbols".to_string())) + } else { + Ok(Some(format!("{}", state.symbol_tables.symbol_displayer()))) + } + }, + ) + .with_command( + Command::new("resolve") + .arg( + Arg::new("location") + .help("The location to resolve") + .required(true), + ) + .about("Resolve a location to an address"), + |args, state| { + let location = args.get_one::("location").unwrap(); + Ok(Some(format!( + "{}", + state + .symbol_tables + .parse_location(location)? + .displayer(&state.symbol_tables) + ))) + }, + ) + .with_command( + Command::new("bp") + .arg(Arg::new("location").help("The location to set a breakpoint at")) + .arg( + Arg::new("delete") + .long("delete") + .short('d') + .action(ArgAction::SetTrue) + .requires("location") + .help("Delete the breakpoint instead of setting it"), + ) + .about("Set a breakpoint or list current breakpoints"), + |args, state| { + if let Some(location) = args.get_one::("location") { + let location = state.symbol_tables.parse_location(location)?; + if args.get_flag("delete") { + let deleted = match location { + Location::Symbol((table, symbol)) => { + state.symbol_tables.delete_breakpoint(&table, &symbol)? + } + Location::Address(address) => { + state.address_breakpoints.shift_remove(&address) + } + }; + if deleted { + Ok(None) + } else { + Ok(Some("No such breakpoint".to_string())) + } + } else { + match location { + Location::Symbol((table, symbol)) => { + state.symbol_tables.set_breakpoint(&table, symbol)?; + } + Location::Address(address) => { + state.address_breakpoints.insert(address); + } + }; + Ok(None) + } + } else { + let mut out = String::new(); + out += &format!("{}", state.symbol_tables.breakpoint_displayer()); + if !state.address_breakpoints.is_empty() { + if !out.is_empty() { + out += "\n"; + } + out += "Address breakpoints:\n"; + out += &format!("{}", state.address_breakpoints.iter().format("\n")); + } + if out.is_empty() { + Ok(Some("No breakpoints".to_string())) + } else { + Ok(Some(out)) + } + } + }, + ) + .with_command( + Command::new("quit") + .visible_alias("q") + .visible_alias("exit") + .about("Quit"), + |_, _| process::exit(0), + ) + // Visible aliases don't actually work, so fake it with hidden subcommands + .with_command(Command::new("q").hide(true), |_, _| process::exit(0)) + .with_command(Command::new("exit").hide(true), |_, _| process::exit(0)) + .run()?; Ok(()) }