/ Check-in [74183a5f]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Experimental changes to the command line shell to make it work better with Unicode on Windows.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | altShellFix
Files: files | file ages | folders
SHA1: 74183a5f803999e1d4e288851c72519c3c53f6b5
User & Date: mistachkin 2016-04-04 02:16:44
Context
2016-04-04
02:33
Refinements to the previous check-in. check-in: b36dfdff user: mistachkin tags: altShellFix
02:16
Experimental changes to the command line shell to make it work better with Unicode on Windows. check-in: 74183a5f user: mistachkin tags: altShellFix
02:05
More refactoring and cleanup work on the Win32 string conversion and utility routines. check-in: 02ccb444 user: mistachkin tags: altShellFix
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/shell.c.

    86     86   # define shell_read_history(X) linenoiseHistoryLoad(X)
    87     87   # define shell_write_history(X) linenoiseHistorySave(X)
    88     88   # define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
    89     89   # define shell_readline(X) linenoise(X)
    90     90   
    91     91   #else
    92     92   
    93         -# define shell_read_history(X) 
           93  +# define shell_read_history(X)
    94     94   # define shell_write_history(X)
    95     95   # define shell_stifle_history(X)
    96     96   
    97     97   # define SHELL_USE_LOCAL_GETLINE 1
    98     98   #endif
    99     99   
   100    100   
................................................................................
   131    131   #define isatty(x) 1
   132    132   #endif
   133    133   
   134    134   /* ctype macros that work with signed characters */
   135    135   #define IsSpace(X)  isspace((unsigned char)X)
   136    136   #define IsDigit(X)  isdigit((unsigned char)X)
   137    137   #define ToLower(X)  (char)tolower((unsigned char)X)
          138  +
          139  +#if defined(_WIN32) || defined(WIN32)
          140  +#include <windows.h>
          141  +
          142  +/* string conversion routines only needed on Win32 */
          143  +extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
          144  +extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
          145  +extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
          146  +#endif
   138    147   
   139    148   /* On Windows, we normally run with output mode of TEXT so that \n characters
   140    149   ** are automatically translated into \r\n.  However, this behavior needs
   141    150   ** to be disabled in some cases (ex: when generating CSV output and when
   142    151   ** rendering quoted strings that contain \n characters).  The following
   143    152   ** routines take care of that.
   144    153   */
   145    154   #if defined(_WIN32) || defined(WIN32)
   146         -static void setBinaryMode(FILE *out){
   147         -  fflush(out);
   148         -  _setmode(_fileno(out), _O_BINARY);
          155  +static void setBinaryMode(FILE *file, int isOutput){
          156  +  if( isOutput ) fflush(file);
          157  +  _setmode(_fileno(file), _O_BINARY);
   149    158   }
   150         -static void setTextMode(FILE *out){
   151         -  fflush(out);
   152         -  _setmode(_fileno(out), _O_TEXT);
          159  +static void setTextMode(FILE *file, int isOutput){
          160  +  if( isOutput ) fflush(file);
          161  +  _setmode(_fileno(file), _O_TEXT);
   153    162   }
   154    163   #else
   155         -# define setBinaryMode(X)
   156         -# define setTextMode(X)
          164  +# define setBinaryMode(X,Y)
          165  +# define setTextMode(X,Y)
   157    166   #endif
   158    167   
   159    168   
   160    169   /* True if the timer is enabled */
   161    170   static int enableTimer = 0;
   162    171   
   163    172   /* Return the current wall-clock time */
................................................................................
   200    209       getrusage(RUSAGE_SELF, &sBegin);
   201    210       iBegin = timeOfDay();
   202    211     }
   203    212   }
   204    213   
   205    214   /* Return the difference of two time_structs in seconds */
   206    215   static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
   207         -  return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + 
          216  +  return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
   208    217            (double)(pEnd->tv_sec - pStart->tv_sec);
   209    218   }
   210    219   
   211    220   /*
   212    221   ** Print the timing results.
   213    222   */
   214    223   static void endTimer(void){
................................................................................
   225    234   
   226    235   #define BEGIN_TIMER beginTimer()
   227    236   #define END_TIMER endTimer()
   228    237   #define HAS_TIMER 1
   229    238   
   230    239   #elif (defined(_WIN32) || defined(WIN32))
   231    240   
   232         -#include <windows.h>
   233         -
   234    241   /* Saved resource information for the beginning of an operation */
   235    242   static HANDLE hProcess;
   236    243   static FILETIME ftKernelBegin;
   237    244   static FILETIME ftUserBegin;
   238    245   static sqlite3_int64 ftWallBegin;
   239    246   typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
   240    247                                       LPFILETIME, LPFILETIME);
................................................................................
   257    264         HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
   258    265         if( NULL != hinstLib ){
   259    266           getProcessTimesAddr =
   260    267               (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
   261    268           if( NULL != getProcessTimesAddr ){
   262    269             return 1;
   263    270           }
   264         -        FreeLibrary(hinstLib); 
          271  +        FreeLibrary(hinstLib);
   265    272         }
   266    273       }
   267    274     }
   268    275     return 0;
   269    276   }
   270    277   
   271    278   /*
................................................................................
   303    310   }
   304    311   
   305    312   #define BEGIN_TIMER beginTimer()
   306    313   #define END_TIMER endTimer()
   307    314   #define HAS_TIMER hasTimer()
   308    315   
   309    316   #else
   310         -#define BEGIN_TIMER 
          317  +#define BEGIN_TIMER
   311    318   #define END_TIMER
   312    319   #define HAS_TIMER 0
   313    320   #endif
   314    321   
   315    322   /*
   316    323   ** Used to prevent warnings about unused parameters
   317    324   */
