On 2012-02-01, at 12:06 AM, REPLeffect wrote:
As a final test, I started over with a fresh copy ov v4.6.3, applied the above patch, and ran a make bootstrap, make update, and make install -- all of which worked wonderfully, without the -fpermissive switch being used.
I have committed your patch. Thanks! Can you double-check that it works for you?
BTW Marc, the MinGW "make check" and shell-command(bug 152) fixes you recently applied work great on my MingW-compiled copy of Gambit also.
Great. As a side note, I should thank the GHC folks (Glasgow Haskell) because the Windows command line escaping algorithm comes from them (see below for the relevant part of their source code, which gives pointers to related documentation).
The escaping algorithm seems to work well when creating a process from an executable (.exe) file. Unfortunately, when starting a process from a batch file (.bat) it appears that the double quotes used to escape the command line arguments are preserved, and are visible to the batch file. In other words, executing:
foo.bat hello and foo.bat "hello"
bind %1 to different strings in the batch file. I'm not sure this glitch can be fixed, and that it is worth fixing.
Marc
-- ------------------------------------------------------------------------ -- Escaping commands for shells
{- On Windows we also use this for running commands. We use CreateProcess, passing a single command-line string (lpCommandLine) as its argument. (CreateProcess is well documented on http://msdn.microsoft.com.)
- It parses the beginning of the string to find the command. If the file name has embedded spaces, it must be quoted, using double quotes thus "foo\this that\cmd" arg1 arg2
- The invoked command can in turn access the entire lpCommandLine string, and the C runtime does indeed do so, parsing it to generate the traditional argument vector argv[0], argv[1], etc. It does this using a complex and arcane set of rules which are described here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm...
(if this URL stops working, you might be able to find it by searching for "Parsing C Command-Line Arguments" on MSDN. Also, the code in the Microsoft C runtime that does this translation is shipped with VC++).
Our goal in runProcess is to take a command filename and list of arguments, and construct a string which inverts the translatsions described above, such that the program at the other end sees exactly the same arguments in its argv[] that we passed to rawSystem.
This inverse translation is implemented by 'translate' below.
Here are some pages that give informations on Windows-related limitations and deviations from Unix conventions:
http://support.microsoft.com/default.aspx?scid=kb;en-us;830473 Command lines and environment variables effectively limited to 8191 characters on Win XP, 2047 on NT/2000 (probably even less on Win 9x):
http://www.microsoft.com/windowsxp/home/using/productdoc/en/default.asp?url=... Command-line substitution under Windows XP. IIRC these facilities (or at least a large subset of them) are available on Win NT and 2000. Some might be available on Win 9x.
http://www.microsoft.com/windowsxp/home/using/productdoc/en/default.asp?url=... How CMD.EXE processes command lines.
Note: CreateProcess does have a separate argument (lpApplicationName) with which you can specify the command, but we have to slap the command into lpCommandLine anyway, so that argv[0] is what a C program expects (namely the application name). So it seems simpler to just use lpCommandLine alone, which CreateProcess supports. -}
translate :: String -> String #if mingw32_HOST_OS translate str = '"' : snd (foldr escape (True,""") str) where escape '"' (b, str) = (True, '\' : '"' : str) escape '\' (True, str) = (True, '\' : '\' : str) escape '\' (False, str) = (False, '\' : str) escape c (b, str) = (False, c : str) -- See long comment above for what this function is trying to do. -- -- The Bool passed back along the string is True iff the -- rest of the string is a sequence of backslashes followed by -- a double quote. #else translate str = ''' : foldr escape "'" str where escape ''' = showString "'\''" escape c = showChar c #endif