cmd: Add for /f delims= support.

oldstable
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
* 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
*

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;
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;

View File

@ -826,14 +826,14 @@ ad
z@y
a|d
no output
@todo_wine@no output
no output
------ delims option
@todo_wine@a
@todo_wine@a@space@
@todo_wine@a d
a
@todo_wine@C r
@todo_wine@foo bar baz
a@space@
a d
a
C r
foo bar baz
@todo_wine@c:\
------ skip option
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_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);