summaryrefslogtreecommitdiffhomepage
path: root/lib.c
AgeCommit message (Collapse)Author
2024-02-21lib: fix documentation typo for `pop()` functionJo-Philipp Wich
The function pops the last, not the first element from the array. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-11-01lib: enforce consistent `index()` behavior with empty needle argumentJo-Philipp Wich
On macOS, the `memmem()` function returns `NULL` instead of the expected start of the haystack string when given a zero-length needle argument. Add special case handling for a zero-length needle argument to ensure that the expected offset `0` is returned on all systems. Ref: #176 Suggested-by: Erwan MAS <erwan@mas.nom.fr> Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-10-12lib: add/improve documentation for require(), loadfile(), loadstring()Jo-Philipp Wich
Add missing documentation for the `require()` function and factor our the description of the compile options dictionary into a separate typedef. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-10-11lib: various documentation fixesJo-Philipp Wich
- Consistently use nullable instead of `type|null` expressions - Use @borrows to reduce some duplicated documentation blocks - Add typedef for timelocal()/timegm() TimeSpec value Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-09-11lib: fix documented return value for `splice()`Jo-Philipp Wich
Make the `splice()` documentation match the actual implementation. Fixes: #170 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-08-09treewide: consolidate platform specific code in platform.cJo-Philipp Wich
Get rid of most __APPLE__ guards by introducing a central platform.c unit providing drop-in replacements for missing APIs. Also move system signal definitions into the new platform file to be able to share them with the upcoming debug library. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-07-27lib: add `signal()` stdlib functionJo-Philipp Wich
The `signal()` standard library function provides functionality for registering signal handler callbacks, restoring default signal behaviour or ignoring specific signals. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-07-13docs: various improvementsJo-Philipp Wich
- Switch JSDoc theme to "clean-jsdoc-theme" - Add some custom CSS and JS tweaks to the theme - Use a condensed README.md for the toplevel directory - Include a longer README.md in the documentation portal - Tweak JSDoc annotations for better output results - Register `ucode.mein.io` CNAME Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-07-12lib: add JSDoc documentationJo-Philipp Wich
Add JSDoc documentation blocks to all exported core functions. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-05-30lib: support object ordering in `uc_sort()`Jo-Philipp Wich
Extend `uc_sort()` to utilize `ucv_object_sort()` in order to support reordering object keys. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2023-01-23types: fix array unshift operations and add test coverageJo-Philipp Wich
- Fix `ucv_array_unshift()` improperly rejecting operation on empty arrays - Fix `uc_unshift()` improperly reversing maintaining argument order - Add missing test coverage for `push()`, `pop()`, `unshift()` and `shift()` array operations. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-11-29lib: uc_json(): accept trailing whitespace when parsing stringsJo-Philipp Wich
Only raise a trailing garbage error if the given JSON source string is followed by a non white space character. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-10-04lib: implement slice() functionJo-Philipp Wich
Implement a new function `slice()` to complement the existing `splice()` function and model it's semantics after the ES6 `Array.slice()` version. Fixes: #106 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-21lib: uc_system(): retry waitpid() on EINTRJo-Philipp Wich
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-05lib: add limit support to split() and replace()Jo-Philipp Wich
Extend the split() and replace() functions to accept an additional optional `limit` argument which limits the amount of split operations / substitutions performed by these functions. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-09-05lib: remove fixed capture group limit in match() and regex replace()Jo-Philipp Wich
Instead of supporting only up to 10 potential regular expression captures, infer the amount of required captures directly from the compiled regexp structure and allocate the match range array dynamically. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-29lib: extend render() to support function valuesJo-Philipp Wich
Extend the `render()` function to accept a function value as first argument, which allows running arbitrary ucode functions and capturing their output. This is especially useful in conjunction with `loadfile()` or `loadstring()` to dynamically compile templates and rendering their output into a string. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-29lib: improve getenv() and split() implementationsJo-Philipp Wich
- getenv(): Allow querying the entire environment by omiting variable name - split(): Properly handle null bytes in subject and separator strings Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24lib: introduce three new functions call(), loadstring() and loadfile()Jo-Philipp Wich
Introduce new functions dealing with on-the-fly compilation of code and execution of functions with different global scope. The `loadstring()` and `loadfile()` functions will compile the given ucode source string or ucode file path respectively and return the entry function of the resulting program. An optional dictionary specifying parse options may be given as second argument. Both functions return `null` on invalid arguments and throw an exception in case of compilation errors. The `call()` function allows invoking a given function value with a different `this` context and/or a different global environment. Finally refactor the existing `uc_require_ucode()` implementation to reuse the new `uc_loadfile()` and `uc_call()` implementations and adjust as well as simplify affected testcases. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24lib: introduce helper function for indenting error messagesJo-Philipp Wich
Factor out the nested syntax error message indentation logic into a separate helper procedure for reuse in other places. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-24lib: simplify include_path()Jo-Philipp Wich
Align the path resolving logic with compiler.c and use strrchr() and a width limited printf pattern to extract the directory name portion. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-12lib: implement gc()Jo-Philipp Wich
Introduce a new stdlib function `gc()` which allows controlling the periodic garbage collector from ucode. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-08-06lib: internally expose new uc_require_library() helperJo-Philipp Wich
Break out the core logic of the uc_require() stl function into a new uc_require_library() helper function and make it available for usage outside of lib.c. Also add a new boolean parameter to the helper function which allows restricting runtime require operations of modules to dynamic libraries only. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-07-30program: add infrastructure to handle multiple sources per programJo-Philipp Wich
The upcoming module support requires maintaining multiple source objects within the same program, so add the necessary infrastructure for it. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-07-30lib: honor constant flag of arraysJo-Philipp Wich
Reject modifications on array values with a type exception when the constant flag is set on the array operated upon. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-06-01lib: refactor `uc_int()`Jo-Philipp Wich
For string cases, turn `int()` into a thin `strtoll()` wrapper which attempts to parse the initial portion of the string as a decimal integer literal, optionally preceded by white space and a sign character. Also introduce an optional `base` argument for string cases while we're at it and adjust the existing stdlib test case accordingly. The function now behaves mostly the same as ECMAScript `parseInt(val, 10)` for string cases, means it will recognize `012` as `12` and not `10` and it will accept trailing non-digit characters after the initial portition of the input string. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-05-30lib: rework uc_index() implementationJo-Philipp Wich
- Fix segfault on passing string haystack with non-string needle argument - Perform strict equality tests against array haystacks - Make string searches binary safe - Improve left index string search performance - Improve right index array search performance - Add missing test coverage for index() and rindex() Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-05-19lib: introduce hexenc() and hexdec()Jo-Philipp Wich
Add two new functions to deal with encoding and decoding of hexadecimal digit strings: - hexenc() - convert the given input value into a lower case hex digit string, implicitely converting the input argument to a string value if needed - hexdec() - decode the given input hex digit string into a byte string, skipping whitespace or optionally specified characters in the input Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-04-07treewide: move json-c compat shims into internal header fileJo-Philipp Wich
Do not expose the json-c compat functions in ucode's public headers to avoid clashes when building on systems with modern json-c. Also remove some explicit json-c/json-c.h includes in places where it is not needed. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-04-07lib: let `json()` accept input objects implementing `read()` methodJo-Philipp Wich
Extend the `uc_json()` implementation to accept readable objects in addition to plain input strings. This allows parsing JSON input directly from open file handles, sockets or other kinds of producer objects without the need to store the entire JSON source string intermediately in memory. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-22Merge pull request #60 from jow-/time-functionsJo-Philipp Wich
lib: add date and time related functions
2022-03-22lib: add date and time related functionsJo-Philipp Wich
Add five new functions to deal with date calculation and timing: - localtime(), gmtime() - return a broken down calendar date and time specification from the given epoch (or now, if absent) in local and UTC time respectively - timelocal(), timegm() - the inverse operation for the former functions, taking a date and time specification (interpreted as local or UTC time respectively) and turning it into an epoch value - clock() - return the second and nanosecond values of the system clock, useful for time/performance measurements Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-03-22lib: provide API function to obtain stdlib function implementationsJo-Philipp Wich
Provide a new API function `uc_stdlib_function()` which allows to fetch the C implementation of the given named standard library function. This is useful for loadable modules or applications that embed ucode which want to reuse core functions such as `sprintf()`. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
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-20lib: add argument position support (`%m$`) to `sprintf()` and `printf()`Jo-Philipp Wich
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-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-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-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-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-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-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>
2022-02-03lib: fix infinite loop on empty regexp matches in uc_match()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. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-02-03lib: fix infinite loop on empty regexp matches in uc_split()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. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-29program: rename bytecode load/write functions, track path of executed fileJo-Philipp Wich
Extend source objects with a `runpath` field which contains the original path of the source being executed by the VM. When instantiating source objects from file paths, the `runpath` will be set to the `filename`. When instantiating source buffers using `uc_source_new_buffer()`, the runpath is initially unset. A new function `uc_source_runpath_set()` can be used to adjust the runtime path being associated with a source object. Extend bytecode loading logic to set the source buffer runtime path to the precompiled bytecode file path being loaded and executed. This is required for `sourcepath()` and relative paths in `include()` to function correctly when executing precompiled programs. Finally rename `uc_program_from_file()` and `uc_program_to_file()` to `uc_program_load()` and `uc_program_write()` respectively since the load part now operates on an `uc_source_t` input buffer instead of a plain `FILE *` handle. Adjust users of these API functions accordingly. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-29lib: fix memory leak in uc_require_ucode()Jo-Philipp Wich
We need to release the compiled module function after we executed it in our VM context. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-26vm: fix NaN strict equality testsJo-Philipp Wich
A performance shortcut in `ucv_is_equal()` incorrectly led to `NaN === NaN` being true. Fix the issue by only comparing pointers when the involved types are not doubles. Due to fixing `NaN !== NaN`, the `uniq()` function now requires a special case to treat multiple NaNs equal for the sake of generating an array of unique values. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-26lib: fix exists() error return valueJo-Philipp Wich
The current implementation incorrectly returned `false` which got treated as `NULL` instead of a boolean `false` value. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
2022-01-23lib: rework format string handlingJo-Philipp Wich
Instead of extracting and forwarding recognized conversion directives from the user supplied format string, properly parse the format string into its components and reassemble a canonical representation of the conversion directive internally before handing it to the libc's sprintf() implementation. Also take care of selecting the proper conversion specifiers for signed and unsigned 64bit integer values to fix broken `%d`, `%i`, `%u`, `%o`, `%x` and `%X` formats on 32bit systems. While reworking the format logic, also slightly improve `%s` argument handling by not duplicate the given value if it already is a string, which reduces the amount of required heap memory. Ref: https://bugs.openwrt.org/index.php?do=details&task_id=4234 Ref: https://git.openwrt.org/3d3d03479d5b4a976cf1320d29f4bd4937d5a4ba Signed-off-by: Jo-Philipp Wich <jo@mein.io>