Commit | Line | Data |
---|---|---|
34e49164 C |
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 | } |