| 16 | use std::path::{Path, PathBuf}; |
| 17 | |
| 18 | fn main() -> Result<(), lexopt::Error> { |
| 19 | env_logger::init(); |
| 20 | |
| 21 | let mut scripts = vec![]; |
| 22 | let mut mode = compiler::Mode::Exec; |
| 23 | let mut expand_code_objects = true; |
| 24 | let mut optimize = 0; |
| 25 | |
| 26 | let mut parser = lexopt::Parser::from_env(); |
| 27 | while let Some(arg) = parser.next()? { |
| 28 | use lexopt::Arg::*; |
| 29 | match arg { |
| 30 | Long("help") | Short('h') => { |
| 31 | let bin_name = parser.bin_name().unwrap_or("dis"); |
| 32 | println!( |
| 33 | "usage: {bin_name} <scripts...> [-m,--mode=exec|single|eval] [-x,--no-expand] [-O]" |
| 34 | ); |
| 35 | println!( |
| 36 | "Compiles and disassembles python script files for viewing their bytecode." |
| 37 | ); |
| 38 | return Ok(()); |
| 39 | } |
| 40 | Value(x) => scripts.push(PathBuf::from(x)), |
| 41 | Long("mode") | Short('m') => { |
| 42 | mode = parser |
| 43 | .value()? |
| 44 | .parse_with(|s| s.parse::<compiler::Mode>().map_err(|e| e.to_string()))? |
| 45 | } |
| 46 | Long("no-expand") | Short('x') => expand_code_objects = false, |
| 47 | Short('O') => optimize += 1, |
| 48 | _ => return Err(arg.unexpected()), |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | if scripts.is_empty() { |
| 53 | return Err("expected at least one argument".into()); |
| 54 | } |
| 55 | |
| 56 | let opts = compiler::CompileOpts { |
| 57 | optimize, |
| 58 | debug_ranges: true, |
| 59 | }; |
| 60 | |
| 61 | for script in &scripts { |
| 62 | if script.exists() && script.is_file() { |
| 63 | let res = display_script(script, mode, opts, expand_code_objects); |
| 64 | if let Err(e) = res { |
| 65 | error!("Error while compiling {script:?}: {e}"); |
| 66 | } |
| 67 | } else { |
| 68 | eprintln!("{script:?} is not a file."); |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | Ok(()) |
| 73 | } |
| 74 | |
| 75 | fn display_script( |