]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Move datatype and structure definitions up near the top in the CLI source code,
authordrh <>
Mon, 23 Mar 2026 21:03:34 +0000 (21:03 +0000)
committerdrh <>
Mon, 23 Mar 2026 21:03:34 +0000 (21:03 +0000)
to facilitate future changes.  No changes to the actual logic (yet).

FossilOrigin-Name: 6b3d84d34d1a84eb8ddff08cd85d9dff6e71099e7a4b2c19db8774d942d3a040

manifest
manifest.uuid
src/shell.c.in

index c7a64473f62809e754d8f5327b301d36488be464..7c02ed602c17d2144a2eab58ab208fcda50230cb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Require\sa\sbutton\sclick\sto\sstart\sthe\sOPFS\sconcurrency\stester,\srather\sthan\ssimply\slaunching\sall\sN\sworkers\simmediately\son\spage\sload.
-D 2026-03-23T13:17:13.272
+C Move\sdatatype\sand\sstructure\sdefinitions\sup\snear\sthe\stop\sin\sthe\sCLI\ssource\scode,\nto\sfacilitate\sfuture\schanges.\s\sNo\schanges\sto\sthe\sactual\slogic\s(yet).
+D 2026-03-23T21:03:34.220
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -734,7 +734,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c f0834917f2b1719d545a0d7eaad693283788f68ecd99871a81c7ff3b12b26209
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
-F src/shell.c.in 02c5b511ae1937312ae15bd0a7134d8c140d938bdf9a027c3f2cc1806c0c9e81
+F src/shell.c.in 38f05b2dde7e1de21d5499bdf6cad979a51e277c0b268997d40f5054d53a2236
 F src/sqlite.h.in 08ce865d8d1af6d6bac10400b5809bf395e442b6537c0fcb994161005f8d3989
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 5d48df11327acaabc45690a1957f0f4643e07afd9f77c5f2326115239fe5a3bc
@@ -2195,8 +2195,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 276c350313a1ac2ebc70c1e8e50ed4baecd4be4d4c93ba04cf5e0078da18700e
-R d8845e730ad8ece5c023a65e81ce4e5a
-U stephan
-Z b977c4ea22736a6a2da0f6286818f4bb
+P 3342d6786e07d3d8dd4b1f2291edea9f8354d384ff21242cc513c218ce6f1630
+R 8c5c587dcf1bcb89f63fe198495d5592
+U drh
+Z f5602963f831d7a71bfe866ee1f1efbc
 # Remove this line to create a well-formed Fossil manifest.
index 759cb824348a53d64b135b98af4343e8cc94807b..dfead07fd064e808159b4a65738d57dde96be628 100644 (file)
@@ -1 +1 @@
-3342d6786e07d3d8dd4b1f2291edea9f8354d384ff21242cc513c218ce6f1630
+6b3d84d34d1a84eb8ddff08cd85d9dff6e71099e7a4b2c19db8774d942d3a040
index 5eade70eb9bda5260f7b83def2f65d43b239862b..51d00f2894bc243d324461268c75982aba466168 100644 (file)
 typedef unsigned int u32;
 typedef unsigned short int u16;
 
+/*
+** Limit input nesting via .read or any other input redirect.
+** It's not too expensive, so a generous allowance can be made.
+*/
+#define MAX_INPUT_NESTING 25
+
+/*
+** Used to prevent warnings about unused parameters
+*/
+#define UNUSED_PARAMETER(x) (void)(x)
+
+/*
+** Number of elements in an array
+*/
+#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
+
 /*
 ** Optionally #include a user-defined header, whereby compilation options
 ** may be set prior to where they take effect, but after platform setup.
@@ -246,1145 +262,1131 @@ INCLUDE ../ext/qrf/qrf.c
 #endif
 
 /*
-** Output routines that are able to redirect to memory rather than
-** doing actually I/O.
-**                                                Works like.
-**                                                --------------
-**   cli_printf(FILE*, const char*, ...);         fprintf()
-**   cli_puts(const char*, FILE*);                fputs()
-**   cli_vprintf(FILE*, const char*, va_list);    vfprintf()
-**
-** These are just thin wrappers with the following added semantics:
-** If the file-scope variable cli_output_capture is not NULL, and
-** if the FILE* argument is stdout or stderr, then rather than
-** writing to stdout/stdout, append the text to the cli_output_capture
-** variable.
-**
-** The cli_exit(int) routine works like exit() except that it
-** first dumps any capture output to stdout.
+** The source code for several run-time loadable extensions is inserted
+** below by the ../tool/mkshellc.tcl script.  Before processing that included
+** code, we need to override some macros to make the included program code
+** work here in the middle of this regular program.
 */
-static sqlite3_str *cli_output_capture = 0; 
-static int cli_printf(FILE *out, const char *zFormat, ...){
-  va_list ap;
-  int rc;
-  va_start(ap,zFormat);
-  if( cli_output_capture && (out==stdout || out==stderr) ){
-    sqlite3_str_vappendf(cli_output_capture, zFormat, ap);
-    rc = 1;
-  }else{
-    rc = sqlite3_vfprintf(out, zFormat, ap);
-  }
-  va_end(ap);
-  return rc;
-}
-static int cli_puts(const char *zText, FILE *out){
-  if( cli_output_capture && (out==stdout || out==stderr) ){
-    sqlite3_str_appendall(cli_output_capture, zText);
-    return 1;
-  }
-  return sqlite3_fputs(zText, out);
-}
-#if 0 /* Not currently used - available if we need it later */
-static int cli_vprintf(FILE *out, const char *zFormat, va_list ap){
-  if( cli_output_capture && (out==stdout || out==stderr) ){
-    sqlite3_str_vappendf(cli_output_capture, zFormat, ap);
-    return 1;
-  }else{
-    return sqlite3_vfprintf(out, zFormat, ap);
-  }
-}
-#endif
-static void cli_exit(int rc){
-  if( cli_output_capture ){
-    char *z = sqlite3_str_finish(cli_output_capture);
-    sqlite3_fputs(z, stdout);
-    fflush(stdout);
-  }
-  exit(rc);
-}
-
-
-#define eputz(z) cli_puts(z,stderr)
-#define sputz(fp,z) cli_puts(z,fp)
+#define SQLITE_EXTENSION_INIT1
+#define SQLITE_EXTENSION_INIT2(X) (void)(X)
 
-/* A version of strcmp() that works with NULL values */
-static int cli_strcmp(const char *a, const char *b){
-  if( a==0 ) a = "";
-  if( b==0 ) b = "";
-  return strcmp(a,b);
-}
-static int cli_strncmp(const char *a, const char *b, size_t n){
-  if( a==0 ) a = "";
-  if( b==0 ) b = "";
-  return strncmp(a,b,n);
-}
+INCLUDE ../ext/misc/windirent.h
+INCLUDE ../ext/misc/memtrace.c
+INCLUDE ../ext/misc/pcachetrace.c
+INCLUDE ../ext/misc/shathree.c
+INCLUDE ../ext/misc/sha1.c
+INCLUDE ../ext/misc/uint.c
+INCLUDE ../ext/misc/decimal.c
+INCLUDE ../ext/misc/base64.c
+INCLUDE ../ext/misc/base85.c
+INCLUDE ../ext/misc/ieee754.c
+INCLUDE ../ext/misc/series.c
+INCLUDE ../ext/misc/regexp.c
+#ifndef SQLITE_SHELL_FIDDLE
+INCLUDE ../ext/misc/fileio.c
+INCLUDE ../ext/misc/completion.c
+INCLUDE ../ext/misc/appendvfs.c
+#endif
+#ifdef SQLITE_HAVE_ZLIB
+INCLUDE ../ext/misc/zipfile.c
+INCLUDE ../ext/misc/sqlar.c
+#endif
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
+INCLUDE ../ext/expert/sqlite3expert.h
+INCLUDE ../ext/expert/sqlite3expert.c
+#endif
+INCLUDE ../ext/intck/sqlite3intck.h
+INCLUDE ../ext/intck/sqlite3intck.c
+INCLUDE ../ext/misc/stmtrand.c
+INCLUDE ../ext/misc/vfstrace.c
 
-/* Return the current wall-clock time in microseconds since the
-** Unix epoch (1970-01-01T00:00:00Z)
-*/
-static sqlite3_int64 timeOfDay(void){
-#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
-  sqlite3_uint64 t;
-  FILETIME tm;
-  GetSystemTimePreciseAsFileTime(&tm);
-  t =  ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
-  t += 116444736000000000LL;
-  t /= 10;
-  return t;
-#elif defined(_WIN32)
-  static sqlite3_vfs *clockVfs = 0;
-  sqlite3_int64 t;
-  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
-  if( clockVfs==0 ) return 0;  /* Never actually happens */
-  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
-    clockVfs->xCurrentTimeInt64(clockVfs, &t);
-  }else{
-    double r;
-    clockVfs->xCurrentTime(clockVfs, &r);
-    t = (sqlite3_int64)(r*86400000.0);
-  }
-  return t*1000;
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
+#define SQLITE_SHELL_HAVE_RECOVER 1
 #else
-  struct timeval sNow;
-  (void)gettimeofday(&sNow,0);
-  return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
+#define SQLITE_SHELL_HAVE_RECOVER 0
+#endif
+#if SQLITE_SHELL_HAVE_RECOVER
+INCLUDE ../ext/recover/sqlite3recover.h
+# ifndef SQLITE_HAVE_SQLITE3R
+INCLUDE ../ext/recover/dbdata.c
+INCLUDE ../ext/recover/sqlite3recover.c
+# endif /* SQLITE_HAVE_SQLITE3R */
+#endif
+#ifdef SQLITE_SHELL_EXTSRC
+# include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC)
 #endif
-}
-
-
-/*
-** Used to prevent warnings about unused parameters
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-
-/*
-** Number of elements in an array
-*/
-#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
-
-/*
-** If the following flag is set, then command execution stops
-** at an error if we are not interactive.
-*/
-static int bail_on_error = 0;
-
-/*
-** Treat stdin as an interactive input if the following variable
-** is true.  Otherwise, assume stdin is connected to a file or pipe.
-*/
-static int stdin_is_interactive = 1;
-
-/*
-** Treat stdout like a TTY if true.
-*/
-static int stdout_is_console = 1;
 
+#if defined(SQLITE_ENABLE_SESSION)
 /*
-** Use this value as the width of the output device.  Or, figure it
-** out at runtime if the value is negative.  Or use a default width
-** if this value is zero.
+** State information for a single open session
 */
-static int stdout_tty_width = -1;
+typedef struct OpenSession OpenSession;
+struct OpenSession {
+  char *zName;             /* Symbolic name for this session */
+  int nFilter;             /* Number of xFilter rejection GLOB patterns */
+  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
+  sqlite3_session *p;      /* The open session */
+};
+#endif
 
-/*
-** The following is the open SQLite database.  We make a pointer
-** to this database a static variable so that it can be accessed
-** by the SIGINT handler to interrupt database processing.
-*/
-static sqlite3 *globalDb = 0;
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
+typedef struct ExpertInfo ExpertInfo;
+struct ExpertInfo {
+  sqlite3expert *pExpert;
+  int bVerbose;
+};
+#endif
 
-/*
-** True if an interrupt (Control-C) has been received.
+/* All the parameters that determine how to render query results.
 */
