1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 12:37:49 +00:00

Merge pull request #414 from Arcterus/test-fix

test: fix -a and -o
This commit is contained in:
Heather 2014-10-18 10:38:52 +04:00
commit 9c27aac8fe

View file

@ -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,