mirror of
https://github.com/janet-lang/janet
synced 2025-11-21 01:34:49 +00:00
Compare commits
31 Commits
mingw-vari
...
v1.37.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83e8aab289 | ||
|
|
85cb35e68f | ||
|
|
5b79b48ae0 | ||
|
|
7c44127bcb | ||
|
|
9338312103 | ||
|
|
a0eeb630e7 | ||
|
|
6535d72bd4 | ||
|
|
a7d424bc81 | ||
|
|
2bceba4a7a | ||
|
|
e3159bb0f5 | ||
|
|
5d1bd8a932 | ||
|
|
bafa6bfff0 | ||
|
|
e2eb7ab4b2 | ||
|
|
9f4497a5ae | ||
|
|
70de8bf092 | ||
|
|
e52575e23a | ||
|
|
10994cbc6a | ||
|
|
abad9d7db9 | ||
|
|
5e443cd29d | ||
|
|
7bf3a9d24c | ||
|
|
d80a7094ae | ||
|
|
ad77bc391c | ||
|
|
2b84fb14b4 | ||
|
|
07155ce657 | ||
|
|
046d28662d | ||
|
|
84dd3db620 | ||
|
|
282f2671ea | ||
|
|
3fc2be3e6e | ||
|
|
d10c1fe759 | ||
|
|
d18472b07d | ||
|
|
43a68dcd2a |
@@ -19,3 +19,8 @@ tasks:
|
|||||||
ninja
|
ninja
|
||||||
ninja test
|
ninja test
|
||||||
sudo ninja install
|
sudo ninja install
|
||||||
|
- meson_min: |
|
||||||
|
cd janet
|
||||||
|
meson setup build_meson_min --buildtype=release -Dsingle_threaded=true -Dnanbox=false -Ddynamic_modules=false -Ddocstrings=false -Dnet=false -Dsourcemaps=false -Dpeg=false -Dassembler=false -Dint_types=false -Dreduced_os=true -Dffi=false
|
||||||
|
cd build_meson_min
|
||||||
|
ninja
|
||||||
|
|||||||
63
.github/workflows/test.yml
vendored
63
.github/workflows/test.yml
vendored
@@ -14,11 +14,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os: [ ubuntu-latest, macos-latest, macos-13 ]
|
os: [ ubuntu-latest, macos-latest, macos-13 ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Build
|
- name: Compile the project
|
||||||
run: make clean && make
|
run: make clean && make
|
||||||
- name: Test
|
- name: Test the project
|
||||||
run: make test
|
run: make test
|
||||||
|
|
||||||
test-windows:
|
test-windows:
|
||||||
@@ -32,24 +32,51 @@ jobs:
|
|||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Setup MSVC
|
- name: Setup MSVC
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
- name: Build
|
- name: Build the project
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: build_win
|
run: build_win
|
||||||
- name: Test
|
- name: Test the project
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: build_win test
|
run: build_win test
|
||||||
|
- name: Test installer build
|
||||||
|
shell: cmd
|
||||||
|
run: build_win dist
|
||||||
|
|
||||||
|
test-windows-min:
|
||||||
|
name: Build and test on Windows Minimal build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ windows-2019 ]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout the repository
|
||||||
|
uses: actions/checkout@master
|
||||||
|
- name: Setup MSVC
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
- name: Setup Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
- name: Install Python Dependencies
|
||||||
|
run: pip install meson ninja
|
||||||
|
- name: Build
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
meson setup build_meson_min --buildtype=release -Dsingle_threaded=true -Dnanbox=false -Ddynamic_modules=false -Ddocstrings=false -Dnet=false -Dsourcemaps=false -Dpeg=false -Dassembler=false -Dint_types=false -Dreduced_os=true -Dffi=false
|
||||||
|
cd build_meson_min
|
||||||
|
ninja
|
||||||
|
|
||||||
test-mingw:
|
test-mingw:
|
||||||
name: Build on Windows with Mingw
|
name: Build on Windows with Mingw
|
||||||
runs-on: windows-2019
|
runs-on: windows-latest
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
msystem: [ UCRT64, MINGW64, MINGW32, CLANG64 ]
|
msystem: [ UCRT64, CLANG64 ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Setup Mingw
|
- name: Setup Mingw
|
||||||
uses: msys2/setup-msys2@v2
|
uses: msys2/setup-msys2@v2
|
||||||
@@ -63,15 +90,15 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: make -j4 CC=gcc
|
run: make -j4 CC=gcc
|
||||||
- name: Test
|
- name: Test
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: make test -j4 CC=gcc
|
run: make -j4 CC=gcc test
|
||||||
|
|
||||||
test-mingw-linux:
|
test-mingw-linux:
|
||||||
name: Build and test with Mingw on Linux + Wine
|
name: Build and test with Mingw on Linux + Wine
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Setup Mingw and wine
|
- name: Setup Mingw and wine
|
||||||
run: |
|
run: |
|
||||||
@@ -79,24 +106,24 @@ jobs:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install libstdc++6:i386 libgcc-s1:i386
|
sudo apt-get install libstdc++6:i386 libgcc-s1:i386
|
||||||
sudo apt-get install gcc-mingw-w64-x86-64-win32 wine wine32 wine64
|
sudo apt-get install gcc-mingw-w64-x86-64-win32 wine wine32 wine64
|
||||||
- name: Build
|
- name: Compile the project
|
||||||
run: make clean && make CC=x86_64-w64-mingw32-gcc LD=x86_64-w64-mingw32-gcc UNAME=MINGW RUN=wine
|
run: make clean && make CC=x86_64-w64-mingw32-gcc LD=x86_64-w64-mingw32-gcc UNAME=MINGW RUN=wine
|
||||||
- name: Test
|
- name: Test the project
|
||||||
run: make test UNAME=MINGW RUN=wine VERBOSE=1
|
run: make test UNAME=MINGW RUN=wine VERBOSE=1
|
||||||
|
|
||||||
test-arm-linux:
|
test-arm-linux:
|
||||||
name: Build and test ARM32 cross compilation
|
name: Build and test ARM32 cross compilation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@master
|
uses: actions/checkout@master
|
||||||
- name: Setup qemu and cross compiler
|
- name: Setup qemu and cross compiler
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install gcc-arm-linux-gnueabi qemu-user
|
sudo apt-get install gcc-arm-linux-gnueabi qemu-user
|
||||||
- name: Build
|
- name: Compile the project
|
||||||
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-gcc
|
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-gcc
|
||||||
- name: Test
|
- name: Test the project
|
||||||
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" SUBRUN="qemu-arm -L /usr/arm-linux-gnueabi/" test VERBOSE=1
|
run: make RUN="qemu-arm -L /usr/arm-linux-gnueabi/" SUBRUN="qemu-arm -L /usr/arm-linux-gnueabi/" test VERBOSE=1
|
||||||
|
|
||||||
test-s390x-linux:
|
test-s390x-linux:
|
||||||
@@ -108,4 +135,4 @@ jobs:
|
|||||||
- name: Do Qemu build and test
|
- name: Do Qemu build and test
|
||||||
run: |
|
run: |
|
||||||
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
docker run --rm -v .:/janet s390x/ubuntu bash -c "apt-get -y update && apt-get -y install git build-essential && cd /janet && make -j3 && make test"
|
docker run --rm -v .:/janet --platform linux/s390x ubuntu bash -c "apt-get -y update && apt-get -y install git build-essential && cd /janet && make -j3 && make test"
|
||||||
|
|||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,11 +1,19 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
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
|
## 1.37.1 - 2024-12-05
|
||||||
|
- Fix meson cross compilation
|
||||||
|
- Update timeout documentation for networking APIs: timeouts raise errors and do not return nil.
|
||||||
|
- Add `janet_addtimeout_nil(double sec);` to the C API.
|
||||||
|
- Change string hashing.
|
||||||
|
- Fix string equality bug.
|
||||||
|
- Add `assertf`
|
||||||
- Change how JANET_PROFILE is loaded to allow more easily customizing the environment.
|
- Change how JANET_PROFILE is loaded to allow more easily customizing the environment.
|
||||||
- Add `*repl-prompt*` dynamic binding to allow customizing the built in repl.
|
- Add `*repl-prompt*` dynamic binding to allow customizing the built in repl.
|
||||||
- Add multiple path support in the `JANET_PATH` environment variables. This lets
|
- Add multiple path support in the `JANET_PATH` environment variables. This lets
|
||||||
user more easily import modules from many directories.
|
user more easily import modules from many directories.
|
||||||
|
- Add `nth` and `only-tags` PEG specials to select from sub-captures while
|
||||||
|
dropping the rest.
|
||||||
|
|
||||||
## 1.36.0 - 2024-09-07
|
## 1.36.0 - 2024-09-07
|
||||||
- Improve error messages in `bundle/add*` functions.
|
- Improve error messages in `bundle/add*` functions.
|
||||||
|
|||||||
@@ -250,8 +250,10 @@ Emacs, and Atom each have syntax packages for the Janet language, though.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
See the [Introduction](https://janet-lang.org/docs/index.html) for more details. If you just want
|
If you just want to try out the language, you don't need to install anything.
|
||||||
to try out the language, you don't need to install anything. You can also move the `janet` executable wherever you want on your system and run it.
|
In this case you can also move the `janet` executable wherever you want on
|
||||||
|
your system and run it. However, for a fuller setup, please see the
|
||||||
|
[Introduction](https://janet-lang.org/docs/index.html) for more details.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ if defined APPVEYOR_REPO_TAG_NAME (
|
|||||||
set RELEASE_VERSION=%JANET_VERSION%
|
set RELEASE_VERSION=%JANET_VERSION%
|
||||||
)
|
)
|
||||||
if defined CI (
|
if defined CI (
|
||||||
set WIXBIN="c:\Program Files (x86)\WiX Toolset v3.11\bin\"
|
set WIXBIN="%WIX%bin\"
|
||||||
|
echo WIXBIN = %WIXBIN%
|
||||||
) else (
|
) else (
|
||||||
set WIXBIN=
|
set WIXBIN=
|
||||||
)
|
)
|
||||||
|
|||||||
29
meson.build
29
meson.build
@@ -20,14 +20,23 @@
|
|||||||
|
|
||||||
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.37.0')
|
version : '1.37.1')
|
||||||
|
|
||||||
# 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')
|
||||||
header_path = join_paths(get_option('prefix'), get_option('includedir'), 'janet')
|
header_path = join_paths(get_option('prefix'), get_option('includedir'), 'janet')
|
||||||
|
|
||||||
# Link math library on all systems
|
# Compilers
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
native_cc = meson.get_compiler('c', native : true)
|
||||||
|
|
||||||
|
# Native deps
|
||||||
|
native_m_dep = native_cc.find_library('m', required : false)
|
||||||
|
native_dl_dep = native_cc.find_library('dl', required : false)
|
||||||
|
native_android_spawn_dep = native_cc.find_library('android-spawn', required : false)
|
||||||
|
native_thread_dep = dependency('threads', native : true)
|
||||||
|
|
||||||
|
# Deps
|
||||||
m_dep = cc.find_library('m', required : false)
|
m_dep = cc.find_library('m', required : false)
|
||||||
dl_dep = cc.find_library('dl', required : false)
|
dl_dep = cc.find_library('dl', required : false)
|
||||||
android_spawn_dep = cc.find_library('android-spawn', required : false)
|
android_spawn_dep = cc.find_library('android-spawn', required : false)
|
||||||
@@ -164,11 +173,18 @@ mainclient_src = [
|
|||||||
'src/mainclient/shell.c'
|
'src/mainclient/shell.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
janet_dependencies = [m_dep, dl_dep, android_spawn_dep]
|
||||||
|
janet_native_dependencies = [native_m_dep, native_dl_dep, native_android_spawn_dep]
|
||||||
|
if not get_option('single_threaded')
|
||||||
|
janet_dependencies += thread_dep
|
||||||
|
janet_native_dependencies += native_thread_dep
|
||||||
|
endif
|
||||||
|
|
||||||
# Build boot binary
|
# Build boot binary
|
||||||
janet_boot = executable('janet-boot', core_src, boot_src,
|
janet_boot = executable('janet-boot', core_src, boot_src,
|
||||||
include_directories : incdir,
|
include_directories : incdir,
|
||||||
c_args : '-DJANET_BOOTSTRAP',
|
c_args : '-DJANET_BOOTSTRAP',
|
||||||
dependencies : [m_dep, dl_dep, thread_dep, android_spawn_dep],
|
dependencies : janet_native_dependencies,
|
||||||
native : true)
|
native : true)
|
||||||
|
|
||||||
# Build janet.c
|
# Build janet.c
|
||||||
@@ -181,11 +197,6 @@ janetc = custom_target('janetc',
|
|||||||
'JANET_PATH', janet_path
|
'JANET_PATH', janet_path
|
||||||
])
|
])
|
||||||
|
|
||||||
janet_dependencies = [m_dep, dl_dep, android_spawn_dep]
|
|
||||||
if not get_option('single_threaded')
|
|
||||||
janet_dependencies += thread_dep
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Allow building with no shared library
|
# Allow building with no shared library
|
||||||
if cc.has_argument('-fvisibility=hidden')
|
if cc.has_argument('-fvisibility=hidden')
|
||||||
lib_cflags = ['-fvisibility=hidden']
|
lib_cflags = ['-fvisibility=hidden']
|
||||||
@@ -231,7 +242,7 @@ if meson.is_cross_build()
|
|||||||
endif
|
endif
|
||||||
janet_nativeclient = executable('janet-native', janetc, mainclient_src,
|
janet_nativeclient = executable('janet-native', janetc, mainclient_src,
|
||||||
include_directories : incdir,
|
include_directories : incdir,
|
||||||
dependencies : janet_dependencies,
|
dependencies : janet_native_dependencies,
|
||||||
c_args : extra_native_cflags,
|
c_args : extra_native_cflags,
|
||||||
native : true)
|
native : true)
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -204,6 +204,16 @@
|
|||||||
[fmt & args]
|
[fmt & args]
|
||||||
(error (string/format fmt ;args)))
|
(error (string/format fmt ;args)))
|
||||||
|
|
||||||
|
(defmacro assertf
|
||||||
|
"Convenience macro that combines `assert` and `string/format`."
|
||||||
|
[x fmt & args]
|
||||||
|
(def v (gensym))
|
||||||
|
~(do
|
||||||
|
(def ,v ,x)
|
||||||
|
(if ,v
|
||||||
|
,v
|
||||||
|
(,errorf ,fmt ,;args))))
|
||||||
|
|
||||||
(defmacro default
|
(defmacro default
|
||||||
``Define a default value for an optional argument.
|
``Define a default value for an optional argument.
|
||||||
Expands to `(def sym (if (= nil sym) val sym))`.``
|
Expands to `(def sym (if (= nil sym) val sym))`.``
|
||||||
@@ -2655,7 +2665,6 @@
|
|||||||
|
|
||||||
(do
|
(do
|
||||||
(var pindex 0)
|
(var pindex 0)
|
||||||
(var pstatus nil)
|
|
||||||
(def len (length buf))
|
(def len (length buf))
|
||||||
(when (= len 0)
|
(when (= len 0)
|
||||||
(:eof p)
|
(:eof p)
|
||||||
@@ -3934,7 +3943,7 @@
|
|||||||
(defn make-sig []
|
(defn make-sig []
|
||||||
(ffi/signature :default real-ret-type ;computed-type-args))
|
(ffi/signature :default real-ret-type ;computed-type-args))
|
||||||
(defn make-ptr []
|
(defn make-ptr []
|
||||||
(assert (ffi/lookup (if lazy (llib) lib) raw-symbol) (string "failed to find ffi symbol " raw-symbol)))
|
(assertf (ffi/lookup (if lazy (llib) lib) raw-symbol) "failed to find ffi symbol %v" raw-symbol))
|
||||||
(if lazy
|
(if lazy
|
||||||
~(defn ,alias ,;meta [,;formal-args]
|
~(defn ,alias ,;meta [,;formal-args]
|
||||||
(,ffi/call (,(delay (make-ptr))) (,(delay (make-sig))) ,;formal-args))
|
(,ffi/call (,(delay (make-ptr))) (,(delay (make-sig))) ,;formal-args))
|
||||||
@@ -4111,7 +4120,7 @@
|
|||||||
"Get the manifest for a give installed bundle"
|
"Get the manifest for a give installed bundle"
|
||||||
[bundle-name]
|
[bundle-name]
|
||||||
(def name (get-manifest-filename bundle-name))
|
(def name (get-manifest-filename bundle-name))
|
||||||
(assert (fexists name) (string "no bundle " bundle-name " found"))
|
(assertf (fexists name) "no bundle %v found" bundle-name)
|
||||||
(parse (slurp name)))
|
(parse (slurp name)))
|
||||||
|
|
||||||
(defn- get-bundle-module
|
(defn- get-bundle-module
|
||||||
@@ -4254,11 +4263,9 @@
|
|||||||
(def missing (seq [d :in deps :when (not (bundle/installed? d))] (string d)))
|
(def missing (seq [d :in deps :when (not (bundle/installed? d))] (string d)))
|
||||||
(when (next missing) (errorf "missing dependencies %s" (string/join missing ", "))))
|
(when (next missing) (errorf "missing dependencies %s" (string/join missing ", "))))
|
||||||
(def bundle-name (get config :name default-bundle-name))
|
(def bundle-name (get config :name default-bundle-name))
|
||||||
(assert bundle-name (errorf "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)
|
||||||
(assert (not (string/check-set "\\/" bundle-name))
|
(assertf (not (string/check-set "\\/" bundle-name))
|
||||||
(string "bundle name "
|
"bundle name %v cannot contain path separators" bundle-name)
|
||||||
bundle-name
|
|
||||||
" cannot contain path separators"))
|
|
||||||
(assert (next bundle-name) "cannot use empty bundle-name")
|
(assert (next bundle-name) "cannot use empty bundle-name")
|
||||||
(assert (not (fexists (get-manifest-filename bundle-name)))
|
(assert (not (fexists (get-manifest-filename bundle-name)))
|
||||||
"bundle is already installed")
|
"bundle is already installed")
|
||||||
@@ -4310,7 +4317,7 @@
|
|||||||
(var i 0)
|
(var i 0)
|
||||||
(def man (bundle/manifest bundle-name))
|
(def man (bundle/manifest bundle-name))
|
||||||
(def files (get man :files @[]))
|
(def files (get man :files @[]))
|
||||||
(assert (os/mkdir dest-dir) (string "could not create directory " dest-dir " (or it already exists)"))
|
(assertf (os/mkdir dest-dir) "could not create directory %v (or it already exists)" dest-dir)
|
||||||
(def s (sep))
|
(def s (sep))
|
||||||
(os/mkdir (string dest-dir s "bundle"))
|
(os/mkdir (string dest-dir s "bundle"))
|
||||||
(def install-hook (string dest-dir s "bundle" s "init.janet"))
|
(def install-hook (string dest-dir s "bundle" s "init.janet"))
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
#define JANET_VERSION_MAJOR 1
|
#define JANET_VERSION_MAJOR 1
|
||||||
#define JANET_VERSION_MINOR 37
|
#define JANET_VERSION_MINOR 37
|
||||||
#define JANET_VERSION_PATCH 0
|
#define JANET_VERSION_PATCH 1
|
||||||
#define JANET_VERSION_EXTRA "-dev"
|
#define JANET_VERSION_EXTRA ""
|
||||||
#define JANET_VERSION "1.37.0-dev"
|
#define JANET_VERSION "1.37.1"
|
||||||
|
|
||||||
/* #define JANET_BUILD "local" */
|
/* #define JANET_BUILD "local" */
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Even if single threaded, include this for atomics! */
|
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -549,8 +548,8 @@ void *janet_optabstract(const Janet *argv, int32_t argc, int32_t n, const JanetA
|
|||||||
/* Atomic refcounts */
|
/* Atomic refcounts */
|
||||||
|
|
||||||
JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x) {
|
JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x) {
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef _MSC_VER
|
||||||
return InterlockedIncrement(x);
|
return _InterlockedIncrement(x);
|
||||||
#elif defined(JANET_USE_STDATOMIC)
|
#elif defined(JANET_USE_STDATOMIC)
|
||||||
return atomic_fetch_add_explicit(x, 1, memory_order_relaxed) + 1;
|
return atomic_fetch_add_explicit(x, 1, memory_order_relaxed) + 1;
|
||||||
#else
|
#else
|
||||||
@@ -559,8 +558,8 @@ JanetAtomicInt janet_atomic_inc(JanetAtomicInt volatile *x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) {
|
JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) {
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef _MSC_VER
|
||||||
return InterlockedDecrement(x);
|
return _InterlockedDecrement(x);
|
||||||
#elif defined(JANET_USE_STDATOMIC)
|
#elif defined(JANET_USE_STDATOMIC)
|
||||||
return atomic_fetch_add_explicit(x, -1, memory_order_acq_rel) - 1;
|
return atomic_fetch_add_explicit(x, -1, memory_order_acq_rel) - 1;
|
||||||
#else
|
#else
|
||||||
@@ -569,8 +568,8 @@ JanetAtomicInt janet_atomic_dec(JanetAtomicInt volatile *x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x) {
|
JanetAtomicInt janet_atomic_load(JanetAtomicInt volatile *x) {
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef _MSC_VER
|
||||||
return InterlockedOr(x, 0);
|
return _InterlockedOr(x, 0);
|
||||||
#elif defined(JANET_USE_STDATOMIC)
|
#elif defined(JANET_USE_STDATOMIC)
|
||||||
return atomic_load_explicit(x, memory_order_acquire);
|
return atomic_load_explicit(x, memory_order_acquire);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -625,6 +625,18 @@ void janet_addtimeout(double sec) {
|
|||||||
add_timeout(to);
|
add_timeout(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set timeout for the current root fiber but resume with nil instead of raising an error */
|
||||||
|
void janet_addtimeout_nil(double sec) {
|
||||||
|
JanetFiber *fiber = janet_vm.root_fiber;
|
||||||
|
JanetTimeout to;
|
||||||
|
to.when = ts_delta(ts_now(), sec);
|
||||||
|
to.fiber = fiber;
|
||||||
|
to.curr_fiber = NULL;
|
||||||
|
to.sched_id = fiber->sched_id;
|
||||||
|
to.is_error = 0;
|
||||||
|
add_timeout(to);
|
||||||
|
}
|
||||||
|
|
||||||
void janet_ev_inc_refcount(void) {
|
void janet_ev_inc_refcount(void) {
|
||||||
janet_atomic_inc(&janet_vm.listener_count);
|
janet_atomic_inc(&janet_vm.listener_count);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ static JanetFFIStruct *build_struct_type(int32_t argc, const Janet *argv) {
|
|||||||
|
|
||||||
JanetFFIStruct *st = janet_abstract(&janet_struct_type,
|
JanetFFIStruct *st = janet_abstract(&janet_struct_type,
|
||||||
sizeof(JanetFFIStruct) + argc * sizeof(JanetFFIStructMember));
|
sizeof(JanetFFIStruct) + argc * sizeof(JanetFFIStructMember));
|
||||||
st->field_count = member_count;
|
st->field_count = 0;
|
||||||
st->size = 0;
|
st->size = 0;
|
||||||
st->align = 1;
|
st->align = 1;
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
@@ -418,6 +418,7 @@ static JanetFFIStruct *build_struct_type(int32_t argc, const Janet *argv) {
|
|||||||
st->fields[i].type = decode_ffi_type(argv[j]);
|
st->fields[i].type = decode_ffi_type(argv[j]);
|
||||||
size_t el_size = type_size(st->fields[i].type);
|
size_t el_size = type_size(st->fields[i].type);
|
||||||
size_t el_align = type_align(st->fields[i].type);
|
size_t el_align = type_align(st->fields[i].type);
|
||||||
|
if (el_align <= 0) janet_panicf("bad field type %V", argv[j]);
|
||||||
if (all_packed || pack_one) {
|
if (all_packed || pack_one) {
|
||||||
if (st->size % el_align != 0) is_aligned = 0;
|
if (st->size % el_align != 0) is_aligned = 0;
|
||||||
st->fields[i].offset = st->size;
|
st->fields[i].offset = st->size;
|
||||||
@@ -433,6 +434,7 @@ static JanetFFIStruct *build_struct_type(int32_t argc, const Janet *argv) {
|
|||||||
st->size += (st->align - 1);
|
st->size += (st->align - 1);
|
||||||
st->size /= st->align;
|
st->size /= st->align;
|
||||||
st->size *= st->align;
|
st->size *= st->align;
|
||||||
|
st->field_count = member_count;
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ typedef struct {
|
|||||||
#ifndef JANET_WINDOWS
|
#ifndef JANET_WINDOWS
|
||||||
JanetStream *stream;
|
JanetStream *stream;
|
||||||
#endif
|
#endif
|
||||||
JanetTable* watch_descriptors;
|
JanetTable *watch_descriptors;
|
||||||
JanetChannel *channel;
|
JanetChannel *channel;
|
||||||
uint32_t default_flags;
|
uint32_t default_flags;
|
||||||
int is_watching;
|
int is_watching;
|
||||||
@@ -85,9 +85,9 @@ static uint32_t decode_watch_flags(const Janet *options, int32_t n) {
|
|||||||
}
|
}
|
||||||
JanetKeyword keyw = janet_unwrap_keyword(options[i]);
|
JanetKeyword keyw = janet_unwrap_keyword(options[i]);
|
||||||
const JanetWatchFlagName *result = janet_strbinsearch(watcher_flags_linux,
|
const JanetWatchFlagName *result = janet_strbinsearch(watcher_flags_linux,
|
||||||
sizeof(watcher_flags_linux) / sizeof(JanetWatchFlagName),
|
sizeof(watcher_flags_linux) / sizeof(JanetWatchFlagName),
|
||||||
sizeof(JanetWatchFlagName),
|
sizeof(JanetWatchFlagName),
|
||||||
keyw);
|
keyw);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
janet_panicf("unknown inotify flag %v", options[i]);
|
janet_panicf("unknown inotify flag %v", options[i]);
|
||||||
}
|
}
|
||||||
@@ -154,99 +154,97 @@ static void watcher_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
|
|||||||
janet_schedule(fiber, janet_wrap_nil());
|
janet_schedule(fiber, janet_wrap_nil());
|
||||||
janet_async_end(fiber);
|
janet_async_end(fiber);
|
||||||
break;
|
break;
|
||||||
case JANET_ASYNC_EVENT_ERR:
|
case JANET_ASYNC_EVENT_ERR: {
|
||||||
{
|
janet_schedule(fiber, janet_wrap_nil());
|
||||||
janet_schedule(fiber, janet_wrap_nil());
|
janet_async_end(fiber);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
read_more:
|
||||||
|
case JANET_ASYNC_EVENT_HUP:
|
||||||
|
case JANET_ASYNC_EVENT_INIT:
|
||||||
|
case JANET_ASYNC_EVENT_READ: {
|
||||||
|
Janet name = janet_wrap_nil();
|
||||||
|
|
||||||
|
/* Assumption - read will never return partial events *
|
||||||
|
* From documentation:
|
||||||
|
*
|
||||||
|
* The behavior when the buffer given to read(2) is too small to
|
||||||
|
* return information about the next event depends on the kernel
|
||||||
|
* version: before Linux 2.6.21, read(2) returns 0; since Linux
|
||||||
|
* 2.6.21, read(2) fails with the error EINVAL. Specifying a buffer
|
||||||
|
* of size
|
||||||
|
*
|
||||||
|
* sizeof(struct inotify_event) + NAME_MAX + 1
|
||||||
|
*
|
||||||
|
* will be sufficient to read at least one event. */
|
||||||
|
ssize_t nread;
|
||||||
|
do {
|
||||||
|
nread = read(stream->handle, buf, sizeof(buf));
|
||||||
|
} while (nread == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
/* Check for errors - special case errors that can just be waited on to fix */
|
||||||
|
if (nread == -1) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
janet_cancel(fiber, janet_ev_lasterr());
|
||||||
|
fiber->ev_state = NULL;
|
||||||
janet_async_end(fiber);
|
janet_async_end(fiber);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
read_more:
|
if (nread < (ssize_t) sizeof(struct inotify_event)) break;
|
||||||
case JANET_ASYNC_EVENT_HUP:
|
|
||||||
case JANET_ASYNC_EVENT_INIT:
|
|
||||||
case JANET_ASYNC_EVENT_READ:
|
|
||||||
{
|
|
||||||
Janet name = janet_wrap_nil();
|
|
||||||
|
|
||||||
/* Assumption - read will never return partial events *
|
/* Iterate through all events read from the buffer */
|
||||||
* From documentation:
|
char *cursor = buf;
|
||||||
*
|
while (cursor < buf + nread) {
|
||||||
* The behavior when the buffer given to read(2) is too small to
|
struct inotify_event inevent;
|
||||||
* return information about the next event depends on the kernel
|
memcpy(&inevent, cursor, sizeof(inevent));
|
||||||
* version: before Linux 2.6.21, read(2) returns 0; since Linux
|
cursor += sizeof(inevent);
|
||||||
* 2.6.21, read(2) fails with the error EINVAL. Specifying a buffer
|
/* Read path of inevent */
|
||||||
* of size
|
if (inevent.len) {
|
||||||
*
|
name = janet_cstringv(cursor);
|
||||||
* sizeof(struct inotify_event) + NAME_MAX + 1
|
cursor += inevent.len;
|
||||||
*
|
|
||||||
* will be sufficient to read at least one event. */
|
|
||||||
ssize_t nread;
|
|
||||||
do {
|
|
||||||
nread = read(stream->handle, buf, sizeof(buf));
|
|
||||||
} while (nread == -1 && errno == EINTR);
|
|
||||||
|
|
||||||
/* Check for errors - special case errors that can just be waited on to fix */
|
|
||||||
if (nread == -1) {
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
janet_cancel(fiber, janet_ev_lasterr());
|
|
||||||
fiber->ev_state = NULL;
|
|
||||||
janet_async_end(fiber);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (nread < (ssize_t) sizeof(struct inotify_event)) break;
|
|
||||||
|
|
||||||
/* Iterate through all events read from the buffer */
|
/* Got an event */
|
||||||
char *cursor = buf;
|
Janet path = janet_table_get(watcher->watch_descriptors, janet_wrap_integer(inevent.wd));
|
||||||
while (cursor < buf + nread) {
|
JanetKV *event = janet_struct_begin(6);
|
||||||
struct inotify_event inevent;
|
janet_struct_put(event, janet_ckeywordv("wd"), janet_wrap_integer(inevent.wd));
|
||||||
memcpy(&inevent, cursor, sizeof(inevent));
|
janet_struct_put(event, janet_ckeywordv("wd-path"), path);
|
||||||
cursor += sizeof(inevent);
|
if (janet_checktype(name, JANET_NIL)) {
|
||||||
/* Read path of inevent */
|
/* We were watching a file directly, so path is the full path. Split into dirname / basename */
|
||||||
if (inevent.len) {
|
JanetString spath = janet_unwrap_string(path);
|
||||||
name = janet_cstringv(cursor);
|
const uint8_t *cursor = spath + janet_string_length(spath);
|
||||||
cursor += inevent.len;
|
const uint8_t *cursor_end = cursor;
|
||||||
|
while (cursor > spath && cursor[0] != '/') {
|
||||||
|
cursor--;
|
||||||
}
|
}
|
||||||
|
if (cursor == spath) {
|
||||||
/* Got an event */
|
|
||||||
Janet path = janet_table_get(watcher->watch_descriptors, janet_wrap_integer(inevent.wd));
|
|
||||||
JanetKV *event = janet_struct_begin(6);
|
|
||||||
janet_struct_put(event, janet_ckeywordv("wd"), janet_wrap_integer(inevent.wd));
|
|
||||||
janet_struct_put(event, janet_ckeywordv("wd-path"), path);
|
|
||||||
if (janet_checktype(name, JANET_NIL)) {
|
|
||||||
/* We were watching a file directly, so path is the full path. Split into dirname / basename */
|
|
||||||
JanetString spath = janet_unwrap_string(path);
|
|
||||||
const uint8_t *cursor = spath + janet_string_length(spath);
|
|
||||||
const uint8_t *cursor_end = cursor;
|
|
||||||
while (cursor > spath && cursor[0] != '/') {
|
|
||||||
cursor--;
|
|
||||||
}
|
|
||||||
if (cursor == spath) {
|
|
||||||
janet_struct_put(event, janet_ckeywordv("dir-name"), path);
|
|
||||||
janet_struct_put(event, janet_ckeywordv("file-name"), name);
|
|
||||||
} else {
|
|
||||||
janet_struct_put(event, janet_ckeywordv("dir-name"), janet_wrap_string(janet_string(spath, (cursor - spath))));
|
|
||||||
janet_struct_put(event, janet_ckeywordv("file-name"), janet_wrap_string(janet_string(cursor + 1, (cursor_end - cursor - 1))));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
janet_struct_put(event, janet_ckeywordv("dir-name"), path);
|
janet_struct_put(event, janet_ckeywordv("dir-name"), path);
|
||||||
janet_struct_put(event, janet_ckeywordv("file-name"), name);
|
janet_struct_put(event, janet_ckeywordv("file-name"), name);
|
||||||
|
} else {
|
||||||
|
janet_struct_put(event, janet_ckeywordv("dir-name"), janet_wrap_string(janet_string(spath, (cursor - spath))));
|
||||||
|
janet_struct_put(event, janet_ckeywordv("file-name"), janet_wrap_string(janet_string(cursor + 1, (cursor_end - cursor - 1))));
|
||||||
}
|
}
|
||||||
janet_struct_put(event, janet_ckeywordv("cookie"), janet_wrap_integer(inevent.cookie));
|
} else {
|
||||||
Janet etype = janet_ckeywordv("type");
|
janet_struct_put(event, janet_ckeywordv("dir-name"), path);
|
||||||
const JanetWatchFlagName *wfn_end = watcher_flags_linux + sizeof(watcher_flags_linux) / sizeof(watcher_flags_linux[0]);
|
janet_struct_put(event, janet_ckeywordv("file-name"), name);
|
||||||
for (const JanetWatchFlagName *wfn = watcher_flags_linux; wfn < wfn_end; wfn++) {
|
|
||||||
if ((inevent.mask & wfn->flag) == wfn->flag) janet_struct_put(event, etype, janet_ckeywordv(wfn->name));
|
|
||||||
}
|
|
||||||
Janet eventv = janet_wrap_struct(janet_struct_end(event));
|
|
||||||
|
|
||||||
janet_channel_give(watcher->channel, eventv);
|
|
||||||
}
|
}
|
||||||
|
janet_struct_put(event, janet_ckeywordv("cookie"), janet_wrap_integer(inevent.cookie));
|
||||||
|
Janet etype = janet_ckeywordv("type");
|
||||||
|
const JanetWatchFlagName *wfn_end = watcher_flags_linux + sizeof(watcher_flags_linux) / sizeof(watcher_flags_linux[0]);
|
||||||
|
for (const JanetWatchFlagName *wfn = watcher_flags_linux; wfn < wfn_end; wfn++) {
|
||||||
|
if ((inevent.mask & wfn->flag) == wfn->flag) janet_struct_put(event, etype, janet_ckeywordv(wfn->name));
|
||||||
|
}
|
||||||
|
Janet eventv = janet_wrap_struct(janet_struct_end(event));
|
||||||
|
|
||||||
/* Read some more if possible */
|
janet_channel_give(watcher->channel, eventv);
|
||||||
goto read_more;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
/* Read some more if possible */
|
||||||
|
goto read_more;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +271,8 @@ static void janet_watcher_unlisten(JanetWatcher *watcher) {
|
|||||||
#define WATCHFLAG_RECURSIVE 0x100000u
|
#define WATCHFLAG_RECURSIVE 0x100000u
|
||||||
|
|
||||||
static const JanetWatchFlagName watcher_flags_windows[] = {
|
static const JanetWatchFlagName watcher_flags_windows[] = {
|
||||||
{"all",
|
{
|
||||||
|
"all",
|
||||||
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
||||||
FILE_NOTIFY_CHANGE_CREATION |
|
FILE_NOTIFY_CHANGE_CREATION |
|
||||||
FILE_NOTIFY_CHANGE_DIR_NAME |
|
FILE_NOTIFY_CHANGE_DIR_NAME |
|
||||||
@@ -282,7 +281,8 @@ static const JanetWatchFlagName watcher_flags_windows[] = {
|
|||||||
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
FILE_NOTIFY_CHANGE_LAST_WRITE |
|
||||||
FILE_NOTIFY_CHANGE_SECURITY |
|
FILE_NOTIFY_CHANGE_SECURITY |
|
||||||
FILE_NOTIFY_CHANGE_SIZE |
|
FILE_NOTIFY_CHANGE_SIZE |
|
||||||
WATCHFLAG_RECURSIVE},
|
WATCHFLAG_RECURSIVE
|
||||||
|
},
|
||||||
{"attributes", FILE_NOTIFY_CHANGE_ATTRIBUTES},
|
{"attributes", FILE_NOTIFY_CHANGE_ATTRIBUTES},
|
||||||
{"creation", FILE_NOTIFY_CHANGE_CREATION},
|
{"creation", FILE_NOTIFY_CHANGE_CREATION},
|
||||||
{"dir-name", FILE_NOTIFY_CHANGE_DIR_NAME},
|
{"dir-name", FILE_NOTIFY_CHANGE_DIR_NAME},
|
||||||
@@ -302,9 +302,9 @@ static uint32_t decode_watch_flags(const Janet *options, int32_t n) {
|
|||||||
}
|
}
|
||||||
JanetKeyword keyw = janet_unwrap_keyword(options[i]);
|
JanetKeyword keyw = janet_unwrap_keyword(options[i]);
|
||||||
const JanetWatchFlagName *result = janet_strbinsearch(watcher_flags_windows,
|
const JanetWatchFlagName *result = janet_strbinsearch(watcher_flags_windows,
|
||||||
sizeof(watcher_flags_windows) / sizeof(JanetWatchFlagName),
|
sizeof(watcher_flags_windows) / sizeof(JanetWatchFlagName),
|
||||||
sizeof(JanetWatchFlagName),
|
sizeof(JanetWatchFlagName),
|
||||||
keyw);
|
keyw);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
janet_panicf("unknown windows filewatch flag %v", options[i]);
|
janet_panicf("unknown windows filewatch flag %v", options[i]);
|
||||||
}
|
}
|
||||||
@@ -339,19 +339,19 @@ typedef struct {
|
|||||||
|
|
||||||
static void read_dir_changes(OverlappedWatch *ow) {
|
static void read_dir_changes(OverlappedWatch *ow) {
|
||||||
BOOL result = ReadDirectoryChangesW(ow->stream->handle,
|
BOOL result = ReadDirectoryChangesW(ow->stream->handle,
|
||||||
(NotifyChange *) ow->buf,
|
(NotifyChange *) ow->buf,
|
||||||
FILE_INFO_PADDING,
|
FILE_INFO_PADDING,
|
||||||
(ow->flags & WATCHFLAG_RECURSIVE) ? TRUE : FALSE,
|
(ow->flags & WATCHFLAG_RECURSIVE) ? TRUE : FALSE,
|
||||||
ow->flags & ~WATCHFLAG_RECURSIVE,
|
ow->flags & ~WATCHFLAG_RECURSIVE,
|
||||||
NULL,
|
NULL,
|
||||||
(OVERLAPPED *) ow,
|
(OVERLAPPED *) ow,
|
||||||
NULL);
|
NULL);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
janet_panicv(janet_ev_lasterr());
|
janet_panicv(janet_ev_lasterr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* watcher_actions_windows[] = {
|
static const char *watcher_actions_windows[] = {
|
||||||
"unknown",
|
"unknown",
|
||||||
"added",
|
"added",
|
||||||
"removed",
|
"removed",
|
||||||
@@ -382,48 +382,47 @@ static void watcher_callback_read(JanetFiber *fiber, JanetAsyncEvent event) {
|
|||||||
case JANET_ASYNC_EVENT_FAILED:
|
case JANET_ASYNC_EVENT_FAILED:
|
||||||
janet_stream_close(ow->stream);
|
janet_stream_close(ow->stream);
|
||||||
break;
|
break;
|
||||||
case JANET_ASYNC_EVENT_COMPLETE:
|
case JANET_ASYNC_EVENT_COMPLETE: {
|
||||||
{
|
if (!watcher->is_watching) {
|
||||||
if (!watcher->is_watching) {
|
janet_stream_close(ow->stream);
|
||||||
janet_stream_close(ow->stream);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
NotifyChange *fni = (NotifyChange *) ow->buf;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
/* Got an event */
|
|
||||||
|
|
||||||
/* Extract name */
|
|
||||||
Janet filename;
|
|
||||||
if (fni->FileNameLength) {
|
|
||||||
int32_t nbytes = (int32_t) WideCharToMultiByte(CP_UTF8, 0, fni->FileName, fni->FileNameLength / sizeof(wchar_t), NULL, 0, NULL, NULL);
|
|
||||||
janet_assert(nbytes, "bad utf8 path");
|
|
||||||
uint8_t *into = janet_string_begin(nbytes);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, fni->FileName, fni->FileNameLength / sizeof(wchar_t), (char *) into, nbytes, NULL, NULL);
|
|
||||||
filename = janet_wrap_string(janet_string_end(into));
|
|
||||||
} else {
|
|
||||||
filename = janet_cstringv("");
|
|
||||||
}
|
|
||||||
|
|
||||||
JanetKV *event = janet_struct_begin(3);
|
|
||||||
janet_struct_put(event, janet_ckeywordv("type"), janet_ckeywordv(watcher_actions_windows[fni->Action]));
|
|
||||||
janet_struct_put(event, janet_ckeywordv("file-name"), filename);
|
|
||||||
janet_struct_put(event, janet_ckeywordv("dir-name"), janet_wrap_string(ow->dir_path));
|
|
||||||
Janet eventv = janet_wrap_struct(janet_struct_end(event));
|
|
||||||
|
|
||||||
janet_channel_give(watcher->channel, eventv);
|
|
||||||
|
|
||||||
/* Next event */
|
|
||||||
if (!fni->NextEntryOffset) break;
|
|
||||||
fni = (NotifyChange *) ((char *)fni + fni->NextEntryOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make another call to read directory changes */
|
|
||||||
read_dir_changes(ow);
|
|
||||||
janet_async_in_flight(fiber);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
NotifyChange *fni = (NotifyChange *) ow->buf;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* Got an event */
|
||||||
|
|
||||||
|
/* Extract name */
|
||||||
|
Janet filename;
|
||||||
|
if (fni->FileNameLength) {
|
||||||
|
int32_t nbytes = (int32_t) WideCharToMultiByte(CP_UTF8, 0, fni->FileName, fni->FileNameLength / sizeof(wchar_t), NULL, 0, NULL, NULL);
|
||||||
|
janet_assert(nbytes, "bad utf8 path");
|
||||||
|
uint8_t *into = janet_string_begin(nbytes);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, fni->FileName, fni->FileNameLength / sizeof(wchar_t), (char *) into, nbytes, NULL, NULL);
|
||||||
|
filename = janet_wrap_string(janet_string_end(into));
|
||||||
|
} else {
|
||||||
|
filename = janet_cstringv("");
|
||||||
|
}
|
||||||
|
|
||||||
|
JanetKV *event = janet_struct_begin(3);
|
||||||
|
janet_struct_put(event, janet_ckeywordv("type"), janet_ckeywordv(watcher_actions_windows[fni->Action]));
|
||||||
|
janet_struct_put(event, janet_ckeywordv("file-name"), filename);
|
||||||
|
janet_struct_put(event, janet_ckeywordv("dir-name"), janet_wrap_string(ow->dir_path));
|
||||||
|
Janet eventv = janet_wrap_struct(janet_struct_end(event));
|
||||||
|
|
||||||
|
janet_channel_give(watcher->channel, eventv);
|
||||||
|
|
||||||
|
/* Next event */
|
||||||
|
if (!fni->NextEntryOffset) break;
|
||||||
|
fni = (NotifyChange *)((char *)fni + fni->NextEntryOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make another call to read directory changes */
|
||||||
|
read_dir_changes(ow);
|
||||||
|
janet_async_in_flight(fiber);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,12 +438,12 @@ static void start_listening_ow(OverlappedWatch *ow) {
|
|||||||
|
|
||||||
static void janet_watcher_add(JanetWatcher *watcher, const char *path, uint32_t flags) {
|
static void janet_watcher_add(JanetWatcher *watcher, const char *path, uint32_t flags) {
|
||||||
HANDLE handle = CreateFileA(path,
|
HANDLE handle = CreateFileA(path,
|
||||||
FILE_LIST_DIRECTORY | GENERIC_READ,
|
FILE_LIST_DIRECTORY | GENERIC_READ,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
NULL,
|
NULL,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_FLAG_OVERLAPPED | FILE_FLAG_BACKUP_SEMANTICS,
|
FILE_FLAG_OVERLAPPED | FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
NULL);
|
NULL);
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
janet_panicv(janet_ev_lasterr());
|
janet_panicv(janet_ev_lasterr());
|
||||||
}
|
}
|
||||||
@@ -574,20 +573,20 @@ static const JanetAbstractType janet_filewatch_at = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_filewatch_make,
|
JANET_CORE_FN(cfun_filewatch_make,
|
||||||
"(filewatch/new channel &opt default-flags)",
|
"(filewatch/new channel &opt default-flags)",
|
||||||
"Create a new filewatcher that will give events to a channel channel. See `filewatch/add` for available flags.\n\n"
|
"Create a new filewatcher that will give events to a channel channel. See `filewatch/add` for available flags.\n\n"
|
||||||
"When an event is triggered by the filewatcher, a struct containing information will be given to channel as with `ev/give`. "
|
"When an event is triggered by the filewatcher, a struct containing information will be given to channel as with `ev/give`. "
|
||||||
"The contents of the channel depend on the OS, but will contain some common keys:\n\n"
|
"The contents of the channel depend on the OS, but will contain some common keys:\n\n"
|
||||||
"* `:type` -- the type of the event that was raised.\n\n"
|
"* `:type` -- the type of the event that was raised.\n\n"
|
||||||
"* `:file-name` -- the base file name of the file that triggered the event.\n\n"
|
"* `:file-name` -- the base file name of the file that triggered the event.\n\n"
|
||||||
"* `:dir-name` -- the directory name of the file that triggered the event.\n\n"
|
"* `:dir-name` -- the directory name of the file that triggered the event.\n\n"
|
||||||
"Events also will contain keys specific to the host OS.\n\n"
|
"Events also will contain keys specific to the host OS.\n\n"
|
||||||
"Windows has no extra properties on events.\n\n"
|
"Windows has no extra properties on events.\n\n"
|
||||||
"Linux has the following extra properties on events:\n\n"
|
"Linux has the following extra properties on events:\n\n"
|
||||||
"* `:wd` -- the integer key returned by `filewatch/add` for the path that triggered this.\n\n"
|
"* `:wd` -- the integer key returned by `filewatch/add` for the path that triggered this.\n\n"
|
||||||
"* `:wd-path` -- the string path for watched directory of file. For files, will be the same as `:file-name`, and for directories, will be the same as `:dir-name`.\n\n"
|
"* `:wd-path` -- the string path for watched directory of file. For files, will be the same as `:file-name`, and for directories, will be the same as `:dir-name`.\n\n"
|
||||||
"* `:cookie` -- a randomized integer used to associate related events, such as :moved-from and :moved-to events.\n\n"
|
"* `:cookie` -- a randomized integer used to associate related events, such as :moved-from and :moved-to events.\n\n"
|
||||||
"") {
|
"") {
|
||||||
janet_sandbox_assert(JANET_SANDBOX_FS_READ);
|
janet_sandbox_assert(JANET_SANDBOX_FS_READ);
|
||||||
janet_arity(argc, 1, -1);
|
janet_arity(argc, 1, -1);
|
||||||
JanetChannel *channel = janet_getchannel(argv, 0);
|
JanetChannel *channel = janet_getchannel(argv, 0);
|
||||||
@@ -598,44 +597,44 @@ 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"
|
||||||
"* `:removed`\n\n"
|
"* `:removed`\n\n"
|
||||||
"* `: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 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);
|
||||||
const char *path = janet_getcstring(argv, 1);
|
const char *path = janet_getcstring(argv, 1);
|
||||||
@@ -645,8 +644,8 @@ JANET_CORE_FN(cfun_filewatch_add,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_filewatch_remove,
|
JANET_CORE_FN(cfun_filewatch_remove,
|
||||||
"(filewatch/remove watcher path)",
|
"(filewatch/remove watcher path)",
|
||||||
"Remove a path from the watcher.") {
|
"Remove a path from the watcher.") {
|
||||||
janet_fixarity(argc, 2);
|
janet_fixarity(argc, 2);
|
||||||
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
||||||
const char *path = janet_getcstring(argv, 1);
|
const char *path = janet_getcstring(argv, 1);
|
||||||
@@ -655,8 +654,8 @@ JANET_CORE_FN(cfun_filewatch_remove,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_filewatch_listen,
|
JANET_CORE_FN(cfun_filewatch_listen,
|
||||||
"(filewatch/listen watcher)",
|
"(filewatch/listen watcher)",
|
||||||
"Listen for changes in the watcher.") {
|
"Listen for changes in the watcher.") {
|
||||||
janet_fixarity(argc, 1);
|
janet_fixarity(argc, 1);
|
||||||
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
||||||
janet_watcher_listen(watcher);
|
janet_watcher_listen(watcher);
|
||||||
@@ -664,8 +663,8 @@ JANET_CORE_FN(cfun_filewatch_listen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JANET_CORE_FN(cfun_filewatch_unlisten,
|
JANET_CORE_FN(cfun_filewatch_unlisten,
|
||||||
"(filewatch/unlisten watcher)",
|
"(filewatch/unlisten watcher)",
|
||||||
"Stop listening for changes on a given watcher.") {
|
"Stop listening for changes on a given watcher.") {
|
||||||
janet_fixarity(argc, 1);
|
janet_fixarity(argc, 1);
|
||||||
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
JanetWatcher *watcher = janet_getabstract(argv, 0, &janet_filewatch_at);
|
||||||
janet_watcher_unlisten(watcher);
|
janet_watcher_unlisten(watcher);
|
||||||
|
|||||||
@@ -829,7 +829,7 @@ JANET_CORE_FN(cfun_stream_accept_loop,
|
|||||||
JANET_CORE_FN(cfun_stream_accept,
|
JANET_CORE_FN(cfun_stream_accept,
|
||||||
"(net/accept stream &opt timeout)",
|
"(net/accept stream &opt timeout)",
|
||||||
"Get the next connection on a server stream. This would usually be called in a loop in a dedicated fiber. "
|
"Get the next connection on a server stream. This would usually be called in a loop in a dedicated fiber. "
|
||||||
"Takes an optional timeout in seconds, after which will return nil. "
|
"Takes an optional timeout in seconds, after which will raise an error. "
|
||||||
"Returns a new duplex stream which represents a connection to the client.") {
|
"Returns a new duplex stream which represents a connection to the client.") {
|
||||||
janet_arity(argc, 1, 2);
|
janet_arity(argc, 1, 2);
|
||||||
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
||||||
@@ -844,7 +844,7 @@ JANET_CORE_FN(cfun_stream_read,
|
|||||||
"Read up to n bytes from a stream, suspending the current fiber until the bytes are available. "
|
"Read up to n bytes from a stream, suspending the current fiber until the bytes are available. "
|
||||||
"`n` can also be the keyword `:all` to read into the buffer until end of stream. "
|
"`n` can also be the keyword `:all` to read into the buffer until end of stream. "
|
||||||
"If less than n bytes are available (and more than 0), will push those bytes and return early. "
|
"If less than n bytes are available (and more than 0), will push those bytes and return early. "
|
||||||
"Takes an optional timeout in seconds, after which will return nil. "
|
"Takes an optional timeout in seconds, after which will raise an error. "
|
||||||
"Returns a buffer with up to n more bytes in it, or raises an error if the read failed.") {
|
"Returns a buffer with up to n more bytes in it, or raises an error if the read failed.") {
|
||||||
janet_arity(argc, 2, 4);
|
janet_arity(argc, 2, 4);
|
||||||
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
||||||
@@ -864,7 +864,7 @@ JANET_CORE_FN(cfun_stream_read,
|
|||||||
JANET_CORE_FN(cfun_stream_chunk,
|
JANET_CORE_FN(cfun_stream_chunk,
|
||||||
"(net/chunk stream nbytes &opt buf timeout)",
|
"(net/chunk stream nbytes &opt buf timeout)",
|
||||||
"Same a net/read, but will wait for all n bytes to arrive rather than return early. "
|
"Same a net/read, but will wait for all n bytes to arrive rather than return early. "
|
||||||
"Takes an optional timeout in seconds, after which will return nil.") {
|
"Takes an optional timeout in seconds, after which will raise an error.") {
|
||||||
janet_arity(argc, 2, 4);
|
janet_arity(argc, 2, 4);
|
||||||
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
||||||
janet_stream_flags(stream, JANET_STREAM_READABLE | JANET_STREAM_SOCKET);
|
janet_stream_flags(stream, JANET_STREAM_READABLE | JANET_STREAM_SOCKET);
|
||||||
@@ -878,7 +878,7 @@ JANET_CORE_FN(cfun_stream_chunk,
|
|||||||
JANET_CORE_FN(cfun_stream_recv_from,
|
JANET_CORE_FN(cfun_stream_recv_from,
|
||||||
"(net/recv-from stream nbytes buf &opt timeout)",
|
"(net/recv-from stream nbytes buf &opt timeout)",
|
||||||
"Receives data from a server stream and puts it into a buffer. Returns the socket-address the "
|
"Receives data from a server stream and puts it into a buffer. Returns the socket-address the "
|
||||||
"packet came from. Takes an optional timeout in seconds, after which will return nil.") {
|
"packet came from. Takes an optional timeout in seconds, after which will raise an error.") {
|
||||||
janet_arity(argc, 3, 4);
|
janet_arity(argc, 3, 4);
|
||||||
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
||||||
janet_stream_flags(stream, JANET_STREAM_UDPSERVER | JANET_STREAM_SOCKET);
|
janet_stream_flags(stream, JANET_STREAM_UDPSERVER | JANET_STREAM_SOCKET);
|
||||||
@@ -892,7 +892,7 @@ JANET_CORE_FN(cfun_stream_recv_from,
|
|||||||
JANET_CORE_FN(cfun_stream_write,
|
JANET_CORE_FN(cfun_stream_write,
|
||||||
"(net/write stream data &opt timeout)",
|
"(net/write stream data &opt timeout)",
|
||||||
"Write data to a stream, suspending the current fiber until the write "
|
"Write data to a stream, suspending the current fiber until the write "
|
||||||
"completes. Takes an optional timeout in seconds, after which will return nil. "
|
"completes. Takes an optional timeout in seconds, after which will raise an error. "
|
||||||
"Returns nil, or raises an error if the write failed.") {
|
"Returns nil, or raises an error if the write failed.") {
|
||||||
janet_arity(argc, 2, 3);
|
janet_arity(argc, 2, 3);
|
||||||
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
||||||
@@ -911,7 +911,7 @@ JANET_CORE_FN(cfun_stream_write,
|
|||||||
JANET_CORE_FN(cfun_stream_send_to,
|
JANET_CORE_FN(cfun_stream_send_to,
|
||||||
"(net/send-to stream dest data &opt timeout)",
|
"(net/send-to stream dest data &opt timeout)",
|
||||||
"Writes a datagram to a server stream. dest is a the destination address of the packet. "
|
"Writes a datagram to a server stream. dest is a the destination address of the packet. "
|
||||||
"Takes an optional timeout in seconds, after which will return nil. "
|
"Takes an optional timeout in seconds, after which will raise an error. "
|
||||||
"Returns stream.") {
|
"Returns stream.") {
|
||||||
janet_arity(argc, 3, 4);
|
janet_arity(argc, 3, 4);
|
||||||
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
JanetStream *stream = janet_getabstract(argv, 0, &janet_stream_type);
|
||||||
|
|||||||
@@ -27,9 +27,10 @@
|
|||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifndef JANET_REDUCED_OS
|
#ifndef JANET_REDUCED_OS
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -251,7 +252,7 @@ JANET_CORE_FN(os_exit,
|
|||||||
}
|
}
|
||||||
janet_deinit();
|
janet_deinit();
|
||||||
if (argc >= 2 && janet_truthy(argv[1])) {
|
if (argc >= 2 && janet_truthy(argv[1])) {
|
||||||
_exit(status);
|
_Exit(status);
|
||||||
} else {
|
} else {
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ static void delim_error(JanetParser *parser, size_t stack_index, char c, const c
|
|||||||
janet_buffer_push_u8(buffer, '`');
|
janet_buffer_push_u8(buffer, '`');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
janet_formatb(buffer, " opened at line %d, column %d", s->line, s->column);
|
janet_formatb(buffer, " opened at line %d, column %d", (int32_t) s->line, (int32_t) s->column);
|
||||||
}
|
}
|
||||||
parser->error = (const char *) janet_string(buffer->data, buffer->count);
|
parser->error = (const char *) janet_string(buffer->data, buffer->count);
|
||||||
parser->flag |= JANET_PARSER_GENERATED_ERROR;
|
parser->flag |= JANET_PARSER_GENERATED_ERROR;
|
||||||
|
|||||||
@@ -71,10 +71,10 @@ int janet_string_compare(const uint8_t *lhs, const uint8_t *rhs) {
|
|||||||
int janet_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash) {
|
int janet_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash) {
|
||||||
int32_t lhash = janet_string_hash(lhs);
|
int32_t lhash = janet_string_hash(lhs);
|
||||||
int32_t llen = janet_string_length(lhs);
|
int32_t llen = janet_string_length(lhs);
|
||||||
if (lhs == rhs)
|
|
||||||
return 1;
|
|
||||||
if (lhash != rhash || llen != rlen)
|
if (lhash != rhash || llen != rlen)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (lhs == rhs)
|
||||||
|
return 1;
|
||||||
return !memcmp(lhs, rhs, rlen);
|
return !memcmp(lhs, rhs, rlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,14 +117,20 @@ const char *const janet_status_names[16] = {
|
|||||||
"alive"
|
"alive"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t janet_hash_mix(uint32_t input, uint32_t more) {
|
||||||
|
uint32_t mix1 = (more + 0x9e3779b9 + (input << 6) + (input >> 2));
|
||||||
|
return input ^ (0x9e3779b9 + (mix1 << 6) + (mix1 >> 2));
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef JANET_PRF
|
#ifndef JANET_PRF
|
||||||
|
|
||||||
int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
|
int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
|
||||||
if (NULL == str) return 5381;
|
if (NULL == str || len == 0) return 5381;
|
||||||
const uint8_t *end = str + len;
|
const uint8_t *end = str + len;
|
||||||
uint32_t hash = 5381;
|
uint32_t hash = 5381;
|
||||||
while (str < end)
|
while (str < end)
|
||||||
hash = (hash << 5) + hash + *str++;
|
hash = (hash << 5) + hash + *str++;
|
||||||
|
hash = janet_hash_mix(hash, (uint32_t) len);
|
||||||
return (int32_t) hash;
|
return (int32_t) hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,11 +246,6 @@ int32_t janet_string_calchash(const uint8_t *str, int32_t len) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t janet_hash_mix(uint32_t input, uint32_t more) {
|
|
||||||
uint32_t mix1 = (more + 0x9e3779b9 + (input << 6) + (input >> 2));
|
|
||||||
return input ^ (0x9e3779b9 + (mix1 << 6) + (mix1 >> 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Computes hash of an array of values */
|
/* Computes hash of an array of values */
|
||||||
int32_t janet_array_calchash(const Janet *array, int32_t len) {
|
int32_t janet_array_calchash(const Janet *array, int32_t len) {
|
||||||
const Janet *end = array + len;
|
const Janet *end = array + len;
|
||||||
|
|||||||
@@ -1442,6 +1442,7 @@ JANET_NO_RETURN JANET_API void janet_sleep_await(double sec);
|
|||||||
/* For use inside listeners - adds a timeout to the current fiber, such that
|
/* For use inside listeners - adds a timeout to the current fiber, such that
|
||||||
* it will be resumed after sec seconds if no other event schedules the current fiber. */
|
* it will be resumed after sec seconds if no other event schedules the current fiber. */
|
||||||
JANET_API void janet_addtimeout(double sec);
|
JANET_API void janet_addtimeout(double sec);
|
||||||
|
JANET_API void janet_addtimeout_nil(double sec);
|
||||||
JANET_API void janet_ev_inc_refcount(void);
|
JANET_API void janet_ev_inc_refcount(void);
|
||||||
JANET_API void janet_ev_dec_refcount(void);
|
JANET_API void janet_ev_dec_refcount(void);
|
||||||
|
|
||||||
|
|||||||
@@ -986,4 +986,13 @@
|
|||||||
(assert (deep= (get (dyn 'a) :source-form) source))
|
(assert (deep= (get (dyn 'a) :source-form) source))
|
||||||
(setdyn *debug* nil)
|
(setdyn *debug* nil)
|
||||||
|
|
||||||
|
# issue #1516
|
||||||
|
(assert-error "assertf 1 argument" (macex '(assertf true)))
|
||||||
|
(assert (assertf true "fun message") "assertf 2 arguments")
|
||||||
|
(assert (assertf true "%s message" "mystery") "assertf 3 arguments")
|
||||||
|
(assert (assertf (not nil) "%s message" "ordinary") "assertf not nil")
|
||||||
|
(assert-error "assertf error 2" (assertf false "fun message"))
|
||||||
|
(assert-error "assertf error 3" (assertf false "%s message" "mystery"))
|
||||||
|
(assert-error "assertf error 4" (assertf nil "%s %s" "alice" "bob"))
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
|||||||
@@ -52,5 +52,7 @@
|
|||||||
(assert (= 26 (ffi/size [:char :pack :int @[:char 21]]))
|
(assert (= 26 (ffi/size [:char :pack :int @[:char 21]]))
|
||||||
"array struct size"))
|
"array struct size"))
|
||||||
|
|
||||||
(end-suite)
|
(compwhen has-ffi
|
||||||
|
(assert-error "bad struct issue #1512" (ffi/struct :void)))
|
||||||
|
|
||||||
|
(end-suite)
|
||||||
|
|||||||
Reference in New Issue
Block a user