mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-27 13:47:42 +00:00 
			
		
		
		
	Compare commits
	
		
			11 Commits
		
	
	
		
			ev-epoll-f
			...
			v1.32.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b5996f5f02 | ||
|   | 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.0 - 2023-10-14 | ||||
| - 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.0') | ||||
|  | ||||
| # 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_MINOR 32 | ||||
| #define JANET_VERSION_PATCH 0 | ||||
| #define JANET_VERSION_EXTRA "" | ||||
| #define JANET_VERSION "1.31.0" | ||||
| #define JANET_VERSION "1.32.0" | ||||
|  | ||||
| /* #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, | ||||
|   | ||||
| @@ -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,15 @@ 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); | ||||
| } | ||||
|  | ||||
| #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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user