1 #!/usr/bin/perl -w
   2 
   3 use strict;
   4 use warnings;
   5 use bigint;
   6 use DBI;
   7 use Data::Dumper;
   8 
   9 
  10 my $project = shift;
  11 my $warns = shift;
  12 my $db_file = shift;
  13 my $db = DBI->connect("dbi:SQLite:$db_file", "", "", {AutoCommit => 0});
  14 
  15 sub text_to_int($)
  16 {
  17     my $text = shift;
  18 
  19     if ($text =~ /s64min/) {
  20         return -(2**63);
  21     } elsif ($text =~/s32min/) {
  22         return -(2**31);
  23     } elsif ($text =~ /s16min/) {
  24         return -(2**15);
  25     } elsif ($text =~ /s64max/) {
  26         return 2**63 - 1;
  27     } elsif ($text =~ /s32max/) {
  28         return 2**31 - 1;
  29     } elsif ($text =~ /s16max/) {
  30         return 2**15 - 1;
  31     } elsif ($text =~ /u64max/) {
  32         return 2**64 - 1;
  33     } elsif ($text =~ /u32max/) {
  34         return 2**32 - 1;
  35     } elsif ($text =~ /u16max/) {
  36         return 2**16 - 1;
  37     }
  38     if ($text =~ /\((.*?)\)/) {
  39         $text = $1;
  40     }
  41     if (!($text =~ /^[-0123456789]/)) {
  42         return "NaN";
  43     }
  44 
  45     return int($text);
  46 }
  47 
  48 sub add_range($$$)
  49 {
  50     my $union = shift;
  51     my $min = shift;
  52     my $max = shift;
  53     my %range;
  54     my @return_union;
  55     my $added = 0;
  56     my $check_next = 0;
  57 
  58     $range{min} = $min;
  59     $range{max} = $max;
  60 
  61     foreach my $tmp (@$union) {
  62         if ($added) {
  63             push @return_union, $tmp;
  64             next;
  65         }
  66 
  67         if ($range{max} < $tmp->{min}) {
  68             push @return_union, \%range;
  69             push @return_union, $tmp;
  70             $added = 1;
  71         } elsif ($range{min} <= $tmp->{min}) {
  72             if ($range{max} <= $tmp->{max}) {
  73                 $range{max} = $tmp->{max};
  74                 push @return_union, \%range;
  75                 $added = 1;
  76             }
  77         } elsif ($range{min} <= $tmp->{max}) {
  78             if ($range{max} <= $tmp->{max}) {
  79                 push @return_union, $tmp;
  80                 $added = 1;
  81             } else {
  82                 $range{min} = $tmp->{min};
  83             }
  84         } else {
  85             push @return_union, $tmp;
  86         }
  87     }
  88 
  89     if (!$added) {
  90         push @return_union, \%range;
  91     }
  92 
  93     return \@return_union;
  94 }
  95 
  96 sub print_num($)
  97 {
  98     my $num = shift;
  99 
 100     if ($num < 0) {
 101         return "(" . $num . ")";
 102     } else {
 103         return $num;
 104     }
 105 }
 106 
 107 sub print_range($)
 108 {
 109     my $range = shift;
 110 
 111     if ($range->{min} == $range->{max}) {
 112         return print_num($range->{min});
 113     } else {
 114         return print_num($range->{min}) . "-" .  print_num($range->{max});
 115     }
 116 }
 117 
 118 sub print_info($$)
 119 {
 120     my $type = shift;
 121     my $union = shift;
 122     my $printed_range = "";
 123     my $i = 0;
 124 
 125     if ($#$union > 100) {
 126         print "$type " . scalar @$union . "\n";
 127         return;
 128     }
 129 
 130     foreach my $range (@$union) {
 131         if ($i) {
 132             $printed_range = $printed_range . ",";
 133         }
 134         $i++;
 135         $printed_range = $printed_range . print_range($range);
 136     }
 137     my $sql = "insert into type_value values ('$type', '$printed_range');";
 138     $db->do($sql);
 139 }
 140 
 141 
 142 $db->do("PRAGMA cache_size = 800000");
 143 $db->do("PRAGMA journal_mode = OFF");
 144 $db->do("PRAGMA count_changes = OFF");
 145 $db->do("PRAGMA temp_store = MEMORY");
 146 $db->do("PRAGMA locking = EXCLUSIVE");
 147 
 148 my ($sth, @row, $cur_type, $type, @ranges, $range_txt, %range, $min, $max, $union_array, $skip);
 149 
 150 $sth = $db->prepare('select type, value from function_type_value order by type');
 151 $sth->execute();
 152 
 153 $skip = 0;
 154 $cur_type = "";
 155 while (@row = $sth->fetchrow_array()) {
 156     $type = $row[0];
 157 
 158     if ($cur_type ne "$type") {
 159         if ($cur_type ne "" && $skip == 0) {
 160             print_info($cur_type, $union_array);
 161         }
 162         $cur_type = $type;
 163         $union_array = ();
 164         $skip = 0;
 165     }
 166 
 167     if ($skip == 1) {
 168         next;
 169     }
 170 
 171     @ranges = split(/,/, $row[1]);
 172     foreach $range_txt (@ranges) {
 173         if ($range_txt =~ /ignore/) {
 174             next;
 175         }
 176         if ($range_txt =~ /(.*[^(])-(.*)/) {
 177             $min = text_to_int($1);
 178             $max = text_to_int($2);
 179         } else {
 180             $min = text_to_int($range_txt);
 181             $max = $min;
 182         }
 183         if ($min =~ /NaN/ || $max =~ /NaN/) {
 184             $skip = 1;
 185             last;
 186         }
 187         $union_array = add_range($union_array, $min, $max);
 188     }
 189 }
 190 if ($skip == 0) {
 191     print_info($cur_type, $union_array);
 192 }
 193 
 194 $db->commit();
 195 $db->disconnect();