mirror of
https://github.com/janet-lang/janet
synced 2025-04-27 05:03:14 +00:00
Merge branch 'master' into ev
This commit is contained in:
commit
95f4bd8e23
@ -2,6 +2,8 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## Unreleased - ???
|
## Unreleased - ???
|
||||||
|
- Add :pipe option to `os/spawn`.
|
||||||
|
- Fix docstring typos.
|
||||||
|
|
||||||
## 1.12.1 - 2020-09-07
|
## 1.12.1 - 2020-09-07
|
||||||
- Make `zero?`, `one?`, `pos?`, and `neg?` polymorphic.
|
- Make `zero?`, `one?`, `pos?`, and `neg?` polymorphic.
|
||||||
|
@ -799,6 +799,10 @@ FILE *janet_getfile(const Janet *argv, int32_t n, int *flags) {
|
|||||||
return iof->file;
|
return iof->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JanetFile *janet_makejfile(FILE *f, int flags) {
|
||||||
|
return makef(f, flags);
|
||||||
|
}
|
||||||
|
|
||||||
Janet janet_makefile(FILE *f, int flags) {
|
Janet janet_makefile(FILE *f, int flags) {
|
||||||
return janet_wrap_abstract(makef(f, flags));
|
return janet_wrap_abstract(makef(f, flags));
|
||||||
}
|
}
|
||||||
|
@ -414,6 +414,36 @@ static Janet os_proc_kill(int32_t argc, Janet *argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create piped file for os/execute and os/spawn. */
|
||||||
|
static JanetFile *make_pipes(JanetHandle *handle, int reverse) {
|
||||||
|
JanetHandle handles[2];
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
if (!CreatePipe(handles, handles + 1, NULL, 0)) janet_panic("failed to create pipe");
|
||||||
|
if (reverse) {
|
||||||
|
JanetHandle temp = handles[0];
|
||||||
|
handles[0] = handles[1];
|
||||||
|
handles[1] = temp;
|
||||||
|
}
|
||||||
|
*handle = handles[1];
|
||||||
|
int fd = _open_osfhandle((intptr_t) handles[0], reverse ? _O_WRONLY : _O_RDONLY);
|
||||||
|
if (fd == -1) janet_panic("could not create file for piping");
|
||||||
|
FILE *f = _fdopen(fd, reverse ? "w" : "r");
|
||||||
|
if (NULL == f) janet_panic(strerror(errno));
|
||||||
|
return janet_makejfile(f, reverse ? JANET_FILE_WRITE : JANET_FILE_READ);
|
||||||
|
#else
|
||||||
|
if (pipe(handles)) janet_panic(strerror(errno));
|
||||||
|
if (reverse) {
|
||||||
|
JanetHandle temp = handles[0];
|
||||||
|
handles[0] = handles[1];
|
||||||
|
handles[1] = temp;
|
||||||
|
}
|
||||||
|
*handle = handles[1];
|
||||||
|
FILE *f = fdopen(handles[0], reverse ? "w" : "r");
|
||||||
|
if (NULL == f) janet_panic(strerror(errno));
|
||||||
|
return janet_makejfile(f, reverse ? JANET_FILE_WRITE : JANET_FILE_READ);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static const JanetMethod proc_methods[] = {
|
static const JanetMethod proc_methods[] = {
|
||||||
{"wait", os_proc_wait},
|
{"wait", os_proc_wait},
|
||||||
{"kill", os_proc_kill},
|
{"kill", os_proc_kill},
|
||||||
@ -470,6 +500,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) {
|
|||||||
|
|
||||||
/* Optional stdio redirections */
|
/* Optional stdio redirections */
|
||||||
JanetFile *new_in = NULL, *new_out = NULL, *new_err = NULL;
|
JanetFile *new_in = NULL, *new_out = NULL, *new_err = NULL;
|
||||||
|
JanetHandle pipe_in = JANET_HANDLE_NONE, pipe_out = JANET_HANDLE_NONE, pipe_err = JANET_HANDLE_NONE;
|
||||||
|
|
||||||
/* Get optional redirections */
|
/* Get optional redirections */
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
@ -477,9 +508,21 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) {
|
|||||||
Janet maybe_stdin = janet_dictionary_get(tab.kvs, tab.cap, janet_ckeywordv("in"));
|
Janet maybe_stdin = janet_dictionary_get(tab.kvs, tab.cap, janet_ckeywordv("in"));
|
||||||
Janet maybe_stdout = janet_dictionary_get(tab.kvs, tab.cap, janet_ckeywordv("out"));
|
Janet maybe_stdout = janet_dictionary_get(tab.kvs, tab.cap, janet_ckeywordv("out"));
|
||||||
Janet maybe_stderr = janet_dictionary_get(tab.kvs, tab.cap, janet_ckeywordv("err"));
|
Janet maybe_stderr = janet_dictionary_get(tab.kvs, tab.cap, janet_ckeywordv("err"));
|
||||||
if (!janet_checktype(maybe_stdin, JANET_NIL)) new_in = janet_getjfile(&maybe_stdin, 0);
|
if (janet_keyeq(maybe_stdin, "pipe")) {
|
||||||
if (!janet_checktype(maybe_stdout, JANET_NIL)) new_out = janet_getjfile(&maybe_stdout, 0);
|
new_in = make_pipes(&pipe_in, 1);
|
||||||
if (!janet_checktype(maybe_stderr, JANET_NIL)) new_err = janet_getjfile(&maybe_stderr, 0);
|
} else if (!janet_checktype(maybe_stdin, JANET_NIL)) {
|
||||||
|
new_in = janet_getjfile(&maybe_stdin, 0);
|
||||||
|
}
|
||||||
|
if (janet_keyeq(maybe_stdout, "pipe")) {
|
||||||
|
new_out = make_pipes(&pipe_out, 0);
|
||||||
|
} else if (!janet_checktype(maybe_stdout, JANET_NIL)) {
|
||||||
|
new_out = janet_getjfile(&maybe_stdout, 0);
|
||||||
|
}
|
||||||
|
if (janet_keyeq(maybe_stderr, "err")) {
|
||||||
|
new_err = make_pipes(&pipe_err, 0);
|
||||||
|
} else if (!janet_checktype(maybe_stderr, JANET_NIL)) {
|
||||||
|
new_err = janet_getjfile(&maybe_stderr, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Result */
|
/* Result */
|
||||||
@ -502,9 +545,24 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) {
|
|||||||
const char *path = (const char *) janet_unwrap_string(exargs.items[0]);
|
const char *path = (const char *) janet_unwrap_string(exargs.items[0]);
|
||||||
|
|
||||||
/* Do IO redirection */
|
/* Do IO redirection */
|
||||||
startupInfo.hStdInput = (HANDLE) _get_osfhandle((new_in == NULL) ? 0 : _fileno(new_in->file));
|
|
||||||
startupInfo.hStdOutput = (HANDLE) _get_osfhandle((new_out == NULL) ? 1 : _fileno(new_out->file));
|
if (pipe_in != JANET_HANDLE_NONE) {
|
||||||
startupInfo.hStdError = (HANDLE) _get_osfhandle((new_err == NULL) ? 2 : _fileno(new_err->file));
|
startupInfo.hStdInput = pipe_in;
|
||||||
|
} else if (new_in != NULL) {
|
||||||
|
startupInfo.hStdInput = (HANDLE) _get_osfhandle(_fileno(new_in->file));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipe_out != JANET_HANDLE_NONE) {
|
||||||
|
startupInfo.hStdInput = pipe_out;
|
||||||
|
} else if (new_out != NULL) {
|
||||||
|
startupInfo.hStdOutput = (HANDLE) _get_osfhandle(_fileno(new_out->file));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipe_err != JANET_HANDLE_NONE) {
|
||||||
|
startupInfo.hStdInput = pipe_err;
|
||||||
|
} else if (new_err != NULL) {
|
||||||
|
startupInfo.hStdError = (HANDLE) _get_osfhandle(_fileno(new_err->file));
|
||||||
|
}
|
||||||
|
|
||||||
/* Use _spawn family of functions. */
|
/* Use _spawn family of functions. */
|
||||||
/* Windows docs say do this before any spawns. */
|
/* Windows docs say do this before any spawns. */
|
||||||
@ -524,6 +582,10 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) {
|
|||||||
janet_panic("failed to create process");
|
janet_panic("failed to create process");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pipe_in != JANET_HANDLE_NONE) CloseHandle(pipe_in);
|
||||||
|
if (pipe_out != JANET_HANDLE_NONE) CloseHandle(pipe_out);
|
||||||
|
if (pipe_err != JANET_HANDLE_NONE) CloseHandle(pipe_err);
|
||||||
|
|
||||||
pHandle = processInfo.hProcess;
|
pHandle = processInfo.hProcess;
|
||||||
tHandle = processInfo.hThread;
|
tHandle = processInfo.hThread;
|
||||||
|
|
||||||
@ -559,13 +621,19 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) {
|
|||||||
/* Posix spawn setup */
|
/* Posix spawn setup */
|
||||||
posix_spawn_file_actions_t actions;
|
posix_spawn_file_actions_t actions;
|
||||||
posix_spawn_file_actions_init(&actions);
|
posix_spawn_file_actions_init(&actions);
|
||||||
if (new_in != NULL) {
|
if (pipe_in != JANET_HANDLE_NONE) {
|
||||||
|
posix_spawn_file_actions_adddup2(&actions, pipe_in, 0);
|
||||||
|
} else if (new_in != NULL) {
|
||||||
posix_spawn_file_actions_adddup2(&actions, fileno(new_in->file), 0);
|
posix_spawn_file_actions_adddup2(&actions, fileno(new_in->file), 0);
|
||||||
}
|
}
|
||||||
if (new_out != NULL) {
|
if (pipe_out != JANET_HANDLE_NONE) {
|
||||||
|
posix_spawn_file_actions_adddup2(&actions, pipe_out, 1);
|
||||||
|
} else if (new_out != NULL) {
|
||||||
posix_spawn_file_actions_adddup2(&actions, fileno(new_out->file), 1);
|
posix_spawn_file_actions_adddup2(&actions, fileno(new_out->file), 1);
|
||||||
}
|
}
|
||||||
if (new_err != NULL) {
|
if (pipe_err != JANET_HANDLE_NONE) {
|
||||||
|
posix_spawn_file_actions_adddup2(&actions, pipe_err, 2);
|
||||||
|
} else if (new_err != NULL) {
|
||||||
posix_spawn_file_actions_adddup2(&actions, fileno(new_err->file), 2);
|
posix_spawn_file_actions_adddup2(&actions, fileno(new_err->file), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,6 +650,10 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) {
|
|||||||
|
|
||||||
posix_spawn_file_actions_destroy(&actions);
|
posix_spawn_file_actions_destroy(&actions);
|
||||||
|
|
||||||
|
if (pipe_in != JANET_HANDLE_NONE) close(pipe_in);
|
||||||
|
if (pipe_out != JANET_HANDLE_NONE) close(pipe_out);
|
||||||
|
if (pipe_err != JANET_HANDLE_NONE) close(pipe_err);
|
||||||
|
|
||||||
if (use_environ) {
|
if (use_environ) {
|
||||||
janet_unlock_environ();
|
janet_unlock_environ();
|
||||||
}
|
}
|
||||||
@ -1554,6 +1626,11 @@ static const JanetReg os_cfuns[] = {
|
|||||||
"env is a table or struct mapping environment variables to values. It can also "
|
"env is a table or struct mapping environment variables to values. It can also "
|
||||||
"contain the keys :in, :out, and :err, which allow redirecting stdio in the subprocess. "
|
"contain the keys :in, :out, and :err, which allow redirecting stdio in the subprocess. "
|
||||||
"These arguments should be core/file values. "
|
"These arguments should be core/file values. "
|
||||||
|
"One can also pass in the :pipe keyword "
|
||||||
|
"for these arguments to create files that will read (for :err and :out) or write (for :in) "
|
||||||
|
"to the file descriptor of the subprocess. This is only useful in os/spawn, which takes "
|
||||||
|
"the same parameters as os/execute, but will return an object that contains references to these "
|
||||||
|
"files via (return-value :in), (return-value :out), and (return-value :err). "
|
||||||
"Returns the exit status of the program.")
|
"Returns the exit status of the program.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -724,15 +724,18 @@ static const JanetReg threadlib_cfuns[] = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"thread/send", cfun_thread_send,
|
"thread/send", cfun_thread_send,
|
||||||
JDOC("(thread/send thread msg)\n\n"
|
JDOC("(thread/send thread msgi &opt timeout)\n\n"
|
||||||
"Send a message to the thread. This will never block and returns thread immediately. "
|
"Send a message to the thread. By default, the timeout is 1 second, but an optional timeout "
|
||||||
|
"in seconds can be provided. Use math/inf for no timeout. "
|
||||||
"Will throw an error if there is a problem sending the message.")
|
"Will throw an error if there is a problem sending the message.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"thread/receive", cfun_thread_receive,
|
"thread/receive", cfun_thread_receive,
|
||||||
JDOC("(thread/receive &opt timeout)\n\n"
|
JDOC("(thread/receive &opt timeout)\n\n"
|
||||||
"Get a message sent to this thread. If timeout is provided, an error will be thrown after the timeout has elapsed but "
|
"Get a message sent to this thread. If timeout (in seconds) is provided, an error "
|
||||||
"no messages are received.")
|
"will be thrown after the timeout has elapsed but "
|
||||||
|
"no messages are received. The default timeout is 1 second, and math/inf cam be passed to "
|
||||||
|
"turn off the timeout.")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"thread/close", cfun_thread_close,
|
"thread/close", cfun_thread_close,
|
||||||
|
@ -315,6 +315,15 @@ JANET_API extern const char *const janet_type_names[16];
|
|||||||
JANET_API extern const char *const janet_signal_names[14];
|
JANET_API extern const char *const janet_signal_names[14];
|
||||||
JANET_API extern const char *const janet_status_names[16];
|
JANET_API extern const char *const janet_status_names[16];
|
||||||
|
|
||||||
|
/* For various IO routines, we want to use an int on posix and HANDLE on windows */
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
typedef void *JanetHandle;
|
||||||
|
#define JANET_HANDLE_NONE NULL
|
||||||
|
#else
|
||||||
|
typedef int JanetHandle;
|
||||||
|
#define JANET_HANDLE_NONE (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Fiber signals */
|
/* Fiber signals */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
JANET_SIGNAL_OK,
|
JANET_SIGNAL_OK,
|
||||||
@ -1647,6 +1656,7 @@ extern JANET_API const JanetAbstractType janet_file_type;
|
|||||||
#define JANET_FILE_NONIL 512
|
#define JANET_FILE_NONIL 512
|
||||||
|
|
||||||
JANET_API Janet janet_makefile(FILE *f, int32_t flags);
|
JANET_API Janet janet_makefile(FILE *f, int32_t flags);
|
||||||
|
JANET_API JanetFile *janet_makejfile(FILE *f, int32_t flags);
|
||||||
JANET_API FILE *janet_getfile(const Janet *argv, int32_t n, int32_t *flags);
|
JANET_API FILE *janet_getfile(const Janet *argv, int32_t n, int32_t *flags);
|
||||||
JANET_API FILE *janet_dynfile(const char *name, FILE *def);
|
JANET_API FILE *janet_dynfile(const char *name, FILE *def);
|
||||||
JANET_API JanetFile *janet_getjfile(const Janet *argv, int32_t n);
|
JANET_API JanetFile *janet_getjfile(const Janet *argv, int32_t n);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user