extensions/sqlite/sqlite-source/printf.c
author David Anderson <dvander@alliedmods.net>
Sun Oct 28 05:48:06 2007 +0000 (2007-10-28)
changeset 1645 27307df4d711
parent 1203 633c25ce6405
permissions -rw-r--r--
updated to sqlite-3.5.1 now that it's stable
used new shared cache functionality (yay)
dvander@1203
     1
/*
dvander@1203
     2
** The "printf" code that follows dates from the 1980's.  It is in
dvander@1203
     3
** the public domain.  The original comments are included here for
dvander@1203
     4
** completeness.  They are very out-of-date but might be useful as
dvander@1203
     5
** an historical reference.  Most of the "enhancements" have been backed
dvander@1203
     6
** out so that the functionality is now the same as standard printf().
dvander@1203
     7
**
dvander@1203
     8
**************************************************************************
dvander@1203
     9
**
dvander@1203
    10
** The following modules is an enhanced replacement for the "printf" subroutines
dvander@1203
    11
** found in the standard C library.  The following enhancements are
dvander@1203
    12
** supported:
dvander@1203
    13
**
dvander@1203
    14
**      +  Additional functions.  The standard set of "printf" functions
dvander@1203
    15
**         includes printf, fprintf, sprintf, vprintf, vfprintf, and
dvander@1203
    16
**         vsprintf.  This module adds the following:
dvander@1203
    17
**
dvander@1203
    18
**           *  snprintf -- Works like sprintf, but has an extra argument
dvander@1203
    19
**                          which is the size of the buffer written to.
dvander@1203
    20
**
dvander@1203
    21
**           *  mprintf --  Similar to sprintf.  Writes output to memory
dvander@1203
    22
**                          obtained from malloc.
dvander@1203
    23
**
dvander@1203
    24
**           *  xprintf --  Calls a function to dispose of output.
dvander@1203
    25
**
dvander@1203
    26
**           *  nprintf --  No output, but returns the number of characters
dvander@1203
    27
**                          that would have been output by printf.
dvander@1203
    28
**
dvander@1203
    29
**           *  A v- version (ex: vsnprintf) of every function is also
dvander@1203
    30
**              supplied.
dvander@1203
    31
**
dvander@1203
    32
**      +  A few extensions to the formatting notation are supported:
dvander@1203
    33
**
dvander@1203
    34
**           *  The "=" flag (similar to "-") causes the output to be
dvander@1203
    35
**              be centered in the appropriately sized field.
dvander@1203
    36
**
dvander@1203
    37
**           *  The %b field outputs an integer in binary notation.
dvander@1203
    38
**
dvander@1203
    39
**           *  The %c field now accepts a precision.  The character output
dvander@1203
    40
**              is repeated by the number of times the precision specifies.
dvander@1203
    41
**
dvander@1203
    42
**           *  The %' field works like %c, but takes as its character the
dvander@1203
    43
**              next character of the format string, instead of the next
dvander@1203
    44
**              argument.  For example,  printf("%.78'-")  prints 78 minus
dvander@1203
    45
**              signs, the same as  printf("%.78c",'-').
dvander@1203
    46
**
dvander@1203
    47
**      +  When compiled using GCC on a SPARC, this version of printf is
dvander@1203
    48
**         faster than the library printf for SUN OS 4.1.
dvander@1203
    49
**
dvander@1203
    50
**      +  All functions are fully reentrant.
dvander@1203
    51
**
dvander@1203
    52
*/
dvander@1203
    53
#include "sqliteInt.h"
dvander@1203
    54
#include <math.h>
dvander@1203
    55
dvander@1203
    56
/*
dvander@1203
    57
** Conversion types fall into various categories as defined by the
dvander@1203
    58
** following enumeration.
dvander@1203
    59
*/
dvander@1203
    60
#define etRADIX       1 /* Integer types.  %d, %x, %o, and so forth */
dvander@1203
    61
#define etFLOAT       2 /* Floating point.  %f */
dvander@1203
    62
#define etEXP         3 /* Exponentional notation. %e and %E */
dvander@1203
    63
#define etGENERIC     4 /* Floating or exponential, depending on exponent. %g */
dvander@1203
    64
#define etSIZE        5 /* Return number of characters processed so far. %n */
dvander@1203
    65
#define etSTRING      6 /* Strings. %s */
dvander@1203
    66
#define etDYNSTRING   7 /* Dynamically allocated strings. %z */
dvander@1203
    67
#define etPERCENT     8 /* Percent symbol. %% */
dvander@1203
    68
#define etCHARX       9 /* Characters. %c */
dvander@1203
    69
/* The rest are extensions, not normally found in printf() */
dvander@1203
    70
#define etCHARLIT    10 /* Literal characters.  %' */
dvander@1203
    71
#define etSQLESCAPE  11 /* Strings with '\'' doubled.  %q */
dvander@1203
    72
#define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '',
dvander@1203
    73
                          NULL pointers replaced by SQL NULL.  %Q */
dvander@1203
    74
#define etTOKEN      13 /* a pointer to a Token structure */
dvander@1203
    75
#define etSRCLIST    14 /* a pointer to a SrcList */
dvander@1203
    76
#define etPOINTER    15 /* The %p conversion */
dvander@1203
    77
#define etSQLESCAPE3 16 /* %w -> Strings with '\"' doubled */
dvander@1203
    78
dvander@1203
    79
dvander@1203
    80
/*
dvander@1203
    81
** An "etByte" is an 8-bit unsigned value.
dvander@1203
    82
*/
dvander@1203
    83
typedef unsigned char etByte;
dvander@1203
    84
dvander@1203
    85
/*
dvander@1203
    86
** Each builtin conversion character (ex: the 'd' in "%d") is described
dvander@1203
    87
** by an instance of the following structure
dvander@1203
    88
*/
dvander@1203
    89
typedef struct et_info {   /* Information about each format field */
dvander@1203
    90
  char fmttype;            /* The format field code letter */
dvander@1203
    91
  etByte base;             /* The base for radix conversion */
dvander@1203
    92
  etByte flags;            /* One or more of FLAG_ constants below */
dvander@1203
    93
  etByte type;             /* Conversion paradigm */
dvander@1203
    94
  etByte charset;          /* Offset into aDigits[] of the digits string */
dvander@1203
    95
  etByte prefix;           /* Offset into aPrefix[] of the prefix string */
dvander@1203
    96
} et_info;
dvander@1203
    97
dvander@1203
    98
/*
dvander@1203
    99
** Allowed values for et_info.flags
dvander@1203
   100
*/
dvander@1203
   101
