Implement setlocal/endlocal.

This commit is contained in:
Mike McCormack 2004-03-22 22:56:58 +00:00 committed by Alexandre Julliard
parent 9d61aee357
commit 9643b79842
3 changed files with 149 additions and 2 deletions

View File

@ -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[];
@ -506,6 +514,133 @@ int status;
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);
}
/*****************************************************************************
* WCMD_setshow_attrib
*

View File

@ -35,6 +35,7 @@ void WCMD_create_dir (void);
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 @@ int WCMD_read_console (char *string, int str_len);
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 @@ typedef struct {
#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

View File

@ -31,7 +31,8 @@ const char *inbuilt[] = {"ATTRIB", "CALL", "CD", "CHDIR", "CLS", "COPY", "CTTY",
"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;
@ -427,6 +428,12 @@ void WCMD_process_command (char *command)
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);
break;