Skip to content

Commit d980254

Browse files
committed
Add address range support for a, i and = and check for invalid POSIX flag usage with GNU only extensions
- Add a context parameter in get_verified_cmd_spec function and update the relative test cases - Add integration tests for address range
1 parent db58849 commit d980254

7 files changed

Lines changed: 116 additions & 8 deletions

File tree

src/sed/command.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ pub struct ProcessingContext {
7070
pub append_elements: Vec<AppendElement>,
7171
}
7272

73+
impl ProcessingContext {
74+
/// Check if POSIX extension is enabled
75+
pub fn is_posix_enabled(&self) -> bool {
76+
self.posix
77+
}
78+
}
79+
7380
#[derive(Clone, Debug)]
7481
/// Elements that shall be appended at the end of each command processing cycle
7582
pub enum AppendElement {

src/sed/compiler.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,14 @@ fn compile_sequence(
264264
let mut cmd = Rc::new(RefCell::new(Command::at_position(lines, line)));
265265
let n_addr = compile_address_range(lines, line, &mut cmd, context)?;
266266
line.eat_spaces();
267-
let mut cmd_spec = get_verified_cmd_spec(lines, line, n_addr)?;
267+
let mut cmd_spec = get_verified_cmd_spec(lines, line, n_addr, context)?;
268268

269269
// Compile the command according to its specification.
270270
let mut cmd_mut = cmd.borrow_mut();
271271
cmd_mut.code = line.current();
272272
match (cmd_spec.handler)(lines, line, &mut cmd_mut, context)? {
273273
CommandHandling::GetNext => {
274-
cmd_spec = get_verified_cmd_spec(lines, line, n_addr)?;
274+
cmd_spec = get_verified_cmd_spec(lines, line, n_addr, context)?;
275275
cmd_mut.code = line.current();
276276
(cmd_spec.handler)(lines, line, &mut cmd_mut, context)?;
277277
}
@@ -1175,6 +1175,7 @@ fn get_verified_cmd_spec(
11751175
lines: &ScriptLineProvider,
11761176
line: &ScriptCharProvider,
11771177
n_addr: usize,
1178+
context: &ProcessingContext,
11781179
) -> UResult<CommandSpec> {
11791180
if line.eol() {
11801181
return compilation_error(lines, line, "command expected");
@@ -1194,9 +1195,18 @@ fn get_verified_cmd_spec(
11941195
);
11951196
}
11961197

1198+
if context.is_posix_enabled() && is_gnu_extension(ch, n_addr) {
1199+
return compilation_error(lines, line, "command only uses one address");
1200+
}
1201+
11971202
Ok(cmd_spec)
11981203
}
11991204

1205+
/// Check if the command usage is a GNU extension (not allowed in POSIX mode)
1206+
fn is_gnu_extension(cmd_code: char, n_addr: usize) -> bool {
1207+
matches!(cmd_code, 'a' | 'i' | '=' | 'l' | 'q' | 'r') && n_addr == 2
1208+
}
1209+
12001210
// Look up a command addresses and handler by its command code.
12011211
fn get_cmd_spec(
12021212
lines: &ScriptLineProvider,
@@ -1209,7 +1219,7 @@ fn get_cmd_spec(
12091219
handler: compile_negation_command,
12101220
}),
12111221
'=' => Ok(CommandSpec {
1212-
n_addr: 1,
1222+
n_addr: 2,
12131223
handler: compile_empty_command,
12141224
}),
12151225
':' => Ok(CommandSpec {
@@ -1225,7 +1235,7 @@ fn get_cmd_spec(
12251235
handler: compile_end_group_command,
12261236
}),
12271237
'a' | 'i' => Ok(CommandSpec {
1228-
n_addr: 1,
1238+
n_addr: 2,
12291239
handler: compile_text_command,
12301240
}),
12311241
'b' | 't' => Ok(CommandSpec {
@@ -1382,7 +1392,7 @@ mod tests {
13821392
fn test_missing_command_character() {
13831393
let lines = ScriptLineProvider::with_active_state("test.sed", 1);
13841394
let line = char_provider_from("");
1385-
let result = get_verified_cmd_spec(&lines, &line, 0);
1395+
let result = get_verified_cmd_spec(&lines, &line, 0, &ctx());
13861396

13871397
assert!(result.is_err());
13881398
let msg = result.unwrap_err().to_string();
@@ -1393,7 +1403,7 @@ mod tests {
13931403
fn test_invalid_command_character() {
13941404
let lines = ScriptLineProvider::with_active_state("script.sed", 2);
13951405
let line = char_provider_from("@");
1396-
let result = get_verified_cmd_spec(&lines, &line, 0);
1406+
let result = get_verified_cmd_spec(&lines, &line, 0, &ctx());
13971407

13981408
assert!(result.is_err());
13991409
let msg = result.unwrap_err().to_string();
@@ -1404,7 +1414,7 @@ mod tests {
14041414
fn test_too_many_addresses() {
14051415
let lines = ScriptLineProvider::with_active_state("input.sed", 3);
14061416
let line = char_provider_from("q"); // q takes one address
1407-
let result = get_verified_cmd_spec(&lines, &line, 2);
1417+
let result = get_verified_cmd_spec(&lines, &line, 2, &ctx());
14081418

14091419
assert!(result.is_err());
14101420
let msg = result.unwrap_err().to_string();
@@ -1417,7 +1427,7 @@ mod tests {
14171427
fn test_valid_command_spec() {
14181428
let lines = ScriptLineProvider::with_active_state("input.sed", 4);
14191429
let line = char_provider_from("a"); // valid command
1420-
let result = get_verified_cmd_spec(&lines, &line, 1);
1430+
let result = get_verified_cmd_spec(&lines, &line, 1, &ctx());
14211431

14221432
assert!(result.is_ok());
14231433
let spec = result.unwrap();

tests/by-util/test_sed.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,30 @@ tb"#,
581581

582582
// Check both POSIX and GNU parsing routines.
583583

584+
check_output_posix!(
585+
text_simple_insert,
586+
[
587+
"-e",
588+
r#"
589+
2,4i\
590+
extra
591+
"#,
592+
LINES1
593+
]
594+
);
595+
596+
check_output_posix!(
597+
text_simple_append,
598+
[
599+
"-e",
600+
r#"
601+
2,4a\
602+
extra
603+
"#,
604+
LINES1
605+
]
606+
);
607+
584608
check_output_posix!(
585609
text_insert_quit,
586610
[
@@ -772,6 +796,8 @@ fn write_two_files() -> std::io::Result<()> {
772796
// =, l commands
773797
check_output!(number_continuous, ["/l2_/=", LINES1, LINES2]);
774798
check_output!(number_separate, ["-s", "/l._8/=", LINES1, LINES2]);
799+
check_output!(number_range, ["-e", "10,12=", LINES1]); // Correct output but test is not passing
800+
check_output!(number_range_out_of_bounds, ["-e", "47,60=", LINES1]);
775801

776802
check_output!(list_ascii, ["-n", "l 60", "input/ascii"]);
777803
check_output!(list_empty, ["-n", "l 60", "input/empty"]);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
l1_1
2+
l1_2
3+
l1_3
4+
l1_4
5+
l1_5
6+
l1_6
7+
l1_7
8+
l1_8
9+
l1_9
10+
10
11+
l1_10
12+
11
13+
l1_11
14+
12
15+
l1_12
16+
l1_13
17+
l1_14
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
l1_1
2+
l1_2
3+
l1_3
4+
l1_4
5+
l1_5
6+
l1_6
7+
l1_7
8+
l1_8
9+
l1_9
10+
l1_10
11+
l1_11
12+
l1_12
13+
l1_13
14+
l1_14
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
l1_1
2+
l1_2
3+
extra
4+
l1_3
5+
extra
6+
l1_4
7+
extra
8+
l1_5
9+
l1_6
10+
l1_7
11+
l1_8
12+
l1_9
13+
l1_10
14+
l1_11
15+
l1_12
16+
l1_13
17+
l1_14
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
l1_1
2+
extra
3+
l1_2
4+
extra
5+
l1_3
6+
extra
7+
l1_4
8+
l1_5
9+
l1_6
10+
l1_7
11+
l1_8
12+
l1_9
13+
l1_10
14+
l1_11
15+
l1_12
16+
l1_13
17+
l1_14

0 commit comments

Comments
 (0)