From: Eric Pouech epouech@codeweavers.com
Separating the cases of: - calling into a new batch file, - calling a label inside current batch file.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- programs/cmd/batch.c | 133 +++++++++++++++++++++------------------- programs/cmd/wcmd.h | 3 +- programs/cmd/wcmdmain.c | 2 +- 3 files changed, 73 insertions(+), 65 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 776f2ea326f..4416dab1705 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -24,6 +24,35 @@
WINE_DEFAULT_DEBUG_CHANNEL(cmd);
+static RETURN_CODE WCMD_batch_main_loop(void) +{ + RETURN_CODE return_code = NO_ERROR; + /* Work through the file line by line until an exit is called. */ + while (!context->skip_rest) + { + CMD_NODE *node; + + switch (WCMD_ReadAndParseLine(NULL, &node, context->h)) + { + case RPL_EOF: + context->skip_rest = TRUE; + break; + case RPL_SUCCESS: + return_code = node_execute(node); + node_dispose_tree(node); + break; + case RPL_SYNTAXERROR: + return_code = RETURN_CODE_SYNTAX_ERROR; + break; + } + } + + /* If there are outstanding setlocal's to the current context, unwind them. */ + while (WCMD_endlocal() == NO_ERROR) {} + + return return_code; +} + /**************************************************************************** * WCMD_batch * @@ -40,78 +69,38 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd); * a label to goto once opened. */
-RETURN_CODE WCMD_batch(const WCHAR *file, WCHAR *command, const WCHAR *startLabel, HANDLE pgmHandle) +RETURN_CODE WCMD_call_batch(const WCHAR *file, WCHAR *command) { - HANDLE h = INVALID_HANDLE_VALUE; - BATCH_CONTEXT *prev_context; - RETURN_CODE return_code = NO_ERROR; + HANDLE h = INVALID_HANDLE_VALUE; + BATCH_CONTEXT *prev_context; + RETURN_CODE return_code = NO_ERROR;
- if (startLabel == NULL) { h = CreateFileW (file, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { - SetLastError (ERROR_FILE_NOT_FOUND); - WCMD_print_error (); - return ERROR_INVALID_FUNCTION; + SetLastError (ERROR_FILE_NOT_FOUND); + WCMD_print_error (); + return ERROR_INVALID_FUNCTION; } - } else { - DuplicateHandle(GetCurrentProcess(), pgmHandle, - GetCurrentProcess(), &h, - 0, FALSE, DUPLICATE_SAME_ACCESS); - }
-/* - * Create a context structure for this batch file. - */ + /* Create a context structure for this batch file. */ + prev_context = context; + context = malloc(sizeof (BATCH_CONTEXT)); + context->h = h; + context->batchfileW = xstrdupW(file); + context->command = command; + memset(context->shift_count, 0x00, sizeof(context->shift_count)); + context->prev_context = prev_context; + context->skip_rest = FALSE;
- prev_context = context; - context = LocalAlloc (LMEM_FIXED, sizeof (BATCH_CONTEXT)); - context->h = h; - context->batchfileW = xstrdupW(file); - context->command = command; - memset(context->shift_count, 0x00, sizeof(context->shift_count)); - context->prev_context = prev_context; - context->skip_rest = FALSE; - - /* If processing a call :label, 'goto' the label in question */ - if (startLabel) { - lstrcpyW(param1, startLabel); - WCMD_goto(); - } + return_code = WCMD_batch_main_loop(); + CloseHandle (h);
-/* - * Work through the file line by line. Specific batch commands are processed here, - * the rest are handled by the main command processor. - */ - - while (!context->skip_rest) - { - CMD_NODE *node; - - switch (WCMD_ReadAndParseLine(NULL, &node, h)) - { - case RPL_EOF: - context->skip_rest = TRUE; - break; - case RPL_SUCCESS: - return_code = node_execute(node); - node_dispose_tree(node); - break; - case RPL_SYNTAXERROR: - return_code = RETURN_CODE_SYNTAX_ERROR; - break; - } - } - CloseHandle (h); + free(context->batchfileW); + free(context); + context = prev_context;
- /* If there are outstanding setlocal's to the current context, unwind them. */ - while (WCMD_endlocal() == NO_ERROR) {} - - free(context->batchfileW); - LocalFree(context); - context = prev_context; - - return return_code; + return return_code; }
/******************************************************************* @@ -671,6 +660,7 @@ RETURN_CODE WCMD_call(WCHAR *command) { LARGE_INTEGER li; WCHAR gotoLabel[MAX_PATH]; + BATCH_CONTEXT *prev_context;
lstrcpyW(gotoLabel, param1);
@@ -683,7 +673,24 @@ RETURN_CODE WCMD_call(WCHAR *command) li.QuadPart = 0; li.u.LowPart = SetFilePointer(context->h, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); - WCMD_batch(context->batchfileW, buffer, gotoLabel, context->h); + + prev_context = context; + context = malloc(sizeof (BATCH_CONTEXT)); + context->h = prev_context->h; + context->batchfileW = prev_context->batchfileW; + context->command = buffer; + memset(context->shift_count, 0x00, sizeof(context->shift_count)); + context->prev_context = prev_context; + context->skip_rest = FALSE; + + /* FIXME as commands here can temper with param1 global variable (ugly) */ + lstrcpyW(param1, gotoLabel); + WCMD_goto(); + + WCMD_batch_main_loop(); + + free(context); + context = prev_context; return_code = errorlevel; SetFilePointer(context->h, li.u.LowPart, &li.u.HighPart, FILE_BEGIN);
diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 9f983160b06..4fad2884e1e 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -155,7 +155,6 @@ typedef int RETURN_CODE; BOOL WCMD_print_volume_information(const WCHAR *);
RETURN_CODE WCMD_assoc(const WCHAR *, BOOL); -RETURN_CODE WCMD_batch(const WCHAR *, WCHAR *, const WCHAR *, HANDLE); RETURN_CODE WCMD_call(WCHAR *command); RETURN_CODE WCMD_choice(WCHAR *); RETURN_CODE WCMD_clear_screen(void); @@ -221,6 +220,8 @@ enum read_parse_line WCMD_ReadAndParseLine(const WCHAR *initialcmd, CMD_NODE **o void node_dispose_tree(CMD_NODE *cmds); RETURN_CODE node_execute(CMD_NODE *node);
+RETURN_CODE WCMD_call_batch(const WCHAR *, WCHAR *); + void *xrealloc(void *, size_t) __WINE_ALLOC_SIZE(2) __WINE_DEALLOC(free);
static inline void *xalloc(size_t sz) __WINE_MALLOC; diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index d3ad93837d4..61d5c0fcbd7 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -1583,7 +1583,7 @@ RETURN_CODE WCMD_run_program(WCHAR *command, BOOL called) BOOL oldinteractive = interactive;
interactive = FALSE; - return_code = WCMD_batch(thisDir, command, NULL, INVALID_HANDLE_VALUE); + return_code = WCMD_call_batch(thisDir, command); interactive = oldinteractive; if (context && !called) { TRACE("Batch completed, but was not 'called' so skipping outer batch too\n");