diff --git a/src/core/builtins/getopts.rs b/src/core/builtins/getopts.rs index 0b5a778f..0956f896 100644 --- a/src/core/builtins/getopts.rs +++ b/src/core/builtins/getopts.rs @@ -86,7 +86,7 @@ pub fn getopts(core: &mut ShellCore, args: &mut Vec) -> i32 { let _ = core.db.set_param("OPTARG", "", None); if let Err(e) = result { - let msg = format!("getopts: {}", &e); + let msg = format!("getopts: {:?}", &e); error::print(&msg, core); return 1; } @@ -104,7 +104,7 @@ pub fn getopts(core: &mut ShellCore, args: &mut Vec) -> i32 { let _ = core.db.set_param("OPTIND", &(index+2).to_string(), None); if let Err(e) = result { - let msg = format!("getopts: {}", &e); + let msg = format!("getopts: {:?}", &e); error::print(&msg, core); return 1; } diff --git a/src/core/builtins/parameter.rs b/src/core/builtins/parameter.rs index b04a9ae5..d9dd1d7a 100644 --- a/src/core/builtins/parameter.rs +++ b/src/core/builtins/parameter.rs @@ -2,6 +2,7 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{error, ShellCore, utils, Feeder}; +use crate::error::ExecError; use crate::utils::exit; use crate::elements::substitution::Substitution; use crate::utils::arg; @@ -27,7 +28,7 @@ pub fn print_all(core: &mut ShellCore) -> i32 { 0 } -fn set_local(arg: &str, core: &mut ShellCore, layer: usize) -> Result<(), String> { +fn set_local(arg: &str, core: &mut ShellCore, layer: usize) -> Result<(), ExecError> { let mut feeder = Feeder::new(arg); if feeder.scanner_name(core) == feeder.len() { // name only let name = feeder.consume(feeder.len()); @@ -36,12 +37,12 @@ fn set_local(arg: &str, core: &mut ShellCore, layer: usize) -> Result<(), String let mut sub = match Substitution::parse(&mut feeder, core) { Some(s) => s, - _ => return Err(format!("local: `{}': not a valid identifier", arg)), + _ => return Err(ExecError::Other(format!("local: `{}': not a valid identifier", arg))), }; match sub.eval(core, Some(layer), false) { true => Ok(()), - false => Err(format!("local: `{}': evaluation error", arg)), + false => Err(ExecError::Other(format!("local: `{}': evaluation error", arg))), } } diff --git a/src/core/builtins/read.rs b/src/core/builtins/read.rs index 4e0efb5a..3bceb335 100644 --- a/src/core/builtins/read.rs +++ b/src/core/builtins/read.rs @@ -31,8 +31,8 @@ pub fn read(core: &mut ShellCore, args: &mut Vec) -> i32 { return 1; }else{ if let Err(e) = core.db.set_param(&a, "", None) { - //let msg = error::readonly(&a); - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); return 1; } } @@ -48,8 +48,8 @@ pub fn read(core: &mut ShellCore, args: &mut Vec) -> i32 { for w in line.trim_end().split(' ') { if pos < args.len()-1 { if let Err(e) = core.db.set_param(&args[pos], &w, None) { - //let msg = error::readonly(&args[pos]); - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); return 1; } pos += 1; @@ -59,8 +59,8 @@ pub fn read(core: &mut ShellCore, args: &mut Vec) -> i32 { } overflow += &w; if let Err(e) = core.db.set_param(&args[pos], &overflow, None) { - //let msg = error::readonly(&args[pos]); - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); return 1; } } diff --git a/src/core/database.rs b/src/core/database.rs index 039f97c7..809eec09 100644 --- a/src/core/database.rs +++ b/src/core/database.rs @@ -177,7 +177,7 @@ impl DataBase { None } - pub fn set_param(&mut self, name: &str, val: &str, layer: Option) -> Result<(), String> { + pub fn set_param(&mut self, name: &str, val: &str, layer: Option) -> Result<(), ExecError> { Self::name_check(name)?; self.write_check(name)?; let layer = self.get_target_layer(name, layer); diff --git a/src/core/database/data.rs b/src/core/database/data.rs index 5a9f386f..514d92d1 100644 --- a/src/core/database/data.rs +++ b/src/core/database/data.rs @@ -33,7 +33,7 @@ pub trait Data { println!("{}={}", name, self.print_body()); } - fn set_as_single(&mut self, _: &str) -> Result<(), String> {Err("Undefined call".to_string())} + fn set_as_single(&mut self, _: &str) -> Result<(), ExecError> {Err(ExecError::Other("Undefined call".to_string()))} fn set_as_array(&mut self, _: &str, _: &str) -> Result<(), String> {Err("not an array".to_string())} fn set_as_assoc(&mut self, _: &str, _: &str) -> Result<(), String> {Err("not an associative table".to_string())} diff --git a/src/core/database/data/single.rs b/src/core/database/data/single.rs index 137125f6..bbf9945b 100644 --- a/src/core/database/data/single.rs +++ b/src/core/database/data/single.rs @@ -2,6 +2,7 @@ //SPDXLicense-Identifier: BSD-3-Clause use crate::core::HashMap; +use crate::error::ExecError; use std::env; use super::Data; @@ -20,7 +21,7 @@ impl Data for SingleData { fn boxed_clone(&self) -> Box { Box::new(self.clone()) } fn print_body(&self) -> String { self.body.clone() } - fn set_as_single(&mut self, value: &str) -> Result<(), String> { + fn set_as_single(&mut self, value: &str) -> Result<(), ExecError> { self.body = value.to_string(); Ok(()) } @@ -31,12 +32,12 @@ impl Data for SingleData { } impl SingleData { - pub fn set_new_entry(db_layer: &mut HashMap>, name: &str, value: &str)-> Result<(), String> { + pub fn set_new_entry(db_layer: &mut HashMap>, name: &str, value: &str)-> Result<(), ExecError> { db_layer.insert( name.to_string(), Box::new(SingleData::from(value)) ); Ok(()) } - pub fn set_value(db_layer: &mut HashMap>, name: &str, val: &str) -> Result<(), String> { + pub fn set_value(db_layer: &mut HashMap>, name: &str, val: &str) -> Result<(), ExecError> { if env::var(name).is_ok() { env::set_var(name, val); } diff --git a/src/elements/command/arithmetic.rs b/src/elements/command/arithmetic.rs index 8cc86fe3..3c503aa9 100644 --- a/src/elements/command/arithmetic.rs +++ b/src/elements/command/arithmetic.rs @@ -4,6 +4,7 @@ use crate::{ShellCore, Feeder}; use super::{Command, Redirect}; use crate::elements::expr::arithmetic::ArithmeticExpr; +use crate::error::ExecError; #[derive(Debug, Clone)] pub struct ArithmeticCommand { @@ -16,9 +17,12 @@ pub struct ArithmeticCommand { impl Command for ArithmeticCommand { fn run(&mut self, core: &mut ShellCore, _: bool) { let exit_status = match self.eval(core).as_deref() { - Some("0") => 1, - Some(_) => 0, - None => 1, + Ok("0") => 1, + Ok(_) => 0, + Err(e) => { + eprintln!("{:?}", e); + 1 + }, }; core.db.exit_status = exit_status; } @@ -40,18 +44,20 @@ impl ArithmeticCommand { } } - pub fn eval(&mut self, core: &mut ShellCore) -> Option { + pub fn eval(&mut self, core: &mut ShellCore) -> Result { let mut ans = String::new(); for a in &mut self.expressions { + ans = a.eval(core)?; + /* match a.eval(core) { Ok(s) => ans = s, Err(e) => { eprintln!("{}", &e); return None; }, - } + }*/ } - Some(ans) + Ok(ans) } pub fn parse(feeder: &mut Feeder, core: &mut ShellCore) -> Option { diff --git a/src/elements/command/for.rs b/src/elements/command/for.rs index c692477a..0b07a8ae 100644 --- a/src/elements/command/for.rs +++ b/src/elements/command/for.rs @@ -80,7 +80,8 @@ impl ForCommand { if let Err(e) = core.db.set_param(&self.name, &p, None) { core.db.exit_status = 1; - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); } if core.continue_counter > 0 { diff --git a/src/elements/expr/arithmetic.rs b/src/elements/expr/arithmetic.rs index 5f1cb249..bf418d4a 100644 --- a/src/elements/expr/arithmetic.rs +++ b/src/elements/expr/arithmetic.rs @@ -11,7 +11,8 @@ pub mod word; mod int; mod float; -use crate::{error, ShellCore}; +use crate::ShellCore; +use crate::error::ExecError; use crate::utils::exit; use self::calculator::calculate; use self::elem::ArithElem; @@ -26,20 +27,15 @@ pub struct ArithmeticExpr { } impl ArithmeticExpr { - pub fn eval(&mut self, core: &mut ShellCore) -> Result { + pub fn eval(&mut self, core: &mut ShellCore) -> Result { match self.eval_elems(core, true)? { ArithElem::Integer(n) => self.ans_to_string(n), ArithElem::Float(f) => Ok(f.to_string()), - /* - Err(msg) => { - eprintln!("sush: {}: {}", &self.text, msg); - None - },*/ _ => exit::internal("invalid calculation result"), } } - pub fn eval_as_assoc_index(&mut self, core: &mut ShellCore) -> Result { + pub fn eval_as_assoc_index(&mut self, core: &mut ShellCore) -> Result { let mut ans = String::new(); for e in &self.elements { @@ -54,7 +50,7 @@ impl ArithmeticExpr { ans += "--"; } }, - None => return Err("not an assoc index".to_string()), + None => return Err(ExecError::ArrayIndexInvalid(w.text.clone())), } }, _ => ans += &e.to_string(), @@ -72,16 +68,17 @@ impl ArithmeticExpr { None }, Err(msg) => { - eprintln!("sush: {}: {}", &self.text, msg); + eprintln!("sush: {}: {:?}", &self.text, msg); None }, _ => exit::internal("invalid calculation result"), } } - pub fn eval_elems(&mut self, core: &mut ShellCore, permit_empty: bool) -> Result { + pub fn eval_elems(&mut self, core: &mut ShellCore, permit_empty: bool) -> Result { if self.elements.is_empty() && ! permit_empty { - return Err("operand expexted (error token: \")\")".to_string()); + return Err(ExecError::OperandExpected("\")\"".to_string())); + //return Err("operand expexted (error token: \")\")".to_string()); } let es = match self.decompose_increments() { Ok(data) => data, @@ -91,7 +88,7 @@ impl ArithmeticExpr { calculate(&es, core) } - fn ans_to_string(&self, n: i64) -> Result { + fn ans_to_string(&self, n: i64) -> Result { let base_str = self.output_base.clone(); if base_str == "10" { @@ -101,16 +98,22 @@ impl ArithmeticExpr { let base = match base_str.parse::() { Ok(b) => b, _ => { + return Err(ExecError::InvalidBase(base_str)); + /* let msg = format!("sush: {0}: invalid arithmetic base (error token is \"{0}\")", base_str); eprintln!("{}", &msg); return Err(msg); + */ }, }; if base <= 1 || base > 64 { + return Err(ExecError::InvalidBase(base_str)); + /* let msg = format!("sush: {0}: invalid arithmetic base (error token is \"{0}\")", base_str); eprintln!("{}", &msg); return Err(msg); + */ } let mut tmp = n.abs(); @@ -150,16 +153,16 @@ impl ArithmeticExpr { std::str::from_utf8(&ascii).unwrap().to_string() } - fn eval_in_cond(&mut self, core: &mut ShellCore) -> Result { - let es = match self.decompose_increments() { - Ok(data) => data, - Err(err_msg) => return Err(err_msg), - }; + fn eval_in_cond(&mut self, core: &mut ShellCore) -> Result { + let es = self.decompose_increments()?; + calculate(&es, core) + /* match calculate(&es, core) { Ok(ans) => Ok(ans), Err(err_msg) => return Err(err_msg), } + */ } fn preinc_to_unarys(&mut self, ans: &mut Vec, pos: usize, inc: i64) -> i64 { @@ -181,7 +184,7 @@ impl ArithmeticExpr { 0 } - fn decompose_increments(&mut self) -> Result, String> { + fn decompose_increments(&mut self) -> Result, ExecError> { let mut ans = vec![]; let mut pre_increment = 0; @@ -206,8 +209,8 @@ impl ArithmeticExpr { } match pre_increment { - 1 => Err(error::syntax("++")), - -1 => Err(error::syntax("--")), + 1 => Err(ExecError::OperandExpected("++".to_string())), + -1 => Err(ExecError::OperandExpected("--".to_string())), _ => Ok(ans), } } diff --git a/src/elements/expr/arithmetic/array_elem.rs b/src/elements/expr/arithmetic/array_elem.rs index bb1257ee..71352530 100644 --- a/src/elements/expr/arithmetic/array_elem.rs +++ b/src/elements/expr/arithmetic/array_elem.rs @@ -2,11 +2,12 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::ShellCore; +use crate::error::ExecError; use super::ArithElem; use crate::elements::subscript::Subscript; pub fn to_operand(name: &String, sub: &mut Subscript, pre_increment: i64, post_increment: i64, - core: &mut ShellCore) -> Result { + core: &mut ShellCore) -> Result { let key = sub.eval(core, name)?; /* let key = match sub.eval(core, name) { @@ -21,14 +22,14 @@ pub fn to_operand(name: &String, sub: &mut Subscript, pre_increment: i64, post_i let mut value_num = match value_str.parse::() { Ok(n) => n, - Err(_) => return Err(format!("{}: not an interger", &name)), + Err(_) => return Err(ExecError::Other(format!("{}: not an interger", &name))), }; if pre_increment != 0 { value_num += pre_increment; match set_value(name, &key, value_num, core) { Ok(()) => {}, - Err(e) => return Err(e), + Err(e) => return Err(ExecError::Other(e)), } } @@ -38,7 +39,7 @@ pub fn to_operand(name: &String, sub: &mut Subscript, pre_increment: i64, post_i value_num += post_increment; match set_value(name, &key, value_num, core) { Ok(()) => {}, - Err(e) => return Err(e), + Err(e) => return Err(ExecError::Other(e)), } } ans diff --git a/src/elements/expr/arithmetic/calculator.rs b/src/elements/expr/arithmetic/calculator.rs index 2d005d06..8755504e 100644 --- a/src/elements/expr/arithmetic/calculator.rs +++ b/src/elements/expr/arithmetic/calculator.rs @@ -1,39 +1,45 @@ //SPDX-FileCopyrightText: 2024 Ryuichi Ueda ryuichiueda@gmail.com //SPDX-License-Identifier: BSD-3-Clause -use crate::{error, ShellCore}; +use crate::ShellCore; +use crate::error::ExecError; use crate::utils::exit; use super::elem::ArithElem; use super::{float, int, rev_polish, trenary, word, array_elem}; -pub fn pop_operand(stack: &mut Vec, core: &mut ShellCore) -> Result { +pub fn pop_operand(stack: &mut Vec, core: &mut ShellCore) -> Result { match stack.pop() { Some(ArithElem::ArrayElem(name, mut sub, inc)) => array_elem::to_operand(&name, &mut sub, 0, inc, core), Some(ArithElem::Word(w, inc)) => word::to_operand(&w, 0, inc, core), Some(ArithElem::InParen(mut a)) => a.eval_elems(core, false), Some(elem) => Ok(elem), - None => Err("no operand 2".to_string()), + None => Err(ExecError::Other("no operand 2".to_string())), } } -fn bin_operation(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Result<(), String> { - match op { +fn bin_operation(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Result<(), ExecError> { + let ans = match op { "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" => word::substitution(op, stack, core), _ => bin_calc_operation(op, stack, core), + }; + + match ans { + Ok(v) => Ok(v), + Err(e) => Err(ExecError::Other(e)), } } fn bin_calc_operation(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Result<(), String> { let right = match pop_operand(stack, core) { Ok(v) => v, - Err(e) => return Err(e), + Err(e) => return Err(format!("{:?}",e)), }; let left = match pop_operand(stack, core) { Ok(v) => v, - Err(e) => return Err(e), + Err(e) => return Err(format!("{:?}",e)), }; if op == "," { @@ -45,12 +51,17 @@ fn bin_calc_operation(op: &str, stack: &mut Vec, core: &mut ShellCore (ArithElem::Float(fl), ArithElem::Float(fr)) => float::bin_calc(op, fl, fr, stack), (ArithElem::Float(fl), ArithElem::Integer(nr)) => float::bin_calc(op, fl, nr as f64, stack), (ArithElem::Integer(nl), ArithElem::Float(fr)) => float::bin_calc(op, nl as f64, fr, stack), - (ArithElem::Integer(nl), ArithElem::Integer(nr)) => int::bin_calc(op, nl, nr, stack), + (ArithElem::Integer(nl), ArithElem::Integer(nr)) => { + match int::bin_calc(op, nl, nr, stack) { + Ok(i) => Ok(i), + Err(e) => Err(format!("{:?}", &e)), + } + }, _ => exit::internal("invalid operand"), }; } -fn unary_operation(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Result<(), String> { +fn unary_operation(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Result<(), ExecError> { let operand = match pop_operand(stack, core) { Ok(v) => v, Err(e) => return Err(e), @@ -63,15 +74,17 @@ fn unary_operation(op: &str, stack: &mut Vec, core: &mut ShellCore) - } } -pub fn calculate(elements: &Vec, core: &mut ShellCore) -> Result { +pub fn calculate(elements: &Vec, core: &mut ShellCore) -> Result { if elements.is_empty() { return Ok(ArithElem::Integer(0)); } + let rev_pol = rev_polish::rearrange(elements)?; + /* let rev_pol = match rev_polish::rearrange(elements) { Ok(ans) => ans, Err(e) => return Err( error::syntax(&e.to_string()) ), - }; + };*/ let mut stack = vec![]; let mut skip_until = String::new(); @@ -113,15 +126,15 @@ pub fn calculate(elements: &Vec, core: &mut ShellCore) -> Result, core: &mut ShellCore) -> Result { +fn check_skip(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Result { let last = pop_operand(stack, core); - let last_result = match &last { - Err(e) => return Err(e.to_string()), + let last_result = match last { + Err(e) => return Err(e), Ok(ArithElem::Integer(0)) => 0, Ok(_) => 1, }; @@ -138,7 +151,7 @@ fn check_skip(op: &str, stack: &mut Vec, core: &mut ShellCore) -> Res Ok("".to_string()) } -fn inc(inc: i64, stack: &mut Vec, core: &mut ShellCore) -> Result<(), String> { +fn inc(inc: i64, stack: &mut Vec, core: &mut ShellCore) -> Result<(), ExecError> { match stack.pop() { Some(ArithElem::Word(w, inc_post)) => { match word::to_operand(&w, inc, inc_post, core) { @@ -158,6 +171,6 @@ fn inc(inc: i64, stack: &mut Vec, core: &mut ShellCore) -> Result<(), Err(e) => Err(e), } }, - _ => Err("invalid increment".to_string()), + _ => Err(ExecError::Other("invalid increment".to_string())), } } diff --git a/src/elements/expr/arithmetic/float.rs b/src/elements/expr/arithmetic/float.rs index 308708cd..20bdd5c4 100644 --- a/src/elements/expr/arithmetic/float.rs +++ b/src/elements/expr/arithmetic/float.rs @@ -2,13 +2,14 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{error, ShellCore}; +use crate::error::ExecError; use super::{ArithElem, word}; -pub fn unary_calc(op: &str, num: f64, stack: &mut Vec) -> Result<(), String> { +pub fn unary_calc(op: &str, num: f64, stack: &mut Vec) -> Result<(), ExecError> { match op { "+" => stack.push( ArithElem::Float(num) ), "-" => stack.push( ArithElem::Float(-num) ), - _ => return Err("not supported operator for float number".to_string()), + _ => return Err(ExecError::Other("not supported operator for float number".to_string())), } Ok(()) } @@ -48,21 +49,21 @@ pub fn bin_calc(op: &str, left: f64, right: f64, } pub fn substitute(op: &str, name: &String, cur: f64, right: f64, core: &mut ShellCore) - -> Result { + -> Result { let new_value = match op { "+=" => cur + right, "-=" => cur - right, "*=" => cur * right, "/=" => { match right == 0.0 { - true => return Err("divided by 0".to_string()), + true => return Err(ExecError::DivZero), false => cur / right, } }, - _ => return Err("Not supprted operation for float numbers".to_string()), + _ => return Err(ExecError::OperandExpected(op.to_string())), }; - match core.db.set_param(&name, &new_value.to_string(), None) { //TODO: simplify, None, None + match core.db.set_param(&name, &new_value.to_string(), None) { Ok(()) => Ok(ArithElem::Float(new_value)), Err(e) => Err(e), } diff --git a/src/elements/expr/arithmetic/int.rs b/src/elements/expr/arithmetic/int.rs index e4bf72d4..ff8eb0f1 100644 --- a/src/elements/expr/arithmetic/int.rs +++ b/src/elements/expr/arithmetic/int.rs @@ -1,11 +1,12 @@ //SPDX-FileCopyrightText: 2024 Ryuichi Ueda ryuichiueda@gmail.com //SPDX-License-Identifier: BSD-3-Clause -use crate::{error, ShellCore}; +use crate::ShellCore; +use crate::error::ExecError; use crate::utils::exit; use super::{ArithElem, word}; -pub fn unary_calc(op: &str, num: i64, stack: &mut Vec) -> Result<(), String> { +pub fn unary_calc(op: &str, num: i64, stack: &mut Vec) -> Result<(), ExecError> { match op { "+" => stack.push( ArithElem::Integer(num) ), "-" => stack.push( ArithElem::Integer(-num) ), @@ -16,7 +17,7 @@ pub fn unary_calc(op: &str, num: i64, stack: &mut Vec) -> Result<(), Ok(()) } -pub fn bin_calc(op: &str, left: i64, right: i64, stack: &mut Vec) -> Result<(), String> { +pub fn bin_calc(op: &str, left: i64, right: i64, stack: &mut Vec) -> Result<(), ExecError> { let bool_to_01 = |b| { if b { 1 } else { 0 } }; let ans = match op { @@ -38,7 +39,7 @@ pub fn bin_calc(op: &str, left: i64, right: i64, stack: &mut Vec) -> "!=" => bool_to_01( left != right ), "%" | "/" => { if right == 0 { - return Err("divided by 0".to_string()); + return Err(ExecError::DivZero); } match op { "%" => left % right, @@ -50,7 +51,7 @@ pub fn bin_calc(op: &str, left: i64, right: i64, stack: &mut Vec) -> let r = right.try_into().unwrap(); left.pow(r) }else{ - return Err( error::exponent(&right.to_string()) ); + return Err(ExecError::Exponent(right)); } }, _ => exit::internal("unknown binary operator"), @@ -61,7 +62,7 @@ pub fn bin_calc(op: &str, left: i64, right: i64, stack: &mut Vec) -> } pub fn substitute(op: &str, name: &String, cur: i64, right: i64, core: &mut ShellCore) - -> Result { + -> Result { let new_value = match op { "+=" => cur + right, "-=" => cur - right, @@ -73,17 +74,17 @@ pub fn substitute(op: &str, name: &String, cur: i64, right: i64, core: &mut Shel ">>=" => if right < 0 {0} else {cur >> right}, "/=" | "%=" => { if right == 0 { - return Err("divided by 0".to_string()); + return Err(ExecError::DivZero); } match op == "%=" { true => cur % right, false => cur / right, } }, - _ => return Err("Not supprted operation for integer numbers".to_string()), + _ => return Err(ExecError::OperandExpected(op.to_string())), }; - match core.db.set_param(&name, &new_value.to_string(), None) { //TOOD: simplify + match core.db.set_param(&name, &new_value.to_string(), None) { Ok(()) => Ok(ArithElem::Integer(new_value)), Err(e) => Err(e), } diff --git a/src/elements/expr/arithmetic/rev_polish.rs b/src/elements/expr/arithmetic/rev_polish.rs index 3ec52488..27adcb38 100644 --- a/src/elements/expr/arithmetic/rev_polish.rs +++ b/src/elements/expr/arithmetic/rev_polish.rs @@ -1,9 +1,10 @@ //SPDX-FileCopyrightText: 2024 Ryuichi Ueda ryuichiueda@gmail.com //SPDX-License-Identifier: BSD-3-Clause +use crate::error::ExecError; use super::elem::ArithElem; -pub fn rearrange(elements: &[ArithElem]) -> Result, ArithElem> { +pub fn rearrange(elements: &[ArithElem]) -> Result, ExecError> { let mut ans = vec![]; let mut stack: Vec = vec![]; @@ -32,7 +33,8 @@ pub fn rearrange(elements: &[ArithElem]) -> Result, ArithElem> { }; if !ok { - return Err(e.clone()); + return Err(ExecError::OperandExpected(e.to_string())); + //return Err(e.clone()); } } diff --git a/src/elements/expr/arithmetic/trenary.rs b/src/elements/expr/arithmetic/trenary.rs index 3f5c85ba..c4ab808f 100644 --- a/src/elements/expr/arithmetic/trenary.rs +++ b/src/elements/expr/arithmetic/trenary.rs @@ -2,11 +2,12 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::ShellCore; +use crate::error::ExecError; use super::{ArithmeticExpr, ArithElem}; use super::calculator; pub fn operation(left: &Option, right: &Option, - stack: &mut Vec, core: &mut ShellCore) -> Result<(), String> { + stack: &mut Vec, core: &mut ShellCore) -> Result<(), ExecError> { let num = match calculator::pop_operand(stack, core) { Ok(v) => v, Err(e) => return Err(e), @@ -14,11 +15,11 @@ pub fn operation(left: &Option, right: &Option, let mut left = match left { Some(c) => c.clone(), - None => return Err("expr not found".to_string()), + None => return Err(ExecError::Other("expr not found".to_string())), }; let mut right = match right { Some(c) => c.clone(), - None => return Err("expr not found".to_string()), + None => return Err(ExecError::Other("expr not found".to_string())), }; let ans = match num { @@ -28,7 +29,7 @@ pub fn operation(left: &Option, right: &Option, Err(e) => return Err(e), } }, - ArithElem::Float(_) => return Err("float condition is not permitted".to_string()), + ArithElem::Float(_) => return Err(ExecError::Other("float condition is not permitted".to_string())), _ => { match left.eval_in_cond(core) { Ok(num) => num, diff --git a/src/elements/expr/arithmetic/word.rs b/src/elements/expr/arithmetic/word.rs index 13133d34..db68e64f 100644 --- a/src/elements/expr/arithmetic/word.rs +++ b/src/elements/expr/arithmetic/word.rs @@ -2,20 +2,21 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{error, ShellCore, Feeder}; +use crate::error::ExecError; use crate::utils; use crate::utils::exit; use super::{ArithElem, ArithmeticExpr, float, int, Word}; pub fn to_operand(w: &Word, pre_increment: i64, post_increment: i64, - core: &mut ShellCore) -> Result { + core: &mut ShellCore) -> Result { if pre_increment != 0 && post_increment != 0 || w.text.find('\'').is_some() { - return Err(error::syntax(&w.text)); + return Err(ExecError::Other(error::syntax(&w.text))); } let name = match w.eval_as_value(core) { Some(v) => v, - None => return Err(format!("{}: wrong substitution", &w.text)), + None => return Err(ExecError::Other(format!("{}: wrong substitution", &w.text))), }; let res = match pre_increment { @@ -25,7 +26,7 @@ pub fn to_operand(w: &Word, pre_increment: i64, post_increment: i64, match res { Ok(n) => return Ok(n), - Err(e) => return Err(e), + Err(e) => return Err(ExecError::Other(e)), } } @@ -200,10 +201,10 @@ fn subs(op: &str, w: &Word, right_value: &ArithElem, core: &mut ShellCore) }; match (current_num, right_value) { - (ArithElem::Integer(cur), ArithElem::Integer(right)) => int::substitute(op, &name, cur, *right, core), - (ArithElem::Float(cur), ArithElem::Integer(right)) => float::substitute(op, &name, cur, *right as f64, core), - (ArithElem::Float(cur), ArithElem::Float(right)) => float::substitute(op, &name, cur, *right, core), - (ArithElem::Integer(cur), ArithElem::Float(right)) => float::substitute(op, &name, cur as f64, *right, core), + (ArithElem::Integer(cur), ArithElem::Integer(right)) => Ok(int::substitute(op, &name, cur, *right, core)?), + (ArithElem::Float(cur), ArithElem::Integer(right)) => Ok(float::substitute(op, &name, cur, *right as f64, core)?), + (ArithElem::Float(cur), ArithElem::Float(right)) => Ok(float::substitute(op, &name, cur, *right, core)?), + (ArithElem::Integer(cur), ArithElem::Float(right)) => Ok(float::substitute(op, &name, cur as f64, *right, core)?), _ => Err("support not yet".to_string()), } } diff --git a/src/elements/subscript.rs b/src/elements/subscript.rs index d3e89573..d22f9ac0 100644 --- a/src/elements/subscript.rs +++ b/src/elements/subscript.rs @@ -2,6 +2,7 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{ShellCore, Feeder}; +use crate::error::ExecError; use super::expr::arithmetic::ArithmeticExpr; #[derive(Debug, Clone, Default)] @@ -12,27 +13,27 @@ pub struct Subscript { } impl Subscript { - pub fn eval(&mut self, core: &mut ShellCore, param_name: &str) -> Result { + pub fn eval(&mut self, core: &mut ShellCore, param_name: &str) -> Result { if self.inner_special != "" { return Ok(self.inner_special.clone()); } if let Some(a) = self.inner.as_mut() { if a.text.chars().all(|c| " \t\n".contains(c)) { - return Err("invalid inner".to_string()); + return Err(ExecError::ArrayIndexInvalid(a.text.clone())); } return match core.db.is_assoc(param_name) { true => { match self.inner.as_mut() { Some(sub) => sub.eval_as_assoc_index(core), - None => Err("no inner".to_string()), + None => Err(ExecError::ArrayIndexInvalid("".to_string())), } }, false => a.eval(core), }; } - Err("evaluation failure".to_string()) + Err(ExecError::ArrayIndexInvalid("".to_string())) } pub fn parse(feeder: &mut Feeder, core: &mut ShellCore) -> Option { diff --git a/src/elements/substitution.rs b/src/elements/substitution.rs index 516901dd..1a54fc8d 100644 --- a/src/elements/substitution.rs +++ b/src/elements/substitution.rs @@ -3,6 +3,7 @@ use crate::{ShellCore, Feeder}; use crate::error; +use crate::error::ExecError; use std::env; use super::array::Array; use super::subscript::Subscript; @@ -89,7 +90,7 @@ impl Substitution { }; if result.is_err() || done { - return result; + return Err(format!("{:?}", result)); } match &self.evaluated_array { @@ -130,7 +131,7 @@ impl Substitution { true } - pub fn get_index(&mut self, core: &mut ShellCore) -> Result { + pub fn get_index(&mut self, core: &mut ShellCore) -> Result { match self.index.clone() { Some(mut s) => { if s.text.chars().all(|c| " \n\t[]".contains(c)) { @@ -138,7 +139,7 @@ impl Substitution { } s.eval(core, &self.name) }, - _ => Err("no index".to_string()), + _ => Err(ExecError::ArrayIndexInvalid("".to_string())), } } diff --git a/src/elements/subword.rs b/src/elements/subword.rs index abbba9a4..72297656 100644 --- a/src/elements/subword.rs +++ b/src/elements/subword.rs @@ -13,7 +13,7 @@ mod varname; mod arithmetic; use crate::{ShellCore, Feeder}; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; use self::arithmetic::Arithmetic; use self::simple::SimpleSubword; use self::braced_param::BracedParam; @@ -66,7 +66,7 @@ pub trait Subword { fn get_text(&self) -> &str; fn set_text(&mut self, _: &str) {} fn boxed_clone(&self) -> Box; - fn substitute(&mut self, _: &mut ShellCore) -> Result<(), String> {Ok(())} + fn substitute(&mut self, _: &mut ShellCore) -> Result<(), ExecError> {Ok(())} fn get_alternative_subwords(&self) -> Vec> {vec![]} fn split(&self) -> Vec>{ diff --git a/src/elements/subword/arithmetic.rs b/src/elements/subword/arithmetic.rs index fe8cb932..b48a8c94 100644 --- a/src/elements/subword/arithmetic.rs +++ b/src/elements/subword/arithmetic.rs @@ -2,7 +2,7 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{ShellCore, Feeder}; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; use crate::elements::command::arithmetic::ArithmeticCommand; use crate::elements::subword::Subword; @@ -16,12 +16,12 @@ impl Subword for Arithmetic { fn get_text(&self) -> &str { &self.text.as_ref() } fn boxed_clone(&self) -> Box {Box::new(self.clone())} - fn substitute(&mut self, core: &mut ShellCore) -> Result<(), String> { - if let Some(s) = self.com.eval(core) { + fn substitute(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { + if let Ok(s) = self.com.eval(core) { self.text = s; return Ok(()); } - Err("arithmetic operation failed".to_string()) + Err(ExecError::OperandExpected(self.com.text.clone())) } } diff --git a/src/elements/subword/braced_param.rs b/src/elements/subword/braced_param.rs index 8c4a1d6e..d7d3385c 100644 --- a/src/elements/subword/braced_param.rs +++ b/src/elements/subword/braced_param.rs @@ -12,7 +12,7 @@ use crate::elements::subword::Subword; use crate::elements::subscript::Subscript; use crate::elements::word::Word; use crate::utils; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; use self::remove::Remove; use self::replace::Replace; use self::substr::Substr; @@ -46,23 +46,21 @@ impl Subword for BracedParam { fn get_text(&self) -> &str { &self.text.as_ref() } fn boxed_clone(&self) -> Box {Box::new(self.clone())} - fn substitute(&mut self, core: &mut ShellCore) -> Result<(), String> { - if ! self.check() { - return Err(format!("{}: bad substitution", &self.text)); - } + fn substitute(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { + self.check()?; if self.indirect { let value = core.db.get_param(&self.param.name).unwrap_or_default(); if utils::is_param(&value) { self.param.name = value; }else{ - return Err(format!("sush: {}: invalid name", &value)); + return Err(ExecError::InvalidName(value)); } } if self.param.subscript.is_some() { if self.param.name == "@" { - return Err(format!("sush: @: bad substitution")); + return Err(ExecError::BadSubstitution("@".to_string())); } return self.subscript_operation(core); } @@ -101,26 +99,19 @@ impl Subword for BracedParam { } impl BracedParam { - fn check(&mut self) -> bool { + fn check(&mut self) -> Result<(), ExecError> { if self.param.name.is_empty() || ! utils::is_param(&self.param.name) { - eprintln!("sush: {}: bad substitution", &self.text); - return false; + return Err(ExecError::BadSubstitution(self.text.clone())); } if self.unknown.len() > 0 && ! self.unknown.starts_with(",") { - eprintln!("sush: {}: bad substitution", &self.text); - return false; + return Err(ExecError::BadSubstitution(self.text.clone())); } - true + Ok(()) } - fn subscript_operation(&mut self, core: &mut ShellCore) -> Result<(), String> { + fn subscript_operation(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { let index = self.param.subscript.clone().unwrap().eval(core, &self.param.name)?; - /* - let index = match self.param.subscript.clone().unwrap().eval(core, &self.param.name) { - Some(s) => s, - None => return Err("index evaluation error".to_string()), - };*/ if core.db.is_assoc(&self.param.name) { return self.subscript_operation_assoc(core, &index); @@ -138,13 +129,13 @@ impl BracedParam { self.optional_operation(core) } - fn subscript_operation_assoc(&mut self, core: &mut ShellCore, index: &str) -> Result<(), String> { + fn subscript_operation_assoc(&mut self, core: &mut ShellCore, index: &str) -> Result<(), ExecError> { let s = core.db.get_array_elem(&self.param.name, index)?; self.text = s; Ok(()) } - fn optional_operation(&mut self, core: &mut ShellCore) -> Result<(), String> { + fn optional_operation(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { self.text = if let Some(s) = self.substr.as_mut() { s.get_text(&self.text, core)? }else if let Some(v) = self.value_check.as_mut() { diff --git a/src/elements/subword/braced_param/remove.rs b/src/elements/subword/braced_param/remove.rs index 5712d0b2..cda85a3d 100644 --- a/src/elements/subword/braced_param/remove.rs +++ b/src/elements/subword/braced_param/remove.rs @@ -4,7 +4,7 @@ use crate::{Feeder, ShellCore}; use crate::elements::subword::braced_param::Word; use crate::utils::glob; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; use super::BracedParam; #[derive(Debug, Clone, Default)] @@ -14,10 +14,10 @@ pub struct Remove { } impl Remove { - pub fn set(&mut self, text: &String, core: &mut ShellCore) -> Result { + pub fn set(&mut self, text: &String, core: &mut ShellCore) -> Result { let mut text = text.clone(); let pattern = self.remove_pattern.as_mut().unwrap() - .eval_for_case_word(core).ok_or("evaluation error")?; + .eval_for_case_word(core).ok_or(ExecError::Other("evaluation error".to_string()))?; let extglob = core.shopts.query("extglob"); if self.remove_symbol.starts_with("##") { @@ -31,7 +31,7 @@ impl Remove { }else if self.remove_symbol.starts_with("%") { self.percent(&mut text, &pattern, extglob); }else { - return Err("unknown symbol".to_string()); + return Err(ExecError::Other("unknown symbol".to_string())); } Ok(text) diff --git a/src/elements/subword/braced_param/replace.rs b/src/elements/subword/braced_param/replace.rs index 88ca1586..42fbd37e 100644 --- a/src/elements/subword/braced_param/replace.rs +++ b/src/elements/subword/braced_param/replace.rs @@ -2,6 +2,7 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{Feeder, ShellCore}; +use crate::error::ExecError; use crate::elements::subword::braced_param::Word; use crate::utils::glob; use crate::error::ParseError; @@ -18,21 +19,21 @@ pub struct Replace { } impl Replace { - fn to_string(&self, w: &Option, core: &mut ShellCore) -> Result { + fn to_string(&self, w: &Option, core: &mut ShellCore) -> Result { if let Some(w) = &w { match w.eval_for_case_word(core) { Some(s) => return Ok(s), None => match w.subwords.len() { 0 => return Ok("".to_string()), - _ => return Err("parse error".to_string()), + _ => return Err(ExecError::Other("parse error".to_string())), }, } } - Err("parse error".to_string()) + Err(ExecError::Other("parse error".to_string())) } - pub fn get_text(&self, text: &String, core: &mut ShellCore) -> Result { + pub fn get_text(&self, text: &String, core: &mut ShellCore) -> Result { let pattern = self.to_string(&self.replace_from, core)?; let string_to = self.to_string(&self.replace_to, core)?; let extglob = core.shopts.query("extglob"); diff --git a/src/elements/subword/braced_param/substr.rs b/src/elements/subword/braced_param/substr.rs index 7e64199d..d8696413 100644 --- a/src/elements/subword/braced_param/substr.rs +++ b/src/elements/subword/braced_param/substr.rs @@ -2,6 +2,7 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{Feeder, ShellCore}; +use crate::error::ExecError; use crate::elements::expr::arithmetic::ArithmeticExpr; use super::BracedParam; @@ -12,16 +13,16 @@ pub struct Substr { } impl Substr { - pub fn get_text(&mut self, text: &String, core: &mut ShellCore) -> Result { + pub fn get_text(&mut self, text: &String, core: &mut ShellCore) -> Result { let offset = self.offset.as_mut().unwrap(); if offset.text == "" { - return Err("bad substitution".to_string()); + return Err(ExecError::OperandExpected("".to_string())); } let mut ans; match offset.eval_as_int(core) { - None => return Err("evaluation error".to_string()), + None => return Err(ExecError::OperandExpected(offset.text.clone())), Some(n) => { ans = text.chars().enumerate() .filter(|(i, _)| (*i as i64) >= n) @@ -36,26 +37,27 @@ impl Substr { Ok(ans) } - fn length(&mut self, text: &String, core: &mut ShellCore) -> Result { + fn length(&mut self, text: &String, core: &mut ShellCore) -> Result { match self.length.as_mut().unwrap().eval_as_int(core) { Some(n) => Ok(text.chars().enumerate() .filter(|(i, _)| (*i as i64) < n) .map(|(_, c)| c).collect()), - None => return Err("length evaluation error".to_string()), + None => return Err(ExecError::OperandExpected(self.length.clone().unwrap().text.clone())), } } pub fn set_partial_position_params(&mut self, array: &mut Vec, - text: &mut String, core: &mut ShellCore) -> Result<(), String> { + text: &mut String, core: &mut ShellCore) -> Result<(), ExecError> { let offset = self.offset.as_mut().unwrap(); if offset.text == "" { - return Err("bad substitution".to_string()); + return Err(ExecError::BadSubstitution(String::new())); } *array = core.db.get_array_all("@"); match offset.eval_as_int(core) { - None => return Err("evaluation error".to_string()), + //None => return Err("evaluation error".to_string()), + None => return Err(ExecError::OperandExpected(offset.text.clone())), Some(n) => { let mut start = std::cmp::max(0, n) as usize; start = std::cmp::min(start, array.len()) as usize; @@ -69,19 +71,19 @@ impl Substr { } let mut length = match self.length.clone() { - None => return Err("bad substitution".to_string()), + None => return Err(ExecError::BadSubstitution("".to_string())), Some(ofs) => ofs, }; if length.text == "" { - return Err("bad substitution".to_string()); + return Err(ExecError::BadSubstitution("".to_string())); } match length.eval_as_int(core) { - None => return Err("evaluation error".to_string()), + None => return Err(ExecError::BadSubstitution(length.text.clone())), Some(n) => { if n < 0 { - return Err(format!("{}: substring expression < 0", n)); + return Err(ExecError::SubstringMinus(n)); } let len = std::cmp::min(n as usize, array.len()); let _ = array.split_off(len); diff --git a/src/elements/subword/braced_param/value_check.rs b/src/elements/subword/braced_param/value_check.rs index 1cf37c74..707ede91 100644 --- a/src/elements/subword/braced_param/value_check.rs +++ b/src/elements/subword/braced_param/value_check.rs @@ -1,10 +1,10 @@ //SPDX-FileCopyrightText: 2024 Ryuichi Ueda ryuichiueda@gmail.com //SPDX-License-Identifier: BSD-3-Clause -use crate::{Feeder, ShellCore}; +use crate::{exit, Feeder, ShellCore}; use crate::elements::subword::BracedParam; use crate::elements::subword::braced_param::Word; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; #[derive(Debug, Clone, Default)] pub struct ValueCheck { @@ -13,7 +13,7 @@ pub struct ValueCheck { } impl ValueCheck { - pub fn set(&mut self, name: &String, text: &String, core: &mut ShellCore) -> Result { + pub fn set(&mut self, name: &String, text: &String, core: &mut ShellCore) -> Result { match self.symbol.as_deref() { Some(":-") => { self.set_alter_word(core)?; @@ -24,24 +24,24 @@ impl ValueCheck { Some("-") => self.minus(text), Some(":+") => self.colon_plus(text, core), Some("+") => self.plus(name, text, core), - _ => Err("no operation".to_string()), + _ => exit::internal("no operation"), } } - fn set_alter_word(&mut self, core: &mut ShellCore) -> Result { - let v = self.alternative_value.clone().ok_or("no alternative value")?; + fn set_alter_word(&mut self, core: &mut ShellCore) -> Result { + let v = self.alternative_value.clone().ok_or(ExecError::OperandExpected("".to_string()))?; self.alternative_value = Some(v.tilde_and_dollar_expansion(core)? ); - let value = v.eval_as_value(core).ok_or("parse error")?; + let value = v.eval_as_value(core).ok_or(ExecError::OperandExpected("".to_string()))?; Ok(value.clone()) } - fn minus(&mut self, text: &String) -> Result { + fn minus(&mut self, text: &String) -> Result { self.alternative_value = None; self.symbol = None; Ok(text.clone()) } - fn plus(&mut self, name: &String, text: &String, core: &mut ShellCore) -> Result { + fn plus(&mut self, name: &String, text: &String, core: &mut ShellCore) -> Result { match core.db.has_value(&name) { true => {self.set_alter_word(core)?;}, false => self.alternative_value = None, @@ -49,7 +49,7 @@ impl ValueCheck { Ok(text.clone()) } - fn colon_plus(&mut self, text: &String, core: &mut ShellCore) -> Result { + fn colon_plus(&mut self, text: &String, core: &mut ShellCore) -> Result { match text.is_empty() { true => self.alternative_value = None, false => {self.set_alter_word(core)?;}, @@ -57,21 +57,21 @@ impl ValueCheck { Ok(text.clone()) } - fn colon_equal(&mut self, name: &String, core: &mut ShellCore) -> Result { + fn colon_equal(&mut self, name: &String, core: &mut ShellCore) -> Result { let value = self.set_alter_word(core)?; core.db.set_param(&name, &value, None)?; self.alternative_value = None; Ok(value) } - fn colon_question(&mut self, name: &String, text: &String, core: &mut ShellCore) -> Result { + fn colon_question(&mut self, name: &String, text: &String, core: &mut ShellCore) -> Result { if core.db.has_value(&name) { self.alternative_value = None; return Ok(text.clone()); } let value = self.set_alter_word(core)?; let msg = format!("{}: {}", &name, &value); - Err(msg) + Err(ExecError::Other(msg)) } pub fn eat(feeder: &mut Feeder, ans: &mut BracedParam, core: &mut ShellCore) diff --git a/src/elements/subword/command.rs b/src/elements/subword/command.rs index ce0bd54a..636a8169 100644 --- a/src/elements/subword/command.rs +++ b/src/elements/subword/command.rs @@ -6,7 +6,7 @@ use crate::elements::Pipe; use crate::elements::command::Command; use crate::elements::command::paren::ParenCommand; use crate::elements::subword::Subword; -use crate::error::ParseError; +use crate::error::{ParseError, ExecError}; use nix::unistd; use std::{thread, time}; use std::fs::File; @@ -24,29 +24,27 @@ impl Subword for CommandSubstitution { fn get_text(&self) -> &str {&self.text.as_ref()} fn boxed_clone(&self) -> Box {Box::new(self.clone())} - fn substitute(&mut self, core: &mut ShellCore) -> Result<(), String> { + fn substitute(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { let mut pipe = Pipe::new("|".to_string()); pipe.set(-1, unistd::getpgrp()); let pid = self.command.exec(core, &mut pipe); let result = self.read(pipe.recv, core); proc_ctrl::wait_pipeline(core, vec![pid], false, false); - result + match result { + true => Ok(()), + false => Err(ExecError::Other("command substitution error".to_string())), + } } } impl CommandSubstitution { fn set_line(&mut self, line: Result) -> bool { - match line { - Ok(ln) => { - self.text.push_str(&ln); - self.text.push('\n'); - true - }, - Err(e) => { - eprintln!("sush: {}", &e); - false - }, + if let Ok(ln) = line { + self.text.push_str(&ln); + self.text.push('\n'); + return true; } + false } fn interrupted(&mut self, count: usize, core: &mut ShellCore) -> bool { @@ -56,7 +54,7 @@ impl CommandSubstitution { core.sigint.load(Relaxed) } - fn read(&mut self, fd: RawFd, core: &mut ShellCore) -> Result<(), String> { + fn read(&mut self, fd: RawFd, core: &mut ShellCore) -> bool { let f = unsafe { File::from_raw_fd(fd) }; let reader = BufReader::new(f); self.text.clear(); @@ -65,11 +63,11 @@ impl CommandSubstitution { break; } if ! self.set_line(line) { - return Err("error: set_line".to_string()); + return false; } } self.text.pop(); - Ok(()) + true } pub fn parse(feeder: &mut Feeder, core: &mut ShellCore) -> Result, ParseError> { diff --git a/src/elements/subword/double_quoted.rs b/src/elements/subword/double_quoted.rs index 6fca6633..961c6d89 100644 --- a/src/elements/subword/double_quoted.rs +++ b/src/elements/subword/double_quoted.rs @@ -3,7 +3,7 @@ use crate::{ShellCore, Feeder}; use crate::utils::exit; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; use crate::elements::word::{Word, substitution}; use crate::elements::subword::CommandSubstitution; use super::{BracedParam, EscapedChar, SimpleSubword, Parameter, Subword, VarName}; @@ -19,7 +19,7 @@ impl Subword for DoubleQuoted { fn get_text(&self) -> &str {&self.text.as_ref()} fn boxed_clone(&self) -> Box {Box::new(self.clone())} - fn substitute(&mut self, core: &mut ShellCore) -> Result<(), String> { + fn substitute(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { let mut word = Word::default(); word.subwords = self.replace_array(core); substitution::eval(&mut word, core)?; diff --git a/src/elements/subword/parameter.rs b/src/elements/subword/parameter.rs index 0eb551e1..c7b7f00e 100644 --- a/src/elements/subword/parameter.rs +++ b/src/elements/subword/parameter.rs @@ -2,6 +2,7 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::{ShellCore, Feeder}; +use crate::error::ExecError; use super::Subword; #[derive(Debug, Clone)] @@ -13,7 +14,7 @@ impl Subword for Parameter { fn get_text(&self) -> &str {&self.text.as_ref()} fn boxed_clone(&self) -> Box {Box::new(self.clone())} - fn substitute(&mut self, core: &mut ShellCore) -> Result<(), String> { + fn substitute(&mut self, core: &mut ShellCore) -> Result<(), ExecError> { if ! self.text.starts_with("$") { return Ok(()); } diff --git a/src/elements/word.rs b/src/elements/word.rs index 72735d1f..834e8059 100644 --- a/src/elements/word.rs +++ b/src/elements/word.rs @@ -10,7 +10,7 @@ mod split; use crate::{ShellCore, Feeder}; use crate::elements::subword; use crate::error; -use crate::error::ParseError; +use crate::error::{ExecError, ParseError}; use super::subword::Subword; use super::subword::simple::SimpleSubword; @@ -67,7 +67,8 @@ impl Word { let mut ws = match self.tilde_and_dollar_expansion(core) { Ok(w) => w.split_and_path_expansion(core), Err(e) => { - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); return None; }, }; @@ -79,7 +80,8 @@ impl Word { match self.tilde_and_dollar_expansion(core) { Ok(mut w) => w.make_unquoted_word(), Err(e) => { - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); return None; }, } @@ -89,13 +91,14 @@ impl Word { match self.tilde_and_dollar_expansion(core) { Ok(mut w) => Some(w.make_glob_string()), Err(e) => { - error::print(&e, core); + let msg = format!("{:?}", &e); + error::print(&msg, core); return None; }, } } - pub fn tilde_and_dollar_expansion(&self, core: &mut ShellCore) -> Result { + pub fn tilde_and_dollar_expansion(&self, core: &mut ShellCore) -> Result { let mut w = self.clone(); tilde_expansion::eval(&mut w, core); substitution::eval(&mut w, core)?; diff --git a/src/elements/word/substitution.rs b/src/elements/word/substitution.rs index 703da534..def4f641 100644 --- a/src/elements/word/substitution.rs +++ b/src/elements/word/substitution.rs @@ -2,21 +2,17 @@ //SPDX-License-Identifier: BSD-3-Clause use crate::ShellCore; +use crate::error::ExecError; use crate::elements::word::Word; use crate::elements::subword::Subword; use crate::elements::subword::parameter::Parameter; -pub fn eval(word: &mut Word, core: &mut ShellCore) -> Result<(), String> { +pub fn eval(word: &mut Word, core: &mut ShellCore) -> Result<(), ExecError> { for i in word.scan_pos("$") { connect_names(&mut word.subwords[i..]); } for w in word.subwords.iter_mut() { w.substitute(core)?; - /* - if let Err(e) = w.substitute(core) { - eprintln!("{}", e); - return false; - }*/ } alternative_replace(word); Ok(()) diff --git a/src/error.rs b/src/error.rs index 2857a2b5..04739b9c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,20 +8,34 @@ use nix::unistd::Pid; #[derive(Debug)] pub enum ExecError { Internal, + ArrayIndexInvalid(String), + BadSubstitution(String), + DivZero, + Exponent(i64), + InvalidBase(String), + InvalidName(String), VariableReadOnly(String), VariableInvalid(String), - ArrayIndexInvalid(String), OperandExpected(String), + SubstringMinus(i64), + Other(String), } impl From for String { fn from(e: ExecError) -> String { match e { ExecError::Internal => "INTERNAL ERROR".to_string(), + ExecError::ArrayIndexInvalid(name) => format!("`{}': not a valid index", name), + ExecError::BadSubstitution(s) => format!("`{}': bad substitution", s), + ExecError::DivZero => "divided by 0".to_string(), + ExecError::Exponent(s) => format!("exponent less than 0 (error token is \"{}\")", s), + ExecError::InvalidName(name) => format!("`{}': invalid name", name), + ExecError::InvalidBase(b) => format!("sush: {0}: invalid arithmetic base (error token is \"{0}\")", b), ExecError::VariableReadOnly(name) => format!("{}: readonly variable", name), ExecError::VariableInvalid(name) => format!("`{}': not a valid identifier", name), - ExecError::ArrayIndexInvalid(name) => format!("`{}': not a valid index", name), ExecError::OperandExpected(name) => format!("`{}': syntax error: operand expected", name), + ExecError::SubstringMinus(n) => format!("{}: substring expression < 0", n), + ExecError::Other(name) => name, } } }