1
0
mirror of https://github.com/janet-lang/janet synced 2026-04-11 17:31:26 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Calvin Rose
c5b3da1ffe Inter 2025-05-16 18:35:33 -05:00
19 changed files with 159 additions and 310 deletions

View File

@@ -1,4 +1,4 @@
image: openbsd/7.6
image: openbsd/7.4
sources:
- https://git.sr.ht/~bakpakin/janet
packages:

View File

@@ -25,7 +25,7 @@ jobs:
name: Build and test on Windows
strategy:
matrix:
os: [ windows-latest, windows-2022 ]
os: [ windows-latest, windows-2019 ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout the repository
@@ -46,7 +46,7 @@ jobs:
name: Build and test on Windows Minimal build
strategy:
matrix:
os: [ windows-2022 ]
os: [ windows-2019 ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout the repository

View File

@@ -1,15 +1,7 @@
# Changelog
All notable changes to this project will be documented in this file.
## 1.39.1 - 2025-08-30
- Add support for chdir in os/spawn on older macOS versions
- Expose channels properly in C API
## 1.39.0 - 2025-08-24
- Various bug fixes
- Add `net/socket`
- Add support for illumos OS
- Raise helpful errors for incorrect arguments to `import`.
## Unreleased - ???
- Allow configuring `JANET_THREAD_LOCAL` during builds to allow multi-threading on unknown compilers.
- Make `ffi/write` append to a buffer instead of insert at 0 by default.
- Add `os/getpid` to get the current process id.

View File

@@ -47,7 +47,6 @@ SPORK_TAG?=master
HAS_SHARED?=1
DEBUGGER=gdb
SONAME_SETTER=-Wl,-soname,
STRIPFLAGS=-x -S
# For cross compilation
HOSTCC?=$(CC)
@@ -55,7 +54,7 @@ HOSTAR?=$(AR)
# Symbols are (optionally) removed later, keep -g as default!
CFLAGS?=-O2 -g
LDFLAGS?=-rdynamic
LIBJANET_LDFLAGS?=$(LDFLAGS)
LIBJANET_LDFLAGS?=$(LD_FLAGS)
RUN:=$(RUN)
@@ -81,12 +80,6 @@ ifeq ($(UNAME), Darwin)
LDCONFIG:=true
else ifeq ($(UNAME), Linux)
CLIBS:=$(CLIBS) -lrt -ldl
else ifeq ($(UNAME), SunOS)
BUILD_CFLAGS+=-D__EXTENSIONS__ -DJANET_NO_NANBOX
BOOT_CFLAGS+=-D__EXTENSIONS__ -DJANET_NO_NANBOX
CLIBS:=-lsocket -lm
STRIPFLAGS=-x
LDCONFIG:=false
endif
# For other unix likes, add flags here!
@@ -220,9 +213,9 @@ build/%.bin.o: src/%.c $(JANET_HEADERS) $(JANET_LOCAL_HEADERS) Makefile
########################
ifeq ($(UNAME), Darwin)
SONAME=libjanet.1.39.dylib
SONAME=libjanet.1.38.dylib
else
SONAME=libjanet.so.1.39
SONAME=libjanet.so.1.38
endif
ifeq ($(MINGW_COMPILER), clang)
@@ -296,7 +289,7 @@ build/janet-%.tar.gz: $(JANET_TARGET) \
README.md build/c/janet.c build/c/shell.c
mkdir -p build/$(JANET_DIST_DIR)/bin
cp $(JANET_TARGET) build/$(JANET_DIST_DIR)/bin/
strip $(STRIPFLAGS) 'build/$(JANET_DIST_DIR)/bin/janet'
strip -x -S 'build/$(JANET_DIST_DIR)/bin/janet'
mkdir -p build/$(JANET_DIST_DIR)/include
cp build/janet.h build/$(JANET_DIST_DIR)/include/
mkdir -p build/$(JANET_DIST_DIR)/lib/
@@ -343,7 +336,7 @@ build/janet.pc: $(JANET_TARGET)
install: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.pc build/janet.h
mkdir -p '$(DESTDIR)$(BINDIR)'
cp $(JANET_TARGET) '$(DESTDIR)$(BINDIR)/janet'
strip $(STRIPFLAGS) '$(DESTDIR)$(BINDIR)/janet'
strip -x -S '$(DESTDIR)$(BINDIR)/janet'
mkdir -p '$(DESTDIR)$(INCLUDEDIR)/janet'
cp -r build/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet'
ln -sf ./janet/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet.h'

View File

@@ -213,10 +213,6 @@ gmake install-jpm-git
NetBSD build instructions are the same as the FreeBSD build instructions.
Alternatively, install the package directly with `pkgin install janet`.
### illumos
Building on illumos is exactly the same as building on FreeBSD.
### Windows
1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&rel=15#) or [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15#).

View File

@@ -1,6 +0,0 @@
# Linux only - uses abstract unix domain sockets
(ev/spawn (net/server :unix "@abc123" (fn [conn] (print (:read conn 1024)) (:close conn))))
(ev/sleep 1)
(def s (net/connect :unix "@abc123" :stream))
(:write s "hello")
(:close s)

View File

@@ -1,4 +1,4 @@
@{
:name "sample-dep1"
:dependencies [{:name "sample-dep2"}]
:dependencies ["sample-dep2"]
}

View File

@@ -20,7 +20,7 @@
project('janet', 'c',
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
version : '1.39.1')
version : '1.38.0')
# Global settings
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')

View File

@@ -158,7 +158,7 @@
``Define an alias for a keyword that is used as a dynamic binding. The
alias is a normal, lexically scoped binding that can be used instead of
a keyword to prevent typos. `defdyn` does not set dynamic bindings or otherwise
replace `dyn` and `setdyn`. The alias *must* start and end with the `*` character, usually
replace `dyn` and `setdyn`. The alias _must_ start and end with the `*` character, usually
called "earmuffs".``
[alias & more]
(assert (symbol? alias) "alias must be a symbol")
@@ -290,6 +290,22 @@
(array/concat accum body)
(tuple/slice accum 0))
(defmacro try
``Try something and catch errors. `body` is any expression,
and `catch` should be a form, the first element of which is a tuple. This tuple
should contain a binding for errors and an optional binding for
the fiber wrapping the body. Returns the result of `body` if no error,
or the result of `catch` if an error.``
[body catch]
(let [[[err fib]] catch
f (gensym)
r (gensym)]
~(let [,f (,fiber/new (fn :try [] ,body) :ie)
,r (,resume ,f)]
(if (,= (,fiber/status ,f) :error)
(do (def ,err ,r) ,(if fib ~(def ,fib ,f)) ,;(tuple/slice catch 1))
,r))))
(defmacro protect
`Evaluate expressions, while capturing any errors. Evaluates to a tuple
of two elements. The first element is true if successful, false if an
@@ -336,23 +352,6 @@
(tuple 'if $fi $fi ret))))))
ret)
(defmacro try
``Try something and catch errors. `body` is any expression,
and `catch` should be a form, the first element of which is a tuple. This tuple
should contain a binding for errors and an optional binding for
the fiber wrapping the body. Returns the result of `body` if no error,
or the result of `catch` if an error.``
[body catch]
(assert (and (not (empty? catch)) (indexed? (catch 0))) "the first element of `catch` must be a tuple or array")
(let [[err fib] (catch 0)
r (or err (gensym))
f (or fib (gensym))]
~(let [,f (,fiber/new (fn :try [] ,body) :ie)
,r (,resume ,f)]
(if (,= (,fiber/status ,f) :error)
(do ,;(tuple/slice catch 1))
,r))))
(defmacro with-syms
"Evaluates `body` with each symbol in `syms` bound to a generated, unique symbol."
[syms & body]
@@ -3181,17 +3180,12 @@
use the name of the module as a prefix. One can also use "`:export true`"
to re-export the imported symbols. If "`:exit true`" is given as an argument,
any errors encountered at the top level in the module will cause `(os/exit 1)`
to be called. Dynamic bindings will NOT be imported. Use :fresh with a truthy
value to bypass the module cache. Use `:only [foo bar baz]` to only import
select bindings into the current environment.``
to be called. Dynamic bindings will NOT be imported. Use :fresh to bypass the
module cache. Use `:only [foo bar baz]` to only import select bindings into the
current environment.``
[path & args]
(assertf (even? (length args)) "args should have even length: %n" args)
(def ps (partition 2 args))
(def argm
(mapcat (fn [[k v]]
(assertf (keyword? k) "expected keyword, got %s: %n" (type k) k)
[k (case k :as (string v) :only ~(quote ,v) v)])
ps))
(def argm (mapcat (fn [[k v]] [k (case k :as (string v) :only ~(quote ,v) v)]) ps))
(tuple import* (string path) ;argm))
(defmacro use
@@ -3254,10 +3248,12 @@
# Terminal codes for emission/tokenization
(def delimiters
(if has-color
{:code ["\e[97m" "\e[39m"]
{:underline ["\e[4m" "\e[24m"]
:code ["\e[97m" "\e[39m"]
:italics ["\e[4m" "\e[24m"]
:bold ["\e[1m" "\e[22m"]}
{:code ["`" "`"]
{:underline ["_" "_"]
:code ["`" "`"]
:italics ["*" "*"]
:bold ["**" "**"]}))
(def modes @{})
@@ -3388,6 +3384,7 @@
(= b (chr `\`)) (do
(++ token-length)
(buffer/push token (get line (++ i))))
(= b (chr "_")) (delim :underline)
(= b (chr "*"))
(if (= (chr "*") (get line (+ i 1)))
(do (++ i)
@@ -3919,14 +3916,8 @@
(compwhen (dyn 'net/listen)
(defn net/server
``
Starts a server with `net/listen`. Runs `net/accept-loop` asynchronously if
`handler` is set and `type` is `:stream` (the default). It is invalid to set
`handler` if `type` is `:datagram`. Returns the new server stream.
``
"Start a server asynchronously with `net/listen` and `net/accept-loop`. Returns the new server stream."
[host port &opt handler type no-reuse]
(assert (not (and (= type :datagram) handler))
"handler not supported for :datagram servers")
(def s (net/listen host port type no-reuse))
(if handler
(ev/go (fn [] (net/accept-loop s handler))))
@@ -4305,14 +4296,20 @@
"Install a bundle from the local filesystem. The name of the bundle will be inferred from the bundle, or passed as a parameter :name in `config`."
[path &keys config]
(def path (bundle-rpath path))
(def clean (get config :clean))
(def check (get config :check))
(def s (sep))
# Detect bundle name
(def infofile-src1 (string path s "bundle" s "info.jdn"))
(def infofile-src2 (string path s "info.jdn"))
(def infofile-src (cond (fexists infofile-src1) infofile-src1
(fexists infofile-src2) infofile-src2))
(def info (-?> infofile-src slurp parse))
(def bundle-name (get config :name (get info :name)))
# Check meta file for dependencies and default name
(def infofile-pre-1 (string path s "bundle" s "info.jdn"))
(def infofile-pre (if (fexists infofile-pre-1) infofile-pre-1 (string path s "info.jdn"))) # allow for alias
(var default-bundle-name nil)
(when (os/stat infofile-pre :mode)
(def info (-> infofile-pre slurp parse))
(def deps (get info :dependencies @[]))
(set default-bundle-name (get info :name))
(def missing (seq [d :in deps :when (not (bundle/installed? d))] (string d)))
(when (next missing) (errorf "missing dependencies %s" (string/join missing ", "))))
(def bundle-name (get config :name default-bundle-name))
(assertf bundle-name "unable to infer bundle name for %v, use :name argument" path)
(assertf (not (string/check-set "\\/" bundle-name))
"bundle name %v cannot contain path separators" bundle-name)
@@ -4322,32 +4319,28 @@
# Setup installed paths
(prime-bundle-paths)
(os/mkdir (bundle-dir bundle-name))
# Copy infofile
(def infofile-dest (bundle-file bundle-name "info.jdn"))
(when infofile-src (copyfile infofile-src infofile-dest))
# Copy aliased initfile
(def initfile-alias (string path s "bundle.janet"))
(def initfile-dest (bundle-file bundle-name "init.janet"))
(when (fexists initfile-alias) (copyfile initfile-alias initfile-dest))
# Aliases for common bundle/ files
(def bundle.janet (string path s "bundle.janet"))
(when (fexists bundle.janet) (copyfile bundle.janet (bundle-file bundle-name "init.janet")))
(when (fexists infofile-pre) (copyfile infofile-pre (bundle-file bundle-name "info.jdn")))
# Copy some files into the new location unconditionally
(def implicit-sources (string path s "bundle"))
(when (= :directory (os/stat implicit-sources :mode))
(copyrf implicit-sources (bundle-dir bundle-name)))
(def man @{:name bundle-name :local-source path :files @[]})
(merge-into man config)
(def infofile (bundle-file bundle-name "info.jdn"))
(put man :auto-remove (get config :auto-remove))
(sync-manifest man)
(edefer (do (print "installation error, uninstalling") (bundle/uninstall bundle-name))
(when (os/stat infofile-dest :mode)
(def info (-> infofile-dest slurp parse))
(def deps (seq [d :in (get info :dependencies @[])]
(string (if (dictionary? d) (get d :name) d))))
(when (os/stat infofile :mode)
(def info (-> infofile slurp parse))
(def deps (get info :dependencies @[]))
(def missing (filter (complement bundle/installed?) deps))
(when (next missing)
(error (string "missing dependencies " (string/join missing ", "))))
(put man :dependencies deps)
(put man :info info))
(def clean (get config :clean))
(def check (get config :check))
(def module (get-bundle-module bundle-name))
(def all-hooks (seq [[k v] :pairs module :when (symbol? k) :unless (get v :private)] (keyword k)))
(put man :hooks all-hooks)

View File

@@ -4,10 +4,10 @@
#define JANETCONF_H
#define JANET_VERSION_MAJOR 1
#define JANET_VERSION_MINOR 39
#define JANET_VERSION_PATCH 1
#define JANET_VERSION_MINOR 38
#define JANET_VERSION_PATCH 0
#define JANET_VERSION_EXTRA ""
#define JANET_VERSION "1.39.1"
#define JANET_VERSION "1.38.0"
/* #define JANET_BUILD "local" */

View File

@@ -653,15 +653,22 @@ JANET_CORE_FN(janet_core_check_int,
"(int? x)",
"Check if x can be exactly represented as a 32 bit signed two's complement integer.") {
janet_fixarity(argc, 1);
return janet_wrap_boolean(janet_checkint(argv[0]));
if (!janet_checktype(argv[0], JANET_NUMBER)) goto ret_false;
double num = janet_unwrap_number(argv[0]);
return janet_wrap_boolean(num == (double)((int32_t)num));
ret_false:
return janet_wrap_false();
}
JANET_CORE_FN(janet_core_check_nat,
"(nat? x)",
"Check if x can be exactly represented as a non-negative 32 bit signed two's complement integer.") {
janet_fixarity(argc, 1);
if (!janet_checkint(argv[0])) return janet_wrap_false();
return janet_wrap_boolean(janet_unwrap_integer(argv[0]) >= 0);
if (!janet_checktype(argv[0], JANET_NUMBER)) goto ret_false;
double num = janet_unwrap_number(argv[0]);
return janet_wrap_boolean(num >= 0 && (num == (double)((int32_t)num)));
ret_false:
return janet_wrap_false();
}
JANET_CORE_FN(janet_core_is_bytes,

View File

@@ -604,44 +604,8 @@ void janet_ev_init_common(void) {
#endif
}
#ifdef JANET_WINDOWS
static VOID CALLBACK janet_timeout_stop(ULONG_PTR ptr) {
UNREFERENCED_PARAMETER(ptr);
ExitThread(0);
}
#elif JANET_ANDROID
static void janet_timeout_stop(int sig_num) {
if (sig_num == SIGUSR1) {
pthread_exit(0);
}
}
#endif
static void handle_timeout_worker(JanetTimeout to, int cancel) {
if (!to.has_worker) return;
#ifdef JANET_WINDOWS
(void) cancel;
QueueUserAPC(janet_timeout_stop, to.worker, 0);
WaitForSingleObject(to.worker, INFINITE);
CloseHandle(to.worker);
#else
#ifdef JANET_ANDROID
if (cancel) janet_assert(!pthread_kill(to.worker, SIGUSR1), "pthread_kill");
#else
if (cancel) janet_assert(!pthread_cancel(to.worker), "pthread_cancel");
#endif
void *res = NULL;
janet_assert(!pthread_join(to.worker, &res), "pthread_join");
#endif
}
/* Common deinit code */
void janet_ev_deinit_common(void) {
JanetTimeout to;
while (peek_timeout(&to)) {
handle_timeout_worker(to, 1);
pop_timeout(0);
}
janet_q_deinit(&janet_vm.spawn);
janet_free(janet_vm.tq);
janet_table_deinit(&janet_vm.threaded_abstracts);
@@ -684,6 +648,19 @@ void janet_addtimeout_nil(double sec) {
add_timeout(to);
}
#ifdef JANET_WINDOWS
static VOID CALLBACK janet_timeout_stop(ULONG_PTR ptr) {
UNREFERENCED_PARAMETER(ptr);
ExitThread(0);
}
#elif JANET_ANDROID
static void janet_timeout_stop(int sig_num) {
if (sig_num == SIGUSR1) {
pthread_exit(0);
}
}
#endif
static void janet_timeout_cb(JanetEVGenericMessage msg) {
(void) msg;
janet_interpreter_interrupt_handled(&janet_vm);
@@ -694,9 +671,11 @@ static DWORD WINAPI janet_timeout_body(LPVOID ptr) {
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
janet_free(ptr);
SleepEx((DWORD)(tto.sec * 1000), TRUE);
janet_interpreter_interrupt(tto.vm);
JanetEVGenericMessage msg = {0};
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
if (janet_fiber_can_resume(tto.fiber)) {
janet_interpreter_interrupt(tto.vm);
JanetEVGenericMessage msg = {0};
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
}
return 0;
}
#else
@@ -717,9 +696,11 @@ static void *janet_timeout_body(void *ptr) {
? (long)((tto.sec - ((uint32_t)tto.sec)) * 1000000000)
: 0;
nanosleep(&ts, &ts);
janet_interpreter_interrupt(tto.vm);
JanetEVGenericMessage msg = {0};
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
if (janet_fiber_can_resume(tto.fiber)) {
janet_interpreter_interrupt(tto.vm);
JanetEVGenericMessage msg = {0};
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
}
return NULL;
}
#endif
@@ -1471,7 +1452,6 @@ JanetFiber *janet_loop1(void) {
}
}
}
handle_timeout_worker(to, 0);
}
/* Run scheduled fibers unless interrupts need to be handled. */
@@ -1519,14 +1499,27 @@ JanetFiber *janet_loop1(void) {
while ((has_timeout = peek_timeout(&to))) {
if (to.curr_fiber != NULL) {
if (!janet_fiber_can_resume(to.curr_fiber)) {
pop_timeout(0);
if (to.has_worker) {
#ifdef JANET_WINDOWS
QueueUserAPC(janet_timeout_stop, to.worker, 0);
WaitForSingleObject(to.worker, INFINITE);
CloseHandle(to.worker);
#else
#ifdef JANET_ANDROID
pthread_kill(to.worker, SIGUSR1);
#else
pthread_cancel(to.worker);
#endif
void *res;
pthread_join(to.worker, &res);
#endif
}
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
handle_timeout_worker(to, 1);
pop_timeout(0);
continue;
}
} else if (to.fiber->sched_id != to.sched_id) {
pop_timeout(0);
handle_timeout_worker(to, 1);
continue;
}
break;
@@ -1691,7 +1684,7 @@ void janet_stream_level_triggered(JanetStream *stream) {
static JanetTimestamp ts_now(void) {
struct timespec now;
janet_assert(-1 != janet_gettime(&now, JANET_TIME_MONOTONIC), "failed to get time");
janet_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &now), "failed to get time");
uint64_t res = 1000 * now.tv_sec;
res += now.tv_nsec / 1000000;
return res;
@@ -1849,7 +1842,7 @@ JanetTimestamp to_interval(const JanetTimestamp ts) {
static JanetTimestamp ts_now(void) {
struct timespec now;
janet_assert(-1 != janet_gettime(&now, JANET_TIME_MONOTONIC), "failed to get time");
janet_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &now), "failed to get time");
uint64_t res = 1000 * now.tv_sec;
res += now.tv_nsec / 1000000;
return res;
@@ -2003,7 +1996,7 @@ void janet_ev_deinit(void) {
static JanetTimestamp ts_now(void) {
struct timespec now;
janet_assert(-1 != janet_gettime(&now, JANET_TIME_MONOTONIC), "failed to get time");
janet_assert(-1 != clock_gettime(CLOCK_REALTIME, &now), "failed to get time");
uint64_t res = 1000 * now.tv_sec;
res += now.tv_nsec / 1000000;
return res;
@@ -3181,7 +3174,6 @@ JANET_NO_RETURN void janet_sleep_await(double sec) {
to.is_error = 0;
to.sched_id = to.fiber->sched_id;
to.curr_fiber = NULL;
to.has_worker = 0;
add_timeout(to);
janet_await();
}
@@ -3239,6 +3231,7 @@ JANET_CORE_FN(cfun_ev_deadline,
janet_free(tto);
janet_panicf("%s", janet_strerror(err));
}
janet_assert(!pthread_detach(worker), "pthread_detach");
#endif
to.has_worker = 1;
to.worker = worker;
@@ -3536,6 +3529,8 @@ void janet_lib_ev(JanetTable *env) {
janet_register_abstract_type(&janet_channel_type);
janet_register_abstract_type(&janet_mutex_type);
janet_register_abstract_type(&janet_rwlock_type);
janet_lib_filewatch(env);
}
#endif

View File

@@ -341,7 +341,7 @@ static int janet_get_sockettype(Janet *argv, int32_t argc, int32_t n) {
/* Needs argc >= offset + 2 */
/* For unix paths, just rertuns a single sockaddr and sets *is_unix to 1,
* otherwise 0. Also, ignores is_bind when is a unix socket. */
static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int socktype, int passive, int *is_unix, socklen_t *sizeout) {
static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int socktype, int passive, int *is_unix) {
/* Unix socket support - not yet supported on windows. */
#ifndef JANET_WINDOWS
if (janet_keyeq(argv[offset], "unix")) {
@@ -352,14 +352,15 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock
}
saddr->sun_family = AF_UNIX;
size_t path_size = sizeof(saddr->sun_path);
snprintf(saddr->sun_path, path_size, "%s", path);
*sizeout = sizeof(struct sockaddr_un);
#ifdef JANET_LINUX
if (path[0] == '@') {
saddr->sun_path[0] = '\0';
*sizeout = offsetof(struct sockaddr_un, sun_path) + janet_string_length(path);
}
snprintf(saddr->sun_path + 1, path_size - 1, "%s", path + 1);
} else
#endif
{
snprintf(saddr->sun_path, path_size, "%s", path);
}
*is_unix = 1;
return (struct addrinfo *) saddr;
}
@@ -384,11 +385,6 @@ static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset, int sock
janet_panicf("could not get address info: %s", gai_strerror(status));
}
*is_unix = 0;
#ifdef JANET_WINDOWS
*sizeout = 0;
#else
*sizeout = sizeof(struct sockaddr_un);
#endif
return ai;
}
@@ -409,13 +405,12 @@ JANET_CORE_FN(cfun_net_sockaddr,
int socktype = janet_get_sockettype(argv, argc, 2);
int is_unix = 0;
int make_arr = (argc >= 3 && janet_truthy(argv[3]));
socklen_t addrsize = 0;
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, &addrsize);
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix);
#ifndef JANET_WINDOWS
/* no unix domain socket support on windows yet */
if (is_unix) {
void *abst = janet_abstract(&janet_address_type, addrsize);
memcpy(abst, ai, addrsize);
void *abst = janet_abstract(&janet_address_type, sizeof(struct sockaddr_un));
memcpy(abst, ai, sizeof(struct sockaddr_un));
Janet ret = janet_wrap_abstract(abst);
return make_arr ? janet_wrap_array(janet_array_n(&ret, 1)) : ret;
}
@@ -466,8 +461,7 @@ JANET_CORE_FN(cfun_net_connect,
}
/* Where we're connecting to */
socklen_t addrlen = 0;
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, &addrlen);
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix);
/* Check if we're binding address */
struct addrinfo *binding = NULL;
@@ -492,6 +486,7 @@ JANET_CORE_FN(cfun_net_connect,
/* Create socket */
JSock sock = JSOCKDEFAULT;
void *addr = NULL;
socklen_t addrlen = 0;
#ifndef JANET_WINDOWS
if (is_unix) {
sock = socket(AF_UNIX, socktype | JSOCKFLAGS, 0);
@@ -501,6 +496,7 @@ JANET_CORE_FN(cfun_net_connect,
janet_panicf("could not create socket: %V", v);
}
addr = (void *) ai;
addrlen = sizeof(struct sockaddr_un);
} else
#endif
{
@@ -547,9 +543,7 @@ JANET_CORE_FN(cfun_net_connect,
}
/* Wrap socket in abstract type JanetStream */
uint32_t udp_flag = 0;
if (socktype == SOCK_DGRAM) udp_flag = JANET_STREAM_UDPSERVER;
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE | udp_flag);
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
/* Set up the socket for non-blocking IO before connecting */
janet_net_socknoblock(sock);
@@ -587,56 +581,6 @@ JANET_CORE_FN(cfun_net_connect,
net_sched_connect(stream);
}
JANET_CORE_FN(cfun_net_socket,
"(net/socket &opt type)",
"Creates a new unbound socket. Type is an optional keyword, "
"either a :stream (usually tcp), or :datagram (usually udp). The default is :stream.") {
janet_arity(argc, 0, 1);
int socktype = janet_get_sockettype(argv, argc, 0);
/* Create socket */
JSock sfd = JSOCKDEFAULT;
struct addrinfo *ai = NULL;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = socktype;
hints.ai_flags = 0;
int status = getaddrinfo(NULL, "0", &hints, &ai);
if (status) {
janet_panicf("could not get address info: %s", gai_strerror(status));
}
struct addrinfo *rp = NULL;
for (rp = ai; rp != NULL; rp = rp->ai_next) {
#ifdef JANET_WINDOWS
sfd = WSASocketW(rp->ai_family, rp->ai_socktype | JSOCKFLAGS, rp->ai_protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
#else
sfd = socket(rp->ai_family, rp->ai_socktype | JSOCKFLAGS, rp->ai_protocol);
#endif
if (JSOCKVALID(sfd)) {
break;
}
}
freeaddrinfo(ai);
if (!JSOCKVALID(sfd)) {
Janet v = janet_ev_lasterr();
janet_panicf("could not create socket: %V", v);
}
/* Wrap socket in abstract type JanetStream */
uint32_t udp_flag = 0;
if (socktype == SOCK_DGRAM) udp_flag = JANET_STREAM_UDPSERVER;
JanetStream *stream = make_stream(sfd, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE | udp_flag);
/* Set up the socket for non-blocking IO */
janet_net_socknoblock(sfd);
return janet_wrap_abstract(stream);
}
static const char *serverify_socket(JSock sfd, int reuse_addr, int reuse_port) {
/* Set various socket options */
int enable = 1;
@@ -720,8 +664,7 @@ JANET_CORE_FN(cfun_net_listen,
/* Get host, port, and handler*/
int socktype = janet_get_sockettype(argv, argc, 2);
int is_unix = 0;
socklen_t addrlen = 0;
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix, &addrlen);
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix);
int reuse = !(argc >= 4 && janet_truthy(argv[3]));
JSock sfd = JSOCKDEFAULT;
@@ -733,7 +676,7 @@ JANET_CORE_FN(cfun_net_listen,
janet_panicf("could not create socket: %V", janet_ev_lasterr());
}
const char *err = serverify_socket(sfd, reuse, 0);
if (NULL != err || bind(sfd, (struct sockaddr *)ai, addrlen)) {
if (NULL != err || bind(sfd, (struct sockaddr *)ai, sizeof(struct sockaddr_un))) {
JSOCKCLOSE(sfd);
janet_free(ai);
if (err) {
@@ -1135,7 +1078,6 @@ void janet_lib_net(JanetTable *env) {
JanetRegExt net_cfuns[] = {
JANET_CORE_REG("net/address", cfun_net_sockaddr),
JANET_CORE_REG("net/listen", cfun_net_listen),
JANET_CORE_REG("net/socket", cfun_net_socket),
JANET_CORE_REG("net/accept", cfun_stream_accept),
JANET_CORE_REG("net/accept-loop", cfun_stream_accept_loop),
JANET_CORE_REG("net/read", cfun_stream_read),

View File

@@ -66,7 +66,6 @@
#ifdef JANET_APPLE
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#include <AvailabilityMacros.h>
#else
extern char **environ;
#endif
@@ -82,14 +81,8 @@ extern char **environ;
#ifndef JANET_SPAWN_NO_CHDIR
#ifdef __GLIBC__
#define JANET_SPAWN_CHDIR
#elif defined(JANET_APPLE)
/* The posix_spawn_file_actions_addchdir_np function
* has only been implemented since macOS 10.15 */
#if defined(MAC_OS_X_VERSION_10_15) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15)
#elif defined(JANET_APPLE) /* Some older versions may not work here. */
#define JANET_SPAWN_CHDIR
#else
#define JANET_SPAWN_NO_CHDIR
#endif
#elif defined(__FreeBSD__) /* Not all BSDs work, for example openBSD doesn't seem to support this */
#define JANET_SPAWN_CHDIR
#endif
@@ -180,8 +173,6 @@ JANET_CORE_FN(os_which,
return janet_ckeywordv("dragonfly");
#elif defined(JANET_BSD)
return janet_ckeywordv("bsd");
#elif defined(JANET_ILLUMOS)
return janet_ckeywordv("illumos");
#else
return janet_ckeywordv("posix");
#endif
@@ -321,13 +312,6 @@ JANET_CORE_FN(os_cpu_count,
return dflt;
}
return janet_wrap_integer(result);
#elif defined(JANET_ILLUMOS)
(void) dflt;
long result = sysconf(_SC_NPROCESSORS_CONF);
if (result < 0) {
return dflt;
}
return janet_wrap_integer(result);
#else
return dflt;
#endif
@@ -2879,9 +2863,6 @@ void janet_lib_os(JanetTable *env) {
JANET_CORE_REG("os/proc-kill", os_proc_kill),
JANET_CORE_REG("os/proc-close", os_proc_close),
JANET_CORE_REG("os/getpid", os_proc_getpid),
#ifdef JANET_EV
JANET_CORE_REG("os/sigaction", os_sigaction),
#endif
#endif
/* high resolution timers */
@@ -2890,6 +2871,7 @@ void janet_lib_os(JanetTable *env) {
#ifdef JANET_EV
JANET_CORE_REG("os/open", os_open), /* fs read and write */
JANET_CORE_REG("os/pipe", os_pipe),
JANET_CORE_REG("os/sigaction", os_sigaction),
#endif
#endif
JANET_REG_END

View File

@@ -1066,7 +1066,7 @@ void janet_buffer_format(
if (form[2] == '\0')
janet_buffer_push_bytes(b, s, l);
else {
if (l != (int32_t) strnlen((const char *) s, l))
if (l != (int32_t) strlen((const char *) s))
janet_panic("string contains zeros");
if (!strchr(form, '.') && l >= 100) {
janet_panic("no precision and string is too long to be formatted");

View File

@@ -931,24 +931,27 @@ int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
#include <mach/clock.h>
#include <mach/mach.h>
int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
if (source == JANET_TIME_CPUTIME) {
clock_t tmp = clock();
spec->tv_sec = tmp / CLOCKS_PER_SEC;
spec->tv_nsec = ((tmp - (spec->tv_sec * CLOCKS_PER_SEC)) * 1000000000) / CLOCKS_PER_SEC;
} else {
if (source == JANET_TIME_REALTIME) {
clock_serv_t cclock;
mach_timespec_t mts;
clock_id_t cid = CALENDAR_CLOCK;
if (source == JANET_TIME_REALTIME) {
cid = CALENDAR_CLOCK;
} else if (source == JANET_TIME_MONOTONIC) {
cid = SYSTEM_CLOCK;
}
host_get_clock_service(mach_host_self(), cid, &cclock);
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
spec->tv_sec = mts.tv_sec;
spec->tv_nsec = mts.tv_nsec;
} else if (source == JANET_TIME_MONOTONIC) {
clock_serv_t cclock;
int nsecs;
mach_msg_type_number_t count;
host_get_clock_service(mach_host_self(), clock, &cclock);
clock_get_attributes(cclock, CLOCK_GET_TIME_RES, (clock_attr_t)&nsecs, &count);
mach_port_deallocate(mach_task_self(), cclock);
clock_getres(CLOCK_MONOTONIC, spec);
}
if (source == JANET_TIME_CPUTIME) {
clock_t tmp = clock();
spec->tv_sec = tmp;
spec->tv_nsec = (tmp - spec->tv_sec) * 1.0e9;
}
return 0;
}

View File

@@ -77,11 +77,6 @@ extern "C" {
#define JANET_CYGWIN 1
#endif
/* Check for Illumos */
#if defined(__illumos__)
#define JANET_ILLUMOS 1
#endif
/* Check Unix */
#if defined(_AIX) \
|| defined(__APPLE__) /* Darwin */ \
@@ -167,7 +162,7 @@ extern "C" {
#endif
/* Check sun */
#if defined(__sun) && !defined(JANET_ILLUMOS)
#ifdef __sun
#define JANET_NO_UTC_MKTIME
#endif
@@ -1465,10 +1460,10 @@ JANET_API int32_t janet_abstract_incref(void *abst);
JANET_API int32_t janet_abstract_decref(void *abst);
/* Expose channel utilities */
JANET_API JanetChannel *janet_channel_make(uint32_t limit);
JANET_API JanetChannel *janet_channel_make_threaded(uint32_t limit);
JANET_API JanetChannel *janet_getchannel(const Janet *argv, int32_t n);
JANET_API JanetChannel *janet_optchannel(const Janet *argv, int32_t argc, int32_t n, JanetChannel *dflt);
JanetChannel *janet_channel_make(uint32_t limit);
JanetChannel *janet_channel_make_threaded(uint32_t limit);
JanetChannel *janet_getchannel(const Janet *argv, int32_t n);
JanetChannel *janet_optchannel(const Janet *argv, int32_t argc, int32_t n, JanetChannel *dflt);
JANET_API int janet_channel_give(JanetChannel *channel, Janet x);
JANET_API int janet_channel_take(JanetChannel *channel, Janet *out);

View File

@@ -865,13 +865,6 @@
(assert (deep= ~(,import* "a" :as "b" :fresh maybe)
(macex '(import a :as b :fresh maybe))) "import macro 2")
# 2af3f21d
(assert-error "import macro 2" (macex '(import a :fresh)))
(assert-error "import macro 3" (macex '(import a :as b :fresh)))
(assert-error "import macro 4" (macex '(import b "notakeyword" value)))
(assert (deep= ~(,import* "a" :fresh nil)
(macex '(import a :fresh nil))) "import macro 5")
# #477 walk preserving bracket type
# 0a1d902f4
(assert (= :brackets (tuple/type (postwalk identity '[])))

View File

@@ -106,8 +106,6 @@
(calc-2 "(+ 9 10 11 12)"))
@[10 26 42]) "parallel subprocesses 2")
# (print "file piping")
# File piping
# a1cc5ca04
(assert-no-error "file writing 1"
@@ -227,8 +225,6 @@
(++ iterations)
(ev/write stream " ")))
# (print "local name / peer name testing")
# Test localname and peername
# 077bf5eba
(repeat 10
@@ -411,8 +407,6 @@
(while (def msg (ev/read connection 100))
(broadcast name (string msg)))))))
# (print "chat app testing")
# Now launch the chat server
(def chat-server (net/listen test-host test-port))
(ev/spawn
@@ -506,8 +500,6 @@
(let [s (net/listen :unix uds-path :stream)]
(:close s))))))
# (print "accept loop testing")
# net/accept-loop level triggering
(gccollect)
(def maxconn 50)
@@ -530,8 +522,6 @@
(assert (= maxconn connect-count))
(:close s)
# (print "running deadline tests...")
# Cancel os/proc-wait with ev/deadline
(let [p (os/spawn [;run janet "-e" "(os/sleep 4)"] :p)]
(var terminated-normally false)
@@ -556,35 +546,9 @@
(ev/sleep 0.15)
(assert (not terminated-normally) "early termination failure 3"))
# Deadline with interrupt
(defmacro with-deadline2
``
Create a fiber to execute `body`, schedule the event loop to cancel
the task (root fiber) associated with `body`'s fiber, and start
`body`'s fiber by resuming it.
The event loop will try to cancel the root fiber if `body`'s fiber
has not completed after at least `sec` seconds.
`sec` is a number that can have a fractional part.
``
[sec & body]
(with-syms [f]
~(let [,f (coro ,;body)]
(,ev/deadline ,sec nil ,f true)
(,resume ,f))))
(for i 0 10
# (print "deadline 1 iteration " i)
(assert (= :done (with-deadline2 10
(ev/sleep 0.01)
:done)) "deadline with interrupt exits normally"))
(for i 0 10
# (print "deadline 2 iteration " i)
(let [f (coro (forever :foo))]
(ev/deadline 0.01 nil f true)
(assert-error "deadline expired" (resume f))))
(let [f (coro (forever :foo))]
(ev/deadline 0.01 nil f true)
(assert-error "deadline expired" (resume f)))
# Use :err :stdout
(def- subproc-code '(do (eprint "hi") (eflush) (print "there") (flush)))