cmd: Introduce CMD_NODE structure.

This will allow to separate better the individual command to
be executed (CMD_COMMAND) from the chaining and I/O handling
of several commands (CMD_NODE).

This also renames CMD_LIST into CMD_COMMAND to fit in above
scheme.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
Eric Pouech 2024-04-11 15:08:30 +02:00 committed by Alexandre Julliard
parent 508b3ac996
commit 7e70824ed5
4 changed files with 144 additions and 123 deletions

View file

@ -86,7 +86,7 @@ void WCMD_batch (WCHAR *file, WCHAR *command, BOOL called, WCHAR *startLabel, HA
*/
while (context -> skip_rest == FALSE) {
CMD_LIST *toExecute = NULL; /* Commands left to be executed */
CMD_NODE *toExecute = NULL; /* Commands left to be executed */
if (!WCMD_ReadAndParseLine(NULL, &toExecute, h))
break;
/* Note: although this batch program itself may be called, we are not retrying

View file

@ -1519,11 +1519,11 @@ void WCMD_echo (const WCHAR *args)
* 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)
*/
static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd,
static void WCMD_part_execute(CMD_NODE **cmdList, const WCHAR *firstcmd,
BOOL isIF, BOOL executecmds)
{
CMD_LIST *curPosition = *cmdList;
int myDepth = (*cmdList)->bracketDepth;
CMD_NODE *curPosition = *cmdList;
int myDepth = (*cmdList)->single->bracketDepth;
WINE_TRACE("cmdList(%p), firstCmd(%s), doIt(%d), isIF(%d)\n", cmdList,
wine_dbgstr_w(firstcmd), executecmds, isIF);
@ -1534,7 +1534,7 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd,
/* Process the first command, if there is one */
if (executecmds && firstcmd && *firstcmd) {
WCHAR *command = xstrdupW(firstcmd);
WCMD_execute (firstcmd, (*cmdList)->redirects, cmdList, FALSE);
WCMD_execute (firstcmd, (*cmdList)->single->redirects, cmdList, FALSE);
free(command);
}
@ -1552,23 +1552,23 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd,
WINE_TRACE("Processing cmdList(%p) - delim(%d) bd(%d / %d) processThese(%d)\n",
*cmdList,
(*cmdList)->prevDelim,
(*cmdList)->bracketDepth,
(*cmdList)->single->prevDelim,
(*cmdList)->single->bracketDepth,
myDepth,
processThese);
/* Execute any statements appended to the line */
/* FIXME: Only if previous call worked for && or failed for || */
if ((*cmdList)->prevDelim == CMD_ONFAILURE ||
(*cmdList)->prevDelim == CMD_ONSUCCESS) {
if (processThese && (*cmdList)->command) {
WCMD_execute ((*cmdList)->command, (*cmdList)->redirects,
if ((*cmdList)->single->prevDelim == CMD_ONFAILURE ||
(*cmdList)->single->prevDelim == CMD_ONSUCCESS) {
if (processThese && (*cmdList)->single->command) {
WCMD_execute ((*cmdList)->single->command, (*cmdList)->single->redirects,
cmdList, FALSE);
}
if (curPosition == *cmdList) *cmdList = (*cmdList)->nextcommand;
/* Execute any appended to the statement with (...) */
} else if ((*cmdList)->bracketDepth > myDepth) {
} else if ((*cmdList)->single->bracketDepth > myDepth) {
if (processThese) {
*cmdList = WCMD_process_commands(*cmdList, TRUE, FALSE);
} else {
@ -1578,19 +1578,19 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd,
/* End of the command - does 'ELSE ' follow as the next command? */
} else {
if (isIF && WCMD_keyword_ws_found(L"else", (*cmdList)->command)) {
if (isIF && WCMD_keyword_ws_found(L"else", (*cmdList)->single->command)) {
/* Swap between if and else processing */
processThese = !executecmds;
/* Process the ELSE part */
if (processThese) {
const int keyw_len = lstrlenW(L"else") + 1;
WCHAR *cmd = ((*cmdList)->command) + keyw_len;
WCHAR *cmd = ((*cmdList)->single->command) + keyw_len;
/* Skip leading whitespace between condition and the command */
while (*cmd && (*cmd==' ' || *cmd=='\t')) cmd++;
if (*cmd) {
WCMD_execute (cmd, (*cmdList)->redirects, cmdList, FALSE);
WCMD_execute (cmd, (*cmdList)->single->redirects, cmdList, FALSE);
}
} else {
/* Loop skipping all commands until we get back to the current
@ -1599,8 +1599,8 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd,
do {
*cmdList = (*cmdList)->nextcommand;
} while (*cmdList &&
((*cmdList)->bracketDepth > myDepth ||
(*cmdList)->prevDelim));
((*cmdList)->single->bracketDepth > myDepth ||
(*cmdList)->single->prevDelim));
/* After the else is complete, we need to now process subsequent commands */
processThese = TRUE;
@ -1610,8 +1610,8 @@ static void WCMD_part_execute(CMD_LIST **cmdList, const WCHAR *firstcmd,
/* If we were in an IF statement and we didn't find an else and yet we get back to
the same bracket depth as the IF, then the IF statement is over. This is required
to handle nested ifs properly */
} else if (isIF && (*cmdList)->bracketDepth == myDepth) {
if (WCMD_keyword_ws_found(L"do", (*cmdList)->command)) {
} else if (isIF && (*cmdList)->single->bracketDepth == myDepth) {
if (WCMD_keyword_ws_found(L"do", (*cmdList)->single->command)) {
WINE_TRACE("Still inside FOR-loop, not an end of IF statement\n");
*cmdList = (*cmdList)->nextcommand;
} else {
@ -1935,9 +1935,9 @@ static int WCMD_for_nexttoken(int lasttoken, WCHAR *tokenstr,
* forf_delims [I] - The delimiters to use when breaking the string apart
* forf_tokens [I] - The tokens to use when breaking the string apart
*/
static void WCMD_parse_line(CMD_LIST *cmdStart,
static void WCMD_parse_line(CMD_NODE *cmdStart,
const WCHAR *firstCmd,
CMD_LIST **cmdEnd,
CMD_NODE **cmdEnd,
const WCHAR variable,
WCHAR *buffer,
BOOL *doExecuted,
@ -2024,7 +2024,7 @@ static void WCMD_parse_line(CMD_LIST *cmdStart,
/* Execute the body of the foor loop with these values */
if (varidx >= 0 && forloopcontext.variable[varidx] && forloopcontext.variable[varidx][0] != forf_eol) {
CMD_LIST *thisCmdStart = cmdStart;
CMD_NODE *thisCmdStart = cmdStart;
*doExecuted = TRUE;
WCMD_part_execute(&thisCmdStart, firstCmd, FALSE, TRUE);
*cmdEnd = thisCmdStart;
@ -2108,13 +2108,13 @@ static FILE* WCMD_forf_getinput(BOOL usebackq, WCHAR *itemstr, BOOL iscmd)
*
*/
void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
void WCMD_for (WCHAR *p, CMD_NODE **cmdList) {
WIN32_FIND_DATAW fd;
HANDLE hff;
int i;
const int in_len = lstrlenW(L"in");
CMD_LIST *setStart, *thisSet, *cmdStart, *cmdEnd;
CMD_NODE *setStart, *thisSet, *cmdStart, *cmdEnd;
WCHAR variable[4];
int varidx = -1;
WCHAR *oldvariablevalue;
@ -2129,7 +2129,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
BOOL doExecuted = FALSE; /* Has the 'do' part been executed */
LONG numbers[3] = {0,0,0}; /* Defaults to 0 in native */
int itemNum;
CMD_LIST *thisCmdStart;
CMD_NODE *thisCmdStart;
int parameterNo = 0;
WCHAR forf_eol = 0;
int forf_skip = 0;
@ -2219,15 +2219,15 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
}
/* Save away where the set of data starts and the variable */
thisDepth = (*cmdList)->bracketDepth;
thisDepth = (*cmdList)->single->bracketDepth;
*cmdList = (*cmdList)->nextcommand;
setStart = (*cmdList);
/* Skip until the close bracket */
WINE_TRACE("Searching %p as the set\n", *cmdList);
while (*cmdList &&
(*cmdList)->command != NULL &&
(*cmdList)->bracketDepth > thisDepth) {
(*cmdList)->single->command != NULL &&
(*cmdList)->single->bracketDepth > thisDepth) {
WINE_TRACE("Skipping %p which is part of the set\n", *cmdList);
*cmdList = (*cmdList)->nextcommand;
}
@ -2238,7 +2238,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* 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) || !WCMD_keyword_ws_found(L"do", (*cmdList)->command)) {
if ((*cmdList == NULL) || !WCMD_keyword_ws_found(L"do", (*cmdList)->single->command)) {
WCMD_output_stderr (WCMD_LoadMessage(WCMD_SYNTAXERR));
return;
}
@ -2252,7 +2252,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
/* Save away the starting position for the commands (and offset for the
first one) */
cmdStart = *cmdList;
firstCmd = (*cmdList)->command + 3; /* Skip 'do ' */
firstCmd = (*cmdList)->single->command + 3; /* Skip 'do ' */
itemNum = 0;
/* If we are recursing directories (ie /R), add all sub directories now, then
@ -2262,8 +2262,8 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
thisSet = setStart;
/* Loop through all set entries */
while (thisSet &&
thisSet->command != NULL &&
thisSet->bracketDepth >= thisDepth) {
thisSet->single->command != NULL &&
thisSet->single->bracketDepth >= thisDepth) {
/* Loop through all entries on the same line */
WCHAR *staticitem;
@ -2272,7 +2272,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
WINE_TRACE("Processing for set %p\n", thisSet);
i = 0;
while (*(staticitem = WCMD_parameter (thisSet->command, i, &itemStart, TRUE, FALSE))) {
while (*(staticitem = WCMD_parameter (thisSet->single->command, i, &itemStart, TRUE, FALSE))) {
/*
* If the parameter within the set has a wildcard then search for matching files
@ -2516,7 +2516,7 @@ void WCMD_for (WCHAR *p, CMD_LIST **cmdList) {
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;
if (cmdEnd && cmdEnd->single->command == NULL) *cmdList = cmdEnd->nextcommand;
}
/**************************************************************************
@ -2567,7 +2567,7 @@ void WCMD_give_help (const WCHAR *args)
* FIXME: DOS is supposed to allow labels with spaces - we don't.
*/
void WCMD_goto (CMD_LIST **cmdList) {
void WCMD_goto (CMD_NODE **cmdList) {
WCHAR string[MAX_PATH];
WCHAR *labelend = NULL;
@ -2903,7 +2903,7 @@ syntax_err:
*
* FIXME: Much more syntax checking needed!
*/
void WCMD_if (WCHAR *p, CMD_LIST **cmdList)
void WCMD_if (WCHAR *p, CMD_NODE **cmdList)
{
int negate; /* Negate condition */
int test; /* Condition evaluation result */
@ -4761,7 +4761,7 @@ int WCMD_volume(BOOL set_label, const WCHAR *path)
*
*/
void WCMD_exit (CMD_LIST **cmdList) {
void WCMD_exit (CMD_NODE **cmdList) {
int rc = wcstol(param1, NULL, 10); /* Note: wcstol of empty parameter is 0 */
if (context && lstrcmpiW(quals, L"/B") == 0) {

View file

@ -45,14 +45,20 @@ typedef enum _CMDdelimiters {
/* Data structure to hold commands to be processed */
typedef struct _CMD_LIST {
typedef struct _CMD_COMMAND
{
WCHAR *command; /* Command string to execute */
WCHAR *redirects; /* Redirects in place */
struct _CMD_LIST *nextcommand; /* Next command string to execute */
CMD_DELIMITERS prevDelim; /* Previous delimiter */
int bracketDepth;/* How deep bracketing have we got to */
WCHAR pipeFile[MAX_PATH]; /* Where to get input from for pipes */
} CMD_LIST;
} CMD_COMMAND;
typedef struct _CMD_NODE
{
CMD_COMMAND *single;
struct _CMD_NODE *nextcommand; /* Next command string to execute */
} CMD_NODE;
void WCMD_assoc (const WCHAR *, BOOL);
void WCMD_batch (WCHAR *, WCHAR *, BOOL, WCHAR *, HANDLE);
@ -68,12 +74,12 @@ void WCMD_directory (WCHAR *);
void WCMD_echo (const WCHAR *);
void WCMD_endlocal (void);
void WCMD_enter_paged_mode(const WCHAR *);
void WCMD_exit (CMD_LIST **cmdList);
void WCMD_for (WCHAR *, CMD_LIST **cmdList);
void WCMD_exit (CMD_NODE **cmdList);
void WCMD_for (WCHAR *, CMD_NODE **cmdList);
BOOL WCMD_get_fullpath(const WCHAR *, SIZE_T, WCHAR *, WCHAR **);
void WCMD_give_help (const WCHAR *args);
void WCMD_goto (CMD_LIST **cmdList);
void WCMD_if (WCHAR *, CMD_LIST **cmdList);
void WCMD_goto (CMD_NODE **cmdList);
void WCMD_if (WCHAR *, CMD_NODE **cmdList);
void WCMD_leave_paged_mode(void);
void WCMD_more (WCHAR *);
void WCMD_move (void);
@ -118,11 +124,11 @@ WCHAR *WCMD_LoadMessage(UINT id);
void WCMD_strsubstW(WCHAR *start, const WCHAR* next, const WCHAR* insert, int len);
BOOL WCMD_ReadFile(const HANDLE hIn, WCHAR *intoBuf, const DWORD maxChars, LPDWORD charsRead);
WCHAR *WCMD_ReadAndParseLine(const WCHAR *initialcmd, CMD_LIST **output, HANDLE readFrom);
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket, BOOL retrycall);
void WCMD_free_commands(CMD_LIST *cmds);
WCHAR *WCMD_ReadAndParseLine(const WCHAR *initialcmd, CMD_NODE **output, HANDLE readFrom);
CMD_NODE *WCMD_process_commands(CMD_NODE *thisCmd, BOOL oneBracket, BOOL retrycall);
void WCMD_free_commands(CMD_NODE *cmds);
void WCMD_execute (const WCHAR *orig_command, const WCHAR *redirects,
CMD_LIST **cmdList, BOOL retrycall);
CMD_NODE **cmdList, BOOL retrycall);
void *xrealloc(void *, size_t) __WINE_ALLOC_SIZE(2) __WINE_DEALLOC(free);
@ -163,7 +169,7 @@ typedef struct _BATCH_CONTEXT {
int shift_count[10]; /* Offset in terms of shifts for %0 - %9 */
struct _BATCH_CONTEXT *prev_context; /* Pointer to the previous context block */
BOOL skip_rest; /* Skip the rest of the batch program and exit */
CMD_LIST *toExecute; /* Commands left to be executed */
CMD_NODE *toExecute; /* Commands left to be executed */
} BATCH_CONTEXT;
/* Data structure to handle building lists during recursive calls */

View file

@ -1250,7 +1250,7 @@ void WCMD_run_program (WCHAR *command, BOOL called)
/* Not found anywhere - were we called? */
if (called) {
CMD_LIST *toExecute = NULL; /* Commands left to be executed */
CMD_NODE *toExecute = NULL; /* Commands left to be executed */
/* Parse the command string, without reading any more input */
WCMD_ReadAndParseLine(command, &toExecute, INVALID_HANDLE_VALUE);
@ -1278,7 +1278,7 @@ void WCMD_run_program (WCHAR *command, BOOL called)
* we are attempting this retry.
*/
void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
CMD_LIST **cmdList, BOOL retrycall)
CMD_NODE **cmdList, BOOL retrycall)
{
WCHAR *cmd, *parms_start, *redir;
WCHAR *pos;
@ -1335,7 +1335,7 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
a change to not wait for the first app to finish but rather the pipe */
if (!(cmd_index == WCMD_FOR || cmd_index == WCMD_IF) &&
cmdList && (*cmdList)->nextcommand &&
(*cmdList)->nextcommand->prevDelim == CMD_PIPE) {
(*cmdList)->nextcommand->single->prevDelim == CMD_PIPE) {
WCHAR temp_path[MAX_PATH];
@ -1345,14 +1345,14 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
/* Generate a unique temporary filename */
GetTempPathW(ARRAY_SIZE(temp_path), temp_path);
GetTempFileNameW(temp_path, L"CMD", 0, (*cmdList)->nextcommand->pipeFile);
GetTempFileNameW(temp_path, L"CMD", 0, (*cmdList)->nextcommand->single->pipeFile);
WINE_TRACE("Using temporary file of %s\n",
wine_dbgstr_w((*cmdList)->nextcommand->pipeFile));
wine_dbgstr_w((*cmdList)->nextcommand->single->pipeFile));
}
/* If piped output, send stdout to the pipe by appending >filename to redirects */
if (piped) {
wsprintfW (new_redir, L"%s > %s", redirects, (*cmdList)->nextcommand->pipeFile);
wsprintfW (new_redir, L"%s > %s", redirects, (*cmdList)->nextcommand->single->pipeFile);
WINE_TRACE("Redirects now %s\n", wine_dbgstr_w(new_redir));
} else {
lstrcpyW(new_redir, redirects);
@ -1404,9 +1404,9 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
*/
if (!(cmd_index == WCMD_FOR || cmd_index == WCMD_IF)) {
/* STDIN could come from a preceding pipe, so delete on close if it does */
if (cmdList && (*cmdList)->pipeFile[0] != 0x00) {
WINE_TRACE("Input coming from %s\n", wine_dbgstr_w((*cmdList)->pipeFile));
h = CreateFileW((*cmdList)->pipeFile, GENERIC_READ,
if (cmdList && (*cmdList)->single->pipeFile[0] != 0x00) {
WINE_TRACE("Input coming from %s\n", wine_dbgstr_w((*cmdList)->single->pipeFile));
h = CreateFileW((*cmdList)->single->pipeFile, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
if (h == INVALID_HANDLE_VALUE) {
@ -1418,7 +1418,7 @@ void WCMD_execute (const WCHAR *command, const WCHAR *redirects,
SetStdHandle (STD_INPUT_HANDLE, h);
/* No need to remember the temporary name any longer once opened */
(*cmdList)->pipeFile[0] = 0x00;
(*cmdList)->single->pipeFile[0] = 0x00;
/* Otherwise STDIN could come from a '<' redirect */
} else if ((pos = wcschr(new_redir,'<')) != NULL) {
@ -1674,18 +1674,18 @@ WCHAR *WCMD_LoadMessage(UINT id) {
*
* Dumps out the parsed command line to ensure syntax is correct
*/
static void WCMD_DumpCommands(CMD_LIST *commands) {
CMD_LIST *thisCmd = commands;
static void WCMD_DumpCommands(CMD_NODE *commands) {
CMD_NODE *thisCmd = commands;
WINE_TRACE("Parsed line:\n");
while (thisCmd != NULL) {
WINE_TRACE("%p %d %2.2d %p %s Redir:%s\n",
thisCmd,
thisCmd->prevDelim,
thisCmd->bracketDepth,
thisCmd->single->prevDelim,
thisCmd->single->bracketDepth,
thisCmd->nextcommand,
wine_dbgstr_w(thisCmd->command),
wine_dbgstr_w(thisCmd->redirects));
wine_dbgstr_w(thisCmd->single->command),
wine_dbgstr_w(thisCmd->single->redirects));
thisCmd = thisCmd->nextcommand;
}
}
@ -1695,16 +1695,15 @@ static void WCMD_DumpCommands(CMD_LIST *commands) {
*
* Adds a command to the current command list
*/
static void WCMD_addCommand(WCHAR *command, int *commandLen,
WCHAR *redirs, int *redirLen,
WCHAR **copyTo, int **copyToLen,
CMD_DELIMITERS prevDelim, int curDepth,
CMD_LIST **output) {
CMD_LIST *thisEntry = NULL;
static CMD_COMMAND *WCMD_createCommand(WCHAR *command, int *commandLen,
WCHAR *redirs, int *redirLen,
WCHAR **copyTo, int **copyToLen,
CMD_DELIMITERS prevDelim, int curDepth)
{
CMD_COMMAND *thisEntry = NULL;
/* Allocate storage for command */
thisEntry = xalloc(sizeof(CMD_LIST));
thisEntry = xalloc(sizeof(CMD_COMMAND));
/* Copy in the command */
if (command) {
@ -1731,14 +1730,23 @@ static void WCMD_addCommand(WCHAR *command, int *commandLen,
}
/* Fill in other fields */
thisEntry->nextcommand = NULL;
thisEntry->prevDelim = prevDelim;
thisEntry->bracketDepth = curDepth;
for (; *output; output = &((*output)->nextcommand)) {}
*output = thisEntry;
return thisEntry;
}
static void WCMD_appendCommand(CMD_COMMAND *command, CMD_NODE **node)
{
CMD_NODE *new = xalloc(sizeof(CMD_NODE));
if (new)
{
new->single = command;
new->nextcommand = NULL;
for (; *node; node = &((*node)->nextcommand)) {}
*node = new;
}
}
/***************************************************************************
* WCMD_IsEndQuote
@ -1808,7 +1816,7 @@ static BOOL WCMD_IsEndQuote(const WCHAR *quote, int quoteIndex)
* - Anything else gets put into the command string (including
* redirects)
*/
WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE readFrom)
WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_NODE **output, HANDLE readFrom)
{
WCHAR *curPos;
int inQuotes = 0;
@ -1819,6 +1827,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
WCHAR *curCopyTo;
int *curLen;
int curDepth = 0;
CMD_COMMAND *single_cmd = NULL;
CMD_DELIMITERS prevDelim = CMD_NONE;
static WCHAR *extraSpace = NULL; /* Deliberately never freed */
BOOL inOneLine = FALSE;
@ -1848,6 +1857,7 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
return NULL;
}
*output = NULL;
/* If initial command read in, use that, otherwise get input from handle */
if (optionalcmd != NULL) {
lstrcpyW(extraSpace, optionalcmd);
@ -2086,12 +2096,11 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
if (curStringLen > 0) {
/* Add the current command */
WCMD_addCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth,
output);
single_cmd = WCMD_createCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth);
WCMD_appendCommand(single_cmd, output);
}
if (*(curPos+1) == '|') {
@ -2160,11 +2169,11 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
}
/* Add the current command */
WCMD_addCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth,
output);
single_cmd = WCMD_createCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth);
WCMD_appendCommand(single_cmd, output);
curDepth++;
} else {
@ -2191,12 +2200,11 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
if (curStringLen > 0) {
/* Add the current command */
WCMD_addCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth,
output);
single_cmd = WCMD_createCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth);
WCMD_appendCommand(single_cmd, output);
}
if (*(curPos+1) == '&') {
@ -2224,20 +2232,21 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
if (curStringLen) {
/* Add the current command */
WCMD_addCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth,
output);
single_cmd = WCMD_createCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth);
WCMD_appendCommand(single_cmd, output);
}
/* Add an empty entry to the command list */
prevDelim = CMD_NONE;
WCMD_addCommand(NULL, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth,
output);
single_cmd = WCMD_createCommand(NULL, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth);
WCMD_appendCommand(single_cmd, output);
curDepth--;
/* Leave inIn if necessary */
@ -2269,11 +2278,11 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
if (*curPos == 0x00 && !lastWasCaret && *curLen > 0) {
/* Add an entry to the command list */
WCMD_addCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth,
output);
single_cmd = WCMD_createCommand(curString, &curStringLen,
curRedirs, &curRedirsLen,
&curCopyTo, &curLen,
prevDelim, curDepth);
WCMD_appendCommand(single_cmd, output);
/* If we had a single line if or else, and we pretended to add
brackets, end them now */
@ -2355,22 +2364,22 @@ WCHAR *WCMD_ReadAndParseLine(const WCHAR *optionalcmd, CMD_LIST **output, HANDLE
*
* Process all the commands read in so far
*/
CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket,
CMD_NODE *WCMD_process_commands(CMD_NODE *thisCmd, BOOL oneBracket,
BOOL retrycall) {
int bdepth = -1;
if (thisCmd && oneBracket) bdepth = thisCmd->bracketDepth;
if (thisCmd && oneBracket) bdepth = thisCmd->single->bracketDepth;
/* Loop through the commands, processing them one by one */
while (thisCmd) {
CMD_LIST *origCmd = thisCmd;
CMD_NODE *origCmd = thisCmd;
/* If processing one bracket only, and we find the end bracket
entry (or less), return */
if (oneBracket && !thisCmd->command &&
bdepth <= thisCmd->bracketDepth) {
if (oneBracket && !thisCmd->single->command &&
bdepth <= thisCmd->single->bracketDepth) {
WINE_TRACE("Finished bracket @ %p, next command is %p\n",
thisCmd, thisCmd->nextcommand);
return thisCmd->nextcommand;
@ -2379,9 +2388,9 @@ CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket,
/* Ignore the NULL entries a ')' inserts (Only 'if' cares
about them and it will be handled in there)
Also, skip over any batch labels (eg. :fred) */
if (thisCmd->command && thisCmd->command[0] != ':') {
WINE_TRACE("Executing command: '%s'\n", wine_dbgstr_w(thisCmd->command));
WCMD_execute (thisCmd->command, thisCmd->redirects, &thisCmd, retrycall);
if (thisCmd->single->command && thisCmd->single->command[0] != ':') {
WINE_TRACE("Executing command: '%s'\n", wine_dbgstr_w(thisCmd->single->command));
WCMD_execute (thisCmd->single->command, thisCmd->single->redirects, &thisCmd, retrycall);
}
/* Step on unless the command itself already stepped on */
@ -2390,6 +2399,13 @@ CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket,
return NULL;
}
static void WCMD_free_command(CMD_COMMAND *cmd)
{
free(cmd->command);
free(cmd->redirects);
free(cmd);
}
/***************************************************************************
* WCMD_free_commands
*
@ -2398,14 +2414,13 @@ CMD_LIST *WCMD_process_commands(CMD_LIST *thisCmd, BOOL oneBracket,
* pointer will be modified within the commands, and hence a single free
* routine is simpler
*/
void WCMD_free_commands(CMD_LIST *cmds) {
void WCMD_free_commands(CMD_NODE *cmds) {
/* Loop through the commands, freeing them one by one */
while (cmds) {
CMD_LIST *thisCmd = cmds;
CMD_NODE *thisCmd = cmds;
cmds = cmds->nextcommand;
free(thisCmd->command);
free(thisCmd->redirects);
WCMD_free_command(thisCmd->single);
free(thisCmd);
}
}
@ -2432,7 +2447,7 @@ int __cdecl wmain (int argc, WCHAR *argvW[])
BOOL opt_q;
int opt_t = 0;
WCHAR comspec[MAX_PATH];
CMD_LIST *toExecute = NULL; /* Commands left to be executed */
CMD_NODE *toExecute = NULL; /* Commands left to be executed */
RTL_OSVERSIONINFOEXW osv;
char osver[50];
STARTUPINFOW startupInfo;