mirror of
https://github.com/reactos/wine.git
synced 2024-11-25 12:49:45 +00:00
cmd.exe: Fix FOR so it works as 'well' as before.
This commit is contained in:
parent
d2e7b401a2
commit
54d890ca1e
@ -109,7 +109,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HAN
|
||||
CMD_LIST *toExecute = NULL; /* Commands left to be executed */
|
||||
if (WCMD_ReadAndParseLine(NULL, &toExecute, h) == NULL)
|
||||
break;
|
||||
WCMD_process_commands(toExecute, FALSE);
|
||||
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||
WCMD_free_commands(toExecute);
|
||||
toExecute = NULL;
|
||||
}
|
||||
@ -168,21 +168,9 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) {
|
||||
i++;
|
||||
p = param;
|
||||
break;
|
||||
case '(':
|
||||
if (where != NULL && i==n) *where = s;
|
||||
s++;
|
||||
while ((*s != '\0') && (*s != ')')) {
|
||||
*p++ = *s++;
|
||||
}
|
||||
if (i == n) {
|
||||
*p = '\0';
|
||||
return param;
|
||||
}
|
||||
if (*s == ')') s++;
|
||||
param[0] = '\0';
|
||||
i++;
|
||||
p = param;
|
||||
break;
|
||||
/* The code to handle bracketed parms is removed because it should no longer
|
||||
be necessary after the multiline support has been added and the for loop
|
||||
set of data is now parseable individually. */
|
||||
case '\0':
|
||||
return param;
|
||||
default:
|
||||
|
@ -40,7 +40,8 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
|
||||
|
||||
void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution, CMD_LIST **cmdList);
|
||||
static void WCMD_part_execute(CMD_LIST **commands, WCHAR *firstcmd, WCHAR *variable,
|
||||
WCHAR *value, BOOL isIF, BOOL conditionTRUE);
|
||||
|
||||
struct env_stack *saved_environment;
|
||||
struct env_stack *pushd_directories;
|
||||
@ -571,6 +572,12 @@ void WCMD_echo (const WCHAR *command) {
|
||||
* WCMD_for
|
||||
*
|
||||
* Batch file loop processing.
|
||||
*
|
||||
* On entry: cmdList contains the syntax up to the set
|
||||
* next cmdList and all in that bracket contain the set data
|
||||
* next cmdlist contains the DO cmd
|
||||
* following that is either brackets or && entries (as per if)
|
||||
*
|
||||
* FIXME: We don't exhaustively check syntax. Any command which works in MessDOS
|
||||
* will probably work here, but the reverse is not necessarily the case...
|
||||
*/
|
||||
@ -579,45 +586,211 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
|
||||
|
||||
WIN32_FIND_DATA fd;
|
||||
HANDLE hff;
|
||||
WCHAR *cmd, *item;
|
||||
WCHAR set[MAX_PATH], param[MAX_PATH];
|
||||
int i;
|
||||
const WCHAR inW[] = {'i', 'n', '\0'};
|
||||
const WCHAR doW[] = {'d', 'o', '\0'};
|
||||
const WCHAR doW[] = {'d', 'o', ' ','\0'};
|
||||
CMD_LIST *setStart, *thisSet, *cmdStart, *cmdEnd;
|
||||
WCHAR variable[4];
|
||||
WCHAR *firstCmd;
|
||||
int thisDepth;
|
||||
|
||||
/* Check:
|
||||
the first line includes the % variable name as first parm
|
||||
we have been provided with more parts to the command
|
||||
and there is at least some set data
|
||||
and IN as the one after that */
|
||||
if (lstrcmpiW (WCMD_parameter (p, 1, NULL), inW)
|
||||
|| lstrcmpiW (WCMD_parameter (p, 3, NULL), doW)
|
||||
|| (param1[0] != '%')) {
|
||||
|| (*cmdList) == NULL
|
||||
|| (*cmdList)->nextcommand == NULL
|
||||
|| (param1[0] != '%')
|
||||
|| (strlenW(param1) > 3)) {
|
||||
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||
return;
|
||||
}
|
||||
lstrcpynW (set, WCMD_parameter (p, 2, NULL), sizeof(set)/sizeof(WCHAR));
|
||||
WCMD_parameter (p, 4, &cmd);
|
||||
strcpyW (param, param1);
|
||||
|
||||
/*
|
||||
* If the parameter within the set has a wildcard then search for matching files
|
||||
* otherwise do a literal substitution.
|
||||
*/
|
||||
/* Save away where the set of data starts and the variable */
|
||||
strcpyW(variable, param1);
|
||||
thisDepth = (*cmdList)->bracketDepth;
|
||||
*cmdList = (*cmdList)->nextcommand;
|
||||
setStart = (*cmdList);
|
||||
|
||||
i = 0;
|
||||
while (*(item = WCMD_parameter (set, i, NULL))) {
|
||||
static const WCHAR wildcards[] = {'*','?','\0'};
|
||||
if (strpbrkW (item, wildcards)) {
|
||||
hff = FindFirstFile (item, &fd);
|
||||
if (hff == INVALID_HANDLE_VALUE) {
|
||||
return;
|
||||
}
|
||||
do {
|
||||
WCMD_execute (cmd, param, fd.cFileName, cmdList);
|
||||
} while (FindNextFile(hff, &fd) != 0);
|
||||
FindClose (hff);
|
||||
}
|
||||
else {
|
||||
WCMD_execute (cmd, param, item, cmdList);
|
||||
}
|
||||
i++;
|
||||
/* Skip until the close bracket */
|
||||
WINE_TRACE("Searching %p as the set\n", *cmdList);
|
||||
while (*cmdList &&
|
||||
(*cmdList)->command != NULL &&
|
||||
(*cmdList)->bracketDepth > thisDepth) {
|
||||
WINE_TRACE("Skipping %p which is part of the set\n", *cmdList);
|
||||
*cmdList = (*cmdList)->nextcommand;
|
||||
}
|
||||
|
||||
/* Skip the close bracket, if there is one */
|
||||
if (*cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* Syntax error if missing close bracket, or nothing following it
|
||||
and once we have the complete set, we expect a DO */
|
||||
WINE_TRACE("Looking for 'do' in %p\n", *cmdList);
|
||||
if ((*cmdList == NULL) ||
|
||||
(CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
(*cmdList)->command, 3, doW, -1) != 2)) {
|
||||
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save away the starting position for the commands (and offset for the
|
||||
first one */
|
||||
cmdStart = *cmdList;
|
||||
cmdEnd = *cmdList;
|
||||
firstCmd = (*cmdList)->command + 3; /* Skip 'do ' */
|
||||
|
||||
thisSet = setStart;
|
||||
/* Loop through all set entries */
|
||||
while (thisSet &&
|
||||
thisSet->command != NULL &&
|
||||
thisSet->bracketDepth >= thisDepth) {
|
||||
|
||||
/* Loop through all entries on the same line */
|
||||
WCHAR *item;
|
||||
|
||||
WINE_TRACE("Processing for set %p\n", thisSet);
|
||||
i = 0;
|
||||
while (*(item = WCMD_parameter (thisSet->command, i, NULL))) {
|
||||
|
||||
/*
|
||||
* If the parameter within the set has a wildcard then search for matching files
|
||||
* otherwise do a literal substitution.
|
||||
*/
|
||||
static const WCHAR wildcards[] = {'*','?','\0'};
|
||||
CMD_LIST *thisCmdStart = cmdStart;
|
||||
|
||||
WINE_TRACE("Processing for item '%s'\n", wine_dbgstr_w(item));
|
||||
if (strpbrkW (item, wildcards)) {
|
||||
hff = FindFirstFile (item, &fd);
|
||||
if (hff != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
thisCmdStart = cmdStart;
|
||||
WINE_TRACE("Processing FOR filename %s\n", wine_dbgstr_w(fd.cFileName));
|
||||
WCMD_part_execute (&thisCmdStart, firstCmd, variable,
|
||||
fd.cFileName, FALSE, TRUE);
|
||||
|
||||
} while (FindNextFile(hff, &fd) != 0);
|
||||
FindClose (hff);
|
||||
}
|
||||
} else {
|
||||
WCMD_part_execute(&thisCmdStart, firstCmd, variable, item, FALSE, TRUE);
|
||||
}
|
||||
|
||||
WINE_TRACE("Post-command, cmdEnd = %p\n", cmdEnd);
|
||||
cmdEnd = thisCmdStart;
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Move onto the next set line */
|
||||
thisSet = thisSet->nextcommand;
|
||||
}
|
||||
|
||||
/* When the loop ends, either something like a GOTO or EXIT /b has terminated
|
||||
all processing, OR it should be pointing to the end of && processing OR
|
||||
it should be pointing at the NULL end of bracket for the DO. The return
|
||||
value needs to be the NEXT command to execute, which it either is, or
|
||||
we need to step over the closing bracket */
|
||||
*cmdList = cmdEnd;
|
||||
if (cmdEnd && cmdEnd->command == NULL) *cmdList = cmdEnd->nextcommand;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* WCMD_part_execute
|
||||
*
|
||||
* Execute a command, and any && or bracketed follow on to the command. The
|
||||
* first command to be executed may not be at the front of the
|
||||
* commands->thiscommand string (eg. it may point after a DO or ELSE
|
||||
* Returns TRUE if something like exit or goto has aborted all processing
|
||||
*/
|
||||
void WCMD_part_execute(CMD_LIST **cmdList, WCHAR *firstcmd, WCHAR *variable,
|
||||
WCHAR *value, BOOL isIF, BOOL conditionTRUE) {
|
||||
|
||||
CMD_LIST *curPosition = *cmdList;
|
||||
int myDepth = (*cmdList)->bracketDepth;
|
||||
|
||||
WINE_TRACE("cmdList(%p), firstCmd(%p), with '%s'='%s', doIt(%d)\n",
|
||||
cmdList, wine_dbgstr_w(firstcmd),
|
||||
wine_dbgstr_w(variable), wine_dbgstr_w(value),
|
||||
conditionTRUE);
|
||||
|
||||
/* Skip leading whitespace between condition and the command */
|
||||
while (firstcmd && *firstcmd && (*firstcmd==' ' || *firstcmd=='\t')) firstcmd++;
|
||||
|
||||
/* Process the first command, if there is one */
|
||||
if (conditionTRUE && firstcmd && *firstcmd) {
|
||||
WCHAR *command = WCMD_strdupW(firstcmd);
|
||||
WCMD_execute (firstcmd, variable, value, cmdList);
|
||||
free (command);
|
||||
}
|
||||
|
||||
|
||||
/* If it didnt move the position, step to next command */
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* Process any other parts of the command */
|
||||
if (*cmdList) {
|
||||
BOOL processThese = TRUE;
|
||||
|
||||
if (isIF) processThese = conditionTRUE;
|
||||
|
||||
while (*cmdList) {
|
||||
const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
|
||||
|
||||
/* execute all appropriate commands */
|
||||
curPosition = *cmdList;
|
||||
|
||||
WINE_TRACE("Processing cmdList(%p) - &(%d) bd(%d / %d)\n",
|
||||
*cmdList,
|
||||
(*cmdList)->isAmphersand,
|
||||
(*cmdList)->bracketDepth, myDepth);
|
||||
|
||||
/* Execute any appended to the statement with &&'s */
|
||||
if ((*cmdList)->isAmphersand) {
|
||||
if (processThese) {
|
||||
WCMD_execute ((*cmdList)->command, variable, value, cmdList);
|
||||
}
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* Execute any appended to the statement with (...) */
|
||||
} else if ((*cmdList)->bracketDepth > myDepth) {
|
||||
if (processThese) {
|
||||
*cmdList = WCMD_process_commands(*cmdList, TRUE, variable, value);
|
||||
WINE_TRACE("Back from processing commands, (next = %p)\n", *cmdList);
|
||||
}
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* End of the command - does 'ELSE ' follow as the next command? */
|
||||
} else {
|
||||
if (isIF && CompareString (LOCALE_USER_DEFAULT,
|
||||
NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
(*cmdList)->command, 5, ifElse, -1) == 2) {
|
||||
|
||||
/* Swap between if and else processing */
|
||||
processThese = !processThese;
|
||||
|
||||
/* Process the ELSE part */
|
||||
if (processThese) {
|
||||
WCHAR *cmd = ((*cmdList)->command) + strlenW(ifElse);
|
||||
|
||||
/* Skip leading whitespace between condition and the command */
|
||||
while (*cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
|
||||
if (*cmd) {
|
||||
WCMD_execute (cmd, variable, value, cmdList);
|
||||
}
|
||||
}
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
} else {
|
||||
WINE_TRACE("Found end of this IF statement (next = %p)\n", *cmdList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -631,22 +804,26 @@ void WCMD_execute (WCHAR *orig_cmd, WCHAR *param, WCHAR *subst, CMD_LIST **cmdLi
|
||||
WCHAR *new_cmd, *p, *s, *dup;
|
||||
int size;
|
||||
|
||||
size = strlenW (orig_cmd);
|
||||
new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
|
||||
dup = s = WCMD_strdupW(orig_cmd);
|
||||
if (param) {
|
||||
size = (strlenW (orig_cmd) + 1) * sizeof(WCHAR);
|
||||
new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
|
||||
dup = s = WCMD_strdupW(orig_cmd);
|
||||
|
||||
while ((p = strstrW (s, param))) {
|
||||
*p = '\0';
|
||||
size += strlenW (subst);
|
||||
new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
|
||||
while ((p = strstrW (s, param))) {
|
||||
*p = '\0';
|
||||
size += strlenW (subst) * sizeof(WCHAR);
|
||||
new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
|
||||
strcatW (new_cmd, s);
|
||||
strcatW (new_cmd, subst);
|
||||
s = p + strlenW (param);
|
||||
}
|
||||
strcatW (new_cmd, s);
|
||||
strcatW (new_cmd, subst);
|
||||
s = p + strlenW (param);
|
||||
WCMD_process_command (new_cmd, cmdList);
|
||||
free (dup);
|
||||
LocalFree ((HANDLE)new_cmd);
|
||||
} else {
|
||||
WCMD_process_command (orig_cmd, cmdList);
|
||||
}
|
||||
strcatW (new_cmd, s);
|
||||
WCMD_process_command (new_cmd, cmdList);
|
||||
free (dup);
|
||||
LocalFree ((HANDLE)new_cmd);
|
||||
}
|
||||
|
||||
|
||||
@ -810,8 +987,6 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
|
||||
static const WCHAR existW[] = {'e','x','i','s','t','\0'};
|
||||
static const WCHAR defdW[] = {'d','e','f','i','n','e','d','\0'};
|
||||
static const WCHAR eqeqW[] = {'=','=','\0'};
|
||||
CMD_LIST *curPosition;
|
||||
int myDepth;
|
||||
|
||||
if (!lstrcmpiW (param1, notW)) {
|
||||
negate = 1;
|
||||
@ -848,81 +1023,7 @@ void WCMD_if (WCHAR *p, CMD_LIST **cmdList) {
|
||||
|
||||
/* Process rest of IF statement which is on the same line
|
||||
Note: This may process all or some of the cmdList (eg a GOTO) */
|
||||
curPosition = *cmdList;
|
||||
myDepth = (*cmdList)->bracketDepth;
|
||||
|
||||
if (test != negate) {
|
||||
WCHAR *cmd = command;
|
||||
|
||||
/* Skip leading whitespace between condition and the command */
|
||||
while (cmd && *cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
|
||||
|
||||
if (cmd && *cmd) {
|
||||
command = WCMD_strdupW(cmd);
|
||||
WCMD_process_command (command, cmdList);
|
||||
free (command);
|
||||
}
|
||||
}
|
||||
|
||||
/* If it didnt move the position, step to next command */
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* Process any other parts of the IF */
|
||||
if (*cmdList) {
|
||||
BOOL processThese = (test != negate);
|
||||
|
||||
while (*cmdList) {
|
||||
const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
|
||||
|
||||
/* execute all appropriate commands */
|
||||
curPosition = *cmdList;
|
||||
|
||||
WINE_TRACE("Processing cmdList(%p) - &(%d) bd(%d / %d)\n",
|
||||
*cmdList,
|
||||
(*cmdList)->isAmphersand,
|
||||
(*cmdList)->bracketDepth, myDepth);
|
||||
|
||||
/* Execute any appended to the statement with &&'s */
|
||||
if ((*cmdList)->isAmphersand) {
|
||||
if (processThese) {
|
||||
WCMD_process_command((*cmdList)->command, cmdList);
|
||||
}
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* Execute any appended to the statement with (...) */
|
||||
} else if ((*cmdList)->bracketDepth > myDepth) {
|
||||
if (processThese) {
|
||||
*cmdList = WCMD_process_commands(*cmdList, TRUE);
|
||||
WINE_TRACE("Back from processing commands, (next = %p)\n", *cmdList);
|
||||
}
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
|
||||
/* End of the command - does 'ELSE ' follow as the next command? */
|
||||
} else {
|
||||
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT,
|
||||
(*cmdList)->command, 5, ifElse, -1) == 2) {
|
||||
|
||||
/* Swap between if and else processing */
|
||||
processThese = !processThese;
|
||||
|
||||
/* Process the ELSE part */
|
||||
if (processThese) {
|
||||
WCHAR *cmd = ((*cmdList)->command) + strlenW(ifElse);
|
||||
|
||||
/* Skip leading whitespace between condition and the command */
|
||||
while (*cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
|
||||
if (*cmd) {
|
||||
WCMD_process_command(cmd, cmdList);
|
||||
}
|
||||
}
|
||||
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
|
||||
} else {
|
||||
WINE_TRACE("Found end of this IF statement (next = %p)\n", *cmdList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WCMD_part_execute(cmdList, command, NULL, NULL, TRUE, (test != negate));
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -62,7 +62,7 @@ void WCMD_output (const WCHAR *format, ...);
|
||||
void WCMD_output_asis (const WCHAR *message);
|
||||
void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2);
|
||||
void WCMD_pause (void);
|
||||
void WCMD_pipe (CMD_LIST **command);
|
||||
void WCMD_pipe (CMD_LIST **command, WCHAR *var, WCHAR *val);
|
||||
void WCMD_popd (void);
|
||||
void WCMD_print_error (void);
|
||||
void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList);
|
||||
@ -101,9 +101,10 @@ WCHAR *WCMD_strdupW(WCHAR *input);
|
||||
BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars,
|
||||
LPDWORD charsRead, const LPOVERLAPPED unused);
|
||||
|
||||
WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
|
||||
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket);
|
||||
void WCMD_free_commands(CMD_LIST *cmds);
|
||||
WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
|
||||
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket, WCHAR *var, WCHAR *val);
|
||||
void WCMD_free_commands(CMD_LIST *cmds);
|
||||
void WCMD_execute (WCHAR *orig_command, WCHAR *parameter, WCHAR *substitution, CMD_LIST **cmdList);
|
||||
|
||||
/* Data structure to hold context when executing batch files */
|
||||
|
||||
|
@ -324,7 +324,7 @@ int wmain (int argc, WCHAR *argvW[])
|
||||
|
||||
/* Parse the command string, without reading any more input */
|
||||
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
|
||||
WCMD_process_commands(toExecute, FALSE);
|
||||
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||
WCMD_free_commands(toExecute);
|
||||
toExecute = NULL;
|
||||
|
||||
@ -417,7 +417,7 @@ int wmain (int argc, WCHAR *argvW[])
|
||||
if (opt_k) {
|
||||
/* Parse the command string, without reading any more input */
|
||||
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
|
||||
WCMD_process_commands(toExecute, FALSE);
|
||||
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||
WCMD_free_commands(toExecute);
|
||||
toExecute = NULL;
|
||||
HeapFree(GetProcessHeap(), 0, cmd);
|
||||
@ -449,7 +449,7 @@ int wmain (int argc, WCHAR *argvW[])
|
||||
if (WCMD_ReadAndParseLine(NULL, &toExecute,
|
||||
GetStdHandle(STD_INPUT_HANDLE)) == NULL)
|
||||
break;
|
||||
WCMD_process_commands(toExecute, FALSE);
|
||||
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||
WCMD_free_commands(toExecute);
|
||||
toExecute = NULL;
|
||||
}
|
||||
@ -497,8 +497,12 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList)
|
||||
while ((p = strchrW(p, '%'))) {
|
||||
i = *(p+1) - '0';
|
||||
|
||||
/* Dont touch %% */
|
||||
if (*(p+1) == '%') {
|
||||
p+=2;
|
||||
|
||||
/* Replace %~ modifications if in batch program */
|
||||
if (context && *(p+1) == '~') {
|
||||
} else if (context && *(p+1) == '~') {
|
||||
WCMD_HandleTildaModifiers(&p, NULL);
|
||||
p++;
|
||||
|
||||
@ -531,13 +535,17 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList)
|
||||
if (context) {
|
||||
p = cmd;
|
||||
while ((p = strchrW(p, '%'))) {
|
||||
s = strchrW(p+1, '%');
|
||||
if (!s) {
|
||||
*p=0x00;
|
||||
if (*(p+1) == '%') {
|
||||
p+=2;
|
||||
} else {
|
||||
t = WCMD_strdupW(s+1);
|
||||
strcpyW(p, t);
|
||||
free(t);
|
||||
s = strchrW(p+1, '%');
|
||||
if (!s) {
|
||||
*p=0x00;
|
||||
} else {
|
||||
t = WCMD_strdupW(s+1);
|
||||
strcpyW(p, t);
|
||||
free(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1487,7 +1495,7 @@ void WCMD_opt_s_strip_quotes(WCHAR *cmd) {
|
||||
* Handle pipes within a command - the DOS way using temporary files.
|
||||
*/
|
||||
|
||||
void WCMD_pipe (CMD_LIST **cmdEntry) {
|
||||
void WCMD_pipe (CMD_LIST **cmdEntry, WCHAR *var, WCHAR *val) {
|
||||
|
||||
WCHAR *p;
|
||||
WCHAR *command = (*cmdEntry)->command;
|
||||
@ -1503,19 +1511,19 @@ void WCMD_pipe (CMD_LIST **cmdEntry) {
|
||||
p = strchrW(command, '|');
|
||||
*p++ = '\0';
|
||||
wsprintf (temp_cmd, redirOut, command, temp_file);
|
||||
WCMD_process_command (temp_cmd, cmdEntry);
|
||||
WCMD_execute (temp_cmd, var, val, cmdEntry);
|
||||
command = p;
|
||||
while ((p = strchrW(command, '|'))) {
|
||||
*p++ = '\0';
|
||||
GetTempFileName (temp_path, cmdW, 0, temp_file2);
|
||||
wsprintf (temp_cmd, redirBoth, command, temp_file, temp_file2);
|
||||
WCMD_process_command (temp_cmd, cmdEntry);
|
||||
WCMD_execute (temp_cmd, var, val, cmdEntry);
|
||||
DeleteFile (temp_file);
|
||||
strcpyW (temp_file, temp_file2);
|
||||
command = p;
|
||||
}
|
||||
wsprintf (temp_cmd, redirIn, command, temp_file);
|
||||
WCMD_process_command (temp_cmd, cmdEntry);
|
||||
WCMD_execute (temp_cmd, var, val, cmdEntry);
|
||||
DeleteFile (temp_file);
|
||||
}
|
||||
|
||||
@ -1913,6 +1921,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||
const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
|
||||
BOOL inRem = FALSE;
|
||||
BOOL inFor = FALSE;
|
||||
BOOL inIn = FALSE;
|
||||
BOOL inIf = FALSE;
|
||||
BOOL inElse= FALSE;
|
||||
BOOL onlyWhiteSpace = FALSE;
|
||||
@ -2057,11 +2066,15 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||
onlyWhiteSpace,
|
||||
inFor, lastWasIn, lastWasDo,
|
||||
inIf, inElse, lastWasElse);
|
||||
if (curLen == 0) {
|
||||
|
||||
/* Ignore open brackets inside the for set */
|
||||
if (curLen == 0 && !inIn) {
|
||||
WINE_TRACE("@@@4\n");
|
||||
curDepth++;
|
||||
|
||||
/* If in quotes, ignore brackets */
|
||||
} else if (inQuotes) {
|
||||
WINE_TRACE("@@@3\n");
|
||||
curString[curLen++] = *curPos;
|
||||
|
||||
/* In a FOR loop, an unquoted '(' may occur straight after
|
||||
@ -2075,6 +2088,13 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||
(inElse && lastWasElse && onlyWhiteSpace) ||
|
||||
(inFor && (lastWasIn || lastWasDo) && onlyWhiteSpace)) {
|
||||
|
||||
WINE_TRACE("@@@2\n");
|
||||
/* If entering into an 'IN', set inIn */
|
||||
if (inFor && lastWasIn && onlyWhiteSpace) {
|
||||
WINE_TRACE("Inside an IN\n");
|
||||
inIn = TRUE;
|
||||
}
|
||||
|
||||
/* Add the current command */
|
||||
thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST));
|
||||
thisEntry->command = HeapAlloc(GetProcessHeap(), 0,
|
||||
@ -2094,6 +2114,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||
|
||||
curDepth++;
|
||||
} else {
|
||||
WINE_TRACE("@@@1\n");
|
||||
curString[curLen++] = *curPos;
|
||||
}
|
||||
break;
|
||||
@ -2159,6 +2180,9 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||
*output = thisEntry;
|
||||
}
|
||||
lastEntry = thisEntry;
|
||||
|
||||
/* Leave inIn if necessary */
|
||||
if (inIn) inIn = FALSE;
|
||||
} else {
|
||||
curString[curLen++] = *curPos;
|
||||
}
|
||||
@ -2227,7 +2251,8 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||
*
|
||||
* Process all the commands read in so far
|
||||
*/
|
||||
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket) {
|
||||
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket,
|
||||
WCHAR *var, WCHAR *val) {
|
||||
|
||||
int bdepth = -1;
|
||||
|
||||
@ -2255,9 +2280,9 @@ CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket) {
|
||||
WINE_TRACE("Executing command: '%s'\n", wine_dbgstr_w(thisCmd->command));
|
||||
|
||||
if (strchrW(thisCmd->command,'|') != NULL) {
|
||||
WCMD_pipe (&thisCmd);
|
||||
WCMD_pipe (&thisCmd, var, val);
|
||||
} else {
|
||||
WCMD_process_command (thisCmd->command, &thisCmd);
|
||||
WCMD_execute (thisCmd->command, var, val, &thisCmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user