# New Ticket Created by Ron Blaschke # Please include the string: [perl #43235] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=43235 >
Attached patch should take care of tickets #37301 and #40972. Windows XP - Visual C++ 8 $ runtests -v t\pmc\env.t t\pmc\env...... 1..12 ok 1 - all Envs are ident ok 2 - getenv ok 3 - setenv/getenv ok 4 - envs are all the same ok 5 - gone/delete ok 6 - iterate ok 7 - exists/delete ok 8 - check whether interface is done ok 9 - get_integer() ok 10 - get_number() ok 11 - getenv - null key ok 12 - setenv/getenv - PMC key ok All tests successful. Files=1, Tests=12, 1 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU) Windows XP - MinGW (GCC) $ runtests -v t\pmc\env.t t\pmc\env...... 1..12 ok 1 - all Envs are ident ok 2 - getenv ok 3 - setenv/getenv ok 4 - envs are all the same ok 5 - gone/delete ok 6 - iterate ok 7 - exists/delete ok 8 - check whether interface is done ok 9 - get_integer() ok 10 - get_number() ok 11 - getenv - null key ok 12 - setenv/getenv - PMC key ok All tests successful. Files=1, Tests=12, 2 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU) Ron
Index: t/pmc/env.t =================================================================== --- t/pmc/env.t (revision 19066) +++ t/pmc/env.t (working copy) @@ -92,11 +92,7 @@ ok 2 OUT -SKIP: -{ - skip 'iterator not available on win32' => 1 - if 'MSWin32' eq $^O; - pasm_output_is( <<'CODE', <<OUT, "iterate" ); +pasm_output_is( <<'CODE', <<OUT, "iterate" ); new P0, .Env set P0["PARROT_1"], "hello" set P0["PARROT_2"], "polly" @@ -121,10 +117,8 @@ CODE ok OUT -} SKIP: { - # This will not work on our unsetenv implementation skip( "no native unsetenv", 1 ) unless $PConfig{"unsetenv"}; pasm_output_is( <<'CODE', <<OUT, "exists/delete" ); @@ -173,10 +167,7 @@ 0 OUTPUT -SKIP: { - skip 'not changing environment on windows', 2 if $^O eq 'MSWin32'; - - pir_output_is( << 'CODE', << 'OUTPUT', "get_integer()" ); +pir_output_is( << 'CODE', << 'OUTPUT', "get_integer()" ); .sub main .local pmc env .local int num_before, num_after, num_diff @@ -197,7 +188,7 @@ 3 OUTPUT - pir_output_is( << 'CODE', << 'OUTPUT', "get_number()" ); +pir_output_is( << 'CODE', << 'OUTPUT', "get_number()" ); .sub main .local pmc env .local num num_before, num_after, num_diff @@ -217,7 +208,6 @@ CODE 3.000000 OUTPUT -} pasm_output_is( <<'CODE', <<OUT, "getenv - null key" ); new P0, .Env Index: config/gen/platform/win32/env.c =================================================================== --- config/gen/platform/win32/env.c (revision 19066) +++ config/gen/platform/win32/env.c (working copy) @@ -1,14 +1,59 @@ /* + On Windows there are two ways to access the environment. Either through the + Windows environment block, using GetEnvironmentVariable, + SetEnvironmentVariable and GetEnvironmentStrings, or the C runtime using + _getenv, _putenv and _environ. + + Changes through the C runtime are reflected in the environment block, but + changes in the environment block are NOT reflected in the C runtime! + + To keep both in sync we always update environment variables through the C + runtime. Getting an environment variable can be done either way, + whichever is more convenient. +*/ + +/* ** Parrot_setenv() */ void Parrot_setenv(const char *name, const char *value) { - SetEnvironmentVariable(name, value); + assert(name != NULL); + assert(value != NULL); + + { + const int name_len = strlen(name ); + const int value_len = strlen(value); + + { + char * const envstring = malloc( + name_len /* name */ + + 1 /* '=' */ + + value_len /* value */ + + 1 /* string terminator */ + ); + if (envstring == NULL) { + /* TODO: Shouldn't we tell anyone that we failed? */ + return; + } + + /* Save a bit of time, by using the fact we already have the + lengths, avoiding strcat */ + strcpy(envstring, name ); + strcpy(envstring + name_len, "=" ); + strcpy(envstring + name_len + 1, value); + + if (_putenv(envstring) == 0) { + /* success */ + } else { + /* TODO: Shouldn't we tell anyone that we failed? */ + } + free(envstring); + } + } } - char * Parrot_getenv(const char *name, int *free_it) { @@ -25,10 +70,15 @@ return buffer; } + void Parrot_unsetenv(const char *name) { - SetEnvironmentVariable(name, NULL); +/* You can remove a variable from the environment by specifying an empty + string -- in other words, by specifying only varname=. + -- _putenv, _wputenv (CRT) documentation +*/ + Parrot_setenv(name, ""); } /*