# New Ticket Created by  Matt Kennedy 
# Please include the string:  [perl #30631]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=30631 >


The attached env.patch patches classes/env.pmc to add vtable methods
elements() and get_iter() and modifies get_string_keyed() to also
accept integer keys so that it is possible to use an Iterator on the
environment. The patch uses the char **environ variable in order to
perform the iteration. I've tested it on Mac OS X with gcc 3.1 and
Linux with gcc 3.2.2.

The envtests.patch patches t/pmc/env.t to add a test case for the
iterator operation on the Env pmc.

Patches were done against the parrot_2004-07-07_070001 snapshot.

-- 
Matt Kennedy
--- classes/env.pmc.orig	2004-07-07 10:05:01.000000000 -0400
+++ classes/env.pmc	2004-07-07 10:51:40.000000000 -0400
@@ -20,11 +20,49 @@
 */
 
 #include "parrot/parrot.h"
+extern char **environ;
 
 pmclass Env singleton {
 
 /*
 
+=item C<INTVAL elements()>
+
+Returns the number of elements in the environment.
+
+=cut
+
+*/
+
+    INTVAL elements () {
+        INTVAL rv = 0;
+        while(environ[rv] != NULL) { rv++; }
+        return rv;
+    }
+
+/*
+
+=item C<PMC* get_iter()>
+
+Returns a new iterator for the environment.
+
+=cut
+
+*/
+
+    PMC* get_iter () {
+        PMC *iter = pmc_new_init(interpreter, enum_class_Iterator, SELF);
+        PMC *key = pmc_new(interpreter, enum_class_Key);
+        PMC_struct_val(iter) = key;
+        PObj_get_FLAGS(key) |= KEY_integer_FLAG;
+        PMC_int_val(key) = 0;
+        if(!environ[0])
+            PMC_int_val(key) = -1;
+        return iter;
+    }
+
+/*
+
 =item C<STRING *get_string_keyed(PMC *key)>
 
 Returns the Parrot string value for the environment variable C<*key>.
@@ -34,24 +72,37 @@
 */
 
     STRING* get_string_keyed(PMC* key) {
-        char *keyname = string_to_cstring(interpreter,
-            VTABLE_get_string(interpreter, key));
         int free_it = 0;
         STRING *retval;
-        char *val = NULL;
+        char *keyname, *envp, *p, *val = NULL;
 
-        if (keyname) {
-            val = Parrot_getenv(keyname, &free_it);
-            string_cstring_free(keyname);
-            if (val) {
-                retval = string_from_cstring(interpreter, val, 0);
-            } else {
-                retval = string_from_cstring(interpreter, "", 0);
-            }
-        } else {
-            retval = string_from_cstring(interpreter, "", 0);
+        switch(PObj_get_FLAGS(key) & KEY_type_FLAGS) {
+            case KEY_integer_FLAG:
+                if(PMC_int_val(key) < 0) {
+                    retval = string_from_cstring(interpreter, "", 0);
+                } else {
+                    envp = environ[PMC_int_val(key)];
+                    p = strchr(envp, '=');
+                    retval = string_from_cstring(interpreter, envp, (p-envp));
+                }
+                break;
+            default:
+                keyname = string_to_cstring(interpreter,
+                    VTABLE_get_string(interpreter, key));
+                if (keyname) {
+                    val = Parrot_getenv(keyname, &free_it);
+                    string_cstring_free(keyname);
+                    if (val) {
+                        retval = string_from_cstring(interpreter, val, 0);
+                    } else {
+                        retval = string_from_cstring(interpreter, "", 0);
+                    }
+                } else {
+                    retval = string_from_cstring(interpreter, "", 0);
+                }
+                if (free_it && val) mem_sys_free(val);
+                break;
         }
-        if (free_it && val) mem_sys_free(val);
         return retval;
     }
 
--- t/pmc/env.t.orig	2004-07-07 10:44:11.000000000 -0400
+++ t/pmc/env.t	2004-07-07 11:34:44.000000000 -0400
@@ -16,7 +16,7 @@
 
 =cut
 
-use Parrot::Test tests => 6;
+use Parrot::Test tests => 7;
 use Test::More;
 use Parrot::Config;
 
@@ -89,6 +89,32 @@
 ok 2
 OUT
 
+output_is(<<'CODE', <<OUT, "iterate");
+    new P0, .Env
+    set P0["PARROT_1"], "hello"
+    set P0["PARROT_2"], "polly"
+    iter P1, P0
+    set I0, 0
+loop:
+    unless P1, loopend
+    shift S2, P1
+    eq S2, "PARROT_1", gotit
+    eq S2, "PARROT_2", gotit
+    branch notit
+gotit:
+    inc I0
+notit:
+    branch loop
+loopend:
+    eq I0, 2, isok
+    print "not "
+isok:
+    print "ok\n"
+    end
+CODE
+ok
+OUT
+
 SKIP: {
     # won't work on our unsetenv implementation
     skip("no native unsetenv", 1) unless $PConfig{"unsetenv"};

Reply via email to