On Tue, May 13, 2025 at 04:49:58PM -0400, Nikolaos Chatzikonstantinou wrote:
> > Not touched in this patch: I think there are places where you get the
> > wrong answer because you don't convert to c_int32 until at the end of
> > the evaluation, whereas m4 1.4.20 is doing ALL operations in signed
> > 32-bit.
> 
> Actually I think we might be in the clear with this one thanks to the
> properties of modular arithmetic that say e.g. (a % c) + (b % c) is
> equal to (a + b) % c. It certainly means that m4p uses more memory as
> it uses bignums right up until the final computation.

True for unsigned math, not so true for signed math.  Then again, POSIX
says:

    https://pubs.opengroup.org/onlinepubs/9799919799/utilities/m4.html

| eval
|   The eval macro shall evaluate its first argument as an arithmetic
| expression, using signed integer arithmetic with at least 32-bit
| precision. At least the following C-language operators shall be
| supported, with precedence, associativity, and behavior as described
| in 1.1.2.1 Arithmetic Precision and Operations:

which in turn says math should be done as if by C's 'unsigned long'
(and m4 1.4.x is only doing it with int, which is not the same as
unsigned long on most 64-bit platforms), m4 1.4.x is NOT quite
POSIX-compliant.  (That's something that I plan to change for m4 1.6,
but for back-compat reasons I'm reluctant to change it for 1.4.x).

At any rate, I suspect you will find that you need to tweak m4p's eval
to match:

$ m4
eval(-1%3)
-1
eval((0x7fffffff+2)%3)
-1
$ m4p
eval(-1%3)
2
eval((0x7fffffff+2)%3)
0

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org


Reply via email to