]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Complete shell transition to using {f,o,e}put{f,z}() emit functions. This fails test...
authorlarrybr <larrybr@noemail.net>
Sat, 11 Nov 2023 20:46:12 +0000 (20:46 +0000)
committerlarrybr <larrybr@noemail.net>
Sat, 11 Nov 2023 20:46:12 +0000 (20:46 +0000)
FossilOrigin-Name: 923c6b8b3a508c715b816c6bcd2ae9ac519bc37a62afc4ef813085c00f1e7cb6

1  2 
ext/consio/console_io.c
ext/consio/console_io.h
manifest
manifest.uuid
src/shell.c.in

index 620200a9505342b3a2861edec832e3ae4a359ac5,0000000000000000000000000000000000000000..8dd53dcf83459576652d044cb03b1e59cd0cf731
mode 100755,000000..100755
--- /dev/null
@@@ -1,637 -1,0 +1,665 @@@
 +/*
 +** 2023 November 4
 +**
 +** The author disclaims copyright to this source code.  In place of
 +** a legal notice, here is a blessing:
 +**
 +**    May you do good and not evil.
 +**    May you find forgiveness for yourself and forgive others.
 +**    May you share freely, never taking more than you give.
 +**
 +********************************************************************************
 +** This file implements various interfaces used for console and stream I/O
 +** by the SQLite project command-line tools, as explained in console_io.h .
 +** Functions prefixed by "SQLITE_INTERNAL_LINKAGE" behave as described there.
 +*/
 +
 +#ifndef SQLITE_CDECL
 +# define SQLITE_CDECL
 +#endif
 +
 +#ifndef SHELL_NO_SYSINC
 +# include <stdarg.h>
 +# include <string.h>
 +# include <stdlib.h>
 +# include <limits.h>
 +# include <assert.h>
 +# include "console_io.h"
 +# include "sqlite3.h"
 +#endif
 +
 +#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
 +# ifndef SHELL_NO_SYSINC
 +#  include <io.h>
 +#  include <fcntl.h>
 +#  undef WIN32_LEAN_AND_MEAN
 +#  define WIN32_LEAN_AND_MEAN
 +#  include <windows.h>
 +# endif
 +# ifdef SHELL_LEGACY_CONSOLE_IO
 +#  define SHELL_CON_TRANSLATE 2 /* Use UTF-8/MBCS translation for console I/O */
 +# else
 +#  define SHELL_CON_TRANSLATE 1 /* Use WCHAR Windows APIs for console I/O */
 +# endif
 +#else
 +# ifndef SHELL_NO_SYSINC
 +#  include <unistd.h>
 +# endif
 +# define SHELL_CON_TRANSLATE 0 /* Use plain C library stream I/O at console */
 +#endif
 +
 +#if SHELL_CON_TRANSLATE
 +static HANDLE handleOfFile(FILE *pf){
 +  int fileDesc = _fileno(pf);
 +  union { intptr_t osfh; HANDLE fh; } fid = {
 +    (fileDesc>=0)? _get_osfhandle(fileDesc) : (intptr_t)INVALID_HANDLE_VALUE
 +  };
 +  return fid.fh;
 +}
 +#endif
 +
 +typedef struct PerStreamTags {
 +#if SHELL_CON_TRANSLATE
 +  HANDLE hx;
 +  DWORD consMode;
 +#else
 +  short reachesConsole;
 +#endif
 +  FILE *pf;
 +} PerStreamTags;
 +
 +/* Define NULL-like value for things which can validly be 0. */
 +#define SHELL_INVALID_FILE_PTR ((FILE *)~0)
 +#if SHELL_CON_TRANSLATE
 +# define SHELL_INVALID_CONS_MODE 0xFFFF0000
 +#endif
 +
 +#if SHELL_CON_TRANSLATE
 +# define CI_INITIALIZER \
 +  { INVALID_HANDLE_VALUE, SHELL_INVALID_CONS_MODE, SHELL_INVALID_FILE_PTR }
 +#else
 +# define CI_INITIALIZER { 0, SHELL_INVALID_FILE_PTR }
 +#endif
 +
 +/* Quickly say whether a known output is going to the console. */
 +static short pstReachesConsole(PerStreamTags *ppst){
 +#if SHELL_CON_TRANSLATE
 +  return (ppst->hx != INVALID_HANDLE_VALUE);
 +#else
 +  return (ppst->reachesConsole != 0);
 +#endif
 +}
 +
 +#if SHELL_CON_TRANSLATE
 +static void restoreConsoleArb(PerStreamTags *ppst){
 +  if( pstReachesConsole(ppst) ) SetConsoleMode(ppst->hx, ppst->consMode);
 +}
 +#else
 +# define restoreConsoleArb(ppst)
 +#endif
 +
 +/* Say whether FILE* appears to be a console, collect associated info. */
 +static short streamOfConsole(FILE *pf, /* out */ PerStreamTags *ppst){
 +#if SHELL_CON_TRANSLATE
 +  short rv = 0;
 +  DWORD dwCM = SHELL_INVALID_CONS_MODE;
 +  HANDLE fh = handleOfFile(pf);
 +  ppst->pf = pf;
 +  if( INVALID_HANDLE_VALUE != fh ){
 +    rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwCM));
 +  }
 +  ppst->hx = (rv)? fh : INVALID_HANDLE_VALUE;
 +  ppst->consMode = dwCM;
 +  return rv;
 +#else
 +  ppst->pf = pf;
 +  ppst->reachesConsole = ( (short)isatty(fileno(pf)) );
 +  return ppst->reachesConsole;
 +#endif
 +}
 +
 +#if SHELL_CON_TRANSLATE
 +/* Define console modes for use with the Windows Console API. */
 +# define SHELL_CONI_MODE \
 +  (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \
 +  | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT)
 +# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \
 +  | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
 +#endif
 +
 +typedef struct ConsoleInfo {
 +  PerStreamTags pstSetup[3];
 +  PerStreamTags pstDesignated[3];
 +  StreamsAreConsole sacSetup;
 +} ConsoleInfo;
 +
 +static short isValidStreamInfo(PerStreamTags *ppst){
 +  return (ppst->pf != SHELL_INVALID_FILE_PTR);
 +}
 +
 +static ConsoleInfo consoleInfo = {
 +  { /* pstSetup */ CI_INITIALIZER, CI_INITIALIZER, CI_INITIALIZER },
 +  { /* pstDesignated[] */ CI_INITIALIZER, CI_INITIALIZER, CI_INITIALIZER },
 +  SAC_NoConsole /* sacSetup */
 +};
 +#undef SHELL_INVALID_FILE_PTR
 +#undef CI_INITIALIZER
 +
 +SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;
 +
 +static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
 +#if SHELL_CON_TRANSLATE
 +  if( pstReachesConsole(ppst) ){
 +    DWORD cm = odir? SHELL_CONO_MODE : SHELL_CONI_MODE;
 +    SetConsoleMode(ppst->hx, cm);
 +# if SHELL_CON_TRANSLATE == 2
 +    _setmode(_fileno(ppst->pf), _O_TEXT);
 +# endif
 +  }
 +#else
 +  (void)ppst;
 +  (void)odir;
 +#endif
 +}
 +
 +SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void){
 +#if SHELL_CON_TRANSLATE
 +  int ix = 0;
 +  while( ix < 6 ){
 +    PerStreamTags *ppst = (ix<3)?
 +      &consoleInfo.pstSetup[ix] : &consoleInfo.pstDesignated[ix-3];
 +    maybeSetupAsConsole(ppst, (ix % 3)>0);
 +    ++ix;
 +  }
 +#endif
 +}
 +
 +SQLITE_INTERNAL_LINKAGE StreamsAreConsole
 +consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){
 +  StreamsAreConsole rv = SAC_NoConsole;
 +  FILE* apf[3] = { pfIn, pfOut, pfErr };
 +  int ix;
 +  for( ix = 2; ix >= 0; --ix ){
 +    PerStreamTags *ppst = &consoleInfo.pstSetup[ix];
 +    if( streamOfConsole(apf[ix], ppst) ){
 +      rv |= (SAC_InConsole<<ix);
 +    }
 +    consoleInfo.pstDesignated[ix] = *ppst;
 +    if( ix > 0 ) fflush(apf[ix]);
 +#if SHELL_CON_TRANSLATE == 2
 +    _setmode(_fileno(apf[ix]), _O_TEXT);
 +#endif
 +  }
 +  consoleInfo.sacSetup = rv;
 +  consoleRenewSetup();
 +  return rv;
 +}
 +
 +SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void ){
 +#if SHELL_CON_TRANSLATE
 +  static ConsoleInfo *pci = &consoleInfo;
 +  if( pci->sacSetup ){
 +    int ix;
 +    for( ix=0; ix<3; ++ix ){
 +      if( pci->sacSetup & (SAC_InConsole<<ix) ){
 +        PerStreamTags *ppst = &pci->pstSetup[ix];
 +# if SHELL_CON_TRANSLATE == 2
 +        static int tmode = _O_TEXT;
 +        /* Consider: Read this mode in consoleClassifySetup somehow.
 +        ** A _get_fmode() call almost works. But not with gcc, yet.
 +        ** This has to be done to make the CLI a callable function
 +        ** when legacy console I/O is done. (This may never happen.)
 +        */
 +        _setmode(_fileno(pci->pstSetup[ix].pf), tmode);
 +# endif
 +        SetConsoleMode(ppst->hx, ppst->consMode);
 +      }
 +    }
 +  }
 +#endif
 +}
 +
 +/* Say whether given FILE* is among those known, via either
 +** consoleClassifySetup() or set{Output,Error}Stream, as
 +** readable, and return an associated PerStreamTags pointer
 +** if so. Otherwise, return 0.
 +*/
 +static PerStreamTags * isKnownReadable(FILE *pf){
 +  static PerStreamTags *apst[] = {
 +    &consoleInfo.pstDesignated[0], &consoleInfo.pstSetup[0], 0
 +  };
 +  int ix = 0;
 +  do {
 +    if( apst[ix]->pf == pf ) break;
 +  } while( apst[++ix] != 0 );
 +  return apst[ix];
 +}
 +
 +/* Say whether given FILE* is among those known, via either
 +** consoleClassifySetup() or set{Output,Error}Stream, as
 +** writable, and return an associated PerStreamTags pointer
 +** if so. Otherwise, return 0.
 +*/
 +static PerStreamTags * isKnownWritable(FILE *pf){
 +  static PerStreamTags *apst[] = {
 +    &consoleInfo.pstDesignated[1], &consoleInfo.pstDesignated[2],
 +    &consoleInfo.pstSetup[1], &consoleInfo.pstSetup[2], 0
 +  };
 +  int ix = 0;
 +  do {
 +    if( apst[ix]->pf == pf ) break;
 +  } while( apst[++ix] != 0 );
 +  return apst[ix];
 +}
 +
 +static FILE *designateEmitStream(FILE *pf, unsigned chix){
 +  FILE *rv = consoleInfo.pstDesignated[chix].pf;
 +  if( pf == invalidFileStream ) return rv;
 +  else{
 +    /* Setting a possibly new output stream. */
 +    PerStreamTags *ppst = isKnownWritable(pf);
 +    if( ppst != 0 ){
 +      PerStreamTags pst = *ppst;
 +      consoleInfo.pstDesignated[chix] = pst;
 +    }else streamOfConsole(pf, &consoleInfo.pstDesignated[chix]);
 +  }
 +  return rv;
 +}
 +
 +SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf){
 +  return designateEmitStream(pf, 1);
 +}
 +SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf){
 +  return designateEmitStream(pf, 2);
 +}
 +
 +#if SHELL_CON_TRANSLATE
 +static void setModeFlushQ(FILE *pf, short bFlush, int mode){
 +  if( bFlush ) fflush(pf);
 +  _setmode(_fileno(pf), mode);
 +}
 +#else
 +# define setModeFlushQ(f, b, m) if(b) fflush(f)
 +#endif
 +
 +SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *pf, short bFlush){
 +  setModeFlushQ(pf, bFlush, _O_BINARY);
 +}
 +SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *pf, short bFlush){
 +  setModeFlushQ(pf, bFlush, _O_TEXT);
 +}
 +#undef setModeFlushQ
 +
 +#if SHELL_CON_TRANSLATE
 +/* Write plain 0-terminated output to stream known as reaching console. */
 +static int conioZstrOut(PerStreamTags *ppst, const char *z){
 +  int rv = 0;
 +  if( z!=NULL && *z!=0 ){
 +    int nc;
 +    int nwc;
 +# if SHELL_CON_TRANSLATE == 2
 +    UINT cocp = GetConsoleOutputCP();
 +    FILE *pfO = ppst->pf;
 +    if( cocp == CP_UTF8 ){
 +      /* This is not legacy action. But it can work better,
 +      ** when the console putatively can handle UTF-8. */
 +      return fputs(z, pfO)<0 ? 0 : (int)strlen(z);
 +    }
 +# endif
 +    nc = (int)strlen(z);
 +    nwc = MultiByteToWideChar(CP_UTF8,0, z,nc, 0,0);
 +    if( nwc > 0 ){
 +      WCHAR *zw = sqlite3_malloc64(nwc*sizeof(WCHAR));
 +      if( zw!=NULL ){
 +        nwc = MultiByteToWideChar(CP_UTF8,0, z,nc, zw,nwc);
 +        if( nwc > 0 ){
 +# if SHELL_CON_TRANSLATE == 2
 +          /* Legacy translation to active code page, then MBCS out. */
 +          rv = WideCharToMultiByte(cocp,0, zw,nwc, 0,0, 0,0);
 +          if( rv != 0 ){
 +            char *zmb = sqlite3_malloc64(rv+1);
 +            if( zmb != NULL ){
 +              rv = WideCharToMultiByte(cocp,0, zw,nwc, zmb,rv, 0,0);
 +              zmb[rv] = 0;
 +              if( fputs(zmb, pfO)<0 ) rv = 0;
 +              sqlite3_free(zmb);
 +            }
 +          }
 +# elif SHELL_CON_TRANSLATE == 1
 +          /* Translation from UTF-8 to UTF-16, then WCHARs out. */
 +          if( WriteConsoleW(ppst->hx, zw,nwc, 0, NULL) ){
 +            rv = nc;
 +          }
 +# endif
 +        }
 +        sqlite3_free(zw);
 +      }
 +    }
 +  }
 +  return rv;
 +}
 +
 +/* For {f,o,e}PrintfUtf8() when stream is known to reach console. */
 +static int conioVmPrintf(PerStreamTags *ppst, const char *zFormat, va_list ap){
 +  char *z = sqlite3_vmprintf(zFormat, ap);
 +  int rv = conioZstrOut(ppst, z);
 +  sqlite3_free(z);
 +  return rv;
 +}
 +#endif /* SHELL_CON_TRANSLATE */
 +
 +
 +static PerStreamTags * getDesignatedEmitStream(FILE *pf, unsigned chix,
 +                                               PerStreamTags *ppst){
 +  PerStreamTags *rv = isKnownWritable(pf);
 +  short isValid = (rv!=0)? isValidStreamInfo(rv) : 0;
 +  if( rv != 0 && isValid ) return rv;
 +  streamOfConsole(pf, ppst);
 +  return ppst;
 +}
 +
 +/* Get stream info, either for designated output or error stream when
 +** chix equals 1 or 2, or for an arbitrary stream when chix == 0.
 +** In either case, ppst references a caller-owned PerStreamTags
 +** struct which may be filled in if none of the known writable
 +** streams is being held by consoleInfo. The ppf parameter is an
 +** output when chix!=0 and an input when chix==0.
 + */
 +static PerStreamTags *
 +getEmitStreamInfo(unsigned chix, PerStreamTags *ppst,
 +                  /* in/out */ FILE **ppf){
 +  PerStreamTags *ppstTry;
 +  FILE *pfEmit;
 +  if( chix > 0 ){
 +    ppstTry = &consoleInfo.pstDesignated[chix];
 +    if( !isValidStreamInfo(ppstTry) ){
 +      ppstTry = &consoleInfo.pstSetup[chix];
 +      pfEmit = ppst->pf;
 +    }else pfEmit = ppstTry->pf;
 +    if( !isValidStreamInfo(ppst) ){
 +      pfEmit = (chix > 1)? stderr : stdout;
 +      ppstTry = ppst;
 +      streamOfConsole(pfEmit, ppstTry);
 +    }
 +    *ppf = pfEmit;
 +  }else{
 +    ppstTry = isKnownWritable(*ppf);
 +    if( ppstTry != 0 ) return ppstTry;
 +    streamOfConsole(*ppf, ppst);
 +    return ppst;
 +  }
 +  return ppstTry;
 +}
 +
 +SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...){
 +  va_list ap;
 +  int rv;
 +  FILE *pfOut;
 +  PerStreamTags pst; /* Needed only for heretofore unknown streams. */
 +  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
 +
 +  va_start(ap, zFormat);
 +#if SHELL_CON_TRANSLATE
 +  if( pstReachesConsole(ppst) ){
 +    rv = conioVmPrintf(ppst, zFormat, ap);
 +  }else{
 +#endif
 +    rv = vfprintf(pfOut, zFormat, ap);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +  va_end(ap);
 +  return rv;
 +}
 +
 +SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...){
 +  va_list ap;
 +  int rv;
 +  FILE *pfErr;
 +  PerStreamTags pst; /* Needed only for heretofore unknown streams. */
 +  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
 +
 +  va_start(ap, zFormat);
 +#if SHELL_CON_TRANSLATE
 +  if( pstReachesConsole(ppst) ){
 +    rv = conioVmPrintf(ppst, zFormat, ap);
 +  }else{
 +#endif
 +    rv = vfprintf(pfErr, zFormat, ap);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +  va_end(ap);
 +  return rv;
 +}
 +
 +SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...){
 +  va_list ap;
 +  int rv;
 +#if SHELL_CON_TRANSLATE
 +  PerStreamTags pst; /* Needed only for heretofore unknown streams. */
 +  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
 +#endif
 +
 +  va_start(ap, zFormat);
 +#if SHELL_CON_TRANSLATE
 +  if( pstReachesConsole(ppst) ){
 +    maybeSetupAsConsole(ppst, 1);
 +    rv = conioVmPrintf(ppst, zFormat, ap);
 +    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
 +  }else{
 +#endif
 +    rv = vfprintf(pfO, zFormat, ap);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +  va_end(ap);
 +  return rv;
 +}
 +
 +SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO){
 +#if SHELL_CON_TRANSLATE
 +  PerStreamTags pst; /* Needed only for heretofore unknown streams. */
 +  PerStreamTags *ppst = getEmitStreamInfo(0, &pst, &pfO);
 +  if( pstReachesConsole(ppst) ){
 +    int rv;
 +    maybeSetupAsConsole(ppst, 1);
 +    rv = conioZstrOut(ppst, z);
 +    if( 0 == isKnownWritable(ppst->pf) ) restoreConsoleArb(ppst);
 +    return rv;
 +  }else {
 +#endif
 +    return (fputs(z, pfO)<0)? 0 : (int)strlen(z);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +}
 +
 +SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z){
 +  FILE *pfErr;
 +  PerStreamTags pst; /* Needed only for heretofore unknown streams. */
 +  PerStreamTags *ppst = getEmitStreamInfo(2, &pst, &pfErr);
 +#if SHELL_CON_TRANSLATE
 +  if( pstReachesConsole(ppst) ) return conioZstrOut(ppst, z);
 +  else {
 +#endif
 +    return (fputs(z, pfErr)<0)? 0 : (int)strlen(z);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +}
 +
 +SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z){
 +  FILE *pfOut;
 +  PerStreamTags pst; /* Needed only for heretofore unknown streams. */
 +  PerStreamTags *ppst = getEmitStreamInfo(1, &pst, &pfOut);
 +#if SHELL_CON_TRANSLATE
 +  if( pstReachesConsole(ppst) ) return conioZstrOut(ppst, z);
 +  else {
 +#endif
 +    return (fputs(z, pfOut)<0)? 0 : (int)strlen(z);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +}
 +
++#if 0
++/* Next 3 functions could be optimized to avoid console mode futzing. */
++SQLITE_INTERNAL_LINKAGE int fPutcUtf8(int ch, FILE *pfO){
++  if( (ch & ~0x7f) != 0 ) return 0;
++  else{
++    char ac[2] = "?";
++    ac[0] = (char)ch;
++    return (fPutsUtf8(ac, pfO) > 0);
++  }
++}
++SQLITE_INTERNAL_LINKAGE int oPutcUtf8(int ch){
++  if( (ch & ~0x7f) != 0 ) return 0;
++  else{
++    char ac[2] = "?";
++    ac[0] = (char)ch;
++    return (oPutsUtf8(ac) > 0);
++  }
++}
++SQLITE_INTERNAL_LINKAGE int ePutcUtf8(int ch){
++  if( (ch & ~0x7f) != 0 ) return 0;
++  else{
++    char ac[2] = "?";
++    ac[0] = (char)ch;
++    return (ePutsUtf8(ac) > 0);
++  }
++}
++#endif
++
 +#if SHELL_CON_TRANSLATE==2
 +static int mbcsToUtf8InPlaceIfValid(char *pc, int nci, int nco, UINT codePage){
 +  WCHAR wcOneCode[2];
 +  int nuo = 0;
 +  int nwConvert = MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS,
 +                                      pc, nci, wcOneCode, 2);
 +  if( nwConvert > 0 ){
 +    nuo = WideCharToMultiByte(CP_UTF8, 0, wcOneCode, nwConvert, pc, nco, 0,0);
 +  }
 +  return nuo;
 +}
 +#endif
 +
 +SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn){
 +  if( pfIn==0 ) pfIn = stdin;
 +#if SHELL_CON_TRANSLATE
 +  if( pfIn == consoleInfo.pstSetup[0].pf
 +      && (consoleInfo.sacSetup & SAC_InConsole)!=0 ){
 +# if SHELL_CON_TRANSLATE==1
 +#  define SHELL_GULP 150 /* Count of WCHARS to be gulped at a time */
 +    WCHAR wcBuf[SHELL_GULP+1];
 +    int lend = 0, noc = 0;
 +    if( ncMax > 0 ) cBuf[0] = 0;
 +    while( noc < ncMax-8-1 && !lend ){
 +      /* There is room for at least 2 more characters and a 0-terminator. */
 +      int na = (ncMax > SHELL_GULP*4+1 + noc)? SHELL_GULP : (ncMax-1 - noc)/4;
 +#  undef SHELL_GULP
 +      DWORD nbr = 0;
 +      BOOL bRC = ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf, na, &nbr, 0);
 +      if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){
 +        /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */
 +        DWORD nbrx;
 +        bRC &= ReadConsoleW(consoleInfo.pstSetup[0].hx, wcBuf+nbr, 1, &nbrx, 0);
 +        if( bRC ) nbr += nbrx;
 +      }
 +      if( !bRC || (noc==0 && nbr==0) ) return 0;
 +      if( nbr > 0 ){
 +        int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0);
 +        if( nmb != 0 && noc+nmb <= ncMax ){
 +          int iseg = noc;
 +          nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0);
 +          noc += nmb;
 +          /* Fixup line-ends as coded by Windows for CR (or "Enter".)
 +          ** This is done without regard for any setMode{Text,Binary}()
 +          ** call that might have been done on the interactive input.
 +          */
 +          if( noc > 0 ){
 +            if( cBuf[noc-1]=='\n' ){
 +              lend = 1;
 +              if( noc > 1 && cBuf[noc-2]=='\r' ) cBuf[--noc-1] = '\n';
 +            }
 +          }
 +          /* Check for ^Z (anywhere in line) too, to act as EOF. */
 +          while( iseg < noc ){
 +            if( cBuf[iseg]=='\x1a' ){
 +              noc = iseg; /* Chop ^Z and anything following. */
 +              lend = 1; /* Counts as end of line too. */
 +              break;
 +            }
 +            ++iseg;
 +          }
 +        }else break; /* Drop apparent garbage in. (Could assert.) */
 +      }else break;
 +    }
 +    /* If got nothing, (after ^Z chop), must be at end-of-file. */
 +    if( noc > 0 ){
 +      cBuf[noc] = 0;
 +      return cBuf;
 +    }else return 0;
 +# elif SHELL_CON_TRANSLATE==2
 +    /* This is not done efficiently because it may never be used.
 +    ** Also, it is interactive input so it need not be fast.  */
 +    int nco = 0;
 +    /* For converstion to WCHAR, or pre-test of same. */
 +    UINT cicp = GetConsoleCP(); /* For translation from mbcs. */
 +    /* If input code page is CP_UTF8, must bypass MBCS input
 +    ** collection because getc() returns 0 for non-ASCII byte
 +    ** Instead, use fgets() which repects character boundaries. */
 +    if( cicp == CP_UTF8 ) return fgets(cBuf, ncMax, pfIn);
 +    while( ncMax-nco >= 5 ){
 +      /* Have space for max UTF-8 group and 0-term. */
 +      int nug = 0;
 +      int c = getc(pfIn);
 +      if( c < 0 ){
 +        if( nco > 0 ) break;
 +        else return 0;
 +      }
 +      cBuf[nco] = (char)c;
 +      if( c < 0x80 ){
 +        ++nco;
 +        if( c == '\n' ) break;
 +        continue;
 +      }
 +      /* Deal with possible mbcs lead byte. */
 +      nug = mbcsToUtf8InPlaceIfValid(cBuf+nco, 1, ncMax-nco-1, cicp);
 +      if( nug > 0 ){
 +        nco += nug;
 +      }else{
 +        /* Must have just mbcs lead byte; get the trail byte(s). */
 +        int ntb = 1, ct;
 +        while( ntb <= 3 ){ /* No more under any multi-byte code. */
 +          ct = getc(pfIn);
 +          if( ct < 0 || ct == '\n' ){
 +            /* Just drop whatever garbage preceded the newline or.
 +            ** EOF. It's not valid, should not happen, and there
 +            ** is no good way to deal with it, short of bailing. */
 +            if( ct > 0 ){
 +              cBuf[nco++] = (int)ct;
 +            }
 +            break;
 +          }
 +          /* Treat ct as bona fide MBCS trailing byte, if valid. */
 +          cBuf[nco+ntb] = ct;
 +          nug = mbcsToUtf8InPlaceIfValid(cBuf+nco, 1+ntb, ncMax-nco-1, cicp);
 +          if( nug > 0 ){
 +            nco += nug;
 +            break;
 +          }
 +        }
 +        if( ct < 0 ) break;
 +      }
 +    }
 +    cBuf[nco] = 0;
 +    return cBuf;
 +# endif
 +  }else{
 +#endif
 +    return fgets(cBuf, ncMax, pfIn);
 +#if SHELL_CON_TRANSLATE
 +  }
 +#endif
 +}
index 2d6178fed3e0afa11e8f17cda288ee9599547848,0000000000000000000000000000000000000000..9a049ad6a6ed671583bdf0678d913c75a386639b
mode 100644,000000..100644
--- /dev/null
@@@ -1,226 -1,0 +1,241 @@@
 +/*
 +** 2023 November 1
 +**
 +** The author disclaims copyright to this source code.  In place of
 +** a legal notice, here is a blessing:
 +**
 +**    May you do good and not evil.
 +**    May you find forgiveness for yourself and forgive others.
 +**    May you share freely, never taking more than you give.
 +**
 +********************************************************************************
 +** This file exposes various interfaces used for console and other I/O
 +** by the SQLite project command-line tools. These interfaces are used
 +** at either source conglomeration time, compilation time, or run time.
 +** This source provides for either inclusion into conglomerated,
 +** "single-source" forms or separate compilation then linking.
 +**
 +** Platform dependencies are "hidden" here by various stratagems so
 +** that, provided certain conditions are met, the programs using this
 +** source or object code compiled from it need no explicit conditional
 +** compilation in their source for their console and stream I/O.
 +**
 +** The symbols and functionality exposed here are not a public API.
 +** This code may change in tandem with other project code as needed.
 +*/
 +
 +#ifndef SQLITE_INTERNAL_LINKAGE
 +# define SQLITE_INTERNAL_LINKAGE extern /* external to translation unit */
 +# include <stdio.h>
 +#else
 +# define SHELL_NO_SYSINC /* Better yet, modify mkshellc.tcl for this. */
 +#endif
 +
 +#ifndef SQLITE3_H
 +# include "sqlite3.h"
 +#endif
 +
 +/* Define enum for use with following function. */
 +typedef enum StreamsAreConsole {
 +  SAC_NoConsole = 0,
 +  SAC_InConsole = 1, SAC_OutConsole = 2, SAC_ErrConsole = 4,
 +  SAC_AnyConsole = 0x7
 +} StreamsAreConsole;
 +
 +/*
 +** Classify the three standard I/O streams according to whether
 +** they are connected to a console attached to the process.
 +**
 +** Returns the bit-wise OR of SAC_{In,Out,Err}Console values,
 +** or SAC_NoConsole if none of the streams reaches a console.
 +**
 +** This function should be called before any I/O is done with
 +** the given streams. As a side-effect, the given inputs are
 +** recorded so that later I/O operations on them may be done
 +** differently than the C library FILE* I/O would be done,
 +** iff the stream is used for the I/O functions that follow,
 +** and to support the ones that use an implicit stream.
 +**
 +** On some platforms, stream or console mode alteration (aka
 +** "Setup") may be made which is undone by consoleRestore().
 +*/
 +SQLITE_INTERNAL_LINKAGE StreamsAreConsole
 +consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr );
 +/* A usual call for convenience: */
 +#define SQLITE_STD_CONSOLE_INIT() consoleClassifySetup(stdin,stdout,stderr)
 +
 +/*
 +** After an initial call to consoleClassifySetup(...), renew
 +** the same setup it effected. (A call not after is an error.)
 +** This will restore state altered by consoleRestore();
 +**
 +** Applications which run an inferior (child) process which
 +** inherits the same I/O streams may call this function after
 +** such a process exits to guard against console mode changes.
 +*/
 +SQLITE_INTERNAL_LINKAGE void consoleRenewSetup(void);
 +
 +/*
 +** Undo any side-effects left by consoleClassifySetup(...).
 +**
 +** This should be called after consoleClassifySetup() and
 +** before the process terminates normally. It is suitable
 +** for use with the atexit() C library procedure. After
 +** this call, no console I/O should be done until one of
 +** console{Classify or Renew}Setup(...) is called again.
 +**
 +** Applications which run an inferior (child) process that
 +** inherits the same I/O streams might call this procedure
 +** before so that said process will have a console setup
 +** however users have configured it or come to expect.
 +*/
 +SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );
 +
 +/*
 +** Set stream to be used for the functions below which write
 +** to "the designated X stream", where X is Output or Error.
 +** Returns the previous value.
 +**
 +** Alternatively, pass the special value, invalidFileStream,
 +** to get the designated stream value without setting it.
 +**
 +** Before the designated streams are set, they default to
 +** those passed to consoleClassifySetup(...), and before
 +** that is called they default to stdout and stderr.
 +**
 +** It is error to close a stream so designated, then, without
 +** designating another, use the corresponding {o,e}Emit(...).
 +*/
 +SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
 +SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
 +SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
 +
 +/*
 +** Emit output like fprintf(). If the output is going to the
 +** console and translation from UTF-8 is necessary, perform
 +** the needed translation. Otherwise, write formatted output
 +** to the provided stream almost as-is, possibly with newline
 +** translation as specified by set{Binary,Text}Mode().
 +*/
 +SQLITE_INTERNAL_LINKAGE int fPrintfUtf8(FILE *pfO, const char *zFormat, ...);
 +/* Like fPrintfUtf8 except stream is always the designated output. */
 +SQLITE_INTERNAL_LINKAGE int oPrintfUtf8(const char *zFormat, ...);
 +/* Like fPrintfUtf8 except stream is always the designated error. */
 +SQLITE_INTERNAL_LINKAGE int ePrintfUtf8(const char *zFormat, ...);
 +
 +/*
 +** Emit output like fputs(). If the output is going to the
 +** console and translation from UTF-8 is necessary, perform
 +** the needed translation. Otherwise, write given text to the
 +** provided stream almost as-is, possibly with newline
 +** translation as specified by set{Binary,Text}Mode().
 +*/
 +SQLITE_INTERNAL_LINKAGE int fPutsUtf8(const char *z, FILE *pfO);
 +/* Like fPutsUtf8 except stream is always the designated output. */
 +SQLITE_INTERNAL_LINKAGE int oPutsUtf8(const char *z);
 +/* Like fPutsUtf8 except stream is always the designated error. */
 +SQLITE_INTERNAL_LINKAGE int ePutsUtf8(const char *z);
 +
++#if 0
++/*
++** Emit output like fputc(), with appropriate translation(s).
++** This is not strictly needed on fully UTF-8-aware platforms.
++** It exists for sake of orthogonality and output designation.
++**
++** The routine returns an error for non-ASCII character input.
++*/
++SQLITE_INTERNAL_LINKAGE int fPutcUtf8(int ch, FILE *pfO);
++/* Like fPutcUtf8 except stream is always the designated output. */
++SQLITE_INTERNAL_LINKAGE int oPutcUtf8(int ch);
++/* Like fPutcUtf8 except stream is always the designated error. */
++SQLITE_INTERNAL_LINKAGE int ePutcUtf8(int ch);
++#endif
++
 +/*
 +** Collect input like fgets(...) with special provisions for input
 +** from the console on platforms that require same. Defers to the
 +** C library fgets() when input is not from the console. Newline
 +** translation may be done as set by set{Binary,Text}Mode(). As a
 +** convenience, pfIn==NULL is treated as stdin.
 +*/
 +SQLITE_INTERNAL_LINKAGE char* fGetsUtf8(char *cBuf, int ncMax, FILE *pfIn);
 +/* Like fGetsUtf8 except stream is always the designated input. */
 +SQLITE_INTERNAL_LINKAGE char* iGetsUtf8(char *cBuf, int ncMax);
 +
 +/*
 +** Set given stream for binary mode, where newline translation is
 +** not done, or for text mode where, for some platforms, newlines
 +** are translated to the platform's conventional char sequence.
 +** If bFlush true, flush the stream.
 +**
 +** An additional side-effect is that if the stream is one passed
 +** to consoleClassifySetup() as an output, it is flushed first.
 +**
 +** Note that binary/text mode has no effect on console I/O
 +** translation. On all platforms, newline to the console starts
 +** a new line and CR,LF chars from the console become a newline.
 +*/
 +SQLITE_INTERNAL_LINKAGE void setBinaryMode(FILE *, short bFlush);
 +SQLITE_INTERNAL_LINKAGE void setTextMode(FILE *, short bFlush);
 +
 +#if 0 /* For use with line editor. (not yet used) */
 +typedef struct Prompts {
 +  int numPrompts;
 +  const char **azPrompts;
 +} Prompts;
 +#endif
 +
 +/*
 +** Macros for use of a line editor.
 +**
 +** The following macros define operations involving use of a
 +** line-editing library or simple console interaction.
 +** A "T" argument is a text (char *) buffer or filename.
 +** A "N" argument is an integer.
 +**
 +** SHELL_ADD_HISTORY(T) // Record text as line(s) of history.
 +** SHELL_READ_HISTORY(T) // Read history from file named by T.
 +** SHELL_WRITE_HISTORY(T) // Write history to file named by T.
 +** SHELL_STIFLE_HISTORY(N) // Limit history to N entries.
 +**
 +** A console program which does interactive console input is
 +** expected to call:
 +** SHELL_READ_HISTORY(T) before collecting such input;
 +** SHELL_ADD_HISTORY(T) as record-worthy input is taken;
 +** SHELL_STIFLE_HISTORY(N) after console input ceases; then
 +** SHELL_WRITE_HISTORY(T) before the program exits.
 +*/
 +
 +/*
 +** Retrieve a single line of input text from an input stream.
 +**
 +** If pfIn is the input stream passed to consoleClassifySetup(),
 +** and azPrompt is not NULL, then a prompt is issued before the
 +** line is collected, as selected by the isContinuation flag.
 +** Array azPrompt[{0,1}] holds the {main,continuation} prompt.
 +**
 +** If zBufPrior is not NULL then it is a buffer from a prior
 +** call to this routine that can be reused, or will be freed.
 +**
 +** The result is stored in space obtained from malloc() and
 +** must either be freed by the caller or else passed back to
 +** this function as zBufPrior for reuse.
 +**
 +** This function may call upon services of a line-editing
 +** library to interactively collect line edited input.
 +*/
 +#if 0 /* not yet implemented */
 +SQLITE_INTERNAL_LINKAGE char *
 +shellGetLine(FILE *pfIn, char *zBufPrior, int nLen,
 +             short isContinuation, Prompts azPrompt);
 +#endif
 +/*
 +** TBD: Define an interface for application(s) to generate
 +** completion candidates for use by the line-editor.
 +**
 +** This may be premature; the CLI is the only application
 +** that does this. Yet, getting line-editing melded into
 +** console I/O is desirable because a line-editing library
 +** may have to establish console operating mode, possibly
 +** in a way that interferes with the above functionality.
 +*/
diff --cc manifest
index 2068eb4fbc85012b74324455ea0c0dd914e0b91a,a6ae666a58df7f7f7bde8420a93a22bfe23d0765..390b40a3a691ebf9cb52e1b5438979173b8c8905
+++ b/manifest
@@@ -1,5 -1,5 +1,5 @@@
- C Fix\smalf\swith\sredirected\sinput\sdue\sto\sbad\sassumption\sthat\sstdin\sis\sa\sconsole\sin\sthe\sfgets()\sreplacement.
- D 2023-11-11T13:09:09.686
 -C JNI\swrapper1:\swhen\schecking\sfor\san\sout-of-bounds\sstatement\scolumn\sindex,\sperform\sthe\sis-statement-finalized\scheck\sbefore\sthe\srange\scheck\sso\sthat\sthe\sformer\sexception\strumps\sthe\slatter.
 -D 2023-11-11T14:50:01.933
++C Complete\sshell\stransition\sto\susing\s{f,o,e}put{f,z}()\semit\sfunctions.\sThis\sfails\stest\s13.1\sin\sjson501.test,\sbut\sso\sdoes\strunk\sin\sthe\ssame\sway.
++D 2023-11-11T20:46:12.670
  F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
  F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
  F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@@ -50,8 -50,6 +50,8 @@@ F ext/README.md fd5f78013b0a2bc6f0067af
  F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
  F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
  F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
- F ext/consio/console_io.c c1e16d6c41a04952784abc4b055c5739c1ee3163aa475859725b66d1ccc656bd x
- F ext/consio/console_io.h c64d51d9f4e387679027d3b0977893390652f40c2e50a3c797506a9abb4856dc
++F ext/consio/console_io.c 0b07826bc3cceb10b12f5a3701fc1540154916a845de003d87c447c8a68c5ba7 x
++F ext/consio/console_io.h ec611fe8f08645d69cb18d46ab2a09c4653f2fc13ecb04c18e6012d8ea89c463
  F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
  F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
  F ext/expert/expert1.test 0dd5cb096d66bed593e33053a3b364f6ef52ed72064bf5cf298364636dbf3cd6
@@@ -727,7 -725,7 +727,7 @@@ F src/random.c 606b00941a1d7dd09c381d32
  F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916
  F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
  F src/select.c 503331aca8785254a7bf3d74ab338a99118fa297e1184a4dde33b3cdf7a9d341
- F src/shell.c.in 2bbff1e18baafccf312c622ce966792f6a70ec77b642d92b0c0df4885df76722
 -F src/shell.c.in 297625a1ba6ea1c08bc2ea1b838b646cad309b62bf08df0e379355629404f140
++F src/shell.c.in 1d689534130f9c242564b820726e4af37a8e1a347025355eb5a7e67a3c1a5306
  F src/sqlite.h.in 4f841d3d117b830ee5ee45e8d89ceff1195f3ebb72d041ace8d116ba4c103b35
  F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
  F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
@@@ -2141,8 -2139,8 +2141,8 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9
  F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
  F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
  F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P 14762a004cdf37d1e12f26aadff8ed3824893278f22ff141de86dd44d9b250f3
- R 5b544ddbaeeb17ecd11dc0a538d27e36
 -P a6ab88e9a67f23ab7885402776282b94033cb48dbe34d4d18356e4dc22aae7cd
 -R 78a63cfa87011ebb24c6cac260db14c9
 -U stephan
 -Z ad92dad6ace48bd20f7cf67cbd6f4f40
++P 79d1f2c1019964dd154fbdd3f349822cb946a2600883994523ed145047f0a9ea 0832f9a8e9f574b157c791c5cddc73aff7b2ff403509f5d78f310494d4a7f93d
++R fd4407aafdd7492d23f3b236cddd5186
 +U larrybr
- Z d3728cfdee8358558d79b5ead14c0ffb
++Z cce7495ad383169e7382f36018db3c19
  # Remove this line to create a well-formed Fossil manifest.
diff --cc manifest.uuid
index f798d85bff267279fb65f7ee254a64bc31ae0dd3,4865106033244019578183bf2f4b9a9c8a99e2e5..5509cbc9909a8aa48d20b6594f1176a8033d26eb
@@@ -1,1 -1,1 +1,1 @@@
- 79d1f2c1019964dd154fbdd3f349822cb946a2600883994523ed145047f0a9ea
 -0832f9a8e9f574b157c791c5cddc73aff7b2ff403509f5d78f310494d4a7f93d
++923c6b8b3a508c715b816c6bcd2ae9ac519bc37a62afc4ef813085c00f1e7cb6
diff --cc src/shell.c.in
index b3b97e1ceca4fd1d97b794aa25969d05d4ec2bb1,0e0dbd36c76feeabb3e66d3879fb1f81de55b99d..e9c226ac77fd02792af9bcfd0a7ce011716582e4
@@@ -237,11 -237,28 +237,40 @@@ extern char *sqlite3_win32_unicode_to_u
  extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
  #endif
  
 -/* On Windows, we normally run with output mode of TEXT so that \n characters
 -** are automatically translated into \r\n.  However, this behavior needs
 -** to be disabled in some cases (ex: when generating CSV output and when
 -** rendering quoted strings that contain \n characters).  The following
 -** routines take care of that.
 -*/
 -#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
 -static void setBinaryMode(FILE *file, int isOutput){
 -  if( isOutput ) fflush(file);
 -  _setmode(_fileno(file), _O_BINARY);
 -}
 -static void setTextMode(FILE *file, int isOutput){
 -  if( isOutput ) fflush(file);
 -  _setmode(_fileno(file), _O_TEXT);
 -}
 -#else
 -# define setBinaryMode(X,Y)
 -# define setTextMode(X,Y)
 -#endif
 +#define SQLITE_INTERNAL_LINKAGE static
 +
 +INCLUDE ../ext/consio/console_io.h
 +INCLUDE ../ext/consio/console_io.c
 +
++/* From here onward, fgets() is redirected to the console_io library. */
++#define fgets(b,n,f) fGetsUtf8(b,n,f)
++/*
++ * Define macros for emitting output text in various ways:
++ *  sputz(s, z)      => emit 0-terminated string z to given stream s
++ *  sputf(s, f, ...) => emit varargs per format f to given stream s
++ *  oputz(z)         => emit 0-terminated string z to default stream
++ *  oputf(f, ...)    => emit varargs per format f to default stream
++ *  eputz(z)         => emit 0-terminated string z to error stream
++ *  eputf(f, ...)    => emit varargs per format f to error stream
++ *  sputc(s, c)  => emit single ASCII character to given stream s
++ *  oputc(c)     => emit single ASCII character to default stream
++ *  eputc(c)     => emit single ASCII character to error stream
++ *
++ * Note that the default stream is whatever has been last set via:
++ *   setOutputStream(FILE *pf)
++ * This is normally the stream that CLI normal output goes to.
++ * For the stand-alone CLI, it is stdout with no .output redirect.
++ */
++#define sputz(s,z) fPutsUtf8(z,s)
++#define sputf fPrintfUtf8
++#define oputz(z) oPutsUtf8(z)
++#define oputf oPrintfUtf8
++#define eputz(z) ePutsUtf8(z)
++#define eputf ePrintfUtf8
++#define sputc(f,c) fPutcUtf8(c,f)
++#define oputc(c) oPutcUtf8(c)
++#define eputc(c) ePutcUtf8(c)
  /* True if the timer is enabled */
  static int enableTimer = 0;
  
@@@ -314,10 -331,10 +343,10 @@@ static void endTimer(void)
      sqlite3_int64 iEnd = timeOfDay();
      struct rusage sEnd;
      getrusage(RUSAGE_SELF, &sEnd);
--    printf("Run Time: real %.3f user %f sys %f\n",
--       (iEnd - iBegin)*0.001,
--       timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
--       timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
++    oputf("Run Time: real %.3f user %f sys %f\n",
++          (iEnd - iBegin)*0.001,
++          timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
++          timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
    }
  }
  
@@@ -393,10 -410,10 +422,10 @@@ static void endTimer(void)
      FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
      sqlite3_int64 ftWallEnd = timeOfDay();
      getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
--    printf("Run Time: real %.3f user %f sys %f\n",
--       (ftWallEnd - ftWallBegin)*0.001,
--       timeDiff(&ftUserBegin, &ftUserEnd),
--       timeDiff(&ftKernelBegin, &ftKernelEnd));
++    oputf("Run Time: real %.3f user %f sys %f\n",
++          (ftWallEnd - ftWallBegin)*0.001,
++          timeDiff(&ftUserBegin, &ftUserEnd),
++          timeDiff(&ftKernelBegin, &ftKernelEnd));
    }
  }
  
@@@ -565,37 -600,243 +594,9 @@@ static char *dynamicContinuePrompt(void
  }
  #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */
  
- /* From here onward, fgets() is redirected to the console_io library. */
- #define fgets(b,n,f) fGetsUtf8(b,n,f)
- /* Also, (varargs) utf8_printf(f,z,...),printf(z,...) so redirected. */
- #define utf8_printf fPrintfUtf8
- #define printf oPrintfUtf8
- /* And, utf8_print(f,z) is redirected to fputsUtf8(z,f) in the library. */
- #define utf8_print(f,z) fPutsUtf8(z,f)
 -#if SHELL_WIN_UTF8_OPT
 -/* Following struct is used for UTF-8 console I/O. */
 -static struct ConsoleState {
 -  int stdinEof;      /* EOF has been seen on console input */
 -  int infsMode;      /* Input file stream mode upon shell start */
 -  UINT inCodePage;   /* Input code page upon shell start */
 -  UINT outCodePage;  /* Output code page upon shell start */
 -  HANDLE hConsole;   /* Console input or output handle */
 -  DWORD consoleMode; /* Console mode upon shell start */
 -} conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };
 -
 -#ifndef _O_U16TEXT /* For build environments lacking this constant: */
 -# define _O_U16TEXT 0x20000
 -#endif
 -
