From 4ae906e46c4c173b79c9c60c6157ff68e05f7464 Mon Sep 17 00:00:00 2001 From: Francois-Xavier Coudert Date: Sat, 25 Dec 2021 15:07:12 +0100 Subject: Fortran: simplify library code for integer-to-decimal conversion libgfortran/ChangeLog: PR libfortran/81986 PR libfortran/99191 * libgfortran.h: Remove gfc_xtoa(), adjust gfc_itoa() and GFC_ITOA_BUF_SIZE. * io/write.c (write_decimal): conversion parameter is always gfc_itoa(), so remove it. Protect from overflow. (xtoa): Move gfc_xtoa and update its name. (xtoa_big): Renamed from ztoa_big for consistency. (write_z): Adjust to new function names. (write_i, write_integer): Remove last arg of write_decimal. * runtime/backtrace.c (error_callback): Comment on the use of gfc_itoa(). * runtime/error.c (gfc_xtoa): Move to io/write.c. * runtime/string.c (gfc_itoa): Take an unsigned argument, remove the handling of negative values. --- libgfortran/runtime/backtrace.c | 1 + libgfortran/runtime/error.c | 31 ------------------------------- libgfortran/runtime/string.c | 39 +++++++++++++++------------------------ 3 files changed, 16 insertions(+), 55 deletions(-) (limited to 'libgfortran/runtime') diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c index 5ac0831..403c7c3 100644 --- a/libgfortran/runtime/backtrace.c +++ b/libgfortran/runtime/backtrace.c @@ -97,6 +97,7 @@ error_callback (void *data, const char *msg, int errnum) iov[1].iov_len = strlen (msg); iov[2].iov_base = (char*) ", errno: "; iov[2].iov_len = strlen (iov[2].iov_base); + /* Async-signal-safe function, errnum must be positive. */ const char *p = gfc_itoa (errnum, errbuf, sizeof (errbuf)); iov[3].iov_base = (char*) p; iov[3].iov_len = strlen (p); diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c index b9c7574..ba6ff86 100644 --- a/libgfortran/runtime/error.c +++ b/libgfortran/runtime/error.c @@ -219,37 +219,6 @@ exit_error (int status) } - -/* gfc_xtoa()-- Integer to hexadecimal conversion. */ - -const char * -gfc_xtoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len) -{ - int digit; - char *p; - - assert (len >= GFC_XTOA_BUF_SIZE); - - if (n == 0) - return "0"; - - p = buffer + GFC_XTOA_BUF_SIZE - 1; - *p = '\0'; - - while (n != 0) - { - digit = n & 0xF; - if (digit > 9) - digit += 'A' - '0' - 10; - - *--p = '0' + digit; - n >>= 4; - } - - return p; -} - - /* Hopefully thread-safe wrapper for a strerror() style function. */ char * diff --git a/libgfortran/runtime/string.c b/libgfortran/runtime/string.c index 536a9cd..835027a 100644 --- a/libgfortran/runtime/string.c +++ b/libgfortran/runtime/string.c @@ -169,21 +169,22 @@ find_option (st_parameter_common *cmp, const char *s1, gfc_charlen_type s1_len, } -/* gfc_itoa()-- Integer to decimal conversion. - The itoa function is a widespread non-standard extension to - standard C, often declared in . Even though the itoa - defined here is a static function we take care not to conflict with - any prior non-static declaration. Hence the 'gfc_' prefix, which - is normally reserved for functions with external linkage. Notably, - in contrast to the *printf() family of functions, this ought to be - async-signal-safe. */ +/* Integer to decimal conversion. + + This function is much more restricted than the widespread (but + non-standard) itoa() function. This version has the following + characteristics: + + - it takes only non-negative arguments + - it is async-signal-safe (we use it runtime/backtrace.c) + - it works in base 10 (see xtoa, otoa, btoa functions + in io/write.c for other radices) + */ const char * -gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len) +gfc_itoa (GFC_UINTEGER_LARGEST n, char *buffer, size_t len) { - int negative; char *p; - GFC_UINTEGER_LARGEST t; if (len < GFC_ITOA_BUF_SIZE) sys_abort (); @@ -191,24 +192,14 @@ gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len) if (n == 0) return "0"; - negative = 0; - t = n; - if (n < 0) - { - negative = 1; - t = -(GFC_UINTEGER_LARGEST) n; /* Must use unsigned to protect from overflow. */ - } - p = buffer + GFC_ITOA_BUF_SIZE - 1; *p = '\0'; - while (t != 0) + while (n != 0) { - *--p = '0' + (t % 10); - t /= 10; + *--p = '0' + (n % 10); + n /= 10; } - if (negative) - *--p = '-'; return p; } -- cgit v1.1