WCMD: implement setlocal/endlocal
Mike McCormack
mike at codeweavers.com
Thu Mar 18 20:22:39 CST 2004
ChangeLog:
* implement setlocal/endlocal
-------------- next part --------------
? programs/wcmd/wcmd.exe.spec.c
Index: programs/wcmd/builtins.c
===================================================================
RCS file: /home/wine/wine/programs/wcmd/builtins.c,v
retrieving revision 1.22
diff -u -r1.22 builtins.c
--- programs/wcmd/builtins.c 18 Mar 2004 04:01:32 -0000 1.22
+++ programs/wcmd/builtins.c 19 Mar 2004 01:34:40 -0000
@@ -36,6 +36,14 @@
void WCMD_execute (char *orig_command, char *parameter, char *substitution);
+struct env_stack
+{
+ struct env_stack *next;
+ WCHAR *strings;
+};
+
+struct env_stack *saved_environment;
+
extern HINSTANCE hinst;
extern char *inbuilt[];
extern char nyi[];
@@ -504,6 +512,133 @@
}
status = MoveFile (param1, param2);
if (!status) WCMD_print_error ();
+}
+
+/*****************************************************************************
+ * WCMD_dupenv
+ *
+ * Make a copy of the environment.
+ */
+WCHAR *WCMD_dupenv( const WCHAR *env )
+{
+ WCHAR *env_copy;
+ int len;
+
+ if( !env )
+ return NULL;
+
+ len = 0;
+ while ( env[len] )
+ len += (lstrlenW(&env[len]) + 1);
+
+ env_copy = LocalAlloc (LMEM_FIXED, (len+1) * sizeof (WCHAR) );
+ if (!env_copy)
+ {
+ WCMD_output ("out of memory\n");
+ return env_copy;
+ }
+ memcpy (env_copy, env, len*sizeof (WCHAR));
+ env_copy[len] = 0;
+
+ return env_copy;
+}
+
+/*****************************************************************************
+ * WCMD_setlocal
+ *
+ * setlocal pushes the environment onto a stack
+ * Save the environment as unicode so we don't screw anything up.
+ */
+void WCMD_setlocal (const char *s) {
+ WCHAR *env;
+ struct env_stack *env_copy;
+
+ /* DISABLEEXTENSIONS ignored */
+
+ env_copy = LocalAlloc (LMEM_FIXED, sizeof (struct env_stack));
+ if( !env_copy )
+ {
+ WCMD_output ("out of memory\n");
+ return;
+ }
+
+ env = GetEnvironmentStringsW ();
+
+ env_copy->strings = WCMD_dupenv (env);
+ if (env_copy->strings)
+ {
+ env_copy->next = saved_environment;
+ saved_environment = env_copy;
+ }
+ else
+ LocalFree (env_copy);
+
+ FreeEnvironmentStringsW (env);
+}
+
+/*****************************************************************************
+ * WCMD_strchrW
+ */
+inline WCHAR *WCMD_strchrW(WCHAR *str, WCHAR ch)
+{
+ while(*str)
+ {
+ if(*str == ch)
+ return str;
+ str++;
+ }
+ return NULL;
+}
+
+/*****************************************************************************
+ * WCMD_endlocal
+ *
+ * endlocal pops the environment off a stack
+ */
+void WCMD_endlocal (void) {
+ WCHAR *env, *old, *p;
+ struct env_stack *temp;
+ int len, n;
+
+ if (!saved_environment)
+ return;
+
+ /* pop the old environment from the stack */
+ temp = saved_environment;
+ saved_environment = temp->next;
+
+ /* delete the current environment, totally */
+ env = GetEnvironmentStringsW ();
+ old = WCMD_dupenv (GetEnvironmentStringsW ());
+ len = 0;
+ while (old[len]) {
+ n = lstrlenW(&old[len]) + 1;
+ p = WCMD_strchrW(&old[len], '=');
+ if (p)
+ {
+ *p++ = 0;
+ SetEnvironmentVariableW (&old[len], NULL);
+ }
+ len += n;
+ }
+ LocalFree (old);
+ FreeEnvironmentStringsW (env);
+
+ /* restore old environment */
+ env = temp->strings;
+ len = 0;
+ while (env[len]) {
+ n = lstrlenW(&env[len]) + 1;
+ p = WCMD_strchrW(&env[len], '=');
+ if (p)
+ {
+ *p++ = 0;
+ SetEnvironmentVariableW (&env[len], p);
+ }
+ len += n;
+ }
+ LocalFree (env);
+ LocalFree (temp);
}
/*****************************************************************************
Index: programs/wcmd/wcmd.h
===================================================================
RCS file: /home/wine/wine/programs/wcmd/wcmd.h,v
retrieving revision 1.13
diff -u -r1.13 wcmd.h
--- programs/wcmd/wcmd.h 13 Dec 2003 03:22:02 -0000 1.13
+++ programs/wcmd/wcmd.h 19 Mar 2004 01:34:40 -0000
@@ -35,6 +35,7 @@
void WCMD_delete (int recurse);
void WCMD_directory (void);
void WCMD_echo (const char *);
+void WCMD_endlocal (void);
void WCMD_enter_paged_mode(void);
void WCMD_for (char *);
void WCMD_give_help (char *command);
@@ -53,6 +54,7 @@
void WCMD_remove_dir (void);
void WCMD_rename (void);
void WCMD_run_program (char *command);
+void WCMD_setlocal (const char *command);
void WCMD_setshow_attrib (void);
void WCMD_setshow_date (void);
void WCMD_setshow_default (void);
@@ -130,5 +132,8 @@
#define WCMD_VER 34
#define WCMD_VOL 35
+#define WCMD_ENDLOCAL 36
+#define WCMD_SETLOCAL 37
+
/* Must be last in list */
-#define WCMD_EXIT 36
+#define WCMD_EXIT 38
Index: programs/wcmd/wcmdmain.c
===================================================================
RCS file: /home/wine/wine/programs/wcmd/wcmdmain.c,v
retrieving revision 1.40
diff -u -r1.40 wcmdmain.c
--- programs/wcmd/wcmdmain.c 18 Mar 2004 04:01:32 -0000 1.40
+++ programs/wcmd/wcmdmain.c 19 Mar 2004 01:34:40 -0000
@@ -31,7 +31,8 @@
"DATE", "DEL", "DIR", "ECHO", "ERASE", "FOR", "GOTO",
"HELP", "IF", "LABEL", "MD", "MKDIR", "MOVE", "PATH", "PAUSE",
"PROMPT", "REM", "REN", "RENAME", "RD", "RMDIR", "SET", "SHIFT",
- "TIME", "TITLE", "TYPE", "VERIFY", "VER", "VOL", "EXIT" };
+ "TIME", "TITLE", "TYPE", "VERIFY", "VER", "VOL",
+ "ENDLOCAL", "SETLOCAL", "EXIT" };
HINSTANCE hinst;
DWORD errorlevel;
@@ -426,6 +427,12 @@
case WCMD_RD:
case WCMD_RMDIR:
WCMD_remove_dir ();
+ break;
+ case WCMD_SETLOCAL:
+ WCMD_setlocal(p);
+ break;
+ case WCMD_ENDLOCAL:
+ WCMD_endlocal();
break;
case WCMD_SET:
WCMD_setshow_env (p);
More information about the wine-patches
mailing list