--/*
-  * Define macros for writing output text in various ways:
-  *  sputz(s, z)      => emit 0-terminated string z to given stream s
-  *  sputf(s, f, ...) => emit varargs per format f to given stream s
-  *  oputz(z)         => emit 0-terminated string z to default stream
-  *  oputf(f, ...)    => emit varargs per format f to default stream
-  *  eputz(z)         => emit 0-terminated string z to error stream
-  *  eputf(f, ...)    => emit varargs per format f to error stream
-  *
-  * Note that the default stream is whatever has been last set via:
-  *   setDefaultOutputStream(FILE *pf)
-  * This is normally the stream that CLI normal output goes to.
-  * For the stand-alone CLI, it is stdout with no .output redirect.
-  */
- #define sputz(s,z) fPutsUtf8(z,s)
- #define sputf fPrintfUtf8
- #define oputz(z) oPutsUtf8(z)
- #define oputf oPrintfUtf8
- #define eputz(z) ePutsUtf8(z)
- #define eputf ePrintfUtf8
 -** If given stream number is a console, return 1 and get some attributes,
 -** else return 0 and set the output attributes to invalid values.
 -*/
 -static short console_attrs(unsigned stnum, HANDLE *pH, DWORD *pConsMode){
 -  static int stid[3] = { STD_INPUT_HANDLE,STD_OUTPUT_HANDLE,STD_ERROR_HANDLE };
 -  HANDLE h;
 -  *pH = INVALID_HANDLE_VALUE;
 -  *pConsMode = 0;
 -  if( stnum > 2 ) return 0;
 -  h = GetStdHandle(stid[stnum]);
 -  if( h!=*pH && GetFileType(h)==FILE_TYPE_CHAR && GetConsoleMode(h,pConsMode) ){
 -    *pH = h;
 -    return 1;
 -  }
 -  return 0;
 -}
 -
 -/*
 -** Perform a runtime test of Windows console to determine if it can
 -** do char-stream I/O correctly when the code page is set to CP_UTF8.
 -** Returns are: 1 => yes it can, 0 => no it cannot
 -**
 -** The console's output code page is momentarily set, then restored.
 -** So this should only be run when the process is given use of the
 -** console for either input or output.
 -*/
 -static short ConsoleDoesUTF8(void){
 -  UINT ocp = GetConsoleOutputCP();
 -  const char TrialUtf8[] = { '\xC8', '\xAB' }; /* "È«" or 2 MBCS characters */
 -  WCHAR aReadBack[1] = { 0 }; /* Read back as 0x022B when decoded as UTF-8. */
 -  CONSOLE_SCREEN_BUFFER_INFO csbInfo = {0};
 -  /* Create an inactive screen buffer with which to do the experiment. */
 -  HANDLE hCSB = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE, 0, 0,
 -                                          CONSOLE_TEXTMODE_BUFFER, NULL);
 -  if( hCSB!=INVALID_HANDLE_VALUE ){
 -    COORD cpos = {0,0};
 -    DWORD rbc;
 -    SetConsoleCursorPosition(hCSB, cpos);
 -    SetConsoleOutputCP(CP_UTF8);
 -    /* Write 2 chars which are a single character in UTF-8 but more in MBCS. */
 -    WriteConsoleA(hCSB, TrialUtf8, sizeof(TrialUtf8), NULL, NULL);
 -    ReadConsoleOutputCharacterW(hCSB, &aReadBack[0], 1, cpos, &rbc);
 -    GetConsoleScreenBufferInfo(hCSB, &csbInfo);
 -    SetConsoleOutputCP(ocp);
 -    CloseHandle(hCSB);
 -  }
 -  /* Return 1 if cursor advanced by 1 position, else 0. */
 -  return (short)(csbInfo.dwCursorPosition.X == 1 && aReadBack[0] == 0x022B);
 -}
 -
 -static short in_console = 0;
 -static short out_console = 0;
 -
 -/*
 -** Determine whether either normal I/O stream is the console,
 -** and whether it can do UTF-8 translation, setting globals
 -** in_console, out_console and mbcs_opted accordingly.
 -*/
 -static void probe_console(void){
 -  HANDLE h;
 -  DWORD cMode;
 -  in_console = console_attrs(0, &h, &cMode);
 -  out_console = console_attrs(1, &h, &cMode);
 -  if( in_console || out_console ) mbcs_opted = !ConsoleDoesUTF8();
 -}
 -
 -/*
 -** If console is used for normal I/O, absent a --no-utf8 option,
 -** prepare console for UTF-8 input (from either typing or suitable
 -** paste operations) and/or for UTF-8 output rendering.
 -**
 -** The console state upon entry is preserved, in conState, so that
 -** console_restore() can later restore the same console state.
 -**
 -** The globals console_utf8_in and console_utf8_out are set, for
 -** later use in selecting UTF-8 or MBCS console I/O translations.
 -** This routine depends upon globals set by probe_console().
 -*/
 -static void console_prepare_utf8(void){
 -  struct ConsoleState csWork = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };
 -
 -  console_utf8_in = console_utf8_out = 0;
 -  if( (!in_console && !out_console) || mbcs_opted ) return;
 -  console_attrs((in_console)? 0 : 1, &conState.hConsole, &conState.consoleMode);
 -  conState.inCodePage = GetConsoleCP();
 -  conState.outCodePage = GetConsoleOutputCP();
 -  if( in_console ){
 -    SetConsoleCP(CP_UTF8);
 -    SetConsoleMode(conState.hConsole, conState.consoleMode
 -                   | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
 -    conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT);
 -    console_utf8_in = 1;
 -  }
 -  if( out_console ){
 -    SetConsoleOutputCP(CP_UTF8);
 -    console_utf8_out = 1;
 -  }
 -}
 -
 -/*
 -** Undo the effects of console_prepare_utf8(), if any.
 -*/
 -static void SQLITE_CDECL console_restore(void){
 -  if( (console_utf8_in||console_utf8_out)
 -      && conState.hConsole!=INVALID_HANDLE_VALUE ){
 -    if( console_utf8_in ){
 -      SetConsoleCP(conState.inCodePage);
 -      _setmode(_fileno(stdin), conState.infsMode);
 -    }
 -    if( console_utf8_out ) SetConsoleOutputCP(conState.outCodePage);
 -    SetConsoleMode(conState.hConsole, conState.consoleMode);
 -    /* Avoid multiple calls. */
 -    conState.hConsole = INVALID_HANDLE_VALUE;
 -    conState.consoleMode = 0;
 -    console_utf8_in = 0;
 -    console_utf8_out = 0;
 -  }
 -}
 -
 -/*
 -** Collect input like fgets(...) with special provisions for input
 -** from the Windows console to get around its strange coding issues.
 -** Defers to plain fgets() when input is not interactive or when the
 -** UTF-8 input is unavailable or opted out.
 -*/
 -static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
 -  if( fin==0 ) fin = stdin;
 -  if( fin==stdin && stdin_is_interactive && console_utf8_in ){
 -# define SQLITE_IALIM 150
 -    wchar_t wbuf[SQLITE_IALIM];
 -    int lend = 0;
 -    int noc = 0;
 -    if( ncmax==0 || conState.stdinEof ) return 0;
 -    buf[0] = 0;
 -    while( noc<ncmax-7-1 && !lend ){
 -      /* There is room for at least 2 more characters and a 0-terminator. */
 -      int na = (ncmax > SQLITE_IALIM*4+1 + noc)
 -        ? SQLITE_IALIM : (ncmax-1 - noc)/4;
 -# undef SQLITE_IALIM
 -      DWORD nbr = 0;
 -      BOOL bRC = ReadConsoleW(conState.hConsole, wbuf, na, &nbr, 0);
 -      if( !bRC || (noc==0 && nbr==0) ) return 0;
 -      if( nbr > 0 ){
 -        int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
 -                                      wbuf,nbr,0,0,0,0);
 -        if( nmb !=0 && noc+nmb <= ncmax ){
 -          int iseg = noc;
 -          nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
 -                                    wbuf,nbr,buf+noc,nmb,0,0);
 -          noc += nmb;
 -          /* Fixup line-ends as coded by Windows for CR (or "Enter".)*/
 -          if( noc > 0 ){
 -            if( buf[noc-1]=='\n' ){
 -              lend = 1;
 -              if( noc > 1 && buf[noc-2]=='\r' ){
 -                buf[noc-2] = '\n';
 -                --noc;
 -              }
 -            }
 -          }
 -          /* Check for ^Z (anywhere in line) too. */
 -          while( iseg < noc ){
 -            if( buf[iseg]==0x1a ){
 -              conState.stdinEof = 1;
 -              noc = iseg; /* Chop ^Z and anything following. */
 -              break;
 -            }
 -            ++iseg;
 -          }
 -        }else break; /* Drop apparent garbage in. (Could assert.) */
 -      }else break;
 -    }
 -    /* If got nothing, (after ^Z chop), must be at end-of-file. */
 -    if( noc == 0 ) return 0;
 -    buf[noc] = 0;
 -    return buf;
 -  }else{
 -    return fgets(buf, ncmax, fin);
 -  }
 -}
 -
 -# define fgets(b,n,f) utf8_fgets(b,n,f)
 -#endif /* SHELL_WIN_UTF8_OPT */
 -
 -/*
 -** Render output like fprintf().  Except, if the output is going to the
 -** console and if this is running on a Windows machine, and if UTF-8
 -** output unavailable (or available but opted out), translate the
 -** output from UTF-8 into MBCS for output through 8-bit stdout stream.
 -** (Without -no-utf8, no translation is needed and must not be done.)
 -*/
 -#if defined(_WIN32) || defined(WIN32)
 -void utf8_printf(FILE *out, const char *zFormat, ...){
 -  va_list ap;
 -  va_start(ap, zFormat);
 -  if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8_out ){
 -    char *z1 = sqlite3_vmprintf(zFormat, ap);
 -    char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
 -    sqlite3_free(z1);
 -    fputs(z2, out);
 -    sqlite3_free(z2);
 -  }else{
 -    vfprintf(out, zFormat, ap);
 -  }
 -  va_end(ap);
 -}
 -#elif !defined(utf8_printf)
 -# define utf8_printf fprintf
 -#endif
 -
 -/*
 -** Render output like fprintf().  This should not be used on anything that
 -** includes string formatting (e.g. "%s").
 -*/
 -#if !defined(raw_printf)
 -# define raw_printf fprintf
 -#endif
--
  /* Indicate out-of-memory and exit. */
  static void shell_out_of_memory(void){
-   utf8_print(stderr,"Error: out of memory\n");
 -  raw_printf(stderr,"Error: out of memory\n");
++  eputz("Error: out of memory\n");
    exit(1);
  }
  
@@@ -627,7 -868,7 +628,7 @@@ static void SQLITE_CDECL iotracePrintf(
    va_start(ap, zFormat);
    z = sqlite3_vmprintf(zFormat, ap);
    va_end(ap);
--  utf8_printf(iotrace, "%s", z);
++  sputf(iotrace, "%s", z);
    sqlite3_free(z);
  }
  #endif
@@@ -653,11 -894,11 +654,11 @@@ static void utf8_width_print(FILE *pOut
      }
    }
    if( n>=aw ){
--    utf8_printf(pOut, "%.*s", i, zUtf);
++    sputf(pOut, "%.*s", i, zUtf);
    }else if( w<0 ){
--    utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
++    sputf(pOut, "%*s%s", aw-n, "", zUtf);
    }else{
--    utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
++    sputf(pOut, "%s%*s", zUtf, aw-n, "");
    }
  }
  
@@@ -806,7 -1064,7 +807,7 @@@ static char *one_input_line(FILE *in, c
    }else{
      zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
  #if SHELL_USE_LOCAL_GETLINE
--    printf("%s", zPrompt);
++    sputz(stdout, zPrompt);
      fflush(stdout);
      do{
        zResult = local_getline(zPrior, stdin);
@@@ -1467,7 -1729,7 +1468,7 @@@ static const char *modeDescr[] = 
  static void shellLog(void *pArg, int iErrCode, const char *zMsg){
    ShellState *p = (ShellState*)pArg;
    if( p->pLog==0 ) return;
--  utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
++  sputf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
    fflush(p->pLog);
  }
  
@@@ -1484,7 -1746,7 +1485,7 @@@ static void shellPutsFunc
  ){
    ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
    (void)nVal;
--  utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
++  sputf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
    sqlite3_result_value(pCtx, apVal[0]);
  }
  
@@@ -1503,8 -1765,8 +1504,7 @@@ static void failIfSafeMode
      va_start(ap, zErrMsg);
      zMsg = sqlite3_vmprintf(zErrMsg, ap);
      va_end(ap);
-     utf8_printf(stderr, "line %d: ", p->lineno);
 -    raw_printf(stderr, "line %d: ", p->lineno);
--    utf8_printf(stderr, "%s\n", zMsg);
++    eputf("line %d: %s\n", p->lineno, zMsg);
      exit(1);
    }
  }
@@@ -1689,7 -1951,7 +1689,7 @@@ static void output_hex_blob(FILE *out, 
    }
    zStr[i*2] = '\0';
  
-   utf8_printf(out,"X'%s'", zStr);
 -  raw_printf(out,"X'%s'", zStr);
++  sputf(out,"X'%s'", zStr);
    sqlite3_free(zStr);
  }
  
@@@ -1726,18 -1988,18 +1726,18 @@@ static void output_quoted_string(FILE *
    if( z==0 ) return;
    for(i=0; (c = z[i])!=0 && c!='\''; i++){}
    if( c==0 ){
--    utf8_printf(out,"'%s'",z);
++    sputf(out,"'%s'",z);
    }else{
-     utf8_print(out, "'");
 -    raw_printf(out, "'");
++    sputz(out, "'");
      while( *z ){
        for(i=0; (c = z[i])!=0 && c!='\''; i++){}
        if( c=='\'' ) i++;
        if( i ){
--        utf8_printf(out, "%.*s", i, z);
++        sputf(out, "%.*s", i, z);
          z += i;
        }
        if( c=='\'' ){
-         utf8_print(out, "'");
 -        raw_printf(out, "'");
++        sputz(out, "'");
          continue;
        }
        if( c==0 ){
        }
        z++;
      }
-     utf8_print(out, "'");
 -    raw_printf(out, "'");
++    sputz(out, "'");
    }
    setTextMode(out, 1);
  }
@@@ -1765,7 -2027,7 +1765,7 @@@ static void output_quoted_escaped_strin
    setBinaryMode(out, 1);
    for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
    if( c==0 ){
--    utf8_printf(out,"'%s'",z);
++    sputf(out,"'%s'",z);
    }else{
      const char *zNL = 0;
      const char *zCR = 0;
        if( z[i]=='\r' ) nCR++;
      }
      if( nNL ){
-       utf8_print(out, "replace(");
 -      raw_printf(out, "replace(");
++      sputz(out, "replace(");
        zNL = unused_string(z, "\\n", "\\012", zBuf1);
      }
      if( nCR ){
-       utf8_print(out, "replace(");
 -      raw_printf(out, "replace(");
++      sputz(out, "replace(");
        zCR = unused_string(z, "\\r", "\\015", zBuf2);
      }
-     utf8_print(out, "'");
 -    raw_printf(out, "'");
++    sputz(out, "'");
      while( *z ){
        for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
        if( c=='\'' ) i++;
        if( i ){
--        utf8_printf(out, "%.*s", i, z);
++        sputf(out, "%.*s", i, z);
          z += i;
        }
        if( c=='\'' ){
-         utf8_print(out, "'");
 -        raw_printf(out, "'");
++        sputz(out, "'");
          continue;
        }
        if( c==0 ){
        }
        z++;
        if( c=='\n' ){
-         utf8_print(out, zNL);
 -        raw_printf(out, "%s", zNL);
++        sputz(out, zNL);
          continue;
        }
-       utf8_print(out, zCR);
 -      raw_printf(out, "%s", zCR);
++      sputz(out, zCR);
      }
-     utf8_print(out, "'");
 -    raw_printf(out, "'");
