http://qs1969.pair.com?node_id=11122532


in reply to Re^8: Influencing the Gconvert macro
in thread Influencing the Gconvert macro

I think it should be fairly simple to amend the perl source so that this warning is eliminated

For anyone interested, here's the patch to sv.c that fixes the problem in a way that doesn't produce any warnings:

Update: The patch meets the objective, but there's still scope for improvement:
1) "précis + 7" is overkill. All that's needed to avoid the compilation warning is "précis + 1";
2) the condition "&& float_need < sizeof(ebuf)" is not needed as it's implied by the next condition;
3) the variable float_need is always set at 35 which feels wrong. AFAICS, "sizeof(ebuf) - float_need" always evaluates to 92 (ie 127 - 35).

--- /cygdrive/c/comp/perl-5.33.2/sv.c 2020-10-04 18:15:27.028350200 ++1100 +++ sv.c 2020-10-04 18:13:55.508841200 +1100 @@ -13109,13 +13109,17 @@ /* check, in manner not involving wrapping, that it w +ill * fit in ebuf */ && float_need < sizeof(ebuf) - && sizeof(ebuf) - float_need > precis + && sizeof(ebuf) - float_need > precis + 7 && !(width || left || plus || alt) && !fill && intsize != 'q' ) { WITH_LC_NUMERIC_SET_TO_NEEDED_IN(in_lc_numeric, - SNPRINTF_G(fv, ebuf, sizeof(ebuf), precis) +#if defined(USE_LONG_DOUBLE) + PERL_UNUSED_RESULT(sprintf(ebuf, "%.*Lg", (int)pr +ecis, (NV) fv)) +#else + PERL_UNUSED_RESULT(sprintf(ebuf, "%.*g", (int)pr +ecis, (NV) fv)) +#endif ); elen = strlen(ebuf); eptr = ebuf;
AFAICT changing précis to précis + 7 does not change functionality, and it's enough to eradicate the warning that the other changes would otherwise introduce
Here's the patch to t/op/sprintf2.t that would have detected the original issue:
--- sprintf2.t_orig 2020-10-04 18:24:56 +1100 +++ sprintf2.t 2020-10-04 18:24:37 +1100 @@ -1178,4 +1178,25 @@ is($off2, 1, "offset after 0"); } +# %g formatting was broken on Ubuntu, Debian and perhaps other system +s +# for a long time. Here we verify that no such breakage still exists. + +if($Config{nvsize} == 8) { + cmp_ok(sprintf("%.54g", 0.3), 'eq', '0.29999999999999998889776975 +3748434595 763683319091796875', + "sprintf( \"%.54g\", 0.3 ) renders correctly"); +} +elsif($Config{nvtype} eq 'long double' && ($Config{longdblkind} == 3 +|| $Config {longdblkind} == 4)) { + cmp_ok(sprintf("%.64g", 0.3), 'eq', '0.30000000000000000001084202 +1724855044 3400745280086994171142578125', + "sprintf( \"%.64g\", 0.3 ) renders correctly"); +} +elsif($Config{nvtype} eq 'long double' && $Config{longdblkind} >= 5 & +& $Config{ longdblkind} <= 8) { + # oops ... TODO (for double-double) +else { + cmp_ok(sprintf("%.115g", 0.3), 'eq', + '0.2999999999999999999999999999999999903703502780638207347 +2011028707 5363407309491758923059023800306022167205810546875', + "sprintf( \"%.115g\", 0.3 ) renders correctly"); +} + + done_testing();
Update:I probably should point out that the "original issue" afflicts only perls whose nvsize is 8, AFAICT.
Therefore, those tests that I've added to sprintf2.t for other types of NV are, in fact,, unrelated to that "original issue".

Cheers,
Rob