Module: wine Branch: master Commit: 327d7ef9e60446e7c421cab15baabee610421c9d URL: http://source.winehq.org/git/wine.git/?a=commit;h=327d7ef9e60446e7c421cab15b...
Author: Jason Edmeades us@edmeades.me.uk Date: Fri Feb 23 22:19:25 2007 +0000
cmd.exe: Add support for call :label and goto :label.
---
programs/cmd/batch.c | 86 +++++++++++++++++++++++++++++++++++++--------- programs/cmd/builtins.c | 6 +++- programs/cmd/wcmd.h | 3 +- programs/cmd/wcmdmain.c | 12 +++--- 4 files changed, 82 insertions(+), 25 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index 1a9d9e1..045046c 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -42,9 +42,12 @@ extern DWORD errorlevel; * * We need to handle recursion correctly, since one batch program might call another. * So parameters for this batch file are held in a BATCH_CONTEXT structure. + * + * To support call within the same batch program, another input parameter is + * a label to goto once opened. */
-void WCMD_batch (char *file, char *command, int called) { +void WCMD_batch (char *file, char *command, int called, char *startLabel, HANDLE pgmHandle) {
#define WCMD_BATCH_EXT_SIZE 5
@@ -55,27 +58,33 @@ char extension_exe[WCMD_BATCH_EXT_SIZE] = ".exe"; unsigned int i; BATCH_CONTEXT *prev_context;
- for(i=0; (i<(sizeof(extension_batch)/WCMD_BATCH_EXT_SIZE)) && - (h == INVALID_HANDLE_VALUE); i++) { - strcpy (string, file); - CharLower (string); - if (strstr (string, extension_batch[i]) == NULL) strcat (string, extension_batch[i]); - h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } - if (h == INVALID_HANDLE_VALUE) { + if (startLabel == NULL) { + for(i=0; (i<(sizeof(extension_batch)/WCMD_BATCH_EXT_SIZE)) && + (h == INVALID_HANDLE_VALUE); i++) { strcpy (string, file); CharLower (string); - if (strstr (string, extension_exe) == NULL) strcat (string, extension_exe); + if (strstr (string, extension_batch[i]) == NULL) strcat (string, extension_batch[i]); h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (h != INVALID_HANDLE_VALUE) { - WCMD_run_program (command, 0); - } else { - SetLastError (ERROR_FILE_NOT_FOUND); - WCMD_print_error (); } - return; + if (h == INVALID_HANDLE_VALUE) { + strcpy (string, file); + CharLower (string); + if (strstr (string, extension_exe) == NULL) strcat (string, extension_exe); + h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h != INVALID_HANDLE_VALUE) { + WCMD_run_program (command, 0); + } else { + SetLastError (ERROR_FILE_NOT_FOUND); + WCMD_print_error (); + } + return; + } + } else { + DuplicateHandle(GetCurrentProcess(), pgmHandle, + GetCurrentProcess(), &h, + 0, FALSE, DUPLICATE_SAME_ACCESS); }
/* @@ -90,6 +99,12 @@ BATCH_CONTEXT *prev_context; context -> prev_context = prev_context; context -> skip_rest = FALSE;
+ /* If processing a call :label, 'goto' the label in question */ + if (startLabel) { + strcpy(param1, startLabel); + WCMD_goto(); + } + /* * Work through the file line by line. Specific batch commands are processed here, * the rest are handled by the main command processor. @@ -695,3 +710,40 @@ void WCMD_HandleTildaModifiers(char **start, char *forVariable) { strcat(*start, pos); free(pos); } + +/******************************************************************* + * WCMD_call - processes a batch call statement + * + * If there is a leading ':', calls within this batch program + * otherwise launches another program. + */ +void WCMD_call (char *command) { + + /* Run other program if no leading ':' */ + if (*command != ':') { + WCMD_run_program(command, 1); + } else { + + char gotoLabel[MAX_PATH]; + + strcpy(gotoLabel, param1); + + if (context) { + + LARGE_INTEGER li; + + /* Save the current file position, call the same file, + restore position */ + li.QuadPart = 0; + li.LowPart = SetFilePointer(context -> h, li.LowPart, + &li.HighPart, FILE_CURRENT); + + WCMD_batch (param1, command, 1, gotoLabel, context->h); + + SetFilePointer(context -> h, li.LowPart, + &li.HighPart, FILE_BEGIN); + } else { + printf("Cannot call batch label outside of a batch script\n"); + } + } +} diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index 346591a..9a8b513 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -434,6 +434,7 @@ char string[MAX_PATH]; return; } if (context != NULL) { + char *paramStart = param1;
/* Handle special :EOF label */ if (lstrcmpi (":eof", param1) == 0) { @@ -441,9 +442,12 @@ char string[MAX_PATH]; return; }
+ /* Support goto :label as well as goto label */ + if (*paramStart == ':') paramStart++; + SetFilePointer (context -> h, 0, NULL, FILE_BEGIN); while (WCMD_fgets (string, sizeof(string), context -> h)) { - if ((string[0] == ':') && (lstrcmpi (&string[1], param1) == 0)) return; + if ((string[0] == ':') && (lstrcmpi (&string[1], paramStart) == 0)) return; } WCMD_output ("Target to GOTO not found\n"); } diff --git a/programs/cmd/wcmd.h b/programs/cmd/wcmd.h index 07d1649..4391d7c 100644 --- a/programs/cmd/wcmd.h +++ b/programs/cmd/wcmd.h @@ -27,7 +27,8 @@ #include <stdio.h> #include <ctype.h>
-void WCMD_batch (char *, char *, int); +void WCMD_batch (char *, char *, int, char *, HANDLE); +void WCMD_call (char *command); void WCMD_change_tty (void); void WCMD_clear_screen (void); void WCMD_copy (void); diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 84d1c04..17b75f3 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -265,7 +265,7 @@ int main (int argc, char *argv[]) if (h != INVALID_HANDLE_VALUE) { CloseHandle (h); #if 0 - WCMD_batch_command (string); + WCMD_batch ((char *)"\autoexec.bat", (char *)"\autoexec.bat", 0, NULL, INVALID_HANDLE_VALUE); #endif }
@@ -422,7 +422,7 @@ void WCMD_process_command (char *command) WCMD_setshow_attrib (); break; case WCMD_CALL: - WCMD_run_program (p, 1); + WCMD_call (p); break; case WCMD_CD: case WCMD_CHDIR: @@ -628,14 +628,14 @@ char filetorun[MAX_PATH]; if (!ext || !strcasecmp( ext, ".bat")) { if (SearchPath (NULL, param1, ".bat", sizeof(filetorun), filetorun, NULL)) { - WCMD_batch (filetorun, command, called); + WCMD_batch (filetorun, command, called, NULL, INVALID_HANDLE_VALUE); return; } } if (!ext || !strcasecmp( ext, ".cmd")) { if (SearchPath (NULL, param1, ".cmd", sizeof(filetorun), filetorun, NULL)) { - WCMD_batch (filetorun, command, called); + WCMD_batch (filetorun, command, called, NULL, INVALID_HANDLE_VALUE); return; } } @@ -644,7 +644,7 @@ char filetorun[MAX_PATH]; char *ext = strrchr( param1, '.' ); if (ext && (!strcasecmp( ext, ".bat" ) || !strcasecmp( ext, ".cmd" ))) { - WCMD_batch (param1, command, called); + WCMD_batch (param1, command, called, NULL, INVALID_HANDLE_VALUE); return; }
@@ -657,7 +657,7 @@ char filetorun[MAX_PATH]; NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) { CloseHandle (h); - WCMD_batch (param1, command, called); + WCMD_batch (param1, command, called, NULL, INVALID_HANDLE_VALUE); return; } }