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

fix build infrastructure ; modernize library use

This patch begins the work of modernizing uutils to work with 1.0-ish
Rust. In particular, it

1. Updates to the latest submodules.

2. Convert mkmain.rs, mkuutils.rs, and src/uutils/uutils.rs
   to new slice syntax and use of new io, fs, and path APIs.

3. Convert src/common/util.rs to new io, fs, and path APIs.

4. Convert fmt to use new APIs.
This commit is contained in:
kwantam 2015-04-16 00:59:33 -04:00
parent e526de0079
commit ecf248c5e3
13 changed files with 102 additions and 109 deletions

2
.gitmodules vendored
View file

@ -1,6 +1,6 @@
[submodule "deps/rust-crypto"] [submodule "deps/rust-crypto"]
path = deps/rust-crypto path = deps/rust-crypto
url = git://github.com/DaGenix/rust-crypto.git url = https://github.com/DaGenix/rust-crypto
[submodule "deps/time"] [submodule "deps/time"]
path = deps/time path = deps/time
url = https://github.com/rust-lang/time url = https://github.com/rust-lang/time

View file

@ -266,6 +266,3 @@ path = "whoami/whoami.rs"
[[bin]] [[bin]]
name = "yes" name = "yes"
path = "yes/yes.rs" path = "yes/yes.rs"
[dependencies.rust-crypto]
git = "https://github.com/dagenix/rust-crypto"

View file

@ -259,7 +259,7 @@ $(BUILDDIR)/stdbuf: $(BUILDDIR)/libstdbuf.$(DYLIB_EXT)
$(BUILDDIR)/.rust-crypto: | $(BUILDDIR) $(BUILDDIR)/.rust-crypto: | $(BUILDDIR)
cd $(BASEDIR)/deps/rust-crypto && $(CARGO) build --release cd $(BASEDIR)/deps/rust-crypto && $(CARGO) build --release
cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/librand*.rlib $(BUILDDIR)/librand.rlib cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/librand*.rlib $(BUILDDIR)/librand.rlib
cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/librustc-serialize*.rlib $(BUILDDIR)/librustc-serialize.rlib cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/librustc_serialize*.rlib $(BUILDDIR)/librustc-serialize.rlib
cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/libtime*.rlib $(BUILDDIR)/libtime.rlib cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/libtime*.rlib $(BUILDDIR)/libtime.rlib
cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/liblibc*.rlib $(BUILDDIR)/liblibc.rlib cp -r $(BASEDIR)/deps/rust-crypto/target/release/deps/liblibc*.rlib $(BUILDDIR)/liblibc.rlib
cp -r $(BASEDIR)/deps/rust-crypto/target/release/libcrypto*.rlib $(BUILDDIR)/libcrypto.rlib cp -r $(BASEDIR)/deps/rust-crypto/target/release/libcrypto*.rlib $(BUILDDIR)/libcrypto.rlib

2
deps/regex vendored

@ -1 +1 @@
Subproject commit b8cc898f17442e5769cbce081d884e47d28c54e5 Subproject commit 399758aeae3dcab382b0af5fa9964c1e32066dda

2
deps/rust-crypto vendored

@ -1 +1 @@
Subproject commit e2ba6ea926782278222558557d3d87221b87c740 Subproject commit 5571cb41690b9cee12025192393ea7df0eddc21b

2
deps/time vendored

@ -1 +1 @@
Subproject commit e216d0de7377a1ae5c8617f6e1a9f60dc61d7ec7 Subproject commit a7869dcee07de6df4e81b48bdfe137c70c153643

View file

@ -1,11 +1,11 @@
#![feature(core, exit_status, old_io, old_path)] #![feature(exit_status)]
use std::env; use std::env;
use std::old_io::{File, Truncate, ReadWrite}; use std::io::Write;
use std::old_path::Path; use std::fs::File;
static TEMPLATE: &'static str = "\ static TEMPLATE: &'static str = "\
#![feature(exit_status)] #![feature(exit_status)]
extern crate \"@UTIL_CRATE@\" as uu@UTIL_CRATE@; extern crate @UTIL_CRATE@ as uu@UTIL_CRATE@;
use std::env; use std::env;
use uu@UTIL_CRATE@::uumain; use uu@UTIL_CRATE@::uumain;
@ -23,14 +23,15 @@ fn main() {
return; return;
} }
let crat = args[1].as_slice(); let crat = &args[1][..];
let outfile = args[2].as_slice(); let outfile = &args[2][..];
let main = TEMPLATE.replace("@UTIL_CRATE@", crat); let main = TEMPLATE.replace("@UTIL_CRATE@", crat);
let mut out = File::open_mode(&Path::new(outfile), Truncate, ReadWrite); match File::create(outfile) {
Ok(mut out) => match out.write_all(main.as_bytes()) {
match out.write_all(main.as_bytes()) { Err(e) => panic!("{}", e),
_ => (),
},
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
_ => (),
} }
} }

