From f3154aabe45b01bcbfd1722ad9e7ec22c92b448c Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sun, 12 Jan 2020 18:42:25 +0100 Subject: [PATCH] mescc: Mes C Library: Support GNU Awk: Add dtoab, %f in vfprintf, vsnprintf. * include/libmes.h (dtoab): Declare. * lib/mes/ntoab.c (ntoab): Update. * lib/mes/dtoab.c: New file. * build-aux/configure-lib.sh (libmes_SOURCES, libc_tcc_SOURCES): Add it. * lib/tests/mes/90-dtoab.c: Test it. * lib/tests/stdio/90-sprintf.c: Test it. * build-aux/check-mescc.sh (tests): Run it, against... * lib/tests/mes/90-dtoab.stdout: ...baseline. * lib/stdio/vfprintf.c (vfprintf): Support %f, even more naive support for %e, %E, %g, %G. * lib/stdio/vsnprintf.c (vsnprintf): Likewise. --- build-aux/check-mescc.sh | 5 ++- build-aux/configure-lib.sh | 2 ++ include/mes/lib.h | 1 + lib/mes/dtoab.c | 46 ++++++++++++++++++++++++++++ lib/stdio/vfprintf.c | 46 +++++++++++++++++++++++++++- lib/stdio/vsnprintf.c | 51 ++++++++++++++++++++++++++++++- lib/tests/mes/90-dtoab.c | 36 ++++++++++++++++++++++ lib/tests/mes/90-dtoab.stdout | 2 ++ lib/tests/stdio/90-sprintf.c | 34 +++++++++++++++++++++ lib/tests/stdio/90-sprintf.stdout | 1 + 10 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 lib/mes/dtoab.c create mode 100644 lib/tests/mes/90-dtoab.c create mode 100644 lib/tests/mes/90-dtoab.stdout create mode 100644 lib/tests/stdio/90-sprintf.c create mode 100644 lib/tests/stdio/90-sprintf.stdout diff --git a/build-aux/check-mescc.sh b/build-aux/check-mescc.sh index d5fc5d07..eec0e4ec 100755 --- a/build-aux/check-mescc.sh +++ b/build-aux/check-mescc.sh @@ -201,6 +201,7 @@ if test -z "$bootstrap"; then lib/tests/dirent/90-readdir.c lib/tests/io/90-stat.c lib/tests/mes/90-abtod.c +lib/tests/mes/90-dtoab.c lib/tests/posix/90-execlp.c lib/tests/posix/90-unsetenv.c lib/tests/signal/90-signal.c @@ -208,6 +209,7 @@ lib/tests/stdio/90-fopen.c lib/tests/stdio/90-fopen-append.c lib/tests/stdio/90-fread-fwrite.c lib/tests/stdio/90-fseek.c +lib/tests/stdio/90-sprintf.c lib/tests/stdlib/90-strtol.c lib/tests/string/90-snprintf.c lib/tests/string/90-strpbrk.c @@ -226,7 +228,6 @@ fi XFAIL_TESTS=" lib/tests/mes/90-abtod.c lib/tests/stdio/90-sprintf.c -lib/tests/stdio/90-sprintf.c " if test $compiler = mescc; then @@ -235,6 +236,7 @@ lib/tests/scaffold/17-compare-unsigned-char-le.c lib/tests/scaffold/17-compare-unsigned-short-le.c lib/tests/scaffold/66-local-char-array.c lib/tests/scaffold/72-typedef-struct-def-local.c +lib/tests/mes/90-dtoab.c lib/tests/scaffold/90-goto-var.c lib/tests/scaffold/91-goto-array.c " @@ -253,6 +255,7 @@ fi if test $mes_cpu = x86; then XFAIL_TESTS="$XFAIL_TESTS +lib/tests/mes/90-dtoab.c " fi diff --git a/build-aux/configure-lib.sh b/build-aux/configure-lib.sh index ccec0f19..0cecaccf 100644 --- a/build-aux/configure-lib.sh +++ b/build-aux/configure-lib.sh @@ -87,6 +87,7 @@ lib/linux/lseek.c else libmes_SOURCES="$libmes_SOURCES lib/mes/abtod.c +lib/mes/dtoab.c " fi @@ -158,6 +159,7 @@ lib/ctype/isupper.c lib/ctype/tolower.c lib/ctype/toupper.c lib/mes/abtod.c +lib/mes/dtoab.c lib/mes/search-path.c lib/posix/execvp.c lib/stdio/fclose.c diff --git a/include/mes/lib.h b/include/mes/lib.h index e05da652..6b66107b 100644 --- a/include/mes/lib.h +++ b/include/mes/lib.h @@ -30,6 +30,7 @@ void __ungetc_set (int filedes, int c); int __ungetc_p (int filedes); double abtod (char const **p, int base); long abtol (char const **p, int base); +char *dtoab (double number, int base, int signed_p); char *itoa (int number); char *ltoa (long number); char *ltoab (long x, int base); diff --git a/lib/mes/dtoab.c b/lib/mes/dtoab.c new file mode 100644 index 00000000..dc190503 --- /dev/null +++ b/lib/mes/dtoab.c @@ -0,0 +1,46 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +#include +#include + +char * +dtoab (double d, int base, int signed_p) +{ + static char dtoa_buf[40]; + long i = (long) d; + char *p = ntoab (i, base, signed_p); + strcpy (dtoa_buf, p); + long f = (d - (double) i) * (double) 100000000000; + if (f) + { + if (f < 0) + f = -f; + strcat (dtoa_buf, "."); + p = ntoab (f, base, 1); + strcat (dtoa_buf, p); + p = strchr (dtoa_buf, 0); + p--; + while (*p && *p == '0') + *p-- = 0; + } + return dtoa_buf; +} diff --git a/lib/stdio/vfprintf.c b/lib/stdio/vfprintf.c index 119e41ae..9de972ad 100644 --- a/lib/stdio/vfprintf.c +++ b/lib/stdio/vfprintf.c @@ -1,6 +1,6 @@ /* -*-comment-start: "//";comment-end:""-*- * GNU Mes --- Maxwell Equations of Software - * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen + * Copyright © 2017,2018,2019 Jan (janneke) Nieuwenhuizen * * This file is part of GNU Mes. * @@ -182,6 +182,50 @@ vfprintf (FILE * f, char const *format, va_list ap) } break; } + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + { + double d = va_arg (ap, double); + char *s = dtoab (d, 10, 1); + if (c == 'E' || c == 'G') + strupr (s); + int length = strlen (s); + if (precision == -1) + precision = length; + if (!left_p) + { + while (width-- > precision) + { + fputc (pad, f); + count++; + } + while (precision > length) + { + fputc ('0', f); + precision--; + width--; + count++; + } + } + while (*s) + { + if (precision-- <= 0) + break; + width--; + fputc (*s++, f); + count++; + } + while (width > 0) + { + width--; + fputc (pad, f); + count++; + } + break; + } case 'n': { int *n = va_arg (ap, int *); diff --git a/lib/stdio/vsnprintf.c b/lib/stdio/vsnprintf.c index 2c224bfe..8b99ff58 100644 --- a/lib/stdio/vsnprintf.c +++ b/lib/stdio/vsnprintf.c @@ -1,6 +1,6 @@ /* -*-comment-start: "//";comment-end:""-*- * GNU Mes --- Maxwell Equations of Software - * Copyright © 2017,2018 Jan (janneke) Nieuwenhuizen + * Copyright © 2017,2018,2019 Jan (janneke) Nieuwenhuizen * * This file is part of GNU Mes. * @@ -198,6 +198,55 @@ vsnprintf (char *str, size_t size, char const *format, va_list ap) } break; } + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + { + double d = va_arg (ap, double); + char *s = dtoab (d, 10, 1); + if (c == 'E' || c == 'G') + strupr (s); + int length = strlen (s); + if (precision == -1) + precision = length; + if (!left_p) + { + while (width-- > precision) + { + if (count < size) + *str++ = pad; + count++; + } + while (precision > length) + { + if (count < size) + *str++ = '0'; + precision--; + width--; + count++; + } + } + while (*s) + { + if (precision-- <= 0) + break; + width--; + c = *s++; + if (count < size) + *str++ = c; + count++; + } + while (width > 0) + { + width--; + if (count < size) + *str++ = pad; + count++; + } + break; + } case 'n': { int *n = va_arg (ap, int *); diff --git a/lib/tests/mes/90-dtoab.c b/lib/tests/mes/90-dtoab.c new file mode 100644 index 00000000..1f7e29d1 --- /dev/null +++ b/lib/tests/mes/90-dtoab.c @@ -0,0 +1,36 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2019 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +#include + +int +main () +{ + double d = 1.23; + char *p = dtoab (d, 10, 1); + puts (p); + + d = -3.141592653589; + p = dtoab (d, 10, 1); + puts (p); + + return 0; +} diff --git a/lib/tests/mes/90-dtoab.stdout b/lib/tests/mes/90-dtoab.stdout new file mode 100644 index 00000000..88609219 --- /dev/null +++ b/lib/tests/mes/90-dtoab.stdout @@ -0,0 +1,2 @@ +1.23 +-3.14159265358 diff --git a/lib/tests/stdio/90-sprintf.c b/lib/tests/stdio/90-sprintf.c new file mode 100644 index 00000000..2401195d --- /dev/null +++ b/lib/tests/stdio/90-sprintf.c @@ -0,0 +1,34 @@ +/* -*-comment-start: "//";comment-end:""-*- + * GNU Mes --- Maxwell Equations of Software + * Copyright © 2019 Jan (janneke) Nieuwenhuizen + * + * This file is part of GNU Mes. + * + * GNU Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * GNU Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Mes. If not, see . + */ + +#include +#include +#include + +int +main () +{ + char buf[20]; + double d = 0; + sprintf (buf, "%.6g", d); + puts (buf); + + return 0; +} diff --git a/lib/tests/stdio/90-sprintf.stdout b/lib/tests/stdio/90-sprintf.stdout new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/lib/tests/stdio/90-sprintf.stdout @@ -0,0 +1 @@ +0