1#!/usr/bin/perl -w
2
3use strict;
4use warnings;
5use bigint;
6use DBI;
7use Data::Dumper;
8
9
10my $project = shift;
11my $warns = shift;
12my $db_file = shift;
13my $db = DBI->connect("dbi:SQLite:$db_file", "", "", {AutoCommit => 0});
14
15sub 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
48sub 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
96sub print_num($)
97{
98    my $num = shift;
99
100    if ($num < 0) {
101        return "(" . $num . ")";
102    } else {
103        return $num;
104    }
105}
106
107sub 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
118sub 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
148my ($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 = "";
155while (@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}
190if ($skip == 0) {
191    print_info($cur_type, $union_array);
192}
193
194$db->commit();
195$db->disconnect();
196