mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-18 09:16:17 +00:00
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:
parent
508b3ac996
commit
7e70824ed5
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
static CMD_COMMAND *WCMD_createCommand(WCHAR *command, int *commandLen,
|
||||
WCHAR *redirs, int *redirLen,
|
||||
WCHAR **copyTo, int **copyToLen,
|
||||
CMD_DELIMITERS prevDelim, int curDepth,
|
||||
CMD_LIST **output) {
|
||||
|
||||
CMD_LIST *thisEntry = NULL;
|
||||
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,
|
||||
single_cmd = WCMD_createCommand(curString, &curStringLen,
|
||||
curRedirs, &curRedirsLen,
|
||||
&curCopyTo, &curLen,
|
||||
prevDelim, curDepth,
|
||||
output);
|
||||
|
||||
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,
|
||||
single_cmd = WCMD_createCommand(curString, &curStringLen,
|
||||
curRedirs, &curRedirsLen,
|
||||
&curCopyTo, &curLen,
|
||||
prevDelim, curDepth,
|
||||
output);
|
||||
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,
|
||||
single_cmd = WCMD_createCommand(curString, &curStringLen,
|
||||
curRedirs, &curRedirsLen,
|
||||
&curCopyTo, &curLen,
|
||||
prevDelim, curDepth,
|
||||
output);
|
||||
|
||||
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,
|
||||
single_cmd = WCMD_createCommand(curString, &curStringLen,
|
||||
curRedirs, &curRedirsLen,
|
||||
&curCopyTo, &curLen,
|
||||
prevDelim, curDepth,
|
||||
output);
|
||||
prevDelim, curDepth);
|
||||
WCMD_appendCommand(single_cmd, output);
|
||||
}
|
||||
|
||||
/* Add an empty entry to the command list */
|
||||
prevDelim = CMD_NONE;
|
||||
WCMD_addCommand(NULL, &curStringLen,
|
||||
single_cmd = WCMD_createCommand(NULL, &curStringLen,
|
||||
curRedirs, &curRedirsLen,
|
||||
&curCopyTo, &curLen,
|
||||
prevDelim, curDepth,
|
||||
output);
|
||||
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,
|
||||
single_cmd = WCMD_createCommand(curString, &curStringLen,
|
||||
curRedirs, &curRedirsLen,
|
||||
&curCopyTo, &curLen,
|
||||
prevDelim, curDepth,
|
||||
output);
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue