texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

texinfo/tp Texinfo/Common.pm Texinfo/Structurin...


From: Patrice Dumas
Subject: texinfo/tp Texinfo/Common.pm Texinfo/Structurin...
Date: Wed, 29 Feb 2012 21:48:10 +0000

CVSROOT:        /sources/texinfo
Module name:    texinfo
Changes by:     Patrice Dumas <pertusus>        12/02/29 21:48:10

Modified files:
        tp/Texinfo     : Common.pm Structuring.pm 
        tp/t           : test_tree_copy.t 

Log message:
        Better copy_tree, when doing the skeleton of the tree collect the new
        reference, then in a second pass use the reference to complete the 
        structures in 'extra'.
        Use it instead of dclone, as dlcone clones all the tree<going through
        the parent.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Common.pm?cvsroot=texinfo&r1=1.137&r2=1.138
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/Texinfo/Structuring.pm?cvsroot=texinfo&r1=1.124&r2=1.125
http://cvs.savannah.gnu.org/viewcvs/texinfo/tp/t/test_tree_copy.t?cvsroot=texinfo&r1=1.1&r2=1.2

Patches:
Index: Texinfo/Common.pm
===================================================================
RCS file: /sources/texinfo/texinfo/tp/Texinfo/Common.pm,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -b -r1.137 -r1.138
--- Texinfo/Common.pm   26 Feb 2012 22:01:48 -0000      1.137
+++ Texinfo/Common.pm   29 Feb 2012 21:48:10 -0000      1.138
@@ -1444,39 +1444,195 @@
 # extra->def_arg
 
 
