The scale factor has to be considered in the multiplication because
many algorithms will depend of the precision configured in the scale,
that, until now, was considered only for division. BSD and Plan9
dc differ about how to handle this, and plan9 always use only the
scale factor, while BSD uses the maximun of the scale factor or the
bigger scale of the operands. The second seems more sensible and
produces output that user would expect, for example 0k 0.5 0.5*p would
produce 0.2 with the BSD criteria, but it would generate 0 with the
plan9 criteria.
Different libcsuse different criteria about buffering stderr
and it created problems in tests merging stdout and stderr.
To avoid the problem just redirect stderr to a different file
and merge them later using cat in a subshell.
As dc supports extended identifiers and we already had
the option -s in bc that modifies the standard behaviour
we can extend bc in the -s mode to support longer names.
The lower case restriction is maintained just for
simplicity but it is possible to extend bc to support
full utf8 identifers.
Divscale uses the function muln() that is not prepared to handle
negative numbers. The solution is to convert them to positive
numbers and handle the sign in divnum() and modnum(). We don't
need a copy of the parameters because they are used directly
with values from the stack, or from the expnum() function that
discards the input parameters when it calls divnum().
When a value was assigned to a register using the 's'
command we were assigning the full value from execution
stack, overwriting the next pointer of the register
stack with the next pointer of the execution stack.
Without these changes, dc can undergo segfaults in a variety of
situations (list of cases that segfault, one for changed line):
1. echo 'e(5)' | bc -lc | dc
2. echo 'la sa sa sa' | dc
3. echo '5p' > a.dc; dc a.dc
Classical dc implementations only apply tail recursion optimization
but we were applying tail call recursion, removing one frame even
when no recursion was involved. This creates problems with bc that
does not track this optimization and it generates values for the Q
command without caring about this optimization.
Using an EXEC variable for every test make easy to run tools to
debug issues like for example using EXEC=valgrind ./0025-ed.sh.
Some tests for ed had a wrong path to the ed binary and they
were not testing the actual ed but the system one.
These are extensions to the POSIX standard but very useful
in situations like writing a commit message where the exit
status can discard the full edit session.
Setting modflag unconditionally in the Q command could
produce that after an error happening dealing with the Q
command then unsaved files were silently ignored.
Setting modflag unconditionally in the E command could
produce that after an error happening dealing with the E
command then unsaved files were silently ignored.
Match was removing the trailing newline to fix some problems
in regex, but this modified the content of the line making
that the output file had embedded NUL characters (and obviously
no newlines).
Match was removing the trailing newline to fix some problems
in regex, but this modified the content of the line making
that the output file had embedded NUL characters (and obviously
no newlines).
The function gettxt() is basically a repeat loop where it loops
until it arrives to the end of the file when it doesn't find a
newline, but the condition to detect the end of file was wrong
and it looped forever in a file without newline.
When a single z commit is executed then nlines == 0, and
we don't have a value for the line where scroll and this
is why we have to call deflines() to setup the default
value.
This simplifies the logic because it avoids the use of an additional
temporary file. The cleanup function is added only to EXIT because
in the way that it is written it works also in the case of signals.
The clear rule of the Makefile only knows about files
that begin with tmp, and having files with the prefix
exp can produce dirty workcopies even after running
make clean.
Support having multiple flags for a single conversion; at least '+'/'#' and
'0' are not exclusive.
Further use strspn() instead of inlined version for correct handling of
string ending with allowed characters.