Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SI-7295 Fix windows batch file with args containing parentheses #3065

Merged
merged 1 commit into from Oct 23, 2013

Conversation

retronym
Copy link
Member

In command scripts, substitution of FOO in if cond ( %FOO% ) happens
before the condition is evaluated. One can use delayed expansion with
if cond (!FOO!) to get a saner behaviour. Or, as I ended up doing here, use
a goto in the body of the if rather than referring directly to variables
there.

Here's a cut down version to demonstrate the old problem:

C:\Users\IEUser>type test.cmd
@echo off

setlocal enableextensions enabledelayedexpansion

if [%~1]==[-toolcp] (
 set CP=%~2
 shift
 shift
)
echo -toolcp %CP%
echo %~1 %~2

C:\Users\IEUser>test.cmd a b
-toolcp
a b

C:\Users\IEUser>test.cmd -toolcp "c:\program files" a b
-toolcp c:\program files
a b

C:\Users\IEUser>test.cmd -toolcp "c:\program files" "a()b" "c()d"
-toolcp c:\program files
a()b c()d

C:\Users\IEUser>test.cmd "a()b" "c()d"
d was unexpected at this time.

I don't understand exactly why the parentheses only mess things up in this
situation. But regardless, lets find another way.

My first attempt to fix this was based on the suggestion in the ticket. But,
as shown below, this fails to capture the -toolcp.

C:\Users\IEUser>type test.cmd
@echo off

setlocal enableextensions enabledelayedexpansion

if [%~1]==[-toolcp] (
  set CP=!2!
  shift
  shift
)
echo -toolcp %CP%
echo %~1 %~2
C:\Users\IEUser>test.cmd "a()b" "c()d"
-toolcp
a()b c()d

C:\Users\IEUser>test.cmd -toolcp "c:\program files" "a()b" "c()d"
-toolcp
a()b c()d

Last stop was the goto you'll find in this patch.

With this patch applied, I tested on Windows 8 with the following:

C:\Users\IEUser>type Desktop\temp.cmd
::#!
@echo off
call scala %0 %*
goto :eof
::!#
println("hello, world")
println(argv.toList)

C:\Users\IEUser>scala Desktop\temp.cmd "foo(bar)baz"
"java" -Xmx256M -Xms32M -Dscala.home="C:\PROGRA~3\scala\bin\.."
-Denv.emacs="" -Dscala.usejavacp=true  -cp "..."
scala.tools.nsc.MainGenericRunner Desktop\temp.cmd "foo(bar)baz"

hello, world
List(foo(bar)baz)

C:\Users\IEUser>scala -toolcp "c:\program files" Desktop\temp.cmd "foo(bar)baz"
"java" -Xmx256M -Xms32M -Dscala.home="C:\PROGRA~3\scala\bin\.."
-Denv.emacs="" -Dscala.usejavacp=true  -cp "...;c:\program files"
scala.tools.nsc.MainGenericRunner  -toolcp "c:\program files" Desktop\temp.cmd "foo(bar)baz"

hello, world
List(foo(bar)baz)

In command scripts, substitution of `FOO` in `if cond ( %FOO% )` happens
*before* the condition is evaluated. One can use delayed expansion with
`if cond (!FOO!)` to get a saner behaviour. Or, as I ended up doing here,
use a goto in the body of the if rather than referring directly to variables
there.

Here's a cut down version to demonstrate the old problem:

    C:\Users\IEUser>type test.cmd
    @echo off

    setlocal enableextensions enabledelayedexpansion

    if [%~1]==[-toolcp] (
      set CP=%~2
      shift
      shift
    )
    echo -toolcp %CP%
    echo %~1 %~2

    C:\Users\IEUser>test.cmd a b
    -toolcp
    a b

    C:\Users\IEUser>test.cmd -toolcp "c:\program files" a b
    -toolcp c:\program files
    a b

    C:\Users\IEUser>test.cmd -toolcp "c:\program files" "a()b" "c()d"
    -toolcp c:\program files
    a()b c()d

    C:\Users\IEUser>test.cmd "a()b" "c()d"
    d was unexpected at this time.

I don't understand exactly why the parentheses only mess things
up in this situation. But regardless, lets find another way.

My first attempt to fix this was based on the suggestion in the ticket.
But, as shown below, this fails to capture the -toolcp.

    C:\Users\IEUser>type test.cmd
    @echo off

    setlocal enableextensions enabledelayedexpansion

    if [%~1]==[-toolcp] (
      set CP=!2!
      shift
      shift
    )
    echo -toolcp %CP%
    echo %~1 %~2
    C:\Users\IEUser>test.cmd "a()b" "c()d"
    -toolcp
    a()b c()d

    C:\Users\IEUser>test.cmd -toolcp "c:\program files" "a()b" "c()d"
    -toolcp
    a()b c()d

Last stop was the goto you'll find in this patch.

With this patch applied, I tested on Windows 8 with the following:

    C:\Users\IEUser>type Desktop\temp.cmd
    ::#!
    @echo off
    call scala %0 %*
    goto :eof
    ::!#
    println("hello, world")
    println(argv.toList)

    C:\Users\IEUser>scala Desktop\temp.cmd "foo(bar)baz"
    "java" -Xmx256M -Xms32M -Dscala.home="C:\PROGRA~3\scala\bin\.."
    -Denv.emacs="" -Dscala.usejavacp=true  -cp "..."
    scala.tools.nsc.MainGenericRunner Desktop\temp.cmd "foo(bar)baz"

    hello, world
    List(foo(bar)baz)

    C:\Users\IEUser>scala -toolcp "c:\program files" Desktop\temp.cmd "foo(bar)baz"
    "java" -Xmx256M -Xms32M -Dscala.home="C:\PROGRA~3\scala\bin\.."
     -Denv.emacs="" -Dscala.usejavacp=true  -cp "...;c:\program files"
     scala.tools.nsc.MainGenericRunner  -toolcp "c:\program files" Desktop\temp.cmd "foo(bar)baz"

    hello, world
    List(foo(bar)baz)
@retronym
Copy link
Member Author

Review by @szeiger

@gourlaysama
Copy link
Member

Actually, the first version worked almost fine already (%~1 and %~2 do contain a()b and c()d), but set is used (well, it is parsed, but never actually called) without quoting, as in, after variable expansion:

set CP=c()d

And the parser complains because ( and ) have a special meaning in batch script (command grouping). You can use the quoted version of set for this, as in this SO question:

set "CP=%~2"

Although goto is fine too :-)

@retronym
Copy link
Member Author

Thanks for that link.

I suppose this still runs into a problem if %2 contains a ", so the goto is probably safer.

retronym added a commit that referenced this pull request Oct 23, 2013
 Fix windows batch file with args containing parentheses
@retronym retronym merged commit e6a5e69 into scala:2.10.x Oct 23, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants