1000:1234:abcd:2000::/120のような省略されたIPv6のアドレスを展開して
リストに格納したいのですが、プレフィックス長(=120)に応じて
展開する部分が一部不完全なので教えてください。
下のコードだと、下4桁の連番生成しかできない上に、プレフィックス長が4の倍数でない場合にうまくいきません。
これを4の倍数でなくても&下4桁以上もちゃんと展開できるようにしたいのですが…。
たとえば、1000:1234:abcd:2000::/127であれば、
1000:1234:abcd:2000:0000:0000:0000:0000
1000:1234:abcd:2000:0000:0000:0000:0001
の二つが出来てほしいのです。
できれば10進数で連番作ったものを16進数変換してる部分もなんとかしたいんですけど…。

sub _Gen{
  my ($addr, $pref) = split(m|/|, $_[0]);
  $addr = &_Format($addr); # ここで省略のない32桁の英数字を4桁ごとに:で区切ったものになる
  $addr =~ s/://g;
  if($pref % 4 != 0 || $pref < 112 || $pref > 128){
    return;
  }elsif($pref == 128){
    1 while $addr =~ s/(\w+)(\w\w\w\w)/$1:$2/;
    return $addr;
  }
  my $fixed = substr($addr, 0, $pref / 4);
  my $keta = (128 - $pref) / 4;
  my (@addrs, $tmp);
  for(my $i=0; $i<16**$keta; $i++){
    $tmp = sprintf("$fixed%0${keta}x", $i);
    1 while $tmp =~ s/(\w+)(\w\w\w\w)/$1:$2/;
    push(@addrs, $tmp);
  }
  return @addrs;
}