summaryrefslogtreecommitdiff
path: root/contrib/mklog
blob: 70308ab44a26dae8adc712259507f8cb110b9f4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/perl
# Copyright (C) 2012 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# GCC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GCC; see the file COPYING.  If not, write to
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.

# This script parses a .diff file generated with 'diff -up' or 'diff -cp'
# and writes a skeleton ChangeLog file to stdout. It does not try to be
# very smart when parsing function names, but it produces a reasonable
# approximation.
#
# Author: Diego Novillo <dnovillo@google.com> and
#         Cary Coutant <ccoutant@google.com>

# Change these settings to reflect your profile.
$username = $ENV{'USER'};
$name = `finger $username | grep -o 'Name: .*'`;
@n = split(/:/, $name);
$name = @n[1]; chop($name);
$addr = $username . "\@my.domain.org";
$date = `date +%Y-%m-%d`; chop ($date);


#-----------------------------------------------------------------------------
# Program starts here. You should not need to edit anything below this
# line.
#-----------------------------------------------------------------------------
if ( $#ARGV != 0 ) {
    $prog = `basename $0`; chop ($prog);
    print "usage: $prog file.diff\n\n";
    print "Adds a ChangeLog template to the start of file.diff\n";
    print "It assumes that file.diff has been created with -up or -cp.\n";
    exit 1;
}

$diff = $ARGV[0];
$dir = `dirname $diff`; chop ($dir);
$basename = `basename $diff`; chop ($basename);
$cl = `mktemp /tmp/$basename.XXXXXX` || exit 1; chop ($cl);
$hdrline = "$date  $name  <$addr>";

open (CLFILE, ">$cl") or die "Could not open file $cl for writing";

print CLFILE "$hdrline\n\n";

# For every file in the .diff print all the function names in ChangeLog
# format.
$bof = 0;
open (DFILE, $diff) or die "Could not open file $diff for reading";
while (<DFILE>) {
    # Check if we found a new file.
    if (/^\+\+\+ (b\/)?(\S+)/) {
	# If we have not seen any function names in the previous file (ie,
	# $bof == 1), we just write out a ':' before starting the next
	# file.
	if ($bof == 1) {
	    print CLFILE ":\n";
	}
	$filename = $2;
	print CLFILE "\t* $filename";
	$bof = 1;
    }

    # Remember the last line in a unified diff block that might start
    # a new function.
    if (/^[-+ ]([a-zA-Z0-9_].*)/) {
        $save_fn = $1;
    }

    # If we find a new function, print it in brackets.  Special case if
    # this is the first function in a file.  
    #
    # Note that we don't try too hard to find good matches.  This should
    # return a superset of the actual set of functions in the .diff file.
    #
    # The first two patterns work with context diff files (diff -c). The
    # third pattern works with unified diff files (diff -u).
    #
    # The fourth pattern looks for the starts of functions or classes
    # within a unified diff block.

    if (/^\*\*\*\*\*\** ([a-zA-Z0-9_].*)/
        || /^[\-\+\!] ([a-zA-Z0-9_]+)[ \t]*\(.*/
	|| /^@@ .* @@ ([a-zA-Z0-9_].*)/
	|| /^[-+ ](\{)/)
      {
	$_ = $1;
	my $fn;
	if (/^\{/) {
	    # Beginning of a new function.
	    $_ = $save_fn;
	} else {
	    $save_fn = "";
	}
	if (/;$/) {
	    # No usable function name found.
	} elsif (/^((class|struct|union|enum) [a-zA-Z0-9_]+)/) {
	    # Discard stuff after the class/struct/etc. tag.
	    $fn = $1;
	} elsif (/([a-zA-Z0-9_][^(]*)\(/) {
	    # Discard template and function parameters.
	    $fn = $1;
	    1 while ($fn =~ s/<[^<>]*>//);
	    $fn =~ s/[ \t]*$//;
	}
	if ($fn && $seen_names{$fn} == 0) {
	    # If this is the first function in the file, we display it next
	    # to the filename, so we need an extra space before the opening
	    # brace.
	    if ($bof) {
		print CLFILE " ";
		$bof = 0;
	    } else {
		print CLFILE "\t";
	    }

	    print CLFILE "($fn):\n";
	    $seen_names{$fn} = 1;
	}
    }
}

# If we have not seen any function names (ie, $bof == 1), we just
# write out a ':'. This happens when there is only one file with no
# functions.
if ($bof == 1) {
    print CLFILE ":\n";
}

print CLFILE "\n";
close (DFILE);

# Concatenate the ChangeLog template and the original .diff file.
system ("cat $diff >>$cl && mv $cl $diff") == 0
    or die "Could not add the ChangeLog entry to $diff";

exit 0;