diff --git a/newlib/libc/tinystdio/vfprintf.c b/newlib/libc/tinystdio/vfprintf.c index a11e7e9363..3b61958642 100644 --- a/newlib/libc/tinystdio/vfprintf.c +++ b/newlib/libc/tinystdio/vfprintf.c @@ -688,6 +688,8 @@ int vfprintf (FILE * stream, const CHAR *fmt, va_list ap_orig) #ifdef _NEED_IO_C99_FORMATS if (c == 'a') { + int init_prec = prec; + c = 'p'; flags |= FL_FLTEXP | FL_FLTHEX; @@ -695,7 +697,15 @@ int vfprintf (FILE * stream, const CHAR *fmt, va_list ap_orig) prec = -1; prec = __float_x_engine(fval, &dtoa, prec, case_convert); + + if(prec < init_prec) /* if dtox engine capped the precision required */ + prec = init_prec; + ndigs = prec + 1; + + if(ndigs > 14) /* the max dtox ndigs */ + ndigs = 14; + exp = dtoa.exp; ndigs_exp = 1; } else diff --git a/test/meson.build b/test/meson.build index ac3e1a471c..16a36d0835 100644 --- a/test/meson.build +++ b/test/meson.build @@ -83,6 +83,7 @@ if (posix_io or not tinystdio) and tests_enable_posix_io 'test-fgetc', 'test-fgets-eof', 'test-wchar', + 'test-vfprintf-hex-prec' ] endif endif diff --git a/test/test-vfprintf-hex-prec.c b/test/test-vfprintf-hex-prec.c new file mode 100644 index 0000000000..af4c7fc139 --- /dev/null +++ b/test/test-vfprintf-hex-prec.c @@ -0,0 +1,62 @@ +/* +* SPDX-License-Identifier: BSD-3-Clause +* +* Copyright © 2024, Synopsys Inc. +* Copyright © 2024, Solid Sands B.V. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* 3. Neither the name of the copyright holder nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +* OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +int main(void) { + int res = 0; + int ret = 0; + size_t len = 0; + char strin[50]; + + res = sprintf(strin, "%.15A\n", 471.2853); + + const char* ref_out = "0X1.D749096BB98C800P+8\n"; + const int ref_len = 23; + + ret = strcmp(strin, ref_out); + len = strlen(strin); + + if ((res != ref_len) || (ret != 0) || (len != ref_len)) { + printf("Test Failed: Failed to read/write 15 digits after decimal point in hex format\n"); + return 1; + } + + printf("Test Passed\n"); + + return 0; +} \ No newline at end of file