diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/shell.c.in | 146 |
1 files changed, 91 insertions, 55 deletions
diff --git a/src/shell.c.in b/src/shell.c.in index b78759c00..395cbd035 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -449,12 +449,20 @@ static int bail_on_error = 0; */ static int stdin_is_interactive = 1; +/* +** If build is for Windows, without 3rd-party line editing, Console +** input and output may be done in a UTF-8 compatible way. This is +** determined by invocation option and OS installed capability. +*/ #if (defined(_WIN32) || defined(WIN32)) && SHELL_USE_LOCAL_GETLINE \ && !defined(SHELL_OMIT_WIN_UTF8) # define SHELL_WIN_UTF8_OPT 1 - static int console_utf8 = sizeof(char*)/4 - 1; + static int console_utf8_in = 0; + static int console_utf8_out = 0; + static int mbcs_opted = 0; #else -# define console_utf8 0 +# define console_utf8_in 0 +# define console_utf8_out 0 # define SHELL_WIN_UTF8_OPT 0 #endif @@ -597,7 +605,7 @@ static struct ConsoleState { int infsMode; /* Input file stream mode upon shell start */ UINT inCodePage; /* Input code page upon shell start */ UINT outCodePage; /* Output code page upon shell start */ - HANDLE hConsoleIn; /* Console input handle */ + HANDLE hConsole; /* Console input or output handle */ DWORD consoleMode; /* Console mode upon shell start */ } conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 }; @@ -607,49 +615,61 @@ static struct ConsoleState { /* ** Prepare console, (if known to be a WIN32 console), for UTF-8 -** input (from either typing or suitable paste operations) and for +** input (from either typing or suitable paste operations) and/or for ** UTF-8 rendering. This may "fail" with a message to stderr, where ** the preparation is not done and common "code page" issues occur. */ -static void console_prepare(void){ +static void console_prepare_utf8(void){ HANDLE hCI = GetStdHandle(STD_INPUT_HANDLE); + HANDLE hCO = GetStdHandle(STD_OUTPUT_HANDLE); + HANDLE hCC = INVALID_HANDLE_VALUE; DWORD consoleMode = 0; - if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR - && GetConsoleMode( hCI, &consoleMode) ){ - if( !IsValidCodePage(CP_UTF8) ){ - fprintf(stderr, "Cannot use UTF-8 code page.\n"); - console_utf8 = 0; - return; - } - conState.hConsoleIn = hCI; - conState.consoleMode = consoleMode; - conState.inCodePage = GetConsoleCP(); - conState.outCodePage = GetConsoleOutputCP(); + u8 conI = 0, conO = 0; + + console_utf8_in = console_utf8_out = 0; + if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR ) conI = 1; + if( isatty(1) && GetFileType(hCO)==FILE_TYPE_CHAR ) conO = 1; + if( (!conI && !conO) || mbcs_opted ) return; + if( conI ) hCC = hCI; + else hCC = hCO; + if( !IsValidCodePage(CP_UTF8) || !GetConsoleMode( hCC, &consoleMode) ){ + fprintf(stderr, "Cannot use UTF-8 code page.\n"); + return; + } + conState.hConsole = hCC; + conState.consoleMode = consoleMode; + conState.inCodePage = GetConsoleCP(); + conState.outCodePage = GetConsoleOutputCP(); + if( conI ){ + console_utf8_in = 1; SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); consoleMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; - SetConsoleMode(conState.hConsoleIn, consoleMode); + SetConsoleMode(conState.hConsole, consoleMode); conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT); - console_utf8 = 1; - }else{ - console_utf8 = 0; + } + if( conO ){ + console_utf8_out = 1; + SetConsoleOutputCP(CP_UTF8); } } /* -** Undo the effects of console_prepare(), if any. +** Undo the effects of console_prepare_utf8(), if any. */ static void SQLITE_CDECL console_restore(void){ - if( console_utf8 && conState.inCodePage!=0 - && conState.hConsoleIn!=INVALID_HANDLE_VALUE ){ - _setmode(_fileno(stdin), conState.infsMode); - SetConsoleCP(conState.inCodePage); - SetConsoleOutputCP(conState.outCodePage); - SetConsoleMode(conState.hConsoleIn, conState.consoleMode); + if( (console_utf8_in||console_utf8_out) + && conState.hConsole!=INVALID_HANDLE_VALUE ){ + if( console_utf8_in ){ + SetConsoleCP(conState.inCodePage); + _setmode(_fileno(stdin), conState.infsMode); + } + if( console_utf8_out ) SetConsoleOutputCP(conState.outCodePage); + SetConsoleMode(conState.hConsole, conState.consoleMode); /* Avoid multiple calls. */ - conState.hConsoleIn = INVALID_HANDLE_VALUE; + conState.hConsole = INVALID_HANDLE_VALUE; conState.consoleMode = 0; - console_utf8 = 0; + console_utf8_in = 0; + console_utf8_out = 0; } } @@ -657,11 +677,11 @@ static void SQLITE_CDECL console_restore(void){ ** Collect input like fgets(...) with special provisions for input ** from the Windows console to get around its strange coding issues. ** Defers to plain fgets() when input is not interactive or when the -** startup option, -utf8, has not been provided or taken effect. +** UTF-8 input is unavailable or opted out. */ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){ if( fin==0 ) fin = stdin; - if( fin==stdin && stdin_is_interactive && console_utf8 ){ + if( fin==stdin && stdin_is_interactive && console_utf8_in ){ # define SQLITE_IALIM 150 wchar_t wbuf[SQLITE_IALIM]; int lend = 0; @@ -674,7 +694,7 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){ ? SQLITE_IALIM : (ncmax-1 - noc)/4; # undef SQLITE_IALIM DWORD nbr = 0; - BOOL bRC = ReadConsoleW(conState.hConsoleIn, wbuf, na, &nbr, 0); + BOOL bRC = ReadConsoleW(conState.hConsole, wbuf, na, &nbr, 0); if( !bRC || (noc==0 && nbr==0) ) return 0; if( nbr > 0 ){ int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR, @@ -720,8 +740,8 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){ /* ** Render output like fprintf(). Except, if the output is going to the -** console and if this is running on a Windows machine, and if the -utf8 -** option is unavailable or (available and inactive), translate the +** console and if this is running on a Windows machine, and if UTF-8 +** output unavailable (or available but opted out), translate the ** output from UTF-8 into MBCS for output through 8-bit stdout stream. ** (With -utf8 active, no translation is needed and must not be done.) */ @@ -729,7 +749,7 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){ void utf8_printf(FILE *out, const char *zFormat, ...){ va_list ap; va_start(ap, zFormat); - if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8 ){ + if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8_out ){ char *z1 = sqlite3_vmprintf(zFormat, ap); char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); sqlite3_free(z1); @@ -942,8 +962,8 @@ static char *local_getline(char *zLine, FILE *in){ #if defined(_WIN32) || defined(WIN32) /* For interactive input on Windows systems, without -utf8, ** translate the multi-byte characterset characters into UTF-8. - ** This is the translation that predates the -utf8 option. */ - if( stdin_is_interactive && in==stdin && !console_utf8 ){ + ** This is the translation that predates console UTF-8 input. */ + if( stdin_is_interactive && in==stdin && !console_utf8_in ){ char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); if( zTrans ){ i64 nTrans = strlen(zTrans)+1; @@ -12227,12 +12247,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ (void)cmdline_option_value(argc, argv, ++i); }else if( cli_strcmp(z,"-init")==0 ){ zInitFile = cmdline_option_value(argc, argv, ++i); + }else if( cli_strcmp(z,"-interactive")==0 ){ + /* Need to check for interactive override here to so that it can + ** affect console setup (for Windows only) and testing thereof. + */ + stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ /* Need to check for batch mode here to so we can avoid printing ** informational messages (like from process_sqliterc) before ** we do the actual processing of arguments later in a second pass. */ stdin_is_interactive = 0; + }else if( cli_strcmp(z,"-utf8")==0 ){ +#if SHELL_WIN_UTF8_OPT + mbcs_opted = 0; +#endif /* SHELL_WIN_UTF8_OPT */ + }else if( cli_strcmp(z,"-no-utf8")==0 ){ +#if SHELL_WIN_UTF8_OPT + mbcs_opted = 1; +#endif /* SHELL_WIN_UTF8_OPT */ }else if( cli_strcmp(z,"-heap")==0 ){ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) const char *zSize; @@ -12372,6 +12405,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ } } +#if SHELL_WIN_UTF8_OPT + /* Get indicated Windows console setup done before running invocation commands. */ + if( stdin_is_interactive || stdout_is_console ){ + console_prepare_utf8(); + } + if( !stdin_is_interactive ){ + setBinaryMode(stdin, 0); + } +#endif + if( data.pAuxDb->zDbFilename==0 ){ #ifndef SQLITE_OMIT_MEMORYDB data.pAuxDb->zDbFilename = ":memory:"; @@ -12498,17 +12541,13 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ 8*(int)sizeof(char*)); return 0; }else if( cli_strcmp(z,"-interactive")==0 ){ - stdin_is_interactive = 1; + /* already handled */ }else if( cli_strcmp(z,"-batch")==0 ){ - stdin_is_interactive = 0; + /* already handled */ }else if( cli_strcmp(z,"-utf8")==0 ){ -#if SHELL_WIN_UTF8_OPT - console_utf8 = 1; -#endif /* SHELL_WIN_UTF8_OPT */ + /* already handled */ }else if( cli_strcmp(z,"-no-utf8")==0 ){ -#if SHELL_WIN_UTF8_OPT - console_utf8 = 0; -#endif /* SHELL_WIN_UTF8_OPT */ + /* already handled */ }else if( cli_strcmp(z,"-heap")==0 ){ i++; }else if( cli_strcmp(z,"-pagecache")==0 ){ @@ -12590,14 +12629,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ } data.cMode = data.mode; } -#if SHELL_WIN_UTF8_OPT - if( console_utf8 && stdin_is_interactive ){ - console_prepare(); - }else{ - setBinaryMode(stdin, 0); - console_utf8 = 0; - } -#endif if( !readStdin ){ /* Run all arguments that do not begin with '-' as if they were separate @@ -12636,7 +12667,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ const char *zCharset = ""; int nHistory; #if SHELL_WIN_UTF8_OPT - if( console_utf8 ) zCharset = " (utf8)"; + switch( console_utf8_in+2*console_utf8_out ){ + default: case 0: break; + case 1: zCharset = " (utf8 in)"; break; + case 2: zCharset = " (utf8 out)"; break; + case 3: zCharset = " (utf8 I/O)"; break; + } #endif printf( "SQLite version %s %.19s%s\n" /*extra-version-info*/ |