]> Repositorios git - scryer-prolog.git/commitdiff
ADDED: file_modification_time/2, obtaining a time stamp.
authorMarkus Triska <[email protected]>
Thu, 16 Jul 2020 20:56:10 +0000 (22:56 +0200)
committerMarkus Triska <[email protected]>
Thu, 16 Jul 2020 21:40:03 +0000 (23:40 +0200)
This addresses a remaining aspect of #511.

src/clause_types.rs
src/lib/files.pl
src/machine/system_calls.rs

index c45466232c6fd83f7c0d809cd9fd50674cdfa3f0..97aac77a508ca5a26a30cd26081c109c9c461dfe 100644 (file)
@@ -179,6 +179,7 @@ pub enum SystemClauseType {
     DeleteFile,
     WorkingDirectory,
     PathCanonical,
+    FileModificationTime,
     DeleteAttribute,
     DeleteHeadAttribute,
     DynamicModuleResolution(usize),
@@ -347,6 +348,7 @@ impl SystemClauseType {
             &SystemClauseType::DeleteFile => clause_name!("$delete_file"),
             &SystemClauseType::WorkingDirectory => clause_name!("$working_directory"),
             &SystemClauseType::PathCanonical => clause_name!("$path_canonical"),
+            &SystemClauseType::FileModificationTime => clause_name!("$file_modification_time"),
             &SystemClauseType::REPL(REPLCodePtr::CompileBatch) => clause_name!("$compile_batch"),
             &SystemClauseType::REPL(REPLCodePtr::UseModule) => clause_name!("$use_module"),
             &SystemClauseType::REPL(REPLCodePtr::UseQualifiedModule) => {
@@ -684,6 +686,7 @@ impl SystemClauseType {
             ("$delete_file", 1) => Some(SystemClauseType::DeleteFile),
             ("$working_directory", 2) => Some(SystemClauseType::WorkingDirectory),
             ("$path_canonical", 2) => Some(SystemClauseType::PathCanonical),
+            ("$file_modification_time", 2) => Some(SystemClauseType::FileModificationTime),
             ("$use_module", 1) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
             ("$use_module_from_file", 1) =>
                     Some(SystemClauseType::REPL(REPLCodePtr::UseModuleFromFile)),
index 69847b2939f633a8526bad8fd8d676dd0d9cc264..481ed08d8bd9f4897f24f3bde5bd93d95863be96 100644 (file)
                   delete_file/1,
                   make_directory/1,
                   working_directory/2,
-                  path_canonical/2]).
+                  path_canonical/2,
+                  file_modification_time/2]).
 
 :- use_module(library(error)).
 :- use_module(library(lists)).
+:- use_module(library(charsio)).
 
 list_of_chars(Cs) :-
         must_be(list, Cs),
@@ -119,3 +121,12 @@ path_canonical(Ps, Cs) :-
         maplist(must_be(character), Ps),
         can_be(list, Cs),
         '$path_canonical'(Ps, Cs).
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+   T is the modification time of File.
+   T is a time stamp, suitable for use in format_time//2 in library(time).
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+file_modification_time(File, T) :-
+        '$file_modification_time'(File, T0),
+        read_term_from_chars(T0, T).
index 2f357873b808effc65be0d5f424530f54aead625..6c8ee3298e6c669335da645533f8bda416a76a0d 100644 (file)
@@ -943,6 +943,22 @@ impl MachineState {
                     }
                 }
             }
+            &SystemClauseType::FileModificationTime => {
+                let file = self.heap_pstr_iter(self[temp_v!(1)]).to_string();
+
+                if let Ok(md) = fs::metadata(file) {
+                    if let Ok(time) = md.modified() {
+                        let chars = self.systemtime_to_timestamp(time);
+                        self.unify(self[temp_v!(2)], chars);
+                    } else {
+                        self.fail = true;
+                        return Ok(());
+                    }
+                } else {
+                    self.fail = true;
+                    return Ok(());
+                }
+            }
             &SystemClauseType::AtEndOfExpansion => {
                 if self.cp == LocalCodePtr::TopLevel(0, 0) {
                     self.at_end_of_expansion = true;
@@ -3227,18 +3243,7 @@ impl MachineState {
                 self.unify(a1, addr);
             }
             &SystemClauseType::CurrentTime => {
-                let system_time = SystemTime::now();
-                let datetime: DateTime<Local> = system_time.into();
-
-                let mut fstr = "[".to_string();
-                let specifiers = vec!["d","m","Y","y","H","M","S","b","B","a","A","w","u","U","W","j","D","x","v"];
-                for spec in specifiers {
-                    fstr.push_str(&format!("'{}'=\"%{}\", ", spec, spec).to_string());
-                }
-                fstr.push_str("finis].");
-                let str = { let s = datetime.format(&fstr).to_string();
-                            self.heap.put_complete_string(&s)
-                          };
+                let str = self.systemtime_to_timestamp(SystemTime::now());
                 self.unify(self[temp_v!(1)], str);
             }
             &SystemClauseType::OpDeclaration => {
@@ -5718,6 +5723,23 @@ impl MachineState {
         return_from_clause!(self.last_call, self)
     }
 
+    pub(super)
+    fn systemtime_to_timestamp(
+        &mut self,
+        system_time: SystemTime
+    ) -> Addr {
+        let datetime: DateTime<Local> = system_time.into();
+
+        let mut fstr = "[".to_string();
+        let specifiers = vec!["d","m","Y","y","H","M","S","b","B","a","A","w","u","U","W","j","D","x","v"];
+        for spec in specifiers {
+            fstr.push_str(&format!("'{}'=\"%{}\", ", spec, spec).to_string());
+        }
+        fstr.push_str("finis].");
+        let s = datetime.format(&fstr).to_string();
+        self.heap.put_complete_string(&s)
+    }
+
     pub(super)
     fn string_encoding_bytes(
         &mut self,