helper: fix segfault parsing invalid code
[smatch.git] / smatch_data / db / fill_db_type_value.pl
blob24753de10a60bfdd4e69e2ade1738896ddb77c07
1 #!/usr/bin/perl -w
3 use strict;
4 use warnings;
5 use bigint;
6 use DBI;
7 use Data::Dumper;
10 my $project = shift;
11 my $warns = shift;
12 my $db_file = shift;
13 my $db = DBI->connect("dbi:SQLite:$db_file", "", "", {AutoCommit => 0});
15 sub text_to_int($)
17 my $text = shift;
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;
38 if ($text =~ /\((.*?)\)/) {
39 $text = $1;
41 if (!($text =~ /^[-0123456789]/)) {
42 return "NaN";
45 return int($text);
48 sub add_range($$$)
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;
58 $range{min} = $min;
59 $range{max} = $max;
61 foreach my $tmp (@$union) {
62 if ($added) {
63 push @return_union, $tmp;
64 next;
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;
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};
84 } else {
85 push @return_union, $tmp;
89 if (!$added) {
90 push @return_union, \%range;
93 return \@return_union;
96 sub print_num($)
98 my $num = shift;
100 if ($num < 0) {
101 return "(" . $num . ")";
102 } else {
103 return $num;
107 sub print_range($)
109 my $range = shift;
111 if ($range->{min} == $range->{max}) {
112 return print_num($range->{min});
113 } else {
114 return print_num($range->{min}) . "-" . print_num($range->{max});
118 sub print_info($$)
120 my $type = shift;
121 my $union = shift;
122 my $printed_range = "";
123 my $i = 0;
125 if ($#$union > 100) {
126 print "$type " . scalar @$union . "\n";
127 return;
130 foreach my $range (@$union) {
131 if ($i) {
132 $printed_range = $printed_range . ",";
134 $i++;
135 $printed_range = $printed_range . print_range($range);
137 my $sql = "insert into type_value values ('$type', '$printed_range');";
138 $db->do($sql);
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");
148 my ($sth, @row, $cur_type, $type, @ranges, $range_txt, %range, $min, $max, $union_array, $skip);
150 $sth = $db->prepare('select type, value from function_type_value order by type');
151 $sth->execute();
153 $skip = 0;
154 $cur_type = "";
155 while (@row = $sth->fetchrow_array()) {
156 $type = $row[0];
158 if ($cur_type ne "$type") {
159 if ($cur_type ne "" && $skip == 0) {
160 print_info($cur_type, $union_array);
162 $cur_type = $type;
163 $union_array = ();
164 $skip = 0;
167 if ($skip == 1) {
168 next;
171 @ranges = split(/,/, $row[1]);
172 foreach $range_txt (@ranges) {
173 if ($range_txt =~ /ignore/) {
174 next;
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;
183 if ($min =~ /NaN/ || $max =~ /NaN/) {
184 $skip = 1;
185 last;
187 $union_array = add_range($union_array, $min, $max);
190 if ($skip == 0) {
191 print_info($cur_type, $union_array);
194 $db->commit();
195 $db->disconnect();