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 */
|
CMD_LIST *toExecute = NULL; /* Commands left to be executed */
|
||||||
if (WCMD_ReadAndParseLine(NULL, &toExecute, h) == NULL)
|
if (WCMD_ReadAndParseLine(NULL, &toExecute, h) == NULL)
|
||||||
break;
|
break;
|
||||||
WCMD_process_commands(toExecute, FALSE);
|
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||||
WCMD_free_commands(toExecute);
|
WCMD_free_commands(toExecute);
|
||||||
toExecute = NULL;
|
toExecute = NULL;
|
||||||
}
|
}
|
||||||
|
@ -168,21 +168,9 @@ WCHAR *WCMD_parameter (WCHAR *s, int n, WCHAR **where) {
|
||||||
i++;
|
i++;
|
||||||
p = param;
|
p = param;
|
||||||
break;
|
break;
|
||||||
case '(':
|
/* The code to handle bracketed parms is removed because it should no longer
|
||||||
if (where != NULL && i==n) *where = s;
|
be necessary after the multiline support has been added and the for loop
|
||||||
s++;
|
set of data is now parseable individually. */
|
||||||
while ((*s != '\0') && (*s != ')')) {
|
|
||||||
*p++ = *s++;
|
|
||||||
}
|
|
||||||
if (i == n) {
|
|
||||||
*p = '\0';
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
if (*s == ')') s++;
|
|
||||||
param[0] = '\0';
|
|
||||||
i++;
|
|
||||||
p = param;
|
|
||||||
break;
|
|
||||||
case '\0':
|
case '\0':
|
||||||
return param;
|
return param;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -40,7 +40,8 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
|
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 *saved_environment;
|
||||||
struct env_stack *pushd_directories;
|
struct env_stack *pushd_directories;
|
||||||
|
@ -571,6 +572,12 @@ void WCMD_echo (const WCHAR *command) {
|
||||||
* WCMD_for
|
* WCMD_for
|
||||||
*
|
*
|
||||||
* Batch file loop processing.
|
* 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
|
* 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...
|
* 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;
|
WIN32_FIND_DATA fd;
|
||||||
HANDLE hff;
|
HANDLE hff;
|
||||||
WCHAR *cmd, *item;
|
|
||||||
WCHAR set[MAX_PATH], param[MAX_PATH];
|
|
||||||
int i;
|
int i;
|
||||||
const WCHAR inW[] = {'i', 'n', '\0'};
|
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)
|
if (lstrcmpiW (WCMD_parameter (p, 1, NULL), inW)
|
||||||
|| lstrcmpiW (WCMD_parameter (p, 3, NULL), doW)
|
|| (*cmdList) == NULL
|
||||||
|| (param1[0] != '%')) {
|
|| (*cmdList)->nextcommand == NULL
|
||||||
|
|| (param1[0] != '%')
|
||||||
|
|| (strlenW(param1) > 3)) {
|
||||||
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
WCMD_output (WCMD_LoadMessage(WCMD_SYNTAXERR));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lstrcpynW (set, WCMD_parameter (p, 2, NULL), sizeof(set)/sizeof(WCHAR));
|
|
||||||
WCMD_parameter (p, 4, &cmd);
|
|
||||||
strcpyW (param, param1);
|
|
||||||
|
|
||||||
/*
|
/* Save away where the set of data starts and the variable */
|
||||||
* If the parameter within the set has a wildcard then search for matching files
|
strcpyW(variable, param1);
|
||||||
* otherwise do a literal substitution.
|
thisDepth = (*cmdList)->bracketDepth;
|
||||||
*/
|
*cmdList = (*cmdList)->nextcommand;
|
||||||
|
setStart = (*cmdList);
|
||||||
|
|
||||||
i = 0;
|
/* Skip until the close bracket */
|
||||||
while (*(item = WCMD_parameter (set, i, NULL))) {
|
WINE_TRACE("Searching %p as the set\n", *cmdList);
|
||||||
static const WCHAR wildcards[] = {'*','?','\0'};
|
while (*cmdList &&
|
||||||
if (strpbrkW (item, wildcards)) {
|
(*cmdList)->command != NULL &&
|
||||||
hff = FindFirstFile (item, &fd);
|
(*cmdList)->bracketDepth > thisDepth) {
|
||||||
if (hff == INVALID_HANDLE_VALUE) {
|
WINE_TRACE("Skipping %p which is part of the set\n", *cmdList);
|
||||||
return;
|
*cmdList = (*cmdList)->nextcommand;
|
||||||
}
|
|
||||||
do {
|
|
||||||
WCMD_execute (cmd, param, fd.cFileName, cmdList);
|
|
||||||
} while (FindNextFile(hff, &fd) != 0);
|
|
||||||
FindClose (hff);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
WCMD_execute (cmd, param, item, cmdList);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
WCHAR *new_cmd, *p, *s, *dup;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = strlenW (orig_cmd);
|
if (param) {
|
||||||
new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
|
size = (strlenW (orig_cmd) + 1) * sizeof(WCHAR);
|
||||||
dup = s = WCMD_strdupW(orig_cmd);
|
new_cmd = (WCHAR *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, size);
|
||||||
|
dup = s = WCMD_strdupW(orig_cmd);
|
||||||
|
|
||||||
while ((p = strstrW (s, param))) {
|
while ((p = strstrW (s, param))) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
size += strlenW (subst);
|
size += strlenW (subst) * sizeof(WCHAR);
|
||||||
new_cmd = (WCHAR *) LocalReAlloc ((HANDLE)new_cmd, size, 0);
|
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, s);
|
||||||
strcatW (new_cmd, subst);
|
WCMD_process_command (new_cmd, cmdList);
|
||||||
s = p + strlenW (param);
|
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 existW[] = {'e','x','i','s','t','\0'};
|
||||||
static const WCHAR defdW[] = {'d','e','f','i','n','e','d','\0'};
|
static const WCHAR defdW[] = {'d','e','f','i','n','e','d','\0'};
|
||||||
static const WCHAR eqeqW[] = {'=','=','\0'};
|
static const WCHAR eqeqW[] = {'=','=','\0'};
|
||||||
CMD_LIST *curPosition;
|
|
||||||
int myDepth;
|
|
||||||
|
|
||||||
if (!lstrcmpiW (param1, notW)) {
|
if (!lstrcmpiW (param1, notW)) {
|
||||||
negate = 1;
|
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
|
/* Process rest of IF statement which is on the same line
|
||||||
Note: This may process all or some of the cmdList (eg a GOTO) */
|
Note: This may process all or some of the cmdList (eg a GOTO) */
|
||||||
curPosition = *cmdList;
|
WCMD_part_execute(cmdList, command, NULL, NULL, TRUE, (test != negate));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
|
@ -62,7 +62,7 @@ void WCMD_output (const WCHAR *format, ...);
|
||||||
void WCMD_output_asis (const WCHAR *message);
|
void WCMD_output_asis (const WCHAR *message);
|
||||||
void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2);
|
void WCMD_parse (WCHAR *s, WCHAR *q, WCHAR *p1, WCHAR *p2);
|
||||||
void WCMD_pause (void);
|
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_popd (void);
|
||||||
void WCMD_print_error (void);
|
void WCMD_print_error (void);
|
||||||
void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList);
|
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,
|
BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars,
|
||||||
LPDWORD charsRead, const LPOVERLAPPED unused);
|
LPDWORD charsRead, const LPOVERLAPPED unused);
|
||||||
|
|
||||||
WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
|
WCHAR *WCMD_ReadAndParseLine(WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
|
||||||
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket);
|
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket, WCHAR *var, WCHAR *val);
|
||||||
void WCMD_free_commands(CMD_LIST *cmds);
|
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 */
|
/* 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 */
|
/* Parse the command string, without reading any more input */
|
||||||
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
|
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
|
||||||
WCMD_process_commands(toExecute, FALSE);
|
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||||
WCMD_free_commands(toExecute);
|
WCMD_free_commands(toExecute);
|
||||||
toExecute = NULL;
|
toExecute = NULL;
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ int wmain (int argc, WCHAR *argvW[])
|
||||||
if (opt_k) {
|
if (opt_k) {
|
||||||
/* Parse the command string, without reading any more input */
|
/* Parse the command string, without reading any more input */
|
||||||
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
|
WCMD_ReadAndParseLine(cmd, &toExecute, INVALID_HANDLE_VALUE);
|
||||||
WCMD_process_commands(toExecute, FALSE);
|
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||||
WCMD_free_commands(toExecute);
|
WCMD_free_commands(toExecute);
|
||||||
toExecute = NULL;
|
toExecute = NULL;
|
||||||
HeapFree(GetProcessHeap(), 0, cmd);
|
HeapFree(GetProcessHeap(), 0, cmd);
|
||||||
|
@ -449,7 +449,7 @@ int wmain (int argc, WCHAR *argvW[])
|
||||||
if (WCMD_ReadAndParseLine(NULL, &toExecute,
|
if (WCMD_ReadAndParseLine(NULL, &toExecute,
|
||||||
GetStdHandle(STD_INPUT_HANDLE)) == NULL)
|
GetStdHandle(STD_INPUT_HANDLE)) == NULL)
|
||||||
break;
|
break;
|
||||||
WCMD_process_commands(toExecute, FALSE);
|
WCMD_process_commands(toExecute, FALSE, NULL, NULL);
|
||||||
WCMD_free_commands(toExecute);
|
WCMD_free_commands(toExecute);
|
||||||
toExecute = NULL;
|
toExecute = NULL;
|
||||||
}
|
}
|
||||||
|
@ -497,8 +497,12 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList)
|
||||||
while ((p = strchrW(p, '%'))) {
|
while ((p = strchrW(p, '%'))) {
|
||||||
i = *(p+1) - '0';
|
i = *(p+1) - '0';
|
||||||
|
|
||||||
|
/* Dont touch %% */
|
||||||
|
if (*(p+1) == '%') {
|
||||||
|
p+=2;
|
||||||
|
|
||||||
/* Replace %~ modifications if in batch program */
|
/* Replace %~ modifications if in batch program */
|
||||||
if (context && *(p+1) == '~') {
|
} else if (context && *(p+1) == '~') {
|
||||||
WCMD_HandleTildaModifiers(&p, NULL);
|
WCMD_HandleTildaModifiers(&p, NULL);
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
|
@ -531,13 +535,17 @@ void WCMD_process_command (WCHAR *command, CMD_LIST **cmdList)
|
||||||
if (context) {
|
if (context) {
|
||||||
p = cmd;
|
p = cmd;
|
||||||
while ((p = strchrW(p, '%'))) {
|
while ((p = strchrW(p, '%'))) {
|
||||||
s = strchrW(p+1, '%');
|
if (*(p+1) == '%') {
|
||||||
if (!s) {
|
p+=2;
|
||||||
*p=0x00;
|
|
||||||
} else {
|
} else {
|
||||||
t = WCMD_strdupW(s+1);
|
s = strchrW(p+1, '%');
|
||||||
strcpyW(p, t);
|
if (!s) {
|
||||||
free(t);
|
*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.
|
* 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 *p;
|
||||||
WCHAR *command = (*cmdEntry)->command;
|
WCHAR *command = (*cmdEntry)->command;
|
||||||
|
@ -1503,19 +1511,19 @@ void WCMD_pipe (CMD_LIST **cmdEntry) {
|
||||||
p = strchrW(command, '|');
|
p = strchrW(command, '|');
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
wsprintf (temp_cmd, redirOut, command, temp_file);
|
wsprintf (temp_cmd, redirOut, command, temp_file);
|
||||||
WCMD_process_command (temp_cmd, cmdEntry);
|
WCMD_execute (temp_cmd, var, val, cmdEntry);
|
||||||
command = p;
|
command = p;
|
||||||
while ((p = strchrW(command, '|'))) {
|
while ((p = strchrW(command, '|'))) {
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
GetTempFileName (temp_path, cmdW, 0, temp_file2);
|
GetTempFileName (temp_path, cmdW, 0, temp_file2);
|
||||||
wsprintf (temp_cmd, redirBoth, command, temp_file, 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);
|
DeleteFile (temp_file);
|
||||||
strcpyW (temp_file, temp_file2);
|
strcpyW (temp_file, temp_file2);
|
||||||
command = p;
|
command = p;
|
||||||
}
|
}
|
||||||
wsprintf (temp_cmd, redirIn, command, temp_file);
|
wsprintf (temp_cmd, redirIn, command, temp_file);
|
||||||
WCMD_process_command (temp_cmd, cmdEntry);
|
WCMD_execute (temp_cmd, var, val, cmdEntry);
|
||||||
DeleteFile (temp_file);
|
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'};
|
const WCHAR ifElse[] = {'e','l','s','e',' ','\0'};
|
||||||
BOOL inRem = FALSE;
|
BOOL inRem = FALSE;
|
||||||
BOOL inFor = FALSE;
|
BOOL inFor = FALSE;
|
||||||
|
BOOL inIn = FALSE;
|
||||||
BOOL inIf = FALSE;
|
BOOL inIf = FALSE;
|
||||||
BOOL inElse= FALSE;
|
BOOL inElse= FALSE;
|
||||||
BOOL onlyWhiteSpace = FALSE;
|
BOOL onlyWhiteSpace = FALSE;
|
||||||
|
@ -2057,11 +2066,15 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||||
onlyWhiteSpace,
|
onlyWhiteSpace,
|
||||||
inFor, lastWasIn, lastWasDo,
|
inFor, lastWasIn, lastWasDo,
|
||||||
inIf, inElse, lastWasElse);
|
inIf, inElse, lastWasElse);
|
||||||
if (curLen == 0) {
|
|
||||||
|
/* Ignore open brackets inside the for set */
|
||||||
|
if (curLen == 0 && !inIn) {
|
||||||
|
WINE_TRACE("@@@4\n");
|
||||||
curDepth++;
|
curDepth++;
|
||||||
|
|
||||||
/* If in quotes, ignore brackets */
|
/* If in quotes, ignore brackets */
|
||||||
} else if (inQuotes) {
|
} else if (inQuotes) {
|
||||||
|
WINE_TRACE("@@@3\n");
|
||||||
curString[curLen++] = *curPos;
|
curString[curLen++] = *curPos;
|
||||||
|
|
||||||
/* In a FOR loop, an unquoted '(' may occur straight after
|
/* 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) ||
|
(inElse && lastWasElse && onlyWhiteSpace) ||
|
||||||
(inFor && (lastWasIn || lastWasDo) && 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 */
|
/* Add the current command */
|
||||||
thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST));
|
thisEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(CMD_LIST));
|
||||||
thisEntry->command = HeapAlloc(GetProcessHeap(), 0,
|
thisEntry->command = HeapAlloc(GetProcessHeap(), 0,
|
||||||
|
@ -2094,6 +2114,7 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||||
|
|
||||||
curDepth++;
|
curDepth++;
|
||||||
} else {
|
} else {
|
||||||
|
WINE_TRACE("@@@1\n");
|
||||||
curString[curLen++] = *curPos;
|
curString[curLen++] = *curPos;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2159,6 +2180,9 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF
|
||||||
*output = thisEntry;
|
*output = thisEntry;
|
||||||
}
|
}
|
||||||
lastEntry = thisEntry;
|
lastEntry = thisEntry;
|
||||||
|
|
||||||
|
/* Leave inIn if necessary */
|
||||||
|
if (inIn) inIn = FALSE;
|
||||||
} else {
|
} else {
|
||||||
curString[curLen++] = *curPos;
|
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
|
* 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;
|
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));
|
WINE_TRACE("Executing command: '%s'\n", wine_dbgstr_w(thisCmd->command));
|
||||||
|
|
||||||
if (strchrW(thisCmd->command,'|') != NULL) {
|
if (strchrW(thisCmd->command,'|') != NULL) {
|
||||||
WCMD_pipe (&thisCmd);
|
WCMD_pipe (&thisCmd, var, val);
|
||||||
} else {
|
} else {
|
||||||
WCMD_process_command (thisCmd->command, &thisCmd);
|
WCMD_execute (thisCmd->command, var, val, &thisCmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue