Skip to content

Commit 2987f2a

Browse files
Working draft for capturing stdout in llvm
1 parent b17f6a3 commit 2987f2a

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

libraries/common/process.effekt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ extern def exit(errorCode: Int) at io: Nothing =
99
"""
1010
chez "(exit ${errorCode})"
1111

12+
// Subprocesses
13+
// ------------
14+
1215
extern jsNode """
1316
const { spawn } = require('node:child_process');
1417
"""
1518
extern llvm """
1619
declare %Pos @c_spawn_options_default()
20+
declare %Pos @c_spawn_options_on_stdout(%Pos, %Pos)
1721
declare %Pos @c_spawn(%Pos, %Pos, %Pos)
1822
"""
1923

@@ -36,14 +40,18 @@ extern def onStdout(opts: SpawnOptions, callback: String => Unit at {io, global}
3640
});
3741
};
3842
return old; })()"""
43+
llvm """
44+
%opts = call %Pos @c_spawn_options_on_stdout(%Pos ${opts}, %Pos ${callback})
45+
ret %Pos %opts
46+
"""
3947

4048
extern type PID
4149
extern def spawn(cmd: String, args: Array[String], options: SpawnOptions): PID =
4250
jsNode """(function() {
43-
let p = spawn(${cmd}, ${args}, ${options});
44-
${options}.onSpawn(p);
45-
return p;
46-
})()"""
51+
let p = spawn(${cmd}, ${args}, ${options});
52+
${options}.onSpawn(p);
53+
return p;
54+
})()"""
4755
llvm """
4856
%proc = call %Pos @c_spawn(%Pos ${cmd}, %Pos ${args}, %Pos ${options})
4957
ret %Pos %proc

libraries/llvm/io.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -735,10 +735,45 @@ struct Pos c_spawn_options_default() {
735735
return (struct Pos) { .tag = 0, .obj = options, };
736736
}
737737

738+
static void my_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
739+
(void)handle;
740+
buf->base = malloc(suggested_size);
741+
buf->len = suggested_size;
742+
}
743+
744+
typedef struct {
745+
struct Pos handler;
746+
} stdout_cb_closure_t;
747+
void stdout_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
748+
stdout_cb_closure_t* clos = (stdout_cb_closure_t*)(stream->data);
749+
if(nread >= 0) {
750+
struct Pos chunk = c_bytearray_construct(nread, (uint8_t*)(buf->base));
751+
sharePositive(clos->handler);
752+
sharePositive(chunk);
753+
run_Pos(clos->handler, chunk);
754+
} else {
755+
uv_read_stop(stream);
756+
erasePositive(clos->handler);
757+
free(clos);
758+
}
759+
}
760+
struct Pos c_spawn_options_on_stdout(struct Pos opts, struct Pos callback) {
761+
uv_process_options_t* options = (uv_process_options_t*)opts.obj;
762+
options->stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
763+
uv_pipe_t* pipe = (uv_pipe_t*)malloc(sizeof(uv_pipe_t));
764+
uv_pipe_init(uv_default_loop(), pipe, 1);
765+
options->stdio[1].data.stream = (uv_stream_t*)pipe;
766+
stdout_cb_closure_t* clos = (stdout_cb_closure_t*)malloc(sizeof(stdout_cb_closure_t));
767+
clos->handler = callback;
768+
pipe->data = clos;
769+
return opts;
770+
}
771+
738772
void on_close(uv_handle_t* handle) {
739773
free(handle);
740774
}
741775
void on_exit(uv_process_t* proc, int64_t exit_status, int term_signal) {
776+
(void)term_signal; (void)exit_status;
742777
char** _args = (char**)proc->data;
743778
if (_args) {
744779
for(int i = 0; _args[i] != NULL; i++) {
@@ -754,15 +789,16 @@ struct Pos c_spawn(struct Pos cmd, struct Pos args, struct Pos options) {
754789
uv_process_t* proc = (uv_process_t*)malloc(sizeof(uv_process_t));
755790

756791
// command
757-
opts->file = (char*)c_bytearray_data(cmd);
792+
char* cmd_s = c_bytearray_into_nullterminated_string(cmd);
793+
opts->file = cmd_s;
758794

759795
// args
760796
int _argc = (int)((uint64_t*)args.obj)[2];
761797
char** _args = (char**)malloc((2 + _argc) * sizeof(char*));
762798
struct Pos* _argv = (struct Pos*)(((uint64_t*)args.obj) + 3);
763-
_args[0] = strdup(opts->file);
799+
_args[0] = cmd_s;
764800
for(int i = 0; i < _argc; i++) {
765-
_args[i + 1] = strdup((char*)c_bytearray_data(_argv[i]));
801+
_args[i + 1] = c_bytearray_into_nullterminated_string(_argv[i]);
766802
}
767803
erasePositive(args);
768804
_args[_argc + 1] = NULL;
@@ -773,6 +809,10 @@ struct Pos c_spawn(struct Pos cmd, struct Pos args, struct Pos options) {
773809

774810
// spawn process
775811
int err = uv_spawn(uv_default_loop(), proc, opts);
812+
813+
if(opts->stdio[1].data.stream)
814+
uv_read_start((uv_stream_t*)(opts->stdio[1].data.stream), my_alloc_cb, stdout_cb);
815+
776816
erasePositive(options);
777817
if(err) {
778818
printf("%s\n", uv_strerror(err));

0 commit comments

Comments
 (0)