[m-rev.] for review: extras/posix: Don't abuse Mercury arrays for exec().

Peter Wang novalazy at gmail.com
Sun Mar 24 14:14:38 AEDT 2019


extras/posix/posix.exec.m:
    Allocate arrays of the correct type instead of passing Mercury array
    elements as (char **).
---
 extras/posix/posix.exec.m | 64 ++++++++++++++++++++++++++-------------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/extras/posix/posix.exec.m b/extras/posix/posix.exec.m
index 17a6930e4..bb336dc00 100644
--- a/extras/posix/posix.exec.m
+++ b/extras/posix/posix.exec.m
@@ -32,19 +32,52 @@
 
 :- implementation.
 
-:- import_module array.
 :- import_module pair.
 
 :- pragma foreign_decl("C", "#include <unistd.h>").
 
 %-----------------------------------------------------------------------------%
 
+:- type string_array.
+
+:- pragma foreign_type("C", string_array, "char **").
+
+:- pred make_string_array(list(string)::in, string_array::out) is det.
+
+:- pragma foreign_proc("C",
+    make_string_array(List::in, Array::out),
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    MR_Word ptr;
+    size_t  len;
+    size_t  i;
+
+    len = 0;
+    ptr = List;
+    while (! MR_list_is_empty(ptr)) {
+        len++;
+        ptr = MR_list_tail(ptr);
+    }
+
+    Array = MR_GC_NEW_ARRAY_ATTRIB(char *, len + 1, MR_ALLOC_ID);
+
+    i = 0;
+    ptr = List;
+    while (! MR_list_is_empty(ptr)) {
+        Array[i] = (char *) MR_list_head(ptr);
+        ptr = MR_list_tail(ptr);
+        i++;
+    }
+
+    Array[i] = NULL;
+").
+
+%-----------------------------------------------------------------------------%
+
 exec(Command, Args, Env, Result, !IO) :-
-    exec0(Command,
-        array(Args ++ [null]),
-        array(list.map(variable, map.to_assoc_list(Env)) ++ [null]),
-        !IO
-    ),
+    make_string_array(Args, ArgsArray),
+    make_string_array(map(variable, map.to_assoc_list(Env)), EnvArray),
+    exec0(Command, ArgsArray, EnvArray, !IO),
     errno(Err, !IO),
     Result = error(Err).
 
@@ -52,27 +85,16 @@ exec(Command, Args, Env, Result, !IO) :-
 
 variable(Name - Value) = Name ++ "=" ++ Value.
 
-:- func null = string.
-:- pragma foreign_proc("C",
-    null = (Null::out),
-    [promise_pure, will_not_call_mercury, thread_safe],
-"
-    Null = NULL;
-").
-
-:- pred exec0(string::in,
-    array(string)::array_ui, array(string)::array_ui,
-    io::di, io::uo) is det.
+:- pred exec0(string::in, string_array::in, string_array::in, io::di, io::uo)
+    is det.
 :- pragma foreign_proc("C",
-    exec0(Command::in, Args::array_ui, Env::array_ui, _IO0::di, _IO::uo),
+    exec0(Command::in, ArgsArray::in, EnvArray::in, _IO0::di, _IO::uo),
     [promise_pure, will_not_call_mercury, tabled_for_io],
 "
     int ret;
 
     do {
-        ret = execve(Command,
-            ((MR_ArrayType *)Args)->elements,
-            ((MR_ArrayType *)Env)->elements);
+        ret = execve(Command, ArgsArray, EnvArray);
     } while (ret == -1 && MR_is_eintr(errno));
 ").
 
-- 
2.21.0



More information about the reviews mailing list