Skip to content

Commit

Permalink
Reject unset parameter with nounset option
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant committed Nov 2, 2022
1 parent a081da3 commit cfac73f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
6 changes: 6 additions & 0 deletions yash-semantics/src/expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ pub enum ErrorCause {
ArithError(ArithError),
/// Assignment to a read-only variable.
AssignReadOnly(ReadOnlyError),
/// Expansion of an unset parameter with the `nounset` option
UnsetParameter,
/// Expansion of an empty value with an error switch
EmptyExpansion(EmptyError),
/// Assignment to a nonassignable parameter
Expand All @@ -126,6 +128,7 @@ impl ErrorCause {
CommandSubstError(_) => "error performing the command substitution",
ArithError(_) => "error evaluating the arithmetic expansion",
AssignReadOnly(_) => "cannot assign to read-only variable",
UnsetParameter => "unset parameter",
EmptyExpansion(error) => error.message_or_default(),
NonassignableParameter(_) => "cannot assign to parameter",
}
Expand All @@ -140,6 +143,7 @@ impl ErrorCause {
CommandSubstError(e) => e.desc().into(),
ArithError(e) => e.to_string().into(),
AssignReadOnly(e) => e.to_string().into(),
UnsetParameter => "unset parameter disallowed by the nounset option".into(),
EmptyExpansion(e) => e.state.description().into(),
NonassignableParameter(e) => e.to_string().into(),
}
Expand All @@ -158,6 +162,7 @@ impl ErrorCause {
&e.read_only_location,
"the variable was made read-only here",
)),
UnsetParameter => None,
EmptyExpansion(_) => None,
NonassignableParameter(_) => None,
}
Expand All @@ -171,6 +176,7 @@ impl std::fmt::Display for ErrorCause {
CommandSubstError(errno) => write!(f, "error in command substitution: {errno}"),
ArithError(error) => error.fmt(f),
AssignReadOnly(error) => error.fmt(f),
UnsetParameter => "unset parameter".fmt(f),
EmptyExpansion(error) => error.fmt(f),
NonassignableParameter(error) => error.fmt(f),
}
Expand Down
36 changes: 35 additions & 1 deletion yash-semantics/src/expansion/initial/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
use super::super::phrase::Phrase;
use super::super::AttrChar;
use super::super::Error;
use super::super::ErrorCause;
use super::super::Origin;
use super::Env;
use yash_env::option::Option::Unset;
use yash_env::option::State::Off;
use yash_env::variable::Value;
use yash_syntax::source::Location;
use yash_syntax::syntax::Modifier;
Expand Down Expand Up @@ -78,7 +81,14 @@ impl ParamRef<'_> {
}
}

// TODO Check for nounset error
// Check for nounset option error //
if value.is_none() && env.inner.options.get(Unset) == Off {
return Err(Error {
cause: ErrorCause::UnsetParameter,
location: self.location.clone(),
});
}

// TODO Reject POSIXly unspecified combinations of name and modifier

// Other modifiers //
Expand Down Expand Up @@ -286,6 +296,30 @@ pub mod tests {
assert_eq!(phrase, Phrase::one_empty_field());
}

#[test]
fn unset_option() {
let mut env = yash_env::Env::new_virtual();
let mut env = Env::new(&mut env);
let param = param("foo");
let param = ParamRef::from(&param);

let phrase = param.expand(&mut env).now_or_never().unwrap().unwrap();
assert_eq!(phrase, Phrase::one_empty_field());
}

#[test]
fn nounset_option() {
let mut env = yash_env::Env::new_virtual();
env.options.set(Unset, Off);
let mut env = Env::new(&mut env);
let param = param("foo");
let param = ParamRef::from(&param);

let e = param.expand(&mut env).now_or_never().unwrap().unwrap_err();
assert_eq!(e.cause, ErrorCause::UnsetParameter);
assert_eq!(e.location, Location::dummy(""));
}

#[test]
fn expand_at_no_join_in_non_splitting_context() {
let mut env = env_with_positional_params_and_ifs();
Expand Down

0 comments on commit cfac73f

Please sign in to comment.