++    sputz(out, "'");
      if( nCR ){
-       utf8_printf(out, ",'%s',char(13))", zCR);
 -      raw_printf(out, ",'%s',char(13))", zCR);
++      sputf(out, ",'%s',char(13))", zCR);
      }
      if( nNL ){
-       utf8_printf(out, ",'%s',char(10))", zNL);
 -      raw_printf(out, ",'%s',char(10))", zNL);
++      sputf(out, ",'%s',char(10))", zNL);
      }
    }
    setTextMode(out, 1);
  */
  static void output_c_string(FILE *out, const char *z){
    unsigned int c;
--  fputc('"', out);
--  while( (c = *(z++))!=0 ){
--    if( c=='\\' ){
--      fputc(c, out);
--      fputc(c, out);
--    }else if( c=='"' ){
--      fputc('\\', out);
--      fputc('"', out);
--    }else if( c=='\t' ){
--      fputc('\\', out);
--      fputc('t', out);
--    }else if( c=='\n' ){
--      fputc('\\', out);
--      fputc('n', out);
--    }else if( c=='\r' ){
--      fputc('\\', out);
--      fputc('r', out);
++  static const char *zq = "\"";
++  char ace[3] = "\\?";
++  char cbsSay;
++  sputz(out, zq);
++  while( (c = *(z++))!= 0 ){
++    switch( c ){
++    case '\\': case '"':
++      cbsSay = (char)c;
++      break;
++    case '\t': cbsSay = 't'; break;
++    case '\n': cbsSay = 'n'; break;
++    case '\r': cbsSay = 'r'; break;
++    case '\f': cbsSay = 'f'; break;
++    default: cbsSay = 0; break;
++    }
++    if( cbsSay ){
++      ace[1] = cbsSay;
++      sputz(out, ace);
      }else if( !isprint(c&0xff) ){
-       utf8_printf(out, "\\%03o", c&0xff);
 -      raw_printf(out, "\\%03o", c&0xff);
++      sputf(out, "\\%03o", c&0xff);
      }else{
--      fputc(c, out);
++      ace[1] = (char)c;
++      sputz(out, ace+1);
      }
    }
--  fputc('"', out);
++  sputz(out, zq);
  }
  
  /*
  */
  static void output_json_string(FILE *out, const char *z, i64 n){
    unsigned int c;
++  static const char *zq = "\"";
++  char ace[3] = "\\?";
++  char cbsSay;
    if( z==0 ) z = "";
    if( n<0 ) n = strlen(z);
--  fputc('"', out);
++  sputz(out, zq);
    while( n-- ){
      c = *(z++);
--    if( c=='\\' || c=='"' ){
--      fputc('\\', out);
--      fputc(c, out);
++    switch( c ){
++    case '"': case '\\':
++      cbsSay = (char)c;
++      break;
++    case '\b': cbsSay = 'b'; break;
++    case '\f': cbsSay = 'f'; break;
++    case '\n': cbsSay = 'n'; break;
++    case '\r': cbsSay = 'r'; break;
++    case '\t': cbsSay = 't'; break;
++    default: cbsSay = 0; break;
++    }
++    if( cbsSay ){
++      ace[1] = cbsSay;
++      sputz(out, ace);
      }else if( c<=0x1f ){
--      fputc('\\', out);
--      if( c=='\b' ){
--        fputc('b', out);
--      }else if( c=='\f' ){
--        fputc('f', out);
--      }else if( c=='\n' ){
--        fputc('n', out);
--      }else if( c=='\r' ){
--        fputc('r', out);
--      }else if( c=='\t' ){
--        fputc('t', out);
--      }else{
-          utf8_printf(out, "u%04x",c);
 -         raw_printf(out, "u%04x",c);
--      }
++      sputf(out, "u%04x", c);
      }else{
--      fputc(c, out);
++      ace[1] = (char)c;
++      sputz(out, ace+1);
      }
    }
--  fputc('"', out);
++  sputz(out, zq);
  }
  
  /*
@@@ -1899,18 -2161,18 +1903,18 @@@ static void output_html_string(FILE *ou
              && z[i]!='\'';
          i++){}
      if( i>0 ){
--      utf8_printf(out,"%.*s",i,z);
++      sputf(out,"%.*s",i,z);
      }
      if( z[i]=='<' ){
-       utf8_print(out,"&lt;");
 -      raw_printf(out,"&lt;");
++      sputz(out,"&lt;");
      }else if( z[i]=='&' ){
-       utf8_print(out,"&amp;");
 -      raw_printf(out,"&amp;");
++      sputz(out,"&amp;");
      }else if( z[i]=='>' ){
-       utf8_print(out,"&gt;");
 -      raw_printf(out,"&gt;");
++      sputz(out,"&gt;");
      }else if( z[i]=='\"' ){
-       utf8_print(out,"&quot;");
 -      raw_printf(out,"&quot;");
++      sputz(out,"&quot;");
      }else if( z[i]=='\'' ){
-       utf8_print(out,"&#39;");
 -      raw_printf(out,"&#39;");
++      sputz(out,"&#39;");
      }else{
        break;
      }
@@@ -1950,7 -2212,7 +1954,7 @@@ static const char needCsvQuote[] = 
  static void output_csv(ShellState *p, const char *z, int bSep){
    FILE *out = p->out;
    if( z==0 ){
--    utf8_printf(out,"%s",p->nullValue);
++    sputf(out,"%s",p->nullValue);
    }else{
      unsigned i;
      for(i=0; z[i]; i++){
      if( i==0 || strstr(z, p->colSeparator)!=0 ){
        char *zQuoted = sqlite3_mprintf("\"%w\"", z);
        shell_check_oom(zQuoted);
-       utf8_print(out, zQuoted);
 -      utf8_printf(out, "%s", zQuoted);
++      sputz(out, zQuoted);
        sqlite3_free(zQuoted);
      }else{
-       utf8_print(out, z);
 -      utf8_printf(out, "%s", z);
++      sputz(out, z);
      }
    }
    if( bSep ){
-     utf8_print(p->out, p->colSeparator);
 -    utf8_printf(p->out, "%s", p->colSeparator);
++    sputz(p->out, p->colSeparator);
    }
  }
  
@@@ -2077,16 -2339,16 +2081,16 @@@ static int shellAuth
    az[1] = zA2;
    az[2] = zA3;
    az[3] = zA4;
--  utf8_printf(p->out, "authorizer: %s", azAction[op]);
++  sputf(p->out, "authorizer: %s", azAction[op]);
    for(i=0; i<4; i++){
-     utf8_print(p->out, " ");
 -    raw_printf(p->out, " ");
++    sputz(p->out, " ");
      if( az[i] ){
        output_c_string(p->out, az[i]);
      }else{
-       utf8_print(p->out, "NULL");
 -      raw_printf(p->out, "NULL");
++      sputz(p->out, "NULL");
      }
    }
-   utf8_print(p->out, "\n");
 -  raw_printf(p->out, "\n");
++  sputz(p->out, "\n");
    if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
    return SQLITE_OK;
  }
@@@ -2124,9 -2386,9 +2128,9 @@@ static void printSchemaLine(FILE *out, 
      }
    }
    if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
--    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
++    sputf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
    }else{
--    utf8_printf(out, "%s%s", z, zTail);
++    sputf(out, "%s%s", z, zTail);
    }
    sqlite3_free(zToFree);
  }
@@@ -2161,7 -2423,7 +2165,7 @@@ static void eqp_append(ShellState *p, i
    if( zText==0 ) return;
    nText = strlen(zText);
    if( p->autoEQPtest ){
--    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
++    sputf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
    }
    pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
    shell_check_oom(pNew);
@@@ -2209,8 -2471,8 +2213,7 @@@ static void eqp_render_level(ShellStat
    for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
      pNext = eqp_next_row(p, iEqpId, pRow);
      z = pRow->zText;
--    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
--                pNext ? "|--" : "`--", z);
++    sputf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
      if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
        memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
        eqp_render_level(p, pRow->iEqpId);
@@@ -2230,13 -2492,13 +2233,13 @@@ static void eqp_render(ShellState *p, i
          eqp_reset(p);
          return;
        }
--      utf8_printf(p->out, "%s\n", pRow->zText+3);
++      sputf(p->out, "%s\n", pRow->zText+3);
        p->sGraph.pRow = pRow->pNext;
        sqlite3_free(pRow);
      }else if( nCycle>0 ){
--      utf8_printf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
++      sputf(p->out, "QUERY PLAN (cycles=%lld [100%%])\n", nCycle);
      }else{
-       utf8_print(p->out, "QUERY PLAN\n");
 -      utf8_printf(p->out, "QUERY PLAN\n");
++      sputz(p->out, "QUERY PLAN\n");
      }
      p->sGraph.zPrefix[0] = 0;
      eqp_render_level(p, 0);
@@@ -2252,13 -2514,13 +2255,13 @@@ static int progress_handler(void *pClie
    ShellState *p = (ShellState*)pClientData;
    p->nProgress++;
    if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
-     utf8_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
 -    raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
++    sputf(p->out, "Progress limit reached (%u)\n", p->nProgress);
      if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
      if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
      return 1;
    }
    if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
-     utf8_printf(p->out, "Progress %u\n", p->nProgress);
 -    raw_printf(p->out, "Progress %u\n", p->nProgress);
++    sputf(p->out, "Progress %u\n", p->nProgress);
    }
    return 0;
  }
@@@ -2271,10 -2533,10 +2274,10 @@@ static void print_dashes(FILE *out, in
    const char zDash[] = "--------------------------------------------------";
    const int nDash = sizeof(zDash) - 1;
    while( N>nDash ){
--    fputs(zDash, out);
++    sputz(out, zDash);
      N -= nDash;
    }
-   utf8_printf(out, "%.*s", N, zDash);
 -  raw_printf(out, "%.*s", N, zDash);
++  sputf(out, "%.*s", N, zDash);
  }
  
  /*
@@@ -2287,15 -2549,15 +2290,15 @@@ static void print_row_separator
  ){
    int i;
    if( nArg>0 ){
--    fputs(zSep, p->out);
++    sputz(p->out, zSep);
      print_dashes(p->out, p->actualWidth[0]+2);
      for(i=1; i<nArg; i++){
--      fputs(zSep, p->out);
++      sputz(p->out, zSep);
        print_dashes(p->out, p->actualWidth[i]+2);
      }
--    fputs(zSep, p->out);
++    sputz(p->out, zSep);
    }
--  fputs("\n", p->out);
++  sputz(p->out, "\n");
  }
  
  /*
@@@ -2325,9 -2587,9 +2328,9 @@@ static int shell_callback
          int len = strlen30(azCol[i] ? azCol[i] : "");
          if( len>w ) w = len;
        }
-       if( p->cnt++>0 ) utf8_print(p->out, p->rowSeparator);
 -      if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
++      if( p->cnt++>0 ) sputz(p->out, p->rowSeparator);
        for(i=0; i<nArg; i++){
--        utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
++        sputf(p->out,"%*s = %s%s", w, azCol[i],
                  azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
        }
        break;
          }
          if( i==iIndent && p->aiIndent && p->pStmt ){
            if( p->iIndent<p->nIndent ){
--            utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
++            sputf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
            }
            p->iIndent++;
          }
        if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
         || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
        ){
--        utf8_printf(p->out, "%s;\n", azArg[0]);
++        sputf(p->out, "%s;\n", azArg[0]);
          break;
        }
        z = sqlite3_mprintf("%s", azArg[0]);
      case MODE_List: {
        if( p->cnt++==0 && p->showHeader ){
          for(i=0; i<nArg; i++){
--          utf8_printf(p->out,"%s%s",azCol[i],
++          sputf(p->out,"%s%s",azCol[i],
                    i==nArg-1 ? p->rowSeparator : p->colSeparator);
          }
        }
        for(i=0; i<nArg; i++){
          char *z = azArg[i];
          if( z==0 ) z = p->nullValue;
-         utf8_print(p->out, z);
 -        utf8_printf(p->out, "%s", z);
++        sputz(p->out, z);
          if( i<nArg-1 ){
-           utf8_print(p->out, p->colSeparator);
 -          utf8_printf(p->out, "%s", p->colSeparator);
++          sputz(p->out, p->colSeparator);
          }else{
-           utf8_print(p->out, p->rowSeparator);
 -          utf8_printf(p->out, "%s", p->rowSeparator);
++          sputz(p->out, p->rowSeparator);
          }
        }
        break;
      }
      case MODE_Html: {
        if( p->cnt++==0 && p->showHeader ){
-         utf8_print(p->out,"<TR>");
 -        raw_printf(p->out,"<TR>");
++        sputz(p->out,"<TR>");
          for(i=0; i<nArg; i++){
-           utf8_print(p->out,"<TH>");
 -          raw_printf(p->out,"<TH>");
++          sputz(p->out,"<TH>");
            output_html_string(p->out, azCol[i]);
-           utf8_print(p->out,"</TH>\n");
 -          raw_printf(p->out,"</TH>\n");
++          sputz(p->out,"</TH>\n");
          }
-         utf8_print(p->out,"</TR>\n");
 -        raw_printf(p->out,"</TR>\n");
++        sputz(p->out,"</TR>\n");
        }
        if( azArg==0 ) break;
-       utf8_print(p->out,"<TR>");
 -      raw_printf(p->out,"<TR>");
++      sputz(p->out,"<TR>");
        for(i=0; i<nArg; i++){
-         utf8_print(p->out,"<TD>");
 -        raw_printf(p->out,"<TD>");
++        sputz(p->out,"<TD>");
          output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
-         utf8_print(p->out,"</TD>\n");
 -        raw_printf(p->out,"</TD>\n");
++        sputz(p->out,"</TD>\n");
        }
-       utf8_print(p->out,"</TR>\n");
 -      raw_printf(p->out,"</TR>\n");
++      sputz(p->out,"</TR>\n");
        break;
      }
      case MODE_Tcl: {
        if( p->cnt++==0 && p->showHeader ){
          for(i=0; i<nArg; i++){
            output_c_string(p->out,azCol[i] ? azCol[i] : "");
-           if(i<nArg-1) utf8_print(p->out, p->colSeparator);
 -          if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
++          if(i<nArg-1) sputz(p->out, p->colSeparator);
          }
-         utf8_print(p->out, p->rowSeparator);
 -        utf8_printf(p->out, "%s", p->rowSeparator);
++        sputz(p->out, p->rowSeparator);
        }
        if( azArg==0 ) break;
        for(i=0; i<nArg; i++){
          output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
-         if(i<nArg-1) utf8_print(p->out, p->colSeparator);
 -        if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
++        if(i<nArg-1) sputz(p->out, p->colSeparator);
        }
-       utf8_print(p->out, p->rowSeparator);
 -      utf8_printf(p->out, "%s", p->rowSeparator);
++      sputz(p->out, p->rowSeparator);
        break;
      }
      case MODE_Csv: {
          for(i=0; i<nArg; i++){
            output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
          }
-         utf8_print(p->out, p->rowSeparator);
 -        utf8_printf(p->out, "%s", p->rowSeparator);
++        sputz(p->out, p->rowSeparator);
        }
        if( nArg>0 ){
          for(i=0; i<nArg; i++){
            output_csv(p, azArg[i], i<nArg-1);
          }
-         utf8_print(p->out, p->rowSeparator);
 -        utf8_printf(p->out, "%s", p->rowSeparator);
++        sputz(p->out, p->rowSeparator);
        }
        setTextMode(p->out, 1);
        break;
      }
      case MODE_Insert: {
        if( azArg==0 ) break;
--      utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
++      sputf(p->out,"INSERT INTO %s",p->zDestTable);
        if( p->showHeader ){
-         utf8_print(p->out,"(");
 -        raw_printf(p->out,"(");
++        sputz(p->out,"(");
          for(i=0; i<nArg; i++){
-           if( i>0 ) utf8_print(p->out, ",");
 -          if( i>0 ) raw_printf(p->out, ",");
++          if( i>0 ) sputz(p->out, ",");
            if( quoteChar(azCol[i]) ){
              char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
              shell_check_oom(z);
-             utf8_printf(p->out, z);
 -            utf8_printf(p->out, "%s", z);
++            sputf(p->out, z);
              sqlite3_free(z);
            }else{
-             utf8_printf(p->out, "%s", azCol[i]);
 -            raw_printf(p->out, "%s", azCol[i]);
++            sputf(p->out, "%s", azCol[i]);
            }
          }
-         utf8_print(p->out,")");
 -        raw_printf(p->out,")");
++        sputz(p->out,")");
        }
        p->cnt++;
        for(i=0; i<nArg; i++){
-         utf8_print(p->out, i>0 ? "," : " VALUES(");
 -        raw_printf(p->out, i>0 ? "," : " VALUES(");
++        sputz(p->out, i>0 ? "," : " VALUES(");
          if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
-           utf8_print(p->out,"NULL");
 -          utf8_printf(p->out,"NULL");
++          sputz(p->out,"NULL");
          }else if( aiType && aiType[i]==SQLITE_TEXT ){
            if( ShellHasFlag(p, SHFLG_Newlines) ){
              output_quoted_string(p->out, azArg[i]);
              output_quoted_escaped_string(p->out, azArg[i]);
            }
          }else if( aiType && aiType[i]==SQLITE_INTEGER ){
-           utf8_print(p->out, azArg[i]);
 -          utf8_printf(p->out,"%s", azArg[i]);
++          sputz(p->out, azArg[i]);
          }else if( aiType && aiType[i]==SQLITE_FLOAT ){
            char z[50];
            double r = sqlite3_column_double(p->pStmt, i);
            sqlite3_uint64 ur;
            memcpy(&ur,&r,sizeof(r));
            if( ur==0x7ff0000000000000LL ){
-             utf8_print(p->out, "9.0e+999");
 -            raw_printf(p->out, "9.0e+999");
++            sputz(p->out, "9.0e+999");
            }else if( ur==0xfff0000000000000LL ){
-             utf8_print(p->out, "-9.0e+999");
 -            raw_printf(p->out, "-9.0e+999");
++            sputz(p->out, "-9.0e+999");
            }else{
              sqlite3_int64 ir = (sqlite3_int64)r;
              if( r==(double)ir ){
              }else{
                sqlite3_snprintf(50,z,"%!.20g", r);
              }
-             utf8_print(p->out, z);
 -            raw_printf(p->out, "%s", z);
++            sputz(p->out, z);
            }
          }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
            const void *pBlob = sqlite3_column_blob(p->pStmt, i);
            int nBlob = sqlite3_column_bytes(p->pStmt, i);
            output_hex_blob(p->out, pBlob, nBlob);
          }else if( isNumber(azArg[i], 0) ){
-           utf8_print(p->out, azArg[i]);
 -          utf8_printf(p->out,"%s", azArg[i]);
++          sputz(p->out, azArg[i]);
          }else if( ShellHasFlag(p, SHFLG_Newlines) ){
            output_quoted_string(p->out, azArg[i]);
          }else{
            output_quoted_escaped_string(p->out, azArg[i]);
          }
        }
-       utf8_print(p->out,");\n");
 -      raw_printf(p->out,");\n");
++      sputz(p->out,");\n");
        break;
      }
      case MODE_Json: {
        p->cnt++;
        for(i=0; i<nArg; i++){
          output_json_string(p->out, azCol[i], -1);
--        putc(':', p->out);
++        sputz(p->out, ":");
          if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
--          fputs("null",p->out);
++          sputz(p->out, "null");
          }else if( aiType && aiType[i]==SQLITE_FLOAT ){
            char z[50];
            double r = sqlite3_column_double(p->pStmt, i);
            sqlite3_uint64 ur;
            memcpy(&ur,&r,sizeof(r));
            if( ur==0x7ff0000000000000LL ){
-             utf8_print(p->out, "9.0e+999");
 -            raw_printf(p->out, "9.0e+999");
++            sputz(p->out, "9.0e+999");
            }else if( ur==0xfff0000000000000LL ){
-             utf8_print(p->out, "-9.0e+999");
 -            raw_printf(p->out, "-9.0e+999");
++            sputz(p->out, "-9.0e+999");
            }else{
              sqlite3_snprintf(50,z,"%!.20g", r);
-             utf8_print(p->out, z);
 -            raw_printf(p->out, "%s", z);
++            sputz(p->out, z);
            }
          }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
            const void *pBlob = sqlite3_column_blob(p->pStmt, i);
          }else if( aiType && aiType[i]==SQLITE_TEXT ){
            output_json_string(p->out, azArg[i], -1);
          }else{
-           utf8_print(p->out, azArg[i]);
 -          utf8_printf(p->out,"%s", azArg[i]);
++          sputz(p->out, azArg[i]);
          }
          if( i<nArg-1 ){
-           utf8_print(p->out, ",");
 -          putc(',', p->out);
++          sputz(p->out, ",");
          }
        }
-       utf8_print(p->out, "}");
 -      putc('}', p->out);
++      sputz(p->out, "}");
        break;
      }
      case MODE_Quote: {
        for(i=0; i<nArg; i++){
          if( i>0 ) fputs(p->colSeparator, p->out);
          if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
-           utf8_print(p->out,"NULL");
 -          utf8_printf(p->out,"NULL");
++          sputz(p->out,"NULL");
          }else if( aiType && aiType[i]==SQLITE_TEXT ){
            output_quoted_string(p->out, azArg[i]);
          }else if( aiType && aiType[i]==SQLITE_INTEGER ){
-           utf8_print(p->out, azArg[i]);
 -          utf8_printf(p->out,"%s", azArg[i]);
++          sputz(p->out, azArg[i]);
          }else if( aiType && aiType[i]==SQLITE_FLOAT ){
            char z[50];
            double r = sqlite3_column_double(p->pStmt, i);
            sqlite3_snprintf(50,z,"%!.20g", r);
-           utf8_print(p->out, z);
 -          raw_printf(p->out, "%s", z);
++          sputz(p->out, z);
          }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
            const void *pBlob = sqlite3_column_blob(p->pStmt, i);
            int nBlob = sqlite3_column_bytes(p->pStmt, i);
            output_hex_blob(p->out, pBlob, nBlob);
          }else if( isNumber(azArg[i], 0) ){
-           utf8_print(p->out, azArg[i]);
 -          utf8_printf(p->out,"%s", azArg[i]);
++          sputz(p->out, azArg[i]);
          }else{
            output_quoted_string(p->out, azArg[i]);
          }
      case MODE_Ascii: {
        if( p->cnt++==0 && p->showHeader ){
          for(i=0; i<nArg; i++){
-           if( i>0 ) utf8_print(p->out, p->colSeparator);
-           utf8_print(p->out, azCol[i] ? azCol[i] : "");
 -          if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
 -          utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
++          if( i>0 ) sputz(p->out, p->colSeparator);
++          sputz(p->out, azCol[i] ? azCol[i] : "");
          }
-         utf8_print(p->out, p->rowSeparator);
 -        utf8_printf(p->out, "%s", p->rowSeparator);
++        sputz(p->out, p->rowSeparator);
        }
        if( azArg==0 ) break;
        for(i=0; i<nArg; i++){
-         if( i>0 ) utf8_print(p->out, p->colSeparator);
-         utf8_print(p->out, azArg[i] ? azArg[i] : p->nullValue);
 -        if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
 -        utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
++        if( i>0 ) sputz(p->out, p->colSeparator);
++        sputz(p->out, azArg[i] ? azArg[i] : p->nullValue);
        }
-       utf8_print(p->out, p->rowSeparator);
 -      utf8_printf(p->out, "%s", p->rowSeparator);
++      sputz(p->out, p->rowSeparator);
        break;
      }
      case MODE_EQP: {
@@@ -2764,7 -3026,7 +2767,7 @@@ static void createSelftestTable(ShellSt
      "DROP TABLE [_shell$self];"
      ,0,0,&zErrMsg);
    if( zErrMsg ){
--    utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
++    sputf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
    }
    sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
@@@ -2867,7 -3129,7 +2870,7 @@@ static int run_table_dump_query
    rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
    if( rc!=SQLITE_OK || !pSelect ){
      char *zContext = shell_error_context(zSelect, p->db);
--    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
++    sputf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
                  sqlite3_errmsg(p->db), zContext);
      sqlite3_free(zContext);
      if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
    nResult = sqlite3_column_count(pSelect);
    while( rc==SQLITE_ROW ){
      z = (const char*)sqlite3_column_text(pSelect, 0);
--    utf8_printf(p->out, "%s", z);
++    sputf(p->out, "%s", z);
      for(i=1; i<nResult; i++){
--      utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
++      sputf(p->out, ",%s", sqlite3_column_text(pSelect, i));
      }
      if( z==0 ) z = "";
      while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
      if( z[0] ){
-       utf8_print(p->out, "\n;\n");
 -      raw_printf(p->out, "\n;\n");
++      sputz(p->out, "\n;\n");
      }else{
-       utf8_print(p->out, ";\n");
 -      raw_printf(p->out, ";\n");
++      sputz(p->out, ";\n");
      }
      rc = sqlite3_step(pSelect);
    }
    rc = sqlite3_finalize(pSelect);
    if( rc!=SQLITE_OK ){
--    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
++    sputf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
                  sqlite3_errmsg(p->db));
      if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
    }
@@@ -2952,7 -3214,7 +2955,7 @@@ static void displayLinuxIoStats(FILE *o
      for(i=0; i<ArraySize(aTrans); i++){
        int n = strlen30(aTrans[i].zPattern);
        if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
--        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
++        sputf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
          break;
        }
      }
@@@ -2984,7 -3246,7 +2987,7 @@@ static void displayStatLine
    }else{
      sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
    }
-   utf8_printf(p->out, "%-36s %s\n", zLabel, zLine);
 -  raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
++  sputf(p->out, "%-36s %s\n", zLabel, zLine);
  }
  
  /*
@@@ -3006,21 -3268,21 +3009,21 @@@ static int display_stats
      sqlite3_stmt *pStmt = pArg->pStmt;
      char z[100];
      nCol = sqlite3_column_count(pStmt);
-     utf8_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
 -    raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
++    sputf(out, "%-36s %d\n", "Number of output columns:", nCol);
      for(i=0; i<nCol; i++){
        sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
--      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
++      sputf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
  #ifndef SQLITE_OMIT_DECLTYPE
        sqlite3_snprintf(30, z+x, "declared type:");
--      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
++      sputf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
  #endif
  #ifdef SQLITE_ENABLE_COLUMN_METADATA
        sqlite3_snprintf(30, z+x, "database name:");
--      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
++      sputf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
        sqlite3_snprintf(30, z+x, "table name:");
--      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
++      sputf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
        sqlite3_snprintf(30, z+x, "origin name:");
--      utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
++      sputf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
  #endif
      }
    }
    if( pArg->statsOn==3 ){
      if( pArg->pStmt ){
        iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP,bReset);
-       utf8_printf(pArg->out, "VM-steps: %d\n", iCur);
 -      raw_printf(pArg->out, "VM-steps: %d\n", iCur);
++      sputf(pArg->out, "VM-steps: %d\n", iCur);
      }
      return 0;
    }
        iHiwtr = iCur = -1;
        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
                          &iCur, &iHiwtr, bReset);
-       utf8_printf(pArg->out,
 -      raw_printf(pArg->out,
++      sputf(pArg->out,
                "Lookaside Slots Used:                %d (max %d)\n",
                iCur, iHiwtr);
        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
                          &iCur, &iHiwtr, bReset);
-       utf8_printf(pArg->out, "Successful lookaside attempts:       %d\n",
 -      raw_printf(pArg->out, "Successful lookaside attempts:       %d\n",
++      sputf(pArg->out, "Successful lookaside attempts:       %d\n",
                iHiwtr);
        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
                          &iCur, &iHiwtr, bReset);
-       utf8_printf(pArg->out, "Lookaside failures due to size:      %d\n",
 -      raw_printf(pArg->out, "Lookaside failures due to size:      %d\n",
++      sputf(pArg->out, "Lookaside failures due to size:      %d\n",
                iHiwtr);
        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
                          &iCur, &iHiwtr, bReset);
-       utf8_printf(pArg->out, "Lookaside failures due to OOM:       %d\n",
 -      raw_printf(pArg->out, "Lookaside failures due to OOM:       %d\n",
++      sputf(pArg->out, "Lookaside failures due to OOM:       %d\n",
                iHiwtr);
      }
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
-     utf8_printf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
 -    raw_printf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
++    sputf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
              iCur);
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
-     utf8_printf(pArg->out, "Page cache hits:                     %d\n", iCur);
 -    raw_printf(pArg->out, "Page cache hits:                     %d\n", iCur);
++    sputf(pArg->out, "Page cache hits:                     %d\n", iCur);
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
-     utf8_printf(pArg->out, "Page cache misses:                   %d\n", iCur);
 -    raw_printf(pArg->out, "Page cache misses:                   %d\n", iCur);
++    sputf(pArg->out, "Page cache misses:                   %d\n", iCur);
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
-     utf8_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
 -    raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
++    sputf(pArg->out, "Page cache writes:                   %d\n", iCur);
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
-     utf8_printf(pArg->out, "Page cache spills:                   %d\n", iCur);
 -    raw_printf(pArg->out, "Page cache spills:                   %d\n", iCur);
++    sputf(pArg->out, "Page cache spills:                   %d\n", iCur);
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
-     utf8_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
 -    raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
++    sputf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
              iCur);
      iHiwtr = iCur = -1;
      sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
-     utf8_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
 -    raw_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
++    sputf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
              iCur);
    }
  
      int iHit, iMiss;
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                                 bReset);
-     utf8_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
 -    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
++    sputf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
-     utf8_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
 -    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
++    sputf(pArg->out, "Sort Operations:                     %d\n", iCur);
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
-     utf8_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
 -    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
++    sputf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
      iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT,
                                 bReset);
      iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS,
                                  bReset);
      if( iHit || iMiss ){
-       utf8_printf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
 -      raw_printf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
++      sputf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
              iHit, iHit+iMiss);
      }
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
-     utf8_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
 -    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
++    sputf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
-     utf8_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
 -    raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
++    sputf(pArg->out, "Reprepare operations:                %d\n", iCur);
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
-     utf8_printf(pArg->out, "Number of times run:                 %d\n", iCur);
 -    raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
++    sputf(pArg->out, "Number of times run:                 %d\n", iCur);
      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
-     utf8_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
 -    raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
++    sputf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
    }
  
  #ifdef __linux__
@@@ -3515,10 -3777,10 +3518,10 @@@ static void print_box_line(FILE *out, i
    const int nDash = sizeof(zDash) - 1;
    N *= 3;
    while( N>nDash ){
-     utf8_print(out, zDash);
 -    utf8_printf(out, zDash);
++    sputz(out, zDash);
      N -= nDash;
    }
--  utf8_printf(out, "%.*s", N, zDash);
++  sputf(out, "%.*s", N, zDash);
  }
  
  /*
@@@ -3533,15 -3795,15 +3536,15 @@@ static void print_box_row_separator
  ){
    int i;
    if( nArg>0 ){
-     utf8_print(p->out, zSep1);
 -    utf8_printf(p->out, "%s", zSep1);
++    sputz(p->out, zSep1);
      print_box_line(p->out, p->actualWidth[0]+2);
      for(i=1; i<nArg; i++){
-       utf8_print(p->out, zSep2);
 -      utf8_printf(p->out, "%s", zSep2);
++      sputz(p->out, zSep2);
        print_box_line(p->out, p->actualWidth[i]+2);
      }
-     utf8_print(p->out, zSep3);
 -    utf8_printf(p->out, "%s", zSep3);
++    sputz(p->out, zSep3);
    }
-   utf8_print(p->out, "\n");
 -  fputs("\n", p->out);
++  sputz(p->out, "\n");
  }
  
  /*
@@@ -3822,8 -4084,8 +3825,8 @@@ static void exec_prepared_stmt_columnar
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          n = strlenChar(azData[i]);
--        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
-         utf8_print(p->out, i==nColumn-1?" |\n":" | ");
 -        fputs(i==nColumn-1?" |\n":" | ", p->out);
++        sputf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
++        sputz(p->out, i==nColumn-1?" |\n":" | ");
        }
        print_row_separator(p, nColumn, "+");
        break;
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          n = strlenChar(azData[i]);
--        utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
-         utf8_print(p->out, i==nColumn-1?" |\n":" | ");
 -        fputs(i==nColumn-1?" |\n":" | ", p->out);
++        sputf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
++        sputz(p->out, i==nColumn-1?" |\n":" | ");
        }
        print_row_separator(p, nColumn, "|");
        break;
        colSep = " " BOX_13 " ";
        rowSep = " " BOX_13 "\n";
        print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
-       utf8_print(p->out, BOX_13 " ");
 -      utf8_printf(p->out, BOX_13 " ");
++      sputz(p->out, BOX_13 " ");
        for(i=0; i<nColumn; i++){
          w = p->actualWidth[i];
          n = strlenChar(azData[i]);
--        utf8_printf(p->out, "%*s%s%*s%s",
++        sputf(p->out, "%*s%s%*s%s",
              (w-n)/2, "", azData[i], (w-n+1)/2, "",
              i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
        }
    }
    for(i=nColumn, j=0; i<nTotal; i++, j++){
      if( j==0 && p->cMode!=MODE_Column ){
-       utf8_print(p->out, p->cMode==MODE_Box?BOX_13" ":"| ");
 -      utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
++      sputz(p->out, p->cMode==MODE_Box?BOX_13" ":"| ");
      }
      z = azData[i];
      if( z==0 ) z = p->nullValue;
      if( p->colWidth[j]<0 ) w = -w;
      utf8_width_print(p->out, w, z);
      if( j==nColumn-1 ){
-       utf8_print(p->out, rowSep);
 -      utf8_printf(p->out, "%s", rowSep);
++      sputz(p->out, rowSep);
        if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
          if( p->cMode==MODE_Table ){
            print_row_separator(p, nColumn, "+");
          }else if( p->cMode==MODE_Box ){
            print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
          }else if( p->cMode==MODE_Column ){
-           utf8_print(p->out, "\n");
 -          raw_printf(p->out, "\n");
++          sputz(p->out, "\n");
          }
        }
        j = -1;
        if( seenInterrupt ) goto columnar_end;
      }else{
-       utf8_print(p->out, colSep);
 -      utf8_printf(p->out, "%s", colSep);
++      sputz(p->out, colSep);
      }
    }
    if( p->cMode==MODE_Table ){
    }
  columnar_end:
    if( seenInterrupt ){
-     utf8_print(p->out, "Interrupt\n");
 -    utf8_printf(p->out, "Interrupt\n");
++    sputz(p->out, "Interrupt\n");
    }
    nData = (nRow+1)*nColumn;
    for(i=0; i<nData; i++){
@@@ -4039,8 -4301,8 +4042,8 @@@ static int expertFinish
  
        if( bVerbose ){
          const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
-         utf8_print(out, "-- Candidates -----------------------------\n");
-         utf8_printf(out, "%s\n", zCand);
 -        raw_printf(out, "-- Candidates -----------------------------\n");
 -        raw_printf(out, "%s\n", zCand);
++        sputz(out, "-- Candidates -----------------------------\n");
++        sputf(out, "%s\n", zCand);
        }
        for(i=0; i<nQuery; i++){
          const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
          const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
          if( zIdx==0 ) zIdx = "(no new indexes)\n";
          if( bVerbose ){
-           utf8_printf(out,"-- Query %d --------------------------------\n",i+1);
-           utf8_printf(out, "%s\n\n", zSql);
 -          raw_printf(out, "-- Query %d --------------------------------\n",i+1);
 -          raw_printf(out, "%s\n\n", zSql);
++          sputf(out,"-- Query %d --------------------------------\n",i+1);
++          sputf(out, "%s\n\n", zSql);
          }
-         utf8_printf(out, "%s\n", zIdx);
-         utf8_printf(out, "%s\n", zEQP);
 -        raw_printf(out, "%s\n", zIdx);
 -        raw_printf(out, "%s\n", zEQP);
++        sputf(out, "%s\n", zIdx);
++        sputf(out, "%s\n", zEQP);
        }
      }
    }
@@@ -4087,18 -4349,18 +4090,18 @@@ static int expertDotCommand
      }
      else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
        if( i==(nArg-1) ){
-         utf8_printf(stderr, "option requires an argument: %s\n", z);
 -        raw_printf(stderr, "option requires an argument: %s\n", z);
++        eputf("option requires an argument: %s\n", z);
          rc = SQLITE_ERROR;
        }else{
          iSample = (int)integerValue(azArg[++i]);
          if( iSample<0 || iSample>100 ){
-           utf8_printf(stderr, "value out of range: %s\n", azArg[i]);
 -          raw_printf(stderr, "value out of range: %s\n", azArg[i]);
++          eputf("value out of range: %s\n", azArg[i]);
            rc = SQLITE_ERROR;
          }
        }
      }
      else{
-       utf8_printf(stderr, "unknown option: %s\n", z);
 -      raw_printf(stderr, "unknown option: %s\n", z);
++      eputf("unknown option: %s\n", z);
        rc = SQLITE_ERROR;
      }
    }
    if( rc==SQLITE_OK ){
      pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
      if( pState->expert.pExpert==0 ){
-       utf8_printf(stderr, "sqlite3_expert_new: %s\n",
 -      raw_printf(stderr, "sqlite3_expert_new: %s\n",
--                 zErr ? zErr : "out of memory");
++      eputf("sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
        rc = SQLITE_ERROR;
      }else{
        sqlite3_expert_config(
@@@ -4434,9 -4696,9 +4436,9 @@@ static int dump_callback(void *pArg, in
    noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
  
    if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
-     if( !dataOnly ) utf8_print(p->out, "DELETE FROM sqlite_sequence;\n");
 -    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
++    if( !dataOnly ) sputz(p->out, "DELETE FROM sqlite_sequence;\n");
    }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
-     if( !dataOnly ) utf8_print(p->out, "ANALYZE sqlite_schema;\n");
 -    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
++    if( !dataOnly ) sputz(p->out, "ANALYZE sqlite_schema;\n");
    }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
      return 0;
    }else if( dataOnly ){
    }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
      char *zIns;
      if( !p->writableSchema ){
-       utf8_print(p->out, "PRAGMA writable_schema=ON;\n");
 -      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
++      sputz(p->out, "PRAGMA writable_schema=ON;\n");
        p->writableSchema = 1;
      }
      zIns = sqlite3_mprintf(
         "VALUES('table','%q','%q',0,'%q');",
         zTable, zTable, zSql);
      shell_check_oom(zIns);
--    utf8_printf(p->out, "%s\n", zIns);
++    sputf(p->out, "%s\n", zIns);
      sqlite3_free(zIns);
      return 0;
    }else{
      p->mode = p->cMode = MODE_Insert;
      rc = shell_exec(p, sSelect.z, 0);
      if( (rc&0xff)==SQLITE_CORRUPT ){
-       utf8_print(p->out, "/****** CORRUPTION ERROR *******/\n");
 -      raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
++      sputz(p->out, "/****** CORRUPTION ERROR *******/\n");
        toggleSelectOrder(p->db);
        shell_exec(p, sSelect.z, 0);
        toggleSelectOrder(p->db);
@@@ -4545,9 -4807,9 +4547,9 @@@ static int run_schema_dump_query
    if( rc==SQLITE_CORRUPT ){
      char *zQ2;
      int len = strlen30(zQuery);
-     utf8_print(p->out, "/****** CORRUPTION ERROR *******/\n");
 -    raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
++    sputz(p->out, "/****** CORRUPTION ERROR *******/\n");
      if( zErr ){
--      utf8_printf(p->out, "/****** %s ******/\n", zErr);
++      sputf(p->out, "/****** %s ******/\n", zErr);
        sqlite3_free(zErr);
        zErr = 0;
      }
      sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
      rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
      if( rc ){
--      utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
++      sputf(p->out, "/****** ERROR: %s ******/\n", zErr);
      }else{
        rc = SQLITE_CORRUPT;
      }
@@@ -4912,10 -5174,10 +4914,10 @@@ static int showHelp(FILE *out, const ch
        }
        if( ((hw^hh)&HH_Undoc)==0 ){
          if( (hh&HH_Summary)!=0 ){
--          utf8_printf(out, ".%s\n", azHelp[i]+1);
++          sputf(out, ".%s\n", azHelp[i]+1);
            ++n;
          }else if( (hw&HW_SummaryOnly)==0 ){
--          utf8_printf(out, "%s\n", azHelp[i]);
++          sputf(out, "%s\n", azHelp[i]);
          }
        }
      }
      shell_check_oom(zPat);
      for(i=0; i<ArraySize(azHelp); i++){
        if( sqlite3_strglob(zPat, azHelp[i])==0 ){
--        utf8_printf(out, "%s\n", azHelp[i]);
++        sputf(out, "%s\n", azHelp[i]);
          j = i+1;
          n++;
        }
          /* when zPattern is a prefix of exactly one command, then include
          ** the details of that command, which should begin at offset j */
          while( j<ArraySize(azHelp)-1 && azHelp[j][0]==' ' ){
--          utf8_printf(out, "%s\n", azHelp[j]);
++          sputf(out, "%s\n", azHelp[j]);
            j++;
          }
        }
        }
        if( azHelp[i][0]=='.' ) j = i;
        if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
--        utf8_printf(out, "%s\n", azHelp[j]);
++        sputf(out, "%s\n", azHelp[j]);
          while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]==' ' ){
            j++;
--          utf8_printf(out, "%s\n", azHelp[j]);
++          sputf(out, "%s\n", azHelp[j]);
          }
          i = j;
          n++;
