Index: /trunk/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm
===================================================================
--- /trunk/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm	(revision 3487)
+++ /trunk/PS-IPP-Metadata-Config/lib/PS/IPP/Metadata/Config.pm	(revision 3488)
@@ -1,5 +1,5 @@
 # Copyright (c) 2005  Joshua Hoblitt
 #
-# $Id: Config.pm,v 1.11 2005-03-23 21:30:37 jhoblitt Exp $
+# $Id: Config.pm,v 1.12 2005-03-24 00:15:15 jhoblitt Exp $
 
 package PS::IPP::Metadata::Config;
@@ -45,7 +45,62 @@
     return undef unless defined $tree;
 
+    # look for duplicate names, there should be none after processing the
+    # multi-symbols
+    $self->_merge_duplicates( $tree ) or return undef;
+
     #print Dumper($tree);
 
     return $tree;
+}
+
+sub _merge_duplicates {
+    my ( $self, $tree ) = @_;
+
+    # encountered names
+    my %names;
+
+    # Iteratate through the parse tree looking for duplicate declarations and
+    # resolving them by discarding elements according to the value of
+    # 'overwrite'.
+    for (my $i = 0; $i < @{$tree}; $i++) {
+        my $elem = $tree->[$i];
+
+        # stop if the prevous pass removed the last element and called redo
+        last unless defined $elem;
+                
+        # recurse through nested metadata
+        if ( $elem->{class} eq "metadata" ) {
+            $self->_merge_duplicates( $elem->{value} );
+        }
+
+        # ignore elements with the "multi" flag
+        if ( defined $elem->{multi} ) {
+            delete $elem->{multi};
+            next;
+        } 
+
+        if ( defined $names{ $elem->{name} } ) {
+            if ( $self->{overwrite} ) {
+                # remove the previous occurance
+                carp "duplicate variable name: ", $elem->{name}
+                    , ", removed previous occurance\n";
+                splice @{$tree}, $names{ $elem->{name} }, 1;
+            } else {
+                # remove the current occurance
+                carp "duplicate variable name: ", $elem->{name}
+                    , ", removed\n";
+                splice @{$tree}, $i, 1;
+            }
+
+            # the list just got shorter by one element so we don't want to
+            # increment the cursor
+            redo;
+        }
+
+        # add element name and location to record of previously seen names
+        $names{ $elem->{name} } = $i;
+    }
+
+    return 1;
 }
 
@@ -86,4 +141,7 @@
     <skip:'[ \t\r]*'> name type <matchrule:$item{type}> comment(?) "\n"
         {
+            $thisparser->{local}{name}{ $item{name} }++
+                unless defined $thisparser->{local}{name}{ $item{name} };
+
             $return = {
                 class   => 'scalar',
@@ -95,4 +153,11 @@
             $return->{comment} = $item{'comment(?)'}[0]
                 if $item{'comment(?)'}[0];
+
+            if ( defined $thisparser->{local}{name}{ $item{name} } ) {
+                $return->{multi}++
+                    if $thisparser->{local}{name}{ $item{name} } =~ /MULTI/;
+            } else {
+                $thisparser->{local}{name}{ $item{name} }++;
+            }
         }
 
@@ -100,4 +165,7 @@
      <skip:'[ \t\r]*'> vname vtype vvalue[ $item{vtype} ] comment(?) "\n"
         {
+            $thisparser->{local}{name}{ $item{vname} }++
+                unless defined $thisparser->{local}{name}{ $item{vname} };
+
             $return = {
                 class   => 'vector',
@@ -113,8 +181,14 @@
 
 multi_declare:
-    <skip:'[ \t\r]*'> name /MULTI/i comment(?) "\n"
-        {{
-            class   => 'comment_line',
-        }}
+    <skip:'[ \t\r]*'> name /MULTI/i <commit> comment(?) "\n"
+        {
+            if ( ! defined $thisparser->{local}{name}{ $item{name} } ) {
+                $thisparser->{local}{name}{ $item{name} } = "MULTI";
+                $return = { class   => 'comment_line' };
+            } else {
+                $return = undef;
+            }
+        }
+    | <error?:redefinition of MULTI> <reject>
 
 metadata:
