Jason Edmeades : cmd: Call and goto finds the next matching label.

Alexandre Julliard julliard at winehq.org
Thu Jul 5 15:25:53 CDT 2018


Module: wine
Branch: master
Commit: 254dc78c2cc5aec26b8af6956c3525c1880bf570
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=254dc78c2cc5aec26b8af6956c3525c1880bf570

Author: Jason Edmeades <us at edmeades.me.uk>
Date:   Wed Jul  4 22:08:39 2018 +0100

cmd: Call and goto finds the next matching label.

A call or a goto will find the next matching label not the first one in the
file. This means it could be later in the file or it could be earlier in the
file, so make goto (which 'call' also uses) first scan from current file
position to the end of the file, and subsequently from the start of the file
to the wrap point.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42823
Signed-off-by: Jason Edmeades <us at edmeades.me.uk>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/cmd/builtins.c                  | 67 +++++++++++++++++++++++---------
 programs/cmd/tests/test_builtins.cmd     | 51 ++++++++++++++++++++++++
 programs/cmd/tests/test_builtins.cmd.exp | 13 +++++++
 3 files changed, 113 insertions(+), 18 deletions(-)

diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 35b68bd..3a0981d 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -2582,30 +2582,61 @@ void WCMD_goto (CMD_LIST **cmdList) {
     if (labelend) *labelend = 0x00;
     WINE_TRACE("goto label: '%s'\n", wine_dbgstr_w(paramStart));
 
-    SetFilePointer (context -> h, 0, NULL, FILE_BEGIN);
-    while (*paramStart &&
-           WCMD_fgets (string, sizeof(string)/sizeof(WCHAR), context -> h)) {
-      str = string;
+    /* Loop through potentially twice - once from current file position
+       through to the end, and second time from start to current file
+       position                                                         */
+    if (*paramStart) {
+        int loop;
+        LARGE_INTEGER startli;
+        for (loop=0; loop<2; loop++) {
+            if (loop==0) {
+              /* On first loop, save the file size */
+              startli.QuadPart = 0;
+              startli.u.LowPart = SetFilePointer(context -> h, startli.u.LowPart,
+                                                 &startli.u.HighPart, FILE_CURRENT);
+            } else {
+              /* On second loop, start at the beginning of the file */
+              WINE_TRACE("Label not found, trying from beginning of file\n");
+              if (loop==1) SetFilePointer (context -> h, 0, NULL, FILE_BEGIN);
+            }
 
-      /* Ignore leading whitespace or no-echo character */
-      while (*str=='@' || isspaceW (*str)) str++;
+            while (WCMD_fgets (string, sizeof(string)/sizeof(WCHAR), context -> h)) {
+              str = string;
 
-      /* If the first real character is a : then this is a label */
-      if (*str == ':') {
-        str++;
+              /* Ignore leading whitespace or no-echo character */
+              while (*str=='@' || isspaceW (*str)) str++;
 
-        /* Skip spaces between : and label */
-        while (isspaceW (*str)) str++;
-        WINE_TRACE("str before brk %s\n", wine_dbgstr_w(str));
+              /* If the first real character is a : then this is a label */
+              if (*str == ':') {
+                str++;
 
-        /* Label ends at whitespace or redirection characters */
-        labelend = strpbrkW(str, labelEndsW);
-        if (labelend) *labelend = 0x00;
-        WINE_TRACE("comparing found label %s\n", wine_dbgstr_w(str));
+                /* Skip spaces between : and label */
+                while (isspaceW (*str)) str++;
+                WINE_TRACE("str before brk %s\n", wine_dbgstr_w(str));
 
-        if (lstrcmpiW (str, paramStart) == 0) return;
-      }
+                /* Label ends at whitespace or redirection characters */
+                labelend = strpbrkW(str, labelEndsW);
+                if (labelend) *labelend = 0x00;
+                WINE_TRACE("comparing found label %s\n", wine_dbgstr_w(str));
+
+                if (lstrcmpiW (str, paramStart) == 0) return;
+              }
+
+              /* See if we have gone beyond the end point if second time through */
+              if (loop==1) {
+                LARGE_INTEGER curli;
+                curli.QuadPart = 0;
+                curli.u.LowPart = SetFilePointer(context -> h, curli.u.LowPart,
+                                                &curli.u.HighPart, FILE_CURRENT);
+                if (curli.QuadPart > startli.QuadPart) {
+                  WINE_TRACE("Reached wrap point, label not found\n");
+                  break;
+                }
+              }
+            }
+        }
     }
+
     WCMD_output_stderr(WCMD_LoadMessage(WCMD_NOTARGET));
     context -> skip_rest = TRUE;
   }
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 49c2d9e..0a8122c 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -3027,6 +3027,57 @@ echo FAILURE at dest 10
 :dest10:this is also ignored
 echo Correctly ignored trailing information
 
+rem Testing which label is reached when there are many options
+echo Begin:
+set nextlabel=
+call :sub
+set nextlabel=middle
+goto :sub
+
+:sub
+echo ..First sub
+if not "%nextlabel%"=="" goto :%nextlabel%
+goto :EOF
+
+:sub
+echo ..Second sub
+if not "%nextlabel%"=="" goto :%nextlabel%
+goto :EOF
+
+:middle
+echo Middle:
+set nextlabel=
+call :sub
+set nextlabel=nearend
+goto :sub
+
+:sub
+echo ..Third sub
+if not "%nextlabel%"=="" goto :%nextlabel%
+goto :EOF
+
+:nearend
+echo Near end:
+set nextlabel=
+call :sub
+set nextlabel=end
+goto :sub
+
+:sub
+echo ..Fourth sub
+if not "%nextlabel%"=="" goto :%nextlabel%
+goto :EOF
+
+:end
+echo At end:
+set nextlabel=
+call :sub
+set nextlabel=done
+goto :sub
+
+:done
+echo Finished
+
 echo ------------ Testing PATH ------------
 set WINE_backup_path=%path%
 set path=original
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index cfde83b..7f4f724 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -1582,6 +1582,19 @@ goto with redirections worked
 Ignoring double colons worked
 label with mixed whitespace and no echo worked
 Correctly ignored trailing information
+Begin:
+..First sub
+..First sub
+Middle:
+..Third sub
+..Third sub
+Near end:
+..Fourth sub
+..Fourth sub
+At end:
+..First sub
+..First sub
+Finished
 ------------ Testing PATH ------------
 PATH=original
 PATH=try2




More information about the wine-cvs mailing list