On Wed, Jun 16, 2021 at 11:40:08PM -0600, Gavin Howard wrote:
> Hello,
>
> My name is Gavin Howard. I have developed a new bc(1) and dc(1)
> implementation. [0]
>
> I propose replacing the current implementations with mine.
>
> Advantages:
>
> * Performance. [1]
> * Extensions for ease of use.
> * With build options to remove most extensions, if desired.
> * Compatible with GNU bc.
> * Already used by default in FreeBSD.
> * Fuzzed thoroughly.
> * No exec needed for bc(1) (both programs are contained in the same
> multi-call binary).
>
> Expectations met:
>
> * Already uses pledge(2) and unveil(2).
> * No dependencies beyond C99, POSIX `make`, and POSIX `sh`.
> * This includes no dependency on editline(3), even though my bc(1)
> and dc(1) have a history implementation.
> * Thorough test suite.
> * Comprehensive man pages.
> * Locale support.
>
> Disadvantages:
>
> * There are incompatibilities with the current bc(1) and dc(1), which
> are listed below. All users would need to be made aware of these
> incompatibilities, so they can update scripts, and scripts in `src/`
> will also need to be updated.
>
> Incompatibilities (failing tests from `regress/usr.bin`):
>
> 1. Current bc(1) and dc(1) return 0 for length(a) where a is 0. Mine
> return 1. This causes my dc(1) to fail `dc/t1.in` and `dc/t28.in`.
> 2. Current dc(1) implements arrays as part of registers. Mine keeps
> arrays and registers separate. This causes my dc(1) to fail
> `dc/t1.in` and `dc/t8.in`.
> 3. Current dc(1) does not print a `nul` byte if given the `P` or `a`
> commands with 0 on the top of the stack. My dc(1) does (because it
> considers 0 to have one digit, see #1). This causes my dc(1) to fail
> `dc/t3.in` and `dc/t13.in`.
> 4. Current dc(1) starts with empty registers, and allows the user to pop
> all items off the register stack. My dc(1) starts with a single item
> in the register and does not allow the user to remove it.
> 5. Current dc(1) will push an item onto a register stack for the `s`
> command. My dc(1) does not since one already exists. This, combined
> with #4, causes my dc(1) to fail `dc/t5.in`
> 6. Current bc(1) and dc(1) have a larger maximum `obase` than mine. This
> causes my dc(1) to fail `dc/t9.in`.
> 7. Current dc(1) does not reset on errors. My dc(1) does, so it fails
> `dc/t12.in`.
> 8. Current dc(1) allows register names with any character. My dc(1)
> requires non-control characters and has a different way of doing
> extended registers. This causes my dc(1) to fail `dc/t15.in`,
> `dc/t16.in`, `dc/t19.in`, `dc/t21.in`, and `dc/t23.in`.
> 9. Current bc(1) is a frontend to dc(1). Mine are combined into the same
> binary and generate and run bytecode. This means that my bc(1) fails
> all of the bc(1) regression tests (which generate dc(1) code) and
> does not have the `-c` option.
>
> Notes:
>
> My dc(1) also fails `dc/t10.in` because it doesn't have the `!` command,
> but https://github.com/openbsd/src/commit/dc405aa075 makes it appear as
> though the current dc(1) does not have the `!` command either.
>
> In https://youtu.be/gvmGfpMgny4?t=1277 , Bob Beck said that unveil(2)
> must not be used on command-line arguments, so I use unveil(2) after all
> command-line files are executed.
>
> Current version is 4.0.2. I am planning to release version 4.1.0 soon,
> but held off in case you are interested and had feedback that might
> help.
>
> I am willing to help maintain them if they are put into OpenBSD, but I
> am also willing to pass them off to whoever you wish, should you wish to
> do so.
>
> I do have a mirror on GitHub.
>
> If you are not interested, feel free to ignore this email.
>
> Regardless, thank you for your time.
>
> Gavin Howard
>
> [0]: https://git.yzena.com/gavin/bc
> [1]: https://git.yzena.com/gavin/bc/src/branch/master/manuals/benchmarks.md
>
I think it is interesting. As for the incompatibilites, my memory says
I followed the original dc and bc when deciding on those (GNU chose to
differs in these cases). Bit it has been 18 years since I wrote the
current versions, so I might misrememeber.
As for moving to your version, I have no opinion yet. I have some
attachment to the current code, but not so strong that I am opposing
replacement upfront. OTOH the current implementaion is almost
maintainance free for many years already. So I dunno.
I'll take a look at your code soon and maybe other devs have opinions.
-Otto