-static volatile int seenInterrupt = 0;
+typedef struct Mode {
+  u8 autoExplain;        /* Automatically turn on .explain mode */
+  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
+  u8 autoEQPtrace;       /* autoEQP is in trace mode */
+  u8 scanstatsOn;        /* True to display scan stats before each finalize */
+  u8 bAutoScreenWidth;   /* Using the TTY to determine screen width */
+  u8 mFlags;             /* MFLG_ECHO, MFLG_CRLF, etc. */
+  u8 eMode;              /* One of the MODE_ values */
+  sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
+} Mode;
 
-/*
-** This is the name of our program. It is set in main(), used
-** in a number of other places, mostly for error messages.
-*/
-static char *Argv0;
+/* Flags for Mode.mFlags */
+#define MFLG_ECHO  0x01  /* Echo inputs to output */
+#define MFLG_CRLF  0x02  /* Use CR/LF output line endings */
+#define MFLG_HDR   0x04  /* .header used to change headers on/off */
 
-/*
-** Prompt strings. Initialized in main. Settable with
-**   .prompt main continue
-*/
-#define PROMPT_LEN_MAX 128
-/* First line prompt.   default: "sqlite> " */
-static char mainPrompt[PROMPT_LEN_MAX];
-/* Continuation prompt. default: "   ...> " */
-static char continuePrompt[PROMPT_LEN_MAX];
 
 /*
-** Write I/O traces to the following stream.
+** State information about the database connection is contained in an
+** instance of the following structure.
 */
-#ifdef SQLITE_ENABLE_IOTRACE
-static FILE *iotrace = 0;
-#endif
+typedef struct ShellState ShellState;
+struct ShellState {
+  sqlite3 *db;           /* The database */
+  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
+  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
+  u8 nEqpLevel;          /* Depth of the EQP output graph */
+  u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
+  u8 bSafeMode;          /* True to prohibit unsafe operations */
+  u8 bSafeModePersist;   /* The long-term value of bSafeMode */
+  u8 eRestoreState;      /* See comments above doAutoDetectRestore() */
+  unsigned statsOn;      /* True to display memory stats before each finalize */
+  unsigned mEqpLines;    /* Mask of vertical lines in the EQP output graph */
+  u8 nPopOutput;         /* Revert .output settings when reaching zero */
+  u8 nPopMode;           /* Revert .mode settings when reaching zero */
+  u8 enableTimer;        /* Enable the timer.  2: permanently 1: only once */
+  int inputNesting;      /* Track nesting level of .read and other redirects */
+  double prevTimer;      /* Last reported timer value */
+  double tmProgress;     /* --timeout option for .progress */
+  i64 lineno;            /* Line number of last line read from in */
+  const char *zInFile;   /* Name of the input file */
+  int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
+  FILE *in;              /* Read commands from this stream */
+  FILE *out;             /* Write results here */
+  FILE *traceOut;        /* Output for sqlite3_trace() */
+  int nErr;              /* Number of errors seen */
+  int writableSchema;    /* True if PRAGMA writable_schema=ON */
+  int nCheck;            /* Number of ".check" commands run */
+  unsigned nProgress;    /* Number of progress callbacks encountered */
+  unsigned mxProgress;   /* Maximum progress callbacks before failing */
+  unsigned flgProgress;  /* Flags for the progress callback */
+  unsigned shellFlgs;    /* Various flags */
+  unsigned nTestRun;     /* Number of test cases run */
+  unsigned nTestErr;     /* Number of test cases that failed */
+  sqlite3_int64 szMax;   /* --maxsize argument to .open */
+  char *zDestTable;      /* Name of destination table when MODE_Insert */
+  char *zTempFile;       /* Temporary file that might need deleting */
+  char *zErrPrefix;      /* Alternative error message prefix */
+  char zTestcase[30];    /* Name of current test case */
+  char outfile[FILENAME_MAX]; /* Filename for *out */
+  sqlite3_stmt *pStmt;   /* Current statement if any. */
+  FILE *pLog;            /* Write log output here */
+  Mode mode;             /* Current display mode */
+  Mode modePrior;        /* Backup */
+  struct SavedMode {     /* Ability to define custom mode configurations */
+    char *zTag;            /* Name of this saved mode */
+    Mode mode;              /* The saved mode */
+  } *aSavedModes;        /* Array of saved .mode settings. system malloc() */
+  int nSavedModes;       /* Number of saved .mode settings */
+  struct AuxDb {         /* Storage space for auxiliary database connections */
+    sqlite3 *db;               /* Connection pointer */
+    const char *zDbFilename;   /* Filename used to open the connection */
+    char *zFreeOnClose;        /* Free this memory allocation on close */
+#if defined(SQLITE_ENABLE_SESSION)
+    int nSession;              /* Number of active sessions */
+    OpenSession aSession[4];   /* Array of sessions.  [0] is in focus. */
+#endif
+  } aAuxDb[5],           /* Array of all database connections */
+    *pAuxDb;             /* Currently active database connection */
+  char *zNonce;          /* Nonce for temporary safe-mode escapes */
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
+  ExpertInfo expert;     /* Valid if previous command was ".expert OPT..." */
+#endif
+  struct DotCmdLine {    /* Info about arguments to a dot-command */
+    const char *zOrig;      /* Original text of the dot-command */
+    char *zCopy;            /* Copy of zOrig, from malloc() */
+    int nAlloc;             /* Size of allocates for arrays below */
+    int nArg;               /* Number of argument slots actually used */
+    char **azArg;           /* Pointer to each argument, dequoted */
+    int *aiOfst;            /* Offset into zOrig[] for start of each arg */
+    char *abQuot;           /* True if the argment was originally quoted */
+  } dot;
+#ifdef SQLITE_SHELL_FIDDLE
+  struct {
+    const char * zInput; /* Input string from wasm/JS proxy */
+    const char * zPos;   /* Cursor pos into zInput */
+    const char * zDefaultDbName; /* Default name for db file */
+  } wasm;
+#endif
+};
 
+#ifdef SQLITE_SHELL_FIDDLE
+static ShellState shellState;
+#endif
 
-/* This is variant of the standard-library strncpy() routine with the
-** one change that the destination string is always zero-terminated, even
-** if there is no zero-terminator in the first n-1 characters of the source
-** string.
-*/
-static char *shell_strncpy(char *dest, const char *src, size_t n){
-  size_t i;
-  for(i=0; i<n-1 && src[i]!=0; i++) dest[i] = src[i];
-  dest[i] = 0;
-  return dest;
-}
 
-/*
-** strcpy() workalike to squelch an unwarranted link-time warning
-** from OpenBSD.
+/* Allowed values for ShellState.mode.autoEQP
 */
-static void shell_strcpy(char *dest, const char *src){
-  while( (*(dest++) = *(src++))!=0 ){}
-}
+#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
+#define AUTOEQP_on       1           /* Automatic EQP is on */
+#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
+#define AUTOEQP_full     3           /* Show full EXPLAIN */
 
-/*
-** Optionally disable dynamic continuation prompt.
-** Unless disabled, the continuation prompt shows open SQL lexemes if any,
-** or open parentheses level if non-zero, or continuation prompt as set.
-** This facility interacts with the scanner and process_input() where the
-** below 5 macros are used.
+/* Allowed values for ShellState.openMode
 */
-#ifdef SQLITE_OMIT_DYNAPROMPT
-# define CONTINUATION_PROMPT continuePrompt
-# define CONTINUE_PROMPT_RESET
-# define CONTINUE_PROMPT_AWAITS(p,s)
-# define CONTINUE_PROMPT_AWAITC(p,c)
-# define CONTINUE_PAREN_INCR(p,n)
-# define CONTINUE_PROMPT_PSTATE 0
-typedef void *t_NoDynaPrompt;
-# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt
-#else
-# define CONTINUATION_PROMPT dynamicContinuePrompt()
-# define CONTINUE_PROMPT_RESET \
-  do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0)
-# define CONTINUE_PROMPT_AWAITS(p,s) \
-  if(p && stdin_is_interactive) setLexemeOpen(p, s, 0)
-# define CONTINUE_PROMPT_AWAITC(p,c) \
-  if(p && stdin_is_interactive) setLexemeOpen(p, 0, c)
-# define CONTINUE_PAREN_INCR(p,n) \
-  if(p && stdin_is_interactive) (trackParenLevel(p,n))
-# define CONTINUE_PROMPT_PSTATE (&dynPrompt)
-typedef struct DynaPrompt *t_DynaPromptRef;
-# define SCAN_TRACKER_REFTYPE t_DynaPromptRef
-
-static struct DynaPrompt {
-  char dynamicPrompt[PROMPT_LEN_MAX];
-  char acAwait[2];
-  int inParenLevel;
-  char *zScannerAwaits;
-} dynPrompt = { {0}, {0}, 0, 0 };
-
-/* Record parenthesis nesting level change, or force level to 0. */
-static void trackParenLevel(struct DynaPrompt *p, int ni){
-  p->inParenLevel += ni;
-  if( ni==0 ) p->inParenLevel = 0;
-  p->zScannerAwaits = 0;
-}
+#define SHELL_OPEN_UNSPEC      0      /* No open-mode specified */
+#define SHELL_OPEN_NORMAL      1      /* Normal database file */
+#define SHELL_OPEN_APPENDVFS   2      /* Use appendvfs */
+#define SHELL_OPEN_ZIPFILE     3      /* Use the zipfile virtual table */
+#define SHELL_OPEN_DESERIALIZE 4      /* Open using sqlite3_deserialize() */
+#define SHELL_OPEN_HEXDB       5      /* Use "dbtotxt" output as data source */
 
-/* Record that a lexeme is opened, or closed with args==0. */
-static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){
-  if( s!=0 || c==0 ){
-    p->zScannerAwaits = s;
-    p->acAwait[0] = 0;
-  }else{
-    p->acAwait[0] = c;
-    p->zScannerAwaits = p->acAwait;
-  }
-}
+/* Allowed values for ShellState.eTraceType
+*/
+#define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
+#define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
+#define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */
 
-/* Upon demand, derive the continuation prompt to display. */
-static char *dynamicContinuePrompt(void){
-  if( continuePrompt[0]==0
-      || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){
-    return continuePrompt;
-  }else{
-    if( dynPrompt.zScannerAwaits ){
-      size_t ncp = strlen(continuePrompt);
-      size_t ndp = strlen(dynPrompt.zScannerAwaits);
-      if( ndp > ncp-3 ) return continuePrompt;
-      shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
-      while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
-      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
-              PROMPT_LEN_MAX-4);
-    }else{
-      if( dynPrompt.inParenLevel>9 ){
-        shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4);
-      }else if( dynPrompt.inParenLevel<0 ){
-        shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
-      }else{
-        shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
-        dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
-      }
-      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
-                    PROMPT_LEN_MAX-4);
-    }
-  }
-  return dynPrompt.dynamicPrompt;
-}
-#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */
+/* Bits in the ShellState.flgProgress variable */
+#define SHELL_PROGRESS_QUIET 0x01  /* Omit announcing every progress callback */
+#define SHELL_PROGRESS_RESET 0x02  /* Reset the count when the progress
+                                   ** callback limit is reached, and for each
+                                   ** top-level SQL statement */
+#define SHELL_PROGRESS_ONCE  0x04  /* Cancel the --limit after firing once */
+#define SHELL_PROGRESS_TMOUT 0x08  /* Stop after tmProgress seconds */
 
