jccunning has asked for the wisdom of the Perl Monks concerning the following question:
I am using following subroutine in a api diff tool I am writing. Problem is that in the C++ api documentation there are class members or parameters with same name. The name is passed to routine as key for searching. When script compares to xml versions of the api and there is a change in one location, for example the type for the public method bits member has changed from uint32_t to uint64_t, then routine finds location for all members that are named "value". Would like to display only the search path containing the change. Initial thought is to pass entire line containing change as the search key. If this is possible, don't know how to implement. Any ideas.
#!/usr/bin/perl use warnings FATAL => qw(all); use strict; use Data::Dump qw(dump pp); use XML::Simple qw(:strict); use Data::Dumper; run(); sub run { my $xml = XMLin( <<'END', ForceArray => ['parameters'], KeyAttr => ['declaratio +n_name', 'name']); <classes name="Panoply::BAR"> <public_methods> <members name="BAR" const="no" kind="function" protection="publi +c" static="no" virtualness="non_virtual" volatile="no"> <parameters declaration_name="pciReg" type="Register::Ptr" /> </members> <members name="bits" const="no" kind="function" protection="publ +ic" static="no" type="void" virtualness="non_virtual" volatile="no"> <parameters declaration_name="value" type="uint64_t" /> </members> <members name="subBitVector" const="no" kind="function" protecti +on="public" static="no" type="void" virtualness="non_virtual" volatil +e="no"> <parameters declaration_name="value" type="const BitVector &am +p;" /> </members> </public_methods> <enums> <members name="ObjectState" kind="enum" protection="public" stat +ic="no" virtualness="non_virtual"> <values name="NEW"> </values> <values name="REFRESHED"> </values> <values name="DIRTY"> </values> </members> </enums> </classes> END my @list; my $sub = sub {push(@list, shift(@_) . ": " . join(" => ", @_))}; findPath($sub, $xml, "value"); print join("\n", @list), "\n"; } sub findPath { my ($sub, $xmlFrag, $match, @path) = @_; return unless $xmlFrag; if (ref($xmlFrag) =~ /HASH/) { for my $key (sort keys %$xmlFrag) { if ($key !~ /$match/) { findPath($sub, $xmlFrag->{$key}, $match, @path, $key); } else { $sub->($match, @path); } } } elsif (ref($xmlFrag) =~ /ARRAY/) { for my $fragIdx (0 .. $#$xmlFrag) { unless ($xmlFrag->[$fragIdx] =~ /$match/) { findPath($sub, $xmlFrag->[$fragIdx], $match, @path, $fragIdx + 1); } else { $sub->($match, @path); } } } return; }
Back to
Seekers of Perl Wisdom