fixed empty arguments being filtered out during word splitting
This commit is contained in:
@@ -94,9 +94,7 @@ impl Expander {
|
|||||||
_ => cur_word.push(ch),
|
_ => cur_word.push(ch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !cur_word.is_empty() {
|
|
||||||
words.push(cur_word);
|
words.push(cur_word);
|
||||||
}
|
|
||||||
words
|
words
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -754,7 +752,7 @@ pub fn expand_proc_sub(raw: &str, is_input: bool) -> ShResult<String> {
|
|||||||
let mut io_stack = IoStack::new();
|
let mut io_stack = IoStack::new();
|
||||||
io_stack.push_frame(io_frame);
|
io_stack.push_frame(io_frame);
|
||||||
|
|
||||||
if let Err(e) = exec_input(raw.to_string(), Some(io_stack)) {
|
if let Err(e) = exec_input(raw.to_string(), Some(io_stack), false) {
|
||||||
eprintln!("{e}");
|
eprintln!("{e}");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -787,7 +785,7 @@ pub fn expand_cmd_sub(raw: &str) -> ShResult<String> {
|
|||||||
match unsafe { fork()? } {
|
match unsafe { fork()? } {
|
||||||
ForkResult::Child => {
|
ForkResult::Child => {
|
||||||
io_stack.push_frame(cmd_sub_io_frame);
|
io_stack.push_frame(cmd_sub_io_frame);
|
||||||
if let Err(e) = exec_input(raw.to_string(), Some(io_stack)) {
|
if let Err(e) = exec_input(raw.to_string(), Some(io_stack), false) {
|
||||||
eprintln!("{e}");
|
eprintln!("{e}");
|
||||||
unsafe { libc::_exit(1) };
|
unsafe { libc::_exit(1) };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ fn run_script<P: AsRef<Path>>(path: P, args: Vec<String>) -> ShResult<()> {
|
|||||||
write_vars(|v| v.cur_scope_mut().bpush_arg(arg))
|
write_vars(|v| v.cur_scope_mut().bpush_arg(arg))
|
||||||
}
|
}
|
||||||
|
|
||||||
exec_input(input, None)
|
exec_input(input, None, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fern_interactive() -> ShResult<()> {
|
fn fern_interactive() -> ShResult<()> {
|
||||||
@@ -187,7 +187,7 @@ fn fern_interactive() -> ShResult<()> {
|
|||||||
match readline.process_input() {
|
match readline.process_input() {
|
||||||
Ok(ReadlineEvent::Line(input)) => {
|
Ok(ReadlineEvent::Line(input)) => {
|
||||||
write_meta(|m| m.start_timer());
|
write_meta(|m| m.start_timer());
|
||||||
if let Err(e) = exec_input(input, None) {
|
if let Err(e) = exec_input(input, None, true) {
|
||||||
match e.kind() {
|
match e.kind() {
|
||||||
ShErrKind::CleanExit(code) => {
|
ShErrKind::CleanExit(code) => {
|
||||||
QUIT_CODE.store(*code, Ordering::SeqCst);
|
QUIT_CODE.store(*code, Ordering::SeqCst);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ impl ExecArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec_input(input: String, io_stack: Option<IoStack>) -> ShResult<()> {
|
pub fn exec_input(input: String, io_stack: Option<IoStack>, interactive: bool) -> ShResult<()> {
|
||||||
let log_tab = read_logic(|l| l.clone());
|
let log_tab = read_logic(|l| l.clone());
|
||||||
let input = expand_aliases(input, HashSet::new(), &log_tab);
|
let input = expand_aliases(input, HashSet::new(), &log_tab);
|
||||||
let mut parser = ParsedSrc::new(Arc::new(input));
|
let mut parser = ParsedSrc::new(Arc::new(input));
|
||||||
@@ -127,7 +127,7 @@ pub fn exec_input(input: String, io_stack: Option<IoStack>) -> ShResult<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dispatcher = Dispatcher::new(parser.extract_nodes());
|
let mut dispatcher = Dispatcher::new(parser.extract_nodes(), interactive);
|
||||||
if let Some(mut stack) = io_stack {
|
if let Some(mut stack) = io_stack {
|
||||||
dispatcher.io_stack.extend(stack.drain(..));
|
dispatcher.io_stack.extend(stack.drain(..));
|
||||||
}
|
}
|
||||||
@@ -136,15 +136,17 @@ pub fn exec_input(input: String, io_stack: Option<IoStack>) -> ShResult<()> {
|
|||||||
|
|
||||||
pub struct Dispatcher {
|
pub struct Dispatcher {
|
||||||
nodes: VecDeque<Node>,
|
nodes: VecDeque<Node>,
|
||||||
|
interactive: bool,
|
||||||
pub io_stack: IoStack,
|
pub io_stack: IoStack,
|
||||||
pub job_stack: JobStack,
|
pub job_stack: JobStack,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dispatcher {
|
impl Dispatcher {
|
||||||
pub fn new(nodes: Vec<Node>) -> Self {
|
pub fn new(nodes: Vec<Node>, interactive: bool) -> Self {
|
||||||
let nodes = VecDeque::from(nodes);
|
let nodes = VecDeque::from(nodes);
|
||||||
Self {
|
Self {
|
||||||
nodes,
|
nodes,
|
||||||
|
interactive,
|
||||||
io_stack: IoStack::new(),
|
io_stack: IoStack::new(),
|
||||||
job_stack: JobStack::new(),
|
job_stack: JobStack::new(),
|
||||||
}
|
}
|
||||||
@@ -265,7 +267,7 @@ impl Dispatcher {
|
|||||||
let subsh_body = subsh.0.to_string();
|
let subsh_body = subsh.0.to_string();
|
||||||
let _guard = ScopeGuard::shared_scope();
|
let _guard = ScopeGuard::shared_scope();
|
||||||
|
|
||||||
exec_input(subsh_body, None)?;
|
exec_input(subsh_body, None, self.interactive)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -607,6 +609,10 @@ impl Dispatcher {
|
|||||||
self.io_stack.append_to_frame(cmd.redirs);
|
self.io_stack.append_to_frame(cmd.redirs);
|
||||||
|
|
||||||
let exec_args = ExecArgs::new(argv)?;
|
let exec_args = ExecArgs::new(argv)?;
|
||||||
|
if self.interactive {
|
||||||
|
log::info!("expanded argv: {:?}", exec_args.argv.iter().map(|s| s.to_str().unwrap()).collect::<Vec<_>>());
|
||||||
|
}
|
||||||
|
|
||||||
let io_frame = self.io_stack.pop_frame();
|
let io_frame = self.io_stack.pop_frame();
|
||||||
run_fork(
|
run_fork(
|
||||||
io_frame,
|
io_frame,
|
||||||
|
|||||||
@@ -802,6 +802,6 @@ pub fn source_file(path: PathBuf) -> ShResult<()> {
|
|||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
file.read_to_string(&mut buf)?;
|
file.read_to_string(&mut buf)?;
|
||||||
exec_input(buf, None)?;
|
exec_input(buf, None, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user