-/* Indicate out-of-memory and exit. */
-static void shell_out_of_memory(void){
-  eputz("Error: out of memory\n");
-  cli_exit(1);
-}
+/* Names of values for Mode.spec.eEsc and Mode.spec.eText
+*/
+static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
+static const char *qrfQuoteNames[] = 
+      { "off","off","sql","hex","csv","tcl","json","relaxed"};
 
-/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
-** out-of-memory error.
+/*
+** These are the allowed shellFlgs values
 */
-static void shell_check_oom(const void *p){
-  if( p==0 ) shell_out_of_memory();
-}
+#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
+#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
+#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
+#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
+#define SHFLG_NoErrLineno    0x00000010 /* Omit line numbers from error msgs */
+#define SHFLG_CountChanges   0x00000020 /* .changes setting */
+#define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
+#define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */
+#define SHFLG_TestingMode    0x00000400 /* allow unsafe testing features */
 
 /*
-** This routine works like printf in that its first argument is a
-** format string and subsequent arguments are values to be substituted
-** in place of % fields.  The result of formatting this string
-** is written to iotrace.
+** Macros for testing and setting shellFlgs
 */
-#ifdef SQLITE_ENABLE_IOTRACE
-static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
-  va_list ap;
-  char *z;
-  if( iotrace==0 ) return;
-  va_start(ap, zFormat);
-  z = sqlite3_vmprintf(zFormat, ap);
-  va_end(ap);
-  cli_printf(iotrace, "%s", z);
-  sqlite3_free(z);
-}
-#endif
+#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
+#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
+#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
 
 /*
-** Compute a string length that is limited to what can be stored in
-** lower 30 bits of a 32-bit signed integer.
+** These are the allowed values for Mode.eMode.  There is a lot of overlap
+** between these values and the Mode.spec.eStyle values, but they are not
+** one-to-one, and thus need to be tracked separately.
 */
-static int strlen30(const char *z){
-  size_t n;
-  if( z==0 ) return 0;
-  n = strlen(z);
-  return n>0x3fffffff ? 0x3fffffff : (int)n;
-}
+#define MODE_Ascii     0  /* Use ASCII unit and record separators (0x1F/0x1E) */
+#define MODE_Box       1  /* Unicode box-drawing characters */
+#define MODE_C         2  /* Comma-separated list of C-strings */
+#define MODE_Column    3  /* One record per line in neat columns */
+#define MODE_Count     4  /* Output only a count of the rows of output */
+#define MODE_Csv       5  /* Quote strings, numbers are plain */
+#define MODE_Html      6  /* Generate an XHTML table */
+#define MODE_Insert    7  /* Generate SQL "insert" statements */
+#define MODE_JAtom     8  /* Comma-separated list of JSON atoms */
+#define MODE_JObject   9  /* One JSON object per row */
+#define MODE_Json     10  /* Output JSON */
+#define MODE_Line     11  /* One column per line.  Blank line between records */
+#define MODE_List     12  /* One record per line with a separator */
+#define MODE_Markdown 13  /* Markdown formatting */
+#define MODE_Off      14  /* No query output shown */
+#define MODE_Psql     15  /* Similar to psql */
+#define MODE_QBox     16  /* BOX with SQL-quoted content */
+#define MODE_Quote    17  /* Quote values as for SQL */
+#define MODE_Split    18  /* Split-column mode */
+#define MODE_Table    19  /* MySQL-style table formatting */
+#define MODE_Tabs     20  /* Tab-separated values */
+#define MODE_Tcl      21  /* Space-separated list of TCL strings */
+#define MODE_Www      22  /* Full web-page output */
+
+#define MODE_BUILTIN  22  /* Maximum built-in mode */
+#define MODE_BATCH    50  /* Default mode for batch processing */
+#define MODE_TTY      51  /* Default mode for interactive processing */
+#define MODE_USER     75  /* First user-defined mode */
+#define MODE_N_USER   25  /* Maximum number of user-defined modes */
 
 /*
-** Return open FILE * if zFile exists, can be opened for read
-** and is an ordinary file or a character stream source.
-** Otherwise return 0.
+** Information about built-in display modes
 */
-static FILE * openChrSource(const char *zFile){
-#if defined(_WIN32) || defined(WIN32)
-  struct __stat64 x = {0};
-# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
-  /* On Windows, open first, then check the stream nature. This order
-  ** is necessary because _stat() and sibs, when checking a named pipe,
-  ** effectively break the pipe as its supplier sees it. */
-  FILE *rv = sqlite3_fopen(zFile, "rb");
-  if( rv==0 ) return 0;
-  if( _fstat64(_fileno(rv), &x) != 0
-      || !STAT_CHR_SRC(x.st_mode)){
-    fclose(rv);
-    rv = 0;
-  }
-  return rv;
-#else
-  struct stat x = {0};
-  int rc = stat(zFile, &x);
-# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
-  if( rc!=0 ) return 0;
-  if( STAT_CHR_SRC(x.st_mode) ){
-    return sqlite3_fopen(zFile, "rb");
-  }else{
-    return 0;
-  }
-#endif
-#undef STAT_CHR_SRC
-}
+typedef struct ModeInfo ModeInfo;
+struct ModeInfo {
+  char zName[9];         /* Symbolic name of the mode */
+  unsigned char eCSep;   /* Column separator */
+  unsigned char eRSep;   /* Row separator */
+  unsigned char eNull;   /* Null representation */
+  unsigned char eText;   /* Default text encoding */
+  unsigned char eHdr;    /* Default header encoding. */
+  unsigned char eBlob;   /* Default blob encoding. */
+  unsigned char bHdr;    /* Show headers by default.  0: n/a, 1: no 2: yes */
+  unsigned char eStyle;  /* Underlying QRF style */
+  unsigned char eCx;     /* 0: other, 1: line, 2: columnar */
+  unsigned char mFlg;    /* Flags. 1=border-off 2=split-column */
+};
+
+/* String constants used by built-in modes */
+static const char *aModeStr[] = 
+  /* 0    1       2       3       4     5        6        7        8    */
+   { 0,   "\n",   "|",    " ",    ",",  "\r\n",  "\036",  "\037",  "\t",
+     "",  "NULL", "null", "\"\"", ": ",                                   };
+  /* 9    10      11      12      13                                    */
 
+static const ModeInfo aModeInfo[] = {
+/*   zName      eCSep  eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
+  { "ascii",    7,     6,    9,    1,    1,    0,   1,   12,    0,  0 },
+  { "box",      0,     0,    9,    1,    1,    0,   2,   1,     2,  0 },
+  { "c",        4,     1,    10,   5,    5,    4,   1,   12,    0,  0 },
+  { "column",   0,     0,    9,    1,    1,    0,   2,   2,     2,  0 },
+  { "count",    0,     0,    0,    0,    0,    0,   0,   3,     0,  0 },
+  { "csv",      4,     5,    9,    3,    3,    0,   1,   12,    0,  0 },
+  { "html",     0,     0,    9,    4,    4,    0,   2,   7,     0,  0 },
+  { "insert",   0,     0,    10,   2,    2,    0,   1,   8,     0,  0 },
+  { "jatom",    4,     1,    11,   6,    6,    0,   1,   12,    0,  0 },
+  { "jobject",  0,     1,    11,   6,    6,    0,   0,   10,    0,  0 },
+  { "json",     0,     0,    11,   6,    6,    0,   0,   9,     0,  0 },
+  { "line",     13,    1,    9,    1,    1,    0,   0,   11,    1,  0 },
+  { "list",     2,     1,    9,    1,    1,    0,   1,   12,    0,  0 },
+  { "markdown", 0,     0,    9,    1,    1,    0,   2,   13,    2,  0 },
+  { "off",      0,     0,    0,    0,    0,    0,   0,   14,    0,  0 },
+  { "psql",     0,     0,    9,    1,    1,    0,   2,   19,    2,  1 },
+  { "qbox",     0,     0,    10,   2,    1,    0,   2,   1,     2,  0 },
+  { "quote",    4,     1,    10,   2,    2,    0,   1,   12,    0,  0 },
+  { "split",    0,     0,    9,    1,    1,    0,   1,   2,     2,  2 },
+  { "table",    0,     0,    9,    1,    1,    0,   2,   19,    2,  0 },
+  { "tabs",     8,     1,    9,    3,    3,    0,   1,   12,    0,  0 },
+  { "tcl",      3,     1,    12,   5,    5,    4,   1,   12,    0,  0 },
+  { "www",      0,     0,    9,    4,    4,    0,   2,   7,     0,  0 }
+};     /*       |     /     /      |     /    /     |    |       \
+       **       |    /     /       |    /    /      |    |        \_ 2: columnar
+       ** Index into aModeStr[]    |   /    /       |    |           1: line
+       **                          |  /    /        |    |           0: other
+       **                          | /    /         |     \
+       **           text encoding  |/     |    show |      \
+       **      v-------------------'      |   hdrs? |       The QRF style
+       **      0: n/a                blob |   v-----'
+       **      1: plain        v_---------'   0: n/a
+       **      2: sql          0: auto        1: no         
+       **      3: csv          1: as-text     2: yes
+       **      4: html         2: sql
+       **      5: c            3: hex
+       **      6: json         4: c
+       **                      5: json
+       **                      6: size
+       ******************************************************************/
 /*
-** This routine reads a line of text from FILE in, stores
-** the text in memory obtained from malloc() and returns a pointer
-** to the text.  NULL is returned at end of file, or if malloc()
-** fails, or if the length of the line is longer than about a gigabyte.
-**
-** If zLine is not NULL then it is a malloced buffer returned from
-** a previous call to this routine that may be reused.
+** These are the column/row/line separators used by the various
+** import/export modes.
 */
-static char *local_getline(char *zLine, FILE *in){
-  int nLine = zLine==0 ? 0 : 100;
-  int n = 0;
-
-  while( 1 ){
-    if( n+100>nLine ){
-      if( nLine>=1073741773 ){
-        free(zLine);
-        return 0;
-      }
-      nLine = nLine*2 + 100;
-      zLine = realloc(zLine, nLine);
-      shell_check_oom(zLine);
-    }
-    if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){
-      if( n==0 ){
-        free(zLine);
-        return 0;
-      }
-      zLine[n] = 0;
-      break;
-    }
-    while( zLine[n] ) n++;
-    if( n>0 && zLine[n-1]=='\n' ){
-      n--;
-      if( n>0 && zLine[n-1]=='\r' ) n--;
-      zLine[n] = 0;
-      break;
-    }
-  }
-  return zLine;
-}
+#define SEP_Column    "|"
+#define SEP_Row       "\n"
+#define SEP_Tab       "\t"
+#define SEP_Space     " "
+#define SEP_Comma     ","
+#define SEP_CrLf      "\r\n"
+#define SEP_Unit      "\x1F"
+#define SEP_Record    "\x1E"
 
 /*
-** Retrieve a single line of input text.
-**
-** If in==0 then read from standard input and prompt before each line.
-** If isContinuation is true, then a continuation prompt is appropriate.
-** If isContinuation is zero, then the main prompt should be used.
-**
-** If zPrior is not NULL then it is a buffer from a prior call to this
-** routine that can be reused.
-**
-** The result is stored in space obtained from malloc() and must either
-** be freed by the caller or else passed back into this routine via the
-** zPrior argument for reuse.
+** Default values for the various QRF limits
 */
