LCOV - differential code coverage report
Current view: top level - src/port - snprintf.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC CBC EUB ECB DUB
Current: Differential Code Coverage HEAD vs 15 Lines: 67.6 % 614 415 2 30 98 69 28 220 167 100 218 2
Current Date: 2023-04-08 17:13:01 Functions: 91.7 % 24 22 2 22 2 22
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 4 4 4 1
Legend: Lines: hit not hit (240..) days: 67.4 % 610 411 2 30 98 69 28 216 167 100 217
Function coverage date bins:
(240..) days: 45.8 % 48 22 2 22 2 22

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * Copyright (c) 1983, 1995, 1996 Eric P. Allman
                                  3                 :  * Copyright (c) 1988, 1993
                                  4                 :  *  The Regents of the University of California.  All rights reserved.
                                  5                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  6                 :  *
                                  7                 :  * Redistribution and use in source and binary forms, with or without
                                  8                 :  * modification, are permitted provided that the following conditions
                                  9                 :  * are met:
                                 10                 :  * 1. Redistributions of source code must retain the above copyright
                                 11                 :  *    notice, this list of conditions and the following disclaimer.
                                 12                 :  * 2. Redistributions in binary form must reproduce the above copyright
                                 13                 :  *    notice, this list of conditions and the following disclaimer in the
                                 14                 :  *    documentation and/or other materials provided with the distribution.
                                 15                 :  * 3. Neither the name of the University nor the names of its contributors
                                 16                 :  *    may be used to endorse or promote products derived from this software
                                 17                 :  *    without specific prior written permission.
                                 18                 :  *
                                 19                 :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                                 20                 :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                                 21                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                                 22                 :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                                 23                 :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                                 24                 :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                                 25                 :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                                 26                 :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                                 27                 :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                                 28                 :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                                 29                 :  * SUCH DAMAGE.
                                 30                 :  *
                                 31                 :  * src/port/snprintf.c
                                 32                 :  */
                                 33                 : 
                                 34                 : #include "c.h"
                                 35                 : 
                                 36                 : #include <math.h>
                                 37                 : 
                                 38                 : /*
                                 39                 :  * We used to use the platform's NL_ARGMAX here, but that's a bad idea,
                                 40                 :  * first because the point of this module is to remove platform dependencies
                                 41                 :  * not perpetuate them, and second because some platforms use ridiculously
                                 42                 :  * large values, leading to excessive stack consumption in dopr().
                                 43                 :  */
                                 44                 : #define PG_NL_ARGMAX 31
                                 45                 : 
                                 46                 : 
                                 47                 : /*
                                 48                 :  *  SNPRINTF, VSNPRINTF and friends
                                 49                 :  *
                                 50                 :  * These versions have been grabbed off the net.  They have been
                                 51                 :  * cleaned up to compile properly and support for most of the C99
                                 52                 :  * specification has been added.  Remaining unimplemented features are:
                                 53                 :  *
                                 54                 :  * 1. No locale support: the radix character is always '.' and the '
                                 55                 :  * (single quote) format flag is ignored.
                                 56                 :  *
                                 57                 :  * 2. No support for the "%n" format specification.
                                 58                 :  *
                                 59                 :  * 3. No support for wide characters ("lc" and "ls" formats).
                                 60                 :  *
                                 61                 :  * 4. No support for "long double" ("Lf" and related formats).
                                 62                 :  *
                                 63                 :  * 5. Space and '#' flags are not implemented.
                                 64                 :  *
                                 65                 :  * In addition, we support some extensions over C99:
                                 66                 :  *
                                 67                 :  * 1. Argument order control through "%n$" and "*n$", as required by POSIX.
                                 68                 :  *
                                 69                 :  * 2. "%m" expands to the value of strerror(errno), where errno is the
                                 70                 :  * value that variable had at the start of the call.  This is a glibc
                                 71                 :  * extension, but a very useful one.
                                 72                 :  *
                                 73                 :  *
                                 74                 :  * Historically the result values of sprintf/snprintf varied across platforms.
                                 75                 :  * This implementation now follows the C99 standard:
                                 76                 :  *
                                 77                 :  * 1. -1 is returned if an error is detected in the format string, or if
                                 78                 :  * a write to the target stream fails (as reported by fwrite).  Note that
                                 79                 :  * overrunning snprintf's target buffer is *not* an error.
                                 80                 :  *
                                 81                 :  * 2. For successful writes to streams, the actual number of bytes written
                                 82                 :  * to the stream is returned.
                                 83                 :  *
                                 84                 :  * 3. For successful sprintf/snprintf, the number of bytes that would have
                                 85                 :  * been written to an infinite-size buffer (excluding the trailing '\0')
                                 86                 :  * is returned.  snprintf will truncate its output to fit in the buffer
                                 87                 :  * (ensuring a trailing '\0' unless count == 0), but this is not reflected
                                 88                 :  * in the function result.
                                 89                 :  *
                                 90                 :  * snprintf buffer overrun can be detected by checking for function result
                                 91                 :  * greater than or equal to the supplied count.
                                 92                 :  */
                                 93                 : 
                                 94                 : /**************************************************************
                                 95                 :  * Original:
                                 96                 :  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
                                 97                 :  * A bombproof version of doprnt (dopr) included.
                                 98                 :  * Sigh.  This sort of thing is always nasty do deal with.  Note that
                                 99                 :  * the version here does not include floating point. (now it does ... tgl)
                                100                 :  **************************************************************/
                                101                 : 
                                102                 : /* Prevent recursion */
                                103                 : #undef  vsnprintf
                                104                 : #undef  snprintf
                                105                 : #undef  vsprintf
                                106                 : #undef  sprintf
                                107                 : #undef  vfprintf
                                108                 : #undef  fprintf
                                109                 : #undef  vprintf
                                110                 : #undef  printf
                                111                 : 
                                112                 : /*
                                113                 :  * Info about where the formatted output is going.
                                114                 :  *
                                115                 :  * dopr and subroutines will not write at/past bufend, but snprintf
                                116                 :  * reserves one byte, ensuring it may place the trailing '\0' there.
                                117                 :  *
                                118                 :  * In snprintf, we use nchars to count the number of bytes dropped on the
                                119                 :  * floor due to buffer overrun.  The correct result of snprintf is thus
                                120                 :  * (bufptr - bufstart) + nchars.  (This isn't as inconsistent as it might
                                121                 :  * seem: nchars is the number of emitted bytes that are not in the buffer now,
                                122                 :  * either because we sent them to the stream or because we couldn't fit them
                                123                 :  * into the buffer to begin with.)
                                124                 :  */
                                125                 : typedef struct
                                126                 : {
                                127                 :     char       *bufptr;         /* next buffer output position */
                                128                 :     char       *bufstart;       /* first buffer element */
                                129                 :     char       *bufend;         /* last+1 buffer element, or NULL */
                                130                 :     /* bufend == NULL is for sprintf, where we assume buf is big enough */
                                131                 :     FILE       *stream;         /* eventual output destination, or NULL */
                                132                 :     int         nchars;         /* # chars sent to stream, or dropped */
                                133                 :     bool        failed;         /* call is a failure; errno is set */
                                134                 : } PrintfTarget;
                                135                 : 
                                136                 : /*
                                137                 :  * Info about the type and value of a formatting parameter.  Note that we
                                138                 :  * don't currently support "long double", "wint_t", or "wchar_t *" data,
                                139                 :  * nor the '%n' formatting code; else we'd need more types.  Also, at this
                                140                 :  * level we need not worry about signed vs unsigned values.
                                141                 :  */
                                142                 : typedef enum
                                143                 : {
                                144                 :     ATYPE_NONE = 0,
                                145                 :     ATYPE_INT,
                                146                 :     ATYPE_LONG,
                                147                 :     ATYPE_LONGLONG,
                                148                 :     ATYPE_DOUBLE,
                                149                 :     ATYPE_CHARPTR
                                150                 : } PrintfArgType;
                                151                 : 
                                152                 : typedef union
                                153                 : {
                                154                 :     int         i;
                                155                 :     long        l;
                                156                 :     long long   ll;
                                157                 :     double      d;
                                158                 :     char       *cptr;
                                159                 : } PrintfArgValue;
                                160                 : 
                                161                 : 
                                162                 : static void flushbuffer(PrintfTarget *target);
                                163                 : static void dopr(PrintfTarget *target, const char *format, va_list args);
 6334 tgl                       164 ECB             : 
                                165                 : 
                                166                 : /*
                                167                 :  * Externally visible entry points.
                                168                 :  *
                                169                 :  * All of these are just wrappers around dopr().  Note it's essential that
                                170                 :  * they not change the value of "errno" before reaching dopr().
                                171                 :  */
                                172                 : 
                                173                 : int
 6603 bruce                     174 GIC    70273981 : pg_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
 6620 bruce                     175 ECB             : {
                                176                 :     PrintfTarget target;
 1698 tgl                       177                 :     char        onebyte[1];
 6334                           178                 : 
                                179                 :     /*
 1698                           180                 :      * C99 allows the case str == NULL when count == 0.  Rather than
                                181                 :      * special-casing this situation further down, we substitute a one-byte
                                182                 :      * local buffer.  Callers cannot tell, since the function result doesn't
                                183                 :      * depend on count.
                                184                 :      */
 1698 tgl                       185 CBC    70273981 :     if (count == 0)
 1698 tgl                       186 ECB             :     {
 1698 tgl                       187 CBC       44711 :         str = onebyte;
                                188           44711 :         count = 1;
                                189                 :     }
 6334 tgl                       190 GIC    70273981 :     target.bufstart = target.bufptr = str;
                                191        70273981 :     target.bufend = str + count - 1;
 6334 tgl                       192 CBC    70273981 :     target.stream = NULL;
 1698 tgl                       193 GIC    70273981 :     target.nchars = 0;
 2883 noah                      194        70273981 :     target.failed = false;
                                195        70273981 :     dopr(&target, fmt, args);
 6334 tgl                       196        70273981 :     *(target.bufptr) = '\0';
 1698 tgl                       197 CBC   140547962 :     return target.failed ? -1 : (target.bufptr - target.bufstart
                                198        70273981 :                                  + target.nchars);
 6620 bruce                     199 ECB             : }
                                200                 : 
                                201                 : int
 6603 bruce                     202 GIC     9581971 : pg_snprintf(char *str, size_t count, const char *fmt,...)
                                203                 : {
 8950 bruce                     204 ECB             :     int         len;
                                205                 :     va_list     args;
                                206                 : 
 8878 bruce                     207 GIC     9581971 :     va_start(args, fmt);
 6603 bruce                     208 CBC     9581971 :     len = pg_vsnprintf(str, count, fmt, args);
 8878                           209         9581977 :     va_end(args);
 8983 scrappy                   210         9581977 :     return len;
 8983 scrappy                   211 ECB             : }
                                212                 : 
 1644 tgl                       213                 : int
 6334 tgl                       214 CBC     3124419 : pg_vsprintf(char *str, const char *fmt, va_list args)
 6334 tgl                       215 ECB             : {
 6031 bruce                     216                 :     PrintfTarget target;
                                217                 : 
 6334 tgl                       218 GIC     3124419 :     target.bufstart = target.bufptr = str;
                                219         3124419 :     target.bufend = NULL;
 6334 tgl                       220 CBC     3124419 :     target.stream = NULL;
 1698 tgl                       221 GIC     3124419 :     target.nchars = 0;          /* not really used in this case */
 2883 noah                      222         3124419 :     target.failed = false;
                                223         3124419 :     dopr(&target, fmt, args);
 6334 tgl                       224         3124419 :     *(target.bufptr) = '\0';
 1698 tgl                       225 CBC     6248838 :     return target.failed ? -1 : (target.bufptr - target.bufstart
                                226         3124419 :                                  + target.nchars);
 6334 tgl                       227 ECB             : }
                                228                 : 
                                229                 : int
 6598 bruce                     230 GIC     3124415 : pg_sprintf(char *str, const char *fmt,...)
                                231                 : {
 6598 bruce                     232 ECB             :     int         len;
                                233                 :     va_list     args;
                                234                 : 
 6598 bruce                     235 GIC     3124415 :     va_start(args, fmt);
 6334 tgl                       236         3124415 :     len = pg_vsprintf(str, fmt, args);
 6598 bruce                     237 CBC     3124423 :     va_end(args);
 6598 bruce                     238 GIC     3124423 :     return len;
 6598 bruce                     239 EUB             : }
                                240                 : 
                                241                 : int
 6334 tgl                       242 CBC      993442 : pg_vfprintf(FILE *stream, const char *fmt, va_list args)
 6334 tgl                       243 ECB             : {
 6031 bruce                     244                 :     PrintfTarget target;
 6334 tgl                       245                 :     char        buffer[1024];   /* size is arbitrary */
                                246                 : 
 6334 tgl                       247 CBC      993442 :     if (stream == NULL)
                                248                 :     {
 6334 tgl                       249 LBC           0 :         errno = EINVAL;
                                250               0 :         return -1;
                                251                 :     }
 6334 tgl                       252 GIC      993442 :     target.bufstart = target.bufptr = buffer;
 1698                           253          993442 :     target.bufend = buffer + sizeof(buffer);    /* use the whole buffer */
 6334 tgl                       254 CBC      993442 :     target.stream = stream;
 6334 tgl                       255 GIC      993442 :     target.nchars = 0;
 2883 noah                      256          993442 :     target.failed = false;
                                257          993442 :     dopr(&target, fmt, args);
                                258                 :     /* dump any remaining buffer contents */
 6334 tgl                       259 CBC      993442 :     flushbuffer(&target);
 2883 noah                      260          993442 :     return target.failed ? -1 : target.nchars;
 6334 tgl                       261 ECB             : }
                                262                 : 
                                263                 : int
 6603 bruce                     264 GIC      729096 : pg_fprintf(FILE *stream, const char *fmt,...)
                                265                 : {
 6603 bruce                     266 EUB             :     int         len;
                                267                 :     va_list     args;
                                268                 : 
 6603 bruce                     269 GIC      729096 :     va_start(args, fmt);
 6334 tgl                       270          729096 :     len = pg_vfprintf(stream, fmt, args);
 6603 bruce                     271          729096 :     va_end(args);
 6603 bruce                     272 CBC      729096 :     return len;
                                273                 : }
                                274                 : 
                                275                 : int
 1644 tgl                       276 UIC           0 : pg_vprintf(const char *fmt, va_list args)
 1644 tgl                       277 ECB             : {
 1644 tgl                       278 LBC           0 :     return pg_vfprintf(stdout, fmt, args);
 1644 tgl                       279 ECB             : }
                                280                 : 
                                281                 : int
 6603 bruce                     282 GIC      257015 : pg_printf(const char *fmt,...)
                                283                 : {
                                284                 :     int         len;
                                285                 :     va_list     args;
                                286                 : 
 6612                           287          257015 :     va_start(args, fmt);
 6334 tgl                       288 CBC      257015 :     len = pg_vfprintf(stdout, fmt, args);
 6612 bruce                     289 GIC      257015 :     va_end(args);
 6612 bruce                     290 CBC      257015 :     return len;
                                291                 : }
                                292                 : 
                                293                 : /*
                                294                 :  * Attempt to write the entire buffer to target->stream; discard the entire
                                295                 :  * buffer in any case.  Call this only when target->stream is defined.
 2883 noah                      296 ECB             :  */
                                297                 : static void
 4382 bruce                     298 GIC      993712 : flushbuffer(PrintfTarget *target)
                                299                 : {
 6031 bruce                     300 CBC      993712 :     size_t      nc = target->bufptr - target->bufstart;
 6334 tgl                       301 ECB             : 
 1698                           302                 :     /*
 1698 tgl                       303 EUB             :      * Don't write anything if we already failed; this is to ensure we
                                304                 :      * preserve the original failure's errno.
 1698 tgl                       305 ECB             :      */
 2883 noah                      306 CBC      993712 :     if (!target->failed && nc > 0)
                                307                 :     {
                                308                 :         size_t      written;
                                309                 : 
 2883 noah                      310 GIC      880810 :         written = fwrite(target->bufstart, 1, nc, target->stream);
                                311          880810 :         target->nchars += written;
                                312          880810 :         if (written != nc)
 2883 noah                      313 UIC           0 :             target->failed = true;
                                314                 :     }
 6334 tgl                       315 GIC      993712 :     target->bufptr = target->bufstart;
                                316          993712 : }
                                317                 : 
                                318                 : 
                                319                 : static bool find_arguments(const char *format, va_list args,
                                320                 :                            PrintfArgValue *argvalues);
                                321                 : static void fmtstr(const char *value, int leftjust, int minlen, int maxwidth,
                                322                 :                    int pointflag, PrintfTarget *target);
                                323                 : static void fmtptr(const void *value, PrintfTarget *target);
                                324                 : static void fmtint(long long value, char type, int forcesign,
                                325                 :                    int leftjust, int minlen, int zpad, int precision, int pointflag,
                                326                 :                    PrintfTarget *target);
                                327                 : static void fmtchar(int value, int leftjust, int minlen, PrintfTarget *target);
                                328                 : static void fmtfloat(double value, char type, int forcesign,
                                329                 :                      int leftjust, int minlen, int zpad, int precision, int pointflag,
                                330                 :                      PrintfTarget *target);
                                331                 : static void dostr(const char *str, int slen, PrintfTarget *target);
                                332                 : static void dopr_outch(int c, PrintfTarget *target);
                                333                 : static void dopr_outchmulti(int c, int slen, PrintfTarget *target);
                                334                 : static int  adjust_sign(int is_negative, int forcesign, int *signvalue);
                                335                 : static int  compute_padlen(int minlen, int vallen, int leftjust);
                                336                 : static void leading_pad(int zpad, int signvalue, int *padlen,
                                337                 :                         PrintfTarget *target);
                                338                 : static void trailing_pad(int padlen, PrintfTarget *target);
                                339                 : 
                                340                 : /*
                                341                 :  * If strchrnul exists (it's a glibc-ism), it's a good bit faster than the
                                342                 :  * equivalent manual loop.  If it doesn't exist, provide a replacement.
                                343                 :  *
                                344                 :  * Note: glibc declares this as returning "char *", but that would require
                                345                 :  * casting away const internally, so we don't follow that detail.
                                346                 :  */
                                347                 : #ifndef HAVE_STRCHRNUL
                                348                 : 
                                349                 : static inline const char *
                                350                 : strchrnul(const char *s, int c)
                                351                 : {
                                352                 :     while (*s != '\0' && *s != c)
                                353                 :         s++;
                                354                 :     return s;
                                355                 : }
                                356                 : 
                                357                 : #else
                                358                 : 
                                359                 : /*
                                360                 :  * glibc's <string.h> declares strchrnul only if _GNU_SOURCE is defined.
                                361                 :  * While we typically use that on glibc platforms, configure will set
                                362                 :  * HAVE_STRCHRNUL whether it's used or not.  Fill in the missing declaration
                                363                 :  * so that this file will compile cleanly with or without _GNU_SOURCE.
                                364                 :  */
                                365                 : #ifndef _GNU_SOURCE
 1649 tgl                       366 ECB             : extern char *strchrnul(const char *s, int c);
                                367                 : #endif
                                368                 : 
                                369                 : #endif                          /* HAVE_STRCHRNUL */
                                370                 : 
                                371                 : 
                                372                 : /*
                                373                 :  * dopr(): the guts of *printf for all cases.
                                374                 :  */
                                375                 : static void
 4382 bruce                     376 GIC    74391835 : dopr(PrintfTarget *target, const char *format, va_list args)
                                377                 : {
 1656 tgl                       378        74391835 :     int         save_errno = errno;
 1649                           379        74391835 :     const char *first_pct = NULL;
                                380                 :     int         ch;
                                381                 :     bool        have_dollar;
                                382                 :     bool        have_star;
                                383                 :     bool        afterstar;
                                384                 :     int         accum;
                                385                 :     int         longlongflag;
                                386                 :     int         longflag;
                                387                 :     int         pointflag;
                                388                 :     int         leftjust;
                                389                 :     int         fieldwidth;
                                390                 :     int         precision;
                                391                 :     int         zpad;
                                392                 :     int         forcesign;
                                393                 :     int         fmtpos;
                                394                 :     int         cvalue;
                                395                 :     long long   numvalue;
 6334 tgl                       396 ECB             :     double      fvalue;
                                397                 :     const char *strvalue;
 1650                           398                 :     PrintfArgValue argvalues[PG_NL_ARGMAX + 1];
                                399                 : 
                                400                 :     /*
 1649                           401                 :      * Initially, we suppose the format string does not use %n$.  The first
                                402                 :      * time we come to a conversion spec that has that, we'll call
                                403                 :      * find_arguments() to check for consistent use of %n$ and fill the
                                404                 :      * argvalues array with the argument values in the correct order.
                                405                 :      */
 1649 tgl                       406 GIC    74391835 :     have_dollar = false;
 6594 bruce                     407 ECB             : 
 1649 tgl                       408 CBC   155809903 :     while (*format != '\0')
 6612 bruce                     409 EUB             :     {
                                410                 :         /* Locate next conversion specifier */
 1649 tgl                       411 CBC    89752455 :         if (*format != '%')
 6334 tgl                       412 ECB             :         {
 1649                           413                 :             /* Scan to next '%' or end of string */
 1649 tgl                       414 GIC    70003911 :             const char *next_pct = strchrnul(format + 1, '%');
                                415                 : 
                                416                 :             /* Dump literal data we just scanned over */
                                417        70003911 :             dostr(format, next_pct - format, target);
                                418        70003917 :             if (target->failed)
 6334 tgl                       419 UIC           0 :                 break;
                                420                 : 
 1649 tgl                       421 CBC    70003917 :             if (*next_pct == '\0')
 6334                           422         8334384 :                 break;
 1649 tgl                       423 GIC    61669533 :             format = next_pct;
                                424                 :         }
 6031 bruce                     425 ECB             : 
                                426                 :         /*
                                427                 :          * Remember start of first conversion spec; if we find %n$, then it's
 1649 tgl                       428                 :          * sufficient for find_arguments() to start here, without rescanning
                                429                 :          * earlier literal text.
 6334                           430                 :          */
 1649 tgl                       431 CBC    81418077 :         if (first_pct == NULL)
                                432        73874022 :             first_pct = format;
 2883 noah                      433 EUB             : 
 1649 tgl                       434 ECB             :         /* Process conversion spec starting at *format */
 1649 tgl                       435 CBC    81418077 :         format++;
 1649 tgl                       436 EUB             : 
 1649 tgl                       437 ECB             :         /* Fast path for conversion spec that is exactly %s */
 1649 tgl                       438 GIC    81418077 :         if (*format == 's')
                                439                 :         {
 1649 tgl                       440 CBC    14092193 :             format++;
                                441        14092193 :             strvalue = va_arg(args, char *);
  624                           442        14092193 :             if (strvalue == NULL)
  624 tgl                       443 LBC           0 :                 strvalue = "(null)";
 1649 tgl                       444 CBC    14092193 :             dostr(strvalue, strlen(strvalue), target);
                                445        14092193 :             if (target->failed)
 1649 tgl                       446 LBC           0 :                 break;
 1649 tgl                       447 GIC    14092193 :             continue;
 1649 tgl                       448 ECB             :         }
                                449                 : 
 6334 tgl                       450 CBC    67325884 :         fieldwidth = precision = zpad = leftjust = forcesign = 0;
                                451        67325884 :         longflag = longlongflag = pointflag = 0;
                                452        67325884 :         fmtpos = accum = 0;
                                453        67325884 :         have_star = afterstar = false;
 6031 bruce                     454         9394442 : nextch2:
 6334 tgl                       455 GIC    76720326 :         ch = *format++;
 8950 bruce                     456 CBC    76720326 :         switch (ch)
 8950 bruce                     457 ECB             :         {
 6334 tgl                       458 GIC      220365 :             case '-':
                                459          220365 :                 leftjust = 1;
                                460          220365 :                 goto nextch2;
                                461             132 :             case '+':
                                462             132 :                 forcesign = 1;
                                463             132 :                 goto nextch2;
                                464         2858010 :             case '0':
                                465                 :                 /* set zero padding if no nonzero digits yet */
                                466         2858010 :                 if (accum == 0 && !pointflag)
                                467         2839251 :                     zpad = '0';
 1061 alvherre                  468 ECB             :                 /* FALL THRU */
 6334 tgl                       469                 :             case '1':
                                470                 :             case '2':
                                471                 :             case '3':
 6334 tgl                       472 EUB             :             case '4':
                                473                 :             case '5':
 6334 tgl                       474 ECB             :             case '6':
                                475                 :             case '7':
                                476                 :             case '8':
                                477                 :             case '9':
 6334 tgl                       478 CBC     5713876 :                 accum = accum * 10 + (ch - '0');
                                479         5713876 :                 goto nextch2;
 6334 tgl                       480 GIC       72745 :             case '.':
                                481           72745 :                 if (have_star)
 6334 tgl                       482 UIC           0 :                     have_star = false;
                                483                 :                 else
 6334 tgl                       484 GIC       72745 :                     fieldwidth = accum;
                                485           72745 :                 pointflag = 1;
 6334 tgl                       486 GBC       72745 :                 accum = 0;
 6334 tgl                       487 GIC       72745 :                 goto nextch2;
                                488          642957 :             case '*':
                                489          642957 :                 if (have_dollar)
                                490                 :                 {
 1649 tgl                       491 ECB             :                     /*
                                492                 :                      * We'll process value after reading n$.  Note it's OK to
                                493                 :                      * assume have_dollar is set correctly, because in a valid
                                494                 :                      * format string the initial % must have had n$ if * does.
                                495                 :                      */
 6334 tgl                       496 LBC           0 :                     afterstar = true;
                                497                 :                 }
 6334 tgl                       498 EUB             :                 else
                                499                 :                 {
                                500                 :                     /* fetch and process value now */
 6031 bruce                     501 GIC      642957 :                     int         starval = va_arg(args, int);
                                502                 : 
 6334 tgl                       503          642957 :                     if (pointflag)
 6334 tgl                       504 ECB             :                     {
 6334 tgl                       505 CBC       28299 :                         precision = starval;
 6334 tgl                       506 GIC       28299 :                         if (precision < 0)
 5500 tgl                       507 ECB             :                         {
 6334 tgl                       508 LBC           0 :                             precision = 0;
 5500 tgl                       509 UIC           0 :                             pointflag = 0;
                                510                 :                         }
                                511                 :                     }
 6334 tgl                       512 ECB             :                     else
                                513                 :                     {
 6334 tgl                       514 CBC      614658 :                         fieldwidth = starval;
 6334 tgl                       515 GBC      614658 :                         if (fieldwidth < 0)
                                516                 :                         {
                                517            2823 :                             leftjust = 1;
 6334 tgl                       518 GIC        2823 :                             fieldwidth = -fieldwidth;
                                519                 :                         }
 6334 tgl                       520 EUB             :                     }
 6334 tgl                       521 ECB             :                 }
 6334 tgl                       522 GBC      642957 :                 have_star = true;
 6334 tgl                       523 GIC      642957 :                 accum = 0;
 6334 tgl                       524 GBC      642957 :                 goto nextch2;
 6334 tgl                       525 UIC           0 :             case '$':
                                526                 :                 /* First dollar sign? */
 1649 tgl                       527 UBC           0 :                 if (!have_dollar)
                                528                 :                 {
 1649 tgl                       529 EUB             :                     /* Yup, so examine all conversion specs in format */
 1649 tgl                       530 UIC           0 :                     if (!find_arguments(first_pct, args, argvalues))
 1649 tgl                       531 GBC           9 :                         goto bad_format;
 1649 tgl                       532 UBC           0 :                     have_dollar = true;
                                533                 :                 }
 6334                           534               0 :                 if (afterstar)
 6334 tgl                       535 EUB             :                 {
                                536                 :                     /* fetch and process star value */
 6031 bruce                     537 UIC           0 :                     int         starval = argvalues[accum].i;
                                538                 : 
 6334 tgl                       539               0 :                     if (pointflag)
 6334 tgl                       540 EUB             :                     {
 6334 tgl                       541 UBC           0 :                         precision = starval;
 6334 tgl                       542 UIC           0 :                         if (precision < 0)
 5500 tgl                       543 EUB             :                         {
 6334 tgl                       544 UBC           0 :                             precision = 0;
 5500 tgl                       545 UIC           0 :                             pointflag = 0;
                                546                 :                         }
 6334 tgl                       547 EUB             :                     }
                                548                 :                     else
                                549                 :                     {
 6334 tgl                       550 UBC           0 :                         fieldwidth = starval;
                                551               0 :                         if (fieldwidth < 0)
 6612 bruce                     552 EUB             :                         {
 6334 tgl                       553 LBC           0 :                             leftjust = 1;
                                554               0 :                             fieldwidth = -fieldwidth;
 6612 bruce                     555 ECB             :                         }
                                556                 :                     }
 6334 tgl                       557 LBC           0 :                     afterstar = false;
 8950 bruce                     558 ECB             :                 }
 6334 tgl                       559                 :                 else
 6334 tgl                       560 UIC           0 :                     fmtpos = accum;
                                561               0 :                 accum = 0;
 6334 tgl                       562 LBC           0 :                 goto nextch2;
 6334 tgl                       563 GIC     2611698 :             case 'l':
                                564         2611698 :                 if (longflag)
                                565           22372 :                     longlongflag = 1;
                                566                 :                 else
                                567         2589326 :                     longflag = 1;
                                568         2611698 :                 goto nextch2;
 3363                           569          132656 :             case 'z':
                                570                 : #if SIZEOF_SIZE_T == 8
 3363 tgl                       571 ECB             : #ifdef HAVE_LONG_INT_64
 3363 tgl                       572 CBC      132656 :                 longflag = 1;
                                573                 : #elif defined(HAVE_LONG_LONG_INT_64)
                                574                 :                 longlongflag = 1;
 3363 tgl                       575 ECB             : #else
                                576                 : #error "Don't know how to print 64bit integers"
                                577                 : #endif
                                578                 : #else
                                579                 :                 /* assume size_t is same size as int */
                                580                 : #endif
 3363 tgl                       581 GBC      132656 :                 goto nextch2;
 6334 tgl                       582 GIC          22 :             case 'h':
 6334 tgl                       583 ECB             :             case '\'':
                                584                 :                 /* ignore these */
 6334 tgl                       585 CBC          22 :                 goto nextch2;
 6334 tgl                       586 GIC    36697384 :             case 'd':
 6334 tgl                       587 EUB             :             case 'i':
 6334 tgl                       588 GBC    36697384 :                 if (!have_star)
 6334 tgl                       589 EUB             :                 {
 6334 tgl                       590 GBC    36677831 :                     if (pointflag)
 6334 tgl                       591 UIC           0 :                         precision = accum;
 6334 tgl                       592 EUB             :                     else
 6334 tgl                       593 GIC    36677831 :                         fieldwidth = accum;
                                594                 :                 }
                                595        36697384 :                 if (have_dollar)
 6334 tgl                       596 ECB             :                 {
 6334 tgl                       597 LBC           0 :                     if (longlongflag)
                                598               0 :                         numvalue = argvalues[fmtpos].ll;
                                599               0 :                     else if (longflag)
 6334 tgl                       600 UIC           0 :                         numvalue = argvalues[fmtpos].l;
 6334 tgl                       601 ECB             :                     else
 6334 tgl                       602 UIC           0 :                         numvalue = argvalues[fmtpos].i;
 6334 tgl                       603 ECB             :                 }
                                604                 :                 else
                                605                 :                 {
 6334 tgl                       606 CBC    36697384 :                     if (longlongflag)
 1649 tgl                       607 GIC       22181 :                         numvalue = va_arg(args, long long);
 6334                           608        36675203 :                     else if (longflag)
                                609         2250759 :                         numvalue = va_arg(args, long);
 6334 tgl                       610 ECB             :                     else
 6334 tgl                       611 GIC    34424444 :                         numvalue = va_arg(args, int);
 6334 tgl                       612 ECB             :                 }
 6334 tgl                       613 GBC    36697384 :                 fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
                                614                 :                        precision, pointflag, target);
 8950 bruce                     615 CBC    36697400 :                 break;
 6334 tgl                       616 GIC    29806409 :             case 'o':
 6334 tgl                       617 ECB             :             case 'u':
                                618                 :             case 'x':
 6334 tgl                       619 EUB             :             case 'X':
 6334 tgl                       620 GBC    29806409 :                 if (!have_star)
 6334 tgl                       621 EUB             :                 {
 6334 tgl                       622 GBC    29806409 :                     if (pointflag)
 6334 tgl                       623 UIC           0 :                         precision = accum;
 6334 tgl                       624 EUB             :                     else
 6334 tgl                       625 GIC    29806409 :                         fieldwidth = accum;
                                626                 :                 }
                                627        29806409 :                 if (have_dollar)
 6598 bruce                     628 ECB             :                 {
 6334 tgl                       629 LBC           0 :                     if (longlongflag)
 1649                           630               0 :                         numvalue = (unsigned long long) argvalues[fmtpos].ll;
 6334                           631               0 :                     else if (longflag)
 6334 tgl                       632 UIC           0 :                         numvalue = (unsigned long) argvalues[fmtpos].l;
 6598 bruce                     633 ECB             :                     else
 6334 tgl                       634 UIC           0 :                         numvalue = (unsigned int) argvalues[fmtpos].i;
 6598 bruce                     635 ECB             :                 }
                                636                 :                 else
 6334 tgl                       637                 :                 {
 6334 tgl                       638 CBC    29806409 :                     if (longlongflag)
 1649                           639             191 :                         numvalue = (unsigned long long) va_arg(args, long long);
 6334 tgl                       640 GIC    29806218 :                     else if (longflag)
 6334 tgl                       641 CBC      448851 :                         numvalue = (unsigned long) va_arg(args, long);
 6334 tgl                       642 EUB             :                     else
 6334 tgl                       643 GIC    29357367 :                         numvalue = (unsigned int) va_arg(args, int);
 6334 tgl                       644 ECB             :                 }
 6334 tgl                       645 GIC    29806409 :                 fmtint(numvalue, ch, forcesign, leftjust, fieldwidth, zpad,
 6334 tgl                       646 ECB             :                        precision, pointflag, target);
 6598 bruce                     647 GBC    29806409 :                 break;
 6334 tgl                       648 GIC       19436 :             case 'c':
 6334 tgl                       649 CBC       19436 :                 if (!have_star)
 6598 bruce                     650 ECB             :                 {
 6334 tgl                       651 CBC       19415 :                     if (pointflag)
 6334 tgl                       652 LBC           0 :                         precision = accum;
 6598 bruce                     653 ECB             :                     else
 6334 tgl                       654 GIC       19415 :                         fieldwidth = accum;
 6598 bruce                     655 ECB             :                 }
 6334 tgl                       656 GBC       19436 :                 if (have_dollar)
 6334 tgl                       657 UIC           0 :                     cvalue = (unsigned char) argvalues[fmtpos].i;
 6598 bruce                     658 ECB             :                 else
 6334 tgl                       659 GIC       19436 :                     cvalue = (unsigned char) va_arg(args, int);
 6334 tgl                       660 CBC       19436 :                 fmtchar(cvalue, leftjust, fieldwidth, target);
 6598 bruce                     661 GBC       19436 :                 break;
 6334 tgl                       662 GIC      606533 :             case 's':
 6334 tgl                       663 CBC      606533 :                 if (!have_star)
                                664                 :                 {
                                665            2500 :                     if (pointflag)
 6334 tgl                       666 UBC           0 :                         precision = accum;
 6334 tgl                       667 ECB             :                     else
 6334 tgl                       668 GIC        2500 :                         fieldwidth = accum;
 6334 tgl                       669 ECB             :                 }
 6334 tgl                       670 CBC      606533 :                 if (have_dollar)
 6334 tgl                       671 UIC           0 :                     strvalue = argvalues[fmtpos].cptr;
 6334 tgl                       672 ECB             :                 else
 6334 tgl                       673 GBC      606533 :                     strvalue = va_arg(args, char *);
                                674                 :                 /* If string is NULL, silently substitute "(null)" */
  624 tgl                       675 CBC      606533 :                 if (strvalue == NULL)
  624 tgl                       676 LBC           0 :                     strvalue = "(null)";
 6334 tgl                       677 CBC      606533 :                 fmtstr(strvalue, leftjust, fieldwidth, precision, pointflag,
 6334 tgl                       678 ECB             :                        target);
 6598 bruce                     679 GIC      606533 :                 break;
 6334 tgl                       680              65 :             case 'p':
                                681                 :                 /* fieldwidth/leftjust are ignored ... */
                                682              65 :                 if (have_dollar)
 6334 tgl                       683 LBC           0 :                     strvalue = argvalues[fmtpos].cptr;
                                684                 :                 else
 6334 tgl                       685 CBC          65 :                     strvalue = va_arg(args, char *);
  624                           686              65 :                 fmtptr((const void *) strvalue, target);
 6598 bruce                     687 GIC          65 :                 break;
 6334 tgl                       688 CBC      194581 :             case 'e':
                                689                 :             case 'E':
 6334 tgl                       690 ECB             :             case 'f':
 6334 tgl                       691 EUB             :             case 'g':
                                692                 :             case 'G':
 6334 tgl                       693 CBC      194581 :                 if (!have_star)
 6597 bruce                     694 ECB             :                 {
 6334 tgl                       695 GIC      175232 :                     if (pointflag)
                                696           44446 :                         precision = accum;
                                697                 :                     else
 6334 tgl                       698 CBC      130786 :                         fieldwidth = accum;
 6597 bruce                     699 ECB             :                 }
 6334 tgl                       700 GIC      194581 :                 if (have_dollar)
 6334 tgl                       701 UIC           0 :                     fvalue = argvalues[fmtpos].d;
 6334 tgl                       702 ECB             :                 else
 6334 tgl                       703 GIC      194581 :                     fvalue = va_arg(args, double);
                                704          194581 :                 fmtfloat(fvalue, ch, forcesign, leftjust,
 6334 tgl                       705 ECB             :                          fieldwidth, zpad,
                                706                 :                          precision, pointflag,
                                707                 :                          target);
 6598 bruce                     708 CBC      194581 :                 break;
 1656 tgl                       709             133 :             case 'm':
 1656 tgl                       710 ECB             :                 {
 1656 tgl                       711 EUB             :                     char        errbuf[PG_STRERROR_R_BUFLEN];
 1656 tgl                       712 GIC         133 :                     const char *errm = strerror_r(save_errno,
                                713                 :                                                   errbuf, sizeof(errbuf));
                                714                 : 
                                715             133 :                     dostr(errm, strlen(errm), target);
                                716                 :                 }
 1656 tgl                       717 GBC         133 :                 break;
 6334 tgl                       718 GIC        1334 :             case '%':
                                719            1334 :                 dopr_outch('%', target);
 6598 bruce                     720            1334 :                 break;
 1585 tgl                       721 LBC           0 :             default:
 1585 tgl                       722 EUB             : 
                                723                 :                 /*
                                724                 :                  * Anything else --- in particular, '\0' indicating end of
 1585 tgl                       725 ECB             :                  * format string --- is bogus.
                                726                 :                  */
 1585 tgl                       727 LBC           0 :                 goto bad_format;
 6598 bruce                     728 ECB             :         }
 1649 tgl                       729                 : 
                                730                 :         /* Check for failure after each conversion spec */
 1649 tgl                       731 GIC    67325875 :         if (target->failed)
 1649 tgl                       732 UIC           0 :             break;
                                733                 :     }
                                734                 : 
 2883 noah                      735 GIC    74391832 :     return;
                                736                 : 
                                737               9 : bad_format:
                                738               9 :     errno = EINVAL;
 2883 noah                      739 GBC           9 :     target->failed = true;
                                740                 : }
                                741                 : 
                                742                 : /*
                                743                 :  * find_arguments(): sort out the arguments for a format spec with %n$
                                744                 :  *
                                745                 :  * If format is valid, return true and fill argvalues[i] with the value
                                746                 :  * for the conversion spec that has %i$ or *i$.  Else return false.
                                747                 :  */
                                748                 : static bool
 1649 tgl                       749 UBC           0 : find_arguments(const char *format, va_list args,
 1649 tgl                       750 EUB             :                PrintfArgValue *argvalues)
                                751                 : {
                                752                 :     int         ch;
                                753                 :     bool        afterstar;
                                754                 :     int         accum;
                                755                 :     int         longlongflag;
                                756                 :     int         longflag;
                                757                 :     int         fmtpos;
                                758                 :     int         i;
  267 peter                     759 UNC           0 :     int         last_dollar = 0;    /* Init to "no dollar arguments known" */
                                760               0 :     PrintfArgType argtypes[PG_NL_ARGMAX + 1] = {0};
                                761                 : 
 1649 tgl                       762 EUB             :     /*
                                763                 :      * This loop must accept the same format strings as the one in dopr().
                                764                 :      * However, we don't need to analyze them to the same level of detail.
                                765                 :      *
                                766                 :      * Since we're only called if there's a dollar-type spec somewhere, we can
                                767                 :      * fail immediately if we find a non-dollar spec.  Per the C99 standard,
                                768                 :      * all argument references in the format string must be one or the other.
                                769                 :      */
 1649 tgl                       770 UBC           0 :     while (*format != '\0')
 1649 tgl                       771 EUB             :     {
                                772                 :         /* Locate next conversion specifier */
 1649 tgl                       773 UBC           0 :         if (*format != '%')
 1649 tgl                       774 EUB             :         {
                                775                 :             /* Unlike dopr, we can just quit if there's no more specifiers */
 1649 tgl                       776 UBC           0 :             format = strchr(format + 1, '%');
 1649 tgl                       777 UIC           0 :             if (format == NULL)
 1649 tgl                       778 UBC           0 :                 break;
 1649 tgl                       779 EUB             :         }
                                780                 : 
                                781                 :         /* Process conversion spec starting at *format */
 1649 tgl                       782 UIC           0 :         format++;
                                783               0 :         longflag = longlongflag = 0;
                                784               0 :         fmtpos = accum = 0;
                                785               0 :         afterstar = false;
                                786               0 : nextch1:
                                787               0 :         ch = *format++;
                                788               0 :         switch (ch)
 1649 tgl                       789 EUB             :         {
 1649 tgl                       790 UBC           0 :             case '-':
 1649 tgl                       791 EUB             :             case '+':
 1649 tgl                       792 UBC           0 :                 goto nextch1;
                                793               0 :             case '0':
 1649 tgl                       794 EUB             :             case '1':
                                795                 :             case '2':
                                796                 :             case '3':
                                797                 :             case '4':
                                798                 :             case '5':
                                799                 :             case '6':
                                800                 :             case '7':
                                801                 :             case '8':
                                802                 :             case '9':
 1649 tgl                       803 UBC           0 :                 accum = accum * 10 + (ch - '0');
 1649 tgl                       804 UIC           0 :                 goto nextch1;
 1649 tgl                       805 UBC           0 :             case '.':
                                806               0 :                 accum = 0;
                                807               0 :                 goto nextch1;
                                808               0 :             case '*':
                                809               0 :                 if (afterstar)
                                810               0 :                     return false;   /* previous star missing dollar */
 1649 tgl                       811 UIC           0 :                 afterstar = true;
                                812               0 :                 accum = 0;
 1649 tgl                       813 UBC           0 :                 goto nextch1;
                                814               0 :             case '$':
                                815               0 :                 if (accum <= 0 || accum > PG_NL_ARGMAX)
                                816               0 :                     return false;
                                817               0 :                 if (afterstar)
 1649 tgl                       818 EUB             :                 {
 1649 tgl                       819 UIC           0 :                     if (argtypes[accum] &&
 1649 tgl                       820 UBC           0 :                         argtypes[accum] != ATYPE_INT)
                                821               0 :                         return false;
                                822               0 :                     argtypes[accum] = ATYPE_INT;
 1649 tgl                       823 UIC           0 :                     last_dollar = Max(last_dollar, accum);
                                824               0 :                     afterstar = false;
 1649 tgl                       825 EUB             :                 }
                                826                 :                 else
 1649 tgl                       827 UIC           0 :                     fmtpos = accum;
                                828               0 :                 accum = 0;
                                829               0 :                 goto nextch1;
                                830               0 :             case 'l':
                                831               0 :                 if (longflag)
                                832               0 :                     longlongflag = 1;
                                833                 :                 else
 1649 tgl                       834 UBC           0 :                     longflag = 1;
                                835               0 :                 goto nextch1;
 1649 tgl                       836 UIC           0 :             case 'z':
                                837                 : #if SIZEOF_SIZE_T == 8
 1649 tgl                       838 EUB             : #ifdef HAVE_LONG_INT_64
 1649 tgl                       839 UBC           0 :                 longflag = 1;
                                840                 : #elif defined(HAVE_LONG_LONG_INT_64)
                                841                 :                 longlongflag = 1;
                                842                 : #else
                                843                 : #error "Don't know how to print 64bit integers"
                                844                 : #endif
 1649 tgl                       845 EUB             : #else
                                846                 :                 /* assume size_t is same size as int */
                                847                 : #endif
 1649 tgl                       848 UIC           0 :                 goto nextch1;
 1649 tgl                       849 UBC           0 :             case 'h':
 1649 tgl                       850 EUB             :             case '\'':
                                851                 :                 /* ignore these */
 1649 tgl                       852 UBC           0 :                 goto nextch1;
 1649 tgl                       853 UIC           0 :             case 'd':
 1649 tgl                       854 EUB             :             case 'i':
                                855                 :             case 'o':
                                856                 :             case 'u':
                                857                 :             case 'x':
                                858                 :             case 'X':
 1649 tgl                       859 UBC           0 :                 if (fmtpos)
                                860                 :                 {
                                861                 :                     PrintfArgType atype;
 1649 tgl                       862 EUB             : 
 1649 tgl                       863 UBC           0 :                     if (longlongflag)
                                864               0 :                         atype = ATYPE_LONGLONG;
                                865               0 :                     else if (longflag)
 1649 tgl                       866 UIC           0 :                         atype = ATYPE_LONG;
 1649 tgl                       867 EUB             :                     else
 1649 tgl                       868 UBC           0 :                         atype = ATYPE_INT;
                                869               0 :                     if (argtypes[fmtpos] &&
                                870               0 :                         argtypes[fmtpos] != atype)
                                871               0 :                         return false;
 1649 tgl                       872 UIC           0 :                     argtypes[fmtpos] = atype;
                                873               0 :                     last_dollar = Max(last_dollar, fmtpos);
 1649 tgl                       874 EUB             :                 }
                                875                 :                 else
 1649 tgl                       876 UBC           0 :                     return false;   /* non-dollar conversion spec */
 1649 tgl                       877 UIC           0 :                 break;
 1649 tgl                       878 UBC           0 :             case 'c':
 1649 tgl                       879 UIC           0 :                 if (fmtpos)
 1649 tgl                       880 EUB             :                 {
 1649 tgl                       881 UBC           0 :                     if (argtypes[fmtpos] &&
                                882               0 :                         argtypes[fmtpos] != ATYPE_INT)
                                883               0 :                         return false;
                                884               0 :                     argtypes[fmtpos] = ATYPE_INT;
 1649 tgl                       885 UIC           0 :                     last_dollar = Max(last_dollar, fmtpos);
                                886                 :                 }
 1649 tgl                       887 EUB             :                 else
 1649 tgl                       888 UBC           0 :                     return false;   /* non-dollar conversion spec */
                                889               0 :                 break;
 1649 tgl                       890 UIC           0 :             case 's':
                                891                 :             case 'p':
                                892               0 :                 if (fmtpos)
                                893                 :                 {
 1649 tgl                       894 UBC           0 :                     if (argtypes[fmtpos] &&
 1649 tgl                       895 UIC           0 :                         argtypes[fmtpos] != ATYPE_CHARPTR)
 1649 tgl                       896 UBC           0 :                         return false;
                                897               0 :                     argtypes[fmtpos] = ATYPE_CHARPTR;
                                898               0 :                     last_dollar = Max(last_dollar, fmtpos);
 1649 tgl                       899 EUB             :                 }
                                900                 :                 else
 1649 tgl                       901 UIC           0 :                     return false;   /* non-dollar conversion spec */
                                902               0 :                 break;
 1649 tgl                       903 UBC           0 :             case 'e':
 1649 tgl                       904 EUB             :             case 'E':
                                905                 :             case 'f':
                                906                 :             case 'g':
                                907                 :             case 'G':
 1649 tgl                       908 UBC           0 :                 if (fmtpos)
 1649 tgl                       909 EUB             :                 {
 1649 tgl                       910 UIC           0 :                     if (argtypes[fmtpos] &&
                                911               0 :                         argtypes[fmtpos] != ATYPE_DOUBLE)
                                912               0 :                         return false;
                                913               0 :                     argtypes[fmtpos] = ATYPE_DOUBLE;
                                914               0 :                     last_dollar = Max(last_dollar, fmtpos);
                                915                 :                 }
 1649 tgl                       916 EUB             :                 else
 1649 tgl                       917 UBC           0 :                     return false;   /* non-dollar conversion spec */
 1649 tgl                       918 UIC           0 :                 break;
                                919               0 :             case 'm':
                                920                 :             case '%':
                                921               0 :                 break;
 1585                           922               0 :             default:
                                923               0 :                 return false;   /* bogus format string */
                                924                 :         }
 1649 tgl                       925 EUB             : 
                                926                 :         /*
                                927                 :          * If we finish the spec with afterstar still set, there's a
                                928                 :          * non-dollar star in there.
                                929                 :          */
 1649 tgl                       930 UBC           0 :         if (afterstar)
                                931               0 :             return false;       /* non-dollar conversion spec */
 1649 tgl                       932 EUB             :     }
                                933                 : 
                                934                 :     /*
                                935                 :      * Format appears valid so far, so collect the arguments in physical
                                936                 :      * order.  (Since we rejected any non-dollar specs that would have
                                937                 :      * collected arguments, we know that dopr() hasn't collected any yet.)
                                938                 :      */
 1649 tgl                       939 UBC           0 :     for (i = 1; i <= last_dollar; i++)
 1649 tgl                       940 EUB             :     {
 1649 tgl                       941 UBC           0 :         switch (argtypes[i])
 1649 tgl                       942 EUB             :         {
 1649 tgl                       943 UBC           0 :             case ATYPE_NONE:
                                944               0 :                 return false;
                                945               0 :             case ATYPE_INT:
 1649 tgl                       946 UIC           0 :                 argvalues[i].i = va_arg(args, int);
                                947               0 :                 break;
                                948               0 :             case ATYPE_LONG:
 1649 tgl                       949 UBC           0 :                 argvalues[i].l = va_arg(args, long);
 1649 tgl                       950 UIC           0 :                 break;
                                951               0 :             case ATYPE_LONGLONG:
                                952               0 :                 argvalues[i].ll = va_arg(args, long long);
 1649 tgl                       953 LBC           0 :                 break;
 1649 tgl                       954 UIC           0 :             case ATYPE_DOUBLE:
                                955               0 :                 argvalues[i].d = va_arg(args, double);
                                956               0 :                 break;
                                957               0 :             case ATYPE_CHARPTR:
                                958               0 :                 argvalues[i].cptr = va_arg(args, char *);
                                959               0 :                 break;
                                960                 :         }
                                961                 :     }
                                962                 : 
 1649 tgl                       963 LBC           0 :     return true;
 1649 tgl                       964 ECB             : }
                                965                 : 
 8983 scrappy                   966                 : static void
 1649 tgl                       967 GIC      606533 : fmtstr(const char *value, int leftjust, int minlen, int maxwidth,
 4382 bruce                     968 ECB             :        int pointflag, PrintfTarget *target)
                                969                 : {
 8950                           970                 :     int         padlen,
                                971                 :                 vallen;         /* amount to pad */
 8983 scrappy                   972                 : 
 6334 tgl                       973                 :     /*
                                974                 :      * If a maxwidth (precision) is specified, we must not fetch more bytes
                                975                 :      * than that.
                                976                 :      */
 6334 tgl                       977 GIC      606533 :     if (pointflag)
 2007 andres                    978 CBC        8950 :         vallen = strnlen(value, maxwidth);
 6334 tgl                       979 ECB             :     else
 6334 tgl                       980 GIC      597583 :         vallen = strlen(value);
                                981                 : 
 1649 tgl                       982 CBC      606533 :     padlen = compute_padlen(minlen, vallen, leftjust);
                                983                 : 
 1649 tgl                       984 GIC      606533 :     if (padlen > 0)
                                985                 :     {
                                986          256081 :         dopr_outchmulti(' ', padlen, target);
                                987          256081 :         padlen = 0;
 8950 bruce                     988 ECB             :     }
 6597                           989                 : 
 6334 tgl                       990 GBC      606533 :     dostr(value, vallen, target);
                                991                 : 
 1649 tgl                       992 CBC      606533 :     trailing_pad(padlen, target);
 8983 scrappy                   993          606533 : }
                                994                 : 
                                995                 : static void
  624 tgl                       996              65 : fmtptr(const void *value, PrintfTarget *target)
                                997                 : {
                                998                 :     int         vallen;
                                999                 :     char        convert[64];
                               1000                 : 
                               1001                 :     /* we rely on regular C library's snprintf to do the basic conversion */
  175 tgl                      1002 GIC          65 :     vallen = snprintf(convert, sizeof(convert), "%p", value);
 2883 noah                     1003 CBC          65 :     if (vallen < 0)
 2883 noah                     1004 LBC           0 :         target->failed = true;
                               1005                 :     else
 2883 noah                     1006 CBC          65 :         dostr(convert, vallen, target);
 6334 tgl                      1007 GIC          65 : }
                               1008                 : 
                               1009                 : static void
 1649 tgl                      1010 CBC    66503795 : fmtint(long long value, char type, int forcesign, int leftjust,
                               1011                 :        int minlen, int zpad, int precision, int pointflag,
 4382 bruce                    1012 ECB             :        PrintfTarget *target)
                               1013                 : {
 1649 andres                   1014                 :     unsigned long long uvalue;
  528 tgl                      1015                 :     int         base;
 6334                          1016                 :     int         dosign;
 6334 tgl                      1017 CBC    66503795 :     const char *cvt = "0123456789abcdef";
 8950 bruce                    1018        66503795 :     int         signvalue = 0;
 8828 tgl                      1019 ECB             :     char        convert[64];
 6597 bruce                    1020 CBC    66503795 :     int         vallen = 0;
 1649 tgl                      1021 ECB             :     int         padlen;         /* amount to pad */
 6334                          1022                 :     int         zeropad;        /* extra leading zeroes */
 8950 bruce                    1023                 : 
 6334 tgl                      1024 CBC    66503795 :     switch (type)
 6334 tgl                      1025 ECB             :     {
 6334 tgl                      1026 CBC    36697388 :         case 'd':
 6334 tgl                      1027 ECB             :         case 'i':
 6334 tgl                      1028 CBC    36697388 :             base = 10;
                               1029        36697388 :             dosign = 1;
                               1030        36697388 :             break;
                               1031            3562 :         case 'o':
                               1032            3562 :             base = 8;
                               1033            3562 :             dosign = 0;
 6334 tgl                      1034 GBC        3562 :             break;
                               1035        29543853 :         case 'u':
 6334 tgl                      1036 GIC    29543853 :             base = 10;
                               1037        29543853 :             dosign = 0;
                               1038        29543853 :             break;
                               1039           27655 :         case 'x':
                               1040           27655 :             base = 16;
                               1041           27655 :             dosign = 0;
                               1042           27655 :             break;
                               1043          231339 :         case 'X':
 6334 tgl                      1044 CBC      231339 :             cvt = "0123456789ABCDEF";
                               1045          231339 :             base = 16;
 6334 tgl                      1046 GIC      231339 :             dosign = 0;
 6334 tgl                      1047 CBC      231339 :             break;
 6334 tgl                      1048 UIC           0 :         default:
                               1049               0 :             return;             /* keep compiler quiet */
                               1050                 :     }
                               1051                 : 
                               1052                 :     /* disable MSVC warning about applying unary minus to an unsigned value */
                               1053                 : #ifdef _MSC_VER
                               1054                 : #pragma warning(push)
                               1055                 : #pragma warning(disable: 4146)
 1611 andrew                   1056 ECB             : #endif
 6334 tgl                      1057 EUB             :     /* Handle +/- */
 6597 bruce                    1058 GIC    66503797 :     if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
 1649 andres                   1059         6664234 :         uvalue = -(unsigned long long) value;
                               1060                 :     else
                               1061        59839564 :         uvalue = (unsigned long long) value;
                               1062                 : #ifdef _MSC_VER
                               1063                 : #pragma warning(pop)
                               1064                 : #endif
                               1065                 : 
 6334 tgl                      1066 ECB             :     /*
                               1067                 :      * SUS: the result of converting 0 with an explicit precision of 0 is no
                               1068                 :      * characters
                               1069                 :      */
 6334 tgl                      1070 CBC    66503798 :     if (value == 0 && pointflag && precision == 0)
 6334 tgl                      1071 LBC           0 :         vallen = 0;
 6334 tgl                      1072 ECB             :     else
                               1073                 :     {
  528                          1074                 :         /*
                               1075                 :          * Convert integer to string.  We special-case each of the possible
                               1076                 :          * base values so as to avoid general-purpose divisions.  On most
                               1077                 :          * machines, division by a fixed constant can be done much more
                               1078                 :          * cheaply than a general divide.
                               1079                 :          */
  528 tgl                      1080 CBC    66503798 :         if (base == 10)
                               1081                 :         {
                               1082                 :             do
                               1083                 :             {
  528 tgl                      1084 GIC   131512845 :                 convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 10];
                               1085       131512845 :                 uvalue = uvalue / 10;
  528 tgl                      1086 CBC   131512845 :             } while (uvalue);
  528 tgl                      1087 ECB             :         }
  528 tgl                      1088 CBC      262556 :         else if (base == 16)
                               1089                 :         {
                               1090                 :             do
                               1091                 :             {
                               1092          710389 :                 convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 16];
  528 tgl                      1093 GIC      710389 :                 uvalue = uvalue / 16;
  528 tgl                      1094 CBC      710389 :             } while (uvalue);
                               1095                 :         }
  528 tgl                      1096 ECB             :         else                    /* base == 8 */
                               1097                 :         {
                               1098                 :             do
  528 tgl                      1099 EUB             :             {
  528 tgl                      1100 GIC       10686 :                 convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 8];
  528 tgl                      1101 CBC       10686 :                 uvalue = uvalue / 8;
  528 tgl                      1102 GIC       10686 :             } while (uvalue);
  528 tgl                      1103 ECB             :         }
                               1104                 :     }
                               1105                 : 
 6334 tgl                      1106 GIC    66503798 :     zeropad = Max(0, precision - vallen);
 8828 tgl                      1107 ECB             : 
 1649 tgl                      1108 GIC    66503798 :     padlen = compute_padlen(minlen, vallen + zeropad, leftjust);
                               1109                 : 
                               1110        66503800 :     leading_pad(zpad, signvalue, &padlen, target);
 6597 bruce                    1111 ECB             : 
 1649 tgl                      1112 GIC    66503800 :     if (zeropad > 0)
 1649 tgl                      1113 LBC           0 :         dopr_outchmulti('0', zeropad, target);
                               1114                 : 
 1649 tgl                      1115 CBC    66503800 :     dostr(convert + sizeof(convert) - vallen, vallen, target);
 6597 bruce                    1116 ECB             : 
 1649 tgl                      1117 GIC    66503803 :     trailing_pad(padlen, target);
                               1118                 : }
 6334 tgl                      1119 ECB             : 
                               1120                 : static void
 4382 bruce                    1121 CBC       19436 : fmtchar(int value, int leftjust, int minlen, PrintfTarget *target)
 6334 tgl                      1122 ECB             : {
                               1123                 :     int         padlen;         /* amount to pad */
                               1124                 : 
 1649 tgl                      1125 CBC       19436 :     padlen = compute_padlen(minlen, 1, leftjust);
                               1126                 : 
 1649 tgl                      1127 GIC       19436 :     if (padlen > 0)
                               1128                 :     {
 1649 tgl                      1129 CBC          21 :         dopr_outchmulti(' ', padlen, target);
 1649 tgl                      1130 GIC          21 :         padlen = 0;
                               1131                 :     }
                               1132                 : 
 6334                          1133           19436 :     dopr_outch(value, target);
 6334 tgl                      1134 ECB             : 
 1649 tgl                      1135 GIC       19436 :     trailing_pad(padlen, target);
 8983 scrappy                  1136           19436 : }
                               1137                 : 
                               1138                 : static void
 6597 bruce                    1139          194581 : fmtfloat(double value, char type, int forcesign, int leftjust,
                               1140                 :          int minlen, int zpad, int precision, int pointflag,
                               1141                 :          PrintfTarget *target)
                               1142                 : {
 6598                          1143          194581 :     int         signvalue = 0;
                               1144                 :     int         prec;
                               1145                 :     int         vallen;
                               1146                 :     char        fmt[8];
                               1147                 :     char        convert[1024];
 2988                          1148          194581 :     int         zeropadlen = 0; /* amount to pad with zeroes */
                               1149                 :     int         padlen;         /* amount to pad with spaces */
                               1150                 : 
                               1151                 :     /*
                               1152                 :      * We rely on the regular C library's snprintf to do the basic conversion,
                               1153                 :      * then handle padding considerations here.
 2988 bruce                    1154 ECB             :      *
 2988 bruce                    1155 EUB             :      * The dynamic range of "double" is about 1E+-308 for IEEE math, and not
  175 tgl                      1156 ECB             :      * too wildly more than that with other hardware.  In "f" format, snprintf
                               1157                 :      * could therefore generate at most 308 characters to the left of the
 2988 bruce                    1158                 :      * decimal point; while we need to allow the precision to get as high as
                               1159                 :      * 308+17 to ensure that we don't truncate significant digits from very
                               1160                 :      * small values.  To handle both these extremes, we use a buffer of 1024
                               1161                 :      * bytes and limit requested precision to 350 digits; this should prevent
                               1162                 :      * buffer overrun even with non-IEEE math.  If the original precision
                               1163                 :      * request was more than 350, separately pad with zeroes.
                               1164                 :      *
                               1165                 :      * We handle infinities and NaNs specially to ensure platform-independent
                               1166                 :      * output.
                               1167                 :      */
 2988 bruce                    1168 GIC      194581 :     if (precision < 0)           /* cover possible overflow of "accum" */
 2988 bruce                    1169 UIC           0 :         precision = 0;
 2988 bruce                    1170 GIC      194581 :     prec = Min(precision, 350);
                               1171                 : 
 1644 tgl                      1172          194581 :     if (isnan(value))
                               1173                 :     {
 1644 tgl                      1174 CBC          67 :         strcpy(convert, "NaN");
                               1175              67 :         vallen = 3;
 1644 tgl                      1176 ECB             :         /* no zero padding, regardless of precision spec */
                               1177                 :     }
 1649                          1178                 :     else
                               1179                 :     {
 1644                          1180                 :         /*
                               1181                 :          * Handle sign (NaNs have no sign, so we don't do this in the case
                               1182                 :          * above).  "value < 0.0" will not be true for IEEE minus zero, so we
                               1183                 :          * detect that by looking for the case where value equals 0.0
                               1184                 :          * according to == but not according to memcmp.
                               1185                 :          */
                               1186                 :         static const double dzero = 0.0;
                               1187                 : 
 1644 tgl                      1188 CBC      384474 :         if (adjust_sign((value < 0.0 ||
                               1189          189960 :                          (value == 0.0 &&
                               1190           35006 :                           memcmp(&value, &dzero, sizeof(double)) != 0)),
 1644 tgl                      1191 ECB             :                         forcesign, &signvalue))
 1644 tgl                      1192 CBC        4554 :             value = -value;
 8828 tgl                      1193 ECB             : 
 1644 tgl                      1194 CBC      194514 :         if (isinf(value))
                               1195                 :         {
 1644 tgl                      1196 GIC          48 :             strcpy(convert, "Infinity");
                               1197              48 :             vallen = 8;
 1644 tgl                      1198 ECB             :             /* no zero padding, regardless of precision spec */
                               1199                 :         }
 1644 tgl                      1200 CBC      194466 :         else if (pointflag)
 1644 tgl                      1201 ECB             :         {
 1644 tgl                      1202 GIC       63680 :             zeropadlen = precision - prec;
 1644 tgl                      1203 CBC       63680 :             fmt[0] = '%';
 1644 tgl                      1204 GBC       63680 :             fmt[1] = '.';
 1644 tgl                      1205 GIC       63680 :             fmt[2] = '*';
                               1206           63680 :             fmt[3] = type;
                               1207           63680 :             fmt[4] = '\0';
  175                          1208           63680 :             vallen = snprintf(convert, sizeof(convert), fmt, prec, value);
                               1209                 :         }
                               1210                 :         else
                               1211                 :         {
 1644                          1212          130786 :             fmt[0] = '%';
                               1213          130786 :             fmt[1] = type;
                               1214          130786 :             fmt[2] = '\0';
  175                          1215          130786 :             vallen = snprintf(convert, sizeof(convert), fmt, value);
                               1216                 :         }
 1644                          1217          194514 :         if (vallen < 0)
 1644 tgl                      1218 UIC           0 :             goto fail;
                               1219                 : 
                               1220                 :         /*
                               1221                 :          * Windows, alone among our supported platforms, likes to emit
                               1222                 :          * three-digit exponent fields even when two digits would do.  Hack
 1640 tgl                      1223 ECB             :          * such results to look like the way everyone else does it.
                               1224                 :          */
                               1225                 : #ifdef WIN32
                               1226                 :         if (vallen >= 6 &&
                               1227                 :             convert[vallen - 5] == 'e' &&
                               1228                 :             convert[vallen - 3] == '0')
                               1229                 :         {
 1640 tgl                      1230 EUB             :             convert[vallen - 3] = convert[vallen - 2];
                               1231                 :             convert[vallen - 2] = convert[vallen - 1];
                               1232                 :             vallen--;
                               1233                 :         }
                               1234                 : #endif
                               1235                 :     }
                               1236                 : 
 1649 tgl                      1237 GBC      194581 :     padlen = compute_padlen(minlen, vallen + zeropadlen, leftjust);
 6597 bruce                    1238 EUB             : 
 1649 tgl                      1239 GBC      194581 :     leading_pad(zpad, signvalue, &padlen, target);
                               1240                 : 
 2988 bruce                    1241 GIC      194581 :     if (zeropadlen > 0)
                               1242                 :     {
                               1243                 :         /* If 'e' or 'E' format, inject zeroes before the exponent */
 2988 bruce                    1244 UBC           0 :         char       *epos = strrchr(convert, 'e');
 2988 bruce                    1245 EUB             : 
 2988 bruce                    1246 UIC           0 :         if (!epos)
                               1247               0 :             epos = strrchr(convert, 'E');
                               1248               0 :         if (epos)
                               1249                 :         {
                               1250                 :             /* pad before exponent */
 2988 bruce                    1251 LBC           0 :             dostr(convert, epos - convert, target);
 1232 tgl                      1252 UIC           0 :             dopr_outchmulti('0', zeropadlen, target);
 2988 bruce                    1253               0 :             dostr(epos, vallen - (epos - convert), target);
 2988 bruce                    1254 ECB             :         }
                               1255                 :         else
                               1256                 :         {
 2988 bruce                    1257 EUB             :             /* no exponent, pad after the digits */
 2988 bruce                    1258 UBC           0 :             dostr(convert, vallen, target);
 1232 tgl                      1259 UIC           0 :             dopr_outchmulti('0', zeropadlen, target);
                               1260                 :         }
                               1261                 :     }
                               1262                 :     else
                               1263                 :     {
                               1264                 :         /* no zero padding, just emit the number as-is */
 2988 bruce                    1265 GIC      194581 :         dostr(convert, vallen, target);
                               1266                 :     }
                               1267                 : 
 1649 tgl                      1268          194581 :     trailing_pad(padlen, target);
 2883 noah                     1269          194581 :     return;
                               1270                 : 
 2883 noah                     1271 LBC           0 : fail:
 2883 noah                     1272 UIC           0 :     target->failed = true;
                               1273                 : }
 8828 tgl                      1274 ECB             : 
                               1275                 : /*
                               1276                 :  * Nonstandard entry point to print a double value efficiently.
                               1277                 :  *
                               1278                 :  * This is approximately equivalent to strfromd(), but has an API more
                               1279                 :  * adapted to what float8out() wants.  The behavior is like snprintf()
 1644                          1280                 :  * with a format of "%.ng", where n is the specified precision.
                               1281                 :  * However, the target buffer must be nonempty (i.e. count > 0), and
                               1282                 :  * the precision is silently bounded to a sane range.
                               1283                 :  */
                               1284                 : int
 1644 tgl                      1285 CBC      114994 : pg_strfromd(char *str, size_t count, int precision, double value)
                               1286                 : {
                               1287                 :     PrintfTarget target;
 1644 tgl                      1288 GIC      114994 :     int         signvalue = 0;
                               1289                 :     int         vallen;
                               1290                 :     char        fmt[8];
                               1291                 :     char        convert[64];
 1644 tgl                      1292 ECB             : 
 1644 tgl                      1293 EUB             :     /* Set up the target like pg_snprintf, but require nonempty buffer */
 1644 tgl                      1294 CBC      114994 :     Assert(count > 0);
 1644 tgl                      1295 GBC      114994 :     target.bufstart = target.bufptr = str;
 1644 tgl                      1296 GIC      114994 :     target.bufend = str + count - 1;
                               1297          114994 :     target.stream = NULL;
                               1298          114994 :     target.nchars = 0;
                               1299          114994 :     target.failed = false;
                               1300                 : 
 1644 tgl                      1301 ECB             :     /*
                               1302                 :      * We bound precision to a reasonable range; the combination of this and
                               1303                 :      * the knowledge that we're using "g" format without padding allows the
                               1304                 :      * convert[] buffer to be reasonably small.
                               1305                 :      */
 1644 tgl                      1306 GIC      114994 :     if (precision < 1)
 1644 tgl                      1307 UIC           0 :         precision = 1;
 1644 tgl                      1308 GIC      114994 :     else if (precision > 32)
 1644 tgl                      1309 UIC           0 :         precision = 32;
 1644 tgl                      1310 ECB             : 
                               1311                 :     /*
                               1312                 :      * The rest is just an inlined version of the fmtfloat() logic above,
                               1313                 :      * simplified using the knowledge that no padding is wanted.
                               1314                 :      */
 1644 tgl                      1315 CBC      114994 :     if (isnan(value))
                               1316                 :     {
 1644 tgl                      1317 GIC        6042 :         strcpy(convert, "NaN");
 1644 tgl                      1318 CBC        6042 :         vallen = 3;
                               1319                 :     }
 1644 tgl                      1320 ECB             :     else
                               1321                 :     {
                               1322                 :         static const double dzero = 0.0;
                               1323                 : 
 1644 tgl                      1324 GIC      108952 :         if (value < 0.0 ||
 1644 tgl                      1325 CBC       92755 :             (value == 0.0 &&
                               1326           13433 :              memcmp(&value, &dzero, sizeof(double)) != 0))
 1644 tgl                      1327 ECB             :         {
 1644 tgl                      1328 CBC       16230 :             signvalue = '-';
                               1329           16230 :             value = -value;
 1644 tgl                      1330 ECB             :         }
                               1331                 : 
 1644 tgl                      1332 GIC      108952 :         if (isinf(value))
 1644 tgl                      1333 EUB             :         {
 1644 tgl                      1334 GBC        3546 :             strcpy(convert, "Infinity");
 1644 tgl                      1335 GIC        3546 :             vallen = 8;
                               1336                 :         }
                               1337                 :         else
                               1338                 :         {
                               1339          105406 :             fmt[0] = '%';
                               1340          105406 :             fmt[1] = '.';
                               1341          105406 :             fmt[2] = '*';
                               1342          105406 :             fmt[3] = 'g';
                               1343          105406 :             fmt[4] = '\0';
  175                          1344          105406 :             vallen = snprintf(convert, sizeof(convert), fmt, precision, value);
 1644                          1345          105406 :             if (vallen < 0)
                               1346                 :             {
 1644 tgl                      1347 UIC           0 :                 target.failed = true;
                               1348               0 :                 goto fail;
                               1349                 :             }
 1640 tgl                      1350 ECB             : 
                               1351                 : #ifdef WIN32
                               1352                 :             if (vallen >= 6 &&
                               1353                 :                 convert[vallen - 5] == 'e' &&
                               1354                 :                 convert[vallen - 3] == '0')
                               1355                 :             {
                               1356                 :                 convert[vallen - 3] = convert[vallen - 2];
                               1357                 :                 convert[vallen - 2] = convert[vallen - 1];
                               1358                 :                 vallen--;
                               1359                 :             }
                               1360                 : #endif
                               1361                 :         }
                               1362                 :     }
 1644                          1363                 : 
 1644 tgl                      1364 GIC      114994 :     if (signvalue)
                               1365           16230 :         dopr_outch(signvalue, &target);
 1644 tgl                      1366 ECB             : 
 1644 tgl                      1367 GIC      114994 :     dostr(convert, vallen, &target);
 1644 tgl                      1368 ECB             : 
 1644 tgl                      1369 CBC      114994 : fail:
 1644 tgl                      1370 GIC      114994 :     *(target.bufptr) = '\0';
                               1371          229988 :     return target.failed ? -1 : (target.bufptr - target.bufstart
 1644 tgl                      1372 CBC      114994 :                                  + target.nchars);
                               1373                 : }
                               1374                 : 
                               1375                 : 
 8828 tgl                      1376 ECB             : static void
 4382 bruce                    1377 CBC   151516206 : dostr(const char *str, int slen, PrintfTarget *target)
                               1378                 : {
 1649 tgl                      1379 ECB             :     /* fast path for common case of slen == 1 */
 1649 tgl                      1380 CBC   151516206 :     if (slen == 1)
                               1381                 :     {
 1649 tgl                      1382 GIC    55737028 :         dopr_outch(*str, target);
 1649 tgl                      1383 CBC    55737031 :         return;
                               1384                 :     }
 1649 tgl                      1385 ECB             : 
 6334 tgl                      1386 CBC   190540911 :     while (slen > 0)
                               1387                 :     {
 6031 bruce                    1388 ECB             :         int         avail;
 6334 tgl                      1389                 : 
 6334 tgl                      1390 GIC    94898471 :         if (target->bufend != NULL)
 6334 tgl                      1391 CBC    92966699 :             avail = target->bufend - target->bufptr;
 6031 bruce                    1392 ECB             :         else
 6334 tgl                      1393 CBC     1931772 :             avail = slen;
                               1394        94898471 :         if (avail <= 0)
 6334 tgl                      1395 ECB             :         {
                               1396                 :             /* buffer full, can we dump to stream? */
 6334 tgl                      1397 GIC      136848 :             if (target->stream == NULL)
                               1398                 :             {
 1698                          1399          136738 :                 target->nchars += slen; /* no, lose the data */
 1698 tgl                      1400 CBC      136738 :                 return;
                               1401                 :             }
 6334                          1402             110 :             flushbuffer(target);
 6334 tgl                      1403 GIC         110 :             continue;
                               1404                 :         }
 6334 tgl                      1405 CBC    94761623 :         avail = Min(avail, slen);
 6334 tgl                      1406 GIC    94761623 :         memmove(target->bufptr, str, avail);
 6334 tgl                      1407 CBC    94761623 :         target->bufptr += avail;
                               1408        94761623 :         str += avail;
 6334 tgl                      1409 GIC    94761623 :         slen -= avail;
 6334 tgl                      1410 EUB             :     }
                               1411                 : }
 8983 scrappy                  1412 ECB             : 
                               1413                 : static void
 4382 bruce                    1414 GIC    63685546 : dopr_outch(int c, PrintfTarget *target)
                               1415                 : {
 6334 tgl                      1416 CBC    63685546 :     if (target->bufend != NULL && target->bufptr >= target->bufend)
                               1417                 :     {
                               1418                 :         /* buffer full, can we dump to stream? */
                               1419           23003 :         if (target->stream == NULL)
                               1420                 :         {
 1698                          1421           23003 :             target->nchars++;    /* no, lose the data */
                               1422           23003 :             return;
                               1423                 :         }
 6334 tgl                      1424 UIC           0 :         flushbuffer(target);
 8950 bruce                    1425 ECB             :     }
 6334 tgl                      1426 GIC    63662546 :     *(target->bufptr++) = c;
                               1427                 : }
                               1428                 : 
 1649 tgl                      1429 ECB             : static void
 1649 tgl                      1430 CBC     1591677 : dopr_outchmulti(int c, int slen, PrintfTarget *target)
                               1431                 : {
 1649 tgl                      1432 ECB             :     /* fast path for common case of slen == 1 */
 1649 tgl                      1433 CBC     1591677 :     if (slen == 1)
                               1434                 :     {
 1649 tgl                      1435 GIC     1242641 :         dopr_outch(c, target);
 1649 tgl                      1436 CBC     1242641 :         return;
                               1437                 :     }
 1649 tgl                      1438 EUB             : 
 1649 tgl                      1439 GBC      698389 :     while (slen > 0)
                               1440                 :     {
 1649 tgl                      1441 ECB             :         int         avail;
                               1442                 : 
 1649 tgl                      1443 GIC      349353 :         if (target->bufend != NULL)
 1649 tgl                      1444 CBC      345041 :             avail = target->bufend - target->bufptr;
 1649 tgl                      1445 ECB             :         else
 1649 tgl                      1446 CBC        4312 :             avail = slen;
                               1447          349353 :         if (avail <= 0)
                               1448                 :         {
                               1449                 :             /* buffer full, can we dump to stream? */
 1649 tgl                      1450 GIC         160 :             if (target->stream == NULL)
                               1451                 :             {
 1649 tgl                      1452 UIC           0 :                 target->nchars += slen; /* no, lose the data */
 1649 tgl                      1453 LBC           0 :                 return;
                               1454                 :             }
 1649 tgl                      1455 CBC         160 :             flushbuffer(target);
 1649 tgl                      1456 GIC         160 :             continue;
 1649 tgl                      1457 ECB             :         }
 1649 tgl                      1458 CBC      349193 :         avail = Min(avail, slen);
 1649 tgl                      1459 GIC      349193 :         memset(target->bufptr, c, avail);
 1649 tgl                      1460 CBC      349193 :         target->bufptr += avail;
                               1461          349193 :         slen -= avail;
 1649 tgl                      1462 ECB             :     }
                               1463                 : }
                               1464                 : 
                               1465                 : 
                               1466                 : static int
 6597 bruce                    1467 CBC    36891898 : adjust_sign(int is_negative, int forcesign, int *signvalue)
                               1468                 : {
 6597 bruce                    1469 GIC    36891898 :     if (is_negative)
                               1470                 :     {
 6597 bruce                    1471 CBC     6668788 :         *signvalue = '-';
                               1472         6668788 :         return true;
 6597 bruce                    1473 ECB             :     }
 6597 bruce                    1474 CBC    30223110 :     else if (forcesign)
                               1475              93 :         *signvalue = '+';
                               1476        30223110 :     return false;
                               1477                 : }
                               1478                 : 
                               1479                 : 
                               1480                 : static int
 1649 tgl                      1481        67324347 : compute_padlen(int minlen, int vallen, int leftjust)
                               1482                 : {
                               1483                 :     int         padlen;
                               1484                 : 
                               1485        67324347 :     padlen = minlen - vallen;
 1649 tgl                      1486 GIC    67324347 :     if (padlen < 0)
 1649 tgl                      1487 CBC    63887213 :         padlen = 0;
 6597 bruce                    1488 GIC    67324347 :     if (leftjust)
 1649 tgl                      1489 CBC      223188 :         padlen = -padlen;
                               1490        67324347 :     return padlen;
 6597 bruce                    1491 ECB             : }
                               1492                 : 
                               1493                 : 
                               1494                 : static void
 1649 tgl                      1495 CBC    66698375 : leading_pad(int zpad, int signvalue, int *padlen, PrintfTarget *target)
 6597 bruce                    1496 ECB             : {
                               1497                 :     int         maxpad;
                               1498                 : 
 6597 bruce                    1499 CBC    66698375 :     if (*padlen > 0 && zpad)
 6597 bruce                    1500 ECB             :     {
 1649 tgl                      1501 GIC     1248275 :         if (signvalue)
 6597 bruce                    1502 ECB             :         {
 1649 tgl                      1503 CBC          90 :             dopr_outch(signvalue, target);
 6334 tgl                      1504 GIC          90 :             --(*padlen);
 1649 tgl                      1505 CBC          90 :             signvalue = 0;
                               1506                 :         }
                               1507         1248275 :         if (*padlen > 0)
 6597 bruce                    1508 ECB             :         {
 1649 tgl                      1509 GBC     1248266 :             dopr_outchmulti(zpad, *padlen, target);
 1649 tgl                      1510 CBC     1248266 :             *padlen = 0;
 6597 bruce                    1511 EUB             :         }
                               1512                 :     }
 1649 tgl                      1513 CBC    66698375 :     maxpad = (signvalue != 0);
 1649 tgl                      1514 GIC    66698375 :     if (*padlen > maxpad)
                               1515                 :     {
                               1516            5264 :         dopr_outchmulti(' ', *padlen - maxpad, target);
 1649 tgl                      1517 CBC        5264 :         *padlen = maxpad;
                               1518                 :     }
                               1519        66698375 :     if (signvalue)
 6597 bruce                    1520 ECB             :     {
 1649 tgl                      1521 CBC     6668791 :         dopr_outch(signvalue, target);
 6597 bruce                    1522 GIC     6668791 :         if (*padlen > 0)
 6334 tgl                      1523 UIC           0 :             --(*padlen);
 6334 tgl                      1524 GIC     6668791 :         else if (*padlen < 0)
 6334 tgl                      1525 UIC           0 :             ++(*padlen);
                               1526                 :     }
 6597 bruce                    1527 GIC    66698375 : }
                               1528                 : 
                               1529                 : 
                               1530                 : static void
 1649 tgl                      1531        67324353 : trailing_pad(int padlen, PrintfTarget *target)
                               1532                 : {
                               1533        67324353 :     if (padlen < 0)
                               1534           82045 :         dopr_outchmulti(' ', -padlen, target);
 6597 bruce                    1535        67324353 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a