#pragma ident "%Z%%M% %I% %E% SMI"
/*
** The "printf" code that follows dates from the 1980's. It is in
** the public domain. The original comments are included here for
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
**************************************************************************
**
** The following modules is an enhanced replacement for the "printf" subroutines
** found in the standard C library. The following enhancements are
** supported:
**
** + Additional functions. The standard set of "printf" functions
** includes printf, fprintf, sprintf, vprintf, vfprintf, and
** vsprintf. This module adds the following:
**
** * snprintf -- Works like sprintf, but has an extra argument
** which is the size of the buffer written to.
**
** * mprintf -- Similar to sprintf. Writes output to memory
** obtained from malloc.
**
** * xprintf -- Calls a function to dispose of output.
**
** * nprintf -- No output, but returns the number of characters
** that would have been output by printf.
**
** * A v- version (ex: vsnprintf) of every function is also
** supplied.
**
** + A few extensions to the formatting notation are supported:
**
** * The "=" flag (similar to "-") causes the output to be
** be centered in the appropriately sized field.
**
** * The %b field outputs an integer in binary notation.
**
** * The %c field now accepts a precision. The character output
** is repeated by the number of times the precision specifies.
**
** * The %' field works like %c, but takes as its character the
** next character of the format string, instead of the next
** argument. For example, printf("%.78'-") prints 78 minus
** signs, the same as printf("%.78c",'-').
**
** + When compiled using GCC on a SPARC, this version of printf is
** faster than the library printf for SUN OS 4.1.
**
** + All functions are fully reentrant.
**
*/
#include "sqliteInt.h"
/*
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
/* The rest are extensions, not normally found in printf() */
NULL pointers replaced by SQL NULL. %Q */
/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;
/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
} et_info;
/*
** Allowed values for et_info.flags
*/
/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
{ 's', 0, 0, etSTRING, 0, 0 },
{ 'q', 0, 0, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
};
/*
** If NOFLOATINGPOINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef etNOFLOATINGPOINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0
** Return the ascii code for the leading digit of *val, then
** multiply "*val" by 10.0 to renormalize.
**
** Example:
** input: *val = 3.14159
** output: *val = 1.4159 function return = '3'
**
** The counter *cnt is incremented each time. After counter exceeds
** 16 (the number of significant digits in a 64-bit float) '0' is
** always returned.
*/
int digit;
d = digit;
digit += '0';
return digit;
}
#endif
/*
** The root program. All variations call this core.
**
** INPUTS:
** func This is a pointer to a function taking three arguments
** 1. A pointer to anything. Same as the "arg" parameter.
** 2. A pointer to the list of characters to be output
** (Note, this list is NOT null terminated.)
** 3. An integer number of characters to be output.
** (Note: This number might be zero.)
**
** arg This is the pointer to anything which will be passed as the
** first argument to "func". Use it for whatever you like.
**
** fmt This is the format string, as in the usual print.
**
** ap This is a pointer to a list of arguments. Same as in
** vfprint.
**
** OUTPUTS:
** The return value is the total number of characters sent to
** the function "func". Returns -1 on a error.
**
** Note that the order in which automatic variables are declared below
** seems to make a big difference in determining how fast this beast
** will run.
*/
static int vxprintf(
void (*func)(void*,const char*,int), /* Consumer of text */
void *arg, /* First argument to the consumer */
int useExtended, /* Allow extended %-conversions */
const char *fmt, /* Format string */
){
int c; /* Next character in the format string */
#ifndef etNOFLOATINGPOINT
#endif
bufpt = 0;
if( c!='%' ){
int amt;
amt = 1;
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
errorflag = 1;
count++;
break;
}
/* Find out what flags are present */
flag_alternateform = flag_zeropad = 0;
do{
switch( c ){
default: break;
}
}while( c==0 && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
if( width<0 ){
flag_leftjustify = 1;
}
c = *++fmt;
}else{
while( c>='0' && c<='9' ){
c = *++fmt;
}
}
}
/* Get the precision */
if( c=='.' ){
precision = 0;
c = *++fmt;
if( c=='*' ){
c = *++fmt;
}else{
while( c>='0' && c<='9' ){
c = *++fmt;
}
}
/* Limit the precision to prevent overflowing buf[] during conversion */
}else{
precision = -1;
}
/* Get the conversion type modifier */
if( c=='l' ){
flag_long = 1;
c = *++fmt;
}else{
flag_long = 0;
}
/* Fetch the info entry for the field */
infop = 0;
}
break;
}
}
zExtra = 0;
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
switch( xtype ){
case etRADIX:
#if 1
/* For the format %#x, the value zero is printed "0" not "0x0".
** I think this is stupid. */
if( longvalue==0 ) flag_alternateform = 0;
#else
/* More sensible: turn off the prefix for octal (to prevent "00"),
** but leave the prefix for hex. */
#endif
if( *(long*)&longvalue<0 ){
prefix = '-';
else prefix = 0;
}else prefix = 0;
}
{
register int base;
do{ /* Convert to ascii */
}while( longvalue>0 );
}
}
char *pre, x;
}
}
break;
case etFLOAT:
case etEXP:
case etGENERIC:
#ifndef etNOFLOATINGPOINT
if( realvalue<0.0 ){
prefix = '-';
}else{
else prefix = 0;
}
rounder = 0.0;
#if 0
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
#else
/* It makes more sense to use 0.5 */
#endif
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( realvalue>0.0 ){
bufpt = "NaN";
length = 3;
break;
}
}
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
}
}else{
}
}else{
flag_rtz = 0;
}
/*
** The "exp+precision" test causes output to be of type etEXP if
** the precision is too large to fit in buf[].
*/
nsd = 0;
*(bufpt++) = '0';
}
*(bufpt--) = 0; /* Null terminate */
}
bufpt++; /* point to next free slot */
}else{ /* etEXP or etGENERIC */
bufpt--; /* point to last digit */
}
bufpt++; /* point to next free slot */
else { *(bufpt++) = '+'; }
if( exp>=100 ){
exp %= 100;
}
}
}
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
int i;
}
i = prefix!=0;
}
#endif
break;
case etSIZE:
break;
case etPERCENT:
buf[0] = '%';
length = 1;
break;
case etCHARLIT:
case etCHARX:
if( precision>=0 ){
}else{
length =1;
}
break;
case etSTRING:
case etDYNSTRING:
if( bufpt==0 ){
bufpt = "";
}else if( xtype==etDYNSTRING ){
}
break;
case etSQLESCAPE:
case etSQLESCAPE2:
{
int i, j, n, c, isnull;
for(i=n=0; (c=arg[i])!=0; i++){
if( c=='\'' ) n++;
}
if( n>etBUFSIZE ){
if( bufpt==0 ) return -1;
}else{
}
j = 0;
for(i=0; (c=arg[i])!=0; i++){
bufpt[j++] = c;
if( c=='\'' ) bufpt[j++] = c;
}
bufpt[j] = 0;
length = j;
}
break;
case etTOKEN: {
break;
}
case etSRCLIST: {
}
break;
}
case etERROR:
buf[0] = '%';
buf[1] = c;
errorflag = 0;
idx = 1+(c!=0);
if( c==0 ) fmt--;
break;
}/* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
** "length" characters long. The field width is "width". Do
** the output.
*/
if( !flag_leftjustify ){
register int nspace;
if( nspace>0 ){
while( nspace>=etSPACESIZE ){
nspace -= etSPACESIZE;
}
}
}
if( length>0 ){
}
if( flag_leftjustify ){
register int nspace;
if( nspace>0 ){
while( nspace>=etSPACESIZE ){
nspace -= etSPACESIZE;
}
}
}
if( zExtra ){
}
}/* End for loop over the format string */
} /* End of function */
/* This structure is used to store state information about the
** write to memory that is currently in progress.
*/
struct sgMprintf {
};
/*
** This function implements the callback from vxprintf.
**
** This routine add nNewChar characters of text in zNewText to
** the sgMprintf structure pointed to by "arg".
*/
}else{
}
}else{
}
}
}
if( nNewChar>0 ){
}
}
}
/*
** This routine is a wrapper around xprintf() that invokes mout() as
** the consumer.
*/
static char *base_vprintf(
void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */
int useInternal, /* Use internal %-conversions if true */
char *zInitBuf, /* Initially write here, before mallocing */
int nInitBuf, /* Size of zInitBuf[] */
const char *zFormat, /* format string */
){
if( xRealloc ){
}
}
}
/*
** Realloc that is a real function, not a macro.
*/
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *z;
return z;
}
/*
** Print into memory obtained from malloc(). Do not use the internal
** %-conversion extensions. This routine is for use by external users.
*/
char *z;
z = base_vprintf((void*(*)(void*,int))realloc, 0,
return z;
}
/* This is the varargs version of sqlite_mprintf.
*/
return base_vprintf((void*(*)(void*,int))realloc, 0,
}
/*
** sqlite_snprintf() works like snprintf() except that it ignores the
** current locale settings. This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
char *z;
return z;
}
/*
** The following four routines implement the varargs versions of the
** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h
** header files for a more detailed description of how these interfaces
** work.
**
** These routines are all just simple wrappers.
*/
int sqlite_exec_printf(
const char *sqlFormat, /* printf-style format string for the SQL */
void *pArg, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string. */
){
int rc;
return rc;
}
int sqlite_exec_vprintf(
const char *sqlFormat, /* printf-style format string for the SQL */
void *pArg, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
){
char *zSql;
int rc;
return rc;
}
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncol, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string */
){
int rc;
return rc;
}
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
){
char *zSql;
int rc;
return rc;
}