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