[Dropping automake; at this point, m4-discuss is the best place to discuss how m4p is progressing]
On Sat, May 10, 2025 at 04:45:26PM -0400, Nikolaos Chatzikonstantinou wrote: > > Try this in the source dir (one time only): > > > > python3 -m venv .venv > > source .venv/bin/activate > > pip install -U pip setuptools wheel > > pip install -e .[tests] > > > > Then anytime you want to try the software navigate to the source directory > > and do: > > > > source .venv/bin/activate > > > > To activate the environment and use "m4p" directly as a command. Any > > changes you make to the source code should be reflected in that m4p script. > > > > And I forgot that you can run the tests with > > pytest > > And select a particular test with > > pytest -k define > > E.g. picks tests/resources/define.txt Thanks; I now have an 'm4p' binary to play with. Without $* and $@ support, tail recursion is not plausible, so I will wait until you have that implemented. An obvious easy difference - you still don't have short-circuiting working in eval: $ echo 'eval(1 || 1/0)' | m4 1 $ echo 'eval(1 || 1/0)' | m4p m4:stdin:1: divide by zero in eval: 1 || 1/0 1 and a bit less obvious is the difference between 1.4.19 and 1.4.20 on when short-circuiting actually works (if you are aiming for a true 1.4.19 experience, you need bug-for-bug compatibility; if you are instead aiming for latest release compatibility, you should favor the fixed eval): $ echo 'eval(1 || (1/0))' | m4-1.4.19 m4:stdin:1: bad expression in eval (excess input): 1 || (1/0) $ echo 'eval(1 || (1/0))' | m4-1.4.20 1 $ echo 'eval(1 || (1/0))' | m4p m4:stdin:1: divide by zero in eval: 1 || (1/0) 1 Another obvious difference that I depend on (and POSIX says it should work): $ echo foo | m4 -Dfoo=bar bar $ echo foo | m4p -Dfoo=bar usage: m4p [-h] [-P] [-v] [-I DIRECTORY] [--debugfile [FILE]] [FILE ...] m4p: error: unrecognized arguments: -Dfoo=bar And then there's this stress test that's worth handling gracefully (you can't prevent stack overflow, because that's computationally equivalent to solving the Halting Problem, so the best you can do is gracefully handle it rather than spewing thousands of lines of errors at the user when they write a script with poor recursion): $ echo 'define(a,a(a))a' | m4; echo $? m4: stack overflow 1 $ echo 'define(a,a(a))a' | m4p; echo $? m4: stack overflow Traceback (most recent call last): File "/home/eblake/m4p/.venv/bin/m4p", line 8, in <module> sys.exit(main()) ^^^^^^ File "/home/eblake/m4p/m4p/main.py", line 27, in main _main() File "/home/eblake/m4p/m4p/main.py", line 102, in _main parser.parse() File "/home/eblake/m4p/m4p/parser.py", line 511, in parse args = self.consume_arguments() ^^^^^^^^^^^^^^^^^^^^^^^^ ... ~2500 lines later... RecursionError: maximum recursion depth exceeded 120 -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org