|
1 |
| -use std::error; |
2 |
| -use std::fmt; |
3 |
| -use std::fs; |
4 |
| -use std::io; |
| 1 | +use std::{env, error, fmt, fs, io}; |
5 | 2 |
|
6 | 3 | use rustc_session::EarlyDiagCtxt;
|
| 4 | +use rustc_span::ErrorGuaranteed; |
7 | 5 |
|
8 | 6 | /// Expands argfiles in command line arguments.
|
9 | 7 | #[derive(Default)]
|
@@ -86,42 +84,71 @@ impl Expander {
|
86 | 84 | fn read_file(path: &str) -> Result<String, Error> {
|
87 | 85 | fs::read_to_string(path).map_err(|e| {
|
88 | 86 | if e.kind() == io::ErrorKind::InvalidData {
|
89 |
| - Error::Utf8Error(Some(path.to_string())) |
| 87 | + Error::Utf8Error(path.to_string()) |
90 | 88 | } else {
|
91 | 89 | Error::IOError(path.to_string(), e)
|
92 | 90 | }
|
93 | 91 | })
|
94 | 92 | }
|
95 | 93 | }
|
96 | 94 |
|
| 95 | +/// Replaces any `@file` arguments with the contents of `file`, with each line of `file` as a |
| 96 | +/// separate argument. |
| 97 | +/// |
97 | 98 | /// **Note:** This function doesn't interpret argument 0 in any special way.
|
98 | 99 | /// If this function is intended to be used with command line arguments,
|
99 | 100 | /// `argv[0]` must be removed prior to calling it manually.
|
100 | 101 | #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
101 |
| -pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> { |
| 102 | +pub fn arg_expand_all( |
| 103 | + early_dcx: &EarlyDiagCtxt, |
| 104 | + at_args: &[String], |
| 105 | +) -> Result<Vec<String>, ErrorGuaranteed> { |
102 | 106 | let mut expander = Expander::default();
|
| 107 | + let mut result = Ok(()); |
103 | 108 | for arg in at_args {
|
104 | 109 | if let Err(err) = expander.arg(arg) {
|
105 |
| - early_dcx.early_fatal(format!("Failed to load argument file: {err}")); |
| 110 | + result = Err(early_dcx.early_err(format!("failed to load argument file: {err}"))); |
106 | 111 | }
|
107 | 112 | }
|
108 |
| - expander.finish() |
| 113 | + result.map(|()| expander.finish()) |
| 114 | +} |
| 115 | + |
| 116 | +/// Gets the raw unprocessed command-line arguments as Unicode strings, without doing any further |
| 117 | +/// processing (e.g., without `@file` expansion). |
| 118 | +/// |
| 119 | +/// This function is identical to [`env::args()`] except that it emits an error when it encounters |
| 120 | +/// non-Unicode arguments instead of panicking. |
| 121 | +pub fn raw_args(early_dcx: &EarlyDiagCtxt) -> Result<Vec<String>, ErrorGuaranteed> { |
| 122 | + let mut res = Ok(Vec::new()); |
| 123 | + for (i, arg) in env::args_os().enumerate() { |
| 124 | + match arg.into_string() { |
| 125 | + Ok(arg) => { |
| 126 | + if let Ok(args) = &mut res { |
| 127 | + args.push(arg); |
| 128 | + } |
| 129 | + } |
| 130 | + Err(arg) => { |
| 131 | + res = |
| 132 | + Err(early_dcx.early_err(format!("argument {i} is not valid Unicode: {arg:?}"))) |
| 133 | + } |
| 134 | + } |
| 135 | + } |
| 136 | + res |
109 | 137 | }
|
110 | 138 |
|
111 | 139 | #[derive(Debug)]
|
112 |
| -pub enum Error { |
113 |
| - Utf8Error(Option<String>), |
| 140 | +enum Error { |
| 141 | + Utf8Error(String), |
114 | 142 | IOError(String, io::Error),
|
115 | 143 | ShellParseError(String),
|
116 | 144 | }
|
117 | 145 |
|
118 | 146 | impl fmt::Display for Error {
|
119 | 147 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
120 | 148 | match self {
|
121 |
| - Error::Utf8Error(None) => write!(fmt, "Utf8 error"), |
122 |
| - Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"), |
123 |
| - Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"), |
124 |
| - Error::ShellParseError(path) => write!(fmt, "Invalid shell-style arguments in {path}"), |
| 149 | + Error::Utf8Error(path) => write!(fmt, "UTF-8 error in {path}"), |
| 150 | + Error::IOError(path, err) => write!(fmt, "IO error: {path}: {err}"), |
| 151 | + Error::ShellParseError(path) => write!(fmt, "invalid shell-style arguments in {path}"), |
125 | 152 | }
|
126 | 153 | }
|
127 | 154 | }
|
|
0 commit comments