Jason Edmeades : cmd: Add for /f delims= support.
Alexandre Julliard
julliard at winehq.org
Wed Oct 24 13:39:41 CDT 2012
Module: wine
Branch: master
Commit: 51b0d941d0b9c9dc60ecbcc99ed0eacae4329e85
URL: http://source.winehq.org/git/wine.git/?a=commit;h=51b0d941d0b9c9dc60ecbcc99ed0eacae4329e85
Author: Jason Edmeades <jason at edmeades.me.uk>
Date: Tue Oct 23 22:05:06 2012 +0100
cmd: Add for /f delims= support.
---
programs/cmd/batch.c | 29 ++++++++++++++++++++++-------
programs/cmd/builtins.c | 13 +++++++------
programs/cmd/tests/test_builtins.cmd.exp | 12 ++++++------
programs/cmd/wcmd.h | 2 ++
4 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 1c0bc24..7b037d7 100644
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -121,9 +121,10 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
}
/*******************************************************************
- * WCMD_parameter
+ * WCMD_parameter_with_delims
*
- * Extracts a delimited parameter from an input string
+ * Extracts a delimited parameter from an input string, providing
+ * the delimiters characters to use
*
* PARAMS
* s [I] input string, non NULL
@@ -135,6 +136,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
* wholecmdline [I] True to indicate this routine is being used to parse the
* command line, and special logic for arg0->1 transition
* needs to be applied.
+ * delims[I] The delimiter characters to use
*
* RETURNS
* Success: The nth delimited parameter found in s
@@ -150,10 +152,9 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
* other API calls, e.g. c:\"a b"\c is returned as c:\a b\c. However, some commands
* need to preserve the exact syntax (echo, for, etc) hence the raw option.
*/
-WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
- BOOL wholecmdline)
+WCHAR *WCMD_parameter_with_delims (WCHAR *s, int n, WCHAR **start, WCHAR **end,
+ BOOL raw, BOOL wholecmdline, const WCHAR *delims)
{
- static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
int curParamNb = 0;
static WCHAR param[MAX_PATH];
WCHAR *p = s, *begin;
@@ -165,7 +166,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
while (TRUE) {
/* Absorb repeated word delimiters until we get to the next token (or the end!) */
- while (*p && (strchrW(defaultDelims, *p) != NULL))
+ while (*p && (strchrW(delims, *p) != NULL))
p++;
if (*p == '\0') return param;
@@ -179,7 +180,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
/* Loop character by character, but just need to special case quotes */
while (*p) {
/* Once we have found a delimiter, break */
- if (strchrW(defaultDelims, *p) != NULL) break;
+ if (strchrW(delims, *p) != NULL) break;
/* Very odd special case - Seems as if a ( acts as a delimiter which is
not swallowed but is effective only when it comes between the program
@@ -218,6 +219,20 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
}
}
+/*******************************************************************
+ * WCMD_parameter
+ *
+ * Extracts a delimited parameter from an input string, using a
+ * default set of delimiter characters. For parameters, see the main
+ * function above.
+ */
+WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
+ BOOL wholecmdline)
+{
+ static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
+ return WCMD_parameter_with_delims (s, n, start, end, raw, wholecmdline, defaultDelims);
+}
+
/****************************************************************************
* WCMD_fgets
*
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 4bb4702..8eaa9e7 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -1600,7 +1600,7 @@ static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
}
if (*pos==' ' && *(pos+1)==0) delims[i++] = *pos;
delims[i++] = 0; /* Null terminate the delims */
- WINE_FIXME("Found delims as '%s'\n", wine_dbgstr_w(delims));
+ WINE_TRACE("Found delims as '%s'\n", wine_dbgstr_w(delims));
/* Save the tokens being requested */
} else if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
@@ -1694,6 +1694,7 @@ static void WCMD_add_dirstowalk(DIRECTORY_STACK *dirsToWalk) {
* doExecuted [O] - Set to TRUE if the DO is ever executed once
* forf_skip [I/O] - How many lines to skip first
* forf_eol [I] - The 'end of line' (comment) character
+ * forf_delims [I] - The delimiters to use when breaking the string apart
*/
static void WCMD_parse_line(CMD_LIST *cmdStart,
const WCHAR *firstCmd,
@@ -1702,7 +1703,8 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
WCHAR *buffer,
BOOL *doExecuted,
int *forf_skip,
- WCHAR forf_eol) {
+ WCHAR forf_eol,
+ WCHAR *forf_delims) {
WCHAR *parm, *where;
@@ -1713,7 +1715,7 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
}
/* Extract the parameter */
- parm = WCMD_parameter (buffer, 0, &where, NULL, FALSE, FALSE);
+ parm = WCMD_parameter_with_delims(buffer, 0, &where, NULL, FALSE, FALSE, forf_delims);
WINE_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
wine_dbgstr_w(buffer));
@@ -2070,7 +2072,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* Read line by line until end of file */
while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted,
- &forf_skip, forf_eol);
+ &forf_skip, forf_eol, forf_delims);
buffer[0] = 0;
}
CloseHandle (input);
@@ -2090,7 +2092,6 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
Note that the last quote is removed from the set and the string terminates
there to mimic windows */
WCHAR *strend = strrchrW(itemStart, forf_usebackq?'\'':'"');
-
if (strend) {
*strend = 0x00;
itemStart++;
@@ -2099,7 +2100,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* Copy the item away from the global buffer used by WCMD_parameter */
strcpyW(buffer, itemStart);
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted,
- &forf_skip, forf_eol);
+ &forf_skip, forf_eol, forf_delims);
/* Only one string can be supplied in the whole set, abort future set processing */
thisSet = NULL;
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index c15a58d..9b5eb3b 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -826,14 +826,14 @@ ad
z at y
a|d
no output
- at todo_wine@no output
+no output
------ delims option
- at todo_wine@a
- at todo_wine@a at space@
- at todo_wine@a d
a
- at todo_wine@C r
- at todo_wine@foo bar baz
+a at space@
+a d
+a
+C r
+foo bar baz
@todo_wine at c:\
------ skip option
c
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h
index d4d148f..26b89c6 100644
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -108,6 +108,8 @@ static inline BOOL WCMD_is_console_handle(HANDLE h)
}
WCHAR *WCMD_fgets (WCHAR *buf, DWORD n, HANDLE stream);
WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw, BOOL wholecmdline);
+WCHAR *WCMD_parameter_with_delims (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
+ BOOL wholecmdline, const WCHAR *delims);
WCHAR *WCMD_skip_leading_spaces (WCHAR *string);
BOOL WCMD_keyword_ws_found(const WCHAR *keyword, int len, const WCHAR *ptr);
void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable, const WCHAR *forValue, BOOL justFors);
More information about the wine-cvs
mailing list