@@@ -4994,7 -5256,7 +4996,7 @@@ static char *readFile(const char *zName
    if( in==0 ) return 0;
    rc = fseek(in, 0, SEEK_END);
    if( rc!=0 ){
-     utf8_printf(stderr, "Error: '%s' not seekable\n", zName);
 -    raw_printf(stderr, "Error: '%s' not seekable\n", zName);
++    eputf("Error: '%s' not seekable\n", zName);
      fclose(in);
      return 0;
    }
    rewind(in);
    pBuf = sqlite3_malloc64( nIn+1 );
    if( pBuf==0 ){
-     utf8_print(stderr, "Error: out of memory\n");
 -    raw_printf(stderr, "Error: out of memory\n");
++    eputz("Error: out of memory\n");
      fclose(in);
      return 0;
    }
    fclose(in);
    if( nRead!=1 ){
      sqlite3_free(pBuf);
-     utf8_printf(stderr, "Error: cannot read '%s'\n", zName);
 -    raw_printf(stderr, "Error: cannot read '%s'\n", zName);
++    eputf("Error: cannot read '%s'\n", zName);
      return 0;
    }
    pBuf[nIn] = 0;
@@@ -5131,7 -5393,7 +5133,7 @@@ static unsigned char *readHexDb(ShellSt
    if( zDbFilename ){
      in = fopen(zDbFilename, "r");
      if( in==0 ){
--      utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
++      eputf("cannot open \"%s\" for reading\n", zDbFilename);
        return 0;
      }
      nLine = 0;
    shell_check_oom(a);
    memset(a, 0, n);
    if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
-     utf8_print(stderr, "invalid pagesize\n");
 -    utf8_printf(stderr, "invalid pagesize\n");
++    sputz(stderr, "invalid pagesize\n");
      goto readHexDb_error;
    }
    for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
@@@ -5194,7 -5456,7 +5196,7 @@@ readHexDb_error
      p->lineno = nLine;
    }
    sqlite3_free(a);
--  utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
++  eputf("Error on line %d of --hexdb input\n", nLine);
    return 0;
  }
  #endif /* SQLITE_OMIT_DESERIALIZE */
@@@ -5270,22 -5532,22 +5272,19 @@@ static void open_db(ShellState *p, int 
      }
      globalDb = p->db;
      if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
--      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
--          zDbFilename, sqlite3_errmsg(p->db));
++      eputf("Error: unable to open database \"%s\": %s\n",
++            zDbFilename, sqlite3_errmsg(p->db));
        if( (openFlags & OPEN_DB_KEEPALIVE)==0 ){
          exit(1);
        }
        sqlite3_close(p->db);
        sqlite3_open(":memory:", &p->db);
        if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
-         utf8_print(stderr,
 -        utf8_printf(stderr,
--          "Also: unable to open substitute in-memory database.\n"
--        );
++        eputz("Also: unable to open substitute in-memory database.\n");
          exit(1);
        }else{
--        utf8_printf(stderr,
--          "Notice: using substitute in-memory database instead of \"%s\"\n",
--          zDbFilename);
++        eputf("Notice: using substitute in-memory database instead of \"%s\"\n",
++              zDbFilename);
        }
      }
      sqlite3_db_config(p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, (int)0, (int*)0);
                     SQLITE_DESERIALIZE_RESIZEABLE |
                     SQLITE_DESERIALIZE_FREEONCLOSE);
        if( rc ){
--        utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
++        eputf("Error: sqlite3_deserialize() returns %d\n", rc);
        }
        if( p->szMax>0 ){
          sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
  void close_db(sqlite3 *db){
    int rc = sqlite3_close(db);
    if( rc ){
--    utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
--        rc, sqlite3_errmsg(db));
++    eputf("Error: sqlite3_close() returns %d: %s\n", rc, sqlite3_errmsg(db));
    }
  }
  
@@@ -5578,8 -5840,8 +5576,7 @@@ static int booleanValue(const char *zAr
    if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
      return 0;
    }
--  utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
--          zArg);
++  eputf("ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n", zArg);
    return 0;
  }
  
@@@ -5617,7 -5879,7 +5614,7 @@@ static FILE *output_file_open(const cha
    }else{
      f = fopen(zFile, bTextMode ? "w" : "wb");
      if( f==0 ){
--      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
++      eputf("Error: cannot open \"%s\"\n", zFile);
      }
    }
    return f;
@@@ -5639,7 -5901,7 +5636,7 @@@ static int sql_trace_callback
    i64 nSql;
    if( p->traceOut==0 ) return 0;
    if( mType==SQLITE_TRACE_CLOSE ){
-     utf8_print(p->traceOut, "-- closing database connection\n");
 -    utf8_printf(p->traceOut, "-- closing database connection\n");
++    sputz(p->traceOut, "-- closing database connection\n");
      return 0;
    }
    if( mType!=SQLITE_TRACE_ROW && pX!=0 && ((const char*)pX)[0]=='-' ){
    switch( mType ){
      case SQLITE_TRACE_ROW:
      case SQLITE_TRACE_STMT: {
--      utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
++      sputf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
        break;
      }
      case SQLITE_TRACE_PROFILE: {
        sqlite3_int64 nNanosec = pX ? *(sqlite3_int64*)pX : 0;
--      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
++      sputf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
        break;
      }
    }
@@@ -5782,12 -6044,12 +5779,11 @@@ static char *SQLITE_CDECL csv_read_one_
          break;
        }
        if( pc==cQuote && c!='\r' ){
--        utf8_printf(stderr, "%s:%d: unescaped %c character\n",
--                p->zFile, p->nLine, cQuote);
++        eputf("%s:%d: unescaped %c character\n", p->zFile, p->nLine, cQuote);
        }
        if( c==EOF ){
--        utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
--                p->zFile, startLine, cQuote);
++        eputf("%s:%d: unterminated %c-quoted field\n",
++              p->zFile, startLine, cQuote);
          p->cTerm = c;
          break;
        }
@@@ -5885,9 -6147,9 +5881,8 @@@ static void tryToCloneData
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
--    utf8_printf(stderr, "Error %d: %s on [%s]\n",
--            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
--            zQuery);
++    eputf("Error %d: %s on [%s]\n",
++          sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery);
      goto end_data_xfer;
    }
    n = sqlite3_column_count(pQuery);
    memcpy(zInsert+i, ");", 3);
    rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
    if( rc ){
--    utf8_printf(stderr, "Error %d: %s on [%s]\n",
--            sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
--            zInsert);
++    eputf("Error %d: %s on [%s]\n",
++          sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb), zInsert);
      goto end_data_xfer;
    }
    for(k=0; k<2; k++){
        } /* End for */
        rc = sqlite3_step(pInsert);
        if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
--        utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
--                        sqlite3_errmsg(newDb));
++        eputf("Error %d: %s\n",
++              sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb));
        }
        sqlite3_reset(pInsert);
        cnt++;
      shell_check_oom(zQuery);
      rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
      if( rc ){
--      utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
++      eputf("Warning: cannot step \"%s\" backwards", zTable);
        break;
      }
    } /* End for(k=0...) */
@@@ -5995,9 -6257,9 +5989,8 @@@ static void tryToCloneSchema
    shell_check_oom(zQuery);
    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
    if( rc ){
--    utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
--                    sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
--                    zQuery);
++    eputf("Error: (%d) %s on [%s]\n", sqlite3_extended_errcode(p->db),
++          sqlite3_errmsg(p->db), zQuery);
      goto end_schema_xfer;
    }
    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
      zSql = sqlite3_column_text(pQuery, 1);
      if( zName==0 || zSql==0 ) continue;
      if( sqlite3_stricmp((char*)zName, "sqlite_sequence")!=0 ){
--      printf("%s... ", zName); fflush(stdout);
++      sputf(stdout, "%s... ", zName); fflush(stdout);
        sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
        if( zErrMsg ){
--        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
++        eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
          sqlite3_free(zErrMsg);
          zErrMsg = 0;
        }
      if( xForEach ){
        xForEach(p, newDb, (const char*)zName);
      }
--    printf("done\n");
++    sputz(stdout, "done\n");
    }
    if( rc!=SQLITE_DONE ){
      sqlite3_finalize(pQuery);
      shell_check_oom(zQuery);
      rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
      if( rc ){
--      utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
--                      sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
--                      zQuery);
++      eputf("Error: (%d) %s on [%s]\n",
++            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db), zQuery);
        goto end_schema_xfer;
      }
      while( sqlite3_step(pQuery)==SQLITE_ROW ){
        zSql = sqlite3_column_text(pQuery, 1);
        if( zName==0 || zSql==0 ) continue;
        if( sqlite3_stricmp((char*)zName, "sqlite_sequence")==0 ) continue;
--      printf("%s... ", zName); fflush(stdout);
++      sputf(stdout, "%s... ", zName); fflush(stdout);
        sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
        if( zErrMsg ){
--        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
++        eputf("Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
          sqlite3_free(zErrMsg);
          zErrMsg = 0;
        }
        if( xForEach ){
          xForEach(p, newDb, (const char*)zName);
        }
--      printf("done\n");
++      sputz(stdout, "done\n");
      }
    }
  end_schema_xfer:
@@@ -6063,13 -6325,13 +6055,12 @@@ static void tryToClone(ShellState *p, c
    int rc;
    sqlite3 *newDb = 0;
    if( access(zNewDb,0)==0 ){
--    utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
++    eputf("File \"%s\" already exists.\n", zNewDb);
      return;
    }
    rc = sqlite3_open(zNewDb, &newDb);
    if( rc ){
--    utf8_printf(stderr, "Cannot create output database: %s\n",
--            sqlite3_errmsg(newDb));
++    eputf("Cannot create output database: %s\n", sqlite3_errmsg(newDb));
    }else{
      sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
      sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
@@@ -6108,7 -6370,7 +6099,7 @@@ static void output_reset(ShellState *p)
        char *zCmd;
        zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
        if( system(zCmd) ){
--        utf8_printf(stderr, "Failed: [%s]\n", zCmd);
++        eputf("Failed: [%s]\n", zCmd);
        }else{
          /* Give the start/open/xdg-open command some time to get
          ** going before we continue, and potential delete the
@@@ -6194,7 -6456,7 +6185,7 @@@ static int shell_dbinfo_command(ShellSt
               "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
               -1, &pStmt, 0);
    if( rc ){
--    utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
++    eputf("error: %s\n", sqlite3_errmsg(p->db));
      sqlite3_finalize(pStmt);
      return 1;
    }
      memcpy(aHdr, pb, 100);
      sqlite3_finalize(pStmt);
    }else{
-     utf8_print(stderr, "unable to read database header\n");
 -    raw_printf(stderr, "unable to read database header\n");
++    sputz(stderr, "unable to read database header\n");
      sqlite3_finalize(pStmt);
      return 1;
    }
    i = get2byteInt(aHdr+16);
    if( i==1 ) i = 65536;
--  utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
--  utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
--  utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
--  utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
++  sputf(p->out, "%-20s %d\n", "database page size:", i);
++  sputf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
++  sputf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
++  sputf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
    for(i=0; i<ArraySize(aField); i++){
      int ofst = aField[i].ofst;
      unsigned int val = get4byteInt(aHdr + ofst);
--    utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
++    sputf(p->out, "%-20s %u", aField[i].zName, val);
      switch( ofst ){
        case 56: {
-         if( val==1 ) utf8_print(p->out, " (utf8)");
-         if( val==2 ) utf8_print(p->out, " (utf16le)");
-         if( val==3 ) utf8_print(p->out, " (utf16be)");
 -        if( val==1 ) raw_printf(p->out, " (utf8)");
 -        if( val==2 ) raw_printf(p->out, " (utf16le)");
 -        if( val==3 ) raw_printf(p->out, " (utf16be)");
++        if( val==1 ) sputz(p->out, " (utf8)");
++        if( val==2 ) sputz(p->out, " (utf16le)");
++        if( val==3 ) sputz(p->out, " (utf16be)");
        }
      }
-     utf8_print(p->out, "\n");
 -    raw_printf(p->out, "\n");
++    sputz(p->out, "\n");
    }
    if( zDb==0 ){
      zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
      char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
      int val = db_int(p->db, zSql);
      sqlite3_free(zSql);
--    utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
++    sputf(p->out, "%-20s %d\n", aQuery[i].zName, val);
    }
    sqlite3_free(zSchemaTab);
    sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
--  utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
++  sputf(p->out, "%-20s %u\n", "data version", iDataVersion);
    return 0;
  }
  #endif /* SQLITE_SHELL_HAVE_RECOVER */
  */
  static int shellDatabaseError(sqlite3 *db){
    const char *zErr = sqlite3_errmsg(db);
--  utf8_printf(stderr, "Error: %s\n", zErr);
++  eputf("Error: %s\n", zErr);
    return 1;
  }
  
@@@ -6572,9 -6834,9 +6563,7 @@@ static int lintFkeyIndexes
        zIndent = "    ";
      }
      else{
-       utf8_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
 -      raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
--          azArg[0], azArg[1]
--      );
++      eputf("Usage: %s %s ?-verbose? ?-groupbyparent?\n", azArg[0], azArg[1]);
        return SQLITE_ERROR;
      }
    }
        if( rc!=SQLITE_OK ) break;
  
        if( res<0 ){
-         utf8_print(stderr, "Error: internal error");
 -        raw_printf(stderr, "Error: internal error");
++        eputz("Error: internal error");
          break;
        }else{
          if( bGroupByParent
          && (bVerbose || res==0)
          && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
          ){
-           utf8_printf(out, "-- Parent table %s\n", zParent);
 -          raw_printf(out, "-- Parent table %s\n", zParent);
++          sputf(out, "-- Parent table %s\n", zParent);
            sqlite3_free(zPrev);
            zPrev = sqlite3_mprintf("%s", zParent);
          }
  
          if( res==0 ){
-           utf8_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
 -          raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
++          sputf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
          }else if( bVerbose ){
-           utf8_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
 -          raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
--              zIndent, zFrom, zTarget
++          sputf(out, "%s/* no extra indexes required for %s -> %s */\n",
++                zIndent, zFrom, zTarget
            );
          }
        }
      sqlite3_free(zPrev);
  
      if( rc!=SQLITE_OK ){
-       utf8_printf(stderr, "%s\n", sqlite3_errmsg(db));
 -      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
++      eputf("%s\n", sqlite3_errmsg(db));
      }
  
      rc2 = sqlite3_finalize(pSql);
      if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
        rc = rc2;
-       utf8_printf(stderr, "%s\n", sqlite3_errmsg(db));
 -      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
++      eputf("%s\n", sqlite3_errmsg(db));
      }
    }else{
-     utf8_printf(stderr, "%s\n", sqlite3_errmsg(db));
 -    raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
++    eputf("%s\n", sqlite3_errmsg(db));
    }
  
    return rc;
@@@ -6671,9 -6933,9 +6660,9 @@@ static int lintDotCommand
    return lintFkeyIndexes(pState, azArg, nArg);
  
   usage:
-   utf8_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
-   utf8_print(stderr, "Where sub-commands are:\n");
-   utf8_print(stderr, "    fkey-indexes\n");
 -  raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
 -  raw_printf(stderr, "Where sub-commands are:\n");
 -  raw_printf(stderr, "    fkey-indexes\n");
++  eputf("Usage %s sub-command ?switches...?\n", azArg[0]);
++  eputz("Where sub-commands are:\n");
++  eputz("    fkey-indexes\n");
    return SQLITE_ERROR;
  }
  
@@@ -6688,9 -6950,9 +6677,7 @@@ static void shellPrepare
    if( *pRc==SQLITE_OK ){
      int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
      if( rc!=SQLITE_OK ){
-       utf8_printf(stderr, "sql error: %s (%d)\n",
 -      raw_printf(stderr, "sql error: %s (%d)\n",
--          sqlite3_errmsg(db), sqlite3_errcode(db)
--      );
++      eputf("sql error: %s (%d)\n", sqlite3_errmsg(db), sqlite3_errcode(db));
        *pRc = rc;
      }
    }
@@@ -6741,7 -7003,7 +6728,7 @@@ void shellFinalize
      int rc = sqlite3_finalize(pStmt);
      if( *pRc==SQLITE_OK ){
        if( rc!=SQLITE_OK ){
-         utf8_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
 -        raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
++        eputf("SQL error: %s\n", sqlite3_errmsg(db));
        }
        *pRc = rc;
      }
@@@ -6762,7 -7024,7 +6749,7 @@@ void shellReset
    if( *pRc==SQLITE_OK ){
      if( rc!=SQLITE_OK ){
        sqlite3 *db = sqlite3_db_handle(pStmt);
-       utf8_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
 -      raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
++      eputf("SQL error: %s\n", sqlite3_errmsg(db));
      }
      *pRc = rc;
    }
@@@ -6812,11 -7074,11 +6799,11 @@@ static int arErrorMsg(ArCommand *pAr, c
    va_start(ap, zFmt);
    z = sqlite3_vmprintf(zFmt, ap);
    va_end(ap);
--  utf8_printf(stderr, "Error: %s\n", z);
++  eputf("Error: %s\n", z);
    if( pAr->fromCmdLine ){
-     utf8_print(stderr, "Use \"-A\" for more help\n");
 -    utf8_printf(stderr, "Use \"-A\" for more help\n");
++    eputz("Use \"-A\" for more help\n");
    }else{
-     utf8_print(stderr, "Use \".archive --help\" for more help\n");
 -    utf8_printf(stderr, "Use \".archive --help\" for more help\n");
++    eputz("Use \".archive --help\" for more help\n");
    }
    sqlite3_free(z);
    return SQLITE_ERROR;
@@@ -6916,7 -7178,7 +6903,7 @@@ static int arParseCommand
    struct ArSwitch *pEnd = &aSwitch[nSwitch];
  
    if( nArg<=1 ){
-     utf8_print(stderr, "Wrong number of arguments.  Usage:\n");
 -    utf8_printf(stderr, "Wrong number of arguments.  Usage:\n");
++    eputz("Wrong number of arguments.  Usage:\n");
      return arUsage(stderr);
    }else{
      char *z = azArg[1];
      }
    }
    if( pAr->eCmd==0 ){
-     utf8_print(stderr, "Required argument missing.  Usage:\n");
 -    utf8_printf(stderr, "Required argument missing.  Usage:\n");
++    eputz("Required argument missing.  Usage:\n");
      return arUsage(stderr);
    }
    return SQLITE_OK;
@@@ -7065,7 -7327,7 +7052,7 @@@ static int arCheckEntries(ArCommand *pA
        }
        shellReset(&rc, pTest);
        if( rc==SQLITE_OK && bOk==0 ){
--        utf8_printf(stderr, "not found in archive: %s\n", z);
++        eputf("not found in archive: %s\n", z);
          rc = SQLITE_ERROR;
        }
      }