................................................................................
   367    374   ** output from UTF-8 into MBCS.
   368    375   */
   369    376   #if defined(_WIN32) || defined(WIN32)
   370    377   void utf8_printf(FILE *out, const char *zFormat, ...){
   371    378     va_list ap;
   372    379     va_start(ap, zFormat);
   373    380     if( stdout_is_console && (out==stdout || out==stderr) ){
   374         -    extern char *sqlite3_win32_utf8_to_mbcs(const char*);
   375    381       char *z1 = sqlite3_vmprintf(zFormat, ap);
   376         -    char *z2 = sqlite3_win32_utf8_to_mbcs(z1);
          382  +    char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
   377    383       sqlite3_free(z1);
   378    384       fputs(z2, out);
   379    385       sqlite3_free(z2);
   380    386     }else{
   381    387       vfprintf(out, zFormat, ap);
   382    388     }
   383    389     va_end(ap);
................................................................................
   445    451       while( IsDigit(*z) ){ z++; }
   446    452       if( realnum ) *realnum = 1;
   447    453     }
   448    454     return *z==0;
   449    455   }
   450    456   
   451    457   /*
   452         -** A global char* and an SQL function to access its current value 
   453         -** from within an SQL statement. This program used to use the 
          458  +** A global char* and an SQL function to access its current value
          459  +** from within an SQL statement. This program used to use the
   454    460   ** sqlite_exec_printf() API to substitue a string into an SQL statement.
   455    461   ** The correct way to do this with sqlite3 is to use the bind API, but
   456    462   ** since the shell is built around the callback paradigm it would be a lot
   457    463   ** of work. Instead just use this hack, which is quite harmless.
   458    464   */
   459    465   static const char *zShellStatic = 0;
   460    466   static void shellstaticFunc(
................................................................................
   512    518         n--;
   513    519         if( n>0 && zLine[n-1]=='\r' ) n--;
   514    520         zLine[n] = 0;
   515    521         break;
   516    522       }
   517    523     }
   518    524   #if defined(_WIN32) || defined(WIN32)
   519         -  /* For interactive input on Windows systems, translate the 
          525  +  /* For interactive input on Windows systems, translate the
   520    526     ** multi-byte characterset characters into UTF-8. */
   521    527     if( stdin_is_interactive ){
   522         -    extern char *sqlite3_win32_mbcs_to_utf8(const char*);
   523         -    char *zTrans = sqlite3_win32_mbcs_to_utf8(zLine);
          528  +    char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
   524    529       if( zTrans ){
   525    530         int nTrans = strlen30(zTrans)+1;
   526    531         if( nTrans>nLine ){
   527    532           zLine = realloc(zLine, nTrans);
   528    533           if( zLine==0 ){
   529    534             sqlite3_free(zTrans);
   530    535             return 0;
................................................................................
   582    587     int nFilter;             /* Number of xFilter rejection GLOB patterns */
   583    588     char **azFilter;         /* Array of xFilter rejection GLOB patterns */
   584    589     sqlite3_session *p;      /* The open session */
   585    590   };
   586    591   #endif
   587    592   
   588    593   /*
   589         -** Shell output mode information from before ".explain on", 
          594  +** Shell output mode information from before ".explain on",
   590    595   ** saved so that it can be restored by ".explain off"
   591    596   */
   592    597   typedef struct SavedModeInfo SavedModeInfo;
   593    598   struct SavedModeInfo {
   594    599     int valid;          /* Is there legit data in here? */
   595    600     int mode;           /* Mode prior to ".explain on" */
   596    601     int showHeader;     /* The ".header" setting prior to ".explain on" */
................................................................................
   719    724   
   720    725   /*
   721    726   ** Output the given string as a quoted string using SQL quoting conventions.
   722    727   */
   723    728   static void output_quoted_string(FILE *out, const char *z){
   724    729     int i;
   725    730     int nSingle = 0;
   726         -  setBinaryMode(out);
          731  +  setBinaryMode(out, 1);
   727    732     for(i=0; z[i]; i++){
   728    733       if( z[i]=='\'' ) nSingle++;
   729    734     }
   730    735     if( nSingle==0 ){
   731    736       utf8_printf(out,"'%s'",z);
   732    737     }else{
   733    738       raw_printf(out,"'");
................................................................................
   742    747         }else{
   743    748           utf8_printf(out,"%s",z);
   744    749           break;
   745    750         }
   746    751       }
   747    752       raw_printf(out,"'");
   748    753     }
   749         -  setTextMode(out);
          754  +  setTextMode(out, 1);
   750    755   }
   751    756   
   752    757   /*
   753    758   ** Output the given string as a quoted according to C or TCL quoting rules.
   754    759   */
   755    760   static void output_c_string(FILE *out, const char *z){
   756    761     unsigned int c;
................................................................................
   784    789   ** Output the given string with characters that are special to
   785    790   ** HTML escaped.
   786    791   */
   787    792   static void output_html_string(FILE *out, const char *z){
   788    793     int i;
   789    794     if( z==0 ) z = "";
   790    795     while( *z ){
   791         -    for(i=0;   z[i] 
   792         -            && z[i]!='<' 
   793         -            && z[i]!='&' 
   794         -            && z[i]!='>' 
   795         -            && z[i]!='\"' 
          796  +    for(i=0;   z[i]
          797  +            && z[i]!='<'
          798  +            && z[i]!='&'
          799  +            && z[i]!='>'
          800  +            && z[i]!='\"'
   796    801               && z[i]!='\'';
   797    802           i++){}
   798    803       if( i>0 ){
   799    804         utf8_printf(out,"%.*s",i,z);
   800    805       }
   801    806       if( z[i]=='<' ){
   802    807         raw_printf(out,"&lt;");
................................................................................
   816    821   }
   817    822   
   818    823   /*
   819    824   ** If a field contains any character identified by a 1 in the following
   820    825   ** array, then the string must be quoted for CSV.
   821    826   */
   822    827   static const char needCsvQuote[] = {
   823         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   824         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   825         -  1, 0, 1, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0, 
   826         -  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
   827         -  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
   828         -  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
   829         -  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0, 
   830         -  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 1, 
   831         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   832         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   833         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   834         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   835         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   836         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   837         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
   838         -  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,   
          828  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          829  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          830  +  1, 0, 1, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0,
          831  +  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
          832  +  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
          833  +  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
          834  +  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
          835  +  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 1,
          836  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          837  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          838  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          839  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          840  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          841  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          842  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
          843  +  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
   839    844   };
   840    845   
   841    846   /*
   842    847   ** Output a single term of CSV.  Actually, p->colSeparator is used for
   843    848   ** the separator, which may or may not be a comma.  p->nullValue is
   844    849   ** the null value.  Strings are quoted if necessary.  The separator
   845    850   ** is only issued if bSep is true.
................................................................................
   848    853     FILE *out = p->out;
   849    854     if( z==0 ){
   850    855       utf8_printf(out,"%s",p->nullValue);
   851    856     }else{
   852    857       int i;
   853    858       int nSep = strlen30(p->colSeparator);
   854    859       for(i=0; z[i]; i++){
   855         -      if( needCsvQuote[((unsigned char*)z)[i]] 
   856         -         || (z[i]==p->colSeparator[0] && 
          860  +      if( needCsvQuote[((unsigned char*)z)[i]]
          861  +         || (z[i]==p->colSeparator[0] &&
   857    862                (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
   858    863           i = 0;
   859    864           break;
   860    865         }
   861    866       }
   862    867       if( i==0 ){
   863    868         putc('"', out);
................................................................................
  1059   1064           output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
  1060   1065           if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
  1061   1066         }
  1062   1067         utf8_printf(p->out, "%s", p->rowSeparator);
  1063   1068         break;
  1064   1069       }
  1065   1070       case MODE_Csv: {
  1066         -      setBinaryMode(p->out);
         1071  +      setBinaryMode(p->out, 1);
  1067   1072         if( p->cnt++==0 && p->showHeader ){
  1068   1073           for(i=0; i<nArg; i++){
  1069   1074             output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
  1070   1075           }
  1071   1076           utf8_printf(p->out, "%s", p->rowSeparator);
  1072   1077         }
  1073   1078         if( nArg>0 ){
  1074   1079           for(i=0; i<nArg; i++){
  1075   1080             output_csv(p, azArg[i], i<nArg-1);
  1076   1081           }
  1077   1082           utf8_printf(p->out, "%s", p->rowSeparator);
  1078   1083         }
  1079         -      setTextMode(p->out);
         1084  +      setTextMode(p->out, 1);
  1080   1085         break;
  1081   1086       }
  1082   1087       case MODE_Insert: {
  1083   1088         p->cnt++;
  1084   1089         if( azArg==0 ) break;
  1085   1090         utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
  1086   1091         if( p->showHeader ){
................................................................................
  1185   1190   }
  1186   1191   
  1187   1192   /* zIn is either a pointer to a NULL-terminated string in memory obtained
  1188   1193   ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
  1189   1194   ** added to zIn, and the result returned in memory obtained from malloc().
  1190   1195   ** zIn, if it was not NULL, is freed.
  1191   1196   **
  1192         -** If the third argument, quote, is not '\0', then it is used as a 
         1197  +** If the third argument, quote, is not '\0', then it is used as a
  1193   1198   ** quote character for zAppend.
  1194   1199   */
  1195   1200   static char *appendText(char *zIn, char const *zAppend, char quote){
  1196   1201     int len;
  1197   1202     int i;
  1198   1203     int nAppend = strlen30(zAppend);
  1199   1204     int nIn = (zIn?strlen30(zIn):0);
................................................................................
  1232   1237   
  1233   1238   /*
  1234   1239   ** Execute a query statement that will generate SQL output.  Print
  1235   1240   ** the result columns, comma-separated, on a line and then add a
  1236   1241   ** semicolon terminator to the end of that line.
  1237   1242   **
  1238   1243   ** If the number of columns is 1 and that column contains text "--"
  1239         -** then write the semicolon on a separate line.  That way, if a 
         1244  +** then write the semicolon on a separate line.  That way, if a
  1240   1245   ** "--" comment occurs at the end of the statement, the comment
  1241   1246   ** won't consume the semicolon terminator.
  1242   1247   */
  1243   1248   static int run_table_dump_query(
  1244   1249     ShellState *p,           /* Query context */
  1245   1250     const char *zSelect,     /* SELECT statement to extract content */
  1246   1251     const char *zFirstRow    /* Print before first row, if not NULL */
................................................................................
  1262   1267     while( rc==SQLITE_ROW ){
  1263   1268       if( zFirstRow ){
  1264   1269         utf8_printf(p->out, "%s", zFirstRow);
  1265   1270         zFirstRow = 0;
  1266   1271       }
  1267   1272       z = (const char*)sqlite3_column_text(pSelect, 0);
  1268   1273       utf8_printf(p->out, "%s", z);
  1269         -    for(i=1; i<nResult; i++){ 
         1274  +    for(i=1; i<nResult; i++){
  1270   1275         utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
  1271   1276       }
  1272   1277       if( z==0 ) z = "";
  1273   1278       while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
  1274   1279       if( z[0] ){
  1275   1280         raw_printf(p->out, "\n;\n");
  1276   1281       }else{
  1277   1282         raw_printf(p->out, ";\n");
  1278         -    }    
         1283  +    }
  1279   1284       rc = sqlite3_step(pSelect);
  1280   1285     }
  1281   1286     rc = sqlite3_finalize(pSelect);
  1282   1287     if( rc!=SQLITE_OK ){
  1283   1288       utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
  1284   1289                   sqlite3_errmsg(p->db));
  1285   1290       if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
................................................................................
  1330   1335         if( strncmp(aTrans[i].zPattern, z, n)==0 ){
  1331   1336           raw_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
  1332   1337           break;
  1333   1338         }
  1334   1339       }
  1335   1340     }
  1336   1341     fclose(in);
  1337         -}   
         1342  +}
  1338   1343   #endif
  1339   1344   
  1340   1345   
  1341   1346   /*
  1342   1347   ** Display memory stats.
  1343   1348   */
  1344   1349   static int display_stats(
................................................................................
  1346   1351     ShellState *pArg,           /* Pointer to ShellState */
  1347   1352     int bReset                  /* True to reset the stats */
  1348   1353   ){
  1349   1354     int iCur;
  1350   1355     int iHiwtr;
  1351   1356   
  1352   1357     if( pArg && pArg->out ){
  1353         -    
         1358  +
  1354   1359       iHiwtr = iCur = -1;
  1355   1360       sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
  1356   1361       raw_printf(pArg->out,
  1357   1362               "Memory Used:                         %d (max %d) bytes\n",
  1358   1363               iCur, iHiwtr);
  1359   1364       iHiwtr = iCur = -1;
  1360   1365       sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
................................................................................
  1430   1435       raw_printf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
  1431   1436               iCur);
  1432   1437       iHiwtr = iCur = -1;
  1433   1438       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
  1434   1439       raw_printf(pArg->out, "Page cache hits:                     %d\n", iCur);
  1435   1440       iHiwtr = iCur = -1;
  1436   1441       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
  1437         -    raw_printf(pArg->out, "Page cache misses:                   %d\n", iCur); 
         1442  +    raw_printf(pArg->out, "Page cache misses:                   %d\n", iCur);
  1438   1443       iHiwtr = iCur = -1;
  1439   1444       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
  1440         -    raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur); 
         1445  +    raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
  1441   1446       iHiwtr = iCur = -1;
  1442   1447       sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
  1443   1448       raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
  1444         -            iCur); 
         1449  +            iCur);
  1445   1450       iHiwtr = iCur = -1;
  1446   1451       sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
  1447   1452       raw_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
  1448         -            iCur); 
         1453  +            iCur);
  1449   1454     }
  1450   1455   
  1451   1456     if( pArg && pArg->out && db && pArg->pStmt ){
  1452   1457       iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
  1453   1458                                  bReset);
  1454   1459       raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
  1455   1460       iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