View file

@ -1,8 +1,8 @@
#![feature(core, exit_status, old_io, old_path)] #![feature(exit_status)]
use std::env; use std::env;
use std::old_io::{File, Truncate, Write}; use std::fs::File;
use std::old_path::Path; use std::io::{Read, Write};
fn main() { fn main() {
let args : Vec<String> = env::args().collect(); let args : Vec<String> = env::args().collect();
@ -16,7 +16,7 @@ fn main() {
let mut util_map = String::new(); let mut util_map = String::new();
let mut hashsum = false; let mut hashsum = false;
for prog in args[2..].iter() { for prog in args[2..].iter() {
match prog.as_slice() { match &prog[..] {
"hashsum" | "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" => { "hashsum" | "md5sum" | "sha1sum" | "sha224sum" | "sha256sum" | "sha384sum" | "sha512sum" => {
if !hashsum { if !hashsum {
crates.push_str("extern crate hashsum;\n"); crates.push_str("extern crate hashsum;\n");
@ -33,18 +33,22 @@ fn main() {
"true" => util_map.push_str("fn uutrue(_: Vec<String>) -> i32 { 0 }\nmap.insert(\"true\", uutrue);\n"), "true" => util_map.push_str("fn uutrue(_: Vec<String>) -> i32 { 0 }\nmap.insert(\"true\", uutrue);\n"),
"false" => util_map.push_str("fn uufalse(_: Vec<String>) -> i32 { 1 }\nmap.insert(\"false\", uufalse);\n"), "false" => util_map.push_str("fn uufalse(_: Vec<String>) -> i32 { 1 }\nmap.insert(\"false\", uufalse);\n"),
_ => { _ => {
crates.push_str(format!("extern crate \"{0}\" as uu{0};\n", prog).as_slice()); crates.push_str(&(format!("extern crate {0} as uu{0};\n", prog))[..]);
util_map.push_str(format!("map.insert(\"{prog}\", uu{prog}::uumain as fn(Vec<String>) -> i32);\n", prog = prog).as_slice()); util_map.push_str(&(format!("map.insert(\"{prog}\", uu{prog}::uumain as fn(Vec<String>) -> i32);\n", prog = prog))[..]);
} }
} }
} }
let outfile = args[1].as_slice(); let outfile = &(args[1])[..];
// XXX: this all just assumes that the IO works correctly // XXX: this all just assumes that the IO works correctly
let mut out = File::open_mode(&Path::new(outfile), Truncate, Write).unwrap(); let mut out = File::create(outfile).unwrap();
let mut input = File::open(&Path::new("src/uutils/uutils.rs")).unwrap(); let mut input = File::open("src/uutils/uutils.rs").unwrap();
let main = input.read_to_string().unwrap().replace("@CRATES@", crates.as_slice()).replace("@UTIL_MAP@", util_map.as_slice());
let mut template = String::new();
input.read_to_string(&mut template).unwrap();
let template = template;
let main = template.replace("@CRATES@", &crates[..]).replace("@UTIL_MAP@", &util_map[..]);
match out.write_all(main.as_bytes()) { match out.write_all(main.as_bytes()) {
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
_ => (), _ => (),

View file

@ -11,35 +11,35 @@ extern crate libc;
macro_rules! show_error( macro_rules! show_error(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::old_io::stderr(), "{}: error: ", ::NAME); pipe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
pipe_writeln!(&mut ::std::old_io::stderr(), $($args)+); pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
}) })
); );
#[macro_export] #[macro_export]
macro_rules! show_warning( macro_rules! show_warning(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::old_io::stderr(), "{}: warning: ", ::NAME); pipe_write!(&mut ::std::io::stderr(), "{}: warning: ", ::NAME);
pipe_writeln!(&mut ::std::old_io::stderr(), $($args)+); pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
}) })
); );
#[macro_export] #[macro_export]
macro_rules! show_info( macro_rules! show_info(
($($args:tt)+) => ({ ($($args:tt)+) => ({
pipe_write!(&mut ::std::old_io::stderr(), "{}: ", ::NAME); pipe_write!(&mut ::std::io::stderr(), "{}: ", ::NAME);
pipe_writeln!(&mut ::std::old_io::stderr(), $($args)+); pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
}) })
); );
#[macro_export] #[macro_export]
macro_rules! eprint( macro_rules! eprint(
($($args:tt)+) => (pipe_write!(&mut ::std::old_io::stderr(), $($args)+)) ($($args:tt)+) => (pipe_write!(&mut ::std::io::stderr(), $($args)+))
); );
#[macro_export] #[macro_export]
macro_rules! eprintln( macro_rules! eprintln(
($($args:tt)+) => (pipe_writeln!(&mut ::std::old_io::stderr(), $($args)+)) ($($args:tt)+) => (pipe_writeln!(&mut ::std::io::stderr(), $($args)+))
); );
#[macro_export] #[macro_export]
@ -85,10 +85,10 @@ macro_rules! return_if_err(
#[macro_export] #[macro_export]
macro_rules! pipe_print( macro_rules! pipe_print(
($($args:tt)+) => ( ($($args:tt)+) => (
match write!(&mut ::std::old_io::stdout(), $($args)+) { match write!(&mut ::std::io::stdout(), $($args)+) {
Ok(_) => true, Ok(_) => true,
Err(f) => { Err(f) => {
if f.kind == ::std::old_io::BrokenPipe { if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false false
} else { } else {
panic!("{}", f) panic!("{}", f)
@ -101,10 +101,10 @@ macro_rules! pipe_print(
#[macro_export] #[macro_export]
macro_rules! pipe_println( macro_rules! pipe_println(
($($args:tt)+) => ( ($($args:tt)+) => (
match writeln!(&mut ::std::old_io::stdout(), $($args)+) { match writeln!(&mut ::std::io::stdout(), $($args)+) {
Ok(_) => true, Ok(_) => true,
Err(f) => { Err(f) => {
if f.kind == ::std::old_io::BrokenPipe { if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false false
} else { } else {
panic!("{}", f) panic!("{}", f)
@ -120,7 +120,7 @@ macro_rules! pipe_write(
match write!($fd, $($args)+) { match write!($fd, $($args)+) {
Ok(_) => true, Ok(_) => true,
Err(f) => { Err(f) => {
if f.kind == ::std::old_io::BrokenPipe { if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false false
} else { } else {
panic!("{}", f) panic!("{}", f)
@ -136,7 +136,7 @@ macro_rules! pipe_writeln(
match writeln!($fd, $($args)+) { match writeln!($fd, $($args)+) {
Ok(_) => true, Ok(_) => true,
Err(f) => { Err(f) => {
if f.kind == ::std::old_io::BrokenPipe { if f.kind() == ::std::io::ErrorKind::BrokenPipe {
false false
} else { } else {
panic!("{}", f) panic!("{}", f)

View file

@ -1,5 +1,4 @@
#![crate_name = "fmt"] #![crate_name = "fmt"]
#![allow(unstable)]
/* /*
* This file is part of `fmt` from the uutils coreutils package. * This file is part of `fmt` from the uutils coreutils package.
@ -10,15 +9,16 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
#![feature(box_syntax)] #![feature(box_syntax,core,rustc_private,collections,str_char,unicode,str_words)]
extern crate core; extern crate core;
extern crate getopts; extern crate getopts;
extern crate unicode; extern crate unicode;
use std::cmp; use std::cmp;
use std::old_io::{BufferedReader, BufferedWriter, File, IoResult}; use std::io::{Read, BufReader, BufWriter};
use std::old_io::stdio::{stdin_raw, stdout_raw}; use std::fs::File;
use std::io::{stdin, stdout, Write};
use linebreak::break_lines; use linebreak::break_lines;
use parasplit::ParagraphStream; use parasplit::ParagraphStream;
@ -41,7 +41,8 @@ mod parasplit;
static NAME: &'static str = "fmt"; static NAME: &'static str = "fmt";
static VERSION: &'static str = "0.0.3"; static VERSION: &'static str = "0.0.3";
struct FmtOptions { pub type FileOrStdReader = BufReader<Box<Read+'static>>;
pub struct FmtOptions {
crown : bool, crown : bool,
tagged : bool, tagged : bool,
mail : bool, mail : bool,
@ -85,13 +86,13 @@ pub fn uumain(args: Vec<String>) -> i32 {
getopts::optflag("h", "help", "Display this help message and exit.") getopts::optflag("h", "help", "Display this help message and exit.")
]; ];
let matches = match getopts::getopts(args.tail(), opts.as_slice()) { let matches = match getopts::getopts(args.tail(), &opts[..]) {
Ok(m) => m, Ok(m) => m,
Err(f) => crash!(1, "{}\nTry `{} --help' for more information.", f, args[0]) Err(f) => crash!(1, "{}\nTry `{} --help' for more information.", f, args[0])
}; };
if matches.opt_present("h") { if matches.opt_present("h") {
print_usage(args[0].as_slice(), opts.as_slice(), ""); print_usage(&(args[0])[..], &opts[..], "");
} }
if matches.opt_present("V") || matches.opt_present("h") { if matches.opt_present("V") || matches.opt_present("h") {
@ -193,18 +194,20 @@ pub fn uumain(args: Vec<String>) -> i32 {
files.push("-".to_string()); files.push("-".to_string());
} }
let mut ostream = box BufferedWriter::new(stdout_raw()) as Box<Writer>; let mut ostream = BufWriter::new(stdout());
for i in files.iter().map(|x| x.as_slice()) { for i in files.iter().map(|x| &x[..]) {
let mut fp = let mut fp = match i {
match open_file(i) { "-" => BufReader::new(box stdin() as Box<Read+'static>),
_ => match File::open(i) {
Ok(f) => BufReader::new(box f as Box<Read+'static>),
Err(e) => { Err(e) => {
show_warning!("{}: {}", i, e); show_warning!("{}: {}", i, e);
continue; continue;
} },
Ok(f) => f },
}; };
let mut p_stream = ParagraphStream::new(&fmt_opts, &mut fp); let p_stream = ParagraphStream::new(&fmt_opts, &mut fp);
for para_result in p_stream { for para_result in p_stream {
match para_result { match para_result {
Err(s) => silent_unwrap!(ostream.write_all(s.as_bytes())), Err(s) => silent_unwrap!(ostream.write_all(s.as_bytes())),
@ -222,18 +225,3 @@ pub fn uumain(args: Vec<String>) -> i32 {
fn print_usage(arg0: &str, opts: &[getopts::OptGroup], errmsg: &str) { fn print_usage(arg0: &str, opts: &[getopts::OptGroup], errmsg: &str) {
println!("Usage: {} [OPTION]... [FILE]...\n\n{}{}", arg0, getopts::usage("Reformat paragraphs from input files (or stdin) to stdout.", opts), errmsg); println!("Usage: {} [OPTION]... [FILE]...\n\n{}{}", arg0, getopts::usage("Reformat paragraphs from input files (or stdin) to stdout.", opts), errmsg);
} }
// uniform interface for opening files
// since we don't need seeking
type FileOrStdReader = BufferedReader<Box<Reader+'static>>;
fn open_file(filename: &str) -> IoResult<FileOrStdReader> {
if filename == "-" {
Ok(BufferedReader::new(box stdin_raw() as Box<Reader>))
} else {
match File::open(&Path::new(filename)) {
Ok(f) => Ok(BufferedReader::new(box f as Box<Reader>)),
Err(e) => return Err(e)
}
}
}

View file

@ -9,6 +9,7 @@
use FmtOptions; use FmtOptions;
use parasplit::{Paragraph, ParaWords, WordInfo}; use parasplit::{Paragraph, ParaWords, WordInfo};
use std::io::{Write, BufWriter, Stdout};
use std::num::{Float, Int, SignedInt}; use std::num::{Float, Int, SignedInt};
use std::i64; use std::i64;
use std::cmp; use std::cmp;
@ -20,7 +21,7 @@ struct BreakArgs<'a> {
indent_str : &'a str, indent_str : &'a str,
indent_len : usize, indent_len : usize,
uniform : bool, uniform : bool,
ostream : &'a mut Box<Writer+'static> ostream : &'a mut BufWriter<Stdout>
} }
impl<'a> BreakArgs<'a> { impl<'a> BreakArgs<'a> {
@ -38,9 +39,9 @@ impl<'a> BreakArgs<'a> {
} }
} }
pub fn break_lines(para: &Paragraph, opts: &FmtOptions, ostream: &mut Box<Writer+'static>) { pub fn break_lines(para: &Paragraph, opts: &FmtOptions, ostream: &mut BufWriter<Stdout>) {
// indent // indent
let p_indent = para.indent_str.as_slice(); let p_indent = &para.indent_str[..];
let p_indent_len = para.indent_len; let p_indent_len = para.indent_len;
// words // words
@ -52,7 +53,7 @@ pub fn break_lines(para: &Paragraph, opts: &FmtOptions, ostream: &mut Box<Writer
let (w, w_len) = match p_words_words.next() { let (w, w_len) = match p_words_words.next() {
Some(winfo) => (winfo.word, winfo.word_nchars), Some(winfo) => (winfo.word, winfo.word_nchars),
None => { None => {
silent_unwrap!(ostream.write_char('\n')); silent_unwrap!(ostream.write_all("\n".as_bytes()));
return; return;
} }
}; };
@ -79,7 +80,7 @@ pub fn break_lines(para: &Paragraph, opts: &FmtOptions, ostream: &mut Box<Writer
let mut break_args = BreakArgs { let mut break_args = BreakArgs {
opts : opts, opts : opts,
init_len : p_init_len, init_len : p_init_len,
indent_str : p_indent, indent_str : &p_indent[..],
indent_len : p_indent_len, indent_len : p_indent_len,
uniform : uniform, uniform : uniform,
ostream : ostream ostream : ostream
@ -96,7 +97,7 @@ pub fn break_lines(para: &Paragraph, opts: &FmtOptions, ostream: &mut Box<Writer
// maxlength would be exceeded, then print a linebreak and indent and continue. // maxlength would be exceeded, then print a linebreak and indent and continue.
fn break_simple<'a, T: Iterator<Item=&'a WordInfo<'a>>>(iter: T, args: &mut BreakArgs<'a>) { fn break_simple<'a, T: Iterator<Item=&'a WordInfo<'a>>>(iter: T, args: &mut BreakArgs<'a>) {
iter.fold((args.init_len, false), |l, winfo| accum_words_simple(args, l, winfo)); iter.fold((args.init_len, false), |l, winfo| accum_words_simple(args, l, winfo));
silent_unwrap!(args.ostream.write_char('\n')); silent_unwrap!(args.ostream.write_all("\n".as_bytes()));
} }
#[inline(always)] #[inline(always)]
@ -131,7 +132,7 @@ fn break_knuth_plass<'a, T: Clone + Iterator<Item=&'a WordInfo<'a>>>(mut iter: T
write_newline(args.indent_str, args.ostream); write_newline(args.indent_str, args.ostream);
} }
// at each breakpoint, keep emitting words until we find the word matching this breakpoint // at each breakpoint, keep emitting words until we find the word matching this breakpoint
for winfo in iter { for winfo in &mut iter {
let (slen, word) = slice_if_fresh(fresh, winfo.word, winfo.word_start, args.uniform, let (slen, word) = slice_if_fresh(fresh, winfo.word, winfo.word_start, args.uniform,
winfo.new_line, winfo.sentence_start, prev_punct); winfo.new_line, winfo.sentence_start, prev_punct);
fresh = false; fresh = false;
@ -170,7 +171,7 @@ fn break_knuth_plass<'a, T: Clone + Iterator<Item=&'a WordInfo<'a>>>(mut iter: T
fresh = false; fresh = false;
write_with_spaces(word, slen, args.ostream); write_with_spaces(word, slen, args.ostream);
} }
silent_unwrap!(args.ostream.write_char('\n')); silent_unwrap!(args.ostream.write_all("\n".as_bytes()));
} }
struct LineBreak<'a> { struct LineBreak<'a> {
@ -435,18 +436,18 @@ fn slice_if_fresh<'a>(fresh: bool, word: &'a str, start: usize, uniform: bool, n
// Write a newline and add the indent. // Write a newline and add the indent.
#[inline(always)] #[inline(always)]
fn write_newline(indent: &str, ostream: &mut Box<Writer>) { fn write_newline(indent: &str, ostream: &mut BufWriter<Stdout>) {
silent_unwrap!(ostream.write_char('\n')); silent_unwrap!(ostream.write_all("\n".as_bytes()));
silent_unwrap!(ostream.write_all(indent.as_bytes())); silent_unwrap!(ostream.write_all(indent.as_bytes()));
} }
// Write the word, along with slen spaces. // Write the word, along with slen spaces.
#[inline(always)] #[inline(always)]
fn write_with_spaces(word: &str, slen: usize, ostream: &mut Box<Writer>) { fn write_with_spaces(word: &str, slen: usize, ostream: &mut BufWriter<Stdout>) {
if slen == 2 { if slen == 2 {
silent_unwrap!(ostream.write_all(" ".as_bytes())); silent_unwrap!(ostream.write_all(" ".as_bytes()));
} else if slen == 1 { } else if slen == 1 {
silent_unwrap!(ostream.write_char(' ')); silent_unwrap!(ostream.write_all(" ".as_bytes()));
} }
silent_unwrap!(ostream.write_all(word.as_bytes())); silent_unwrap!(ostream.write_all(word.as_bytes()));
} }

View file

@ -8,7 +8,7 @@
*/ */
use core::iter::Peekable; use core::iter::Peekable;
use std::old_io::Lines; use std::io::{BufRead, Lines};
use std::slice::Iter; use std::slice::Iter;
use std::str::CharRange; use std::str::CharRange;
use unicode::str::UnicodeStr; use unicode::str::UnicodeStr;
@ -69,11 +69,11 @@ struct FileLine {
// iterator that produces a stream of Lines from a file // iterator that produces a stream of Lines from a file
pub struct FileLines<'a> { pub struct FileLines<'a> {
opts : &'a FmtOptions, opts : &'a FmtOptions,
lines : Lines<'a, FileOrStdReader>, lines : Lines<&'a mut FileOrStdReader>,
} }
impl<'a> FileLines<'a> { impl<'a> FileLines<'a> {
fn new<'b>(opts: &'b FmtOptions, lines: Lines<'b, FileOrStdReader>) -> FileLines<'b> { fn new<'b>(opts: &'b FmtOptions, lines: Lines<&'b mut FileOrStdReader>) -> FileLines<'b> {
FileLines { opts: opts, lines: lines } FileLines { opts: opts, lines: lines }
} }
@ -81,14 +81,14 @@ impl<'a> FileLines<'a> {
fn match_prefix(&self, line: &str) -> (bool, usize) { fn match_prefix(&self, line: &str) -> (bool, usize) {
if !self.opts.use_prefix { return (true, 0); } if !self.opts.use_prefix { return (true, 0); }
FileLines::match_prefix_generic(self.opts.prefix.as_slice(), line, self.opts.xprefix) FileLines::match_prefix_generic(&self.opts.prefix[..], line, self.opts.xprefix)
} }
// returns true if this line should be formatted // returns true if this line should be formatted
fn match_anti_prefix(&self, line: &str) -> bool { fn match_anti_prefix(&self, line: &str) -> bool {
if !self.opts.use_anti_prefix { return true; } if !self.opts.use_anti_prefix { return true; }
match FileLines::match_prefix_generic(self.opts.anti_prefix.as_slice(), line, self.opts.xanti_prefix) { match FileLines::match_prefix_generic(&self.opts.anti_prefix[..], line, self.opts.xanti_prefix) {
(true, _) => false, (true, _) => false,
(_ , _) => true (_ , _) => true
} }
@ -156,16 +156,16 @@ impl<'a> Iterator for FileLines<'a> {
// emit a blank line // emit a blank line
// Err(true) indicates that this was a linebreak, // Err(true) indicates that this was a linebreak,
// which is important to know when detecting mail headers // which is important to know when detecting mail headers
if n.as_slice().is_whitespace() { if n.is_whitespace() {
return Some(Line::NoFormatLine("\n".to_string(), true)); return Some(Line::NoFormatLine("\n".to_string(), true));
} }
// if this line does not match the prefix, // if this line does not match the prefix,
// emit the line unprocessed and iterate again // emit the line unprocessed and iterate again
let (pmatch, poffset) = self.match_prefix(n.as_slice()); let (pmatch, poffset) = self.match_prefix(&n[..]);
if !pmatch { if !pmatch {
return Some(Line::NoFormatLine(n, false)); return Some(Line::NoFormatLine(n, false));
} else if n.as_slice()[poffset + self.opts.prefix.len()..].is_whitespace() { } else if n[poffset + self.opts.prefix.len()..].is_whitespace() {
// if the line matches the prefix, but is blank after, // if the line matches the prefix, but is blank after,
// don't allow lines to be combined through it (that is, // don't allow lines to be combined through it (that is,
// treat it like a blank line, except that since it's // treat it like a blank line, except that since it's
@ -176,13 +176,13 @@ impl<'a> Iterator for FileLines<'a> {
// skip if this line matches the anti_prefix // skip if this line matches the anti_prefix
// (NOTE definition of match_anti_prefix is TRUE if we should process) // (NOTE definition of match_anti_prefix is TRUE if we should process)
if !self.match_anti_prefix(n.as_slice()) { if !self.match_anti_prefix(&n[..]) {
return Some(Line::NoFormatLine(n, false)); return Some(Line::NoFormatLine(n, false));
} }
// figure out the indent, prefix, and prefixindent ending points // figure out the indent, prefix, and prefixindent ending points
let prefix_end = poffset + self.opts.prefix.len(); let prefix_end = poffset + self.opts.prefix.len();
let (indent_end, prefix_len, indent_len) = self.compute_indent(n.as_slice(), prefix_end); let (indent_end, prefix_len, indent_len) = self.compute_indent(&n[..], prefix_end);
Some(Line::FormatLine(FileLine { Some(Line::FormatLine(FileLine {
line : n, line : n,
@ -233,7 +233,7 @@ impl<'a> ParagraphStream<'a> {
if line.indent_end > 0 { if line.indent_end > 0 {
false false
} else { } else {
let l_slice = line.line.as_slice(); let l_slice = &line.line[..];
if l_slice.starts_with("From ") { if l_slice.starts_with("From ") {
true true
} else { } else {
@ -314,7 +314,7 @@ impl<'a> Iterator for ParagraphStream<'a> {
indent_len = 2; indent_len = 2;
} else { } else {
if self.opts.crown || self.opts.tagged { if self.opts.crown || self.opts.tagged {
init_str.push_str(&fl.line.as_slice()[..fl.indent_end]); init_str.push_str(&fl.line[..fl.indent_end]);
init_len = fl.indent_len; init_len = fl.indent_len;
init_end = fl.indent_end; init_end = fl.indent_end;
} else { } else {
@ -324,7 +324,7 @@ impl<'a> Iterator for ParagraphStream<'a> {
// these will be overwritten in the 2nd line of crown or tagged mode, but // these will be overwritten in the 2nd line of crown or tagged mode, but
// we are not guaranteed to get to the 2nd line, e.g., if the next line // we are not guaranteed to get to the 2nd line, e.g., if the next line
// is a NoFormatLine or None. Thus, we set sane defaults the 1st time around // is a NoFormatLine or None. Thus, we set sane defaults the 1st time around
indent_str.push_str(&fl.line.as_slice()[..fl.indent_end]); indent_str.push_str(&fl.line[..fl.indent_end]);
indent_len = fl.indent_len; indent_len = fl.indent_len;
indent_end = fl.indent_end; indent_end = fl.indent_end;
@ -358,7 +358,7 @@ impl<'a> Iterator for ParagraphStream<'a> {
} else { } else {
// this is part of the same paragraph, get the indent info from this line // this is part of the same paragraph, get the indent info from this line
indent_str.clear(); indent_str.clear();
indent_str.push_str(&fl.line.as_slice()[..fl.indent_end]); indent_str.push_str(&fl.line[..fl.indent_end]);
indent_len = fl.indent_len; indent_len = fl.indent_len;
indent_end = fl.indent_end; indent_end = fl.indent_end;
} }
@ -415,7 +415,7 @@ impl<'a> ParaWords<'a> {
// no extra spacing for mail headers; always exactly 1 space // no extra spacing for mail headers; always exactly 1 space
// safe to trim_left on every line of a mail header, since the // safe to trim_left on every line of a mail header, since the
// first line is guaranteed not to have any spaces // first line is guaranteed not to have any spaces
self.words.extend(self.para.lines.iter().flat_map(|x| StrExt::words(x.as_slice())).map(|x| WordInfo { self.words.extend(self.para.lines.iter().flat_map(|x| x.words()).map(|x| WordInfo {
word : x, word : x,
word_start : 0, word_start : 0,
word_nchars : x.len(), // OK for mail headers; only ASCII allowed (unicode is escaped) word_nchars : x.len(), // OK for mail headers; only ASCII allowed (unicode is escaped)
@ -430,17 +430,17 @@ impl<'a> ParaWords<'a> {
self.words.extend( self.words.extend(
if self.opts.crown || self.opts.tagged { if self.opts.crown || self.opts.tagged {
// crown and tagged mode has the "init" in the first line, so slice from there // crown and tagged mode has the "init" in the first line, so slice from there
WordSplit::new(self.opts, &self.para.lines[0].as_slice()[self.para.init_end..]) WordSplit::new(self.opts, &self.para.lines[0][self.para.init_end..])
} else { } else {
// otherwise we slice from the indent // otherwise we slice from the indent
WordSplit::new(self.opts, &self.para.lines[0].as_slice()[self.para.indent_end..]) WordSplit::new(self.opts, &self.para.lines[0][self.para.indent_end..])
}); });
if self.para.lines.len() > 1 { if self.para.lines.len() > 1 {
let indent_end = self.para.indent_end; let indent_end = self.para.indent_end;
let opts = self.opts; let opts = self.opts;
self.words.extend( self.words.extend(
self.para.lines.iter().skip(1).flat_map(|x| WordSplit::new(opts, &x.as_slice()[indent_end..]))); self.para.lines.iter().skip(1).flat_map(|x| WordSplit::new(opts, &x[indent_end..])));
} }
} }
} }
@ -485,7 +485,7 @@ impl<'a> WordSplit<'a> {
impl<'a> WordSplit<'a> { impl<'a> WordSplit<'a> {
fn new<'b>(opts: &'b FmtOptions, string: &'b str) -> WordSplit<'b> { fn new<'b>(opts: &'b FmtOptions, string: &'b str) -> WordSplit<'b> {
// wordsplits *must* start at a non-whitespace character // wordsplits *must* start at a non-whitespace character
let trim_string = StrExt::trim_left(string); let trim_string = string.trim_left();
WordSplit { opts: opts, string: trim_string, length: string.len(), position: 0, prev_punct: false } WordSplit { opts: opts, string: trim_string, length: string.len(), position: 0, prev_punct: false }
} }

View file

@ -1,5 +1,5 @@
#![crate_name = "uutils"] #![crate_name = "uutils"]
#![feature(core, exit_status, old_path, rustc_private)] #![feature(exit_status, rustc_private)]
/* /*
* This file is part of the uutils coreutils package. * This file is part of the uutils coreutils package.
@ -16,6 +16,7 @@ extern crate getopts;
use std::env; use std::env;
use std::collections::hash_map::HashMap; use std::collections::hash_map::HashMap;
use std::path::Path;
static NAME: &'static str = "uutils"; static NAME: &'static str = "uutils";
static VERSION: &'static str = "1.0.0"; static VERSION: &'static str = "1.0.0";
@ -44,8 +45,9 @@ fn main() {
let mut args : Vec<String> = env::args().collect(); let mut args : Vec<String> = env::args().collect();
// try binary name as util name. // try binary name as util name.
let binary = Path::new(args[0].as_slice()); let args0 = args[0].clone();
let binary_as_util = binary.filename_str().unwrap(); let binary = Path::new(&args0[..]);
let binary_as_util = binary.file_name().unwrap().to_str().unwrap();
match umap.get(binary_as_util) { match umap.get(binary_as_util) {
Some(&uumain) => { Some(&uumain) => {
@ -69,7 +71,7 @@ fn main() {
// try first arg as util name. // try first arg as util name.
if args.len() >= 2 { if args.len() >= 2 {
args.remove(0); args.remove(0);
let util = args[0].as_slice(); let util = &args[0][..];
match umap.get(util) { match umap.get(util) {
Some(&uumain) => { Some(&uumain) => {
@ -77,10 +79,10 @@ fn main() {
return return
} }
None => { None => {
if args[0].as_slice() == "--help" { if &args[0][..] == "--help" {
// see if they want help on a specific util // see if they want help on a specific util
if args.len() >= 2 { if args.len() >= 2 {
let util = args[1].as_slice(); let util = &args[1][..];
match umap.get(util) { match umap.get(util) {
Some(&uumain) => { Some(&uumain) => {
env::set_exit_status(uumain(vec![util.to_string(), "--help".to_string()])); env::set_exit_status(uumain(vec![util.to_string(), "--help".to_string()]));