]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Merge the latest trunk enhancments into the reuse-schema branch.
authordrh <>
Fri, 27 Mar 2026 13:13:32 +0000 (13:13 +0000)
committerdrh <>
Fri, 27 Mar 2026 13:13:32 +0000 (13:13 +0000)
FossilOrigin-Name: 337a9f3f4724f5f46ca5cd000a3742f5f3c9682f23f9f9fcdd6aa42f1501b3d3

1  2 
manifest
manifest.uuid
src/main.c
src/shell.c.in
src/sqlite.h.in
src/tclsqlite.c
src/vdbe.c

diff --cc manifest
index 8f778ae44a57354018021d593ddd5f523f69925a,0a15ae3ac3efde51c47c958edfb4fe51bbc38223..c17e532796ae7b2eaf7accdb578fa346d417fb61
+++ b/manifest
@@@ -1,5 -1,5 +1,5 @@@
- C Merge\sall\sthe\slatest\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch
- D 2026-03-21T18:42:16.487
 -C Add\sa\scomment\sshowing\sreserved\sfile-control\snumbers\sto\ssqlite3.h
 -D 2026-03-27T11:46:11.333
++C Merge\sthe\slatest\strunk\senhancments\sinto\sthe\sreuse-schema\sbranch.
++D 2026-03-27T13:13:32.943
  F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
  F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
  F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@@ -697,10 -694,10 +697,10 @@@ F src/hash.h 46b92795a95bfefb210f52f0c3
  F src/hwtime.h 21c2cf1f736e7b97502c3674d0c386db3f06870d6f10d0cf8174e2a4b8cb726e
  F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
  F src/insert.c dfd311b0ac2d4f6359e62013db67799757f4d2cc56cca5c10f4888acfbbfa3fd
- F src/json.c 7401618493219bb605408be48d2ea5ed5c9055f1c3b733268331eb0174048746
+ F src/json.c 5027b856cd9b621dc9ba66b211e21a440ccdc63cefdefb44c51e7d3ac550d1a4
  F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
  F src/loadext.c 56a542244fbefc739a2ef57fac007c16b2aefdb4377f584e9547db2ce3e071f9
- F src/main.c b66ee684a0cf1e0f3f1e8735f6f4de525ad624c1981fbfc4bee2aeca920e07eb
 -F src/main.c 387bb9d0216d6d35b221481ba8e661d94ad043060cd89581b6422c269ce680a0
++F src/main.c 2b8335837a1c778f4976a3b3242f74205bdda0b5100c43b6a882fd3b147dd85e
  F src/malloc.c 422f7e0498e1c9ef967f06283b6f2c0b16db6b905d8e06f6dbc8baaa3e4e6c5a
  F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
  F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@@ -730,22 -727,22 +730,22 @@@ F src/parse.y 3b784d6083380a950e3b1b32c
  F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
  F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba
  F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
 -F src/pragma.c 789ef67117b74b5be0a2db6681f7f0c55e6913791b9da309aefd280de2c8a74d
 -F src/prepare.c f6a6e28a281bd1d1da12f47d370a81af46159b40f73bf7fa0b276b664f9c8b7d
 +F src/pragma.c 16bfe475bb6bcc14eb9dbb2847fec6383fb7361fc4cd23b390e3e10daf089bd7
 +F src/prepare.c 40312476d751aa775fc7de9620c3b6fe42b268f3f49f832eb8c27588a7dd9cbe
- F src/printf.c 9cff219dba73b1aa9a8113e83e962f03f7bea8b6eb51cefb25bc468d5a69fb2d
+ F src/printf.c a440c004a3892cc3d334fa90e0ae59720918fe26c16942d4d45e2534640ce786
  F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
  F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
  F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
  F src/select.c ffe199f025a0dd74670d2a77232bdea364a4d7b36f32c64a6572d39ba6a11576
- F src/shell.c.in 6702a4092c573e69b1496a380b1fb50be0b37409d66c8a10d616c0ef92cbd97f
- F src/sqlite.h.in 924eeda59f2ae7693fa761471844787fe7330f922c1e1b63f3b9c83199884e87
 -F src/shell.c.in 91ee40ec3f75192362cbaa0ad85316140b8dde00a184113d73a837fb6173dbcc
 -F src/sqlite.h.in e7acbb01518f05c5a342149ec1eeb1afcdccf9b90a6e9770a4893ae9a3c756ae
