[project @ 2005-05-06 00:30:56 by sof]
authorsof <unknown>
Fri, 6 May 2005 00:30:57 +0000 (00:30 +0000)
committersof <unknown>
Fri, 6 May 2005 00:30:57 +0000 (00:30 +0000)
[mingw only]
Work around bug in win32 Console API which showed up in the GHCi UI:
if the user typed in characters prior to the appearance of the prompt,
the first of these characters always came out as a 'g'. The GHCi UI does
for good reasons one-character reads from 'stdin', which causes the
underlying APIs to become confused. A simple repro case is the following
piece of C code:

/*----------------------*/
#include <stdio.h>
#include <windows.h>
int main()
{
    char ch1,ch2;
    HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
    DWORD dw;

    /* Type in some characters before the prompt appears and be amused.. */
    sleep(1000); printf("? ");
    ReadConsoleA(hStdIn,&ch1,1,&dw,NULL);
    ReadConsoleA(hStdIn,&ch2,1,&dw,NULL);
/*  or, if you want to use libc:
    read(0,&ch1,1); read(0,&ch2,1); */

    printf("%c%c\n", ch1,ch2);
    return 0;
}
/*----------------------*/

This happens across win32 OSes, and I can't see anything untoward as far
as API usage goes (the GHC IO implementation uses read(), but that
reduces to ReadConsoleA() calls.) People inside the Behemoth might want
to have a closer look at this..

Not much we can do about this except work around the problem by flushing
the input buffer prior to reading from stdin. Not ideal, as type-ahead
is a useful feature. Flushing is handled by GHC.ConsoleHandler.flushConsole

Merge to STABLE.

ghc/compiler/ghci/InteractiveUI.hs

index 6040404..8e865e8 100644 (file)
@@ -45,6 +45,8 @@ import System.Posix
 #if __GLASGOW_HASKELL__ > 504
        hiding (getEnv)
 #endif
+#else
+import GHC.ConsoleHandler ( flushConsole )
 #endif
 
 #ifdef USE_READLINE
@@ -189,6 +191,13 @@ interactiveUI session srcs maybe_expr = do
    Readline.initialize
 #endif
 
+#if defined(mingw32_HOST_OS)
+    -- The win32 Console API mutates the first character of 
+    -- type-ahead when reading from it in a non-buffered manner. Work
+    -- around this by flushing the input buffer of type-ahead characters.
+    -- 
+   GHC.ConsoleHandler.flushConsole stdin
+#endif
    startGHCi (runGHCi srcs maybe_expr)
        GHCiState{ progname = "<interactive>",
                   args = [],