................................................................................
  1503   1508         }
  1504   1509         n++;
  1505   1510         sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
  1506   1511         sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
  1507   1512         sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
  1508   1513         utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
  1509   1514         rEstLoop *= rEst;
  1510         -      raw_printf(pArg->out, 
         1515  +      raw_printf(pArg->out,
  1511   1516             "         nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
  1512   1517             nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
  1513   1518         );
  1514   1519       }
  1515   1520     }
  1516   1521     raw_printf(pArg->out, "---------------------------\n");
  1517   1522   #endif
................................................................................
  1530   1535     }
  1531   1536     return 0;
  1532   1537   }
  1533   1538   
  1534   1539   /*
  1535   1540   ** If compiled statement pSql appears to be an EXPLAIN statement, allocate
  1536   1541   ** and populate the ShellState.aiIndent[] array with the number of
  1537         -** spaces each opcode should be indented before it is output. 
         1542  +** spaces each opcode should be indented before it is output.
  1538   1543   **
  1539   1544   ** The indenting rules are:
  1540   1545   **
  1541   1546   **     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
  1542   1547   **       all opcodes that occur between the p2 jump destination and the opcode
  1543   1548   **       itself by 2 spaces.
  1544   1549   **
................................................................................
  1635   1640     sqlite3_free(p->aiIndent);
  1636   1641     p->aiIndent = 0;
  1637   1642     p->nIndent = 0;
  1638   1643     p->iIndent = 0;
  1639   1644   }
  1640   1645   
  1641   1646   /*
  1642         -** Execute a statement or set of statements.  Print 
  1643         -** any result rows/columns depending on the current mode 
         1647  +** Execute a statement or set of statements.  Print
         1648  +** any result rows/columns depending on the current mode
  1644   1649   ** set via the supplied callback.
  1645   1650   **
  1646         -** This is very similar to SQLite's built-in sqlite3_exec() 
  1647         -** function except it takes a slightly different callback 
         1651  +** This is very similar to SQLite's built-in sqlite3_exec()
         1652  +** function except it takes a slightly different callback
  1648   1653   ** and callback data argument.
  1649   1654   */
  1650   1655   static int shell_exec(
  1651   1656     sqlite3 *db,                              /* An open database */
  1652   1657     const char *zSql,                         /* SQL to be evaluated */
  1653   1658     int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
  1654   1659                                               /* (not the same as sqlite3_exec) */
................................................................................
  1712   1717           pArg->cMode = pArg->mode;
  1713   1718           if( pArg->autoExplain
  1714   1719            && sqlite3_column_count(pStmt)==8
  1715   1720            && sqlite3_strlike("%EXPLAIN%", sqlite3_sql(pStmt),0)==0
  1716   1721           ){
  1717   1722             pArg->cMode = MODE_Explain;
  1718   1723           }
  1719         -      
         1724  +
  1720   1725           /* If the shell is currently in ".explain" mode, gather the extra
  1721   1726           ** data required to add indents to the output.*/
  1722   1727           if( pArg->cMode==MODE_Explain ){
  1723   1728             explain_data_prepare(pArg, pStmt);
  1724   1729           }
  1725   1730         }
  1726   1731   