-#ifndef SQLITE_SHELL_FIDDLE
-static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
-  char *zPrompt;
-  char *zResult;
-  if( in!=0 ){
-    zResult = local_getline(zPrior, in);
-  }else{
-    zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
-#if SHELL_USE_LOCAL_GETLINE
-    sputz(stdout, zPrompt);
-    fflush(stdout);
-    do{
-      zResult = local_getline(zPrior, stdin);
-      zPrior = 0;
-      /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
-      if( zResult==0 ) sqlite3_sleep(50);
-    }while( zResult==0 && seenInterrupt>0 );
-#else
-    free(zPrior);
-    zResult = shell_readline(zPrompt);
-    while( zResult==0 ){
-      /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
-      sqlite3_sleep(50);
-      if( seenInterrupt==0 ) break;
-      zResult = shell_readline("");
-    }
-    if( zResult && *zResult ) shell_add_history(zResult);
+#ifndef DFLT_CHAR_LIMIT
+# define DFLT_CHAR_LIMIT  300
+#endif
+#ifndef DFLT_LINE_LIMIT
+# define DFLT_LINE_LIMIT  5
+#endif
+#ifndef DFLT_TITLE_LIMIT
+# define DFLT_TITLE_LIMIT 20
+#endif
+#ifndef DFLT_MULTI_INSERT
+# define DFLT_MULTI_INSERT 3000
 #endif
-  }
-  return zResult;
-}
-#endif /* !SQLITE_SHELL_FIDDLE */
 
 /*
-** Return the value of a hexadecimal digit.  Return -1 if the input
-** is not a hex digit.
+** If the following flag is set, then command execution stops
+** at an error if we are not interactive.
 */
-static int hexDigitValue(char c){
-  if( c>='0' && c<='9' ) return c - '0';
-  if( c>='a' && c<='f' ) return c - 'a' + 10;
-  if( c>='A' && c<='F' ) return c - 'A' + 10;
-  return -1;
-}
+static int bail_on_error = 0;
 
 /*
-** Interpret zArg as an integer value, possibly with suffixes.
-**
-** If the value specified by zArg is outside the range of values that
-** can be represented using a 64-bit twos-complement integer, then return
-** the nearest representable value.
+** Treat stdin as an interactive input if the following variable
+** is true.  Otherwise, assume stdin is connected to a file or pipe.
 */
-static sqlite3_int64 integerValue(const char *zArg){
-  sqlite3_uint64 v = 0;
-  static const struct { char *zSuffix; unsigned int iMult; } aMult[] = {
-    { "KiB", 1024 },
-    { "MiB", 1024*1024 },
-    { "GiB", 1024*1024*1024 },
-    { "KB",  1000 },
-    { "MB",  1000000 },
-    { "GB",  1000000000 },
-    { "K",   1000 },
-    { "M",   1000000 },
-    { "G",   1000000000 },
-  };
-  int i;
-  int isNeg = 0;
-  if( zArg[0]=='-' ){
-    isNeg = 1;
-    zArg++;
-  }else if( zArg[0]=='+' ){
-    zArg++;
-  }
-  if( zArg[0]=='0' && zArg[1]=='x' ){
-    int x;
-    zArg += 2;
-    while( (x = hexDigitValue(zArg[0]))>=0 ){
-      if( v > 0x0fffffffffffffffULL ) goto integer_overflow;
-      v = (v<<4) + x;
-      zArg++;
-    }
-  }else{
-    while( IsDigit(zArg[0]) ){
-      if( v>=922337203685477580LL ){
-        if( v>922337203685477580LL || zArg[0]>='8' ) goto integer_overflow;
-      }
-      v = v*10 + (zArg[0] - '0');
-      zArg++;
-    }
-  }
-  for(i=0; i<ArraySize(aMult); i++){
-    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
-      if( 0x7fffffffffffffffULL/aMult[i].iMult < v ) goto integer_overflow;
-      v *= aMult[i].iMult;
-      break;
-    }
-  }
-  if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow;
-  return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v;
-integer_overflow:
-  return isNeg ? (i64)0x8000000000000000LL : 0x7fffffffffffffffLL;
-}
+static int stdin_is_interactive = 1;
 
 /*
-** A variable length string to which one can append text.
+** Treat stdout like a TTY if true.
 */
-typedef struct ShellText ShellText;
-struct ShellText {
-  char *zTxt;       /* The text */
-  i64 n;            /* Number of bytes of zTxt[] actually used */
-  i64 nAlloc;       /* Number of bytes allocated for zTxt[] */
-};
+static int stdout_is_console = 1;
 
 /*
-** Initialize and destroy a ShellText object
+** Use this value as the width of the output device.  Or, figure it
+** out at runtime if the value is negative.  Or use a default width
+** if this value is zero.
 */
-static void initText(ShellText *p){
-  memset(p, 0, sizeof(*p));
-}
-static void freeText(ShellText *p){
-  sqlite3_free(p->zTxt);
-  initText(p);
-}
+static int stdout_tty_width = -1;
 
-/* zIn is either a pointer to a NULL-terminated string in memory obtained
-** from malloc(), or a NULL pointer. The string pointed to by zAppend is
-** added to zIn, and the result returned in memory obtained from malloc().
-** zIn, if it was not NULL, is freed.
-**
-** If the third argument, quote, is not '\0', then it is used as a
-** quote character for zAppend.
+/*
+** The following is the open SQLite database.  We make a pointer
+** to this database a static variable so that it can be accessed
+** by the SIGINT handler to interrupt database processing.
 */
-static void appendText(ShellText *p, const char *zAppend, char quote){
-  i64 len;
-  i64 i;
-  i64 nAppend = strlen30(zAppend);
-
-  len = nAppend+p->n+1;
-  if( quote ){
-    len += 2;
-    for(i=0; i<nAppend; i++){
-      if( zAppend[i]==quote ) len++;
-    }
-  }
-
-  if( p->zTxt==0 || p->n+len>=p->nAlloc ){
-    p->nAlloc = p->nAlloc*2 + len + 20;
-    p->zTxt = sqlite3_realloc64(p->zTxt, p->nAlloc);
-    shell_check_oom(p->zTxt);
-  }
-
-  if( quote ){
-    char *zCsr = p->zTxt+p->n;
-    *zCsr++ = quote;
-    for(i=0; i<nAppend; i++){
-      *zCsr++ = zAppend[i];
-      if( zAppend[i]==quote ) *zCsr++ = quote;
-    }
-    *zCsr++ = quote;
-    p->n = (i64)(zCsr - p->zTxt);
-    *zCsr = '\0';
-  }else{
-    memcpy(p->zTxt+p->n, zAppend, nAppend);
-    p->n += nAppend;
-    p->zTxt[p->n] = '\0';
-  }
-}
+static sqlite3 *globalDb = 0;
 
 /*
-** Attempt to determine if identifier zName needs to be quoted, either
-** because it contains non-alphanumeric characters, or because it is an
-** SQLite keyword.  Be conservative in this estimate:  When in doubt assume
-** that quoting is required.
-**
-** Return '"' if quoting is required.  Return 0 if no quoting is required.
+** True if an interrupt (Control-C) has been received.
 */
-static char quoteChar(const char *zName){
-  int i;
-  if( zName==0 ) return '"';
-  if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"';
-  for(i=0; zName[i]; i++){
-    if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '"';
-  }
-  return sqlite3_keyword_check(zName, i) ? '"' : 0;
-}
+static volatile int seenInterrupt = 0;
 
 /*
-** Construct a fake object name and column list to describe the structure
-** of the view, virtual table, or table valued function zSchema.zName.
-**
-** The returned string comes from sqlite3_mprintf() and should be freed
-** by the caller using sqlite3_free().
+** This is the name of our program. It is set in main(), used
+** in a number of other places, mostly for error messages.
 */
-static char *shellFakeSchema(
-  sqlite3 *db,            /* The database connection containing the vtab */
-  const char *zSchema,    /* Schema of the database holding the vtab */
-  const char *zName       /* The name of the virtual table */
-){
-  sqlite3_stmt *pStmt = 0;
-  char *zSql;
-  ShellText s;
-  char cQuote;
-  char *zDiv = "(";
-  int nRow = 0;
-
-  zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
-                         zSchema ? zSchema : "main", zName);
-  shell_check_oom(zSql);
-  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
-  sqlite3_free(zSql);
-  initText(&s);
-  if( zSchema ){
-    cQuote = quoteChar(zSchema);
-    if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
-    appendText(&s, zSchema, cQuote);
-    appendText(&s, ".", 0);
-  }
-  cQuote = quoteChar(zName);
-  appendText(&s, zName, cQuote);
-  while( sqlite3_step(pStmt)==SQLITE_ROW ){
-    const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
-    nRow++;
-    appendText(&s, zDiv, 0);
-    zDiv = ",";
-    if( zCol==0 ) zCol = "";
-    cQuote = quoteChar(zCol);
-    appendText(&s, zCol, cQuote);
-  }
-  appendText(&s, ")", 0);
-  sqlite3_finalize(pStmt);
-  if( nRow==0 ){
-    freeText(&s);
-    s.zTxt = 0;
-  }
-  return s.zTxt;
-}
+static char *Argv0;
 
 /*
-** SQL function:  strtod(X)
-**
-** Use the C-library strtod() function to convert string X into a double.
-** Used for comparing the accuracy of SQLite's internal text-to-float conversion
-** routines against the C-library.
+** Prompt strings. Initialized in main. Settable with
+**   .prompt main continue
 */
-static void shellStrtod(
-  sqlite3_context *pCtx,
-  int nVal,
-  sqlite3_value **apVal
-){
-  char *z = (char*)sqlite3_value_text(apVal[0]);
-  UNUSED_PARAMETER(nVal);
-  if( z==0 ) return;
-  sqlite3_result_double(pCtx, strtod(z,0));
-}
+#define PROMPT_LEN_MAX 128
+/* First line prompt.   default: "sqlite> " */
+static char mainPrompt[PROMPT_LEN_MAX];
+/* Continuation prompt. default: "   ...> " */
+static char continuePrompt[PROMPT_LEN_MAX];
 
 /*
-** SQL function:  dtostr(X)
-**
-** Use the C-library printf() function to convert real value X into a string.
-** Used for comparing the accuracy of SQLite's internal float-to-text conversion
-** routines against the C-library.
+** Write I/O traces to the following stream.
 */