#define FLAG_SIGNED  1     /* True if the value to convert is signed */
dvander@1203
   102
#define FLAG_INTERN  2     /* True if for internal use only */
dvander@1203
   103
#define FLAG_STRING  4     /* Allow infinity precision */
dvander@1203
   104
dvander@1203
   105
dvander@1203
   106
/*
dvander@1203
   107
** The following table is searched linearly, so it is good to put the
dvander@1203
   108
** most frequently used conversion types first.
dvander@1203
   109
*/
dvander@1203
   110
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
dvander@1203
   111
static const char aPrefix[] = "-x0\000X0";
dvander@1203
   112
static const et_info fmtinfo[] = {
dvander@1203
   113
  {  'd', 10, 1, etRADIX,      0,  0 },
dvander@1203
   114
  {  's',  0, 4, etSTRING,     0,  0 },
dvander@1203
   115
  {  'g',  0, 1, etGENERIC,    30, 0 },
dvander@1645
   116
  {  'z',  0, 4, etDYNSTRING,  0,  0 },
dvander@1203
   117
  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
dvander@1203
   118
  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
dvander@1203
   119
  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
dvander@1203
   120
  {  'c',  0, 0, etCHARX,      0,  0 },
dvander@1203
   121
  {  'o',  8, 0, etRADIX,      0,  2 },
dvander@1203
   122
  {  'u', 10, 0, etRADIX,      0,  0 },
dvander@1203
   123
  {  'x', 16, 0, etRADIX,      16, 1 },
dvander@1203
   124
  {  'X', 16, 0, etRADIX,      0,  4 },
dvander@1203
   125
#ifndef SQLITE_OMIT_FLOATING_POINT
dvander@1203
   126
  {  'f',  0, 1, etFLOAT,      0,  0 },
dvander@1203
   127
  {  'e',  0, 1, etEXP,        30, 0 },
dvander@1203
   128
  {  'E',  0, 1, etEXP,        14, 0 },
dvander@1203
   129
  {  'G',  0, 1, etGENERIC,    14, 0 },
dvander@1203
   130
#endif
dvander@1203
   131
  {  'i', 10, 1, etRADIX,      0,  0 },
dvander@1203
   132
  {  'n',  0, 0, etSIZE,       0,  0 },
dvander@1203
   133
  {  '%',  0, 0, etPERCENT,    0,  0 },
dvander@1203
   134
  {  'p', 16, 0, etPOINTER,    0,  1 },
dvander@1203
   135
  {  'T',  0, 2, etTOKEN,      0,  0 },
dvander@1203
   136
  {  'S',  0, 2, etSRCLIST,    0,  0 },
dvander@1203
   137
};
dvander@1203
   138
#define etNINFO  (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
dvander@1203
   139
dvander@1203
   140
/*
dvander@1203
   141
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
dvander@1203
   142
** conversions will work.
dvander@1203
   143
*/
dvander@1203
   144
#ifndef SQLITE_OMIT_FLOATING_POINT
dvander@1203
   145
/*
dvander@1203
   146
** "*val" is a double such that 0.1 <= *val < 10.0
dvander@1203
   147
** Return the ascii code for the leading digit of *val, then
dvander@1203
   148
** multiply "*val" by 10.0 to renormalize.
dvander@1203
   149
**
dvander@1203
   150
** Example:
dvander@1203
   151
**     input:     *val = 3.14159
dvander@1203
   152
**     output:    *val = 1.4159    function return = '3'
dvander@1203
   153
**
dvander@1203
   154
** The counter *cnt is incremented each time.  After counter exceeds
dvander@1203
   155
** 16 (the number of significant digits in a 64-bit float) '0' is
dvander@1203
   156
** always returned.
dvander@1203
   157
*/
dvander@1203
   158
static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
dvander@1203
   159
  int digit;
dvander@1203
   160
  LONGDOUBLE_TYPE d;
dvander@1203
   161
  if( (*cnt)++ >= 16 ) return '0';
dvander@1203
   162
  digit = (int)*val;
dvander@1203
   163
  d = digit;
dvander@1203
   164
  digit += '0';
dvander@1203
   165
  *val = (*val - d)*10.0;
dvander@1203
   166
  return digit;
dvander@1203
   167
}
dvander@1203
   168
#endif /* SQLITE_OMIT_FLOATING_POINT */
dvander@1203
   169
dvander@1203
   170
/*
dvander@1203
   171
** On machines with a small stack size, you can redefine the
dvander@1203
   172
** SQLITE_PRINT_BUF_SIZE to be less than 350.  But beware - for
dvander@1203
   173
** smaller values some %f conversions may go into an infinite loop.
dvander@1203
   174
*/
dvander@1203
   175
#ifndef SQLITE_PRINT_BUF_SIZE
dvander@1203
   176
# define SQLITE_PRINT_BUF_SIZE 350
dvander@1203
   177
#endif
dvander@1203
   178
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE  /* Size of the output buffer */
dvander@1203
   179
dvander@1203
   180
/*
dvander@1203
   181
** The root program.  All variations call this core.
dvander@1203
   182
**
dvander@1203
   183
** INPUTS:
dvander@1203
   184
**   func   This is a pointer to a function taking three arguments
dvander@1203
   185
**            1. A pointer to anything.  Same as the "arg" parameter.
dvander@1203
   186
**            2. A pointer to the list of characters to be output
dvander@1203
   187
**               (Note, this list is NOT null terminated.)
dvander@1203
   188
**            3. An integer number of characters to be output.
dvander@1203
   189
**               (Note: This number might be zero.)
dvander@1203
   190
**
dvander@1203
   191
**   arg    This is the pointer to anything which will be passed as the
dvander@1203
   192
**          first argument to "func".  Use it for whatever you like.
dvander@1203
   193
**
dvander@1203
   194
**   fmt    This is the format string, as in the usual print.
dvander@1203
   195
**
dvander@1203
   196
**   ap     This is a pointer to a list of arguments.  Same as in
dvander@1203
   197
**          vfprint.
dvander@1203
   198
**
dvander@1203
   199
** OUTPUTS:
dvander@1203
   200
**          The return value is the total number of characters sent to
dvander@1203
   201
**          the function "func".  Returns -1 on a error.
dvander@1203
   202
**
dvander@1203
   203
** Note that the order in which automatic variables are declared below
dvander@1203
   204
** seems to make a big difference in determining how fast this beast
dvander@1203
   205
** will run.
dvander@1203
   206
*/
dvander@1203
   207