@@@ -7132,18 -7394,18 +7119,15 @@@ static int arListCommand(ArCommand *pAr
    shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                       pAr->zSrcTable, zWhere);
    if( pAr->bDryRun ){
--    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
++    sputf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
    }else{
      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
        if( pAr->bVerbose ){
--        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
--            sqlite3_column_text(pSql, 0),
--            sqlite3_column_int(pSql, 1),
--            sqlite3_column_text(pSql, 2),
--            sqlite3_column_text(pSql, 3)
--        );
++        sputf(pAr->p->out, "%s % 10d  %s  %s\n",
++              sqlite3_column_text(pSql, 0), sqlite3_column_int(pSql, 1),
++              sqlite3_column_text(pSql, 2),sqlite3_column_text(pSql, 3));
        }else{
--        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
++        sputf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
        }
      }
    }
    return rc;
  }
  
--
  /*
  ** Implementation of .ar "Remove" command.
  */
@@@ -7171,7 -7433,7 +7154,7 @@@ static int arRemoveCommand(ArCommand *p
      zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
                             pAr->zSrcTable, zWhere);
      if( pAr->bDryRun ){
--      utf8_printf(pAr->p->out, "%s\n", zSql);
++      sputf(pAr->p->out, "%s\n", zSql);
      }else{
        char *zErr = 0;
        rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
          }
        }
        if( zErr ){
--        utf8_printf(stdout, "ERROR: %s\n", zErr);
++        sputf(stdout, "ERROR: %s\n", zErr);
          sqlite3_free(zErr);
        }
      }
@@@ -7248,11 -7510,11 +7231,11 @@@ static int arExtractCommand(ArCommand *
        j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
        sqlite3_bind_int(pSql, j, i);
        if( pAr->bDryRun ){
--        utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
++        sputf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
        }else{
          while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
            if( i==0 && pAr->bVerbose ){
--            utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
++            sputf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
            }
          }
        }
  static int arExecSql(ArCommand *pAr, const char *zSql){
    int rc;
    if( pAr->bDryRun ){
--    utf8_printf(pAr->p->out, "%s\n", zSql);
++    sputf(pAr->p->out, "%s\n", zSql);
      rc = SQLITE_OK;
    }else{
      char *zErr = 0;
      rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
      if( zErr ){
--      utf8_printf(stdout, "ERROR: %s\n", zErr);
++      sputf(stdout, "ERROR: %s\n", zErr);
        sqlite3_free(zErr);
      }
    }
@@@ -7453,15 -7715,15 +7436,13 @@@ static int arDotCommand
        }
        cmd.db = 0;
        if( cmd.bDryRun ){
--        utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
--             eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
++        sputf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
++              eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
        }
        rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
               eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
        if( rc!=SQLITE_OK ){
--        utf8_printf(stderr, "cannot open file: %s (%s)\n",
--            cmd.zFile, sqlite3_errmsg(cmd.db)
--        );
++        eputf("cannot open file: %s (%s)\n", cmd.zFile, sqlite3_errmsg(cmd.db));
          goto end_ar_command;
        }
        sqlite3_fileio_init(cmd.db, 0, 0);
        if( cmd.eCmd!=AR_CMD_CREATE
         && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
        ){
-         utf8_print(stderr, "database does not contain an 'sqlar' table\n");
 -        utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
++        eputz("database does not contain an 'sqlar' table\n");
          rc = SQLITE_ERROR;
          goto end_ar_command;
        }
@@@ -7532,7 -7794,7 +7513,7 @@@ end_ar_command
  */
  static int recoverSqlCb(void *pCtx, const char *zSql){
    ShellState *pState = (ShellState*)pCtx;
--  utf8_printf(pState->out, "%s;\n", zSql);
++  sputf(pState->out, "%s;\n", zSql);
    return SQLITE_OK;
  }
  
@@@ -7575,7 -7837,7 +7556,7 @@@ static int recoverDatabaseCmd(ShellStat
        bRowids = 0;
      }
      else{
--      utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
++      eputf("unexpected option: %s\n", azArg[i]);
        showHelp(pState->out, azArg[0]);
        return 1;
      }
    if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
      const char *zErr = sqlite3_recover_errmsg(p);
      int errCode = sqlite3_recover_errcode(p);
-     utf8_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
 -    raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
++    eputf("sql error: %s (%d)\n", zErr, errCode);
    }
    rc = sqlite3_recover_finish(p);
    return rc;
  #define rc_err_oom_die(rc) \
    if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
    else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
--    fprintf(stderr,"E:%d\n",rc), assert(0)
++    eputf("E:%d\n",rc), assert(0)
  #else
  static void rc_err_oom_die(int rc){
    if( rc==SQLITE_NOMEM ) shell_check_oom(0);
@@@ -7873,7 -8134,7 +7854,7 @@@ static int do_meta_command(char *zLine
  #ifndef SQLITE_OMIT_AUTHORIZATION
    if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
      if( nArg!=2 ){
-       utf8_print(stderr, "Usage: .auth ON|OFF\n");
 -      raw_printf(stderr, "Usage: .auth ON|OFF\n");
++      eputz("Usage: .auth ON|OFF\n");
        rc = 1;
        goto meta_command_exit;
      }
            bAsync = 1;
          }else
          {
--          utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
++          eputf("unknown option: %s\n", azArg[j]);
            return 1;
          }
        }else if( zDestFile==0 ){
          zDb = zDestFile;
          zDestFile = azArg[j];
        }else{
-         utf8_print(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
 -        raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
++        eputz("Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
          return 1;
        }
      }
      if( zDestFile==0 ){
-       utf8_print(stderr, "missing FILENAME argument on .backup\n");
 -      raw_printf(stderr, "missing FILENAME argument on .backup\n");
++      eputz("missing FILENAME argument on .backup\n");
        return 1;
      }
      if( zDb==0 ) zDb = "main";
      rc = sqlite3_open_v2(zDestFile, &pDest,
                    SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
      if( rc!=SQLITE_OK ){
--      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
++      eputf("Error: cannot open \"%s\"\n", zDestFile);
        close_db(pDest);
        return 1;
      }
      open_db(p, 0);
      pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
      if( pBackup==0 ){
--      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
++      eputf("Error: %s\n", sqlite3_errmsg(pDest));
        close_db(pDest);
        return 1;
      }
      if( rc==SQLITE_DONE ){
        rc = 0;
      }else{
--      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
++      eputf("Error: %s\n", sqlite3_errmsg(pDest));
        rc = 1;
      }
      close_db(pDest);
      if( nArg==2 ){
        bail_on_error = booleanValue(azArg[1]);
      }else{
-       utf8_print(stderr, "Usage: .bail on|off\n");
 -      raw_printf(stderr, "Usage: .bail on|off\n");
++      eputz("Usage: .bail on|off\n");
        rc = 1;
      }
    }else
          setTextMode(p->out, 1);
        }
      }else{
-       utf8_print(stderr, "The \".binary\" command is deprecated."
-                          " Use \".crnl\" instead.\n"
-                          "Usage: .binary on|off\n");
 -      raw_printf(stderr, "The \".binary\" command is deprecated."
 -                         " Use \".crnl\" instead.\n");
 -      raw_printf(stderr, "Usage: .binary on|off\n");
++      eputz("The \".binary\" command is deprecated. Use \".crnl\" instead.\n"
++            "Usage: .binary on|off\n");
        rc = 1;
      }
    }else
        rc = chdir(azArg[1]);
  #endif
        if( rc ){
--        utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
++        eputf("Cannot change to directory \"%s\"\n", azArg[1]);
          rc = 1;
        }
      }else{
-       utf8_print(stderr, "Usage: .cd DIRECTORY\n");
 -      raw_printf(stderr, "Usage: .cd DIRECTORY\n");
++      eputz("Usage: .cd DIRECTORY\n");
        rc = 1;
      }
    }else
      if( nArg==2 ){
        setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
      }else{
-       utf8_print(stderr, "Usage: .changes on|off\n");
 -      raw_printf(stderr, "Usage: .changes on|off\n");
++      eputz("Usage: .changes on|off\n");
        rc = 1;
      }
    }else
      char *zRes = 0;
      output_reset(p);
      if( nArg!=2 ){
-       utf8_print(stderr, "Usage: .check GLOB-PATTERN\n");
 -      raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
++      eputz("Usage: .check GLOB-PATTERN\n");
        rc = 2;
      }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
        rc = 2;
      }else if( testcase_glob(azArg[1],zRes)==0 ){
--      utf8_printf(stderr,
--                 "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
--                 p->zTestcase, azArg[1], zRes);
++      eputf("testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
++            p->zTestcase, azArg[1], zRes);
        rc = 1;
      }else{
--      utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
++      oputf("testcase-%s ok\n", p->zTestcase);
        p->nCheck++;
      }
      sqlite3_free(zRes);
      if( nArg==2 ){
        tryToClone(p, azArg[1]);
      }else{
-       utf8_print(stderr, "Usage: .clone FILENAME\n");
 -      raw_printf(stderr, "Usage: .clone FILENAME\n");
++      eputz("Usage: .clone FILENAME\n");
        rc = 1;
      }
    }else
            zFile = "(temporary-file)";
          }
          if( p->pAuxDb == &p->aAuxDb[i] ){
--          utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
++          sputf(stdout, "ACTIVE %d: %s\n", i, zFile);
          }else if( p->aAuxDb[i].db!=0 ){
--          utf8_printf(stdout, "       %d: %s\n", i, zFile);
++          sputf(stdout, "       %d: %s\n", i, zFile);
          }
        }
      }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
        if( i<0 || i>=ArraySize(p->aAuxDb) ){
          /* No-op */
        }else if( p->pAuxDb == &p->aAuxDb[i] ){
-         utf8_print(stderr, "cannot close the active database connection\n");
 -        raw_printf(stderr, "cannot close the active database connection\n");
++        eputz("cannot close the active database connection\n");
          rc = 1;
        }else if( p->aAuxDb[i].db ){
          session_close_all(p, i);
          p->aAuxDb[i].db = 0;
        }
      }else{
-       utf8_print(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
 -      raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
++      eputz("Usage: .connection [close] [CONNECTION-NUMBER]\n");
        rc = 1;
      }
    }else
        }
      }else{
  #if !defined(_WIN32) && !defined(WIN32)
-       utf8_print(stderr, "The \".crnl\" is a no-op on non-Windows machines.\n");
 -      raw_printf(stderr, "The \".crnl\" is a no-op on non-Windows machines.\n");
++      eputz("The \".crnl\" is a no-op on non-Windows machines.\n");
  #endif
-       utf8_print(stderr, "Usage: .crnl on|off\n");
 -      raw_printf(stderr, "Usage: .crnl on|off\n");
++      eputz("Usage: .crnl on|off\n");
        rc = 1;
      }
    }else
      open_db(p, 0);
      rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
      if( rc ){
--      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
++      eputf("Error: %s\n", sqlite3_errmsg(p->db));
        rc = 1;
      }else{
        while( sqlite3_step(pStmt)==SQLITE_ROW ){
        int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
        int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
        const char *z = azName[i*2+1];
--      utf8_printf(p->out, "%s: %s %s%s\n",
--         azName[i*2],
--         z && z[0] ? z : "\"\"",
--         bRdonly ? "r/o" : "r/w",
--         eTxn==SQLITE_TXN_NONE ? "" :
++      sputf(p->out, "%s: %s %s%s\n",
++            azName[i*2], z && z[0] ? z : "\"\"", bRdonly ? "r/o" : "r/w",
++            eTxn==SQLITE_TXN_NONE ? "" :
              eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
        free(azName[i*2]);
        free(azName[i*2+1]);
          sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
        }
        sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
--      utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
++      sputf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
        if( nArg>1 ) break;
      }
      if( nArg>1 && ii==ArraySize(aDbConfig) ){
--      utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
-       utf8_print(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
 -      utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
++      eputf("Error: unknown dbconfig \"%s\"\n", azArg[1]);
++      eputz("Enter \".dbconfig\" with no arguments for a list\n");
      }
    }else
  
          if( z[0]=='-' ) z++;
          if( cli_strcmp(z,"preserve-rowids")==0 ){
  #ifdef SQLITE_OMIT_VIRTUALTABLE
-           utf8_print(stderr, "The --preserve-rowids option is not compatible"
 -          raw_printf(stderr, "The --preserve-rowids option is not compatible"
--                             " with SQLITE_OMIT_VIRTUALTABLE\n");
++          eputz("The --preserve-rowids option is not compatible"
++                " with SQLITE_OMIT_VIRTUALTABLE\n");
            rc = 1;
            sqlite3_free(zLike);
            goto meta_command_exit;
            ShellSetFlag(p, SHFLG_DumpNoSys);
          }else
          {
-           utf8_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
 -          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
++          eputf("Unknown option \"%s\" on \".dump\"\n", azArg[i]);
            rc = 1;
            sqlite3_free(zLike);
            goto meta_command_exit;
        /* When playing back a "dump", the content might appear in an order
        ** which causes immediate foreign key constraints to be violated.
        ** So disable foreign-key constraint enforcement to prevent problems. */
-       utf8_print(p->out, "PRAGMA foreign_keys=OFF;\n");
-       utf8_print(p->out, "BEGIN TRANSACTION;\n");
 -      raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
 -      raw_printf(p->out, "BEGIN TRANSACTION;\n");
++      sputz(p->out, "PRAGMA foreign_keys=OFF;\n");
++      sputz(p->out, "BEGIN TRANSACTION;\n");
      }
      p->writableSchema = 0;
      p->showHeader = 0;
      }
      sqlite3_free(zLike);
      if( p->writableSchema ){
-       utf8_print(p->out, "PRAGMA writable_schema=OFF;\n");
 -      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
++      sputz(p->out, "PRAGMA writable_schema=OFF;\n");
        p->writableSchema = 0;
      }
      sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
      sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
      if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
-       utf8_print(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
 -      raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
++      sputz(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
      }
      p->showHeader = savedShowHeader;
      p->shellFlgs = savedShellFlags;
      if( nArg==2 ){
        setOrClearFlag(p, SHFLG_Echo, azArg[1]);
      }else{
-       utf8_print(stderr, "Usage: .echo on|off\n");
 -      raw_printf(stderr, "Usage: .echo on|off\n");
++      eputz("Usage: .echo on|off\n");
        rc = 1;
      }
    }else
          p->autoEQP = (u8)booleanValue(azArg[1]);
        }
      }else{
-       utf8_print(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
 -      raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
++      eputz("Usage: .eqp off|on|trace|trigger|full\n");
        rc = 1;
      }
    }else
  #ifndef SQLITE_OMIT_VIRTUALTABLE
    if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
      if( p->bSafeMode ){
-       utf8_printf(stderr,
 -      raw_printf(stderr,
--        "Cannot run experimental commands such as \"%s\" in safe mode\n",
--        azArg[0]);
++      eputf("Cannot run experimental commands such as \"%s\" in safe mode\n",
++            azArg[0]);
        rc = 1;
      }else{
        open_db(p, 0);
  
      /* --help lists all file-controls */
      if( cli_strcmp(zCmd,"help")==0 ){
-       utf8_print(p->out, "Available file-controls:\n");
 -      utf8_printf(p->out, "Available file-controls:\n");
++      sputz(p->out, "Available file-controls:\n");
        for(i=0; i<ArraySize(aCtrl); i++){
--        utf8_printf(p->out, "  .filectrl %s %s\n",
--                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
++        sputf(p->out, "  .filectrl %s %s\n",
++              aCtrl[i].zCtrlName, aCtrl[i].zUsage);
        }
        rc = 1;
        goto meta_command_exit;
            filectrl = aCtrl[i].ctrlCode;
            iCtrl = i;
          }else{
--          utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
--                              "Use \".filectrl --help\" for help\n", zCmd);
++          eputf("Error: ambiguous file-control: \"%s\"\n"
++                "Use \".filectrl --help\" for help\n", zCmd);
            rc = 1;
            goto meta_command_exit;
          }
        }
      }
      if( filectrl<0 ){
--      utf8_printf(stderr,"Error: unknown file-control: %s\n"
--                         "Use \".filectrl --help\" for help\n", zCmd);
++      eputf("Error: unknown file-control: %s\n"
++            "Use \".filectrl --help\" for help\n", zCmd);
      }else{
        switch(filectrl){
          case SQLITE_FCNTL_SIZE_LIMIT: {
            if( nArg!=2 ) break;
            sqlite3_file_control(p->db, zSchema, filectrl, &z);
            if( z ){
--            utf8_printf(p->out, "%s\n", z);
++            sputf(p->out, "%s\n", z);
              sqlite3_free(z);
            }
            isOk = 2;
            }
            x = -1;
            sqlite3_file_control(p->db, zSchema, filectrl, &x);
--          utf8_printf(p->out,"%d\n", x);
++          sputf(p->out,"%d\n", x);
            isOk = 2;
            break;
          }
        }
      }
      if( isOk==0 && iCtrl>=0 ){
--      utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
++      sputf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
        rc = 1;
      }else if( isOk==1 ){
        char zBuf[100];
        sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
-       utf8_printf(p->out, "%s\n", zBuf);
 -      raw_printf(p->out, "%s\n", zBuf);
++      sputf(p->out, "%s\n", zBuf);
      }
    }else
  
        nArg = 1;
      }
      if( nArg!=1 ){
-       utf8_print(stderr, "Usage: .fullschema ?--indent?\n");
 -      raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
++      eputz("Usage: .fullschema ?--indent?\n");
        rc = 1;
        goto meta_command_exit;
      }
        }
      }
      if( doStats==0 ){
-       utf8_print(p->out, "/* No STAT tables available */\n");
 -      raw_printf(p->out, "/* No STAT tables available */\n");
++      sputz(p->out, "/* No STAT tables available */\n");
      }else{
-       utf8_print(p->out, "ANALYZE sqlite_schema;\n");
 -      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
++      sputz(p->out, "ANALYZE sqlite_schema;\n");
        data.cMode = data.mode = MODE_Insert;
        data.zDestTable = "sqlite_stat1";
        shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
        data.zDestTable = "sqlite_stat4";
        shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
-       utf8_print(p->out, "ANALYZE sqlite_schema;\n");
 -      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
++      sputz(p->out, "ANALYZE sqlite_schema;\n");
      }
    }else
  
        p->showHeader = booleanValue(azArg[1]);
        p->shellFlgs |= SHFLG_HeaderSet;
      }else{
-       utf8_print(stderr, "Usage: .headers on|off\n");
 -      raw_printf(stderr, "Usage: .headers on|off\n");
++      eputz("Usage: .headers on|off\n");
        rc = 1;
      }
    }else
      if( nArg>=2 ){
        n = showHelp(p->out, azArg[1]);
        if( n==0 ){
--        utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
++        sputf(p->out, "Nothing matches '%s'\n", azArg[1]);
        }
      }else{
        showHelp(p->out, 0);
          }else if( zTable==0 ){
            zTable = z;
          }else{
--          utf8_printf(p->out, "ERROR: extra argument: \"%s\".  Usage:\n", z);
++          sputf(p->out, "ERROR: extra argument: \"%s\".  Usage:\n", z);
            showHelp(p->out, "import");
            goto meta_command_exit;
          }
          xRead = csv_read_one_field;
          useOutputMode = 0;
        }else{
--        utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
++        sputf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
          showHelp(p->out, "import");
          goto meta_command_exit;
        }
      }
      if( zTable==0 ){
--      utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
--                  zFile==0 ? "FILE" : "TABLE");
++      sputf(p->out, "ERROR: missing %s argument. Usage:\n",
++            zFile==0 ? "FILE" : "TABLE");
        showHelp(p->out, "import");
        goto meta_command_exit;
      }
        ** the column and row separator characters from the output mode. */
        nSep = strlen30(p->colSeparator);
        if( nSep==0 ){
-         utf8_print(stderr,
 -        raw_printf(stderr,
--                   "Error: non-null column separator required for import\n");
++        eputz("Error: non-null column separator required for import\n");
          goto meta_command_exit;
        }
        if( nSep>1 ){
-         utf8_print(stderr,
 -        raw_printf(stderr,
--              "Error: multi-character column separators not allowed"
++        eputz("Error: multi-character column separators not allowed"
                " for import\n");
          goto meta_command_exit;
        }
        nSep = strlen30(p->rowSeparator);
        if( nSep==0 ){
-         utf8_print(stderr,
 -        raw_printf(stderr,
--            "Error: non-null row separator required for import\n");
++        eputz("Error: non-null row separator required for import\n");
          goto meta_command_exit;
        }
        if( nSep==2 && p->mode==MODE_Csv
          nSep = strlen30(p->rowSeparator);
        }
        if( nSep>1 ){
-         utf8_print(stderr, "Error: multi-character row separators not allowed"
 -        raw_printf(stderr, "Error: multi-character row separators not allowed"
--                           " for import\n");
++        eputz("Error: multi-character row separators not allowed"
++              " for import\n");
          goto meta_command_exit;
        }
        sCtx.cColSep = (u8)p->colSeparator[0];
      sCtx.nLine = 1;
      if( sCtx.zFile[0]=='|' ){
  #ifdef SQLITE_OMIT_POPEN
-       utf8_print(stderr, "Error: pipes are not supported in this OS\n");
 -      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
++      eputz("Error: pipes are not supported in this OS\n");
        goto meta_command_exit;
  #else
        sCtx.in = popen(sCtx.zFile+1, "r");
        sCtx.xCloser = fclose;
      }
      if( sCtx.in==0 ){
--      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
++      eputf("Error: cannot open \"%s\"\n", zFile);
        goto meta_command_exit;
      }
      if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
        char zSep[2];
        zSep[1] = 0;
        zSep[0] = sCtx.cColSep;
-       utf8_print(p->out, "Column separator ");
 -      utf8_printf(p->out, "Column separator ");
++      sputz(p->out, "Column separator ");
        output_c_string(p->out, zSep);
-       utf8_print(p->out, ", row separator ");
 -      utf8_printf(p->out, ", row separator ");
++      sputz(p->out, ", row separator ");
        zSep[0] = sCtx.cRowSep;
        output_c_string(p->out, zSep);
-       utf8_print(p->out, "\n");
 -      utf8_printf(p->out, "\n");
++      sputz(p->out, "\n");
      }
      sCtx.z = sqlite3_malloc64(120);
      if( sCtx.z==0 ){
        }
        zColDefs = zAutoColumn(0, &dbCols, &zRenames);
        if( zRenames!=0 ){
--        utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
--                    "Columns renamed during .import %s due to duplicates:\n"
--                    "%s\n", sCtx.zFile, zRenames);
++        sputf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
++              "Columns renamed during .import %s due to duplicates:\n"
++              "%s\n", sCtx.zFile, zRenames);
          sqlite3_free(zRenames);
        }
        assert(dbCols==0);
        if( zColDefs==0 ){
--        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
++        eputf("%s: empty file\n", sCtx.zFile);
        import_fail:
          sqlite3_free(zCreate);
          sqlite3_free(zSql);
        }
        zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
        if( eVerbose>=1 ){
--        utf8_printf(p->out, "%s\n", zCreate);
++        sputf(p->out, "%s\n", zCreate);
        }
        rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
        if( rc ){
--        utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
++        eputf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
          goto import_fail;
        }
        sqlite3_free(zCreate);
      }
      if( rc ){
        if (pStmt) sqlite3_finalize(pStmt);
--      utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
++      eputf("Error: %s\n", sqlite3_errmsg(p->db));
        goto import_fail;
      }
      sqlite3_free(zSql);
      zSql[j++] = ')';
      zSql[j] = 0;
      if( eVerbose>=2 ){
--      utf8_printf(p->out, "Insert using: %s\n", zSql);
++      sputf(p->out, "Insert using: %s\n", zSql);
      }
      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
      if( rc ){
--      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
++      eputf("Error: %s\n", sqlite3_errmsg(p->db));
        if (pStmt) sqlite3_finalize(pStmt);
        goto import_fail;
      }
          }
          sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
          if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
