SDCC has 4 functions in stdlib.h to convert integers into string: _uitoa, _itoa, _ultoa, _ltoa.
Since making sprintf as efficient as these will take some time, we still need them for now.
However, there are some problems with them that should be fixed:
- Their names are not in the namespace reserved for implementation-specific extensions and could collide with names used by users. They should be changed to start with two underscores.
- They are not tested in regression tests.
- They are not available for all ports.
Diff:
Diff:
Can return value be a pointer to null char at end of result (to simplify compute len = res - str)?
Last edit: Sergey Belyashov 2020-07-07
I have added regression tests for
_itoa,_uitoa,_ltoaand_ultoafunctions. These tests compiles to huge binaries. If compile as is (without partitioning) z80 port fails to compile with segmentation fault. I think, it is because of memory overflow.But now stm8-large port has failed (u)itoa farm tests with segmentation fault. On my local desktop it pass all tests.
The ususal thing to do in such a case (new regression test fails for some ports), is to open a bug report for this newly discoved issue, and disable the test (using #define 0 with a comment referencing the bug number).
In this case, I have already opened the bug [#3082] for it.
Also, IMO, it would be good, if we can do some testing even on the smaller targets. Even if for those targets only one or to tests are done per function.
Related
Bugs:
#3082I think, these functions can be implemented on z80/z180/z80n/ez80 using bin2bcd convertion. It faster than div/mod algorithm.
Yes. I've used this approach on the ColecoVision before (see attachment), and it would make sense to use it here (I never got around to doing it, since in the long term, I intend to do a big printf-implementation-overhaul, but to be realistic, it makes more sense to just use the bcd stuff now, so we get an improvement quick with the existing functions).
Have some other SDCC ports instructions which simplifies BCD arithmetics?
Last edit: Sergey Belyashov 2020-07-12
Mcs51 has DA which is the only instruction I'm pretty sure I have never used.
The Padauk have a half-carry flag. But they lack a decimal-adjust instruction, so the flag isn't really useful. One could still try something like
However, if you want to use BCD, I'd suggest doing it port-by-port with individual patches, not one big patch that changes all ports at the same time.
My idea: implement uitoa with radix 10 using port internal functions
void __uitobcd(unsigned int v, unsigned char r[3]),void __ultobcd(unsigned long v, unsigned char r[5]), and, possible,__ulltobcd(unsigned long long v, unsigned char r[10]). So result function will looks like:Last edit: Sergey Belyashov 2020-07-13
There are implementation of uitobcd and ultobcd for Z80 (mostly all Z80-like, except Rabbits):
I have tests for them. So if they OK, I may commit as:
Last edit: Sergey Belyashov 2020-07-13
Anyway, I think it is better to fix the names first before adding port-specicif implementations (so we're not adding a lot of files that would have to be renamed later - though since we use svn,. not git, a rename doesn't harm the history).
I'd suggest to go for simply renaming _ultoa to __ultoa, etc unless there is a good reason to choose a different name.
This microsoft page seems to indicate that only ultoa is non-compliant and _ultoa is ok:
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/itoa-itow?view=vs-2019
Are you sure that the name with a single underscore is non-compliant?
Sure is a very strong word, and reserved identifiers are not my speciality. There is a reason a WG14 document on this is titled "What we think we reserve" (N2493).
And looking at the details again we apparently should be okay with the old name:
Clearly, identifiers beginning with two underscores or an underscore followed by a capital letter are reserved. Traditionally, the former is mostly used for implementation extensions, while the latter is mostly used for introducing new standard fetures.
In the current C2X draft we also have: "All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces." (and I assume the wording is the same in earlier standards).
So we could indeed continue to use _ultoa as name for a function in our library, as we use it for a file-scope identifier in the ordinary namespace. Still it is cleaner to use the __ prefix for all implementation extensions, even though the _ prefix is allowed in this corner case.
I'm asking because many other compilers seem to have
_ultoaand I cannot find any that have__ultoa.That is indeed an argument for going back to the old name. I only knew about some using ultoa (i.e. without any underscores) in OS-specific libraries, ie.e. not pure C mode.
Do we have a list of names for these functions for common compilers (LLVM, GCC, IAR, etc)?
Some Google-Fu for _ultoa gives:
https://docs.microsoft.com/en-us/previous-versions/d5t0h1wd(v=vs.140)
https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rtref/ultoa.htm
http://www.x-hacker.org/ng/wclr/ng14015b.html
https://doxygen.reactos.org/d9/db3/itoa_8c.html
http://www.smorgasbordet.com/pellesc/changes_271_272.htm
https://fossies.org/diffs/SDL2/2.0.6_vs_2.0.7/configure.in-diff.html
When I search for ultoa I find even many more.
But searching for __ultoa finds very little.
Those common compilers and the libraries usually used with them all seem not to provide it or provide the non-conforming ones.
Implemented for Z80 in [r11726].
Convertion is done with 3 algorithms:
If number is equal to 0, then string "0" is returned.
If radix is 0 or 1 then empty string is returned (not covered by test).
Exported both symbols like
__itoaand___itoa. So renaming can be done later.Rename done in [r11731]. Tests had been added already.
I think we can close this bug report (unless someone objects). BCD optimization would be a feature, not a bugfix.
BCD is already implemented for pure Z80 port. For itoa it faster about 2 times than generic algorithm used for custom radix. For ltoa it faster about 10-20%.
I suggest to review
__uitobcd,__ultobcd, and__strreversenew functions too. If all is OK, then I port them for Z180, EZ80, Z80N targets.Implemented for eZ80, Z180 and Z80N in [r11753].
Can we also have
__ltoaand__ultoain pdk ports?Here is the patch:
$ svn diff
Too little target. Theoretically it is possible but unusefull.
Sorry, I don't understand your comment.
The patch above enables the generic
__ltoaand__ultoaC implementations to be included in the PDK libraries. No more work required._ltoaand_ultoaincluding__modulongand__divulongsums up to 302 instructions (PDK usually has 1024-3096 instructions in code memory available).Currently I'm working on a tiny printf which could use this functions and for sure others might need them as well.