Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / scripts / extract_c_and_res.pl
1 #!/usr/bin/perl -w
2 use strict;
3
4 sub pr2 { print "$_[0]\n"; }
5 sub mylog { print @_;}
6
7
8 # to be launched from the git directory
9 die "usage: $0 commithashafter [commithashbefore]"
10 if(@ARGV <= 0 || @ARGV >= 3);
11
12 # update: now I also extract the headers files, the one
13 # that were modified in the commit and the one that are
14 # locally used and that may contain useful type information
15 # for spatch.
16
17 # update: now I also extract some include/linux/header.h files, the
18 # one having the same name of one of the driver.
19
20 my $target_dir = "/tmp/extract_c_and_res/$ARGV[0]";
21 `mkdir -p $target_dir`;
22 my $old_dir = "/tmp/extract_c_and_res/$ARGV[0]_old";
23 `mkdir -p $old_dir`;
24 my $new_dir = "/tmp/extract_c_and_res/$ARGV[0]_new";
25 `mkdir -p $new_dir`;
26
27 my $commit_new = $ARGV[0];
28 my $commit_old = $ARGV[1] || "$commit_new^"; # default parent
29
30 my $gitfile = "$target_dir/$commit_new.gitinfo";
31 my $makefile = "$target_dir/Makefile";
32
33 `git show $commit_new > $gitfile `;
34
35
36 # processing the patch
37
38 my @files = ();
39 my $files = {};
40 my @driverheaders_in_include = ();
41
42
43 open FILE, "$gitfile" or die "$!";
44 while(<FILE>) {
45
46 # allow other dir ? # fs|mm there is drivers under arch/ too
47 if(/^diff --git a\/((drivers|sound)\/.*?\.[ch]) b/){
48 mylog " $1\n";
49
50 push @files, $1;
51 $files->{$1} = 1;
52
53 }
54 elsif(/^diff --git a\/(include\/.*?\.h) b/) {
55 mylog "potential header driver $1\n";
56 push @driverheaders_in_include, $1;
57 }
58 elsif(/^diff --git a\//) {
59 mylog " not driver:$_";
60 }
61 elsif(/^diff/) {
62 die "PB: strange diff line: $_";
63 }
64 }
65
66 # extracting the .c and .h of the patch
67
68 my $counter=0;
69
70 # to be able to later find the corresponding local included header file
71 my $kerneldir_of_file = {};
72
73 my @finalcfiles = ();
74 my $finalcfiles = {};
75
76 foreach my $f (@files) {
77 my ($base) = `basename $f`;
78 chomp $base;
79 my $res = $base;
80 if($base =~ /\.c$/) {
81 $res =~ s/\.c$/.res/;
82 }
83 if($base =~ /\.h$/) {
84 $res =~ s/\.h$/.h.res/;
85 }
86
87 pr2 "processing: $f $base $res";
88 if(-e "$target_dir/$base") {
89 $counter++;
90 $base = "${counter}_$base";
91 $res = "${counter}_$res";
92 pr2 "try transform one file because already exist: $base";
93 if($base =~ /\.h$/) {
94 die "PB: Two header files share the same name: $base.";
95 }
96
97 }
98 die "PB: one of the file already exist: $base" if (-e "$target_dir/$base");
99
100 `git-cat-file blob $commit_old:$f > $target_dir/$base`;
101 `git-cat-file blob $commit_new:$f > $target_dir/$res`;
102
103 `git-cat-file blob $commit_old:$f > $old_dir/$base`;
104 `git-cat-file blob $commit_new:$f > $new_dir/$base`;
105
106 $kerneldir_of_file->{$base} = `dirname $f`;
107 chomp $kerneldir_of_file->{$base};
108
109 push @finalcfiles, $base;
110 $finalcfiles->{$base} = 1;
111
112
113 }
114
115 # generate Makefile
116
117 open MAKE, ">$makefile" or die "$!";
118 print MAKE "CEDESCRIPTION=\"\"\n";
119 print MAKE "SP=foo.cocci\n";
120 print MAKE "SOURCES = ";
121 my $last = shift @finalcfiles;
122 foreach my $f (@finalcfiles) {
123 print MAKE "$f \\\n\t";
124 }
125 print MAKE "$last\n";
126
127 print MAKE "
128
129 TOP=../..
130 include \$(TOP)/generic_makefile
131 ";
132
133
134
135 # process potential driver headers of include/
136
137 foreach my $f (@driverheaders_in_include) {
138 my $base = `basename $f`;
139 chomp $base;
140 if($base =~ /.h$/) {
141 $base =~ s/.h$/.c/;
142 } else { die "PB: internal error"; }
143
144
145 # julia want all .h that were in the patch, not just the headers
146 # of our heuristic. Hence the comment.
147
148 # pr2 "$f $base";
149 # if(defined($finalcfiles->{$base})) {
150 {
151 # pr2 "found header of driver in include/: $f of $base";
152 my $dir = `dirname $f`;
153 chomp $dir;
154 `mkdir -p $target_dir/$dir`;
155 `git-cat-file blob $commit_old:$f > $target_dir/$f`;
156 `git-cat-file blob $commit_new:$f > $target_dir/$f.res`;
157
158 `mkdir -p $old_dir/$dir`;
159 `mkdir -p $new_dir/$dir`;
160 `git-cat-file blob $commit_old:$f > $old_dir/$f`;
161 `git-cat-file blob $commit_new:$f > $new_dir/$f`;
162
163 }
164 }
165
166 # compute other linux headers not in the patch
167
168 my @linuxheaders = `cd $target_dir; grep -E \"#include +\<[^>]*\>\" *.c *.h`;
169 foreach my $line (@linuxheaders) {
170 chomp $line;
171 #pr2 ($line);
172 if($line =~ /^(.*)?:#include *\<([^>]*)\>/) {
173 my ($_file, $f) = ($1, $2);
174
175 my $base = `basename $f`;
176 chomp $base;
177 if($base =~ /.h$/) {
178 $base =~ s/.h$/.c/;
179 } else { die "PB: internal error"; }
180
181 if(defined($finalcfiles->{$base}) && ! -e "$target_dir/include/$f") {
182 pr2 "found header of driver in include/: $f of $base";
183 my $dir = `dirname $f`;
184 chomp $dir;
185 `mkdir -p $target_dir/include/$dir`;
186 `git-cat-file blob $commit_old:include/$f > $target_dir/include/$f`;
187 }
188 } else { pr2 "pb regexp: $line"; }
189 }
190
191
192 # compute other local headers not in the patch
193
194 my @headers = `cd $target_dir; grep -E \"#include +\\".*\\"\" *.c *.h`;
195
196 my $hfiles = {};
197 foreach my $line (@headers) {
198 chomp $line;
199 #pr2 ($line);
200 if($line =~ /^(.*)?:#include *"(.*)"/) {
201
202 my ($file, $header) = ($1, $2);
203 my $dir = $kerneldir_of_file->{$file};
204
205 my $fullheader = "$dir/$header";
206 #pr2 ($fullheader);
207
208 if($files->{$fullheader}) {
209 pr2 "INFO: $fullheader was already in commit";
210 } else {
211 $hfiles->{$fullheader} = 1;
212 }
213
214 } else { pr2 "pb regexp: $line"; }
215
216 }
217
218 foreach my $h (keys %{$hfiles}) {
219 my ($base) = `basename $h`;
220 chomp $base;
221 pr2 "processing additionnal header file: $h $base";
222
223 if(-e "$target_dir/$base") {
224 pr2 "-------------------------------------";
225 pr2 "PB: local header (not modified in the git) $base already exists";
226 pr2 "BUT I CONTINUE, but may have more .failed in the end";
227 pr2 "-------------------------------------";
228 } else {
229 `git-cat-file blob $commit_old:$h > $target_dir/$base`;
230 }
231 }