From c6aa2068e2068ec68673b9b91dc7b68445c48365 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Adri=C3=A1n=20Arroyo=20Calle?= Date: Fri, 9 Dec 2022 23:46:00 +0100 Subject: [PATCH] Add predicate copy_file/2 in library(files) --- build/instructions_template.rs | 4 ++++ src/lib/files.pl | 10 ++++++++-- src/machine/dispatch.rs | 8 ++++++++ src/machine/system_calls.rs | 13 +++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index bc1ca703..f8cce3f4 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -262,6 +262,8 @@ enum SystemClauseType { DeleteFile, #[strum_discriminants(strum(props(Arity = "2", Name = "$rename_file")))] RenameFile, + #[strum_discriminants(strum(props(Arity = "2", Name = "$copy_file")))] + CopyFile, #[strum_discriminants(strum(props(Arity = "2", Name = "$working_directory")))] WorkingDirectory, #[strum_discriminants(strum(props(Arity = "1", Name = "$delete_directory")))] @@ -1611,6 +1613,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::CallMakeDirectoryPath(_) | &Instruction::CallDeleteFile(_) | &Instruction::CallRenameFile(_) | + &Instruction::CallCopyFile(_) | &Instruction::CallWorkingDirectory(_) | &Instruction::CallDeleteDirectory(_) | &Instruction::CallPathCanonical(_) | @@ -1825,6 +1828,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::ExecuteMakeDirectoryPath(_) | &Instruction::ExecuteDeleteFile(_) | &Instruction::ExecuteRenameFile(_) | + &Instruction::ExecuteCopyFile(_) | &Instruction::ExecuteWorkingDirectory(_) | &Instruction::ExecuteDeleteDirectory(_) | &Instruction::ExecutePathCanonical(_) | diff --git a/src/lib/files.pl b/src/lib/files.pl index 1e856ff1..7d0afeda 100644 --- a/src/lib/files.pl +++ b/src/lib/files.pl @@ -70,8 +70,9 @@ In this library, directories and files are represented as file_exists/1, directory_exists/1, delete_file/1, - rename_file/2, - delete_directory/1, + rename_file/2, + copy_file/2, + delete_directory/1, make_directory/1, make_directory_path/1, working_directory/2, @@ -150,6 +151,11 @@ rename_file(File, Renamed) :- must_be(chars, Renamed), '$rename_file'(File, Renamed). +copy_file(File, Copied) :- + file_must_exist(File, copy_file/2), + must_be(chars, Copied), + '$copy_file'(File, Copied). + %% delete_directory(+Directory). % % Succeeds if Directory is deleted from the current system. diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index ee57a83e..1cc1d365 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -3533,6 +3533,14 @@ impl Machine { self.rename_file(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } + &Instruction::CallCopyFile(_) => { + self.copy_file(); + step_or_fail!(self, self.machine_st.p += 1); + } + &Instruction::ExecuteCopyFile(_) => { + self.copy_file(); + step_or_fail!(self, self.machine_st.p = self.machine_st.cp); + } &Instruction::CallWorkingDirectory(_) => { try_or_throw!(self.machine_st, self.working_directory()); step_or_fail!(self, self.machine_st.p += 1); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 275c0ce7..515baba6 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1653,6 +1653,19 @@ impl Machine { self.machine_st.fail = true; } + #[inline(always)] + pub(crate) fn copy_file(&mut self) { + if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) { + if let Some(copied) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) { + if fs::copy(file.as_str(), copied.as_str()).is_ok() { + return; + } + } + } + + self.machine_st.fail = true; + } + #[inline(always)] pub(crate) fn delete_directory(&mut self) { if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) { -- 2.54.0