++F src/shell.c.in 5df627411c239325de5a08410859c90eb18a3cf21516a169a6652f8a8ad8241e
++F src/sqlite.h.in caaacf199e9e7df2e1ff4eba893d7f23a76e9487e9d6e9805c3ca125deff8416
  F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
  F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
 -F src/sqliteInt.h 9716721fb57e32938a1d30a84560ce7633c63860a2209e188c87afad15d4b464
 +F src/sqliteInt.h 0836d90234eb4e3131ea2d3b54184620a6bfcc44e7600362505a58e944ed5cad
- F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
+ F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
 -F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
 +F src/status.c 426bbfac49c3501675d3c2db63834a29d78e14587695e81327f86689d7eb1593
  F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
- F src/tclsqlite.c 3d9855481d3169acc9030975ef5aed233effcef6043d68963820c18cc40900f2
 -F src/tclsqlite.c 7401c73c917a4d1b380c896a324c8d8eb533a999559d9e339d479596553bebfd
++F src/tclsqlite.c 2a8c7f54fc667a4d4aa71c93bf547b7ca05d33bd3f96394ec80462c25a7bb1ed
  F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
  F src/test1.c 3e3b013f59ffcb57dce00c90d55907072d71d4e970cb0a590cb261efe11bae9c
  F src/test2.c 2b9ab96bba63a1c369d5769390475259ad210f144a877805f2e32e563f9e93c1
@@@ -802,15 -798,15 +802,15 @@@ F src/trigger.c 5497958d682b6269924b19c
  F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
  F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
  F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
- F src/util.c 51662502243422f3238a7220fe00de32d9a7d0d3149dd33c6d721d7039cb2e74
+ F src/util.c c24ed5647e81eea3abe3d9878b709425a3e843cbf4580ac442ed46b93824138c
 -F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
 -F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
 -F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
 +F src/vacuum.c 13b7c418199d6344e341eb6ae3759b7886f925c0f5920d30925dbe45fc933fbd
- F src/vdbe.c 2f981ecab2985a3427966395cc8628256015ec2ef2f9b994edec17eff4afd13e
++F src/vdbe.c 3c797690341d92a6330088fa2212f8dd3c2329ceadc46ad0b36e6fcca4c853bf
 +F src/vdbe.h e085d965c37e722b60303ec9345f42bd14a89e0c5ae9760ce648f24d6848fd86
  F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
  F src/vdbeapi.c 6cdcbe5c7afa754c998e73d2d5d2805556268362914b952811bdfb9c78a37cf1
 -F src/vdbeaux.c 81687c55682b9f4d942186695f4f7fa4743c564a985e0889def52eded9076d61
 -F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692
 +F src/vdbeaux.c fa683c4bdfa13c7b8f03b76698cce403589000d81114f1a0e77d6f7946f6bb48
 +F src/vdbeblob.c ad7e1db18b53074702ce267f48106c12fb1ac76b54b6eb3aefa4188411eb7c46
- F src/vdbemem.c 05610ea8423c4c852a9039e47fb6a2706d4d848758602ebf30da6c3212344695
+ F src/vdbemem.c 5af6cf1253ac2aed0612b85138a1faf43f30ad38777d554db6c85b7281fa79fb
  F src/vdbesort.c b69220f4ea9ffea5fdef34d968c60305444eea909252a81933b54c296d9cca70
  F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41
  F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
@@@ -2209,8 -2195,8 +2209,8 @@@ F tool/warnings-clang.sh bbf6a1e685e534
  F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
  F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
  F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
- P c35597d4db59385e973c8f555f2b5016147a9f767829583e1d3c08ccd740a035 8e1d0c4eac303cd0834449f4792605c0ed983db1f360af42300f0048dadbbef8
- R 5d4905f7dd58ea224aeb6b3b1ab8915b
 -P c5af6a10245b6b847d30002806c1577b020c36ab27f7b1cf202ade136aa4779c
 -R 51ff65a6bd1b538cf25dd22d8d1484ee
++P f54462c4b1838d613785adf63073347ff8019de8b6438806f3dfa79eb9847593 cd472d7c85f3fda54bba5166eae72b5f9b86861c4a1160583e8ee902ba992255
++R 569fb353a340a32b263662c23b972d63
  U drh
- Z 4a3579fa736f68fb57d702cfcd2c09d7
 -Z d9594447f664fc3f5df800bf2243aaf0
