mirror of
https://github.com/janet-lang/janet
synced 2025-11-02 08:33:04 +00:00
Compare commits
16 Commits
ev-epoll-f
...
v1.32.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc5beda0d2 | ||
|
|
a363fd926d | ||
|
|
21ebede529 | ||
|
|
15d67e9191 | ||
|
|
b5996f5f02 | ||
|
|
83204dc293 | ||
|
|
e3f4142d2a | ||
|
|
f18ad36b1b | ||
|
|
cb25a2ecd6 | ||
|
|
741a5036e8 | ||
|
|
549ee95f3d | ||
|
|
6ae81058aa | ||
|
|
267c603824 | ||
|
|
a8f583a372 | ||
|
|
2b5d90f73a | ||
|
|
4139e426fe |
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
gcc
|
||||
- name: Build the project
|
||||
shell: cmd
|
||||
run: make -j CC=gcc
|
||||
run: make -j4 CC=gcc JANET_NO_AMALG=1
|
||||
|
||||
test-mingw-linux:
|
||||
name: Build and test with Mingw on Linux + Wine
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -34,8 +34,11 @@ local
|
||||
|
||||
# Common test files I use.
|
||||
temp.janet
|
||||
temp*.janet
|
||||
temp.c
|
||||
temp*janet
|
||||
temp*.c
|
||||
scratch.janet
|
||||
scratch.c
|
||||
|
||||
# Emscripten
|
||||
*.bc
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## Unreleased - ???
|
||||
## 1.32.1 - 2023-10-15
|
||||
- Fix return value from C function `janet_dobytes` when called on Janet functions that yield to event loop.
|
||||
- Change C API for event loop interaction - get rid of JanetListener and instead use `janet_async_start` and `janet_async_end`.
|
||||
- Rework event loop to make fewer system calls on kqueue and epoll.
|
||||
- Expose atomic refcount abstraction in janet.h
|
||||
- Add `array/weak` for weak references in arrays
|
||||
- Add support for weak tables via `table/weak`, `table/weak-keys`, and `table/weak-values`.
|
||||
|
||||
4
Makefile
4
Makefile
@@ -196,9 +196,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile
|
||||
########################
|
||||
|
||||
ifeq ($(UNAME), Darwin)
|
||||
SONAME=libjanet.1.31.dylib
|
||||
SONAME=libjanet.1.32.dylib
|
||||
else
|
||||
SONAME=libjanet.so.1.31
|
||||
SONAME=libjanet.so.1.32
|
||||
endif
|
||||
|
||||
build/c/shell.c: src/mainclient/shell.c
|
||||
|
||||
5
examples/posix-exec.janet
Normal file
5
examples/posix-exec.janet
Normal file
@@ -0,0 +1,5 @@
|
||||
# Switch to python
|
||||
|
||||
(print "running in Janet")
|
||||
(os/posix-exec ["python"] :p)
|
||||
(print "will not print")
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
project('janet', 'c',
|
||||
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||
version : '1.31.0')
|
||||
version : '1.32.1')
|
||||
|
||||
# Global settings
|
||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#define JANETCONF_H
|
||||
|
||||
#define JANET_VERSION_MAJOR 1
|
||||
#define JANET_VERSION_MINOR 31
|
||||
#define JANET_VERSION_PATCH 0
|
||||
#define JANET_VERSION_MINOR 32
|
||||
#define JANET_VERSION_PATCH 1
|
||||
#define JANET_VERSION_EXTRA ""
|
||||
#define JANET_VERSION "1.31.0"
|
||||
#define JANET_VERSION "1.32.1"
|
||||
|
||||
/* #define JANET_BUILD "local" */
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const c
|
||||
int32_t not_raw = raw;
|
||||
if (not_raw < 0) not_raw += length + 1;
|
||||
if (not_raw < 0 || not_raw > length)
|
||||
janet_panicf("%s index %d out of range [%d,%d]", which, raw, -length - 1, length);
|
||||
janet_panicf("%s index %d out of range [%d,%d]", which, (int64_t) raw, -(int64_t)length - 1, (int64_t) length);
|
||||
return not_raw;
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const ch
|
||||
int32_t not_raw = raw;
|
||||
if (not_raw < 0) not_raw += length;
|
||||
if (not_raw < 0 || not_raw > length)
|
||||
janet_panicf("%s index %d out of range [%d,%d)", which, raw, -length, length);
|
||||
janet_panicf("%s index %d out of range [%d,%d)", which, (int64_t)raw, -(int64_t)length, (int64_t)length);
|
||||
return not_raw;
|
||||
}
|
||||
|
||||
|
||||
@@ -255,6 +255,7 @@ static void add_timeout(JanetTimeout to) {
|
||||
|
||||
void janet_async_end(JanetFiber *fiber) {
|
||||
if (fiber->ev_callback) {
|
||||
fiber->ev_callback(fiber, JANET_ASYNC_EVENT_DEINIT);
|
||||
janet_gcunroot(janet_wrap_abstract(fiber->ev_stream));
|
||||
fiber->ev_callback = NULL;
|
||||
if (fiber->ev_state) {
|
||||
@@ -267,7 +268,16 @@ void janet_async_end(JanetFiber *fiber) {
|
||||
}
|
||||
}
|
||||
|
||||
void *janet_async_start(JanetFiber *fiber, JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, size_t data_size) {
|
||||
void janet_async_in_flight(JanetFiber *fiber) {
|
||||
#ifdef JANET_WINDOWS
|
||||
fiber->flags |= JANET_FIBER_EV_FLAG_IN_FLIGHT;
|
||||
#else
|
||||
(void) fiber;
|
||||
#endif
|
||||
}
|
||||
|
||||
void janet_async_start(JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state) {
|
||||
JanetFiber *fiber = janet_vm.root_fiber;
|
||||
janet_assert(!fiber->ev_callback, "double async on fiber");
|
||||
if (mode & JANET_ASYNC_LISTEN_READ) stream->read_fiber = fiber;
|
||||
if (mode & JANET_ASYNC_LISTEN_WRITE) stream->write_fiber = fiber;
|
||||
@@ -275,14 +285,9 @@ void *janet_async_start(JanetFiber *fiber, JanetStream *stream, JanetAsyncMode m
|
||||
fiber->ev_stream = stream;
|
||||
janet_ev_inc_refcount();
|
||||
janet_gcroot(janet_wrap_abstract(stream));
|
||||
if (data_size) {
|
||||
void *data = janet_malloc(data_size);
|
||||
fiber->ev_state = data;
|
||||
return data;
|
||||
} else {
|
||||
fiber->ev_state = NULL;
|
||||
return NULL;
|
||||
}
|
||||
fiber->ev_state = state;
|
||||
callback(fiber, JANET_ASYNC_EVENT_INIT);
|
||||
janet_await();
|
||||
}
|
||||
|
||||
void janet_fiber_did_resume(JanetFiber *fiber) {
|
||||
@@ -2199,7 +2204,7 @@ void ev_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
case JANET_ASYNC_EVENT_USER: {
|
||||
case JANET_ASYNC_EVENT_INIT: {
|
||||
int32_t chunk_size = state->bytes_left > JANET_EV_CHUNKSIZE ? JANET_EV_CHUNKSIZE : state->bytes_left;
|
||||
memset(&(state->overlapped), 0, sizeof(OVERLAPPED));
|
||||
int status;
|
||||
@@ -2237,7 +2242,7 @@ void ev_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
fiber->flags |= JANET_FIBER_EV_FLAG_IN_FLIGHT;
|
||||
janet_async_in_flight(fiber);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
@@ -2253,7 +2258,7 @@ void ev_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
|
||||
read_more:
|
||||
case JANET_ASYNC_EVENT_HUP:
|
||||
case JANET_ASYNC_EVENT_USER:
|
||||
case JANET_ASYNC_EVENT_INIT:
|
||||
case JANET_ASYNC_EVENT_READ: {
|
||||
JanetBuffer *buffer = state->buf;
|
||||
int32_t bytes_left = state->bytes_left;
|
||||
@@ -2332,9 +2337,8 @@ void ev_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
static void janet_ev_read_generic(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int is_chunked, JanetReadMode mode, int flags) {
|
||||
JanetFiber *f = janet_vm.root_fiber;
|
||||
StateRead *state = (StateRead *) janet_async_start(f, stream, JANET_ASYNC_LISTEN_READ, ev_callback_read, sizeof(StateRead));
|
||||
static JANET_NO_RETURN void janet_ev_read_generic(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int is_chunked, JanetReadMode mode, int flags) {
|
||||
StateRead *state = janet_malloc(sizeof(StateRead));
|
||||
state->is_chunk = is_chunked;
|
||||
state->buf = buf;
|
||||
state->bytes_left = nbytes;
|
||||
@@ -2345,23 +2349,23 @@ static void janet_ev_read_generic(JanetStream *stream, JanetBuffer *buf, int32_t
|
||||
#else
|
||||
state->flags = flags;
|
||||
#endif
|
||||
ev_callback_read(f, JANET_ASYNC_EVENT_USER);
|
||||
janet_async_start(stream, JANET_ASYNC_LISTEN_READ, ev_callback_read, state);
|
||||
}
|
||||
|
||||
void janet_ev_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes) {
|
||||
JANET_NO_RETURN void janet_ev_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes) {
|
||||
janet_ev_read_generic(stream, buf, nbytes, 0, JANET_ASYNC_READMODE_READ, 0);
|
||||
}
|
||||
void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes) {
|
||||
JANET_NO_RETURN void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes) {
|
||||
janet_ev_read_generic(stream, buf, nbytes, 1, JANET_ASYNC_READMODE_READ, 0);
|
||||
}
|
||||
#ifdef JANET_NET
|
||||
void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
janet_ev_read_generic(stream, buf, nbytes, 0, JANET_ASYNC_READMODE_RECV, flags);
|
||||
}
|
||||
void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
janet_ev_read_generic(stream, buf, nbytes, 1, JANET_ASYNC_READMODE_RECV, flags);
|
||||
}
|
||||
void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
janet_ev_read_generic(stream, buf, nbytes, 0, JANET_ASYNC_READMODE_RECVFROM, flags);
|
||||
}
|
||||
#endif
|
||||
@@ -2431,7 +2435,7 @@ void ev_callback_write(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case JANET_ASYNC_EVENT_USER: {
|
||||
case JANET_ASYNC_EVENT_INIT: {
|
||||
/* Begin write */
|
||||
int32_t len;
|
||||
const uint8_t *bytes;
|
||||
@@ -2461,7 +2465,7 @@ void ev_callback_write(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
status = WSASendTo(sock, &state->wbuf, 1, NULL, state->flags, to, tolen, &state->overlapped, NULL);
|
||||
if (status) {
|
||||
if (WSA_IO_PENDING == WSAGetLastError()) {
|
||||
fiber->flags |= JANET_FIBER_EV_FLAG_IN_FLIGHT;
|
||||
janet_async_in_flight(fiber);
|
||||
} else {
|
||||
janet_cancel(fiber, janet_ev_lasterr());
|
||||
janet_async_end(fiber);
|
||||
@@ -2486,7 +2490,7 @@ void ev_callback_write(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
status = WriteFile(stream->handle, bytes, len, NULL, &state->overlapped);
|
||||
if (!status) {
|
||||
if (ERROR_IO_PENDING == GetLastError()) {
|
||||
fiber->flags |= JANET_FIBER_EV_FLAG_IN_FLIGHT;
|
||||
janet_async_in_flight(fiber);
|
||||
} else {
|
||||
janet_cancel(fiber, janet_ev_lasterr());
|
||||
janet_async_end(fiber);
|
||||
@@ -2505,7 +2509,7 @@ void ev_callback_write(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
janet_cancel(fiber, janet_cstringv("stream hup"));
|
||||
janet_async_end(fiber);
|
||||
break;
|
||||
case JANET_ASYNC_EVENT_USER:
|
||||
case JANET_ASYNC_EVENT_INIT:
|
||||
case JANET_ASYNC_EVENT_WRITE: {
|
||||
int32_t start, len;
|
||||
const uint8_t *bytes;
|
||||
@@ -2570,10 +2574,8 @@ void ev_callback_write(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
static void janet_ev_write_generic(JanetStream *stream, void *buf, void *dest_abst, JanetWriteMode mode, int is_buffer, int flags) {
|
||||
JanetFiber *f = janet_vm.root_fiber;
|
||||
StateWrite *state = (StateWrite *) janet_async_start(f, stream, JANET_ASYNC_LISTEN_WRITE,
|
||||
ev_callback_write, sizeof(StateWrite));
|
||||
static JANET_NO_RETURN void janet_ev_write_generic(JanetStream *stream, void *buf, void *dest_abst, JanetWriteMode mode, int is_buffer, int flags) {
|
||||
StateWrite *state = janet_malloc(sizeof(StateWrite));
|
||||
state->is_buffer = is_buffer;
|
||||
state->src.buf = buf;
|
||||
state->dest_abst = dest_abst;
|
||||
@@ -2584,31 +2586,31 @@ static void janet_ev_write_generic(JanetStream *stream, void *buf, void *dest_ab
|
||||
state->flags = flags;
|
||||
state->start = 0;
|
||||
#endif
|
||||
ev_callback_write(f, JANET_ASYNC_EVENT_USER);
|
||||
janet_async_start(stream, JANET_ASYNC_LISTEN_WRITE, ev_callback_write, state);
|
||||
}
|
||||
|
||||
void janet_ev_write_buffer(JanetStream *stream, JanetBuffer *buf) {
|
||||
JANET_NO_RETURN void janet_ev_write_buffer(JanetStream *stream, JanetBuffer *buf) {
|
||||
janet_ev_write_generic(stream, buf, NULL, JANET_ASYNC_WRITEMODE_WRITE, 1, 0);
|
||||
}
|
||||
|
||||
void janet_ev_write_string(JanetStream *stream, JanetString str) {
|
||||
JANET_NO_RETURN void janet_ev_write_string(JanetStream *stream, JanetString str) {
|
||||
janet_ev_write_generic(stream, (void *) str, NULL, JANET_ASYNC_WRITEMODE_WRITE, 0, 0);
|
||||
}
|
||||
|
||||
#ifdef JANET_NET
|
||||
void janet_ev_send_buffer(JanetStream *stream, JanetBuffer *buf, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_send_buffer(JanetStream *stream, JanetBuffer *buf, int flags) {
|
||||
janet_ev_write_generic(stream, buf, NULL, JANET_ASYNC_WRITEMODE_SEND, 1, flags);
|
||||
}
|
||||
|
||||
void janet_ev_send_string(JanetStream *stream, JanetString str, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_send_string(JanetStream *stream, JanetString str, int flags) {
|
||||
janet_ev_write_generic(stream, (void *) str, NULL, JANET_ASYNC_WRITEMODE_SEND, 0, flags);
|
||||
}
|
||||
|
||||
void janet_ev_sendto_buffer(JanetStream *stream, JanetBuffer *buf, void *dest, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_sendto_buffer(JanetStream *stream, JanetBuffer *buf, void *dest, int flags) {
|
||||
janet_ev_write_generic(stream, buf, dest, JANET_ASYNC_WRITEMODE_SENDTO, 1, flags);
|
||||
}
|
||||
|
||||
void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags) {
|
||||
JANET_NO_RETURN void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags) {
|
||||
janet_ev_write_generic(stream, (void *) str, dest, JANET_ASYNC_WRITEMODE_SENDTO, 0, flags);
|
||||
}
|
||||
#endif
|
||||
@@ -2999,7 +3001,6 @@ JANET_CORE_FN(janet_cfun_stream_read,
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_read(stream, buffer, n);
|
||||
}
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_cfun_stream_chunk,
|
||||
@@ -3014,7 +3015,6 @@ JANET_CORE_FN(janet_cfun_stream_chunk,
|
||||
double to = janet_optnumber(argv, argc, 3, INFINITY);
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_readchunk(stream, buffer, n);
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(janet_cfun_stream_write,
|
||||
@@ -3034,7 +3034,6 @@ JANET_CORE_FN(janet_cfun_stream_write,
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_write_string(stream, bytes.bytes);
|
||||
}
|
||||
janet_await();
|
||||
}
|
||||
|
||||
static int mutexgc(void *p, size_t size) {
|
||||
|
||||
@@ -999,13 +999,13 @@ typedef struct {
|
||||
uint64_t x;
|
||||
} sysv64_sseint_return;
|
||||
typedef sysv64_int_return janet_sysv64_variant_1(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f,
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
typedef sysv64_sse_return janet_sysv64_variant_2(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f,
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
typedef sysv64_intsse_return janet_sysv64_variant_3(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f,
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
typedef sysv64_sseint_return janet_sysv64_variant_4(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e, uint64_t f,
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
double r1, double r2, double r3, double r4, double r5, double r6, double r7, double r8);
|
||||
|
||||
static Janet janet_ffi_sysv64(JanetFFISignature *signature, void *function_pointer, const Janet *argv) {
|
||||
union {
|
||||
|
||||
@@ -239,8 +239,8 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
|
||||
fiber->data + tuplehead,
|
||||
oldtop - tuplehead)
|
||||
: janet_wrap_tuple(janet_tuple_n(
|
||||
fiber->data + tuplehead,
|
||||
oldtop - tuplehead));
|
||||
fiber->data + tuplehead,
|
||||
oldtop - tuplehead));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,8 +370,8 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
|
||||
fiber->data + tuplehead,
|
||||
fiber->stacktop - tuplehead)
|
||||
: janet_wrap_tuple(janet_tuple_n(
|
||||
fiber->data + tuplehead,
|
||||
fiber->stacktop - tuplehead));
|
||||
fiber->data + tuplehead,
|
||||
fiber->stacktop - tuplehead));
|
||||
}
|
||||
stacksize = tuplehead - fiber->stackstart + 1;
|
||||
} else {
|
||||
|
||||
@@ -124,6 +124,13 @@ void net_callback_connect(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
switch (event) {
|
||||
default:
|
||||
break;
|
||||
#ifndef JANET_WINDOWS
|
||||
/* Wait until we have an actually event before checking.
|
||||
* Windows doesn't support async connect with this, just try immediately.*/
|
||||
case JANET_ASYNC_EVENT_INIT:
|
||||
#endif
|
||||
case JANET_ASYNC_EVENT_DEINIT:
|
||||
return;
|
||||
case JANET_ASYNC_EVENT_CLOSE:
|
||||
janet_cancel(fiber, janet_cstringv("stream closed"));
|
||||
janet_async_end(fiber);
|
||||
@@ -154,12 +161,9 @@ void net_callback_connect(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
}
|
||||
|
||||
static void net_sched_connect(JanetStream *stream) {
|
||||
JanetFiber *f = janet_vm.root_fiber;
|
||||
NetStateConnect *state = (NetStateConnect *) janet_async_start(f, stream, JANET_ASYNC_LISTEN_WRITE, net_callback_connect, sizeof(NetStateConnect));
|
||||
NetStateConnect *state = janet_malloc(sizeof(NetStateConnect));
|
||||
state->did_connect = 0;
|
||||
#ifdef JANET_WINDOWS
|
||||
net_callback_connect(f, JANET_ASYNC_EVENT_USER);
|
||||
#endif
|
||||
janet_async_start(stream, JANET_ASYNC_LISTEN_WRITE, net_callback_connect, state);
|
||||
}
|
||||
|
||||
/* State machine for accepting connections. */
|
||||
@@ -229,14 +233,16 @@ void net_callback_accept(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_accept(JanetStream *stream, JanetFunction *fun) {
|
||||
Janet err;
|
||||
JanetFiber *f = janet_vm.root_fiber;
|
||||
NetStateAccept *state = (NetStateAccept *) janet_async_start(f, stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, sizeof(NetStateAccept));
|
||||
NetStateAccept *state = janet_malloc(sizeof(NetStateAccept));
|
||||
memset(&state->overlapped, 0, sizeof(WSAOVERLAPPED));
|
||||
memset(&state->buf, 0, 1024);
|
||||
state->function = fun;
|
||||
state->lstream = stream;
|
||||
if (net_sched_accept_impl(state, f, &err)) janet_panicv(err);
|
||||
janet_await();
|
||||
if (net_sched_accept_impl(state, janet_root_fiber(), &err)) {
|
||||
janet_free(state);
|
||||
janet_panicv(err);
|
||||
}
|
||||
janet_async_start(stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, state);
|
||||
}
|
||||
|
||||
static int net_sched_accept_impl(NetStateAccept *state, JanetFiber *fiber, Janet *err) {
|
||||
@@ -253,7 +259,7 @@ static int net_sched_accept_impl(NetStateAccept *state, JanetFiber *fiber, Janet
|
||||
int code = WSAGetLastError();
|
||||
if (code == WSA_IO_PENDING) {
|
||||
/* indicates io is happening async */
|
||||
fiber->flags |= JANET_FIBER_EV_FLAG_IN_FLIGHT;
|
||||
janet_async_in_flight(fiber);
|
||||
return 0;
|
||||
}
|
||||
*err = janet_ev_lasterr();
|
||||
@@ -282,7 +288,7 @@ void net_callback_accept(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
janet_schedule(fiber, janet_wrap_nil());
|
||||
janet_async_end(fiber);
|
||||
return;
|
||||
case JANET_ASYNC_EVENT_USER:
|
||||
case JANET_ASYNC_EVENT_INIT:
|
||||
case JANET_ASYNC_EVENT_READ: {
|
||||
#if defined(JANET_LINUX)
|
||||
JSock connfd = accept4(stream->handle, NULL, NULL, SOCK_CLOEXEC);
|
||||
@@ -310,11 +316,10 @@ void net_callback_accept(JanetFiber *fiber, JanetAsyncEvent event) {
|
||||
}
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_accept(JanetStream *stream, JanetFunction *fun) {
|
||||
JanetFiber *f = janet_vm.root_fiber;
|
||||
NetStateAccept *state = (NetStateAccept *) janet_async_start(f, stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, sizeof(NetStateAccept));
|
||||
NetStateAccept *state = janet_malloc(sizeof(NetStateAccept));
|
||||
memset(state, 0, sizeof(NetStateAccept));
|
||||
state->function = fun;
|
||||
net_callback_accept(f, JANET_ASYNC_EVENT_USER);
|
||||
janet_await();
|
||||
janet_async_start(stream, JANET_ASYNC_LISTEN_READ, net_callback_accept, state);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -851,7 +856,6 @@ JANET_CORE_FN(cfun_stream_read,
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_recv(stream, buffer, n, MSG_NOSIGNAL);
|
||||
}
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_stream_chunk,
|
||||
@@ -866,7 +870,6 @@ JANET_CORE_FN(cfun_stream_chunk,
|
||||
double to = janet_optnumber(argv, argc, 3, INFINITY);
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_recvchunk(stream, buffer, n, MSG_NOSIGNAL);
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_stream_recv_from,
|
||||
@@ -881,7 +884,6 @@ JANET_CORE_FN(cfun_stream_recv_from,
|
||||
double to = janet_optnumber(argv, argc, 3, INFINITY);
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_recvfrom(stream, buffer, n, MSG_NOSIGNAL);
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_stream_write,
|
||||
@@ -901,7 +903,6 @@ JANET_CORE_FN(cfun_stream_write,
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_send_string(stream, bytes.bytes, MSG_NOSIGNAL);
|
||||
}
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_stream_send_to,
|
||||
@@ -922,7 +923,6 @@ JANET_CORE_FN(cfun_stream_send_to,
|
||||
if (to != INFINITY) janet_addtimeout(to);
|
||||
janet_ev_sendto_string(stream, bytes.bytes, dest, MSG_NOSIGNAL);
|
||||
}
|
||||
janet_await();
|
||||
}
|
||||
|
||||
JANET_CORE_FN(cfun_stream_flush,
|
||||
|
||||
104
src/core/os.c
104
src/core/os.c
@@ -1081,11 +1081,18 @@ static JanetFile *get_stdio_for_handle(JanetHandle handle, void *orig, int iswri
|
||||
}
|
||||
#endif
|
||||
|
||||
static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
||||
typedef enum {
|
||||
JANET_EXECUTE_EXECUTE,
|
||||
JANET_EXECUTE_SPAWN,
|
||||
JANET_EXECUTE_EXEC
|
||||
} JanetExecuteMode;
|
||||
|
||||
static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
|
||||
janet_sandbox_assert(JANET_SANDBOX_SUBPROCESS);
|
||||
janet_arity(argc, 1, 3);
|
||||
|
||||
/* Get flags */
|
||||
int is_spawn = mode == JANET_EXECUTE_SPAWN;
|
||||
uint64_t flags = 0;
|
||||
if (argc > 1) {
|
||||
flags = janet_getflags(argv, 1, "epxd");
|
||||
@@ -1109,7 +1116,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
||||
int pipe_owner_flags = (is_spawn && (flags & 0x8)) ? JANET_PROC_ALLOW_ZOMBIE : 0;
|
||||
|
||||
/* Get optional redirections */
|
||||
if (argc > 2) {
|
||||
if (argc > 2 && (mode != JANET_EXECUTE_EXEC)) {
|
||||
JanetDictView tab = janet_getdictionary(argv, 2);
|
||||
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"));
|
||||
@@ -1230,12 +1237,32 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
||||
* of posix_spawn would modify the argv array passed in. */
|
||||
char *const *cargv = (char *const *)child_argv;
|
||||
|
||||
/* Use posix_spawn to spawn new process */
|
||||
|
||||
if (use_environ) {
|
||||
janet_lock_environ();
|
||||
}
|
||||
|
||||
/* exec mode */
|
||||
if (mode == JANET_EXECUTE_EXEC) {
|
||||
#ifdef JANET_WINDOWS
|
||||
janet_panic("not supported on windows");
|
||||
#else
|
||||
int status;
|
||||
if (!use_environ) {
|
||||
environ = envp;
|
||||
}
|
||||
do {
|
||||
if (janet_flag_at(flags, 1)) {
|
||||
status = execvp(cargv[0], cargv);
|
||||
} else {
|
||||
status = execv(cargv[0], cargv);
|
||||
}
|
||||
} while (status == -1 && errno == EINTR);
|
||||
janet_panicf("%p: %s", cargv[0], strerror(errno ? errno : ENOENT));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Use posix_spawn to spawn new process */
|
||||
|
||||
/* Posix spawn setup */
|
||||
posix_spawn_file_actions_t actions;
|
||||
posix_spawn_file_actions_init(&actions);
|
||||
@@ -1344,7 +1371,7 @@ JANET_CORE_FN(os_execute,
|
||||
"contain the keys :in, :out, and :err, which allow redirecting stdio in the subprocess. "
|
||||
"These arguments should be core/file values. "
|
||||
"Returns the exit status of the program.") {
|
||||
return os_execute_impl(argc, argv, 0);
|
||||
return os_execute_impl(argc, argv, JANET_EXECUTE_EXECUTE);
|
||||
}
|
||||
|
||||
JANET_CORE_FN(os_spawn,
|
||||
@@ -1357,7 +1384,43 @@ JANET_CORE_FN(os_spawn,
|
||||
"The returned value `proc` has the fields :in, :out, :err, :return-code, and "
|
||||
"the additional field :pid on unix-like platforms. Use `(os/proc-wait proc)` to rejoin the "
|
||||
"subprocess or `(os/proc-kill proc)`.") {
|
||||
return os_execute_impl(argc, argv, 1);
|
||||
return os_execute_impl(argc, argv, JANET_EXECUTE_SPAWN);
|
||||
}
|
||||
|
||||
JANET_CORE_FN(os_posix_exec,
|
||||
"(os/posix-exec args &opt flags env)",
|
||||
"Use the execvpe or execve system calls to replace the current process with an interface similar to os/execute. "
|
||||
"Hoever, instead of creating a subprocess, the current process is replaced. Is not supported on windows, and "
|
||||
"does not allow redirection of stdio.") {
|
||||
return os_execute_impl(argc, argv, JANET_EXECUTE_EXEC);
|
||||
}
|
||||
|
||||
JANET_CORE_FN(os_posix_fork,
|
||||
"(os/posix-fork)",
|
||||
"Make a `fork` system call and create a new process. Return nil if in the new process, otherwise a core/process object (as returned by os/spawn). "
|
||||
"Not supported on all systems (POSIX only).") {
|
||||
janet_sandbox_assert(JANET_SANDBOX_SUBPROCESS);
|
||||
janet_fixarity(argc, 0);
|
||||
(void) argv;
|
||||
#ifdef JANET_WINDOWS
|
||||
janet_panic("not supported");
|
||||
#else
|
||||
pid_t result;
|
||||
do {
|
||||
result = fork();
|
||||
} while (result == -1 && errno == EINTR);
|
||||
if (result == -1) {
|
||||
janet_panic(strerror(errno));
|
||||
}
|
||||
if (result) {
|
||||
JanetProc *proc = janet_abstract(&ProcAT, sizeof(JanetProc));
|
||||
memset(proc, 0, sizeof(JanetProc));
|
||||
proc->pid = result;
|
||||
proc->flags = JANET_PROC_ALLOW_ZOMBIE;
|
||||
return janet_wrap_abstract(proc);
|
||||
}
|
||||
return janet_wrap_nil();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JANET_EV
|
||||
@@ -2336,34 +2399,6 @@ JANET_CORE_FN(os_permission_int,
|
||||
return janet_wrap_integer(os_get_unix_mode(argv, 0));
|
||||
}
|
||||
|
||||
JANET_CORE_FN(os_posix_fork,
|
||||
"(os/posix-fork)",
|
||||
"Make a `fork` system call and create a new process. Return nil if in the new process, otherwise a core/process object (as returned by os/spawn). "
|
||||
"Not supported on all systems (POSIX only).") {
|
||||
janet_sandbox_assert(JANET_SANDBOX_SUBPROCESS);
|
||||
janet_fixarity(argc, 0);
|
||||
(void) argv;
|
||||
#ifdef JANET_WINDOWS
|
||||
janet_panic("not supported");
|
||||
#else
|
||||
pid_t result;
|
||||
do {
|
||||
result = fork();
|
||||
} while (result == -1 && errno == EINTR);
|
||||
if (result == -1) {
|
||||
janet_panic(strerror(errno));
|
||||
}
|
||||
if (result) {
|
||||
JanetProc *proc = janet_abstract(&ProcAT, sizeof(JanetProc));
|
||||
memset(proc, 0, sizeof(JanetProc));
|
||||
proc->pid = result;
|
||||
proc->flags = JANET_PROC_ALLOW_ZOMBIE;
|
||||
return janet_wrap_abstract(proc);
|
||||
}
|
||||
return janet_wrap_nil();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JANET_EV
|
||||
|
||||
/*
|
||||
@@ -2651,6 +2686,7 @@ void janet_lib_os(JanetTable *env) {
|
||||
JANET_CORE_REG("os/spawn", os_spawn),
|
||||
JANET_CORE_REG("os/shell", os_shell),
|
||||
JANET_CORE_REG("os/posix-fork", os_posix_fork),
|
||||
JANET_CORE_REG("os/posix-exec", os_posix_exec),
|
||||
/* no need to sandbox process management if you can't create processes
|
||||
* (allows for limited functionality if use exposes C-functions to create specific processes) */
|
||||
JANET_CORE_REG("os/proc-wait", os_proc_wait),
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <float.h>
|
||||
|
||||
/* Implements a pretty printer for Janet. The pretty printer
|
||||
* is simple and not that flexible, but fast. */
|
||||
@@ -38,11 +39,15 @@
|
||||
/* Temporary buffer size */
|
||||
#define BUFSIZE 64
|
||||
|
||||
/* Preprocessor hacks */
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
static void number_to_string_b(JanetBuffer *buffer, double x) {
|
||||
janet_buffer_ensure(buffer, buffer->count + BUFSIZE, 2);
|
||||
const char *fmt = (x == floor(x) &&
|
||||
x <= JANET_INTMAX_DOUBLE &&
|
||||
x >= JANET_INTMIN_DOUBLE) ? "%.0f" : "%g";
|
||||
x >= JANET_INTMIN_DOUBLE) ? "%.0f" : ("%." STR(DBL_DIG) "g");
|
||||
int count;
|
||||
if (x == 0.0) {
|
||||
/* Prevent printing of '-0' */
|
||||
@@ -772,6 +777,8 @@ struct FmtMapping {
|
||||
/* Janet uses fixed width integer types for most things, so map
|
||||
* format specifiers to these fixed sizes */
|
||||
static const struct FmtMapping format_mappings[] = {
|
||||
{'D', PRId64},
|
||||
{'I', PRIi64},
|
||||
{'d', PRId64},
|
||||
{'i', PRIi64},
|
||||
{'o', PRIo64},
|
||||
@@ -850,13 +857,19 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
c = scanformat(c, form, width, precision);
|
||||
switch (*c++) {
|
||||
case 'c': {
|
||||
int n = va_arg(args, long);
|
||||
int n = va_arg(args, int);
|
||||
nb = snprintf(item, MAX_ITEM, form, n);
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
case 'i': {
|
||||
int64_t n = va_arg(args, int);
|
||||
int64_t n = (int64_t) va_arg(args, int32_t);
|
||||
nb = snprintf(item, MAX_ITEM, form, n);
|
||||
break;
|
||||
}
|
||||
case 'D':
|
||||
case 'I': {
|
||||
int64_t n = va_arg(args, int64_t);
|
||||
nb = snprintf(item, MAX_ITEM, form, n);
|
||||
break;
|
||||
}
|
||||
@@ -864,7 +877,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
case 'X':
|
||||
case 'o':
|
||||
case 'u': {
|
||||
uint64_t n = va_arg(args, unsigned int);
|
||||
uint64_t n = va_arg(args, uint64_t);
|
||||
nb = snprintf(item, MAX_ITEM, form, n);
|
||||
break;
|
||||
}
|
||||
@@ -908,7 +921,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
janet_buffer_push_cstring(b, typestr(va_arg(args, Janet)));
|
||||
break;
|
||||
case 'T': {
|
||||
int types = va_arg(args, long);
|
||||
int types = va_arg(args, int);
|
||||
pushtypes(b, types);
|
||||
break;
|
||||
}
|
||||
@@ -1017,6 +1030,8 @@ void janet_buffer_format(
|
||||
janet_getinteger(argv, arg));
|
||||
break;
|
||||
}
|
||||
case 'D':
|
||||
case 'I':
|
||||
case 'd':
|
||||
case 'i': {
|
||||
int64_t n = janet_getinteger64(argv, arg);
|
||||
|
||||
@@ -32,6 +32,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
int errflags = 0, done = 0;
|
||||
int32_t index = 0;
|
||||
Janet ret = janet_wrap_nil();
|
||||
JanetFiber *fiber = NULL;
|
||||
const uint8_t *where = sourcePath ? janet_cstring(sourcePath) : NULL;
|
||||
|
||||
if (where) janet_gcroot(janet_wrap_string(where));
|
||||
@@ -47,7 +48,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
JanetCompileResult cres = janet_compile(form, env, where);
|
||||
if (cres.status == JANET_COMPILE_OK) {
|
||||
JanetFunction *f = janet_thunk(cres.funcdef);
|
||||
JanetFiber *fiber = janet_fiber(f, 64, 0, NULL);
|
||||
fiber = janet_fiber(f, 64, 0, NULL);
|
||||
fiber->env = env;
|
||||
JanetSignal status = janet_continue(fiber, janet_wrap_nil(), &ret);
|
||||
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
||||
@@ -112,9 +113,14 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
#ifdef JANET_EV
|
||||
/* Enter the event loop if we are not already in it */
|
||||
if (janet_vm.stackn == 0) {
|
||||
janet_gcroot(ret);
|
||||
if (fiber) {
|
||||
janet_gcroot(janet_wrap_fiber(fiber));
|
||||
}
|
||||
janet_loop();
|
||||
janet_gcunroot(ret);
|
||||
if (fiber) {
|
||||
janet_gcunroot(janet_wrap_fiber(fiber));
|
||||
ret = fiber->last_value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (out) *out = ret;
|
||||
|
||||
@@ -596,8 +596,7 @@ typedef enum {
|
||||
JANET_ASYNC_EVENT_READ = 6,
|
||||
JANET_ASYNC_EVENT_WRITE = 7,
|
||||
JANET_ASYNC_EVENT_COMPLETE = 8, /* Used on windows for IOCP */
|
||||
JANET_ASYNC_EVENT_FAILED = 9, /* Used on windows for IOCP */
|
||||
JANET_ASYNC_EVENT_USER = 10
|
||||
JANET_ASYNC_EVENT_FAILED = 9 /* Used on windows for IOCP */
|
||||
} JanetAsyncEvent;
|
||||
|
||||
typedef enum {
|
||||
@@ -606,9 +605,7 @@ typedef enum {
|
||||
JANET_ASYNC_LISTEN_BOTH
|
||||
} JanetAsyncMode;
|
||||
|
||||
/* Typedefs */
|
||||
typedef struct JanetStream JanetStream;
|
||||
typedef void (*JanetEVCallback)(JanetFiber *fiber, JanetAsyncEvent event);
|
||||
|
||||
/* Wrapper around file descriptors and HANDLEs that can be polled. */
|
||||
struct JanetStream {
|
||||
@@ -620,9 +617,24 @@ struct JanetStream {
|
||||
const void *methods; /* Methods for this stream */
|
||||
};
|
||||
|
||||
typedef void (*JanetEVCallback)(JanetFiber *fiber, JanetAsyncEvent event);
|
||||
|
||||
/* Start listening for events from a stream on the current root fiber. After
|
||||
* calling this, users should call janet_await() before returning from the
|
||||
* current C Function. This also will call janet_await.
|
||||
* mode is which events to listen for, and callback is the function pointer to
|
||||
* call when ever an event is sent from the event loop. state is an optional (can be NULL)
|
||||
* pointer to data allocated with janet_malloc. This pointer will be passed to callback as
|
||||
* fiber->ev_state. It will also be freed for you by the runtime when the event loop determines
|
||||
* it can no longer be referenced. On windows, the contents of state MUST contained an OVERLAPPED struct. */
|
||||
JANET_API JANET_NO_RETURN void janet_async_start(JanetStream *stream, JanetAsyncMode mode, JanetEVCallback callback, void *state);
|
||||
|
||||
/* Do not send any more events to the given callback. Call this after scheduling fiber to be resume
|
||||
* or canceled. */
|
||||
JANET_API void janet_async_end(JanetFiber *fiber);
|
||||
JANET_API void *janet_async_start(JanetFiber *fiber, JanetStream *stream,
|
||||
JanetAsyncMode mode, JanetEVCallback callback, size_t data_size);
|
||||
|
||||
/* Needed for windows to mark a fiber as waiting for an IOCP completion event. Noop on other platforms. */
|
||||
JANET_API void janet_async_in_flight(JanetFiber *fiber);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1488,22 +1500,22 @@ JANET_API void janet_ev_post_event(JanetVM *vm, JanetCallback cb, JanetEVGeneric
|
||||
JANET_API void janet_ev_default_threaded_callback(JanetEVGenericMessage return_value);
|
||||
|
||||
/* Read async from a stream */
|
||||
JANET_API void janet_ev_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes);
|
||||
JANET_API void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_readchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes);
|
||||
#ifdef JANET_NET
|
||||
JANET_API void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||
JANET_API void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||
JANET_API void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_recv(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_recvchunk(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_recvfrom(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags);
|
||||
#endif
|
||||
|
||||
/* Write async to a stream */
|
||||
JANET_API void janet_ev_write_buffer(JanetStream *stream, JanetBuffer *buf);
|
||||
JANET_API void janet_ev_write_string(JanetStream *stream, JanetString str);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_write_buffer(JanetStream *stream, JanetBuffer *buf);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_write_string(JanetStream *stream, JanetString str);
|
||||
#ifdef JANET_NET
|
||||
JANET_API void janet_ev_send_buffer(JanetStream *stream, JanetBuffer *buf, int flags);
|
||||
JANET_API void janet_ev_send_string(JanetStream *stream, JanetString str, int flags);
|
||||
JANET_API void janet_ev_sendto_buffer(JanetStream *stream, JanetBuffer *buf, void *dest, int flags);
|
||||
JANET_API void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_send_buffer(JanetStream *stream, JanetBuffer *buf, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_send_string(JanetStream *stream, JanetString str, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_sendto_buffer(JanetStream *stream, JanetBuffer *buf, void *dest, int flags);
|
||||
JANET_NO_RETURN JANET_API void janet_ev_sendto_string(JanetStream *stream, JanetString str, void *dest, int flags);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -502,10 +502,10 @@ static void kright(void) {
|
||||
}
|
||||
|
||||
static void krightw(void) {
|
||||
while (gbl_pos != gbl_len && !isspace(gbl_buf[gbl_pos])) {
|
||||
while (gbl_pos != gbl_len && isspace(gbl_buf[gbl_pos])) {
|
||||
gbl_pos++;
|
||||
}
|
||||
while (gbl_pos != gbl_len && isspace(gbl_buf[gbl_pos])) {
|
||||
while (gbl_pos != gbl_len && !isspace(gbl_buf[gbl_pos])) {
|
||||
gbl_pos++;
|
||||
}
|
||||
refresh();
|
||||
|
||||
Reference in New Issue
Block a user