about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2022-08-22 05:00:41 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2022-08-22 05:00:41 +0000
commit4b8930e212a898efd5c2fa1fce40c9db9e4c20b2 (patch)
tree3b63709b24c7f93ee416ed1989d55d45ff11c5fc /lib
parentd55353a6c2b108bf5e6ae37b831d1b1dc19e4c83 (diff)
downloadnetpbm-mirror-4b8930e212a898efd5c2fa1fce40c9db9e4c20b2.tar.gz
netpbm-mirror-4b8930e212a898efd5c2fa1fce40c9db9e4c20b2.tar.xz
netpbm-mirror-4b8930e212a898efd5c2fa1fce40c9db9e4c20b2.zip
Make internal 'snprintf', 'vsnprintf' just wrap libc 'snprintf', 'vsnprintf'
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@4419 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r--lib/util/nstring.c707
-rw-r--r--lib/util/nstring.h4
2 files changed, 29 insertions, 682 deletions
diff --git a/lib/util/nstring.c b/lib/util/nstring.c
index 00da4f35..4bbb041f 100644
--- a/lib/util/nstring.c
+++ b/lib/util/nstring.c
@@ -2,87 +2,26 @@
                                nstring.c
 ===============================================================================
 
-   THIS MODULE WAS ADAPTED FOR NETPBM BY BRYAN HENDERSON ON 2002.03.24.
-   Bryan got the base snprintf.c from
-   http://www.ijs.si/software/snprintf/snprintf-2.2.tar.gz, but made
-   a lot of changes and additions.
-   The code from ww.ijs.si was written by
-
-     Mark Martinec <mark.martinec@ijs.si>
-
-   in April 1999 and June 2000.  Martinec claims copyright as of 1999, 2000,
-   2001, and 2002 and licenses the code to Netpbm maintainers and users (as
-   members of the public) under the GNU General Public License.
-
-   All other authors likewise license this code to the public under the
-   GNU General Public license.
-
- *
- * FEATURES
- * - careful adherence to specs regarding flags, field width and precision;
- * - good performance for large string handling (large format, large
- *   argument or large paddings). Performance is similar to system's sprintf
- *   and in several cases significantly better (make sure you compile with
- *   optimizations turned on, tell the compiler the code is strict ANSI
- *   if necessary to give it more freedom for optimizations);
- * - return value semantics per ISO/IEC 9899:1999 ("ISO C99");
- * - written in standard ISO/ANSI C - requires an ANSI C compiler.
- *
- * IMPLEMENTED CONVERSION SPECIFIERS AND DATA TYPES
- *
- * This snprintf implements only the following conversion specifiers:
- * s, c, d, u, o, x, X, p, f  (and synonyms: i, D, U, O - see below)
- * with flags: '-', '+', ' ', '0' and '#'.
- * An asterisk is acceptable for field width as well as precision.
- *
- * Length modifiers 'h' (short int), 'l' (long int),
- * and 'll' (long long int) are implemented.
- *
- * Conversion of numeric data (conversion specifiers d, u, o, x, X, p)
- * with length modifiers (none or h, l, ll) is left to the system routine
- * sprintf, but all handling of flags, field width and precision as well as
- * c and s conversions is done very carefully by this portable routine.
- * If a string precision (truncation) is specified (e.g. %.8s) it is
- * guaranteed the string beyond the specified precision will not be referenced.
- *
- * Length modifiers h, l and ll are ignored for c and s conversions (you
- * can't use data types wint_t and wchar_t).
- *
- * The following common synonyms for conversion characters are acceptable:
- *   - i is a synonym for d
- *   - D is a synonym for ld, explicit length modifiers are ignored
- *   - U is a synonym for lu, explicit length modifiers are ignored
- *   - O is a synonym for lo, explicit length modifiers are ignored
- * The D, O and U conversion characters are nonstandard, they are accepted
- * for backward compatibility only, and should not be used for new code.
- *
- * The following is specifically NOT implemented:
- *   - flag ' (thousands' grouping character) is recognized but ignored
- *   - numeric conversion specifiers: e, E, g, G and synonym F,
- *     as well as the new a and A conversion specifiers
- *   - length modifier 'L' (long double) and 'q' (quad - use 'll' instead)
- *   - wide character/string conversions: lc, ls, and nonstandard
- *     synonyms C and S
- *   - writeback of converted string length: conversion character n
- *   - the n$ specification for direct reference to n-th argument
- *   - locales
- *
- * It is permitted for str_m to be zero, and it is permitted to specify NULL
- * pointer for resulting string argument if str_m is zero (as per ISO C99).
- *
- * The return value is the number of characters which would be generated
- * for the given input, excluding the trailing null. If this value
- * is greater or equal to str_m, not all characters from the result
- * have been stored in str, output bytes beyond the (str_m-1) -th character
- * are discarded. If str_m is greater than zero it is guaranteed
- * the resulting string will be null-terminated.
- *
- * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1,
- * but is different from some older and vendor implementations,
- * and is also different from XPG, XSH5, SUSv2 specifications.
- * For historical discussion on changes in the semantics and standards
- * of snprintf see printf(3) man page in the Linux programmers manual.
- *
+  pm_snprintf (and pm_vsnprintf) in this file used to be derived from
+  'portable_snprintf' from
+  http://www.ijs.si/software/snprintf/snprintf-2.2.tar.gz, because not all
+  system C libraries had snprintf.  But in 2013, we extended that snprintf to
+  implement %f by calling 'snprintf' in the system C library, just to see if
+  it caused any build failures.  As of August 2022, there had been no
+  complaints of problems caused by this reliance on the system providing
+  snprintf, so we just made pm_snprintf a wrapper of snprintf for everything.
+
+  Eventually we will remove pm_snprintf and pm_vsnprintf altogether and their
+  callers will call 'snprintf' and 'vsnprintf' instead
+
+  Note that snprintf is required by the C99 standard.
+
+  The code from which pm_snprintf was formerly derived was protected by
+  copyright and licensed to the public under GPL.  A user in August 2022 noted
+  that GPL was insufficient for his use of it, making him unable to use
+  libnetpbm.
+
+  Code in this file is contributed to the public domain by its authors.
 =============================================================================*/
 #define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */
 #define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
