Mercurial > hg > CbC > CbC_gcc
comparison contrib/legacy/mklog.pl @ 152:2b5abeee2509
update gcc11
author | anatofuz |
---|---|
date | Mon, 25 May 2020 07:50:57 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
145:1830386684a0 | 152:2b5abeee2509 |
---|---|
1 #!/usr/bin/perl | |
2 # Copyright (C) 2012-2017 Free Software Foundation, Inc. | |
3 # | |
4 # This file is part of GCC. | |
5 # | |
6 # GCC is free software; you can redistribute it and/or modify | |
7 # it under the terms of the GNU General Public License as published by | |
8 # the Free Software Foundation; either version 3, or (at your option) | |
9 # any later version. | |
10 # | |
11 # GCC is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU General Public License for more details. | |
15 # | |
16 # You should have received a copy of the GNU General Public License | |
17 # along with GCC; see the file COPYING. If not, write to | |
18 # the Free Software Foundation, 51 Franklin Street, Fifth Floor, | |
19 # Boston, MA 02110-1301, USA. | |
20 | |
21 # This script parses a .diff file generated with 'diff -up' or 'diff -cp' | |
22 # and adds a skeleton ChangeLog file to the file. It does not try to be | |
23 # very smart when parsing function names, but it produces a reasonable | |
24 # approximation. | |
25 # | |
26 # Author: Diego Novillo <dnovillo@google.com> and | |
27 # Cary Coutant <ccoutant@google.com> | |
28 | |
29 use File::Temp; | |
30 use File::Copy qw(cp mv); | |
31 | |
32 $date = `date +%Y-%m-%d`; chop ($date); | |
33 | |
34 $dot_mklog_format_msg = | |
35 "The .mklog format is:\n" | |
36 . "NAME = ...\n" | |
37 . "EMAIL = ...\n"; | |
38 | |
39 # Create a .mklog to reflect your profile, if necessary. | |
40 my $conf = "$ENV{HOME}/.mklog"; | |
41 if (-f "$conf") { | |
42 open (CONF, "$conf") | |
43 or die "Could not open file '$conf' for reading: $!\n"; | |
44 while (<CONF>) { | |
45 if (m/^\s*NAME\s*=\s*(.*?)\s*$/) { | |
46 $name = $1; | |
47 } elsif (m/^\s*EMAIL\s*=\s*(.*?)\s*$/) { | |
48 $addr = $1; | |
49 } | |
50 } | |
51 if (!($name && $addr)) { | |
52 die "Could not read .mklog settings.\n" | |
53 . $dot_mklog_format_msg; | |
54 } | |
55 } else { | |
56 $name = `git config user.name`; | |
57 chomp($name); | |
58 $addr = `git config user.email`; | |
59 chomp($addr); | |
60 | |
61 if (!($name && $addr)) { | |
62 die "Could not read git user.name and user.email settings.\n" | |
63 . "Please add missing git settings, or create a .mklog file in" | |
64 . " $ENV{HOME}.\n" | |
65 . $dot_mklog_format_msg; | |
66 } | |
67 } | |
68 | |
69 $gcc_root = $0; | |
70 $gcc_root =~ s/[^\\\/]+$/../; | |
71 | |
72 #----------------------------------------------------------------------------- | |
73 # Program starts here. You should not need to edit anything below this | |
74 # line. | |
75 #----------------------------------------------------------------------------- | |
76 $inline = 0; | |
77 if ($#ARGV == 1 && ("$ARGV[0]" eq "-i" || "$ARGV[0]" eq "--inline")) { | |
78 shift; | |
79 $inline = 1; | |
80 } elsif ($#ARGV != 0) { | |
81 $prog = `basename $0`; chop ($prog); | |
82 print <<EOF; | |
83 usage: $prog [ -i | --inline ] file.diff | |
84 | |
85 Generate ChangeLog template for file.diff. | |
86 It assumes that patch has been created with -up or -cp. | |
87 When -i is used, the ChangeLog template is followed by the contents of | |
88 file.diff. | |
89 When file.diff is -, read standard input. | |
90 When -i is used and file.diff is not -, it writes to file.diff, otherwise it | |
91 writes to stdout. | |
92 EOF | |
93 exit 1; | |
94 } | |
95 | |
96 $diff = $ARGV[0]; | |
97 $dir = `dirname $diff`; chop ($dir); | |
98 $basename = `basename $diff`; chop ($basename); | |
99 $hdrline = "$date $name <$addr>"; | |
100 | |
101 sub get_clname ($) { | |
102 return ('ChangeLog', $_[0]) if ($_[0] !~ /[\/\\]/); | |
103 | |
104 my $dirname = $_[0]; | |
105 while ($dirname) { | |
106 my $clname = "$dirname/ChangeLog"; | |
107 if (-f "$gcc_root/$clname" || -f "$clname") { | |
108 my $relname = substr ($_[0], length ($dirname) + 1); | |
109 return ($clname, $relname); | |
110 } else { | |
111 $dirname =~ s/[\/\\]?[^\/\\]*$//; | |
112 } | |
113 } | |
114 | |
115 return ('Unknown ChangeLog', $_[0]); | |
116 } | |
117 | |
118 sub remove_suffixes ($) { | |
119 my $filename = $_[0]; | |
120 $filename =~ s/^[ab]\///; | |
121 $filename =~ s/\.jj$//; | |
122 return $filename; | |
123 } | |
124 | |
125 sub is_context_hunk_start { | |
126 return @_[0] =~ /^\*\*\*\*\*\** ([a-zA-Z0-9_].*)/; | |
127 } | |
128 | |
129 sub is_unified_hunk_start { | |
130 return @_[0] =~ /^@@ .* @@ ([a-zA-Z0-9_].*)/; | |
131 } | |
132 | |
133 # Check if line is a top-level declaration. | |
134 sub is_top_level { | |
135 my ($function, $is_context_diff) = (@_); | |
136 if (is_unified_hunk_start ($function) | |
137 || is_context_hunk_start ($function)) { | |
138 return 1; | |
139 } | |
140 if ($is_context_diff) { | |
141 $function =~ s/^..//; | |
142 } else { | |
143 $function =~ s/^.//; | |
144 } | |
145 return $function && $function !~ /^[\s{#]/; | |
146 } | |
147 | |
148 # Read contents of .diff file | |
149 open (DFILE, $diff) or die "Could not open file $diff for reading"; | |
150 chomp (my @diff_lines = <DFILE>); | |
151 close (DFILE); | |
152 | |
153 # Array diff_lines is modified by the log generation, so save a copy in | |
154 # orig_diff_lines if needed. | |
155 if ($inline) { | |
156 @orig_diff_lines = @diff_lines; | |
157 } | |
158 | |
159 # For every file in the .diff print all the function names in ChangeLog | |
160 # format. | |
161 %cl_entries = (); | |
162 $change_msg = undef; | |
163 $look_for_funs = 0; | |
164 $clname = get_clname(''); | |
165 $line_idx = 0; | |
166 foreach (@diff_lines) { | |
167 # Stop processing functions if we found a new file. | |
168 # Remember both left and right names because one may be /dev/null. | |
169 # Don't be fooled by line markers in case of context diff. | |
170 if (!/\*\*\*$/ && /^[+*][+*][+*] +(\S+)/) { | |
171 $left = remove_suffixes ($1); | |
172 $look_for_funs = 0; | |
173 } | |
174 if (!/---$/ && /^--- +(\S+)?/) { | |
175 $right = remove_suffixes ($1); | |
176 $look_for_funs = 0; | |
177 } | |
178 | |
179 # Check if the body of diff started. | |
180 # We should now have both left and right name, | |
181 # so we can decide filename. | |
182 | |
183 if ($left && (/^\*{15}/ || /^@@ /)) { | |
184 # If we have not seen any function names in the previous file (ie, | |
185 # $change_msg is empty), we just write out a ':' before starting the next | |
186 # file. | |
187 if ($clname) { | |
188 $cl_entries{$clname} .= $change_msg ? "$change_msg" : ":\n"; | |
189 } | |
190 | |
191 if ($left eq $right) { | |
192 $filename = $left; | |
193 } elsif($left eq '/dev/null') { | |
194 $filename = $right; | |
195 } elsif($right eq '/dev/null') { | |
196 $filename = $left; | |
197 } else { | |
198 my @ldirs = split /[\/\\]/, $left; | |
199 my @rdirs = split /[\/\\]/, $right; | |
200 | |
201 $filename = ''; | |
202 while ((my $l = pop @ldirs) && (my $r = pop @rdirs)) { | |
203 last if ($l ne $r); | |
204 $filename = "$l/$filename"; | |
205 } | |
206 $filename =~ s/\/$//; | |
207 | |
208 if (!$filename) { | |
209 print STDERR "Error: failed to parse diff for $left and $right\n"; | |
210 exit 1; | |
211 } | |
212 } | |
213 $left = $right = undef; | |
214 ($clname, $relname) = get_clname ($filename); | |
215 $cl_entries{$clname} .= "\t* $relname"; | |
216 $change_msg = ''; | |
217 $look_for_funs = $filename =~ '\.(c|cpp|C|cc|h|inc|def)$'; | |
218 } | |
219 | |
220 # Context diffs have extra whitespace after first char; | |
221 # remove it to make matching easier. | |
222 if ($is_context_diff) { | |
223 s/^([-+! ]) /\1/; | |
224 } | |
225 | |
226 # Remember the last line in a diff block that might start | |
227 # a new function. | |
228 if (/^[-+! ]([a-zA-Z0-9_].*)/) { | |
229 $save_fn = $1; | |
230 } | |
231 | |
232 # Check if file is newly added. | |
233 # Two patterns: for context and unified diff. | |
234 if (/^\*\*\* 0 \*\*\*\*/ | |
235 || /^@@ -0,0 \+1.* @@/) { | |
236 $change_msg = $filename =~ /testsuite.*(?<!\.exp)$/ ? ": New test.\n" : ": New file.\n"; | |
237 $look_for_funs = 0; | |
238 } | |
239 | |
240 # Check if file was removed. | |
241 # Two patterns: for context and unified diff. | |
242 if (/^--- 0 ----/ | |
243 || /^@@ -1.* \+0,0 @@/) { | |
244 $change_msg = ": Remove.\n"; | |
245 $look_for_funs = 0; | |
246 } | |
247 | |
248 if (is_unified_hunk_start ($diff_lines[$line_idx])) { | |
249 $is_context_diff = 0; | |
250 } | |
251 elsif (is_context_hunk_start ($diff_lines[$line_idx])) { | |
252 $is_context_diff = 1; | |
253 } | |
254 | |
255 # If we find a new function, print it in brackets. Special case if | |
256 # this is the first function in a file. | |
257 # | |
258 # Note that we don't try too hard to find good matches. This should | |
259 # return a superset of the actual set of functions in the .diff file. | |
260 # | |
261 # The first pattern works with context diff files (diff -c). The | |
262 # second pattern works with unified diff files (diff -u). | |
263 # | |
264 # The third pattern looks for the starts of functions or classes | |
265 # within a diff block both for context and unified diff files. | |
266 if ($look_for_funs | |
267 && (/^\*\*\*\*\*\** ([a-zA-Z0-9_].*)/ | |
268 || /^@@ .* @@ ([a-zA-Z0-9_].*)/ | |
269 || /^[-+! ](\{)/)) | |
270 { | |
271 $_ = $1; | |
272 my $fn; | |
273 if (/^\{/) { | |
274 # Beginning of a new function. | |
275 $_ = $save_fn; | |
276 } else { | |
277 $save_fn = ""; | |
278 } | |
279 if (/;$/) { | |
280 # No usable function name found. | |
281 } elsif (/^((class|struct|union|enum) [a-zA-Z0-9_]+)/) { | |
282 # Discard stuff after the class/struct/etc. tag. | |
283 $fn = $1; | |
284 } elsif (/([a-zA-Z0-9_][^(]*)\(/) { | |
285 # Discard template and function parameters. | |
286 $fn = $1; | |
287 1 while ($fn =~ s/<[^<>]*>//); | |
288 $fn =~ s/[ \t]*$//; | |
289 } | |
290 # Check is function really modified | |
291 $no_real_change = 0; | |
292 $idx = $line_idx; | |
293 # Skip line info in context diffs. | |
294 while ($idx <= $#diff_lines && $is_context_diff | |
295 && $diff_lines[$idx + 1] =~ /^[-\*]{3} [0-9]/) { | |
296 ++$idx; | |
297 } | |
298 # Check all lines till the first change | |
299 # for the presence of really changed function | |
300 do { | |
301 ++$idx; | |
302 $no_real_change = $idx > $#diff_lines | |
303 || is_top_level ($diff_lines[$idx], $is_context_diff); | |
304 } while (!$no_real_change && ($diff_lines[$idx] !~ /^[-+!]/)); | |
305 if ($fn && !$seen_names{$fn} && !$no_real_change) { | |
306 # If this is the first function in the file, we display it next | |
307 # to the filename, so we need an extra space before the opening | |
308 # brace. | |
309 if (!$change_msg) { | |
310 $change_msg .= " "; | |
311 } else { | |
312 $change_msg .= "\t"; | |
313 } | |
314 | |
315 $change_msg .= "($fn):\n"; | |
316 $seen_names{$fn} = 1; | |
317 } | |
318 } | |
319 $line_idx++; | |
320 } | |
321 | |
322 # If we have not seen any function names (ie, $change_msg is empty), we just | |
323 # write out a ':'. This happens when there is only one file with no | |
324 # functions. | |
325 $cl_entries{$clname} .= $change_msg ? "$change_msg\n" : ":\n"; | |
326 | |
327 if ($inline && $diff ne "-") { | |
328 # Get a temp filename, rather than an open filehandle, because we use | |
329 # the open to truncate. | |
330 $tmp = mktemp("tmp.XXXXXXXX") or die "Could not create temp file: $!"; | |
331 | |
332 # Copy the permissions to the temp file (in File::Copy module version | |
333 # 2.15 and later). | |
334 cp $diff, $tmp or die "Could not copy patch file to temp file: $!"; | |
335 | |
336 # Open the temp file, clearing contents. | |
337 open (OUTPUTFILE, '>', $tmp) or die "Could not open temp file: $!"; | |
338 } else { | |
339 *OUTPUTFILE = STDOUT; | |
340 } | |
341 | |
342 # Print the log | |
343 foreach my $clname (keys %cl_entries) { | |
344 print OUTPUTFILE "$clname:\n\n$hdrline\n\n$cl_entries{$clname}\n"; | |
345 } | |
346 | |
347 if ($inline) { | |
348 # Append the patch to the log | |
349 foreach (@orig_diff_lines) { | |
350 print OUTPUTFILE "$_\n"; | |
351 } | |
352 } | |
353 | |
354 if ($inline && $diff ne "-") { | |
355 # Close $tmp | |
356 close(OUTPUTFILE); | |
357 | |
358 # Write new contents to $diff atomically | |
359 mv $tmp, $diff or die "Could not move temp file to patch file: $!"; | |
360 } | |
361 | |
362 exit 0; |