helper: fix segfault parsing invalid code
[smatch.git] / smatch_data / db / fill_db_type_size.pl
blob812e05390ebc6c4c53db760afd3b7d491492c3b8
1 #!/usr/bin/perl -w
3 use strict;
4 use warnings;
5 use bigint;
6 use DBI;
7 use Data::Dumper;
9 my $project = shift;
10 my $warns = shift;
11 my $db_file = shift;
12 my $db = DBI->connect("dbi:SQLite:$db_file", "", "", {AutoCommit => 0});
14 my $raw_line;
16 sub text_to_int($)
18 my $text = shift;
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;
39 if ($text =~ /\((.*?)\)/) {
40 $text = $1;
42 if (!($text =~ /^[-0123456789]/)) {
43 return "NaN";
46 return int($text);
49 sub add_range($$$)
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;
59 $range{min} = $min;
60 $range{max} = $max;
62 foreach my $tmp (@$union) {
63 if ($added) {
64 push @return_union, $tmp;
65 next;
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;
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};
85 } else {
86 push @return_union, $tmp;
90 if (!$added) {
91 push @return_union, \%range;
94 return \@return_union;
97 sub print_num($)
99 my $num = shift;
101 if ($num < 0) {
102 return "(" . $num . ")";
103 } else {
104 return $num;
108 sub print_range($)
110 my $range = shift;
112 if ($range->{min} == $range->{max}) {
113 return print_num($range->{min});
114 } else {
115 return print_num($range->{min}) . "-" . print_num($range->{max});
119 sub print_info($$)
121 my $type = shift;
122 my $union = shift;
123 my $printed_range = "";
124 my $i = 0;
126 foreach my $range (@$union) {
127 if ($i) {
128 $printed_range = $printed_range . ",";
130 $i++;
131 $printed_range = $printed_range . print_range($range);
133 my $sql = "insert into type_size values ('$type', '$printed_range');";
134 $db->do($sql);
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");
144 my ($sth, @row, $cur_type, $type, @ranges, $range_txt, %range, $min, $max, $union_array, $skip);
146 $sth = $db->prepare('select * from function_type_size order by type');
147 $sth->execute();
149 $skip = 0;
150 $cur_type = "";
151 while (@row = $sth->fetchrow_array()) {
152 $raw_line = join ',', @row;
154 $type = $row[2];
156 if ($cur_type ne "$type") {
157 if ($cur_type ne "" && $skip == 0) {
158 print_info($cur_type, $union_array);
160 $cur_type = $type;
161 $union_array = ();
162 $skip = 0;
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;
174 if ($min =~ /NaN/ || $max =~ /NaN/) {
175 $skip = 1;
177 $union_array = add_range($union_array, $min, $max);
180 if ($skip == 0) {
181 print_info($cur_type, $union_array);
184 $db->commit();
185 $db->disconnect();