@@ -91,9 +30,6 @@
    /* Because of conditional compilation, this is GNU source only if the C
       library is GNU.
    */
-#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
-#define PORTABLE_SNPRINTF_VERSION_MINOR 2
-
 #include <sys/types.h>
 #include <limits.h>
 #include <string.h>
@@ -108,64 +44,6 @@
 
 #include "nstring.h"
 
-#ifdef isdigit
-#undef isdigit
-#endif
-#define isdigit(c) ((c) >= '0' && (c) <= '9')
-
-/* For copying strings longer or equal to 'breakeven_point'
- * it is more efficient to call memcpy() than to do it inline.
- * The value depends mostly on the processor architecture,
- * but also on the compiler and its optimization capabilities.
- * The value is not critical, some small value greater than zero
- * will be just fine if you don't care to squeeze every drop
- * of performance out of the code.
- *
- * Small values favor memcpy, large values favor inline code.
- */
-#if defined(__alpha__) || defined(__alpha)
-#  define breakeven_point   2	/* AXP (DEC Alpha)     - gcc or cc or egcs */
-#endif
-#if defined(__i386__)  || defined(__i386)
-#  define breakeven_point  12	/* Intel Pentium/Linux - gcc 2.96 */
-#endif
-#if defined(__hppa)
-#  define breakeven_point  10	/* HP-PA               - gcc */
-#endif
-#if defined(__sparc__) || defined(__sparc)
-#  define breakeven_point  33	/* Sun Sparc 5         - gcc 2.8.1 */
-#endif
-
-/* some other values of possible interest: */
-/* #define breakeven_point  8 */  /* VAX 4000          - vaxc */
-/* #define breakeven_point 19 */  /* VAX 4000          - gcc 2.7.0 */
-
-#ifndef breakeven_point
-#  define breakeven_point   6	/* some reasonable one-size-fits-all value */
-#endif
-
-#define fast_memcpy(d,s,n) \
-  { register size_t nn = (size_t)(n); \
-    if (nn >= breakeven_point) memcpy((d), (s), nn); \
-    else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
-      register char *dd; register const char *ss; \
-      for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
-
-#define fast_memset(d,c,n) \
-  { register size_t nn = (size_t)(n); \
-    if (nn >= breakeven_point) memset((d), (int)(c), nn); \
-    else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
-      register char *dd; register const int cc=(int)(c); \
-      for (dd=(d); nn>0; nn--) *dd++ = cc; } }
-
-/* declarations */
-
-static char credits[] = "\n\
-@(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\
-@(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\
-@(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n";
-
-
 /* MacOS X before 10.7, for one, does not have strnlen */
 size_t
 pm_strnlen(const char * const s,
@@ -182,556 +60,25 @@ pm_strnlen(const char * const s,
 
 void
 pm_vsnprintf(char *       const str,
-             size_t       const str_m,
+             size_t       const maxSize,
              const char * const fmt,
              va_list            ap,
              size_t *     const sizeP) {
 
-    size_t str_l = 0;
-    const char *p = fmt;
+    int rc;
 
-    /* In contrast with POSIX, the ISO C99 now says that str can be
-       NULL and str_m can be 0.  This is more useful than the old:
-       if (str_m < 1) return -1;
-    */
+    rc = vsnprintf(str, maxSize, fmt, ap);
 
-    if (!p) p = "";
-    while (*p) {
-        if (*p != '%') {
-            /* if (str_l < str_m) str[str_l++] = *p++; -- this would
-               be sufficient but the following code achieves better
-               performance for cases * where format string is long and
-               contains few conversions
-            */
-            const char *q = strchr(p + 1,'%');
-            size_t n = !q ? strlen(p) : (q - p);
-            if (str_l < str_m) {
-                size_t const avail = str_m - str_l;
-                fast_memcpy(str + str_l, p, (MIN(n, avail)));
-            }
-            p += n; str_l += n;
-        } else {
-            size_t min_field_width;
-            size_t precision = 0;
-            bool precision_specified;
-            bool justify_left;
-            bool alternate_form;
-            bool force_sign;
-            bool space_for_positive;
-                /* If both the ' ' and '+' flags appear,
-                   the ' ' flag should be ignored.
-                */
-            char length_modifier = '\0';  /* allowed values: \0, h, l, L */
-            char tmp[32];
-                /* temporary buffer for simple numeric->string conversion */
-
-            const char *str_arg;
-                /* string address in case of string argument */
-            size_t str_arg_l;
-                /* natural field width of arg without padding and sign */
-            unsigned char uchar_arg;
-                /* unsigned char argument value - only defined for c
-                   conversion.  N.B. standard explicitly states the char
-                   argument for the c conversion is unsigned.
-                */
-
-            bool zero_padding;
-
-            size_t number_of_zeros_to_pad;
-                /* number of zeros to be inserted for numeric
-                   conversions as required by the precision or minimal
-                   field width
-                */
-
-            size_t zero_padding_insertion_ind;
-                /* index into tmp where zero padding is to be inserted */
-
-            char fmt_spec;
-                /* current conversion specifier character */
-
-            str_arg = credits;
-                /* just to make compiler happy (defined but not used) */
-            str_arg = NULL;
-            ++p;  /* skip '%' */
-
-            /* parse flags */
-            justify_left = false;  /* initial value */
-            alternate_form = false;  /* initial value */
-            force_sign = false;  /* initial value */
-            space_for_positive = false;  /* initial value */
-            zero_padding = false;  /* initial value */
-            number_of_zeros_to_pad = 0;  /* initial value */
-            zero_padding_insertion_ind = 0;  /* initial value */
-            fmt_spec = '\0';  /* initial value */
-
-            while (*p == '0' || *p == '-' || *p == '+' ||
-                   *p == ' ' || *p == '#' || *p == '\'') {
-                switch (*p) {
-                case '0': zero_padding = true; break;
-                case '-': justify_left = true; break;
-                case '+': force_sign = true; space_for_positive = false; break;
-                case ' ': force_sign = true; break;
-                    /* If both the ' ' and '+' flags appear, the ' '
-                       flag should be ignored
-                    */
-                case '#': alternate_form = true; break;
-                case '\'': break;
-                }
-                ++p;
-            }
-            /* If the '0' and '-' flags both appear, the '0' flag
-               should be ignored.
-            */
+    assert((size_t)rc == rc);
 
-            /* parse field width */
-            if (*p == '*') {
-                int j;
-                ++p;
-                j = va_arg(ap, int);
-                if (j >= 0) { min_field_width = j; justify_left = false; }
-                else { min_field_width = -j; justify_left = true; }
-            } else if (isdigit((int)(*p))) {
-                /* size_t could be wider than unsigned int; make sure
-                   we treat argument like common implementations do
-                */
-                unsigned int uj = *p++ - '0';
-                while (isdigit((int)(*p)))
-                    uj = 10*uj + (unsigned int)(*p++ - '0');
-                min_field_width = uj;
-            } else
-                min_field_width = 0;
-
-            /* parse precision */
-            if (*p == '.') {
-                ++p;
-                precision_specified = true;
-                if (*p == '*') {
-                    int j = va_arg(ap, int);
-                    p++;
-                    if (j >= 0) precision = j;
-                    else {
-                        precision_specified = false; precision = 0;
-                        /* NOTE: Solaris 2.6 man page claims that in
-                           this case the precision should be set to 0.
-                           Digital Unix 4.0, HPUX 10 and BSD man page
-                           claim that this case should be treated as
-                           unspecified precision, which is what we do
-                           here.
-                        */
-                    }
-                } else if (isdigit((int)(*p))) {
-                    /* size_t could be wider than unsigned int; make
-                       sure we treat argument like common
-                       implementations do
-                    */
-                    unsigned int uj = *p++ - '0';
-                    while (isdigit((int)(*p)))
-                        uj = 10*uj + (unsigned int)(*p++ - '0');
-                    precision = uj;
-                }
-            } else
-                precision_specified = false;
-
-            /* parse 'h', 'l' and 'll' length modifiers */
-            if (*p == 'h' || *p == 'l') {
-                length_modifier = *p; p++;
-                if (length_modifier == 'l' && *p == 'l') {
-                    /* double l = long long */
-                    length_modifier = 'l';  /* treat it as a single 'l' */
-                    p++;
-                }
-            }
-            fmt_spec = *p;
-
-            /* common synonyms: */
-            switch (fmt_spec) {
-            case 'i': fmt_spec = 'd'; break;
-            case 'D': fmt_spec = 'd'; length_modifier = 'l'; break;
-            case 'U': fmt_spec = 'u'; length_modifier = 'l'; break;
-            case 'O': fmt_spec = 'o'; length_modifier = 'l'; break;
-            default: break;
-            }
-            /* get parameter value, do initial processing */
-            switch (fmt_spec) {
-            case '%':
-                /* % behaves similar to 's' regarding flags and field widths */
-            case 'c':
-                /* c behaves similar to 's' regarding flags and field widths */
-            case 's':
-                /* wint_t and wchar_t not handled */
-                length_modifier = '\0';
-                /* the result of zero padding flag with non-numeric
-                    conversion specifier is undefined. Solaris and
-                    HPUX 10 does zero padding in this case, Digital
-                    Unix and Linux does not.
-                */
-
-                zero_padding = false;
-                    /* turn zero padding off for string conversions */
-                str_arg_l = 1;
-                switch (fmt_spec) {
-                case '%':
-                    str_arg = p; break;
-                case 'c': {
-                    int j = va_arg(ap, int);
-                    uchar_arg = (unsigned char) j;
-                        /* standard demands unsigned char */
-                    str_arg = (const char *) &uchar_arg;
-                    break;
-                }
-                case 's':
-                    str_arg = va_arg(ap, const char *);
-                    if (!str_arg)
-                        /* make sure not to address string beyond the
-                           specified precision !!!
-                        */
-                        str_arg_l = 0;
-                    else if (!precision_specified)
-                        /* truncate string if necessary as requested by
-                           precision
-                        */
-                        str_arg_l = strlen(str_arg);
-                    else if (precision == 0)
-                        str_arg_l = 0;
-                    else {
-                        /* memchr on HP does not like n > 2^31  !!! */
-                        const char * q =
-                            memchr(str_arg, '\0', MIN(precision, 0x7fffffff));
-                        str_arg_l = !q ? precision : (q-str_arg);
-                    }
-                    break;
-                default: break;
-                }
-                break;
-            case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': {
-                /* NOTE: the u, o, x, X and p conversion specifiers imply
-                   the value is unsigned;  d implies a signed value
-                */
-                int arg_sign = 0;
-                /* 0  if numeric argument is zero (or if pointer is NULL
-                      for 'p'),
-                   +1 if greater than zero (or nonzero for unsigned arguments),
-                   -1 if negative (unsigned argument is never negative)
-                */
-
-                int int_arg = 0;
-                unsigned int uint_arg = 0;
-                   /* defined only for length modifier h, or for no
-                      length modifiers
-                   */
-
-                long int long_arg = 0;  unsigned long int ulong_arg = 0;
-                /* only defined for length modifier l */
-
-                void *ptr_arg = NULL;
-                /* pointer argument value -only defined for p conversion */
-
-                if (fmt_spec == 'p') {
-                    /* HPUX 10: An l, h, ll or L before any other
-                        conversion character (other than d, i, u, o,
-                        x, or X) is ignored.
-
-                      Digital Unix: not specified, but seems to behave
-                      as HPUX does.
-
-                      Solaris: If an h, l, or L appears before any
-                      other conversion specifier (other than d, i, u,
-                      o, x, or X), the behavior is
-                      undefined. (Actually %hp converts only 16-bits
-                      of address and %llp treats address as 64-bit
-                      data which is incompatible with (void *)
-                      argument on a 32-bit system).
-                    */
-
-                    length_modifier = '\0';
-                    ptr_arg = va_arg(ap, void *);
-                    if (ptr_arg != NULL) arg_sign = 1;
-                } else if (fmt_spec == 'd') {  /* signed */
-                    switch (length_modifier) {
-                    case '\0':
-                    case 'h':
-                        /* It is non-portable to specify a second
-                           argument of char or short to va_arg,
-                           because arguments seen by the called
-                           function are not char or short.  C converts
-                           char and short arguments to int before
-                           passing them to a function.
-                        */
-                        int_arg = va_arg(ap, int);
-                        if      (int_arg > 0) arg_sign =  1;
-                        else if (int_arg < 0) arg_sign = -1;
-                        break;
-                    case 'l':
-                        long_arg = va_arg(ap, long int);
-                        if      (long_arg > 0) arg_sign =  1;
-                        else if (long_arg < 0) arg_sign = -1;
-                        break;
-                    }
-                } else {  /* unsigned */
-                    switch (length_modifier) {
-                    case '\0':
-                    case 'h':
-                        uint_arg = va_arg(ap, unsigned int);
-                        if (uint_arg)
-                            arg_sign = 1;
-                        break;
-                    case 'l':
-                        ulong_arg = va_arg(ap, unsigned long int);
-                        if (ulong_arg)
-                            arg_sign = 1;
-                        break;
-                    }
-                }
-                str_arg = tmp; str_arg_l = 0;
-                /* NOTE: For d, i, u, o, x, and X conversions, if
-                   precision is specified, the '0' flag should be
-                   ignored. This is so with Solaris 2.6, Digital UNIX
-                   4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with
-                   Perl.
-                */
-                if (precision_specified)
-                    zero_padding = false;
-                if (fmt_spec == 'd') {
-                    if (force_sign && arg_sign >= 0)
-                        tmp[str_arg_l++] = space_for_positive ? ' ' : '+';
-                    /* leave negative numbers for sprintf to handle,
-                       to avoid handling tricky cases like (short
-                       int)(-32768)
-                    */
-                } else if (alternate_form) {
-                    if (arg_sign != 0 && (fmt_spec == 'x' ||
-                                          fmt_spec == 'X')) {
-                        tmp[str_arg_l++] = '0';
-                        tmp[str_arg_l++] = fmt_spec;
-                    }
-                    /* alternate form should have no effect for p
-                       conversion, but ...
-                    */
-                }
-                zero_padding_insertion_ind = str_arg_l;
-                if (!precision_specified)
-                    precision = 1;   /* default precision is 1 */
-                if (precision == 0 && arg_sign == 0) {
-                    /* converted to null string */
-                    /* When zero value is formatted with an explicit
-                       precision 0, the resulting formatted string is
-                       empty (d, i, u, o, x, X, p).
-                    */
-                } else {
-                    char f[5]; int f_l = 0;
-                    f[f_l++] = '%';
-                        /* construct a simple format string for sprintf */
-                    if (!length_modifier) { }
-                    else if (length_modifier=='2') {
-                        f[f_l++] = 'l'; f[f_l++] = 'l';
-                    }
-                    else
-                        f[f_l++] = length_modifier;
-                    f[f_l++] = fmt_spec; f[f_l++] = '\0';
-                    if (fmt_spec == 'p')
-                        str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg);
-                    else if (fmt_spec == 'd') {  /* signed */
-                        switch (length_modifier) {
-                        case '\0':
-                        case 'h':
-                            str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg);
-                            break;
-                        case 'l':
-                            str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg);
-                            break;
-                        }
-                    } else {  /* unsigned */
-                        switch (length_modifier) {
-                        case '\0':
-                        case 'h':
-                            str_arg_l += sprintf(tmp+str_arg_l, f, uint_arg);
-                            break;
-                        case 'l':
-                            str_arg_l += sprintf(tmp+str_arg_l, f, ulong_arg);
-                            break;
-                        }
-                    }
-                    /* include the optional minus sign and possible "0x"
-                       in the region before the zero padding insertion point
-                    */
-                    if (zero_padding_insertion_ind < str_arg_l &&
-                        tmp[zero_padding_insertion_ind] == '-') {
-                        zero_padding_insertion_ind += 1;
-                    }
-                    if (zero_padding_insertion_ind + 1 < str_arg_l &&
-                        tmp[zero_padding_insertion_ind]   == '0' &&
-                        (tmp[zero_padding_insertion_ind+1] == 'x' ||
-                         tmp[zero_padding_insertion_ind+1] == 'X') ) {
-                        zero_padding_insertion_ind += 2;
-                    }
-                }
-                {
-                    size_t const num_of_digits =
-                        str_arg_l - zero_padding_insertion_ind;
-                    if (alternate_form && fmt_spec == 'o'
-                        /* unless zero is already the first character */
-                        && !(zero_padding_insertion_ind < str_arg_l
-                             && tmp[zero_padding_insertion_ind] == '0')) {
-                        /* assure leading zero for alternate-form
-                           octal numbers
-                        */
-                        if (!precision_specified ||
-                            precision < num_of_digits+1) {
-                            /* precision is increased to force the
-                               first character to be zero, except if a
-                               zero value is formatted with an
-                               explicit precision of zero
-                            */
-                            precision = num_of_digits+1;
-                            precision_specified = true;
-                        }
-                    }
-                    /* zero padding to specified precision? */
-                    if (num_of_digits < precision)
-                        number_of_zeros_to_pad = precision - num_of_digits;
-                }
-                /* zero padding to specified minimal field width? */
-                if (!justify_left && zero_padding) {
-                    int const n =
-                        min_field_width - (str_arg_l+number_of_zeros_to_pad);
-                    if (n > 0)
-                        number_of_zeros_to_pad += n;
-                }
-            } break;
-            case 'f': {
-                char f[10];
-                if (precision_specified)
-                    snprintf(f, ARRAY_SIZE(f), "%%%u.%uf",
-                             (unsigned)min_field_width, (unsigned)precision);
-                else
-                    snprintf(f, ARRAY_SIZE(f), "%%%uf",
-                             (unsigned)min_field_width);
-
-                str_arg_l = sprintf(tmp, f, va_arg(ap, double));
-                str_arg = &tmp[0];
-
-                min_field_width = 0;
-                zero_padding_insertion_ind = 0;
-            } break;
-            default:
-                /* Unrecognized conversion specifier.  Discard the
-                   unrecognized conversion, just keep the unrecognized
-                   conversion character.
-                */
-                zero_padding = false;
-                    /* turn zero padding off for non-numeric convers. */
-                /* reset flags */
-                justify_left = true;
-                min_field_width = 0;
-                str_arg = p;
-                str_arg_l = 0;
-                if (*p)
-                    /* include invalid conversion specifier unchanged
-                       if not at end-of-string
-                    */
-                    ++str_arg_l;
-                break;
-            }
-            if (*p)
-                p++;  /* step over the just processed conversion specifier */
-            /* insert padding to the left as requested by
-               min_field_width; this does not include the zero padding
-               in case of numerical conversions
-            */
-
-            if (!justify_left) {
-                /* left padding with blank or zero */
-                int n = min_field_width - (str_arg_l + number_of_zeros_to_pad);
-                if (n > 0) {
-                    if (str_l < str_m) {
-                        size_t const avail = str_m - str_l;
-                        fast_memset(str + str_l, (zero_padding ? '0' : ' '),
-                                    (MIN(n, avail)));
-                    }
-                    str_l += n;
-                }
-            }
-            /* zero padding as requested by the precision or by the
-               minimal field width for numeric conversions required?
-            */
-            if (number_of_zeros_to_pad <= 0) {
-                /* will not copy first part of numeric right now,
-                   force it to be copied later in its entirety
-                */
-                zero_padding_insertion_ind = 0;
-            } else {
-                {
-                    /* insert first part of numerics (sign or '0x') before
-                       zero padding
-                    */
-                    int const n = zero_padding_insertion_ind;
-                    if (n > 0) {
-                        if (str_l < str_m) {
-                            size_t const avail = str_m - str_l;
-                            fast_memcpy(str + str_l, str_arg, (MIN(n, avail)));
-                        }
-                        str_l += n;
-                    }
-                }
-                {
-                    /* insert zero padding as requested by the precision
-                       or min field width
-                    */
-                    int const n = number_of_zeros_to_pad;
-                    if (n > 0) {
-                        if (str_l < str_m) {
-                            size_t const avail = str_m - str_l;
-                            fast_memset(str + str_l, '0', (MIN(n, avail)));
-                        }
-                        str_l += n;
-                    }
-                }
-            }
-            /* insert formatted string (or as-is conversion specifier
-               for unknown conversions)
-            */
-            {
-                int const n = str_arg_l - zero_padding_insertion_ind;
-                if (n > 0) {
-                    if (str_l < str_m) {
-                        size_t const avail = str_m-str_l;
-                        fast_memcpy(str + str_l,
-                                    str_arg + zero_padding_insertion_ind,
-                                    MIN(n, avail));
-                    }
-                    str_l += n;
-                }
-            }
-            /* insert right padding */
-            if (justify_left) {
-                /* right blank padding to the field width */
-                int const n =
-                    min_field_width - (str_arg_l + number_of_zeros_to_pad);
-                if (n > 0) {
-                    if (str_l < str_m) {
-                        size_t const avail = str_m - str_l;
-                        fast_memset(str+str_l, ' ', (MIN(n, avail)));
-                    }
-                    str_l += n;
-                }
-            }
-        }
-    }
-    if (str_m > 0) {
-        /* make sure the string is null-terminated even at the expense
-           of overwriting the last character (shouldn't happen, but
-           just in case)
-        */
-        str[MIN(str_l, str_m - 1)] = '\0';
-    }
-    *sizeP = str_l;
+    *sizeP = (size_t)rc;
 }
 
 
 
 int
 pm_snprintf(char *       const dest,
-            size_t       const str_m,
+            size_t       const maxSize,
             const char * const fmt,
             ...) {
 
@@ -740,7 +87,7 @@ pm_snprintf(char *       const dest,
 
     va_start(ap, fmt);
 
-    pm_vsnprintf(dest, str_m, fmt, ap, &size);
+    pm_vsnprintf(dest, maxSize, fmt, ap, &size);
 
     va_end(ap);
 
diff --git a/lib/util/nstring.h b/lib/util/nstring.h
index 56ec1b2b..1f03e4f2 100644
--- a/lib/util/nstring.h
+++ b/lib/util/nstring.h
@@ -157,13 +157,13 @@ pm_strnlen(const char * const s,
 
 int
 pm_snprintf(char *       const dest,
-            size_t       const str_m,
+            size_t       const maxSize,
             const char * const fmt,
             ...) PM_GNU_PRINTF_ATTR(3,4);
 
 void
 pm_vsnprintf(char *       const str,
-             size_t       const str_m,
+             size_t       const maxSize,
              const char * const fmt,
              va_list            ap,
              size_t *     const sizeP);