static int vxprintf(
dvander@1203
   208
  void (*func)(void*,const char*,int),     /* Consumer of text */
dvander@1203
   209
  void *arg,                         /* First argument to the consumer */
dvander@1203
   210
  int useExtended,                   /* Allow extended %-conversions */
dvander@1203
   211
  const char *fmt,                   /* Format string */
dvander@1203
   212
  va_list ap                         /* arguments */
dvander@1203
   213
){
dvander@1203
   214
  int c;                     /* Next character in the format string */
dvander@1203
   215
  char *bufpt;               /* Pointer to the conversion buffer */
dvander@1203
   216
  int precision;             /* Precision of the current field */
dvander@1203
   217
  int length;                /* Length of the field */
dvander@1203
   218
  int idx;                   /* A general purpose loop counter */
dvander@1203
   219
  int count;                 /* Total number of characters output */
dvander@1203
   220
  int width;                 /* Width of the current field */
dvander@1203
   221
  etByte flag_leftjustify;   /* True if "-" flag is present */
dvander@1203
   222
  etByte flag_plussign;      /* True if "+" flag is present */
dvander@1203
   223
  etByte flag_blanksign;     /* True if " " flag is present */
dvander@1203
   224
  etByte flag_alternateform; /* True if "#" flag is present */
dvander@1203
   225
  etByte flag_altform2;      /* True if "!" flag is present */
dvander@1203
   226
  etByte flag_zeropad;       /* True if field width constant starts with zero */
dvander@1203
   227
  etByte flag_long;          /* True if "l" flag is present */
dvander@1203
   228
  etByte flag_longlong;      /* True if the "ll" flag is present */
dvander@1203
   229
  etByte done;               /* Loop termination flag */
dvander@1203
   230
  sqlite_uint64 longvalue;   /* Value for integer types */
dvander@1203
   231
  LONGDOUBLE_TYPE realvalue; /* Value for real types */
dvander@1203
   232
  const et_info *infop;      /* Pointer to the appropriate info structure */
dvander@1203
   233
  char buf[etBUFSIZE];       /* Conversion buffer */
dvander@1203
   234
  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
dvander@1203
   235
  etByte errorflag = 0;      /* True if an error is encountered */
dvander@1203
   236
  etByte xtype;              /* Conversion paradigm */
dvander@1203
   237
  char *zExtra;              /* Extra memory used for etTCLESCAPE conversions */
dvander@1203
   238
  static const char spaces[] =
dvander@1203
   239
   "                                                                         ";
dvander@1203
   240
#define etSPACESIZE (sizeof(spaces)-1)
dvander@1203
   241
#ifndef SQLITE_OMIT_FLOATING_POINT
dvander@1203
   242
  int  exp, e2;              /* exponent of real numbers */
dvander@1203
   243
  double rounder;            /* Used for rounding floating point values */
dvander@1203
   244
  etByte flag_dp;            /* True if decimal point should be shown */
dvander@1203
   245
  etByte flag_rtz;           /* True if trailing zeros should be removed */
dvander@1203
   246
  etByte flag_exp;           /* True to force display of the exponent */
dvander@1203
   247
  int nsd;                   /* Number of significant digits returned */
dvander@1203
   248
#endif
dvander@1203
   249
dvander@1203
   250
  func(arg,"",0);
dvander@1203
   251
  count = length = 0;
dvander@1203
   252
  bufpt = 0;
dvander@1203
   253
  for(; (c=(*fmt))!=0; ++fmt){
dvander@1203
   254
    if( c!='%' ){
dvander@1203
   255
      int amt;
dvander@1203
   256
      bufpt = (char *)fmt;
dvander@1203
   257
      amt = 1;
dvander@1203
   258
      while( (c=(*++fmt))!='%' && c!=0 ) amt++;
dvander@1203
   259
      (*func)(arg,bufpt,amt);
dvander@1203
   260
      count += amt;
dvander@1203
   261
      if( c==0 ) break;
dvander@1203
   262
    }
dvander@1203
   263
    if( (c=(*++fmt))==0 ){
dvander@1203
   264
      errorflag = 1;
dvander@1203
   265
      (*func)(arg,"%",1);
dvander@1203
   266
      count++;
dvander@1203
   267
      break;
dvander@1203
   268
    }
dvander@1203
   269
    /* Find out what flags are present */
dvander@1203
   270
    flag_leftjustify = flag_plussign = flag_blanksign = 
dvander@1203
   271
     flag_alternateform = flag_altform2 = flag_zeropad = 0;
dvander@1203
   272
    done = 0;
dvander@1203
   273
    do{
dvander@1203
   274
      switch( c ){
dvander@1203
   275
        case '-':   flag_leftjustify = 1;     break;
dvander@1203
   276
        case '+':   flag_plussign = 1;        break;
dvander@1203
   277
        case ' ':   flag_blanksign = 1;       break;
dvander@1203
   278
        case '#':   flag_alternateform = 1;   break;
dvander@1203
   279
        case '!':   flag_altform2 = 1;        break;
dvander@1203
   280
        case '0':   flag_zeropad = 1;         break;
dvander@1203
   281
        default:    done = 1;                 break;
dvander@1203
   282
      }
dvander@1203
   283
    }while( !done && (c=(*++fmt))!=0 );
dvander@1203
   284
    /* Get the field width */
dvander@1203
   285
    width = 0;
dvander@1203
   286
    if( c=='*' ){
dvander@1203
   287
      width = va_arg(ap,int);
dvander@1203
   288
      if( width<0 ){
dvander@1203
   289
        flag_leftjustify = 1;
dvander@1203
   290
        width = -width;
dvander@1203
   291
      }
dvander@1203
   292
      c = *++fmt;
dvander@1203
   293
    }else{
dvander@1203
   294
      while( c>='0' && c<='9' ){
dvander@1203
   295
        width = width*10 + c - '0';
dvander@1203
   296
        c = *++fmt;
dvander@1203
   297
      }
dvander@1203
   298
    }
dvander@1203
   299
    if( width > etBUFSIZE-10 ){
dvander@1203
   300
      width = etBUFSIZE-10;
dvander@1203
   301
    }
dvander@1203
   302
    /* Get the precision */
dvander@1203
   303
    if( c=='.' ){
dvander@1203
   304
      precision = 0;
dvander@1203
   305
      c = *++fmt;
dvander@1203
   306
      if( c=='*' ){
dvander@1203
   307
        precision = va_arg(ap,int);
dvander@1203
   308
        if( precision<0 ) precision = -precision;
dvander@1203
   309
        c = *++fmt;
dvander@1203
   310
      }else{
dvander@1203
   311
        while( c>='0' && c<='9' ){
dvander@1203
   312
          precision = precision*10 + c - '0';
dvander@1203
   313
          c = *++fmt;
dvander@1203
   314
        }
dvander@1203
   315
      }
dvander@1203
   316
    }else{
dvander@1203
   317
      precision = -1;
dvander@1203
   318
    }
dvander@1203
   319
    /* Get the conversion type modifier */
dvander@1203
   320
    if( c=='l' ){
dvander@1203
   321
      flag_long = 1;
dvander@1203
   322
      c = *++fmt;
dvander@1203
   323
      if( c=='l' ){
dvander@1203
   324
        flag_longlong = 1;
dvander@1203
   325
        c = *++fmt;
dvander@1203
   326
      }else{
dvander@1203
   327
        flag_longlong = 0;
dvander@1203
   328
      }
dvander@1203
   329
    }else{
dvander@1203
   330
      flag_long = flag_longlong = 0;
dvander@1203
   331
    }
dvander@1203
   332
    /* Fetch the info entry for the field */
dvander@1203
   333
    infop = 0;
dvander@1203
   334
    for(idx=0; idx<etNINFO; idx++){
dvander@1203
   335
      if( c==fmtinfo[idx].fmttype ){
dvander@1203
   336
        infop = &fmtinfo[idx];
dvander@1203
   337
        if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
dvander@1203
   338
          xtype = infop->type;
dvander@1203
   339
        }else{
dvander@1203
   340
          return -1;
dvander@1203
   341
        }
dvander@1203
   342
        break;
dvander@1203
   343
      }
dvander@1203
   344
    }
dvander@1203
   345
    zExtra = 0;
dvander@1203
   346
    if( infop==0 ){
dvander@1203
   347
      return -1;
dvander@1203
   348
    }
dvander@1203
   349
dvander@1203
   350
dvander@1203
   351
    /* Limit the precision to prevent overflowing buf[] during conversion */
dvander@1203
   352
    if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
dvander@1203
   353
      precision = etBUFSIZE-40;
dvander@1203
   354
    }
