[7c3008e] | 1 | #!/usr/bin/perl |
---|
| 2 | |
---|
| 3 | use strict; |
---|
| 4 | |
---|
| 5 | use XML::Parser; |
---|
| 6 | use IO::File; |
---|
| 7 | use IO::Pipe; |
---|
| 8 | |
---|
| 9 | sub genviz { |
---|
| 10 | my($file, $outfile)= @_; |
---|
| 11 | my %nodes; |
---|
| 12 | my $chars; |
---|
| 13 | my $in_node; |
---|
| 14 | my $in_lan; |
---|
| 15 | my $lan; |
---|
| 16 | my %links; |
---|
| 17 | my %lans; |
---|
| 18 | my $rv; |
---|
| 19 | my $dotfile = "/tmp/split$$.dot"; |
---|
| 20 | my $neato = "/usr/local/bin/neato"; |
---|
| 21 | my $g = new IO::File(">$dotfile") || return; |
---|
| 22 | my $p = new IO::Pipe() || return; |
---|
| 23 | my $out = new IO::File(">$outfile"); |
---|
| 24 | |
---|
| 25 | sub start_element { |
---|
| 26 | my($expat, $element) = @_; |
---|
| 27 | $in_node++ if $element eq "node"; |
---|
| 28 | if ( $element eq "lan" ) { |
---|
| 29 | $in_lan++; |
---|
| 30 | $lan = {}; |
---|
| 31 | } |
---|
| 32 | } |
---|
| 33 | |
---|
| 34 | sub end_element { |
---|
| 35 | my($expat, $element) = @_; |
---|
| 36 | |
---|
| 37 | $in_node = 0 if $element eq "node"; |
---|
| 38 | $nodes{$chars} = "node" if $in_node && $element eq "vname"; |
---|
| 39 | if ($in_lan) { |
---|
| 40 | if ( $element ne "lan") { |
---|
| 41 | $lan->{$element} = $chars if $element =~/(vname|vnode)/; |
---|
| 42 | } |
---|
| 43 | else { |
---|
| 44 | $in_lan = 0; |
---|
| 45 | my $vname = $lan->{'vname'}; |
---|
| 46 | if ( $links{$vname} && @{$links{$vname}} ==2 ) { |
---|
| 47 | # this link needs to be a lan |
---|
| 48 | $nodes{$vname} = "lan"; |
---|
| 49 | $lans{$lan->{'vname'}} = (); |
---|
| 50 | foreach my $l (@{$links{$vname}}) { |
---|
| 51 | push(@{$lans{$vname}}, $l); |
---|
| 52 | } |
---|
| 53 | push(@{$lans{$vname}}, $lan->{'vnode'}); |
---|
| 54 | $links{$vname} = (); |
---|
| 55 | $lan={}; |
---|
| 56 | return; |
---|
| 57 | } |
---|
| 58 | if ( $lans{$vname} && @{$lans{$vname}}) { |
---|
| 59 | push(@{$lans{$vname}}, $lan->{'vnode'}); |
---|
| 60 | $lan = {}; |
---|
| 61 | return; |
---|
| 62 | } |
---|
| 63 | $links{$vname} = () unless $links{$vname}; |
---|
| 64 | push(@{$links{$vname}}, $lan->{'vnode'}); |
---|
| 65 | $lan = {}; |
---|
| 66 | return; |
---|
| 67 | } |
---|
| 68 | } |
---|
| 69 | } |
---|
| 70 | sub found_chars { |
---|
| 71 | my($expat, $data) = @_; |
---|
| 72 | $chars = $data; |
---|
| 73 | } |
---|
| 74 | |
---|
| 75 | my $parser = new XML::Parser(Handlers => { |
---|
| 76 | Start => \&start_element, |
---|
| 77 | End => \&end_element, |
---|
| 78 | Char => \&found_chars |
---|
| 79 | }); |
---|
| 80 | |
---|
| 81 | print "$file\n"; |
---|
| 82 | $parser->parsefile($file); |
---|
| 83 | |
---|
| 84 | print $g "graph G {\n"; |
---|
| 85 | foreach my $n (keys %nodes) { |
---|
| 86 | print $g "\t$n\n"; |
---|
| 87 | } |
---|
| 88 | foreach my $l (keys %links) { |
---|
| 89 | print $g "\t", join(" -- ", @{$links{$l}}), "\n"; |
---|
| 90 | } |
---|
| 91 | foreach my $l (keys %lans) { |
---|
| 92 | foreach my $n (@{$lans{$l}}) { |
---|
| 93 | print $g "\t $n -- $l\n"; |
---|
| 94 | } |
---|
| 95 | } |
---|
| 96 | print $g "}\n"; |
---|
| 97 | $g->close(); |
---|
| 98 | $p->reader("$neato -Gstart=rand -Gepsilon=0.005 -Gmaxiter=20000 " . |
---|
| 99 | "-Gpack=true $dotfile"); |
---|
| 100 | print $out "<vis>\n"; |
---|
| 101 | while (<$p>) { |
---|
| 102 | /^\s*(\w+)\s+\[.*pos=\"(\d+),(\d+)\"/ && do { |
---|
| 103 | my ($n, $x, $y) = ($1, $2, $3); |
---|
| 104 | |
---|
| 105 | print "<node><name>$n</name><x>$x</x><y>$y</y><type>$nodes{$n}". |
---|
| 106 | "</type></node>\n" if $nodes{$n}; |
---|
| 107 | }; |
---|
| 108 | } |
---|
| 109 | print $out "</vis>\n"; |
---|
| 110 | $p->close(); |
---|
| 111 | unlink("$dotfile"); |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | genviz($ARGV[0], $ARGV[1]); |
---|