-sub copy_tree($$);
-sub copy_tree($$)
+sub _copy_tree($$$);
+sub _copy_tree($$$)
 {
   my $current = shift;
   my $parent = shift;
+  my $reference_associations = shift;
   my $new = {};
+  $reference_associations->{$current} = $new;
   $new->{'parent'} = $parent if ($parent);
   foreach my $key ('type', 'cmdname', 'text') {
     $new->{$key} = $current->{$key} if (exists($current->{$key}));
   }
   foreach my $key ('args', 'contents') {
     if ($current->{$key}) {
+      if (ref($current->{$key}) ne 'ARRAY') {
+        my $command_or_type = '';
+        if ($new->{'cmdname'}) {
+          $command_or_type = '@'.$new->{'cmdname'};
+        } elsif ($new->{'type'}) {
+          $command_or_type = $new->{'type'};
+        }
+        print STDERR "Not an array [$command_or_type] $key 
".ref($current->{$key})."\n";
+      }
       $new->{$key} = [];
+      $reference_associations->{$current->{$key}} = $new->{$key};
       foreach my $child (@{$current->{$key}}) {
-        push @{$new->{$key}}, copy_tree($child, $new);
+        push @{$new->{$key}}, _copy_tree($child, $new, 
$reference_associations);
       }
     }
   }
   if ($current->{'extra'}) {
     $new->{'extra'} = {};
     foreach my $key (keys %{$current->{'extra'}}) {
-      if (!ref($current->{'extra'}->{$key})) {
-        $new->{'extra'}->{$key} = $current->{'extra'}->{$key};
+      if ($current->{'cmdname'} and $current->{'cmdname'} eq 'multitable'
+          and $key eq 'prototypes') {
+        $new->{'extra'}->{$key} = [];
+        $reference_associations->{$current->{'extra'}->{$key}} = $new->{$key};
+        foreach my $child (@{$current->{'extra'}->{$key}}) {
+          push @{$new->{'extra'}->{$key}}, 
+                  _copy_tree($child, $new, $reference_associations);
       }
+      } elsif (!ref($current->{'extra'}->{$key})) {
+        $new->{'extra'}->{$key} = $current->{'extra'}->{$key};
     }
-    if ($current->{'extra'}->{'end_command'}) {
-      # FIXME this should be a ref to the end command instead...
-      $new->{'extra'}->{'end_command'} = 1;
     }
   }
   return $new;
 }
 
+# Not used.
+sub _collect_references($$);
+sub _collect_references($$)
+{
+  my $current = shift;
+  my $references = shift;
+  foreach my $key ('args', 'contents') {
+    if ($current->{$key}) {
+      $references->{$current->{$key}} = $current->{$key};
+      foreach my $child (@{$current->{$key}}) {
+        $references->{$child} = $child;
+        _collect_references($child, $references);
+      }
+    }
+  }
+}
+
+sub _substitute_references_in_array($$$);
+sub _substitute_references_in_array($$$)
+{
+  my $array = shift;
+  my $reference_associations = shift;
+  my $context = shift;
+
+  my $result = [];
+  my $index = 0;
+  foreach my $item (@{$array}) {
+    if (!ref($item)) {
+      push @{$result}, $item;
+    } elsif ($reference_associations->{$item}) {
+      push @{$result}, $reference_associations->{$item};
+    } elsif (ref($item) eq 'ARRAY') {
+      push @$result, 
+        _substitute_references_in_array($item, $reference_associations,
+                                        "$context [$index]");
+    } elsif (defined($item->{'text'})) {
+      my $new_text = _copy_tree($item, undef, $reference_associations);
+      substitute_references($item, $new_text, $reference_associations);
+      push @{$result}, $new_text;
+    } else {
+      print STDERR "Trouble with $context [$index] (".ref($item).")\n";
+      push @{$result}, undef;
+    }
+    $index++;
+  }
+  return $result;
+}
+
+sub substitute_references($$$);
+sub substitute_references($$$)
+{
+  my $current = shift;
+  my $new = shift;
+  my $reference_associations = shift;
+  
+  foreach my $key ('args', 'contents') {
+    if ($new->{$key}) {
+      my $index = 0;
+      foreach my $child (@{$new->{$key}}) {
+        substitute_references($child, $current->{$key}->[$index],
+                              $reference_associations);
+        $index++;
+      }
+    }
+  }
+  if ($current->{'extra'}) {
+    foreach my $key (keys %{$current->{'extra'}}) {
+      if (ref($current->{'extra'}->{$key})) {
+        my $command_or_type = '';
+        if ($new->{'cmdname'}) {
+          $command_or_type = '@'.$new->{'cmdname'};
+        } elsif ($new->{'type'}) {
+          $command_or_type = $new->{'type'};
+        }
+        
+        if ($current->{'cmdname'} and $current->{'cmdname'} eq 'multitable'
+            and $key eq 'prototypes') {
+          my $index = 0;
+          foreach my $child (@{$new->{'extra'}->{$key}}) {
+            substitute_references($child, 
$current->{'extra'}->{$key}->[$index],
+                                  $reference_associations);
+            $index++;
+          }
+        } elsif ($reference_associations->{$current->{'extra'}->{$key}}) {
+          $new->{'extra'}->{$key} 
+            = $reference_associations->{$current->{'extra'}->{$key}};
+          #print STDERR "Done [$command_or_type]: $key\n";
+        } else {
+          if (ref($current->{'extra'}->{$key}) eq 'ARRAY') {
+            
+            #print STDERR "Array $command_or_type -> $key\n";
+            $new->{'extra'}->{$key} = _substitute_references_in_array(
+              $current->{'extra'}->{$key}, $reference_associations,
+              "[$command_or_type]{$key}");
+          } else {
+            if (($current->{'cmdname'} 
+                 and ($current->{'cmdname'} eq 'listoffloats'
+                     or $current->{'cmdname'} eq 'float') 
+                 and $key eq 'type')
+                 or ($key eq 'index_entry')
+                 or ($current->{'type'} 
+                     and $current->{'type'} eq 'menu_entry'
+                     and $key eq 'menu_entry_node')) {
+              foreach my $type_key (keys(%{$current->{'extra'}->{$key}})) {
+                if (!ref($current->{'extra'}->{$key}->{$type_key})) {
+                  $new->{'extra'}->{$key}->{$type_key} 
+                    = $current->{'extra'}->{$key}->{$type_key};
+                } elsif 
($reference_associations->{$current->{'extra'}->{$key}->{$type_key}}) {
+                  $new->{'extra'}->{$key}->{$type_key}
+                    = 
$reference_associations->{$current->{'extra'}->{$key}->{$type_key}};
+                } elsif (ref($current->{'extra'}->{$key}->{$type_key}) eq 
'ARRAY') {
+                  $new->{'extra'}->{$key}->{$type_key}
+                    = _substitute_references_in_array(
+                      $current->{'extra'}->{$key}->{$type_key}, 
+                      $reference_associations,
+                      "[$command_or_type]{$key}{$type_key}");
+                } else {
+                  print STDERR "Not substituting [$command_or_type]{$key}: 
$type_key\n";
+                }
+              }
+            } else {
+              print STDERR "Not substituting [$command_or_type]: $key 
($current->{'extra'}->{$key})\n";
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+sub copy_tree($;$)
+{
+  my $current = shift;
+  my $parent = shift;
+  my $reference_associations = {};
+  my $copy = _copy_tree($current, $parent, $reference_associations);
+  substitute_references($current, $copy, $reference_associations);
+  return $copy;
+}
+
 sub modify_tree($$$;$);
 sub modify_tree($$$;$)
 {

Index: Texinfo/Structuring.pm
===================================================================
RCS file: /sources/texinfo/texinfo/tp/Texinfo/Structuring.pm,v
retrieving revision 1.124
retrieving revision 1.125
diff -u -b -r1.124 -r1.125
--- Texinfo/Structuring.pm      26 Feb 2012 22:01:48 -0000      1.124
+++ Texinfo/Structuring.pm      29 Feb 2012 21:48:10 -0000      1.125
@@ -29,7 +29,7 @@
 # for error messages 
 use Texinfo::Convert::Texinfo;
 
-use Storable qw(dclone);
+use Carp qw(cluck);
 
 require Exporter;
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
@@ -430,6 +430,8 @@
         if (@correct_level_offset_commands) {
           push @{$contents[-1]->{'contents'}}, @correct_level_offset_commands;
         }
+        #print STDERR "* $current_section_level 
"._print_root_command_texi($current_section)."\n";
+        #print STDERR "  $next_section_level 
"._print_root_command_texi($next_section)."\n";
         while ($next_section_level - $current_section_level > 1) {
           $current_section_level++;
           my $new_section = {'cmdname' =>
@@ -457,6 +459,7 @@
                  'contents' => [],
                  'parent' => $new_section->{'args'}->[0]->{'contents'}->[1]}];
           push @contents, $new_section;
+          #print STDERR "  -> "._print_root_command_texi($new_section)."\n";
         }
         my @set_level_offset_commands = _correct_level($next_section,
                                                        $contents[-1], -1);
@@ -1365,7 +1368,7 @@
       if ($content->{'cmdname'} eq 'top') {
         $new_node_tree = {'contents' => [{'text' => 'Top'}]};
       } else {
-        $new_node_tree = dclone({'contents' 
+        $new_node_tree = Texinfo::Common::copy_tree({'contents' 
           => $content->{'extra'}->{'misc_content'}});
       }
       my $new_node = _new_node ($self, $new_node_tree);
@@ -1386,6 +1389,17 @@
   return address@hidden;
 }
 
+sub _copy_contents($)
+{
+  my $contents = shift;
+  if (ref($contents) ne 'ARRAY') {
+    cluck "$contents not an array";
+    return undef;
+  }
+  my $copy = Texinfo::Common::copy_tree({'contents' => $contents});
+  return $copy->{'contents'};
+}
+
 sub _new_node_menu_entry($$)
 {
   my $self = shift;
@@ -1395,7 +1409,8 @@
 
   my $menu_entry_node = {'type' => 'menu_entry_node'};
   $menu_entry_node->{'contents'}
-    = dclone ($node_contents);
+    = _copy_contents ($node_contents);
+
   foreach my $content (@{$menu_entry_node->{'contents'}}) {
     $content->{'parent'} = $menu_entry_node;
   }
@@ -1579,9 +1594,9 @@
         and $node->{'extra'}->{'associated_section'}->{'extra'}
         and 
$node->{'extra'}->{'associated_section'}->{'extra'}->{'misc_content'}) {
       $node_title_contents
-        = 
dclone($node->{'extra'}->{'associated_section'}->{'extra'}->{'misc_content'});
+        = 
_copy_contents($node->{'extra'}->{'associated_section'}->{'extra'}->{'misc_content'});
     } else {
-      $node_title_contents = dclone($node->{'extra'}->{'node_content'});
+      $node_title_contents = 
_copy_contents($node->{'extra'}->{'node_content'});
     }
     my $menu_comment = {'type' => 'menu_comment'};
     $menu_comment->{'contents'}->[0] = {'type' => 'preformatted',
@@ -1599,7 +1614,7 @@
       foreach my $menu (@{$node->{'menus'}}) {
         foreach my $entry (@{$menu->{'contents'}}) {
           if ($entry->{'type'} and $entry->{'type'} eq 'menu_entry') {
-            push @master_menu_contents, dclone($entry);
+            push @master_menu_contents, Texinfo::Common::copy_tree($entry);
           }
         }
       }

Index: t/test_tree_copy.t
===================================================================
RCS file: /sources/texinfo/texinfo/tp/t/test_tree_copy.t,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- t/test_tree_copy.t  29 Dec 2011 23:24:49 -0000      1.1
+++ t/test_tree_copy.t  29 Feb 2012 21:48:10 -0000      1.2
@@ -72,16 +72,15 @@
 ';
 
 my $tree = Texinfo::Parser::parse_texi_text(undef, $text);
-
+my $reference_associations = {};
 my $copy = Texinfo::Common::copy_tree($tree, undef);
 
 my $texi_tree = Texinfo::Convert::Texinfo::convert($tree);
 
 is ($text, $texi_tree, "tree to texi and original match");
 
-#print STDERR diff(\$text, \$texi_tree);
-
 my $texi_copy = Texinfo::Convert::Texinfo::convert($copy);
+is ($texi_copy, $texi_tree, "tree and copy to texi match");
 
 #{
 #  local $Data::Dumper::Purity = 1;
@@ -90,8 +89,4 @@
 #}
 
 
-is ($texi_copy, $texi_tree, "tree and copy to texi match");
-
-#print STDERR diff(\$texi_copy, \$texi_tree);
-
 1;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]