dvander@1203
   355
dvander@1203
   356
    /*
dvander@1203
   357
    ** At this point, variables are initialized as follows:
dvander@1203
   358
    **
dvander@1203
   359
    **   flag_alternateform          TRUE if a '#' is present.
dvander@1203
   360
    **   flag_altform2               TRUE if a '!' is present.
dvander@1203
   361
    **   flag_plussign               TRUE if a '+' is present.
dvander@1203
   362
    **   flag_leftjustify            TRUE if a '-' is present or if the
dvander@1203
   363
    **                               field width was negative.
dvander@1203
   364
    **   flag_zeropad                TRUE if the width began with 0.
dvander@1203
   365
    **   flag_long                   TRUE if the letter 'l' (ell) prefixed
dvander@1203
   366
    **                               the conversion character.
dvander@1203
   367
    **   flag_longlong               TRUE if the letter 'll' (ell ell) prefixed
dvander@1203
   368
    **                               the conversion character.
dvander@1203
   369
    **   flag_blanksign              TRUE if a ' ' is present.
dvander@1203
   370
    **   width                       The specified field width.  This is
dvander@1203
   371
    **                               always non-negative.  Zero is the default.
dvander@1203
   372
    **   precision                   The specified precision.  The default
dvander@1203
   373
    **                               is -1.
dvander@1203
   374
    **   xtype                       The class of the conversion.
dvander@1203
   375
    **   infop                       Pointer to the appropriate info struct.
dvander@1203
   376
    */
dvander@1203
   377
    switch( xtype ){
dvander@1203
   378
      case etPOINTER:
dvander@1203
   379
        flag_longlong = sizeof(char*)==sizeof(i64);
dvander@1203
   380
        flag_long = sizeof(char*)==sizeof(long int);
dvander@1203
   381
        /* Fall through into the next case */
dvander@1203
   382
      case etRADIX:
dvander@1203
   383
        if( infop->flags & FLAG_SIGNED ){
dvander@1203
   384
          i64 v;
dvander@1203
   385
          if( flag_longlong )   v = va_arg(ap,i64);
dvander@1203
   386
          else if( flag_long )  v = va_arg(ap,long int);
dvander@1203
   387
          else                  v = va_arg(ap,int);
dvander@1203
   388
          if( v<0 ){
dvander@1203
   389
            longvalue = -v;
dvander@1203
   390
            prefix = '-';
dvander@1203
   391
          }else{
dvander@1203
   392
            longvalue = v;
dvander@1203
   393
            if( flag_plussign )        prefix = '+';
dvander@1203
   394
            else if( flag_blanksign )  prefix = ' ';
dvander@1203
   395
            else                       prefix = 0;
dvander@1203
   396
          }
dvander@1203
   397
        }else{
dvander@1203
   398
          if( flag_longlong )   longvalue = va_arg(ap,u64);
dvander@1203
   399
          else if( flag_long )  longvalue = va_arg(ap,unsigned long int);
dvander@1203
   400
          else                  longvalue = va_arg(ap,unsigned int);
dvander@1203
   401
          prefix = 0;
dvander@1203
   402
        }
dvander@1203
   403
        if( longvalue==0 ) flag_alternateform = 0;
dvander@1203
   404
        if( flag_zeropad && precision<width-(prefix!=0) ){
dvander@1203
   405
          precision = width-(prefix!=0);
dvander@1203
   406
        }
dvander@1203
   407
        bufpt = &buf[etBUFSIZE-1];
dvander@1203
   408
        {
dvander@1203
   409
          register const char *cset;      /* Use registers for speed */
dvander@1203
   410
          register int base;
dvander@1203
   411
          cset = &aDigits[infop->charset];
dvander@1203
   412
          base = infop->base;
dvander@1203
   413
          do{                                           /* Convert to ascii */
dvander@1203
   414
            *(--bufpt) = cset[longvalue%base];
dvander@1203
   415
            longvalue = longvalue/base;
dvander@1203
   416
          }while( longvalue>0 );
dvander@1203
   417
        }
dvander@1203
   418
        length = &buf[etBUFSIZE-1]-bufpt;
dvander@1203
   419
        for(idx=precision-length; idx>0; idx--){
dvander@1203
   420
          *(--bufpt) = '0';                             /* Zero pad */
dvander@1203
   421
        }
dvander@1203
   422
        if( prefix ) *(--bufpt) = prefix;               /* Add sign */
dvander@1203
   423
        if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */
dvander@1203
   424
          const char *pre;
dvander@1203
   425
          char x;
dvander@1203
   426
          pre = &aPrefix[infop->prefix];
dvander@1203
   427
          if( *bufpt!=pre[0] ){
dvander@1203
   428
            for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
dvander@1203
   429
          }
dvander@1203
   430
        }
