[1/7] cmd: Add support for LSS comparison operator in if statements (try 4)
Frédéric Delanoy
frederic.delanoy at gmail.com
Sat Sep 17 03:54:38 CDT 2011
Adapted from John Gilik's original patches
See http://www.winehq.org/pipermail/wine-patches/2010-March/085912.html
Changes since original: changed operands parsing, memchecks
---
programs/cmd/builtins.c | 56 ++++++++++++++++++++++++++++-
programs/cmd/tests/test_builtins.cmd | 56 +++++++++++++++++++++++++++--
programs/cmd/tests/test_builtins.cmd.exp | 40 +++++++++++++++++++--
3 files changed, 142 insertions(+), 10 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 99a2314..d31201a 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1500,11 +1500,13 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
int negate; /* Negate condition */
int test; /* Condition evaluation result */
WCHAR condition[MAX_PATH], *command, *s;
+ WCHAR *left = NULL, *compOp = NULL, *right = NULL;
static const WCHAR notW[] = {'n','o','t','\0'};
static const WCHAR errlvlW[] = {'e','r','r','o','r','l','e','v','e','l','\0'};
static const WCHAR existW[] = {'e','x','i','s','t','\0'};
static const WCHAR defdW[] = {'d','e','f','i','n','e','d','\0'};
static const WCHAR eqeqW[] = {'=','=','\0'};
+ static const WCHAR lssW[] = {'l','s','s','\0'};
static const WCHAR parmI[] = {'/','I','\0'};
int caseInsensitive = (strstrW(quals, parmI) != NULL);
@@ -1540,13 +1542,63 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
WCMD_parameter(s, 1, &command, NULL);
}
else {
- WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
- return;
+ WCHAR *leftPart, *leftPartEnd, *rightPart, *rightPartEnd;
+ long int a, b;
+ WCHAR *endptr_a, *endptr_b;
+ BOOL bothInts;
+
+ /* Need to get surrounding quotes, so we can't use return value of WCMD_parameter */
+ WCMD_parameter(p, 0+negate+caseInsensitive, &leftPart, &leftPartEnd);
+ if (!(left = HeapAlloc(GetProcessHeap(), 0, (leftPartEnd-leftPart+2)*sizeof(WCHAR))))
+ goto err;
+
+ memcpy(left, leftPart, (leftPartEnd-leftPart+1)*sizeof(WCHAR));
+ left[leftPartEnd-leftPart+1] = '\0';
+
+ if (!(compOp = WCMD_strdupW(WCMD_parameter(p, 1+negate+caseInsensitive, NULL, NULL))))
+ goto err;
+
+ WCMD_parameter(p, 2+negate+caseInsensitive, &rightPart, &rightPartEnd);
+ if (!(right = HeapAlloc(GetProcessHeap(), 0, (rightPartEnd-rightPart+2)*sizeof(WCHAR))))
+ goto err;
+
+ memcpy(right, rightPart, (rightPartEnd-rightPart+1)*sizeof(WCHAR));
+ right[rightPartEnd-rightPart+1] = '\0';
+
+ a = strtolW(left, &endptr_a, 0);
+ b = strtolW(right, &endptr_b, 0);
+ bothInts = (!*endptr_a) && (!*endptr_b);
+
+ if (!lstrcmpiW(compOp, lssW)) {
+ if (bothInts)
+ test = (a < b);
+ else
+ test = caseInsensitive ? (lstrcmpiW(left, right) < 0)
+ : (lstrcmpW (left, right) < 0);
+ }
+ else {
+ HeapFree(GetProcessHeap(), 0, left);
+ HeapFree(GetProcessHeap(), 0, compOp);
+ HeapFree(GetProcessHeap(), 0, right);
+ WCMD_output(WCMD_LoadMessage(WCMD_SYNTAXERR));
+ return;
+ }
+ HeapFree(GetProcessHeap(), 0, left);
+ HeapFree(GetProcessHeap(), 0, compOp);
+ HeapFree(GetProcessHeap(), 0, right);
+ WCMD_parameter(p, 3+negate+caseInsensitive, &command, NULL);
}
/* Process rest of IF statement which is on the same line
Note: This may process all or some of the cmdList (eg a GOTO) */
WCMD_part_execute(cmdList, command, NULL, NULL, TRUE, (test != negate));
+ return;
+
+err:
+ HeapFree(GetProcessHeap(), 0, left);
+ HeapFree(GetProcessHeap(), 0, compOp);
+ HeapFree(GetProcessHeap(), 0, right);
+ WINE_ERR("Insufficient memory!\n");
}
/****************************************************************************
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 35ab181..328ad23 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -552,7 +552,7 @@ if exist foo (
)
cd .. & rd foobar
-echo ------------ Testing if/else --------------
+echo ------------ Testing if/else ------------
echo if/else should work with blocks
if 0 == 0 (
echo if seems to work
@@ -569,19 +569,19 @@ if /c==/c (
) else (
echo parameter detection seems to be broken
)
-echo Testing case sensitivity with and without /i option
+echo ... case sensitivity with and without /i option ...
if bar==BAR echo if does not default to case sensitivity
if not bar==BAR echo if seems to default to case sensitivity
if /i foo==FOO echo if /i seems to work
if /i not foo==FOO echo if /i seems to be broken
if /I foo==FOO echo if /I seems to work
if /I not foo==FOO echo if /I seems to be broken
-echo Testing string comparisons
+echo ... string comparisons ...
if abc == abc (echo equal) else echo non equal
if abc =="abc" (echo equal) else echo non equal
if "abc"== abc (echo equal) else echo non equal
if "abc"== "abc" (echo equal) else echo non equal
-echo Testing tabs handling
+echo ... tabs handling ...
if at tab@1==1 echo doom
if @tab at 1==1 echo doom
if 1==1 (echo doom) else at tab@echo quake
@@ -590,6 +590,54 @@ if 1==0 at tab@(echo doom) else echo quake
if 1==0 (echo doom)@tab at else echo quake
if 1==0 (echo doom) else at tab@echo quake
+echo ... comparison operators ...
+rem NT4 misevaluates conditionals in for loops so we have to use subroutines as workarounds
+rem Imbricated for loops parameters are currently not expanded correctly; this prevents usage of simpler imbricated for loops in tests
+echo ...... for strings ......
+rem NT4 stops processing of the whole batch file as soon as it finds a
+rem comparison operator non fully uppercased, such as lss instead of LSS, so we
+rem can't test those here.
+if LSS LSS LSSfoo (echo foo)
+if LSS LSS LSS (echo bar)
+if 1.1 LSS 1.10 (echo toto) else echo lulu
+if "-1" LSS "1" (echo foo) else echo bar
+if "9" LSS "010" (echo loulou) else echo picsou
+if /i foo LSS FoOc echo if /i seems to work for LSS
+if /I not foo LSS FOOb echo if /I seems to be broken for LSS
+set STR_PARMS=A B AB BA AA
+for %%i in (%STR_PARMS%) do call :LSStest %%i A
+for %%i in (%STR_PARMS%) do call :LSStest %%i B
+for %%i in (%STR_PARMS%) do call :LSStest %%i AB
+for %%i in (%STR_PARMS%) do call :LSStest %%i BA
+for %%i in (%STR_PARMS%) do call :LSStest %%i AA
+if b LSS B (echo b LSS B) else echo NT4
+if /I b LSS B echo b LSS B insensitive
+if b LSS A echo b LSS A
+if /I b LSS A echo b LSS A insensitive
+if a LSS B (echo a LSS B) else echo NT4
+if /I a LSS B echo a LSS B insensitive
+if A LSS b echo A LSS b
+if /I A LSS b echo A LSS b insensitive
+echo ...... for numbers ......
+if -1 LSS 1 (echo foo) else echo bar
+if 11 LSS 101 (echo riri) else echo fifi
+if 9 LSS 010 (echo loulou) else echo picsou
+set INT_PARMS=0 1 10 9
+for %%i in (%INT_PARMS%) do call :LSStest %%i 0
+for %%i in (%INT_PARMS%) do call :LSStest %%i 1
+for %%i in (%INT_PARMS%) do call :LSStest %%i 10
+for %%i in (%INT_PARMS%) do call :LSStest %%i 9
+goto :endIfCompOpsSubroutines
+
+rem IF subroutines helpers
+:LSStest
+if %1 LSS %2 echo %1 LSS %2
+goto :eof
+
+:endIfCompOpsSubroutines
+set STR_PARMS=
+set INT_PARMS=
+
echo -----------Testing for -----------
echo ...plain FOR
for %%i in (A B C) do echo %%i
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 31b1780..0563ac4 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -378,21 +378,21 @@ bar
bar
NUL
@todo_wine at foo created
------------- Testing if/else --------------
+------------ Testing if/else ------------
if/else should work with blocks
if seems to work
else seems to work
if seems not to detect /c as parameter
-Testing case sensitivity with and without /i option
+... case sensitivity with and without /i option ...
if seems to default to case sensitivity
if /i seems to work
if /I seems to work
-Testing string comparisons
+... string comparisons ...
equal
non equal
non equal
equal
-Testing tabs handling
+... tabs handling ...
doom
doom
doom
@@ -400,6 +400,38 @@ lol
quake
quake
quake
+... comparison operators ...
+...... for strings ......
+foo
+toto
+bar at or_broken@foo
+picsou
+if /i seems to work for LSS
+A LSS B
+AB LSS B
+AA LSS B
+A LSS AB
+AA LSS AB
+A LSS BA
+B LSS BA
+AB LSS BA
+AA LSS BA
+A LSS AA
+b LSS B at or_broken@NT4
+a LSS B at or_broken@NT4
+a LSS B insensitive
+A LSS b
+A LSS b insensitive
+...... for numbers ......
+foo
+riri
+picsou
+0 LSS 1
+0 LSS 10
+1 LSS 10
+9 LSS 10
+0 LSS 9
+1 LSS 9
-----------Testing for -----------
...plain FOR
A
--
1.7.6.3
More information about the wine-patches
mailing list