Age | Commit message (Collapse) | Author |
|
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>
|
|
When a for() loop body, initializer, test or increment expression compiles
further code, e.g. by invoking invoke() or require(), the opcode pool will
be reallocated, potentially changing the addresses of all opcodes.
This might lead to an invalid memory access when previously cached opcode
pointers are accessed later on.
Solve this issue by obtaining the relative offsets of the corresponding
opcodes, avoiding the need for pointer dereferences.
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>
|
|
Get rid of the distinction between lexer/parser errors and runtime
exceptions, use exceptions everywhere instead.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Keep an open FILE* reference to processed source files in order to
be able to rewind and extract error context later
- Build a proper call stack when invoking utpl functions
- Report call stack in exceptions
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|