=?UTF-8?Q?Fr=C3=A9d=C3=A9ric=20Delanoy=20?=: cmd: Add support for LSS comparison operator in if statements.

Alexandre Julliard julliard at winehq.org
Fri Oct 26 11:36:21 CDT 2012


Module: wine
Branch: master
Commit: 154710a0932e915426b3f08356794aeb7141aa72
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=154710a0932e915426b3f08356794aeb7141aa72

Author: Frédéric Delanoy <frederic.delanoy at gmail.com>
Date:   Thu Oct 25 23:48:02 2012 +0200

cmd: Add support for LSS comparison operator in if statements.

---

 programs/cmd/builtins.c                  |   63 ++++++++++++++++++++++++++---
 programs/cmd/tests/test_builtins.cmd.exp |   50 ++++++++++++------------
 2 files changed, 81 insertions(+), 32 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index af669d3..95419a1 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -104,6 +104,7 @@ static const WCHAR onW[]  = {'O','N','\0'};
 static const WCHAR offW[] = {'O','F','F','\0'};
 static const WCHAR parmY[] = {'/','Y','\0'};
 static const WCHAR parmNoY[] = {'/','-','Y','\0'};
+static const WCHAR eqeqW[]   = {'=','=','\0'};
 
 static HINSTANCE hinst;
 struct env_stack *saved_environment;
@@ -2332,6 +2333,52 @@ void WCMD_popd (void) {
     LocalFree (temp);
 }
 
+/*******************************************************************
+ * evaluate_if_comparison
+ *
+ * Evaluates an "if" comparison operation
+ *
+ * PARAMS
+ *  leftOperand     [I] left operand, non NULL
+ *  operator        [I] "if" binary comparison operator, non NULL
+ *  rightOperand    [I] right operand, non NULL
+ *  caseInsensitive [I] 0 for case sensitive comparison, anything else for insensitive
+ *
+ * RETURNS
+ *  Success:  1 if operator applied to the operands evaluates to TRUE
+ *            0 if operator applied to the operands evaluates to FALSE
+ *  Failure: -1 if operator is not recognized
+ */
+static int evaluate_if_comparison(const WCHAR *leftOperand, const WCHAR *operator,
+                                  const WCHAR *rightOperand, int caseInsensitive)
+{
+    WCHAR *endptr_leftOp, *endptr_rightOp;
+    long int leftOperand_int, rightOperand_int;
+    BOOL int_operands;
+    static const WCHAR lssW[]  = {'l','s','s','\0'};
+
+    /* == is a special case, as it always compares strings */
+    if (!lstrcmpiW(operator, eqeqW))
+        return caseInsensitive ? lstrcmpiW(leftOperand, rightOperand) == 0
+                               : lstrcmpW (leftOperand, rightOperand) == 0;
+
+    /* Check if we have plain integers (in decimal, octal or hexadecimal notation) */
+    leftOperand_int = strtolW(leftOperand, &endptr_leftOp, 0);
+    rightOperand_int = strtolW(rightOperand, &endptr_rightOp, 0);
+    int_operands = (!*endptr_leftOp) && (!*endptr_rightOp);
+
+    /* Perform actual (integer or string) comparison */
+    if (!lstrcmpiW(operator, lssW)) {
+        if (int_operands)
+            return leftOperand_int < rightOperand_int;
+        else
+            return caseInsensitive ? lstrcmpiW(leftOperand, rightOperand) < 0
+                                   : lstrcmpW (leftOperand, rightOperand) < 0;
+    }
+
+    return -1;
+}
+
 /****************************************************************************
  * WCMD_if
  *
@@ -2355,7 +2402,6 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList)
   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 parmI[]   = {'/','I','\0'};
   int caseInsensitive = (strstrW(quals, parmI) != NULL);
 
@@ -2394,18 +2440,21 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList)
     while (*p == ' ' || *p == '\t')
       p++;
 
-    if (strncmpW(p, eqeqW, strlenW(eqeqW)))
-      goto syntax_err;
-
-    strcpyW(operator, eqeqW);
+    if (!strncmpW(p, eqeqW, strlenW(eqeqW)))
+      strcpyW(operator, eqeqW);
+    else {
+      strcpyW(operator, WCMD_parameter(p, 0, &paramStart, FALSE, FALSE));
+      if (!*operator) goto syntax_err;
+    }
     p += strlenW(operator);
 
     strcpyW(rightOperand, WCMD_parameter(p, 0, &paramStart, TRUE, FALSE));
     if (!*rightOperand)
       goto syntax_err;
 
-    test = caseInsensitive ? lstrcmpiW(leftOperand, rightOperand) == 0
-                           : lstrcmpW (leftOperand, rightOperand) == 0;
+    test = evaluate_if_comparison(leftOperand, operator, rightOperand, caseInsensitive);
+    if (test == -1)
+      goto syntax_err;
 
     p = paramStart + strlenW(rightOperand);
     WCMD_parameter(p, 0, &command, FALSE, FALSE);
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 9b5eb3b..b25eb9e 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -441,25 +441,25 @@ quake
 --- comparison operators
 ------ for strings
 LSS string can be used as operand for LSS comparison
- at todo_wine@floats are handled as strings
- at todo_wine@numbers in quotes are handled as strings
- at todo_wine@negative numbers as well at or_broken@NT4
- at todo_wine@if /i seems to work for LSS
- at todo_wine@A LSS B
- at todo_wine@AB LSS B
- at todo_wine@AA LSS B
- at todo_wine@A LSS AB
- at todo_wine@AA LSS AB
- at todo_wine@A LSS BA
- at todo_wine@B LSS BA
- at todo_wine@AB LSS BA
- at todo_wine@AA LSS BA
- at todo_wine@A LSS AA
- at todo_wine@b LSS B at or_broken@NT4
- at todo_wine@a LSS B at or_broken@NT4
- at todo_wine@a LSS B insensitive
- at todo_wine@A LSS b
- at todo_wine@A LSS b insensitive
+floats are handled as strings
+numbers in quotes are handled as strings
+negative numbers as well at or_broken@NT4
+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
 @todo_wine at A LEQ A
 @todo_wine at A LEQ B
 @todo_wine at B LEQ B
@@ -540,12 +540,12 @@ also in negative form
 hexa handled
 also in negative form
 11 LSS 101
- at todo_wine@0 LSS 1
- at todo_wine@0 LSS 10
- at todo_wine@1 LSS 10
- at todo_wine@9 LSS 10
- at todo_wine@0 LSS 9
- at todo_wine@1 LSS 9
+0 LSS 1
+0 LSS 10
+1 LSS 10
+9 LSS 10
+0 LSS 9
+1 LSS 9
 @todo_wine at 0 LEQ 0
 @todo_wine at 0 LEQ 1
 @todo_wine at 1 LEQ 1




More information about the wine-cvs mailing list