hd/main.rs

193 lines
5.7 KiB
Rust

mod version;
mod hdinfo;
fn main()
{
let mut filenames=vec!();
let mut state=parseargs(&mut filenames);
state.hexdump_filenames_or_stdin(&filenames);
}
fn parseargs(filenames:&mut Vec<String>)->hdinfo::Hdinfo
{
let argv:Vec<String>=std::env::args().collect();
let mut curarg=1;
let mut state:hdinfo::Hdinfo=hdinfo::Hdinfo::new();
let helpmsg=format!("hd v{}\n\
usage: {} [-abh] [-n OFFSET] [-r RADIX] [-w WIDTH] [--help] FILES\n\
-a Don't display ASCII dump\n\
-b Don't display binary file offset\n\
-h, --help Display this help\n\
-n SIZE Number of bytes to read\n\
-r RADIX Number base (default: 16)\n\
-w WIDTH Number of columns for output\n\n\
SIZE An unsigned integer or a percentage (e.g., 50%)\n\
RADIX One of: 8, 10, 16",
version::VERSION,
argv[0]);
// Parse each file
while curarg < argv.len()
{
// Set width of columns
if argv[curarg]=="-w"
{
if argv.len()>curarg+1
{
curarg+=1;
state.columns=match argv[curarg].parse::<usize>()
{
Ok(n) => n,
Err(_) => 8,
};
}
else
{
print!("error: -w requires WIDTH argument\n");
std::process::exit(1);
}
}
// Set radix/base for hex dump
else if argv[curarg]=="-r"
{
if argv.len()>curarg+1
{
curarg+=1;
state.radix=match argv[curarg].parse::<usize>()
{
Ok(n) => n as u32,
Err(_) => 16u32,
};
if ![2,8,10,16].contains(&state.radix)
{
print!("error: unrecognized radix '{}'\n",state.radix);
std::process::exit(1);
}
}
else
{
print!("error: -r requires RADIX argument\n");
std::process::exit(1);
}
}
// Set number of bytes to read
else if argv[curarg]=="-n"
{
if argv.len()>curarg+1
{
curarg+=1;
// Set percentage
if argv[curarg].chars().nth(argv[curarg].len()-1).unwrap()=='%'
{
state.percent=match argv[curarg][0..argv[curarg].len()-1].parse::<usize>()
{
Ok(n) => n as f32/100.0,
Err(_) => 1.0,
};
}
// Set bytes offset
else
{
state.numbytes=match argv[curarg].parse::<usize>()
{
Ok(n) => n,
Err(_) => 0,
};
}
}
else
{
print!("error: -n requires SIZE argument\n");
std::process::exit(1);
}
}
// Options
else if argv[curarg].chars().nth(0).unwrap()=='-'
{
// Long option
if argv[curarg].len()>curarg && argv[curarg].chars().nth(1).unwrap()=='-'
{
match argv[curarg].as_str()
{
// Display help message
"--help" =>
{
print!("{}\n",helpmsg);
std::process::exit(0);
},
// Unrecognized option
_ =>
{
print!("error: unrecognized long option '{}'\n",argv[curarg]);
std::process::exit(1);
},
}
}
// Short options
else
{
for i in 1..argv[curarg].len()
{
let c=argv[curarg].chars().nth(i).unwrap();
match c
{
// Toggle showoffset (display file offset of hexdump)
'b' =>
{
state.showoffset=false;
},
// Toggle showascii (show ascii rendering)
'a' =>
{
state.showascii=false;
},
// Display help message
'h' =>
{
print!("{}\n",helpmsg);
std::process::exit(0);
},
// Warning for short options with arguments
'w' | 'n' | 'r' =>
{
print!("warning: use -{} on its own\n",
argv[curarg].chars().nth(i).unwrap());
},
// Unrecognized option
_ =>
{
print!("error: unrecognized short option '{}'\n",c);
std::process::exit(1);
}
}
}
}
}
// Default options treated as input filenames
else
{
filenames.push(argv[curarg].clone());
}
curarg+=1;
}
return state;
}