................................................................................
  1738   1743             if( !pData ){
  1739   1744               rc = SQLITE_NOMEM;
  1740   1745             }else{
  1741   1746               char **azCols = (char **)pData;      /* Names of result columns */
  1742   1747               char **azVals = &azCols[nCol];       /* Results */
  1743   1748               int *aiTypes = (int *)&azVals[nCol]; /* Result types */
  1744   1749               int i, x;
  1745         -            assert(sizeof(int) <= sizeof(char *)); 
         1750  +            assert(sizeof(int) <= sizeof(char *));
  1746   1751               /* save off ptrs to column names */
  1747   1752               for(i=0; i<nCol; i++){
  1748   1753                 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
  1749   1754               }
  1750   1755               do{
  1751   1756                 /* extract the data and data types */
  1752   1757                 for(i=0; i<nCol; i++){
................................................................................
  1759   1764                   if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
  1760   1765                     rc = SQLITE_NOMEM;
  1761   1766                     break; /* from for */
  1762   1767                   }
  1763   1768                 } /* end for */
  1764   1769   
  1765   1770                 /* if data and types extracted successfully... */
  1766         -              if( SQLITE_ROW == rc ){ 
         1771  +              if( SQLITE_ROW == rc ){
  1767   1772                   /* call the supplied callback with the result row data */
  1768   1773                   if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
  1769   1774                     rc = SQLITE_ABORT;
  1770   1775                   }else{
  1771   1776                     rc = sqlite3_step(pStmt);
  1772   1777                   }
  1773   1778                 }
................................................................................
  1789   1794         }
  1790   1795   
  1791   1796         /* print loop-counters if required */
  1792   1797         if( pArg && pArg->scanstatsOn ){
  1793   1798           display_scanstats(db, pArg);
  1794   1799         }
  1795   1800   
  1796         -      /* Finalize the statement just executed. If this fails, save a 
         1801  +      /* Finalize the statement just executed. If this fails, save a
  1797   1802         ** copy of the error message. Otherwise, set zSql to point to the
  1798   1803         ** next statement to execute. */
  1799   1804         rc2 = sqlite3_finalize(pStmt);
  1800   1805         if( rc!=SQLITE_NOMEM ) rc = rc2;
  1801   1806         if( rc==SQLITE_OK ){
  1802   1807           zSql = zLeftover;
  1803   1808           while( IsSpace(zSql[0]) ) zSql++;
................................................................................
  1831   1836     ShellState *p = (ShellState *)pArg;
  1832   1837   
  1833   1838     UNUSED_PARAMETER(azCol);
  1834   1839     if( nArg!=3 ) return 1;
  1835   1840     zTable = azArg[0];
  1836   1841     zType = azArg[1];
  1837   1842     zSql = azArg[2];
  1838         -  
         1843  +
  1839   1844     if( strcmp(zTable, "sqlite_sequence")==0 ){
  1840   1845       zPrepStmt = "DELETE FROM sqlite_sequence;\n";
  1841   1846     }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
  1842   1847       raw_printf(p->out, "ANALYZE sqlite_master;\n");
  1843   1848     }else if( strncmp(zTable, "sqlite_", 7)==0 ){
  1844   1849       return 0;
  1845   1850     }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
................................................................................
  1861   1866   
  1862   1867     if( strcmp(zType, "table")==0 ){
  1863   1868       sqlite3_stmt *pTableInfo = 0;
  1864   1869       char *zSelect = 0;
  1865   1870       char *zTableInfo = 0;
  1866   1871       char *zTmp = 0;
  1867   1872       int nRow = 0;
  1868         -   
         1873  +
  1869   1874       zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
  1870   1875       zTableInfo = appendText(zTableInfo, zTable, '"');
  1871   1876       zTableInfo = appendText(zTableInfo, ");", 0);
  1872   1877   
  1873   1878       rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0);
  1874   1879       free(zTableInfo);
  1875   1880       if( rc!=SQLITE_OK || !pTableInfo ){
................................................................................
  1920   1925   ** Run zQuery.  Use dump_callback() as the callback routine so that
  1921   1926   ** the contents of the query are output as SQL statements.
  1922   1927   **
  1923   1928   ** If we get a SQLITE_CORRUPT error, rerun the query after appending
  1924   1929   ** "ORDER BY rowid DESC" to the end.
  1925   1930   */
  1926   1931   static int run_schema_dump_query(
  1927         -  ShellState *p, 
         1932  +  ShellState *p,
  1928   1933     const char *zQuery
  1929   1934   ){
  1930   1935     int rc;
  1931   1936     char *zErr = 0;
  1932   1937     rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
  1933   1938     if( rc==SQLITE_CORRUPT ){
  1934   1939       char *zQ2;
................................................................................
  2042   2047       ".session ?NAME? SUBCOMMAND ?ARGS...?\n"
  2043   2048       "If ?NAME? is omitted, the first defined session is used.\n"
  2044   2049       "Subcommands:\n"
  2045   2050       "   attach TABLE             Attach TABLE\n"
  2046   2051       "   changeset FILE           Write a changeset into FILE\n"
  2047   2052       "   close                    Close one session\n"
  2048   2053       "   enable ?BOOLEAN?         Set or query the enable bit\n"
  2049         -    "   filter GLOB...           Reject tables matching GLOBs\n" 
         2054  +    "   filter GLOB...           Reject tables matching GLOBs\n"
  2050   2055       "   indirect ?BOOLEAN?       Mark or query the indirect status\n"
  2051   2056       "   isempty                  Query whether the session is empty\n"
  2052   2057       "   list                     List currently open session names\n"
  2053   2058       "   open DB NAME             Open a new session on DB\n"
  2054   2059       "   patchset FILE            Write a patchset into FILE\n"
  2055   2060     );
  2056   2061   }
................................................................................
  2177   2182       sqlite3_open(p->zDbFilename, &p->db);
  2178   2183       globalDb = p->db;
  2179   2184       if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
  2180   2185         sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
  2181   2186             shellstaticFunc, 0, 0);
  2182   2187       }
  2183   2188       if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
  2184         -      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n", 
         2189  +      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
  2185   2190             p->zDbFilename, sqlite3_errmsg(p->db));
  2186   2191         if( keepAlive ) return;
  2187   2192         exit(1);
  2188   2193       }
  2189   2194   #ifndef SQLITE_OMIT_LOAD_EXTENSION
  2190   2195       sqlite3_enable_load_extension(p->db, 1);
  2191   2196   #endif
