mirror of
https://github.com/janet-lang/janet
synced 2025-11-26 12:14:49 +00:00
Compare commits
5 Commits
no-critica
...
posix-spaw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a62d1c35d4 | ||
|
|
9a737d1fc4 | ||
|
|
03672cc82b | ||
|
|
73af64e6ff | ||
|
|
2262759751 |
@@ -1,4 +1,4 @@
|
|||||||
image: openbsd/7.6
|
image: openbsd/7.4
|
||||||
sources:
|
sources:
|
||||||
- https://git.sr.ht/~bakpakin/janet
|
- https://git.sr.ht/~bakpakin/janet
|
||||||
packages:
|
packages:
|
||||||
|
|||||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
name: Build and test on Windows
|
name: Build and test on Windows
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ windows-latest, windows-2022 ]
|
os: [ windows-latest, windows-2019 ]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
name: Build and test on Windows Minimal build
|
name: Build and test on Windows Minimal build
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ windows-2022 ]
|
os: [ windows-2019 ]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
|
|||||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -2,23 +2,9 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## Unreleased - ???
|
## Unreleased - ???
|
||||||
- Add `gcperthread` callback for abstract types. This lets threaded abstracts have a finalizer that is called per thread, as well as a global finalizer.
|
|
||||||
- Add `JANET_DO_ERROR_*` flags to describe the return value of `janet_dobytes` and `janet_dostring`.
|
|
||||||
|
|
||||||
## 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`.
|
|
||||||
- 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.
|
- Make `ffi/write` append to a buffer instead of insert at 0 by default.
|
||||||
- Add `os/getpid` to get the current process id.
|
- Add `os/getpid` to get the current process id.
|
||||||
- Add `:out` option to `os/spawn` to be able to redirect stderr to stdout with pipes.
|
- Add `:out` option to `os/spawn` to be able to redirect stderr to stdout with pipes.
|
||||||
Add `interrupt?` argument to `ev/deadline` to use VM interruptions.
|
|
||||||
|
|
||||||
## 1.38.0 - 2025-03-18
|
## 1.38.0 - 2025-03-18
|
||||||
- Add `bundle/replace`
|
- Add `bundle/replace`
|
||||||
|
|||||||
17
Makefile
17
Makefile
@@ -47,7 +47,6 @@ SPORK_TAG?=master
|
|||||||
HAS_SHARED?=1
|
HAS_SHARED?=1
|
||||||
DEBUGGER=gdb
|
DEBUGGER=gdb
|
||||||
SONAME_SETTER=-Wl,-soname,
|
SONAME_SETTER=-Wl,-soname,
|
||||||
STRIPFLAGS=-x -S
|
|
||||||
|
|
||||||
# For cross compilation
|
# For cross compilation
|
||||||
HOSTCC?=$(CC)
|
HOSTCC?=$(CC)
|
||||||
@@ -55,7 +54,7 @@ HOSTAR?=$(AR)
|
|||||||
# Symbols are (optionally) removed later, keep -g as default!
|
# Symbols are (optionally) removed later, keep -g as default!
|
||||||
CFLAGS?=-O2 -g
|
CFLAGS?=-O2 -g
|
||||||
LDFLAGS?=-rdynamic
|
LDFLAGS?=-rdynamic
|
||||||
LIBJANET_LDFLAGS?=$(LDFLAGS)
|
LIBJANET_LDFLAGS?=$(LD_FLAGS)
|
||||||
RUN:=$(RUN)
|
RUN:=$(RUN)
|
||||||
|
|
||||||
|
|
||||||
@@ -81,12 +80,6 @@ ifeq ($(UNAME), Darwin)
|
|||||||
LDCONFIG:=true
|
LDCONFIG:=true
|
||||||
else ifeq ($(UNAME), Linux)
|
else ifeq ($(UNAME), Linux)
|
||||||
CLIBS:=$(CLIBS) -lrt -ldl
|
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
|
endif
|
||||||
|
|
||||||
# For other unix likes, add flags here!
|
# 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)
|
ifeq ($(UNAME), Darwin)
|
||||||
SONAME=libjanet.1.40.dylib
|
SONAME=libjanet.1.38.dylib
|
||||||
else
|
else
|
||||||
SONAME=libjanet.so.1.40
|
SONAME=libjanet.so.1.38
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(MINGW_COMPILER), clang)
|
ifeq ($(MINGW_COMPILER), clang)
|
||||||
@@ -296,7 +289,7 @@ build/janet-%.tar.gz: $(JANET_TARGET) \
|
|||||||
README.md build/c/janet.c build/c/shell.c
|
README.md build/c/janet.c build/c/shell.c
|
||||||
mkdir -p build/$(JANET_DIST_DIR)/bin
|
mkdir -p build/$(JANET_DIST_DIR)/bin
|
||||||
cp $(JANET_TARGET) 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
|
mkdir -p build/$(JANET_DIST_DIR)/include
|
||||||
cp build/janet.h build/$(JANET_DIST_DIR)/include/
|
cp build/janet.h build/$(JANET_DIST_DIR)/include/
|
||||||
mkdir -p build/$(JANET_DIST_DIR)/lib/
|
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
|
install: $(JANET_TARGET) $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) build/janet.pc build/janet.h
|
||||||
mkdir -p '$(DESTDIR)$(BINDIR)'
|
mkdir -p '$(DESTDIR)$(BINDIR)'
|
||||||
cp $(JANET_TARGET) '$(DESTDIR)$(BINDIR)/janet'
|
cp $(JANET_TARGET) '$(DESTDIR)$(BINDIR)/janet'
|
||||||
strip $(STRIPFLAGS) '$(DESTDIR)$(BINDIR)/janet'
|
strip -x -S '$(DESTDIR)$(BINDIR)/janet'
|
||||||
mkdir -p '$(DESTDIR)$(INCLUDEDIR)/janet'
|
mkdir -p '$(DESTDIR)$(INCLUDEDIR)/janet'
|
||||||
cp -r build/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet'
|
cp -r build/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet'
|
||||||
ln -sf ./janet/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet.h'
|
ln -sf ./janet/janet.h '$(DESTDIR)$(INCLUDEDIR)/janet.h'
|
||||||
|
|||||||
@@ -213,10 +213,6 @@ gmake install-jpm-git
|
|||||||
NetBSD build instructions are the same as the FreeBSD build instructions.
|
NetBSD build instructions are the same as the FreeBSD build instructions.
|
||||||
Alternatively, install the package directly with `pkgin install janet`.
|
Alternatively, install the package directly with `pkgin install janet`.
|
||||||
|
|
||||||
### illumos
|
|
||||||
|
|
||||||
Building on illumos is exactly the same as building on FreeBSD.
|
|
||||||
|
|
||||||
### Windows
|
### 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#).
|
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#).
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ for %%f in (src\boot\*.c) do (
|
|||||||
)
|
)
|
||||||
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
%JANET_LINK% /out:build\janet_boot.exe build\boot\*.obj
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
@rem note that there is no default sysroot being baked in
|
|
||||||
build\janet_boot . > build\c\janet.c
|
build\janet_boot . > build\c\janet.c
|
||||||
@if errorlevel 1 goto :BUILDFAIL
|
@if errorlevel 1 goto :BUILDFAIL
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@{
|
@{
|
||||||
:name "sample-dep1"
|
:name "sample-dep1"
|
||||||
:dependencies [{:name "sample-dep2"}]
|
:dependencies ["sample-dep2"]
|
||||||
}
|
}
|
||||||
|
|||||||
5
janet.1
5
janet.1
@@ -214,7 +214,7 @@ Don't execute a script, only compile it to check for errors. Useful for linting
|
|||||||
.BR \-m\ syspath
|
.BR \-m\ syspath
|
||||||
Set the dynamic binding :syspath to the string syspath so that Janet will load system modules
|
Set the dynamic binding :syspath to the string syspath so that Janet will load system modules
|
||||||
from a directory different than the default. The default is set when Janet is built, and defaults to
|
from a directory different than the default. The default is set when Janet is built, and defaults to
|
||||||
/usr/local/lib/janet on Linux/Posix. On Windows, there is no default value. This option supersedes JANET_PATH.
|
/usr/local/lib/janet on Linux/Posix, and C:/Janet/Library on Windows. This option supersedes JANET_PATH.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BR \-c\ source\ output
|
.BR \-c\ source\ output
|
||||||
@@ -255,7 +255,8 @@ and then arguments to the script.
|
|||||||
.RS
|
.RS
|
||||||
The location to look for Janet libraries. This is the only environment variable Janet needs to
|
The location to look for Janet libraries. This is the only environment variable Janet needs to
|
||||||
find native and source code modules. If no JANET_PATH is set, Janet will look in
|
find native and source code modules. If no JANET_PATH is set, Janet will look in
|
||||||
the default location set at compile time. This should be a colon-separated list of directory names on Linux/Posix, and a semicolon-separated list on Windows. Note that a typical setup (i.e. not NixOS / Guix) will only use a single directory.
|
the default location set at compile time. This should be a list of as well as a colon
|
||||||
|
separate list of such directories.
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.B JANET_PROFILE
|
.B JANET_PROFILE
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
project('janet', 'c',
|
project('janet', 'c',
|
||||||
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
|
default_options : ['c_std=c99', 'build.c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||||
version : '1.40.0')
|
version : '1.38.0')
|
||||||
|
|
||||||
# Global settings
|
# Global settings
|
||||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||||
@@ -105,9 +105,6 @@ endif
|
|||||||
if get_option('arch_name') != ''
|
if get_option('arch_name') != ''
|
||||||
conf.set('JANET_ARCH_NAME', get_option('arch_name'))
|
conf.set('JANET_ARCH_NAME', get_option('arch_name'))
|
||||||
endif
|
endif
|
||||||
if get_option('thread_local_prefix') != ''
|
|
||||||
conf.set('JANET_THREAD_LOCAL', get_option('thread_local_prefix'))
|
|
||||||
endif
|
|
||||||
jconf = configure_file(output : 'janetconf.h',
|
jconf = configure_file(output : 'janetconf.h',
|
||||||
configuration : conf)
|
configuration : conf)
|
||||||
|
|
||||||
@@ -281,7 +278,6 @@ test_files = [
|
|||||||
'test/suite-corelib.janet',
|
'test/suite-corelib.janet',
|
||||||
'test/suite-debug.janet',
|
'test/suite-debug.janet',
|
||||||
'test/suite-ev.janet',
|
'test/suite-ev.janet',
|
||||||
'test/suite-ev2.janet',
|
|
||||||
'test/suite-ffi.janet',
|
'test/suite-ffi.janet',
|
||||||
'test/suite-filewatch.janet',
|
'test/suite-filewatch.janet',
|
||||||
'test/suite-inttypes.janet',
|
'test/suite-inttypes.janet',
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ option('max_macro_expand', type : 'integer', min : 1, max : 8000, value : 200)
|
|||||||
option('stack_max', type : 'integer', min : 8096, max : 0x7fffffff, value : 0x7fffffff)
|
option('stack_max', type : 'integer', min : 8096, max : 0x7fffffff, value : 0x7fffffff)
|
||||||
|
|
||||||
option('arch_name', type : 'string', value: '')
|
option('arch_name', type : 'string', value: '')
|
||||||
option('thread_local_prefix', type : 'string', value: '')
|
|
||||||
option('os_name', type : 'string', value: '')
|
option('os_name', type : 'string', value: '')
|
||||||
option('shared', type : 'boolean', value: true)
|
option('shared', type : 'boolean', value: true)
|
||||||
option('cryptorand', type : 'boolean', value: true)
|
option('cryptorand', type : 'boolean', value: true)
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
``Define an alias for a keyword that is used as a dynamic binding. The
|
``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
|
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
|
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".``
|
called "earmuffs".``
|
||||||
[alias & more]
|
[alias & more]
|
||||||
(assert (symbol? alias) "alias must be a symbol")
|
(assert (symbol? alias) "alias must be a symbol")
|
||||||
@@ -290,6 +290,22 @@
|
|||||||
(array/concat accum body)
|
(array/concat accum body)
|
||||||
(tuple/slice accum 0))
|
(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
|
(defmacro protect
|
||||||
`Evaluate expressions, while capturing any errors. Evaluates to a tuple
|
`Evaluate expressions, while capturing any errors. Evaluates to a tuple
|
||||||
of two elements. The first element is true if successful, false if an
|
of two elements. The first element is true if successful, false if an
|
||||||
@@ -336,23 +352,6 @@
|
|||||||
(tuple 'if $fi $fi ret))))))
|
(tuple 'if $fi $fi ret))))))
|
||||||
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
|
(defmacro with-syms
|
||||||
"Evaluates `body` with each symbol in `syms` bound to a generated, unique symbol."
|
"Evaluates `body` with each symbol in `syms` bound to a generated, unique symbol."
|
||||||
[syms & body]
|
[syms & body]
|
||||||
@@ -1104,9 +1103,8 @@
|
|||||||
and use `array/concat` to concatenate the results, but only if
|
and use `array/concat` to concatenate the results, but only if
|
||||||
no `inds` are provided. Multiple data structures can be handled
|
no `inds` are provided. Multiple data structures can be handled
|
||||||
if each `inds` is a data structure and `f` is a function of
|
if each `inds` is a data structure and `f` is a function of
|
||||||
arity one more than the number of `inds`. Note that `f` is only
|
arity one more than the number of `inds`. The resulting array
|
||||||
applied to values at indeces up to the largest index of the
|
has a length that is the shortest of `ind` and each of `inds`.
|
||||||
shortest of `ind` and each of `inds`.
|
|
||||||
```
|
```
|
||||||
[f ind & inds]
|
[f ind & inds]
|
||||||
(def res @[])
|
(def res @[])
|
||||||
@@ -1145,8 +1143,8 @@
|
|||||||
structure `ind`, but only if no `inds` are provided. Multiple
|
structure `ind`, but only if no `inds` are provided. Multiple
|
||||||
data structures can be handled if each `inds` is a data
|
data structures can be handled if each `inds` is a data
|
||||||
structure and `pred` is a function of arity one more than the
|
structure and `pred` is a function of arity one more than the
|
||||||
number of `inds`. The resulting array has a length that is no
|
number of `inds`. The resulting array has a length that is the
|
||||||
longer than the shortest of `ind` and each of `inds`.
|
shortest of `ind` and each of `inds`.
|
||||||
```
|
```
|
||||||
[pred ind & inds]
|
[pred ind & inds]
|
||||||
(def res @[])
|
(def res @[])
|
||||||
@@ -1934,7 +1932,7 @@
|
|||||||
that will match any value without creating a binding.
|
that will match any value without creating a binding.
|
||||||
|
|
||||||
While a symbol pattern will ordinarily match any value, the pattern `(@ <sym>)`,
|
While a symbol pattern will ordinarily match any value, the pattern `(@ <sym>)`,
|
||||||
where `<sym>` is any symbol, will attempt to match `x` against a value
|
where <sym> is any symbol, will attempt to match `x` against a value
|
||||||
already bound to `<sym>`, rather than matching and rebinding it.
|
already bound to `<sym>`, rather than matching and rebinding it.
|
||||||
|
|
||||||
Any other value pattern will only match if it is equal to `x`.
|
Any other value pattern will only match if it is equal to `x`.
|
||||||
@@ -2575,7 +2573,7 @@
|
|||||||
* `:env` -- the environment to compile against - default is the current env
|
* `:env` -- the environment to compile against - default is the current env
|
||||||
|
|
||||||
* `:source` -- source path for better errors (use keywords for non-paths) - default
|
* `:source` -- source path for better errors (use keywords for non-paths) - default
|
||||||
is `:<anonymous>`
|
is :<anonymous>
|
||||||
|
|
||||||
* `:on-compile-error` -- callback when compilation fails - default is bad-compile
|
* `:on-compile-error` -- callback when compilation fails - default is bad-compile
|
||||||
|
|
||||||
@@ -3181,17 +3179,12 @@
|
|||||||
use the name of the module as a prefix. One can also use "`:export true`"
|
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,
|
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)`
|
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
|
to be called. Dynamic bindings will NOT be imported. Use :fresh to bypass the
|
||||||
value to bypass the module cache. Use `:only [foo bar baz]` to only import
|
module cache. Use `:only [foo bar baz]` to only import select bindings into the
|
||||||
select bindings into the current environment.``
|
current environment.``
|
||||||
[path & args]
|
[path & args]
|
||||||
(assertf (even? (length args)) "args should have even length: %n" args)
|
|
||||||
(def ps (partition 2 args))
|
(def ps (partition 2 args))
|
||||||
(def argm
|
(def argm (mapcat (fn [[k v]] [k (case k :as (string v) :only ~(quote ,v) v)]) ps))
|
||||||
(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))
|
|
||||||
(tuple import* (string path) ;argm))
|
(tuple import* (string path) ;argm))
|
||||||
|
|
||||||
(defmacro use
|
(defmacro use
|
||||||
@@ -3254,10 +3247,12 @@
|
|||||||
# Terminal codes for emission/tokenization
|
# Terminal codes for emission/tokenization
|
||||||
(def delimiters
|
(def delimiters
|
||||||
(if has-color
|
(if has-color
|
||||||
{:code ["\e[97m" "\e[39m"]
|
{:underline ["\e[4m" "\e[24m"]
|
||||||
|
:code ["\e[97m" "\e[39m"]
|
||||||
:italics ["\e[4m" "\e[24m"]
|
:italics ["\e[4m" "\e[24m"]
|
||||||
:bold ["\e[1m" "\e[22m"]}
|
:bold ["\e[1m" "\e[22m"]}
|
||||||
{:code ["`" "`"]
|
{:underline ["_" "_"]
|
||||||
|
:code ["`" "`"]
|
||||||
:italics ["*" "*"]
|
:italics ["*" "*"]
|
||||||
:bold ["**" "**"]}))
|
:bold ["**" "**"]}))
|
||||||
(def modes @{})
|
(def modes @{})
|
||||||
@@ -3388,6 +3383,7 @@
|
|||||||
(= b (chr `\`)) (do
|
(= b (chr `\`)) (do
|
||||||
(++ token-length)
|
(++ token-length)
|
||||||
(buffer/push token (get line (++ i))))
|
(buffer/push token (get line (++ i))))
|
||||||
|
(= b (chr "_")) (delim :underline)
|
||||||
(= b (chr "*"))
|
(= b (chr "*"))
|
||||||
(if (= (chr "*") (get line (+ i 1)))
|
(if (= (chr "*") (get line (+ i 1)))
|
||||||
(do (++ i)
|
(do (++ i)
|
||||||
@@ -3919,14 +3915,8 @@
|
|||||||
|
|
||||||
(compwhen (dyn 'net/listen)
|
(compwhen (dyn 'net/listen)
|
||||||
(defn net/server
|
(defn net/server
|
||||||
``
|
"Start a server asynchronously with `net/listen` and `net/accept-loop`. Returns the new server stream."
|
||||||
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.
|
|
||||||
``
|
|
||||||
[host port &opt handler type no-reuse]
|
[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))
|
(def s (net/listen host port type no-reuse))
|
||||||
(if handler
|
(if handler
|
||||||
(ev/go (fn [] (net/accept-loop s handler))))
|
(ev/go (fn [] (net/accept-loop s handler))))
|
||||||
@@ -4305,14 +4295,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`."
|
"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]
|
[path &keys config]
|
||||||
(def path (bundle-rpath path))
|
(def path (bundle-rpath path))
|
||||||
|
(def clean (get config :clean))
|
||||||
|
(def check (get config :check))
|
||||||
(def s (sep))
|
(def s (sep))
|
||||||
# Detect bundle name
|
# Check meta file for dependencies and default name
|
||||||
(def infofile-src1 (string path s "bundle" s "info.jdn"))
|
(def infofile-pre-1 (string path s "bundle" s "info.jdn"))
|
||||||
(def infofile-src2 (string path s "info.jdn"))
|
(def infofile-pre (if (fexists infofile-pre-1) infofile-pre-1 (string path s "info.jdn"))) # allow for alias
|
||||||
(def infofile-src (cond (fexists infofile-src1) infofile-src1
|
(var default-bundle-name nil)
|
||||||
(fexists infofile-src2) infofile-src2))
|
(when (os/stat infofile-pre :mode)
|
||||||
(def info (-?> infofile-src slurp parse))
|
(def info (-> infofile-pre slurp parse))
|
||||||
(def bundle-name (get config :name (get info :name)))
|
(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 bundle-name "unable to infer bundle name for %v, use :name argument" path)
|
||||||
(assertf (not (string/check-set "\\/" bundle-name))
|
(assertf (not (string/check-set "\\/" bundle-name))
|
||||||
"bundle name %v cannot contain path separators" bundle-name)
|
"bundle name %v cannot contain path separators" bundle-name)
|
||||||
@@ -4322,32 +4318,28 @@
|
|||||||
# Setup installed paths
|
# Setup installed paths
|
||||||
(prime-bundle-paths)
|
(prime-bundle-paths)
|
||||||
(os/mkdir (bundle-dir bundle-name))
|
(os/mkdir (bundle-dir bundle-name))
|
||||||
# Copy infofile
|
# Aliases for common bundle/ files
|
||||||
(def infofile-dest (bundle-file bundle-name "info.jdn"))
|
(def bundle.janet (string path s "bundle.janet"))
|
||||||
(when infofile-src (copyfile infofile-src infofile-dest))
|
(when (fexists bundle.janet) (copyfile bundle.janet (bundle-file bundle-name "init.janet")))
|
||||||
# Copy aliased initfile
|
(when (fexists infofile-pre) (copyfile infofile-pre (bundle-file bundle-name "info.jdn")))
|
||||||
(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))
|
|
||||||
# Copy some files into the new location unconditionally
|
# Copy some files into the new location unconditionally
|
||||||
(def implicit-sources (string path s "bundle"))
|
(def implicit-sources (string path s "bundle"))
|
||||||
(when (= :directory (os/stat implicit-sources :mode))
|
(when (= :directory (os/stat implicit-sources :mode))
|
||||||
(copyrf implicit-sources (bundle-dir bundle-name)))
|
(copyrf implicit-sources (bundle-dir bundle-name)))
|
||||||
(def man @{:name bundle-name :local-source path :files @[]})
|
(def man @{:name bundle-name :local-source path :files @[]})
|
||||||
(merge-into man config)
|
(merge-into man config)
|
||||||
|
(def infofile (bundle-file bundle-name "info.jdn"))
|
||||||
|
(put man :auto-remove (get config :auto-remove))
|
||||||
(sync-manifest man)
|
(sync-manifest man)
|
||||||
(edefer (do (print "installation error, uninstalling") (bundle/uninstall bundle-name))
|
(edefer (do (print "installation error, uninstalling") (bundle/uninstall bundle-name))
|
||||||
(when (os/stat infofile-dest :mode)
|
(when (os/stat infofile :mode)
|
||||||
(def info (-> infofile-dest slurp parse))
|
(def info (-> infofile slurp parse))
|
||||||
(def deps (seq [d :in (get info :dependencies @[])]
|
(def deps (get info :dependencies @[]))
|
||||||
(string (if (dictionary? d) (get d :name) d))))
|
|
||||||
(def missing (filter (complement bundle/installed?) deps))
|
(def missing (filter (complement bundle/installed?) deps))
|
||||||
(when (next missing)
|
(when (next missing)
|
||||||
(error (string "missing dependencies " (string/join missing ", "))))
|
(error (string "missing dependencies " (string/join missing ", "))))
|
||||||
(put man :dependencies deps)
|
(put man :dependencies deps)
|
||||||
(put man :info info))
|
(put man :info info))
|
||||||
(def clean (get config :clean))
|
|
||||||
(def check (get config :check))
|
|
||||||
(def module (get-bundle-module bundle-name))
|
(def module (get-bundle-module bundle-name))
|
||||||
(def all-hooks (seq [[k v] :pairs module :when (symbol? k) :unless (get v :private)] (keyword k)))
|
(def all-hooks (seq [[k v] :pairs module :when (symbol? k) :unless (get v :private)] (keyword k)))
|
||||||
(put man :hooks all-hooks)
|
(put man :hooks all-hooks)
|
||||||
@@ -4490,10 +4482,8 @@
|
|||||||
(errorf "bad path %s - file is a %s" src mode)))
|
(errorf "bad path %s - file is a %s" src mode)))
|
||||||
|
|
||||||
(defn bundle/add-bin
|
(defn bundle/add-bin
|
||||||
``
|
`Shorthand for adding scripts during an install. Scripts will be installed to
|
||||||
Shorthand for adding scripts during an install. Scripts will be installed to
|
(string (dyn *syspath*) "/bin") by default and will be set to be executable.`
|
||||||
`(string (dyn *syspath*) "/bin")` by default and will be set to be executable.
|
|
||||||
``
|
|
||||||
[manifest src &opt dest chmod-mode]
|
[manifest src &opt dest chmod-mode]
|
||||||
(def s (sep))
|
(def s (sep))
|
||||||
(default dest (last (string/split s src)))
|
(default dest (last (string/split s src)))
|
||||||
@@ -4638,7 +4628,7 @@
|
|||||||
--reinstall (-B) name : Reinstall a bundle by bundle name
|
--reinstall (-B) name : Reinstall a bundle by bundle name
|
||||||
--uninstall (-u) name : Uninstall a bundle by bundle name
|
--uninstall (-u) name : Uninstall a bundle by bundle name
|
||||||
--update-all (-U) : Reinstall all installed bundles
|
--update-all (-U) : Reinstall all installed bundles
|
||||||
--prune (-P) : Uninstall all bundles that are orphaned
|
--prune (-P) : Uninstalled all bundles that are orphaned
|
||||||
--list (-L) : List all installed bundles
|
--list (-L) : List all installed bundles
|
||||||
-- : Stop handling options
|
-- : Stop handling options
|
||||||
```)
|
```)
|
||||||
|
|||||||
@@ -4,16 +4,15 @@
|
|||||||
#define JANETCONF_H
|
#define JANETCONF_H
|
||||||
|
|
||||||
#define JANET_VERSION_MAJOR 1
|
#define JANET_VERSION_MAJOR 1
|
||||||
#define JANET_VERSION_MINOR 40
|
#define JANET_VERSION_MINOR 38
|
||||||
#define JANET_VERSION_PATCH 0
|
#define JANET_VERSION_PATCH 0
|
||||||
#define JANET_VERSION_EXTRA ""
|
#define JANET_VERSION_EXTRA ""
|
||||||
#define JANET_VERSION "1.40.0"
|
#define JANET_VERSION "1.38.0"
|
||||||
|
|
||||||
/* #define JANET_BUILD "local" */
|
/* #define JANET_BUILD "local" */
|
||||||
|
|
||||||
/* These settings all affect linking, so use cautiously. */
|
/* These settings all affect linking, so use cautiously. */
|
||||||
/* #define JANET_SINGLE_THREADED */
|
/* #define JANET_SINGLE_THREADED */
|
||||||
/* #define JANET_THREAD_LOCAL _Thread_local */
|
|
||||||
/* #define JANET_NO_DYNAMIC_MODULES */
|
/* #define JANET_NO_DYNAMIC_MODULES */
|
||||||
/* #define JANET_NO_NANBOX */
|
/* #define JANET_NO_NANBOX */
|
||||||
/* #define JANET_API __attribute__((visibility ("default"))) */
|
/* #define JANET_API __attribute__((visibility ("default"))) */
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void *janet_abstract_threaded(const JanetAbstractType *atype, size_t size) {
|
|||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
|
|
||||||
size_t janet_os_mutex_size(void) {
|
size_t janet_os_mutex_size(void) {
|
||||||
return sizeof(SRWLOCK);
|
return sizeof(CRITICAL_SECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t janet_os_rwlock_size(void) {
|
size_t janet_os_rwlock_size(void) {
|
||||||
@@ -96,20 +96,20 @@ size_t janet_os_rwlock_size(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void janet_os_mutex_init(JanetOSMutex *mutex) {
|
void janet_os_mutex_init(JanetOSMutex *mutex) {
|
||||||
InitializeSRWLock((PSRWLOCK) mutex);
|
InitializeCriticalSection((CRITICAL_SECTION *) mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void janet_os_mutex_deinit(JanetOSMutex *mutex) {
|
void janet_os_mutex_deinit(JanetOSMutex *mutex) {
|
||||||
/* no op? */
|
DeleteCriticalSection((CRITICAL_SECTION *) mutex);
|
||||||
(void) mutex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void janet_os_mutex_lock(JanetOSMutex *mutex) {
|
void janet_os_mutex_lock(JanetOSMutex *mutex) {
|
||||||
AcquireSRWLockExclusive((PSRWLOCK) mutex);
|
EnterCriticalSection((CRITICAL_SECTION *) mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void janet_os_mutex_unlock(JanetOSMutex *mutex) {
|
void janet_os_mutex_unlock(JanetOSMutex *mutex) {
|
||||||
ReleaseSRWLockExclusive((PSRWLOCK) mutex);
|
/* error handling? May want to keep counter */
|
||||||
|
LeaveCriticalSection((CRITICAL_SECTION *) mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void janet_os_rwlock_init(JanetOSRWLock *rwlock) {
|
void janet_os_rwlock_init(JanetOSRWLock *rwlock) {
|
||||||
|
|||||||
@@ -589,16 +589,6 @@ JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JanetAtomicInt janet_atomic_load_relaxed(JanetAtomicInt volatile *x) {
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
return _InterlockedOr(x, 0);
|
|
||||||
#elif defined(JANET_USE_STDATOMIC)
|
|
||||||
return atomic_load_explicit(x, memory_order_relaxed);
|
|
||||||
#else
|
|
||||||
return __atomic_load_n(x, __ATOMIC_RELAXED);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some definitions for function-like macros */
|
/* Some definitions for function-like macros */
|
||||||
|
|
||||||
JANET_API JanetStructHead *(janet_struct_head)(JanetStruct st) {
|
JANET_API JanetStructHead *(janet_struct_head)(JanetStruct st) {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ JanetModule janet_native(const char *name, const uint8_t **error) {
|
|||||||
JanetBuildConfig modconf = getter();
|
JanetBuildConfig modconf = getter();
|
||||||
JanetBuildConfig host = janet_config_current();
|
JanetBuildConfig host = janet_config_current();
|
||||||
if (host.major != modconf.major ||
|
if (host.major != modconf.major ||
|
||||||
host.minor != modconf.minor ||
|
host.minor < modconf.minor ||
|
||||||
host.bits != modconf.bits) {
|
host.bits != modconf.bits) {
|
||||||
char errbuf[128];
|
char errbuf[128];
|
||||||
snprintf(errbuf, sizeof(errbuf), "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
|
snprintf(errbuf, sizeof(errbuf), "config mismatch - host %d.%.d.%d(%.4x) vs. module %d.%d.%d(%.4x)",
|
||||||
@@ -653,15 +653,22 @@ JANET_CORE_FN(janet_core_check_int,
|
|||||||
"(int? x)",
|
"(int? x)",
|
||||||
"Check if x can be exactly represented as a 32 bit signed two's complement integer.") {
|
"Check if x can be exactly represented as a 32 bit signed two's complement integer.") {
|
||||||
janet_fixarity(argc, 1);
|
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,
|
JANET_CORE_FN(janet_core_check_nat,
|
||||||
"(nat? x)",
|
"(nat? x)",
|
||||||
"Check if x can be exactly represented as a non-negative 32 bit signed two's complement integer.") {
|
"Check if x can be exactly represented as a non-negative 32 bit signed two's complement integer.") {
|
||||||
janet_fixarity(argc, 1);
|
janet_fixarity(argc, 1);
|
||||||
if (!janet_checkint(argv[0])) return janet_wrap_false();
|
if (!janet_checktype(argv[0], JANET_NUMBER)) goto ret_false;
|
||||||
return janet_wrap_boolean(janet_unwrap_integer(argv[0]) >= 0);
|
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,
|
JANET_CORE_FN(janet_core_is_bytes,
|
||||||
|
|||||||
148
src/core/ev.c
148
src/core/ev.c
@@ -83,7 +83,7 @@ struct JanetChannel {
|
|||||||
int closed;
|
int closed;
|
||||||
int is_threaded;
|
int is_threaded;
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
SRWLOCK lock;
|
CRITICAL_SECTION lock;
|
||||||
#else
|
#else
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
#endif
|
#endif
|
||||||
@@ -353,22 +353,21 @@ JanetStream *janet_stream(JanetHandle handle, uint32_t flags, const JanetMethod
|
|||||||
|
|
||||||
static void janet_stream_close_impl(JanetStream *stream) {
|
static void janet_stream_close_impl(JanetStream *stream) {
|
||||||
stream->flags |= JANET_STREAM_CLOSED;
|
stream->flags |= JANET_STREAM_CLOSED;
|
||||||
int canclose = !(stream->flags & JANET_STREAM_NOT_CLOSEABLE);
|
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
if (stream->handle != INVALID_HANDLE_VALUE) {
|
if (stream->handle != INVALID_HANDLE_VALUE) {
|
||||||
#ifdef JANET_NET
|
#ifdef JANET_NET
|
||||||
if (stream->flags & JANET_STREAM_SOCKET) {
|
if (stream->flags & JANET_STREAM_SOCKET) {
|
||||||
if (canclose) closesocket((SOCKET) stream->handle);
|
closesocket((SOCKET) stream->handle);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (canclose) CloseHandle(stream->handle);
|
CloseHandle(stream->handle);
|
||||||
}
|
}
|
||||||
stream->handle = INVALID_HANDLE_VALUE;
|
stream->handle = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (stream->handle != -1) {
|
if (stream->handle != -1) {
|
||||||
if (canclose) close(stream->handle);
|
close(stream->handle);
|
||||||
stream->handle = -1;
|
stream->handle = -1;
|
||||||
#ifdef JANET_EV_POLL
|
#ifdef JANET_EV_POLL
|
||||||
uint32_t i = stream->index;
|
uint32_t i = stream->index;
|
||||||
@@ -604,44 +603,8 @@ void janet_ev_init_common(void) {
|
|||||||
#endif
|
#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 */
|
/* Common deinit code */
|
||||||
void janet_ev_deinit_common(void) {
|
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_q_deinit(&janet_vm.spawn);
|
||||||
janet_free(janet_vm.tq);
|
janet_free(janet_vm.tq);
|
||||||
janet_table_deinit(&janet_vm.threaded_abstracts);
|
janet_table_deinit(&janet_vm.threaded_abstracts);
|
||||||
@@ -684,6 +647,13 @@ void janet_addtimeout_nil(double sec) {
|
|||||||
add_timeout(to);
|
add_timeout(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
static VOID CALLBACK janet_timeout_stop(ULONG_PTR ptr) {
|
||||||
|
UNREFERENCED_PARAMETER(ptr);
|
||||||
|
ExitThread(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void janet_timeout_cb(JanetEVGenericMessage msg) {
|
static void janet_timeout_cb(JanetEVGenericMessage msg) {
|
||||||
(void) msg;
|
(void) msg;
|
||||||
janet_interpreter_interrupt_handled(&janet_vm);
|
janet_interpreter_interrupt_handled(&janet_vm);
|
||||||
@@ -694,21 +664,15 @@ static DWORD WINAPI janet_timeout_body(LPVOID ptr) {
|
|||||||
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
|
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
|
||||||
janet_free(ptr);
|
janet_free(ptr);
|
||||||
SleepEx((DWORD)(tto.sec * 1000), TRUE);
|
SleepEx((DWORD)(tto.sec * 1000), TRUE);
|
||||||
|
if (janet_fiber_can_resume(tto.fiber)) {
|
||||||
janet_interpreter_interrupt(tto.vm);
|
janet_interpreter_interrupt(tto.vm);
|
||||||
JanetEVGenericMessage msg = {0};
|
JanetEVGenericMessage msg = {0};
|
||||||
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
|
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void *janet_timeout_body(void *ptr) {
|
static void *janet_timeout_body(void *ptr) {
|
||||||
#ifdef JANET_ANDROID
|
|
||||||
struct sigaction action;
|
|
||||||
memset(&action, 0, sizeof(action));
|
|
||||||
sigemptyset(&action.sa_mask);
|
|
||||||
action.sa_flags = 0;
|
|
||||||
action.sa_handler = &janet_timeout_stop;
|
|
||||||
sigaction(SIGUSR1, &action, NULL);
|
|
||||||
#endif
|
|
||||||
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
|
JanetThreadedTimeout tto = *(JanetThreadedTimeout *)ptr;
|
||||||
janet_free(ptr);
|
janet_free(ptr);
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
@@ -717,9 +681,11 @@ static void *janet_timeout_body(void *ptr) {
|
|||||||
? (long)((tto.sec - ((uint32_t)tto.sec)) * 1000000000)
|
? (long)((tto.sec - ((uint32_t)tto.sec)) * 1000000000)
|
||||||
: 0;
|
: 0;
|
||||||
nanosleep(&ts, &ts);
|
nanosleep(&ts, &ts);
|
||||||
|
if (janet_fiber_can_resume(tto.fiber)) {
|
||||||
janet_interpreter_interrupt(tto.vm);
|
janet_interpreter_interrupt(tto.vm);
|
||||||
JanetEVGenericMessage msg = {0};
|
JanetEVGenericMessage msg = {0};
|
||||||
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
|
janet_ev_post_event(tto.vm, janet_timeout_cb, msg);
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -839,34 +805,6 @@ static int janet_chanat_gc(void *p, size_t s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void janet_chanat_remove_vmref(JanetQueue *fq) {
|
|
||||||
JanetChannelPending *pending = fq->data;
|
|
||||||
if (fq->head <= fq->tail) {
|
|
||||||
for (int32_t i = fq->head; i < fq->tail; i++) {
|
|
||||||
if (pending[i].thread == &janet_vm) pending[i].thread = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int32_t i = fq->head; i < fq->capacity; i++) {
|
|
||||||
if (pending[i].thread == &janet_vm) pending[i].thread = NULL;
|
|
||||||
}
|
|
||||||
for (int32_t i = 0; i < fq->tail; i++) {
|
|
||||||
if (pending[i].thread == &janet_vm) pending[i].thread = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int janet_chanat_gcperthread(void *p, size_t s) {
|
|
||||||
(void) s;
|
|
||||||
JanetChannel *chan = p;
|
|
||||||
janet_chan_lock(chan);
|
|
||||||
/* Make sure that the internals of the threaded channel no longer reference _this_ thread. Replace
|
|
||||||
* those references with NULL. */
|
|
||||||
janet_chanat_remove_vmref(&chan->read_pending);
|
|
||||||
janet_chanat_remove_vmref(&chan->write_pending);
|
|
||||||
janet_chan_unlock(chan);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void janet_chanat_mark_fq(JanetQueue *fq) {
|
static void janet_chanat_mark_fq(JanetQueue *fq) {
|
||||||
JanetChannelPending *pending = fq->data;
|
JanetChannelPending *pending = fq->data;
|
||||||
if (fq->head <= fq->tail) {
|
if (fq->head <= fq->tail) {
|
||||||
@@ -949,9 +887,8 @@ static void janet_thread_chan_cb(JanetEVGenericMessage msg) {
|
|||||||
int is_read = (mode == JANET_CP_MODE_CHOICE_READ) || (mode == JANET_CP_MODE_READ);
|
int is_read = (mode == JANET_CP_MODE_CHOICE_READ) || (mode == JANET_CP_MODE_READ);
|
||||||
if (is_read) {
|
if (is_read) {
|
||||||
JanetChannelPending reader;
|
JanetChannelPending reader;
|
||||||
while (!janet_q_pop(&channel->read_pending, &reader, sizeof(reader))) {
|
if (!janet_q_pop(&channel->read_pending, &reader, sizeof(reader))) {
|
||||||
JanetVM *vm = reader.thread;
|
JanetVM *vm = reader.thread;
|
||||||
if (!vm) continue;
|
|
||||||
JanetEVGenericMessage msg;
|
JanetEVGenericMessage msg;
|
||||||
msg.tag = reader.mode;
|
msg.tag = reader.mode;
|
||||||
msg.fiber = reader.fiber;
|
msg.fiber = reader.fiber;
|
||||||
@@ -959,13 +896,11 @@ static void janet_thread_chan_cb(JanetEVGenericMessage msg) {
|
|||||||
msg.argp = channel;
|
msg.argp = channel;
|
||||||
msg.argj = x;
|
msg.argj = x;
|
||||||
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
JanetChannelPending writer;
|
JanetChannelPending writer;
|
||||||
while (!janet_q_pop(&channel->write_pending, &writer, sizeof(writer))) {
|
if (!janet_q_pop(&channel->write_pending, &writer, sizeof(writer))) {
|
||||||
JanetVM *vm = writer.thread;
|
JanetVM *vm = writer.thread;
|
||||||
if (!vm) continue;
|
|
||||||
JanetEVGenericMessage msg;
|
JanetEVGenericMessage msg;
|
||||||
msg.tag = writer.mode;
|
msg.tag = writer.mode;
|
||||||
msg.fiber = writer.fiber;
|
msg.fiber = writer.fiber;
|
||||||
@@ -973,7 +908,6 @@ static void janet_thread_chan_cb(JanetEVGenericMessage msg) {
|
|||||||
msg.argp = channel;
|
msg.argp = channel;
|
||||||
msg.argj = janet_wrap_nil();
|
msg.argj = janet_wrap_nil();
|
||||||
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1037,9 +971,7 @@ static int janet_channel_push_with_lock(JanetChannel *channel, Janet x, int mode
|
|||||||
msg.argi = (int32_t) reader.sched_id;
|
msg.argi = (int32_t) reader.sched_id;
|
||||||
msg.argp = channel;
|
msg.argp = channel;
|
||||||
msg.argj = x;
|
msg.argj = x;
|
||||||
if (vm) {
|
|
||||||
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (reader.mode == JANET_CP_MODE_CHOICE_READ) {
|
if (reader.mode == JANET_CP_MODE_CHOICE_READ) {
|
||||||
janet_schedule(reader.fiber, make_read_result(channel, x));
|
janet_schedule(reader.fiber, make_read_result(channel, x));
|
||||||
@@ -1094,9 +1026,7 @@ static int janet_channel_pop_with_lock(JanetChannel *channel, Janet *item, int i
|
|||||||
msg.argi = (int32_t) writer.sched_id;
|
msg.argi = (int32_t) writer.sched_id;
|
||||||
msg.argp = channel;
|
msg.argp = channel;
|
||||||
msg.argj = janet_wrap_nil();
|
msg.argj = janet_wrap_nil();
|
||||||
if (vm) {
|
|
||||||
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (writer.mode == JANET_CP_MODE_CHOICE_WRITE) {
|
if (writer.mode == JANET_CP_MODE_CHOICE_WRITE) {
|
||||||
janet_schedule(writer.fiber, make_write_result(channel));
|
janet_schedule(writer.fiber, make_write_result(channel));
|
||||||
@@ -1360,9 +1290,7 @@ JANET_CORE_FN(cfun_channel_close,
|
|||||||
msg.tag = JANET_CP_MODE_CLOSE;
|
msg.tag = JANET_CP_MODE_CLOSE;
|
||||||
msg.argi = (int32_t) writer.sched_id;
|
msg.argi = (int32_t) writer.sched_id;
|
||||||
msg.argj = janet_wrap_nil();
|
msg.argj = janet_wrap_nil();
|
||||||
if (vm) {
|
|
||||||
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (janet_fiber_can_resume(writer.fiber)) {
|
if (janet_fiber_can_resume(writer.fiber)) {
|
||||||
if (writer.mode == JANET_CP_MODE_CHOICE_WRITE) {
|
if (writer.mode == JANET_CP_MODE_CHOICE_WRITE) {
|
||||||
@@ -1383,9 +1311,7 @@ JANET_CORE_FN(cfun_channel_close,
|
|||||||
msg.tag = JANET_CP_MODE_CLOSE;
|
msg.tag = JANET_CP_MODE_CLOSE;
|
||||||
msg.argi = (int32_t) reader.sched_id;
|
msg.argi = (int32_t) reader.sched_id;
|
||||||
msg.argj = janet_wrap_nil();
|
msg.argj = janet_wrap_nil();
|
||||||
if (vm) {
|
|
||||||
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
janet_ev_post_event(vm, janet_thread_chan_cb, msg);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (janet_fiber_can_resume(reader.fiber)) {
|
if (janet_fiber_can_resume(reader.fiber)) {
|
||||||
if (reader.mode == JANET_CP_MODE_CHOICE_READ) {
|
if (reader.mode == JANET_CP_MODE_CHOICE_READ) {
|
||||||
@@ -1478,10 +1404,7 @@ const JanetAbstractType janet_channel_type = {
|
|||||||
NULL, /* compare */
|
NULL, /* compare */
|
||||||
NULL, /* hash */
|
NULL, /* hash */
|
||||||
janet_chanat_next,
|
janet_chanat_next,
|
||||||
NULL, /* call */
|
JANET_ATEND_NEXT
|
||||||
NULL, /* length */
|
|
||||||
NULL, /* bytes */
|
|
||||||
janet_chanat_gcperthread
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Main event loop */
|
/* Main event loop */
|
||||||
@@ -1514,13 +1437,12 @@ JanetFiber *janet_loop1(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handle_timeout_worker(to, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Run scheduled fibers unless interrupts need to be handled. */
|
/* Run scheduled fibers unless interrupts need to be handled. */
|
||||||
while (janet_vm.spawn.head != janet_vm.spawn.tail) {
|
while (janet_vm.spawn.head != janet_vm.spawn.tail) {
|
||||||
/* Don't run until all interrupts have been marked as handled by calling janet_interpreter_interrupt_handled */
|
/* Don't run until all interrupts have been marked as handled by calling janet_interpreter_interrupt_handled */
|
||||||
if (janet_atomic_load_relaxed(&janet_vm.auto_suspend)) break;
|
if (janet_vm.auto_suspend) break;
|
||||||
JanetTask task = {NULL, janet_wrap_nil(), JANET_SIGNAL_OK, 0};
|
JanetTask task = {NULL, janet_wrap_nil(), JANET_SIGNAL_OK, 0};
|
||||||
janet_q_pop(&janet_vm.spawn, &task, sizeof(task));
|
janet_q_pop(&janet_vm.spawn, &task, sizeof(task));
|
||||||
if (task.fiber->gc.flags & JANET_FIBER_EV_FLAG_SUSPENDED) janet_ev_dec_refcount();
|
if (task.fiber->gc.flags & JANET_FIBER_EV_FLAG_SUSPENDED) janet_ev_dec_refcount();
|
||||||
@@ -1562,14 +1484,23 @@ JanetFiber *janet_loop1(void) {
|
|||||||
while ((has_timeout = peek_timeout(&to))) {
|
while ((has_timeout = peek_timeout(&to))) {
|
||||||
if (to.curr_fiber != NULL) {
|
if (to.curr_fiber != NULL) {
|
||||||
if (!janet_fiber_can_resume(to.curr_fiber)) {
|
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
|
||||||
|
pthread_cancel(to.worker);
|
||||||
|
void *res;
|
||||||
|
pthread_join(to.worker, &res);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
|
janet_table_remove(&janet_vm.active_tasks, janet_wrap_fiber(to.curr_fiber));
|
||||||
handle_timeout_worker(to, 1);
|
pop_timeout(0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (to.fiber->sched_id != to.sched_id) {
|
} else if (to.fiber->sched_id != to.sched_id) {
|
||||||
pop_timeout(0);
|
pop_timeout(0);
|
||||||
handle_timeout_worker(to, 1);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1734,7 +1665,7 @@ void janet_stream_level_triggered(JanetStream *stream) {
|
|||||||
|
|
||||||
static JanetTimestamp ts_now(void) {
|
static JanetTimestamp ts_now(void) {
|
||||||
struct timespec now;
|
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;
|
uint64_t res = 1000 * now.tv_sec;
|
||||||
res += now.tv_nsec / 1000000;
|
res += now.tv_nsec / 1000000;
|
||||||
return res;
|
return res;
|
||||||
@@ -1892,7 +1823,7 @@ JanetTimestamp to_interval(const JanetTimestamp ts) {
|
|||||||
|
|
||||||
static JanetTimestamp ts_now(void) {
|
static JanetTimestamp ts_now(void) {
|
||||||
struct timespec now;
|
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;
|
uint64_t res = 1000 * now.tv_sec;
|
||||||
res += now.tv_nsec / 1000000;
|
res += now.tv_nsec / 1000000;
|
||||||
return res;
|
return res;
|
||||||
@@ -2046,7 +1977,7 @@ void janet_ev_deinit(void) {
|
|||||||
|
|
||||||
static JanetTimestamp ts_now(void) {
|
static JanetTimestamp ts_now(void) {
|
||||||
struct timespec now;
|
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;
|
uint64_t res = 1000 * now.tv_sec;
|
||||||
res += now.tv_nsec / 1000000;
|
res += now.tv_nsec / 1000000;
|
||||||
return res;
|
return res;
|
||||||
@@ -2218,7 +2149,7 @@ void janet_ev_post_event(JanetVM *vm, JanetCallback cb, JanetEVGenericMessage ms
|
|||||||
event.cb = cb;
|
event.cb = cb;
|
||||||
int fd = vm->selfpipe[1];
|
int fd = vm->selfpipe[1];
|
||||||
/* handle a bit of back pressure before giving up. */
|
/* handle a bit of back pressure before giving up. */
|
||||||
int tries = 20;
|
int tries = 4;
|
||||||
while (tries > 0) {
|
while (tries > 0) {
|
||||||
int status;
|
int status;
|
||||||
do {
|
do {
|
||||||
@@ -3065,8 +2996,7 @@ static JanetEVGenericMessage janet_go_thread_subr(JanetEVGenericMessage args) {
|
|||||||
uint32_t count1;
|
uint32_t count1;
|
||||||
memcpy(&count1, nextbytes, sizeof(count1));
|
memcpy(&count1, nextbytes, sizeof(count1));
|
||||||
size_t count = (size_t) count1;
|
size_t count = (size_t) count1;
|
||||||
/* Use division to avoid overflowing size_t */
|
if (count > (endbytes - nextbytes) * sizeof(JanetCFunRegistry)) {
|
||||||
if (count > (endbytes - nextbytes - sizeof(count1)) / sizeof(JanetCFunRegistry)) {
|
|
||||||
janet_panic("thread message invalid");
|
janet_panic("thread message invalid");
|
||||||
}
|
}
|
||||||
janet_vm.registry_count = count;
|
janet_vm.registry_count = count;
|
||||||
@@ -3224,7 +3154,6 @@ JANET_NO_RETURN void janet_sleep_await(double sec) {
|
|||||||
to.is_error = 0;
|
to.is_error = 0;
|
||||||
to.sched_id = to.fiber->sched_id;
|
to.sched_id = to.fiber->sched_id;
|
||||||
to.curr_fiber = NULL;
|
to.curr_fiber = NULL;
|
||||||
to.has_worker = 0;
|
|
||||||
add_timeout(to);
|
add_timeout(to);
|
||||||
janet_await();
|
janet_await();
|
||||||
}
|
}
|
||||||
@@ -3259,9 +3188,6 @@ JANET_CORE_FN(cfun_ev_deadline,
|
|||||||
to.is_error = 0;
|
to.is_error = 0;
|
||||||
to.sched_id = to.fiber->sched_id;
|
to.sched_id = to.fiber->sched_id;
|
||||||
if (use_interrupt) {
|
if (use_interrupt) {
|
||||||
#ifdef JANET_ANDROID
|
|
||||||
janet_sandbox_assert(JANET_SANDBOX_SIGNAL);
|
|
||||||
#endif
|
|
||||||
JanetThreadedTimeout *tto = janet_malloc(sizeof(JanetThreadedTimeout));
|
JanetThreadedTimeout *tto = janet_malloc(sizeof(JanetThreadedTimeout));
|
||||||
if (NULL == tto) {
|
if (NULL == tto) {
|
||||||
JANET_OUT_OF_MEMORY;
|
JANET_OUT_OF_MEMORY;
|
||||||
@@ -3579,6 +3505,8 @@ void janet_lib_ev(JanetTable *env) {
|
|||||||
janet_register_abstract_type(&janet_channel_type);
|
janet_register_abstract_type(&janet_channel_type);
|
||||||
janet_register_abstract_type(&janet_mutex_type);
|
janet_register_abstract_type(&janet_mutex_type);
|
||||||
janet_register_abstract_type(&janet_rwlock_type);
|
janet_register_abstract_type(&janet_rwlock_type);
|
||||||
|
|
||||||
|
janet_lib_filewatch(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -599,33 +599,33 @@ JANET_CORE_FN(cfun_filewatch_make,
|
|||||||
JANET_CORE_FN(cfun_filewatch_add,
|
JANET_CORE_FN(cfun_filewatch_add,
|
||||||
"(filewatch/add watcher path &opt flags)",
|
"(filewatch/add watcher path &opt flags)",
|
||||||
"Add a path to the watcher. Available flags depend on the current OS, and are as follows:\n\n"
|
"Add a path to the watcher. Available flags depend on the current OS, and are as follows:\n\n"
|
||||||
"Windows/MINGW (flags correspond to `FILE_NOTIFY_CHANGE_*` flags in win32 documentation):\n\n"
|
"Windows/MINGW (flags correspond to FILE_NOTIFY_CHANGE_* flags in win32 documentation):\n\n"
|
||||||
"* `:all` - trigger an event for all of the below triggers.\n\n"
|
"* `:all` - trigger an event for all of the below triggers.\n\n"
|
||||||
"* `:attributes` - `FILE_NOTIFY_CHANGE_ATTRIBUTES`\n\n"
|
"* `:attributes` - FILE_NOTIFY_CHANGE_ATTRIBUTES\n\n"
|
||||||
"* `:creation` - `FILE_NOTIFY_CHANGE_CREATION`\n\n"
|
"* `:creation` - FILE_NOTIFY_CHANGE_CREATION\n\n"
|
||||||
"* `:dir-name` - `FILE_NOTIFY_CHANGE_DIR_NAME`\n\n"
|
"* `:dir-name` - FILE_NOTIFY_CHANGE_DIR_NAME\n\n"
|
||||||
"* `:last-access` - `FILE_NOTIFY_CHANGE_LAST_ACCESS`\n\n"
|
"* `:last-access` - FILE_NOTIFY_CHANGE_LAST_ACCESS\n\n"
|
||||||
"* `:last-write` - `FILE_NOTIFY_CHANGE_LAST_WRITE`\n\n"
|
"* `:last-write` - FILE_NOTIFY_CHANGE_LAST_WRITE\n\n"
|
||||||
"* `:security` - `FILE_NOTIFY_CHANGE_SECURITY`\n\n"
|
"* `:security` - FILE_NOTIFY_CHANGE_SECURITY\n\n"
|
||||||
"* `:size` - `FILE_NOTIFY_CHANGE_SIZE`\n\n"
|
"* `:size` - FILE_NOTIFY_CHANGE_SIZE\n\n"
|
||||||
"* `:recursive` - watch subdirectories recursively\n\n"
|
"* `:recursive` - watch subdirectories recursively\n\n"
|
||||||
"Linux (flags correspond to `IN_*` flags from <sys/inotify.h>):\n\n"
|
"Linux (flags correspond to IN_* flags from <sys/inotify.h>):\n\n"
|
||||||
"* `:access` - `IN_ACCESS`\n\n"
|
"* `:access` - IN_ACCESS\n\n"
|
||||||
"* `:all` - `IN_ALL_EVENTS`\n\n"
|
"* `:all` - IN_ALL_EVENTS\n\n"
|
||||||
"* `:attrib` - `IN_ATTRIB`\n\n"
|
"* `:attrib` - IN_ATTRIB\n\n"
|
||||||
"* `:close-nowrite` - `IN_CLOSE_NOWRITE`\n\n"
|
"* `:close-nowrite` - IN_CLOSE_NOWRITE\n\n"
|
||||||
"* `:close-write` - `IN_CLOSE_WRITE`\n\n"
|
"* `:close-write` - IN_CLOSE_WRITE\n\n"
|
||||||
"* `:create` - `IN_CREATE`\n\n"
|
"* `:create` - IN_CREATE\n\n"
|
||||||
"* `:delete` - `IN_DELETE`\n\n"
|
"* `:delete` - IN_DELETE\n\n"
|
||||||
"* `:delete-self` - `IN_DELETE_SELF`\n\n"
|
"* `:delete-self` - IN_DELETE_SELF\n\n"
|
||||||
"* `:ignored` - `IN_IGNORED`\n\n"
|
"* `:ignored` - IN_IGNORED\n\n"
|
||||||
"* `:modify` - `IN_MODIFY`\n\n"
|
"* `:modify` - IN_MODIFY\n\n"
|
||||||
"* `:move-self` - `IN_MOVE_SELF`\n\n"
|
"* `:move-self` - IN_MOVE_SELF\n\n"
|
||||||
"* `:moved-from` - `IN_MOVED_FROM`\n\n"
|
"* `:moved-from` - IN_MOVED_FROM\n\n"
|
||||||
"* `:moved-to` - `IN_MOVED_TO`\n\n"
|
"* `:moved-to` - IN_MOVED_TO\n\n"
|
||||||
"* `:open` - `IN_OPEN`\n\n"
|
"* `:open` - IN_OPEN\n\n"
|
||||||
"* `:q-overflow` - `IN_Q_OVERFLOW`\n\n"
|
"* `:q-overflow` - IN_Q_OVERFLOW\n\n"
|
||||||
"* `:unmount` - `IN_UNMOUNT`\n\n\n"
|
"* `:unmount` - IN_UNMOUNT\n\n\n"
|
||||||
"On Windows, events will have the following possible types:\n\n"
|
"On Windows, events will have the following possible types:\n\n"
|
||||||
"* `:unknown`\n\n"
|
"* `:unknown`\n\n"
|
||||||
"* `:added`\n\n"
|
"* `:added`\n\n"
|
||||||
@@ -633,7 +633,7 @@ JANET_CORE_FN(cfun_filewatch_add,
|
|||||||
"* `:modified`\n\n"
|
"* `:modified`\n\n"
|
||||||
"* `:renamed-old`\n\n"
|
"* `:renamed-old`\n\n"
|
||||||
"* `:renamed-new`\n\n"
|
"* `:renamed-new`\n\n"
|
||||||
"On Linux, events will have a `:type` corresponding to the possible flags, excluding `:all`.\n"
|
"On Linux, events will a `:type` corresponding to the possible flags, excluding `:all`.\n"
|
||||||
"") {
|
"") {
|
||||||
janet_arity(argc, 2, -1);
|
janet_arity(argc, 2, -1);
|
||||||
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
||||||
|
|||||||
@@ -346,9 +346,6 @@ static void janet_deinit_block(JanetGCObject *mem) {
|
|||||||
break;
|
break;
|
||||||
case JANET_MEMORY_ABSTRACT: {
|
case JANET_MEMORY_ABSTRACT: {
|
||||||
JanetAbstractHead *head = (JanetAbstractHead *)mem;
|
JanetAbstractHead *head = (JanetAbstractHead *)mem;
|
||||||
if (head->type->gcperthread) {
|
|
||||||
janet_assert(!head->type->gcperthread(head->data, head->size), "per-thread finalizer failed");
|
|
||||||
}
|
|
||||||
if (head->type->gc) {
|
if (head->type->gc) {
|
||||||
janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
|
janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
|
||||||
}
|
}
|
||||||
@@ -500,12 +497,9 @@ void janet_sweep() {
|
|||||||
/* If not visited... */
|
/* If not visited... */
|
||||||
if (!janet_truthy(items[i].value)) {
|
if (!janet_truthy(items[i].value)) {
|
||||||
void *abst = janet_unwrap_abstract(items[i].key);
|
void *abst = janet_unwrap_abstract(items[i].key);
|
||||||
JanetAbstractHead *head = janet_abstract_head(abst);
|
|
||||||
if (head->type->gcperthread) {
|
|
||||||
janet_assert(!head->type->gcperthread(head->data, head->size), "per-thread finalizer failed");
|
|
||||||
}
|
|
||||||
if (0 == janet_abstract_decref(abst)) {
|
if (0 == janet_abstract_decref(abst)) {
|
||||||
/* Run finalizer */
|
/* Run finalizer */
|
||||||
|
JanetAbstractHead *head = janet_abstract_head(abst);
|
||||||
if (head->type->gc) {
|
if (head->type->gc) {
|
||||||
janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
|
janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
|
||||||
}
|
}
|
||||||
@@ -678,11 +672,8 @@ void janet_clear_memory(void) {
|
|||||||
for (int32_t i = 0; i < janet_vm.threaded_abstracts.capacity; i++) {
|
for (int32_t i = 0; i < janet_vm.threaded_abstracts.capacity; i++) {
|
||||||
if (janet_checktype(items[i].key, JANET_ABSTRACT)) {
|
if (janet_checktype(items[i].key, JANET_ABSTRACT)) {
|
||||||
void *abst = janet_unwrap_abstract(items[i].key);
|
void *abst = janet_unwrap_abstract(items[i].key);
|
||||||
JanetAbstractHead *head = janet_abstract_head(abst);
|
|
||||||
if (head->type->gcperthread) {
|
|
||||||
janet_assert(!head->type->gcperthread(head->data, head->size), "per-thread finalizer failed");
|
|
||||||
}
|
|
||||||
if (0 == janet_abstract_decref(abst)) {
|
if (0 == janet_abstract_decref(abst)) {
|
||||||
|
JanetAbstractHead *head = janet_abstract_head(abst);
|
||||||
if (head->type->gc) {
|
if (head->type->gc) {
|
||||||
janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
|
janet_assert(!head->type->gc(head->data, head->size), "finalizer failed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ static int janet_get_sockettype(Janet *argv, int32_t argc, int32_t n) {
|
|||||||
/* Needs argc >= offset + 2 */
|
/* Needs argc >= offset + 2 */
|
||||||
/* For unix paths, just rertuns a single sockaddr and sets *is_unix to 1,
|
/* 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. */
|
* 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. */
|
/* Unix socket support - not yet supported on windows. */
|
||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
if (janet_keyeq(argv[offset], "unix")) {
|
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;
|
saddr->sun_family = AF_UNIX;
|
||||||
size_t path_size = sizeof(saddr->sun_path);
|
size_t path_size = sizeof(saddr->sun_path);
|
||||||
snprintf(saddr->sun_path, path_size, "%s", path);
|
|
||||||
*sizeout = sizeof(struct sockaddr_un);
|
|
||||||
#ifdef JANET_LINUX
|
#ifdef JANET_LINUX
|
||||||
if (path[0] == '@') {
|
if (path[0] == '@') {
|
||||||
saddr->sun_path[0] = '\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
|
#endif
|
||||||
|
{
|
||||||
|
snprintf(saddr->sun_path, path_size, "%s", path);
|
||||||
|
}
|
||||||
*is_unix = 1;
|
*is_unix = 1;
|
||||||
return (struct addrinfo *) saddr;
|
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));
|
janet_panicf("could not get address info: %s", gai_strerror(status));
|
||||||
}
|
}
|
||||||
*is_unix = 0;
|
*is_unix = 0;
|
||||||
#ifdef JANET_WINDOWS
|
|
||||||
*sizeout = 0;
|
|
||||||
#else
|
|
||||||
*sizeout = sizeof(struct sockaddr_un);
|
|
||||||
#endif
|
|
||||||
return ai;
|
return ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,13 +405,12 @@ JANET_CORE_FN(cfun_net_sockaddr,
|
|||||||
int socktype = janet_get_sockettype(argv, argc, 2);
|
int socktype = janet_get_sockettype(argv, argc, 2);
|
||||||
int is_unix = 0;
|
int is_unix = 0;
|
||||||
int make_arr = (argc >= 3 && janet_truthy(argv[3]));
|
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);
|
||||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, &addrsize);
|
|
||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
/* no unix domain socket support on windows yet */
|
/* no unix domain socket support on windows yet */
|
||||||
if (is_unix) {
|
if (is_unix) {
|
||||||
void *abst = janet_abstract(&janet_address_type, addrsize);
|
void *abst = janet_abstract(&janet_address_type, sizeof(struct sockaddr_un));
|
||||||
memcpy(abst, ai, addrsize);
|
memcpy(abst, ai, sizeof(struct sockaddr_un));
|
||||||
Janet ret = janet_wrap_abstract(abst);
|
Janet ret = janet_wrap_abstract(abst);
|
||||||
return make_arr ? janet_wrap_array(janet_array_n(&ret, 1)) : ret;
|
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 */
|
/* Where we're connecting to */
|
||||||
socklen_t addrlen = 0;
|
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix);
|
||||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 0, &is_unix, &addrlen);
|
|
||||||
|
|
||||||
/* Check if we're binding address */
|
/* Check if we're binding address */
|
||||||
struct addrinfo *binding = NULL;
|
struct addrinfo *binding = NULL;
|
||||||
@@ -492,6 +486,7 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
/* Create socket */
|
/* Create socket */
|
||||||
JSock sock = JSOCKDEFAULT;
|
JSock sock = JSOCKDEFAULT;
|
||||||
void *addr = NULL;
|
void *addr = NULL;
|
||||||
|
socklen_t addrlen = 0;
|
||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
if (is_unix) {
|
if (is_unix) {
|
||||||
sock = socket(AF_UNIX, socktype | JSOCKFLAGS, 0);
|
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);
|
janet_panicf("could not create socket: %V", v);
|
||||||
}
|
}
|
||||||
addr = (void *) ai;
|
addr = (void *) ai;
|
||||||
|
addrlen = sizeof(struct sockaddr_un);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@@ -547,9 +543,7 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wrap socket in abstract type JanetStream */
|
/* Wrap socket in abstract type JanetStream */
|
||||||
uint32_t udp_flag = 0;
|
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
|
||||||
if (socktype == SOCK_DGRAM) udp_flag = JANET_STREAM_UDPSERVER;
|
|
||||||
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE | udp_flag);
|
|
||||||
|
|
||||||
/* Set up the socket for non-blocking IO before connecting */
|
/* Set up the socket for non-blocking IO before connecting */
|
||||||
janet_net_socknoblock(sock);
|
janet_net_socknoblock(sock);
|
||||||
@@ -587,56 +581,6 @@ JANET_CORE_FN(cfun_net_connect,
|
|||||||
net_sched_connect(stream);
|
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) {
|
static const char *serverify_socket(JSock sfd, int reuse_addr, int reuse_port) {
|
||||||
/* Set various socket options */
|
/* Set various socket options */
|
||||||
int enable = 1;
|
int enable = 1;
|
||||||
@@ -713,15 +657,14 @@ JANET_CORE_FN(cfun_net_listen,
|
|||||||
"The type parameter specifies the type of network connection, either "
|
"The type parameter specifies the type of network connection, either "
|
||||||
"a :stream (usually tcp), or :datagram (usually udp). If not specified, the default is "
|
"a :stream (usually tcp), or :datagram (usually udp). If not specified, the default is "
|
||||||
":stream. The host and port arguments are the same as in net/address. The last boolean parameter `no-reuse` will "
|
":stream. The host and port arguments are the same as in net/address. The last boolean parameter `no-reuse` will "
|
||||||
"disable the use of `SO_REUSEADDR` and `SO_REUSEPORT` when creating a server on some operating systems.") {
|
"disable the use of SO_REUSEADDR and SO_REUSEPORT when creating a server on some operating systems.") {
|
||||||
janet_sandbox_assert(JANET_SANDBOX_NET_LISTEN);
|
janet_sandbox_assert(JANET_SANDBOX_NET_LISTEN);
|
||||||
janet_arity(argc, 2, 4);
|
janet_arity(argc, 2, 4);
|
||||||
|
|
||||||
/* Get host, port, and handler*/
|
/* Get host, port, and handler*/
|
||||||
int socktype = janet_get_sockettype(argv, argc, 2);
|
int socktype = janet_get_sockettype(argv, argc, 2);
|
||||||
int is_unix = 0;
|
int is_unix = 0;
|
||||||
socklen_t addrlen = 0;
|
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix);
|
||||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0, socktype, 1, &is_unix, &addrlen);
|
|
||||||
int reuse = !(argc >= 4 && janet_truthy(argv[3]));
|
int reuse = !(argc >= 4 && janet_truthy(argv[3]));
|
||||||
|
|
||||||
JSock sfd = JSOCKDEFAULT;
|
JSock sfd = JSOCKDEFAULT;
|
||||||
@@ -733,7 +676,7 @@ JANET_CORE_FN(cfun_net_listen,
|
|||||||
janet_panicf("could not create socket: %V", janet_ev_lasterr());
|
janet_panicf("could not create socket: %V", janet_ev_lasterr());
|
||||||
}
|
}
|
||||||
const char *err = serverify_socket(sfd, reuse, 0);
|
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);
|
JSOCKCLOSE(sfd);
|
||||||
janet_free(ai);
|
janet_free(ai);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -1135,7 +1078,6 @@ void janet_lib_net(JanetTable *env) {
|
|||||||
JanetRegExt net_cfuns[] = {
|
JanetRegExt net_cfuns[] = {
|
||||||
JANET_CORE_REG("net/address", cfun_net_sockaddr),
|
JANET_CORE_REG("net/address", cfun_net_sockaddr),
|
||||||
JANET_CORE_REG("net/listen", cfun_net_listen),
|
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", cfun_stream_accept),
|
||||||
JANET_CORE_REG("net/accept-loop", cfun_stream_accept_loop),
|
JANET_CORE_REG("net/accept-loop", cfun_stream_accept_loop),
|
||||||
JANET_CORE_REG("net/read", cfun_stream_read),
|
JANET_CORE_REG("net/read", cfun_stream_read),
|
||||||
|
|||||||
@@ -66,7 +66,6 @@
|
|||||||
#ifdef JANET_APPLE
|
#ifdef JANET_APPLE
|
||||||
#include <crt_externs.h>
|
#include <crt_externs.h>
|
||||||
#define environ (*_NSGetEnviron())
|
#define environ (*_NSGetEnviron())
|
||||||
#include <AvailabilityMacros.h>
|
|
||||||
#else
|
#else
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
#endif
|
#endif
|
||||||
@@ -82,14 +81,8 @@ extern char **environ;
|
|||||||
#ifndef JANET_SPAWN_NO_CHDIR
|
#ifndef JANET_SPAWN_NO_CHDIR
|
||||||
#ifdef __GLIBC__
|
#ifdef __GLIBC__
|
||||||
#define JANET_SPAWN_CHDIR
|
#define JANET_SPAWN_CHDIR
|
||||||
#elif defined(JANET_APPLE)
|
#elif defined(JANET_APPLE) /* Some older versions may not work here. */
|
||||||
/* 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)
|
|
||||||
#define JANET_SPAWN_CHDIR
|
#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 */
|
#elif defined(__FreeBSD__) /* Not all BSDs work, for example openBSD doesn't seem to support this */
|
||||||
#define JANET_SPAWN_CHDIR
|
#define JANET_SPAWN_CHDIR
|
||||||
#endif
|
#endif
|
||||||
@@ -180,8 +173,6 @@ JANET_CORE_FN(os_which,
|
|||||||
return janet_ckeywordv("dragonfly");
|
return janet_ckeywordv("dragonfly");
|
||||||
#elif defined(JANET_BSD)
|
#elif defined(JANET_BSD)
|
||||||
return janet_ckeywordv("bsd");
|
return janet_ckeywordv("bsd");
|
||||||
#elif defined(JANET_ILLUMOS)
|
|
||||||
return janet_ckeywordv("illumos");
|
|
||||||
#else
|
#else
|
||||||
return janet_ckeywordv("posix");
|
return janet_ckeywordv("posix");
|
||||||
#endif
|
#endif
|
||||||
@@ -321,13 +312,6 @@ JANET_CORE_FN(os_cpu_count,
|
|||||||
return dflt;
|
return dflt;
|
||||||
}
|
}
|
||||||
return janet_wrap_integer(result);
|
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
|
#else
|
||||||
return dflt;
|
return dflt;
|
||||||
#endif
|
#endif
|
||||||
@@ -1270,7 +1254,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
|
|||||||
} else if (new_in != JANET_HANDLE_NONE) {
|
} else if (new_in != JANET_HANDLE_NONE) {
|
||||||
startupInfo.hStdInput = new_in;
|
startupInfo.hStdInput = new_in;
|
||||||
} else {
|
} else {
|
||||||
startupInfo.hStdInput = (HANDLE) _get_osfhandle(_fileno(stdin));
|
startupInfo.hStdInput = (HANDLE) _get_osfhandle(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe_out != JANET_HANDLE_NONE) {
|
if (pipe_out != JANET_HANDLE_NONE) {
|
||||||
@@ -1278,7 +1262,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
|
|||||||
} else if (new_out != JANET_HANDLE_NONE) {
|
} else if (new_out != JANET_HANDLE_NONE) {
|
||||||
startupInfo.hStdOutput = new_out;
|
startupInfo.hStdOutput = new_out;
|
||||||
} else {
|
} else {
|
||||||
startupInfo.hStdOutput = (HANDLE) _get_osfhandle(_fileno(stdout));
|
startupInfo.hStdOutput = (HANDLE) _get_osfhandle(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe_err != JANET_HANDLE_NONE) {
|
if (pipe_err != JANET_HANDLE_NONE) {
|
||||||
@@ -1288,7 +1272,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, JanetExecuteMode mode) {
|
|||||||
} else if (stderr_is_stdout) {
|
} else if (stderr_is_stdout) {
|
||||||
startupInfo.hStdError = startupInfo.hStdOutput;
|
startupInfo.hStdError = startupInfo.hStdOutput;
|
||||||
} else {
|
} else {
|
||||||
startupInfo.hStdError = (HANDLE) _get_osfhandle(_fileno(stderr));
|
startupInfo.hStdError = (HANDLE) _get_osfhandle(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cp_failed = 0;
|
int cp_failed = 0;
|
||||||
@@ -2879,9 +2863,6 @@ void janet_lib_os(JanetTable *env) {
|
|||||||
JANET_CORE_REG("os/proc-kill", os_proc_kill),
|
JANET_CORE_REG("os/proc-kill", os_proc_kill),
|
||||||
JANET_CORE_REG("os/proc-close", os_proc_close),
|
JANET_CORE_REG("os/proc-close", os_proc_close),
|
||||||
JANET_CORE_REG("os/getpid", os_proc_getpid),
|
JANET_CORE_REG("os/getpid", os_proc_getpid),
|
||||||
#ifdef JANET_EV
|
|
||||||
JANET_CORE_REG("os/sigaction", os_sigaction),
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* high resolution timers */
|
/* high resolution timers */
|
||||||
@@ -2890,6 +2871,7 @@ void janet_lib_os(JanetTable *env) {
|
|||||||
#ifdef JANET_EV
|
#ifdef JANET_EV
|
||||||
JANET_CORE_REG("os/open", os_open), /* fs read and write */
|
JANET_CORE_REG("os/open", os_open), /* fs read and write */
|
||||||
JANET_CORE_REG("os/pipe", os_pipe),
|
JANET_CORE_REG("os/pipe", os_pipe),
|
||||||
|
JANET_CORE_REG("os/sigaction", os_sigaction),
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
JANET_REG_END
|
JANET_REG_END
|
||||||
|
|||||||
@@ -1060,12 +1060,20 @@ void janet_buffer_format(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 's': {
|
case 's': {
|
||||||
const char *s = janet_getcbytes(argv, arg);
|
JanetByteView bytes = janet_getbytes(argv, arg);
|
||||||
|
const uint8_t *s = bytes.bytes;
|
||||||
|
int32_t l = bytes.len;
|
||||||
if (form[2] == '\0')
|
if (form[2] == '\0')
|
||||||
janet_buffer_push_cstring(b, s);
|
janet_buffer_push_bytes(b, s, l);
|
||||||
else {
|
else {
|
||||||
|
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");
|
||||||
|
} else {
|
||||||
nb = snprintf(item, MAX_ITEM, form, s);
|
nb = snprintf(item, MAX_ITEM, form, s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'V': {
|
case 'V': {
|
||||||
|
|||||||
@@ -26,8 +26,7 @@
|
|||||||
#include "state.h"
|
#include "state.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Run a string of code. The return value is a set of error flags, JANET_DO_ERROR_RUNTIME, JANET_DO_ERROR_COMPILE, and JANET_DOR_ERROR_PARSE if
|
/* Run a string */
|
||||||
* any errors were encountered in those phases. More information is printed to stderr. */
|
|
||||||
int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out) {
|
int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out) {
|
||||||
JanetParser *parser;
|
JanetParser *parser;
|
||||||
int errflags = 0, done = 0;
|
int errflags = 0, done = 0;
|
||||||
@@ -56,7 +55,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
|||||||
JanetSignal status = janet_continue(fiber, janet_wrap_nil(), &ret);
|
JanetSignal status = janet_continue(fiber, janet_wrap_nil(), &ret);
|
||||||
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
||||||
janet_stacktrace_ext(fiber, ret, "");
|
janet_stacktrace_ext(fiber, ret, "");
|
||||||
errflags |= JANET_DO_ERROR_RUNTIME;
|
errflags |= 0x01;
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -76,7 +75,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
|||||||
janet_eprintf("%s:%d:%d: compile error: %s\n", sourcePath,
|
janet_eprintf("%s:%d:%d: compile error: %s\n", sourcePath,
|
||||||
line, col, (const char *)cres.error);
|
line, col, (const char *)cres.error);
|
||||||
}
|
}
|
||||||
errflags |= JANET_DO_ERROR_COMPILE;
|
errflags |= 0x02;
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,7 +89,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
|||||||
break;
|
break;
|
||||||
case JANET_PARSE_ERROR: {
|
case JANET_PARSE_ERROR: {
|
||||||
const char *e = janet_parser_error(parser);
|
const char *e = janet_parser_error(parser);
|
||||||
errflags |= JANET_DO_ERROR_PARSE;
|
errflags |= 0x04;
|
||||||
ret = janet_cstringv(e);
|
ret = janet_cstringv(e);
|
||||||
int32_t line = (int32_t) parser->line;
|
int32_t line = (int32_t) parser->line;
|
||||||
int32_t col = (int32_t) parser->column;
|
int32_t col = (int32_t) parser->column;
|
||||||
|
|||||||
@@ -23,11 +23,8 @@
|
|||||||
#ifndef JANET_STATE_H_defined
|
#ifndef JANET_STATE_H_defined
|
||||||
#define JANET_STATE_H_defined
|
#define JANET_STATE_H_defined
|
||||||
|
|
||||||
#ifndef JANET_AMALG
|
|
||||||
#include "features.h"
|
|
||||||
#include <janet.h>
|
#include <janet.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JANET_EV
|
#ifdef JANET_EV
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
|
|||||||
@@ -931,24 +931,27 @@ int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
|
|||||||
#include <mach/clock.h>
|
#include <mach/clock.h>
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
|
int janet_gettime(struct timespec *spec, enum JanetTimeSource source) {
|
||||||
if (source == JANET_TIME_CPUTIME) {
|
if (source == JANET_TIME_REALTIME) {
|
||||||
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 {
|
|
||||||
clock_serv_t cclock;
|
clock_serv_t cclock;
|
||||||
mach_timespec_t mts;
|
mach_timespec_t mts;
|
||||||
clock_id_t cid = CALENDAR_CLOCK;
|
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||||
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);
|
|
||||||
clock_get_time(cclock, &mts);
|
clock_get_time(cclock, &mts);
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
spec->tv_sec = mts.tv_sec;
|
spec->tv_sec = mts.tv_sec;
|
||||||
spec->tv_nsec = mts.tv_nsec;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
#define vm_maybe_auto_suspend(COND)
|
#define vm_maybe_auto_suspend(COND)
|
||||||
#else
|
#else
|
||||||
#define vm_maybe_auto_suspend(COND) do { \
|
#define vm_maybe_auto_suspend(COND) do { \
|
||||||
if ((COND) && janet_atomic_load_relaxed(&janet_vm.auto_suspend)) { \
|
if ((COND) && janet_vm.auto_suspend) { \
|
||||||
fiber->flags |= (JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP); \
|
fiber->flags |= (JANET_FIBER_RESUME_NO_USEVAL | JANET_FIBER_RESUME_NO_SKIP); \
|
||||||
vm_return(JANET_SIGNAL_INTERRUPT, janet_wrap_nil()); \
|
vm_return(JANET_SIGNAL_INTERRUPT, janet_wrap_nil()); \
|
||||||
} \
|
} \
|
||||||
|
|||||||
@@ -67,21 +67,11 @@ extern "C" {
|
|||||||
#define JANET_LINUX 1
|
#define JANET_LINUX 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for Android */
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
#define JANET_ANDROID 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check for Cygwin */
|
/* Check for Cygwin */
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
#define JANET_CYGWIN 1
|
#define JANET_CYGWIN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for Illumos */
|
|
||||||
#if defined(__illumos__)
|
|
||||||
#define JANET_ILLUMOS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check Unix */
|
/* Check Unix */
|
||||||
#if defined(_AIX) \
|
#if defined(_AIX) \
|
||||||
|| defined(__APPLE__) /* Darwin */ \
|
|| defined(__APPLE__) /* Darwin */ \
|
||||||
@@ -167,7 +157,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check sun */
|
/* Check sun */
|
||||||
#if defined(__sun) && !defined(JANET_ILLUMOS)
|
#ifdef __sun
|
||||||
#define JANET_NO_UTC_MKTIME
|
#define JANET_NO_UTC_MKTIME
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -175,12 +165,14 @@ extern "C" {
|
|||||||
/* Also enable the thread library only if not single-threaded */
|
/* Also enable the thread library only if not single-threaded */
|
||||||
#ifdef JANET_SINGLE_THREADED
|
#ifdef JANET_SINGLE_THREADED
|
||||||
#define JANET_THREAD_LOCAL
|
#define JANET_THREAD_LOCAL
|
||||||
#elif !(defined(JANET_THREAD_LOCAL)) && defined(__GNUC__)
|
#undef JANET_THREADS
|
||||||
|
#elif defined(__GNUC__)
|
||||||
#define JANET_THREAD_LOCAL __thread
|
#define JANET_THREAD_LOCAL __thread
|
||||||
#elif !(defined(JANET_THREAD_LOCAL)) && defined(_MSC_BUILD)
|
#elif defined(_MSC_BUILD)
|
||||||
#define JANET_THREAD_LOCAL __declspec(thread)
|
#define JANET_THREAD_LOCAL __declspec(thread)
|
||||||
#elif !(defined(JANET_THREAD_LOCAL))
|
#else
|
||||||
#define JANET_THREAD_LOCAL
|
#define JANET_THREAD_LOCAL
|
||||||
|
#undef JANET_THREADS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Enable or disable dynamic module loading. Enabled by default. */
|
/* Enable or disable dynamic module loading. Enabled by default. */
|
||||||
@@ -599,7 +591,6 @@ typedef void *JanetAbstract;
|
|||||||
#define JANET_STREAM_WRITABLE 0x400
|
#define JANET_STREAM_WRITABLE 0x400
|
||||||
#define JANET_STREAM_ACCEPTABLE 0x800
|
#define JANET_STREAM_ACCEPTABLE 0x800
|
||||||
#define JANET_STREAM_UDPSERVER 0x1000
|
#define JANET_STREAM_UDPSERVER 0x1000
|
||||||
#define JANET_STREAM_NOT_CLOSEABLE 0x2000
|
|
||||||
#define JANET_STREAM_TOCLOSE 0x10000
|
#define JANET_STREAM_TOCLOSE 0x10000
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -672,7 +663,6 @@ typedef int32_t JanetAtomicInt;
|
|||||||
JANET_API JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x);
|
JANET_API JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x);
|
||||||
JANET_API JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x);
|
JANET_API JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x);
|
||||||
JANET_API JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x);
|
JANET_API JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x);
|
||||||
JANET_API JanetAtomicInt janet_atomic_load_relaxed(JanetAtomicInt volatile *x);
|
|
||||||
|
|
||||||
/* We provide three possible implementations of Janets. The preferred
|
/* We provide three possible implementations of Janets. The preferred
|
||||||
* nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the
|
* nanboxing approach, for 32 or 64 bits, and the standard C version. Code in the rest of the
|
||||||
@@ -1188,7 +1178,6 @@ struct JanetAbstractType {
|
|||||||
Janet(*call)(void *p, int32_t argc, Janet *argv);
|
Janet(*call)(void *p, int32_t argc, Janet *argv);
|
||||||
size_t (*length)(void *p, size_t len);
|
size_t (*length)(void *p, size_t len);
|
||||||
JanetByteView(*bytes)(void *p, size_t len);
|
JanetByteView(*bytes)(void *p, size_t len);
|
||||||
int (*gcperthread)(void *data, size_t len);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Some macros to let us add extra types to JanetAbstract types without
|
/* Some macros to let us add extra types to JanetAbstract types without
|
||||||
@@ -1208,8 +1197,7 @@ struct JanetAbstractType {
|
|||||||
#define JANET_ATEND_NEXT NULL,JANET_ATEND_CALL
|
#define JANET_ATEND_NEXT NULL,JANET_ATEND_CALL
|
||||||
#define JANET_ATEND_CALL NULL,JANET_ATEND_LENGTH
|
#define JANET_ATEND_CALL NULL,JANET_ATEND_LENGTH
|
||||||
#define JANET_ATEND_LENGTH NULL,JANET_ATEND_BYTES
|
#define JANET_ATEND_LENGTH NULL,JANET_ATEND_BYTES
|
||||||
#define JANET_ATEND_BYTES NULL,JANET_ATEND_GCPERTHREAD
|
#define JANET_ATEND_BYTES
|
||||||
#define JANET_ATEND_GCPERTHREAD
|
|
||||||
|
|
||||||
struct JanetReg {
|
struct JanetReg {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -1467,10 +1455,10 @@ JANET_API int32_t janet_abstract_incref(void *abst);
|
|||||||
JANET_API int32_t janet_abstract_decref(void *abst);
|
JANET_API int32_t janet_abstract_decref(void *abst);
|
||||||
|
|
||||||
/* Expose channel utilities */
|
/* Expose channel utilities */
|
||||||
JANET_API JanetChannel *janet_channel_make(uint32_t limit);
|
JanetChannel *janet_channel_make(uint32_t limit);
|
||||||
JANET_API JanetChannel *janet_channel_make_threaded(uint32_t limit);
|
JanetChannel *janet_channel_make_threaded(uint32_t limit);
|
||||||
JANET_API JanetChannel *janet_getchannel(const Janet *argv, int32_t n);
|
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_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_give(JanetChannel *channel, Janet x);
|
||||||
JANET_API int janet_channel_take(JanetChannel *channel, Janet *out);
|
JANET_API int janet_channel_take(JanetChannel *channel, Janet *out);
|
||||||
|
|
||||||
@@ -1618,9 +1606,6 @@ JANET_API JanetTable *janet_core_env(JanetTable *replacements);
|
|||||||
JANET_API JanetTable *janet_core_lookup_table(JanetTable *replacements);
|
JANET_API JanetTable *janet_core_lookup_table(JanetTable *replacements);
|
||||||
|
|
||||||
/* Execute strings */
|
/* Execute strings */
|
||||||
#define JANET_DO_ERROR_RUNTIME 0x01
|
|
||||||
#define JANET_DO_ERROR_COMPILE 0x02
|
|
||||||
#define JANET_DO_ERROR_PARSE 0x04
|
|
||||||
JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out);
|
JANET_API int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char *sourcePath, Janet *out);
|
||||||
JANET_API int janet_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out);
|
JANET_API int janet_dostring(JanetTable *env, const char *str, const char *sourcePath, Janet *out);
|
||||||
|
|
||||||
|
|||||||
@@ -865,13 +865,6 @@
|
|||||||
(assert (deep= ~(,import* "a" :as "b" :fresh maybe)
|
(assert (deep= ~(,import* "a" :as "b" :fresh maybe)
|
||||||
(macex '(import a :as b :fresh maybe))) "import macro 2")
|
(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
|
# #477 walk preserving bracket type
|
||||||
# 0a1d902f4
|
# 0a1d902f4
|
||||||
(assert (= :brackets (tuple/type (postwalk identity '[])))
|
(assert (= :brackets (tuple/type (postwalk identity '[])))
|
||||||
|
|||||||
@@ -106,8 +106,6 @@
|
|||||||
(calc-2 "(+ 9 10 11 12)"))
|
(calc-2 "(+ 9 10 11 12)"))
|
||||||
@[10 26 42]) "parallel subprocesses 2")
|
@[10 26 42]) "parallel subprocesses 2")
|
||||||
|
|
||||||
# (print "file piping")
|
|
||||||
|
|
||||||
# File piping
|
# File piping
|
||||||
# a1cc5ca04
|
# a1cc5ca04
|
||||||
(assert-no-error "file writing 1"
|
(assert-no-error "file writing 1"
|
||||||
@@ -227,8 +225,6 @@
|
|||||||
(++ iterations)
|
(++ iterations)
|
||||||
(ev/write stream " ")))
|
(ev/write stream " ")))
|
||||||
|
|
||||||
# (print "local name / peer name testing")
|
|
||||||
|
|
||||||
# Test localname and peername
|
# Test localname and peername
|
||||||
# 077bf5eba
|
# 077bf5eba
|
||||||
(repeat 10
|
(repeat 10
|
||||||
@@ -411,8 +407,6 @@
|
|||||||
(while (def msg (ev/read connection 100))
|
(while (def msg (ev/read connection 100))
|
||||||
(broadcast name (string msg)))))))
|
(broadcast name (string msg)))))))
|
||||||
|
|
||||||
# (print "chat app testing")
|
|
||||||
|
|
||||||
# Now launch the chat server
|
# Now launch the chat server
|
||||||
(def chat-server (net/listen test-host test-port))
|
(def chat-server (net/listen test-host test-port))
|
||||||
(ev/spawn
|
(ev/spawn
|
||||||
@@ -506,8 +500,6 @@
|
|||||||
(let [s (net/listen :unix uds-path :stream)]
|
(let [s (net/listen :unix uds-path :stream)]
|
||||||
(:close s))))))
|
(:close s))))))
|
||||||
|
|
||||||
# (print "accept loop testing")
|
|
||||||
|
|
||||||
# net/accept-loop level triggering
|
# net/accept-loop level triggering
|
||||||
(gccollect)
|
(gccollect)
|
||||||
(def maxconn 50)
|
(def maxconn 50)
|
||||||
@@ -530,8 +522,6 @@
|
|||||||
(assert (= maxconn connect-count))
|
(assert (= maxconn connect-count))
|
||||||
(:close s)
|
(:close s)
|
||||||
|
|
||||||
# (print "running deadline tests...")
|
|
||||||
|
|
||||||
# Cancel os/proc-wait with ev/deadline
|
# Cancel os/proc-wait with ev/deadline
|
||||||
(let [p (os/spawn [;run janet "-e" "(os/sleep 4)"] :p)]
|
(let [p (os/spawn [;run janet "-e" "(os/sleep 4)"] :p)]
|
||||||
(var terminated-normally false)
|
(var terminated-normally false)
|
||||||
@@ -556,35 +546,9 @@
|
|||||||
(ev/sleep 0.15)
|
(ev/sleep 0.15)
|
||||||
(assert (not terminated-normally) "early termination failure 3"))
|
(assert (not terminated-normally) "early termination failure 3"))
|
||||||
|
|
||||||
# Deadline with interrupt
|
(let [f (coro (forever :foo))]
|
||||||
(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)
|
(ev/deadline 0.01 nil f true)
|
||||||
(assert-error "deadline expired" (resume f))))
|
(assert-error "deadline expired" (resume f)))
|
||||||
|
|
||||||
# Use :err :stdout
|
# Use :err :stdout
|
||||||
(def- subproc-code '(do (eprint "hi") (eflush) (print "there") (flush)))
|
(def- subproc-code '(do (eprint "hi") (eflush) (print "there") (flush)))
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
# Copyright (c) 2025 Calvin Rose & contributors
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
# of this software and associated documentation files (the "Software"), to
|
|
||||||
# deal in the Software without restriction, including without limitation the
|
|
||||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
||||||
# sell copies of the Software, and to permit persons to whom the Software is
|
|
||||||
# furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
||||||
# IN THE SOFTWARE.
|
|
||||||
|
|
||||||
(import ./helper :prefix "" :exit true)
|
|
||||||
(start-suite)
|
|
||||||
|
|
||||||
# Issue #1629
|
|
||||||
(def thread-channel (ev/thread-chan 100))
|
|
||||||
(def super (ev/thread-chan 10))
|
|
||||||
(defn worker []
|
|
||||||
(while true
|
|
||||||
(def item (ev/take thread-channel))
|
|
||||||
(when (= item :deadline)
|
|
||||||
(ev/deadline 0.1 nil (fiber/current) true))))
|
|
||||||
(ev/thread worker nil :n super)
|
|
||||||
(ev/give thread-channel :item)
|
|
||||||
(ev/sleep 0.05)
|
|
||||||
(ev/give thread-channel :item)
|
|
||||||
(ev/sleep 0.05)
|
|
||||||
(ev/give thread-channel :deadline)
|
|
||||||
(ev/sleep 0.05)
|
|
||||||
(ev/give thread-channel :item)
|
|
||||||
(ev/sleep 0.05)
|
|
||||||
(ev/give thread-channel :item)
|
|
||||||
(ev/sleep 0.15)
|
|
||||||
(assert (deep= '(:error "deadline expired" nil) (ev/take super)) "deadline expirataion")
|
|
||||||
|
|
||||||
# Another variant
|
|
||||||
(def thread-channel (ev/thread-chan 100))
|
|
||||||
(def super (ev/thread-chan 10))
|
|
||||||
(defn worker []
|
|
||||||
(while true
|
|
||||||
(def item (ev/take thread-channel))
|
|
||||||
(when (= item :deadline)
|
|
||||||
(ev/deadline 0.1))))
|
|
||||||
(ev/thread worker nil :n super)
|
|
||||||
(ev/give thread-channel :deadline)
|
|
||||||
(ev/sleep 0.2)
|
|
||||||
(assert (deep= '(:error "deadline expired" nil) (ev/take super)) "deadline expirataion")
|
|
||||||
|
|
||||||
(end-suite)
|
|
||||||
@@ -136,8 +136,5 @@
|
|||||||
"keyword slice")
|
"keyword slice")
|
||||||
(assert (= 'symbol (symbol/slice "some_symbol_slice" 5 11)) "symbol slice")
|
(assert (= 'symbol (symbol/slice "some_symbol_slice" 5 11)) "symbol slice")
|
||||||
|
|
||||||
# Check string formatting, #1600
|
|
||||||
(assert (= "" (string/format "%.99s" @"")) "string/format %s buffer")
|
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|
||||||
|
|||||||
@@ -37,12 +37,6 @@
|
|||||||
Version="$(var.Version)"
|
Version="$(var.Version)"
|
||||||
Manufacturer="$(var.Manufacturer)"
|
Manufacturer="$(var.Manufacturer)"
|
||||||
UpgradeCode="$(var.UpgradeCode)">
|
UpgradeCode="$(var.UpgradeCode)">
|
||||||
<!--
|
|
||||||
perUser means destination will be under user's %AppData% directory,
|
|
||||||
not Program Files or similar.
|
|
||||||
|
|
||||||
see: https://learn.microsoft.com/en-us/windows/win32/msi/installation-context
|
|
||||||
-->
|
|
||||||
<Package Compressed="yes"
|
<Package Compressed="yes"
|
||||||
InstallScope="perUser"
|
InstallScope="perUser"
|
||||||
Manufacturer="$(var.Manufacturer)"
|
Manufacturer="$(var.Manufacturer)"
|
||||||
|
|||||||
Reference in New Issue
Block a user