[PATCH 5/6] [cmd] Add support for for /f option 'usebackq'

Ann and Jason Edmeades jason at edmeades.me.uk
Tue Oct 16 18:42:53 CDT 2012


Correctly change behaviour based on the usebackq option, and
make the running of the process and parsing of the response
actually work.

(Note extra tracepoint which looks out of place is because when
a batch program is run under for /f in tests around usebackq,
the tests just ends without any diagnostics, and this means you
can work out why!)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20121017/a36c550d/attachment.html>
-------------- next part --------------
From ad9a220da86e0298b2612b0e58fc90509ea54be1 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <jason at edmeades.me.uk>
Date: Wed, 17 Oct 2012 00:28:50 +0100
Subject: [PATCH 5/6] [cmd] Add support for for /f option 'usebackq'

Correctly change behaviour based on the usebackq option, and
make the running of the process and parsing of the response
actually work.

(Note extra tracepoint which looks out of place is because when
a batch program is run under for /f in tests around usebackq,
the tests just ends without any diagnostics, and this means you
can work out why!)
---
 programs/cmd/batch.c                     |    1 +
 programs/cmd/builtins.c                  |   46 +++++++++++++++++++-----------
 programs/cmd/tests/test_builtins.cmd     |   14 +++++++--
 programs/cmd/tests/test_builtins.cmd.exp |    4 +++
 4 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index bacb6cd..903c22b 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -113,6 +113,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
   HeapFree(GetProcessHeap(), 0, context->batchfileW);
   LocalFree (context);
   if ((prev_context != NULL) && (!called)) {
+    WINE_TRACE("Batch completed, which was not 'called' so skipping outer batch too\n");
     prev_context -> skip_rest = TRUE;
     context = prev_context;
   }
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 73b2b52..82de0bc 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1651,7 +1651,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
                          usebackqW, sizeof(usebackqW)/sizeof(WCHAR)) == CSTR_EQUAL) {
         forf_usebackq = TRUE;
         pos = pos + sizeof(usebackqW)/sizeof(WCHAR);
-        if (forf_usebackq) WINE_FIXME("Found usebackq\n");
+        WINE_TRACE("Found usebackq\n");
 
       /* Save the supplied delims. Slightly odd as space can be a delimiter but only
          if you finish the optionsroot string with delims= otherwise the space is
@@ -1875,38 +1875,53 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
             /* else ignore them! */
 
         /* Filesets - either a list of files, or a command to run and parse the output */
-        } else if (doFileset && *itemStart != '"') {
+        } else if (doFileset && ((!forf_usebackq && *itemStart != '"') ||
+                                 (forf_usebackq && *itemStart != '\''))) {
 
             HANDLE input;
-            WCHAR temp_file[MAX_PATH];
+            WCHAR  temp_file[MAX_PATH];
 
             WINE_TRACE("Processing for filespec from item %d '%s'\n", itemNum,
                        wine_dbgstr_w(item));
+            temp_file[0] = 0x00;
+
 
             /* If backquote or single quote, we need to launch that command
                and parse the results - use a temporary file                 */
-            if (*itemStart == '`' || *itemStart == '\'') {
+            if ((forf_usebackq && *itemStart == '`') ||
+                (!forf_usebackq && *itemStart == '\'')) {
 
-                WCHAR temp_path[MAX_PATH], temp_cmd[MAXSTRING];
-                static const WCHAR redirOut[] = {'>','%','s','\0'};
-                static const WCHAR cmdW[]     = {'C','M','D','\0'};
+                WCHAR temp_str[MAX_PATH], temp_cmd[MAXSTRING];
+                static const WCHAR redirOutW[]  = {'>','%','s','\0'};
+                static const WCHAR cmdW[]       = {'C','M','D','\0'};
+                static const WCHAR cmdslashcW[] = {'C','M','D','.','E','X','E',' ',
+                                                   '/','C',' ','"','%','s','"','\0'};
 
                 /* Remove trailing character */
                 itemStart[strlenW(itemStart)-1] = 0x00;
 
                 /* Get temp filename */
-                GetTempPathW(sizeof(temp_path)/sizeof(WCHAR), temp_path);
-                GetTempFileNameW(temp_path, cmdW, 0, temp_file);
+                GetTempPathW(sizeof(temp_str)/sizeof(WCHAR), temp_str);
+                GetTempFileNameW(temp_str, cmdW, 0, temp_file);
 
-                /* Execute program and redirect output */
-                wsprintfW(temp_cmd, redirOut, (itemStart+1), temp_file);
-                WCMD_execute (itemStart, temp_cmd, NULL, NULL, NULL, FALSE);
+                /* Redirect output to the temporary file */
+                wsprintfW(temp_str, redirOutW, temp_file);
+                wsprintfW(temp_cmd, cmdslashcW, itemStart+1);
+                WINE_TRACE("Issuing '%s' with redirs '%s'\n",
+                           wine_dbgstr_w(temp_cmd), wine_dbgstr_w(temp_str));
+                WCMD_execute (temp_cmd, temp_str, NULL, NULL, NULL, FALSE);
 
                 /* Open the file, read line by line and process */
                 input = CreateFileW(temp_file, GENERIC_READ, FILE_SHARE_READ,
                                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
             } else {
 
+                /* Remove surrounding quotes */
+                if (forf_usebackq && *item == '"') {
+                  item[strlenW(item)-1] = 0x00;
+                  item++;
+                }
+
                 /* Open the file, read line by line and process */
                 input = CreateFileW(item, GENERIC_READ, FILE_SHARE_READ,
                                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -1954,12 +1969,11 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
             }
 
             /* Delete the temporary file */
-            if (*itemStart == '`' || *itemStart == '\'') {
-                DeleteFileW(temp_file);
-            }
+            if (temp_file[0]) DeleteFileW(temp_file);
 
         /* Filesets - A string literal */
-        } else if (doFileset && *itemStart == '"') {
+        } else if (doFileset && ((!forf_usebackq && *itemStart == '"') ||
+                                 (forf_usebackq && *itemStart == '\''))) {
             WCHAR buffer[MAXSTRING];
             WCHAR *where, *parm;
 
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index 578826b..bdc4a3f 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1000,9 +1000,17 @@ echo.>> bar
 echo kkk>>bar
 for /f %%k in (foo bar) do echo %%k
 for /f %%k in (bar foo) do echo %%k
-rem echo ------ command argument
-rem Not implemented on NT4
-rem FIXME: Not testable right now in wine: not implemented and would need
+echo ------ command argument
+rem Not implemented on NT4, need to skip it as no way to get output otherwise
+if "%CD%"=="" goto :SkipFORFcmdNT4
+for /f %%i in ('echo.Passed1') do echo %%i
+for /f "usebackq" %%i in (`echo.Passed2`) do echo %%i
+for /f usebackq %%i in (`echo.Passed3`) do echo %%i
+goto :ContinueFORF
+:SkipFORFcmdNT4
+for /l %%i in (1,1,3) do echo Missing functionality - Broken%%i
+:ContinueFORF
+rem FIXME: Rest not testable right now in wine: not implemented and would need
 rem preliminary grep-like program implementation (e.g. like findstr or fc) even
 rem for a simple todo_wine test
 rem (for /f "usebackq" %%i in (`echo z a b`) do echo %%i) || echo not supported
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 12fbd8f..c0b7baf 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -638,6 +638,10 @@ kkk
 a
 b
 c
+------ command argument
+Passed1 at or_broken@Missing functionality - Broken1
+Passed2 at or_broken@Missing functionality - Broken2
+Passed3 at or_broken@Missing functionality - Broken3
 ------ eol option
 @todo_wine at ad
 @todo_wine at z@y
-- 
1.7.9.5


More information about the wine-patches mailing list