................................................................................
  2341   2346   */
  2342   2347   static void output_file_close(FILE *f){
  2343   2348     if( f && f!=stdout && f!=stderr ) fclose(f);
  2344   2349   }
  2345   2350   
  2346   2351   /*
  2347   2352   ** Try to open an output file.   The names "stdout" and "stderr" are
  2348         -** recognized and do the right thing.  NULL is returned if the output 
         2353  +** recognized and do the right thing.  NULL is returned if the output
  2349   2354   ** filename is "off".
  2350   2355   */
  2351   2356   static FILE *output_file_open(const char *zFile){
  2352   2357     FILE *f;
  2353   2358     if( strcmp(zFile,"stdout")==0 ){
  2354   2359       f = stdout;
  2355   2360     }else if( strcmp(zFile, "stderr")==0 ){
................................................................................
  2530   2535   ** work for WITHOUT ROWID tables.
  2531   2536   */
  2532   2537   static void tryToCloneData(
  2533   2538     ShellState *p,
  2534   2539     sqlite3 *newDb,
  2535   2540     const char *zTable
  2536   2541   ){
  2537         -  sqlite3_stmt *pQuery = 0; 
         2542  +  sqlite3_stmt *pQuery = 0;
  2538   2543     sqlite3_stmt *pInsert = 0;
  2539   2544     char *zQuery = 0;
  2540   2545     char *zInsert = 0;
  2541   2546     int rc;
  2542   2547     int i, j, n;
  2543   2548     int nTable = (int)strlen(zTable);
  2544   2549     int k = 0;
................................................................................
  2834   2839     utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
  2835   2840     for(i=0; i<ArraySize(aField); i++){
  2836   2841       int ofst = aField[i].ofst;
  2837   2842       unsigned int val = get4byteInt(aHdr + ofst);
  2838   2843       utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
  2839   2844       switch( ofst ){
  2840   2845         case 56: {
  2841         -        if( val==1 ) raw_printf(p->out, " (utf8)"); 
  2842         -        if( val==2 ) raw_printf(p->out, " (utf16le)"); 
  2843         -        if( val==3 ) raw_printf(p->out, " (utf16be)"); 
         2846  +        if( val==1 ) raw_printf(p->out, " (utf8)");
         2847  +        if( val==2 ) raw_printf(p->out, " (utf16le)");
         2848  +        if( val==3 ) raw_printf(p->out, " (utf16be)");
  2844   2849         }
  2845   2850       }
  2846   2851       raw_printf(p->out, "\n");
  2847   2852     }
  2848   2853     if( zDb==0 ){
  2849   2854       zSchemaTab = sqlite3_mprintf("main.sqlite_master");
  2850   2855     }else if( strcmp(zDb,"temp")==0 ){
................................................................................
  2896   2901     */
  2897   2902     while( zLine[h] && nArg<ArraySize(azArg) ){
  2898   2903       while( IsSpace(zLine[h]) ){ h++; }
  2899   2904       if( zLine[h]==0 ) break;
  2900   2905       if( zLine[h]=='\'' || zLine[h]=='"' ){
  2901   2906         int delim = zLine[h++];
  2902   2907         azArg[nArg++] = &zLine[h];
  2903         -      while( zLine[h] && zLine[h]!=delim ){ 
         2908  +      while( zLine[h] && zLine[h]!=delim ){
  2904   2909           if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
  2905         -        h++; 
         2910  +        h++;
  2906   2911         }
  2907   2912         if( zLine[h]==delim ){
  2908   2913           zLine[h++] = 0;
  2909   2914         }
  2910   2915         if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
  2911   2916       }else{
  2912   2917         azArg[nArg++] = &zLine[h];
................................................................................
  2985   2990         rc = 1;
  2986   2991       }
  2987   2992     }else
  2988   2993   
  2989   2994     if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
  2990   2995       if( nArg==2 ){
  2991   2996         if( booleanValue(azArg[1]) ){
  2992         -        setBinaryMode(p->out);
         2997  +        setBinaryMode(p->out, 1);
  2993   2998         }else{
  2994         -        setTextMode(p->out);
         2999  +        setTextMode(p->out, 1);
  2995   3000         }
  2996   3001       }else{
  2997   3002         raw_printf(stderr, "Usage: .binary on|off\n");
  2998   3003         rc = 1;
  2999   3004       }
  3000   3005     }else
  3001   3006   
................................................................................
  3059   3064       }
  3060   3065       raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
  3061   3066       raw_printf(p->out, "BEGIN TRANSACTION;\n");
  3062   3067       p->writableSchema = 0;
  3063   3068       sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
  3064   3069       p->nErr = 0;
  3065   3070       if( nArg==1 ){
  3066         -      run_schema_dump_query(p, 
         3071  +      run_schema_dump_query(p,
  3067   3072           "SELECT name, type, sql FROM sqlite_master "
  3068   3073           "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
  3069   3074         );
  3070         -      run_schema_dump_query(p, 
         3075  +      run_schema_dump_query(p,
  3071   3076           "SELECT name, type, sql FROM sqlite_master "
  3072   3077           "WHERE name=='sqlite_sequence'"
  3073   3078         );
  3074   3079         run_table_dump_query(p,
  3075   3080           "SELECT sql FROM sqlite_master "
  3076   3081           "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
  3077   3082         );
................................................................................
  3112   3117   
  3113   3118     if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
  3114   3119       if( nArg==2 ){
  3115   3120         p->autoEQP = booleanValue(azArg[1]);
  3116   3121       }else{
  3117   3122         raw_printf(stderr, "Usage: .eqp on|off\n");
  3118   3123         rc = 1;
  3119         -    }   
         3124  +    }
  3120   3125     }else
  3121   3126   
  3122   3127     if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
  3123   3128       if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
  3124   3129       rc = 2;
  3125   3130     }else
  3126   3131   
................................................................................
  3494   3499         { "trigger_depth",         SQLITE_LIMIT_TRIGGER_DEPTH             },
  3495   3500         { "worker_threads",        SQLITE_LIMIT_WORKER_THREADS            },
  3496   3501       };
  3497   3502       int i, n2;
  3498   3503       open_db(p, 0);
  3499   3504       if( nArg==1 ){
  3500   3505         for(i=0; i<ArraySize(aLimit); i++){
  3501         -        printf("%20s %d\n", aLimit[i].zLimitName, 
         3506  +        printf("%20s %d\n", aLimit[i].zLimitName,
  3502   3507                  sqlite3_limit(p->db, aLimit[i].limitCode, -1));
  3503   3508         }
  3504   3509       }else if( nArg>3 ){
  3505   3510         raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
  3506   3511         rc = 1;
  3507   3512         goto meta_command_exit;
  3508   3513       }else{
................................................................................
  3931   3936           }else{
  3932   3937             rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
  3933   3938           }
  3934   3939           if( rc ){
  3935   3940             printf("Error: error code %d\n", rc);
  3936   3941             rc = 0;
  3937   3942           }
  3938         -        if( pChng 
         3943  +        if( pChng
  3939   3944             && fwrite(pChng, szChng, 1, out)!=1 ){
  3940   3945             raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
  3941   3946                     szChng);
  3942   3947           }
  3943   3948           sqlite3_free(pChng);
  3944   3949           fclose(out);
  3945   3950         }
................................................................................
  3984   3989           nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
  3985   3990           pSession->azFilter = sqlite3_malloc( nByte );
  3986   3991           if( pSession->azFilter==0 ){
  3987   3992             raw_printf(stderr, "Error: out or memory\n");
  3988   3993             exit(1);
  3989   3994           }
  3990   3995           for(ii=1; ii<nCmd; ii++){
  3991         -          pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]); 
         3996  +          pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
  3992   3997           }
  3993   3998           pSession->nFilter = ii-1;
  3994   3999         }
  3995   4000       }else
  3996   4001   
  3997   4002       /* .session indirect ?BOOLEAN?
  3998   4003       ** Query or set the indirect flag
................................................................................
  4317   4322       if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
  4318   4323         utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
  4319   4324       }else{
  4320   4325         switch(testctrl){
  4321   4326   
  4322   4327           /* sqlite3_test_control(int, db, int) */
  4323   4328           case SQLITE_TESTCTRL_OPTIMIZATIONS:
  4324         -        case SQLITE_TESTCTRL_RESERVE:             
         4329  +        case SQLITE_TESTCTRL_RESERVE:
  4325   4330             if( nArg==3 ){
  4326         -            int opt = (int)strtol(azArg[2], 0, 0);        
         4331  +            int opt = (int)strtol(azArg[2], 0, 0);
  4327   4332               rc2 = sqlite3_test_control(testctrl, p->db, opt);
  4328   4333               raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
  4329   4334             } else {
  4330   4335               utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
  4331   4336                       azArg[1]);
  4332   4337             }
  4333   4338             break;
................................................................................
  4343   4348             } else {
  4344   4349               utf8_printf(stderr,"Error: testctrl %s takes no options\n",
  4345   4350                           azArg[1]);
  4346   4351             }
  4347   4352             break;
  4348   4353   
  4349   4354           /* sqlite3_test_control(int, uint) */
  4350         -        case SQLITE_TESTCTRL_PENDING_BYTE:        
         4355  +        case SQLITE_TESTCTRL_PENDING_BYTE:
  4351   4356             if( nArg==3 ){
  4352   4357               unsigned int opt = (unsigned int)integerValue(azArg[2]);
  4353   4358               rc2 = sqlite3_test_control(testctrl, opt);
  4354   4359               raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
  4355   4360             } else {
  4356   4361               utf8_printf(stderr,"Error: testctrl %s takes a single unsigned"
  4357   4362                              " int option\n", azArg[1]);
  4358   4363             }
  4359   4364             break;
  4360         -          
         4365  +
  4361   4366           /* sqlite3_test_control(int, int) */
  4362         -        case SQLITE_TESTCTRL_ASSERT:              
  4363         -        case SQLITE_TESTCTRL_ALWAYS:      
  4364         -        case SQLITE_TESTCTRL_NEVER_CORRUPT:        
         4367  +        case SQLITE_TESTCTRL_ASSERT:
         4368  +        case SQLITE_TESTCTRL_ALWAYS:
         4369  +        case SQLITE_TESTCTRL_NEVER_CORRUPT:
  4365   4370             if( nArg==3 ){
  4366         -            int opt = booleanValue(azArg[2]);        
         4371  +            int opt = booleanValue(azArg[2]);
  4367   4372               rc2 = sqlite3_test_control(testctrl, opt);
  4368   4373               raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
  4369   4374             } else {
  4370   4375               utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
  4371   4376                               azArg[1]);
  4372   4377             }
  4373   4378             break;
  4374   4379   
  4375   4380           /* sqlite3_test_control(int, char *) */
  4376   4381   #ifdef SQLITE_N_KEYWORD
  4377         -        case SQLITE_TESTCTRL_ISKEYWORD:           
         4382  +        case SQLITE_TESTCTRL_ISKEYWORD:
  4378   4383             if( nArg==3 ){
  4379         -            const char *opt = azArg[2];        
         4384  +            const char *opt = azArg[2];
  4380   4385               rc2 = sqlite3_test_control(testctrl, opt);
  4381   4386               raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
  4382   4387             } else {
  4383   4388               utf8_printf(stderr,
  4384   4389                           "Error: testctrl %s takes a single char * option\n",
  4385   4390                           azArg[1]);
  4386   4391             }
  4387   4392             break;
  4388   4393   #endif
  4389   4394   
  4390   4395           case SQLITE_TESTCTRL_IMPOSTER:
  4391   4396             if( nArg==5 ){
  4392         -            rc2 = sqlite3_test_control(testctrl, p->db, 
         4397  +            rc2 = sqlite3_test_control(testctrl, p->db,
  4393   4398                             azArg[2],
  4394   4399                             integerValue(azArg[3]),
  4395   4400                             integerValue(azArg[4]));
  4396   4401               raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
  4397   4402             }else{
  4398   4403               raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
  4399   4404             }
  4400   4405             break;
  4401   4406   
  4402         -        case SQLITE_TESTCTRL_BITVEC_TEST:         
  4403         -        case SQLITE_TESTCTRL_FAULT_INSTALL:       
  4404         -        case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: 
  4405         -        case SQLITE_TESTCTRL_SCRATCHMALLOC:       
         4407  +        case SQLITE_TESTCTRL_BITVEC_TEST:
         4408  +        case SQLITE_TESTCTRL_FAULT_INSTALL:
         4409  +        case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
         4410  +        case SQLITE_TESTCTRL_SCRATCHMALLOC:
  4406   4411           default:
  4407   4412             utf8_printf(stderr,
  4408   4413                         "Error: CLI support for testctrl %s not implemented\n",
  4409   4414                         azArg[1]);
  4410   4415             break;
  4411   4416         }
  4412   4417       }
  4413   4418     }else
  4414   4419   
  4415   4420     if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
  4416   4421       open_db(p, 0);
  4417   4422       sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
  4418   4423     }else
  4419         -    
         4424  +
  4420   4425     if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
  4421   4426       if( nArg==2 ){
  4422   4427         enableTimer = booleanValue(azArg[1]);
  4423   4428         if( enableTimer && !HAS_TIMER ){
  4424   4429           raw_printf(stderr, "Error: timer not available on this system.\n");
  4425   4430           enableTimer = 0;
  4426   4431         }
  4427   4432       }else{
  4428   4433         raw_printf(stderr, "Usage: .timer on|off\n");
  4429   4434         rc = 1;
  4430   4435       }
  4431   4436     }else
  4432         -  
         4437  +
  4433   4438     if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
  4434   4439       open_db(p, 0);
  4435   4440       if( nArg!=2 ){
  4436   4441         raw_printf(stderr, "Usage: .trace FILE|off\n");
  4437   4442         rc = 1;
  4438   4443         goto meta_command_exit;
  4439   4444       }
