Top > MyPage
 

moduleの一覧を作るまで

moduleの一覧を作るまで

何が必要か、どのように一覧にするか

必要なもの

  1. 標準モジュールの一覧: 基本的に、標準モジュールはインストールする必要がないので、これらのモジュールは別にする(一応、我々が何を使っているかという資料のため一覧は作る)。したがって、標準モジュールの一覧をファイルで用意して判別する。
  2. プラグマの一覧: これは標準モジュールとは区別されるが、基本的に1同様、我々がインストールで必要なものではない。したがって、これらの一覧ファイルも必要。
  3. 自分たちで作成したモジュール群: もちろん、必要がない。ただしこれは、KML::*、KQ::*というようになっているので、これはファイル等の用意は不要(実際にはKML.pmなどもあった!)。

どのようにインストールすべき一覧を作成するか

  1. 標準モジュール、プラグマの一覧を上記ファイルなどから作成し、自作のモジュールは排除し、そして、それに残ったものを前記標準モジュール・プラグマ一覧の後ろにくっつける。
  2. File::Findを使って、*.pl、*.pm、*.cgiのファイルリストを作成しながら、それらを片っ端からopenしてなめて、m/^\s*use\s+([0-9a-zA-Z_\:\.]+)[\s\;\(]*?/)でひっかったものをハッシュに保存。
  3. すでに、modulesInstall.shにインストールすべきモジュールは書かれているので、それとマージする。

できあがるモジュールリストは

次のような区切り文字を利用して、一覧にする。

-----pragma-----

-----standard-----

上記2つを除いたものが

-----all modules-----

で、さらに、このなかで、modulesInstall.shの中に書いてあるものを除いたもの が(つまり、新たにインストールすべきモジュール一覧)

-----should install-----

というようなリストを作成。ただしファイルはCSVとし、1桁目はモジュール名、もしくは-----pragma-----というような区切り文字。2桁目は、そのモジュールを使っているモジュール名とその行番号の一覧(複数ある場合は|で区切る)とする。「should install」は「all modules」と重複しているので、「should install」には2桁目には書き込まない(無駄だから)。

実装

と、大雑把に計画を立てて、とりあえず実装を始める。

標準モジュールの一覧作成

man perlmodlib

とやると、モジュールの一覧が出るので、このperlmodlib.1というファイルを探し、

man2html.exe perlmodlib.1 > perlmodlib.html

で、htmlファイルにし、これから一覧を作成。ついでに、yamlファイルの方が何かとプログラミングに便利なので、ほんの数行の

while(<>){
   chomp;
   print "  - " . $_ . "\n";
}

を作成して、ちょこちょこっとエディターで編集し完成。実際には「プラグマ」と「標準モジュールの」のそれぞれハッシュに、モジュール名の無名配列をセットするyamlを作成した。

Pragmatic:
  - attributes
  - attrs
  - autouse
  - base
  - bigint
  - bignum
  - bigrat
  - blib
  - bytes
  ......
Standard:
  - AnyDBM_File
  - Attribute::Handlers
  - AutoLoader
  - AutoSplit
  - B
  - B::Asmdata
  - B::Assembler
  - B::Bblock
  - B::Bytecode
  - B::C
  - B::CC
  - B::Concise
  ......

という感じ。

そんでもって、実装

use strict;
use warnings;
use File::Find;
use File::Basename;
use URI::file;
use File::Spec;
use YAML;
my %modules;
my %standards;
my %pragmas;
my @already;
my %should;

###yamlから、プラグマと標準モジュールの一覧を取得
my $list = YAML::LoadFile('/cus/KML/standard.yml');

###標準モジュールの配列のリファレンス
my $standard = $list->{Standard};
###プラグマティックモジュールの配列のリファレンス
my $pragma   = $list->{Pragmatic};

###modulesInstall.shから、すでに記述しているモジュールを取得
open(IN, "</cus/KML/root/schema/memo/modulesInstall.sh")
  or die "no modulesInstall.sh";

while (<IN>) {
  if ($_ =~ m/install (.+)\"/) {
    push @already, $1;
  }
}
close(IN);


####File::Findに渡すアブルーチン
sub mkListModule {
  ###ファイルじゃなければおしまい
  return unless -f;
  ###拡張子が以下の3種じゃなければおしまい
  return unless $File::Find::name =~ /(.*pm$)|(.*pl$)|(.*cgi$)/;
  ###h2xsで(makeしたときに)作成されるものもやめる
  return if $File::Find::name =~ /.*blib.*/;
  ###cpanモジュールを変更したものもやめる
  return if $File::Find::name =~ /.*cpan*/;

  ###分ける必要がなかった!!
  my @extlist = ('\.pm', '\.pl', '\.cgi');
  my ($name, $dir, $ext) = fileparse($File::Find::name, @extlist);
  my $fname = $dir . $name . "$ext";

  ###ファイル毎に全て舐めていく
  my $flag = 1;
  open(IN, $fname);
  my $lineNum = 0;
  while (<IN>) {
    $lineNum++;
#     use base qw(Class::Simple);
#     use lib qw(/cus/KML/lib);
#     use strict;
#     use warnings;
#     use Data::Dumper;
#     use Time::Piece;
#     use Time::Seconds;
#     use Date::Japanese::Era;
#     use KML::Utils::Gengo;
#などをひっかける!
    if ($_ =~ m/^\s*use\s+([0-9a-zA-Z_\:\.]+)[\s\;\(]*?/) {

      ##自分とこのモジュールはスキップ
if ($1 =~ m/(KML\:\:.*)|(KQ\:\:.*)|(DUM\:\:.*)|^KMLDB|^KQDB|^KML|KQ/) {
        next;
      }
      ##use 5.00008;などもスキップ
      if ($1 =~ m/^5[\d\.]+$/) {
        next;
      }

      ##プラグマだったら、%pragmasに入れる。
      ##ついでに、書いてあるファイルと行番号を入れる(以下同様)
      foreach my $p (@$pragma) {
        if ($1 eq $p) {
          push @{ $pragmas{$1} }, "$fname/$lineNum";
          $flag = 0;
        }
      }
      ##プラグマじゃなく、標準モジュールだったら%standardに入れる
      if ($flag) {
        foreach my $s (@$standard) {
          if ($1 eq $s) {
            push @{ $standards{$1} }, "$fname/$lineNum";
            $flag = 0;
          }
        }

      }
      ##上記2つじゃないときに、%modulesに入れる
      if ($flag) {
        push @{ $modules{$1} }, "$fname/$lineNum";
        my $fflag = 1;

        foreach my $a (@already) {
          if ($a eq $1) {
            $fflag = 0;
          }
        }
        if ($fflag) {
          $should{$1} = 1;
        }
        $fflag = 1;
      }
      $flag = 1;
    }
  }
  close(IN);
}

my $callBack = \&mkListModule;

##2つのディレクトリーをなめる
find($callBack, "/cus/KML");
find($callBack, "/cus/KQ");


##あとは標準出力に出力

foreach my $f (sort keys %modules) {
  print $f , ",", join('|', @{ $modules{$f} }), "\n";
}

print "-----pragma-----\n";
foreach my $f (sort keys %pragmas) {
  print $f , ",", join('|', @{ $pragmas{$f} }), "\n";
}

print "-----standard-----\n";
foreach my $f (sort keys %standards) {
  print $f , ",", join('|', @{ $standards{$f} }), "\n";
}

print "-----should install-----\n";

foreach my $f (sort keys %should) {
  print $f . "\n";
}

[2007-02-04 10:43]