summaryrefslogtreecommitdiffhomepage
AgeCommit message (Collapse)Author
2022-03-21CI: build on macOSPaul Spooren
Build minimal version to detect compile issues. Signed-off-by: Paul Spooren <mail@aparcar.org>
2022-03-21Merge pull request #53 from jow-/string-format-argpos-supportJo-Philipp Wich
lib: add argument position support (`%m$`) to `sprintf()` and `printf()`
2022-03-20Merge pull request #52 from jow-/portability-fixesJo-Philipp Wich
Portability fixes for macOS
2022-03-20lib: add argument position support (`%m$`) to `sprintf()` and `printf()`Jo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15treewide: remove legacy json-c include directivesJo-Philipp Wich
We now include `json-c/json-c.h` on all supported environments. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15tests: 21_regex_literals: generalize syntax error test caseJo-Philipp Wich
Different libc implementations produce different syntax error messages on invalid regular expression patterns, so rework the test case to produce stable output across all environments. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15tests: 16_sort: fix logic flaw exposed on OS XJo-Philipp Wich
A typo in the custom order function of the test case caused the test case to yield differently sorted results on OS X, triggered by differences in the libc's `qsort()` implementation. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15tests: run_tests.sh: pass dummy value to `-T` flagJo-Philipp Wich
Since OS X `getopt()` does not handle optional arguments, we need to always pass a value to `-T`. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15lib: disallow zero padding for %s formatsJo-Philipp Wich
Filter the zero padding `0` flag for `%s` formats to achieve constisten outputs on Linux and OS X systems. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15tests: run_tests.sh: use greadlink if availableJo-Philipp Wich
This ensures that GNU readlink is preferred over OS X own readlink when executing test cases. This is required due to lacking `-f` flag support on OS X. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15resolv: make OS X compatibleJo-Philipp Wich
OS X `socket()` does not support the `SOCK_NONBLOCK` or `SOCK_CLOEXEC` constants, so apply these flags using `fcntl()` after creating the socket. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15fs: avoid Linux specific sys/sysmacros.h include on OS XJo-Philipp Wich
It should be enough to include `sys/types.h` to obtain `major()` and `minor()` definitions on OS X, so avoid including the the Linux specific `sys/sysmacros.h` header in this case. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15uloop: use execvp() on OS XJo-Philipp Wich
Since `execvpe()` is a GNU extension, fall back to using `execve()` on OS X. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15lib: add naive sigtimedwait() stub for OS XJo-Philipp Wich
OS X does not implement `sigtimedwait()` used by `uc_system()` - add a simple implementation of it. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15build: consolidate CMakeLists.txt and cover OS X deviationsJo-Philipp Wich
- Add OS X specific linker flags - Default disable Linux specific modules on OS X - Simplify json-c discovery - Fix uloop_timeout_remaining64() detection Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15include: add OS X compatible endian.h headerJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-15include: rename include guards to avoid clashes with system headersJo-Philipp Wich
Identifiers starting with one or two underscores are reserved for system headers and toolchain implementations and should not appear in user code. Also on OS X, the ucode __TYPES_H_ guard clashes with the system types.h header. Rename all ucode header guards to avoid such clashes. Supersedes: #43 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-14Merge pull request #51 from jow-/nl80211-fixesJo-Philipp Wich
nl80211: add missing attributes and correct some attribute flags
2022-03-14Merge pull request #48 from jow-/cli-reworkJo-Philipp Wich
main: rework CLI frontend
2022-03-14nl80211: add missing attributes and correct some attribute flagsJo-Philipp Wich
Suggested-by: John Crispin <john@phrozen.org> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-14lib: adjust require(), render() and include() raw mode semanticsJo-Philipp Wich
- Let `require()` always evaluate the executed code in raw mode - Let `render()` always evaluate the executed code in template mode - Let `include()` inherit the raw mode semantics of the calling scope Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-14main: rework CLI frontendJo-Philipp Wich
- Change command line flags to be align better with those of other interpreters and with the gcc compiler, e.g. `-D` and `-U` to define and undefine globals, `-e` to execute script expression etc. - Pass only excess CLI arguments as `ARGV` to scripts, e.g. `ucode -e 'print("Hello world")' -- -x -y` would pass only `[ "-x", "-y" ]` as ARGV contents - Default to raw mode and introduce flag to enable template mode Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-14Merge pull request #50 from jow-/musl-empty-render-crashJo-Philipp Wich
lib: fix potential integer underflow on empty render output
2022-03-14lib: fix potential integer underflow on empty render outputJo-Philipp Wich
The current `uc_render()` implementation uses a `fseek()` call on the `open_memstream()` provided `FILE *` stream to reserve headroom for the `uc_string_t` header. The `fseek()` call alone does not guarantee that the underlying buffer length is updated on all libc implementations though. This may lead to an integer underflow later on when the `uc_string_t` header length is substracted from the buffer length after invoking a template that did not produce any output write operations. In such a case, a very large value is assigned to `ustr->length` leading to uninitialized or out-of-bounds memory accesses later on. Solve this issue by writing the header structure as data using `fwrite()` which should yield the expected behaviour on all libc environments. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-14Merge pull request #49 from jow-/vm-computed-prop-crashJo-Philipp Wich
vm: fix crash on object literals with non-string computed properties
2022-03-14vm: fix crash on object literals with non-string computed propertiesJo-Philipp Wich
When executing an object literal declaration using non-string computed property name values, the VM crashed caused by an attempt to use a NULL pointer (result of ucv_string_get() on a non-string value) as hash table key. Fix this issue by using the `ucv_key_set()` infrastructure which deals with the implicit stringification of non-string key values. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-08Merge pull request #46 from jow-/ubus-pub-sub-supportJo-Philipp Wich
ubus: add object publishing, notify and subscribe support
2022-03-08Merge pull request #47 from jow-/new-operatorsJo-Philipp Wich
syntax: support add new operators
2022-03-07syntax: support add new operatorsJo-Philipp Wich
- Support ES2016 exponentiation (**) and exponentiation assignment (**=) - Support ES2020 nullish coalescing (??) and logical nullish assignment (??=) - Support ES2021 logical and assignment (&&=) and logical or assignment (||=) Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-07ubus: add event supportJo-Philipp Wich
Extend the ubus binding to cover ubus event handling APIs. Instantiating ubus event listener: listener = conn.listener( "event.type.*", function (type, data) { ...event callback... } ); listener.remove(); Broadcasting events: conn.event("event.type.foo", { ...event data... }); Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-07ubus: refactor error and argument handlingJo-Philipp Wich
- Add more detailled error messages - Introduce helpers for fetching and validating function call arguments - Get rid of some uneeded blob->jso->ucv conversions Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-07ubus: add object publishing, notify and subscribe supportJo-Philipp Wich
Extend the ubus binding to cover ubus object publishing, notifications on objects, as well as subscriber APIs. Instantiating ubus objects: obj = conn.publish("objname", { methodname: { args: { ...argspec... }, call: function(request) { ...method handler... } }, ... }, function() { ...subscription status change handler... }); obj.notify(...); obj.remove(); Emitting notifications: obj.notify("notificationtype", { ...notification data... }, function(type, data) { ...data callback... }, function(idx, ret) { ...status callback... }, function() { ...completion callback... }, 100 /* timeout */ ); Instantiating subscribers: sub = conn.subscriber( function(notify) { ...notification handler... }, function(id) { ...object gone handler... } ); sub.subscribe("objname"); sub.unsubscribe("objname"); sub.remove(); Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-06uloop: clear errno before integer conversion attemptsJo-Philipp Wich
In some cases, errno contains stale values from prior function invocations which might lead to random failures in uc_uloop_run(), uc_uloop_timer_set() and uc_uloop_timer(). Solve this issue by explicitly initializing errno to 0. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-03types: treat resource type prototypes as GC rootsJo-Philipp Wich
Mark reachable resource type prototype objects during incremental GC steps in order to avoid freeing them prematurely. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-02Merge pull request #45 from jow-/lib-add-uloopJo-Philipp Wich
lib: introduce uloop binding
2022-03-02lib: introduce uloop bindingJo-Philipp Wich
The uloop module allows controlling the uloop event loop and supports adding timeouts, processes and file descriptors. Example: #!ucode -RS let fs = require("fs"); let uloop = require("uloop"); let fd1 = fs.popen("echo 1; sleep 1; echo 2; sleep 1; echo 3", "r"); let fd2 = fs.popen("echo 4; sleep 1; echo 5; sleep 1; echo 6", "r"); function fd_read_callback(flags) { if (flags & uloop.ULOOP_READ) { let line = this.handle().read("line"); printf("Line from fd <%s/%d>: <%s>\n", this, this.fileno(), trim(line)); } } uloop.init(); uloop.timer(1500, function() { printf("Timeout after 1500ms\n"); }); uloop.handle(fd1, fd_read_callback, uloop.ULOOP_READ); uloop.handle(fd2, fd_read_callback, uloop.ULOOP_READ); uloop.process("date", [ "+%s" ], { LC_ALL: "C" }, function(exitcode) { printf("Date command exited with code %d\n", exitcode); }); uloop.run(); Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-02vm: release this context on exception in managed method callJo-Philipp Wich
When attempting to invoke a non-function value as method or when the the internal recursion limit was exceeded, `uc_vm_call_function()` emitted and internal runtime exception and freed the function value but not the `this` context associated with the method call. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-15tests: fix proto() testcaseJo-Philipp Wich
Fixes: 4ce69a8 ("fs: implement access(), mkstemp(), file.flush() and proc.flush()") Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-15fs: implement access(), mkstemp(), file.flush() and proc.flush()Jo-Philipp Wich
The `access()` function allows testing the path given in the first argument for accessibility according to the permissions specified in the second mode string argument. The mode string characters may be `r`, `w`, `x` or `f` which correspond to `R_OK` - path is readable, `W_OK` - path is writable, `X_OK` - path is executable or `F_OK` - path exists respectively. The `mkstemp()` function creates a secure temporary file, unlinks it and returns the open file handle. The temporary path is constructed based on the optional template argument. If the template argument contains a slash, the path is taken as-is, if it contains no slashes, `/tmp/` is prepended. If the template does not end with `XXXXXX`, a `.XXXXXX` suffix is appended to the path. If the template is omitted, `/tmp/XXXXXX` is used. The `file.flush()` and `proc.flush()` functions call `fflush()` on the underlying file handle respectively. They take no arguments. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-11compiler: fix patchlist corruption on switch statement syntax errorsJo-Philipp Wich
When compiling a switch statement with duplicate `default` cases or a switch statement with syntax errors before the body block, two error handling cases were hit in the code that prematurely returned from the function without resetting the compiler's patchlist pointer away from the on-stack patchlist that had been set up for the switch statement. Upon processing a subsequent break or continue control statement, a realloc was performed on the then invalid patchlist contents, triggering a segmentation fault or libc assert. Solve this issue by not returning from the function but breaking the switch body parsing loop. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-11lib: change `ord()` to always return single byte valueJo-Philipp Wich
The most common usecase is extracting the value of a single byte at a specific offset, e.g. to scan a string char-by-char to construct a hash. Furthermore, constructing an array which contains the results of multiple `ord()` invocations is trivial while efficiently extracting a single byte value without the overhead of an intermediate array is not. Due to that, change `ord()` to always return a single integer byte value at the offset specified as second argument or at offset 0 in case no argument was supplied. That means that `ord("Abc", 0, 1, 2)` will now return `65` instead of the former `[ 65, 98, 99 ]` result. Code relying on the former behaviour should either perform multiple calls to `ord()`, passing different offsets each time or switch to the `struct` module which allows efficient unpacking of string data. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-11vallist: fix storing/retrieving short strings with 8bit byte valuesJo-Philipp Wich
Due to using signed byte values when writing/reading short strings to/from pointer addresses, 8 bit characters where incorrectly clamped to `-1` (`255`). Fix this issue by treating the input string as `uint8_t` array. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-08compiler: fix incorrect loop break targetsJo-Philipp Wich
When patching jump targets for break statments while compiling for-loop statments, we need jump beyond the instructions popping intermediate loop variables off the stack but before the pop instructions removing local loop body variables to prevent a stack position mismatch between compiler and vm. Before that change, local loop body variables remained on the stack, breaking the expected stack layout. Fixes: b3d758b compiler: ("fix for/break miscompilation") Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-07Merge pull request #38 from jow-/function-memory-modelJo-Philipp Wich
treewide: rework function memory model
2022-02-07source: convert source objects into proper uc_value_t typeJo-Philipp Wich
Instead of implementing a custom limited refcount logic, turn uc_source_t instances into proper uc_value_t objects. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-07treewide: rework function memory modelJo-Philipp Wich
- Instead of treating individual program functions as managed ucode types, demote uc_function_t values to pointers into a uc_program_t entity - Promote uc_program_t to a managed type - Let uc_closure_t claim references to the owning program of the enclosed uc_function_t - Redefine public APIs uc_compile() and uc_vm_execute() APIs to return and expect an uc_program_t object respectively - Remove vallist indirection for function loading and let the compiler emit the function id directly when producing function construction code Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03Merge pull request #37 from jow-/stdlib-testsJo-Philipp Wich
2022-02-03tests: add functional tests for builtin functionsJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03lib: fix leaking tokener in uc_json() on parse exceptionJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03lib: fix infinite loop on empty regexp matches in uc_replace()Jo-Philipp Wich
The regular expression `/()/` will match the empty string, causing the match loop to never advance. Add extra logic to deal with this case, similar to the empty separator string logic. Apply a similar exception to replacements of empty search strings, those should yield the same result as empty regexp matches. Signed-off-by: Jo-Philipp Wich <jo@mein.io>