-static void shellDtostr(
-  sqlite3_context *pCtx,
-  int nVal,
-  sqlite3_value **apVal
-){
-  double r = sqlite3_value_double(apVal[0]);
-  int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26;
-  char z[400];
-  if( n<1 ) n = 1;
-  if( n>350 ) n = 350;
-  sprintf(z, "%#+.*e", n, r);
-  sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
-}
+#ifdef SQLITE_ENABLE_IOTRACE
+static FILE *iotrace = 0;
+#endif
 
 /*
-** SQL function:  shell_add_schema(S,X)
-**
-** Add the schema name X to the CREATE statement in S and return the result.
-** Examples:
-**
-**    CREATE TABLE t1(x)   ->   CREATE TABLE xyz.t1(x);
-**
-** Also works on
+** Output routines that are able to redirect to memory rather than
+** doing actually I/O.
+**                                                Works like.
+**                                                --------------
+**   cli_printf(FILE*, const char*, ...);         fprintf()
+**   cli_puts(const char*, FILE*);                fputs()
+**   cli_vprintf(FILE*, const char*, va_list);    vfprintf()
 **
-**    CREATE INDEX
-**    CREATE UNIQUE INDEX
-**    CREATE VIEW
-**    CREATE TRIGGER
-**    CREATE VIRTUAL TABLE
+** These are just thin wrappers with the following added semantics:
+** If the file-scope variable cli_output_capture is not NULL, and
+** if the FILE* argument is stdout or stderr, then rather than
+** writing to stdout/stdout, append the text to the cli_output_capture
+** variable.
 **
-** This UDF is used by the .schema command to insert the schema name of
-** attached databases into the middle of the sqlite_schema.sql field.
+** The cli_exit(int) routine works like exit() except that it
+** first dumps any capture output to stdout.
 */
-static void shellAddSchemaName(
-  sqlite3_context *pCtx,
-  int nVal,
-  sqlite3_value **apVal
-){
-  static const char *aPrefix[] = {
-     "TABLE",
-     "INDEX",
-     "UNIQUE INDEX",
-     "VIEW",
-     "TRIGGER",
-     "VIRTUAL TABLE"
-  };
-  int i = 0;
-  const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
-  const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
-  const char *zName = (const char*)sqlite3_value_text(apVal[2]);
-  sqlite3 *db = sqlite3_context_db_handle(pCtx);
-  UNUSED_PARAMETER(nVal);
-  if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){
-    for(i=0; i<ArraySize(aPrefix); i++){
-      int n = strlen30(aPrefix[i]);
-      if( cli_strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
-        char *z = 0;
-        char *zFake = 0;
-        if( zSchema ){
-          char cQuote = quoteChar(zSchema);
-          if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
-            z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
-          }else{
-            z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
-          }
-        }
-        if( zName
-         && aPrefix[i][0]=='V'
-         && (zFake = shellFakeSchema(db, zSchema, zName))!=0
-        ){
-          if( z==0 ){
-            z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
-          }else{
-            z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
-          }
-          sqlite3_free(zFake);
-        }
-        if( z ){
-          sqlite3_result_text(pCtx, z, -1, sqlite3_free);
-          return;
-        }
-      }
-    }
+static sqlite3_str *cli_output_capture = 0; 
+static int cli_printf(FILE *out, const char *zFormat, ...){
+  va_list ap;
+  int rc;
+  va_start(ap,zFormat);
+  if( cli_output_capture && (out==stdout || out==stderr) ){
+    sqlite3_str_vappendf(cli_output_capture, zFormat, ap);
+    rc = 1;
+  }else{
+    rc = sqlite3_vfprintf(out, zFormat, ap);
   }
-  sqlite3_result_value(pCtx, apVal[0]);
+  va_end(ap);
+  return rc;
+}
+static int cli_puts(const char *zText, FILE *out){
+  if( cli_output_capture && (out==stdout || out==stderr) ){
+    sqlite3_str_appendall(cli_output_capture, zText);
+    return 1;
+  }
+  return sqlite3_fputs(zText, out);
+}
+#if 0 /* Not currently used - available if we need it later */
+static int cli_vprintf(FILE *out, const char *zFormat, va_list ap){
+  if( cli_output_capture && (out==stdout || out==stderr) ){
+    sqlite3_str_vappendf(cli_output_capture, zFormat, ap);
+    return 1;
+  }else{
+    return sqlite3_vfprintf(out, zFormat, ap);
+  }
+}
+#endif
+static void cli_exit(int rc){
+  if( cli_output_capture ){
+    char *z = sqlite3_str_finish(cli_output_capture);
+    sqlite3_fputs(z, stdout);
+    fflush(stdout);
+  }
+  exit(rc);
 }
 
-/*
-** The source code for several run-time loadable extensions is inserted
-** below by the ../tool/mkshellc.tcl script.  Before processing that included
-** code, we need to override some macros to make the included program code
-** work here in the middle of this regular program.
-*/
-#define SQLITE_EXTENSION_INIT1
-#define SQLITE_EXTENSION_INIT2(X) (void)(X)
 
-INCLUDE ../ext/misc/windirent.h
-INCLUDE ../ext/misc/memtrace.c
-INCLUDE ../ext/misc/pcachetrace.c
-INCLUDE ../ext/misc/shathree.c
-INCLUDE ../ext/misc/sha1.c
-INCLUDE ../ext/misc/uint.c
-INCLUDE ../ext/misc/decimal.c
-INCLUDE ../ext/misc/base64.c
-INCLUDE ../ext/misc/base85.c
-INCLUDE ../ext/misc/ieee754.c
-INCLUDE ../ext/misc/series.c
-INCLUDE ../ext/misc/regexp.c
-#ifndef SQLITE_SHELL_FIDDLE
-INCLUDE ../ext/misc/fileio.c
-INCLUDE ../ext/misc/completion.c
-INCLUDE ../ext/misc/appendvfs.c
-#endif
-#ifdef SQLITE_HAVE_ZLIB
-INCLUDE ../ext/misc/zipfile.c
-INCLUDE ../ext/misc/sqlar.c
-#endif
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
-INCLUDE ../ext/expert/sqlite3expert.h
-INCLUDE ../ext/expert/sqlite3expert.c
-#endif
-INCLUDE ../ext/intck/sqlite3intck.h
-INCLUDE ../ext/intck/sqlite3intck.c
-INCLUDE ../ext/misc/stmtrand.c
-INCLUDE ../ext/misc/vfstrace.c
+#define eputz(z) cli_puts(z,stderr)
+#define sputz(fp,z) cli_puts(z,fp)
 
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
-#define SQLITE_SHELL_HAVE_RECOVER 1
-#else
-#define SQLITE_SHELL_HAVE_RECOVER 0
-#endif
-#if SQLITE_SHELL_HAVE_RECOVER
-INCLUDE ../ext/recover/sqlite3recover.h
-# ifndef SQLITE_HAVE_SQLITE3R
-INCLUDE ../ext/recover/dbdata.c
-INCLUDE ../ext/recover/sqlite3recover.c
-# endif /* SQLITE_HAVE_SQLITE3R */
-#endif
-#ifdef SQLITE_SHELL_EXTSRC
-# include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC)
-#endif
+/* A version of strcmp() that works with NULL values */
+static int cli_strcmp(const char *a, const char *b){
+  if( a==0 ) a = "";
+  if( b==0 ) b = "";
+  return strcmp(a,b);
+}
+static int cli_strncmp(const char *a, const char *b, size_t n){
+  if( a==0 ) a = "";
+  if( b==0 ) b = "";
+  return strncmp(a,b,n);
+}
 
-#if defined(SQLITE_ENABLE_SESSION)
-/*
-** State information for a single open session
+/* Return the current wall-clock time in microseconds since the
+** Unix epoch (1970-01-01T00:00:00Z)
 */
-typedef struct OpenSession OpenSession;
-struct OpenSession {
-  char *zName;             /* Symbolic name for this session */
-  int nFilter;             /* Number of xFilter rejection GLOB patterns */
-  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
-  sqlite3_session *p;      /* The open session */
-};
+static sqlite3_int64 timeOfDay(void){
+#if defined(_WIN64) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
+  sqlite3_uint64 t;
+  FILETIME tm;
+  GetSystemTimePreciseAsFileTime(&tm);
+  t =  ((u64)tm.dwHighDateTime<<32) | (u64)tm.dwLowDateTime;
+  t += 116444736000000000LL;
+  t /= 10;
+  return t;
+#elif defined(_WIN32)
+  static sqlite3_vfs *clockVfs = 0;
+  sqlite3_int64 t;
+  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
+  if( clockVfs==0 ) return 0;  /* Never actually happens */
+  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
+    clockVfs->xCurrentTimeInt64(clockVfs, &t);
+  }else{
+    double r;
+    clockVfs->xCurrentTime(clockVfs, &r);
+    t = (sqlite3_int64)(r*86400000.0);
+  }
+  return t*1000;
+#else
+  struct timeval sNow;
+  (void)gettimeofday(&sNow,0);
+  return ((i64)sNow.tv_sec)*1000000 + sNow.tv_usec;
 #endif
+}
 
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
-typedef struct ExpertInfo ExpertInfo;
-struct ExpertInfo {
-  sqlite3expert *pExpert;
-  int bVerbose;
-};
-#endif
 
-/* All the parameters that determine how to render query results.
-*/
-typedef struct Mode {
-  u8 autoExplain;        /* Automatically turn on .explain mode */
-  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
-  u8 autoEQPtrace;       /* autoEQP is in trace mode */
-  u8 scanstatsOn;        /* True to display scan stats before each finalize */
-  u8 bAutoScreenWidth;   /* Using the TTY to determine screen width */
-  u8 mFlags;             /* MFLG_ECHO, MFLG_CRLF, etc. */
-  u8 eMode;              /* One of the MODE_ values */
-  sqlite3_qrf_spec spec; /* Spec to be passed into QRF */
-} Mode;
 
-/* Flags for Mode.mFlags */
-#define MFLG_ECHO  0x01  /* Echo inputs to output */
-#define MFLG_CRLF  0x02  /* Use CR/LF output line endings */
-#define MFLG_HDR   0x04  /* .header used to change headers on/off */
+/* This is variant of the standard-library strncpy() routine with the
+** one change that the destination string is always zero-terminated, even
+** if there is no zero-terminator in the first n-1 characters of the source
+** string.
+*/
+static char *shell_strncpy(char *dest, const char *src, size_t n){
+  size_t i;
+  for(i=0; i<n-1 && src[i]!=0; i++) dest[i] = src[i];
+  dest[i] = 0;
+  return dest;
+}
 
+/*
+** strcpy() workalike to squelch an unwarranted link-time warning
+** from OpenBSD.
+*/
+static void shell_strcpy(char *dest, const char *src){
+  while( (*(dest++) = *(src++))!=0 ){}
+}
 
 /*
-** State information about the database connection is contained in an
-** instance of the following structure.
+** Optionally disable dynamic continuation prompt.
+** Unless disabled, the continuation prompt shows open SQL lexemes if any,
+** or open parentheses level if non-zero, or continuation prompt as set.
+** This facility interacts with the scanner and process_input() where the
+** below 5 macros are used.
 */
