[07/16] CMD.exe: Support call :label and goto :label
Ann & Jason Edmeades
us at edmeades.me.uk
Mon Feb 19 18:38:23 CST 2007
-------------- next part --------------
>From nobody Mon Sep 17 00:00:00 2001
From: Jason Edmeades <us at edmeades.me.uk>
Date: Sat Feb 17 22:34:05 2007 +0000
Subject: [PATCH] Support call :label and goto :label
---
programs/cmd/batch.c | 85 ++++++++++++++++++++++++++++++++++++++---------
programs/cmd/builtins.c | 6 +++
programs/cmd/wcmd.h | 3 +-
programs/cmd/wcmdmain.c | 10 +++---
4 files changed, 80 insertions(+), 24 deletions(-)
54f6f3b80913a8ff76f53bf44d0dc64dd3b3f84c
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c
index 4ac6f78..324d8cf 100755
--- a/programs/cmd/batch.c
+++ b/programs/cmd/batch.c
@@ -42,9 +42,12 @@ #define MAXSTRING 8192
*
* 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]
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.
@@ -649,3 +664,39 @@ void WCMD_HandleTildaModifiers(char **st
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 836900a..7f00068 100755
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -433,6 +433,7 @@ char string[MAX_PATH];
return;
}
if (context != NULL) {
+ char *paramStart = param1;
/* Handle special :EOF label */
if (lstrcmpi (":eof", param1) == 0) {
@@ -440,9 +441,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 263412e..cd2ea75 100755
--- a/programs/cmd/wcmd.h
+++ b/programs/cmd/wcmd.h
@@ -27,7 +27,8 @@ #include <stdarg.h>
#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 8077fb8..adb5a42 100755
--- a/programs/cmd/wcmdmain.c
+++ b/programs/cmd/wcmdmain.c
@@ -403,7 +403,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:
@@ -603,14 +603,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;
}
}
@@ -619,7 +619,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;
}
@@ -632,7 +632,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;
}
}
--
1.3.0
More information about the wine-patches
mailing list