Skip to content

Commit fa8b38a

Browse files
authored
Merge pull request #206 from grisenti/main
awk: update implementation to match latest posix standard
2 parents b9c8a77 + 22bd929 commit fa8b38a

File tree

12 files changed

+248
-23
lines changed

12 files changed

+248
-23
lines changed

awk/src/compiler.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ lazy_static::lazy_static! {
139139
min_args: 1,
140140
max_args: 1,
141141
}),
142+
(Rule::fflush, BuiltinFunctionInfo {
143+
function: BuiltinFunction::FFlush,
144+
min_args: 0,
145+
max_args: 1,
146+
}),
142147
(Rule::system, BuiltinFunctionInfo {
143148
function: BuiltinFunction::System,
144149
min_args: 1,
@@ -1142,16 +1147,19 @@ impl Compiler {
11421147
let stmt = first_child(simple_stmt);
11431148
let stmt_line_col = stmt.line_col();
11441149
match stmt.as_rule() {
1145-
Rule::delete_element => {
1150+
Rule::array_delete => {
11461151
let mut inner = stmt.into_inner();
11471152
let name = inner.next().unwrap();
11481153
let get_instruction = self
11491154
.get_var(name.as_str(), locals)
11501155
.map_err(|msg| pest_error_from_span(name.as_span(), msg))?;
11511156
instructions.push(get_instruction, stmt_line_col);
1152-
let index = inner.next().unwrap();
1153-
self.compile_expr(index, instructions, locals)?;
1154-
instructions.push(OpCode::Delete, stmt_line_col);
1157+
if let Some(index) = inner.next() {
1158+
self.compile_expr(index, instructions, locals)?;
1159+
instructions.push(OpCode::DeleteElement, stmt_line_col);
1160+
} else {
1161+
instructions.push(OpCode::ClearArray, stmt_line_col);
1162+
}
11551163
}
11561164
Rule::expr => {
11571165
self.compile_expr(stmt, instructions, locals)?;
@@ -1451,6 +1459,10 @@ impl Compiler {
14511459
Rule::ut_for => self.compile_for(stmt, instructions, locals),
14521460
Rule::ut_foreach => self.compile_for_each(stmt, instructions, locals),
14531461
Rule::simple_statement => self.compile_simple_statement(stmt, instructions, locals),
1462+
Rule::nextfile => {
1463+
instructions.push(OpCode::NextFile, stmt.line_col());
1464+
Ok(())
1465+
}
14541466
Rule::next => {
14551467
instructions.push(OpCode::Next, stmt.line_col());
14561468
Ok(())
@@ -3022,6 +3034,12 @@ mod test {
30223034
assert_eq!(instructions, vec![OpCode::Next]);
30233035
}
30243036

3037+
#[test]
3038+
fn test_compile_nextfile() {
3039+
let (instructions, _) = compile_stmt("nextfile;");
3040+
assert_eq!(instructions, vec![OpCode::NextFile]);
3041+
}
3042+
30253043
#[test]
30263044
fn test_compile_exit() {
30273045
let (instructions, _) = compile_stmt("exit;");
@@ -3047,18 +3065,27 @@ mod test {
30473065
}
30483066

30493067
#[test]
3050-
fn test_compile_delete() {
3068+
fn test_compile_delete_element() {
30513069
let (instructions, _) = compile_stmt("delete a[1];");
30523070
assert_eq!(
30533071
instructions,
30543072
vec![
30553073
OpCode::GetGlobal(FIRST_GLOBAL_VAR),
30563074
OpCode::PushConstant(0),
3057-
OpCode::Delete,
3075+
OpCode::DeleteElement,
30583076
]
30593077
);
30603078
}
30613079

3080+
#[test]
3081+
fn test_compile_clear_array() {
3082+
let (instructions, _) = compile_stmt("delete a");
3083+
assert_eq!(
3084+
instructions,
3085+
vec![OpCode::GetGlobal(FIRST_GLOBAL_VAR), OpCode::ClearArray]
3086+
);
3087+
}
3088+
30623089
#[test]
30633090
fn test_compile_simple_print() {
30643091
let (instructions, constant) = compile_stmt("print 1;");
@@ -3885,6 +3912,8 @@ mod test {
38853912
r#"
38863913
BEGIN {
38873914
close("file");
3915+
fflush("file");
3916+
fflush();
38883917
system("ls");
38893918
}
38903919
"#,
@@ -3899,6 +3928,17 @@ mod test {
38993928
},
39003929
OpCode::Pop,
39013930
OpCode::PushConstant(1),
3931+
OpCode::CallBuiltin {
3932+
function: BuiltinFunction::FFlush,
3933+
argc: 1
3934+
},
3935+
OpCode::Pop,
3936+
OpCode::CallBuiltin {
3937+
function: BuiltinFunction::FFlush,
3938+
argc: 0
3939+
},
3940+
OpCode::Pop,
3941+
OpCode::PushConstant(2),
39023942
OpCode::CallBuiltin {
39033943
function: BuiltinFunction::System,
39043944
argc: 1,

awk/src/grammar.pest

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ builtin_func = _{
4646
| tolower
4747
| toupper
4848
| close
49+
| fflush
4950
| system
5051
}
5152

@@ -69,6 +70,7 @@ substr = { "substr" }
6970
tolower = { "tolower" }
7071
toupper = { "toupper" }
7172
close = { "close" }
73+
fflush = { "fflush" }
7274
system = { "system" }
7375

7476
keyword = {
@@ -161,31 +163,33 @@ ut_for = { "for" ~ "(" ~ simple_statement? ~ ";" ~ expr? ~ ";" ~ simple_stat
161163
ut_foreach = { "for" ~ "(" ~ name ~ in_op ~ name ~ ")" ~ opt_newline ~ unterminated_statement }
162164

163165
terminatable_statement = _{
164-
simple_statement
166+
nextfile
165167
| next
166168
| break_stmt
167169
| continue_stmt
168170
| exit_stmt
169171
| return_stmt
170172
| do_while
173+
| simple_statement
171174
}
172175

173176
do_while = { "do" ~ opt_newline ~ terminated_statement ~ "while" ~ "(" ~ expr ~ ")" }
174177
next = { "next" }
178+
nextfile = { "nextfile" }
175179
break_stmt = { "break" }
176180
continue_stmt = { "continue" }
177181

178182
return_stmt = { "return" ~ expr? }
179183
exit_stmt = { "exit" ~ expr? }
180184

181185
simple_statement = {
182-
delete_element
186+
array_delete
183187
| print_stmt
184188
| expr
185189
}
186190

187-
delete_element = {
188-
"delete" ~ name ~ "[" ~ expr ~ "]"
191+
array_delete = {
192+
"delete" ~ name ~ ("[" ~ expr ~ "]")?
189193
}
190194

191195
print_stmt = {

awk/src/interpreter/io.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,22 @@ impl WriteFiles {
224224
Ok(())
225225
}
226226

227+
pub fn flush_file(&mut self, filename: &str) -> bool {
228+
if let Some(file) = self.files.get_mut(filename) {
229+
file.flush().is_ok()
230+
} else {
231+
false
232+
}
233+
}
234+
235+
pub fn flush_all(&mut self) -> bool {
236+
let mut success = true;
237+
for file in self.files.values_mut() {
238+
success = success && file.flush().is_ok();
239+
}
240+
success
241+
}
242+
227243
pub fn close_file(&mut self, filename: &str) {
228244
self.files.remove(filename);
229245
}
@@ -288,6 +304,22 @@ impl WritePipes {
288304
Ok(())
289305
}
290306

307+
pub fn flush_file(&mut self, filename: &str) -> bool {
308+
if let Some(file) = self.pipes.get(filename) {
309+
unsafe { libc::fflush(*file) == 0 }
310+
} else {
311+
false
312+
}
313+
}
314+
315+
pub fn flush_all(&mut self) -> bool {
316+
let mut success = true;
317+
for file in self.pipes.values() {
318+
success = success && unsafe { libc::fflush(*file) == 0 };
319+
}
320+
success
321+
}
322+
291323
pub fn close_pipe(&mut self, filename: &str) {
292324
if let Some(file) = self.pipes.remove(filename) {
293325
unsafe {

0 commit comments

Comments
 (0)