cmd: Add for /f delims= support.

This commit is contained in:
Jason Edmeades 2012-10-23 22:05:06 +01:00 committed by Alexandre Julliard
parent a45301cb93
commit 51b0d941d0
4 changed files with 37 additions and 19 deletions

View File

@ -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 * PARAMS
* s [I] input string, non NULL * 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 * wholecmdline [I] True to indicate this routine is being used to parse the
* command line, and special logic for arg0->1 transition * command line, and special logic for arg0->1 transition
* needs to be applied. * needs to be applied.
* delims[I] The delimiter characters to use
* *
* RETURNS * RETURNS
* Success: The nth delimited parameter found in s * 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 * 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. * 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, WCHAR *WCMD_parameter_with_delims (WCHAR *s, int n, WCHAR **start, WCHAR **end,
BOOL wholecmdline) BOOL raw, BOOL wholecmdline, const WCHAR *delims)
{ {
static const WCHAR defaultDelims[] = { ' ', '\t', ',', '=', ';', '\0' };
int curParamNb = 0; int curParamNb = 0;
static WCHAR param[MAX_PATH]; static WCHAR param[MAX_PATH];
WCHAR *p = s, *begin; WCHAR *p = s, *begin;
@ -165,7 +166,7 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **start, WCHAR **end, BOOL raw,
while (TRUE) { while (TRUE) {
/* Absorb repeated word delimiters until we get to the next token (or the end!) */ /* 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++; p++;
if (*p == '\0') return param; 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 */ /* Loop character by character, but just need to special case quotes */
while (*p) { while (*p) {
/* Once we have found a delimiter, break */ /* 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 /* 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 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 * WCMD_fgets
* *

View File

@ -1600,7 +1600,7 @@ static BOOL WCMD_parse_forf_options(WCHAR *options, WCHAR *eol, int *skip,
} }
if (*pos==' ' && *(pos+1)==0) delims[i++] = *pos; if (*pos==' ' && *(pos+1)==0) delims[i++] = *pos;
delims[i++] = 0; /* Null terminate the delims */ 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 */ /* Save the tokens being requested */
} else if (CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, } 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 * doExecuted [O] - Set to TRUE if the DO is ever executed once
* forf_skip [I/O] - How many lines to skip first * forf_skip [I/O] - How many lines to skip first
* forf_eol [I] - The 'end of line' (comment) character * 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, static void WCMD_parse_line(CMD_LIST *cmdStart,
const WCHAR *firstCmd, const WCHAR *firstCmd,
@ -1702,7 +1703,8 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
WCHAR *buffer, WCHAR *buffer,
BOOL *doExecuted, BOOL *doExecuted,
int *forf_skip, int *forf_skip,
WCHAR forf_eol) { WCHAR forf_eol,
WCHAR *forf_delims) {
WCHAR *parm, *where; WCHAR *parm, *where;
@ -1713,7 +1715,7 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
} }
/* Extract the parameter */ /* 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_TRACE("Parsed parameter: %s from %s\n", wine_dbgstr_w(parm),
wine_dbgstr_w(buffer)); wine_dbgstr_w(buffer));
@ -2070,7 +2072,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* Read line by line until end of file */ /* Read line by line until end of file */
while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) { while (WCMD_fgets(buffer, sizeof(buffer)/sizeof(WCHAR), input)) {
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted, WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted,
&forf_skip, forf_eol); &forf_skip, forf_eol, forf_delims);
buffer[0] = 0; buffer[0] = 0;
} }
CloseHandle (input); 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 Note that the last quote is removed from the set and the string terminates
there to mimic windows */ there to mimic windows */
WCHAR *strend = strrchrW(itemStart, forf_usebackq?'\'':'"'); WCHAR *strend = strrchrW(itemStart, forf_usebackq?'\'':'"');
if (strend) { if (strend) {
*strend = 0x00; *strend = 0x00;
itemStart++; 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 */ /* Copy the item away from the global buffer used by WCMD_parameter */
strcpyW(buffer, itemStart); strcpyW(buffer, itemStart);
WCMD_parse_line(cmdStart, firstCmd, &cmdEnd, variable, buffer, &doExecuted, 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 */ /* Only one string can be supplied in the whole set, abort future set processing */
thisSet = NULL; thisSet = NULL;

View File

@ -826,14 +826,14 @@ ad
z@y z@y
a|d a|d
no output no output
@todo_wine@no output no output
------ delims option ------ delims option
@todo_wine@a
@todo_wine@a@space@
@todo_wine@a d
a a
@todo_wine@C r a@space@
@todo_wine@foo bar baz a d
a
C r
foo bar baz
@todo_wine@c:\ @todo_wine@c:\
------ skip option ------ skip option
c c

View File

@ -108,6 +108,8 @@ static inline BOOL WCMD_is_console_handle(HANDLE h)
} }
WCHAR *WCMD_fgets (WCHAR *buf, DWORD n, HANDLE stream); 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 (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); WCHAR *WCMD_skip_leading_spaces (WCHAR *string);
BOOL WCMD_keyword_ws_found(const WCHAR *keyword, int len, const WCHAR *ptr); 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); void WCMD_HandleTildaModifiers(WCHAR **start, const WCHAR *forVariable, const WCHAR *forValue, BOOL justFors);