xref: /third_party/curl/lib/mprintf.c (revision 13498266)
113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci */
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci#include "dynbuf.h"
2713498266Sopenharmony_ci#include "curl_printf.h"
2813498266Sopenharmony_ci#include <curl/mprintf.h>
2913498266Sopenharmony_ci
3013498266Sopenharmony_ci#include "curl_memory.h"
3113498266Sopenharmony_ci/* The last #include file should be: */
3213498266Sopenharmony_ci#include "memdebug.h"
3313498266Sopenharmony_ci
3413498266Sopenharmony_ci/*
3513498266Sopenharmony_ci * If SIZEOF_SIZE_T has not been defined, default to the size of long.
3613498266Sopenharmony_ci */
3713498266Sopenharmony_ci
3813498266Sopenharmony_ci#ifdef HAVE_LONGLONG
3913498266Sopenharmony_ci#  define LONG_LONG_TYPE long long
4013498266Sopenharmony_ci#  define HAVE_LONG_LONG_TYPE
4113498266Sopenharmony_ci#else
4213498266Sopenharmony_ci#  if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
4313498266Sopenharmony_ci#    define LONG_LONG_TYPE __int64
4413498266Sopenharmony_ci#    define HAVE_LONG_LONG_TYPE
4513498266Sopenharmony_ci#  else
4613498266Sopenharmony_ci#    undef LONG_LONG_TYPE
4713498266Sopenharmony_ci#    undef HAVE_LONG_LONG_TYPE
4813498266Sopenharmony_ci#  endif
4913498266Sopenharmony_ci#endif
5013498266Sopenharmony_ci
5113498266Sopenharmony_ci/*
5213498266Sopenharmony_ci * Non-ANSI integer extensions
5313498266Sopenharmony_ci */
5413498266Sopenharmony_ci
5513498266Sopenharmony_ci#if (defined(_WIN32_WCE)) || \
5613498266Sopenharmony_ci    (defined(__MINGW32__)) || \
5713498266Sopenharmony_ci    (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
5813498266Sopenharmony_ci#  define MP_HAVE_INT_EXTENSIONS
5913498266Sopenharmony_ci#endif
6013498266Sopenharmony_ci
6113498266Sopenharmony_ci/*
6213498266Sopenharmony_ci * Max integer data types that mprintf.c is capable
6313498266Sopenharmony_ci */
6413498266Sopenharmony_ci
6513498266Sopenharmony_ci#ifdef HAVE_LONG_LONG_TYPE
6613498266Sopenharmony_ci#  define mp_intmax_t LONG_LONG_TYPE
6713498266Sopenharmony_ci#  define mp_uintmax_t unsigned LONG_LONG_TYPE
6813498266Sopenharmony_ci#else
6913498266Sopenharmony_ci#  define mp_intmax_t long
7013498266Sopenharmony_ci#  define mp_uintmax_t unsigned long
7113498266Sopenharmony_ci#endif
7213498266Sopenharmony_ci
7313498266Sopenharmony_ci#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
7413498266Sopenharmony_ci                        fit negative DBL_MAX (317 letters) */
7513498266Sopenharmony_ci#define MAX_PARAMETERS 128 /* number of input arguments */
7613498266Sopenharmony_ci#define MAX_SEGMENTS   128 /* number of output segments */
7713498266Sopenharmony_ci
7813498266Sopenharmony_ci#ifdef __AMIGA__
7913498266Sopenharmony_ci# undef FORMAT_INT
8013498266Sopenharmony_ci#endif
8113498266Sopenharmony_ci
8213498266Sopenharmony_ci/* Lower-case digits.  */
8313498266Sopenharmony_cistatic const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
8413498266Sopenharmony_ci
8513498266Sopenharmony_ci/* Upper-case digits.  */
8613498266Sopenharmony_cistatic const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
8713498266Sopenharmony_ci
8813498266Sopenharmony_ci#define OUTCHAR(x)                                      \
8913498266Sopenharmony_ci  do {                                                  \
9013498266Sopenharmony_ci    if(!stream(x, userp))                               \
9113498266Sopenharmony_ci      done++;                                           \
9213498266Sopenharmony_ci    else                                                \
9313498266Sopenharmony_ci      return done; /* return on failure */              \
9413498266Sopenharmony_ci  } while(0)
9513498266Sopenharmony_ci
9613498266Sopenharmony_ci/* Data type to read from the arglist */
9713498266Sopenharmony_citypedef enum {
9813498266Sopenharmony_ci  FORMAT_STRING,
9913498266Sopenharmony_ci  FORMAT_PTR,
10013498266Sopenharmony_ci  FORMAT_INTPTR,
10113498266Sopenharmony_ci  FORMAT_INT,
10213498266Sopenharmony_ci  FORMAT_LONG,
10313498266Sopenharmony_ci  FORMAT_LONGLONG,
10413498266Sopenharmony_ci  FORMAT_INTU,
10513498266Sopenharmony_ci  FORMAT_LONGU,
10613498266Sopenharmony_ci  FORMAT_LONGLONGU,
10713498266Sopenharmony_ci  FORMAT_DOUBLE,
10813498266Sopenharmony_ci  FORMAT_LONGDOUBLE,
10913498266Sopenharmony_ci  FORMAT_WIDTH,
11013498266Sopenharmony_ci  FORMAT_PRECISION
11113498266Sopenharmony_ci} FormatType;
11213498266Sopenharmony_ci
11313498266Sopenharmony_ci/* conversion and display flags */
11413498266Sopenharmony_cienum {
11513498266Sopenharmony_ci  FLAGS_SPACE      = 1<<0,
11613498266Sopenharmony_ci  FLAGS_SHOWSIGN   = 1<<1,
11713498266Sopenharmony_ci  FLAGS_LEFT       = 1<<2,
11813498266Sopenharmony_ci  FLAGS_ALT        = 1<<3,
11913498266Sopenharmony_ci  FLAGS_SHORT      = 1<<4,
12013498266Sopenharmony_ci  FLAGS_LONG       = 1<<5,
12113498266Sopenharmony_ci  FLAGS_LONGLONG   = 1<<6,
12213498266Sopenharmony_ci  FLAGS_LONGDOUBLE = 1<<7,
12313498266Sopenharmony_ci  FLAGS_PAD_NIL    = 1<<8,
12413498266Sopenharmony_ci  FLAGS_UNSIGNED   = 1<<9,
12513498266Sopenharmony_ci  FLAGS_OCTAL      = 1<<10,
12613498266Sopenharmony_ci  FLAGS_HEX        = 1<<11,
12713498266Sopenharmony_ci  FLAGS_UPPER      = 1<<12,
12813498266Sopenharmony_ci  FLAGS_WIDTH      = 1<<13, /* '*' or '*<num>$' used */
12913498266Sopenharmony_ci  FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */
13013498266Sopenharmony_ci  FLAGS_PREC       = 1<<15, /* precision was specified */
13113498266Sopenharmony_ci  FLAGS_PRECPARAM  = 1<<16, /* precision PARAMETER was specified */
13213498266Sopenharmony_ci  FLAGS_CHAR       = 1<<17, /* %c story */
13313498266Sopenharmony_ci  FLAGS_FLOATE     = 1<<18, /* %e or %E */
13413498266Sopenharmony_ci  FLAGS_FLOATG     = 1<<19, /* %g or %G */
13513498266Sopenharmony_ci  FLAGS_SUBSTR     = 1<<20  /* no input, only substring */
13613498266Sopenharmony_ci};
13713498266Sopenharmony_ci
13813498266Sopenharmony_cienum {
13913498266Sopenharmony_ci  DOLLAR_UNKNOWN,
14013498266Sopenharmony_ci  DOLLAR_NOPE,
14113498266Sopenharmony_ci  DOLLAR_USE
14213498266Sopenharmony_ci};
14313498266Sopenharmony_ci
14413498266Sopenharmony_ci/*
14513498266Sopenharmony_ci * Describes an input va_arg type and hold its value.
14613498266Sopenharmony_ci */
14713498266Sopenharmony_cistruct va_input {
14813498266Sopenharmony_ci  FormatType type; /* FormatType */
14913498266Sopenharmony_ci  union {
15013498266Sopenharmony_ci    char *str;
15113498266Sopenharmony_ci    void *ptr;
15213498266Sopenharmony_ci    mp_intmax_t nums; /* signed */
15313498266Sopenharmony_ci    mp_uintmax_t numu; /* unsigned */
15413498266Sopenharmony_ci    double dnum;
15513498266Sopenharmony_ci  } val;
15613498266Sopenharmony_ci};
15713498266Sopenharmony_ci
15813498266Sopenharmony_ci/*
15913498266Sopenharmony_ci * Describes an output segment.
16013498266Sopenharmony_ci */
16113498266Sopenharmony_cistruct outsegment {
16213498266Sopenharmony_ci  int width;     /* width OR width parameter number */
16313498266Sopenharmony_ci  int precision; /* precision OR precision parameter number */
16413498266Sopenharmony_ci  unsigned int flags;
16513498266Sopenharmony_ci  unsigned int input; /* input argument array index */
16613498266Sopenharmony_ci  char *start;      /* format string start to output */
16713498266Sopenharmony_ci  size_t outlen;     /* number of bytes from the format string to output */
16813498266Sopenharmony_ci};
16913498266Sopenharmony_ci
17013498266Sopenharmony_cistruct nsprintf {
17113498266Sopenharmony_ci  char *buffer;
17213498266Sopenharmony_ci  size_t length;
17313498266Sopenharmony_ci  size_t max;
17413498266Sopenharmony_ci};
17513498266Sopenharmony_ci
17613498266Sopenharmony_cistruct asprintf {
17713498266Sopenharmony_ci  struct dynbuf *b;
17813498266Sopenharmony_ci  char merr;
17913498266Sopenharmony_ci};
18013498266Sopenharmony_ci
18113498266Sopenharmony_ci/* the provided input number is 1-based but this returns the number 0-based.
18213498266Sopenharmony_ci
18313498266Sopenharmony_ci   returns -1 if no valid number was provided.
18413498266Sopenharmony_ci*/
18513498266Sopenharmony_cistatic int dollarstring(char *input, char **end)
18613498266Sopenharmony_ci{
18713498266Sopenharmony_ci  if(ISDIGIT(*input)) {
18813498266Sopenharmony_ci    int number = 0;
18913498266Sopenharmony_ci    do {
19013498266Sopenharmony_ci      if(number < MAX_PARAMETERS) {
19113498266Sopenharmony_ci        number *= 10;
19213498266Sopenharmony_ci        number += *input - '0';
19313498266Sopenharmony_ci      }
19413498266Sopenharmony_ci      input++;
19513498266Sopenharmony_ci    } while(ISDIGIT(*input));
19613498266Sopenharmony_ci
19713498266Sopenharmony_ci    if(number && (number <= MAX_PARAMETERS) && ('$' == *input)) {
19813498266Sopenharmony_ci      *end = ++input;
19913498266Sopenharmony_ci      return number - 1;
20013498266Sopenharmony_ci    }
20113498266Sopenharmony_ci  }
20213498266Sopenharmony_ci  return -1;
20313498266Sopenharmony_ci}
20413498266Sopenharmony_ci
20513498266Sopenharmony_ci/*
20613498266Sopenharmony_ci * Parse the format string.
20713498266Sopenharmony_ci *
20813498266Sopenharmony_ci * Create two arrays. One describes the inputs, one describes the outputs.
20913498266Sopenharmony_ci *
21013498266Sopenharmony_ci * Returns zero on success.
21113498266Sopenharmony_ci */
21213498266Sopenharmony_ci
21313498266Sopenharmony_ci#define PFMT_OK          0
21413498266Sopenharmony_ci#define PFMT_DOLLAR      1 /* bad dollar for main param */
21513498266Sopenharmony_ci#define PFMT_DOLLARWIDTH 2 /* bad dollar use for width */
21613498266Sopenharmony_ci#define PFMT_DOLLARPREC  3 /* bad dollar use for precision */
21713498266Sopenharmony_ci#define PFMT_MANYARGS    4 /* too many input arguments used */
21813498266Sopenharmony_ci#define PFMT_PREC        5 /* precision overflow */
21913498266Sopenharmony_ci#define PFMT_PRECMIX     6 /* bad mix of precision specifiers */
22013498266Sopenharmony_ci#define PFMT_WIDTH       7 /* width overflow */
22113498266Sopenharmony_ci#define PFMT_INPUTGAP    8 /* gap in arguments */
22213498266Sopenharmony_ci#define PFMT_WIDTHARG    9 /* attempted to use same arg twice, for width */
22313498266Sopenharmony_ci#define PFMT_PRECARG    10 /* attempted to use same arg twice, for prec */
22413498266Sopenharmony_ci#define PFMT_MANYSEGS   11 /* maxed out output segments */
22513498266Sopenharmony_ci
22613498266Sopenharmony_cistatic int parsefmt(const char *format,
22713498266Sopenharmony_ci                    struct outsegment *out,
22813498266Sopenharmony_ci                    struct va_input *in,
22913498266Sopenharmony_ci                    int *opieces,
23013498266Sopenharmony_ci                    int *ipieces, va_list arglist)
23113498266Sopenharmony_ci{
23213498266Sopenharmony_ci  char *fmt = (char *)format;
23313498266Sopenharmony_ci  int param_num = 0;
23413498266Sopenharmony_ci  int param;
23513498266Sopenharmony_ci  int width;
23613498266Sopenharmony_ci  int precision;
23713498266Sopenharmony_ci  unsigned int flags;
23813498266Sopenharmony_ci  FormatType type;
23913498266Sopenharmony_ci  int max_param = -1;
24013498266Sopenharmony_ci  int i;
24113498266Sopenharmony_ci  int ocount = 0;
24213498266Sopenharmony_ci  unsigned char usedinput[MAX_PARAMETERS/8];
24313498266Sopenharmony_ci  size_t outlen = 0;
24413498266Sopenharmony_ci  struct outsegment *optr;
24513498266Sopenharmony_ci  int use_dollar = DOLLAR_UNKNOWN;
24613498266Sopenharmony_ci  char *start = fmt;
24713498266Sopenharmony_ci
24813498266Sopenharmony_ci  /* clear, set a bit for each used input */
24913498266Sopenharmony_ci  memset(usedinput, 0, sizeof(usedinput));
25013498266Sopenharmony_ci
25113498266Sopenharmony_ci  while(*fmt) {
25213498266Sopenharmony_ci    if(*fmt == '%') {
25313498266Sopenharmony_ci      struct va_input *iptr;
25413498266Sopenharmony_ci      bool loopit = TRUE;
25513498266Sopenharmony_ci      fmt++;
25613498266Sopenharmony_ci      outlen = fmt - start - 1;
25713498266Sopenharmony_ci      if(*fmt == '%') {
25813498266Sopenharmony_ci        /* this means a %% that should be output only as %. Create an output
25913498266Sopenharmony_ci           segment. */
26013498266Sopenharmony_ci        if(outlen) {
26113498266Sopenharmony_ci          optr = &out[ocount++];
26213498266Sopenharmony_ci          if(ocount > MAX_SEGMENTS)
26313498266Sopenharmony_ci            return PFMT_MANYSEGS;
26413498266Sopenharmony_ci          optr->input = 0;
26513498266Sopenharmony_ci          optr->flags = FLAGS_SUBSTR;
26613498266Sopenharmony_ci          optr->start = start;
26713498266Sopenharmony_ci          optr->outlen = outlen;
26813498266Sopenharmony_ci        }
26913498266Sopenharmony_ci        start = fmt;
27013498266Sopenharmony_ci        fmt++;
27113498266Sopenharmony_ci        continue; /* while */
27213498266Sopenharmony_ci      }
27313498266Sopenharmony_ci
27413498266Sopenharmony_ci      flags = width = precision = 0;
27513498266Sopenharmony_ci
27613498266Sopenharmony_ci      if(use_dollar != DOLLAR_NOPE) {
27713498266Sopenharmony_ci        param = dollarstring(fmt, &fmt);
27813498266Sopenharmony_ci        if(param < 0) {
27913498266Sopenharmony_ci          if(use_dollar == DOLLAR_USE)
28013498266Sopenharmony_ci            /* illegal combo */
28113498266Sopenharmony_ci            return PFMT_DOLLAR;
28213498266Sopenharmony_ci
28313498266Sopenharmony_ci          /* we got no positional, just get the next arg */
28413498266Sopenharmony_ci          param = -1;
28513498266Sopenharmony_ci          use_dollar = DOLLAR_NOPE;
28613498266Sopenharmony_ci        }
28713498266Sopenharmony_ci        else
28813498266Sopenharmony_ci          use_dollar = DOLLAR_USE;
28913498266Sopenharmony_ci      }
29013498266Sopenharmony_ci      else
29113498266Sopenharmony_ci        param = -1;
29213498266Sopenharmony_ci
29313498266Sopenharmony_ci      /* Handle the flags */
29413498266Sopenharmony_ci      while(loopit) {
29513498266Sopenharmony_ci        switch(*fmt++) {
29613498266Sopenharmony_ci        case ' ':
29713498266Sopenharmony_ci          flags |= FLAGS_SPACE;
29813498266Sopenharmony_ci          break;
29913498266Sopenharmony_ci        case '+':
30013498266Sopenharmony_ci          flags |= FLAGS_SHOWSIGN;
30113498266Sopenharmony_ci          break;
30213498266Sopenharmony_ci        case '-':
30313498266Sopenharmony_ci          flags |= FLAGS_LEFT;
30413498266Sopenharmony_ci          flags &= ~FLAGS_PAD_NIL;
30513498266Sopenharmony_ci          break;
30613498266Sopenharmony_ci        case '#':
30713498266Sopenharmony_ci          flags |= FLAGS_ALT;
30813498266Sopenharmony_ci          break;
30913498266Sopenharmony_ci        case '.':
31013498266Sopenharmony_ci          if('*' == *fmt) {
31113498266Sopenharmony_ci            /* The precision is picked from a specified parameter */
31213498266Sopenharmony_ci            flags |= FLAGS_PRECPARAM;
31313498266Sopenharmony_ci            fmt++;
31413498266Sopenharmony_ci
31513498266Sopenharmony_ci            if(use_dollar == DOLLAR_USE) {
31613498266Sopenharmony_ci              precision = dollarstring(fmt, &fmt);
31713498266Sopenharmony_ci              if(precision < 0)
31813498266Sopenharmony_ci                /* illegal combo */
31913498266Sopenharmony_ci                return PFMT_DOLLARPREC;
32013498266Sopenharmony_ci            }
32113498266Sopenharmony_ci            else
32213498266Sopenharmony_ci              /* get it from the next argument */
32313498266Sopenharmony_ci              precision = -1;
32413498266Sopenharmony_ci          }
32513498266Sopenharmony_ci          else {
32613498266Sopenharmony_ci            bool is_neg = FALSE;
32713498266Sopenharmony_ci            flags |= FLAGS_PREC;
32813498266Sopenharmony_ci            precision = 0;
32913498266Sopenharmony_ci            if('-' == *fmt) {
33013498266Sopenharmony_ci              is_neg = TRUE;
33113498266Sopenharmony_ci              fmt++;
33213498266Sopenharmony_ci            }
33313498266Sopenharmony_ci            while(ISDIGIT(*fmt)) {
33413498266Sopenharmony_ci              if(precision > INT_MAX/10)
33513498266Sopenharmony_ci                return PFMT_PREC;
33613498266Sopenharmony_ci              precision *= 10;
33713498266Sopenharmony_ci              precision += *fmt - '0';
33813498266Sopenharmony_ci              fmt++;
33913498266Sopenharmony_ci            }
34013498266Sopenharmony_ci            if(is_neg)
34113498266Sopenharmony_ci              precision = -precision;
34213498266Sopenharmony_ci          }
34313498266Sopenharmony_ci          if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
34413498266Sopenharmony_ci             (FLAGS_PREC | FLAGS_PRECPARAM))
34513498266Sopenharmony_ci            /* it is not permitted to use both kinds of precision for the same
34613498266Sopenharmony_ci               argument */
34713498266Sopenharmony_ci            return PFMT_PRECMIX;
34813498266Sopenharmony_ci          break;
34913498266Sopenharmony_ci        case 'h':
35013498266Sopenharmony_ci          flags |= FLAGS_SHORT;
35113498266Sopenharmony_ci          break;
35213498266Sopenharmony_ci#if defined(MP_HAVE_INT_EXTENSIONS)
35313498266Sopenharmony_ci        case 'I':
35413498266Sopenharmony_ci          if((fmt[0] == '3') && (fmt[1] == '2')) {
35513498266Sopenharmony_ci            flags |= FLAGS_LONG;
35613498266Sopenharmony_ci            fmt += 2;
35713498266Sopenharmony_ci          }
35813498266Sopenharmony_ci          else if((fmt[0] == '6') && (fmt[1] == '4')) {
35913498266Sopenharmony_ci            flags |= FLAGS_LONGLONG;
36013498266Sopenharmony_ci            fmt += 2;
36113498266Sopenharmony_ci          }
36213498266Sopenharmony_ci          else {
36313498266Sopenharmony_ci#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
36413498266Sopenharmony_ci            flags |= FLAGS_LONGLONG;
36513498266Sopenharmony_ci#else
36613498266Sopenharmony_ci            flags |= FLAGS_LONG;
36713498266Sopenharmony_ci#endif
36813498266Sopenharmony_ci          }
36913498266Sopenharmony_ci          break;
37013498266Sopenharmony_ci#endif
37113498266Sopenharmony_ci        case 'l':
37213498266Sopenharmony_ci          if(flags & FLAGS_LONG)
37313498266Sopenharmony_ci            flags |= FLAGS_LONGLONG;
37413498266Sopenharmony_ci          else
37513498266Sopenharmony_ci            flags |= FLAGS_LONG;
37613498266Sopenharmony_ci          break;
37713498266Sopenharmony_ci        case 'L':
37813498266Sopenharmony_ci          flags |= FLAGS_LONGDOUBLE;
37913498266Sopenharmony_ci          break;
38013498266Sopenharmony_ci        case 'q':
38113498266Sopenharmony_ci          flags |= FLAGS_LONGLONG;
38213498266Sopenharmony_ci          break;
38313498266Sopenharmony_ci        case 'z':
38413498266Sopenharmony_ci          /* the code below generates a warning if -Wunreachable-code is
38513498266Sopenharmony_ci             used */
38613498266Sopenharmony_ci#if (SIZEOF_SIZE_T > SIZEOF_LONG)
38713498266Sopenharmony_ci          flags |= FLAGS_LONGLONG;
38813498266Sopenharmony_ci#else
38913498266Sopenharmony_ci          flags |= FLAGS_LONG;
39013498266Sopenharmony_ci#endif
39113498266Sopenharmony_ci          break;
39213498266Sopenharmony_ci        case 'O':
39313498266Sopenharmony_ci#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
39413498266Sopenharmony_ci          flags |= FLAGS_LONGLONG;
39513498266Sopenharmony_ci#else
39613498266Sopenharmony_ci          flags |= FLAGS_LONG;
39713498266Sopenharmony_ci#endif
39813498266Sopenharmony_ci          break;
39913498266Sopenharmony_ci        case '0':
40013498266Sopenharmony_ci          if(!(flags & FLAGS_LEFT))
40113498266Sopenharmony_ci            flags |= FLAGS_PAD_NIL;
40213498266Sopenharmony_ci          FALLTHROUGH();
40313498266Sopenharmony_ci        case '1': case '2': case '3': case '4':
40413498266Sopenharmony_ci        case '5': case '6': case '7': case '8': case '9':
40513498266Sopenharmony_ci          flags |= FLAGS_WIDTH;
40613498266Sopenharmony_ci          width = 0;
40713498266Sopenharmony_ci          fmt--;
40813498266Sopenharmony_ci          do {
40913498266Sopenharmony_ci            if(width > INT_MAX/10)
41013498266Sopenharmony_ci              return PFMT_WIDTH;
41113498266Sopenharmony_ci            width *= 10;
41213498266Sopenharmony_ci            width += *fmt - '0';
41313498266Sopenharmony_ci            fmt++;
41413498266Sopenharmony_ci          } while(ISDIGIT(*fmt));
41513498266Sopenharmony_ci          break;
41613498266Sopenharmony_ci        case '*':  /* read width from argument list */
41713498266Sopenharmony_ci          flags |= FLAGS_WIDTHPARAM;
41813498266Sopenharmony_ci          if(use_dollar == DOLLAR_USE) {
41913498266Sopenharmony_ci            width = dollarstring(fmt, &fmt);
42013498266Sopenharmony_ci            if(width < 0)
42113498266Sopenharmony_ci              /* illegal combo */
42213498266Sopenharmony_ci              return PFMT_DOLLARWIDTH;
42313498266Sopenharmony_ci          }
42413498266Sopenharmony_ci          else
42513498266Sopenharmony_ci            /* pick from the next argument */
42613498266Sopenharmony_ci            width = -1;
42713498266Sopenharmony_ci          break;
42813498266Sopenharmony_ci        default:
42913498266Sopenharmony_ci          loopit = FALSE;
43013498266Sopenharmony_ci          fmt--;
43113498266Sopenharmony_ci          break;
43213498266Sopenharmony_ci        } /* switch */
43313498266Sopenharmony_ci      } /* while */
43413498266Sopenharmony_ci
43513498266Sopenharmony_ci      switch(*fmt) {
43613498266Sopenharmony_ci      case 'S':
43713498266Sopenharmony_ci        flags |= FLAGS_ALT;
43813498266Sopenharmony_ci        FALLTHROUGH();
43913498266Sopenharmony_ci      case 's':
44013498266Sopenharmony_ci        type = FORMAT_STRING;
44113498266Sopenharmony_ci        break;
44213498266Sopenharmony_ci      case 'n':
44313498266Sopenharmony_ci        type = FORMAT_INTPTR;
44413498266Sopenharmony_ci        break;
44513498266Sopenharmony_ci      case 'p':
44613498266Sopenharmony_ci        type = FORMAT_PTR;
44713498266Sopenharmony_ci        break;
44813498266Sopenharmony_ci      case 'd':
44913498266Sopenharmony_ci      case 'i':
45013498266Sopenharmony_ci        if(flags & FLAGS_LONGLONG)
45113498266Sopenharmony_ci          type = FORMAT_LONGLONG;
45213498266Sopenharmony_ci        else if(flags & FLAGS_LONG)
45313498266Sopenharmony_ci          type = FORMAT_LONG;
45413498266Sopenharmony_ci        else
45513498266Sopenharmony_ci          type = FORMAT_INT;
45613498266Sopenharmony_ci        break;
45713498266Sopenharmony_ci      case 'u':
45813498266Sopenharmony_ci        if(flags & FLAGS_LONGLONG)
45913498266Sopenharmony_ci          type = FORMAT_LONGLONGU;
46013498266Sopenharmony_ci        else if(flags & FLAGS_LONG)
46113498266Sopenharmony_ci          type = FORMAT_LONGU;
46213498266Sopenharmony_ci        else
46313498266Sopenharmony_ci          type = FORMAT_INTU;
46413498266Sopenharmony_ci        flags |= FLAGS_UNSIGNED;
46513498266Sopenharmony_ci        break;
46613498266Sopenharmony_ci      case 'o':
46713498266Sopenharmony_ci        type = FORMAT_INT;
46813498266Sopenharmony_ci        flags |= FLAGS_OCTAL;
46913498266Sopenharmony_ci        break;
47013498266Sopenharmony_ci      case 'x':
47113498266Sopenharmony_ci        type = FORMAT_INTU;
47213498266Sopenharmony_ci        flags |= FLAGS_HEX|FLAGS_UNSIGNED;
47313498266Sopenharmony_ci        break;
47413498266Sopenharmony_ci      case 'X':
47513498266Sopenharmony_ci        type = FORMAT_INTU;
47613498266Sopenharmony_ci        flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
47713498266Sopenharmony_ci        break;
47813498266Sopenharmony_ci      case 'c':
47913498266Sopenharmony_ci        type = FORMAT_INT;
48013498266Sopenharmony_ci        flags |= FLAGS_CHAR;
48113498266Sopenharmony_ci        break;
48213498266Sopenharmony_ci      case 'f':
48313498266Sopenharmony_ci        type = FORMAT_DOUBLE;
48413498266Sopenharmony_ci        break;
48513498266Sopenharmony_ci      case 'e':
48613498266Sopenharmony_ci        type = FORMAT_DOUBLE;
48713498266Sopenharmony_ci        flags |= FLAGS_FLOATE;
48813498266Sopenharmony_ci        break;
48913498266Sopenharmony_ci      case 'E':
49013498266Sopenharmony_ci        type = FORMAT_DOUBLE;
49113498266Sopenharmony_ci        flags |= FLAGS_FLOATE|FLAGS_UPPER;
49213498266Sopenharmony_ci        break;
49313498266Sopenharmony_ci      case 'g':
49413498266Sopenharmony_ci        type = FORMAT_DOUBLE;
49513498266Sopenharmony_ci        flags |= FLAGS_FLOATG;
49613498266Sopenharmony_ci        break;
49713498266Sopenharmony_ci      case 'G':
49813498266Sopenharmony_ci        type = FORMAT_DOUBLE;
49913498266Sopenharmony_ci        flags |= FLAGS_FLOATG|FLAGS_UPPER;
50013498266Sopenharmony_ci        break;
50113498266Sopenharmony_ci      default:
50213498266Sopenharmony_ci        /* invalid instruction, disregard and continue */
50313498266Sopenharmony_ci        continue;
50413498266Sopenharmony_ci      } /* switch */
50513498266Sopenharmony_ci
50613498266Sopenharmony_ci      if(flags & FLAGS_WIDTHPARAM) {
50713498266Sopenharmony_ci        if(width < 0)
50813498266Sopenharmony_ci          width = param_num++;
50913498266Sopenharmony_ci        else {
51013498266Sopenharmony_ci          /* if this identifies a parameter already used, this
51113498266Sopenharmony_ci             is illegal */
51213498266Sopenharmony_ci          if(usedinput[width/8] & (1 << (width&7)))
51313498266Sopenharmony_ci            return PFMT_WIDTHARG;
51413498266Sopenharmony_ci        }
51513498266Sopenharmony_ci        if(width >= MAX_PARAMETERS)
51613498266Sopenharmony_ci          return PFMT_MANYARGS;
51713498266Sopenharmony_ci        if(width >= max_param)
51813498266Sopenharmony_ci          max_param = width;
51913498266Sopenharmony_ci
52013498266Sopenharmony_ci        in[width].type = FORMAT_WIDTH;
52113498266Sopenharmony_ci        /* mark as used */
52213498266Sopenharmony_ci        usedinput[width/8] |= (unsigned char)(1 << (width&7));
52313498266Sopenharmony_ci      }
52413498266Sopenharmony_ci
52513498266Sopenharmony_ci      if(flags & FLAGS_PRECPARAM) {
52613498266Sopenharmony_ci        if(precision < 0)
52713498266Sopenharmony_ci          precision = param_num++;
52813498266Sopenharmony_ci        else {
52913498266Sopenharmony_ci          /* if this identifies a parameter already used, this
53013498266Sopenharmony_ci             is illegal */
53113498266Sopenharmony_ci          if(usedinput[precision/8] & (1 << (precision&7)))
53213498266Sopenharmony_ci            return PFMT_PRECARG;
53313498266Sopenharmony_ci        }
53413498266Sopenharmony_ci        if(precision >= MAX_PARAMETERS)
53513498266Sopenharmony_ci          return PFMT_MANYARGS;
53613498266Sopenharmony_ci        if(precision >= max_param)
53713498266Sopenharmony_ci          max_param = precision;
53813498266Sopenharmony_ci
53913498266Sopenharmony_ci        in[precision].type = FORMAT_PRECISION;
54013498266Sopenharmony_ci        usedinput[precision/8] |= (unsigned char)(1 << (precision&7));
54113498266Sopenharmony_ci      }
54213498266Sopenharmony_ci
54313498266Sopenharmony_ci      /* Handle the specifier */
54413498266Sopenharmony_ci      if(param < 0)
54513498266Sopenharmony_ci        param = param_num++;
54613498266Sopenharmony_ci      if(param >= MAX_PARAMETERS)
54713498266Sopenharmony_ci        return PFMT_MANYARGS;
54813498266Sopenharmony_ci      if(param >= max_param)
54913498266Sopenharmony_ci        max_param = param;
55013498266Sopenharmony_ci
55113498266Sopenharmony_ci      iptr = &in[param];
55213498266Sopenharmony_ci      iptr->type = type;
55313498266Sopenharmony_ci
55413498266Sopenharmony_ci      /* mark this input as used */
55513498266Sopenharmony_ci      usedinput[param/8] |= (unsigned char)(1 << (param&7));
55613498266Sopenharmony_ci
55713498266Sopenharmony_ci      fmt++;
55813498266Sopenharmony_ci      optr = &out[ocount++];
55913498266Sopenharmony_ci      if(ocount > MAX_SEGMENTS)
56013498266Sopenharmony_ci        return PFMT_MANYSEGS;
56113498266Sopenharmony_ci      optr->input = param;
56213498266Sopenharmony_ci      optr->flags = flags;
56313498266Sopenharmony_ci      optr->width = width;
56413498266Sopenharmony_ci      optr->precision = precision;
56513498266Sopenharmony_ci      optr->start = start;
56613498266Sopenharmony_ci      optr->outlen = outlen;
56713498266Sopenharmony_ci      start = fmt;
56813498266Sopenharmony_ci    }
56913498266Sopenharmony_ci    else
57013498266Sopenharmony_ci      fmt++;
57113498266Sopenharmony_ci  }
57213498266Sopenharmony_ci
57313498266Sopenharmony_ci  /* is there a trailing piece */
57413498266Sopenharmony_ci  outlen = fmt - start;
57513498266Sopenharmony_ci  if(outlen) {
57613498266Sopenharmony_ci    optr = &out[ocount++];
57713498266Sopenharmony_ci    if(ocount > MAX_SEGMENTS)
57813498266Sopenharmony_ci      return PFMT_MANYSEGS;
57913498266Sopenharmony_ci    optr->input = 0;
58013498266Sopenharmony_ci    optr->flags = FLAGS_SUBSTR;
58113498266Sopenharmony_ci    optr->start = start;
58213498266Sopenharmony_ci    optr->outlen = outlen;
58313498266Sopenharmony_ci  }
58413498266Sopenharmony_ci
58513498266Sopenharmony_ci  /* Read the arg list parameters into our data list */
58613498266Sopenharmony_ci  for(i = 0; i < max_param + 1; i++) {
58713498266Sopenharmony_ci    struct va_input *iptr = &in[i];
58813498266Sopenharmony_ci    if(!(usedinput[i/8] & (1 << (i&7))))
58913498266Sopenharmony_ci      /* bad input */
59013498266Sopenharmony_ci      return PFMT_INPUTGAP;
59113498266Sopenharmony_ci
59213498266Sopenharmony_ci    /* based on the type, read the correct argument */
59313498266Sopenharmony_ci    switch(iptr->type) {
59413498266Sopenharmony_ci    case FORMAT_STRING:
59513498266Sopenharmony_ci      iptr->val.str = va_arg(arglist, char *);
59613498266Sopenharmony_ci      break;
59713498266Sopenharmony_ci
59813498266Sopenharmony_ci    case FORMAT_INTPTR:
59913498266Sopenharmony_ci    case FORMAT_PTR:
60013498266Sopenharmony_ci      iptr->val.ptr = va_arg(arglist, void *);
60113498266Sopenharmony_ci      break;
60213498266Sopenharmony_ci
60313498266Sopenharmony_ci    case FORMAT_LONGLONGU:
60413498266Sopenharmony_ci      iptr->val.numu = (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
60513498266Sopenharmony_ci      break;
60613498266Sopenharmony_ci
60713498266Sopenharmony_ci    case FORMAT_LONGLONG:
60813498266Sopenharmony_ci      iptr->val.nums = (mp_intmax_t)va_arg(arglist, mp_intmax_t);
60913498266Sopenharmony_ci      break;
61013498266Sopenharmony_ci
61113498266Sopenharmony_ci    case FORMAT_LONGU:
61213498266Sopenharmony_ci      iptr->val.numu = (mp_uintmax_t)va_arg(arglist, unsigned long);
61313498266Sopenharmony_ci      break;
61413498266Sopenharmony_ci
61513498266Sopenharmony_ci    case FORMAT_LONG:
61613498266Sopenharmony_ci      iptr->val.nums = (mp_intmax_t)va_arg(arglist, long);
61713498266Sopenharmony_ci      break;
61813498266Sopenharmony_ci
61913498266Sopenharmony_ci    case FORMAT_INTU:
62013498266Sopenharmony_ci      iptr->val.numu = (mp_uintmax_t)va_arg(arglist, unsigned int);
62113498266Sopenharmony_ci      break;
62213498266Sopenharmony_ci
62313498266Sopenharmony_ci    case FORMAT_INT:
62413498266Sopenharmony_ci    case FORMAT_WIDTH:
62513498266Sopenharmony_ci    case FORMAT_PRECISION:
62613498266Sopenharmony_ci      iptr->val.nums = (mp_intmax_t)va_arg(arglist, int);
62713498266Sopenharmony_ci      break;
62813498266Sopenharmony_ci
62913498266Sopenharmony_ci    case FORMAT_DOUBLE:
63013498266Sopenharmony_ci      iptr->val.dnum = va_arg(arglist, double);
63113498266Sopenharmony_ci      break;
63213498266Sopenharmony_ci
63313498266Sopenharmony_ci    default:
63413498266Sopenharmony_ci      DEBUGASSERT(NULL); /* unexpected */
63513498266Sopenharmony_ci      break;
63613498266Sopenharmony_ci    }
63713498266Sopenharmony_ci  }
63813498266Sopenharmony_ci  *ipieces = max_param + 1;
63913498266Sopenharmony_ci  *opieces = ocount;
64013498266Sopenharmony_ci
64113498266Sopenharmony_ci  return PFMT_OK;
64213498266Sopenharmony_ci}
64313498266Sopenharmony_ci
64413498266Sopenharmony_ci/*
64513498266Sopenharmony_ci * formatf() - the general printf function.
64613498266Sopenharmony_ci *
64713498266Sopenharmony_ci * It calls parsefmt() to parse the format string. It populates two arrays;
64813498266Sopenharmony_ci * one that describes the input arguments and one that describes a number of
64913498266Sopenharmony_ci * output segments.
65013498266Sopenharmony_ci *
65113498266Sopenharmony_ci * On success, the input array describes the type of all arguments and their
65213498266Sopenharmony_ci * values.
65313498266Sopenharmony_ci *
65413498266Sopenharmony_ci * The function then iterates over the output sengments and outputs them one
65513498266Sopenharmony_ci * by one until done. Using the appropriate input arguments (if any).
65613498266Sopenharmony_ci *
65713498266Sopenharmony_ci * All output is sent to the 'stream()' callback, one byte at a time.
65813498266Sopenharmony_ci */
65913498266Sopenharmony_ci
66013498266Sopenharmony_cistatic int formatf(
66113498266Sopenharmony_ci  void *userp, /* untouched by format(), just sent to the stream() function in
66213498266Sopenharmony_ci                  the second argument */
66313498266Sopenharmony_ci  /* function pointer called for each output character */
66413498266Sopenharmony_ci  int (*stream)(unsigned char, void *),
66513498266Sopenharmony_ci  const char *format,    /* %-formatted string */
66613498266Sopenharmony_ci  va_list ap_save) /* list of parameters */
66713498266Sopenharmony_ci{
66813498266Sopenharmony_ci  static const char nilstr[] = "(nil)";
66913498266Sopenharmony_ci  const char *digits = lower_digits;   /* Base-36 digits for numbers.  */
67013498266Sopenharmony_ci  int done = 0;   /* number of characters written  */
67113498266Sopenharmony_ci  int i;
67213498266Sopenharmony_ci  int ocount = 0; /* number of output segments */
67313498266Sopenharmony_ci  int icount = 0; /* number of input arguments */
67413498266Sopenharmony_ci
67513498266Sopenharmony_ci  struct outsegment output[MAX_SEGMENTS];
67613498266Sopenharmony_ci  struct va_input input[MAX_PARAMETERS];
67713498266Sopenharmony_ci  char work[BUFFSIZE];
67813498266Sopenharmony_ci
67913498266Sopenharmony_ci  /* 'workend' points to the final buffer byte position, but with an extra
68013498266Sopenharmony_ci     byte as margin to avoid the (false?) warning Coverity gives us
68113498266Sopenharmony_ci     otherwise */
68213498266Sopenharmony_ci  char *workend = &work[sizeof(work) - 2];
68313498266Sopenharmony_ci
68413498266Sopenharmony_ci  /* Parse the format string */
68513498266Sopenharmony_ci  if(parsefmt(format, output, input, &ocount, &icount, ap_save))
68613498266Sopenharmony_ci    return 0;
68713498266Sopenharmony_ci
68813498266Sopenharmony_ci  for(i = 0; i < ocount; i++) {
68913498266Sopenharmony_ci    struct outsegment *optr = &output[i];
69013498266Sopenharmony_ci    struct va_input *iptr;
69113498266Sopenharmony_ci    bool is_alt;            /* Format spec modifiers.  */
69213498266Sopenharmony_ci    int width;              /* Width of a field.  */
69313498266Sopenharmony_ci    int prec;               /* Precision of a field.  */
69413498266Sopenharmony_ci    bool is_neg;            /* Decimal integer is negative.  */
69513498266Sopenharmony_ci    unsigned long base;     /* Base of a number to be written.  */
69613498266Sopenharmony_ci    mp_uintmax_t num;       /* Integral values to be written.  */
69713498266Sopenharmony_ci    mp_intmax_t signed_num; /* Used to convert negative in positive.  */
69813498266Sopenharmony_ci    char *w;
69913498266Sopenharmony_ci    size_t outlen = optr->outlen;
70013498266Sopenharmony_ci    int flags = optr->flags;
70113498266Sopenharmony_ci
70213498266Sopenharmony_ci    if(outlen) {
70313498266Sopenharmony_ci      char *str = optr->start;
70413498266Sopenharmony_ci      for(; outlen && *str; outlen--)
70513498266Sopenharmony_ci        OUTCHAR(*str++);
70613498266Sopenharmony_ci      if(optr->flags & FLAGS_SUBSTR)
70713498266Sopenharmony_ci        /* this is just a substring */
70813498266Sopenharmony_ci        continue;
70913498266Sopenharmony_ci    }
71013498266Sopenharmony_ci
71113498266Sopenharmony_ci    /* pick up the specified width */
71213498266Sopenharmony_ci    if(flags & FLAGS_WIDTHPARAM) {
71313498266Sopenharmony_ci      width = (int)input[optr->width].val.nums;
71413498266Sopenharmony_ci      if(width < 0) {
71513498266Sopenharmony_ci        /* "A negative field width is taken as a '-' flag followed by a
71613498266Sopenharmony_ci           positive field width." */
71713498266Sopenharmony_ci        if(width == INT_MIN)
71813498266Sopenharmony_ci          width = INT_MAX;
71913498266Sopenharmony_ci        else
72013498266Sopenharmony_ci          width = -width;
72113498266Sopenharmony_ci        flags |= FLAGS_LEFT;
72213498266Sopenharmony_ci        flags &= ~FLAGS_PAD_NIL;
72313498266Sopenharmony_ci      }
72413498266Sopenharmony_ci    }
72513498266Sopenharmony_ci    else
72613498266Sopenharmony_ci      width = optr->width;
72713498266Sopenharmony_ci
72813498266Sopenharmony_ci    /* pick up the specified precision */
72913498266Sopenharmony_ci    if(flags & FLAGS_PRECPARAM) {
73013498266Sopenharmony_ci      prec = (int)input[optr->precision].val.nums;
73113498266Sopenharmony_ci      if(prec < 0)
73213498266Sopenharmony_ci        /* "A negative precision is taken as if the precision were
73313498266Sopenharmony_ci           omitted." */
73413498266Sopenharmony_ci        prec = -1;
73513498266Sopenharmony_ci    }
73613498266Sopenharmony_ci    else if(flags & FLAGS_PREC)
73713498266Sopenharmony_ci      prec = optr->precision;
73813498266Sopenharmony_ci    else
73913498266Sopenharmony_ci      prec = -1;
74013498266Sopenharmony_ci
74113498266Sopenharmony_ci    is_alt = (flags & FLAGS_ALT) ? 1 : 0;
74213498266Sopenharmony_ci    iptr = &input[optr->input];
74313498266Sopenharmony_ci
74413498266Sopenharmony_ci    switch(iptr->type) {
74513498266Sopenharmony_ci    case FORMAT_INTU:
74613498266Sopenharmony_ci    case FORMAT_LONGU:
74713498266Sopenharmony_ci    case FORMAT_LONGLONGU:
74813498266Sopenharmony_ci      flags |= FLAGS_UNSIGNED;
74913498266Sopenharmony_ci      FALLTHROUGH();
75013498266Sopenharmony_ci    case FORMAT_INT:
75113498266Sopenharmony_ci    case FORMAT_LONG:
75213498266Sopenharmony_ci    case FORMAT_LONGLONG:
75313498266Sopenharmony_ci      num = iptr->val.numu;
75413498266Sopenharmony_ci      if(flags & FLAGS_CHAR) {
75513498266Sopenharmony_ci        /* Character.  */
75613498266Sopenharmony_ci        if(!(flags & FLAGS_LEFT))
75713498266Sopenharmony_ci          while(--width > 0)
75813498266Sopenharmony_ci            OUTCHAR(' ');
75913498266Sopenharmony_ci        OUTCHAR((char) num);
76013498266Sopenharmony_ci        if(flags & FLAGS_LEFT)
76113498266Sopenharmony_ci          while(--width > 0)
76213498266Sopenharmony_ci            OUTCHAR(' ');
76313498266Sopenharmony_ci        break;
76413498266Sopenharmony_ci      }
76513498266Sopenharmony_ci      if(flags & FLAGS_OCTAL) {
76613498266Sopenharmony_ci        /* Octal unsigned integer */
76713498266Sopenharmony_ci        base = 8;
76813498266Sopenharmony_ci        is_neg = FALSE;
76913498266Sopenharmony_ci      }
77013498266Sopenharmony_ci      else if(flags & FLAGS_HEX) {
77113498266Sopenharmony_ci        /* Hexadecimal unsigned integer */
77213498266Sopenharmony_ci        digits = (flags & FLAGS_UPPER)? upper_digits : lower_digits;
77313498266Sopenharmony_ci        base = 16;
77413498266Sopenharmony_ci        is_neg = FALSE;
77513498266Sopenharmony_ci      }
77613498266Sopenharmony_ci      else if(flags & FLAGS_UNSIGNED) {
77713498266Sopenharmony_ci        /* Decimal unsigned integer */
77813498266Sopenharmony_ci        base = 10;
77913498266Sopenharmony_ci        is_neg = FALSE;
78013498266Sopenharmony_ci      }
78113498266Sopenharmony_ci      else {
78213498266Sopenharmony_ci        /* Decimal integer.  */
78313498266Sopenharmony_ci        base = 10;
78413498266Sopenharmony_ci
78513498266Sopenharmony_ci        is_neg = (iptr->val.nums < (mp_intmax_t)0);
78613498266Sopenharmony_ci        if(is_neg) {
78713498266Sopenharmony_ci          /* signed_num might fail to hold absolute negative minimum by 1 */
78813498266Sopenharmony_ci          signed_num = iptr->val.nums + (mp_intmax_t)1;
78913498266Sopenharmony_ci          signed_num = -signed_num;
79013498266Sopenharmony_ci          num = (mp_uintmax_t)signed_num;
79113498266Sopenharmony_ci          num += (mp_uintmax_t)1;
79213498266Sopenharmony_ci        }
79313498266Sopenharmony_ci      }
79413498266Sopenharmony_cinumber:
79513498266Sopenharmony_ci      /* Supply a default precision if none was given.  */
79613498266Sopenharmony_ci      if(prec == -1)
79713498266Sopenharmony_ci        prec = 1;
79813498266Sopenharmony_ci
79913498266Sopenharmony_ci      /* Put the number in WORK.  */
80013498266Sopenharmony_ci      w = workend;
80113498266Sopenharmony_ci      switch(base) {
80213498266Sopenharmony_ci      case 10:
80313498266Sopenharmony_ci        while(num > 0) {
80413498266Sopenharmony_ci          *w-- = (char)('0' + (num % 10));
80513498266Sopenharmony_ci          num /= 10;
80613498266Sopenharmony_ci        }
80713498266Sopenharmony_ci        break;
80813498266Sopenharmony_ci      default:
80913498266Sopenharmony_ci        while(num > 0) {
81013498266Sopenharmony_ci          *w-- = digits[num % base];
81113498266Sopenharmony_ci          num /= base;
81213498266Sopenharmony_ci        }
81313498266Sopenharmony_ci        break;
81413498266Sopenharmony_ci      }
81513498266Sopenharmony_ci      width -= (int)(workend - w);
81613498266Sopenharmony_ci      prec -= (int)(workend - w);
81713498266Sopenharmony_ci
81813498266Sopenharmony_ci      if(is_alt && base == 8 && prec <= 0) {
81913498266Sopenharmony_ci        *w-- = '0';
82013498266Sopenharmony_ci        --width;
82113498266Sopenharmony_ci      }
82213498266Sopenharmony_ci
82313498266Sopenharmony_ci      if(prec > 0) {
82413498266Sopenharmony_ci        width -= prec;
82513498266Sopenharmony_ci        while(prec-- > 0 && w >= work)
82613498266Sopenharmony_ci          *w-- = '0';
82713498266Sopenharmony_ci      }
82813498266Sopenharmony_ci
82913498266Sopenharmony_ci      if(is_alt && base == 16)
83013498266Sopenharmony_ci        width -= 2;
83113498266Sopenharmony_ci
83213498266Sopenharmony_ci      if(is_neg || (flags & FLAGS_SHOWSIGN) || (flags & FLAGS_SPACE))
83313498266Sopenharmony_ci        --width;
83413498266Sopenharmony_ci
83513498266Sopenharmony_ci      if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_PAD_NIL))
83613498266Sopenharmony_ci        while(width-- > 0)
83713498266Sopenharmony_ci          OUTCHAR(' ');
83813498266Sopenharmony_ci
83913498266Sopenharmony_ci      if(is_neg)
84013498266Sopenharmony_ci        OUTCHAR('-');
84113498266Sopenharmony_ci      else if(flags & FLAGS_SHOWSIGN)
84213498266Sopenharmony_ci        OUTCHAR('+');
84313498266Sopenharmony_ci      else if(flags & FLAGS_SPACE)
84413498266Sopenharmony_ci        OUTCHAR(' ');
84513498266Sopenharmony_ci
84613498266Sopenharmony_ci      if(is_alt && base == 16) {
84713498266Sopenharmony_ci        OUTCHAR('0');
84813498266Sopenharmony_ci        if(flags & FLAGS_UPPER)
84913498266Sopenharmony_ci          OUTCHAR('X');
85013498266Sopenharmony_ci        else
85113498266Sopenharmony_ci          OUTCHAR('x');
85213498266Sopenharmony_ci      }
85313498266Sopenharmony_ci
85413498266Sopenharmony_ci      if(!(flags & FLAGS_LEFT) && (flags & FLAGS_PAD_NIL))
85513498266Sopenharmony_ci        while(width-- > 0)
85613498266Sopenharmony_ci          OUTCHAR('0');
85713498266Sopenharmony_ci
85813498266Sopenharmony_ci      /* Write the number.  */
85913498266Sopenharmony_ci      while(++w <= workend) {
86013498266Sopenharmony_ci        OUTCHAR(*w);
86113498266Sopenharmony_ci      }
86213498266Sopenharmony_ci
86313498266Sopenharmony_ci      if(flags & FLAGS_LEFT)
86413498266Sopenharmony_ci        while(width-- > 0)
86513498266Sopenharmony_ci          OUTCHAR(' ');
86613498266Sopenharmony_ci      break;
86713498266Sopenharmony_ci
86813498266Sopenharmony_ci    case FORMAT_STRING: {
86913498266Sopenharmony_ci      const char *str;
87013498266Sopenharmony_ci      size_t len;
87113498266Sopenharmony_ci
87213498266Sopenharmony_ci      str = (char *)iptr->val.str;
87313498266Sopenharmony_ci      if(!str) {
87413498266Sopenharmony_ci        /* Write null string if there's space.  */
87513498266Sopenharmony_ci        if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) {
87613498266Sopenharmony_ci          str = nilstr;
87713498266Sopenharmony_ci          len = sizeof(nilstr) - 1;
87813498266Sopenharmony_ci          /* Disable quotes around (nil) */
87913498266Sopenharmony_ci          flags &= (~FLAGS_ALT);
88013498266Sopenharmony_ci        }
88113498266Sopenharmony_ci        else {
88213498266Sopenharmony_ci          str = "";
88313498266Sopenharmony_ci          len = 0;
88413498266Sopenharmony_ci        }
88513498266Sopenharmony_ci      }
88613498266Sopenharmony_ci      else if(prec != -1)
88713498266Sopenharmony_ci        len = (size_t)prec;
88813498266Sopenharmony_ci      else if(*str == '\0')
88913498266Sopenharmony_ci        len = 0;
89013498266Sopenharmony_ci      else
89113498266Sopenharmony_ci        len = strlen(str);
89213498266Sopenharmony_ci
89313498266Sopenharmony_ci      width -= (len > INT_MAX) ? INT_MAX : (int)len;
89413498266Sopenharmony_ci
89513498266Sopenharmony_ci      if(flags & FLAGS_ALT)
89613498266Sopenharmony_ci        OUTCHAR('"');
89713498266Sopenharmony_ci
89813498266Sopenharmony_ci      if(!(flags&FLAGS_LEFT))
89913498266Sopenharmony_ci        while(width-- > 0)
90013498266Sopenharmony_ci          OUTCHAR(' ');
90113498266Sopenharmony_ci
90213498266Sopenharmony_ci      for(; len && *str; len--)
90313498266Sopenharmony_ci        OUTCHAR(*str++);
90413498266Sopenharmony_ci      if(flags&FLAGS_LEFT)
90513498266Sopenharmony_ci        while(width-- > 0)
90613498266Sopenharmony_ci          OUTCHAR(' ');
90713498266Sopenharmony_ci
90813498266Sopenharmony_ci      if(flags & FLAGS_ALT)
90913498266Sopenharmony_ci        OUTCHAR('"');
91013498266Sopenharmony_ci      break;
91113498266Sopenharmony_ci    }
91213498266Sopenharmony_ci
91313498266Sopenharmony_ci    case FORMAT_PTR:
91413498266Sopenharmony_ci      /* Generic pointer.  */
91513498266Sopenharmony_ci      if(iptr->val.ptr) {
91613498266Sopenharmony_ci        /* If the pointer is not NULL, write it as a %#x spec.  */
91713498266Sopenharmony_ci        base = 16;
91813498266Sopenharmony_ci        digits = (flags & FLAGS_UPPER)? upper_digits : lower_digits;
91913498266Sopenharmony_ci        is_alt = TRUE;
92013498266Sopenharmony_ci        num = (size_t) iptr->val.ptr;
92113498266Sopenharmony_ci        is_neg = FALSE;
92213498266Sopenharmony_ci        goto number;
92313498266Sopenharmony_ci      }
92413498266Sopenharmony_ci      else {
92513498266Sopenharmony_ci        /* Write "(nil)" for a nil pointer.  */
92613498266Sopenharmony_ci        const char *point;
92713498266Sopenharmony_ci
92813498266Sopenharmony_ci        width -= (int)(sizeof(nilstr) - 1);
92913498266Sopenharmony_ci        if(flags & FLAGS_LEFT)
93013498266Sopenharmony_ci          while(width-- > 0)
93113498266Sopenharmony_ci            OUTCHAR(' ');
93213498266Sopenharmony_ci        for(point = nilstr; *point != '\0'; ++point)
93313498266Sopenharmony_ci          OUTCHAR(*point);
93413498266Sopenharmony_ci        if(!(flags & FLAGS_LEFT))
93513498266Sopenharmony_ci          while(width-- > 0)
93613498266Sopenharmony_ci            OUTCHAR(' ');
93713498266Sopenharmony_ci      }
93813498266Sopenharmony_ci      break;
93913498266Sopenharmony_ci
94013498266Sopenharmony_ci    case FORMAT_DOUBLE: {
94113498266Sopenharmony_ci      char formatbuf[32]="%";
94213498266Sopenharmony_ci      char *fptr = &formatbuf[1];
94313498266Sopenharmony_ci      size_t left = sizeof(formatbuf)-strlen(formatbuf);
94413498266Sopenharmony_ci      int len;
94513498266Sopenharmony_ci
94613498266Sopenharmony_ci      if(flags & FLAGS_WIDTH)
94713498266Sopenharmony_ci        width = optr->width;
94813498266Sopenharmony_ci
94913498266Sopenharmony_ci      if(flags & FLAGS_PREC)
95013498266Sopenharmony_ci        prec = optr->precision;
95113498266Sopenharmony_ci
95213498266Sopenharmony_ci      if(flags & FLAGS_LEFT)
95313498266Sopenharmony_ci        *fptr++ = '-';
95413498266Sopenharmony_ci      if(flags & FLAGS_SHOWSIGN)
95513498266Sopenharmony_ci        *fptr++ = '+';
95613498266Sopenharmony_ci      if(flags & FLAGS_SPACE)
95713498266Sopenharmony_ci        *fptr++ = ' ';
95813498266Sopenharmony_ci      if(flags & FLAGS_ALT)
95913498266Sopenharmony_ci        *fptr++ = '#';
96013498266Sopenharmony_ci
96113498266Sopenharmony_ci      *fptr = 0;
96213498266Sopenharmony_ci
96313498266Sopenharmony_ci      if(width >= 0) {
96413498266Sopenharmony_ci        if(width >= (int)sizeof(work))
96513498266Sopenharmony_ci          width = sizeof(work)-1;
96613498266Sopenharmony_ci        /* RECURSIVE USAGE */
96713498266Sopenharmony_ci        len = curl_msnprintf(fptr, left, "%d", width);
96813498266Sopenharmony_ci        fptr += len;
96913498266Sopenharmony_ci        left -= len;
97013498266Sopenharmony_ci      }
97113498266Sopenharmony_ci      if(prec >= 0) {
97213498266Sopenharmony_ci        /* for each digit in the integer part, we can have one less
97313498266Sopenharmony_ci           precision */
97413498266Sopenharmony_ci        size_t maxprec = sizeof(work) - 2;
97513498266Sopenharmony_ci        double val = iptr->val.dnum;
97613498266Sopenharmony_ci        if(width > 0 && prec <= width)
97713498266Sopenharmony_ci          maxprec -= width;
97813498266Sopenharmony_ci        while(val >= 10.0) {
97913498266Sopenharmony_ci          val /= 10;
98013498266Sopenharmony_ci          maxprec--;
98113498266Sopenharmony_ci        }
98213498266Sopenharmony_ci
98313498266Sopenharmony_ci        if(prec > (int)maxprec)
98413498266Sopenharmony_ci          prec = (int)maxprec-1;
98513498266Sopenharmony_ci        if(prec < 0)
98613498266Sopenharmony_ci          prec = 0;
98713498266Sopenharmony_ci        /* RECURSIVE USAGE */
98813498266Sopenharmony_ci        len = curl_msnprintf(fptr, left, ".%d", prec);
98913498266Sopenharmony_ci        fptr += len;
99013498266Sopenharmony_ci      }
99113498266Sopenharmony_ci      if(flags & FLAGS_LONG)
99213498266Sopenharmony_ci        *fptr++ = 'l';
99313498266Sopenharmony_ci
99413498266Sopenharmony_ci      if(flags & FLAGS_FLOATE)
99513498266Sopenharmony_ci        *fptr++ = (char)((flags & FLAGS_UPPER) ? 'E':'e');
99613498266Sopenharmony_ci      else if(flags & FLAGS_FLOATG)
99713498266Sopenharmony_ci        *fptr++ = (char)((flags & FLAGS_UPPER) ? 'G' : 'g');
99813498266Sopenharmony_ci      else
99913498266Sopenharmony_ci        *fptr++ = 'f';
100013498266Sopenharmony_ci
100113498266Sopenharmony_ci      *fptr = 0; /* and a final null-termination */
100213498266Sopenharmony_ci
100313498266Sopenharmony_ci#ifdef __clang__
100413498266Sopenharmony_ci#pragma clang diagnostic push
100513498266Sopenharmony_ci#pragma clang diagnostic ignored "-Wformat-nonliteral"
100613498266Sopenharmony_ci#endif
100713498266Sopenharmony_ci      /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
100813498266Sopenharmony_ci         output characters */
100913498266Sopenharmony_ci#ifdef HAVE_SNPRINTF
101013498266Sopenharmony_ci      (snprintf)(work, sizeof(work), formatbuf, iptr->val.dnum);
101113498266Sopenharmony_ci#else
101213498266Sopenharmony_ci      (sprintf)(work, formatbuf, iptr->val.dnum);
101313498266Sopenharmony_ci#endif
101413498266Sopenharmony_ci#ifdef __clang__
101513498266Sopenharmony_ci#pragma clang diagnostic pop
101613498266Sopenharmony_ci#endif
101713498266Sopenharmony_ci      DEBUGASSERT(strlen(work) <= sizeof(work));
101813498266Sopenharmony_ci      for(fptr = work; *fptr; fptr++)
101913498266Sopenharmony_ci        OUTCHAR(*fptr);
102013498266Sopenharmony_ci      break;
102113498266Sopenharmony_ci    }
102213498266Sopenharmony_ci
102313498266Sopenharmony_ci    case FORMAT_INTPTR:
102413498266Sopenharmony_ci      /* Answer the count of characters written.  */
102513498266Sopenharmony_ci#ifdef HAVE_LONG_LONG_TYPE
102613498266Sopenharmony_ci      if(flags & FLAGS_LONGLONG)
102713498266Sopenharmony_ci        *(LONG_LONG_TYPE *) iptr->val.ptr = (LONG_LONG_TYPE)done;
102813498266Sopenharmony_ci      else
102913498266Sopenharmony_ci#endif
103013498266Sopenharmony_ci        if(flags & FLAGS_LONG)
103113498266Sopenharmony_ci          *(long *) iptr->val.ptr = (long)done;
103213498266Sopenharmony_ci      else if(!(flags & FLAGS_SHORT))
103313498266Sopenharmony_ci        *(int *) iptr->val.ptr = (int)done;
103413498266Sopenharmony_ci      else
103513498266Sopenharmony_ci        *(short *) iptr->val.ptr = (short)done;
103613498266Sopenharmony_ci      break;
103713498266Sopenharmony_ci
103813498266Sopenharmony_ci    default:
103913498266Sopenharmony_ci      break;
104013498266Sopenharmony_ci    }
104113498266Sopenharmony_ci  }
104213498266Sopenharmony_ci  return done;
104313498266Sopenharmony_ci}
104413498266Sopenharmony_ci
104513498266Sopenharmony_ci/* fputc() look-alike */
104613498266Sopenharmony_cistatic int addbyter(unsigned char outc, void *f)
104713498266Sopenharmony_ci{
104813498266Sopenharmony_ci  struct nsprintf *infop = f;
104913498266Sopenharmony_ci  if(infop->length < infop->max) {
105013498266Sopenharmony_ci    /* only do this if we haven't reached max length yet */
105113498266Sopenharmony_ci    *infop->buffer++ = outc; /* store */
105213498266Sopenharmony_ci    infop->length++; /* we are now one byte larger */
105313498266Sopenharmony_ci    return 0;     /* fputc() returns like this on success */
105413498266Sopenharmony_ci  }
105513498266Sopenharmony_ci  return 1;
105613498266Sopenharmony_ci}
105713498266Sopenharmony_ci
105813498266Sopenharmony_ciint curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
105913498266Sopenharmony_ci                    va_list ap_save)
106013498266Sopenharmony_ci{
106113498266Sopenharmony_ci  int retcode;
106213498266Sopenharmony_ci  struct nsprintf info;
106313498266Sopenharmony_ci
106413498266Sopenharmony_ci  info.buffer = buffer;
106513498266Sopenharmony_ci  info.length = 0;
106613498266Sopenharmony_ci  info.max = maxlength;
106713498266Sopenharmony_ci
106813498266Sopenharmony_ci  retcode = formatf(&info, addbyter, format, ap_save);
106913498266Sopenharmony_ci  if(info.max) {
107013498266Sopenharmony_ci    /* we terminate this with a zero byte */
107113498266Sopenharmony_ci    if(info.max == info.length) {
107213498266Sopenharmony_ci      /* we're at maximum, scrap the last letter */
107313498266Sopenharmony_ci      info.buffer[-1] = 0;
107413498266Sopenharmony_ci      DEBUGASSERT(retcode);
107513498266Sopenharmony_ci      retcode--; /* don't count the nul byte */
107613498266Sopenharmony_ci    }
107713498266Sopenharmony_ci    else
107813498266Sopenharmony_ci      info.buffer[0] = 0;
107913498266Sopenharmony_ci  }
108013498266Sopenharmony_ci  return retcode;
108113498266Sopenharmony_ci}
108213498266Sopenharmony_ci
108313498266Sopenharmony_ciint curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
108413498266Sopenharmony_ci{
108513498266Sopenharmony_ci  int retcode;
108613498266Sopenharmony_ci  va_list ap_save; /* argument pointer */
108713498266Sopenharmony_ci  va_start(ap_save, format);
108813498266Sopenharmony_ci  retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
108913498266Sopenharmony_ci  va_end(ap_save);
109013498266Sopenharmony_ci  return retcode;
109113498266Sopenharmony_ci}
109213498266Sopenharmony_ci
109313498266Sopenharmony_ci/* fputc() look-alike */
109413498266Sopenharmony_cistatic int alloc_addbyter(unsigned char outc, void *f)
109513498266Sopenharmony_ci{
109613498266Sopenharmony_ci  struct asprintf *infop = f;
109713498266Sopenharmony_ci  CURLcode result = Curl_dyn_addn(infop->b, &outc, 1);
109813498266Sopenharmony_ci  if(result) {
109913498266Sopenharmony_ci    infop->merr = result == CURLE_TOO_LARGE ? MERR_TOO_LARGE : MERR_MEM;
110013498266Sopenharmony_ci    return 1 ; /* fail */
110113498266Sopenharmony_ci  }
110213498266Sopenharmony_ci  return 0;
110313498266Sopenharmony_ci}
110413498266Sopenharmony_ci
110513498266Sopenharmony_ci/* appends the formatted string, returns MERR error code */
110613498266Sopenharmony_ciint Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save)
110713498266Sopenharmony_ci{
110813498266Sopenharmony_ci  struct asprintf info;
110913498266Sopenharmony_ci  info.b = dyn;
111013498266Sopenharmony_ci  info.merr = MERR_OK;
111113498266Sopenharmony_ci
111213498266Sopenharmony_ci  (void)formatf(&info, alloc_addbyter, format, ap_save);
111313498266Sopenharmony_ci  if(info.merr) {
111413498266Sopenharmony_ci    Curl_dyn_free(info.b);
111513498266Sopenharmony_ci    return info.merr;
111613498266Sopenharmony_ci  }
111713498266Sopenharmony_ci  return 0;
111813498266Sopenharmony_ci}
111913498266Sopenharmony_ci
112013498266Sopenharmony_cichar *curl_mvaprintf(const char *format, va_list ap_save)
112113498266Sopenharmony_ci{
112213498266Sopenharmony_ci  struct asprintf info;
112313498266Sopenharmony_ci  struct dynbuf dyn;
112413498266Sopenharmony_ci  info.b = &dyn;
112513498266Sopenharmony_ci  Curl_dyn_init(info.b, DYN_APRINTF);
112613498266Sopenharmony_ci  info.merr = MERR_OK;
112713498266Sopenharmony_ci
112813498266Sopenharmony_ci  (void)formatf(&info, alloc_addbyter, format, ap_save);
112913498266Sopenharmony_ci  if(info.merr) {
113013498266Sopenharmony_ci    Curl_dyn_free(info.b);
113113498266Sopenharmony_ci    return NULL;
113213498266Sopenharmony_ci  }
113313498266Sopenharmony_ci  if(Curl_dyn_len(info.b))
113413498266Sopenharmony_ci    return Curl_dyn_ptr(info.b);
113513498266Sopenharmony_ci  return strdup("");
113613498266Sopenharmony_ci}
113713498266Sopenharmony_ci
113813498266Sopenharmony_cichar *curl_maprintf(const char *format, ...)
113913498266Sopenharmony_ci{
114013498266Sopenharmony_ci  va_list ap_save;
114113498266Sopenharmony_ci  char *s;
114213498266Sopenharmony_ci  va_start(ap_save, format);
114313498266Sopenharmony_ci  s = curl_mvaprintf(format, ap_save);
114413498266Sopenharmony_ci  va_end(ap_save);
114513498266Sopenharmony_ci  return s;
114613498266Sopenharmony_ci}
114713498266Sopenharmony_ci
114813498266Sopenharmony_cistatic int storebuffer(unsigned char outc, void *f)
114913498266Sopenharmony_ci{
115013498266Sopenharmony_ci  char **buffer = f;
115113498266Sopenharmony_ci  **buffer = outc;
115213498266Sopenharmony_ci  (*buffer)++;
115313498266Sopenharmony_ci  return 0;
115413498266Sopenharmony_ci}
115513498266Sopenharmony_ci
115613498266Sopenharmony_ciint curl_msprintf(char *buffer, const char *format, ...)
115713498266Sopenharmony_ci{
115813498266Sopenharmony_ci  va_list ap_save; /* argument pointer */
115913498266Sopenharmony_ci  int retcode;
116013498266Sopenharmony_ci  va_start(ap_save, format);
116113498266Sopenharmony_ci  retcode = formatf(&buffer, storebuffer, format, ap_save);
116213498266Sopenharmony_ci  va_end(ap_save);
116313498266Sopenharmony_ci  *buffer = 0; /* we terminate this with a zero byte */
116413498266Sopenharmony_ci  return retcode;
116513498266Sopenharmony_ci}
116613498266Sopenharmony_ci
116713498266Sopenharmony_cistatic int fputc_wrapper(unsigned char outc, void *f)
116813498266Sopenharmony_ci{
116913498266Sopenharmony_ci  int out = outc;
117013498266Sopenharmony_ci  FILE *s = f;
117113498266Sopenharmony_ci  int rc = fputc(out, s);
117213498266Sopenharmony_ci  if(rc == out)
117313498266Sopenharmony_ci    return 0;
117413498266Sopenharmony_ci  return 1;
117513498266Sopenharmony_ci}
117613498266Sopenharmony_ci
117713498266Sopenharmony_ciint curl_mprintf(const char *format, ...)
117813498266Sopenharmony_ci{
117913498266Sopenharmony_ci  int retcode;
118013498266Sopenharmony_ci  va_list ap_save; /* argument pointer */
118113498266Sopenharmony_ci  va_start(ap_save, format);
118213498266Sopenharmony_ci
118313498266Sopenharmony_ci  retcode = formatf(stdout, fputc_wrapper, format, ap_save);
118413498266Sopenharmony_ci  va_end(ap_save);
118513498266Sopenharmony_ci  return retcode;
118613498266Sopenharmony_ci}
118713498266Sopenharmony_ci
118813498266Sopenharmony_ciint curl_mfprintf(FILE *whereto, const char *format, ...)
118913498266Sopenharmony_ci{
119013498266Sopenharmony_ci  int retcode;
119113498266Sopenharmony_ci  va_list ap_save; /* argument pointer */
119213498266Sopenharmony_ci  va_start(ap_save, format);
119313498266Sopenharmony_ci  retcode = formatf(whereto, fputc_wrapper, format, ap_save);
119413498266Sopenharmony_ci  va_end(ap_save);
119513498266Sopenharmony_ci  return retcode;
119613498266Sopenharmony_ci}
119713498266Sopenharmony_ci
119813498266Sopenharmony_ciint curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
119913498266Sopenharmony_ci{
120013498266Sopenharmony_ci  int retcode = formatf(&buffer, storebuffer, format, ap_save);
120113498266Sopenharmony_ci  *buffer = 0; /* we terminate this with a zero byte */
120213498266Sopenharmony_ci  return retcode;
120313498266Sopenharmony_ci}
120413498266Sopenharmony_ci
120513498266Sopenharmony_ciint curl_mvprintf(const char *format, va_list ap_save)
120613498266Sopenharmony_ci{
120713498266Sopenharmony_ci  return formatf(stdout, fputc_wrapper, format, ap_save);
120813498266Sopenharmony_ci}
120913498266Sopenharmony_ci
121013498266Sopenharmony_ciint curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
121113498266Sopenharmony_ci{
121213498266Sopenharmony_ci  return formatf(whereto, fputc_wrapper, format, ap_save);
121313498266Sopenharmony_ci}
1214