dvander@1203
   431
        length = &buf[etBUFSIZE-1]-bufpt;
dvander@1203
   432
        break;
dvander@1203
   433
      case etFLOAT:
dvander@1203
   434
      case etEXP:
dvander@1203
   435
      case etGENERIC:
dvander@1203
   436
        realvalue = va_arg(ap,double);
dvander@1203
   437
#ifndef SQLITE_OMIT_FLOATING_POINT
dvander@1203
   438
        if( precision<0 ) precision = 6;         /* Set default precision */
dvander@1203
   439
        if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
dvander@1203
   440
        if( realvalue<0.0 ){
dvander@1203
   441
          realvalue = -realvalue;
dvander@1203
   442
          prefix = '-';
dvander@1203
   443
        }else{
dvander@1203
   444
          if( flag_plussign )          prefix = '+';
dvander@1203
   445
          else if( flag_blanksign )    prefix = ' ';
dvander@1203
   446
          else                         prefix = 0;
dvander@1203
   447
        }
dvander@1203
   448
        if( xtype==etGENERIC && precision>0 ) precision--;
dvander@1203
   449
#if 0
dvander@1203
   450
        /* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
dvander@1203
   451
        for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
dvander@1203
   452
#else
dvander@1203
   453
        /* It makes more sense to use 0.5 */
dvander@1203
   454
        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
dvander@1203
   455
#endif
dvander@1203
   456
        if( xtype==etFLOAT ) realvalue += rounder;
dvander@1203
   457
        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
dvander@1203
   458
        exp = 0;
dvander@1203
   459
        if( sqlite3_isnan(realvalue) ){
dvander@1203
   460
          bufpt = "NaN";
dvander@1203
   461
          length = 3;
dvander@1203
   462
          break;
dvander@1203
   463
        }
dvander@1203
   464
        if( realvalue>0.0 ){
dvander@1203
   465
          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
dvander@1203
   466
          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
dvander@1203
   467
          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
dvander@1203
   468
          while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
dvander@1203
   469
          while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
dvander@1203
   470
          if( exp>350 || exp<-350 ){
dvander@1203
   471
            if( prefix=='-' ){
dvander@1203
   472
              bufpt = "-Inf";
dvander@1203
   473
            }else if( prefix=='+' ){
dvander@1203
   474
              bufpt = "+Inf";
dvander@1203
   475
            }else{
dvander@1203
   476
              bufpt = "Inf";
dvander@1203
   477
            }
dvander@1203
   478
            length = strlen(bufpt);
dvander@1203
   479
            break;
dvander@1203
   480
          }
dvander@1203
   481
        }
dvander@1203
   482
        bufpt = buf;
dvander@1203
   483
        /*
dvander@1203
   484
        ** If the field type is etGENERIC, then convert to either etEXP
dvander@1203
   485
        ** or etFLOAT, as appropriate.
dvander@1203
   486
        */
dvander@1203
   487
        flag_exp = xtype==etEXP;
dvander@1203
   488
        if( xtype!=etFLOAT ){
dvander@1203
   489
          realvalue += rounder;
dvander@1203
   490
          if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
dvander@1203
   491
        }
dvander@1203
   492
        if( xtype==etGENERIC ){
dvander@1203
   493
          flag_rtz = !flag_alternateform;
dvander@1203
   494
          if( exp<-4 || exp>precision ){
dvander@1203
   495
            xtype = etEXP;
dvander@1203
   496
          }else{
dvander@1203
   497
            precision = precision - exp;
dvander@1203
   498
            xtype = etFLOAT;
dvander@1203
   499
          }
dvander@1203
   500
        }else{
dvander@1203
   501
          flag_rtz = 0;
dvander@1203
   502
        }
dvander@1203
   503
        if( xtype==etEXP ){
dvander@1203
   504
          e2 = 0;
dvander@1203
   505
        }else{
dvander@1203
   506
          e2 = exp;
dvander@1203
   507
        }
dvander@1203
   508
        nsd = 0;
dvander@1203
   509
        flag_dp = (precision>0) | flag_alternateform | flag_altform2;
dvander@1203
   510
        /* The sign in front of the number */
dvander@1203
   511
        if( prefix ){
dvander@1203
   512
          *(bufpt++) = prefix;
dvander@1203
   513
        }
dvander@1203
   514
        /* Digits prior to the decimal point */
dvander@1203
   515
        if( e2<0 ){
dvander@1203
   516
          *(bufpt++) = '0';
dvander@1203
   517
        }else{
dvander@1203
   518
          for(; e2>=0; e2--){
dvander@1203
   519
            *(bufpt++) = et_getdigit(&realvalue,&nsd);
dvander@1203
   520
          }
dvander@1203
   521
        }
dvander@1203
   522
        /* The decimal point */
dvander@1203
   523
        if( flag_dp ){
dvander@1203
   524
          *(bufpt++) = '.';
dvander@1203
   525
        }
dvander@1203
   526
        /* "0" digits after the decimal point but before the first
dvander@1203
   527
        ** significant digit of the number */
dvander@1203
   528
        for(e2++; e2<0 && precision>0; precision--, e2++){
dvander@1203
   529
          *(bufpt++) = '0';
dvander@1203
   530
        }
dvander@1203
   531
        /* Significant digits after the decimal point */
dvander@1203
   532
        while( (precision--)>0 ){
dvander@1203
   533
          *(bufpt++) = et_getdigit(&realvalue,&nsd);
dvander@1203
   534
        }
dvander@1203
   535
        /* Remove trailing zeros and the "." if no digits follow the "." */
dvander@1203
   536
        if( flag_rtz && flag_dp ){
dvander@1203
   537
          while( bufpt[-1]=='0' ) *(--bufpt) = 0;
dvander@1203
   538
          assert( bufpt>buf );
dvander@1203
   539
          if( bufpt[-1]=='.' ){
dvander@1203
   540
            if( flag_altform2 ){
dvander@1203
   541
              *(bufpt++) = '0';
dvander@1203
   542
            }else{
dvander@1203
   543
              *(--bufpt) = 0;
dvander@1203
   544
            }
dvander@1203
   545
          }
dvander@1203
   546
        }
dvander@1203
   547
        /* Add the "eNNN" suffix */