-typedef struct ShellState ShellState;
-struct ShellState {
-  sqlite3 *db;           /* The database */
-  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
-  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
-  u8 nEqpLevel;          /* Depth of the EQP output graph */
-  u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
-  u8 bSafeMode;          /* True to prohibit unsafe operations */
-  u8 bSafeModePersist;   /* The long-term value of bSafeMode */
-  u8 eRestoreState;      /* See comments above doAutoDetectRestore() */
-  unsigned statsOn;      /* True to display memory stats before each finalize */
-  unsigned mEqpLines;    /* Mask of vertical lines in the EQP output graph */
-  u8 nPopOutput;         /* Revert .output settings when reaching zero */
-  u8 nPopMode;           /* Revert .mode settings when reaching zero */
-  u8 enableTimer;        /* Enable the timer.  2: permanently 1: only once */
-  int inputNesting;      /* Track nesting level of .read and other redirects */
-  double prevTimer;      /* Last reported timer value */
-  double tmProgress;     /* --timeout option for .progress */
-  i64 lineno;            /* Line number of last line read from in */
-  const char *zInFile;   /* Name of the input file */
-  int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
-  FILE *in;              /* Read commands from this stream */
-  FILE *out;             /* Write results here */
-  FILE *traceOut;        /* Output for sqlite3_trace() */
-  int nErr;              /* Number of errors seen */
-  int writableSchema;    /* True if PRAGMA writable_schema=ON */
-  int nCheck;            /* Number of ".check" commands run */
-  unsigned nProgress;    /* Number of progress callbacks encountered */
-  unsigned mxProgress;   /* Maximum progress callbacks before failing */
-  unsigned flgProgress;  /* Flags for the progress callback */
-  unsigned shellFlgs;    /* Various flags */
-  unsigned nTestRun;     /* Number of test cases run */
-  unsigned nTestErr;     /* Number of test cases that failed */
-  sqlite3_int64 szMax;   /* --maxsize argument to .open */
-  char *zDestTable;      /* Name of destination table when MODE_Insert */
-  char *zTempFile;       /* Temporary file that might need deleting */
-  char *zErrPrefix;      /* Alternative error message prefix */
-  char zTestcase[30];    /* Name of current test case */
-  char outfile[FILENAME_MAX]; /* Filename for *out */
-  sqlite3_stmt *pStmt;   /* Current statement if any. */
-  FILE *pLog;            /* Write log output here */
-  Mode mode;             /* Current display mode */
-  Mode modePrior;        /* Backup */
-  struct SavedMode {     /* Ability to define custom mode configurations */
-    char *zTag;            /* Name of this saved mode */
-    Mode mode;              /* The saved mode */
-  } *aSavedModes;        /* Array of saved .mode settings. system malloc() */
-  int nSavedModes;       /* Number of saved .mode settings */
-  struct AuxDb {         /* Storage space for auxiliary database connections */
-    sqlite3 *db;               /* Connection pointer */
-    const char *zDbFilename;   /* Filename used to open the connection */
-    char *zFreeOnClose;        /* Free this memory allocation on close */
-#if defined(SQLITE_ENABLE_SESSION)
-    int nSession;              /* Number of active sessions */
-    OpenSession aSession[4];   /* Array of sessions.  [0] is in focus. */
-#endif
-  } aAuxDb[5],           /* Array of all database connections */
-    *pAuxDb;             /* Currently active database connection */
-  char *zNonce;          /* Nonce for temporary safe-mode escapes */
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_AUTHORIZATION)
-  ExpertInfo expert;     /* Valid if previous command was ".expert OPT..." */
-#endif
-  struct DotCmdLine {    /* Info about arguments to a dot-command */
-    const char *zOrig;      /* Original text of the dot-command */
-    char *zCopy;            /* Copy of zOrig, from malloc() */
-    int nAlloc;             /* Size of allocates for arrays below */
-    int nArg;               /* Number of argument slots actually used */
-    char **azArg;           /* Pointer to each argument, dequoted */
-    int *aiOfst;            /* Offset into zOrig[] for start of each arg */
-    char *abQuot;           /* True if the argment was originally quoted */
-  } dot;
-#ifdef SQLITE_SHELL_FIDDLE
-  struct {
-    const char * zInput; /* Input string from wasm/JS proxy */
-    const char * zPos;   /* Cursor pos into zInput */
-    const char * zDefaultDbName; /* Default name for db file */
-  } wasm;
-#endif
-};
-
-#ifdef SQLITE_SHELL_FIDDLE
-static ShellState shellState;
-#endif
+#ifdef SQLITE_OMIT_DYNAPROMPT
+# define CONTINUATION_PROMPT continuePrompt
+# define CONTINUE_PROMPT_RESET
+# define CONTINUE_PROMPT_AWAITS(p,s)
+# define CONTINUE_PROMPT_AWAITC(p,c)
+# define CONTINUE_PAREN_INCR(p,n)
+# define CONTINUE_PROMPT_PSTATE 0
+typedef void *t_NoDynaPrompt;
+# define SCAN_TRACKER_REFTYPE t_NoDynaPrompt
+#else
+# define CONTINUATION_PROMPT dynamicContinuePrompt()
+# define CONTINUE_PROMPT_RESET \
+  do {setLexemeOpen(&dynPrompt,0,0); trackParenLevel(&dynPrompt,0);} while(0)
+# define CONTINUE_PROMPT_AWAITS(p,s) \
+  if(p && stdin_is_interactive) setLexemeOpen(p, s, 0)
+# define CONTINUE_PROMPT_AWAITC(p,c) \
+  if(p && stdin_is_interactive) setLexemeOpen(p, 0, c)
+# define CONTINUE_PAREN_INCR(p,n) \
+  if(p && stdin_is_interactive) (trackParenLevel(p,n))
+# define CONTINUE_PROMPT_PSTATE (&dynPrompt)
+typedef struct DynaPrompt *t_DynaPromptRef;
+# define SCAN_TRACKER_REFTYPE t_DynaPromptRef
 
+static struct DynaPrompt {
+  char dynamicPrompt[PROMPT_LEN_MAX];
+  char acAwait[2];
+  int inParenLevel;
+  char *zScannerAwaits;
+} dynPrompt = { {0}, {0}, 0, 0 };
 
-/* Allowed values for ShellState.mode.autoEQP
-*/
-#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
-#define AUTOEQP_on       1           /* Automatic EQP is on */
-#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
-#define AUTOEQP_full     3           /* Show full EXPLAIN */
+/* Record parenthesis nesting level change, or force level to 0. */
+static void trackParenLevel(struct DynaPrompt *p, int ni){
+  p->inParenLevel += ni;
+  if( ni==0 ) p->inParenLevel = 0;
+  p->zScannerAwaits = 0;
+}
 
-/* Allowed values for ShellState.openMode
-*/
-#define SHELL_OPEN_UNSPEC      0      /* No open-mode specified */
-#define SHELL_OPEN_NORMAL      1      /* Normal database file */
-#define SHELL_OPEN_APPENDVFS   2      /* Use appendvfs */
-#define SHELL_OPEN_ZIPFILE     3      /* Use the zipfile virtual table */
-#define SHELL_OPEN_DESERIALIZE 4      /* Open using sqlite3_deserialize() */
-#define SHELL_OPEN_HEXDB       5      /* Use "dbtotxt" output as data source */
+/* Record that a lexeme is opened, or closed with args==0. */
+static void setLexemeOpen(struct DynaPrompt *p, char *s, char c){
+  if( s!=0 || c==0 ){
+    p->zScannerAwaits = s;
+    p->acAwait[0] = 0;
+  }else{
+    p->acAwait[0] = c;
+    p->zScannerAwaits = p->acAwait;
+  }
+}
 
-/* Allowed values for ShellState.eTraceType
-*/
-#define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
-#define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
-#define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */
+/* Upon demand, derive the continuation prompt to display. */
+static char *dynamicContinuePrompt(void){
+  if( continuePrompt[0]==0
+      || (dynPrompt.zScannerAwaits==0 && dynPrompt.inParenLevel == 0) ){
+    return continuePrompt;
+  }else{
+    if( dynPrompt.zScannerAwaits ){
+      size_t ncp = strlen(continuePrompt);
+      size_t ndp = strlen(dynPrompt.zScannerAwaits);
+      if( ndp > ncp-3 ) return continuePrompt;
+      shell_strcpy(dynPrompt.dynamicPrompt, dynPrompt.zScannerAwaits);
+      while( ndp<3 ) dynPrompt.dynamicPrompt[ndp++] = ' ';
+      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
+              PROMPT_LEN_MAX-4);
+    }else{
+      if( dynPrompt.inParenLevel>9 ){
+        shell_strncpy(dynPrompt.dynamicPrompt, "(..", 4);
+      }else if( dynPrompt.inParenLevel<0 ){
+        shell_strncpy(dynPrompt.dynamicPrompt, ")x!", 4);
+      }else{
+        shell_strncpy(dynPrompt.dynamicPrompt, "(x.", 4);
+        dynPrompt.dynamicPrompt[2] = (char)('0'+dynPrompt.inParenLevel);
+      }
+      shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3,
+                    PROMPT_LEN_MAX-4);
+    }
+  }
+  return dynPrompt.dynamicPrompt;
+}
+#endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */
 
-/* Bits in the ShellState.flgProgress variable */
-#define SHELL_PROGRESS_QUIET 0x01  /* Omit announcing every progress callback */
-#define SHELL_PROGRESS_RESET 0x02  /* Reset the count when the progress
-                                   ** callback limit is reached, and for each
-                                   ** top-level SQL statement */
-#define SHELL_PROGRESS_ONCE  0x04  /* Cancel the --limit after firing once */
-#define SHELL_PROGRESS_TMOUT 0x08  /* Stop after tmProgress seconds */
+/* Indicate out-of-memory and exit. */
+static void shell_out_of_memory(void){
+  eputz("Error: out of memory\n");
+  cli_exit(1);
+}
 
-/* Names of values for Mode.spec.eEsc and Mode.spec.eText
+/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
+** out-of-memory error.
 */
-static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
-static const char *qrfQuoteNames[] = 
-      { "off","off","sql","hex","csv","tcl","json","relaxed"};
+static void shell_check_oom(const void *p){
+  if( p==0 ) shell_out_of_memory();
+}
 
 /*
-** These are the allowed shellFlgs values
+** This routine works like printf in that its first argument is a
+** format string and subsequent arguments are values to be substituted
+** in place of % fields.  The result of formatting this string
+** is written to iotrace.
 */
-#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
-#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
-#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
-#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
-#define SHFLG_NoErrLineno    0x00000010 /* Omit line numbers from error msgs */
-#define SHFLG_CountChanges   0x00000020 /* .changes setting */
-#define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
-#define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */
-#define SHFLG_TestingMode    0x00000400 /* allow unsafe testing features */
+#ifdef SQLITE_ENABLE_IOTRACE
+static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
+  va_list ap;
+  char *z;
+  if( iotrace==0 ) return;
+  va_start(ap, zFormat);
+  z = sqlite3_vmprintf(zFormat, ap);
+  va_end(ap);
+  cli_printf(iotrace, "%s", z);
+  sqlite3_free(z);
+}
+#endif
 
 /*
-** Macros for testing and setting shellFlgs
+** Compute a string length that is limited to what can be stored in
+** lower 30 bits of a 32-bit signed integer.
 */
-#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
-#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
-#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
+static int strlen30(const char *z){
+  size_t n;
+  if( z==0 ) return 0;
+  n = strlen(z);
+  return n>0x3fffffff ? 0x3fffffff : (int)n;
+}
 
 /*
-** These are the allowed values for Mode.eMode.  There is a lot of overlap
-** between these values and the Mode.spec.eStyle values, but they are not
-** one-to-one, and thus need to be tracked separately.
+** Return open FILE * if zFile exists, can be opened for read
+** and is an ordinary file or a character stream source.
+** Otherwise return 0.
 */