................................................................................
  4505   4510           raw_printf(stderr, "User-Delete failed: %d\n", rc);
  4506   4511           rc = 1;
  4507   4512         }
  4508   4513       }else{
  4509   4514         raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
  4510   4515         rc = 1;
  4511   4516         goto meta_command_exit;
  4512         -    }    
         4517  +    }
  4513   4518     }else
  4514   4519   #endif /* SQLITE_USER_AUTHENTICATION */
  4515   4520   
  4516   4521     if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
  4517   4522       utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
  4518   4523           sqlite3_libversion(), sqlite3_sourceid());
  4519   4524     }else
................................................................................
  4737   4742         if( p->backslashOn ) resolve_backslashes(zSql);
  4738   4743         BEGIN_TIMER;
  4739   4744         rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
  4740   4745         END_TIMER;
  4741   4746         if( rc || zErrMsg ){
  4742   4747           char zPrefix[100];
  4743   4748           if( in!=0 || !stdin_is_interactive ){
  4744         -          sqlite3_snprintf(sizeof(zPrefix), zPrefix, 
         4749  +          sqlite3_snprintf(sizeof(zPrefix), zPrefix,
  4745   4750                              "Error: near line %d:", startline);
  4746   4751           }else{
  4747   4752             sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
  4748   4753           }
  4749   4754           if( zErrMsg!=0 ){
  4750   4755             utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
  4751   4756             sqlite3_free(zErrMsg);
................................................................................
  4879   4884     }
  4880   4885     sqlite3_free(zBuf);
  4881   4886   }
  4882   4887   
  4883   4888   /*
  4884   4889   ** Show available command line options
  4885   4890   */
  4886         -static const char zOptions[] = 
         4891  +static const char zOptions[] =
  4887   4892     "   -ascii               set output mode to 'ascii'\n"
  4888   4893     "   -bail                stop after hitting an error\n"
  4889   4894     "   -batch               force batch I/O\n"
  4890   4895     "   -column              set output mode to 'column'\n"
  4891   4896     "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
  4892   4897     "   -csv                 set output mode to 'csv'\n"
  4893   4898     "   -echo                print commands before execution\n"
................................................................................
  4916   4921     "   -vfs NAME            use NAME as the default VFS\n"
  4917   4922   #ifdef SQLITE_ENABLE_VFSTRACE
  4918   4923     "   -vfstrace            enable tracing of all VFS calls\n"
  4919   4924   #endif
  4920   4925   ;
  4921   4926   static void usage(int showDetail){
  4922   4927     utf8_printf(stderr,
  4923         -      "Usage: %s [OPTIONS] FILENAME [SQL]\n"  
         4928  +      "Usage: %s [OPTIONS] FILENAME [SQL]\n"
  4924   4929         "FILENAME is the name of an SQLite database. A new database is created\n"
  4925   4930         "if the file does not previously exist.\n", Argv0);
  4926   4931     if( showDetail ){
  4927   4932       utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
  4928   4933     }else{
  4929   4934       raw_printf(stderr, "Use the -help option for additional information\n");
  4930   4935     }
................................................................................
  4978   4983       utf8_printf(stderr, "%s: Error: missing argument to %s\n",
  4979   4984               argv[0], argv[argc-1]);
  4980   4985       exit(1);
  4981   4986     }
  4982   4987     return argv[i];
  4983   4988   }
  4984   4989   
         4990  +#ifndef SQLITE_SHELL_IS_UTF8
         4991  +#  if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
         4992  +#    define SQLITE_SHELL_IS_UTF8          (0)
         4993  +#  else
         4994  +#    define SQLITE_SHELL_IS_UTF8          (1)
         4995  +#  endif
         4996  +#endif
         4997  +
         4998  +#if SQLITE_SHELL_IS_UTF8
  4985   4999   int SQLITE_CDECL main(int argc, char **argv){
         5000  +#else
         5001  +int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
         5002  +  char **argv = 0;
         5003  +#endif
  4986   5004     char *zErrMsg = 0;
  4987   5005     ShellState data;
  4988   5006     const char *zInitFile = 0;
  4989   5007     int i;
  4990   5008     int rc = 0;
  4991   5009     int warnInmemoryDb = 0;
  4992   5010     int readStdin = 1;
  4993   5011     int nCmd = 0;
  4994   5012     char **azCmd = 0;
  4995   5013   
         5014  +  setBinaryMode(stdin, 0);
         5015  +  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
         5016  +
  4996   5017   #if USE_SYSTEM_SQLITE+0!=1
  4997   5018     if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
  4998   5019       utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
  4999   5020               sqlite3_sourceid(), SQLITE_SOURCE_ID);
  5000   5021       exit(1);
  5001   5022     }
  5002   5023   #endif
  5003         -  setBinaryMode(stdin);
  5004         -  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
  5005         -  Argv0 = argv[0];
  5006   5024     main_init(&data);
         5025  +#if !SQLITE_SHELL_IS_UTF8
         5026  +  sqlite3_initialize();
         5027  +  argv = sqlite3_malloc64(sizeof(argv[0])*argc);
         5028  +  if( argv==0 ){
         5029  +    raw_printf(stderr, "out of memory\n");
         5030  +    exit(1);
         5031  +  }
         5032  +  for(i=0; i<argc; i++){
         5033  +    argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]);
         5034  +    if( argv[i]==0 ){
         5035  +      raw_printf(stderr, "out of memory\n");
         5036  +      exit(1);
         5037  +    }
         5038  +  }
         5039  +#endif
         5040  +  Argv0 = argv[0];
  5007   5041     stdin_is_interactive = isatty(0);
  5008   5042     stdout_is_console = isatty(1);
  5009   5043   
  5010   5044     /* Make sure we have a valid signal handler early, before anything
  5011   5045     ** else is done.
  5012   5046     */
  5013   5047   #ifdef SIGINT
................................................................................
  5057   5091        || strcmp(z,"-cmd")==0
  5058   5092       ){
  5059   5093         (void)cmdline_option_value(argc, argv, ++i);
  5060   5094       }else if( strcmp(z,"-init")==0 ){
  5061   5095         zInitFile = cmdline_option_value(argc, argv, ++i);
  5062   5096       }else if( strcmp(z,"-batch")==0 ){
  5063   5097         /* Need to check for batch mode here to so we can avoid printing
  5064         -      ** informational messages (like from process_sqliterc) before 
         5098  +      ** informational messages (like from process_sqliterc) before
  5065   5099         ** we do the actual processing of arguments later in a second pass.
  5066   5100         */
  5067   5101         stdin_is_interactive = 0;
  5068   5102       }else if( strcmp(z,"-heap")==0 ){
  5069   5103   #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
  5070   5104         const char *zSize;
  5071   5105         sqlite3_int64 szHeap;
................................................................................
  5332   5366       }
  5333   5367     }
  5334   5368     set_table_name(&data, 0);
  5335   5369     if( data.db ){
  5336   5370       session_close_all(&data);
  5337   5371       sqlite3_close(data.db);
  5338   5372     }
  5339         -  sqlite3_free(data.zFreeOnClose); 
         5373  +  sqlite3_free(data.zFreeOnClose);
         5374  +#if !SQLITE_SHELL_IS_UTF8
         5375  +  for(i=0; i<argc; i++) sqlite3_free(argv[i]);
         5376  +  sqlite3_free(argv);
         5377  +#endif
  5340   5378     return rc;
  5341   5379   }