dvander@1203
   548
        if( flag_exp || (xtype==etEXP && exp) ){
dvander@1203
   549
          *(bufpt++) = aDigits[infop->charset];
dvander@1203
   550
          if( exp<0 ){
dvander@1203
   551
            *(bufpt++) = '-'; exp = -exp;
dvander@1203
   552
          }else{
dvander@1203
   553
            *(bufpt++) = '+';
dvander@1203
   554
          }
dvander@1203
   555
          if( exp>=100 ){
dvander@1203
   556
            *(bufpt++) = (exp/100)+'0';                /* 100's digit */
dvander@1203
   557
            exp %= 100;
dvander@1203
   558
          }
dvander@1203
   559
          *(bufpt++) = exp/10+'0';                     /* 10's digit */
dvander@1203
   560
          *(bufpt++) = exp%10+'0';                     /* 1's digit */
dvander@1203
   561
        }
dvander@1203
   562
        *bufpt = 0;
dvander@1203
   563
dvander@1203
   564
        /* The converted number is in buf[] and zero terminated. Output it.
dvander@1203
   565
        ** Note that the number is in the usual order, not reversed as with
dvander@1203
   566
        ** integer conversions. */
dvander@1203
   567
        length = bufpt-buf;
dvander@1203
   568
        bufpt = buf;
dvander@1203
   569
dvander@1203
   570
        /* Special case:  Add leading zeros if the flag_zeropad flag is
dvander@1203
   571
        ** set and we are not left justified */
dvander@1203
   572
        if( flag_zeropad && !flag_leftjustify && length < width){
dvander@1203
   573
          int i;
dvander@1203
   574
          int nPad = width - length;
dvander@1203
   575
          for(i=width; i>=nPad; i--){
dvander@1203
   576
            bufpt[i] = bufpt[i-nPad];
dvander@1203
   577
          }
dvander@1203
   578
          i = prefix!=0;
dvander@1203
   579
          while( nPad-- ) bufpt[i++] = '0';
dvander@1203
   580
          length = width;
dvander@1203
   581
        }
dvander@1203
   582
#endif
dvander@1203
   583
        break;
dvander@1203
   584
      case etSIZE:
dvander@1203
   585
        *(va_arg(ap,int*)) = count;
dvander@1203
   586
        length = width = 0;
dvander@1203
   587
        break;
dvander@1203
   588
      case etPERCENT:
dvander@1203
   589
        buf[0] = '%';
dvander@1203
   590
        bufpt = buf;
dvander@1203
   591
        length = 1;
dvander@1203
   592
        break;
dvander@1203
   593
      case etCHARLIT:
dvander@1203
   594
      case etCHARX:
dvander@1203
   595
        c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
dvander@1203
   596
        if( precision>=0 ){
dvander@1203
   597
          for(idx=1; idx<precision; idx++) buf[idx] = c;
dvander@1203
   598
          length = precision;
dvander@1203
   599
        }else{
dvander@1203
   600
          length =1;
dvander@1203
   601
        }
dvander@1203
   602
        bufpt = buf;
dvander@1203
   603
        break;
dvander@1203
   604
      case etSTRING:
dvander@1203
   605
      case etDYNSTRING:
dvander@1203
   606
        bufpt = va_arg(ap,char*);
dvander@1203
   607
        if( bufpt==0 ){
dvander@1203
   608
          bufpt = "";
dvander@1203
   609
        }else if( xtype==etDYNSTRING ){
dvander@1203
   610
          zExtra = bufpt;
dvander@1203
   611
        }
dvander@1203
   612
        length = strlen(bufpt);
dvander@1203
   613
        if( precision>=0 && precision<length ) length = precision;
dvander@1203
   614
        break;
dvander@1203
   615
      case etSQLESCAPE:
dvander@1203
   616
      case etSQLESCAPE2:
dvander@1203
   617
      case etSQLESCAPE3: {
dvander@1203
   618
        int i, j, n, ch, isnull;
dvander@1203
   619
        int needQuote;
dvander@1203
   620
        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
dvander@1203
   621
        char *escarg = va_arg(ap,char*);
dvander@1203
   622
        isnull = escarg==0;
dvander@1203
   623
        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
dvander@1203
   624
        for(i=n=0; (ch=escarg[i])!=0; i++){
dvander@1203
   625
          if( ch==q )  n++;
dvander@1203
   626
        }
dvander@1203
   627
        needQuote = !isnull && xtype==etSQLESCAPE2;
dvander@1203
   628
        n += i + 1 + needQuote*2;
dvander@1203
   629
        if( n>etBUFSIZE ){
dvander@1645
   630
          bufpt = zExtra = sqlite3_malloc( n );
dvander@1203
   631
          if( bufpt==0 ) return -1;
dvander@1203
   632
        }else{
dvander@1203
   633
          bufpt = buf;
dvander@1203
   634
        }
dvander@1203
   635
        j = 0;
dvander@1203
   636
        if( needQuote ) bufpt[j++] = q;
dvander@1203
   637
        for(i=0; (ch=escarg[i])!=0; i++){
dvander@1203
   638
          bufpt[j++] = ch;
dvander@1203
   639
          if( ch==q ) bufpt[j++] = ch;
dvander@1203
   640
        }
dvander@1203
   641
        if( needQuote ) bufpt[j++] = q;
dvander@1203
   642
        bufpt[j] = 0;
dvander@1203
   643
        length = j;
dvander@1203
   644
        /* The precision is ignored on %q and %Q */
dvander@1203
   645
        /* if( precision>=0 && precision<length ) length = precision; */
dvander@1203
   646
        break;
dvander@1203
   647
      }
dvander@1203
   648
      case etTOKEN: {
dvander@1203
   649
        Token *pToken = va_arg(ap, Token*);
dvander@1203
   650
        if( pToken && pToken->z ){
dvander@1203
   651
          (*func)(arg, (char*)pToken->z, pToken->n);
dvander@1203
   652
        }
dvander@1203
   653
        length = width = 0;
dvander@1203
   654
        break;
dvander@1203
   655
      }
dvander@1203
   656
      case etSRCLIST: {
dvander@1203
   657
        SrcList *pSrc = va_arg(ap, SrcList*);
dvander@1203
   658
        int k = va_arg(ap, int);
dvander@1203
   659
        struct SrcList_item *pItem = &pSrc->a[k];
dvander@1203
   660
        assert( k>=0 && k<pSrc->nSrc );
dvander@1203
   661
        if( pItem->zDatabase && pItem->zDatabase[0] ){
dvander@1203
   662
          (*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase));
dvander@1203
   663
          (*func)(arg, ".", 1);
dvander@1203
   664
        }
dvander@1203
   665
        (*func)(arg, pItem->zName, strlen(pItem->zName));
dvander@1203
   666
        length = width = 0;
