mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-30 12:37:49 +00:00
commit
9c27aac8fe
1 changed files with 181 additions and 27 deletions
208
src/test/test.rs
208
src/test/test.rs
|
@ -12,6 +12,7 @@
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate num;
|
extern crate num;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::os::{args_as_bytes};
|
use std::os::{args_as_bytes};
|
||||||
use std::str::{from_utf8};
|
use std::str::{from_utf8};
|
||||||
use num::bigint::{BigInt};
|
use num::bigint::{BigInt};
|
||||||
|
@ -38,14 +39,20 @@ pub fn uumain(_: Vec<String>) -> int {
|
||||||
},
|
},
|
||||||
_ => args.slice(1, args.len()),
|
_ => args.slice(1, args.len()),
|
||||||
};
|
};
|
||||||
1 - dispatch(args) as int
|
let mut error = false;
|
||||||
|
let retval = 1 - parse_expr(args, &mut error) as int;
|
||||||
|
if error {
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
retval
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn one(args: &[&[u8]]) -> bool {
|
fn one(args: &[&[u8]]) -> bool {
|
||||||
args[0].len() > 0
|
args[0].len() > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn two(args: &[&[u8]]) -> bool {
|
fn two(args: &[&[u8]], error: &mut bool) -> bool {
|
||||||
match args[0] {
|
match args[0] {
|
||||||
b"!" => !one(args.slice_from(1)),
|
b"!" => !one(args.slice_from(1)),
|
||||||
b"-b" => path(args[1], BlockSpecial),
|
b"-b" => path(args[1], BlockSpecial),
|
||||||
|
@ -66,11 +73,14 @@ fn two(args: &[&[u8]]) -> bool {
|
||||||
b"-w" => path(args[1], Writable),
|
b"-w" => path(args[1], Writable),
|
||||||
b"-x" => path(args[1], Executable),
|
b"-x" => path(args[1], Executable),
|
||||||
b"-z" => !one(args.slice_from(1)),
|
b"-z" => !one(args.slice_from(1)),
|
||||||
_ => false,
|
_ => {
|
||||||
|
*error = true;
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn three(args: &[&[u8]]) -> bool {
|
fn three(args: &[&[u8]], error: &mut bool) -> bool {
|
||||||
match args[1] {
|
match args[1] {
|
||||||
b"=" => args[0] == args[2],
|
b"=" => args[0] == args[2],
|
||||||
b"!=" => args[0] != args[2],
|
b"!=" => args[0] != args[2],
|
||||||
|
@ -80,28 +90,25 @@ fn three(args: &[&[u8]]) -> bool {
|
||||||
b"-ge" => integers(args[0], args[2], GreaterEqual),
|
b"-ge" => integers(args[0], args[2], GreaterEqual),
|
||||||
b"-lt" => integers(args[0], args[2], Less),
|
b"-lt" => integers(args[0], args[2], Less),
|
||||||
b"-le" => integers(args[0], args[2], LessEqual),
|
b"-le" => integers(args[0], args[2], LessEqual),
|
||||||
b"-a" => one(args.slice_to(1)) && one(args.slice_from(2)),
|
|
||||||
b"-o" => one(args.slice_to(1)) || one(args.slice_from(2)),
|
|
||||||
_ => match args[0] {
|
_ => match args[0] {
|
||||||
b"!" => !two(args.slice_from(1)),
|
b"!" => !two(args.slice_from(1), error),
|
||||||
_ => false,
|
_ => {
|
||||||
|
*error = true;
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn four(args: &[&[u8]]) -> bool {
|
fn four(args: &[&[u8]], error: &mut bool) -> bool {
|
||||||
let (val, len) = match args[0] {
|
match args[0] {
|
||||||
b"!" => (!three(args.slice_from(1)), 4),
|
b"!" => {
|
||||||
_ => (three(args), 3)
|
!three(args.slice_from(1), error)
|
||||||
};
|
}
|
||||||
if len < args.len() {
|
_ => {
|
||||||
match args[len] {
|
*error = true;
|
||||||
b"-a" => val && dispatch(args.slice_from(len + 1)),
|
false
|
||||||
b"-o" => val || dispatch(args.slice_from(len + 1)),
|
|
||||||
_ => false
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
val
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,16 +146,163 @@ fn isatty(fd: &[u8]) -> bool {
|
||||||
.map(|i| unsafe { isatty(i) == 1 }).unwrap_or(false)
|
.map(|i| unsafe { isatty(i) == 1 }).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(args: &[&[u8]]) -> bool {
|
fn dispatch(args: &mut &[&[u8]], error: &mut bool) -> bool {
|
||||||
match args.len() {
|
let (val, idx) = match args.len() {
|
||||||
0 => false,
|
0 => {
|
||||||
1 => one(args),
|
*error = true;
|
||||||
2 => two(args),
|
(false, 0)
|
||||||
3 => three(args),
|
}
|
||||||
_ => four(args)
|
1 => (one(*args), 1),
|
||||||
|
2 => dispatch_two(args, error),
|
||||||
|
3 => dispatch_three(args, error),
|
||||||
|
_ => dispatch_four(args, error)
|
||||||
|
};
|
||||||
|
*args = (*args).slice_from(idx);
|
||||||
|
val
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_two(args: &mut &[&[u8]], error: &mut bool) -> (bool, uint) {
|
||||||
|
let val = two(*args, error);
|
||||||
|
if *error {
|
||||||
|
*error = false;
|
||||||
|
(one(*args), 1)
|
||||||
|
} else {
|
||||||
|
(val, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dispatch_three(args: &mut &[&[u8]], error: &mut bool) -> (bool, uint) {
|
||||||
|
let val = three(*args, error);
|
||||||
|
if *error {
|
||||||
|
*error = false;
|
||||||
|
dispatch_two(args, error)
|
||||||
|
} else {
|
||||||
|
(val, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_four(args: &mut &[&[u8]], error: &mut bool) -> (bool, uint) {
|
||||||
|
let val = four(*args, error);
|
||||||
|
if *error {
|
||||||
|
*error = false;
|
||||||
|
dispatch_three(args, error)
|
||||||
|
} else {
|
||||||
|
(val, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Precedence {
|
||||||
|
Unknown = 0,
|
||||||
|
Paren, // FIXME: this is useless (parentheses have not been implemented)
|
||||||
|
Or,
|
||||||
|
And,
|
||||||
|
BUnOp,
|
||||||
|
BinOp,
|
||||||
|
UnOp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expr(mut args: &[&[u8]], error: &mut bool) -> bool {
|
||||||
|
if args.len() == 0 {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
let hashmap = setup_hashmap();
|
||||||
|
let lhs = dispatch(&mut args, error);
|
||||||
|
|
||||||
|
if args.len() > 0 {
|
||||||
|
parse_expr_helper(&hashmap, &mut args, lhs, Unknown, error)
|
||||||
|
} else {
|
||||||
|
lhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expr_helper<'a>(hashmap: &HashMap<&'a [u8], Precedence>,
|
||||||
|
args: &mut &[&'a [u8]],
|
||||||
|
mut lhs: bool,
|
||||||
|
min_prec: Precedence,
|
||||||
|
error: &mut bool) -> bool {
|
||||||
|
let mut prec = *hashmap.find(&args[0]).unwrap_or_else(|| {
|
||||||
|
*error = true;
|
||||||
|
&min_prec
|
||||||
|
});
|
||||||
|
while !*error && args.len() > 0 && prec as uint >= min_prec as uint {
|
||||||
|
let op = args[0];
|
||||||
|
*args = (*args).slice_from(1);
|
||||||
|
let mut rhs = dispatch(args, error);
|
||||||
|
while args.len() > 0 {
|
||||||
|
let subprec = *hashmap.find(&args[0]).unwrap_or_else(|| {
|
||||||
|
*error = true;
|
||||||
|
&min_prec
|
||||||
|
});
|
||||||
|
if subprec as uint <= prec as uint || *error {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rhs = parse_expr_helper(hashmap, args, rhs, subprec, error);
|
||||||
|
}
|
||||||
|
lhs = match prec {
|
||||||
|
UnOp | BUnOp => {
|
||||||
|
*error = true;
|
||||||
|
false
|
||||||
|
}
|
||||||
|
And => lhs && rhs,
|
||||||
|
Or => lhs || rhs,
|
||||||
|
BinOp => three(&[if lhs { b" " } else { b"" }, op, if rhs { b" " } else { b"" }], error),
|
||||||
|
Paren => unimplemented!(), // TODO: implement parentheses
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
if args.len() > 0 {
|
||||||
|
prec = *hashmap.find(&args[0]).unwrap_or_else(|| {
|
||||||
|
*error = true;
|
||||||
|
&min_prec
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lhs
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn setup_hashmap<'a>() -> HashMap<&'a [u8], Precedence> {
|
||||||
|
let mut hashmap = HashMap::<&'a [u8], Precedence>::new();
|
||||||
|
|
||||||
|
hashmap.insert(b"-b", UnOp);
|
||||||
|
hashmap.insert(b"-c", UnOp);
|
||||||
|
hashmap.insert(b"-d", UnOp);
|
||||||
|
hashmap.insert(b"-e", UnOp);
|
||||||
|
hashmap.insert(b"-f", UnOp);
|
||||||
|
hashmap.insert(b"-g", UnOp);
|
||||||
|
hashmap.insert(b"-h", UnOp);
|
||||||
|
hashmap.insert(b"-L", UnOp);
|
||||||
|
hashmap.insert(b"-n", UnOp);
|
||||||
|
hashmap.insert(b"-p", UnOp);
|
||||||
|
hashmap.insert(b"-r", UnOp);
|
||||||
|
hashmap.insert(b"-S", UnOp);
|
||||||
|
hashmap.insert(b"-s", UnOp);
|
||||||
|
hashmap.insert(b"-t", UnOp);
|
||||||
|
hashmap.insert(b"-u", UnOp);
|
||||||
|
hashmap.insert(b"-w", UnOp);
|
||||||
|
hashmap.insert(b"-x", UnOp);
|
||||||
|
hashmap.insert(b"-z", UnOp);
|
||||||
|
|
||||||
|
hashmap.insert(b"=", BinOp);
|
||||||
|
hashmap.insert(b"!=", BinOp);
|
||||||
|
hashmap.insert(b"-eq", BinOp);
|
||||||
|
hashmap.insert(b"-ne", BinOp);
|
||||||
|
hashmap.insert(b"-gt", BinOp);
|
||||||
|
hashmap.insert(b"-ge", BinOp);
|
||||||
|
hashmap.insert(b"-lt", BinOp);
|
||||||
|
hashmap.insert(b"-le", BinOp);
|
||||||
|
|
||||||
|
hashmap.insert(b"!", BUnOp);
|
||||||
|
|
||||||
|
hashmap.insert(b"-a", And);
|
||||||
|
hashmap.insert(b"-o", Or);
|
||||||
|
|
||||||
|
hashmap.insert(b"(", Paren);
|
||||||
|
hashmap.insert(b")", Paren);
|
||||||
|
|
||||||
|
hashmap
|
||||||
|
}
|
||||||
|
|
||||||
#[deriving(Eq, PartialEq)]
|
#[deriving(Eq, PartialEq)]
|
||||||
enum PathCondition {
|
enum PathCondition {
|
||||||
BlockSpecial,
|
BlockSpecial,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue