mirror of
https://github.com/janet-lang/janet
synced 2025-11-06 10:33:03 +00:00
Compare commits
2 Commits
v1.9.1
...
appveyor-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1579509a47 | ||
|
|
d3da9e7a0d |
@@ -1,12 +0,0 @@
|
||||
image: openbsd/latest
|
||||
sources:
|
||||
- https://git.sr.ht/~bakpakin/janet
|
||||
packages:
|
||||
- meson
|
||||
tasks:
|
||||
- build: |
|
||||
cd janet
|
||||
meson setup build --buildtype=release
|
||||
cd build
|
||||
ninja
|
||||
ninja test
|
||||
@@ -1,23 +0,0 @@
|
||||
image: openbsd/latest
|
||||
sources:
|
||||
- https://git.sr.ht/~bakpakin/janet
|
||||
packages:
|
||||
- meson
|
||||
tasks:
|
||||
- build: |
|
||||
cd janet
|
||||
meson setup build --buildtype=release
|
||||
cd build
|
||||
meson configure -Dsingle_threaded=true
|
||||
meson configure -Dnanbox=false
|
||||
meson configure -Ddynamic_modules=false
|
||||
meson configure -Ddocstrings=false
|
||||
meson configure -Dnet=false
|
||||
meson configure -Dsourcemaps=false
|
||||
meson configure -Dpeg=false
|
||||
meson configure -Dassembler=false
|
||||
meson configure -Dint_types=false
|
||||
meson configure -Dtyped_arrays=false
|
||||
meson configure -Dreduced_os=true
|
||||
meson configure -Dprf=false
|
||||
ninja # will not pass tests but should build
|
||||
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,22 +1,7 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 1.9.1 - 2020-05-12
|
||||
- Add :prefix option to declare-source
|
||||
- Re-enable minimal builds with the debugger.
|
||||
- Add several flags for configuring Janet on different platforms.
|
||||
- Fix broken meson build from 1.9.0 and add meson to CI.
|
||||
- Fix compilation issue when nanboxing is disabled.
|
||||
|
||||
## 1.9.0 - 2020-05-10
|
||||
- Add `:ldflags` option to many jpm declare functions.
|
||||
- Add `errorf` to core.
|
||||
- Add `lenprefix` combinator to PEGs.
|
||||
- Add `%M`, `%m`, `%N`, and `%n` formatters to formatting functions. These are the
|
||||
same as `%Q`, `%q`, `%P`, and `%p`, but will not truncate long values.
|
||||
- Add `fiber/root`.
|
||||
- Add beta `net/` module to core for socket based networking.
|
||||
- Add the `parse` function to parse strings of source code more conveniently.
|
||||
## Unreleased - ???
|
||||
- Add `jpm rule-tree` subcommand.
|
||||
- Add `--offline` flag to jpm to force use of the cache.
|
||||
- Allow sending pointers and C functions across threads via `thread/send`.
|
||||
@@ -37,7 +22,7 @@ All notable changes to this project will be documented in this file.
|
||||
- Add os/umask
|
||||
- Add os/perm-int
|
||||
- Add os/perm-string
|
||||
- Add :int-permissions option for os/stat.
|
||||
- Add :octal-permissions option for os/stat.
|
||||
- Add `jpm repl` subcommand, as well as `post-deps` macro in project.janet files.
|
||||
- Various bug fixes.
|
||||
|
||||
|
||||
19
Makefile
19
Makefile
@@ -96,7 +96,6 @@ JANET_CORE_SOURCES=src/core/abstract.c \
|
||||
src/core/io.c \
|
||||
src/core/marsh.c \
|
||||
src/core/math.c \
|
||||
src/core/net.c \
|
||||
src/core/os.c \
|
||||
src/core/parse.c \
|
||||
src/core/peg.c \
|
||||
@@ -195,12 +194,12 @@ valgrind: $(JANET_TARGET)
|
||||
test: $(JANET_TARGET) $(TEST_PROGRAMS)
|
||||
for f in test/suite*.janet; do ./$(JANET_TARGET) "$$f" || exit; done
|
||||
for f in examples/*.janet; do ./$(JANET_TARGET) -k "$$f"; done
|
||||
./$(JANET_TARGET) -k jpm
|
||||
./$(JANET_TARGET) -k auxbin/jpm
|
||||
|
||||
valtest: $(JANET_TARGET) $(TEST_PROGRAMS)
|
||||
for f in test/suite*.janet; do $(VALGRIND_COMMAND) ./$(JANET_TARGET) "$$f" || exit; done
|
||||
for f in examples/*.janet; do ./$(JANET_TARGET) -k "$$f"; done
|
||||
$(VALGRIND_COMMAND) ./$(JANET_TARGET) -k jpm
|
||||
$(VALGRIND_COMMAND) ./$(JANET_TARGET) -k auxbin/jpm
|
||||
|
||||
callgrind: $(JANET_TARGET)
|
||||
for f in test/suite*.janet; do valgrind --tool=callgrind ./$(JANET_TARGET) "$$f" || exit; done
|
||||
@@ -214,7 +213,7 @@ dist: build/janet-dist.tar.gz
|
||||
build/janet-%.tar.gz: $(JANET_TARGET) \
|
||||
src/include/janet.h src/conf/janetconf.h \
|
||||
jpm.1 janet.1 LICENSE CONTRIBUTING.md $(JANET_LIBRARY) $(JANET_STATIC_LIBRARY) \
|
||||
build/doc.html README.md build/janet.c build/shell.c jpm
|
||||
build/doc.html README.md build/janet.c build/shell.c auxbin/jpm
|
||||
$(eval JANET_DIST_DIR = "janet-$(shell basename $*)")
|
||||
mkdir -p build/$(JANET_DIST_DIR)
|
||||
cp -r $^ build/$(JANET_DIST_DIR)/
|
||||
@@ -259,7 +258,7 @@ install: $(JANET_TARGET) build/janet.pc
|
||||
cp $(JANET_STATIC_LIBRARY) '$(DESTDIR)$(LIBDIR)/libjanet.a'
|
||||
ln -sf $(SONAME) '$(DESTDIR)$(LIBDIR)/libjanet.so'
|
||||
ln -sf libjanet.so.$(shell $(JANET_TARGET) -e '(print janet/version)') $(DESTDIR)$(LIBDIR)/$(SONAME)
|
||||
cp -rf jpm '$(DESTDIR)$(BINDIR)'
|
||||
cp -rf auxbin/* '$(DESTDIR)$(BINDIR)'
|
||||
mkdir -p '$(DESTDIR)$(MANPATH)'
|
||||
cp janet.1 '$(DESTDIR)$(MANPATH)'
|
||||
cp jpm.1 '$(DESTDIR)$(MANPATH)'
|
||||
@@ -290,7 +289,6 @@ build/janet.tmLanguage: tools/tm_lang_gen.janet $(JANET_TARGET)
|
||||
|
||||
clean:
|
||||
-rm -rf build vgcore.* callgrind.*
|
||||
-rm -rf test/install/build test/install/modpath
|
||||
|
||||
test-install:
|
||||
cd test/install \
|
||||
@@ -300,11 +298,10 @@ test-install:
|
||||
&& build/testexec \
|
||||
&& jpm --verbose quickbin testexec.janet build/testexec2 \
|
||||
&& build/testexec2 \
|
||||
&& mkdir -p modpath \
|
||||
&& jpm --verbose --testdeps --modpath=./modpath install https://github.com/janet-lang/json.git
|
||||
cd test/install && jpm --verbose --test --modpath=./modpath install https://github.com/janet-lang/jhydro.git
|
||||
cd test/install && jpm --verbose --test --modpath=./modpath install https://github.com/janet-lang/path.git
|
||||
cd test/install && jpm --verbose --test --modpath=./modpath install https://github.com/janet-lang/argparse.git
|
||||
&& jpm --verbose --testdeps --modpath=. install https://github.com/janet-lang/json.git
|
||||
cd test/install && jpm --verbose --test --modpath=. install https://github.com/janet-lang/jhydro.git
|
||||
cd test/install && jpm --verbose --test --modpath=. install https://github.com/janet-lang/path.git
|
||||
cd test/install && jpm --verbose --test --modpath=. install https://github.com/janet-lang/argparse.git
|
||||
|
||||
.PHONY: clean install repl debug valgrind test \
|
||||
valtest emscripten dist uninstall docs grammar format
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
[](https://travis-ci.org/janet-lang/janet)
|
||||
[](https://builds.sr.ht/~bakpakin/janet/freebsd.yml?)
|
||||
[](https://builds.sr.ht/~bakpakin/janet/openbsd.yml?)
|
||||
[](https://builds.sr.ht/~bakpakin/janet/meson.yml?)
|
||||
[](https://builds.sr.ht/~bakpakin/janet/meson_min.yml?)
|
||||
|
||||
<img src="https://raw.githubusercontent.com/janet-lang/janet/master/assets/janet-w200.png" alt="Janet logo" width=200 align="left">
|
||||
|
||||
|
||||
14
appveyor.yml
14
appveyor.yml
@@ -4,6 +4,7 @@ image:
|
||||
- Visual Studio 2019
|
||||
configuration:
|
||||
- Release
|
||||
- Debug
|
||||
platform:
|
||||
- x64
|
||||
- x86
|
||||
@@ -13,24 +14,23 @@ environment:
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
# skip unsupported combinations
|
||||
init:
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %platform%
|
||||
|
||||
install:
|
||||
- set JANET_BUILD=%appveyor_repo_commit:~0,7%
|
||||
before_build:
|
||||
- choco install nsis -y -pre --version 3.05
|
||||
# Replace makensis.exe and files with special long string build. This should
|
||||
# prevent issues when setting PATH during installation.
|
||||
- 7z e "tools\nsis-3.05-strlen_8192.zip" -o"C:\Program Files (x86)\NSIS\" -y
|
||||
|
||||
build_script:
|
||||
- set JANET_BUILD=%appveyor_repo_commit:~0,7%
|
||||
- build_win all
|
||||
|
||||
test_script:
|
||||
- refreshenv
|
||||
# We need to reload vcvars after refreshing
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" %platform%
|
||||
- build_win test-install
|
||||
- set janet_outname=%appveyor_repo_tag_name%
|
||||
- if "%janet_outname%"=="" set /P janet_outname=<build\version.txt
|
||||
build: off
|
||||
|
||||
artifacts:
|
||||
- name: janet.c
|
||||
|
||||
656
jpm → auxbin/jpm
656
jpm → auxbin/jpm
@@ -15,145 +15,6 @@
|
||||
(def- statext (if is-win ".static.lib" ".a"))
|
||||
(def- absprefix (if is-win "C:\\" "/"))
|
||||
|
||||
#
|
||||
# Defaults
|
||||
#
|
||||
|
||||
(def- exe-dir
|
||||
"Directory containing jpm script"
|
||||
(do
|
||||
(def exe (dyn :current-file))
|
||||
(def i (last (string/find-all sep exe)))
|
||||
(slice exe 0 i)))
|
||||
|
||||
(def JANET_MODPATH (or (os/getenv "JANET_MODPATH") (dyn :syspath)))
|
||||
|
||||
# Default based on janet binary location
|
||||
(def JANET_HEADERPATH (or (os/getenv "JANET_HEADERPATH")
|
||||
(string exe-dir "/../include/janet")))
|
||||
(def JANET_LIBPATH (or (os/getenv "JANET_LIBPATH")
|
||||
(string exe-dir "/../lib")))
|
||||
|
||||
# We want setting JANET_PATH to contain installed binaries. However, it is convenient
|
||||
# to have globally installed binaries got to the same place as jpm itself, which is on
|
||||
# the $PATH.
|
||||
(def JANET_BINPATH (or (os/getenv "JANET_BINPATH")
|
||||
(if-let [mp (os/getenv "JANET_MODPATH")] (string mp "/bin"))
|
||||
(if-let [mp (os/getenv "JANET_PATH")] (string mp "/bin"))
|
||||
exe-dir))
|
||||
|
||||
#
|
||||
# Utilities
|
||||
#
|
||||
|
||||
(defn find-manifest-dir
|
||||
"Get the path to the directory containing manifests for installed
|
||||
packages."
|
||||
[]
|
||||
(string (dyn :modpath JANET_MODPATH) sep ".manifests"))
|
||||
|
||||
(defn find-manifest
|
||||
"Get the full path of a manifest file given a package name."
|
||||
[name]
|
||||
(string (find-manifest-dir) sep name ".jdn"))
|
||||
|
||||
(defn find-cache
|
||||
"Return the path to the global cache."
|
||||
[]
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
(string path sep ".cache"))
|
||||
|
||||
(defn rm
|
||||
"Remove a directory and all sub directories."
|
||||
[path]
|
||||
(if (= (os/lstat path :mode) :directory)
|
||||
(do
|
||||
(each subpath (os/dir path)
|
||||
(rm (string path sep subpath)))
|
||||
(os/rmdir path))
|
||||
(os/rm path)))
|
||||
|
||||
(defn- rimraf
|
||||
"Hard delete directory tree"
|
||||
[path]
|
||||
(if is-win
|
||||
# windows get rid of read-only files
|
||||
(os/shell `rmdir /S /Q "` path `"`))
|
||||
(rm path))
|
||||
|
||||
(defn clear-cache
|
||||
"Clear the global git cache."
|
||||
[]
|
||||
(def cache (find-cache))
|
||||
(print "clearing " cache "...")
|
||||
(rimraf cache))
|
||||
|
||||
(def- default-pkglist
|
||||
(or (os/getenv "JANET_PKGLIST") "https://github.com/janet-lang/pkgs.git"))
|
||||
|
||||
(defn- pslurp
|
||||
"Like slurp, but with file/popen instead file/open. Also trims output"
|
||||
[cmd]
|
||||
(string/trim (with [f (file/popen cmd)] (:read f :all))))
|
||||
|
||||
(def- path-splitter
|
||||
"split paths on / and \\."
|
||||
(peg/compile ~(any (* '(any (if-not (set `\/`) 1)) (+ (set `\/`) -1)))))
|
||||
|
||||
(defn create-dirs
|
||||
"Create all directories needed for a file (mkdir -p)."
|
||||
[dest]
|
||||
(def segs (peg/match path-splitter dest))
|
||||
(for i 1 (length segs)
|
||||
(def path (string/join (slice segs 0 i) sep))
|
||||
(unless (empty? path) (os/mkdir path))))
|
||||
|
||||
(def- filepath-replacer
|
||||
"Convert url with potential bad characters into a file path element."
|
||||
(peg/compile ~(% (any (+ (/ '(set "<>:\"/\\|?*") "_") '1)))))
|
||||
|
||||
(defn filepath-replace
|
||||
"Remove special characters from a string or path
|
||||
to make it into a path segment."
|
||||
[repo]
|
||||
(get (peg/match filepath-replacer repo) 0))
|
||||
|
||||
(defn shell
|
||||
"Do a shell command"
|
||||
[& args]
|
||||
(if (dyn :verbose)
|
||||
(print ;(interpose " " args)))
|
||||
(def res (os/execute args :p))
|
||||
(unless (zero? res)
|
||||
(error (string "command exited with status " res))))
|
||||
|
||||
(defn copy
|
||||
"Copy a file or directory recursively from one location to another."
|
||||
[src dest]
|
||||
(print "copying " src " to " dest "...")
|
||||
(if is-win
|
||||
(let [end (last (peg/match path-splitter src))
|
||||
isdir (= (os/stat src :mode) :directory)]
|
||||
(shell "xcopy" src (if isdir (string dest "\\" end) dest) "/y" "/s" "/e" "/i"))
|
||||
(shell "cp" "-rf" src dest)))
|
||||
|
||||
(defn mkdir
|
||||
"Create a directory if it doesn't exist. If it does exist, do nothing.
|
||||
If we can't create it, give a friendly error. Return true if created, false if
|
||||
existing. Throw an error if we can't create it."
|
||||
[dir]
|
||||
(os/mkdir dir))
|
||||
|
||||
(defn- abspath
|
||||
"Create an absolute path. Does not resolve . and .. (useful for
|
||||
generating entries in install manifest file)."
|
||||
[path]
|
||||
(if (if is-win
|
||||
(peg/match '(+ "\\" (* (range "AZ" "az") ":\\")) path)
|
||||
(string/has-prefix? "/" path))
|
||||
path
|
||||
(string (os/cwd) sep path)))
|
||||
|
||||
#
|
||||
# Rule Engine
|
||||
#
|
||||
@@ -239,6 +100,91 @@
|
||||
(each thunk thunks (thunk)))
|
||||
(unless phony target))
|
||||
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
|
||||
(def- exe-dir
|
||||
"Directory containing jpm script"
|
||||
(do
|
||||
(def exe (dyn :current-file))
|
||||
(def i (last (string/find-all sep exe)))
|
||||
(slice exe 0 i)))
|
||||
|
||||
(def JANET_MODPATH (or (os/getenv "JANET_MODPATH") (dyn :syspath)))
|
||||
|
||||
# Default based on janet binary location
|
||||
(def JANET_HEADERPATH (or (os/getenv "JANET_HEADERPATH")
|
||||
(string exe-dir "/../include/janet")))
|
||||
(def JANET_LIBPATH (or (os/getenv "JANET_LIBPATH")
|
||||
(string exe-dir "/../lib")))
|
||||
|
||||
(def JANET_BINPATH (or (os/getenv "JANET_BINPATH")
|
||||
(string (dyn :syspath) "/bin")))
|
||||
|
||||
#
|
||||
# Compilation Defaults
|
||||
#
|
||||
|
||||
(def default-compiler (or (os/getenv "CC") (if is-win "cl.exe" "cc")))
|
||||
(def default-linker (or (os/getenv "CC") (if is-win "link.exe" "cc")))
|
||||
(def default-archiver (or (os/getenv "AR") (if is-win "lib.exe" "ar")))
|
||||
|
||||
# Detect threads
|
||||
(def env (fiber/getenv (fiber/current)))
|
||||
(def threads? (not (not (env 'thread/new))))
|
||||
|
||||
# Default flags for natives, but not required
|
||||
(def default-lflags (if is-win ["/nologo"] []))
|
||||
(def default-cflags
|
||||
(if is-win
|
||||
["/nologo" "/MD"]
|
||||
["-std=c99" "-Wall" "-Wextra"]))
|
||||
|
||||
# Link to pthreads
|
||||
(def- thread-flags (if is-win [] (if threads? ["-lpthread"] [])))
|
||||
|
||||
# Required flags for dynamic libraries. These
|
||||
# are used no matter what for dynamic libraries.
|
||||
(def- dynamic-cflags
|
||||
(if is-win
|
||||
["/LD"]
|
||||
["-fPIC"]))
|
||||
(def- dynamic-lflags
|
||||
(if is-win
|
||||
["/DLL" ;thread-flags]
|
||||
(if is-mac
|
||||
["-shared" "-undefined" "dynamic_lookup" ;thread-flags]
|
||||
["-shared" ;thread-flags])))
|
||||
|
||||
(defn- opt
|
||||
"Get an option, allowing overrides via dynamic bindings AND some
|
||||
default value dflt if no dynamic binding is set."
|
||||
[opts key dflt]
|
||||
(def ret (or (opts key) (dyn key dflt)))
|
||||
(if (= nil ret)
|
||||
(error (string "option :" key " not set")))
|
||||
ret)
|
||||
|
||||
(defn check-cc
|
||||
"Ensure we have a c compiler."
|
||||
[]
|
||||
(if is-win
|
||||
(do
|
||||
(if (os/getenv "INCLUDE") (break))
|
||||
(error "Run jpm inside a Developer Command Prompt.
|
||||
jpm needs a c compiler to compile natives. You can install the MSVC compiler from
|
||||
microsoft.com"))
|
||||
(do)))
|
||||
|
||||
(defn create-dirs
|
||||
"Create all directories needed for a file (mkdir -p)."
|
||||
[dest]
|
||||
(def segs (string/split "/" dest))
|
||||
(for i 1 (length segs)
|
||||
(def path (string/join (slice segs 0 i) "/"))
|
||||
(unless (empty? path) (os/mkdir path))))
|
||||
|
||||
#
|
||||
# Importing a file
|
||||
#
|
||||
@@ -258,7 +204,7 @@
|
||||
(def env (make-env))
|
||||
(put env :jpm-no-deps no-deps)
|
||||
(loop [k :keys _env :when (symbol? k)]
|
||||
(unless ((_env k) :private) (put env k (_env k))))
|
||||
(unless ((_env k) :private) (put env k (_env k))))
|
||||
env)
|
||||
|
||||
(defn require-jpm
|
||||
@@ -291,69 +237,62 @@
|
||||
~',(reduce |(eval $1) nil body)))
|
||||
|
||||
#
|
||||
# C Compilation
|
||||
# OS and shell helpers
|
||||
#
|
||||
|
||||
(def default-compiler (or (os/getenv "CC") (if is-win "cl.exe" "cc")))
|
||||
(def default-linker (or (os/getenv "CC") (if is-win "link.exe" "cc")))
|
||||
(def default-archiver (or (os/getenv "AR") (if is-win "lib.exe" "ar")))
|
||||
(def- path-splitter
|
||||
"split paths on / and \\."
|
||||
(peg/compile ~(any (* '(any (if-not (set `\/`) 1)) (+ (set `\/`) -1)))))
|
||||
|
||||
# Detect threads
|
||||
(def env (fiber/getenv (fiber/current)))
|
||||
(def threads? (not (not (env 'thread/new))))
|
||||
(def- filepath-replacer
|
||||
"Convert url with potential bad characters into a file path element."
|
||||
(peg/compile ~(% (any (+ (/ '(set "<>:\"/\\|?*") "_") '1)))))
|
||||
|
||||
# Default libraries to link
|
||||
(def- thread-flags
|
||||
(if is-win []
|
||||
(if threads? ["-lpthread"] [])))
|
||||
(defn filepath-replace
|
||||
"Remove special characters from a string or path
|
||||
to make it into a path segment."
|
||||
[repo]
|
||||
(get (peg/match filepath-replacer repo) 0))
|
||||
|
||||
# lflags needed for the janet binary.
|
||||
(def janet-lflags
|
||||
(case (os/which)
|
||||
:macos ["-ldl" "-lm" ;thread-flags]
|
||||
:windows [;thread-flags]
|
||||
:linux ["-lm" "-ldl" "-lrt" ;thread-flags]
|
||||
["-lm" ;thread-flags]))
|
||||
(defn shell
|
||||
"Do a shell command"
|
||||
[& args]
|
||||
(if (dyn :verbose)
|
||||
(print ;(interpose " " args)))
|
||||
(def res (os/execute args :p))
|
||||
(unless (zero? res)
|
||||
(error (string "command exited with status " res))))
|
||||
|
||||
# Default flags for natives, but not required
|
||||
(def default-lflags (if is-win ["/nologo"] []))
|
||||
(def default-cflags
|
||||
(if is-win
|
||||
["/nologo" "/MD"]
|
||||
["-std=c99" "-Wall" "-Wextra"]))
|
||||
|
||||
# Required flags for dynamic libraries. These
|
||||
# are used no matter what for dynamic libraries.
|
||||
(def- dynamic-cflags
|
||||
(if is-win
|
||||
["/LD"]
|
||||
["-fPIC"]))
|
||||
(def- dynamic-lflags
|
||||
(if is-win
|
||||
["/DLL" ;thread-flags]
|
||||
(if is-mac
|
||||
["-shared" "-undefined" "dynamic_lookup" ;thread-flags]
|
||||
["-shared" ;thread-flags])))
|
||||
|
||||
(defn- opt
|
||||
"Get an option, allowing overrides via dynamic bindings AND some
|
||||
default value dflt if no dynamic binding is set."
|
||||
[opts key dflt]
|
||||
(def ret (or (opts key) (dyn key dflt)))
|
||||
(if (= nil ret)
|
||||
(error (string "option :" key " not set")))
|
||||
ret)
|
||||
|
||||
(defn check-cc
|
||||
"Ensure we have a c compiler."
|
||||
[]
|
||||
(if is-win
|
||||
(defn rm
|
||||
"Remove a directory and all sub directories."
|
||||
[path]
|
||||
(if (= (os/lstat path :mode) :directory)
|
||||
(do
|
||||
(if (os/getenv "INCLUDE") (break))
|
||||
(error "Run jpm inside a Developer Command Prompt.
|
||||
jpm needs a c compiler to compile natives. You can install the MSVC compiler from
|
||||
microsoft.com"))
|
||||
(do)))
|
||||
(each subpath (os/dir path)
|
||||
(rm (string path sep subpath)))
|
||||
(os/rmdir path))
|
||||
(os/rm path)))
|
||||
|
||||
(defn copy
|
||||
"Copy a file or directory recursively from one location to another."
|
||||
[src dest]
|
||||
(print "copying " src " to " dest "...")
|
||||
(if is-win
|
||||
(let [end (last (peg/match path-splitter src))
|
||||
isdir (= (os/stat src :mode) :directory)]
|
||||
(shell "xcopy" src (if isdir (string dest "\\" end) dest) "/y" "/s" "/e" "/i"))
|
||||
(shell "cp" "-rf" src dest)))
|
||||
|
||||
(defn mkdir
|
||||
"Create a directory if it doesn't exist. If it does exist, do nothing.
|
||||
If we can't create it, give a friendly error. Return true if created, false if
|
||||
existing. Throw an error if we can't create it."
|
||||
[dir]
|
||||
(os/mkdir dir))
|
||||
|
||||
#
|
||||
# C Compilation
|
||||
#
|
||||
|
||||
(defn- embed-name
|
||||
"Rename a janet symbol for embedding."
|
||||
@@ -440,14 +379,13 @@
|
||||
(def cflags (getcflags opts))
|
||||
(def lflags [;(opt opts :lflags default-lflags)
|
||||
;(if (opts :static) [] dynamic-lflags)])
|
||||
(def ldflags [;(opt opts :ldflags [])])
|
||||
(rule target objects
|
||||
(check-cc)
|
||||
(print "linking " target "...")
|
||||
(create-dirs target)
|
||||
(if is-win
|
||||
(shell linker ;ldflags (string "/OUT:" target) ;objects (win-import-library) ;lflags)
|
||||
(shell linker ;cflags ;ldflags `-o` target ;objects ;lflags))))
|
||||
(shell linker ;lflags (string "/OUT:" target) ;objects (win-import-library))
|
||||
(shell linker ;cflags `-o` target ;objects ;lflags))))
|
||||
|
||||
(defn- archive-c
|
||||
"Link object files together to make a static library."
|
||||
@@ -496,78 +434,6 @@
|
||||
[path]
|
||||
(string (string/slice path 0 (- -1 (length modext))) statext))
|
||||
|
||||
(defn- make-bin-source
|
||||
[declarations lookup-into-invocations]
|
||||
(string
|
||||
declarations
|
||||
```
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
janet_init();
|
||||
|
||||
/* Get core env */
|
||||
JanetTable *env = janet_core_env(NULL);
|
||||
JanetTable *lookup = janet_env_lookup(env);
|
||||
JanetTable *temptab;
|
||||
int handle = janet_gclock();
|
||||
|
||||
/* Load natives into unmarshalling dictionary */
|
||||
|
||||
```
|
||||
lookup-into-invocations
|
||||
```
|
||||
/* Unmarshal bytecode */
|
||||
Janet marsh_out = janet_unmarshal(
|
||||
janet_payload_image_embed,
|
||||
janet_payload_image_embed_size,
|
||||
0,
|
||||
lookup,
|
||||
NULL);
|
||||
|
||||
/* Verify the marshalled object is a function */
|
||||
if (!janet_checktype(marsh_out, JANET_FUNCTION)) {
|
||||
fprintf(stderr, "invalid bytecode image - expected function.");
|
||||
return 1;
|
||||
}
|
||||
JanetFunction *jfunc = janet_unwrap_function(marsh_out);
|
||||
|
||||
/* Check arity */
|
||||
janet_arity(argc, jfunc->def->min_arity, jfunc->def->max_arity);
|
||||
|
||||
/* Collect command line arguments */
|
||||
JanetArray *args = janet_array(argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
janet_array_push(args, janet_cstringv(argv[i]));
|
||||
}
|
||||
|
||||
/* Create enviornment */
|
||||
temptab = janet_table(0);
|
||||
temptab = env;
|
||||
janet_table_put(temptab, janet_ckeywordv("args"), janet_wrap_array(args));
|
||||
janet_gcroot(janet_wrap_table(temptab));
|
||||
|
||||
/* Unlock GC */
|
||||
janet_gcunlock(handle);
|
||||
|
||||
/* Run everything */
|
||||
JanetFiber *fiber = janet_fiber(jfunc, 64, argc, argc ? args->data : NULL);
|
||||
fiber->env = temptab;
|
||||
Janet out;
|
||||
JanetSignal result = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||
if (result != JANET_SIGNAL_OK && result != JANET_SIGNAL_EVENT) {
|
||||
janet_stacktrace(fiber, out);
|
||||
janet_deinit();
|
||||
return result;
|
||||
}
|
||||
#ifdef JANET_NET
|
||||
janet_loop();
|
||||
#endif
|
||||
janet_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
```))
|
||||
|
||||
(defn- create-executable
|
||||
"Links an image with libjanet.a (or .lib) to produce an
|
||||
executable. Also will try to link native modules into the
|
||||
@@ -584,7 +450,6 @@ int main(int argc, const char **argv) {
|
||||
(def entry-env (dofile source))
|
||||
(def main ((entry-env 'main) :value))
|
||||
(def dep-lflags @[])
|
||||
(def dep-ldflags @[])
|
||||
|
||||
# Create marshalling dictionary
|
||||
(def mdict (invert (env-lookup root-env)))
|
||||
@@ -618,35 +483,142 @@ int main(int argc, const char **argv) {
|
||||
"\", 0);\n\n")
|
||||
(when-let [lfs (meta :lflags)]
|
||||
(array/concat dep-lflags lfs))
|
||||
(when-let [lfs (meta :ldflags)]
|
||||
(array/concat dep-ldflags lfs))
|
||||
(buffer/push-string declarations
|
||||
"extern void "
|
||||
(meta :static-entry)
|
||||
"(JanetTable *);\n"))
|
||||
|
||||
|
||||
# Build image
|
||||
(def image (marshal main mdict))
|
||||
# Make image byte buffer
|
||||
(create-buffer-c-impl image cimage_dest "janet_payload_image")
|
||||
# Append main function
|
||||
(spit cimage_dest (make-bin-source declarations lookup-into-invocations) :ab)
|
||||
# Compile and link final exectable
|
||||
(do
|
||||
(def cc (opt opts :compiler default-compiler))
|
||||
(def ldflags [;dep-ldflags ;(opt opts :ldflags [])])
|
||||
(def lflags [;static-libs (libjanet) ;dep-lflags ;(opt opts :lflags default-lflags) ;janet-lflags])
|
||||
(def cflags (getcflags opts))
|
||||
(def defines (make-defines (opt opts :defines {})))
|
||||
(print "compiling and linking " dest "...")
|
||||
(if is-win
|
||||
(shell cc ;cflags ;ldflags cimage_dest ;lflags `/link` (string "/OUT:" dest))
|
||||
(shell cc ;cflags ;ldflags `-o` dest cimage_dest ;lflags)))))
|
||||
(spit cimage_dest (string
|
||||
"\n"
|
||||
declarations
|
||||
```
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
janet_init();
|
||||
|
||||
/* Get core env */
|
||||
JanetTable *env = janet_core_env(NULL);
|
||||
JanetTable *lookup = janet_env_lookup(env);
|
||||
JanetTable *temptab;
|
||||
int handle = janet_gclock();
|
||||
|
||||
/* Load natives into unmarshalling dictionary */
|
||||
|
||||
```
|
||||
lookup-into-invocations
|
||||
```
|
||||
/* Unmarshal bytecode */
|
||||
Janet marsh_out = janet_unmarshal(
|
||||
janet_payload_image_embed,
|
||||
janet_payload_image_embed_size,
|
||||
0,
|
||||
lookup,
|
||||
NULL);
|
||||
|
||||
/* Verify the marshalled object is a function */
|
||||
if (!janet_checktype(marsh_out, JANET_FUNCTION)) {
|
||||
fprintf(stderr, "invalid bytecode image - expected function.");
|
||||
return 1;
|
||||
}
|
||||
JanetFunction *jfunc = janet_unwrap_function(marsh_out);
|
||||
|
||||
/* Check arity */
|
||||
janet_arity(argc, jfunc->def->min_arity, jfunc->def->max_arity);
|
||||
|
||||
/* Collect command line arguments */
|
||||
JanetArray *args = janet_array(argc);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
janet_array_push(args, janet_cstringv(argv[i]));
|
||||
}
|
||||
|
||||
/* Create enviornment */
|
||||
temptab = janet_table(0);
|
||||
temptab = env;
|
||||
janet_table_put(temptab, janet_ckeywordv("args"), janet_wrap_array(args));
|
||||
janet_gcroot(janet_wrap_table(temptab));
|
||||
|
||||
/* Unlock GC */
|
||||
janet_gcunlock(handle);
|
||||
|
||||
/* Run everything */
|
||||
JanetFiber *fiber = janet_fiber(jfunc, 64, argc, argc ? args->data : NULL);
|
||||
fiber->env = temptab;
|
||||
Janet out;
|
||||
JanetSignal result = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||
if (result) {
|
||||
janet_stacktrace(fiber, out);
|
||||
janet_deinit();
|
||||
return result;
|
||||
}
|
||||
janet_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
```) :ab)
|
||||
|
||||
# Compile and link final exectable
|
||||
(do
|
||||
(def extra-lflags (case (os/which)
|
||||
:macos ["-ldl" "-lm" ;thread-flags]
|
||||
:windows [;thread-flags]
|
||||
:linux ["-lm" "-ldl" "-lrt" ;thread-flags]
|
||||
#default
|
||||
["-lm" ;thread-flags]))
|
||||
(def cc (opt opts :compiler default-compiler))
|
||||
(def lflags [;dep-lflags ;(opt opts :lflags default-lflags) ;extra-lflags])
|
||||
(def cflags (getcflags opts))
|
||||
(def defines (make-defines (opt opts :defines {})))
|
||||
(print "compiling and linking " dest "...")
|
||||
(if is-win
|
||||
(shell cc ;cflags cimage_dest ;static-libs (libjanet) ;lflags `/link` (string "/OUT:" dest))
|
||||
(shell cc ;cflags `-o` dest cimage_dest ;static-libs (libjanet) ;lflags)))))
|
||||
|
||||
(defn- abspath
|
||||
"Create an absolute path. Does not resolve . and .. (useful for
|
||||
generating entries in install manifest file)."
|
||||
[path]
|
||||
(if (if is-win
|
||||
(peg/match '(+ "\\" (* (range "AZ" "az") ":\\")) path)
|
||||
(string/has-prefix? "/" path))
|
||||
path
|
||||
(string (os/cwd) sep path)))
|
||||
|
||||
#
|
||||
# Installation and Dependencies
|
||||
# Public utilities
|
||||
#
|
||||
|
||||
(defn parse
|
||||
"Read a string of Janet source and parse out the first expression."
|
||||
[src]
|
||||
(let [p (parser/new)]
|
||||
(:consume p src)
|
||||
(if (= :error (:status p))
|
||||
(error (string "Could not parse: " (parser/error p))))
|
||||
(:produce p)))
|
||||
|
||||
(defn find-manifest-dir
|
||||
"Get the path to the directory containing manifests for installed
|
||||
packages."
|
||||
[]
|
||||
(string (dyn :modpath JANET_MODPATH) sep ".manifests"))
|
||||
|
||||
(defn find-manifest
|
||||
"Get the full path of a manifest file given a package name."
|
||||
[name]
|
||||
(string (find-manifest-dir) sep name ".jdn"))
|
||||
|
||||
(defn find-cache
|
||||
"Return the path to the global cache."
|
||||
[]
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
(string path sep ".cache"))
|
||||
|
||||
(defn uninstall
|
||||
"Uninstall bundle named name"
|
||||
[name]
|
||||
@@ -660,6 +632,23 @@ int main(int argc, const char **argv) {
|
||||
(rm manifest)
|
||||
(print "Uninstalled.")))
|
||||
|
||||
(defn- rimraf
|
||||
"Hard delete directory tree"
|
||||
[path]
|
||||
(if is-win
|
||||
# windows get rid of read-only files
|
||||
(os/shell `rmdir /S /Q "` path `"`))
|
||||
(rm path))
|
||||
|
||||
(defn clear-cache
|
||||
"Clear the global git cache."
|
||||
[]
|
||||
(def cache (find-cache))
|
||||
(print "clearing " cache "...")
|
||||
(rimraf cache))
|
||||
|
||||
(def- default-pkglist (or (os/getenv "JANET_PKGLIST") "https://github.com/janet-lang/pkgs.git"))
|
||||
|
||||
(defn install-git
|
||||
"Install a bundle from git. If the bundle is already installed, the bundle
|
||||
is reinistalled (but not rebuilt if artifacts are cached)."
|
||||
@@ -674,9 +663,9 @@ int main(int argc, const char **argv) {
|
||||
(unless (string/find ":" repo)
|
||||
(def pkgs
|
||||
(try (require "pkgs")
|
||||
([err f]
|
||||
(install-git (dyn :pkglist default-pkglist))
|
||||
(require "pkgs"))))
|
||||
([err f]
|
||||
(install-git (dyn :pkglist default-pkglist))
|
||||
(require "pkgs"))))
|
||||
(def next-repo (get-in pkgs ['packages :value (symbol repo)]))
|
||||
(unless next-repo
|
||||
(error (string "package " repo " not found.")))
|
||||
@@ -693,11 +682,11 @@ int main(int argc, const char **argv) {
|
||||
(error (string "did not find cached repo for dependency " repo))
|
||||
(set fresh true))
|
||||
(when (mkdir module-dir)
|
||||
(set fresh true)
|
||||
(print "cloning repository " repo " to " module-dir)
|
||||
(unless (zero? (os/execute ["git" "clone" repo module-dir] :p))
|
||||
(rimraf module-dir)
|
||||
(error (string "could not clone git dependency " repo)))))
|
||||
(set fresh true)
|
||||
(print "cloning repository " repo " to " module-dir)
|
||||
(unless (zero? (os/execute ["git" "clone" repo module-dir] :p))
|
||||
(rimraf module-dir)
|
||||
(error (string "could not clone git dependency " repo)))))
|
||||
(def olddir (os/cwd))
|
||||
(try
|
||||
(with-dyns [:rules @{}
|
||||
@@ -730,6 +719,11 @@ int main(int argc, const char **argv) {
|
||||
(mkdir destdir)
|
||||
(copy src destdir)))
|
||||
|
||||
(defn- pslurp
|
||||
"Like slurp, but with file/popen instead file/open. Also trims output"
|
||||
[cmd]
|
||||
(string/trim (with [f (file/popen cmd)] (:read f :all))))
|
||||
|
||||
(defn- make-lockfile
|
||||
[&opt filename]
|
||||
(default filename "lockfile.jdn")
|
||||
@@ -788,12 +782,12 @@ int main(int argc, const char **argv) {
|
||||
(compile-c opts src (out-path src ".c" objext)))
|
||||
(def objects (map (fn [path] (out-path path ".c" objext)) sources))
|
||||
(when-let [embedded (opts :embedded)]
|
||||
(loop [src :in embedded]
|
||||
(def c-src (out-path src ".janet" ".janet.c"))
|
||||
(def o-src (out-path src ".janet" (if is-win ".janet.obj" ".janet.o")))
|
||||
(array/push objects o-src)
|
||||
(create-buffer-c src c-src (embed-name src))
|
||||
(compile-c opts c-src o-src)))
|
||||
(loop [src :in embedded]
|
||||
(def c-src (out-path src ".janet" ".janet.c"))
|
||||
(def o-src (out-path src ".janet" (if is-win ".janet.obj" ".janet.o")))
|
||||
(array/push objects o-src)
|
||||
(create-buffer-c src c-src (embed-name src))
|
||||
(compile-c opts c-src o-src)))
|
||||
(link-c opts lname ;objects)
|
||||
(add-dep "build" lname)
|
||||
(install-rule lname path)
|
||||
@@ -807,7 +801,6 @@ int main(int argc, const char **argv) {
|
||||
"# Metadata for static library %s\n\n%.20p"
|
||||
(string name statext)
|
||||
{:static-entry ename
|
||||
:ldflags ~',(opts :ldflags)
|
||||
:lflags ~',(opts :lflags)})))
|
||||
(add-dep "build" metaname)
|
||||
(install-rule metaname path)
|
||||
@@ -822,24 +815,21 @@ int main(int argc, const char **argv) {
|
||||
(compile-c opts src (out-path src ".c" sobjext) true))
|
||||
(def sobjects (map (fn [path] (out-path path ".c" sobjext)) sources))
|
||||
(when-let [embedded (opts :embedded)]
|
||||
(loop [src :in embedded]
|
||||
(def c-src (out-path src ".janet" ".janet.c"))
|
||||
(def o-src (out-path src ".janet" sjobjext))
|
||||
(array/push sobjects o-src)
|
||||
# Buffer c-src is already declared by dynamic module
|
||||
(compile-c opts c-src o-src true)))
|
||||
(loop [src :in embedded]
|
||||
(def c-src (out-path src ".janet" ".janet.c"))
|
||||
(def o-src (out-path src ".janet" sjobjext))
|
||||
(array/push sobjects o-src)
|
||||
# Buffer c-src is already declared by dynamic module
|
||||
(compile-c opts c-src o-src true)))
|
||||
(archive-c opts sname ;sobjects)
|
||||
(add-dep "build" sname)
|
||||
(install-rule sname path)))
|
||||
|
||||
(defn declare-source
|
||||
"Create Janet modules. This does not actually build the module(s),
|
||||
but registers them for packaging and installation. :source should be an
|
||||
array of files and directores to copy into JANET_MODPATH or JANET_PATH.
|
||||
:prefix can optionally be given to modify the destination path to be
|
||||
(string JANET_PATH prefix source)."
|
||||
[&keys {:source sources :prefix prefix}]
|
||||
(def path (string (dyn :modpath JANET_MODPATH) (or prefix "")))
|
||||
"Create a Janet modules. This does not actually build the module(s),
|
||||
but registers it for packaging and installation."
|
||||
[&keys {:source sources}]
|
||||
(def path (dyn :modpath JANET_MODPATH))
|
||||
(if (bytes? sources)
|
||||
(install-rule sources path)
|
||||
(each s sources
|
||||
@@ -856,10 +846,10 @@ int main(int argc, const char **argv) {
|
||||
is marshalled into bytecode which is then embedded in a final executable for distribution.\n\n
|
||||
This executable can be installed as well to the --binpath given."
|
||||
[&keys {:install install :name name :entry entry :headers headers
|
||||
:cflags cflags :lflags lflags :deps deps :ldflags ldflags}]
|
||||
:cflags cflags :lflags lflags :deps deps}]
|
||||
(def name (if is-win (string name ".exe") name))
|
||||
(def dest (string "build" sep name))
|
||||
(create-executable @{:cflags cflags :lflags lflags :ldflags ldflags} entry dest)
|
||||
(create-executable @{:cflags cflags :lflags lflags} entry dest)
|
||||
(add-dep "build" dest)
|
||||
(when headers
|
||||
(each h headers (add-dep dest h)))
|
||||
@@ -895,8 +885,8 @@ int main(int argc, const char **argv) {
|
||||
(eachp [i d] (sorted root-deps)
|
||||
(print-rule-tree
|
||||
d (dec depth)
|
||||
(string prefix-part (if (= i l) " └─" " ├─"))
|
||||
(string prefix-part (if (= i l) " " " │ ")))))))
|
||||
(string prefix-part (if (= i l) " └─" " ├─"))
|
||||
(string prefix-part (if (= i l) " " " │ ")))))))
|
||||
|
||||
(defn declare-archive
|
||||
"Build a janet archive. This is a file that bundles together many janet
|
||||
@@ -999,10 +989,10 @@ on a project, or from anywhere to do operations on the global module cache (modp
|
||||
Subcommands are:
|
||||
build : build all artifacts
|
||||
help : show this help text
|
||||
install (repo or name)... : install artifacts. If a repo is given, install the contents of that
|
||||
install (repo or name) : install artifacts. If a repo is given, install the contents of that
|
||||
git repository, assuming that the repository is a jpm project. If not, build
|
||||
and install the current project.
|
||||
uninstall (module)... : uninstall a module. If no module is given, uninstall the module
|
||||
uninstall (module) : uninstall a module. If no module is given, uninstall the module
|
||||
defined by the current directory.
|
||||
show-paths : prints the paths that will be used to install things.
|
||||
clean : remove any generated files or artifacts
|
||||
@@ -1066,20 +1056,20 @@ Flags are:
|
||||
(local-rule "clean"))
|
||||
|
||||
(defn install
|
||||
[& repo]
|
||||
(if (empty? repo)
|
||||
(local-rule "install")
|
||||
(each rep repo (install-git rep))))
|
||||
[&opt repo]
|
||||
(if repo
|
||||
(install-git repo)
|
||||
(local-rule "install")))
|
||||
|
||||
(defn test
|
||||
[]
|
||||
(local-rule "test"))
|
||||
|
||||
(defn- uninstall-cmd
|
||||
[& what]
|
||||
(if (empty? what)
|
||||
(local-rule "uninstall")
|
||||
(each wha what (uninstall wha))))
|
||||
[&opt what]
|
||||
(if what
|
||||
(uninstall what)
|
||||
(local-rule "uninstall")))
|
||||
|
||||
(defn deps
|
||||
[]
|
||||
@@ -1114,10 +1104,10 @@ Flags are:
|
||||
(def env
|
||||
(try
|
||||
(require-jpm "./project.janet")
|
||||
([err f]
|
||||
(if (= "cannot open ./project.janet" err)
|
||||
(put (make-jpm-env) :project {})
|
||||
(propagate err f)))))
|
||||
([err f]
|
||||
(if (= "cannot open ./project.janet" err)
|
||||
(put (make-jpm-env) :project {})
|
||||
(propagate err f)))))
|
||||
(setdyn :pretty-format (if-not (dyn :nocolor) "%.20Q" "%.20q"))
|
||||
(setdyn :err-color (if-not (dyn :nocolor) true))
|
||||
(def p (env :project))
|
||||
@@ -116,7 +116,7 @@ copy src\include\janet.h dist\janet.h
|
||||
copy src\conf\janetconf.h dist\janetconf.h
|
||||
copy build\libjanet.lib dist\libjanet.lib
|
||||
|
||||
copy .\jpm dist\jpm
|
||||
copy auxbin\jpm dist\jpm
|
||||
copy tools\jpm.bat dist\jpm.bat
|
||||
|
||||
@rem Create installer
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
(with [conn (net/connect "127.0.0.1" "8000")]
|
||||
(printf "Connected to %q!" conn)
|
||||
(:write conn "Echo...")
|
||||
(print "Wrote to connection...")
|
||||
(def res (:read conn 1024))
|
||||
(pp res))
|
||||
@@ -1,13 +0,0 @@
|
||||
(defn handler
|
||||
"Simple handler for connections."
|
||||
[stream]
|
||||
(defer (:close stream)
|
||||
(def id (gensym))
|
||||
(def b @"")
|
||||
(print "Connection " id "!")
|
||||
(while (:read stream 1024 b)
|
||||
(:write stream b)
|
||||
(buffer/clear b))
|
||||
(printf "Done %v!" id)))
|
||||
|
||||
(net/server "127.0.0.1" "8000" handler)
|
||||
@@ -1,7 +1,6 @@
|
||||
# This file is invoked by build_win.bat
|
||||
# Relevant configuration variables are set there.
|
||||
|
||||
SetCompressor /FINAL /SOLID lzma
|
||||
Unicode True
|
||||
|
||||
!echo "Program Files: ${PROGRAMFILES}"
|
||||
@@ -111,7 +110,7 @@ section "Janet" BfWSection
|
||||
# Bin files
|
||||
file /oname=bin\janet.exe dist\janet.exe
|
||||
file /oname=logo.ico assets\icon.ico
|
||||
file /oname=bin\jpm.janet .\jpm
|
||||
file /oname=bin\jpm.janet auxbin\jpm
|
||||
file /oname=bin\jpm.bat tools\jpm.bat
|
||||
|
||||
# C headers and library files
|
||||
|
||||
2
janet.1
2
janet.1
@@ -175,7 +175,7 @@ after an error. Persistent mode can be good for debugging and testing.
|
||||
|
||||
.TP
|
||||
.BR \-q
|
||||
Hide the logo in the repl.
|
||||
Quiet output. Don't print a repl prompt or expression results to stdout.
|
||||
|
||||
.TP
|
||||
.BR \-k
|
||||
|
||||
9
jpm.1
9
jpm.1
@@ -100,20 +100,19 @@ Builds all artifacts specified in the project.janet file in the current director
|
||||
be created in the ./build/ directory.
|
||||
|
||||
.TP
|
||||
.BR install\ [\fBrepo...\fR]
|
||||
.BR install\ [\fBrepo\fR]
|
||||
|
||||
When run with no arguments, installs all installable artifacts in the current project to
|
||||
the current JANET_MODPATH for modules and JANET_BINPATH for executables and scripts. Can also
|
||||
take an optional git repository URL and will install all artifacts in that repository instead.
|
||||
When run with an argument, install does not need to be run from a jpm project directory. Will also
|
||||
install multiple dependencies in one command.
|
||||
When run with an argument, install does not need to be run from a jpm project directory.
|
||||
|
||||
.TP
|
||||
.BR uninstall\ [\fBname...\fR]
|
||||
.BR uninstall\ [\fBname\fR]
|
||||
Uninstall a project installed with install. uninstall expects the name of the project, not the
|
||||
repository url, path to installed file or executable name. The name of the project must be specified
|
||||
at the top of the project.janet file in the declare-project form. If no name is given, uninstalls
|
||||
the current project if installed. Will also uninstall multiple packages in one command.
|
||||
the current project if installed.
|
||||
|
||||
.TP
|
||||
.BR clean
|
||||
|
||||
15
meson.build
15
meson.build
@@ -20,7 +20,7 @@
|
||||
|
||||
project('janet', 'c',
|
||||
default_options : ['c_std=c99', 'b_lundef=false', 'default_library=both'],
|
||||
version : '1.9.1')
|
||||
version : '1.9.0-dev')
|
||||
|
||||
# Global settings
|
||||
janet_path = join_paths(get_option('prefix'), get_option('libdir'), 'janet')
|
||||
@@ -59,7 +59,6 @@ conf.set('JANET_NO_DOCSTRINGS', not get_option('docstrings'))
|
||||
conf.set('JANET_NO_SOURCEMAPS', not get_option('sourcemaps'))
|
||||
conf.set('JANET_NO_ASSEMBLER', not get_option('assembler'))
|
||||
conf.set('JANET_NO_PEG', not get_option('peg'))
|
||||
conf.set('JANET_NO_NET', not get_option('net'))
|
||||
conf.set('JANET_REDUCED_OS', get_option('reduced_os'))
|
||||
conf.set('JANET_NO_TYPED_ARRAY', not get_option('typed_array'))
|
||||
conf.set('JANET_NO_INT_TYPES', not get_option('int_types'))
|
||||
@@ -68,9 +67,6 @@ conf.set('JANET_RECURSION_GUARD', get_option('recursion_guard'))
|
||||
conf.set('JANET_MAX_PROTO_DEPTH', get_option('max_proto_depth'))
|
||||
conf.set('JANET_MAX_MACRO_EXPAND', get_option('max_macro_expand'))
|
||||
conf.set('JANET_STACK_MAX', get_option('stack_max'))
|
||||
conf.set('JANET_NO_UMASK', not get_option('umask'))
|
||||
conf.set('JANET_NO_REALPATH', not get_option('realpath'))
|
||||
conf.set('JANET_NO_PROCESSES', not get_option('processes'))
|
||||
if get_option('os_name') != ''
|
||||
conf.set('JANET_OS_NAME', get_option('os_name'))
|
||||
endif
|
||||
@@ -116,7 +112,6 @@ core_src = [
|
||||
'src/core/io.c',
|
||||
'src/core/marsh.c',
|
||||
'src/core/math.c',
|
||||
'src/core/net.c',
|
||||
'src/core/os.c',
|
||||
'src/core/parse.c',
|
||||
'src/core/peg.c',
|
||||
@@ -224,8 +219,7 @@ test_files = [
|
||||
'test/suite5.janet',
|
||||
'test/suite6.janet',
|
||||
'test/suite7.janet',
|
||||
'test/suite8.janet',
|
||||
'test/suite9.janet'
|
||||
'test/suite8.janet'
|
||||
]
|
||||
foreach t : test_files
|
||||
test(t, janet_nativeclient, args : files([t]), workdir : meson.current_source_dir())
|
||||
@@ -247,5 +241,8 @@ pkg.generate(libjanet,
|
||||
install_man('janet.1')
|
||||
install_man('jpm.1')
|
||||
install_headers(['src/include/janet.h', jconf], subdir: 'janet')
|
||||
install_data(sources : ['jpm'], install_dir : get_option('bindir'))
|
||||
janet_binscripts = [
|
||||
'auxbin/jpm'
|
||||
]
|
||||
install_data(sources : janet_binscripts, install_dir : get_option('bindir'))
|
||||
install_data(sources : ['tools/.keep'], install_dir : join_paths(get_option('libdir'), 'janet'))
|
||||
|
||||
@@ -11,10 +11,6 @@ option('peg', type : 'boolean', value : true)
|
||||
option('typed_array', type : 'boolean', value : true)
|
||||
option('int_types', type : 'boolean', value : true)
|
||||
option('prf', type : 'boolean', value : true)
|
||||
option('net', type : 'boolean', value : true)
|
||||
option('processes', type : 'boolean', value : true)
|
||||
option('umask', type : 'boolean', value : true)
|
||||
option('realpath', type : 'boolean', value : true)
|
||||
|
||||
option('recursion_guard', type : 'integer', min : 10, max : 8000, value : 1024)
|
||||
option('max_proto_depth', type : 'integer', min : 10, max : 8000, value : 200)
|
||||
|
||||
@@ -141,11 +141,6 @@
|
||||
[x &opt err]
|
||||
(if x x (error (if err err "assert failure"))))
|
||||
|
||||
(defn errorf
|
||||
"A combination of error and string/format. Equivalent to (error (string/format fmt ;args))"
|
||||
[fmt & args]
|
||||
(error (string/format fmt ;args)))
|
||||
|
||||
(defmacro default
|
||||
"Define a default value for an optional argument.
|
||||
Expands to (def sym (if (= nil sym) val sym))"
|
||||
@@ -245,8 +240,8 @@
|
||||
[& body]
|
||||
(let [f (gensym) r (gensym)]
|
||||
~(let [,f (,fiber/new (fn [] ,;body) :ie)
|
||||
,r (,resume ,f)]
|
||||
[(,not= :error (,fiber/status ,f)) ,r])))
|
||||
,r (,resume ,f)]
|
||||
[(,not= :error (,fiber/status ,f)) ,r])))
|
||||
|
||||
(defmacro and
|
||||
"Evaluates to the last argument if all preceding elements are truthy, otherwise
|
||||
@@ -374,7 +369,7 @@
|
||||
"Similar to with, but if binding is false or nil, evaluates
|
||||
the falsey path. Otherwise, evaluates the truthy path. In both cases,
|
||||
ctor is bound to binding."
|
||||
[[binding ctor dtor] truthy &opt falsey]
|
||||
[[binding ctor dtor] truthy &opt falsey ]
|
||||
~(if-let [,binding ,ctor]
|
||||
,(apply defer [(or dtor :close) binding] [truthy])
|
||||
,falsey))
|
||||
@@ -623,9 +618,9 @@
|
||||
(case (length functions)
|
||||
0 nil
|
||||
1 (in functions 0)
|
||||
2 (let [[f g] functions] (fn [& x] (f (g ;x))))
|
||||
3 (let [[f g h] functions] (fn [& x] (f (g (h ;x)))))
|
||||
4 (let [[f g h i] functions] (fn [& x] (f (g (h (i ;x))))))
|
||||
2 (let [[f g] functions] (fn [& x] (f (g ;x))))
|
||||
3 (let [[f g h] functions] (fn [& x] (f (g (h ;x)))))
|
||||
4 (let [[f g h i] functions] (fn [& x] (f (g (h (i ;x))))))
|
||||
(let [[f g h i] functions]
|
||||
(comp (fn [x] (f (g (h (i x)))))
|
||||
;(tuple/slice functions 4 -1)))))
|
||||
@@ -1075,7 +1070,7 @@
|
||||
[bindings & body]
|
||||
(def dyn-forms
|
||||
(seq [i :range [0 (length bindings) 2]]
|
||||
~(setdyn ,(bindings i) ,(bindings (+ i 1)))))
|
||||
~(setdyn ,(bindings i) ,(bindings (+ i 1)))))
|
||||
~(,resume (,fiber/new (fn [] ,;dyn-forms ,;body) :p)))
|
||||
|
||||
(defmacro with-vars
|
||||
@@ -1089,12 +1084,12 @@
|
||||
(def setnew (seq [i :range [0 len 2]] ['set (vars i) (vars (+ i 1))]))
|
||||
(def restoreold (seq [i :range [0 len 2]] ['set (vars i) (temp (/ i 2))]))
|
||||
(with-syms [ret f s]
|
||||
~(do
|
||||
,;saveold
|
||||
(def ,f (,fiber/new (fn [] ,;setnew ,;body) :ti))
|
||||
(def ,ret (,resume ,f))
|
||||
,;restoreold
|
||||
(if (= (,fiber/status ,f) :dead) ,ret (,propagate ,ret ,f)))))
|
||||
~(do
|
||||
,;saveold
|
||||
(def ,f (,fiber/new (fn [] ,;setnew ,;body) :ti))
|
||||
(def ,ret (,resume ,f))
|
||||
,;restoreold
|
||||
(if (= (,fiber/status ,f) :dead) ,ret (,propagate ,ret ,f)))))
|
||||
|
||||
(defn partial
|
||||
"Partial function application."
|
||||
@@ -1412,9 +1407,9 @@
|
||||
~(do (def ,pattern ,expr) ,(onmatch))))
|
||||
|
||||
(and (tuple? pattern) (= :parens (tuple/type pattern)))
|
||||
(if (= (get pattern 0) '@)
|
||||
(if (and (= (pattern 0) '@) (symbol? (pattern 1)))
|
||||
# Unification with external values
|
||||
~(if (= ,(get pattern 1) ,expr) ,(onmatch) ,sentinel)
|
||||
~(if (= ,(pattern 1) ,expr) ,(onmatch) ,sentinel)
|
||||
(match-1
|
||||
(in pattern 0) expr
|
||||
(fn []
|
||||
@@ -1448,7 +1443,7 @@
|
||||
(if (= key nil)
|
||||
(onmatch)
|
||||
~(do (def ,$val (,get ,$dict ,key))
|
||||
,(match-1 [(in pattern key) [not= nil $val]] $val aux seen)))))
|
||||
,(match-1 [(in pattern key) [not= nil $val]] $val aux seen)))))
|
||||
,sentinel)))
|
||||
|
||||
:else ~(if (= ,pattern ,expr) ,(onmatch) ,sentinel)))
|
||||
@@ -1756,8 +1751,8 @@
|
||||
:array (tuple/slice (map freeze x))
|
||||
:tuple (tuple/slice (map freeze x))
|
||||
:table (if-let [p (table/getproto x)]
|
||||
(freeze (merge (table/clone p) x))
|
||||
(struct ;(map freeze (kvs x))))
|
||||
(freeze (merge (table/clone p) x))
|
||||
(struct ;(map freeze (kvs x))))
|
||||
:struct (struct ;(map freeze (kvs x)))
|
||||
:buffer (string x)
|
||||
x))
|
||||
@@ -1956,7 +1951,6 @@
|
||||
(default on-parse-error bad-parse)
|
||||
(default evaluator (fn evaluate [x &] (x)))
|
||||
(default where "<anonymous>")
|
||||
(default guard :ydt)
|
||||
|
||||
# Are we done yet?
|
||||
(var going true)
|
||||
@@ -1983,19 +1977,12 @@
|
||||
(string err " on line " line ", column " column)
|
||||
err))
|
||||
(on-compile-error msg errf where))))
|
||||
guard))
|
||||
(or guard :a)))
|
||||
(fiber/setenv f env)
|
||||
(while (fiber/can-resume? f)
|
||||
(def res (resume f resumeval))
|
||||
(when good (when going (set resumeval (onstatus f res))))))
|
||||
|
||||
(defn parse-err
|
||||
"Handle parser error in the correct environment"
|
||||
[p where]
|
||||
(def f (coro (on-parse-error p where)))
|
||||
(fiber/setenv f env)
|
||||
(resume f))
|
||||
|
||||
# Loop
|
||||
(def buf @"")
|
||||
(while going
|
||||
@@ -2013,12 +2000,12 @@
|
||||
(while (parser/has-more p)
|
||||
(eval1 (parser/produce p)))
|
||||
(when (= (parser/status p) :error)
|
||||
(parse-err p where))))
|
||||
(on-parse-error p where))))
|
||||
# Check final parser state
|
||||
(while (parser/has-more p)
|
||||
(eval1 (parser/produce p)))
|
||||
(when (= (parser/status p) :error)
|
||||
(parse-err p where))
|
||||
(on-parse-error p where))
|
||||
|
||||
(in env :exit-value env))
|
||||
|
||||
@@ -2065,19 +2052,6 @@
|
||||
(res)
|
||||
(error (res :error))))
|
||||
|
||||
(defn parse
|
||||
"Parse a string and return the first value. For complex parsing, such as for a repl with error handling,
|
||||
use the parser api."
|
||||
[str]
|
||||
(let [p (parser/new)]
|
||||
(parser/consume p str)
|
||||
(parser/eof p)
|
||||
(if (parser/has-more p)
|
||||
(parser/produce p)
|
||||
(if (= :error (parser/status p))
|
||||
(error (parser/error p))
|
||||
(error "no value")))))
|
||||
|
||||
(def make-image-dict
|
||||
"A table used in combination with marshal to marshal code (images), such that
|
||||
(make-image x) is the same as (marshal x make-image-dict)."
|
||||
@@ -2131,12 +2105,11 @@
|
||||
(defn- find-prefix
|
||||
[pre]
|
||||
(or (find-index |(and (string? ($ 0)) (string/has-prefix? pre ($ 0))) module/paths) 0))
|
||||
(array/insert module/paths 0 [(string ":cur:/:all:" ext) loader check-.])
|
||||
(def all-index (find-prefix ":all:"))
|
||||
(array/insert module/paths all-index [(string ":all:" ext) loader not-check-.])
|
||||
(def sys-index (find-prefix ":sys:"))
|
||||
(array/insert module/paths sys-index [(string ":sys:/:all:" ext) loader not-check-.])
|
||||
(def curall-index (find-prefix ":cur:/:all:"))
|
||||
(array/insert module/paths curall-index [(string ":cur:/:all:" ext) loader check-.])
|
||||
module/paths)
|
||||
|
||||
(module/add-paths ":native:" :native)
|
||||
@@ -2154,7 +2127,7 @@
|
||||
(when f
|
||||
(def res
|
||||
(try (do (file/read f 1) true)
|
||||
([err] nil)))
|
||||
([err] nil)))
|
||||
(file/close f)
|
||||
res))))
|
||||
|
||||
@@ -2176,8 +2149,8 @@
|
||||
(when (mod-filter checker path)
|
||||
(if (function? p)
|
||||
(when-let [res (p path)]
|
||||
(set ret [res mod-kind])
|
||||
(break))
|
||||
(set ret [res mod-kind])
|
||||
(break))
|
||||
(do
|
||||
(def fullpath (string (module/expand-path path p)))
|
||||
(when (fexists fullpath)
|
||||
@@ -2360,15 +2333,12 @@
|
||||
[&opt nth frame-idx]
|
||||
(in (.slots frame-idx) (or nth 0)))
|
||||
|
||||
# Conditional compilation for disasm
|
||||
(def disasm-alias (if-let [x (_env 'disasm)] (x :value)))
|
||||
|
||||
(defn .disasm
|
||||
"Gets the assembly for the current function."
|
||||
[&opt n]
|
||||
(def frame (.frame n))
|
||||
(def func (frame :function))
|
||||
(disasm-alias func))
|
||||
(disasm func))
|
||||
|
||||
(defn .bytecode
|
||||
"Get the bytecode for the current function."
|
||||
@@ -2380,10 +2350,10 @@
|
||||
[&opt n]
|
||||
(def frame (.frame n))
|
||||
(def func (frame :function))
|
||||
(def dasm (disasm-alias func))
|
||||
(def bytecode (in dasm 'bytecode))
|
||||
(def dasm (disasm func))
|
||||
(def bytecode (dasm 'bytecode))
|
||||
(def pc (frame :pc))
|
||||
(def sourcemap (in dasm 'sourcemap))
|
||||
(def sourcemap (dasm 'sourcemap))
|
||||
(var last-loc [-2 -2])
|
||||
(print "\n signal: " (.signal))
|
||||
(print " function: " (dasm 'name) " [" (in dasm 'source "") "]")
|
||||
@@ -2405,6 +2375,14 @@
|
||||
(print))
|
||||
(print))
|
||||
|
||||
(defn .source
|
||||
"Show the source code for the function being debugged."
|
||||
[&opt n]
|
||||
(def frame (.frame n))
|
||||
(def s (frame :source))
|
||||
(def all-source (slurp s))
|
||||
(print "\n" all-source "\n"))
|
||||
|
||||
(defn .breakall
|
||||
"Set breakpoints on all instructions in the current function."
|
||||
[&opt n]
|
||||
@@ -2423,22 +2401,6 @@
|
||||
(debug/unfbreak fun i))
|
||||
(print "Cleared " (length bytecode) " breakpoints in " fun))
|
||||
|
||||
(unless (get _env 'disasm)
|
||||
(put _env '.disasm nil)
|
||||
(put _env '.bytecode nil)
|
||||
(put _env '.breakall nil)
|
||||
(put _env '.clearall nil)
|
||||
(put _env '.ppasm nil))
|
||||
(put _env 'disasm-alias nil)
|
||||
|
||||
(defn .source
|
||||
"Show the source code for the function being debugged."
|
||||
[&opt n]
|
||||
(def frame (.frame n))
|
||||
(def s (frame :source))
|
||||
(def all-source (slurp s))
|
||||
(print "\n" all-source "\n"))
|
||||
|
||||
(defn .break
|
||||
"Set breakpoint at the current pc."
|
||||
[]
|
||||
@@ -2479,11 +2441,8 @@
|
||||
(set res (debug/step (.fiber))))
|
||||
res)
|
||||
|
||||
(def debugger-env
|
||||
"An environment that contains dot prefixed functions for debugging."
|
||||
@{})
|
||||
|
||||
(def- debugger-keys (filter (partial string/has-prefix? ".") (keys _env)))
|
||||
(def- debugger-env @{})
|
||||
(each k debugger-keys (put debugger-env k (_env k)) (put _env k nil))
|
||||
(put _env 'debugger-keys nil)
|
||||
|
||||
@@ -2536,19 +2495,19 @@
|
||||
|
||||
(fn [f x]
|
||||
(if (= :dead (fiber/status f))
|
||||
(do
|
||||
(put e '_ @{:value x})
|
||||
(printf (get e :pretty-format "%q") x)
|
||||
(flush))
|
||||
(put e '_ @{:value x})
|
||||
(if (e :debug)
|
||||
(enter-debugger f x)
|
||||
(do (debug/stacktrace f x) (eflush))))))
|
||||
|
||||
(run-context {:env env
|
||||
:chunks chunks
|
||||
:expander (fn [x] [pp x])
|
||||
:on-status (or onsignal (make-onsignal env 1))
|
||||
:source "repl"}))
|
||||
|
||||
(put _env 'debugger-env nil)
|
||||
|
||||
###
|
||||
###
|
||||
### CLI Tool Main
|
||||
@@ -2578,9 +2537,6 @@
|
||||
|
||||
(def- importers {'import true 'import* true 'use true 'dofile true 'require true})
|
||||
|
||||
# conditional compilation for reduced os
|
||||
(def- getenv-alias (if-let [entry (in _env 'os/getenv)] (entry :value) (fn [&])))
|
||||
|
||||
(defn cli-main
|
||||
"Entrance for the Janet CLI tool. Call this functions with the command line
|
||||
arguments as an array or tuple of strings to invoke the CLI interface."
|
||||
@@ -2598,8 +2554,8 @@
|
||||
(var *debug* false)
|
||||
(var *compile-only* false)
|
||||
|
||||
(if-let [jp (getenv-alias "JANET_PATH")] (setdyn :syspath jp))
|
||||
(if-let [jp (getenv-alias "JANET_HEADERPATH")] (setdyn :headerpath jp))
|
||||
(if-let [jp (os/getenv "JANET_PATH")] (setdyn :syspath jp))
|
||||
(if-let [jp (os/getenv "JANET_HEADERPATH")] (setdyn :headerpath jp))
|
||||
|
||||
# Flag handlers
|
||||
(def handlers
|
||||
@@ -2614,7 +2570,7 @@
|
||||
-d : Set the debug flag in the repl
|
||||
-r : Enter the repl after running all scripts
|
||||
-p : Keep on executing if there is a top level error (persistent)
|
||||
-q : Hide logo (quiet)
|
||||
-q : Hide prompt, logo, and repl output (quiet)
|
||||
-k : Compile scripts but do not execute (flycheck)
|
||||
-m syspath : Set system path for loading global modules
|
||||
-c source output : Compile janet source code into an image
|
||||
@@ -2706,15 +2662,16 @@
|
||||
(def getter (if *raw-stdin* getstdin getline))
|
||||
(defn getchunk [buf p]
|
||||
(getter (getprompt p) buf env))
|
||||
(def onsig (if *quiet* (fn [x &] x) nil))
|
||||
(setdyn :pretty-format (if *colorize* "%.20Q" "%.20q"))
|
||||
(setdyn :err-color (if *colorize* true))
|
||||
(repl getchunk nil env)))
|
||||
(repl getchunk onsig env)))
|
||||
|
||||
(put _env 'no-side-effects nil)
|
||||
(put _env 'is-safe-def nil)
|
||||
(put _env 'safe-forms nil)
|
||||
(put _env 'importers nil)
|
||||
(put _env 'getenv-alias nil)
|
||||
|
||||
|
||||
###
|
||||
###
|
||||
@@ -2801,7 +2758,6 @@
|
||||
"src/core/io.c"
|
||||
"src/core/marsh.c"
|
||||
"src/core/math.c"
|
||||
"src/core/net.c"
|
||||
"src/core/os.c"
|
||||
"src/core/parse.c"
|
||||
"src/core/peg.c"
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
#define JANET_VERSION_MAJOR 1
|
||||
#define JANET_VERSION_MINOR 9
|
||||
#define JANET_VERSION_PATCH 1
|
||||
#define JANET_VERSION_PATCH 0
|
||||
#define JANET_VERSION_EXTRA ""
|
||||
#define JANET_VERSION "1.9.1"
|
||||
#define JANET_VERSION "1.9.0-dev"
|
||||
|
||||
/* #define JANET_BUILD "local" */
|
||||
|
||||
@@ -45,22 +45,14 @@
|
||||
/* #define JANET_NO_DOCSTRINGS */
|
||||
/* #define JANET_NO_SOURCEMAPS */
|
||||
/* #define JANET_REDUCED_OS */
|
||||
/* #define JANET_NO_PROCESSES */
|
||||
/* #define JANET_NO_ASSEMBLER */
|
||||
/* #define JANET_NO_PEG */
|
||||
/* #define JANET_NO_NET */
|
||||
/* #define JANET_NO_TYPED_ARRAY */
|
||||
/* #define JANET_NO_INT_TYPES */
|
||||
|
||||
/* Other settings */
|
||||
/* #define JANET_NO_ASSEMBLER */
|
||||
/* #define JANET_NO_PEG */
|
||||
/* #define JANET_NO_TYPED_ARRAY */
|
||||
/* #define JANET_NO_INT_TYPES */
|
||||
/* #define JANET_NO_PRF */
|
||||
/* #define JANET_NO_UTC_MKTIME */
|
||||
/* #define JANET_NO_REALPATH */
|
||||
/* #define JANET_NO_SYMLINKS */
|
||||
/* #define JANET_NO_UMASK */
|
||||
/* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */
|
||||
/* #define JANET_EXIT(msg) do { printf("C assert failed executing janet: %s\n", msg); exit(1); } while (0) */
|
||||
/* #define JANET_TOP_LEVEL_SIGNAL(msg) call_my_function((msg), stderr) */
|
||||
/* #define JANET_RECURSION_GUARD 1024 */
|
||||
/* #define JANET_MAX_PROTO_DEPTH 200 */
|
||||
/* #define JANET_MAX_MACRO_EXPAND 200 */
|
||||
|
||||
@@ -964,7 +964,7 @@ static const JanetReg asm_cfuns[] = {
|
||||
"asm", cfun_asm,
|
||||
JDOC("(asm assembly)\n\n"
|
||||
"Returns a new function that is the compiled result of the assembly.\n"
|
||||
"The syntax for the assembly can be found on the Janet website. Will throw an\n"
|
||||
"The syntax for the assembly can be found on the janet wiki. Will throw an\n"
|
||||
"error on invalid assembly.")
|
||||
},
|
||||
{
|
||||
|
||||
@@ -27,15 +27,6 @@
|
||||
#include "fiber.h"
|
||||
#endif
|
||||
|
||||
JANET_NO_RETURN static void janet_top_level_signal(const char *msg) {
|
||||
#ifdef JANET_TOP_LEVEL_SIGNAL
|
||||
JANET_TOP_LEVEL_SIGNAL(msg);
|
||||
#else
|
||||
fputs(msg, stdout);
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void janet_signalv(JanetSignal sig, Janet message) {
|
||||
if (janet_vm_return_reg != NULL) {
|
||||
*janet_vm_return_reg = message;
|
||||
@@ -46,8 +37,8 @@ void janet_signalv(JanetSignal sig, Janet message) {
|
||||
longjmp(*janet_vm_jmp_buf, sig);
|
||||
#endif
|
||||
} else {
|
||||
const char *str = (const char *)janet_formatc("janet top level signal - %v\n", message);
|
||||
janet_top_level_signal(str);
|
||||
fputs((const char *)janet_formatc("janet top level signal - %v\n", message), stdout);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -855,10 +855,10 @@ static const JanetReg compile_cfuns[] = {
|
||||
{
|
||||
"compile", cfun,
|
||||
JDOC("(compile ast &opt env source)\n\n"
|
||||
"Compiles an Abstract Syntax Tree (ast) into a function. "
|
||||
"Compiles an Abstract Syntax Tree (ast) into a janet function. "
|
||||
"Pair the compile function with parsing functionality to implement "
|
||||
"eval. Returns a new function and does not modify ast. Returns an error "
|
||||
"struct with keys :line, :column, and :error if compilation fails.")
|
||||
"eval. Returns a janet function and does not modify ast. Throws an "
|
||||
"error if the ast cannot be compiled.")
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -643,8 +643,8 @@ static const JanetReg corelib_cfuns[] = {
|
||||
{
|
||||
"hash", janet_core_hash,
|
||||
JDOC("(hash value)\n\n"
|
||||
"Gets a hash for any value. The hash is an integer can be used "
|
||||
"as a cheap hash function for all values. If two values are strictly equal, "
|
||||
"Gets a hash value for any janet value. The hash is an integer can be used "
|
||||
"as a cheap hash function for all janet objects. If two values are strictly equal, "
|
||||
"then they will have the same hash value.")
|
||||
},
|
||||
{
|
||||
@@ -685,9 +685,9 @@ static const JanetReg corelib_cfuns[] = {
|
||||
"\t:all:\tthe value of path verbatim\n"
|
||||
"\t:cur:\tthe current file, or (dyn :current-file)\n"
|
||||
"\t:dir:\tthe directory containing the current file\n"
|
||||
"\t:name:\tthe name component of path, with extension if given\n"
|
||||
"\t:name:\tthe filename component of path, with extension if given\n"
|
||||
"\t:native:\tthe extension used to load natives, .so or .dll\n"
|
||||
"\t:sys:\tthe system path, or (dyn :syspath)")
|
||||
"\t:sys:\tthe system path, or (syn :syspath)")
|
||||
},
|
||||
{
|
||||
"int?", janet_core_check_int,
|
||||
@@ -742,7 +742,7 @@ static void janet_quick_asm(
|
||||
janet_def(env, name, janet_wrap_function(janet_thunk(def)), doc);
|
||||
}
|
||||
|
||||
/* Macros for easier inline assembly */
|
||||
/* Macros for easier inline janet assembly */
|
||||
#define SSS(op, a, b, c) ((op) | ((a) << 8) | ((b) << 16) | ((c) << 24))
|
||||
#define SS(op, a, b) ((op) | ((a) << 8) | ((b) << 16))
|
||||
#define SSI(op, a, b, I) ((op) | ((a) << 8) | ((b) << 16) | ((uint32_t)(I) << 24))
|
||||
@@ -1004,9 +1004,6 @@ static void janet_load_libs(JanetTable *env) {
|
||||
#ifdef JANET_THREADS
|
||||
janet_lib_thread(env);
|
||||
#endif
|
||||
#ifdef JANET_NET
|
||||
janet_lib_net(env);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JANET_BOOTSTRAP
|
||||
@@ -1024,7 +1021,7 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
||||
janet_quick_asm(env, JANET_FUN_NEXT,
|
||||
"next", 2, 1, 2, 2, next_asm, sizeof(next_asm),
|
||||
JDOC("(next ds &opt key)\n\n"
|
||||
"Gets the next key in a data structure. Can be used to iterate through "
|
||||
"Gets the next key in a datastructure. Can be used to iterate through "
|
||||
"the keys of a data structure in an unspecified order. Keys are guaranteed "
|
||||
"to be seen only once per iteration if they data structure is not mutated "
|
||||
"during iteration. If key is nil, next returns the first key. If next "
|
||||
@@ -1035,8 +1032,7 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
||||
"Propagate a signal from a fiber to the current fiber. The resulting "
|
||||
"stack trace from the current fiber will include frames from fiber. If "
|
||||
"fiber is in a state that can be resumed, resuming the current fiber will "
|
||||
"first resume fiber. This function can be used to re-raise an error without "
|
||||
"losing the original stack trace."));
|
||||
"first resume fiber."));
|
||||
janet_quick_asm(env, JANET_FUN_DEBUG,
|
||||
"debug", 1, 0, 1, 1, debug_asm, sizeof(debug_asm),
|
||||
JDOC("(debug &opt x)\n\n"
|
||||
@@ -1108,7 +1104,7 @@ JanetTable *janet_core_env(JanetTable *replacements) {
|
||||
JDOC("(/ & xs)\n\n"
|
||||
"Returns the quotient of xs. If xs is empty, returns 1. If xs has one value x, returns "
|
||||
"the reciprocal of x. Otherwise return the first value of xs repeatedly divided by the remaining "
|
||||
"values."));
|
||||
"values. Division by two integers uses truncating division."));
|
||||
templatize_varop(env, JANET_FUN_BAND, "band", -1, -1, JOP_BAND,
|
||||
JDOC("(band & xs)\n\n"
|
||||
"Returns the bit-wise and of all values in xs. Each x in xs must be an integer."));
|
||||
|
||||
@@ -26,11 +26,7 @@
|
||||
#define JANET_FEATURES_H_defined
|
||||
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
#endif
|
||||
|
||||
/* Needed for realpath on linux */
|
||||
|
||||
@@ -405,10 +405,6 @@ JanetFiber *janet_current_fiber(void) {
|
||||
return janet_vm_fiber;
|
||||
}
|
||||
|
||||
JanetFiber *janet_root_fiber(void) {
|
||||
return janet_vm_root_fiber;
|
||||
}
|
||||
|
||||
/* CFuns */
|
||||
|
||||
static Janet cfun_fiber_getenv(int32_t argc, Janet *argv) {
|
||||
@@ -512,12 +508,6 @@ static Janet cfun_fiber_current(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_fiber(janet_vm_fiber);
|
||||
}
|
||||
|
||||
static Janet cfun_fiber_root(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_fixarity(argc, 0);
|
||||
return janet_wrap_fiber(janet_vm_root_fiber);
|
||||
}
|
||||
|
||||
static Janet cfun_fiber_maxstack(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
JanetFiber *fiber = janet_getfiber(argv, 0);
|
||||
@@ -585,12 +575,6 @@ static const JanetReg fiber_cfuns[] = {
|
||||
"\t:alive - the fiber is currently running and cannot be resumed\n"
|
||||
"\t:new - the fiber has just been created and not yet run")
|
||||
},
|
||||
{
|
||||
"fiber/root", cfun_fiber_root,
|
||||
JDOC("(fiber/root)\n\n"
|
||||
"Returns the current root fiber. The root fiber is the oldest ancestor "
|
||||
"that does not have a parent.")
|
||||
},
|
||||
{
|
||||
"fiber/current", cfun_fiber_current,
|
||||
JDOC("(fiber/current)\n\n"
|
||||
|
||||
@@ -389,9 +389,6 @@ void janet_collect(void) {
|
||||
if (janet_vm_gc_suspend) return;
|
||||
depth = JANET_RECURSION_GUARD;
|
||||
orig_rootcount = janet_vm_root_count;
|
||||
#ifdef JANET_NET
|
||||
janet_net_markloop();
|
||||
#endif
|
||||
for (i = 0; i < orig_rootcount; i++)
|
||||
janet_mark(janet_vm_roots[i]);
|
||||
while (orig_rootcount < janet_vm_root_count) {
|
||||
@@ -533,7 +530,7 @@ void *janet_srealloc(void *mem, size_t size) {
|
||||
if (i == 0) break;
|
||||
}
|
||||
}
|
||||
JANET_EXIT("invalid janet_srealloc");
|
||||
janet_exit("invalid janet_srealloc");
|
||||
}
|
||||
|
||||
void janet_sfinalizer(void *mem, JanetScratchFinalizer finalizer) {
|
||||
@@ -554,5 +551,5 @@ void janet_sfree(void *mem) {
|
||||
if (i == 0) break;
|
||||
}
|
||||
}
|
||||
JANET_EXIT("invalid janet_sfree");
|
||||
janet_exit("invalid janet_sfree");
|
||||
}
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef JANET_WINDOWS
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static int cfun_io_gc(void *p, size_t len);
|
||||
@@ -89,17 +87,18 @@ static Janet makef(FILE *f, int flags) {
|
||||
JanetFile *iof = (JanetFile *) janet_abstract(&janet_file_type, sizeof(JanetFile));
|
||||
iof->file = f;
|
||||
iof->flags = flags;
|
||||
#ifndef JANET_WINDOWS
|
||||
/* While we would like fopen to set cloexec by default (like O_CLOEXEC) with the e flag, that is
|
||||
* not standard. */
|
||||
if (!(flags & JANET_FILE_NOT_CLOSEABLE))
|
||||
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
return janet_wrap_abstract(iof);
|
||||
}
|
||||
|
||||
/* Open a process */
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
#ifdef __EMSCRIPTEN__
|
||||
static Janet cfun_io_popen(int32_t argc, Janet *argv) {
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
janet_panic("not implemented on this platform");
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
#else
|
||||
static Janet cfun_io_popen(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
const uint8_t *fname = janet_getstring(argv, 0);
|
||||
@@ -130,7 +129,6 @@ static Janet cfun_io_popen(int32_t argc, Janet *argv) {
|
||||
static Janet cfun_io_temp(int32_t argc, Janet *argv) {
|
||||
(void)argv;
|
||||
janet_fixarity(argc, 0);
|
||||
// XXX use mkostemp when we can to avoid CLOEXEC race.
|
||||
FILE *tmp = tmpfile();
|
||||
if (!tmp)
|
||||
janet_panicf("unable to create temporary file - %s", strerror(errno));
|
||||
@@ -241,24 +239,12 @@ static Janet cfun_io_fflush(int32_t argc, Janet *argv) {
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
#ifdef JANET_WINDOWS
|
||||
#define pclose _pclose
|
||||
#define WEXITSTATUS(x) x
|
||||
#endif
|
||||
|
||||
/* Cleanup a file */
|
||||
static int cfun_io_gc(void *p, size_t len) {
|
||||
(void) len;
|
||||
JanetFile *iof = (JanetFile *)p;
|
||||
if (!(iof->flags & (JANET_FILE_NOT_CLOSEABLE | JANET_FILE_CLOSED))) {
|
||||
/* We can't panic inside a gc, so just ignore bad statuses here */
|
||||
if (iof->flags & JANET_FILE_PIPED) {
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
pclose(iof->file);
|
||||
#endif
|
||||
} else {
|
||||
fclose(iof->file);
|
||||
}
|
||||
return fclose(iof->file);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -272,12 +258,14 @@ static Janet cfun_io_fclose(int32_t argc, Janet *argv) {
|
||||
if (iof->flags & (JANET_FILE_NOT_CLOSEABLE))
|
||||
janet_panic("file not closable");
|
||||
if (iof->flags & JANET_FILE_PIPED) {
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
#ifdef JANET_WINDOWS
|
||||
#define pclose _pclose
|
||||
#define WEXITSTATUS(x) x
|
||||
#endif
|
||||
int status = pclose(iof->file);
|
||||
iof->flags |= JANET_FILE_CLOSED;
|
||||
if (status == -1) janet_panic("could not close file");
|
||||
return janet_wrap_integer(WEXITSTATUS(status));
|
||||
#endif
|
||||
} else {
|
||||
if (fclose(iof->file)) janet_panic("could not close file");
|
||||
iof->flags |= JANET_FILE_CLOSED;
|
||||
@@ -652,7 +640,6 @@ static const JanetReg io_cfuns[] = {
|
||||
"for the relative number of bytes to seek in the file. n may be a real "
|
||||
"number to handle large files of more the 4GB. Returns the file handle.")
|
||||
},
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
{
|
||||
"file/popen", cfun_io_popen,
|
||||
JDOC("(file/popen path &opt mode)\n\n"
|
||||
@@ -661,7 +648,6 @@ static const JanetReg io_cfuns[] = {
|
||||
"process can be read from the file. In :w mode, the stdin of the process "
|
||||
"can be written to. Returns the new file.")
|
||||
},
|
||||
#endif
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -1417,17 +1417,17 @@ static const JanetReg marsh_cfuns[] = {
|
||||
{
|
||||
"marshal", cfun_marshal,
|
||||
JDOC("(marshal x &opt reverse-lookup buffer)\n\n"
|
||||
"Marshal a value into a buffer and return the buffer. The buffer "
|
||||
"Marshal a janet value into a buffer and return the buffer. The buffer "
|
||||
"can the later be unmarshalled to reconstruct the initial value. "
|
||||
"Optionally, one can pass in a reverse lookup table to not marshal "
|
||||
"aliased values that are found in the table. Then a forward"
|
||||
"lookup table can be used to recover the original value when "
|
||||
"lookup table can be used to recover the original janet value when "
|
||||
"unmarshalling.")
|
||||
},
|
||||
{
|
||||
"unmarshal", cfun_unmarshal,
|
||||
JDOC("(unmarshal buffer &opt lookup)\n\n"
|
||||
"Unmarshal a value from a buffer. An optional lookup table "
|
||||
"Unmarshal a janet value from a buffer. An optional lookup table "
|
||||
"can be provided to allow for aliases to be resolved. Returns the value "
|
||||
"unmarshalled from the buffer.")
|
||||
},
|
||||
|
||||
@@ -413,7 +413,7 @@ static const JanetReg math_cfuns[] = {
|
||||
"math/rng", cfun_rng_make,
|
||||
JDOC("(math/rng &opt seed)\n\n"
|
||||
"Creates a Psuedo-Random number generator, with an optional seed. "
|
||||
"The seed should be an unsigned 32 bit integer or a buffer. "
|
||||
"The seed should be an unsigned 32 bit integer. "
|
||||
"Do not use this for cryptography. Returns a core/rng abstract type.")
|
||||
},
|
||||
{
|
||||
@@ -480,7 +480,7 @@ static const JanetReg math_cfuns[] = {
|
||||
},
|
||||
{
|
||||
"math/next", janet_nextafter,
|
||||
JDOC("(math/next x y)\n\n"
|
||||
JDOC("(math/next y)\n\n"
|
||||
"Returns the next representable floating point value after x in the direction of y.")
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
|
||||
677
src/core/net.c
677
src/core/net.c
@@ -1,677 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Calvin Rose
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef JANET_AMALG
|
||||
#include "features.h"
|
||||
#include <janet.h>
|
||||
#include "util.h"
|
||||
#endif
|
||||
|
||||
#ifdef JANET_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment (lib, "Ws2_32.lib")
|
||||
#pragma comment (lib, "Mswsock.lib")
|
||||
#pragma comment (lib, "Advapi32.lib")
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <poll.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Streams
|
||||
*/
|
||||
|
||||
#define JANET_STREAM_CLOSED 1
|
||||
#define JANET_STREAM_READABLE 2
|
||||
#define JANET_STREAM_WRITABLE 4
|
||||
|
||||
static int janet_stream_close(void *p, size_t s);
|
||||
static int janet_stream_getter(void *p, Janet key, Janet *out);
|
||||
static const JanetAbstractType StreamAT = {
|
||||
"core/stream",
|
||||
janet_stream_close,
|
||||
NULL,
|
||||
janet_stream_getter,
|
||||
JANET_ATEND_GET
|
||||
};
|
||||
|
||||
#ifdef JANET_WINDOWS
|
||||
typedef struct {
|
||||
SOCKET fd;
|
||||
int flags;
|
||||
} JanetStream;
|
||||
#define JSOCKCLOSE(x) closesocket(x)
|
||||
#define JSOCKDEFAULT INVALID_SOCKET
|
||||
#define JLASTERR WSAGetLastError()
|
||||
#define JSOCKVALID(x) ((x) != INVALID_SOCKET)
|
||||
#define JEINTR WSAEINTR
|
||||
#define JEWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define JEAGAIN WSAEWOULDBLOCK
|
||||
#define JPOLL WSAPoll
|
||||
#define JPollStruct WSAPOLLFD
|
||||
#define JSock SOCKET
|
||||
#define JReadInt long
|
||||
#define JSOCKFLAGS 0
|
||||
static JanetStream *make_stream(SOCKET fd, int flags) {
|
||||
u_long iMode = 0;
|
||||
JanetStream *stream = janet_abstract(&StreamAT, sizeof(JanetStream));
|
||||
ioctlsocket(fd, FIONBIO, &iMode);
|
||||
stream->fd = fd;
|
||||
stream->flags = flags;
|
||||
return stream;
|
||||
}
|
||||
#else
|
||||
typedef struct {
|
||||
int fd;
|
||||
int flags;
|
||||
} JanetStream;
|
||||
#define JSOCKCLOSE(x) close(x)
|
||||
#define JSOCKDEFAULT 0
|
||||
#define JLASTERR errno
|
||||
#define JSOCKVALID(x) ((x) >= 0)
|
||||
#define JEINTR EINTR
|
||||
#define JEWOULDBLOCK EWOULDBLOCK
|
||||
#define JEAGAIN EAGAIN
|
||||
#define JPOLL poll
|
||||
#define JPollStruct struct pollfd
|
||||
#define JSock int
|
||||
#define JReadInt ssize_t
|
||||
#ifdef SOCK_CLOEXEC
|
||||
#define JSOCKFLAGS SOCK_CLOEXEC
|
||||
#else
|
||||
#define JSOCKFLAGS 0
|
||||
#endif
|
||||
static JanetStream *make_stream(int fd, int flags) {
|
||||
JanetStream *stream = janet_abstract(&StreamAT, sizeof(JanetStream));
|
||||
#ifndef SOCK_CLOEXEC
|
||||
int extra = O_CLOEXEC;
|
||||
#else
|
||||
int extra = 0;
|
||||
#endif
|
||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK | extra);
|
||||
stream->fd = fd;
|
||||
stream->flags = flags;
|
||||
return stream;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We pass this flag to all send calls to prevent sigpipe */
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
static int janet_stream_close(void *p, size_t s) {
|
||||
(void) s;
|
||||
JanetStream *stream = p;
|
||||
if (!(stream->flags & JANET_STREAM_CLOSED)) {
|
||||
stream->flags |= JANET_STREAM_CLOSED;
|
||||
JSOCKCLOSE(stream->fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event loop
|
||||
*/
|
||||
|
||||
/* This large struct describes a waiting file descriptor, as well
|
||||
* as what to do when we get an event for it. It is a variant type, where
|
||||
* each variant implements a simple state machine. */
|
||||
typedef struct {
|
||||
|
||||
/* File descriptor to listen for events on. */
|
||||
JanetStream *stream;
|
||||
|
||||
/* Fiber to resume when event finishes. Can be NULL, in which case,
|
||||
* no fiber is resumed when event completes. */
|
||||
JanetFiber *fiber;
|
||||
|
||||
/* What kind of event we are listening for.
|
||||
* As more IO functionality get's added, we can
|
||||
* expand this. */
|
||||
enum {
|
||||
JLE_READ_CHUNK,
|
||||
JLE_READ_SOME,
|
||||
JLE_READ_ACCEPT,
|
||||
JLE_CONNECT,
|
||||
JLE_WRITE_FROM_BUFFER,
|
||||
JLE_WRITE_FROM_STRINGLIKE
|
||||
} event_type;
|
||||
|
||||
/* Each variant can have a different payload. */
|
||||
union {
|
||||
|
||||
/* JLE_READ_CHUNK/JLE_READ_SOME */
|
||||
struct {
|
||||
int32_t bytes_left;
|
||||
JanetBuffer *buf;
|
||||
} read_chunk;
|
||||
|
||||
/* JLE_READ_ACCEPT */
|
||||
struct {
|
||||
JanetFunction *handler;
|
||||
} read_accept;
|
||||
|
||||
/* JLE_WRITE_FROM_BUFFER */
|
||||
struct {
|
||||
JanetBuffer *buf;
|
||||
int32_t start;
|
||||
} write_from_buffer;
|
||||
|
||||
/* JLE_WRITE_FROM_STRINGLIKE */
|
||||
struct {
|
||||
const uint8_t *str;
|
||||
int32_t start;
|
||||
} write_from_stringlike;
|
||||
|
||||
} data;
|
||||
|
||||
} JanetLoopFD;
|
||||
|
||||
#define JANET_LOOPFD_MAX 1024
|
||||
|
||||
/* Global loop data */
|
||||
JANET_THREAD_LOCAL JPollStruct janet_vm_pollfds[JANET_LOOPFD_MAX];
|
||||
JANET_THREAD_LOCAL JanetLoopFD janet_vm_loopfds[JANET_LOOPFD_MAX];
|
||||
JANET_THREAD_LOCAL int janet_vm_loop_count;
|
||||
|
||||
/* We could also add/remove gc roots. This is easier for now. */
|
||||
void janet_net_markloop(void) {
|
||||
for (int i = 0; i < janet_vm_loop_count; i++) {
|
||||
JanetLoopFD lfd = janet_vm_loopfds[i];
|
||||
if (lfd.fiber != NULL) {
|
||||
janet_mark(janet_wrap_fiber(lfd.fiber));
|
||||
}
|
||||
janet_mark(janet_wrap_abstract(lfd.stream));
|
||||
switch (lfd.event_type) {
|
||||
default:
|
||||
break;
|
||||
case JLE_READ_CHUNK:
|
||||
case JLE_READ_SOME:
|
||||
janet_mark(janet_wrap_buffer(lfd.data.read_chunk.buf));
|
||||
break;
|
||||
case JLE_READ_ACCEPT:
|
||||
janet_mark(janet_wrap_function(lfd.data.read_accept.handler));
|
||||
break;
|
||||
case JLE_CONNECT:
|
||||
break;
|
||||
case JLE_WRITE_FROM_BUFFER:
|
||||
janet_mark(janet_wrap_buffer(lfd.data.write_from_buffer.buf));
|
||||
break;
|
||||
case JLE_WRITE_FROM_STRINGLIKE:
|
||||
janet_mark(janet_wrap_string(lfd.data.write_from_stringlike.str));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a loop fd to the global event loop */
|
||||
static int janet_loop_schedule(JanetLoopFD lfd, short events) {
|
||||
if (janet_vm_loop_count == JANET_LOOPFD_MAX) {
|
||||
return -1;
|
||||
}
|
||||
int index = janet_vm_loop_count++;
|
||||
janet_vm_loopfds[index] = lfd;
|
||||
janet_vm_pollfds[index].fd = lfd.stream->fd;
|
||||
janet_vm_pollfds[index].events = events;
|
||||
janet_vm_pollfds[index].revents = 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Remove event from list */
|
||||
static void janet_loop_rmindex(int index) {
|
||||
janet_vm_loopfds[index] = janet_vm_loopfds[--janet_vm_loop_count];
|
||||
janet_vm_pollfds[index] = janet_vm_pollfds[janet_vm_loop_count];
|
||||
}
|
||||
|
||||
|
||||
/* Return delta in number of loop fds. Abstracted out so
|
||||
* we can separate out the polling logic */
|
||||
static size_t janet_loop_event(size_t index) {
|
||||
JanetLoopFD *jlfd = janet_vm_loopfds + index;
|
||||
JanetStream *stream = jlfd->stream;
|
||||
JSock fd = stream->fd;
|
||||
int ret = 1;
|
||||
int should_resume = 0;
|
||||
Janet resumeval = janet_wrap_nil();
|
||||
if (stream->flags & JANET_STREAM_CLOSED) {
|
||||
should_resume = 1;
|
||||
ret = 0;
|
||||
} else {
|
||||
switch (jlfd->event_type) {
|
||||
case JLE_READ_CHUNK:
|
||||
case JLE_READ_SOME: {
|
||||
JanetBuffer *buffer = jlfd->data.read_chunk.buf;
|
||||
int32_t bytes_left = jlfd->data.read_chunk.bytes_left;
|
||||
janet_buffer_extra(buffer, bytes_left);
|
||||
if (!(stream->flags & JANET_STREAM_READABLE)) {
|
||||
should_resume = 1;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
JReadInt nread;
|
||||
do {
|
||||
nread = recv(fd, buffer->data + buffer->count, bytes_left, 0);
|
||||
} while (nread == -1 && JLASTERR == JEINTR);
|
||||
if (JLASTERR == JEAGAIN || JLASTERR == JEWOULDBLOCK) {
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nread > 0) {
|
||||
buffer->count += nread;
|
||||
bytes_left -= nread;
|
||||
} else {
|
||||
bytes_left = 0;
|
||||
}
|
||||
if (jlfd->event_type == JLE_READ_SOME || bytes_left == 0) {
|
||||
should_resume = 1;
|
||||
if (nread > 0) {
|
||||
resumeval = janet_wrap_buffer(buffer);
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
jlfd->data.read_chunk.bytes_left = bytes_left;
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JLE_READ_ACCEPT: {
|
||||
JSock connfd = accept(fd, NULL, NULL);
|
||||
if (JSOCKVALID(connfd)) {
|
||||
/* Made a new connection socket */
|
||||
JanetStream *stream = make_stream(connfd, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
|
||||
Janet streamv = janet_wrap_abstract(stream);
|
||||
JanetFunction *handler = jlfd->data.read_accept.handler;
|
||||
Janet out;
|
||||
JanetFiber *fiberp = NULL;
|
||||
/* Launch connection fiber */
|
||||
JanetSignal sig = janet_pcall(handler, 1, &streamv, &out, &fiberp);
|
||||
if (sig != JANET_SIGNAL_OK && sig != JANET_SIGNAL_EVENT) {
|
||||
janet_stacktrace(fiberp, out);
|
||||
}
|
||||
}
|
||||
ret = JANET_LOOPFD_MAX;
|
||||
break;
|
||||
}
|
||||
case JLE_WRITE_FROM_BUFFER:
|
||||
case JLE_WRITE_FROM_STRINGLIKE: {
|
||||
int32_t start, len;
|
||||
const uint8_t *bytes;
|
||||
if (!(stream->flags & JANET_STREAM_WRITABLE)) {
|
||||
should_resume = 1;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
if (jlfd->event_type == JLE_WRITE_FROM_BUFFER) {
|
||||
JanetBuffer *buffer = jlfd->data.write_from_buffer.buf;
|
||||
bytes = buffer->data;
|
||||
len = buffer->count;
|
||||
start = jlfd->data.write_from_buffer.start;
|
||||
} else {
|
||||
bytes = jlfd->data.write_from_stringlike.str;
|
||||
len = janet_string_length(bytes);
|
||||
start = jlfd->data.write_from_stringlike.start;
|
||||
}
|
||||
if (start < len) {
|
||||
int32_t nbytes = len - start;
|
||||
JReadInt nwrote;
|
||||
do {
|
||||
nwrote = send(fd, bytes + start, nbytes, MSG_NOSIGNAL);
|
||||
} while (nwrote == -1 && JLASTERR == JEINTR);
|
||||
if (nwrote > 0) {
|
||||
start += nwrote;
|
||||
} else {
|
||||
start = len;
|
||||
}
|
||||
}
|
||||
if (start >= len) {
|
||||
should_resume = 1;
|
||||
ret = 0;
|
||||
} else {
|
||||
if (jlfd->event_type == JLE_WRITE_FROM_BUFFER) {
|
||||
jlfd->data.write_from_buffer.start = start;
|
||||
} else {
|
||||
jlfd->data.write_from_stringlike.start = start;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JLE_CONNECT: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume a fiber for some events */
|
||||
if (NULL != jlfd->fiber && should_resume) {
|
||||
/* Resume the fiber */
|
||||
Janet out;
|
||||
JanetSignal sig = janet_continue(jlfd->fiber, resumeval, &out);
|
||||
if (sig != JANET_SIGNAL_OK && sig != JANET_SIGNAL_EVENT) {
|
||||
janet_stacktrace(jlfd->fiber, out);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove this handler from the handler pool. */
|
||||
if (should_resume) janet_loop_rmindex((int) index);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void janet_loop1(void) {
|
||||
/* Remove closed file descriptors */
|
||||
for (int i = 0; i < janet_vm_loop_count;) {
|
||||
if (janet_vm_loopfds[i].stream->flags & JANET_STREAM_CLOSED) {
|
||||
janet_loop_rmindex(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
/* Poll */
|
||||
if (janet_vm_loop_count == 0) return;
|
||||
int ready;
|
||||
do {
|
||||
ready = JPOLL(janet_vm_pollfds, janet_vm_loop_count, -1);
|
||||
} while (ready == -1 && JLASTERR == JEINTR);
|
||||
if (ready == -1) return;
|
||||
/* Handle events */
|
||||
for (int i = 0; i < janet_vm_loop_count;) {
|
||||
int revents = janet_vm_pollfds[i].revents;
|
||||
janet_vm_pollfds[i].revents = 0;
|
||||
if ((janet_vm_pollfds[i].events | POLLHUP | POLLERR) & revents) {
|
||||
size_t delta = janet_loop_event(i);
|
||||
i += (int) delta;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void janet_loop(void) {
|
||||
while (janet_vm_loop_count) {
|
||||
janet_loop1();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduling Helpers
|
||||
*/
|
||||
|
||||
#define JANET_SCHED_FSOME 1
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_read(JanetStream *stream, JanetBuffer *buf, int32_t nbytes, int flags) {
|
||||
JanetLoopFD lfd;
|
||||
lfd.stream = stream;
|
||||
lfd.fiber = janet_root_fiber();
|
||||
lfd.event_type = (flags & JANET_SCHED_FSOME) ? JLE_READ_SOME : JLE_READ_CHUNK;
|
||||
lfd.data.read_chunk.buf = buf;
|
||||
lfd.data.read_chunk.bytes_left = nbytes;
|
||||
janet_loop_schedule(lfd, POLLIN);
|
||||
janet_signalv(JANET_SIGNAL_EVENT, janet_wrap_nil());
|
||||
}
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_write_buffer(JanetStream *stream, JanetBuffer *buf) {
|
||||
JanetLoopFD lfd;
|
||||
lfd.stream = stream;
|
||||
lfd.fiber = janet_root_fiber();
|
||||
lfd.event_type = JLE_WRITE_FROM_BUFFER;
|
||||
lfd.data.write_from_buffer.buf = buf;
|
||||
lfd.data.write_from_buffer.start = 0;
|
||||
janet_loop_schedule(lfd, POLLOUT);
|
||||
janet_signalv(JANET_SIGNAL_EVENT, janet_wrap_nil());
|
||||
}
|
||||
|
||||
JANET_NO_RETURN static void janet_sched_write_stringlike(JanetStream *stream, const uint8_t *str) {
|
||||
JanetLoopFD lfd;
|
||||
lfd.stream = stream;
|
||||
lfd.fiber = janet_root_fiber();
|
||||
lfd.event_type = JLE_WRITE_FROM_STRINGLIKE;
|
||||
lfd.data.write_from_stringlike.str = str;
|
||||
lfd.data.write_from_stringlike.start = 0;
|
||||
janet_loop_schedule(lfd, POLLOUT);
|
||||
janet_signalv(JANET_SIGNAL_EVENT, janet_wrap_nil());
|
||||
}
|
||||
|
||||
/* Needs argc >= offset + 2 */
|
||||
static struct addrinfo *janet_get_addrinfo(Janet *argv, int32_t offset) {
|
||||
/* Get host and port */
|
||||
const char *host = janet_getcstring(argv, offset);
|
||||
const char *port;
|
||||
if (janet_checkint(argv[offset + 1])) {
|
||||
port = (const char *)janet_to_string(argv[offset + 1]);
|
||||
} else {
|
||||
port = janet_getcstring(argv, offset + 1);
|
||||
}
|
||||
/* getaddrinfo */
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
int status = getaddrinfo(host, port, &hints, &ai);
|
||||
if (status) {
|
||||
janet_panicf("could not get address info: %s", gai_strerror(status));
|
||||
}
|
||||
return ai;
|
||||
}
|
||||
|
||||
/*
|
||||
* C Funs
|
||||
*/
|
||||
|
||||
static Janet cfun_net_connect(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
|
||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0);
|
||||
|
||||
/* Create socket */
|
||||
JSock sock = socket(ai->ai_family, ai->ai_socktype | JSOCKFLAGS, ai->ai_protocol);
|
||||
if (!JSOCKVALID(sock)) {
|
||||
freeaddrinfo(ai);
|
||||
janet_panic("could not create socket");
|
||||
}
|
||||
|
||||
/* Connect to socket */
|
||||
int status = connect(sock, ai->ai_addr, (int) ai->ai_addrlen);
|
||||
freeaddrinfo(ai);
|
||||
if (status == -1) {
|
||||
JSOCKCLOSE(sock);
|
||||
janet_panic("could not connect to socket");
|
||||
}
|
||||
|
||||
/* Wrap socket in abstract type JanetStream */
|
||||
JanetStream *stream = make_stream(sock, JANET_STREAM_READABLE | JANET_STREAM_WRITABLE);
|
||||
return janet_wrap_abstract(stream);
|
||||
}
|
||||
|
||||
static Janet cfun_net_server(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 3);
|
||||
|
||||
/* Get host, port, and handler*/
|
||||
JanetFunction *fun = janet_getfunction(argv, 2);
|
||||
|
||||
struct addrinfo *ai = janet_get_addrinfo(argv, 0);
|
||||
|
||||
/* Check all addrinfos in a loop for the first that we can bind to. */
|
||||
JSock sfd = JSOCKDEFAULT;
|
||||
struct addrinfo *rp = NULL;
|
||||
for (rp = ai; rp != NULL; rp = rp->ai_next) {
|
||||
sfd = socket(rp->ai_family, rp->ai_socktype | JSOCKFLAGS, rp->ai_protocol);
|
||||
if (!JSOCKVALID(sfd)) continue;
|
||||
/* Set various socket options */
|
||||
int enable = 1;
|
||||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(int)) < 0) {
|
||||
JSOCKCLOSE(sfd);
|
||||
janet_panic("setsockopt(SO_REUSEADDR) failed");
|
||||
}
|
||||
#ifdef SO_NOSIGPIPE
|
||||
if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, &enable, sizeof(int)) < 0) {
|
||||
JSOCKCLOSE(sfd);
|
||||
janet_panic("setsockopt(SO_NOSIGPIPE) failed");
|
||||
}
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) {
|
||||
JSOCKCLOSE(sfd);
|
||||
janet_panic("setsockopt(SO_REUSEPORT) failed");
|
||||
}
|
||||
#endif
|
||||
/* Bind */
|
||||
if (bind(sfd, rp->ai_addr, (int) rp->ai_addrlen) == 0) break;
|
||||
JSOCKCLOSE(sfd);
|
||||
}
|
||||
if (NULL == rp) {
|
||||
freeaddrinfo(ai);
|
||||
janet_panic("could not bind to any sockets");
|
||||
}
|
||||
|
||||
/* listen */
|
||||
int status = listen(sfd, 1024);
|
||||
freeaddrinfo(ai);
|
||||
if (status) {
|
||||
JSOCKCLOSE(sfd);
|
||||
janet_panic("could not listen on file descriptor");
|
||||
}
|
||||
|
||||
/* Put sfd on our loop */
|
||||
JanetLoopFD lfd = {0};
|
||||
lfd.stream = make_stream(sfd, 0);
|
||||
lfd.event_type = JLE_READ_ACCEPT;
|
||||
lfd.data.read_accept.handler = fun;
|
||||
janet_loop_schedule(lfd, POLLIN);
|
||||
|
||||
return janet_wrap_abstract(lfd.stream);
|
||||
}
|
||||
|
||||
static Janet cfun_stream_read(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 3);
|
||||
JanetStream *stream = janet_getabstract(argv, 0, &StreamAT);
|
||||
int32_t n = janet_getnat(argv, 1);
|
||||
JanetBuffer *buffer = janet_optbuffer(argv, argc, 2, 10);
|
||||
janet_sched_read(stream, buffer, n, JANET_SCHED_FSOME);
|
||||
}
|
||||
|
||||
static Janet cfun_stream_chunk(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 3);
|
||||
JanetStream *stream = janet_getabstract(argv, 0, &StreamAT);
|
||||
int32_t n = janet_getnat(argv, 1);
|
||||
JanetBuffer *buffer = janet_optbuffer(argv, argc, 2, 10);
|
||||
janet_sched_read(stream, buffer, n, 0);
|
||||
}
|
||||
|
||||
static Janet cfun_stream_close(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
JanetStream *stream = janet_getabstract(argv, 0, &StreamAT);
|
||||
janet_stream_close(stream, 0);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
static Janet cfun_stream_write(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 2);
|
||||
JanetStream *stream = janet_getabstract(argv, 0, &StreamAT);
|
||||
if (janet_checktype(argv[1], JANET_BUFFER)) {
|
||||
janet_sched_write_buffer(stream, janet_getbuffer(argv, 1));
|
||||
} else {
|
||||
JanetByteView bytes = janet_getbytes(argv, 1);
|
||||
janet_sched_write_stringlike(stream, bytes.bytes);
|
||||
}
|
||||
}
|
||||
|
||||
static const JanetMethod stream_methods[] = {
|
||||
{"chunk", cfun_stream_chunk},
|
||||
{"close", cfun_stream_close},
|
||||
{"read", cfun_stream_read},
|
||||
{"write", cfun_stream_write},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static int janet_stream_getter(void *p, Janet key, Janet *out) {
|
||||
(void) p;
|
||||
if (!janet_checktype(key, JANET_KEYWORD)) return 0;
|
||||
return janet_getmethod(janet_unwrap_keyword(key), stream_methods, out);
|
||||
}
|
||||
|
||||
static const JanetReg net_cfuns[] = {
|
||||
{
|
||||
"net/server", cfun_net_server,
|
||||
JDOC("(net/server host port handler)\n\n"
|
||||
"Start a TCP server. handler is a function that will be called with a stream "
|
||||
"on each connection to the server. Returns a new stream that is neither readable nor "
|
||||
"writeable.")
|
||||
},
|
||||
{
|
||||
"net/read", cfun_stream_read,
|
||||
JDOC("(net/read stream nbytes &opt buf)\n\n"
|
||||
"Read up to n bytes from a stream, suspending the current fiber until the bytes are available. "
|
||||
"If less than n bytes are available (and more than 0), will push those bytes and return early. "
|
||||
"Returns a buffer with up to n more bytes in it.")
|
||||
},
|
||||
{
|
||||
"net/chunk", cfun_stream_chunk,
|
||||
JDOC("(net/chunk stream nbytes &opt buf)\n\n"
|
||||
"Same a net/read, but will wait for all n bytes to arrive rather than return early.")
|
||||
},
|
||||
{
|
||||
"net/write", cfun_stream_write,
|
||||
JDOC("(net/write stream data)\n\n"
|
||||
"Write data to a stream, suspending the current fiber until the write "
|
||||
"completes. Returns stream.")
|
||||
},
|
||||
{
|
||||
"net/close", cfun_stream_close,
|
||||
JDOC("(net/close stream)\n\n"
|
||||
"Close a stream so that no further communication can occur.")
|
||||
},
|
||||
{
|
||||
"net/connect", cfun_net_connect,
|
||||
JDOC("(net/connect host port)\n\n"
|
||||
"Open a connection to communicate with a server. Returns a duplex stream "
|
||||
"that can be used to communicate with the server.")
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
void janet_lib_net(JanetTable *env) {
|
||||
janet_vm_loop_count = 0;
|
||||
#ifdef JANET_WINDOWS
|
||||
WSADATA wsaData;
|
||||
janet_assert(!WSAStartup(MAKEWORD(2, 2), &wsaData), "could not start winsock");
|
||||
#endif
|
||||
janet_core_cfuns(env, NULL, net_cfuns);
|
||||
}
|
||||
|
||||
void janet_net_deinit(void) {
|
||||
#ifdef JANET_WINDOWS
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
@@ -182,9 +182,18 @@ static Janet os_exit(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
#ifndef JANET_REDUCED_OS
|
||||
#ifdef JANET_REDUCED_OS
|
||||
/* Provide a dud os/getenv so boot.janet and init.janet work, but nothing else */
|
||||
|
||||
static Janet os_getenv(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_arity(argc, 1, 2);
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
#else
|
||||
/* Provide full os functionality */
|
||||
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
/* Get env for os_execute */
|
||||
static char **os_execute_env(int32_t argc, const Janet *argv) {
|
||||
char **envp = NULL;
|
||||
@@ -380,26 +389,15 @@ static Janet os_execute(int32_t argc, Janet *argv) {
|
||||
char *const *cargv = (char *const *)child_argv;
|
||||
|
||||
/* Use posix_spawn to spawn new process */
|
||||
|
||||
int use_environ = !janet_flag_at(flags, 0);
|
||||
|
||||
if (use_environ) {
|
||||
janet_lock_environ();
|
||||
}
|
||||
|
||||
pid_t pid;
|
||||
if (janet_flag_at(flags, 1)) {
|
||||
status = posix_spawnp(&pid,
|
||||
child_argv[0], NULL, NULL, cargv,
|
||||
use_environ ? environ : envp);
|
||||
janet_flag_at(flags, 0) ? envp : environ);
|
||||
} else {
|
||||
status = posix_spawn(&pid,
|
||||
child_argv[0], NULL, NULL, cargv,
|
||||
use_environ ? environ : envp);
|
||||
}
|
||||
|
||||
if (use_environ) {
|
||||
janet_unlock_environ();
|
||||
janet_flag_at(flags, 0) ? envp : environ);
|
||||
}
|
||||
|
||||
/* Wait for child */
|
||||
@@ -435,8 +433,6 @@ static Janet os_shell(int32_t argc, Janet *argv) {
|
||||
: janet_wrap_boolean(stat);
|
||||
}
|
||||
|
||||
#endif /* JANET_NO_PROCESSES */
|
||||
|
||||
static Janet os_environ(int32_t argc, Janet *argv) {
|
||||
(void) argv;
|
||||
janet_fixarity(argc, 0);
|
||||
@@ -610,7 +606,7 @@ static Janet os_cryptorand(int32_t argc, Janet *argv) {
|
||||
In both cases, use this fallback path for now... */
|
||||
int rc;
|
||||
int randfd;
|
||||
RETRY_EINTR(randfd, open("/dev/urandom", O_RDONLY | O_CLOEXEC));
|
||||
RETRY_EINTR(randfd, open("/dev/urandom", O_RDONLY));
|
||||
if (randfd < 0)
|
||||
janet_panic(genericerr);
|
||||
while (n > 0) {
|
||||
@@ -757,8 +753,8 @@ static Janet os_mktime(int32_t argc, Janet *argv) {
|
||||
t = mktime(&t_info);
|
||||
} else {
|
||||
/* utc time */
|
||||
#ifdef JANET_NO_UTC_MKTIME
|
||||
janet_panic("os/mktime UTC not supported on this platform");
|
||||
#ifdef __sun
|
||||
janet_panic("os/mktime UTC not supported on Solaris");
|
||||
return janet_wrap_nil();
|
||||
#else
|
||||
t = timegm(&t_info);
|
||||
@@ -772,12 +768,6 @@ static Janet os_mktime(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_number((double)t);
|
||||
}
|
||||
|
||||
#ifdef JANET_NO_SYMLINKS
|
||||
#define j_symlink link
|
||||
#else
|
||||
#define j_symlink symlink
|
||||
#endif
|
||||
|
||||
static Janet os_link(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 2, 3);
|
||||
#ifdef JANET_WINDOWS
|
||||
@@ -788,7 +778,7 @@ static Janet os_link(int32_t argc, Janet *argv) {
|
||||
#else
|
||||
const char *oldpath = janet_getcstring(argv, 0);
|
||||
const char *newpath = janet_getcstring(argv, 1);
|
||||
int res = ((argc == 3 && janet_truthy(argv[2])) ? j_symlink : link)(oldpath, newpath);
|
||||
int res = ((argc == 3 && janet_truthy(argv[2])) ? symlink : link)(oldpath, newpath);
|
||||
if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath);
|
||||
return janet_wrap_nil();
|
||||
#endif
|
||||
@@ -804,14 +794,12 @@ static Janet os_symlink(int32_t argc, Janet *argv) {
|
||||
#else
|
||||
const char *oldpath = janet_getcstring(argv, 0);
|
||||
const char *newpath = janet_getcstring(argv, 1);
|
||||
int res = j_symlink(oldpath, newpath);
|
||||
int res = symlink(oldpath, newpath);
|
||||
if (-1 == res) janet_panicf("%s: %s -> %s", strerror(errno), oldpath, newpath);
|
||||
return janet_wrap_nil();
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef j_symlink
|
||||
|
||||
static Janet os_mkdir(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
const char *path = janet_getcstring(argv, 0);
|
||||
@@ -877,7 +865,6 @@ static Janet os_remove(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
#ifndef JANET_NO_SYMLINKS
|
||||
static Janet os_readlink(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
#ifdef JANET_WINDOWS
|
||||
@@ -894,7 +881,6 @@ static Janet os_readlink(int32_t argc, Janet *argv) {
|
||||
return janet_stringv((const uint8_t *)buffer, len);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JANET_WINDOWS
|
||||
|
||||
@@ -1163,7 +1149,6 @@ static Janet os_chmod(int32_t argc, Janet *argv) {
|
||||
return janet_wrap_nil();
|
||||
}
|
||||
|
||||
#ifndef JANET_NO_UMASK
|
||||
static Janet os_umask(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
int mask = (int) os_getmode(argv, 0);
|
||||
@@ -1174,7 +1159,6 @@ static Janet os_umask(int32_t argc, Janet *argv) {
|
||||
#endif
|
||||
return janet_wrap_integer(janet_perm_to_unix(res));
|
||||
}
|
||||
#endif
|
||||
|
||||
static Janet os_dir(int32_t argc, Janet *argv) {
|
||||
janet_arity(argc, 1, 2);
|
||||
@@ -1224,9 +1208,9 @@ static Janet os_rename(int32_t argc, Janet *argv) {
|
||||
|
||||
static Janet os_realpath(int32_t argc, Janet *argv) {
|
||||
janet_fixarity(argc, 1);
|
||||
#ifdef JANET_NO_REALPATH
|
||||
#ifdef JANET_WINDOWS
|
||||
(void) argv;
|
||||
janet_panic("os/realpath not supported on this platform");
|
||||
janet_panic("os/realpath not supported on Windows");
|
||||
#else
|
||||
const char *src = janet_getcstring(argv, 0);
|
||||
char *dest = realpath(src, NULL);
|
||||
@@ -1267,8 +1251,12 @@ static const JanetReg os_cfuns[] = {
|
||||
"\t:freebsd\n"
|
||||
"\t:openbsd\n"
|
||||
"\t:netbsd\n"
|
||||
"\t:posix - A POSIX compatible system (default)\n\n"
|
||||
"May also return a custom keyword specified at build time.")
|
||||
"\t:posix - A POSIX compatible system (default)")
|
||||
},
|
||||
{
|
||||
"os/getenv", os_getenv,
|
||||
JDOC("(os/getenv variable &opt dflt)\n\n"
|
||||
"Get the string value of an environment variable.")
|
||||
},
|
||||
{
|
||||
"os/arch", os_arch,
|
||||
@@ -1288,16 +1276,11 @@ static const JanetReg os_cfuns[] = {
|
||||
JDOC("(os/environ)\n\n"
|
||||
"Get a copy of the os environment table.")
|
||||
},
|
||||
{
|
||||
"os/getenv", os_getenv,
|
||||
JDOC("(os/getenv variable &opt dflt)\n\n"
|
||||
"Get the string value of an environment variable.")
|
||||
},
|
||||
{
|
||||
"os/dir", os_dir,
|
||||
JDOC("(os/dir dir &opt array)\n\n"
|
||||
"Iterate over files and subdirectories in a directory. Returns an array of paths parts, "
|
||||
"with only the file name or directory name and no prefix.")
|
||||
"with only the filename or directory name and no prefix.")
|
||||
},
|
||||
{
|
||||
"os/stat", os_stat,
|
||||
@@ -1316,7 +1299,7 @@ static const JanetReg os_cfuns[] = {
|
||||
"\t:blocks - number of blocks in file. 0 on windows\n"
|
||||
"\t:blocksize - size of blocks in file. 0 on windows\n"
|
||||
"\t:accessed - timestamp when file last accessed\n"
|
||||
"\t:changed - timestamp when file last changed (permissions changed)\n"
|
||||
"\t:changed - timestamp when file last chnaged (permissions changed)\n"
|
||||
"\t:modified - timestamp when file last modified (content changed)\n")
|
||||
},
|
||||
{
|
||||
@@ -1343,13 +1326,11 @@ static const JanetReg os_cfuns[] = {
|
||||
JDOC("(os/cd path)\n\n"
|
||||
"Change current directory to path. Returns nil on success, errors on failure.")
|
||||
},
|
||||
#ifndef JANET_NO_UMASK
|
||||
{
|
||||
"os/umask", os_umask,
|
||||
JDOC("(os/umask mask)\n\n"
|
||||
"Set a new umask, returns the old umask.")
|
||||
},
|
||||
#endif
|
||||
{
|
||||
"os/mkdir", os_mkdir,
|
||||
JDOC("(os/mkdir path)\n\n"
|
||||
@@ -1375,7 +1356,6 @@ static const JanetReg os_cfuns[] = {
|
||||
"Iff symlink is falsey or not provided, "
|
||||
"creates a hard link. Does not work on Windows.")
|
||||
},
|
||||
#ifndef JANET_NO_SYMLINKS
|
||||
{
|
||||
"os/symlink", os_symlink,
|
||||
JDOC("(os/symlink oldpath newpath)\n\n"
|
||||
@@ -1386,8 +1366,6 @@ static const JanetReg os_cfuns[] = {
|
||||
JDOC("(os/readlink path)\n\n"
|
||||
"Read the contents of a symbolic link. Does not work on Windows.\n")
|
||||
},
|
||||
#endif
|
||||
#ifndef JANET_NO_PROCESSES
|
||||
{
|
||||
"os/execute", os_execute,
|
||||
JDOC("(os/execute args &opts flags env)\n\n"
|
||||
@@ -1405,7 +1383,6 @@ static const JanetReg os_cfuns[] = {
|
||||
JDOC("(os/shell str)\n\n"
|
||||
"Pass a command string str directly to the system shell.")
|
||||
},
|
||||
#endif
|
||||
{
|
||||
"os/setenv", os_setenv,
|
||||
JDOC("(os/setenv variable value)\n\n"
|
||||
|
||||
@@ -790,7 +790,7 @@ static int parsermark(void *p, size_t size) {
|
||||
janet_mark(parser->args[i]);
|
||||
}
|
||||
if (parser->flag & JANET_PARSER_GENERATED_ERROR) {
|
||||
janet_mark(janet_wrap_string((const uint8_t *) parser->error));
|
||||
janet_mark(janet_wrap_string(parser->error));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -928,7 +928,7 @@ static Janet cfun_parse_error(int32_t argc, Janet *argv) {
|
||||
const char *err = janet_parser_error(p);
|
||||
if (err) {
|
||||
return (p->flag & JANET_PARSER_GENERATED_ERROR)
|
||||
? janet_wrap_string((const uint8_t *) err)
|
||||
? janet_wrap_string(err)
|
||||
: janet_cstringv(err);
|
||||
}
|
||||
return janet_wrap_nil();
|
||||
@@ -1139,7 +1139,7 @@ static const JanetReg parse_cfuns[] = {
|
||||
"parser/new", cfun_parse_parser,
|
||||
JDOC("(parser/new)\n\n"
|
||||
"Creates and returns a new parser object. Parsers are state machines "
|
||||
"that can receive bytes, and generate a stream of values.")
|
||||
"that can receive bytes, and generate a stream of janet values.")
|
||||
},
|
||||
{
|
||||
"parser/clone", cfun_parse_clone,
|
||||
|
||||
@@ -413,38 +413,6 @@ tail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
case RULE_LENPREFIX: {
|
||||
int oldmode = s->mode;
|
||||
s->mode = PEG_MODE_NORMAL;
|
||||
const uint8_t *next_text;
|
||||
CapState cs = cap_save(s);
|
||||
down1(s);
|
||||
next_text = peg_rule(s, s->bytecode + rule[1], text);
|
||||
up1(s);
|
||||
if (NULL == next_text) return NULL;
|
||||
s->mode = oldmode;
|
||||
int32_t num_sub_captures = s->captures->count - cs.cap;
|
||||
Janet lencap;
|
||||
if (num_sub_captures <= 0 ||
|
||||
(lencap = s->captures->data[cs.cap], !janet_checkint(lencap))) {
|
||||
cap_load(s, cs);
|
||||
return NULL;
|
||||
}
|
||||
int32_t nrep = janet_unwrap_integer(lencap);
|
||||
/* drop captures from len pattern */
|
||||
cap_load(s, cs);
|
||||
for (int32_t i = 0; i < nrep; i++) {
|
||||
down1(s);
|
||||
next_text = peg_rule(s, s->bytecode + rule[2], next_text);
|
||||
up1(s);
|
||||
if (NULL == next_text) {
|
||||
cap_load(s, cs);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return next_text;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,9 +657,6 @@ static void spec_if(Builder *b, int32_t argc, const Janet *argv) {
|
||||
static void spec_ifnot(Builder *b, int32_t argc, const Janet *argv) {
|
||||
spec_branch(b, argc, argv, RULE_IFNOT);
|
||||
}
|
||||
static void spec_lenprefix(Builder *b, int32_t argc, const Janet *argv) {
|
||||
spec_branch(b, argc, argv, RULE_LENPREFIX);
|
||||
}
|
||||
|
||||
static void spec_between(Builder *b, int32_t argc, const Janet *argv) {
|
||||
peg_fixarity(b, argc, 3);
|
||||
@@ -882,7 +847,6 @@ static const SpecialPair peg_specials[] = {
|
||||
{"group", spec_group},
|
||||
{"if", spec_if},
|
||||
{"if-not", spec_ifnot},
|
||||
{"lenprefix", spec_lenprefix},
|
||||
{"look", spec_look},
|
||||
{"not", spec_not},
|
||||
{"opt", spec_opt},
|
||||
@@ -1136,7 +1100,6 @@ static void *peg_unmarshal(JanetMarshalContext *ctx) {
|
||||
break;
|
||||
case RULE_IF:
|
||||
case RULE_IFNOT:
|
||||
case RULE_LENPREFIX:
|
||||
/* [rule_a, rule_b (b if not a)] */
|
||||
if (rule[1] >= blen) goto bad;
|
||||
if (rule[2] >= blen) goto bad;
|
||||
@@ -1320,7 +1283,8 @@ static const JanetReg peg_cfuns[] = {
|
||||
"peg/match", cfun_peg_match,
|
||||
JDOC("(peg/match peg text &opt start & args)\n\n"
|
||||
"Match a Parsing Expression Grammar to a byte string and return an array of captured values. "
|
||||
"Returns nil if text does not match the language defined by peg. The syntax of PEGs is documented on the Janet website.")
|
||||
"Returns nil if text does not match the language defined by peg. The syntax of PEGs are very "
|
||||
"similar to those defined by LPeg, and have similar capabilities.")
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -155,9 +155,6 @@ static void janet_escape_string_impl(JanetBuffer *buffer, const uint8_t *str, in
|
||||
case '\\':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\\\", 2);
|
||||
break;
|
||||
case '\t':
|
||||
janet_buffer_push_bytes(buffer, (const uint8_t *)"\\t", 2);
|
||||
break;
|
||||
default:
|
||||
if (c < 32 || c > 126) {
|
||||
uint8_t buf[4];
|
||||
@@ -530,7 +527,7 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
if (!isarray && !(S->flags & JANET_PRETTY_ONELINE) && len >= JANET_PRETTY_IND_ONELINE)
|
||||
janet_buffer_push_u8(S->buffer, ' ');
|
||||
if (is_dict_value && len >= JANET_PRETTY_IND_ONELINE) print_newline(S, 0);
|
||||
if (len > JANET_PRETTY_ARRAY_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
|
||||
if (len > JANET_PRETTY_ARRAY_LIMIT) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i) print_newline(S, 0);
|
||||
janet_pretty_one(S, arr[i], 0);
|
||||
@@ -594,7 +591,7 @@ static void janet_pretty_one(struct pretty *S, Janet x, int is_dict_value) {
|
||||
if (is_dict_value && len >= JANET_PRETTY_DICT_ONELINE) print_newline(S, 0);
|
||||
for (i = 0; i < cap; i++) {
|
||||
if (!janet_checktype(kvs[i].key, JANET_NIL)) {
|
||||
if (counter == JANET_PRETTY_DICT_LIMIT && !(S->flags & JANET_PRETTY_NOTRUNC)) {
|
||||
if (counter == JANET_PRETTY_DICT_LIMIT) {
|
||||
print_newline(S, 0);
|
||||
janet_buffer_push_cstring(S->buffer, "...");
|
||||
break;
|
||||
@@ -754,6 +751,7 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': {
|
||||
int32_t n = va_arg(args, long);
|
||||
@@ -804,10 +802,6 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
pushtypes(b, types);
|
||||
break;
|
||||
}
|
||||
case 'M':
|
||||
case 'm':
|
||||
case 'N':
|
||||
case 'n':
|
||||
case 'Q':
|
||||
case 'q':
|
||||
case 'P':
|
||||
@@ -815,13 +809,11 @@ void janet_formatbv(JanetBuffer *b, const char *format, va_list args) {
|
||||
int depth = atoi(precision);
|
||||
if (depth < 1) depth = 4;
|
||||
char d = c[-1];
|
||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||
int has_notrunc = (d == 'M') || (d == 'm') || (d == 'N') || (d == 'n');
|
||||
int has_color = (d == 'P') || (d == 'Q');
|
||||
int has_oneline = (d == 'Q') || (d == 'q');
|
||||
int flags = 0;
|
||||
flags |= has_color ? JANET_PRETTY_COLOR : 0;
|
||||
flags |= has_oneline ? JANET_PRETTY_ONELINE : 0;
|
||||
flags |= has_notrunc ? JANET_PRETTY_NOTRUNC : 0;
|
||||
janet_pretty_(b, depth, flags, va_arg(args, Janet), startlen);
|
||||
break;
|
||||
}
|
||||
@@ -912,6 +904,7 @@ void janet_buffer_format(
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': {
|
||||
int32_t n = janet_getinteger(argv, arg);
|
||||
@@ -953,24 +946,19 @@ void janet_buffer_format(
|
||||
janet_description_b(b, argv[arg]);
|
||||
break;
|
||||
}
|
||||
case 'M':
|
||||
case 'm':
|
||||
case 'N':
|
||||
case 'n':
|
||||
case 'Q':
|
||||
case 'q':
|
||||
case 'P':
|
||||
case 'p': { /* janet pretty , precision = depth */
|
||||
int depth = atoi(precision);
|
||||
if (depth < 1) depth = 4;
|
||||
char d = strfrmt[-1];
|
||||
int has_color = (d == 'P') || (d == 'Q') || (d == 'M') || (d == 'N');
|
||||
int has_oneline = (d == 'Q') || (d == 'q') || (d == 'N') || (d == 'n');
|
||||
int has_notrunc = (d == 'M') || (d == 'm') || (d == 'N') || (d == 'n');
|
||||
if (depth < 1)
|
||||
depth = 4;
|
||||
char c = strfrmt[-1];
|
||||
int has_color = (c == 'P') || (c == 'Q');
|
||||
int has_oneline = (c == 'Q') || (c == 'q');
|
||||
int flags = 0;
|
||||
flags |= has_color ? JANET_PRETTY_COLOR : 0;
|
||||
flags |= has_oneline ? JANET_PRETTY_ONELINE : 0;
|
||||
flags |= has_notrunc ? JANET_PRETTY_NOTRUNC : 0;
|
||||
janet_pretty_(b, depth, flags, argv[arg], startlen);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ void janetc_regalloc_free(JanetcRegisterAllocator *ra, int32_t reg) {
|
||||
int32_t janetc_regalloc_temp(JanetcRegisterAllocator *ra, JanetcRegisterTemp nth) {
|
||||
int32_t oldmax = ra->max;
|
||||
if (ra->regtemps & (1 << nth)) {
|
||||
JANET_EXIT("regtemp already allocated");
|
||||
janet_exit("regtemp already allocated");
|
||||
}
|
||||
ra->regtemps |= 1 << nth;
|
||||
int32_t reg = janetc_regalloc_1(ra);
|
||||
|
||||
@@ -50,7 +50,7 @@ int janet_dobytes(JanetTable *env, const uint8_t *bytes, int32_t len, const char
|
||||
JanetFiber *fiber = janet_fiber(f, 64, 0, NULL);
|
||||
fiber->env = env;
|
||||
JanetSignal status = janet_continue(fiber, janet_wrap_nil(), &ret);
|
||||
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
||||
if (status != JANET_SIGNAL_OK) {
|
||||
janet_stacktrace(fiber, ret);
|
||||
errflags |= 0x01;
|
||||
done = 1;
|
||||
|
||||
@@ -43,7 +43,6 @@ extern JANET_THREAD_LOCAL int janet_vm_stackn;
|
||||
/* The current running fiber on the current thread.
|
||||
* Set and unset by janet_run. */
|
||||
extern JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber;
|
||||
extern JANET_THREAD_LOCAL JanetFiber *janet_vm_root_fiber;
|
||||
|
||||
/* The current pointer to the inner most jmp_buf. The current
|
||||
* return point for panics. */
|
||||
|
||||
@@ -542,7 +542,7 @@ static const JanetReg string_cfuns[] = {
|
||||
{
|
||||
"string/from-bytes", cfun_string_frombytes,
|
||||
JDOC("(string/from-bytes & byte-vals)\n\n"
|
||||
"Creates a string from integer parameters with byte values. All integers "
|
||||
"Creates a string from integer params with byte values. All integers "
|
||||
"will be coerced to the range of 1 byte 0-255.")
|
||||
},
|
||||
{
|
||||
@@ -573,7 +573,7 @@ static const JanetReg string_cfuns[] = {
|
||||
},
|
||||
{
|
||||
"string/find-all", cfun_string_findall,
|
||||
JDOC("(string/find-all patt str)\n\n"
|
||||
JDOC("(string/find patt str)\n\n"
|
||||
"Searches for all instances of pattern patt in string "
|
||||
"str. Returns an array of all indices of found patterns. Overlapping "
|
||||
"instances of the pattern are not counted, meaning a byte in string "
|
||||
@@ -627,7 +627,7 @@ static const JanetReg string_cfuns[] = {
|
||||
{
|
||||
"string/format", cfun_string_format,
|
||||
JDOC("(string/format format & values)\n\n"
|
||||
"Similar to snprintf, but specialized for operating with Janet values. Returns "
|
||||
"Similar to snprintf, but specialized for operating with janet. Returns "
|
||||
"a new string.")
|
||||
},
|
||||
{
|
||||
|
||||
@@ -465,15 +465,11 @@ static int thread_worker(JanetMailboxPair *pair) {
|
||||
Janet argv[1] = { parentv };
|
||||
fiber = janet_fiber(func, 64, 1, argv);
|
||||
JanetSignal sig = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||
if (sig != JANET_SIGNAL_OK && sig < JANET_SIGNAL_USER0) {
|
||||
if (sig != JANET_SIGNAL_OK) {
|
||||
janet_eprintf("in thread %v: ", janet_wrap_abstract(janet_make_thread(pair->newbox, encode)));
|
||||
janet_stacktrace(fiber, out);
|
||||
}
|
||||
|
||||
#ifdef JANET_NET
|
||||
janet_loop();
|
||||
#endif
|
||||
|
||||
/* Normal exit */
|
||||
destroy_mailbox_pair(pair);
|
||||
janet_deinit();
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
#include <errno.h>
|
||||
|
||||
/* Handle runtime errors */
|
||||
#ifndef JANET_EXIT
|
||||
#ifndef janet_exit
|
||||
#include <stdio.h>
|
||||
#define JANET_EXIT(m) do { \
|
||||
fprintf(stderr, "C runtime error at line %d in file %s: %s\n",\
|
||||
#define janet_exit(m) do { \
|
||||
printf("C runtime error at line %d in file %s: %s\n",\
|
||||
__LINE__,\
|
||||
__FILE__,\
|
||||
(m));\
|
||||
@@ -44,13 +44,13 @@
|
||||
#endif
|
||||
|
||||
#define janet_assert(c, m) do { \
|
||||
if (!(c)) JANET_EXIT((m)); \
|
||||
if (!(c)) janet_exit((m)); \
|
||||
} while (0)
|
||||
|
||||
/* What to do when out of memory */
|
||||
#ifndef JANET_OUT_OF_MEMORY
|
||||
#include <stdio.h>
|
||||
#define JANET_OUT_OF_MEMORY do { fprintf(stderr, "janet out of memory\n"); exit(1); } while (0)
|
||||
#define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0)
|
||||
#endif
|
||||
|
||||
/* Omit docstrings in some builds */
|
||||
@@ -126,10 +126,5 @@ void janet_lib_inttypes(JanetTable *env);
|
||||
#ifdef JANET_THREADS
|
||||
void janet_lib_thread(JanetTable *env);
|
||||
#endif
|
||||
#ifdef JANET_NET
|
||||
void janet_lib_net(JanetTable *env);
|
||||
void janet_net_deinit(void);
|
||||
void janet_net_markloop(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,6 @@ JANET_THREAD_LOCAL JanetTable *janet_vm_registry;
|
||||
JANET_THREAD_LOCAL JanetTable *janet_vm_abstract_registry;
|
||||
JANET_THREAD_LOCAL int janet_vm_stackn = 0;
|
||||
JANET_THREAD_LOCAL JanetFiber *janet_vm_fiber = NULL;
|
||||
JANET_THREAD_LOCAL JanetFiber *janet_vm_root_fiber = NULL;
|
||||
JANET_THREAD_LOCAL Janet *janet_vm_return_reg = NULL;
|
||||
JANET_THREAD_LOCAL jmp_buf *janet_vm_jmp_buf = NULL;
|
||||
|
||||
@@ -1245,9 +1244,7 @@ Janet janet_call(JanetFunction *fun, int32_t argc, const Janet *argv) {
|
||||
janet_vm_stackn = oldn;
|
||||
janet_gcunlock(handle);
|
||||
|
||||
if (signal != JANET_SIGNAL_OK) {
|
||||
janet_panicv(*janet_vm_return_reg);
|
||||
}
|
||||
if (signal != JANET_SIGNAL_OK) janet_panicv(*janet_vm_return_reg);
|
||||
|
||||
return *janet_vm_return_reg;
|
||||
}
|
||||
@@ -1279,12 +1276,10 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
|
||||
|
||||
/* Continue child fiber if it exists */
|
||||
if (fiber->child) {
|
||||
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
|
||||
JanetFiber *child = fiber->child;
|
||||
janet_vm_stackn++;
|
||||
JanetSignal sig = janet_continue(child, in, &in);
|
||||
janet_vm_stackn--;
|
||||
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
|
||||
if (sig != JANET_SIGNAL_OK && !(child->flags & (1 << sig))) {
|
||||
*out = in;
|
||||
return sig;
|
||||
@@ -1313,7 +1308,6 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
|
||||
Janet *old_vm_return_reg = janet_vm_return_reg;
|
||||
|
||||
/* Setup fiber */
|
||||
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
|
||||
janet_vm_fiber = fiber;
|
||||
janet_gcroot(janet_wrap_fiber(fiber));
|
||||
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
|
||||
@@ -1339,7 +1333,6 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
|
||||
janet_gcunroot(janet_wrap_fiber(fiber));
|
||||
|
||||
/* Restore global state */
|
||||
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
|
||||
janet_vm_gc_suspend = handle;
|
||||
janet_vm_fiber = old_vm_fiber;
|
||||
janet_vm_stackn = oldn;
|
||||
@@ -1421,10 +1414,6 @@ int janet_init(void) {
|
||||
janet_vm_core_env = NULL;
|
||||
/* Seed RNG */
|
||||
janet_rng_seed(janet_default_rng(), 0);
|
||||
/* Fibers */
|
||||
janet_vm_fiber = NULL;
|
||||
janet_vm_root_fiber = NULL;
|
||||
janet_vm_stackn = 0;
|
||||
/* Threads */
|
||||
#ifdef JANET_THREADS
|
||||
janet_threads_init();
|
||||
@@ -1444,12 +1433,7 @@ void janet_deinit(void) {
|
||||
janet_vm_abstract_registry = NULL;
|
||||
janet_vm_core_env = NULL;
|
||||
free(janet_vm_traversal_base);
|
||||
janet_vm_fiber = NULL;
|
||||
janet_vm_root_fiber = NULL;
|
||||
#ifdef JANET_THREADS
|
||||
janet_threads_deinit();
|
||||
#endif
|
||||
#ifdef JANET_NET
|
||||
janet_net_deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -27,12 +27,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Variable length arrays are ok */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4200 )
|
||||
#endif
|
||||
|
||||
/***** START SECTION CONFIG *****/
|
||||
|
||||
#include "janetconf.h"
|
||||
@@ -130,17 +124,6 @@ extern "C" {
|
||||
/* Check emscripten */
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#define JANET_NO_DYNAMIC_MODULES
|
||||
#define JANET_NO_PROCESSES
|
||||
#endif
|
||||
|
||||
/* Check sun */
|
||||
#ifdef __sun
|
||||
#define JANET_NO_UTC_MKTIME
|
||||
#endif
|
||||
|
||||
/* Add some windows flags */
|
||||
#ifdef JANET_WINDOWS
|
||||
#define JANET_NO_REALPATH
|
||||
#endif
|
||||
|
||||
/* Define how global janet state is declared */
|
||||
@@ -176,11 +159,6 @@ extern "C" {
|
||||
#define JANET_TYPED_ARRAY
|
||||
#endif
|
||||
|
||||
/* Enable or disable networking */
|
||||
#if !defined(JANET_NO_NET) && !defined(__EMSCRIPTEN__)
|
||||
#define JANET_NET
|
||||
#endif
|
||||
|
||||
/* Enable or disable large int types (for now 64 bit, maybe 128 / 256 bit integer types) */
|
||||
#ifndef JANET_NO_INT_TYPES
|
||||
#define JANET_INT_TYPES
|
||||
@@ -311,8 +289,6 @@ typedef enum {
|
||||
JANET_SIGNAL_USER9
|
||||
} JanetSignal;
|
||||
|
||||
#define JANET_SIGNAL_EVENT JANET_SIGNAL_USER9
|
||||
|
||||
/* Fiber statuses - mostly corresponds to signals. */
|
||||
typedef enum {
|
||||
JANET_STATUS_DEAD,
|
||||
@@ -333,6 +309,14 @@ typedef enum {
|
||||
JANET_STATUS_ALIVE
|
||||
} JanetFiberStatus;
|
||||
|
||||
#ifdef JANET_NANBOX_64
|
||||
typedef union Janet Janet;
|
||||
#elif defined(JANET_NANBOX_32)
|
||||
typedef union Janet Janet;
|
||||
#else
|
||||
typedef struct Janet Janet;
|
||||
#endif
|
||||
|
||||
/* Use type punning for GC objects */
|
||||
typedef struct JanetGCObject JanetGCObject;
|
||||
|
||||
@@ -363,6 +347,15 @@ typedef struct JanetByteView JanetByteView;
|
||||
typedef struct JanetDictView JanetDictView;
|
||||
typedef struct JanetRange JanetRange;
|
||||
typedef struct JanetRNG JanetRNG;
|
||||
typedef Janet(*JanetCFunction)(int32_t argc, Janet *argv);
|
||||
|
||||
/* String and other aliased pointer types */
|
||||
typedef const uint8_t *JanetString;
|
||||
typedef const uint8_t *JanetSymbol;
|
||||
typedef const uint8_t *JanetKeyword;
|
||||
typedef const Janet *JanetTuple;
|
||||
typedef const JanetKV *JanetStruct;
|
||||
typedef void *JanetAbstract;
|
||||
|
||||
/* Basic types for all Janet Values */
|
||||
typedef enum JanetType {
|
||||
@@ -384,61 +377,6 @@ typedef enum JanetType {
|
||||
JANET_POINTER
|
||||
} JanetType;
|
||||
|
||||
/* Recursive type (Janet) */
|
||||
#ifdef JANET_NANBOX_64
|
||||
typedef union Janet Janet;
|
||||
union Janet {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
double number;
|
||||
void *pointer;
|
||||
};
|
||||
#elif defined(JANET_NANBOX_32)
|
||||
typedef union Janet Janet;
|
||||
union Janet {
|
||||
struct {
|
||||
#ifdef JANET_BIG_ENDIAN
|
||||
uint32_t type;
|
||||
union {
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
} payload;
|
||||
#else
|
||||
union {
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
} payload;
|
||||
uint32_t type;
|
||||
#endif
|
||||
} tagged;
|
||||
double number;
|
||||
uint64_t u64;
|
||||
};
|
||||
#else
|
||||
typedef struct Janet Janet;
|
||||
struct Janet {
|
||||
union {
|
||||
uint64_t u64;
|
||||
double number;
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
const void *cpointer;
|
||||
} as;
|
||||
JanetType type;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* C functions */
|
||||
typedef Janet(*JanetCFunction)(int32_t argc, Janet *argv);
|
||||
|
||||
/* String and other aliased pointer types */
|
||||
typedef const uint8_t *JanetString;
|
||||
typedef const uint8_t *JanetSymbol;
|
||||
typedef const uint8_t *JanetKeyword;
|
||||
typedef const Janet *JanetTuple;
|
||||
typedef const JanetKV *JanetStruct;
|
||||
typedef void *JanetAbstract;
|
||||
|
||||
#define JANET_COUNT_TYPES (JANET_POINTER + 1)
|
||||
|
||||
/* Type flags */
|
||||
@@ -547,6 +485,13 @@ JANET_API Janet janet_wrap_integer(int32_t x);
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* 64 Nanboxed Janet value */
|
||||
union Janet {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
double number;
|
||||
void *pointer;
|
||||
};
|
||||
#define janet_u64(x) ((x).u64)
|
||||
|
||||
#define JANET_NANBOX_TAGBITS 0xFFFF800000000000llu
|
||||
@@ -631,6 +576,27 @@ JANET_API Janet janet_nanbox_from_bits(uint64_t bits);
|
||||
|
||||
#elif defined(JANET_NANBOX_32)
|
||||
|
||||
/* 32 bit nanboxed janet */
|
||||
union Janet {
|
||||
struct {
|
||||
#ifdef JANET_BIG_ENDIAN
|
||||
uint32_t type;
|
||||
union {
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
} payload;
|
||||
#else
|
||||
union {
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
} payload;
|
||||
uint32_t type;
|
||||
#endif
|
||||
} tagged;
|
||||
double number;
|
||||
uint64_t u64;
|
||||
};
|
||||
|
||||
#define JANET_DOUBLE_OFFSET 0xFFFF
|
||||
|
||||
#define janet_u64(x) ((x).u64)
|
||||
@@ -681,6 +647,18 @@ JANET_API Janet janet_nanbox32_from_tagp(uint32_t tag, void *pointer);
|
||||
|
||||
#else
|
||||
|
||||
/* A general janet value type for more standard C */
|
||||
struct Janet {
|
||||
union {
|
||||
uint64_t u64;
|
||||
double number;
|
||||
int32_t integer;
|
||||
void *pointer;
|
||||
const void *cpointer;
|
||||
} as;
|
||||
JanetType type;
|
||||
};
|
||||
|
||||
#define janet_u64(x) ((x).as.u64)
|
||||
#define janet_type(x) ((x).type)
|
||||
#define janet_checktype(x, t) ((x).type == (t))
|
||||
@@ -1133,11 +1111,6 @@ extern enum JanetInstructionType janet_instructions[JOP_INSTRUCTION_COUNT];
|
||||
|
||||
/***** START SECTION MAIN *****/
|
||||
|
||||
/* Event Loop */
|
||||
#ifdef JANET_NET
|
||||
JANET_API void janet_loop(void);
|
||||
#endif
|
||||
|
||||
/* Parsing */
|
||||
extern JANET_API const JanetAbstractType janet_parser_type;
|
||||
JANET_API void janet_parser_init(JanetParser *parser);
|
||||
@@ -1313,7 +1286,6 @@ JANET_API JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity, int32
|
||||
JANET_API JanetFiber *janet_fiber_reset(JanetFiber *fiber, JanetFunction *callee, int32_t argc, const Janet *argv);
|
||||
JANET_API JanetFiberStatus janet_fiber_status(JanetFiber *fiber);
|
||||
JANET_API JanetFiber *janet_current_fiber(void);
|
||||
JANET_API JanetFiber *janet_root_fiber(void);
|
||||
|
||||
/* Treat similar types through uniform interfaces for iteration */
|
||||
JANET_API int janet_indexed_view(Janet seq, const Janet **data, int32_t *len);
|
||||
@@ -1373,7 +1345,6 @@ JANET_API int janet_verify(JanetFuncDef *def);
|
||||
/* Pretty printing */
|
||||
#define JANET_PRETTY_COLOR 1
|
||||
#define JANET_PRETTY_ONELINE 2
|
||||
#define JANET_PRETTY_NOTRUNC 4
|
||||
JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, Janet x);
|
||||
|
||||
/* Misc */
|
||||
@@ -1587,7 +1558,6 @@ typedef enum {
|
||||
RULE_ERROR, /* [rule] */
|
||||
RULE_DROP, /* [rule] */
|
||||
RULE_BACKMATCH, /* [tag] */
|
||||
RULE_LENPREFIX, /* [rule_a, rule_b (repeat rule_b rule_a times)] */
|
||||
} JanetPegOpcode;
|
||||
|
||||
typedef struct {
|
||||
@@ -1684,11 +1654,6 @@ JANET_API int janet_thread_send(JanetThread *thread, Janet msg, double timeout);
|
||||
|
||||
/***** END SECTION MAIN *****/
|
||||
|
||||
/* Re-enable popped variable length array warnings */
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1011,15 +1011,10 @@ int main(int argc, char **argv) {
|
||||
JanetFiber *fiber = janet_fiber(janet_unwrap_function(mainfun), 64, 1, mainargs);
|
||||
fiber->env = env;
|
||||
status = janet_continue(fiber, janet_wrap_nil(), &out);
|
||||
if (status != JANET_SIGNAL_OK && status != JANET_SIGNAL_EVENT) {
|
||||
if (status != JANET_SIGNAL_OK) {
|
||||
janet_stacktrace(fiber, out);
|
||||
}
|
||||
|
||||
#ifdef JANET_NET
|
||||
status = JANET_SIGNAL_OK;
|
||||
janet_loop();
|
||||
#endif
|
||||
|
||||
/* Deinitialize vm */
|
||||
janet_deinit();
|
||||
janet_line_deinit();
|
||||
|
||||
1
test/install/.gitignore
vendored
1
test/install/.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
/build
|
||||
/modpath
|
||||
.cache
|
||||
.manifests
|
||||
json.*
|
||||
|
||||
@@ -252,33 +252,4 @@ neldb\0\0\0\xD8\x05printG\x01\0\xDE\xDE\xDE'\x03\0marshal_tes/\x02
|
||||
(assert (< [1 2 3] [1 2 3 -1]) "tuple comparison 5")
|
||||
(assert (> [1 2 3] [1 2]) "tuple comparison 6")
|
||||
|
||||
# Lenprefix rule
|
||||
|
||||
(def peg (peg/compile ~(* (lenprefix (/ (* '(any (if-not ":" 1)) ":") ,scan-number) 1) -1)))
|
||||
|
||||
(assert (peg/match peg "5:abcde") "lenprefix 1")
|
||||
(assert (not (peg/match peg "5:abcdef")) "lenprefix 2")
|
||||
(assert (not (peg/match peg "5:abcd")) "lenprefix 3")
|
||||
|
||||
# Packet capture
|
||||
|
||||
(def peg2
|
||||
(peg/compile
|
||||
~{# capture packet length in tag :header-len
|
||||
:packet-header (* (/ ':d+ ,scan-number :header-len) ":")
|
||||
|
||||
# capture n bytes from a backref :header-len
|
||||
:packet-body '(lenprefix (-> :header-len) 1)
|
||||
|
||||
# header, followed by body, and drop the :header-len capture
|
||||
:packet (/ (* :packet-header :packet-body) ,|$1)
|
||||
|
||||
# any exact seqence of packets (no extra characters)
|
||||
:main (* (any :packet) -1)}))
|
||||
|
||||
(assert (deep= @["a" "bb" "ccc"] (peg/match peg2 "1:a2:bb3:ccc")) "lenprefix 4")
|
||||
(assert (deep= @["a" "bb" "cccccc"] (peg/match peg2 "1:a2:bb6:cccccc")) "lenprefix 5")
|
||||
(assert (= nil (peg/match peg2 "1:a2:bb:5:cccccc")) "lenprefix 6")
|
||||
(assert (= nil (peg/match peg2 "1:a2:bb:7:cccccc")) "lenprefix 7")
|
||||
|
||||
(end-suite)
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# Copyright (c) 2020 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 9)
|
||||
|
||||
# Net testing
|
||||
|
||||
(defn handler
|
||||
"Simple handler for connections."
|
||||
[stream]
|
||||
(defer (:close stream)
|
||||
(def id (gensym))
|
||||
(def b @"")
|
||||
(:read stream 1024 b)
|
||||
(:write stream b)
|
||||
(buffer/clear b)))
|
||||
|
||||
(def s (net/server "127.0.0.1" "8000" handler))
|
||||
(assert s "made server 1")
|
||||
|
||||
(defn test-echo [msg]
|
||||
(with [conn (net/connect "127.0.0.1" "8000")]
|
||||
(:write conn msg)
|
||||
(def res (:read conn 1024))
|
||||
(assert (= (string res) msg) (string "echo " msg))))
|
||||
|
||||
(test-echo "hello")
|
||||
(test-echo "world")
|
||||
(test-echo (string/repeat "abcd" 200))
|
||||
|
||||
(:close s)
|
||||
|
||||
(end-suite)
|
||||
@@ -230,53 +230,53 @@
|
||||
<key>name</key>
|
||||
<string>punctuation.other.janet</string>
|
||||
</dict>
|
||||
<!-- string>(?<![\.:\w_\-=!@\$%^&?/<>*]) token match here (?![\.:\w_\-=!@\$%^&?/<>*])</string -->
|
||||
<!-- string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*]) token match here (?![\.:\w_\-=!@\$%^&?|\\/<>*])</string -->
|
||||
<key>literal</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*])(true|false|nil)(?![\.:\w_\-=!@\$%^&?/<>*])</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*])(true|false|nil)(?![\.:\w_\-=!@\$%^&?|\\/<>*])</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.janet</string>
|
||||
</dict>
|
||||
<key>corelib</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*])(%ALLSYMBOLS%)(?![\.:\w_\-=!@\$%^&?/<>*])</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*])(%ALLSYMBOLS%)(?![\.:\w_\-=!@\$%^&?|\\/<>*])</string>
|
||||
<key>name</key>
|
||||
<string>keyword.control.janet</string>
|
||||
</dict>
|
||||
<key>keysym</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*]):[\.:\w_\-=!@\$%^&?/<>*]*</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*]):[\.:\w_\-=!@\$%^&?|\\/<>*]*</string>
|
||||
<key>name</key>
|
||||
<string>constant.keyword.janet</string>
|
||||
</dict>
|
||||
<key>symbol</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*])[\.a-zA-Z_\-=!@\$%^&?/<>*][\.:\w_\-=!@\$%^&?/<>*]*</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*])[\.a-zA-Z_\-=!@\$%^&?|\\/<>*][\.:\w_\-=!@\$%^&?|\\/<>*]*</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.janet</string>
|
||||
</dict>
|
||||
<key>hex-number</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*])[-+]?0x([_\da-fA-F]+|[_\da-fA-F]+\.[_\da-fA-F]*|\.[_\da-fA-F]+)(&[+-]?[\da-fA-F]+)?(?![\.:\w_\-=!@\$%^&?/<>*])</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*])[-+]?0x([_\da-fA-F]+|[_\da-fA-F]+\.[_\da-fA-F]*|\.[_\da-fA-F]+)(&[+-]?[\da-fA-F]+)?(?![\.:\w_\-=!@\$%^&?|\\/<>*])</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.hex.janet</string>
|
||||
</dict>
|
||||
<key>dec-number</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*])[-+]?([_\d]+|[_\d]+\.[_\d]*|\.[_\d]+)([eE&][+-]?[\d]+)?(?![\.:\w_\-=!@\$%^&?/<>*])</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*])[-+]?([_\d]+|[_\d]+\.[_\d]*|\.[_\d]+)([eE&][+-]?[\d]+)?(?![\.:\w_\-=!@\$%^&?|\\/<>*])</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.decimal.janet</string>
|
||||
</dict>
|
||||
<key>r-number</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?/<>*])[-+]?\d\d?r([_\w]+|[_\w]+\.[_\w]*|\.[_\w]+)(&[+-]?[\w]+)?(?![\.:\w_\-=!@\$%^&?/<>*])</string>
|
||||
<string>(?<![\.:\w_\-=!@\$%^&?|\\/<>*])[-+]?\d\d?r([_\w]+|[_\w]+\.[_\w]*|\.[_\w]+)(&[+-]?[\w]+)?(?![\.:\w_\-=!@\$%^&?|\\/<>*])</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.decimal.janet</string>
|
||||
</dict>
|
||||
|
||||
Reference in New Issue
Block a user