dvander@1203
   667
        break;
dvander@1203
   668
      }
dvander@1203
   669
    }/* End switch over the format type */
dvander@1203
   670
    /*
dvander@1203
   671
    ** The text of the conversion is pointed to by "bufpt" and is
dvander@1203
   672
    ** "length" characters long.  The field width is "width".  Do
dvander@1203
   673
    ** the output.
dvander@1203
   674
    */
dvander@1203
   675
    if( !flag_leftjustify ){
dvander@1203
   676
      register int nspace;
dvander@1203
   677
      nspace = width-length;
dvander@1203
   678
      if( nspace>0 ){
dvander@1203
   679
        count += nspace;
dvander@1203
   680
        while( nspace>=etSPACESIZE ){
dvander@1203
   681
          (*func)(arg,spaces,etSPACESIZE);
dvander@1203
   682
          nspace -= etSPACESIZE;
dvander@1203
   683
        }
dvander@1203
   684
        if( nspace>0 ) (*func)(arg,spaces,nspace);
dvander@1203
   685
      }
dvander@1203
   686
    }
dvander@1203
   687
    if( length>0 ){
dvander@1203
   688
      (*func)(arg,bufpt,length);
dvander@1203
   689
      count += length;
dvander@1203
   690
    }
dvander@1203
   691
    if( flag_leftjustify ){
dvander@1203
   692
      register int nspace;
dvander@1203
   693
      nspace = width-length;
dvander@1203
   694
      if( nspace>0 ){
dvander@1203
   695
        count += nspace;
dvander@1203
   696
        while( nspace>=etSPACESIZE ){
dvander@1203
   697
          (*func)(arg,spaces,etSPACESIZE);
dvander@1203
   698
          nspace -= etSPACESIZE;
dvander@1203
   699
        }
dvander@1203
   700
        if( nspace>0 ) (*func)(arg,spaces,nspace);
dvander@1203
   701
      }
dvander@1203
   702
    }
dvander@1203
   703
    if( zExtra ){
dvander@1645
   704
      sqlite3_free(zExtra);
dvander@1203
   705
    }
dvander@1203
   706
  }/* End for loop over the format string */
dvander@1203
   707
  return errorflag ? -1 : count;
dvander@1203
   708
} /* End of function */
dvander@1203
   709
dvander@1203
   710
dvander@1203
   711
/* This structure is used to store state information about the
dvander@1203
   712
** write to memory that is currently in progress.
dvander@1203
   713
*/
dvander@1203
   714
struct sgMprintf {
dvander@1203
   715
  char *zBase;     /* A base allocation */
dvander@1203
   716
  char *zText;     /* The string collected so far */
dvander@1203
   717
  int  nChar;      /* Length of the string so far */
dvander@1203
   718
  int  nTotal;     /* Output size if unconstrained */
dvander@1203
   719
  int  nAlloc;     /* Amount of space allocated in zText */
dvander@1203
   720
  void *(*xRealloc)(void*,int);  /* Function used to realloc memory */
dvander@1645
   721
  int  iMallocFailed;            /* True if xRealloc() has failed */
dvander@1203
   722
};
dvander@1203
   723
dvander@1203
   724
/* 
dvander@1203
   725
** This function implements the callback from vxprintf. 
dvander@1203
   726
**
dvander@1203
   727
** This routine add nNewChar characters of text in zNewText to
dvander@1203
   728
** the sgMprintf structure pointed to by "arg".
dvander@1203
   729
*/
dvander@1203
   730
static void mout(void *arg, const char *zNewText, int nNewChar){
dvander@1203
   731
  struct sgMprintf *pM = (struct sgMprintf*)arg;
dvander@1645
   732
  if( pM->iMallocFailed ) return;
dvander@1203
   733
  pM->nTotal += nNewChar;
dvander@1645
   734
  if( pM->zText ){
dvander@1645
   735
    if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
dvander@1645
   736
      if( pM->xRealloc==0 ){
dvander@1645
   737
        nNewChar =  pM->nAlloc - pM->nChar - 1;
dvander@1203
   738
      }else{
dvander@1645
   739
        int nAlloc = pM->nChar + nNewChar*2 + 1;
dvander@1645
   740
        if( pM->zText==pM->zBase ){
dvander@1645
   741
          pM->zText = pM->xRealloc(0, nAlloc);
dvander@1645
   742
          if( pM->zText==0 ){
dvander@1645
   743
            pM->nAlloc = 0;
dvander@1645
   744
            pM->iMallocFailed = 1;
dvander@1645
   745
            return;
dvander@1645
   746
          }else if( pM->nChar ){
dvander@1645
   747
            memcpy(pM->zText, pM->zBase, pM->nChar);
dvander@1645
   748
          }
dvander@1203
   749
        }else{
dvander@1645
   750
          char *zNew;
dvander@1645
   751
          zNew = pM->xRealloc(pM->zText, nAlloc);
dvander@1645
   752
          if( zNew ){
dvander@1645
   753
            pM->zText = zNew;
dvander@1645
   754
          }else{
dvander@1645
   755
            pM->iMallocFailed = 1;
dvander@1645
   756
            pM->xRealloc(pM->zText, 0);
dvander@1645
   757
            pM->zText = 0;
dvander@1645
   758
            pM->nAlloc = 0;
dvander@1645
   759
            return;
dvander@1645
   760
          }
dvander@1203
   761
        }
dvander@1645
   762
        pM->nAlloc = nAlloc;
dvander@1203
   763
      }
dvander@1203
   764
    }
dvander@1203
   765
    if( nNewChar>0 ){
dvander@1203
   766
      memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
dvander@1203
   767
      pM->nChar += nNewChar;
dvander@1203
   768
    }
dvander@1203
   769
    pM->zText[pM->nChar] = 0;
dvander@1203
   770
  }
dvander@1203
   771
}
dvander@1203
   772
dvander@1203
   773
/*
dvander@1203
   774
** This routine is a wrapper around xprintf() that invokes mout() as
dvander@1203
   775
** the consumer.  
dvander@1203
   776
*/
dvander@1203
   777