-#define MODE_Ascii     0  /* Use ASCII unit and record separators (0x1F/0x1E) */
-#define MODE_Box       1  /* Unicode box-drawing characters */
-#define MODE_C         2  /* Comma-separated list of C-strings */
-#define MODE_Column    3  /* One record per line in neat columns */
-#define MODE_Count     4  /* Output only a count of the rows of output */
-#define MODE_Csv       5  /* Quote strings, numbers are plain */
-#define MODE_Html      6  /* Generate an XHTML table */
-#define MODE_Insert    7  /* Generate SQL "insert" statements */
-#define MODE_JAtom     8  /* Comma-separated list of JSON atoms */
-#define MODE_JObject   9  /* One JSON object per row */
-#define MODE_Json     10  /* Output JSON */
-#define MODE_Line     11  /* One column per line.  Blank line between records */
-#define MODE_List     12  /* One record per line with a separator */
-#define MODE_Markdown 13  /* Markdown formatting */
-#define MODE_Off      14  /* No query output shown */
-#define MODE_Psql     15  /* Similar to psql */
-#define MODE_QBox     16  /* BOX with SQL-quoted content */
-#define MODE_Quote    17  /* Quote values as for SQL */
-#define MODE_Split    18  /* Split-column mode */
-#define MODE_Table    19  /* MySQL-style table formatting */
-#define MODE_Tabs     20  /* Tab-separated values */
-#define MODE_Tcl      21  /* Space-separated list of TCL strings */
-#define MODE_Www      22  /* Full web-page output */
-
-#define MODE_BUILTIN  22  /* Maximum built-in mode */
-#define MODE_BATCH    50  /* Default mode for batch processing */
-#define MODE_TTY      51  /* Default mode for interactive processing */
-#define MODE_USER     75  /* First user-defined mode */
-#define MODE_N_USER   25  /* Maximum number of user-defined modes */
-
-/*
-** Information about built-in display modes
+static FILE * openChrSource(const char *zFile){
+#if defined(_WIN32) || defined(WIN32)
+  struct __stat64 x = {0};
+# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
+  /* On Windows, open first, then check the stream nature. This order
+  ** is necessary because _stat() and sibs, when checking a named pipe,
+  ** effectively break the pipe as its supplier sees it. */
+  FILE *rv = sqlite3_fopen(zFile, "rb");
+  if( rv==0 ) return 0;
+  if( _fstat64(_fileno(rv), &x) != 0
+      || !STAT_CHR_SRC(x.st_mode)){
+    fclose(rv);
+    rv = 0;
+  }
+  return rv;
+#else
+  struct stat x = {0};
+  int rc = stat(zFile, &x);
+# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
+  if( rc!=0 ) return 0;
+  if( STAT_CHR_SRC(x.st_mode) ){
+    return sqlite3_fopen(zFile, "rb");
+  }else{
+    return 0;
+  }
+#endif
+#undef STAT_CHR_SRC
+}
+
+/*
+** This routine reads a line of text from FILE in, stores
+** the text in memory obtained from malloc() and returns a pointer
+** to the text.  NULL is returned at end of file, or if malloc()
+** fails, or if the length of the line is longer than about a gigabyte.
+**
+** If zLine is not NULL then it is a malloced buffer returned from
+** a previous call to this routine that may be reused.
 */
-typedef struct ModeInfo ModeInfo;
-struct ModeInfo {
-  char zName[9];         /* Symbolic name of the mode */
-  unsigned char eCSep;   /* Column separator */
-  unsigned char eRSep;   /* Row separator */
-  unsigned char eNull;   /* Null representation */
-  unsigned char eText;   /* Default text encoding */
-  unsigned char eHdr;    /* Default header encoding. */
-  unsigned char eBlob;   /* Default blob encoding. */
-  unsigned char bHdr;    /* Show headers by default.  0: n/a, 1: no 2: yes */
-  unsigned char eStyle;  /* Underlying QRF style */
-  unsigned char eCx;     /* 0: other, 1: line, 2: columnar */
-  unsigned char mFlg;    /* Flags. 1=border-off 2=split-column */
+static char *local_getline(char *zLine, FILE *in){
+  int nLine = zLine==0 ? 0 : 100;
+  int n = 0;
+
+  while( 1 ){
+    if( n+100>nLine ){
+      if( nLine>=1073741773 ){
+        free(zLine);
+        return 0;
+      }
+      nLine = nLine*2 + 100;
+      zLine = realloc(zLine, nLine);
+      shell_check_oom(zLine);
+    }
+    if( sqlite3_fgets(&zLine[n], nLine - n, in)==0 ){
+      if( n==0 ){
+        free(zLine);
+        return 0;
+      }
+      zLine[n] = 0;
+      break;
+    }
+    while( zLine[n] ) n++;
+    if( n>0 && zLine[n-1]=='\n' ){
+      n--;
+      if( n>0 && zLine[n-1]=='\r' ) n--;
+      zLine[n] = 0;
+      break;
+    }
+  }
+  return zLine;
+}
+
+/*
+** Retrieve a single line of input text.
+**
+** If in==0 then read from standard input and prompt before each line.
+** If isContinuation is true, then a continuation prompt is appropriate.
+** If isContinuation is zero, then the main prompt should be used.
+**
+** If zPrior is not NULL then it is a buffer from a prior call to this
+** routine that can be reused.
+**
+** The result is stored in space obtained from malloc() and must either
+** be freed by the caller or else passed back into this routine via the
+** zPrior argument for reuse.
+*/
+#ifndef SQLITE_SHELL_FIDDLE
+static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){
+  char *zPrompt;
+  char *zResult;
+  FILE *in = p->in;
+  if( in!=0 ){
+    zResult = local_getline(zPrior, in);
+  }else{
+    zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt;
+#if SHELL_USE_LOCAL_GETLINE
+    sputz(stdout, zPrompt);
+    fflush(stdout);
+    do{
+      zResult = local_getline(zPrior, stdin);
+      zPrior = 0;
+      /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
+      if( zResult==0 ) sqlite3_sleep(50);
+    }while( zResult==0 && seenInterrupt>0 );
+#else
+    free(zPrior);
+    zResult = shell_readline(zPrompt);
+    while( zResult==0 ){
+      /* ^C trap creates a false EOF, so let "interrupt" thread catch up. */
+      sqlite3_sleep(50);
+      if( seenInterrupt==0 ) break;
+      zResult = shell_readline("");
+    }
+    if( zResult && *zResult ) shell_add_history(zResult);
+#endif
+  }
+  return zResult;
+}
+#endif /* !SQLITE_SHELL_FIDDLE */
+
+/*
+** Return the value of a hexadecimal digit.  Return -1 if the input
+** is not a hex digit.
+*/
+static int hexDigitValue(char c){
+  if( c>='0' && c<='9' ) return c - '0';
+  if( c>='a' && c<='f' ) return c - 'a' + 10;
+  if( c>='A' && c<='F' ) return c - 'A' + 10;
+  return -1;
+}
+
+/*
+** Interpret zArg as an integer value, possibly with suffixes.
+**
+** If the value specified by zArg is outside the range of values that
+** can be represented using a 64-bit twos-complement integer, then return
+** the nearest representable value.
+*/
+static sqlite3_int64 integerValue(const char *zArg){
+  sqlite3_uint64 v = 0;
+  static const struct { char *zSuffix; unsigned int iMult; } aMult[] = {
+    { "KiB", 1024 },
+    { "MiB", 1024*1024 },
+    { "GiB", 1024*1024*1024 },
+    { "KB",  1000 },
+    { "MB",  1000000 },
+    { "GB",  1000000000 },
+    { "K",   1000 },
+    { "M",   1000000 },
+    { "G",   1000000000 },
+  };
+  int i;
+  int isNeg = 0;
+  if( zArg[0]=='-' ){
+    isNeg = 1;
+    zArg++;
+  }else if( zArg[0]=='+' ){
+    zArg++;
+  }
+  if( zArg[0]=='0' && zArg[1]=='x' ){
+    int x;
+    zArg += 2;
+    while( (x = hexDigitValue(zArg[0]))>=0 ){
+      if( v > 0x0fffffffffffffffULL ) goto integer_overflow;
+      v = (v<<4) + x;
+      zArg++;
+    }
+  }else{
+    while( IsDigit(zArg[0]) ){
+      if( v>=922337203685477580LL ){
+        if( v>922337203685477580LL || zArg[0]>='8' ) goto integer_overflow;
+      }
+      v = v*10 + (zArg[0] - '0');
+      zArg++;
+    }
+  }
+  for(i=0; i<ArraySize(aMult); i++){
+    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
+      if( 0x7fffffffffffffffULL/aMult[i].iMult < v ) goto integer_overflow;
+      v *= aMult[i].iMult;
+      break;
+    }
+  }
+  if( isNeg && v>0x7fffffffffffffffULL ) goto integer_overflow;
+  return isNeg? -(sqlite3_int64)v : (sqlite3_int64)v;
+integer_overflow:
+  return isNeg ? (i64)0x8000000000000000LL : 0x7fffffffffffffffLL;
+}
+
+/*
+** A variable length string to which one can append text.
+*/
+typedef struct ShellText ShellText;
+struct ShellText {
+  char *zTxt;       /* The text */
+  i64 n;            /* Number of bytes of zTxt[] actually used */
+  i64 nAlloc;       /* Number of bytes allocated for zTxt[] */
 };
 
-/* String constants used by built-in modes */
-static const char *aModeStr[] = 
-  /* 0    1       2       3       4     5        6        7        8    */
-   { 0,   "\n",   "|",    " ",    ",",  "\r\n",  "\036",  "\037",  "\t",
-     "",  "NULL", "null", "\"\"", ": ",                                   };
-  /* 9    10      11      12      13                                    */
+/*
+** Initialize and destroy a ShellText object
+*/
+static void initText(ShellText *p){
+  memset(p, 0, sizeof(*p));
+}
+static void freeText(ShellText *p){
+  sqlite3_free(p->zTxt);
+  initText(p);
+}
+
+/* zIn is either a pointer to a NULL-terminated string in memory obtained
+** from malloc(), or a NULL pointer. The string pointed to by zAppend is
+** added to zIn, and the result returned in memory obtained from malloc().
+** zIn, if it was not NULL, is freed.
+**
+** If the third argument, quote, is not '\0', then it is used as a
+** quote character for zAppend.
+*/
+static void appendText(ShellText *p, const char *zAppend, char quote){
+  i64 len;
+  i64 i;
+  i64 nAppend = strlen30(zAppend);
+
+  len = nAppend+p->n+1;
+  if( quote ){
+    len += 2;
+    for(i=0; i<nAppend; i++){
+      if( zAppend[i]==quote ) len++;
+    }
+  }
+
+  if( p->zTxt==0 || p->n+len>=p->nAlloc ){
+    p->nAlloc = p->nAlloc*2 + len + 20;
+    p->zTxt = sqlite3_realloc64(p->zTxt, p->nAlloc);
+    shell_check_oom(p->zTxt);
+  }
+
+  if( quote ){
+    char *zCsr = p->zTxt+p->n;
+    *zCsr++ = quote;
+    for(i=0; i<nAppend; i++){
+      *zCsr++ = zAppend[i];
+      if( zAppend[i]==quote ) *zCsr++ = quote;
+    }
+    *zCsr++ = quote;
+    p->n = (i64)(zCsr - p->zTxt);
+    *zCsr = '\0';
+  }else{
+    memcpy(p->zTxt+p->n, zAppend, nAppend);
+    p->n += nAppend;
+    p->zTxt[p->n] = '\0';
+  }
+}
 
