четверг, 12 августа 2010 г.

скрипт для подсчета частоты импортированных символов

таки пришлось сегодня самому писать
берет на входе 1 или больше файлов, произведенных dumpbin /imports (я использовал от visual c++ 2008 - возможно для других версий формат выходного файла поменялся и нужно поправить функцию parse_file) и выдает на выходе статистику


#!/usr/bin/perl -w
# Simple script for calculating import symbols frequency
# 12 Aug 2010 (C) RedPlait
use strict;
use warnings;

# data for imports data storing:
#  hash with lowercased module name as key
#   and ref to hash as value
#     where this hash has function names as key and imports count as value
sub parse_file
{
  my($fname, $href) = @_;
  if ( !open(FILE, '<', $fname) )
  {
    warn("Cannot open $fname");
    return;
  }
  my($str, $state, $mod_name, $func_name, $processed, $current_mod);
  $processed = 0;
  $state = 0;
  while( $str = <FILE> )
  {
    chomp $str;
    # stop on Summary string
    last if ( $str =~ /^  Summary/ );
    # check if we have some section with import
    if ( $str =~ /^  Section contains the following imports/ )
    {
      $state = 1;
      next;
    }
    # check for imported module name
    if ( $state == 1 && $str =~ /^    (\w.*)$/ )
    {
      $mod_name = lc($1);
      if ( exists $href->{$mod_name} )
      {
        $current_mod = $href->{$mod_name};
      } else {
        $current_mod = {};
        $href->{$mod_name} = $current_mod;
      }
      $state = 2;
      next;
    }
    # check for start of imported functions
    if ( $state == 2 && $str =~ /Index of first forwarder reference$/ )
    {
      # skip empty string
      $str = <FILE>;
      $state = 3;
      next;
    }
    if ( $state == 3 )
    {
      if ( $str eq '' )
      {
        $state = 1;
        next;
      }
      ($func_name) = (split /\s+/, $str)[2];
      if ( ! defined $func_name )
      {
        $state = 0;
        next;
      }
      $current_mod->{$func_name}++;
      $processed++;
    }
  }
  close FILE;
  return $processed;
}

sub dump_freq_sorted
{
  my($href, $out_f) = @_;
  my($iter, $mod_name, @tmp);
  foreach $mod_name (sort keys %$href)
  {
    push @tmp, 
      map { [ $mod_name, $_, $href->{$mod_name}->{$_} ] } 
        keys %{ $href->{$mod_name} };
  }
  # now in each item from @tmp is ref to array where 
  # located module_name, function_name and import_count
  foreach $iter ( sort { $b->[2] <=> $a->[2] ||
                         $a->[0] cmp $b->[0] ||
                         $a->[1] cmp $b->[1]
                       } @tmp )
  {
    printf($out_f "%s!%s: %d\n", (@$iter)[0..2]);
  }
}

# MAIN
my %db;
parse_file($_, \%db) foreach @ARGV;
dump_freq_sorted(\%db, \*STDOUT);

Комментариев нет:

Отправить комментарий