Changes to test/shell1.test.

    72     72   } {0 {}}
    73     73   do_test shell1-1.3.3 {
    74     74     catchcmd "-init FOO test.db BAD .quit" ""
    75     75   } {1 {Error: near "BAD": syntax error}}
    76     76   
    77     77   # -echo                print commands before execution
    78     78   do_test shell1-1.4.1 {
    79         -  catchcmd "-echo test.db" "" 
           79  +  catchcmd "-echo test.db" ""
    80     80   } {0 {}}
    81     81   
    82     82   # -[no]header          turn headers on or off
    83     83   do_test shell1-1.5.1 {
    84         -  catchcmd "-header test.db" "" 
           84  +  catchcmd "-header test.db" ""
    85     85   } {0 {}}
    86     86   do_test shell1-1.5.2 {
    87         -  catchcmd "-noheader test.db" "" 
           87  +  catchcmd "-noheader test.db" ""
    88     88   } {0 {}}
    89     89   
    90     90   # -bail                stop after hitting an error
    91     91   do_test shell1-1.6.1 {
    92         -  catchcmd "-bail test.db" "" 
           92  +  catchcmd "-bail test.db" ""
    93     93   } {0 {}}
    94     94   
    95     95   # -interactive         force interactive I/O
    96     96   do_test shell1-1.7.1 {
    97     97     set res [catchcmd "-interactive test.db" ".quit"]
    98     98     set rc [lindex $res 0]
    99     99     list $rc \
   100    100          [regexp {SQLite version} $res] \
   101    101          [regexp {Enter ".help" for usage hints} $res]
   102    102   } {0 1 1}
   103    103   
   104    104   # -batch               force batch I/O
   105    105   do_test shell1-1.8.1 {
   106         -  catchcmd "-batch test.db" "" 
          106  +  catchcmd "-batch test.db" ""
   107    107   } {0 {}}
   108    108   
   109    109   # -column              set output mode to 'column'
   110    110   do_test shell1-1.9.1 {
   111         -  catchcmd "-column test.db" "" 
          111  +  catchcmd "-column test.db" ""
   112    112   } {0 {}}
   113    113   
   114    114   # -csv                 set output mode to 'csv'
   115    115   do_test shell1-1.10.1 {
   116         -  catchcmd "-csv test.db" "" 
          116  +  catchcmd "-csv test.db" ""
   117    117   } {0 {}}
   118    118   
   119    119   # -html                set output mode to HTML
   120    120   do_test shell1-1.11.1 {
   121         -  catchcmd "-html test.db" "" 
          121  +  catchcmd "-html test.db" ""
   122    122   } {0 {}}
   123    123   
   124    124   # -line                set output mode to 'line'
   125    125   do_test shell1-1.12.1 {
   126         -  catchcmd "-line test.db" "" 
          126  +  catchcmd "-line test.db" ""
   127    127   } {0 {}}
   128    128   
   129    129   # -list                set output mode to 'list'
   130    130   do_test shell1-1.13.1 {
   131         -  catchcmd "-list test.db" "" 
          131  +  catchcmd "-list test.db" ""
   132    132   } {0 {}}
   133    133   
   134    134   # -separator 'x'       set output field separator (|)
   135    135   do_test shell1-1.14.1 {
   136         -  catchcmd "-separator 'x' test.db" "" 
          136  +  catchcmd "-separator 'x' test.db" ""
   137    137   } {0 {}}
   138    138   do_test shell1-1.14.2 {
   139         -  catchcmd "-separator x test.db" "" 
          139  +  catchcmd "-separator x test.db" ""
   140    140   } {0 {}}
   141    141   do_test shell1-1.14.3 {
   142    142     set res [catchcmd "-separator" ""]
   143    143     set rc [lindex $res 0]
   144    144     list $rc \
   145    145          [regexp {Error: missing argument to -separator} $res]
   146    146   } {1 1}
   147    147   
   148    148   # -stats               print memory stats before each finalize
   149    149   do_test shell1-1.14b.1 {
   150         -  catchcmd "-stats test.db" "" 
          150  +  catchcmd "-stats test.db" ""
   151    151   } {0 {}}
   152    152   
   153    153   # -nullvalue 'text'    set text string for NULL values
   154    154   do_test shell1-1.15.1 {
   155    155     catchcmd "-nullvalue 'x' test.db" ""
   156    156   } {0 {}}
   157    157   do_test shell1-1.15.2 {
................................................................................
   171    171   
   172    172   #----------------------------------------------------------------------------
   173    173   # Test cases shell1-2.*: Basic "dot" command token parsing.
   174    174   #
   175    175   
   176    176   # check first token handling
   177    177   do_test shell1-2.1.1 {
   178         -  catchcmd "test.db" ".foo" 
          178  +  catchcmd "test.db" ".foo"
   179    179   } {1 {Error: unknown command or invalid arguments:  "foo". Enter ".help" for help}}
   180    180   do_test shell1-2.1.2 {
   181    181     catchcmd "test.db" ".\"foo OFF\""
   182    182   } {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
   183    183   do_test shell1-2.1.3 {
   184    184     catchcmd "test.db" ".\'foo OFF\'"
   185    185   } {1 {Error: unknown command or invalid arguments:  "foo OFF". Enter ".help" for help}}
................................................................................
   905    905         error "failed with error: $res"
   906    906       }
   907    907       if {$res ne "$oldChar\n"} {
   908    908         error "failed with byte $hex mismatch"
   909    909       }
   910    910     }
   911    911   } {}
          912  +
          913  +do_test shell1-6.0 {
          914  +  # The file name here is the word "test" in Chinese.
          915  +  # In UTF-8, it is encoded as: \xE6\xB5\x8B\xE8\xAF\x95
          916  +  set fileName \u6D4B\u8BD5; append fileName .db
          917  +  set x [catchcmdex $fileName "CREATE TABLE t1(x);\n.schema\n"]
          918  +  set code [lindex $x 0]
          919  +  set res [string trim [lindex $x 1]]
          920  +  if {$code ne "0"} {
          921  +    error "failed with error: $res"
          922  +  }
          923  +  if {$res ne "CREATE TABLE t1(x);"} {
          924  +    error "failed with mismatch: $res"
          925  +  }
          926  +  if {![file exists $fileName]} {
          927  +    error "file \"$fileName\" (MBCS) does not exist"
          928  +  }
          929  +  forcedelete $fileName
          930  +} {}
   912    931   
   913    932   finish_test