++Z 586663d6d2f0e2701d4ccd34adf4afd8
  # Remove this line to create a well-formed Fossil manifest.
diff --cc manifest.uuid
index b69da68a6ce98ab6db37f064c6510ad95d84faf0,0f229184a665424f793915cf3ff582fbeb51b5ed..3ac159f1eb380d5fe34f3616c07455507d19d5d5
@@@ -1,1 -1,1 +1,1 @@@
- f54462c4b1838d613785adf63073347ff8019de8b6438806f3dfa79eb9847593
 -cd472d7c85f3fda54bba5166eae72b5f9b86861c4a1160583e8ee902ba992255
++337a9f3f4724f5f46ca5cd000a3742f5f3c9682f23f9f9fcdd6aa42f1501b3d3
diff --cc src/main.c
Simple merge
diff --cc src/shell.c.in
index e183ab03227a91111fc3c643d6f355ba8ab94f4e,c931055ca2c7b961b25e99ea7476f768a56fa210..f71e062747bfacf6db0020be6006026f0ee8e95d
@@@ -246,1147 -262,1131 +262,1133 @@@ INCLUDE ../ext/qrf/qrf.
  #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;
- }
- /* 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;
-   }
- }
 -#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 */
++#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_READONLY     4     /* Open a normal database read-only */
++#define SHELL_OPEN_DESERIALIZE  5     /* Open using sqlite3_deserialize() */
++#define SHELL_OPEN_HEXDB        6     /* Use "dbtotxt" output as data source */
++#define SHELL_OPEN_SHAREDSCHEMA 7     /* Open for schema reuse */
  
- /* 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) */
+ /* 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 */
  
- /* Indicate out-of-memory and exit. */
- static void shell_out_of_memory(void){
-   eputz("Error: out of memory\n");
-   cli_exit(1);
- }
+ /* 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 */
  
- /* Check a pointer to see if it is NULL.  If it is NULL, exit with an
- ** out-of-memory error.
+ /* Names of values for Mode.spec.eEsc and Mode.spec.eText
  */
- static void shell_check_oom(const void *p){
-   if( p==0 ) shell_out_of_memory();
- }
+ static const char *qrfEscNames[] = { "auto", "off", "ascii", "symbol" };
+ static const char *qrfQuoteNames[] = 
+       { "off","off","sql","hex","csv","tcl","json","relaxed"};
  
  /*
- ** 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.
+ ** These are the allowed shellFlgs values
  */
- #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 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 */
  
  /*
- ** Compute a string length that is limited to what can be stored in
- ** lower 30 bits of a 32-bit signed integer.
+ ** Macros for testing and setting shellFlgs
  */
- static int strlen30(const char *z){
-   size_t n;
-   if( z==0 ) return 0;
-   n = strlen(z);
-   return n>0x3fffffff ? 0x3fffffff : (int)n;
- }
+ #define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
+ #define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
+ #define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
  
  /*
- ** Return open FILE * if zFile exists, can be opened for read
- ** and is an ordinary file or a character stream source.
- ** Otherwise return 0.
+ ** 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 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
- }
+ #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 */
  
  /*
- ** 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.
+ ** Information about built-in display modes
  */
- static char *local_getline(char *zLine, FILE *in){
-   int nLine = zLine==0 ? 0 : 100;
-   int n = 0;
+ 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 */
+ };
  
-   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;
- }
+ /* 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
+        ******************************************************************/
+ /*
+ ** These are the column/row/line separators used by the various
+ ** import/export modes.
+ */
+ #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.
- */
- 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;
-         }
-       }
-     }
+ ** The cli_exit(int) routine works like exit() except that it
+ ** first dumps any capture output to stdout.
+ */
+ 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_READONLY     4     /* Open a normal database read-only */
- #define SHELL_OPEN_DESERIALIZE  5     /* Open using sqlite3_deserialize() */
- #define SHELL_OPEN_HEXDB        6     /* Use "dbtotxt" output as data source */
- #define SHELL_OPEN_SHAREDSCHEMA 7     /* Open for schema reuse */
+ /* 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 */
+ 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
+ }
  
  /*
- ** Information about built-in display modes
+ ** 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)
diff --cc src/sqlite.h.in
Simple merge
diff --cc src/tclsqlite.c
Simple merge
diff --cc src/vdbe.c
Simple merge