Module: wine Branch: master Commit: 254dc78c2cc5aec26b8af6956c3525c1880bf570 URL: https://source.winehq.org/git/wine.git/?a=commit;h=254dc78c2cc5aec26b8af6956...
Author: Jason Edmeades us@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@edmeades.me.uk Signed-off-by: Alexandre Julliard julliard@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