diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs new file mode 100644 index 000000000000..0906d358badd --- /dev/null +++ b/src/librustc_driver/args.rs @@ -0,0 +1,53 @@ +use std::error; +use std::fmt; +use std::fs; +use std::io; +use std::str; +use std::sync::atomic::{AtomicBool, Ordering}; + +static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); + +pub fn used_unstable_argsfile() -> bool { + USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) +} + +pub fn arg_expand(arg: String) -> Result, Error> { + if arg.starts_with("@") { + let path = &arg[1..]; + let file = match fs::read_to_string(path) { + Ok(file) => { + USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); + file + } + Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { + return Err(Error::Utf8Error(Some(path.to_string()))); + } + Err(err) => return Err(Error::IOError(path.to_string(), err)), + }; + Ok(file.lines().map(ToString::to_string).collect()) + } else { + Ok(vec![arg]) + } +} + +#[derive(Debug)] +pub enum Error { + Utf8Error(Option), + IOError(String, io::Error), +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Utf8Error(None) => write!(fmt, "Utf8 error"), + Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), + Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &'static str { + "argument error" + } +} diff --git a/src/librustc_driver/args/mod.rs b/src/librustc_driver/args/mod.rs deleted file mode 100644 index a59f9afd8beb..000000000000 --- a/src/librustc_driver/args/mod.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::env; -use std::error; -use std::fmt; -use std::fs; -use std::io; -use std::str; -use std::sync::atomic::{AtomicBool, Ordering}; - -#[cfg(test)] -mod tests; - -static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); - -pub fn used_unstable_argsfile() -> bool { - USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) -} - -pub struct ArgsIter { - base: env::ArgsOs, - file: std::vec::IntoIter, -} - -impl ArgsIter { - pub fn new() -> Self { - ArgsIter { base: env::args_os(), file: vec![].into_iter() } - } -} - -impl Iterator for ArgsIter { - type Item = Result; - - fn next(&mut self) -> Option { - loop { - if let Some(line) = self.file.next() { - return Some(Ok(line)); - } - - let arg = - self.base.next().map(|arg| arg.into_string().map_err(|_| Error::Utf8Error(None))); - match arg { - Some(Err(err)) => return Some(Err(err)), - Some(Ok(ref arg)) if arg.starts_with("@") => { - let path = &arg[1..]; - let file = match fs::read_to_string(path) { - Ok(file) => { - USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); - file - } - Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { - return Some(Err(Error::Utf8Error(Some(path.to_string())))); - } - Err(err) => return Some(Err(Error::IOError(path.to_string(), err))), - }; - self.file = - file.lines().map(ToString::to_string).collect::>().into_iter(); - } - Some(Ok(arg)) => return Some(Ok(arg)), - None => return None, - } - } - } -} - -#[derive(Debug)] -pub enum Error { - Utf8Error(Option), - IOError(String, io::Error), -} - -impl fmt::Display for Error { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Error::Utf8Error(None) => write!(fmt, "Utf8 error"), - Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), - Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), - } - } -} - -impl error::Error for Error { - fn description(&self) -> &'static str { - "argument error" - } -} diff --git a/src/librustc_driver/args/tests.rs b/src/librustc_driver/args/tests.rs deleted file mode 100644 index 080dd5cb746c..000000000000 --- a/src/librustc_driver/args/tests.rs +++ /dev/null @@ -1,145 +0,0 @@ -use super::*; - -use std::str; - -fn want_args(v: impl IntoIterator) -> Vec { - v.into_iter().map(String::from).collect() -} - -fn got_args(file: &[u8]) -> Result, Error> { - let ret = str::from_utf8(file) - .map_err(|_| Error::Utf8Error(None))? - .lines() - .map(ToString::to_string) - .collect::>(); - Ok(ret) -} - -#[test] -fn nothing() { - let file = b""; - - assert_eq!(got_args(file).unwrap(), want_args(vec![])); -} - -#[test] -fn empty() { - let file = b"\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec![""])); -} - -#[test] -fn simple() { - let file = b"foo"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); -} - -#[test] -fn simple_eol() { - let file = b"foo\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); -} - -#[test] -fn multi() { - let file = b"foo\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_eol() { - let file = b"foo\nbar\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_empty() { - let file = b"foo\n\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_eol() { - let file = b"foo\n\nbar\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_start() { - let file = b"\nfoo\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); -} - -#[test] -fn multi_empty_end() { - let file = b"foo\nbar\n\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); -} - -#[test] -fn simple_eol_crlf() { - let file = b"foo\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); -} - -#[test] -fn multi_crlf() { - let file = b"foo\r\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_eol_crlf() { - let file = b"foo\r\nbar\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); -} - -#[test] -fn multi_empty_crlf() { - let file = b"foo\r\n\r\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_eol_crlf() { - let file = b"foo\r\n\r\nbar\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); -} - -#[test] -fn multi_empty_start_crlf() { - let file = b"\r\nfoo\r\nbar"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); -} - -#[test] -fn multi_empty_end_crlf() { - let file = b"foo\r\nbar\r\n\r\n"; - - assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); -} - -#[test] -fn bad_utf8() { - let file = b"foo\x80foo"; - - match got_args(file).unwrap_err() { - Error::Utf8Error(_) => (), - bad => panic!("bad err: {:?}", bad), - } -} diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4843c1a951b3..2cec404c3d7f 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -140,14 +140,22 @@ impl Callbacks for TimePassesCallbacks { // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. pub fn run_compiler( - args: &[String], + at_args: &[String], callbacks: &mut (dyn Callbacks + Send), file_loader: Option>, emitter: Option> ) -> interface::Result<()> { + let mut args = Vec::new(); + for arg in at_args { + match args::arg_expand(arg.clone()) { + Ok(arg) => args.extend(arg), + Err(err) => early_error(ErrorOutputType::default(), + &format!("Failed to load argument file: {}", err)), + } + } let diagnostic_output = emitter.map(|emitter| DiagnosticOutput::Raw(emitter)) .unwrap_or(DiagnosticOutput::Default); - let matches = match handle_options(args) { + let matches = match handle_options(&args) { Some(matches) => matches, None => return Ok(()), }; @@ -1199,10 +1207,10 @@ pub fn main() { init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); let result = report_ices_to_stderr_if_any(|| { - let args = args::ArgsIter::new().enumerate() - .map(|(i, arg)| arg.unwrap_or_else(|err| { - early_error(ErrorOutputType::default(), - &format!("Argument {} is not valid: {}", i, err)) + let args = env::args_os().enumerate() + .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { + early_error(ErrorOutputType::default(), + &format!("Argument {} is not valid Unicode: {:?}", i, arg)) })) .collect::>(); run_compiler(&args, &mut callbacks, None, None) diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs index c017e7b5ea60..161715685b57 100644 --- a/src/test/ui/commandline-argfile-badutf8.rs +++ b/src/test/ui/commandline-argfile-badutf8.rs @@ -1,7 +1,6 @@ // Check to see if we can get parameters from an @argsfile file // // build-fail -// normalize-stderr-test: "Argument \d+" -> "Argument $$N" // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args #[cfg(not(cmdline_set))] diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/commandline-argfile-badutf8.stderr index cd8a03e34eac..9af6fc0a518d 100644 --- a/src/test/ui/commandline-argfile-badutf8.stderr +++ b/src/test/ui/commandline-argfile-badutf8.stderr @@ -1,2 +1,2 @@ -error: Argument $N is not valid: Utf8 error in $DIR/commandline-argfile-badutf8.args +error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs index 34faf0763359..a29b4ab062de 100644 --- a/src/test/ui/commandline-argfile-missing.rs +++ b/src/test/ui/commandline-argfile-missing.rs @@ -1,7 +1,7 @@ // Check to see if we can get parameters from an @argsfile file // +// ignore-tidy-linelength // build-fail -// normalize-stderr-test: "Argument \d+" -> "Argument $$N" // normalize-stderr-test: "os error \d+" -> "os error $$ERR" // normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING " // compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/commandline-argfile-missing.stderr index c0017782f2eb..179ad8310041 100644 --- a/src/test/ui/commandline-argfile-missing.stderr +++ b/src/test/ui/commandline-argfile-missing.stderr @@ -1,2 +1,2 @@ -error: Argument $N is not valid: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR) +error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)