--          utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
--                          "filling the rest with NULL\n",
--                          sCtx.zFile, startLine, nCol, i+1);
++          eputf("%s:%d: expected %d columns but found %d"
++                " - filling the rest with NULL\n",
++                sCtx.zFile, startLine, nCol, i+1);
            i += 2;
            while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
          }
            xRead(&sCtx);
            i++;
          }while( sCtx.cTerm==sCtx.cColSep );
--        utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
--                        "extras ignored\n",
--                        sCtx.zFile, startLine, nCol, i);
++        eputf("%s:%d: expected %d columns but found %d - extras ignored\n",
++              sCtx.zFile, startLine, nCol, i);
        }
        if( i>=nCol ){
          sqlite3_step(pStmt);
          rc = sqlite3_reset(pStmt);
          if( rc!=SQLITE_OK ){
--          utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
--                      startLine, sqlite3_errmsg(p->db));
++          eputf("%s:%d: INSERT failed: %s\n",
++                sCtx.zFile, startLine, sqlite3_errmsg(p->db));
            sCtx.nErr++;
          }else{
            sCtx.nRow++;
      sqlite3_finalize(pStmt);
      if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
      if( eVerbose>0 ){
--      utf8_printf(p->out,
--          "Added %d rows with %d errors using %d lines of input\n",
--          sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
++      sputf(p->out,
++            "Added %d rows with %d errors using %d lines of input\n",
++            sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
      }
    }else
  #endif /* !defined(SQLITE_SHELL_FIDDLE) */
      int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
      int i;
      if( !ShellHasFlag(p,SHFLG_TestingMode) ){
--      utf8_printf(stderr, ".%s unavailable without --unsafe-testing\n",
--                  "imposter");
++      eputf(".%s unavailable without --unsafe-testing\n",
++            "imposter");
        rc = 1;
        goto meta_command_exit;
      }
      if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
-       utf8_print(stderr, "Usage: .imposter INDEX IMPOSTER\n"
 -      utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
--                          "       .imposter off\n");
++      eputz("Usage: .imposter INDEX IMPOSTER\n"
++            "       .imposter off\n");
        /* Also allowed, but not documented:
        **
        **    .imposter TABLE IMPOSTER
      }
      sqlite3_finalize(pStmt);
      if( i==0 || tnum==0 ){
--      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
++      eputf("no such index: \"%s\"\n", azArg[1]);
        rc = 1;
        sqlite3_free(zCollist);
        goto meta_command_exit;
        rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
        sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
        if( rc ){
--        utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
++        eputf("Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
        }else{
--        utf8_printf(stdout, "%s;\n", zSql);
-         utf8_printf(stdout,
 -        raw_printf(stdout,
--          "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
--          azArg[1], isWO ? "table" : "index"
--        );
++        sputf(stdout, "%s;\n", zSql);
++        sputf(stdout, "WARNING: writing to an imposter table will corrupt"
++              " the \"%s\" %s!\n", azArg[1], isWO ? "table" : "index");
        }
      }else{
-       utf8_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
 -      raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
++      eputf("SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
        rc = 1;
      }
      sqlite3_free(zSql);
      }else{
        iotrace = fopen(azArg[1], "w");
        if( iotrace==0 ){
--        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
++        eputf("Error: cannot open \"%s\"\n", azArg[1]);
          sqlite3IoTrace = 0;
          rc = 1;
        }else{
      open_db(p, 0);
      if( nArg==1 ){
        for(i=0; i<ArraySize(aLimit); i++){
--        printf("%20s %d\n", aLimit[i].zLimitName,
--               sqlite3_limit(p->db, aLimit[i].limitCode, -1));
++        sputf(stdout, "%20s %d\n", aLimit[i].zLimitName,
++              sqlite3_limit(p->db, aLimit[i].limitCode, -1));
        }
      }else if( nArg>3 ){
-       utf8_print(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
 -      raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
++      eputz("Usage: .limit NAME ?NEW-VALUE?\n");
        rc = 1;
        goto meta_command_exit;
      }else{
            if( iLimit<0 ){
              iLimit = i;
            }else{
--            utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
++            eputf("ambiguous limit: \"%s\"\n", azArg[1]);
              rc = 1;
              goto meta_command_exit;
            }
          }
        }
        if( iLimit<0 ){
--        utf8_printf(stderr, "unknown limit: \"%s\"\n"
--                        "enter \".limits\" with no arguments for a list.\n",
--                         azArg[1]);
++        eputf("unknown limit: \"%s\"\n"
++              "enter \".limits\" with no arguments for a list.\n",
++              azArg[1]);
          rc = 1;
          goto meta_command_exit;
        }
          sqlite3_limit(p->db, aLimit[iLimit].limitCode,
                        (int)integerValue(azArg[2]));
        }
--      printf("%20s %d\n", aLimit[iLimit].zLimitName,
--             sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
++      sputf(stdout, "%20s %d\n", aLimit[iLimit].zLimitName,
++            sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
      }
    }else
  
      failIfSafeMode(p, "cannot run .load in safe mode");
      if( nArg<2 || azArg[1][0]==0 ){
        /* Must have a non-empty FILE. (Will not load self.) */
-       utf8_print(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
 -      raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
++      eputz("Usage: .load FILE ?ENTRYPOINT?\n");
        rc = 1;
        goto meta_command_exit;
      }
      open_db(p, 0);
      rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
      if( rc!=SQLITE_OK ){
--      utf8_printf(stderr, "Error: %s\n", zErrMsg);
++      eputf("Error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        rc = 1;
      }
  
    if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
      if( nArg!=2 ){
-       utf8_print(stderr, "Usage: .log FILENAME\n");
 -      raw_printf(stderr, "Usage: .log FILENAME\n");
++      eputz("Usage: .log FILENAME\n");
        rc = 1;
      }else{
        const char *zFile = azArg[1];
         && cli_strcmp(zFile,"on")!=0
         && cli_strcmp(zFile,"off")!=0
        ){
-         utf8_print(stdout, "cannot set .log to anything other "
 -        raw_printf(stdout, "cannot set .log to anything other "
--                   "than \"on\" or \"off\"\n");
++        sputf(stdout, "cannot set .log to anything other"
++              " than \"on\" or \"off\"\n");
          zFile = "off";
        }
        output_file_close(p->pLog);
        }else if( zTabname==0 ){
          zTabname = z;
        }else if( z[0]=='-' ){
--        utf8_printf(stderr, "unknown option: %s\n", z);
-         utf8_print(stderr,  "options:\n"
 -        utf8_printf(stderr, "options:\n"
--                            "  --noquote\n"
--                            "  --quote\n"
--                            "  --wordwrap on/off\n"
--                            "  --wrap N\n"
--                            "  --ww\n");
++        eputf("unknown option: %s\n", z);
++        eputz("options:\n"
++              "  --noquote\n"
++              "  --quote\n"
++              "  --wordwrap on/off\n"
++              "  --wrap N\n"
++              "  --ww\n");
          rc = 1;
          goto meta_command_exit;
        }else{
--        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
++        eputf("extra argument: \"%s\"\n", z);
          rc = 1;
          goto meta_command_exit;
        }
        if( p->mode==MODE_Column
         || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
        ){
-         utf8_printf
 -        raw_printf
--          (p->out,
--           "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
--           modeDescr[p->mode], p->cmOpts.iWrap,
--           p->cmOpts.bWordWrap ? "on" : "off",
--           p->cmOpts.bQuote ? "" : "no");
++        sputf(p->out,
++              "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
++              modeDescr[p->mode], p->cmOpts.iWrap,
++              p->cmOpts.bWordWrap ? "on" : "off",
++              p->cmOpts.bQuote ? "" : "no");
        }else{
-         utf8_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
 -        raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
++        sputf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
        }
        zMode = modeDescr[p->mode];
      }
      }else if( cli_strncmp(zMode,"json",n2)==0 ){
        p->mode = MODE_Json;
      }else{
-       utf8_print(stderr, "Error: mode should be one of: "
 -      raw_printf(stderr, "Error: mode should be one of: "
--         "ascii box column csv html insert json line list markdown "
--         "qbox quote table tabs tcl\n");
++      eputz("Error: mode should be one of: "
++            "ascii box column csv html insert json line list markdown "
++            "qbox quote table tabs tcl\n");
        rc = 1;
      }
      p->cMode = p->mode;
  #ifndef SQLITE_SHELL_FIDDLE
    if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
      if( nArg!=2 ){
-       utf8_print(stderr, "Usage: .nonce NONCE\n");
 -      raw_printf(stderr, "Usage: .nonce NONCE\n");
++      eputz("Usage: .nonce NONCE\n");
        rc = 1;
      }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
-       utf8_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
 -      raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
--                 p->lineno, azArg[1]);
++      eputf("line %d: incorrect nonce: \"%s\"\n",
++            p->lineno, azArg[1]);
        exit(1);
      }else{
        p->bSafeMode = 0;
        sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
                         "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
      }else{
-       utf8_print(stderr, "Usage: .nullvalue STRING\n");
 -      raw_printf(stderr, "Usage: .nullvalue STRING\n");
++      eputz("Usage: .nullvalue STRING\n");
        rc = 1;
      }
    }else
        }else
  #endif /* !SQLITE_SHELL_FIDDLE */
        if( z[0]=='-' ){
--        utf8_printf(stderr, "unknown option: %s\n", z);
++        eputf("unknown option: %s\n", z);
          rc = 1;
          goto meta_command_exit;
        }else if( zFN ){
--        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
++        eputf("extra argument: \"%s\"\n", z);
          rc = 1;
          goto meta_command_exit;
        }else{
        p->pAuxDb->zDbFilename = zNewFilename;
        open_db(p, OPEN_DB_KEEPALIVE);
        if( p->db==0 ){
--        utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
++        eputf("Error: cannot open '%s'\n", zNewFilename);
          sqlite3_free(zNewFilename);
        }else{
          p->pAuxDb->zFreeOnClose = zNewFilename;
          }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
            eMode = 'e';  /* text editor */
          }else{
--          utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n",
--                      azArg[i]);
++          sputf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", azArg[i]);
            showHelp(p->out, azArg[0]);
            rc = 1;
            goto meta_command_exit;
            break;
          }
        }else{
--        utf8_printf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n",
--                    azArg[i]);
++        sputf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n", azArg[i]);
          showHelp(p->out, azArg[0]);
          rc = 1;
          sqlite3_free(zFile);
      shell_check_oom(zFile);
      if( zFile[0]=='|' ){
  #ifdef SQLITE_OMIT_POPEN
-       utf8_print(stderr, "Error: pipes are not supported in this OS\n");
 -      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
++      eputz("Error: pipes are not supported in this OS\n");
        rc = 1;
        p->out = stdout;
  #else
        p->out = popen(zFile + 1, "w");
        if( p->out==0 ){
--        utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
++        eputf("Error: cannot open pipe \"%s\"\n", zFile + 1);
          p->out = stdout;
          rc = 1;
        }else{
        p->out = output_file_open(zFile, bTxtMode);
        if( p->out==0 ){
          if( cli_strcmp(zFile,"off")!=0 ){
--          utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
++          eputf("Error: cannot write to \"%s\"\n", zFile);
          }
          p->out = stdout;
          rc = 1;
               "SELECT key, quote(value) "
               "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
          while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
--          utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
--                      sqlite3_column_text(pStmt,1));
++          sputf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
++                sqlite3_column_text(pStmt,1));
          }
          sqlite3_finalize(pStmt);
        }
          rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
          sqlite3_free(zSql);
          if( rx!=SQLITE_OK ){
--          utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
++          sputf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
            sqlite3_finalize(pStmt);
            pStmt = 0;
            rc = 1;
    if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
      int i;
      for(i=1; i<nArg; i++){
-       if( i>1 ) utf8_print(p->out, " ");
-       utf8_print(p->out, azArg[i]);
 -      if( i>1 ) raw_printf(p->out, " ");
 -      utf8_printf(p->out, "%s", azArg[i]);
++      if( i>1 ) sputz(p->out, " ");
++      sputz(p->out, azArg[i]);
      }
-     utf8_print(p->out, "\n");
 -    raw_printf(p->out, "\n");
++    sputz(p->out, "\n");
    }else
  
  #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
          }
          if( cli_strcmp(z,"limit")==0 ){
            if( i+1>=nArg ){
-             utf8_print(stderr, "Error: missing argument on --limit\n");
 -            utf8_printf(stderr, "Error: missing argument on --limit\n");
++            eputz("Error: missing argument on --limit\n");
              rc = 1;
              goto meta_command_exit;
            }else{
            }
            continue;
          }
--        utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
++        eputf("Error: unknown option: \"%s\"\n", azArg[i]);
          rc = 1;
          goto meta_command_exit;
        }else{
      int savedLineno = p->lineno;
      failIfSafeMode(p, "cannot run .read in safe mode");
      if( nArg!=2 ){
-       utf8_print(stderr, "Usage: .read FILE\n");
 -      raw_printf(stderr, "Usage: .read FILE\n");
++      eputz("Usage: .read FILE\n");
        rc = 1;
        goto meta_command_exit;
      }
      if( azArg[1][0]=='|' ){
  #ifdef SQLITE_OMIT_POPEN
-       utf8_print(stderr, "Error: pipes are not supported in this OS\n");
 -      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
++      eputz("Error: pipes are not supported in this OS\n");
        rc = 1;
        p->out = stdout;
  #else
        p->in = popen(azArg[1]+1, "r");
        if( p->in==0 ){
--        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
++        eputf("Error: cannot open \"%s\"\n", azArg[1]);
          rc = 1;
        }else{
          rc = process_input(p);
        }
  #endif
      }else if( (p->in = openChrSource(azArg[1]))==0 ){
--      utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
++      eputf("Error: cannot open \"%s\"\n", azArg[1]);
        rc = 1;
      }else{
        rc = process_input(p);
        zSrcFile = azArg[2];
        zDb = azArg[1];
      }else{
-       utf8_print(stderr, "Usage: .restore ?DB? FILE\n");
 -      raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
++      eputz("Usage: .restore ?DB? FILE\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_open(zSrcFile, &pSrc);
      if( rc!=SQLITE_OK ){
--      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
++      eputf("Error: cannot open \"%s\"\n", zSrcFile);
        close_db(pSrc);
        return 1;
      }
      open_db(p, 0);
      pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
      if( pBackup==0 ){
--      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
++      eputf("Error: %s\n", sqlite3_errmsg(p->db));
        close_db(pSrc);
        return 1;
      }
      if( rc==SQLITE_DONE ){
        rc = 0;
      }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
-       utf8_print(stderr, "Error: source database is busy\n");
 -      raw_printf(stderr, "Error: source database is busy\n");
++      eputz("Error: source database is busy\n");
        rc = 1;
      }else{
--      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
++      eputf("Error: %s\n", sqlite3_errmsg(p->db));
        rc = 1;
      }
      close_db(pSrc);
            p->db, SQLITE_DBCONFIG_STMT_SCANSTATUS, p->scanstatsOn, (int*)0
        );
  #if !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-       utf8_print(stderr, "Warning: .scanstats not available in this build.\n");
 -      raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
++      eputz("Warning: .scanstats not available in this build.\n");
  #elif !defined(SQLITE_ENABLE_BYTECODE_VTAB)
        if( p->scanstatsOn==3 ){
--        raw_printf(stderr, 
--            "Warning: \".scanstats vm\" not available in this build.\n"
--        );
++        eputz("Warning: \".scanstats vm\" not available in this build.\n");
        }
  #endif
      }else{
-       utf8_print(stderr, "Usage: .scanstats on|off|est\n");
 -      raw_printf(stderr, "Usage: .scanstats on|off|est\n");
++      eputz("Usage: .scanstats on|off|est\n");
        rc = 1;
      }
    }else
        }else if( optionMatch(azArg[ii],"nosys") ){
          bNoSystemTabs = 1;
        }else if( azArg[ii][0]=='-' ){
--        utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
++        eputf("Unknown option: \"%s\"\n", azArg[ii]);
          rc = 1;
          goto meta_command_exit;
        }else if( zName==0 ){
          zName = azArg[ii];
        }else{
-         utf8_print(stderr,
 -        raw_printf(stderr,
--                   "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
++        eputz("Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
          rc = 1;
          goto meta_command_exit;
        }
        rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
                                -1, &pStmt, 0);
        if( rc ){
--        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
++        eputf("Error: %s\n", sqlite3_errmsg(p->db));
          sqlite3_finalize(pStmt);
          rc = 1;
          goto meta_command_exit;
        appendText(&sSelect, "sql IS NOT NULL"
                             " ORDER BY snum, rowid", 0);
        if( bDebug ){
--        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
++        sputf(p->out, "SQL: %s;\n", sSelect.z);
        }else{
          rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
        }
        freeText(&sSelect);
      }
      if( zErrMsg ){
--      utf8_printf(stderr,"Error: %s\n", zErrMsg);
++      eputf("Error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        rc = 1;
      }else if( rc != SQLITE_OK ){
-       utf8_print(stderr,"Error: querying schema information\n");
 -      raw_printf(stderr,"Error: querying schema information\n");
++      eputz("Error: querying schema information\n");
        rc = 1;
      }else{
        rc = 0;
        if( nCmd!=2 ) goto session_syntax_error;
        if( pSession->p==0 ){
          session_not_open:
-         utf8_print(stderr, "ERROR: No sessions are open\n");
 -        raw_printf(stderr, "ERROR: No sessions are open\n");
++        eputz("ERROR: No sessions are open\n");
        }else{
          rc = sqlite3session_attach(pSession->p, azCmd[1]);
          if( rc ){
-           utf8_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n",rc);
 -          raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
++          eputf("ERROR: sqlite3session_attach() returns %d\n",rc);
            rc = 0;
          }
        }
        if( pSession->p==0 ) goto session_not_open;
        out = fopen(azCmd[1], "wb");
        if( out==0 ){
--        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
--                    azCmd[1]);
++        eputf("ERROR: cannot open \"%s\" for writing\n",
++              azCmd[1]);
        }else{
          int szChng;
          void *pChng;
            rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
          }
          if( rc ){
--          printf("Error: error code %d\n", rc);
++          sputf(stdout, "Error: error code %d\n", rc);
            rc = 0;
          }
          if( pChng
            && fwrite(pChng, szChng, 1, out)!=1 ){
-           utf8_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
 -          raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
--                  szChng);
++          eputf("ERROR: Failed to write entire %d-byte output\n",
++                szChng);
          }
          sqlite3_free(pChng);
          fclose(out);
        ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
        if( pAuxDb->nSession ){
          ii = sqlite3session_enable(pSession->p, ii);
--        utf8_printf(p->out, "session %s enable flag = %d\n",
--                    pSession->zName, ii);
++        sputf(p->out, "session %s enable flag = %d\n", pSession->zName, ii);
        }
      }else
  
          sqlite3_free(pSession->azFilter);
          nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
          pSession->azFilter = sqlite3_malloc( nByte );
--        if( pSession->azFilter==0 ){
-           utf8_print(stderr, "Error: out or memory\n");
 -          raw_printf(stderr, "Error: out or memory\n");
--          exit(1);
--        }
++        shell_check_oom( pSession->azFilter );
          for(ii=1; ii<nCmd; ii++){
            char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
            shell_check_oom(x);
        ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
        if( pAuxDb->nSession ){
          ii = sqlite3session_indirect(pSession->p, ii);
--        utf8_printf(p->out, "session %s indirect flag = %d\n",
--                    pSession->zName, ii);
++        sputf(p->out, "session %s indirect flag = %d\n", pSession->zName, ii);
        }
      }else
  
        if( nCmd!=1 ) goto session_syntax_error;
        if( pAuxDb->nSession ){
          ii = sqlite3session_isempty(pSession->p);
--        utf8_printf(p->out, "session %s isempty flag = %d\n",
--                    pSession->zName, ii);
++        sputf(p->out, "session %s isempty flag = %d\n", pSession->zName, ii);
        }
      }else
  
      */
      if( cli_strcmp(azCmd[0],"list")==0 ){
        for(i=0; i<pAuxDb->nSession; i++){
--        utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
++        sputf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
        }
      }else
  
        if( zName[0]==0 ) goto session_syntax_error;
        for(i=0; i<pAuxDb->nSession; i++){
          if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
--          utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
++          eputf("Session \"%s\" already exists\n", zName);
            goto meta_command_exit;
          }
        }
        if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
-         utf8_printf(stderr,
 -        raw_printf(stderr,
--                   "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
++        eputf("Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
          goto meta_command_exit;
        }
        pSession = &pAuxDb->aSession[pAuxDb->nSession];
        rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
        if( rc ){
-         utf8_printf(stderr, "Cannot open session: error code=%d\n", rc);
 -        raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
++        eputf("Cannot open session: error code=%d\n", rc);
          rc = 0;
          goto meta_command_exit;
        }
        int i, v;
        for(i=1; i<nArg; i++){
          v = booleanValue(azArg[i]);
--        utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
++        sputf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
        }
      }
      if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
          char zBuf[200];
          v = integerValue(azArg[i]);
          sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
-         utf8_print(p->out, zBuf);
 -        utf8_printf(p->out, "%s", zBuf);
++        sputz(p->out, zBuf);
        }
      }
    }else
          bVerbose++;
        }else
        {
--        utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
--                    azArg[i], azArg[0]);
-         utf8_print(stderr, "Should be one of: --init -v\n");
 -        raw_printf(stderr, "Should be one of: --init -v\n");
