Age | Commit message (Collapse) | Author |
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Replace the former AST walking interpreter implementation with a single pass
bytecode compiler and a corresponding virtual machine.
The rewrite lays the groundwork for a couple of improvements with will be
subsequently implemented:
- Ability to precompile ucode sources into binary byte code
- Strippable debug information
- Reduced runtime memory usage
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Since we're putting the intermediate JSON return value, the associated tag
info will get freed as well, resulting in use-after-free when raising a
syntax error due to usage of continue or break outside of loop structures.
Read the tag type and offset values before releasing the intermediate `rv`
value.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of obtaining and caching direct opcode pointers, use relative
references when dealing with opcodes since direct or indirect calls to
uc_execute_op() might lead to reallocations of the opcode array, shifting
memory addresses and invalidating pointers taken before the invocation.
Such stale pointer accesses could be commonly triggered when one part
of the processed expression was a require() or include() call loading
relatively large ucode sources.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Eliminate dead code left after regex literal parsing changes
- Properly handle short octal sequences at end of string
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that the single char escapes `\a`, `\b`, `\e`, `\f`, `\n`,
`\r`, `\t` and `\v` keep working. Since they're not part of the POSIX
extended regular expression spec, they're not handled by the RE engine
so we need to substitute them by their actual byte value while parsing
the literal.
Fixes: ac5cb87 ("syntax: fix string and regex literal parsing quirks")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Do not interprete escape sequences in regexp literals
- Do not improperly substitute control escape sequences such as
`\n` or `\a` after a backslash
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Fixes: 8b4d0d5 ("tests: prefer `let` over `local`")
Fixes: a162cf7 ("treewide: rebrand to ucode")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Promote the use of `let` to move ucode examples closer to ES syntax.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of counting the keys individually, use the existing
json_object_object_length() function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Optimize the strncmp() based token lookup with an integer comparison
approach which roughly cuts the time of the source code parsing phase
in half.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Do not emit dummy T_ASSIGN nodes for plain variable declarations without
initialization (`let foo` or `local foo`).
This also allows simplifying `ut_check_for_in()` since we only need to
deal with one common structure for both `for (... in ...)` and
`for (local ... in ...)` cases.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
This brings the utpl script syntax closer to ES5/ES6 and allows to use
existing syntax highlightings in IDEs and editors.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that a call like `fn((1, 2), 3)` invokes the function with arguments
`2, 3` and not `1, 2, 3`.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Tune the grammar and rework the VM to properly yield the last result of
list expressions in various contexts.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
In the alternative `if` syntax mode, support a specific `elif` keyword instead
of requiring an `else` branch followed by a disjunct `if` statement.
The advantage is that templates do not require error-prone redundant `endif`
keywords in else-if ladders.
After this change, the following example:
{% if (...): %}
One condition
{% else if (...): %}
Another condition
{% else if (...): %}
A third condition
{% else %}
Final condition
{% endif; endif; endif %}
... can be simplified into:
{% if (...): %}
One condition
{% elif (...): %}
Another condition
{% elif (...): %}
A third condition
{% else %}
Final condition
{% endif %}
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When reporting parse errors, we might not have a function context so avoid
dereferencing it without checking.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
By specifying a name, followed by an equal sign before the actual option
value, the corresponding JSON data is stored as global variable with the
given name, instead of turning each object key into a variable itself.
For example while `utpl -e '{ "foo": true, "bar": false }' ...` will set
two variables `foo` and `bar`, the alternative syntax
`utpl -e 'baz={ "foo": true, "bar": false }' ...` will declare a single
variable `baz` holding the object `{ "foo": true, "bar": false }`.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When a module is requested via -m but not found on the system, we do not have
a context opcode available when instantiating the exception, which leads to
a segmentation faul when attempting to access the source text offset.
Avoid the deref by checking the opcode pointer for non-null.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Extend the existing `s != NULL` conditional to cover all state pointer
accesses.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Reverse the order of the ungetc() calls to properly restore the first two
probed bytes.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
|
|
Also handle calls to C functions.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Ensure that exceptions ocurring in sort(), filter(), replace() etc.
callback functions are properly forwarded to the caller
- Also fix invalid free() invocations in ut_replace()
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Zero the scope object pointer in the scope structure before putting the
JSON object in order to avoid a double-free by the scope's userdata
destructor function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Since we're invoking ut_execute_op() to obtain the assignment value, the
operand pool might have been reallocated at a different memory address,
invalidating the label opcode pointer.
Obtain a reference to the underlying json label value and re-obtain
the assignment opcode pointer with each iteration to avoid dereferencing
stale pointers.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Store the invocation scope and function context in the call stack frame
and not in the function object to properly deal with recursive invocations.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
At EOF, ut_parse_error() will receive 0 as token offset, which led to a
null pointer dereference when creating the exception value.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|