Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
printf.c1578 linesDownload Raw Back to src
1/*2** The "printf" code that follows dates from the 1980's.  It is in3** the public domain. 4**5**************************************************************************6**7** This file contains code for a set of "printf"-like routines.  These8** routines format strings much like the printf() from the standard C9** library, though the implementation here has enhancements to support10** SQLite.11*/12#include "sqliteInt.h"13 14/*15** Conversion types fall into various categories as defined by the16** following enumeration.17*/18#define etRADIX       0 /* non-decimal integer types.  %x %o */19#define etFLOAT       1 /* Floating point.  %f */20#define etEXP         2 /* Exponentional notation. %e and %E */21#define etGENERIC     3 /* Floating or exponential, depending on exponent. %g */22#define etSIZE        4 /* Return number of characters processed so far. %n */23#define etSTRING      5 /* Strings. %s */24#define etDYNSTRING   6 /* Dynamically allocated strings. %z */25#define etPERCENT     7 /* Percent symbol. %% */26#define etCHARX       8 /* Characters. %c */27/* The rest are extensions, not normally found in printf() */28#define etESCAPE_q    9  /* Strings with '\'' doubled.  %q */29#define etESCAPE_Q    10 /* Strings with '\'' doubled and enclosed in '',30                            NULL pointers replaced by SQL NULL.  %Q */31#define etTOKEN       11 /* a pointer to a Token structure */32#define etSRCITEM     12 /* a pointer to a SrcItem */33#define etPOINTER     13 /* The %p conversion */34#define etESCAPE_w    14 /* %w -> Strings with '\"' doubled */35#define etORDINAL     15 /* %r -> 1st, 2nd, 3rd, 4th, etc.  English only */36#define etDECIMAL     16 /* %d or %u, but not %x, %o */37 38#define etINVALID     17 /* Any unrecognized conversion type */39 40 41/*42** An "etByte" is an 8-bit unsigned value.43*/44typedef unsigned char etByte;45 46/*47** Each builtin conversion character (ex: the 'd' in "%d") is described48** by an instance of the following structure49*/50typedef struct et_info {   /* Information about each format field */51  char fmttype;            /* The format field code letter */52  etByte base;             /* The base for radix conversion */53  etByte flags;            /* One or more of FLAG_ constants below */54  etByte type;             /* Conversion paradigm */55  etByte charset;          /* Offset into aDigits[] of the digits string */56  etByte prefix;           /* Offset into aPrefix[] of the prefix string */57  char iNxt;               /* Next with same hash, or 0 for end of chain */58} et_info;59 60/*61** Allowed values for et_info.flags62*/63#define FLAG_SIGNED    1     /* True if the value to convert is signed */64#define FLAG_STRING    4     /* Allow infinite precision */65 66/*67** The table is searched by hash.  In the case of %C where C is the character68** and that character has ASCII value j, then the hash is j%23.69**70** The order of the entries in fmtinfo[] and the hash chain was entered71** manually, but based on the output of the following TCL script:72*/73#if 0  /*****  Beginning of script ******/74foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {75  scan $c %c x76  set n($c) $x77}78set mx [llength [array names n]]79puts "count: $mx"80 81set mx 2782puts "*********** mx=$mx ************"83for {set r 0} {$r<$mx} {incr r} {84  puts -nonewline [format %2d: $r]85  foreach c [array names n] {86    if {($n($c))%$mx==$r} {puts -nonewline " $c"}87  }88  puts ""89}90#endif /***** End of script ********/91 92static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";93static const char aPrefix[] = "-x0\000X0";94static const et_info fmtinfo[23] = {95  /*  0 */  {  's',  0, 4, etSTRING,     0,  0,  1 },96  /*  1 */  {  'E',  0, 1, etEXP,        14, 0,  0 },  /* Hash: 0 */97  /*  2 */  {  'u', 10, 0, etDECIMAL,    0,  0,  3 },98  /*  3 */  {  'G',  0, 1, etGENERIC,    14, 0,  0 },  /* Hash: 2 */99  /*  4 */  {  'w',  0, 4, etESCAPE_w,   0,  0,  0 },100  /*  5 */  {  'x', 16, 0, etRADIX,      16, 1,  0 },101  /*  6 */  {  'c',  0, 0, etCHARX,      0,  0,  0 },  /* Hash: 7 */102  /*  7 */  {  'z',  0, 4, etDYNSTRING,  0,  0,  6 },103  /*  8 */  {  'd', 10, 1, etDECIMAL,    0,  0,  0 },104  /*  9 */  {  'e',  0, 1, etEXP,        30, 0,  0 },105  /* 10 */  {  'f',  0, 1, etFLOAT,      0,  0,  0 },106  /* 11 */  {  'g',  0, 1, etGENERIC,    30, 0,  0 },107  /* 12 */  {  'Q',  0, 4, etESCAPE_Q,   0,  0,  0 },108  /* 13 */  {  'i', 10, 1, etDECIMAL,    0,  0,  0 },109  /* 14 */  {  '%',  0, 0, etPERCENT,    0,  0, 16 },110  /* 15 */  {  'T',  0, 0, etTOKEN,      0,  0,  0 },111  /* 16 */  {  'S',  0, 0, etSRCITEM,    0,  0,  0 },  /* Hash: 14 */112  /* 17 */  {  'X', 16, 0, etRADIX,      0,  4,  0 },  /* Hash: 19 */113  /* 18 */  {  'n',  0, 0, etSIZE,       0,  0,  0 },114  /* 19 */  {  'o',  8, 0, etRADIX,      0,  2, 17 },115  /* 20 */  {  'p', 16, 0, etPOINTER,    0,  1,  0 },116  /* 21 */  {  'q',  0, 4, etESCAPE_q,   0,  0,  0 },117  /* 22 */  {  'r', 10, 1, etORDINAL,    0,  0,  0 }118};119 120/* Additional Notes:121**122**    %S    Takes a pointer to SrcItem.  Shows name or database.name123**    %!S   Like %S but prefer the zName over the zAlias124*/125 126/*127** Set the StrAccum object to an error mode.128*/129void sqlite3StrAccumSetError(StrAccum *p, u8 eError){130  assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );131  p->accError = eError;132  if( p->mxAlloc ) sqlite3_str_reset(p);133  if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError);134}135 136/*137** Extra argument values from a PrintfArguments object138*/139static sqlite3_int64 getIntArg(PrintfArguments *p){140  if( p->nArg<=p->nUsed ) return 0;141  return sqlite3_value_int64(p->apArg[p->nUsed++]);142}143static double getDoubleArg(PrintfArguments *p){144  if( p->nArg<=p->nUsed ) return 0.0;145  return sqlite3_value_double(p->apArg[p->nUsed++]);146}147static char *getTextArg(PrintfArguments *p){148  if( p->nArg<=p->nUsed ) return 0;149  return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);150}151 152/*153** Allocate memory for a temporary buffer needed for printf rendering.154**155** If the requested size of the temp buffer is larger than the size156** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.157** Do the size check before the memory allocation to prevent rogue158** SQL from requesting large allocations using the precision or width159** field of the printf() function.160*/161static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){162  char *z;163  if( pAccum->accError ) return 0;164  if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){165    sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);166    return 0;167  }168  z = sqlite3DbMallocRaw(pAccum->db, n);169  if( z==0 ){170    sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);171  }172  return z;173}174 175/*176** On machines with a small stack size, you can redefine the177** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.178*/179#ifndef SQLITE_PRINT_BUF_SIZE180# define SQLITE_PRINT_BUF_SIZE 70181#endif182#define etBUFSIZE SQLITE_PRINT_BUF_SIZE  /* Size of the output buffer */183 184/*185** Hard limit on the precision of floating-point conversions.186*/187#ifndef SQLITE_PRINTF_PRECISION_LIMIT188# define SQLITE_FP_PRECISION_LIMIT 100000000189#endif190 191/*192** Render a string given by "fmt" into the StrAccum object.193*/194void sqlite3_str_vappendf(195  sqlite3_str *pAccum,       /* Accumulate results here */196  const char *fmt,           /* Format string */197  va_list ap                 /* arguments */198){199  int c;                     /* Next character in the format string */200  char *bufpt;               /* Pointer to the conversion buffer */201  int precision;             /* Precision of the current field */202  int length;                /* Length of the field */203  int idx;                   /* A general purpose loop counter */204  int width;                 /* Width of the current field */205  etByte flag_leftjustify;   /* True if "-" flag is present */206  etByte flag_prefix;        /* '+' or ' ' or 0 for prefix */207  etByte flag_alternateform; /* True if "#" flag is present */208  etByte flag_altform2;      /* True if "!" flag is present */209  etByte flag_zeropad;       /* True if field width constant starts with zero */210  etByte flag_long;          /* 1 for the "l" flag, 2 for "ll", 0 by default */211  etByte done;               /* Loop termination flag */212  etByte cThousand;          /* Thousands separator for %d and %u */213  etByte xtype = etINVALID;  /* Conversion paradigm */214  u8 bArgList;               /* True for SQLITE_PRINTF_SQLFUNC */215  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */216  sqlite_uint64 longvalue;   /* Value for integer types */217  double realvalue;          /* Value for real types */218  const et_info *infop;      /* Pointer to the appropriate info structure */219  char *zOut;                /* Rendering buffer */220  int nOut;                  /* Size of the rendering buffer */221  char *zExtra = 0;          /* Malloced memory used by some conversion */222  int exp, e2;               /* exponent of real numbers */223  etByte flag_dp;            /* True if decimal point should be shown */224  etByte flag_rtz;           /* True if trailing zeros should be removed */225 226  PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */227  char buf[etBUFSIZE];       /* Conversion buffer */228 229  /* pAccum never starts out with an empty buffer that was obtained from 230  ** malloc().  This precondition is required by the mprintf("%z...")231  ** optimization. */232  assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );233 234  bufpt = 0;235  if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){236    pArgList = va_arg(ap, PrintfArguments*);237    bArgList = 1;238  }else{239    bArgList = 0;240  }241  for(; (c=(*fmt))!=0; ++fmt){242    if( c!='%' ){243      bufpt = (char *)fmt;244#if HAVE_STRCHRNUL245      fmt = strchrnul(fmt, '%');246#else247      fmt = strchr(fmt, '%');248      if( fmt==0 ){249        fmt = bufpt + strlen(bufpt);250      }251#endif252      sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));253      if( *fmt==0 ) break;254    }255    if( (c=(*++fmt))==0 ){256      sqlite3_str_append(pAccum, "%", 1);257      break;258    }259    /* Find out what flags are present */260    flag_leftjustify = flag_prefix = cThousand =261     flag_alternateform = flag_altform2 = flag_zeropad = 0;262    done = 0;263    width = 0;264    flag_long = 0;265    precision = -1;266    do{267      switch( c ){268        case '-':   flag_leftjustify = 1;     break;269        case '+':   flag_prefix = '+';        break;270        case ' ':   flag_prefix = ' ';        break;271        case '#':   flag_alternateform = 1;   break;272        case '!':   flag_altform2 = 1;        break;273        case '0':   flag_zeropad = 1;         break;274        case ',':   cThousand = ',';          break;275        default:    done = 1;                 break;276        case 'l': {277          flag_long = 1;278          c = *++fmt;279          if( c=='l' ){280            c = *++fmt;281            flag_long = 2;282          }283          done = 1;284          break;285        }286        case '1': case '2': case '3': case '4': case '5':287        case '6': case '7': case '8': case '9': {288          unsigned wx = c - '0';289          while( (c = *++fmt)>='0' && c<='9' ){290            wx = wx*10 + c - '0';291          }292          testcase( wx>0x7fffffff );293          width = wx & 0x7fffffff;294#ifdef SQLITE_PRINTF_PRECISION_LIMIT295          if( width>SQLITE_PRINTF_PRECISION_LIMIT ){296            width = SQLITE_PRINTF_PRECISION_LIMIT;297          }298#endif299          if( c!='.' && c!='l' ){300            done = 1;301          }else{302            fmt--;303          }304          break;305        }306        case '*': {307          if( bArgList ){308            width = (int)getIntArg(pArgList);309          }else{310            width = va_arg(ap,int);311          }312          if( width<0 ){313            flag_leftjustify = 1;314            width = width >= -2147483647 ? -width : 0;315          }316#ifdef SQLITE_PRINTF_PRECISION_LIMIT317          if( width>SQLITE_PRINTF_PRECISION_LIMIT ){318            width = SQLITE_PRINTF_PRECISION_LIMIT;319          }320#endif321          if( (c = fmt[1])!='.' && c!='l' ){322            c = *++fmt;323            done = 1;324          }325          break;326        }327        case '.': {328          c = *++fmt;329          if( c=='*' ){330            if( bArgList ){331              precision = (int)getIntArg(pArgList);332            }else{333              precision = va_arg(ap,int);334            }335            if( precision<0 ){336              precision = precision >= -2147483647 ? -precision : -1;337            }338            c = *++fmt;339          }else{340            unsigned px = 0;341            while( c>='0' && c<='9' ){342              px = px*10 + c - '0';343              c = *++fmt;344            }345            testcase( px>0x7fffffff );346            precision = px & 0x7fffffff;347          }348#ifdef SQLITE_PRINTF_PRECISION_LIMIT349          if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){350            precision = SQLITE_PRINTF_PRECISION_LIMIT;351          }352#endif353          if( c=='l' ){354            --fmt;355          }else{356            done = 1;357          }358          break;359        }360      }361    }while( !done && (c=(*++fmt))!=0 );362 363    /* Fetch the info entry for the field */364#ifdef SQLITE_EBCDIC365    /* The hash table only works for ASCII.  For EBCDIC, we need to do366    ** a linear search of the table */367    infop = &fmtinfo[0];368    xtype = etINVALID;369    for(idx=0; idx<ArraySize(fmtinfo); idx++){370      if( c==fmtinfo[idx].fmttype ){371        infop = &fmtinfo[idx];372        xtype = infop->type;373        break;374      }375    }376#else377    /* Fast hash-table lookup */378    assert( ArraySize(fmtinfo)==23 );379    idx = ((unsigned)c) % 23;380    if( fmtinfo[idx].fmttype==c381     || fmtinfo[idx = fmtinfo[idx].iNxt].fmttype==c382    ){383      infop = &fmtinfo[idx];384      xtype = infop->type;385    }else{386      infop = &fmtinfo[0];387      xtype = etINVALID;388    }389#endif390 391    /*392    ** At this point, variables are initialized as follows:393    **394    **   flag_alternateform          TRUE if a '#' is present.395    **   flag_altform2               TRUE if a '!' is present.396    **   flag_prefix                 '+' or ' ' or zero397    **   flag_leftjustify            TRUE if a '-' is present or if the398    **                               field width was negative.399    **   flag_zeropad                TRUE if the width began with 0.400    **   flag_long                   1 for "l", 2 for "ll"401    **   width                       The specified field width.  This is402    **                               always non-negative.  Zero is the default.403    **   precision                   The specified precision.  The default404    **                               is -1.405    **   xtype                       The class of the conversion.406    **   infop                       Pointer to the appropriate info struct.407    */408    assert( width>=0 );409    assert( precision>=(-1) );410    switch( xtype ){411      case etPOINTER:412        flag_long = sizeof(char*)==sizeof(i64) ? 2 :413                     sizeof(char*)==sizeof(long int) ? 1 : 0;414        /* no break */ deliberate_fall_through415      case etORDINAL:416      case etRADIX:      417        cThousand = 0;418        /* no break */ deliberate_fall_through419      case etDECIMAL:420        if( infop->flags & FLAG_SIGNED ){421          i64 v;422          if( bArgList ){423            v = getIntArg(pArgList);424          }else if( flag_long ){425            if( flag_long==2 ){426              v = va_arg(ap,i64) ;427            }else{428              v = va_arg(ap,long int);429            }430          }else{431            v = va_arg(ap,int);432          }433          if( v<0 ){434            testcase( v==SMALLEST_INT64 );435            testcase( v==(-1) );436            longvalue = ~v;437            longvalue++;438            prefix = '-';439          }else{440            longvalue = v;441            prefix = flag_prefix;442          }443        }else{444          if( bArgList ){445            longvalue = (u64)getIntArg(pArgList);446          }else if( flag_long ){447            if( flag_long==2 ){448              longvalue = va_arg(ap,u64);449            }else{450              longvalue = va_arg(ap,unsigned long int);451            }452          }else{453            longvalue = va_arg(ap,unsigned int);454          }455          prefix = 0;456        }457 458#if WHERETRACE_ENABLED459        if( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0;460#endif461#if TREETRACE_ENABLED462        if( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0;463#endif464 465        if( longvalue==0 ) flag_alternateform = 0;466        if( flag_zeropad && precision<width-(prefix!=0) ){467          precision = width-(prefix!=0);468        }469        if( precision<etBUFSIZE-10-etBUFSIZE/3 ){470          nOut = etBUFSIZE;471          zOut = buf;472        }else{473          u64 n;474          n = (u64)precision + 10;475          if( cThousand ) n += precision/3;476          zOut = zExtra = printfTempBuf(pAccum, n);477          if( zOut==0 ) return;478          nOut = (int)n;479        }480        bufpt = &zOut[nOut-1];481        if( xtype==etORDINAL ){482          static const char zOrd[] = "thstndrd";483          int x = (int)(longvalue % 10);484          if( x>=4 || (longvalue/10)%10==1 ){485            x = 0;486          }487          *(--bufpt) = zOrd[x*2+1];488          *(--bufpt) = zOrd[x*2];489        }490        {491          const char *cset = &aDigits[infop->charset];492          u8 base = infop->base;493          do{                                           /* Convert to ascii */494            *(--bufpt) = cset[longvalue%base];495            longvalue = longvalue/base;496          }while( longvalue>0 );497        }498        length = (int)(&zOut[nOut-1]-bufpt);499        while( precision>length ){500          *(--bufpt) = '0';                             /* Zero pad */501          length++;502        }503        if( cThousand ){504          int nn = (length - 1)/3;  /* Number of "," to insert */505          int ix = (length - 1)%3 + 1;506          bufpt -= nn;507          for(idx=0; nn>0; idx++){508            bufpt[idx] = bufpt[idx+nn];509            ix--;510            if( ix==0 ){511              bufpt[++idx] = cThousand;512              nn--;513              ix = 3;514            }515          }516        }517        if( prefix ) *(--bufpt) = prefix;               /* Add sign */518        if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */519          const char *pre;520          char x;521          pre = &aPrefix[infop->prefix];522          for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;523        }524        length = (int)(&zOut[nOut-1]-bufpt);525        break;526      case etFLOAT:527      case etEXP:528      case etGENERIC: {529        FpDecode s;530        int iRound;531        int j;532 533        if( bArgList ){534          realvalue = getDoubleArg(pArgList);535        }else{536          realvalue = va_arg(ap,double);537        }538        if( precision<0 ) precision = 6;         /* Set default precision */539#ifdef SQLITE_FP_PRECISION_LIMIT540        if( precision>SQLITE_FP_PRECISION_LIMIT ){541          precision = SQLITE_FP_PRECISION_LIMIT;542        }543#endif544        if( xtype==etFLOAT ){545          iRound = -precision;546        }else if( xtype==etGENERIC ){547          if( precision==0 ) precision = 1;548          iRound = precision;549        }else{550          iRound = precision+1;551        }552        sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);553        if( s.isSpecial ){554          if( s.isSpecial==2 ){555            bufpt = flag_zeropad ? "null" : "NaN";556            length = sqlite3Strlen30(bufpt);557            break;558          }else if( flag_zeropad ){559            s.z[0] = '9';560            s.iDP = 1000;561            s.n = 1;562          }else{563            memcpy(buf, "-Inf", 5);564            bufpt = buf;565            if( s.sign=='-' ){566              /* no-op */567            }else if( flag_prefix ){568              buf[0] = flag_prefix;569            }else{570              bufpt++;571            }572            length = sqlite3Strlen30(bufpt);573            break;574          }575        }576        if( s.sign=='-' ){577          if( flag_alternateform578           && !flag_prefix579           && xtype==etFLOAT580           && s.iDP<=iRound581          ){582            /* Suppress the minus sign if all of the following are true:583            **   *  The value displayed is zero584            **   *  The '#' flag is used585            **   *  The '+' flag is not used, and586            **   *  The format is %f587            */588            prefix = 0;589          }else{590            prefix = '-';591          }592        }else{593          prefix = flag_prefix;594        }595 596        exp = s.iDP-1;597 598        /*599        ** If the field type is etGENERIC, then convert to either etEXP600        ** or etFLOAT, as appropriate.601        */602        if( xtype==etGENERIC ){603          assert( precision>0 );604          precision--;605          flag_rtz = !flag_alternateform;606          if( exp<-4 || exp>precision ){607            xtype = etEXP;608          }else{609            precision = precision - exp;610            xtype = etFLOAT;611          }612        }else{613          flag_rtz = flag_altform2;614        }615        if( xtype==etEXP ){616          e2 = 0;617        }else{618          e2 = s.iDP - 1;619        }620        bufpt = buf;621        {622          i64 szBufNeeded;           /* Size of a temporary buffer needed */623          szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;624          if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;625          if( szBufNeeded > etBUFSIZE ){626            bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);627            if( bufpt==0 ) return;628          }629        }630        zOut = bufpt;631        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;632        /* The sign in front of the number */633        if( prefix ){634          *(bufpt++) = prefix;635        }636        /* Digits prior to the decimal point */637        j = 0;638        if( e2<0 ){639          *(bufpt++) = '0';640        }else{641          for(; e2>=0; e2--){642            *(bufpt++) = j<s.n ? s.z[j++] : '0';643            if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';644          }645        }646        /* The decimal point */647        if( flag_dp ){648          *(bufpt++) = '.';649        }650        /* "0" digits after the decimal point but before the first651        ** significant digit of the number */652        for(e2++; e2<0 && precision>0; precision--, e2++){653          *(bufpt++) = '0';654        }655        /* Significant digits after the decimal point */656        while( (precision--)>0 ){657          *(bufpt++) = j<s.n ? s.z[j++] : '0';658        }659        /* Remove trailing zeros and the "." if no digits follow the "." */660        if( flag_rtz && flag_dp ){661          while( bufpt[-1]=='0' ) *(--bufpt) = 0;662          assert( bufpt>zOut );663          if( bufpt[-1]=='.' ){664            if( flag_altform2 ){665              *(bufpt++) = '0';666            }else{667              *(--bufpt) = 0;668            }669          }670        }671        /* Add the "eNNN" suffix */672        if( xtype==etEXP ){673          exp = s.iDP - 1;674          *(bufpt++) = aDigits[infop->charset];675          if( exp<0 ){676            *(bufpt++) = '-'; exp = -exp;677          }else{678            *(bufpt++) = '+';679          }680          if( exp>=100 ){681            *(bufpt++) = (char)((exp/100)+'0');        /* 100's digit */682            exp %= 100;683          }684          *(bufpt++) = (char)(exp/10+'0');             /* 10's digit */685          *(bufpt++) = (char)(exp%10+'0');             /* 1's digit */686        }687        *bufpt = 0;688 689        /* The converted number is in buf[] and zero terminated. Output it.690        ** Note that the number is in the usual order, not reversed as with691        ** integer conversions. */692        length = (int)(bufpt-zOut);693        bufpt = zOut;694 695        /* Special case:  Add leading zeros if the flag_zeropad flag is696        ** set and we are not left justified */697        if( flag_zeropad && !flag_leftjustify && length < width){698          int i;699          int nPad = width - length;700          for(i=width; i>=nPad; i--){701            bufpt[i] = bufpt[i-nPad];702          }703          i = prefix!=0;704          while( nPad-- ) bufpt[i++] = '0';705          length = width;706        }707        break;708      }709      case etSIZE:710        if( !bArgList ){711          *(va_arg(ap,int*)) = pAccum->nChar;712        }713        length = width = 0;714        break;715      case etPERCENT:716        buf[0] = '%';717        bufpt = buf;718        length = 1;719        break;720      case etCHARX:721        if( bArgList ){722          bufpt = getTextArg(pArgList);723          length = 1;724          if( bufpt ){725            buf[0] = c = *(bufpt++);726            if( (c&0xc0)==0xc0 ){727              while( length<4 && (bufpt[0]&0xc0)==0x80 ){728                buf[length++] = *(bufpt++);729              }730            }731          }else{732            buf[0] = 0;733          }734        }else{735          unsigned int ch = va_arg(ap,unsigned int);736          length = sqlite3AppendOneUtf8Character(buf, ch);737        }738        if( precision>1 ){739          i64 nPrior = 1;740          width -= precision-1;741          if( width>1 && !flag_leftjustify ){742            sqlite3_str_appendchar(pAccum, width-1, ' ');743            width = 0;744          }745          sqlite3_str_append(pAccum, buf, length);746          precision--;747          while( precision > 1 ){748            i64 nCopyBytes;749            if( nPrior > precision-1 ) nPrior = precision - 1;750            nCopyBytes = length*nPrior;751            if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){752              sqlite3StrAccumEnlarge(pAccum, nCopyBytes);753            }754            if( pAccum->accError ) break;755            sqlite3_str_append(pAccum,756                 &pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);757            precision -= nPrior;758            nPrior *= 2;759          }760        }761        bufpt = buf;762        flag_altform2 = 1;763        goto adjust_width_for_utf8;764      case etSTRING:765      case etDYNSTRING:766        if( bArgList ){767          bufpt = getTextArg(pArgList);768          xtype = etSTRING;769        }else{770          bufpt = va_arg(ap,char*);771        }772        if( bufpt==0 ){773          bufpt = "";774        }else if( xtype==etDYNSTRING ){775          if( pAccum->nChar==0776           && pAccum->mxAlloc777           && width==0778           && precision<0779           && pAccum->accError==0780          ){781            /* Special optimization for sqlite3_mprintf("%z..."):782            ** Extend an existing memory allocation rather than creating783            ** a new one. */784            assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );785            pAccum->zText = bufpt;786            pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt);787            pAccum->nChar = 0x7fffffff & (int)strlen(bufpt);788            pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED;789            length = 0;790            break;791          }792          zExtra = bufpt;793        }794        if( precision>=0 ){795          if( flag_altform2 ){796            /* Set length to the number of bytes needed in order to display797            ** precision characters */798            unsigned char *z = (unsigned char*)bufpt;799            while( precision-- > 0 && z[0] ){800              SQLITE_SKIP_UTF8(z);801            }802            length = (int)(z - (unsigned char*)bufpt);803          }else{804            for(length=0; length<precision && bufpt[length]; length++){}805          }806        }else{807          length = 0x7fffffff & (int)strlen(bufpt);808        }809      adjust_width_for_utf8:810        if( flag_altform2 && width>0 ){811          /* Adjust width to account for extra bytes in UTF-8 characters */812          int ii = length - 1;813          while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;814        }815        break;816      case etESCAPE_q:          /* %q: Escape ' characters */817      case etESCAPE_Q:          /* %Q: Escape ' and enclose in '...' */818      case etESCAPE_w: {        /* %w: Escape " characters */819        i64 i, j, k, n;820        int needQuote = 0;821        char ch;822        char *escarg;823        char q;824 825        if( bArgList ){826          escarg = getTextArg(pArgList);827        }else{828          escarg = va_arg(ap,char*);829        }830        if( escarg==0 ){831          escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)");832        }else if( xtype==etESCAPE_Q ){833          needQuote = 1;834        }835        if( xtype==etESCAPE_w ){836          q = '"';837          flag_alternateform = 0;838        }else{839          q = '\'';840        }841        /* For %q, %Q, and %w, the precision is the number of bytes (or842        ** characters if the ! flags is present) to use from the input.843        ** Because of the extra quoting characters inserted, the number844        ** of output characters may be larger than the precision.845        */846        k = precision;847        for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){848          if( ch==q )  n++;849          if( flag_altform2 && (ch&0xc0)==0xc0 ){850            while( (escarg[i+1]&0xc0)==0x80 ){ i++; }851          }852        }853        if( flag_alternateform ){854          /* For %#q, do unistr()-style backslash escapes for855          ** all control characters, and for backslash itself.856          ** For %#Q, do the same but only if there is at least857          ** one control character. */858          u32 nBack = 0;859          u32 nCtrl = 0;860          for(k=0; k<i; k++){861            if( escarg[k]=='\\' ){862              nBack++;863            }else if( ((u8*)escarg)[k]<=0x1f ){864              nCtrl++;865            }866          }867          if( nCtrl || xtype==etESCAPE_q ){868            n += nBack + 5*nCtrl;869            if( xtype==etESCAPE_Q ){870              n += 10;871              needQuote = 2;872            }873          }else{874            flag_alternateform = 0;875          }876        }877        n += i + 3;878        if( n>etBUFSIZE ){879          bufpt = zExtra = printfTempBuf(pAccum, n);880          if( bufpt==0 ) return;881        }else{882          bufpt = buf;883        }884        j = 0;885        if( needQuote ){886          if( needQuote==2 ){887            memcpy(&bufpt[j], "unistr('", 8);888            j += 8;889          }else{890            bufpt[j++] = '\'';891          }892        }893        k = i;894        if( flag_alternateform ){895          for(i=0; i<k; i++){896            bufpt[j++] = ch = escarg[i];897            if( ch==q ){898              bufpt[j++] = ch;899            }else if( ch=='\\' ){900              bufpt[j++] = '\\';901            }else if( ((unsigned char)ch)<=0x1f ){902              bufpt[j-1] = '\\';903              bufpt[j++] = 'u';904              bufpt[j++] = '0';905              bufpt[j++] = '0';906              bufpt[j++] = ch>=0x10 ? '1' : '0';907              bufpt[j++] = "0123456789abcdef"[ch&0xf];908            }909          }910        }else{911          for(i=0; i<k; i++){912            bufpt[j++] = ch = escarg[i];913            if( ch==q ) bufpt[j++] = ch;914          }915        }916        if( needQuote ){917          bufpt[j++] = '\'';918          if( needQuote==2 ) bufpt[j++] = ')';919        }920        bufpt[j] = 0;921        length = j;922        goto adjust_width_for_utf8;923      }924      case etTOKEN: {925        if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;926        if( flag_alternateform ){927          /* %#T means an Expr pointer that uses Expr.u.zToken */928          Expr *pExpr = va_arg(ap,Expr*);929          if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){930            sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);931            sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);932          }933        }else{934          /* %T means a Token pointer */935          Token *pToken = va_arg(ap, Token*);936          assert( bArgList==0 );937          if( pToken && pToken->n ){938            sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);939            sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);940          }941        }942        length = width = 0;943        break;944      }945      case etSRCITEM: {946        SrcItem *pItem;947        if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;948        pItem = va_arg(ap, SrcItem*);949        assert( bArgList==0 );950        if( pItem->zAlias && !flag_altform2 ){951          sqlite3_str_appendall(pAccum, pItem->zAlias);952        }else if( pItem->zName ){953          if( pItem->fg.fixedSchema==0954           && pItem->fg.isSubquery==0955           && pItem->u4.zDatabase!=0956          ){957            sqlite3_str_appendall(pAccum, pItem->u4.zDatabase);958            sqlite3_str_append(pAccum, ".", 1);959          }960          sqlite3_str_appendall(pAccum, pItem->zName);961        }else if( pItem->zAlias ){962          sqlite3_str_appendall(pAccum, pItem->zAlias);963        }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */964          Select *pSel = pItem->u4.pSubq->pSelect;965          assert( pSel!=0 ); 966          if( pSel->selFlags & SF_NestedFrom ){967            sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);968          }else if( pSel->selFlags & SF_MultiValue ){969            assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );970            sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",971                                pItem->u1.nRow);972          }else{973            sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);974          }975        }976        length = width = 0;977        break;978      }979      default: {980        assert( xtype==etINVALID );981        return;982      }983    }/* End switch over the format type */984    /*985    ** The text of the conversion is pointed to by "bufpt" and is986    ** "length" characters long.  The field width is "width".  Do987    ** the output.  Both length and width are in bytes, not characters,988    ** at this point.  If the "!" flag was present on string conversions989    ** indicating that width and precision should be expressed in characters,990    ** then the values have been translated prior to reaching this point.991    */992    width -= length;993    if( width>0 ){994      if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');995      sqlite3_str_append(pAccum, bufpt, length);996      if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');997    }else{998      sqlite3_str_append(pAccum, bufpt, length);999    }1000 1001    if( zExtra ){1002      sqlite3DbFree(pAccum->db, zExtra);1003      zExtra = 0;1004    }1005  }/* End for loop over the format string */1006} /* End of function */1007 1008 1009/*1010** The z string points to the first character of a token that is1011** associated with an error.  If db does not already have an error1012** byte offset recorded, try to compute the error byte offset for1013** z and set the error byte offset in db.1014*/1015void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){1016  const Parse *pParse;1017  const char *zText;1018  const char *zEnd;1019  assert( z!=0 );1020  if( NEVER(db==0) ) return;1021  if( db->errByteOffset!=(-2) ) return;1022  pParse = db->pParse;1023  if( NEVER(pParse==0) ) return;1024  zText =pParse->zTail;1025  if( NEVER(zText==0) ) return;1026  zEnd = &zText[strlen(zText)];1027  if( SQLITE_WITHIN(z,zText,zEnd) ){1028    db->errByteOffset = (int)(z-zText);1029  }1030}1031 1032/*1033** If pExpr has a byte offset for the start of a token, record that as1034** as the error offset.1035*/1036void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){1037  while( pExpr1038     && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)1039  ){1040    pExpr = pExpr->pLeft;1041  }1042  if( pExpr==0 ) return;1043  if( ExprHasProperty(pExpr, EP_FromDDL) ) return;1044  db->errByteOffset = pExpr->w.iOfst;1045}1046 1047/*1048** Enlarge the memory allocation on a StrAccum object so that it is1049** able to accept at least N more bytes of text.1050**1051** Return the number of bytes of text that StrAccum is able to accept1052** after the attempted enlargement.  The value returned might be zero.1053*/1054int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){1055  char *zNew;1056  assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */1057  if( p->accError ){1058    testcase(p->accError==SQLITE_TOOBIG);1059    testcase(p->accError==SQLITE_NOMEM);1060    return 0;1061  }1062  if( p->mxAlloc==0 ){1063    sqlite3StrAccumSetError(p, SQLITE_TOOBIG);1064    return p->nAlloc - p->nChar - 1;1065  }else{1066    char *zOld = isMalloced(p) ? p->zText : 0;1067    i64 szNew = p->nChar + N + 1;1068    if( szNew+p->nChar<=p->mxAlloc ){1069      /* Force exponential buffer size growth as long as it does not overflow,1070      ** to avoid having to call this routine too often */1071      szNew += p->nChar;1072    }1073    if( szNew > p->mxAlloc ){1074      sqlite3_str_reset(p);1075      sqlite3StrAccumSetError(p, SQLITE_TOOBIG);1076      return 0;1077    }else{1078      p->nAlloc = (int)szNew;1079    }1080    if( p->db ){1081      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);1082    }else{1083      zNew = sqlite3Realloc(zOld, p->nAlloc);1084    }1085    if( zNew ){1086      assert( p->zText!=0 || p->nChar==0 );1087      if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);1088      p->zText = zNew;1089      p->nAlloc = sqlite3DbMallocSize(p->db, zNew);1090      p->printfFlags |= SQLITE_PRINTF_MALLOCED;1091    }else{1092      sqlite3_str_reset(p);1093      sqlite3StrAccumSetError(p, SQLITE_NOMEM);1094      return 0;1095    }1096  }1097  assert( N>=0 && N<=0x7fffffff );1098  return (int)N;1099}1100 1101/*1102** Append N copies of character c to the given string buffer.1103*/1104void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){1105  testcase( p->nChar + (i64)N > 0x7fffffff );1106  if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){1107    return;1108  }1109  while( (N--)>0 ) p->zText[p->nChar++] = c;1110}1111 1112/*1113** The StrAccum "p" is not large enough to accept N new bytes of z[].1114** So enlarge if first, then do the append.1115**1116** This is a helper routine to sqlite3_str_append() that does special-case1117** work (enlarging the buffer) using tail recursion, so that the1118** sqlite3_str_append() routine can use fast calling semantics.1119*/1120static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){1121  N = sqlite3StrAccumEnlarge(p, N);1122  if( N>0 ){1123    memcpy(&p->zText[p->nChar], z, N);1124    p->nChar += N;1125  }1126}1127 1128/*1129** Append N bytes of text from z to the StrAccum object.  Increase the1130** size of the memory allocation for StrAccum if necessary.1131*/1132void sqlite3_str_append(sqlite3_str *p, const char *z, int N){1133  assert( z!=0 || N==0 );1134  assert( p->zText!=0 || p->nChar==0 || p->accError );1135  assert( N>=0 );1136  assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );1137  if( p->nChar+N >= p->nAlloc ){1138    enlargeAndAppend(p,z,N);1139  }else if( N ){1140    assert( p->zText );1141    p->nChar += N;1142    memcpy(&p->zText[p->nChar-N], z, N);1143  }1144}1145 1146/*1147** Append the complete text of zero-terminated string z[] to the p string.1148*/1149void sqlite3_str_appendall(sqlite3_str *p, const char *z){1150  sqlite3_str_append(p, z, sqlite3Strlen30(z));1151}1152 1153 1154/*1155** Finish off a string by making sure it is zero-terminated.1156** Return a pointer to the resulting string.  Return a NULL1157** pointer if any kind of error was encountered.1158*/1159static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){1160  char *zText;1161  assert( p->mxAlloc>0 && !isMalloced(p) );1162  zText = sqlite3DbMallocRaw(p->db, 1+(u64)p->nChar );1163  if( zText ){1164    memcpy(zText, p->zText, p->nChar+1);1165    p->printfFlags |= SQLITE_PRINTF_MALLOCED;1166  }else{1167    sqlite3StrAccumSetError(p, SQLITE_NOMEM);1168  }1169  p->zText = zText;1170  return zText;1171}1172char *sqlite3StrAccumFinish(StrAccum *p){1173  if( p->zText ){1174    p->zText[p->nChar] = 0;1175    if( p->mxAlloc>0 && !isMalloced(p) ){1176      return strAccumFinishRealloc(p);1177    }1178  }1179  return p->zText;1180}1181 1182/*1183** Use the content of the StrAccum passed as the second argument1184** as the result of an SQL function.1185*/1186void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){1187  if( p->accError ){1188    sqlite3_result_error_code(pCtx, p->accError);1189    sqlite3_str_reset(p);1190  }else if( isMalloced(p) ){1191    sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);1192  }else{1193    sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);1194    sqlite3_str_reset(p);1195  }1196}1197 1198/*1199** This singleton is an sqlite3_str object that is returned if1200** sqlite3_malloc() fails to provide space for a real one.  This

Showing the first 1,200 of 1578 lines. Download the file for the rest.