static char *base_vprintf(
dvander@1645
   778
  void *(*xRealloc)(void*, int),  /* realloc() function. May be NULL */
dvander@1203
   779
  int useInternal,                /* Use internal %-conversions if true */
dvander@1203
   780
  char *zInitBuf,                 /* Initially write here, before mallocing */
dvander@1203
   781
  int nInitBuf,                   /* Size of zInitBuf[] */
dvander@1203
   782
  const char *zFormat,            /* format string */
dvander@1203
   783
  va_list ap                      /* arguments */
dvander@1203
   784
){
dvander@1203
   785
  struct sgMprintf sM;
dvander@1203
   786
  sM.zBase = sM.zText = zInitBuf;
dvander@1203
   787
  sM.nChar = sM.nTotal = 0;
dvander@1203
   788
  sM.nAlloc = nInitBuf;
dvander@1203
   789
  sM.xRealloc = xRealloc;
dvander@1645
   790
  sM.iMallocFailed = 0;
dvander@1203
   791
  vxprintf(mout, &sM, useInternal, zFormat, ap);
dvander@1645
   792
  assert(sM.iMallocFailed==0 || sM.zText==0);
dvander@1645
   793
  if( xRealloc && !sM.iMallocFailed ){
dvander@1203
   794
    if( sM.zText==sM.zBase ){
dvander@1203
   795
      sM.zText = xRealloc(0, sM.nChar+1);
dvander@1203
   796
      if( sM.zText ){
dvander@1203
   797
        memcpy(sM.zText, sM.zBase, sM.nChar+1);
dvander@1203
   798
      }
dvander@1203
   799
    }else if( sM.nAlloc>sM.nChar+10 ){
dvander@1645
   800
      char *zNew;
dvander@1645
   801
      sqlite3MallocBenignFailure(1);
dvander@1645
   802
      zNew = xRealloc(sM.zText, sM.nChar+1);
dvander@1203
   803
      if( zNew ){
dvander@1203
   804
        sM.zText = zNew;
dvander@1203
   805
      }
dvander@1203
   806
    }
dvander@1203
   807
  }
dvander@1203
   808
  return sM.zText;
dvander@1203
   809
}
dvander@1203
   810
dvander@1203
   811
/*
dvander@1203
   812
** Realloc that is a real function, not a macro.
dvander@1203
   813
*/
dvander@1203
   814
static void *printf_realloc(void *old, int size){
dvander@1645
   815
  return sqlite3_realloc(old, size);
dvander@1203
   816
}
dvander@1203
   817
dvander@1203
   818
/*
dvander@1203
   819
** Print into memory obtained from sqliteMalloc().  Use the internal
dvander@1203
   820
** %-conversion extensions.
dvander@1203
   821
*/
dvander@1645
   822
char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
dvander@1645
   823
  char *z;
dvander@1203
   824
  char zBase[SQLITE_PRINT_BUF_SIZE];
dvander@1645
   825
  z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
dvander@1645
   826
  if( z==0 && db!=0 ){
dvander@1645
   827
    db->mallocFailed = 1;
dvander@1645
   828
  }
dvander@1645
   829
  return z;
dvander@1203
   830
}
dvander@1203
   831
dvander@1203
   832
/*
dvander@1203
   833
** Print into memory obtained from sqliteMalloc().  Use the internal
dvander@1203
   834
** %-conversion extensions.
dvander@1203
   835
*/
dvander@1645
   836
char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
dvander@1203
   837
  va_list ap;
dvander@1203
   838
  char *z;
dvander@1203
   839
  char zBase[SQLITE_PRINT_BUF_SIZE];
dvander@1203
   840
  va_start(ap, zFormat);
dvander@1203
   841
  z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
dvander@1203
   842
  va_end(ap);
dvander@1645
   843
  if( z==0 && db!=0 ){
dvander@1645
   844
    db->mallocFailed = 1;
dvander@1645
   845
  }
dvander@1203
   846
  return z;
dvander@1203
   847
}
dvander@1203
   848
dvander@1203
   849
/*
dvander@1203
   850
** Print into memory obtained from sqlite3_malloc().  Omit the internal
dvander@1203
   851
** %-conversion extensions.
dvander@1203
   852
*/
dvander@1203
   853
char *sqlite3_vmprintf(const char *zFormat, va_list ap){
dvander@1203
   854
  char zBase[SQLITE_PRINT_BUF_SIZE];
dvander@1203
   855
  return base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
dvander@1203
   856
}
dvander@1203
   857
dvander@1203
   858
/*
dvander@1203
   859
** Print into memory obtained from sqlite3_malloc()().  Omit the internal
dvander@1203
   860
** %-conversion extensions.
dvander@1203
   861
*/
dvander@1203
   862
char *sqlite3_mprintf(const char *zFormat, ...){
dvander@1203
   863
  va_list ap;
dvander@1203
   864
  char *z;
dvander@1203
   865
  va_start(ap, zFormat);
dvander@1203
   866
  z = sqlite3_vmprintf(zFormat, ap);
dvander@1203
   867
  va_end(ap);
dvander@1203
   868
  return z;
dvander@1203
   869
}
dvander@1203
   870
dvander@1203
   871
/*
dvander@1203
   872
** sqlite3_snprintf() works like snprintf() except that it ignores the
dvander@1203
   873
** current locale settings.  This is important for SQLite because we
dvander@1203
   874
** are not able to use a "," as the decimal point in place of "." as
dvander@1203
   875
** specified by some locales.
dvander@1203
   876
*/
dvander@1203
   877
char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
dvander@1203
   878
  char *z;
dvander@1203
   879
  va_list ap;
dvander@1203
   880
dvander@1203
   881
  if( n<=0 ){
dvander@1203
   882
    return zBuf;
dvander@1203
   883
  }
dvander@1203
   884
  zBuf[0] = 0;
dvander@1203
   885
  va_start(ap,zFormat);
dvander@1203
   886
  z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
dvander@1203
   887
  va_end(ap);
dvander@1203
   888
  return z;
dvander@1203
   889
}
dvander@1203
   890
dvander@1203
   891
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) || defined(SQLITE_MEMDEBUG)
dvander@1203
   892
/*
dvander@1203
   893
** A version of printf() that understands %lld.  Used for debugging.
dvander@1203
   894
** The printf() built into some versions of windows does not understand %lld
dvander@1203
   895
** and segfaults if you give it a long long int.
dvander@1203
   896
*/
dvander@1203
   897
void sqlite3DebugPrintf(const char *zFormat, ...){
dvander@1203
   898
  extern int getpid(void);
dvander@1203
   899
  va_list ap;
dvander@1203
   900
  char zBuf[500];
dvander@1203
   901
  va_start(ap, zFormat);
dvander@1203
   902
  base_vprintf(0, 0, zBuf, sizeof(zBuf), zFormat, ap);
dvander@1203
   903
  va_end(ap);
dvander@1203
   904
  fprintf(stdout,"%s", zBuf);
dvander@1203
   905
  fflush(stdout);
dvander@1203
   906
}
dvander@1203
   907
#endif