-static const ModeInfo aModeInfo[] = {
-/*   zName      eCSep  eRSep eNull eText eHdr eBlob bHdr eStyle eCx mFlg */
-  { "ascii",    7,     6,    9,    1,    1,    0,   1,   12,    0,  0 },
-  { "box",      0,     0,    9,    1,    1,    0,   2,   1,     2,  0 },
-  { "c",        4,     1,    10,   5,    5,    4,   1,   12,    0,  0 },
-  { "column",   0,     0,    9,    1,    1,    0,   2,   2,     2,  0 },
-  { "count",    0,     0,    0,    0,    0,    0,   0,   3,     0,  0 },
-  { "csv",      4,     5,    9,    3,    3,    0,   1,   12,    0,  0 },
-  { "html",     0,     0,    9,    4,    4,    0,   2,   7,     0,  0 },
-  { "insert",   0,     0,    10,   2,    2,    0,   1,   8,     0,  0 },
-  { "jatom",    4,     1,    11,   6,    6,    0,   1,   12,    0,  0 },
-  { "jobject",  0,     1,    11,   6,    6,    0,   0,   10,    0,  0 },
-  { "json",     0,     0,    11,   6,    6,    0,   0,   9,     0,  0 },
-  { "line",     13,    1,    9,    1,    1,    0,   0,   11,    1,  0 },
-  { "list",     2,     1,    9,    1,    1,    0,   1,   12,    0,  0 },
-  { "markdown", 0,     0,    9,    1,    1,    0,   2,   13,    2,  0 },
-  { "off",      0,     0,    0,    0,    0,    0,   0,   14,    0,  0 },
-  { "psql",     0,     0,    9,    1,    1,    0,   2,   19,    2,  1 },
-  { "qbox",     0,     0,    10,   2,    1,    0,   2,   1,     2,  0 },
-  { "quote",    4,     1,    10,   2,    2,    0,   1,   12,    0,  0 },
-  { "split",    0,     0,    9,    1,    1,    0,   1,   2,     2,  2 },
-  { "table",    0,     0,    9,    1,    1,    0,   2,   19,    2,  0 },
-  { "tabs",     8,     1,    9,    3,    3,    0,   1,   12,    0,  0 },
-  { "tcl",      3,     1,    12,   5,    5,    4,   1,   12,    0,  0 },
-  { "www",      0,     0,    9,    4,    4,    0,   2,   7,     0,  0 }
-};     /*       |     /     /      |     /    /     |    |       \
-       **       |    /     /       |    /    /      |    |        \_ 2: columnar
-       ** Index into aModeStr[]    |   /    /       |    |           1: line
-       **                          |  /    /        |    |           0: other
-       **                          | /    /         |     \
-       **           text encoding  |/     |    show |      \
-       **      v-------------------'      |   hdrs? |       The QRF style
-       **      0: n/a                blob |   v-----'
-       **      1: plain        v_---------'   0: n/a
-       **      2: sql          0: auto        1: no         
-       **      3: csv          1: as-text     2: yes
-       **      4: html         2: sql
-       **      5: c            3: hex
-       **      6: json         4: c
-       **                      5: json
-       **                      6: size
-       ******************************************************************/
 /*
-** These are the column/row/line separators used by the various
-** import/export modes.
+** Attempt to determine if identifier zName needs to be quoted, either
+** because it contains non-alphanumeric characters, or because it is an
+** SQLite keyword.  Be conservative in this estimate:  When in doubt assume
+** that quoting is required.
+**
+** Return '"' if quoting is required.  Return 0 if no quoting is required.
 */
-#define SEP_Column    "|"
-#define SEP_Row       "\n"
-#define SEP_Tab       "\t"
-#define SEP_Space     " "
-#define SEP_Comma     ","
-#define SEP_CrLf      "\r\n"
-#define SEP_Unit      "\x1F"
-#define SEP_Record    "\x1E"
+static char quoteChar(const char *zName){
+  int i;
+  if( zName==0 ) return '"';
+  if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '"';
+  for(i=0; zName[i]; i++){
+    if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '"';
+  }
+  return sqlite3_keyword_check(zName, i) ? '"' : 0;
+}
 
 /*
-** Default values for the various QRF limits
+** Construct a fake object name and column list to describe the structure
+** of the view, virtual table, or table valued function zSchema.zName.
+**
+** The returned string comes from sqlite3_mprintf() and should be freed
+** by the caller using sqlite3_free().
 */
-#ifndef DFLT_CHAR_LIMIT
-# define DFLT_CHAR_LIMIT  300
-#endif
-#ifndef DFLT_LINE_LIMIT
-# define DFLT_LINE_LIMIT  5
-#endif
-#ifndef DFLT_TITLE_LIMIT
-# define DFLT_TITLE_LIMIT 20
-#endif
-#ifndef DFLT_MULTI_INSERT
-# define DFLT_MULTI_INSERT 3000
-#endif
+static char *shellFakeSchema(
+  sqlite3 *db,            /* The database connection containing the vtab */
+  const char *zSchema,    /* Schema of the database holding the vtab */
+  const char *zName       /* The name of the virtual table */
+){
+  sqlite3_stmt *pStmt = 0;
+  char *zSql;
+  ShellText s;
+  char cQuote;
+  char *zDiv = "(";
+  int nRow = 0;
+
+  zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
+                         zSchema ? zSchema : "main", zName);
+  shell_check_oom(zSql);
+  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+  sqlite3_free(zSql);
+  initText(&s);
+  if( zSchema ){
+    cQuote = quoteChar(zSchema);
+    if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
+    appendText(&s, zSchema, cQuote);
+    appendText(&s, ".", 0);
+  }
+  cQuote = quoteChar(zName);
+  appendText(&s, zName, cQuote);
+  while( sqlite3_step(pStmt)==SQLITE_ROW ){
+    const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
+    nRow++;
+    appendText(&s, zDiv, 0);
+    zDiv = ",";
+    if( zCol==0 ) zCol = "";
+    cQuote = quoteChar(zCol);
+    appendText(&s, zCol, cQuote);
+  }
+  appendText(&s, ")", 0);
+  sqlite3_finalize(pStmt);
+  if( nRow==0 ){
+    freeText(&s);
+    s.zTxt = 0;
+  }
+  return s.zTxt;
+}
 
 /*
-** Limit input nesting via .read or any other input redirect.
-** It's not too expensive, so a generous allowance can be made.
+** SQL function:  strtod(X)
+**
+** Use the C-library strtod() function to convert string X into a double.
+** Used for comparing the accuracy of SQLite's internal text-to-float conversion
+** routines against the C-library.
 */
-#define MAX_INPUT_NESTING 25
+static void shellStrtod(
+  sqlite3_context *pCtx,
+  int nVal,
+  sqlite3_value **apVal
+){
+  char *z = (char*)sqlite3_value_text(apVal[0]);
+  UNUSED_PARAMETER(nVal);
+  if( z==0 ) return;
+  sqlite3_result_double(pCtx, strtod(z,0));
+}
+
+/*
+** SQL function:  dtostr(X)
+**
+** Use the C-library printf() function to convert real value X into a string.
+** Used for comparing the accuracy of SQLite's internal float-to-text conversion
+** routines against the C-library.
+*/
+static void shellDtostr(
+  sqlite3_context *pCtx,
+  int nVal,
+  sqlite3_value **apVal
+){
+  double r = sqlite3_value_double(apVal[0]);
+  int n = nVal>=2 ? sqlite3_value_int(apVal[1]) : 26;
+  char z[400];
+  if( n<1 ) n = 1;
+  if( n>350 ) n = 350;
+  sprintf(z, "%#+.*e", n, r);
+  sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
+}
+
+/*
+** SQL function:  shell_add_schema(S,X)
+**
+** Add the schema name X to the CREATE statement in S and return the result.
+** Examples:
+**
+**    CREATE TABLE t1(x)   ->   CREATE TABLE xyz.t1(x);
+**
+** Also works on
+**
+**    CREATE INDEX
+**    CREATE UNIQUE INDEX
+**    CREATE VIEW
+**    CREATE TRIGGER
+**    CREATE VIRTUAL TABLE
+**
+** This UDF is used by the .schema command to insert the schema name of
+** attached databases into the middle of the sqlite_schema.sql field.
+*/
+static void shellAddSchemaName(
+  sqlite3_context *pCtx,
+  int nVal,
+  sqlite3_value **apVal
+){
+  static const char *aPrefix[] = {
+     "TABLE",
+     "INDEX",
+     "UNIQUE INDEX",
+     "VIEW",
+     "TRIGGER",
+     "VIRTUAL TABLE"
+  };
+  int i = 0;
+  const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
+  const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
+  const char *zName = (const char*)sqlite3_value_text(apVal[2]);
+  sqlite3 *db = sqlite3_context_db_handle(pCtx);
+  UNUSED_PARAMETER(nVal);
+  if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){
+    for(i=0; i<ArraySize(aPrefix); i++){
+      int n = strlen30(aPrefix[i]);
+      if( cli_strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
+        char *z = 0;
+        char *zFake = 0;
+        if( zSchema ){
+          char cQuote = quoteChar(zSchema);
+          if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
+            z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
+          }else{
+            z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
+          }
+        }
+        if( zName
+         && aPrefix[i][0]=='V'
+         && (zFake = shellFakeSchema(db, zSchema, zName))!=0
+        ){
+          if( z==0 ){
+            z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
+          }else{
+            z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
+          }
+          sqlite3_free(zFake);
+        }
+        if( z ){
+          sqlite3_result_text(pCtx, z, -1, sqlite3_free);
+          return;
+        }
+      }
+    }
+  }
+  sqlite3_result_value(pCtx, apVal[0]);
+}
+
 
 /************************* BEGIN PERFORMANCE TIMER *****************************/
 #if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
@@ -12373,12 +12375,13 @@ static void echo_group_input(ShellState *p, const char *zDo){
 ** impl because we need the global shellState and cannot access it from that
 ** function without moving lots of code around (creating a larger/messier diff).
 */
-static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
+static char *one_input_line(ShellState *p, char *zPrior, int isContinuation){
   /* Parse the next line from shellState.wasm.zInput. */
   const char *zBegin = shellState.wasm.zPos;
   const char *z = zBegin;
   char *zLine = 0;
   i64 nZ = 0;
+  FILE *in = p->in;
 
   UNUSED_PARAMETER(in);
   UNUSED_PARAMETER(isContinuation);
@@ -12436,7 +12439,7 @@ static int process_input(ShellState *p, const char *zSrc){
   CONTINUE_PROMPT_RESET;
   while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
     fflush(p->out);
-    zLine = one_input_line(p->in, zLine, nSql>0);
+    zLine = one_input_line(p, zLine, nSql>0);
     if( zLine==0 ){
       /* End of input */
       if( p->in==0 && stdin_is_interactive ) cli_puts("\n", p->out);