Skip to content

Commit 2725792

Browse files
committed
mswin: improve configure.bat syntax
Introduce shellsplit.cmd to simplify configure.bat command line parsing. Makefile macro definition and opt-dir list now free from quoting. eg. now can use as ``` configure --with-opt-dir=c:/src/zlib;c:/src/libffi CC="cl -std:c11" DEFS=-DOPT_THREADED_CODE=2 ```
1 parent 3095904 commit 2725792

3 files changed

Lines changed: 205 additions & 23 deletions

File tree

win32/configure.bat

100755100644
Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,43 @@ set confargs=%config_make:.mak=.sub%
3333
set debug_configure=
3434
echo>%config_make% # CONFIGURE
3535
type nul > %confargs%
36+
set args=%*
37+
goto :loop
38+
39+
:shift_argv
40+
call %~dp0shellsplit.cmd
41+
set "argv1=%argv2%"
42+
set "argv2=%argv%"
43+
if not defined argv1 if defined argv2 goto :shift_argv
44+
exit /b
45+
46+
:take_arg
47+
if defined arg exit /b
48+
if not defined argv2 exit /b
49+
if not "%argv2:~0,1%"=="-" (set "arg=%argv2%" & call :shift_argv)
50+
exit /b
51+
52+
:set
53+
set %1
54+
exit /b
55+
3656
:loop
37-
if [%1] == [] goto :end ;
38-
if "%~1" == "" (shift & goto :loop)
39-
for /f "delims== tokens=1,*" %%I in ("%~1") do ((set "opt=%%I") && (set "arg=%%J"))
40-
set "eq=="
41-
if "%arg%" == "" if not "%~1" == "%opt%=%arg%" (set "eq=")
42-
shift
57+
call :shift_argv
58+
if not defined argv1 goto :end
59+
60+
for /f "delims== tokens=1*" %%I in (" %argv1% ") do ((set "opt=%%I") && (set "arg=%%J"))
61+
set "opt=%opt:~1%"
62+
set "eq="
63+
if defined arg (
64+
set "eq=="
65+
set "arg=%arg:~0,-1%"
66+
) else (
67+
set "opt=%opt:~0,-1%"
68+
)
69+
if "%opt%"=="" (
70+
echo 1>&2 %configure%: assignment for empty variable name %argv1%
71+
exit /b 1
72+
)
4373
if "%opt%" == "--debug-configure" (
4474
echo on
4575
set "debug_configure=yes"
@@ -85,7 +115,7 @@ for /f "delims== tokens=1,*" %%I in ("%~1") do ((set "opt=%%I") && (set "arg=%%J
85115
)
86116
goto :loop ;
87117
:target
88-
if "%eq%" == "" (set "arg=%~1" & shift)
118+
if "%eq%" == "" call :take_arg
89119
if "%arg%" == "" (
90120
echo 1>&2 %configure%: missing argument for %opt%
91121
exit /b 1
@@ -105,32 +135,37 @@ goto :loop ;
105135
)
106136
goto :unknown_opt
107137
:name
108-
if "%eq%" == "" (set "arg=%~1" & shift)
138+
if "%eq%" == "" call :take_arg
109139
echo>> %config_make% %var% = %arg%
110140
goto :loopend ;
111141
:dir
112-
if "%eq%" == "" (set "arg=%~1" & shift)
142+
if "%eq%" == "" call :take_arg
113143
echo>> %config_make% %opt:~2% = %arg:\=/%
114144
goto :loopend ;
115145
:enable
116-
echo>>%confargs% "%opt%" \
117-
if %enable% == yes (set "opt=%opt:~9%") else (set "opt=%opt:~10%")
118-
if "%opt%" == "install-doc" (
146+
if %enable% == yes (
147+
if "%eq%" == "" call :take_arg
148+
set "feature=%opt:~9%"
149+
) else (
150+
set "feature=%opt:~10%"
151+
)
152+
if %enable% == yes if defined arg set "enable=%arg%"
153+
if "%feature%" == "install-doc" (
119154
echo>> %config_make% RDOCTARGET = %enable:yes=r%doc
120155
)
121-
if "%opt%" == "install-static-library" (
156+
if "%feature%" == "install-static-library" (
122157
echo>> %config_make% INSTALL_STATIC_LIBRARY = %enable%
123158
)
124-
if "%opt%" == "debug-env" (
159+
if "%feature%" == "debug-env" (
125160
echo>> %config_make% ENABLE_DEBUG_ENV = %enable%
126161
)
127-
if "%opt%" == "devel" (
162+
if "%feature%" == "devel" (
128163
echo>> %config_make% RUBY_DEVEL = %enable%
129164
)
130-
if "%opt%" == "rubygems" (
131-
echo>> %config_make% USE_RUBYGEMS = %enable%
165+
if "%feature%" == "rubygems" (
166+
echo>> %config_make% USE_RUBYGEMS = %enable%
132167
)
133-
goto :loop ;
168+
goto :loopend ;
134169
:withoutarg
135170
echo>>%confargs% "%opt%" \
136171
if "%opt%" == "--without-baseruby" goto :nobaseruby
@@ -140,7 +175,7 @@ goto :loop ;
140175
goto :loop ;
141176
:witharg
142177
if "%opt%" == "--with-static-linked-ext" goto :extstatic
143-
if "%eq%" == "" (set "arg=%~1" & shift)
178+
if "%eq%" == "" call :take_arg
144179
if not "%arg%" == "" (
145180
echo>>%confargs% "%opt%=%arg:$=$$%" \
146181
) else (
@@ -158,7 +193,7 @@ goto :loop ;
158193
:ntver
159194
::- For version constants, see
160195
::- https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt#remarks
161-
if "%eq%" == "" (set "NTVER=%~1" & shift) else (set "NTVER=%arg%")
196+
if "%eq%" == "" (set "NTVER=%~1" & call :shift_argv) else (set "NTVER=%arg%")
162197
if /i not "%NTVER:~0,2%" == "0x" if /i not "%NTVER:~0,13%" == "_WIN32_WINNT_" (
163198
for %%i in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
164199
call :set NTVER=%%NTVER:%%i=%%i%%
@@ -168,11 +203,11 @@ goto :loop ;
168203
echo>> %config_make% NTVER = %NTVER%
169204
goto :loopend ;
170205
:extout
171-
if "%eq%" == "" (set "arg=%~1" & shift)
206+
if "%eq%" == "" call :take_arg
172207
if not "%arg%" == ".ext" (echo>> %config_make% EXTOUT = %arg%)
173208
goto :loopend ;
174209
:path
175-
if "%eq%" == "" (set "arg=%~1" & shift)
210+
if "%eq%" == "" call :take_arg
176211
set "pathlist=%pathlist%%arg:\=/%;"
177212
goto :loopend ;
178213
:extstatic
@@ -236,7 +271,7 @@ goto :loop ;
236271
echo --with-ntver=0xXXXX target NT version (shouldn't use with old SDK)
237272
echo --with-ntver=_WIN32_WINNT_XXXX
238273
echo --with-ntver=XXXX same as --with-ntver=_WIN32_WINNT_XXXX
239-
echo Note that '[1m=,;[m' need to be enclosed within double quotes in batch file command line.
274+
echo Note that parameters containing spaces must be enclosed within double quotes.
240275
del %confargs% %config_make%
241276
goto :EOF
242277
:unknown_opt

win32/shellsplit.cmd

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
rem shellsplit.cmd
2+
rem input : %args%
3+
rem output: one unquoted %argv%, remains are in %args%
4+
rem note : the empty argument "" is completely ignored.
5+
6+
setlocal EnableExtensions DisableDelayedExpansion
7+
8+
if not defined V set V=0
9+
10+
goto :main
11+
12+
:set
13+
set %*
14+
exit /b
15+
16+
:main
17+
set OUT=
18+
if not defined args (
19+
goto :return_arg
20+
)
21+
set "PENDING=%args%"
22+
set UNQ=
23+
set QTD=
24+
25+
set "HT= "
26+
:: .subst(\", `DQ`) (currently disabled)
27+
rem set "PENDING=%PENDING:\"=`??%" &
28+
:: .subst(", \tsep)
29+
call :set "PENDING=%%PENDING:"=%HT%sep%%"
30+
31+
::#### split into unquoted part, quoted part, remains
32+
:loop
33+
34+
for /F "tokens=1,2* delims=%HT%" %%I in (" %PENDING%") do (
35+
set "UNQ=%%I"
36+
call :set "UNQ=%%UNQ:~1%%"
37+
set "QTD=%%J"
38+
set "PENDING=%%K"
39+
)
40+
41+
if %V%==1 (
42+
echo unquoted:
43+
(echo UNQ :"%UNQ%")&(echo QTD :"%QTD%")&(echo REST:"%PENDING%")&(if defined OUT echo OUT:"%OUT%")
44+
)
45+
46+
if defined QTD set "QTD=%QTD:~3%" &:: remove sep
47+
if defined PENDING set "PENDING=%PENDING:~3%" &:: ditto
48+
49+
if %V%==1 (
50+
(echo QTD :"%QTD%")&(echo REST:"%PENDING%")
51+
)
52+
53+
if not defined UNQ if defined OUT (
54+
set concat_next=true
55+
goto :process_unquote
56+
)
57+
58+
set concat_prev=
59+
set concat_check=
60+
if defined UNQ set "concat_check=%UNQ:~0,1%"
61+
if not "%concat_check%"==" " set concat_prev=true
62+
63+
set concat_next=
64+
set concat_check=
65+
if defined UNQ set "concat_check=%UNQ:~-1%"
66+
if not "%concat_check%"==" " set concat_next=true
67+
68+
if not defined concat_prev if defined OUT (
69+
goto :return_arg
70+
)
71+
72+
::#### process unquoted part
73+
:process_unquote
74+
75+
if defined UNQ if "%UNQ: =%"=="" set UNQ=
76+
if not defined UNQ goto :process_quoted
77+
78+
for /F "tokens=1* eol=" %%I in ("%UNQ%") do (
79+
set "token=%%I"
80+
set "UNQ=%%J"
81+
)
82+
83+
if %V%==1 (
84+
(echo unq :"%token%")&(echo UNQ :"%UNQ%")
85+
)
86+
87+
set "OUT=%OUT%%token%"
88+
if defined UNQ (
89+
goto :return_arg
90+
) else (
91+
if not defined concat_next (
92+
goto :return_arg
93+
)
94+
)
95+
96+
::#### process quoted part
97+
:process_quoted
98+
99+
if %V%==1 (
100+
echo quoted:
101+
(echo UNQ :"%UNQ%")&(echo QTD :"%QTD%")&(echo REST:"%PENDING%")&(if defined OUT echo OUT:"%OUT%")
102+
)
103+
104+
set "OUT=%OUT%%QTD%"
105+
set QTD=
106+
107+
if not defined PENDING (
108+
goto :return_arg
109+
)
110+
goto :loop
111+
112+
::#### return splitted argv
113+
:return_arg
114+
115+
if defined PENDING call :set "PENDING=%%PENDING:%HT%sep="%%"
116+
set eq="
117+
118+
endlocal & set "argv=%OUT%" & set "args=%UNQ%%eq%%QTD%%eq%%PENDING%"
119+
120+
exit /b

win32/test_shellsplit.cmd

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@echo off & if not [%1]==[] goto :process
2+
3+
echo.
4+
echo This script demonstrates how shellsplit.cmd works.
5+
echo usage: %0 arg1 arg2...
6+
echo.
7+
echo Prints separated arguments as (arg1)(arg2)...
8+
echo - splits commandline with spaces/tabs. cmd.exe standard rule is ignored.
9+
echo - you can use double quotes to contain spaces/tabs into an argument.
10+
echo - you can not escape double quote.
11+
echo - solitary "" is ignored since cmd.exe variables cannot represent empty value.
12+
exit /b 0
13+
14+
:process
15+
setlocal
16+
set V=0
17+
18+
set "args=%*"
19+
20+
:loop
21+
call %~dp0\shellsplit.cmd
22+
if not defined argv goto :end
23+
set /p "tmp=(%argv%)"<NUL
24+
goto :loop
25+
26+
:end
27+
endlocal & exit /b 0

0 commit comments

Comments
 (0)