1 # Copyright 2012, INRIA
2 # Julia Lawall, Gilles Muller
3 # Copyright 2010-2011, INRIA, University of Copenhagen
4 # Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
5 # Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
6 # Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
7 # This file is part of Coccinelle.
9 # Coccinelle is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, according to version 2 of the License.
13 # Coccinelle is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
21 # The authors reserve the right to distribute this or future versions of
22 # Coccinelle under other licenses.
28 sub pr2
{ print "$_[0]\n"; }
29 sub mylog
{ print @_;}
32 # to be launched from the git directory
33 die "usage: $0 commithashafter [commithashbefore]"
34 if(@ARGV <= 0 || @ARGV >= 3);
36 # update: now I also extract the headers files, the one
37 # that were modified in the commit and the one that are
38 # locally used and that may contain useful type information
41 # update: now I also extract some include/linux/header.h files, the
42 # one having the same name of one of the driver.
44 my $target_dir = "/tmp/extract_c_and_res/$ARGV[0]";
45 `mkdir -p $target_dir`;
46 my $old_dir = "/tmp/extract_c_and_res/$ARGV[0]_old";
48 my $new_dir = "/tmp/extract_c_and_res/$ARGV[0]_new";
51 my $commit_new = $ARGV[0];
52 my $commit_old = $ARGV[1] || "$commit_new^"; # default parent
54 my $gitfile = "$target_dir/$commit_new.gitinfo";
55 my $makefile = "$target_dir/Makefile";
57 `git show $commit_new > $gitfile `;
60 # processing the patch
64 my @driverheaders_in_include = ();
67 open FILE
, "$gitfile" or die "$!";
70 # allow other dir ? # fs|mm there is drivers under arch/ too
71 if(/^diff --git a\/((drivers
|sound
)\
/.*?\.[ch]) b/){
78 elsif(/^diff --git a\/(include\
/.*?\.h) b/) {
79 mylog
"potential header driver $1\n";
80 push @driverheaders_in_include, $1;
82 elsif(/^diff --git a\//) {
83 mylog
" not driver:$_";
86 die "PB: strange diff line: $_";
90 # extracting the .c and .h of the patch
94 # to be able to later find the corresponding local included header file
95 my $kerneldir_of_file = {};
100 foreach my $f (@files) {
101 my ($base) = `basename $f`;
104 if($base =~ /\.c$/) {
105 $res =~ s/\.c$/.res/;
107 if($base =~ /\.h$/) {
108 $res =~ s/\.h$/.h.res/;
111 pr2
"processing: $f $base $res";
112 if(-e
"$target_dir/$base") {
114 $base = "${counter}_$base";
115 $res = "${counter}_$res";
116 pr2
"try transform one file because already exist: $base";
117 if($base =~ /\.h$/) {
118 die "PB: Two header files share the same name: $base.";
122 die "PB: one of the file already exist: $base" if (-e
"$target_dir/$base");
124 `git cat-file blob $commit_old:$f > $target_dir/$base`;
125 `git cat-file blob $commit_new:$f > $target_dir/$res`;
127 `git cat-file blob $commit_old:$f > $old_dir/$base`;
128 `git cat-file blob $commit_new:$f > $new_dir/$base`;
130 $kerneldir_of_file->{$base} = `dirname $f`;
131 chomp $kerneldir_of_file->{$base};
133 push @finalcfiles, $base;
134 $finalcfiles->{$base} = 1;
141 open MAKE
, ">$makefile" or die "$!";
142 print MAKE
"CEDESCRIPTION=\"\"\n";
143 print MAKE
"SP=foo.cocci\n";
144 print MAKE
"SOURCES = ";
145 my $last = shift @finalcfiles;
146 foreach my $f (@finalcfiles) {
147 print MAKE
"$f \\\n\t";
149 print MAKE
"$last\n";
154 include \$(TOP)/generic_makefile
159 # process potential driver headers of include/
161 foreach my $f (@driverheaders_in_include) {
162 my $base = `basename $f`;
166 } else { die "PB: internal error"; }
169 # julia want all .h that were in the patch, not just the headers
170 # of our heuristic. Hence the comment.
173 # if(defined($finalcfiles->{$base})) {
175 # pr2 "found header of driver in include/: $f of $base";
176 my $dir = `dirname $f`;
178 `mkdir -p $target_dir/$dir`;
179 `git cat-file blob $commit_old:$f > $target_dir/$f`;
180 `git cat-file blob $commit_new:$f > $target_dir/$f.res`;
182 `mkdir -p $old_dir/$dir`;
183 `mkdir -p $new_dir/$dir`;
184 `git cat-file blob $commit_old:$f > $old_dir/$f`;
185 `git cat-file blob $commit_new:$f > $new_dir/$f`;
190 # compute other linux headers not in the patch
192 my @linuxheaders = `cd $target_dir; grep -E \"#include +\<[^>]*\>\" *.c *.h`;
193 foreach my $line (@linuxheaders) {
196 if($line =~ /^(.*)?:#include *\<([^>]*)\>/) {
197 my ($_file, $f) = ($1, $2);
199 my $base = `basename $f`;
203 } else { die "PB: internal error"; }
205 if(defined($finalcfiles->{$base}) && ! -e
"$target_dir/include/$f") {
206 pr2
"found header of driver in include/: $f of $base";
207 my $dir = `dirname $f`;
209 `mkdir -p $target_dir/include/$dir`;
210 `git cat-file blob $commit_old:include/$f > $target_dir/include/$f`;
212 } else { pr2
"pb regexp: $line"; }
216 # compute other local headers not in the patch
218 my @headers = `cd $target_dir; grep -E \"#include +\\".*\\"\" *.c *.h`;
221 foreach my $line (@headers) {
224 if($line =~ /^(.*)?:#include *"(.*)"/) {
226 my ($file, $header) = ($1, $2);
227 my $dir = $kerneldir_of_file->{$file};
229 my $fullheader = "$dir/$header";
232 if($files->{$fullheader}) {
233 pr2
"INFO: $fullheader was already in commit";
235 $hfiles->{$fullheader} = 1;
238 } else { pr2
"pb regexp: $line"; }
242 foreach my $h (keys %{$hfiles}) {
243 my ($base) = `basename $h`;
245 pr2
"processing additionnal header file: $h $base";
247 if(-e
"$target_dir/$base") {
248 pr2
"-------------------------------------";
249 pr2
"PB: local header (not modified in the git) $base already exists";
250 pr2
"BUT I CONTINUE, but may have more .failed in the end";
251 pr2
"-------------------------------------";
253 `git cat-file blob $commit_old:$h > $target_dir/$base`;