[gambit-list] compiling Gambit 4.6.3 under MinGW/MSys

Marc Feeley feeley at iro.umontreal.ca
Wed Feb 1 10:05:53 EST 2012


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/progs_12.asp

        (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=/WINDOWSXP/home/using/productdoc/en/percent.asp
    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=/WINDOWSXP/home/using/productdoc/en/Cmd.asp
    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




More information about the Gambit-list mailing list