++        eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);
++        eputz("Should be one of: --init -v\n");
          rc = 1;
          goto meta_command_exit;
        }
            -1, &pStmt, 0);
        }
        if( rc ){
-         utf8_print(stderr, "Error querying the selftest table\n");
 -        raw_printf(stderr, "Error querying the selftest table\n");
++        eputz("Error querying the selftest table\n");
          rc = 1;
          sqlite3_finalize(pStmt);
          goto meta_command_exit;
          if( zAns==0 ) continue;
          k = 0;
          if( bVerbose>0 ){
--          printf("%d: %s %s\n", tno, zOp, zSql);
++          sputf(stdout, "%d: %s %s\n", tno, zOp, zSql);
          }
          if( cli_strcmp(zOp,"memo")==0 ){
--          utf8_printf(p->out, "%s\n", zSql);
++          sputf(p->out, "%s\n", zSql);
          }else
          if( cli_strcmp(zOp,"run")==0 ){
            char *zErrMsg = 0;
            rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
            nTest++;
            if( bVerbose ){
--            utf8_printf(p->out, "Result: %s\n", str.z);
++            sputf(p->out, "Result: %s\n", str.z);
            }
            if( rc || zErrMsg ){
              nErr++;
              rc = 1;
--            utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
++            sputf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
              sqlite3_free(zErrMsg);
            }else if( cli_strcmp(zAns,str.z)!=0 ){
              nErr++;
              rc = 1;
--            utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
--            utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
++            sputf(p->out, "%d: Expected: [%s]\n", tno, zAns);
++            sputf(p->out, "%d:      Got: [%s]\n", tno, str.z);
            }
--        }else
--        {
--          utf8_printf(stderr,
--            "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
++        }
++        else{
++          eputf("Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
            rc = 1;
            break;
          }
        sqlite3_finalize(pStmt);
      } /* End loop over k */
      freeText(&str);
--    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
++    sputf(p->out, "%d errors out of %d tests\n", nErr, nTest);
    }else
  
    if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
      if( nArg<2 || nArg>3 ){
-       utf8_print(stderr, "Usage: .separator COL ?ROW?\n");
 -      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
++      eputz("Usage: .separator COL ?ROW?\n");
        rc = 1;
      }
      if( nArg>=2 ){
            bDebug = 1;
          }else
          {
--          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
--                      azArg[i], azArg[0]);
++          eputf("Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]);
            showHelp(p->out, azArg[0]);
            rc = 1;
            goto meta_command_exit;
          }
        }else if( zLike ){
-         utf8_print(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
 -        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
++        eputz("Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
          rc = 1;
          goto meta_command_exit;
        }else{
      freeText(&sQuery);
      freeText(&sSql);
      if( bDebug ){
--      utf8_printf(p->out, "%s\n", zSql);
++      sputf(p->out, "%s\n", zSql);
      }else{
        shell_exec(p, zSql, 0);
      }
            "' OR ') as query, tname from tabcols group by tname)"
            , zRevText);
        shell_check_oom(zRevText);
--      if( bDebug ) utf8_printf(p->out, "%s\n", zRevText);
++      if( bDebug ) sputf(p->out, "%s\n", zRevText);
        lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0);
        if( lrc!=SQLITE_OK ){
          /* assert(lrc==SQLITE_NOMEM); // might also be SQLITE_ERROR if the
            const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0);
            sqlite3_stmt *pCheckStmt;
            lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0);
--          if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery);
++          if( bDebug ) sputf(p->out, "%s\n", zGenQuery);
            if( lrc!=SQLITE_OK ){
              rc = 1;
            }else{
                double countIrreversible = sqlite3_column_double(pCheckStmt, 0);
                if( countIrreversible>0 ){
                  int sz = (int)(countIrreversible + 0.5);
--                utf8_printf(stderr,
--                     "Digest includes %d invalidly encoded text field%s.\n",
--                            sz, (sz>1)? "s": "");
++                eputf("Digest includes %d invalidly encoded text field%s.\n",
++                      sz, (sz>1)? "s": "");
                }
              }
              sqlite3_finalize(pCheckStmt);
            sqlite3_finalize(pStmt);
          }
        }
-       if( rc ) utf8_print(stderr, ".sha3sum failed.\n");
 -      if( rc ) utf8_printf(stderr, ".sha3sum failed.\n");
++      if( rc ) eputz(".sha3sum failed.\n");
        sqlite3_free(zRevText);
      }
  #endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */
      int i, x;
      failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
      if( nArg<2 ){
-       utf8_print(stderr, "Usage: .system COMMAND\n");
 -      raw_printf(stderr, "Usage: .system COMMAND\n");
++      eputz("Usage: .system COMMAND\n");
        rc = 1;
        goto meta_command_exit;
      }
        zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                               zCmd, azArg[i]);
      }
 +    consoleRestore();
      x = zCmd!=0 ? system(zCmd) : 1;
 +    consoleRenewSetup();
      sqlite3_free(zCmd);
-     if( x ) utf8_printf(stderr, "System command returns %d\n", x);
 -    if( x ) raw_printf(stderr, "System command returns %d\n", x);
++    if( x ) eputf("System command returns %d\n", x);
    }else
  #endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */
  
      const char *zOut;
      int i;
      if( nArg!=1 ){
-       utf8_print(stderr, "Usage: .show\n");
 -      raw_printf(stderr, "Usage: .show\n");
++      eputz("Usage: .show\n");
        rc = 1;
        goto meta_command_exit;
      }
--    utf8_printf(p->out, "%12.12s: %s\n","echo",
--                azBool[ShellHasFlag(p, SHFLG_Echo)]);
--    utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
--    utf8_printf(p->out, "%12.12s: %s\n","explain",
--         p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
--    utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
++    sputf(p->out, "%12.12s: %s\n","echo",
++          azBool[ShellHasFlag(p, SHFLG_Echo)]);
++    sputf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
++    sputf(p->out, "%12.12s: %s\n","explain",
++          p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
++    sputf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
      if( p->mode==MODE_Column
       || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
      ){
--      utf8_printf
--        (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
--         modeDescr[p->mode], p->cmOpts.iWrap,
--         p->cmOpts.bWordWrap ? "on" : "off",
--         p->cmOpts.bQuote ? "" : "no");
++      sputf(p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
++            modeDescr[p->mode], p->cmOpts.iWrap,
++            p->cmOpts.bWordWrap ? "on" : "off",
++            p->cmOpts.bQuote ? "" : "no");
      }else{
--      utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
--    }
--    utf8_printf(p->out, "%12.12s: ", "nullvalue");
--      output_c_string(p->out, p->nullValue);
-       utf8_print(p->out, "\n");
 -      raw_printf(p->out, "\n");
--    utf8_printf(p->out,"%12.12s: %s\n","output",
--            strlen30(p->outfile) ? p->outfile : "stdout");
--    utf8_printf(p->out,"%12.12s: ", "colseparator");
--      output_c_string(p->out, p->colSeparator);
-       utf8_print(p->out, "\n");
 -      raw_printf(p->out, "\n");
--    utf8_printf(p->out,"%12.12s: ", "rowseparator");
--      output_c_string(p->out, p->rowSeparator);
-       utf8_print(p->out, "\n");
 -      raw_printf(p->out, "\n");
++      sputf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
++    }
++    sputf(p->out, "%12.12s: ", "nullvalue");
++    output_c_string(p->out, p->nullValue);
++    sputz(p->out, "\n");
++    sputf(p->out,"%12.12s: %s\n","output",
++          strlen30(p->outfile) ? p->outfile : "stdout");
++    sputf(p->out,"%12.12s: ", "colseparator");
++     output_c_string(p->out, p->colSeparator);
++     sputz(p->out, "\n");
++    sputf(p->out,"%12.12s: ", "rowseparator");
++     output_c_string(p->out, p->rowSeparator);
++     sputz(p->out, "\n");
      switch( p->statsOn ){
        case 0:  zOut = "off";     break;
        default: zOut = "on";      break;
        case 2:  zOut = "stmt";    break;
        case 3:  zOut = "vmstep";  break;
      }
--    utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
--    utf8_printf(p->out, "%12.12s: ", "width");
++    sputf(p->out, "%12.12s: %s\n","stats", zOut);
++    sputf(p->out, "%12.12s: ", "width");
      for (i=0;i<p->nWidth;i++) {
-       utf8_printf(p->out, "%d ", p->colWidth[i]);
 -      raw_printf(p->out, "%d ", p->colWidth[i]);
++      sputf(p->out, "%d ", p->colWidth[i]);
      }
-     utf8_print(p->out, "\n");
 -    raw_printf(p->out, "\n");
--    utf8_printf(p->out, "%12.12s: %s\n", "filename",
--                p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
++    sputz(p->out, "\n");
++    sputf(p->out, "%12.12s: %s\n", "filename",
++          p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
    }else
  
    if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
      }else if( nArg==1 ){
        display_stats(p->db, p, 0);
      }else{
-       utf8_print(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
 -      raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
++      eputz("Usage: .stats ?on|off|stmt|vmstep?\n");
        rc = 1;
      }
    }else
        /* It is an historical accident that the .indexes command shows an error
        ** when called with the wrong number of arguments whereas the .tables
        ** command does not. */
-       utf8_print(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
 -      raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
++      eputz("Usage: .indexes ?LIKE-PATTERN?\n");
        rc = 1;
        sqlite3_finalize(pStmt);
        goto meta_command_exit;
        for(i=0; i<nPrintRow; i++){
          for(j=i; j<nRow; j+=nPrintRow){
            char *zSp = j<nPrintRow ? "" : "  ";
--          utf8_printf(p->out, "%s%-*s", zSp, maxlen,
--                      azResult[j] ? azResult[j]:"");
++          sputf(p->out, "%s%-*s", zSp, maxlen, azResult[j] ? azResult[j]:"");
          }
-         utf8_print(p->out, "\n");
 -        raw_printf(p->out, "\n");
++        sputz(p->out, "\n");
        }
      }
  
      output_reset(p);
      p->out = output_file_open("testcase-out.txt", 0);
      if( p->out==0 ){
-       utf8_print(stderr, "Error: cannot open 'testcase-out.txt'\n");
 -      raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
++      eputz("Error: cannot open 'testcase-out.txt'\n");
      }
      if( nArg>=2 ){
        sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
  
      /* --help lists all test-controls */
      if( cli_strcmp(zCmd,"help")==0 ){
-       utf8_print(p->out, "Available test-controls:\n");
 -      utf8_printf(p->out, "Available test-controls:\n");
++      sputz(p->out, "Available test-controls:\n");
        for(i=0; i<ArraySize(aCtrl); i++){
          if( aCtrl[i].unSafe && !ShellHasFlag(p,SHFLG_TestingMode) ) continue;
--        utf8_printf(p->out, "  .testctrl %s %s\n",
--                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
++        sputf(p->out, "  .testctrl %s %s\n",
++              aCtrl[i].zCtrlName, aCtrl[i].zUsage);
        }
        rc = 1;
        goto meta_command_exit;
            testctrl = aCtrl[i].ctrlCode;
            iCtrl = i;
          }else{
--          utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
--                              "Use \".testctrl --help\" for help\n", zCmd);
++          eputf("Error: ambiguous test-control: \"%s\"\n"
++                "Use \".testctrl --help\" for help\n", zCmd);
            rc = 1;
            goto meta_command_exit;
          }
        }
      }
      if( testctrl<0 ){
--      utf8_printf(stderr,"Error: unknown test-control: %s\n"
--                         "Use \".testctrl --help\" for help\n", zCmd);
++      eputf("Error: unknown test-control: %s\n"
++            "Use \".testctrl --help\" for help\n", zCmd);
      }else{
        switch(testctrl){
  
              sqlite3 *db;
              if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
                sqlite3_randomness(sizeof(ii),&ii);
--              printf("-- random seed: %d\n", ii);
++              sputf(stdout, "-- random seed: %d\n", ii);
              }
              if( nArg==3 ){
                db = 0;
          case SQLITE_TESTCTRL_SEEK_COUNT: {
            u64 x = 0;
            rc2 = sqlite3_test_control(testctrl, p->db, &x);
--          utf8_printf(p->out, "%llu\n", x);
++          sputf(p->out, "%llu\n", x);
            isOk = 3;
            break;
          }
                int val = 0;
                rc2 = sqlite3_test_control(testctrl, -id, &val);
                if( rc2!=SQLITE_OK ) break;
-               if( id>1 ) utf8_print(p->out, "  ");
 -              if( id>1 ) utf8_printf(p->out, "  ");
--              utf8_printf(p->out, "%d: %d", id, val);
++              if( id>1 ) sputz(p->out, "  ");
++              sputf(p->out, "%d: %d", id, val);
                id++;
              }
-             if( id>1 ) utf8_print(p->out, "\n");
 -            if( id>1 ) utf8_printf(p->out, "\n");
++            if( id>1 ) sputz(p->out, "\n");
              isOk = 3;
            }
            break;
        }
      }
      if( isOk==0 && iCtrl>=0 ){
--      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
++      sputf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
        rc = 1;
      }else if( isOk==1 ){
-       utf8_printf(p->out, "%d\n", rc2);
 -      raw_printf(p->out, "%d\n", rc2);
++      sputf(p->out, "%d\n", rc2);
      }else if( isOk==2 ){
-       utf8_printf(p->out, "0x%08x\n", rc2);
 -      raw_printf(p->out, "0x%08x\n", rc2);
++      sputf(p->out, "0x%08x\n", rc2);
      }
    }else
  #endif /* !defined(SQLITE_UNTESTABLE) */
      if( nArg==2 ){
        enableTimer = booleanValue(azArg[1]);
        if( enableTimer && !HAS_TIMER ){
-         utf8_print(stderr, "Error: timer not available on this system.\n");
 -        raw_printf(stderr, "Error: timer not available on this system.\n");
++        eputz("Error: timer not available on this system.\n");
          enableTimer = 0;
        }
      }else{
-       utf8_print(stderr, "Usage: .timer on|off\n");
 -      raw_printf(stderr, "Usage: .timer on|off\n");
++      eputz("Usage: .timer on|off\n");
        rc = 1;
      }
    }else
            mType |= SQLITE_TRACE_CLOSE;
          }
          else {
-           utf8_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
 -          raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
++          eputf("Unknown option \"%s\" on \".trace\"\n", z);
            rc = 1;
            goto meta_command_exit;
          }
      int lenOpt;
      char *zOpt;
      if( nArg<2 ){
-       utf8_print(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
 -      raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
++      eputz("Usage: .unmodule [--allexcept] NAME ...\n");
        rc = 1;
        goto meta_command_exit;
      }
  #if SQLITE_USER_AUTHENTICATION
    if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
      if( nArg<2 ){
-       utf8_print(stderr, "Usage: .user SUBCOMMAND ...\n");
 -      raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
++      eputz("Usage: .user SUBCOMMAND ...\n");
        rc = 1;
        goto meta_command_exit;
      }
      open_db(p, 0);
      if( cli_strcmp(azArg[1],"login")==0 ){
        if( nArg!=4 ){
-         utf8_print(stderr, "Usage: .user login USER PASSWORD\n");
 -        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
++        eputz("Usage: .user login USER PASSWORD\n");
          rc = 1;
          goto meta_command_exit;
        }
        rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                       strlen30(azArg[3]));
        if( rc ){
--        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
++        eputf("Authentication failed for user %s\n", azArg[2]);
          rc = 1;
        }
      }else if( cli_strcmp(azArg[1],"add")==0 ){
        if( nArg!=5 ){
-         utf8_print(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
 -        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
++        eputz("Usage: .user add USER PASSWORD ISADMIN\n");
          rc = 1;
          goto meta_command_exit;
        }
        rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                              booleanValue(azArg[4]));
        if( rc ){
-         utf8_printf(stderr, "User-Add failed: %d\n", rc);
 -        raw_printf(stderr, "User-Add failed: %d\n", rc);
++        eputf("User-Add failed: %d\n", rc);
          rc = 1;
        }
      }else if( cli_strcmp(azArg[1],"edit")==0 ){
        if( nArg!=5 ){
-         utf8_print(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
 -        raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
++        eputz("Usage: .user edit USER PASSWORD ISADMIN\n");
          rc = 1;
          goto meta_command_exit;
        }
        rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                                booleanValue(azArg[4]));
        if( rc ){
-         utf8_printf(stderr, "User-Edit failed: %d\n", rc);
 -        raw_printf(stderr, "User-Edit failed: %d\n", rc);
++        eputf("User-Edit failed: %d\n", rc);
          rc = 1;
        }
      }else if( cli_strcmp(azArg[1],"delete")==0 ){
        if( nArg!=3 ){
-         utf8_print(stderr, "Usage: .user delete USER\n");
 -        raw_printf(stderr, "Usage: .user delete USER\n");
++        eputz("Usage: .user delete USER\n");
          rc = 1;
          goto meta_command_exit;
        }
        rc = sqlite3_user_delete(p->db, azArg[2]);
        if( rc ){
-         utf8_printf(stderr, "User-Delete failed: %d\n", rc);
 -        raw_printf(stderr, "User-Delete failed: %d\n", rc);
++        eputf("User-Delete failed: %d\n", rc);
          rc = 1;
        }
      }else{
-       utf8_print(stderr, "Usage: .user login|add|edit|delete ...\n");
 -      raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
++      eputz("Usage: .user login|add|edit|delete ...\n");
        rc = 1;
        goto meta_command_exit;
      }
  
    if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
      char *zPtrSz = sizeof(void*)==8 ? "64-bit" : "32-bit";
--    utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
--        sqlite3_libversion(), sqlite3_sourceid());
++    sputf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
++          sqlite3_libversion(), sqlite3_sourceid());
  #if SQLITE_HAVE_ZLIB
--    utf8_printf(p->out, "zlib version %s\n", zlibVersion());
++    sputf(p->out, "zlib version %s\n", zlibVersion());
  #endif
  #define CTIMEOPT_VAL_(opt) #opt
  #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
  #if defined(__clang__) && defined(__clang_major__)
--    utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
--                    CTIMEOPT_VAL(__clang_minor__) "."
--                    CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
++    sputf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
++          CTIMEOPT_VAL(__clang_minor__) "."
++          CTIMEOPT_VAL(__clang_patchlevel__) " (%s)\n", zPtrSz);
  #elif defined(_MSC_VER)
--    utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
++    sputf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) " (%s)\n", zPtrSz);
  #elif defined(__GNUC__) && defined(__VERSION__)
--    utf8_printf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz);
++    sputf(p->out, "gcc-" __VERSION__ " (%s)\n", zPtrSz);
  #endif
    }else
  
      if( p->db ){
        sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
        if( pVfs ){
--        utf8_printf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
-         utf8_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
-         utf8_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
-         utf8_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
 -        raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
 -        raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
 -        raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
++        sputf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
++        sputf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
++        sputf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
++        sputf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
        }
      }
    }else
        sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
      }
      for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
--      utf8_printf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
--           pVfs==pCurrent ? "  <--- CURRENT" : "");
-       utf8_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
-       utf8_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
-       utf8_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
 -      raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
 -      raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
 -      raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
++      sputf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
++            pVfs==pCurrent ? "  <--- CURRENT" : "");
++      sputf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
++      sputf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
++      sputf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
        if( pVfs->pNext ){
-         utf8_print(p->out, "-----------------------------------\n");
 -        raw_printf(p->out, "-----------------------------------\n");
++        sputz(p->out, "-----------------------------------\n");
        }
      }
    }else
      if( p->db ){
        sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
        if( zVfsName ){
--        utf8_printf(p->out, "%s\n", zVfsName);
++        sputf(p->out, "%s\n", zVfsName);
          sqlite3_free(zVfsName);
        }
      }
    }else
  
    {
--    utf8_printf(stderr, "Error: unknown command or invalid arguments: "
--      " \"%s\". Enter \".help\" for help\n", azArg[0]);
++    eputf("Error: unknown command or invalid arguments: "
++          " \"%s\". Enter \".help\" for help\n", azArg[0]);
      rc = 1;
    }
  
@@@ -11407,7 -11666,7 +11358,7 @@@ static int runOneSqlLine(ShellState *p
      }else{
        sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
      }
--    utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
++    eputf("%s %s\n", zPrefix, zErrorTail);
      sqlite3_free(zErrMsg);
      zErrMsg = 0;
      return 1;
      sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
              "changes: %lld   total_changes: %lld",
              sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
-     utf8_printf(p->out, "%s\n", zLineBuf);
 -    raw_printf(p->out, "%s\n", zLineBuf);
++    sputf(p->out, "%s\n", zLineBuf);
    }
    return 0;
  }
  
  static void echo_group_input(ShellState *p, const char *zDo){
--  if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
++  if( ShellHasFlag(p, SHFLG_Echo) ) sputf(p->out, "%s\n", zDo);
  }
  
  #ifdef SQLITE_SHELL_FIDDLE
@@@ -11480,8 -11739,8 +11431,8 @@@ static int process_input(ShellState *p)
  
    if( p->inputNesting==MAX_INPUT_NESTING ){
      /* This will be more informative in a later version. */
--    utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
--                " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
++    eputf("Input nesting limit (%d) reached at line %d."
++          " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
      return 1;
    }
    ++p->inputNesting;
      zLine = one_input_line(p->in, zLine, nSql>0);
      if( zLine==0 ){
        /* End of input */
--      if( p->in==0 && stdin_is_interactive ) printf("\n");
++      if( p->in==0 && stdin_is_interactive ) oputz("\n");
        break;
      }
      if( seenInterrupt ){
@@@ -11702,8 -11961,8 +11653,8 @@@ static void process_sqliterc
    if( sqliterc == NULL ){
      home_dir = find_home_dir(0);
      if( home_dir==0 ){
-       utf8_print(stderr, "-- warning: cannot find home directory;"
 -      raw_printf(stderr, "-- warning: cannot find home directory;"
--                      " cannot read ~/.sqliterc\n");
++      eputz("-- warning: cannot find home directory;"
++            " cannot read ~/.sqliterc\n");
        return;
      }
      zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
    p->in = fopen(sqliterc,"rb");
    if( p->in ){
      if( stdin_is_interactive ){
--      utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
++      eputf("-- Loading resources from %s\n", sqliterc);
      }
      if( process_input(p) && bail_on_error ) exit(1);
      fclose(p->in);
    }else if( sqliterc_override!=0 ){
--    utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
++    eputf("cannot open: \"%s\"\n", sqliterc);
      if( bail_on_error ) exit(1);
    }
    p->in = inSaved;
@@@ -11794,14 -12059,14 +11745,13 @@@ static const char zOptions[] 
  #endif
  ;
  static void usage(int showDetail){
--  utf8_printf(stderr,
--      "Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
--      "FILENAME is the name of an SQLite database. A new database is created\n"
--      "if the file does not previously exist. Defaults to :memory:.\n", Argv0);
++  eputf("Usage: %s [OPTIONS] [FILENAME [SQL]]\n"
++       "FILENAME is the name of an SQLite database. A new database is created\n"
++       "if the file does not previously exist. Defaults to :memory:.\n", Argv0);
    if( showDetail ){
--    utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
++    eputf("OPTIONS include:\n%s", zOptions);
    }else{
-     utf8_print(stderr, "Use the -help option for additional information\n");
 -    raw_printf(stderr, "Use the -help option for additional information\n");
++    eputz("Use the -help option for additional information\n");
    }
    exit(1);
  }
  */
  static void verify_uninitialized(void){
    if( sqlite3_config(-1)==SQLITE_MISUSE ){
-     utf8_print(stdout, "WARNING: attempt to configure SQLite after"
 -    utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
--                        " initialization.\n");
++    sputz(stdout, "WARNING: attempt to configure SQLite after"
++          " initialization.\n");
    }
  }
  
@@@ -11869,15 -12134,15 +11819,15 @@@ static void printBold(const char *zText
  */
  static char *cmdline_option_value(int argc, char **argv, int i){
    if( i==argc ){
--    utf8_printf(stderr, "%s: Error: missing argument to %s\n",
--            argv[0], argv[argc-1]);
++    eputf("%s: Error: missing argument to %s\n",
++          argv[0], argv[argc-1]);
      exit(1);
    }
    return argv[i];
  }
  
  static void sayAbnormalExit(void){
--  if( seenInterrupt ) fprintf(stderr, "Program interrupted.\n");
++  if( seenInterrupt ) eputf("Program interrupted.\n");
  }
  
  #ifndef SQLITE_SHELL_IS_UTF8
@@@ -11941,9 -12207,9 +11891,8 @@@ int SQLITE_CDECL wmain(int argc, wchar_
  #if !defined(_WIN32_WCE)
    if( getenv("SQLITE_DEBUG_BREAK") ){
      if( isatty(0) && isatty(2) ){
--      fprintf(stderr,
--          "attach debugger to process %d and press any key to continue.\n",
--          GETPID());
++      eputf("attach debugger to process %d and press any key to continue.\n",
++            GETPID());
        fgetc(stdin);
      }else{
  #if defined(_WIN32) || defined(WIN32)
    signal(SIGINT, interrupt_handler);
  #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
    if( !SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE) ){
--    fprintf(stderr, "No ^C handler.\n");
++    eputf("No ^C handler.\n");
    }
  #endif
  
  #if USE_SYSTEM_SQLITE+0!=1
    if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
--    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
--            sqlite3_sourceid(), SQLITE_SOURCE_ID);
++    eputf("SQLite header and source version mismatch\n%s\n%s\n",
++          sqlite3_sourceid(), SQLITE_SOURCE_ID);
      exit(1);
    }
  #endif
    memset(&data, 0, sizeof(data));
  #ifdef SQLITE_DEBUG
    if( sqlite3_memory_used()>mem_main_enter ){
--    utf8_printf(stderr, "Memory leaked: %u bytes\n",
--                (unsigned int)(sqlite3_memory_used()-mem_main_enter));
++    eputf("Memory leaked: %u bytes\n",
++          (unsigned int)(sqlite3_memory_used()-mem_main_enter));
    }
  #endif
  #endif /* !SQLITE_SHELL_FIDDLE */