Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb4ea5ef15 | ||
|
|
04023934fd | ||
|
|
addc2db04a |
No files matched your search
+3
-3
@@ -361,11 +361,11 @@ impl Command {
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Command-specific data
|
||||
/// After parsing, t, b Label elements are converted into BranchTarget ones.
|
||||
/// After parsing, t, T, b Label elements are converted into BranchTarget ones.
|
||||
pub enum CommandData {
|
||||
None,
|
||||
BranchTarget(Option<Rc<RefCell<Command>>>), // Commands for 'b', 't', '{'
|
||||
Label(Option<String>), // Label name for 'b', 't', ':'
|
||||
BranchTarget(Option<Rc<RefCell<Command>>>), // Commands for 'b', 't', 'T', '{'
|
||||
Label(Option<String>), // Label name for 'b', 't', 'T', ':'
|
||||
Path(PathBuf), // File path for 'r'
|
||||
NamedWriter(Rc<RefCell<NamedWriter>>), // File output for 'w'
|
||||
Number(usize), // Number for 'l', 'q', 'Q' (GNU)
|
||||
|
||||
+16
-2
@@ -213,8 +213,8 @@ fn resolve_branch_targets(
|
||||
resolve_branch_targets(Some(sub_head.clone()), context)?;
|
||||
}
|
||||
|
||||
// Only for 't' or 'b' commands:
|
||||
if matches!(cmd.code, 't' | 'b') {
|
||||
// Only for 't', 'T', or 'b' commands:
|
||||
if matches!(cmd.code, 't' | 'T' | 'b') {
|
||||
// Take ownership of the current data
|
||||
let old_data = mem::replace(&mut cmd.data, CommandData::None);
|
||||
|
||||
@@ -1574,6 +1574,10 @@ fn get_cmd_spec(
|
||||
n_addr: 2,
|
||||
handler: compile_subst_command,
|
||||
}),
|
||||
'T' if !posix => Ok(CommandSpec {
|
||||
n_addr: 2,
|
||||
handler: compile_label_command,
|
||||
}),
|
||||
'w' => Ok(CommandSpec {
|
||||
n_addr: 2,
|
||||
handler: compile_write_file_command,
|
||||
@@ -1665,6 +1669,16 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lookup_branch_commands() {
|
||||
// b, t, and T all share compile_label_command and accept 2 addresses.
|
||||
for code in ['b', 't', 'T'] {
|
||||
let (lines, line) = make_providers("123abc");
|
||||
let cmd = get_cmd_spec(&lines, &line, code, false).unwrap();
|
||||
assert_eq!(cmd.n_addr, 2, "command `{code}` should accept 2 addresses");
|
||||
}
|
||||
}
|
||||
|
||||
// Utility to create a ScriptCharProvider from a &str
|
||||
fn char_provider_from(s: &str) -> ScriptCharProvider {
|
||||
ScriptCharProvider::new(s)
|
||||
|
||||
@@ -831,6 +831,23 @@ fn process_file(
|
||||
// Branch to the end of the script.
|
||||
break;
|
||||
}
|
||||
'T' if context.substitution_made => {
|
||||
// A substitution was made since the last cycle or T,
|
||||
// so reset the flag and fall through without branching.
|
||||
context.substitution_made = false;
|
||||
}
|
||||
'T' => {
|
||||
// Branch to the specified label or end if none is given
|
||||
// if no substitution was made since last cycle or T.
|
||||
let target = extract_variant!(command, BranchTarget);
|
||||
if target.is_some() {
|
||||
// New command to execute
|
||||
current.clone_from(target);
|
||||
continue;
|
||||
}
|
||||
// Branch to the end of the script.
|
||||
break;
|
||||
}
|
||||
'w' => {
|
||||
// Append the pattern space to the specified file.
|
||||
let writer = extract_variant!(command, NamedWriter);
|
||||
|
||||
@@ -1414,6 +1414,59 @@ tb"#,
|
||||
]
|
||||
);
|
||||
|
||||
// T branches when NO substitution was made (inverse of t).
|
||||
// Lines not ending in "2" leave s/2$/X/ with no match, so T branches to
|
||||
// :skip and keeps the original line; lines ending in "2" fall through and
|
||||
// get the "SUB " mark.
|
||||
check_output!(
|
||||
branch_no_sub_simple,
|
||||
[
|
||||
"-n",
|
||||
"-e",
|
||||
r#"
|
||||
s/2$/X/
|
||||
Tskip
|
||||
s/^/SUB /
|
||||
:skip
|
||||
p
|
||||
"#,
|
||||
LINES1
|
||||
]
|
||||
);
|
||||
|
||||
// Check that T also clears the substitution-done flag, matching t.
|
||||
// After s/// sets the flag, the first T sees a substitution so it does
|
||||
// not branch but still clears the flag; the second T then sees no
|
||||
// substitution and branches to :y. Reaching :y (CLEARED) rather than
|
||||
// falling through to :x (NOTCLEARED) proves the first T cleared the flag.
|
||||
check_output!(
|
||||
branch_no_sub_clears,
|
||||
[
|
||||
"-n",
|
||||
"-e",
|
||||
r#"
|
||||
s/^/^/
|
||||
Tx
|
||||
Ty
|
||||
:x
|
||||
s/^/NOTCLEARED /p
|
||||
b
|
||||
:y
|
||||
s/^/CLEARED /p
|
||||
"#,
|
||||
LINES1
|
||||
]
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn test_branch_no_sub_non_posix() {
|
||||
new_ucmd!()
|
||||
.args(&["--posix", "T"])
|
||||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_contains("invalid command code");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Text: a, c, i
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
CLEARED ^l1_1
|
||||
CLEARED ^l1_2
|
||||
CLEARED ^l1_3
|
||||
CLEARED ^l1_4
|
||||
CLEARED ^l1_5
|
||||
CLEARED ^l1_6
|
||||
CLEARED ^l1_7
|
||||
CLEARED ^l1_8
|
||||
CLEARED ^l1_9
|
||||
CLEARED ^l1_10
|
||||
CLEARED ^l1_11
|
||||
CLEARED ^l1_12
|
||||
CLEARED ^l1_13
|
||||
CLEARED ^l1_14
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
l1_1
|
||||
SUB l1_X
|
||||
l1_3
|
||||
l1_4
|
||||
l1_5
|
||||
l1_6
|
||||
l1_7
|
||||
l1_8
|
||||
l1_9
|
||||
l1_10
|
||||
l1_11
|
||||
SUB l1_1X
|
||||
l1_13
|
||||
l1_14
|
||||
Reference in new issue
Block a user