1*2b15cb3dSCy Schubert /* 2*2b15cb3dSCy Schubert * Modified by Dave Hart for integration into NTP 4.2.7 <hart@ntp.org> 3*2b15cb3dSCy Schubert * 4*2b15cb3dSCy Schubert * Changed in a backwards-incompatible way to separate HAVE_SNPRINTF 5*2b15cb3dSCy Schubert * from HW_WANT_RPL_SNPRINTF, etc. for each of the four replaced 6*2b15cb3dSCy Schubert * functions. 7*2b15cb3dSCy Schubert * 8*2b15cb3dSCy Schubert * Changed to honor hw_force_rpl_snprintf=yes, etc. This is used by NTP 9*2b15cb3dSCy Schubert * to test rpl_snprintf() and rpl_vsnprintf() on platforms which provide 10*2b15cb3dSCy Schubert * C99-compliant implementations. 11*2b15cb3dSCy Schubert */ 12*2b15cb3dSCy Schubert 13*2b15cb3dSCy Schubert /* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */ 14*2b15cb3dSCy Schubert 15*2b15cb3dSCy Schubert /* 16*2b15cb3dSCy Schubert * Copyright (c) 1995 Patrick Powell. 17*2b15cb3dSCy Schubert * 18*2b15cb3dSCy Schubert * This code is based on code written by Patrick Powell <papowell@astart.com>. 19*2b15cb3dSCy Schubert * It may be used for any purpose as long as this notice remains intact on all 20*2b15cb3dSCy Schubert * source code distributions. 21*2b15cb3dSCy Schubert */ 22*2b15cb3dSCy Schubert 23*2b15cb3dSCy Schubert /* 24*2b15cb3dSCy Schubert * Copyright (c) 2008 Holger Weiss. 25*2b15cb3dSCy Schubert * 26*2b15cb3dSCy Schubert * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>. 27*2b15cb3dSCy Schubert * My changes to the code may freely be used, modified and/or redistributed for 28*2b15cb3dSCy Schubert * any purpose. It would be nice if additions and fixes to this file (including 29*2b15cb3dSCy Schubert * trivial code cleanups) would be sent back in order to let me include them in 30*2b15cb3dSCy Schubert * the version available at <http://www.jhweiss.de/software/snprintf.html>. 31*2b15cb3dSCy Schubert * However, this is not a requirement for using or redistributing (possibly 32*2b15cb3dSCy Schubert * modified) versions of this file, nor is leaving this notice intact mandatory. 33*2b15cb3dSCy Schubert */ 34*2b15cb3dSCy Schubert 35*2b15cb3dSCy Schubert /* 36*2b15cb3dSCy Schubert * History 37*2b15cb3dSCy Schubert * 38*2b15cb3dSCy Schubert * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1: 39*2b15cb3dSCy Schubert * 40*2b15cb3dSCy Schubert * Fixed the detection of infinite floating point values on IRIX (and 41*2b15cb3dSCy Schubert * possibly other systems) and applied another few minor cleanups. 42*2b15cb3dSCy Schubert * 43*2b15cb3dSCy Schubert * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0: 44*2b15cb3dSCy Schubert * 45*2b15cb3dSCy Schubert * Added a lot of new features, fixed many bugs, and incorporated various 46*2b15cb3dSCy Schubert * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery 47*2b15cb3dSCy Schubert * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller 48*2b15cb3dSCy Schubert * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH 49*2b15cb3dSCy Schubert * projects. The additions include: support the "e", "E", "g", "G", and 50*2b15cb3dSCy Schubert * "F" conversion specifiers (and use conversion style "f" or "F" for the 51*2b15cb3dSCy Schubert * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", 52*2b15cb3dSCy Schubert * "t", and "z" length modifiers; support the "#" flag and the (non-C99) 53*2b15cb3dSCy Schubert * "'" flag; use localeconv(3) (if available) to get both the current 54*2b15cb3dSCy Schubert * locale's decimal point character and the separator between groups of 55*2b15cb3dSCy Schubert * digits; fix the handling of various corner cases of field width and 56*2b15cb3dSCy Schubert * precision specifications; fix various floating point conversion bugs; 57*2b15cb3dSCy Schubert * handle infinite and NaN floating point values; don't attempt to write to 58*2b15cb3dSCy Schubert * the output buffer (which may be NULL) if a size of zero was specified; 59*2b15cb3dSCy Schubert * check for integer overflow of the field width, precision, and return 60*2b15cb3dSCy Schubert * values and during the floating point conversion; use the OUTCHAR() macro 61*2b15cb3dSCy Schubert * instead of a function for better performance; provide asprintf(3) and 62*2b15cb3dSCy Schubert * vasprintf(3) functions; add new test cases. The replacement functions 63*2b15cb3dSCy Schubert * have been renamed to use an "rpl_" prefix, the function calls in the 64*2b15cb3dSCy Schubert * main project (and in this file) must be redefined accordingly for each 65*2b15cb3dSCy Schubert * replacement function which is needed (by using Autoconf or other means). 66*2b15cb3dSCy Schubert * Various other minor improvements have been applied and the coding style 67*2b15cb3dSCy Schubert * was cleaned up for consistency. 68*2b15cb3dSCy Schubert * 69*2b15cb3dSCy Schubert * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13: 70*2b15cb3dSCy Schubert * 71*2b15cb3dSCy Schubert * C99 compliant snprintf(3) and vsnprintf(3) functions return the number 72*2b15cb3dSCy Schubert * of characters that would have been written to a sufficiently sized 73*2b15cb3dSCy Schubert * buffer (excluding the '\0'). The original code simply returned the 74*2b15cb3dSCy Schubert * length of the resulting output string, so that's been fixed. 75*2b15cb3dSCy Schubert * 76*2b15cb3dSCy Schubert * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8: 77*2b15cb3dSCy Schubert * 78*2b15cb3dSCy Schubert * The original code assumed that both snprintf(3) and vsnprintf(3) were 79*2b15cb3dSCy Schubert * missing. Some systems only have snprintf(3) but not vsnprintf(3), so 80*2b15cb3dSCy Schubert * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. 81*2b15cb3dSCy Schubert * 82*2b15cb3dSCy Schubert * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i: 83*2b15cb3dSCy Schubert * 84*2b15cb3dSCy Schubert * The PGP code was using unsigned hexadecimal formats. Unfortunately, 85*2b15cb3dSCy Schubert * unsigned formats simply didn't work. 86*2b15cb3dSCy Schubert * 87*2b15cb3dSCy Schubert * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1: 88*2b15cb3dSCy Schubert * 89*2b15cb3dSCy Schubert * Ok, added some minimal floating point support, which means this probably 90*2b15cb3dSCy Schubert * requires libm on most operating systems. Don't yet support the exponent 91*2b15cb3dSCy Schubert * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just 92*2b15cb3dSCy Schubert * wasn't being exercised in ways which showed it, so that's been fixed. 93*2b15cb3dSCy Schubert * Also, formatted the code to Mutt conventions, and removed dead code left 94*2b15cb3dSCy Schubert * over from the original. Also, there is now a builtin-test, run with: 95*2b15cb3dSCy Schubert * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf 96*2b15cb3dSCy Schubert * 97*2b15cb3dSCy Schubert * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43: 98*2b15cb3dSCy Schubert * 99*2b15cb3dSCy Schubert * This was ugly. It is still ugly. I opted out of floating point 100*2b15cb3dSCy Schubert * numbers, but the formatter understands just about everything from the 101*2b15cb3dSCy Schubert * normal C string format, at least as far as I can tell from the Solaris 102*2b15cb3dSCy Schubert * 2.5 printf(3S) man page. 103*2b15cb3dSCy Schubert */ 104*2b15cb3dSCy Schubert 105*2b15cb3dSCy Schubert /* 106*2b15cb3dSCy Schubert * ToDo 107*2b15cb3dSCy Schubert * 108*2b15cb3dSCy Schubert * - Add wide character support. 109*2b15cb3dSCy Schubert * - Add support for "%a" and "%A" conversions. 110*2b15cb3dSCy Schubert * - Create test routines which predefine the expected results. Our test cases 111*2b15cb3dSCy Schubert * usually expose bugs in system implementations rather than in ours :-) 112*2b15cb3dSCy Schubert */ 113*2b15cb3dSCy Schubert 114*2b15cb3dSCy Schubert /* 115*2b15cb3dSCy Schubert * Usage 116*2b15cb3dSCy Schubert * 117*2b15cb3dSCy Schubert * 1) The following preprocessor macros should be defined to 1 if the feature or 118*2b15cb3dSCy Schubert * file in question is available on the target system (by using Autoconf or 119*2b15cb3dSCy Schubert * other means), though basic functionality should be available as long as 120*2b15cb3dSCy Schubert * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: 121*2b15cb3dSCy Schubert * 122*2b15cb3dSCy Schubert * HW_WANT_RPL_VSNPRINTF 123*2b15cb3dSCy Schubert * HW_WANT_RPL_SNPRINTF 124*2b15cb3dSCy Schubert * HW_WANT_RPL_VASPRINTF 125*2b15cb3dSCy Schubert * HW_WANT_RPL_ASPRINTF 126*2b15cb3dSCy Schubert * HAVE_VSNPRINTF // define to 1 #if HW_WANT_RPL_VSNPRINTF 127*2b15cb3dSCy Schubert * HAVE_SNPRINTF // define to 1 #if HW_WANT_RPL_SNPRINTF 128*2b15cb3dSCy Schubert * HAVE_VASPRINTF // define to 1 #if HW_WANT_RPL_VASPRINTF 129*2b15cb3dSCy Schubert * HAVE_ASPRINTF // define to 1 #if HW_WANT_RPL_ASPRINTF 130*2b15cb3dSCy Schubert * HAVE_STDARG_H 131*2b15cb3dSCy Schubert * HAVE_STDDEF_H 132*2b15cb3dSCy Schubert * HAVE_STDINT_H 133*2b15cb3dSCy Schubert * HAVE_STDLIB_H 134*2b15cb3dSCy Schubert * HAVE_INTTYPES_H 135*2b15cb3dSCy Schubert * HAVE_LOCALE_H 136*2b15cb3dSCy Schubert * HAVE_LOCALECONV 137*2b15cb3dSCy Schubert * HAVE_LCONV_DECIMAL_POINT 138*2b15cb3dSCy Schubert * HAVE_LCONV_THOUSANDS_SEP 139*2b15cb3dSCy Schubert * HAVE_LONG_DOUBLE 140*2b15cb3dSCy Schubert * HAVE_LONG_LONG_INT 141*2b15cb3dSCy Schubert * HAVE_UNSIGNED_LONG_LONG_INT 142*2b15cb3dSCy Schubert * HAVE_INTMAX_T 143*2b15cb3dSCy Schubert * HAVE_UINTMAX_T 144*2b15cb3dSCy Schubert * HAVE_UINTPTR_T 145*2b15cb3dSCy Schubert * HAVE_PTRDIFF_T 146*2b15cb3dSCy Schubert * HAVE_VA_COPY 147*2b15cb3dSCy Schubert * HAVE___VA_COPY 148*2b15cb3dSCy Schubert * 149*2b15cb3dSCy Schubert * 2) The calls to the functions which should be replaced must be redefined 150*2b15cb3dSCy Schubert * throughout the project files (by using Autoconf or other means): 151*2b15cb3dSCy Schubert * 152*2b15cb3dSCy Schubert * #if HW_WANT_RPL_VSNPRINTF 153*2b15cb3dSCy Schubert * #define vsnprintf rpl_vsnprintf 154*2b15cb3dSCy Schubert * #endif 155*2b15cb3dSCy Schubert * #if HW_WANT_RPL_SNPRINTF 156*2b15cb3dSCy Schubert * #define snprintf rpl_snprintf 157*2b15cb3dSCy Schubert * #endif 158*2b15cb3dSCy Schubert * #if HW_WANT_RPL_VASPRINTF 159*2b15cb3dSCy Schubert * #define vasprintf rpl_vasprintf 160*2b15cb3dSCy Schubert * #endif 161*2b15cb3dSCy Schubert * #if HW_WANT_RPL_ASPRINTF 162*2b15cb3dSCy Schubert * #define asprintf rpl_asprintf 163*2b15cb3dSCy Schubert * #endif 164*2b15cb3dSCy Schubert * 165*2b15cb3dSCy Schubert * 3) The required replacement functions should be declared in some header file 166*2b15cb3dSCy Schubert * included throughout the project files: 167*2b15cb3dSCy Schubert * 168*2b15cb3dSCy Schubert * #if HAVE_CONFIG_H 169*2b15cb3dSCy Schubert * #include <config.h> 170*2b15cb3dSCy Schubert * #endif 171*2b15cb3dSCy Schubert * #if HAVE_STDARG_H 172*2b15cb3dSCy Schubert * #include <stdarg.h> 173*2b15cb3dSCy Schubert * #if HW_WANT_RPL_VSNPRINTF 174*2b15cb3dSCy Schubert * int rpl_vsnprintf(char *, size_t, const char *, va_list); 175*2b15cb3dSCy Schubert * #endif 176*2b15cb3dSCy Schubert * #if HW_WANT_RPL_SNPRINTF 177*2b15cb3dSCy Schubert * int rpl_snprintf(char *, size_t, const char *, ...); 178*2b15cb3dSCy Schubert * #endif 179*2b15cb3dSCy Schubert * #if HW_WANT_RPL_VASPRINTF 180*2b15cb3dSCy Schubert * int rpl_vasprintf(char **, const char *, va_list); 181*2b15cb3dSCy Schubert * #endif 182*2b15cb3dSCy Schubert * #if HW_WANT_RPL_ASPRINTF 183*2b15cb3dSCy Schubert * int rpl_asprintf(char **, const char *, ...); 184*2b15cb3dSCy Schubert * #endif 185*2b15cb3dSCy Schubert * #endif 186*2b15cb3dSCy Schubert * 187*2b15cb3dSCy Schubert * Autoconf macros for handling step 1 and step 2 are available at 188*2b15cb3dSCy Schubert * <http://www.jhweiss.de/software/snprintf.html>. 189*2b15cb3dSCy Schubert */ 190*2b15cb3dSCy Schubert 191*2b15cb3dSCy Schubert #if HAVE_CONFIG_H 192224ba2bdSOllivier Robert #include <config.h> 193*2b15cb3dSCy Schubert #endif /* HAVE_CONFIG_H */ 194224ba2bdSOllivier Robert 195*2b15cb3dSCy Schubert #if TEST_SNPRINTF 196*2b15cb3dSCy Schubert #include <math.h> /* For pow(3), NAN, and INFINITY. */ 197*2b15cb3dSCy Schubert #include <string.h> /* For strcmp(3). */ 198*2b15cb3dSCy Schubert #if defined(__NetBSD__) || \ 199*2b15cb3dSCy Schubert defined(__FreeBSD__) || \ 200*2b15cb3dSCy Schubert defined(__OpenBSD__) || \ 201*2b15cb3dSCy Schubert defined(__NeXT__) || \ 202*2b15cb3dSCy Schubert defined(__bsd__) 203*2b15cb3dSCy Schubert #define OS_BSD 1 204*2b15cb3dSCy Schubert #elif defined(sgi) || defined(__sgi) 205*2b15cb3dSCy Schubert #ifndef __c99 206*2b15cb3dSCy Schubert #define __c99 /* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */ 207*2b15cb3dSCy Schubert #endif /* !defined(__c99) */ 208*2b15cb3dSCy Schubert #define OS_IRIX 1 209*2b15cb3dSCy Schubert #define OS_SYSV 1 210*2b15cb3dSCy Schubert #elif defined(__svr4__) 211*2b15cb3dSCy Schubert #define OS_SYSV 1 212*2b15cb3dSCy Schubert #elif defined(__linux__) 213*2b15cb3dSCy Schubert #define OS_LINUX 1 214*2b15cb3dSCy Schubert #endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */ 215*2b15cb3dSCy Schubert #if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */ 216*2b15cb3dSCy Schubert #ifdef HAVE_SNPRINTF 217*2b15cb3dSCy Schubert #undef HAVE_SNPRINTF 218*2b15cb3dSCy Schubert #endif /* defined(HAVE_SNPRINTF) */ 219*2b15cb3dSCy Schubert #ifdef HAVE_VSNPRINTF 220*2b15cb3dSCy Schubert #undef HAVE_VSNPRINTF 221*2b15cb3dSCy Schubert #endif /* defined(HAVE_VSNPRINTF) */ 222*2b15cb3dSCy Schubert #ifdef HAVE_ASPRINTF 223*2b15cb3dSCy Schubert #undef HAVE_ASPRINTF 224*2b15cb3dSCy Schubert #endif /* defined(HAVE_ASPRINTF) */ 225*2b15cb3dSCy Schubert #ifdef HAVE_VASPRINTF 226*2b15cb3dSCy Schubert #undef HAVE_VASPRINTF 227*2b15cb3dSCy Schubert #endif /* defined(HAVE_VASPRINTF) */ 228*2b15cb3dSCy Schubert #ifdef snprintf 229*2b15cb3dSCy Schubert #undef snprintf 230*2b15cb3dSCy Schubert #endif /* defined(snprintf) */ 231*2b15cb3dSCy Schubert #ifdef vsnprintf 232*2b15cb3dSCy Schubert #undef vsnprintf 233*2b15cb3dSCy Schubert #endif /* defined(vsnprintf) */ 234*2b15cb3dSCy Schubert #ifdef asprintf 235*2b15cb3dSCy Schubert #undef asprintf 236*2b15cb3dSCy Schubert #endif /* defined(asprintf) */ 237*2b15cb3dSCy Schubert #ifdef vasprintf 238*2b15cb3dSCy Schubert #undef vasprintf 239*2b15cb3dSCy Schubert #endif /* defined(vasprintf) */ 240*2b15cb3dSCy Schubert #else /* By default, we assume a modern system for testing. */ 241*2b15cb3dSCy Schubert #ifndef HAVE_STDARG_H 242*2b15cb3dSCy Schubert #define HAVE_STDARG_H 1 243*2b15cb3dSCy Schubert #endif /* HAVE_STDARG_H */ 244*2b15cb3dSCy Schubert #ifndef HAVE_STDDEF_H 245*2b15cb3dSCy Schubert #define HAVE_STDDEF_H 1 246*2b15cb3dSCy Schubert #endif /* HAVE_STDDEF_H */ 247*2b15cb3dSCy Schubert #ifndef HAVE_STDINT_H 248*2b15cb3dSCy Schubert #define HAVE_STDINT_H 1 249*2b15cb3dSCy Schubert #endif /* HAVE_STDINT_H */ 250*2b15cb3dSCy Schubert #ifndef HAVE_STDLIB_H 251*2b15cb3dSCy Schubert #define HAVE_STDLIB_H 1 252*2b15cb3dSCy Schubert #endif /* HAVE_STDLIB_H */ 253*2b15cb3dSCy Schubert #ifndef HAVE_INTTYPES_H 254*2b15cb3dSCy Schubert #define HAVE_INTTYPES_H 1 255*2b15cb3dSCy Schubert #endif /* HAVE_INTTYPES_H */ 256*2b15cb3dSCy Schubert #ifndef HAVE_LOCALE_H 257*2b15cb3dSCy Schubert #define HAVE_LOCALE_H 1 258*2b15cb3dSCy Schubert #endif /* HAVE_LOCALE_H */ 259*2b15cb3dSCy Schubert #ifndef HAVE_LOCALECONV 260*2b15cb3dSCy Schubert #define HAVE_LOCALECONV 1 261*2b15cb3dSCy Schubert #endif /* !defined(HAVE_LOCALECONV) */ 262*2b15cb3dSCy Schubert #ifndef HAVE_LCONV_DECIMAL_POINT 263*2b15cb3dSCy Schubert #define HAVE_LCONV_DECIMAL_POINT 1 264*2b15cb3dSCy Schubert #endif /* HAVE_LCONV_DECIMAL_POINT */ 265*2b15cb3dSCy Schubert #ifndef HAVE_LCONV_THOUSANDS_SEP 266*2b15cb3dSCy Schubert #define HAVE_LCONV_THOUSANDS_SEP 1 267*2b15cb3dSCy Schubert #endif /* HAVE_LCONV_THOUSANDS_SEP */ 268*2b15cb3dSCy Schubert #ifndef HAVE_LONG_DOUBLE 269*2b15cb3dSCy Schubert #define HAVE_LONG_DOUBLE 1 270*2b15cb3dSCy Schubert #endif /* !defined(HAVE_LONG_DOUBLE) */ 271*2b15cb3dSCy Schubert #ifndef HAVE_LONG_LONG_INT 272*2b15cb3dSCy Schubert #define HAVE_LONG_LONG_INT 1 273*2b15cb3dSCy Schubert #endif /* !defined(HAVE_LONG_LONG_INT) */ 274*2b15cb3dSCy Schubert #ifndef HAVE_UNSIGNED_LONG_LONG_INT 275*2b15cb3dSCy Schubert #define HAVE_UNSIGNED_LONG_LONG_INT 1 276*2b15cb3dSCy Schubert #endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */ 277*2b15cb3dSCy Schubert #ifndef HAVE_INTMAX_T 278*2b15cb3dSCy Schubert #define HAVE_INTMAX_T 1 279*2b15cb3dSCy Schubert #endif /* !defined(HAVE_INTMAX_T) */ 280*2b15cb3dSCy Schubert #ifndef HAVE_UINTMAX_T 281*2b15cb3dSCy Schubert #define HAVE_UINTMAX_T 1 282*2b15cb3dSCy Schubert #endif /* !defined(HAVE_UINTMAX_T) */ 283*2b15cb3dSCy Schubert #ifndef HAVE_UINTPTR_T 284*2b15cb3dSCy Schubert #define HAVE_UINTPTR_T 1 285*2b15cb3dSCy Schubert #endif /* !defined(HAVE_UINTPTR_T) */ 286*2b15cb3dSCy Schubert #ifndef HAVE_PTRDIFF_T 287*2b15cb3dSCy Schubert #define HAVE_PTRDIFF_T 1 288*2b15cb3dSCy Schubert #endif /* !defined(HAVE_PTRDIFF_T) */ 289*2b15cb3dSCy Schubert #ifndef HAVE_VA_COPY 290*2b15cb3dSCy Schubert #define HAVE_VA_COPY 1 291*2b15cb3dSCy Schubert #endif /* !defined(HAVE_VA_COPY) */ 292*2b15cb3dSCy Schubert #ifndef HAVE___VA_COPY 293*2b15cb3dSCy Schubert #define HAVE___VA_COPY 1 294*2b15cb3dSCy Schubert #endif /* !defined(HAVE___VA_COPY) */ 295*2b15cb3dSCy Schubert #endif /* HAVE_CONFIG_H */ 296*2b15cb3dSCy Schubert #define snprintf rpl_snprintf 297*2b15cb3dSCy Schubert #define vsnprintf rpl_vsnprintf 298*2b15cb3dSCy Schubert #define asprintf rpl_asprintf 299*2b15cb3dSCy Schubert #define vasprintf rpl_vasprintf 300*2b15cb3dSCy Schubert #endif /* TEST_SNPRINTF */ 301224ba2bdSOllivier Robert 302*2b15cb3dSCy Schubert #if HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || HW_WANT_RPL_VASPRINTF 303*2b15cb3dSCy Schubert #include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ 304*2b15cb3dSCy Schubert #ifdef VA_START 305*2b15cb3dSCy Schubert #undef VA_START 306*2b15cb3dSCy Schubert #endif /* defined(VA_START) */ 307*2b15cb3dSCy Schubert #ifdef VA_SHIFT 308*2b15cb3dSCy Schubert #undef VA_SHIFT 309*2b15cb3dSCy Schubert #endif /* defined(VA_SHIFT) */ 310*2b15cb3dSCy Schubert #if HAVE_STDARG_H 311224ba2bdSOllivier Robert #include <stdarg.h> 312*2b15cb3dSCy Schubert #define VA_START(ap, last) va_start(ap, last) 313*2b15cb3dSCy Schubert #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ 314*2b15cb3dSCy Schubert #else /* Assume <varargs.h> is available. */ 315224ba2bdSOllivier Robert #include <varargs.h> 316*2b15cb3dSCy Schubert #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ 317*2b15cb3dSCy Schubert #define VA_SHIFT(ap, value, type) value = va_arg(ap, type) 318*2b15cb3dSCy Schubert #endif /* HAVE_STDARG_H */ 319224ba2bdSOllivier Robert 320*2b15cb3dSCy Schubert #if HW_WANT_RPL_VASPRINTF 321*2b15cb3dSCy Schubert #if HAVE_STDLIB_H 322*2b15cb3dSCy Schubert #include <stdlib.h> /* For malloc(3). */ 323*2b15cb3dSCy Schubert #endif /* HAVE_STDLIB_H */ 324*2b15cb3dSCy Schubert #ifdef VA_COPY 325*2b15cb3dSCy Schubert #undef VA_COPY 326*2b15cb3dSCy Schubert #endif /* defined(VA_COPY) */ 327*2b15cb3dSCy Schubert #ifdef VA_END_COPY 328*2b15cb3dSCy Schubert #undef VA_END_COPY 329*2b15cb3dSCy Schubert #endif /* defined(VA_END_COPY) */ 330*2b15cb3dSCy Schubert #if HAVE_VA_COPY 331*2b15cb3dSCy Schubert #define VA_COPY(dest, src) va_copy(dest, src) 332*2b15cb3dSCy Schubert #define VA_END_COPY(ap) va_end(ap) 333*2b15cb3dSCy Schubert #elif HAVE___VA_COPY 334*2b15cb3dSCy Schubert #define VA_COPY(dest, src) __va_copy(dest, src) 335*2b15cb3dSCy Schubert #define VA_END_COPY(ap) va_end(ap) 336*2b15cb3dSCy Schubert #else 337*2b15cb3dSCy Schubert #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) 338*2b15cb3dSCy Schubert #define VA_END_COPY(ap) /* No-op. */ 339*2b15cb3dSCy Schubert #define NEED_MYMEMCPY 1 340*2b15cb3dSCy Schubert static void *mymemcpy(void *, void *, size_t); 341*2b15cb3dSCy Schubert #endif /* HAVE_VA_COPY */ 342*2b15cb3dSCy Schubert #endif /* HW_WANT_RPL_VASPRINTF */ 3439c2daa00SOllivier Robert 344*2b15cb3dSCy Schubert #if HW_WANT_RPL_VSNPRINTF 345*2b15cb3dSCy Schubert #include <errno.h> /* For ERANGE and errno. */ 346*2b15cb3dSCy Schubert #include <limits.h> /* For *_MAX. */ 347*2b15cb3dSCy Schubert #if HAVE_INTTYPES_H 348*2b15cb3dSCy Schubert #include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */ 349*2b15cb3dSCy Schubert #endif /* HAVE_INTTYPES_H */ 350*2b15cb3dSCy Schubert #if HAVE_LOCALE_H 351*2b15cb3dSCy Schubert #include <locale.h> /* For localeconv(3). */ 352*2b15cb3dSCy Schubert #endif /* HAVE_LOCALE_H */ 353*2b15cb3dSCy Schubert #if HAVE_STDDEF_H 354*2b15cb3dSCy Schubert #include <stddef.h> /* For ptrdiff_t. */ 355*2b15cb3dSCy Schubert #endif /* HAVE_STDDEF_H */ 356*2b15cb3dSCy Schubert #if HAVE_STDINT_H 357*2b15cb3dSCy Schubert #include <stdint.h> /* For intmax_t. */ 358*2b15cb3dSCy Schubert #endif /* HAVE_STDINT_H */ 359*2b15cb3dSCy Schubert 360*2b15cb3dSCy Schubert /* Support for unsigned long long int. We may also need ULLONG_MAX. */ 361*2b15cb3dSCy Schubert #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ 362*2b15cb3dSCy Schubert #ifdef UINT_MAX 363*2b15cb3dSCy Schubert #define ULONG_MAX UINT_MAX 364224ba2bdSOllivier Robert #else 365*2b15cb3dSCy Schubert #define ULONG_MAX INT_MAX 366*2b15cb3dSCy Schubert #endif /* defined(UINT_MAX) */ 367*2b15cb3dSCy Schubert #endif /* !defined(ULONG_MAX) */ 368*2b15cb3dSCy Schubert #ifdef ULLONG 369*2b15cb3dSCy Schubert #undef ULLONG 370*2b15cb3dSCy Schubert #endif /* defined(ULLONG) */ 371*2b15cb3dSCy Schubert #if HAVE_UNSIGNED_LONG_LONG_INT 372*2b15cb3dSCy Schubert #define ULLONG unsigned long long int 373*2b15cb3dSCy Schubert #ifndef ULLONG_MAX 374*2b15cb3dSCy Schubert #define ULLONG_MAX ULONG_MAX 375*2b15cb3dSCy Schubert #endif /* !defined(ULLONG_MAX) */ 376224ba2bdSOllivier Robert #else 377*2b15cb3dSCy Schubert #define ULLONG unsigned long int 378*2b15cb3dSCy Schubert #ifdef ULLONG_MAX 379*2b15cb3dSCy Schubert #undef ULLONG_MAX 380*2b15cb3dSCy Schubert #endif /* defined(ULLONG_MAX) */ 381*2b15cb3dSCy Schubert #define ULLONG_MAX ULONG_MAX 382*2b15cb3dSCy Schubert #endif /* HAVE_LONG_LONG_INT */ 383*2b15cb3dSCy Schubert 384*2b15cb3dSCy Schubert /* Support for uintmax_t. We also need UINTMAX_MAX. */ 385*2b15cb3dSCy Schubert #ifdef UINTMAX_T 386*2b15cb3dSCy Schubert #undef UINTMAX_T 387*2b15cb3dSCy Schubert #endif /* defined(UINTMAX_T) */ 388*2b15cb3dSCy Schubert #if HAVE_UINTMAX_T || defined(uintmax_t) 389*2b15cb3dSCy Schubert #define UINTMAX_T uintmax_t 390*2b15cb3dSCy Schubert #ifndef UINTMAX_MAX 391*2b15cb3dSCy Schubert #define UINTMAX_MAX ULLONG_MAX 392*2b15cb3dSCy Schubert #endif /* !defined(UINTMAX_MAX) */ 393224ba2bdSOllivier Robert #else 394*2b15cb3dSCy Schubert #define UINTMAX_T ULLONG 395*2b15cb3dSCy Schubert #ifdef UINTMAX_MAX 396*2b15cb3dSCy Schubert #undef UINTMAX_MAX 397*2b15cb3dSCy Schubert #endif /* defined(UINTMAX_MAX) */ 398*2b15cb3dSCy Schubert #define UINTMAX_MAX ULLONG_MAX 399*2b15cb3dSCy Schubert #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ 400*2b15cb3dSCy Schubert 401*2b15cb3dSCy Schubert /* Support for long double. */ 402*2b15cb3dSCy Schubert #ifndef LDOUBLE 403*2b15cb3dSCy Schubert #if HAVE_LONG_DOUBLE 404*2b15cb3dSCy Schubert #define LDOUBLE long double 405*2b15cb3dSCy Schubert #else 406*2b15cb3dSCy Schubert #define LDOUBLE double 407*2b15cb3dSCy Schubert #endif /* HAVE_LONG_DOUBLE */ 408*2b15cb3dSCy Schubert #endif /* !defined(LDOUBLE) */ 409*2b15cb3dSCy Schubert 410*2b15cb3dSCy Schubert /* Support for long long int. */ 411*2b15cb3dSCy Schubert #ifndef LLONG 412*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT 413*2b15cb3dSCy Schubert #define LLONG long long int 414*2b15cb3dSCy Schubert #else 415*2b15cb3dSCy Schubert #define LLONG long int 416*2b15cb3dSCy Schubert #endif /* HAVE_LONG_LONG_INT */ 417*2b15cb3dSCy Schubert #endif /* !defined(LLONG) */ 418*2b15cb3dSCy Schubert 419*2b15cb3dSCy Schubert /* Support for intmax_t. */ 420*2b15cb3dSCy Schubert #ifndef INTMAX_T 421*2b15cb3dSCy Schubert #if HAVE_INTMAX_T || defined(intmax_t) 422*2b15cb3dSCy Schubert #define INTMAX_T intmax_t 423*2b15cb3dSCy Schubert #else 424*2b15cb3dSCy Schubert #define INTMAX_T LLONG 425*2b15cb3dSCy Schubert #endif /* HAVE_INTMAX_T || defined(intmax_t) */ 426*2b15cb3dSCy Schubert #endif /* !defined(INTMAX_T) */ 427*2b15cb3dSCy Schubert 428*2b15cb3dSCy Schubert /* Support for uintptr_t. */ 429*2b15cb3dSCy Schubert #ifndef UINTPTR_T 430*2b15cb3dSCy Schubert #if HAVE_UINTPTR_T || defined(uintptr_t) 431*2b15cb3dSCy Schubert #define UINTPTR_T uintptr_t 432*2b15cb3dSCy Schubert #else 433*2b15cb3dSCy Schubert #define UINTPTR_T unsigned long int 434*2b15cb3dSCy Schubert #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ 435*2b15cb3dSCy Schubert #endif /* !defined(UINTPTR_T) */ 436*2b15cb3dSCy Schubert 437*2b15cb3dSCy Schubert /* Support for ptrdiff_t. */ 438*2b15cb3dSCy Schubert #ifndef PTRDIFF_T 439*2b15cb3dSCy Schubert #if HAVE_PTRDIFF_T || defined(ptrdiff_t) 440*2b15cb3dSCy Schubert #define PTRDIFF_T ptrdiff_t 441*2b15cb3dSCy Schubert #else 442*2b15cb3dSCy Schubert #define PTRDIFF_T long int 443*2b15cb3dSCy Schubert #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ 444*2b15cb3dSCy Schubert #endif /* !defined(PTRDIFF_T) */ 445*2b15cb3dSCy Schubert 446*2b15cb3dSCy Schubert /* 447*2b15cb3dSCy Schubert * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: 448*2b15cb3dSCy Schubert * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an 449*2b15cb3dSCy Schubert * unsigned type if necessary. This should work just fine in practice. 450*2b15cb3dSCy Schubert */ 451*2b15cb3dSCy Schubert #ifndef UPTRDIFF_T 452*2b15cb3dSCy Schubert #define UPTRDIFF_T PTRDIFF_T 453*2b15cb3dSCy Schubert #endif /* !defined(UPTRDIFF_T) */ 454*2b15cb3dSCy Schubert 455*2b15cb3dSCy Schubert /* 456*2b15cb3dSCy Schubert * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). 457*2b15cb3dSCy Schubert * However, we'll simply use size_t and convert it to a signed type if 458*2b15cb3dSCy Schubert * necessary. This should work just fine in practice. 459*2b15cb3dSCy Schubert */ 460*2b15cb3dSCy Schubert #ifndef SSIZE_T 461*2b15cb3dSCy Schubert #define SSIZE_T size_t 462*2b15cb3dSCy Schubert #endif /* !defined(SSIZE_T) */ 463*2b15cb3dSCy Schubert 464*2b15cb3dSCy Schubert /* Either ERANGE or E2BIG should be available everywhere. */ 465*2b15cb3dSCy Schubert #ifndef ERANGE 466*2b15cb3dSCy Schubert #define ERANGE E2BIG 467*2b15cb3dSCy Schubert #endif /* !defined(ERANGE) */ 468*2b15cb3dSCy Schubert #ifndef EOVERFLOW 469*2b15cb3dSCy Schubert #define EOVERFLOW ERANGE 470*2b15cb3dSCy Schubert #endif /* !defined(EOVERFLOW) */ 471*2b15cb3dSCy Schubert 472*2b15cb3dSCy Schubert /* 473*2b15cb3dSCy Schubert * Buffer size to hold the octal string representation of UINT128_MAX without 474*2b15cb3dSCy Schubert * nul-termination ("3777777777777777777777777777777777777777777"). 475*2b15cb3dSCy Schubert */ 476*2b15cb3dSCy Schubert #ifdef MAX_CONVERT_LENGTH 477*2b15cb3dSCy Schubert #undef MAX_CONVERT_LENGTH 478*2b15cb3dSCy Schubert #endif /* defined(MAX_CONVERT_LENGTH) */ 479*2b15cb3dSCy Schubert #define MAX_CONVERT_LENGTH 43 480*2b15cb3dSCy Schubert 481*2b15cb3dSCy Schubert /* Format read states. */ 482*2b15cb3dSCy Schubert #define PRINT_S_DEFAULT 0 483*2b15cb3dSCy Schubert #define PRINT_S_FLAGS 1 484*2b15cb3dSCy Schubert #define PRINT_S_WIDTH 2 485*2b15cb3dSCy Schubert #define PRINT_S_DOT 3 486*2b15cb3dSCy Schubert #define PRINT_S_PRECISION 4 487*2b15cb3dSCy Schubert #define PRINT_S_MOD 5 488*2b15cb3dSCy Schubert #define PRINT_S_CONV 6 489*2b15cb3dSCy Schubert 490*2b15cb3dSCy Schubert /* Format flags. */ 491*2b15cb3dSCy Schubert #define PRINT_F_MINUS (1 << 0) 492*2b15cb3dSCy Schubert #define PRINT_F_PLUS (1 << 1) 493*2b15cb3dSCy Schubert #define PRINT_F_SPACE (1 << 2) 494*2b15cb3dSCy Schubert #define PRINT_F_NUM (1 << 3) 495*2b15cb3dSCy Schubert #define PRINT_F_ZERO (1 << 4) 496*2b15cb3dSCy Schubert #define PRINT_F_QUOTE (1 << 5) 497*2b15cb3dSCy Schubert #define PRINT_F_UP (1 << 6) 498*2b15cb3dSCy Schubert #define PRINT_F_UNSIGNED (1 << 7) 499*2b15cb3dSCy Schubert #define PRINT_F_TYPE_G (1 << 8) 500*2b15cb3dSCy Schubert #define PRINT_F_TYPE_E (1 << 9) 501*2b15cb3dSCy Schubert 502*2b15cb3dSCy Schubert /* Conversion flags. */ 503*2b15cb3dSCy Schubert #define PRINT_C_CHAR 1 504*2b15cb3dSCy Schubert #define PRINT_C_SHORT 2 505*2b15cb3dSCy Schubert #define PRINT_C_LONG 3 506*2b15cb3dSCy Schubert #define PRINT_C_LLONG 4 507*2b15cb3dSCy Schubert #define PRINT_C_LDOUBLE 5 508*2b15cb3dSCy Schubert #define PRINT_C_SIZE 6 509*2b15cb3dSCy Schubert #define PRINT_C_PTRDIFF 7 510*2b15cb3dSCy Schubert #define PRINT_C_INTMAX 8 511*2b15cb3dSCy Schubert 512*2b15cb3dSCy Schubert #ifndef MAX 513*2b15cb3dSCy Schubert #define MAX(x, y) ((x >= y) ? x : y) 514*2b15cb3dSCy Schubert #endif /* !defined(MAX) */ 515*2b15cb3dSCy Schubert #ifndef CHARTOINT 516*2b15cb3dSCy Schubert #define CHARTOINT(ch) (ch - '0') 517*2b15cb3dSCy Schubert #endif /* !defined(CHARTOINT) */ 518*2b15cb3dSCy Schubert #ifndef ISDIGIT 519*2b15cb3dSCy Schubert #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') 520*2b15cb3dSCy Schubert #endif /* !defined(ISDIGIT) */ 521*2b15cb3dSCy Schubert #ifndef ISNAN 522*2b15cb3dSCy Schubert #define ISNAN(x) (x != x) 523*2b15cb3dSCy Schubert #endif /* !defined(ISNAN) */ 524*2b15cb3dSCy Schubert #ifndef ISINF 525*2b15cb3dSCy Schubert #define ISINF(x) (x != 0.0 && x + x == x) 526*2b15cb3dSCy Schubert #endif /* !defined(ISINF) */ 527*2b15cb3dSCy Schubert 528*2b15cb3dSCy Schubert #ifdef OUTCHAR 529*2b15cb3dSCy Schubert #undef OUTCHAR 530*2b15cb3dSCy Schubert #endif /* defined(OUTCHAR) */ 531*2b15cb3dSCy Schubert #define OUTCHAR(str, len, size, ch) \ 532*2b15cb3dSCy Schubert do { \ 533*2b15cb3dSCy Schubert if (len + 1 < size) \ 534*2b15cb3dSCy Schubert str[len] = ch; \ 535*2b15cb3dSCy Schubert (len)++; \ 536*2b15cb3dSCy Schubert } while (/* CONSTCOND */ 0) 537*2b15cb3dSCy Schubert 538*2b15cb3dSCy Schubert static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); 539*2b15cb3dSCy Schubert static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); 540*2b15cb3dSCy Schubert static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); 541*2b15cb3dSCy Schubert static void printsep(char *, size_t *, size_t); 542*2b15cb3dSCy Schubert static int getnumsep(int); 543*2b15cb3dSCy Schubert static int getexponent(LDOUBLE); 544*2b15cb3dSCy Schubert static int convert(UINTMAX_T, char *, size_t, int, int); 545*2b15cb3dSCy Schubert static UINTMAX_T cast(LDOUBLE); 546*2b15cb3dSCy Schubert static UINTMAX_T myround(LDOUBLE); 547*2b15cb3dSCy Schubert static LDOUBLE mypow10(int); 548224ba2bdSOllivier Robert 549224ba2bdSOllivier Robert int 550*2b15cb3dSCy Schubert rpl_vsnprintf(char *str, size_t size, const char *format, va_list args); 551*2b15cb3dSCy Schubert 552*2b15cb3dSCy Schubert int 553*2b15cb3dSCy Schubert rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) 554224ba2bdSOllivier Robert { 555*2b15cb3dSCy Schubert LDOUBLE fvalue; 556*2b15cb3dSCy Schubert INTMAX_T value; 557*2b15cb3dSCy Schubert unsigned char cvalue; 558*2b15cb3dSCy Schubert const char *strvalue; 559*2b15cb3dSCy Schubert INTMAX_T *intmaxptr; 560*2b15cb3dSCy Schubert PTRDIFF_T *ptrdiffptr; 561*2b15cb3dSCy Schubert SSIZE_T *sizeptr; 562*2b15cb3dSCy Schubert LLONG *llongptr; 563*2b15cb3dSCy Schubert long int *longptr; 564*2b15cb3dSCy Schubert int *intptr; 565*2b15cb3dSCy Schubert short int *shortptr; 566*2b15cb3dSCy Schubert signed char *charptr; 567*2b15cb3dSCy Schubert size_t len = 0; 568*2b15cb3dSCy Schubert int overflow = 0; 569*2b15cb3dSCy Schubert int base = 0; 570*2b15cb3dSCy Schubert int cflags = 0; 571*2b15cb3dSCy Schubert int flags = 0; 572*2b15cb3dSCy Schubert int width = 0; 573*2b15cb3dSCy Schubert int precision = -1; 574*2b15cb3dSCy Schubert int state = PRINT_S_DEFAULT; 575*2b15cb3dSCy Schubert char ch = *format++; 576*2b15cb3dSCy Schubert 577*2b15cb3dSCy Schubert /* 578*2b15cb3dSCy Schubert * C99 says: "If `n' is zero, nothing is written, and `s' may be a null 579*2b15cb3dSCy Schubert * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer 580*2b15cb3dSCy Schubert * even if a size larger than zero was specified. At least NetBSD's 581*2b15cb3dSCy Schubert * snprintf(3) does the same, as well as other versions of this file. 582*2b15cb3dSCy Schubert * (Though some of these versions will write to a non-NULL buffer even 583*2b15cb3dSCy Schubert * if a size of zero was specified, which violates the standard.) 584*2b15cb3dSCy Schubert */ 585*2b15cb3dSCy Schubert if (str == NULL && size != 0) 586*2b15cb3dSCy Schubert size = 0; 587*2b15cb3dSCy Schubert 588*2b15cb3dSCy Schubert while (ch != '\0') 589*2b15cb3dSCy Schubert switch (state) { 590*2b15cb3dSCy Schubert case PRINT_S_DEFAULT: 591*2b15cb3dSCy Schubert if (ch == '%') 592*2b15cb3dSCy Schubert state = PRINT_S_FLAGS; 593*2b15cb3dSCy Schubert else 594*2b15cb3dSCy Schubert OUTCHAR(str, len, size, ch); 595*2b15cb3dSCy Schubert ch = *format++; 596*2b15cb3dSCy Schubert break; 597*2b15cb3dSCy Schubert case PRINT_S_FLAGS: 598*2b15cb3dSCy Schubert switch (ch) { 599*2b15cb3dSCy Schubert case '-': 600*2b15cb3dSCy Schubert flags |= PRINT_F_MINUS; 601*2b15cb3dSCy Schubert ch = *format++; 602*2b15cb3dSCy Schubert break; 603*2b15cb3dSCy Schubert case '+': 604*2b15cb3dSCy Schubert flags |= PRINT_F_PLUS; 605*2b15cb3dSCy Schubert ch = *format++; 606*2b15cb3dSCy Schubert break; 607*2b15cb3dSCy Schubert case ' ': 608*2b15cb3dSCy Schubert flags |= PRINT_F_SPACE; 609*2b15cb3dSCy Schubert ch = *format++; 610*2b15cb3dSCy Schubert break; 611*2b15cb3dSCy Schubert case '#': 612*2b15cb3dSCy Schubert flags |= PRINT_F_NUM; 613*2b15cb3dSCy Schubert ch = *format++; 614*2b15cb3dSCy Schubert break; 615*2b15cb3dSCy Schubert case '0': 616*2b15cb3dSCy Schubert flags |= PRINT_F_ZERO; 617*2b15cb3dSCy Schubert ch = *format++; 618*2b15cb3dSCy Schubert break; 619*2b15cb3dSCy Schubert case '\'': /* SUSv2 flag (not in C99). */ 620*2b15cb3dSCy Schubert flags |= PRINT_F_QUOTE; 621*2b15cb3dSCy Schubert ch = *format++; 622*2b15cb3dSCy Schubert break; 623*2b15cb3dSCy Schubert default: 624*2b15cb3dSCy Schubert state = PRINT_S_WIDTH; 625*2b15cb3dSCy Schubert break; 626224ba2bdSOllivier Robert } 627*2b15cb3dSCy Schubert break; 628*2b15cb3dSCy Schubert case PRINT_S_WIDTH: 629*2b15cb3dSCy Schubert if (ISDIGIT(ch)) { 630*2b15cb3dSCy Schubert ch = CHARTOINT(ch); 631*2b15cb3dSCy Schubert if (width > (INT_MAX - ch) / 10) { 632*2b15cb3dSCy Schubert overflow = 1; 633*2b15cb3dSCy Schubert goto out; 634*2b15cb3dSCy Schubert } 635*2b15cb3dSCy Schubert width = 10 * width + ch; 636*2b15cb3dSCy Schubert ch = *format++; 637*2b15cb3dSCy Schubert } else if (ch == '*') { 638*2b15cb3dSCy Schubert /* 639*2b15cb3dSCy Schubert * C99 says: "A negative field width argument is 640*2b15cb3dSCy Schubert * taken as a `-' flag followed by a positive 641*2b15cb3dSCy Schubert * field width." (7.19.6.1, 5) 642*2b15cb3dSCy Schubert */ 643*2b15cb3dSCy Schubert if ((width = va_arg(args, int)) < 0) { 644*2b15cb3dSCy Schubert flags |= PRINT_F_MINUS; 645*2b15cb3dSCy Schubert width = -width; 646*2b15cb3dSCy Schubert } 647*2b15cb3dSCy Schubert ch = *format++; 648*2b15cb3dSCy Schubert state = PRINT_S_DOT; 649*2b15cb3dSCy Schubert } else 650*2b15cb3dSCy Schubert state = PRINT_S_DOT; 651*2b15cb3dSCy Schubert break; 652*2b15cb3dSCy Schubert case PRINT_S_DOT: 653*2b15cb3dSCy Schubert if (ch == '.') { 654*2b15cb3dSCy Schubert state = PRINT_S_PRECISION; 655*2b15cb3dSCy Schubert ch = *format++; 656*2b15cb3dSCy Schubert } else 657*2b15cb3dSCy Schubert state = PRINT_S_MOD; 658*2b15cb3dSCy Schubert break; 659*2b15cb3dSCy Schubert case PRINT_S_PRECISION: 660*2b15cb3dSCy Schubert if (precision == -1) 661*2b15cb3dSCy Schubert precision = 0; 662*2b15cb3dSCy Schubert if (ISDIGIT(ch)) { 663*2b15cb3dSCy Schubert ch = CHARTOINT(ch); 664*2b15cb3dSCy Schubert if (precision > (INT_MAX - ch) / 10) { 665*2b15cb3dSCy Schubert overflow = 1; 666*2b15cb3dSCy Schubert goto out; 667*2b15cb3dSCy Schubert } 668*2b15cb3dSCy Schubert precision = 10 * precision + ch; 669*2b15cb3dSCy Schubert ch = *format++; 670*2b15cb3dSCy Schubert } else if (ch == '*') { 671*2b15cb3dSCy Schubert /* 672*2b15cb3dSCy Schubert * C99 says: "A negative precision argument is 673*2b15cb3dSCy Schubert * taken as if the precision were omitted." 674*2b15cb3dSCy Schubert * (7.19.6.1, 5) 675*2b15cb3dSCy Schubert */ 676*2b15cb3dSCy Schubert if ((precision = va_arg(args, int)) < 0) 677*2b15cb3dSCy Schubert precision = -1; 678*2b15cb3dSCy Schubert ch = *format++; 679*2b15cb3dSCy Schubert state = PRINT_S_MOD; 680*2b15cb3dSCy Schubert } else 681*2b15cb3dSCy Schubert state = PRINT_S_MOD; 682*2b15cb3dSCy Schubert break; 683*2b15cb3dSCy Schubert case PRINT_S_MOD: 684*2b15cb3dSCy Schubert switch (ch) { 685*2b15cb3dSCy Schubert case 'h': 686*2b15cb3dSCy Schubert ch = *format++; 687*2b15cb3dSCy Schubert if (ch == 'h') { /* It's a char. */ 688*2b15cb3dSCy Schubert ch = *format++; 689*2b15cb3dSCy Schubert cflags = PRINT_C_CHAR; 690*2b15cb3dSCy Schubert } else 691*2b15cb3dSCy Schubert cflags = PRINT_C_SHORT; 692*2b15cb3dSCy Schubert break; 693*2b15cb3dSCy Schubert case 'l': 694*2b15cb3dSCy Schubert ch = *format++; 695*2b15cb3dSCy Schubert if (ch == 'l') { /* It's a long long. */ 696*2b15cb3dSCy Schubert ch = *format++; 697*2b15cb3dSCy Schubert cflags = PRINT_C_LLONG; 698*2b15cb3dSCy Schubert } else 699*2b15cb3dSCy Schubert cflags = PRINT_C_LONG; 700*2b15cb3dSCy Schubert break; 701*2b15cb3dSCy Schubert case 'L': 702*2b15cb3dSCy Schubert cflags = PRINT_C_LDOUBLE; 703*2b15cb3dSCy Schubert ch = *format++; 704*2b15cb3dSCy Schubert break; 705*2b15cb3dSCy Schubert case 'j': 706*2b15cb3dSCy Schubert cflags = PRINT_C_INTMAX; 707*2b15cb3dSCy Schubert ch = *format++; 708*2b15cb3dSCy Schubert break; 709*2b15cb3dSCy Schubert case 't': 710*2b15cb3dSCy Schubert cflags = PRINT_C_PTRDIFF; 711*2b15cb3dSCy Schubert ch = *format++; 712*2b15cb3dSCy Schubert break; 713*2b15cb3dSCy Schubert case 'z': 714*2b15cb3dSCy Schubert cflags = PRINT_C_SIZE; 715*2b15cb3dSCy Schubert ch = *format++; 716*2b15cb3dSCy Schubert break; 717*2b15cb3dSCy Schubert } 718*2b15cb3dSCy Schubert state = PRINT_S_CONV; 719*2b15cb3dSCy Schubert break; 720*2b15cb3dSCy Schubert case PRINT_S_CONV: 721*2b15cb3dSCy Schubert switch (ch) { 722*2b15cb3dSCy Schubert case 'd': 723*2b15cb3dSCy Schubert /* FALLTHROUGH */ 724*2b15cb3dSCy Schubert case 'i': 725*2b15cb3dSCy Schubert switch (cflags) { 726*2b15cb3dSCy Schubert case PRINT_C_CHAR: 727*2b15cb3dSCy Schubert value = (signed char)va_arg(args, int); 728*2b15cb3dSCy Schubert break; 729*2b15cb3dSCy Schubert case PRINT_C_SHORT: 730*2b15cb3dSCy Schubert value = (short int)va_arg(args, int); 731*2b15cb3dSCy Schubert break; 732*2b15cb3dSCy Schubert case PRINT_C_LONG: 733*2b15cb3dSCy Schubert value = va_arg(args, long int); 734*2b15cb3dSCy Schubert break; 735*2b15cb3dSCy Schubert case PRINT_C_LLONG: 736*2b15cb3dSCy Schubert value = va_arg(args, LLONG); 737*2b15cb3dSCy Schubert break; 738*2b15cb3dSCy Schubert case PRINT_C_SIZE: 739*2b15cb3dSCy Schubert value = va_arg(args, SSIZE_T); 740*2b15cb3dSCy Schubert break; 741*2b15cb3dSCy Schubert case PRINT_C_INTMAX: 742*2b15cb3dSCy Schubert value = va_arg(args, INTMAX_T); 743*2b15cb3dSCy Schubert break; 744*2b15cb3dSCy Schubert case PRINT_C_PTRDIFF: 745*2b15cb3dSCy Schubert value = va_arg(args, PTRDIFF_T); 746*2b15cb3dSCy Schubert break; 747*2b15cb3dSCy Schubert default: 748*2b15cb3dSCy Schubert value = va_arg(args, int); 749*2b15cb3dSCy Schubert break; 750*2b15cb3dSCy Schubert } 751*2b15cb3dSCy Schubert fmtint(str, &len, size, value, 10, width, 752*2b15cb3dSCy Schubert precision, flags); 753*2b15cb3dSCy Schubert break; 754*2b15cb3dSCy Schubert case 'X': 755*2b15cb3dSCy Schubert flags |= PRINT_F_UP; 756*2b15cb3dSCy Schubert /* FALLTHROUGH */ 757*2b15cb3dSCy Schubert case 'x': 758*2b15cb3dSCy Schubert base = 16; 759*2b15cb3dSCy Schubert /* FALLTHROUGH */ 760*2b15cb3dSCy Schubert case 'o': 761*2b15cb3dSCy Schubert if (base == 0) 762*2b15cb3dSCy Schubert base = 8; 763*2b15cb3dSCy Schubert /* FALLTHROUGH */ 764*2b15cb3dSCy Schubert case 'u': 765*2b15cb3dSCy Schubert if (base == 0) 766*2b15cb3dSCy Schubert base = 10; 767*2b15cb3dSCy Schubert flags |= PRINT_F_UNSIGNED; 768*2b15cb3dSCy Schubert switch (cflags) { 769*2b15cb3dSCy Schubert case PRINT_C_CHAR: 770*2b15cb3dSCy Schubert value = (unsigned char)va_arg(args, 771*2b15cb3dSCy Schubert unsigned int); 772*2b15cb3dSCy Schubert break; 773*2b15cb3dSCy Schubert case PRINT_C_SHORT: 774*2b15cb3dSCy Schubert value = (unsigned short int)va_arg(args, 775*2b15cb3dSCy Schubert unsigned int); 776*2b15cb3dSCy Schubert break; 777*2b15cb3dSCy Schubert case PRINT_C_LONG: 778*2b15cb3dSCy Schubert value = va_arg(args, unsigned long int); 779*2b15cb3dSCy Schubert break; 780*2b15cb3dSCy Schubert case PRINT_C_LLONG: 781*2b15cb3dSCy Schubert value = va_arg(args, ULLONG); 782*2b15cb3dSCy Schubert break; 783*2b15cb3dSCy Schubert case PRINT_C_SIZE: 784*2b15cb3dSCy Schubert value = va_arg(args, size_t); 785*2b15cb3dSCy Schubert break; 786*2b15cb3dSCy Schubert case PRINT_C_INTMAX: 787*2b15cb3dSCy Schubert value = va_arg(args, UINTMAX_T); 788*2b15cb3dSCy Schubert break; 789*2b15cb3dSCy Schubert case PRINT_C_PTRDIFF: 790*2b15cb3dSCy Schubert value = va_arg(args, UPTRDIFF_T); 791*2b15cb3dSCy Schubert break; 792*2b15cb3dSCy Schubert default: 793*2b15cb3dSCy Schubert value = va_arg(args, unsigned int); 794*2b15cb3dSCy Schubert break; 795*2b15cb3dSCy Schubert } 796*2b15cb3dSCy Schubert fmtint(str, &len, size, value, base, width, 797*2b15cb3dSCy Schubert precision, flags); 798*2b15cb3dSCy Schubert break; 799*2b15cb3dSCy Schubert case 'A': 800*2b15cb3dSCy Schubert /* Not yet supported, we'll use "%F". */ 801*2b15cb3dSCy Schubert /* FALLTHROUGH */ 802*2b15cb3dSCy Schubert case 'F': 803*2b15cb3dSCy Schubert flags |= PRINT_F_UP; 804*2b15cb3dSCy Schubert /* FALLTHROUGH */ 805*2b15cb3dSCy Schubert case 'a': 806*2b15cb3dSCy Schubert /* Not yet supported, we'll use "%f". */ 807*2b15cb3dSCy Schubert /* FALLTHROUGH */ 808*2b15cb3dSCy Schubert case 'f': 809*2b15cb3dSCy Schubert if (cflags == PRINT_C_LDOUBLE) 810*2b15cb3dSCy Schubert fvalue = va_arg(args, LDOUBLE); 811*2b15cb3dSCy Schubert else 812*2b15cb3dSCy Schubert fvalue = va_arg(args, double); 813*2b15cb3dSCy Schubert fmtflt(str, &len, size, fvalue, width, 814*2b15cb3dSCy Schubert precision, flags, &overflow); 815*2b15cb3dSCy Schubert if (overflow) 816*2b15cb3dSCy Schubert goto out; 817*2b15cb3dSCy Schubert break; 818*2b15cb3dSCy Schubert case 'E': 819*2b15cb3dSCy Schubert flags |= PRINT_F_UP; 820*2b15cb3dSCy Schubert /* FALLTHROUGH */ 821*2b15cb3dSCy Schubert case 'e': 822*2b15cb3dSCy Schubert flags |= PRINT_F_TYPE_E; 823*2b15cb3dSCy Schubert if (cflags == PRINT_C_LDOUBLE) 824*2b15cb3dSCy Schubert fvalue = va_arg(args, LDOUBLE); 825*2b15cb3dSCy Schubert else 826*2b15cb3dSCy Schubert fvalue = va_arg(args, double); 827*2b15cb3dSCy Schubert fmtflt(str, &len, size, fvalue, width, 828*2b15cb3dSCy Schubert precision, flags, &overflow); 829*2b15cb3dSCy Schubert if (overflow) 830*2b15cb3dSCy Schubert goto out; 831*2b15cb3dSCy Schubert break; 832*2b15cb3dSCy Schubert case 'G': 833*2b15cb3dSCy Schubert flags |= PRINT_F_UP; 834*2b15cb3dSCy Schubert /* FALLTHROUGH */ 835*2b15cb3dSCy Schubert case 'g': 836*2b15cb3dSCy Schubert flags |= PRINT_F_TYPE_G; 837*2b15cb3dSCy Schubert if (cflags == PRINT_C_LDOUBLE) 838*2b15cb3dSCy Schubert fvalue = va_arg(args, LDOUBLE); 839*2b15cb3dSCy Schubert else 840*2b15cb3dSCy Schubert fvalue = va_arg(args, double); 841*2b15cb3dSCy Schubert /* 842*2b15cb3dSCy Schubert * If the precision is zero, it is treated as 843*2b15cb3dSCy Schubert * one (cf. C99: 7.19.6.1, 8). 844*2b15cb3dSCy Schubert */ 845*2b15cb3dSCy Schubert if (precision == 0) 846*2b15cb3dSCy Schubert precision = 1; 847*2b15cb3dSCy Schubert fmtflt(str, &len, size, fvalue, width, 848*2b15cb3dSCy Schubert precision, flags, &overflow); 849*2b15cb3dSCy Schubert if (overflow) 850*2b15cb3dSCy Schubert goto out; 851*2b15cb3dSCy Schubert break; 852*2b15cb3dSCy Schubert case 'c': 853*2b15cb3dSCy Schubert cvalue = va_arg(args, int); 854*2b15cb3dSCy Schubert OUTCHAR(str, len, size, cvalue); 855*2b15cb3dSCy Schubert break; 856*2b15cb3dSCy Schubert case 's': 857*2b15cb3dSCy Schubert strvalue = va_arg(args, char *); 858*2b15cb3dSCy Schubert fmtstr(str, &len, size, strvalue, width, 859*2b15cb3dSCy Schubert precision, flags); 860*2b15cb3dSCy Schubert break; 861*2b15cb3dSCy Schubert case 'p': 862*2b15cb3dSCy Schubert /* 863*2b15cb3dSCy Schubert * C99 says: "The value of the pointer is 864*2b15cb3dSCy Schubert * converted to a sequence of printing 865*2b15cb3dSCy Schubert * characters, in an implementation-defined 866*2b15cb3dSCy Schubert * manner." (C99: 7.19.6.1, 8) 867*2b15cb3dSCy Schubert */ 868*2b15cb3dSCy Schubert if ((strvalue = va_arg(args, void *)) == NULL) 869*2b15cb3dSCy Schubert /* 870*2b15cb3dSCy Schubert * We use the glibc format. BSD prints 871*2b15cb3dSCy Schubert * "0x0", SysV "0". 872*2b15cb3dSCy Schubert */ 873*2b15cb3dSCy Schubert fmtstr(str, &len, size, "(nil)", width, 874*2b15cb3dSCy Schubert -1, flags); 875*2b15cb3dSCy Schubert else { 876*2b15cb3dSCy Schubert /* 877*2b15cb3dSCy Schubert * We use the BSD/glibc format. SysV 878*2b15cb3dSCy Schubert * omits the "0x" prefix (which we emit 879*2b15cb3dSCy Schubert * using the PRINT_F_NUM flag). 880*2b15cb3dSCy Schubert */ 881*2b15cb3dSCy Schubert flags |= PRINT_F_NUM; 882*2b15cb3dSCy Schubert flags |= PRINT_F_UNSIGNED; 883*2b15cb3dSCy Schubert fmtint(str, &len, size, 884*2b15cb3dSCy Schubert (UINTPTR_T)strvalue, 16, width, 885*2b15cb3dSCy Schubert precision, flags); 886*2b15cb3dSCy Schubert } 887*2b15cb3dSCy Schubert break; 888*2b15cb3dSCy Schubert case 'n': 889*2b15cb3dSCy Schubert switch (cflags) { 890*2b15cb3dSCy Schubert case PRINT_C_CHAR: 891*2b15cb3dSCy Schubert charptr = va_arg(args, signed char *); 892*2b15cb3dSCy Schubert *charptr = len; 893*2b15cb3dSCy Schubert break; 894*2b15cb3dSCy Schubert case PRINT_C_SHORT: 895*2b15cb3dSCy Schubert shortptr = va_arg(args, short int *); 896*2b15cb3dSCy Schubert *shortptr = len; 897*2b15cb3dSCy Schubert break; 898*2b15cb3dSCy Schubert case PRINT_C_LONG: 899*2b15cb3dSCy Schubert longptr = va_arg(args, long int *); 900*2b15cb3dSCy Schubert *longptr = len; 901*2b15cb3dSCy Schubert break; 902*2b15cb3dSCy Schubert case PRINT_C_LLONG: 903*2b15cb3dSCy Schubert llongptr = va_arg(args, LLONG *); 904*2b15cb3dSCy Schubert *llongptr = len; 905*2b15cb3dSCy Schubert break; 906*2b15cb3dSCy Schubert case PRINT_C_SIZE: 907*2b15cb3dSCy Schubert /* 908*2b15cb3dSCy Schubert * C99 says that with the "z" length 909*2b15cb3dSCy Schubert * modifier, "a following `n' conversion 910*2b15cb3dSCy Schubert * specifier applies to a pointer to a 911*2b15cb3dSCy Schubert * signed integer type corresponding to 912*2b15cb3dSCy Schubert * size_t argument." (7.19.6.1, 7) 913*2b15cb3dSCy Schubert */ 914*2b15cb3dSCy Schubert sizeptr = va_arg(args, SSIZE_T *); 915*2b15cb3dSCy Schubert *sizeptr = len; 916*2b15cb3dSCy Schubert break; 917*2b15cb3dSCy Schubert case PRINT_C_INTMAX: 918*2b15cb3dSCy Schubert intmaxptr = va_arg(args, INTMAX_T *); 919*2b15cb3dSCy Schubert *intmaxptr = len; 920*2b15cb3dSCy Schubert break; 921*2b15cb3dSCy Schubert case PRINT_C_PTRDIFF: 922*2b15cb3dSCy Schubert ptrdiffptr = va_arg(args, PTRDIFF_T *); 923*2b15cb3dSCy Schubert *ptrdiffptr = len; 924*2b15cb3dSCy Schubert break; 925*2b15cb3dSCy Schubert default: 926*2b15cb3dSCy Schubert intptr = va_arg(args, int *); 927*2b15cb3dSCy Schubert *intptr = len; 928*2b15cb3dSCy Schubert break; 929*2b15cb3dSCy Schubert } 930*2b15cb3dSCy Schubert break; 931*2b15cb3dSCy Schubert case '%': /* Print a "%" character verbatim. */ 932*2b15cb3dSCy Schubert OUTCHAR(str, len, size, ch); 933*2b15cb3dSCy Schubert break; 934*2b15cb3dSCy Schubert default: /* Skip other characters. */ 935*2b15cb3dSCy Schubert break; 936*2b15cb3dSCy Schubert } 937*2b15cb3dSCy Schubert ch = *format++; 938*2b15cb3dSCy Schubert state = PRINT_S_DEFAULT; 939*2b15cb3dSCy Schubert base = cflags = flags = width = 0; 940*2b15cb3dSCy Schubert precision = -1; 941*2b15cb3dSCy Schubert break; 942*2b15cb3dSCy Schubert } 943*2b15cb3dSCy Schubert out: 944*2b15cb3dSCy Schubert if (len < size) 945*2b15cb3dSCy Schubert str[len] = '\0'; 946*2b15cb3dSCy Schubert else if (size > 0) 947*2b15cb3dSCy Schubert str[size - 1] = '\0'; 948*2b15cb3dSCy Schubert 949*2b15cb3dSCy Schubert if (overflow || len >= INT_MAX) { 950*2b15cb3dSCy Schubert errno = overflow ? EOVERFLOW : ERANGE; 951*2b15cb3dSCy Schubert return -1; 952*2b15cb3dSCy Schubert } 953*2b15cb3dSCy Schubert return (int)len; 954*2b15cb3dSCy Schubert } 955*2b15cb3dSCy Schubert 956*2b15cb3dSCy Schubert static void 957*2b15cb3dSCy Schubert fmtstr(char *str, size_t *len, size_t size, const char *value, int width, 958*2b15cb3dSCy Schubert int precision, int flags) 959*2b15cb3dSCy Schubert { 960*2b15cb3dSCy Schubert int padlen, strln; /* Amount to pad. */ 961*2b15cb3dSCy Schubert int noprecision = (precision == -1); 962*2b15cb3dSCy Schubert 963*2b15cb3dSCy Schubert if (value == NULL) /* We're forgiving. */ 964*2b15cb3dSCy Schubert value = "(null)"; 965*2b15cb3dSCy Schubert 966*2b15cb3dSCy Schubert /* If a precision was specified, don't read the string past it. */ 967*2b15cb3dSCy Schubert for (strln = 0; value[strln] != '\0' && 968*2b15cb3dSCy Schubert (noprecision || strln < precision); strln++) 969*2b15cb3dSCy Schubert continue; 970*2b15cb3dSCy Schubert 971*2b15cb3dSCy Schubert if ((padlen = width - strln) < 0) 972*2b15cb3dSCy Schubert padlen = 0; 973*2b15cb3dSCy Schubert if (flags & PRINT_F_MINUS) /* Left justify. */ 974*2b15cb3dSCy Schubert padlen = -padlen; 975*2b15cb3dSCy Schubert 976*2b15cb3dSCy Schubert while (padlen > 0) { /* Leading spaces. */ 977*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ' '); 978*2b15cb3dSCy Schubert padlen--; 979*2b15cb3dSCy Schubert } 980*2b15cb3dSCy Schubert while (*value != '\0' && (noprecision || precision-- > 0)) { 981*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, *value); 982*2b15cb3dSCy Schubert value++; 983*2b15cb3dSCy Schubert } 984*2b15cb3dSCy Schubert while (padlen < 0) { /* Trailing spaces. */ 985*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ' '); 986*2b15cb3dSCy Schubert padlen++; 987*2b15cb3dSCy Schubert } 988*2b15cb3dSCy Schubert } 989*2b15cb3dSCy Schubert 990*2b15cb3dSCy Schubert static void 991*2b15cb3dSCy Schubert fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, 992*2b15cb3dSCy Schubert int precision, int flags) 993*2b15cb3dSCy Schubert { 994*2b15cb3dSCy Schubert UINTMAX_T uvalue; 995*2b15cb3dSCy Schubert char iconvert[MAX_CONVERT_LENGTH]; 996*2b15cb3dSCy Schubert char sign = 0; 997*2b15cb3dSCy Schubert char hexprefix = 0; 998*2b15cb3dSCy Schubert int spadlen = 0; /* Amount to space pad. */ 999*2b15cb3dSCy Schubert int zpadlen = 0; /* Amount to zero pad. */ 1000*2b15cb3dSCy Schubert int pos; 1001*2b15cb3dSCy Schubert int separators = (flags & PRINT_F_QUOTE); 1002*2b15cb3dSCy Schubert int noprecision = (precision == -1); 1003*2b15cb3dSCy Schubert 1004*2b15cb3dSCy Schubert if (flags & PRINT_F_UNSIGNED) 1005*2b15cb3dSCy Schubert uvalue = value; 1006*2b15cb3dSCy Schubert else { 1007*2b15cb3dSCy Schubert uvalue = (value >= 0) ? value : -value; 1008*2b15cb3dSCy Schubert if (value < 0) 1009*2b15cb3dSCy Schubert sign = '-'; 1010*2b15cb3dSCy Schubert else if (flags & PRINT_F_PLUS) /* Do a sign. */ 1011*2b15cb3dSCy Schubert sign = '+'; 1012*2b15cb3dSCy Schubert else if (flags & PRINT_F_SPACE) 1013*2b15cb3dSCy Schubert sign = ' '; 1014*2b15cb3dSCy Schubert } 1015*2b15cb3dSCy Schubert 1016*2b15cb3dSCy Schubert pos = convert(uvalue, iconvert, sizeof(iconvert), base, 1017*2b15cb3dSCy Schubert flags & PRINT_F_UP); 1018*2b15cb3dSCy Schubert 1019*2b15cb3dSCy Schubert if (flags & PRINT_F_NUM && uvalue != 0) { 1020*2b15cb3dSCy Schubert /* 1021*2b15cb3dSCy Schubert * C99 says: "The result is converted to an `alternative form'. 1022*2b15cb3dSCy Schubert * For `o' conversion, it increases the precision, if and only 1023*2b15cb3dSCy Schubert * if necessary, to force the first digit of the result to be a 1024*2b15cb3dSCy Schubert * zero (if the value and precision are both 0, a single 0 is 1025*2b15cb3dSCy Schubert * printed). For `x' (or `X') conversion, a nonzero result has 1026*2b15cb3dSCy Schubert * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) 1027*2b15cb3dSCy Schubert */ 1028*2b15cb3dSCy Schubert switch (base) { 1029*2b15cb3dSCy Schubert case 8: 1030*2b15cb3dSCy Schubert if (precision <= pos) 1031*2b15cb3dSCy Schubert precision = pos + 1; 1032*2b15cb3dSCy Schubert break; 1033*2b15cb3dSCy Schubert case 16: 1034*2b15cb3dSCy Schubert hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; 1035*2b15cb3dSCy Schubert break; 1036*2b15cb3dSCy Schubert } 1037*2b15cb3dSCy Schubert } 1038*2b15cb3dSCy Schubert 1039*2b15cb3dSCy Schubert if (separators) /* Get the number of group separators we'll print. */ 1040*2b15cb3dSCy Schubert separators = getnumsep(pos); 1041*2b15cb3dSCy Schubert 1042*2b15cb3dSCy Schubert zpadlen = precision - pos - separators; 1043*2b15cb3dSCy Schubert spadlen = width /* Minimum field width. */ 1044*2b15cb3dSCy Schubert - separators /* Number of separators. */ 1045*2b15cb3dSCy Schubert - MAX(precision, pos) /* Number of integer digits. */ 1046*2b15cb3dSCy Schubert - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ 1047*2b15cb3dSCy Schubert - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ 1048*2b15cb3dSCy Schubert 1049*2b15cb3dSCy Schubert if (zpadlen < 0) 1050*2b15cb3dSCy Schubert zpadlen = 0; 1051*2b15cb3dSCy Schubert if (spadlen < 0) 1052*2b15cb3dSCy Schubert spadlen = 0; 1053*2b15cb3dSCy Schubert 1054*2b15cb3dSCy Schubert /* 1055*2b15cb3dSCy Schubert * C99 says: "If the `0' and `-' flags both appear, the `0' flag is 1056*2b15cb3dSCy Schubert * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a 1057*2b15cb3dSCy Schubert * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) 1058*2b15cb3dSCy Schubert */ 1059*2b15cb3dSCy Schubert if (flags & PRINT_F_MINUS) /* Left justify. */ 1060*2b15cb3dSCy Schubert spadlen = -spadlen; 1061*2b15cb3dSCy Schubert else if (flags & PRINT_F_ZERO && noprecision) { 1062*2b15cb3dSCy Schubert zpadlen += spadlen; 1063*2b15cb3dSCy Schubert spadlen = 0; 1064*2b15cb3dSCy Schubert } 1065*2b15cb3dSCy Schubert while (spadlen > 0) { /* Leading spaces. */ 1066*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ' '); 1067*2b15cb3dSCy Schubert spadlen--; 1068*2b15cb3dSCy Schubert } 1069*2b15cb3dSCy Schubert if (sign != 0) /* Sign. */ 1070*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, sign); 1071*2b15cb3dSCy Schubert if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ 1072*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, '0'); 1073*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, hexprefix); 1074*2b15cb3dSCy Schubert } 1075*2b15cb3dSCy Schubert while (zpadlen > 0) { /* Leading zeros. */ 1076*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, '0'); 1077*2b15cb3dSCy Schubert zpadlen--; 1078*2b15cb3dSCy Schubert } 1079*2b15cb3dSCy Schubert while (pos > 0) { /* The actual digits. */ 1080*2b15cb3dSCy Schubert pos--; 1081*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, iconvert[pos]); 1082*2b15cb3dSCy Schubert if (separators > 0 && pos > 0 && pos % 3 == 0) 1083*2b15cb3dSCy Schubert printsep(str, len, size); 1084*2b15cb3dSCy Schubert } 1085*2b15cb3dSCy Schubert while (spadlen < 0) { /* Trailing spaces. */ 1086*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ' '); 1087*2b15cb3dSCy Schubert spadlen++; 1088*2b15cb3dSCy Schubert } 1089*2b15cb3dSCy Schubert } 1090*2b15cb3dSCy Schubert 1091*2b15cb3dSCy Schubert static void 1092*2b15cb3dSCy Schubert fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, 1093*2b15cb3dSCy Schubert int precision, int flags, int *overflow) 1094*2b15cb3dSCy Schubert { 1095*2b15cb3dSCy Schubert LDOUBLE ufvalue; 1096*2b15cb3dSCy Schubert UINTMAX_T intpart; 1097*2b15cb3dSCy Schubert UINTMAX_T fracpart; 1098*2b15cb3dSCy Schubert UINTMAX_T mask; 1099*2b15cb3dSCy Schubert const char *infnan = NULL; 1100*2b15cb3dSCy Schubert char iconvert[MAX_CONVERT_LENGTH]; 1101*2b15cb3dSCy Schubert char fconvert[MAX_CONVERT_LENGTH]; 1102*2b15cb3dSCy Schubert char econvert[4]; /* "e-12" (without nul-termination). */ 1103*2b15cb3dSCy Schubert char esign = 0; 1104*2b15cb3dSCy Schubert char sign = 0; 1105*2b15cb3dSCy Schubert int leadfraczeros = 0; 1106*2b15cb3dSCy Schubert int exponent = 0; 1107*2b15cb3dSCy Schubert int emitpoint = 0; 1108*2b15cb3dSCy Schubert int omitzeros = 0; 1109*2b15cb3dSCy Schubert int omitcount = 0; 1110*2b15cb3dSCy Schubert int padlen = 0; 1111*2b15cb3dSCy Schubert int epos = 0; 1112*2b15cb3dSCy Schubert int fpos = 0; 1113*2b15cb3dSCy Schubert int ipos = 0; 1114*2b15cb3dSCy Schubert int separators = (flags & PRINT_F_QUOTE); 1115*2b15cb3dSCy Schubert int estyle = (flags & PRINT_F_TYPE_E); 1116*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT 1117*2b15cb3dSCy Schubert struct lconv *lc = localeconv(); 1118*2b15cb3dSCy Schubert #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ 1119*2b15cb3dSCy Schubert 1120*2b15cb3dSCy Schubert /* 1121*2b15cb3dSCy Schubert * AIX' man page says the default is 0, but C99 and at least Solaris' 1122*2b15cb3dSCy Schubert * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX 1123*2b15cb3dSCy Schubert * defaults to 6. 1124*2b15cb3dSCy Schubert */ 1125*2b15cb3dSCy Schubert if (precision == -1) 1126*2b15cb3dSCy Schubert precision = 6; 1127*2b15cb3dSCy Schubert 1128*2b15cb3dSCy Schubert if (fvalue < 0.0) 1129*2b15cb3dSCy Schubert sign = '-'; 1130*2b15cb3dSCy Schubert else if (flags & PRINT_F_PLUS) /* Do a sign. */ 1131*2b15cb3dSCy Schubert sign = '+'; 1132*2b15cb3dSCy Schubert else if (flags & PRINT_F_SPACE) 1133*2b15cb3dSCy Schubert sign = ' '; 1134*2b15cb3dSCy Schubert 1135*2b15cb3dSCy Schubert if (ISNAN(fvalue)) 1136*2b15cb3dSCy Schubert infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; 1137*2b15cb3dSCy Schubert else if (ISINF(fvalue)) 1138*2b15cb3dSCy Schubert infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; 1139*2b15cb3dSCy Schubert 1140*2b15cb3dSCy Schubert if (infnan != NULL) { 1141*2b15cb3dSCy Schubert if (sign != 0) 1142*2b15cb3dSCy Schubert iconvert[ipos++] = sign; 1143*2b15cb3dSCy Schubert while (*infnan != '\0') 1144*2b15cb3dSCy Schubert iconvert[ipos++] = *infnan++; 1145*2b15cb3dSCy Schubert fmtstr(str, len, size, iconvert, width, ipos, flags); 1146*2b15cb3dSCy Schubert return; 1147*2b15cb3dSCy Schubert } 1148*2b15cb3dSCy Schubert 1149*2b15cb3dSCy Schubert /* "%e" (or "%E") or "%g" (or "%G") conversion. */ 1150*2b15cb3dSCy Schubert if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { 1151*2b15cb3dSCy Schubert if (flags & PRINT_F_TYPE_G) { 1152*2b15cb3dSCy Schubert /* 1153*2b15cb3dSCy Schubert * For "%g" (and "%G") conversions, the precision 1154*2b15cb3dSCy Schubert * specifies the number of significant digits, which 1155*2b15cb3dSCy Schubert * includes the digits in the integer part. The 1156*2b15cb3dSCy Schubert * conversion will or will not be using "e-style" (like 1157*2b15cb3dSCy Schubert * "%e" or "%E" conversions) depending on the precision 1158*2b15cb3dSCy Schubert * and on the exponent. However, the exponent can be 1159*2b15cb3dSCy Schubert * affected by rounding the converted value, so we'll 1160*2b15cb3dSCy Schubert * leave this decision for later. Until then, we'll 1161*2b15cb3dSCy Schubert * assume that we're going to do an "e-style" conversion 1162*2b15cb3dSCy Schubert * (in order to get the exponent calculated). For 1163*2b15cb3dSCy Schubert * "e-style", the precision must be decremented by one. 1164*2b15cb3dSCy Schubert */ 1165*2b15cb3dSCy Schubert precision--; 1166*2b15cb3dSCy Schubert /* 1167*2b15cb3dSCy Schubert * For "%g" (and "%G") conversions, trailing zeros are 1168*2b15cb3dSCy Schubert * removed from the fractional portion of the result 1169*2b15cb3dSCy Schubert * unless the "#" flag was specified. 1170*2b15cb3dSCy Schubert */ 1171*2b15cb3dSCy Schubert if (!(flags & PRINT_F_NUM)) 1172*2b15cb3dSCy Schubert omitzeros = 1; 1173*2b15cb3dSCy Schubert } 1174*2b15cb3dSCy Schubert exponent = getexponent(fvalue); 1175*2b15cb3dSCy Schubert estyle = 1; 1176*2b15cb3dSCy Schubert } 1177*2b15cb3dSCy Schubert 1178*2b15cb3dSCy Schubert again: 1179*2b15cb3dSCy Schubert /* 1180*2b15cb3dSCy Schubert * Sorry, we only support 9, 19, or 38 digits (that is, the number of 1181*2b15cb3dSCy Schubert * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value 1182*2b15cb3dSCy Schubert * minus one) past the decimal point due to our conversion method. 1183*2b15cb3dSCy Schubert */ 1184*2b15cb3dSCy Schubert switch (sizeof(UINTMAX_T)) { 1185*2b15cb3dSCy Schubert case 16: 1186*2b15cb3dSCy Schubert if (precision > 38) 1187*2b15cb3dSCy Schubert precision = 38; 1188*2b15cb3dSCy Schubert break; 1189*2b15cb3dSCy Schubert case 8: 1190*2b15cb3dSCy Schubert if (precision > 19) 1191*2b15cb3dSCy Schubert precision = 19; 1192*2b15cb3dSCy Schubert break; 1193*2b15cb3dSCy Schubert default: 1194*2b15cb3dSCy Schubert if (precision > 9) 1195*2b15cb3dSCy Schubert precision = 9; 1196*2b15cb3dSCy Schubert break; 1197*2b15cb3dSCy Schubert } 1198*2b15cb3dSCy Schubert 1199*2b15cb3dSCy Schubert ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; 1200*2b15cb3dSCy Schubert if (estyle) /* We want exactly one integer digit. */ 1201*2b15cb3dSCy Schubert ufvalue /= mypow10(exponent); 1202*2b15cb3dSCy Schubert 1203*2b15cb3dSCy Schubert if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { 1204*2b15cb3dSCy Schubert *overflow = 1; 1205*2b15cb3dSCy Schubert return; 1206*2b15cb3dSCy Schubert } 1207*2b15cb3dSCy Schubert 1208*2b15cb3dSCy Schubert /* 1209*2b15cb3dSCy Schubert * Factor of ten with the number of digits needed for the fractional 1210*2b15cb3dSCy Schubert * part. For example, if the precision is 3, the mask will be 1000. 1211*2b15cb3dSCy Schubert */ 1212*2b15cb3dSCy Schubert mask = mypow10(precision); 1213*2b15cb3dSCy Schubert /* 1214*2b15cb3dSCy Schubert * We "cheat" by converting the fractional part to integer by 1215*2b15cb3dSCy Schubert * multiplying by a factor of ten. 1216*2b15cb3dSCy Schubert */ 1217*2b15cb3dSCy Schubert if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { 1218*2b15cb3dSCy Schubert /* 1219*2b15cb3dSCy Schubert * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 1220*2b15cb3dSCy Schubert * (because precision = 3). Now, myround(1000 * 0.99962) will 1221*2b15cb3dSCy Schubert * return 1000. So, the integer part must be incremented by one 1222*2b15cb3dSCy Schubert * and the fractional part must be set to zero. 1223*2b15cb3dSCy Schubert */ 1224*2b15cb3dSCy Schubert intpart++; 1225*2b15cb3dSCy Schubert fracpart = 0; 1226*2b15cb3dSCy Schubert if (estyle && intpart == 10) { 1227*2b15cb3dSCy Schubert /* 1228*2b15cb3dSCy Schubert * The value was rounded up to ten, but we only want one 1229*2b15cb3dSCy Schubert * integer digit if using "e-style". So, the integer 1230*2b15cb3dSCy Schubert * part must be set to one and the exponent must be 1231*2b15cb3dSCy Schubert * incremented by one. 1232*2b15cb3dSCy Schubert */ 1233*2b15cb3dSCy Schubert intpart = 1; 1234*2b15cb3dSCy Schubert exponent++; 1235*2b15cb3dSCy Schubert } 1236*2b15cb3dSCy Schubert } 1237*2b15cb3dSCy Schubert 1238*2b15cb3dSCy Schubert /* 1239*2b15cb3dSCy Schubert * Now that we know the real exponent, we can check whether or not to 1240*2b15cb3dSCy Schubert * use "e-style" for "%g" (and "%G") conversions. If we don't need 1241*2b15cb3dSCy Schubert * "e-style", the precision must be adjusted and the integer and 1242*2b15cb3dSCy Schubert * fractional parts must be recalculated from the original value. 1243*2b15cb3dSCy Schubert * 1244*2b15cb3dSCy Schubert * C99 says: "Let P equal the precision if nonzero, 6 if the precision 1245*2b15cb3dSCy Schubert * is omitted, or 1 if the precision is zero. Then, if a conversion 1246*2b15cb3dSCy Schubert * with style `E' would have an exponent of X: 1247*2b15cb3dSCy Schubert * 1248*2b15cb3dSCy Schubert * - if P > X >= -4, the conversion is with style `f' (or `F') and 1249*2b15cb3dSCy Schubert * precision P - (X + 1). 1250*2b15cb3dSCy Schubert * 1251*2b15cb3dSCy Schubert * - otherwise, the conversion is with style `e' (or `E') and precision 1252*2b15cb3dSCy Schubert * P - 1." (7.19.6.1, 8) 1253*2b15cb3dSCy Schubert * 1254*2b15cb3dSCy Schubert * Note that we had decremented the precision by one. 1255*2b15cb3dSCy Schubert */ 1256*2b15cb3dSCy Schubert if (flags & PRINT_F_TYPE_G && estyle && 1257*2b15cb3dSCy Schubert precision + 1 > exponent && exponent >= -4) { 1258*2b15cb3dSCy Schubert precision -= exponent; 1259*2b15cb3dSCy Schubert estyle = 0; 1260*2b15cb3dSCy Schubert goto again; 1261*2b15cb3dSCy Schubert } 1262*2b15cb3dSCy Schubert 1263*2b15cb3dSCy Schubert if (estyle) { 1264*2b15cb3dSCy Schubert if (exponent < 0) { 1265*2b15cb3dSCy Schubert exponent = -exponent; 1266*2b15cb3dSCy Schubert esign = '-'; 1267*2b15cb3dSCy Schubert } else 1268*2b15cb3dSCy Schubert esign = '+'; 1269*2b15cb3dSCy Schubert 1270*2b15cb3dSCy Schubert /* 1271*2b15cb3dSCy Schubert * Convert the exponent. The sizeof(econvert) is 4. So, the 1272*2b15cb3dSCy Schubert * econvert buffer can hold e.g. "e+99" and "e-99". We don't 1273*2b15cb3dSCy Schubert * support an exponent which contains more than two digits. 1274*2b15cb3dSCy Schubert * Therefore, the following stores are safe. 1275*2b15cb3dSCy Schubert */ 1276*2b15cb3dSCy Schubert epos = convert(exponent, econvert, 2, 10, 0); 1277*2b15cb3dSCy Schubert /* 1278*2b15cb3dSCy Schubert * C99 says: "The exponent always contains at least two digits, 1279*2b15cb3dSCy Schubert * and only as many more digits as necessary to represent the 1280*2b15cb3dSCy Schubert * exponent." (7.19.6.1, 8) 1281*2b15cb3dSCy Schubert */ 1282*2b15cb3dSCy Schubert if (epos == 1) 1283*2b15cb3dSCy Schubert econvert[epos++] = '0'; 1284*2b15cb3dSCy Schubert econvert[epos++] = esign; 1285*2b15cb3dSCy Schubert econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; 1286*2b15cb3dSCy Schubert } 1287*2b15cb3dSCy Schubert 1288*2b15cb3dSCy Schubert /* Convert the integer part and the fractional part. */ 1289*2b15cb3dSCy Schubert ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); 1290*2b15cb3dSCy Schubert if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ 1291*2b15cb3dSCy Schubert fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); 1292*2b15cb3dSCy Schubert 1293*2b15cb3dSCy Schubert leadfraczeros = precision - fpos; 1294*2b15cb3dSCy Schubert 1295*2b15cb3dSCy Schubert if (omitzeros) { 1296*2b15cb3dSCy Schubert if (fpos > 0) /* Omit trailing fractional part zeros. */ 1297*2b15cb3dSCy Schubert while (omitcount < fpos && fconvert[omitcount] == '0') 1298*2b15cb3dSCy Schubert omitcount++; 1299*2b15cb3dSCy Schubert else { /* The fractional part is zero, omit it completely. */ 1300*2b15cb3dSCy Schubert omitcount = precision; 1301*2b15cb3dSCy Schubert leadfraczeros = 0; 1302*2b15cb3dSCy Schubert } 1303*2b15cb3dSCy Schubert precision -= omitcount; 1304*2b15cb3dSCy Schubert } 1305*2b15cb3dSCy Schubert 1306*2b15cb3dSCy Schubert /* 1307*2b15cb3dSCy Schubert * Print a decimal point if either the fractional part is non-zero 1308*2b15cb3dSCy Schubert * and/or the "#" flag was specified. 1309*2b15cb3dSCy Schubert */ 1310*2b15cb3dSCy Schubert if (precision > 0 || flags & PRINT_F_NUM) 1311*2b15cb3dSCy Schubert emitpoint = 1; 1312*2b15cb3dSCy Schubert if (separators) /* Get the number of group separators we'll print. */ 1313*2b15cb3dSCy Schubert separators = getnumsep(ipos); 1314*2b15cb3dSCy Schubert 1315*2b15cb3dSCy Schubert padlen = width /* Minimum field width. */ 1316*2b15cb3dSCy Schubert - ipos /* Number of integer digits. */ 1317*2b15cb3dSCy Schubert - epos /* Number of exponent characters. */ 1318*2b15cb3dSCy Schubert - precision /* Number of fractional digits. */ 1319*2b15cb3dSCy Schubert - separators /* Number of group separators. */ 1320*2b15cb3dSCy Schubert - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ 1321*2b15cb3dSCy Schubert - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ 1322*2b15cb3dSCy Schubert 1323*2b15cb3dSCy Schubert if (padlen < 0) 1324*2b15cb3dSCy Schubert padlen = 0; 1325*2b15cb3dSCy Schubert 1326*2b15cb3dSCy Schubert /* 1327*2b15cb3dSCy Schubert * C99 says: "If the `0' and `-' flags both appear, the `0' flag is 1328*2b15cb3dSCy Schubert * ignored." (7.19.6.1, 6) 1329*2b15cb3dSCy Schubert */ 1330*2b15cb3dSCy Schubert if (flags & PRINT_F_MINUS) /* Left justifty. */ 1331*2b15cb3dSCy Schubert padlen = -padlen; 1332*2b15cb3dSCy Schubert else if (flags & PRINT_F_ZERO && padlen > 0) { 1333*2b15cb3dSCy Schubert if (sign != 0) { /* Sign. */ 1334*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, sign); 1335*2b15cb3dSCy Schubert sign = 0; 1336*2b15cb3dSCy Schubert } 1337*2b15cb3dSCy Schubert while (padlen > 0) { /* Leading zeros. */ 1338*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, '0'); 1339*2b15cb3dSCy Schubert padlen--; 1340*2b15cb3dSCy Schubert } 1341*2b15cb3dSCy Schubert } 1342*2b15cb3dSCy Schubert while (padlen > 0) { /* Leading spaces. */ 1343*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ' '); 1344*2b15cb3dSCy Schubert padlen--; 1345*2b15cb3dSCy Schubert } 1346*2b15cb3dSCy Schubert if (sign != 0) /* Sign. */ 1347*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, sign); 1348*2b15cb3dSCy Schubert while (ipos > 0) { /* Integer part. */ 1349*2b15cb3dSCy Schubert ipos--; 1350*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, iconvert[ipos]); 1351*2b15cb3dSCy Schubert if (separators > 0 && ipos > 0 && ipos % 3 == 0) 1352*2b15cb3dSCy Schubert printsep(str, len, size); 1353*2b15cb3dSCy Schubert } 1354*2b15cb3dSCy Schubert if (emitpoint) { /* Decimal point. */ 1355*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT 1356*2b15cb3dSCy Schubert if (lc->decimal_point != NULL && *lc->decimal_point != '\0') 1357*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, *lc->decimal_point); 1358*2b15cb3dSCy Schubert else /* We'll always print some decimal point character. */ 1359*2b15cb3dSCy Schubert #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ 1360*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, '.'); 1361*2b15cb3dSCy Schubert } 1362*2b15cb3dSCy Schubert while (leadfraczeros > 0) { /* Leading fractional part zeros. */ 1363*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, '0'); 1364*2b15cb3dSCy Schubert leadfraczeros--; 1365*2b15cb3dSCy Schubert } 1366*2b15cb3dSCy Schubert while (fpos > omitcount) { /* The remaining fractional part. */ 1367*2b15cb3dSCy Schubert fpos--; 1368*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, fconvert[fpos]); 1369*2b15cb3dSCy Schubert } 1370*2b15cb3dSCy Schubert while (epos > 0) { /* Exponent. */ 1371*2b15cb3dSCy Schubert epos--; 1372*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, econvert[epos]); 1373*2b15cb3dSCy Schubert } 1374*2b15cb3dSCy Schubert while (padlen < 0) { /* Trailing spaces. */ 1375*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ' '); 1376*2b15cb3dSCy Schubert padlen++; 1377*2b15cb3dSCy Schubert } 1378*2b15cb3dSCy Schubert } 1379*2b15cb3dSCy Schubert 1380*2b15cb3dSCy Schubert static void 1381*2b15cb3dSCy Schubert printsep(char *str, size_t *len, size_t size) 1382*2b15cb3dSCy Schubert { 1383*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP 1384*2b15cb3dSCy Schubert struct lconv *lc = localeconv(); 1385*2b15cb3dSCy Schubert int i; 1386*2b15cb3dSCy Schubert 1387*2b15cb3dSCy Schubert if (lc->thousands_sep != NULL) 1388*2b15cb3dSCy Schubert for (i = 0; lc->thousands_sep[i] != '\0'; i++) 1389*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, lc->thousands_sep[i]); 1390*2b15cb3dSCy Schubert else 1391*2b15cb3dSCy Schubert #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ 1392*2b15cb3dSCy Schubert OUTCHAR(str, *len, size, ','); 1393*2b15cb3dSCy Schubert } 1394*2b15cb3dSCy Schubert 1395*2b15cb3dSCy Schubert static int 1396*2b15cb3dSCy Schubert getnumsep(int digits) 1397*2b15cb3dSCy Schubert { 1398*2b15cb3dSCy Schubert int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; 1399*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP 1400*2b15cb3dSCy Schubert int strln; 1401*2b15cb3dSCy Schubert struct lconv *lc = localeconv(); 1402*2b15cb3dSCy Schubert 1403*2b15cb3dSCy Schubert /* We support an arbitrary separator length (including zero). */ 1404*2b15cb3dSCy Schubert if (lc->thousands_sep != NULL) { 1405*2b15cb3dSCy Schubert for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) 1406*2b15cb3dSCy Schubert continue; 1407*2b15cb3dSCy Schubert separators *= strln; 1408*2b15cb3dSCy Schubert } 1409*2b15cb3dSCy Schubert #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ 1410*2b15cb3dSCy Schubert return separators; 1411*2b15cb3dSCy Schubert } 1412*2b15cb3dSCy Schubert 1413*2b15cb3dSCy Schubert static int 1414*2b15cb3dSCy Schubert getexponent(LDOUBLE value) 1415*2b15cb3dSCy Schubert { 1416*2b15cb3dSCy Schubert LDOUBLE tmp = (value >= 0.0) ? value : -value; 1417*2b15cb3dSCy Schubert int exponent = 0; 1418*2b15cb3dSCy Schubert 1419*2b15cb3dSCy Schubert /* 1420*2b15cb3dSCy Schubert * We check for 99 > exponent > -99 in order to work around possible 1421*2b15cb3dSCy Schubert * endless loops which could happen (at least) in the second loop (at 1422*2b15cb3dSCy Schubert * least) if we're called with an infinite value. However, we checked 1423*2b15cb3dSCy Schubert * for infinity before calling this function using our ISINF() macro, so 1424*2b15cb3dSCy Schubert * this might be somewhat paranoid. 1425*2b15cb3dSCy Schubert */ 1426*2b15cb3dSCy Schubert while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) 1427*2b15cb3dSCy Schubert tmp *= 10; 1428*2b15cb3dSCy Schubert while (tmp >= 10.0 && ++exponent < 99) 1429*2b15cb3dSCy Schubert tmp /= 10; 1430*2b15cb3dSCy Schubert 1431*2b15cb3dSCy Schubert return exponent; 1432*2b15cb3dSCy Schubert } 1433*2b15cb3dSCy Schubert 1434*2b15cb3dSCy Schubert static int 1435*2b15cb3dSCy Schubert convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) 1436*2b15cb3dSCy Schubert { 1437*2b15cb3dSCy Schubert const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; 1438*2b15cb3dSCy Schubert size_t pos = 0; 1439*2b15cb3dSCy Schubert 1440*2b15cb3dSCy Schubert /* We return an unterminated buffer with the digits in reverse order. */ 1441*2b15cb3dSCy Schubert do { 1442*2b15cb3dSCy Schubert buf[pos++] = digits[value % base]; 1443*2b15cb3dSCy Schubert value /= base; 1444*2b15cb3dSCy Schubert } while (value != 0 && pos < size); 1445*2b15cb3dSCy Schubert 1446*2b15cb3dSCy Schubert return (int)pos; 1447*2b15cb3dSCy Schubert } 1448*2b15cb3dSCy Schubert 1449*2b15cb3dSCy Schubert static UINTMAX_T 1450*2b15cb3dSCy Schubert cast(LDOUBLE value) 1451*2b15cb3dSCy Schubert { 1452*2b15cb3dSCy Schubert UINTMAX_T result; 1453*2b15cb3dSCy Schubert 1454*2b15cb3dSCy Schubert /* 1455*2b15cb3dSCy Schubert * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be 1456*2b15cb3dSCy Schubert * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), 1457*2b15cb3dSCy Schubert * it may be increased to the nearest higher representable value for the 1458*2b15cb3dSCy Schubert * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE 1459*2b15cb3dSCy Schubert * value although converting the latter to UINTMAX_T would overflow. 1460*2b15cb3dSCy Schubert */ 1461*2b15cb3dSCy Schubert if (value >= UINTMAX_MAX) 1462*2b15cb3dSCy Schubert return UINTMAX_MAX; 1463*2b15cb3dSCy Schubert 1464*2b15cb3dSCy Schubert result = value; 1465*2b15cb3dSCy Schubert /* 1466*2b15cb3dSCy Schubert * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to 1467*2b15cb3dSCy Schubert * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates 1468*2b15cb3dSCy Schubert * the standard). Sigh. 1469*2b15cb3dSCy Schubert */ 1470*2b15cb3dSCy Schubert return (result <= value) ? result : result - 1; 1471*2b15cb3dSCy Schubert } 1472*2b15cb3dSCy Schubert 1473*2b15cb3dSCy Schubert static UINTMAX_T 1474*2b15cb3dSCy Schubert myround(LDOUBLE value) 1475*2b15cb3dSCy Schubert { 1476*2b15cb3dSCy Schubert UINTMAX_T intpart = cast(value); 1477*2b15cb3dSCy Schubert 1478*2b15cb3dSCy Schubert return ((value -= intpart) < 0.5) ? intpart : intpart + 1; 1479*2b15cb3dSCy Schubert } 1480*2b15cb3dSCy Schubert 1481*2b15cb3dSCy Schubert static LDOUBLE 1482*2b15cb3dSCy Schubert mypow10(int exponent) 1483*2b15cb3dSCy Schubert { 1484*2b15cb3dSCy Schubert LDOUBLE result = 1; 1485*2b15cb3dSCy Schubert 1486*2b15cb3dSCy Schubert while (exponent > 0) { 1487*2b15cb3dSCy Schubert result *= 10; 1488*2b15cb3dSCy Schubert exponent--; 1489*2b15cb3dSCy Schubert } 1490*2b15cb3dSCy Schubert while (exponent < 0) { 1491*2b15cb3dSCy Schubert result /= 10; 1492*2b15cb3dSCy Schubert exponent++; 1493*2b15cb3dSCy Schubert } 1494*2b15cb3dSCy Schubert return result; 1495*2b15cb3dSCy Schubert } 1496*2b15cb3dSCy Schubert #endif /* HW_WANT_RPL_VSNPRINTF */ 1497*2b15cb3dSCy Schubert 1498*2b15cb3dSCy Schubert #if HW_WANT_RPL_VASPRINTF 1499*2b15cb3dSCy Schubert #if NEED_MYMEMCPY 1500*2b15cb3dSCy Schubert void * 1501*2b15cb3dSCy Schubert mymemcpy(void *dst, void *src, size_t len) 1502*2b15cb3dSCy Schubert { 1503*2b15cb3dSCy Schubert const char *from = src; 1504*2b15cb3dSCy Schubert char *to = dst; 1505*2b15cb3dSCy Schubert 1506*2b15cb3dSCy Schubert /* No need for optimization, we use this only to replace va_copy(3). */ 1507*2b15cb3dSCy Schubert while (len-- > 0) 1508*2b15cb3dSCy Schubert *to++ = *from++; 1509*2b15cb3dSCy Schubert return dst; 1510*2b15cb3dSCy Schubert } 1511*2b15cb3dSCy Schubert #endif /* NEED_MYMEMCPY */ 1512*2b15cb3dSCy Schubert 1513*2b15cb3dSCy Schubert int 1514*2b15cb3dSCy Schubert rpl_vasprintf(char **ret, const char *format, va_list ap); 1515*2b15cb3dSCy Schubert 1516*2b15cb3dSCy Schubert int 1517*2b15cb3dSCy Schubert rpl_vasprintf(char **ret, const char *format, va_list ap) 1518*2b15cb3dSCy Schubert { 1519*2b15cb3dSCy Schubert size_t size; 1520*2b15cb3dSCy Schubert int len; 1521*2b15cb3dSCy Schubert va_list aq; 1522*2b15cb3dSCy Schubert 1523*2b15cb3dSCy Schubert VA_COPY(aq, ap); 1524*2b15cb3dSCy Schubert len = vsnprintf(NULL, 0, format, aq); 1525*2b15cb3dSCy Schubert VA_END_COPY(aq); 1526*2b15cb3dSCy Schubert if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) 1527*2b15cb3dSCy Schubert return -1; 1528*2b15cb3dSCy Schubert return vsnprintf(*ret, size, format, ap); 1529*2b15cb3dSCy Schubert } 1530*2b15cb3dSCy Schubert #endif /* HW_WANT_RPL_VASPRINTF */ 1531*2b15cb3dSCy Schubert 1532*2b15cb3dSCy Schubert #if HW_WANT_RPL_SNPRINTF 1533*2b15cb3dSCy Schubert #if HAVE_STDARG_H 1534*2b15cb3dSCy Schubert int 1535*2b15cb3dSCy Schubert rpl_snprintf(char *str, size_t size, const char *format, ...); 1536*2b15cb3dSCy Schubert 1537*2b15cb3dSCy Schubert int 1538*2b15cb3dSCy Schubert rpl_snprintf(char *str, size_t size, const char *format, ...) 1539ce265a54SOllivier Robert #else 1540*2b15cb3dSCy Schubert int 1541*2b15cb3dSCy Schubert rpl_snprintf(va_alist) va_dcl 1542*2b15cb3dSCy Schubert #endif /* HAVE_STDARG_H */ 1543*2b15cb3dSCy Schubert { 1544*2b15cb3dSCy Schubert #if !HAVE_STDARG_H 1545*2b15cb3dSCy Schubert char *str; 1546*2b15cb3dSCy Schubert size_t size; 1547*2b15cb3dSCy Schubert char *format; 1548*2b15cb3dSCy Schubert #endif /* HAVE_STDARG_H */ 1549*2b15cb3dSCy Schubert va_list ap; 1550*2b15cb3dSCy Schubert int len; 1551*2b15cb3dSCy Schubert 1552*2b15cb3dSCy Schubert VA_START(ap, format); 1553*2b15cb3dSCy Schubert VA_SHIFT(ap, str, char *); 1554*2b15cb3dSCy Schubert VA_SHIFT(ap, size, size_t); 1555*2b15cb3dSCy Schubert VA_SHIFT(ap, format, const char *); 1556*2b15cb3dSCy Schubert len = vsnprintf(str, size, format, ap); 1557*2b15cb3dSCy Schubert va_end(ap); 1558*2b15cb3dSCy Schubert return len; 1559*2b15cb3dSCy Schubert } 1560*2b15cb3dSCy Schubert #endif /* HW_WANT_RPL_SNPRINTF */ 1561*2b15cb3dSCy Schubert 1562*2b15cb3dSCy Schubert #if HW_WANT_RPL_ASPRINTF 1563*2b15cb3dSCy Schubert #if HAVE_STDARG_H 1564*2b15cb3dSCy Schubert int 1565*2b15cb3dSCy Schubert rpl_asprintf(char **ret, const char *format, ...); 1566*2b15cb3dSCy Schubert 1567*2b15cb3dSCy Schubert int 1568*2b15cb3dSCy Schubert rpl_asprintf(char **ret, const char *format, ...) 1569*2b15cb3dSCy Schubert #else 1570*2b15cb3dSCy Schubert int 1571*2b15cb3dSCy Schubert rpl_asprintf(va_alist) va_dcl 1572*2b15cb3dSCy Schubert #endif /* HAVE_STDARG_H */ 1573*2b15cb3dSCy Schubert { 1574*2b15cb3dSCy Schubert #if !HAVE_STDARG_H 1575*2b15cb3dSCy Schubert char **ret; 1576*2b15cb3dSCy Schubert char *format; 1577*2b15cb3dSCy Schubert #endif /* HAVE_STDARG_H */ 1578*2b15cb3dSCy Schubert va_list ap; 1579*2b15cb3dSCy Schubert int len; 1580*2b15cb3dSCy Schubert 1581*2b15cb3dSCy Schubert VA_START(ap, format); 1582*2b15cb3dSCy Schubert VA_SHIFT(ap, ret, char **); 1583*2b15cb3dSCy Schubert VA_SHIFT(ap, format, const char *); 1584*2b15cb3dSCy Schubert len = vasprintf(ret, format, ap); 1585*2b15cb3dSCy Schubert va_end(ap); 1586*2b15cb3dSCy Schubert return len; 1587*2b15cb3dSCy Schubert } 1588*2b15cb3dSCy Schubert #endif /* HW_WANT_RPL_ASPRINTF */ 1589*2b15cb3dSCy Schubert #else /* Dummy declaration to avoid empty translation unit warnings. */ 1590*2b15cb3dSCy Schubert int main(void); 1591*2b15cb3dSCy Schubert #endif /* HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || [...] */ 1592*2b15cb3dSCy Schubert 1593*2b15cb3dSCy Schubert #if TEST_SNPRINTF 1594*2b15cb3dSCy Schubert int 1595*2b15cb3dSCy Schubert main(void) 1596*2b15cb3dSCy Schubert { 1597*2b15cb3dSCy Schubert const char *float_fmt[] = { 1598*2b15cb3dSCy Schubert /* "%E" and "%e" formats. */ 1599*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX 1600*2b15cb3dSCy Schubert "%.16e", 1601*2b15cb3dSCy Schubert "%22.16e", 1602*2b15cb3dSCy Schubert "%022.16e", 1603*2b15cb3dSCy Schubert "%-22.16e", 1604*2b15cb3dSCy Schubert "%#+'022.16e", 1605*2b15cb3dSCy Schubert #endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */ 1606*2b15cb3dSCy Schubert "foo|%#+0123.9E|bar", 1607*2b15cb3dSCy Schubert "%-123.9e", 1608*2b15cb3dSCy Schubert "%123.9e", 1609*2b15cb3dSCy Schubert "%+23.9e", 1610*2b15cb3dSCy Schubert "%+05.8e", 1611*2b15cb3dSCy Schubert "%-05.8e", 1612*2b15cb3dSCy Schubert "%05.8e", 1613*2b15cb3dSCy Schubert "%+5.8e", 1614*2b15cb3dSCy Schubert "%-5.8e", 1615*2b15cb3dSCy Schubert "% 5.8e", 1616*2b15cb3dSCy Schubert "%5.8e", 1617*2b15cb3dSCy Schubert "%+4.9e", 1618*2b15cb3dSCy Schubert #if !OS_LINUX /* glibc sometimes gets these wrong. */ 1619*2b15cb3dSCy Schubert "%+#010.0e", 1620*2b15cb3dSCy Schubert "%#10.1e", 1621*2b15cb3dSCy Schubert "%10.5e", 1622*2b15cb3dSCy Schubert "% 10.5e", 1623*2b15cb3dSCy Schubert "%5.0e", 1624*2b15cb3dSCy Schubert "%5.e", 1625*2b15cb3dSCy Schubert "%#5.0e", 1626*2b15cb3dSCy Schubert "%#5.e", 1627*2b15cb3dSCy Schubert "%3.2e", 1628*2b15cb3dSCy Schubert "%3.1e", 1629*2b15cb3dSCy Schubert "%-1.5e", 1630*2b15cb3dSCy Schubert "%1.5e", 1631*2b15cb3dSCy Schubert "%01.3e", 1632*2b15cb3dSCy Schubert "%1.e", 1633*2b15cb3dSCy Schubert "%.1e", 1634*2b15cb3dSCy Schubert "%#.0e", 1635*2b15cb3dSCy Schubert "%+.0e", 1636*2b15cb3dSCy Schubert "% .0e", 1637*2b15cb3dSCy Schubert "%.0e", 1638*2b15cb3dSCy Schubert "%#.e", 1639*2b15cb3dSCy Schubert "%+.e", 1640*2b15cb3dSCy Schubert "% .e", 1641*2b15cb3dSCy Schubert "%.e", 1642*2b15cb3dSCy Schubert "%4e", 1643*2b15cb3dSCy Schubert "%e", 1644*2b15cb3dSCy Schubert "%E", 1645*2b15cb3dSCy Schubert #endif /* !OS_LINUX */ 1646*2b15cb3dSCy Schubert /* "%F" and "%f" formats. */ 1647*2b15cb3dSCy Schubert #if !OS_BSD && !OS_IRIX 1648*2b15cb3dSCy Schubert "% '022f", 1649*2b15cb3dSCy Schubert "%+'022f", 1650*2b15cb3dSCy Schubert "%-'22f", 1651*2b15cb3dSCy Schubert "%'22f", 1652*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT 1653*2b15cb3dSCy Schubert "%.16f", 1654*2b15cb3dSCy Schubert "%22.16f", 1655*2b15cb3dSCy Schubert "%022.16f", 1656*2b15cb3dSCy Schubert "%-22.16f", 1657*2b15cb3dSCy Schubert "%#+'022.16f", 1658*2b15cb3dSCy Schubert #endif /* HAVE_LONG_LONG_INT */ 1659*2b15cb3dSCy Schubert #endif /* !OS_BSD && !OS_IRIX */ 1660*2b15cb3dSCy Schubert "foo|%#+0123.9F|bar", 1661*2b15cb3dSCy Schubert "%-123.9f", 1662*2b15cb3dSCy Schubert "%123.9f", 1663*2b15cb3dSCy Schubert "%+23.9f", 1664*2b15cb3dSCy Schubert "%+#010.0f", 1665*2b15cb3dSCy Schubert "%#10.1f", 1666*2b15cb3dSCy Schubert "%10.5f", 1667*2b15cb3dSCy Schubert "% 10.5f", 1668*2b15cb3dSCy Schubert "%+05.8f", 1669*2b15cb3dSCy Schubert "%-05.8f", 1670*2b15cb3dSCy Schubert "%05.8f", 1671*2b15cb3dSCy Schubert "%+5.8f", 1672*2b15cb3dSCy Schubert "%-5.8f", 1673*2b15cb3dSCy Schubert "% 5.8f", 1674*2b15cb3dSCy Schubert "%5.8f", 1675*2b15cb3dSCy Schubert "%5.0f", 1676*2b15cb3dSCy Schubert "%5.f", 1677*2b15cb3dSCy Schubert "%#5.0f", 1678*2b15cb3dSCy Schubert "%#5.f", 1679*2b15cb3dSCy Schubert "%+4.9f", 1680*2b15cb3dSCy Schubert "%3.2f", 1681*2b15cb3dSCy Schubert "%3.1f", 1682*2b15cb3dSCy Schubert "%-1.5f", 1683*2b15cb3dSCy Schubert "%1.5f", 1684*2b15cb3dSCy Schubert "%01.3f", 1685*2b15cb3dSCy Schubert "%1.f", 1686*2b15cb3dSCy Schubert "%.1f", 1687*2b15cb3dSCy Schubert "%#.0f", 1688*2b15cb3dSCy Schubert "%+.0f", 1689*2b15cb3dSCy Schubert "% .0f", 1690*2b15cb3dSCy Schubert "%.0f", 1691*2b15cb3dSCy Schubert "%#.f", 1692*2b15cb3dSCy Schubert "%+.f", 1693*2b15cb3dSCy Schubert "% .f", 1694*2b15cb3dSCy Schubert "%.f", 1695*2b15cb3dSCy Schubert "%4f", 1696*2b15cb3dSCy Schubert "%f", 1697*2b15cb3dSCy Schubert "%F", 1698*2b15cb3dSCy Schubert /* "%G" and "%g" formats. */ 1699*2b15cb3dSCy Schubert #if !OS_BSD && !OS_IRIX && !OS_LINUX 1700*2b15cb3dSCy Schubert "% '022g", 1701*2b15cb3dSCy Schubert "%+'022g", 1702*2b15cb3dSCy Schubert "%-'22g", 1703*2b15cb3dSCy Schubert "%'22g", 1704*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT 1705*2b15cb3dSCy Schubert "%.16g", 1706*2b15cb3dSCy Schubert "%22.16g", 1707*2b15cb3dSCy Schubert "%022.16g", 1708*2b15cb3dSCy Schubert "%-22.16g", 1709*2b15cb3dSCy Schubert "%#+'022.16g", 1710*2b15cb3dSCy Schubert #endif /* HAVE_LONG_LONG_INT */ 1711*2b15cb3dSCy Schubert #endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */ 1712*2b15cb3dSCy Schubert "foo|%#+0123.9G|bar", 1713*2b15cb3dSCy Schubert "%-123.9g", 1714*2b15cb3dSCy Schubert "%123.9g", 1715*2b15cb3dSCy Schubert "%+23.9g", 1716*2b15cb3dSCy Schubert "%+05.8g", 1717*2b15cb3dSCy Schubert "%-05.8g", 1718*2b15cb3dSCy Schubert "%05.8g", 1719*2b15cb3dSCy Schubert "%+5.8g", 1720*2b15cb3dSCy Schubert "%-5.8g", 1721*2b15cb3dSCy Schubert "% 5.8g", 1722*2b15cb3dSCy Schubert "%5.8g", 1723*2b15cb3dSCy Schubert "%+4.9g", 1724*2b15cb3dSCy Schubert #if !OS_LINUX /* glibc sometimes gets these wrong. */ 1725*2b15cb3dSCy Schubert "%+#010.0g", 1726*2b15cb3dSCy Schubert "%#10.1g", 1727*2b15cb3dSCy Schubert "%10.5g", 1728*2b15cb3dSCy Schubert "% 10.5g", 1729*2b15cb3dSCy Schubert "%5.0g", 1730*2b15cb3dSCy Schubert "%5.g", 1731*2b15cb3dSCy Schubert "%#5.0g", 1732*2b15cb3dSCy Schubert "%#5.g", 1733*2b15cb3dSCy Schubert "%3.2g", 1734*2b15cb3dSCy Schubert "%3.1g", 1735*2b15cb3dSCy Schubert "%-1.5g", 1736*2b15cb3dSCy Schubert "%1.5g", 1737*2b15cb3dSCy Schubert "%01.3g", 1738*2b15cb3dSCy Schubert "%1.g", 1739*2b15cb3dSCy Schubert "%.1g", 1740*2b15cb3dSCy Schubert "%#.0g", 1741*2b15cb3dSCy Schubert "%+.0g", 1742*2b15cb3dSCy Schubert "% .0g", 1743*2b15cb3dSCy Schubert "%.0g", 1744*2b15cb3dSCy Schubert "%#.g", 1745*2b15cb3dSCy Schubert "%+.g", 1746*2b15cb3dSCy Schubert "% .g", 1747*2b15cb3dSCy Schubert "%.g", 1748*2b15cb3dSCy Schubert "%4g", 1749*2b15cb3dSCy Schubert "%g", 1750*2b15cb3dSCy Schubert "%G", 1751*2b15cb3dSCy Schubert #endif /* !OS_LINUX */ 1752*2b15cb3dSCy Schubert NULL 1753*2b15cb3dSCy Schubert }; 1754*2b15cb3dSCy Schubert double float_val[] = { 1755*2b15cb3dSCy Schubert -4.136, 1756*2b15cb3dSCy Schubert -134.52, 1757*2b15cb3dSCy Schubert -5.04030201, 1758*2b15cb3dSCy Schubert -3410.01234, 1759*2b15cb3dSCy Schubert -999999.999999, 1760*2b15cb3dSCy Schubert -913450.29876, 1761*2b15cb3dSCy Schubert -913450.2, 1762*2b15cb3dSCy Schubert -91345.2, 1763*2b15cb3dSCy Schubert -9134.2, 1764*2b15cb3dSCy Schubert -913.2, 1765*2b15cb3dSCy Schubert -91.2, 1766*2b15cb3dSCy Schubert -9.2, 1767*2b15cb3dSCy Schubert -9.9, 1768*2b15cb3dSCy Schubert 4.136, 1769*2b15cb3dSCy Schubert 134.52, 1770*2b15cb3dSCy Schubert 5.04030201, 1771*2b15cb3dSCy Schubert 3410.01234, 1772*2b15cb3dSCy Schubert 999999.999999, 1773*2b15cb3dSCy Schubert 913450.29876, 1774*2b15cb3dSCy Schubert 913450.2, 1775*2b15cb3dSCy Schubert 91345.2, 1776*2b15cb3dSCy Schubert 9134.2, 1777*2b15cb3dSCy Schubert 913.2, 1778*2b15cb3dSCy Schubert 91.2, 1779*2b15cb3dSCy Schubert 9.2, 1780*2b15cb3dSCy Schubert 9.9, 1781*2b15cb3dSCy Schubert 9.96, 1782*2b15cb3dSCy Schubert 9.996, 1783*2b15cb3dSCy Schubert 9.9996, 1784*2b15cb3dSCy Schubert 9.99996, 1785*2b15cb3dSCy Schubert 9.999996, 1786*2b15cb3dSCy Schubert 9.9999996, 1787*2b15cb3dSCy Schubert 9.99999996, 1788*2b15cb3dSCy Schubert 0.99999996, 1789*2b15cb3dSCy Schubert 0.99999999, 1790*2b15cb3dSCy Schubert 0.09999999, 1791*2b15cb3dSCy Schubert 0.00999999, 1792*2b15cb3dSCy Schubert 0.00099999, 1793*2b15cb3dSCy Schubert 0.00009999, 1794*2b15cb3dSCy Schubert 0.00000999, 1795*2b15cb3dSCy Schubert 0.00000099, 1796*2b15cb3dSCy Schubert 0.00000009, 1797*2b15cb3dSCy Schubert 0.00000001, 1798*2b15cb3dSCy Schubert 0.0000001, 1799*2b15cb3dSCy Schubert 0.000001, 1800*2b15cb3dSCy Schubert 0.00001, 1801*2b15cb3dSCy Schubert 0.0001, 1802*2b15cb3dSCy Schubert 0.001, 1803*2b15cb3dSCy Schubert 0.01, 1804*2b15cb3dSCy Schubert 0.1, 1805*2b15cb3dSCy Schubert 1.0, 1806*2b15cb3dSCy Schubert 1.5, 1807*2b15cb3dSCy Schubert -1.5, 1808*2b15cb3dSCy Schubert -1.0, 1809*2b15cb3dSCy Schubert -0.1, 1810*2b15cb3dSCy Schubert #if !OS_BSD /* BSD sometimes gets these wrong. */ 1811*2b15cb3dSCy Schubert #ifdef INFINITY 1812*2b15cb3dSCy Schubert INFINITY, 1813*2b15cb3dSCy Schubert -INFINITY, 1814*2b15cb3dSCy Schubert #endif /* defined(INFINITY) */ 1815*2b15cb3dSCy Schubert #ifdef NAN 1816*2b15cb3dSCy Schubert NAN, 1817*2b15cb3dSCy Schubert #endif /* defined(NAN) */ 1818*2b15cb3dSCy Schubert #endif /* !OS_BSD */ 1819*2b15cb3dSCy Schubert 0 1820*2b15cb3dSCy Schubert }; 1821*2b15cb3dSCy Schubert const char *long_fmt[] = { 1822*2b15cb3dSCy Schubert "foo|%0123ld|bar", 1823*2b15cb3dSCy Schubert #if !OS_IRIX 1824*2b15cb3dSCy Schubert "% '0123ld", 1825*2b15cb3dSCy Schubert "%+'0123ld", 1826*2b15cb3dSCy Schubert "%-'123ld", 1827*2b15cb3dSCy Schubert "%'123ld", 1828*2b15cb3dSCy Schubert #endif /* !OS_IRiX */ 1829*2b15cb3dSCy Schubert "%123.9ld", 1830*2b15cb3dSCy Schubert "% 123.9ld", 1831*2b15cb3dSCy Schubert "%+123.9ld", 1832*2b15cb3dSCy Schubert "%-123.9ld", 1833*2b15cb3dSCy Schubert "%0123ld", 1834*2b15cb3dSCy Schubert "% 0123ld", 1835*2b15cb3dSCy Schubert "%+0123ld", 1836*2b15cb3dSCy Schubert "%-0123ld", 1837*2b15cb3dSCy Schubert "%10.5ld", 1838*2b15cb3dSCy Schubert "% 10.5ld", 1839*2b15cb3dSCy Schubert "%+10.5ld", 1840*2b15cb3dSCy Schubert "%-10.5ld", 1841*2b15cb3dSCy Schubert "%010ld", 1842*2b15cb3dSCy Schubert "% 010ld", 1843*2b15cb3dSCy Schubert "%+010ld", 1844*2b15cb3dSCy Schubert "%-010ld", 1845*2b15cb3dSCy Schubert "%4.2ld", 1846*2b15cb3dSCy Schubert "% 4.2ld", 1847*2b15cb3dSCy Schubert "%+4.2ld", 1848*2b15cb3dSCy Schubert "%-4.2ld", 1849*2b15cb3dSCy Schubert "%04ld", 1850*2b15cb3dSCy Schubert "% 04ld", 1851*2b15cb3dSCy Schubert "%+04ld", 1852*2b15cb3dSCy Schubert "%-04ld", 1853*2b15cb3dSCy Schubert "%5.5ld", 1854*2b15cb3dSCy Schubert "%+22.33ld", 1855*2b15cb3dSCy Schubert "%01.3ld", 1856*2b15cb3dSCy Schubert "%1.5ld", 1857*2b15cb3dSCy Schubert "%-1.5ld", 1858*2b15cb3dSCy Schubert "%44ld", 1859*2b15cb3dSCy Schubert "%4ld", 1860*2b15cb3dSCy Schubert "%4.0ld", 1861*2b15cb3dSCy Schubert "%4.ld", 1862*2b15cb3dSCy Schubert "%.44ld", 1863*2b15cb3dSCy Schubert "%.4ld", 1864*2b15cb3dSCy Schubert "%.0ld", 1865*2b15cb3dSCy Schubert "%.ld", 1866*2b15cb3dSCy Schubert "%ld", 1867*2b15cb3dSCy Schubert NULL 1868*2b15cb3dSCy Schubert }; 1869*2b15cb3dSCy Schubert long int long_val[] = { 1870*2b15cb3dSCy Schubert #ifdef LONG_MAX 1871*2b15cb3dSCy Schubert LONG_MAX, 1872*2b15cb3dSCy Schubert #endif /* LONG_MAX */ 1873*2b15cb3dSCy Schubert #ifdef LONG_MIN 1874*2b15cb3dSCy Schubert LONG_MIN, 1875*2b15cb3dSCy Schubert #endif /* LONG_MIN */ 1876*2b15cb3dSCy Schubert -91340, 1877*2b15cb3dSCy Schubert 91340, 1878*2b15cb3dSCy Schubert 341, 1879*2b15cb3dSCy Schubert 134, 1880*2b15cb3dSCy Schubert 0203, 1881*2b15cb3dSCy Schubert -1, 1882*2b15cb3dSCy Schubert 1, 1883*2b15cb3dSCy Schubert 0 1884*2b15cb3dSCy Schubert }; 1885*2b15cb3dSCy Schubert const char *ulong_fmt[] = { 1886*2b15cb3dSCy Schubert /* "%u" formats. */ 1887*2b15cb3dSCy Schubert "foo|%0123lu|bar", 1888*2b15cb3dSCy Schubert #if !OS_IRIX 1889*2b15cb3dSCy Schubert "% '0123lu", 1890*2b15cb3dSCy Schubert "%+'0123lu", 1891*2b15cb3dSCy Schubert "%-'123lu", 1892*2b15cb3dSCy Schubert "%'123lu", 1893*2b15cb3dSCy Schubert #endif /* !OS_IRiX */ 1894*2b15cb3dSCy Schubert "%123.9lu", 1895*2b15cb3dSCy Schubert "% 123.9lu", 1896*2b15cb3dSCy Schubert "%+123.9lu", 1897*2b15cb3dSCy Schubert "%-123.9lu", 1898*2b15cb3dSCy Schubert "%0123lu", 1899*2b15cb3dSCy Schubert "% 0123lu", 1900*2b15cb3dSCy Schubert "%+0123lu", 1901*2b15cb3dSCy Schubert "%-0123lu", 1902*2b15cb3dSCy Schubert "%5.5lu", 1903*2b15cb3dSCy Schubert "%+22.33lu", 1904*2b15cb3dSCy Schubert "%01.3lu", 1905*2b15cb3dSCy Schubert "%1.5lu", 1906*2b15cb3dSCy Schubert "%-1.5lu", 1907*2b15cb3dSCy Schubert "%44lu", 1908*2b15cb3dSCy Schubert "%lu", 1909*2b15cb3dSCy Schubert /* "%o" formats. */ 1910*2b15cb3dSCy Schubert "foo|%#0123lo|bar", 1911*2b15cb3dSCy Schubert "%#123.9lo", 1912*2b15cb3dSCy Schubert "%# 123.9lo", 1913*2b15cb3dSCy Schubert "%#+123.9lo", 1914*2b15cb3dSCy Schubert "%#-123.9lo", 1915*2b15cb3dSCy Schubert "%#0123lo", 1916*2b15cb3dSCy Schubert "%# 0123lo", 1917*2b15cb3dSCy Schubert "%#+0123lo", 1918*2b15cb3dSCy Schubert "%#-0123lo", 1919*2b15cb3dSCy Schubert "%#5.5lo", 1920*2b15cb3dSCy Schubert "%#+22.33lo", 1921*2b15cb3dSCy Schubert "%#01.3lo", 1922*2b15cb3dSCy Schubert "%#1.5lo", 1923*2b15cb3dSCy Schubert "%#-1.5lo", 1924*2b15cb3dSCy Schubert "%#44lo", 1925*2b15cb3dSCy Schubert "%#lo", 1926*2b15cb3dSCy Schubert "%123.9lo", 1927*2b15cb3dSCy Schubert "% 123.9lo", 1928*2b15cb3dSCy Schubert "%+123.9lo", 1929*2b15cb3dSCy Schubert "%-123.9lo", 1930*2b15cb3dSCy Schubert "%0123lo", 1931*2b15cb3dSCy Schubert "% 0123lo", 1932*2b15cb3dSCy Schubert "%+0123lo", 1933*2b15cb3dSCy Schubert "%-0123lo", 1934*2b15cb3dSCy Schubert "%5.5lo", 1935*2b15cb3dSCy Schubert "%+22.33lo", 1936*2b15cb3dSCy Schubert "%01.3lo", 1937*2b15cb3dSCy Schubert "%1.5lo", 1938*2b15cb3dSCy Schubert "%-1.5lo", 1939*2b15cb3dSCy Schubert "%44lo", 1940*2b15cb3dSCy Schubert "%lo", 1941*2b15cb3dSCy Schubert /* "%X" and "%x" formats. */ 1942*2b15cb3dSCy Schubert "foo|%#0123lX|bar", 1943*2b15cb3dSCy Schubert "%#123.9lx", 1944*2b15cb3dSCy Schubert "%# 123.9lx", 1945*2b15cb3dSCy Schubert "%#+123.9lx", 1946*2b15cb3dSCy Schubert "%#-123.9lx", 1947*2b15cb3dSCy Schubert "%#0123lx", 1948*2b15cb3dSCy Schubert "%# 0123lx", 1949*2b15cb3dSCy Schubert "%#+0123lx", 1950*2b15cb3dSCy Schubert "%#-0123lx", 1951*2b15cb3dSCy Schubert "%#5.5lx", 1952*2b15cb3dSCy Schubert "%#+22.33lx", 1953*2b15cb3dSCy Schubert "%#01.3lx", 1954*2b15cb3dSCy Schubert "%#1.5lx", 1955*2b15cb3dSCy Schubert "%#-1.5lx", 1956*2b15cb3dSCy Schubert "%#44lx", 1957*2b15cb3dSCy Schubert "%#lx", 1958*2b15cb3dSCy Schubert "%#lX", 1959*2b15cb3dSCy Schubert "%123.9lx", 1960*2b15cb3dSCy Schubert "% 123.9lx", 1961*2b15cb3dSCy Schubert "%+123.9lx", 1962*2b15cb3dSCy Schubert "%-123.9lx", 1963*2b15cb3dSCy Schubert "%0123lx", 1964*2b15cb3dSCy Schubert "% 0123lx", 1965*2b15cb3dSCy Schubert "%+0123lx", 1966*2b15cb3dSCy Schubert "%-0123lx", 1967*2b15cb3dSCy Schubert "%5.5lx", 1968*2b15cb3dSCy Schubert "%+22.33lx", 1969*2b15cb3dSCy Schubert "%01.3lx", 1970*2b15cb3dSCy Schubert "%1.5lx", 1971*2b15cb3dSCy Schubert "%-1.5lx", 1972*2b15cb3dSCy Schubert "%44lx", 1973*2b15cb3dSCy Schubert "%lx", 1974*2b15cb3dSCy Schubert "%lX", 1975*2b15cb3dSCy Schubert NULL 1976*2b15cb3dSCy Schubert }; 1977*2b15cb3dSCy Schubert unsigned long int ulong_val[] = { 1978*2b15cb3dSCy Schubert #ifdef ULONG_MAX 1979*2b15cb3dSCy Schubert ULONG_MAX, 1980*2b15cb3dSCy Schubert #endif /* ULONG_MAX */ 1981*2b15cb3dSCy Schubert 91340, 1982*2b15cb3dSCy Schubert 341, 1983*2b15cb3dSCy Schubert 134, 1984*2b15cb3dSCy Schubert 0203, 1985*2b15cb3dSCy Schubert 1, 1986*2b15cb3dSCy Schubert 0 1987*2b15cb3dSCy Schubert }; 1988*2b15cb3dSCy Schubert const char *llong_fmt[] = { 1989*2b15cb3dSCy Schubert "foo|%0123lld|bar", 1990*2b15cb3dSCy Schubert "%123.9lld", 1991*2b15cb3dSCy Schubert "% 123.9lld", 1992*2b15cb3dSCy Schubert "%+123.9lld", 1993*2b15cb3dSCy Schubert "%-123.9lld", 1994*2b15cb3dSCy Schubert "%0123lld", 1995*2b15cb3dSCy Schubert "% 0123lld", 1996*2b15cb3dSCy Schubert "%+0123lld", 1997*2b15cb3dSCy Schubert "%-0123lld", 1998*2b15cb3dSCy Schubert "%5.5lld", 1999*2b15cb3dSCy Schubert "%+22.33lld", 2000*2b15cb3dSCy Schubert "%01.3lld", 2001*2b15cb3dSCy Schubert "%1.5lld", 2002*2b15cb3dSCy Schubert "%-1.5lld", 2003*2b15cb3dSCy Schubert "%44lld", 2004*2b15cb3dSCy Schubert "%lld", 2005*2b15cb3dSCy Schubert NULL 2006*2b15cb3dSCy Schubert }; 2007*2b15cb3dSCy Schubert LLONG llong_val[] = { 2008*2b15cb3dSCy Schubert #ifdef LLONG_MAX 2009*2b15cb3dSCy Schubert LLONG_MAX, 2010*2b15cb3dSCy Schubert #endif /* LLONG_MAX */ 2011*2b15cb3dSCy Schubert #ifdef LLONG_MIN 2012*2b15cb3dSCy Schubert LLONG_MIN, 2013*2b15cb3dSCy Schubert #endif /* LLONG_MIN */ 2014*2b15cb3dSCy Schubert -91340, 2015*2b15cb3dSCy Schubert 91340, 2016*2b15cb3dSCy Schubert 341, 2017*2b15cb3dSCy Schubert 134, 2018*2b15cb3dSCy Schubert 0203, 2019*2b15cb3dSCy Schubert -1, 2020*2b15cb3dSCy Schubert 1, 2021*2b15cb3dSCy Schubert 0 2022*2b15cb3dSCy Schubert }; 2023*2b15cb3dSCy Schubert const char *string_fmt[] = { 2024*2b15cb3dSCy Schubert "foo|%10.10s|bar", 2025*2b15cb3dSCy Schubert "%-10.10s", 2026*2b15cb3dSCy Schubert "%10.10s", 2027*2b15cb3dSCy Schubert "%10.5s", 2028*2b15cb3dSCy Schubert "%5.10s", 2029*2b15cb3dSCy Schubert "%10.1s", 2030*2b15cb3dSCy Schubert "%1.10s", 2031*2b15cb3dSCy Schubert "%10.0s", 2032*2b15cb3dSCy Schubert "%0.10s", 2033*2b15cb3dSCy Schubert "%-42.5s", 2034*2b15cb3dSCy Schubert "%2.s", 2035*2b15cb3dSCy Schubert "%.10s", 2036*2b15cb3dSCy Schubert "%.1s", 2037*2b15cb3dSCy Schubert "%.0s", 2038*2b15cb3dSCy Schubert "%.s", 2039*2b15cb3dSCy Schubert "%4s", 2040*2b15cb3dSCy Schubert "%s", 2041*2b15cb3dSCy Schubert NULL 2042*2b15cb3dSCy Schubert }; 2043*2b15cb3dSCy Schubert const char *string_val[] = { 2044*2b15cb3dSCy Schubert "Hello", 2045*2b15cb3dSCy Schubert "Hello, world!", 2046*2b15cb3dSCy Schubert "Sound check: One, two, three.", 2047*2b15cb3dSCy Schubert "This string is a little longer than the other strings.", 2048*2b15cb3dSCy Schubert "1", 2049*2b15cb3dSCy Schubert "", 2050*2b15cb3dSCy Schubert NULL 2051*2b15cb3dSCy Schubert }; 2052*2b15cb3dSCy Schubert #if !OS_SYSV /* SysV uses a different format than we do. */ 2053*2b15cb3dSCy Schubert const char *pointer_fmt[] = { 2054*2b15cb3dSCy Schubert "foo|%p|bar", 2055*2b15cb3dSCy Schubert "%42p", 2056*2b15cb3dSCy Schubert "%p", 2057*2b15cb3dSCy Schubert NULL 2058*2b15cb3dSCy Schubert }; 2059*2b15cb3dSCy Schubert const char *pointer_val[] = { 2060*2b15cb3dSCy Schubert *pointer_fmt, 2061*2b15cb3dSCy Schubert *string_fmt, 2062*2b15cb3dSCy Schubert *string_val, 2063*2b15cb3dSCy Schubert NULL 2064*2b15cb3dSCy Schubert }; 2065*2b15cb3dSCy Schubert #endif /* !OS_SYSV */ 2066*2b15cb3dSCy Schubert char buf1[1024], buf2[1024]; 2067*2b15cb3dSCy Schubert double value, digits = 9.123456789012345678901234567890123456789; 2068*2b15cb3dSCy Schubert int i, j, r1, r2, failed = 0, num = 0; 2069*2b15cb3dSCy Schubert 2070*2b15cb3dSCy Schubert /* 2071*2b15cb3dSCy Schubert * Use -DTEST_NILS in order to also test the conversion of nil values. Might 2072*2b15cb3dSCy Schubert * segfault on systems which don't support converting a NULL pointer with "%s" 2073*2b15cb3dSCy Schubert * and lets some test cases fail against BSD and glibc due to bugs in their 2074*2b15cb3dSCy Schubert * implementations. 2075*2b15cb3dSCy Schubert */ 2076*2b15cb3dSCy Schubert #ifndef TEST_NILS 2077*2b15cb3dSCy Schubert #define TEST_NILS 0 2078*2b15cb3dSCy Schubert #elif TEST_NILS 2079*2b15cb3dSCy Schubert #undef TEST_NILS 2080*2b15cb3dSCy Schubert #define TEST_NILS 1 2081*2b15cb3dSCy Schubert #endif /* !defined(TEST_NILS) */ 2082*2b15cb3dSCy Schubert #ifdef TEST 2083*2b15cb3dSCy Schubert #undef TEST 2084*2b15cb3dSCy Schubert #endif /* defined(TEST) */ 2085*2b15cb3dSCy Schubert #define TEST(fmt, val) \ 2086*2b15cb3dSCy Schubert do { \ 2087*2b15cb3dSCy Schubert for (i = 0; fmt[i] != NULL; i++) \ 2088*2b15cb3dSCy Schubert for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \ 2089*2b15cb3dSCy Schubert r1 = sprintf(buf1, fmt[i], val[j]); \ 2090*2b15cb3dSCy Schubert r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \ 2091*2b15cb3dSCy Schubert if (strcmp(buf1, buf2) != 0 || r1 != r2) { \ 2092*2b15cb3dSCy Schubert (void)printf("Results don't match, " \ 2093*2b15cb3dSCy Schubert "format string: %s\n" \ 2094*2b15cb3dSCy Schubert "\t sprintf(3): [%s] (%d)\n" \ 2095*2b15cb3dSCy Schubert "\tsnprintf(3): [%s] (%d)\n", \ 2096*2b15cb3dSCy Schubert fmt[i], buf1, r1, buf2, r2); \ 2097*2b15cb3dSCy Schubert failed++; \ 2098*2b15cb3dSCy Schubert } \ 2099*2b15cb3dSCy Schubert num++; \ 2100*2b15cb3dSCy Schubert } \ 2101*2b15cb3dSCy Schubert } while (/* CONSTCOND */ 0) 2102*2b15cb3dSCy Schubert 2103*2b15cb3dSCy Schubert #if HAVE_LOCALE_H 2104*2b15cb3dSCy Schubert (void)setlocale(LC_ALL, ""); 2105*2b15cb3dSCy Schubert #endif /* HAVE_LOCALE_H */ 2106*2b15cb3dSCy Schubert 2107*2b15cb3dSCy Schubert (void)puts("Testing our snprintf(3) against your system's sprintf(3)."); 2108*2b15cb3dSCy Schubert TEST(float_fmt, float_val); 2109*2b15cb3dSCy Schubert TEST(long_fmt, long_val); 2110*2b15cb3dSCy Schubert TEST(ulong_fmt, ulong_val); 2111*2b15cb3dSCy Schubert TEST(llong_fmt, llong_val); 2112*2b15cb3dSCy Schubert TEST(string_fmt, string_val); 2113*2b15cb3dSCy Schubert #if !OS_SYSV /* SysV uses a different format than we do. */ 2114*2b15cb3dSCy Schubert TEST(pointer_fmt, pointer_val); 2115*2b15cb3dSCy Schubert #endif /* !OS_SYSV */ 2116*2b15cb3dSCy Schubert (void)printf("Result: %d out of %d tests failed.\n", failed, num); 2117*2b15cb3dSCy Schubert 2118*2b15cb3dSCy Schubert (void)fputs("Checking how many digits we support: ", stdout); 2119*2b15cb3dSCy Schubert for (i = 0; i < 100; i++) { 2120*2b15cb3dSCy Schubert value = pow(10, i) * digits; 2121*2b15cb3dSCy Schubert (void)sprintf(buf1, "%.1f", value); 2122*2b15cb3dSCy Schubert (void)snprintf(buf2, sizeof(buf2), "%.1f", value); 2123*2b15cb3dSCy Schubert if (strcmp(buf1, buf2) != 0) { 2124*2b15cb3dSCy Schubert (void)printf("apparently %d.\n", i); 2125*2b15cb3dSCy Schubert break; 2126*2b15cb3dSCy Schubert } 2127*2b15cb3dSCy Schubert } 2128*2b15cb3dSCy Schubert return (failed == 0) ? 0 : 1; 2129*2b15cb3dSCy Schubert } 2130*2b15cb3dSCy Schubert #endif /* TEST_SNPRINTF */ 2131*2b15cb3dSCy Schubert 2132*2b15cb3dSCy Schubert /* vim: set joinspaces textwidth=80: */ 2133