dc: Relax tail call optimization

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.
This commit is contained in:
Roberto E. Vargas Caballero 2026-01-17 10:57:43 +01:00
parent 9439e85c04
commit 2544b70216
2 changed files with 22 additions and 3 deletions

6
dc.c
View File

@ -1892,14 +1892,14 @@ execmacro(void)
return;
}
/* check for tail recursion */
for (ch = *input->s; ch > 0 && ch < UCHAR_MAX; ch = *input->s) {
for (ch = *input->s; ch > 0 && ch <= UCHAR_MAX; ch = *input->s) {
if (!isspace(ch))
break;
++input->s;
}
if (ch == '\0') {
/* check for tail recursion */
if (ch == '\0' && strcmp(input->buf, v.u.s) == 0) {
free(input->buf);
input->buf = input->s = v.u.s;
return;

19
tests/0045-dc.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/sh
set -e
tmp=$$.tmp
trap 'rm -f $tmp' EXIT
trap 'exit $?' HUP INT TERM
echo 0 > $tmp
../dc -i <<'EOF' | diff -u - $tmp
[ 0 Lxs. 2Q]s<128>
[ .7853981633974483096156608458198757210492923498437764 1/ Lxs. 3Q]s<130>
[K 52><130> ]s<129>
[Sxlx 0=<128> lx 1=<129> 0 Lxs. 1Q]s<1>
1l<1>xps.
EOF