We were trying to check if the output of the program is empty but we
were passing `:output nil` to ext:run-program. Thus, the stream from
which we trying to read was nil which is the stream designator for the
standard input. The empty read succeeded only by chance if the
standard input had no available characters to read.
After this commit
(setf (logical-pathname-translations "x")
(list ("X:a;*;b;*;*.*" "/hello/*/hi/*/what/*.*")))
(translate-logical-pathname #p"x:a;bonjour;b;barev;greetings.me")
will return a correct result
#P"/hello/bonjour/hi/barev/what/greetings.me"
Related to #784.
The function find_list_wilds incorrectly collected results from calling
find_wilds, and the latter returned incorrect results when the component fully
matched. It seems that this was a single function that was later split with
errors.
This change saves us from a segfault when we try to match multiple wild
components. Previously find_list_wilds for
(setf (logical-pathname-translations "x")
`(("X:a;*;b;*;*.*" "/hello/*/hi/*/what/*.*")))
;; ((#P"X:A;*;B;*;*.*" #P"/hello/*/hi/*/what/*.*"))
(translate-logical-pathname #p"x:a;bonjour;b;barev;greetings.me")
returned #1=((BONJUR) #1# BAREV).
Moreover fix an issue where we've compared incorrect character in find_wilds to
determine the end of the glob (we've compared the source character with #\*
instead of the character after).
Fixes#784.
On x86_64, gcc 12.2.0 from debian 12 miscompiles the code we had
previously. It generates code that copies symbol.macfun and
symbol.sfdef using an aligned move SSE instruction which requires 16
byte alignment of its operand. This alignment is not present in
general, leading to a segfault for instance when calling (copy-symbol
t t). By reordering the assignments, we avoid triggering the bug.
these functions are not used by us yet, so these issues were not noticed. Most
notably we did not assign the vector type and did not release the object.
We don't eagerly dereference bytecodes.data->vector.self in case when data is
assigned ECL_NIL. IN that case the *data vector is NULL. That saves us from the
necessity to allocate a vector when we don't use the data segment at all.
Previously we did not perform necessary checks for whether we should update the
frame size and stack pointer or whether we should resize the stack. This commit
fixes these functions and adds a missing function to API ecl_stack_frame_pop.
This is to avoid a situation where the form evaluated by CMP-EVAL treats the
compiler environment as its own local environment. That caused recently a
regression, because we count indexes in FIFO order for sake of dlat closures
Before local closures:
v first from top (correct)
[compiler-env-record form-record]
After local closures
v first from bottom (incorrect)
[compiler-env-record form-record]
After this commit:
v first from bottom after the boundary
[compiler-env-record | form-record]
This way we don't need to separately keep track for whether the function
boundary was crossed for the env, and we don't need to /think hard/ when
captured vector should be allocated.
Moreover the test for whether the parent crosses the function boundary is
precise now, and we save memory when we don't need to allocat a vector.
Commit f36f53a933 accidently(?) reversed the test
by adding the else clause without switghing != to ==.
SYMBOL-MACROLET does not change top-levelness of its children (unlike other
bindings), so we should set lexical_level=1 when we encounter /other/ binding
than SYMBOL-MACRO.
Moreover we add :DECLARE to the mix. The macro LOCALLY does not change
top-levelness either.
This step simplifies logic where we import either from lexenv or from cmpenv.
The next step is to add a correction to locations in cmpenv to address the most
recent regression in passing env from the c compiler to the bytecodes compiler.
- {run,bds,frs}_set_size functions were very similar; I've updated them to
follow the same naming convention and execution order to indicate that.
- these functions are now renamed to xxx_set_limit -that simplifies some code
- there were inconsistencies in how we've treated boot sizes (limit vs size)
All these operations were propagated up to the condition system in order to
reset the stack margin in the case of a non-local exit. We can do that easily
with open-coded unwind protect within stacks.
Objects have a well defind extent so there is no need to rely on GC for
them. This change allows us to move stack initialization before garbage
collector is introduced into the system (or even without any GC).
This commit removes initial bindings array from the process and allocates it
only in the bds stack. To make fields in the structure less confusing we rename
initial_bindings slot to inherit_bindings_p.
On observable behavior change is that bindings are inherited when the process is
enabled, not when it is created. That was not specified in documentation so it
should be fine to change this behavior. Moreover it makes more sense from the
programmer perspective -- we want to inherit bindings of the process that starts
our thread, not the one that creates it.
Also remove an unused operator FEstack_advance. Macro definition names do not
change and they expand (when appropriate) to the inline function.
New function names refer to data_stack, while upcased macro names mentions only
the STACK. This is in line with how forth refers to the data stack when it is
not ambiguous.
We didn't export *TEST-NAME*, FAILED and TEST-FAILURE from 2am-ecl, so the macro
FAIL did not work correctly.
The test mix.0010.file-stream-fd contained a safeguard for a bug from 2016, no
need to guard against that today.
The GC is enabled when we create initial symbols. The function make_this_symbol
initializes symbols from a static table as follows:
1. initialize symbol structure fields
2. associate the symbol with its package
3. associate the symbol with its function
4. increment cl_num_symbols_in_core
Most notably in point 2:
s->symbol.name = ecl_make_constant_base_string(name,-1);
GC's stacks_scanner marks
[cl_symbols; cl_symbols+cl_num_symbols_in_core]
in other words, if the GC kicks in between 1. and 4., the symbol name may be
garbage collected, messing the symbol name and package exports.
To mitigate that, we assign intermediate values on the stack and increment
the number of symbols in core after the symbol is initialized:
1. store initialization values on stack -- cl_object foo = alloc();
2. initialize symbol structure fields
3. increment cl_num_symbols_in_core
4. associate the symbol with its package and function
Since the stack frame is always marked fully, decrementing the pointer keeps a
reference to the unbound object effectively preventing its garbage collection
until it is overwritten by another binding or the stack is closed.