aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.build13
-rw-r--r--scripts/Makefile.clean2
-rw-r--r--scripts/Makefile.lib15
-rw-r--r--scripts/basic/Makefile2
-rw-r--r--scripts/basic/docproc.c129
-rw-r--r--scripts/basic/hash.c64
-rwxr-xr-xscripts/checkpatch.pl150
-rw-r--r--scripts/gcc-goto.sh5
-rwxr-xr-xscripts/get_maintainer.pl1162
-rw-r--r--scripts/kallsyms.c8
-rwxr-xr-xscripts/kernel-doc54
-rw-r--r--scripts/mod/modpost.c5
-rw-r--r--scripts/recordmcount.c363
-rw-r--r--scripts/recordmcount.h366
-rwxr-xr-xscripts/recordmcount.pl9
-rwxr-xr-xscripts/setlocalversion6
17 files changed, 2025 insertions, 329 deletions
diff --git a/scripts/Makefile b/scripts/Makefile
index 842dbc2d5aed..2e088109fbd5 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -11,6 +11,7 @@ hostprogs-$(CONFIG_KALLSYMS) += kallsyms
11hostprogs-$(CONFIG_LOGO) += pnmtologo 11hostprogs-$(CONFIG_LOGO) += pnmtologo
12hostprogs-$(CONFIG_VT) += conmakehash 12hostprogs-$(CONFIG_VT) += conmakehash
13hostprogs-$(CONFIG_IKCONFIG) += bin2c 13hostprogs-$(CONFIG_IKCONFIG) += bin2c
14hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
14 15
15always := $(hostprogs-y) $(hostprogs-m) 16always := $(hostprogs-y) $(hostprogs-m)
16 17
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index a1a5cf95a68d..5ad25e17b6cb 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -209,12 +209,23 @@ cmd_modversions = \
209endif 209endif
210 210
211ifdef CONFIG_FTRACE_MCOUNT_RECORD 211ifdef CONFIG_FTRACE_MCOUNT_RECORD
212ifdef BUILD_C_RECORDMCOUNT
213# Due to recursion, we must skip empty.o.
214# The empty.o file is created in the make process in order to determine
215# the target endianness and word size. It is made before all other C
216# files, including recordmcount.
217cmd_record_mcount = if [ $(@) != "scripts/mod/empty.o" ]; then \
218 $(objtree)/scripts/recordmcount "$(@)"; \
219 fi;
220else
212cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ 221cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
213 "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ 222 "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
214 "$(if $(CONFIG_64BIT),64,32)" \ 223 "$(if $(CONFIG_64BIT),64,32)" \
215 "$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \ 224 "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
225 "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
216 "$(if $(part-of-module),1,0)" "$(@)"; 226 "$(if $(part-of-module),1,0)" "$(@)";
217endif 227endif
228endif
218 229
219define rule_cc_o_c 230define rule_cc_o_c
220 $(call echo-cmd,checksrc) $(cmd_checksrc) \ 231 $(call echo-cmd,checksrc) $(cmd_checksrc) \
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 6f89fbb56256..686cb0d31c7c 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -45,6 +45,8 @@ __clean-files := $(extra-y) $(always) \
45 $(host-progs) \ 45 $(host-progs) \
46 $(hostprogs-y) $(hostprogs-m) $(hostprogs-) 46 $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
47 47
48__clean-files := $(filter-out $(no-clean-files), $(__clean-files))
49
48# as clean-files is given relative to the current directory, this adds 50# as clean-files is given relative to the current directory, this adds
49# a $(obj) prefix, except for absolute paths 51# a $(obj) prefix, except for absolute paths
50 52
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 54fd1b700131..4c72c1189479 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -101,14 +101,6 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
101modname_flags = $(if $(filter 1,$(words $(modname))),\ 101modname_flags = $(if $(filter 1,$(words $(modname))),\
102 -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") 102 -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
103 103
104#hash values
105ifdef CONFIG_DYNAMIC_DEBUG
106debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
107 -D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
108else
109debug_flags =
110endif
111
112orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ 104orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
113 $(ccflags-y) $(CFLAGS_$(basetarget).o) 105 $(ccflags-y) $(CFLAGS_$(basetarget).o)
114_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) 106_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
@@ -128,7 +120,9 @@ _c_flags += $(if $(patsubst n%,, \
128endif 120endif
129 121
130ifdef CONFIG_SYMBOL_PREFIX 122ifdef CONFIG_SYMBOL_PREFIX
131_cpp_flags += -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX)) 123_sym_flags = -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX))
124_cpp_flags += $(_sym_flags)
125_a_flags += $(_sym_flags)
132endif 126endif
133 127
134 128
@@ -152,8 +146,7 @@ endif
152 146
153c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ 147c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
154 $(__c_flags) $(modkern_cflags) \ 148 $(__c_flags) $(modkern_cflags) \
155 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \ 149 -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
156 $(debug_flags)
157 150
158a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ 151a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
159 $(__a_flags) $(modkern_aflags) 152 $(__a_flags) $(modkern_aflags)
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 09559951df12..4c324a1f1e0e 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -9,7 +9,7 @@
9# fixdep: Used to generate dependency information during build process 9# fixdep: Used to generate dependency information during build process
10# docproc: Used in Documentation/DocBook 10# docproc: Used in Documentation/DocBook
11 11
12hostprogs-y := fixdep docproc hash 12hostprogs-y := fixdep docproc
13always := $(hostprogs-y) 13always := $(hostprogs-y)
14 14
15# fixdep is needed to compile other host programs 15# fixdep is needed to compile other host programs
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
index 79ab973fb43a..fc3b18d844af 100644
--- a/scripts/basic/docproc.c
+++ b/scripts/basic/docproc.c
@@ -34,12 +34,14 @@
34 * 34 *
35 */ 35 */
36 36
37#define _GNU_SOURCE
37#include <stdio.h> 38#include <stdio.h>
38#include <stdlib.h> 39#include <stdlib.h>
39#include <string.h> 40#include <string.h>
40#include <ctype.h> 41#include <ctype.h>
41#include <unistd.h> 42#include <unistd.h>
42#include <limits.h> 43#include <limits.h>
44#include <errno.h>
43#include <sys/types.h> 45#include <sys/types.h>
44#include <sys/wait.h> 46#include <sys/wait.h>
45 47
@@ -54,6 +56,7 @@ typedef void FILEONLY(char * file);
54FILEONLY *internalfunctions; 56FILEONLY *internalfunctions;
55FILEONLY *externalfunctions; 57FILEONLY *externalfunctions;
56FILEONLY *symbolsonly; 58FILEONLY *symbolsonly;
59FILEONLY *findall;
57 60
58typedef void FILELINE(char * file, char * line); 61typedef void FILELINE(char * file, char * line);
59FILELINE * singlefunctions; 62FILELINE * singlefunctions;
@@ -65,12 +68,30 @@ FILELINE * docsection;
65#define KERNELDOCPATH "scripts/" 68#define KERNELDOCPATH "scripts/"
66#define KERNELDOC "kernel-doc" 69#define KERNELDOC "kernel-doc"
67#define DOCBOOK "-docbook" 70#define DOCBOOK "-docbook"
71#define LIST "-list"
68#define FUNCTION "-function" 72#define FUNCTION "-function"
69#define NOFUNCTION "-nofunction" 73#define NOFUNCTION "-nofunction"
70#define NODOCSECTIONS "-no-doc-sections" 74#define NODOCSECTIONS "-no-doc-sections"
71 75
72static char *srctree, *kernsrctree; 76static char *srctree, *kernsrctree;
73 77
78static char **all_list = NULL;
79static int all_list_len = 0;
80
81static void consume_symbol(const char *sym)
82{
83 int i;
84
85 for (i = 0; i < all_list_len; i++) {
86 if (!all_list[i])
87 continue;
88 if (strcmp(sym, all_list[i]))
89 continue;
90 all_list[i] = NULL;
91 break;
92 }
93}
94
74static void usage (void) 95static void usage (void)
75{ 96{
76 fprintf(stderr, "Usage: docproc {doc|depend} file\n"); 97 fprintf(stderr, "Usage: docproc {doc|depend} file\n");
@@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type)
248 struct symfile * sym = &symfilelist[i]; 269 struct symfile * sym = &symfilelist[i];
249 for (j=0; j < sym->symbolcnt; j++) { 270 for (j=0; j < sym->symbolcnt; j++) {
250 vec[idx++] = type; 271 vec[idx++] = type;
272 consume_symbol(sym->symbollist[j].name);
251 vec[idx++] = sym->symbollist[j].name; 273 vec[idx++] = sym->symbollist[j].name;
252 } 274 }
253 } 275 }
@@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line)
287 vec[idx++] = &line[i]; 309 vec[idx++] = &line[i];
288 } 310 }
289 } 311 }
312 for (i = 0; i < idx; i++) {
313 if (strcmp(vec[i], FUNCTION))
314 continue;
315 consume_symbol(vec[i + 1]);
316 }
290 vec[idx++] = filename; 317 vec[idx++] = filename;
291 vec[idx] = NULL; 318 vec[idx] = NULL;
292 exec_kernel_doc(vec); 319 exec_kernel_doc(vec);
@@ -306,6 +333,10 @@ static void docsect(char *filename, char *line)
306 if (*s == '\n') 333 if (*s == '\n')
307 *s = '\0'; 334 *s = '\0';
308 335
336 asprintf(&s, "DOC: %s", line);
337 consume_symbol(s);
338 free(s);
339
309 vec[0] = KERNELDOC; 340 vec[0] = KERNELDOC;
310 vec[1] = DOCBOOK; 341 vec[1] = DOCBOOK;
311 vec[2] = FUNCTION; 342 vec[2] = FUNCTION;
@@ -315,6 +346,84 @@ static void docsect(char *filename, char *line)
315 exec_kernel_doc(vec); 346 exec_kernel_doc(vec);
316} 347}
317 348
349static void find_all_symbols(char *filename)
350{
351 char *vec[4]; /* kerneldoc -list file NULL */
352 pid_t pid;
353 int ret, i, count, start;
354 char real_filename[PATH_MAX + 1];
355 int pipefd[2];
356 char *data, *str;
357 size_t data_len = 0;
358
359 vec[0] = KERNELDOC;
360 vec[1] = LIST;
361 vec[2] = filename;
362 vec[3] = NULL;
363
364 if (pipe(pipefd)) {
365 perror("pipe");
366 exit(1);
367 }
368
369 switch (pid=fork()) {
370 case -1:
371 perror("fork");
372 exit(1);
373 case 0:
374 close(pipefd[0]);
375 dup2(pipefd[1], 1);
376 memset(real_filename, 0, sizeof(real_filename));
377 strncat(real_filename, kernsrctree, PATH_MAX);
378 strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
379 PATH_MAX - strlen(real_filename));
380 execvp(real_filename, vec);
381 fprintf(stderr, "exec ");
382 perror(real_filename);
383 exit(1);
384 default:
385 close(pipefd[1]);
386 data = malloc(4096);
387 do {
388 while ((ret = read(pipefd[0],
389 data + data_len,
390 4096)) > 0) {
391 data_len += ret;
392 data = realloc(data, data_len + 4096);
393 }
394 } while (ret == -EAGAIN);
395 if (ret != 0) {
396 perror("read");
397 exit(1);
398 }
399 waitpid(pid, &ret ,0);
400 }
401 if (WIFEXITED(ret))
402 exitstatus |= WEXITSTATUS(ret);
403 else
404 exitstatus = 0xff;
405
406 count = 0;
407 /* poor man's strtok, but with counting */
408 for (i = 0; i < data_len; i++) {
409 if (data[i] == '\n') {
410 count++;
411 data[i] = '\0';
412 }
413 }
414 start = all_list_len;
415 all_list_len += count;
416 all_list = realloc(all_list, sizeof(char *) * all_list_len);
417 str = data;
418 for (i = 0; i < data_len && start != all_list_len; i++) {
419 if (data[i] == '\0') {
420 all_list[start] = str;
421 str = data + i + 1;
422 start++;
423 }
424 }
425}
426
318/* 427/*
319 * Parse file, calling action specific functions for: 428 * Parse file, calling action specific functions for:
320 * 1) Lines containing !E 429 * 1) Lines containing !E
@@ -322,7 +431,8 @@ static void docsect(char *filename, char *line)
322 * 3) Lines containing !D 431 * 3) Lines containing !D
323 * 4) Lines containing !F 432 * 4) Lines containing !F
324 * 5) Lines containing !P 433 * 5) Lines containing !P
325 * 6) Default lines - lines not matching the above 434 * 6) Lines containing !C
435 * 7) Default lines - lines not matching the above
326 */ 436 */
327static void parse_file(FILE *infile) 437static void parse_file(FILE *infile)
328{ 438{
@@ -365,6 +475,12 @@ static void parse_file(FILE *infile)
365 s++; 475 s++;
366 docsection(line + 2, s); 476 docsection(line + 2, s);
367 break; 477 break;
478 case 'C':
479 while (*s && !isspace(*s)) s++;
480 *s = '\0';
481 if (findall)
482 findall(line+2);
483 break;
368 default: 484 default:
369 defaultline(line); 485 defaultline(line);
370 } 486 }
@@ -380,6 +496,7 @@ static void parse_file(FILE *infile)
380int main(int argc, char *argv[]) 496int main(int argc, char *argv[])
381{ 497{
382 FILE * infile; 498 FILE * infile;
499 int i;
383 500
384 srctree = getenv("SRCTREE"); 501 srctree = getenv("SRCTREE");
385 if (!srctree) 502 if (!srctree)
@@ -415,6 +532,7 @@ int main(int argc, char *argv[])
415 symbolsonly = find_export_symbols; 532 symbolsonly = find_export_symbols;
416 singlefunctions = noaction2; 533 singlefunctions = noaction2;
417 docsection = noaction2; 534 docsection = noaction2;
535 findall = find_all_symbols;
418 parse_file(infile); 536 parse_file(infile);
419 537
420 /* Rewind to start from beginning of file again */ 538 /* Rewind to start from beginning of file again */
@@ -425,8 +543,16 @@ int main(int argc, char *argv[])
425 symbolsonly = printline; 543 symbolsonly = printline;
426 singlefunctions = singfunc; 544 singlefunctions = singfunc;
427 docsection = docsect; 545 docsection = docsect;
546 findall = NULL;
428 547
429 parse_file(infile); 548 parse_file(infile);
549
550 for (i = 0; i < all_list_len; i++) {
551 if (!all_list[i])
552 continue;
553 fprintf(stderr, "Warning: didn't use docs for %s\n",
554 all_list[i]);
555 }
430 } 556 }
431 else if (strcmp("depend", argv[1]) == 0) 557 else if (strcmp("depend", argv[1]) == 0)
432 { 558 {
@@ -439,6 +565,7 @@ int main(int argc, char *argv[])
439 symbolsonly = adddep; 565 symbolsonly = adddep;
440 singlefunctions = adddep2; 566 singlefunctions = adddep2;
441 docsection = adddep2; 567 docsection = adddep2;
568 findall = adddep;
442 parse_file(infile); 569 parse_file(infile);
443 printf("\n"); 570 printf("\n");
444 } 571 }
diff --git a/scripts/basic/hash.c b/scripts/basic/hash.c
deleted file mode 100644
index 2ef5d3f666b8..000000000000
--- a/scripts/basic/hash.c
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
3 *
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#define DYNAMIC_DEBUG_HASH_BITS 6
11
12static const char *program;
13
14static void usage(void)
15{
16 printf("Usage: %s <djb2|r5> <modname>\n", program);
17 exit(1);
18}
19
20/* djb2 hashing algorithm by Dan Bernstein. From:
21 * http://www.cse.yorku.ca/~oz/hash.html
22 */
23
24static unsigned int djb2_hash(char *str)
25{
26 unsigned long hash = 5381;
27 int c;
28
29 c = *str;
30 while (c) {
31 hash = ((hash << 5) + hash) + c;
32 c = *++str;
33 }
34 return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
35}
36
37static unsigned int r5_hash(char *str)
38{
39 unsigned long hash = 0;
40 int c;
41
42 c = *str;
43 while (c) {
44 hash = (hash + (c << 4) + (c >> 4)) * 11;
45 c = *++str;
46 }
47 return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
48}
49
50int main(int argc, char *argv[])
51{
52 program = argv[0];
53
54 if (argc != 3)
55 usage();
56 if (!strcmp(argv[1], "djb2"))
57 printf("%d\n", djb2_hash(argv[2]));
58 else if (!strcmp(argv[1], "r5"))
59 printf("%d\n", r5_hash(argv[2]));
60 else
61 usage();
62 exit(0);
63}
64
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2039acdf5122..90b54d4697fd 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2,7 +2,7 @@
2# (c) 2001, Dave Jones. (the file handling bit) 2# (c) 2001, Dave Jones. (the file handling bit)
3# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) 3# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
4# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) 4# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
5# (c) 2008,2009, Andy Whitcroft <apw@canonical.com> 5# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
6# Licensed under the terms of the GNU GPL License version 2 6# Licensed under the terms of the GNU GPL License version 2
7 7
8use strict; 8use strict;
@@ -10,7 +10,7 @@ use strict;
10my $P = $0; 10my $P = $0;
11$P =~ s@.*/@@g; 11$P =~ s@.*/@@g;
12 12
13my $V = '0.30'; 13my $V = '0.31';
14 14
15use Getopt::Long qw(:config no_auto_abbrev); 15use Getopt::Long qw(:config no_auto_abbrev);
16 16
@@ -103,6 +103,8 @@ for my $key (keys %debug) {
103 die "$@" if ($@); 103 die "$@" if ($@);
104} 104}
105 105
106my $rpt_cleaners = 0;
107
106if ($terse) { 108if ($terse) {
107 $emacs = 1; 109 $emacs = 1;
108 $quiet++; 110 $quiet++;
@@ -150,6 +152,20 @@ our $Sparse = qr{
150# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check 152# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
151our $Attribute = qr{ 153our $Attribute = qr{
152 const| 154 const|
155 __percpu|
156 __nocast|
157 __safe|
158 __bitwise__|
159 __packed__|
160 __packed2__|
161 __naked|
162 __maybe_unused|
163 __always_unused|
164 __noreturn|
165 __used|
166 __cold|
167 __noclone|
168 __deprecated|
153 __read_mostly| 169 __read_mostly|
154 __kprobes| 170 __kprobes|
155 __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| 171 __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
@@ -675,15 +691,15 @@ sub ctx_block_get {
675 $blk .= $rawlines[$line]; 691 $blk .= $rawlines[$line];
676 692
677 # Handle nested #if/#else. 693 # Handle nested #if/#else.
678 if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { 694 if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
679 push(@stack, $level); 695 push(@stack, $level);
680 } elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { 696 } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
681 $level = $stack[$#stack - 1]; 697 $level = $stack[$#stack - 1];
682 } elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) { 698 } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
683 $level = pop(@stack); 699 $level = pop(@stack);
684 } 700 }
685 701
686 foreach my $c (split(//, $rawlines[$line])) { 702 foreach my $c (split(//, $lines[$line])) {
687 ##print "C<$c>L<$level><$open$close>O<$off>\n"; 703 ##print "C<$c>L<$level><$open$close>O<$off>\n";
688 if ($off > 0) { 704 if ($off > 0) {
689 $off--; 705 $off--;
@@ -843,7 +859,12 @@ sub annotate_values {
843 $av_preprocessor = 0; 859 $av_preprocessor = 0;
844 } 860 }
845 861
846 } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) { 862 } elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
863 print "CAST($1)\n" if ($dbg_values > 1);
864 push(@av_paren_type, $type);
865 $type = 'C';
866
867 } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
847 print "DECLARE($1)\n" if ($dbg_values > 1); 868 print "DECLARE($1)\n" if ($dbg_values > 1);
848 $type = 'T'; 869 $type = 'T';
849 870
@@ -1308,7 +1329,11 @@ sub process {
1308 $here = "#$realline: " if ($file); 1329 $here = "#$realline: " if ($file);
1309 1330
1310 # extract the filename as it passes 1331 # extract the filename as it passes
1311 if ($line=~/^\+\+\+\s+(\S+)/) { 1332 if ($line =~ /^diff --git.*?(\S+)$/) {
1333 $realfile = $1;
1334 $realfile =~ s@^([^/]*)/@@;
1335
1336 } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
1312 $realfile = $1; 1337 $realfile = $1;
1313 $realfile =~ s@^([^/]*)/@@; 1338 $realfile =~ s@^([^/]*)/@@;
1314 1339
@@ -1332,6 +1357,14 @@ sub process {
1332 1357
1333 $cnt_lines++ if ($realcnt != 0); 1358 $cnt_lines++ if ($realcnt != 0);
1334 1359
1360# Check for incorrect file permissions
1361 if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
1362 my $permhere = $here . "FILE: $realfile\n";
1363 if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
1364 ERROR("do not set execute permissions for source files\n" . $permhere);
1365 }
1366 }
1367
1335#check the patch for a signoff: 1368#check the patch for a signoff:
1336 if ($line =~ /^\s*signed-off-by:/i) { 1369 if ($line =~ /^\s*signed-off-by:/i) {
1337 # This is a signoff, if ugly, so do not double report. 1370 # This is a signoff, if ugly, so do not double report.
@@ -1389,21 +1422,38 @@ sub process {
1389 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { 1422 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
1390 my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 1423 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1391 ERROR("trailing whitespace\n" . $herevet); 1424 ERROR("trailing whitespace\n" . $herevet);
1425 $rpt_cleaners = 1;
1392 } 1426 }
1393 1427
1394# check for Kconfig help text having a real description 1428# check for Kconfig help text having a real description
1429# Only applies when adding the entry originally, after that we do not have
1430# sufficient context to determine whether it is indeed long enough.
1395 if ($realfile =~ /Kconfig/ && 1431 if ($realfile =~ /Kconfig/ &&
1396 $line =~ /\+?\s*(---)?help(---)?$/) { 1432 $line =~ /\+\s*(?:---)?help(?:---)?$/) {
1397 my $length = 0; 1433 my $length = 0;
1398 for (my $l = $linenr; defined($lines[$l]); $l++) { 1434 my $cnt = $realcnt;
1399 my $f = $lines[$l]; 1435 my $ln = $linenr + 1;
1436 my $f;
1437 my $is_end = 0;
1438 while ($cnt > 0 && defined $lines[$ln - 1]) {
1439 $f = $lines[$ln - 1];
1440 $cnt-- if ($lines[$ln - 1] !~ /^-/);
1441 $is_end = $lines[$ln - 1] =~ /^\+/;
1442 $ln++;
1443
1444 next if ($f =~ /^-/);
1445 $f =~ s/^.//;
1400 $f =~ s/#.*//; 1446 $f =~ s/#.*//;
1401 $f =~ s/^\s+//; 1447 $f =~ s/^\s+//;
1402 next if ($f =~ /^$/); 1448 next if ($f =~ /^$/);
1403 last if ($f =~ /^\s*config\s/); 1449 if ($f =~ /^\s*config\s/) {
1450 $is_end = 1;
1451 last;
1452 }
1404 $length++; 1453 $length++;
1405 } 1454 }
1406 WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($length < 4); 1455 WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
1456 #print "is_end<$is_end> length<$length>\n";
1407 } 1457 }
1408 1458
1409# check we are in a valid source file if not then ignore this hunk 1459# check we are in a valid source file if not then ignore this hunk
@@ -1450,6 +1500,7 @@ sub process {
1450 $rawline =~ /^\+\s* \s*/) { 1500 $rawline =~ /^\+\s* \s*/) {
1451 my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 1501 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1452 ERROR("code indent should use tabs where possible\n" . $herevet); 1502 ERROR("code indent should use tabs where possible\n" . $herevet);
1503 $rpt_cleaners = 1;
1453 } 1504 }
1454 1505
1455# check for space before tabs. 1506# check for space before tabs.
@@ -1459,10 +1510,13 @@ sub process {
1459 } 1510 }
1460 1511
1461# check for spaces at the beginning of a line. 1512# check for spaces at the beginning of a line.
1462 if ($rawline =~ /^\+ / && $rawline !~ /\+ +\*/) { 1513# Exceptions:
1514# 1) within comments
1515# 2) indented preprocessor commands
1516# 3) hanging labels
1517 if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) {
1463 my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 1518 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1464 WARN("please, no space for starting a line, \ 1519 WARN("please, no spaces at the start of a line\n" . $herevet);
1465 excluding comments\n" . $herevet);
1466 } 1520 }
1467 1521
1468# check we are in a valid C source file if not then ignore this hunk 1522# check we are in a valid C source file if not then ignore this hunk
@@ -1598,7 +1652,7 @@ sub process {
1598 1652
1599 if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { 1653 if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
1600 ERROR("that open brace { should be on the previous line\n" . 1654 ERROR("that open brace { should be on the previous line\n" .
1601 "$here\n$ctx\n$lines[$ctx_ln - 1]\n"); 1655 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
1602 } 1656 }
1603 if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && 1657 if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
1604 $ctx =~ /\)\s*\;\s*$/ && 1658 $ctx =~ /\)\s*\;\s*$/ &&
@@ -1607,7 +1661,7 @@ sub process {
1607 my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); 1661 my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
1608 if ($nindent > $indent) { 1662 if ($nindent > $indent) {
1609 WARN("trailing semicolon indicates no statements, indent implies otherwise\n" . 1663 WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
1610 "$here\n$ctx\n$lines[$ctx_ln - 1]\n"); 1664 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
1611 } 1665 }
1612 } 1666 }
1613 } 1667 }
@@ -1768,8 +1822,17 @@ sub process {
1768 !defined $suppress_export{$realline_next} && 1822 !defined $suppress_export{$realline_next} &&
1769 ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || 1823 ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
1770 $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { 1824 $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
1825 # Handle definitions which produce identifiers with
1826 # a prefix:
1827 # XXX(foo);
1828 # EXPORT_SYMBOL(something_foo);
1771 my $name = $1; 1829 my $name = $1;
1772 if ($stat !~ /(?: 1830 if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
1831 $name =~ /^${Ident}_$2/) {
1832#print "FOO C name<$name>\n";
1833 $suppress_export{$realline_next} = 1;
1834
1835 } elsif ($stat !~ /(?:
1773 \n.}\s*$| 1836 \n.}\s*$|
1774 ^.DEFINE_$Ident\(\Q$name\E\)| 1837 ^.DEFINE_$Ident\(\Q$name\E\)|
1775 ^.DECLARE_$Ident\(\Q$name\E\)| 1838 ^.DECLARE_$Ident\(\Q$name\E\)|
@@ -1806,6 +1869,23 @@ sub process {
1806 $herecurr); 1869 $herecurr);
1807 } 1870 }
1808 1871
1872# check for static const char * arrays.
1873 if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
1874 WARN("static const char * array should probably be static const char * const\n" .
1875 $herecurr);
1876 }
1877
1878# check for static char foo[] = "bar" declarations.
1879 if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
1880 WARN("static char array declaration should probably be static const char\n" .
1881 $herecurr);
1882 }
1883
1884# check for declarations of struct pci_device_id
1885 if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
1886 WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
1887 }
1888
1809# check for new typedefs, only function parameters and sparse annotations 1889# check for new typedefs, only function parameters and sparse annotations
1810# make sense. 1890# make sense.
1811 if ($line =~ /\btypedef\s/ && 1891 if ($line =~ /\btypedef\s/ &&
@@ -1899,6 +1979,11 @@ sub process {
1899 ERROR("open brace '{' following $1 go on the same line\n" . $hereprev); 1979 ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
1900 } 1980 }
1901 1981
1982# missing space after union, struct or enum definition
1983 if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
1984 WARN("missing space after $1 definition\n" . $herecurr);
1985 }
1986
1902# check for spacing round square brackets; allowed: 1987# check for spacing round square brackets; allowed:
1903# 1. with a type on the left -- int [] a; 1988# 1. with a type on the left -- int [] a;
1904# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, 1989# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
@@ -2176,21 +2261,29 @@ sub process {
2176 my $value = $2; 2261 my $value = $2;
2177 2262
2178 # Flatten any parentheses 2263 # Flatten any parentheses
2179 $value =~ s/\)\(/\) \(/g; 2264 $value =~ s/\(/ \(/g;
2265 $value =~ s/\)/\) /g;
2180 while ($value =~ s/\[[^\{\}]*\]/1/ || 2266 while ($value =~ s/\[[^\{\}]*\]/1/ ||
2181 $value !~ /(?:$Ident|-?$Constant)\s* 2267 $value !~ /(?:$Ident|-?$Constant)\s*
2182 $Compare\s* 2268 $Compare\s*
2183 (?:$Ident|-?$Constant)/x && 2269 (?:$Ident|-?$Constant)/x &&
2184 $value =~ s/\([^\(\)]*\)/1/) { 2270 $value =~ s/\([^\(\)]*\)/1/) {
2185 } 2271 }
2186 2272#print "value<$value>\n";
2187 if ($value =~ /^(?:$Ident|-?$Constant)$/) { 2273 if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
2188 ERROR("return is not a function, parentheses are not required\n" . $herecurr); 2274 ERROR("return is not a function, parentheses are not required\n" . $herecurr);
2189 2275
2190 } elsif ($spacing !~ /\s+/) { 2276 } elsif ($spacing !~ /\s+/) {
2191 ERROR("space required before the open parenthesis '('\n" . $herecurr); 2277 ERROR("space required before the open parenthesis '('\n" . $herecurr);
2192 } 2278 }
2193 } 2279 }
2280# Return of what appears to be an errno should normally be -'ve
2281 if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
2282 my $name = $1;
2283 if ($name ne 'EOF' && $name ne 'ERROR') {
2284 WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
2285 }
2286 }
2194 2287
2195# Need a space before open parenthesis after if, while etc 2288# Need a space before open parenthesis after if, while etc
2196 if ($line=~/\b(if|while|for|switch)\(/) { 2289 if ($line=~/\b(if|while|for|switch)\(/) {
@@ -2409,8 +2502,8 @@ sub process {
2409 \.$Ident\s*=\s*| 2502 \.$Ident\s*=\s*|
2410 ^\"|\"$ 2503 ^\"|\"$
2411 }x; 2504 }x;
2412 #print "REST<$rest> dstat<$dstat>\n"; 2505 #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
2413 if ($rest ne '') { 2506 if ($rest ne '' && $rest ne ',') {
2414 if ($rest !~ /while\s*\(/ && 2507 if ($rest !~ /while\s*\(/ &&
2415 $dstat !~ /$exceptions/) 2508 $dstat !~ /$exceptions/)
2416 { 2509 {
@@ -2839,6 +2932,15 @@ sub process {
2839 print "\n" if ($quiet == 0); 2932 print "\n" if ($quiet == 0);
2840 } 2933 }
2841 2934
2935 if ($quiet == 0) {
2936 # If there were whitespace errors which cleanpatch can fix
2937 # then suggest that.
2938 if ($rpt_cleaners) {
2939 print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
2940 print " scripts/cleanfile\n\n";
2941 }
2942 }
2943
2842 if ($clean == 1 && $quiet == 0) { 2944 if ($clean == 1 && $quiet == 0) {
2843 print "$vname has no obvious style problems and is ready for submission.\n" 2945 print "$vname has no obvious style problems and is ready for submission.\n"
2844 } 2946 }
diff --git a/scripts/gcc-goto.sh b/scripts/gcc-goto.sh
new file mode 100644
index 000000000000..520d16b1ffaf
--- /dev/null
+++ b/scripts/gcc-goto.sh
@@ -0,0 +1,5 @@
1#!/bin/sh
2# Test for gcc 'asm goto' suport
3# Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
4
5echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index b2281982f52f..d21ec3a89603 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -13,7 +13,7 @@
13use strict; 13use strict;
14 14
15my $P = $0; 15my $P = $0;
16my $V = '0.24'; 16my $V = '0.26-beta6';
17 17
18use Getopt::Long qw(:config no_auto_abbrev); 18use Getopt::Long qw(:config no_auto_abbrev);
19 19
@@ -24,15 +24,19 @@ my $email_maintainer = 1;
24my $email_list = 1; 24my $email_list = 1;
25my $email_subscriber_list = 0; 25my $email_subscriber_list = 0;
26my $email_git_penguin_chiefs = 0; 26my $email_git_penguin_chiefs = 0;
27my $email_git = 1; 27my $email_git = 0;
28my $email_git_all_signature_types = 0; 28my $email_git_all_signature_types = 0;
29my $email_git_blame = 0; 29my $email_git_blame = 0;
30my $email_git_blame_signatures = 1;
31my $email_git_fallback = 1;
30my $email_git_min_signatures = 1; 32my $email_git_min_signatures = 1;
31my $email_git_max_maintainers = 5; 33my $email_git_max_maintainers = 5;
32my $email_git_min_percent = 5; 34my $email_git_min_percent = 5;
33my $email_git_since = "1-year-ago"; 35my $email_git_since = "1-year-ago";
34my $email_hg_since = "-365"; 36my $email_hg_since = "-365";
37my $interactive = 0;
35my $email_remove_duplicates = 1; 38my $email_remove_duplicates = 1;
39my $email_use_mailmap = 1;
36my $output_multiline = 1; 40my $output_multiline = 1;
37my $output_separator = ", "; 41my $output_separator = ", ";
38my $output_roles = 0; 42my $output_roles = 0;
@@ -49,8 +53,13 @@ my $pattern_depth = 0;
49my $version = 0; 53my $version = 0;
50my $help = 0; 54my $help = 0;
51 55
56my $vcs_used = 0;
57
52my $exit = 0; 58my $exit = 0;
53 59
60my %commit_author_hash;
61my %commit_signer_hash;
62
54my @penguin_chief = (); 63my @penguin_chief = ();
55push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org"); 64push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
56#Andrew wants in on most everything - 2009/01/14 65#Andrew wants in on most everything - 2009/01/14
@@ -73,7 +82,6 @@ my @signature_tags = ();
73push(@signature_tags, "Signed-off-by:"); 82push(@signature_tags, "Signed-off-by:");
74push(@signature_tags, "Reviewed-by:"); 83push(@signature_tags, "Reviewed-by:");
75push(@signature_tags, "Acked-by:"); 84push(@signature_tags, "Acked-by:");
76my $signaturePattern = "\(" . join("|", @signature_tags) . "\)";
77 85
78# rfc822 email address - preloaded methods go here. 86# rfc822 email address - preloaded methods go here.
79my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; 87my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
@@ -86,31 +94,70 @@ my %VCS_cmds;
86my %VCS_cmds_git = ( 94my %VCS_cmds_git = (
87 "execute_cmd" => \&git_execute_cmd, 95 "execute_cmd" => \&git_execute_cmd,
88 "available" => '(which("git") ne "") && (-d ".git")', 96 "available" => '(which("git") ne "") && (-d ".git")',
89 "find_signers_cmd" => "git log --no-color --since=\$email_git_since -- \$file", 97 "find_signers_cmd" =>
90 "find_commit_signers_cmd" => "git log --no-color -1 \$commit", 98 "git log --no-color --since=\$email_git_since " .
99 '--format="GitCommit: %H%n' .
100 'GitAuthor: %an <%ae>%n' .
101 'GitDate: %aD%n' .
102 'GitSubject: %s%n' .
103 '%b%n"' .
104 " -- \$file",
105 "find_commit_signers_cmd" =>
106 "git log --no-color " .
107 '--format="GitCommit: %H%n' .
108 'GitAuthor: %an <%ae>%n' .
109 'GitDate: %aD%n' .
110 'GitSubject: %s%n' .
111 '%b%n"' .
112 " -1 \$commit",
113 "find_commit_author_cmd" =>
114 "git log --no-color " .
115 '--format="GitCommit: %H%n' .
116 'GitAuthor: %an <%ae>%n' .
117 'GitDate: %aD%n' .
118 'GitSubject: %s%n"' .
119 " -1 \$commit",
91 "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file", 120 "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
92 "blame_file_cmd" => "git blame -l \$file", 121 "blame_file_cmd" => "git blame -l \$file",
93 "commit_pattern" => "^commit [0-9a-f]{40,40}", 122 "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
94 "blame_commit_pattern" => "^([0-9a-f]+) " 123 "blame_commit_pattern" => "^([0-9a-f]+) ",
124 "author_pattern" => "^GitAuthor: (.*)",
125 "subject_pattern" => "^GitSubject: (.*)",
95); 126);
96 127
97my %VCS_cmds_hg = ( 128my %VCS_cmds_hg = (
98 "execute_cmd" => \&hg_execute_cmd, 129 "execute_cmd" => \&hg_execute_cmd,
99 "available" => '(which("hg") ne "") && (-d ".hg")', 130 "available" => '(which("hg") ne "") && (-d ".hg")',
100 "find_signers_cmd" => 131 "find_signers_cmd" =>
101 "hg log --date=\$email_hg_since" . 132 "hg log --date=\$email_hg_since " .
102 " --template='commit {node}\\n{desc}\\n' -- \$file", 133 "--template='HgCommit: {node}\\n" .
103 "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit", 134 "HgAuthor: {author}\\n" .
135 "HgSubject: {desc}\\n'" .
136 " -- \$file",
137 "find_commit_signers_cmd" =>
138 "hg log " .
139 "--template='HgSubject: {desc}\\n'" .
140 " -r \$commit",
141 "find_commit_author_cmd" =>
142 "hg log " .
143 "--template='HgCommit: {node}\\n" .
144 "HgAuthor: {author}\\n" .
145 "HgSubject: {desc|firstline}\\n'" .
146 " -r \$commit",
104 "blame_range_cmd" => "", # not supported 147 "blame_range_cmd" => "", # not supported
105 "blame_file_cmd" => "hg blame -c \$file", 148 "blame_file_cmd" => "hg blame -n \$file",
106 "commit_pattern" => "^commit [0-9a-f]{40,40}", 149 "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
107 "blame_commit_pattern" => "^([0-9a-f]+):" 150 "blame_commit_pattern" => "^([ 0-9a-f]+):",
151 "author_pattern" => "^HgAuthor: (.*)",
152 "subject_pattern" => "^HgSubject: (.*)",
108); 153);
109 154
110if (-f "${lk_path}.get_maintainer.conf") { 155my $conf = which_conf(".get_maintainer.conf");
156if (-f $conf) {
111 my @conf_args; 157 my @conf_args;
112 open(my $conffile, '<', "${lk_path}.get_maintainer.conf") 158 open(my $conffile, '<', "$conf")
113 or warn "$P: Can't open .get_maintainer.conf: $!\n"; 159 or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
160
114 while (<$conffile>) { 161 while (<$conffile>) {
115 my $line = $_; 162 my $line = $_;
116 163
@@ -136,13 +183,17 @@ if (!GetOptions(
136 'git!' => \$email_git, 183 'git!' => \$email_git,
137 'git-all-signature-types!' => \$email_git_all_signature_types, 184 'git-all-signature-types!' => \$email_git_all_signature_types,
138 'git-blame!' => \$email_git_blame, 185 'git-blame!' => \$email_git_blame,
186 'git-blame-signatures!' => \$email_git_blame_signatures,
187 'git-fallback!' => \$email_git_fallback,
139 'git-chief-penguins!' => \$email_git_penguin_chiefs, 188 'git-chief-penguins!' => \$email_git_penguin_chiefs,
140 'git-min-signatures=i' => \$email_git_min_signatures, 189 'git-min-signatures=i' => \$email_git_min_signatures,
141 'git-max-maintainers=i' => \$email_git_max_maintainers, 190 'git-max-maintainers=i' => \$email_git_max_maintainers,
142 'git-min-percent=i' => \$email_git_min_percent, 191 'git-min-percent=i' => \$email_git_min_percent,
143 'git-since=s' => \$email_git_since, 192 'git-since=s' => \$email_git_since,
144 'hg-since=s' => \$email_hg_since, 193 'hg-since=s' => \$email_hg_since,
194 'i|interactive!' => \$interactive,
145 'remove-duplicates!' => \$email_remove_duplicates, 195 'remove-duplicates!' => \$email_remove_duplicates,
196 'mailmap!' => \$email_use_mailmap,
146 'm!' => \$email_maintainer, 197 'm!' => \$email_maintainer,
147 'n!' => \$email_usename, 198 'n!' => \$email_usename,
148 'l!' => \$email_list, 199 'l!' => \$email_list,
@@ -181,13 +232,9 @@ if (-t STDIN && !@ARGV) {
181 die "$P: missing patchfile or -f file - use --help if necessary\n"; 232 die "$P: missing patchfile or -f file - use --help if necessary\n";
182} 233}
183 234
184if ($output_separator ne ", ") { 235$output_multiline = 0 if ($output_separator ne ", ");
185 $output_multiline = 0; 236$output_rolestats = 1 if ($interactive);
186} 237$output_roles = 1 if ($output_rolestats);
187
188if ($output_rolestats) {
189 $output_roles = 1;
190}
191 238
192if ($sections) { 239if ($sections) {
193 $email = 0; 240 $email = 0;
@@ -197,6 +244,7 @@ if ($sections) {
197 $subsystem = 0; 244 $subsystem = 0;
198 $web = 0; 245 $web = 0;
199 $keywords = 0; 246 $keywords = 0;
247 $interactive = 0;
200} else { 248} else {
201 my $selections = $email + $scm + $status + $subsystem + $web; 249 my $selections = $email + $scm + $status + $subsystem + $web;
202 if ($selections == 0) { 250 if ($selections == 0) {
@@ -215,10 +263,6 @@ if (!top_of_kernel_tree($lk_path)) {
215 . "a linux kernel source tree.\n"; 263 . "a linux kernel source tree.\n";
216} 264}
217 265
218if ($email_git_all_signature_types) {
219 $signaturePattern = "(.+?)[Bb][Yy]:";
220}
221
222## Read MAINTAINERS for type/value pairs 266## Read MAINTAINERS for type/value pairs
223 267
224my @typevalue = (); 268my @typevalue = ();
@@ -253,31 +297,82 @@ while (<$maint>) {
253} 297}
254close($maint); 298close($maint);
255 299
256my %mailmap;
257 300
258if ($email_remove_duplicates) { 301#
259 open(my $mailmap, '<', "${lk_path}.mailmap") 302# Read mail address map
260 or warn "$P: Can't open .mailmap: $!\n"; 303#
261 while (<$mailmap>) {
262 my $line = $_;
263 304
264 next if ($line =~ m/^\s*#/); 305my $mailmap;
265 next if ($line =~ m/^\s*$/);
266 306
267 my ($name, $address) = parse_email($line); 307read_mailmap();
268 $line = format_email($name, $address, $email_usename);
269 308
270 next if ($line =~ m/^\s*$/); 309sub read_mailmap {
310 $mailmap = {
311 names => {},
312 addresses => {}
313 };
271 314
272 if (exists($mailmap{$name})) { 315 return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
273 my $obj = $mailmap{$name}; 316
274 push(@$obj, $address); 317 open(my $mailmap_file, '<', "${lk_path}.mailmap")
275 } else { 318 or warn "$P: Can't open .mailmap: $!\n";
276 my @arr = ($address); 319
277 $mailmap{$name} = \@arr; 320 while (<$mailmap_file>) {
321 s/#.*$//; #strip comments
322 s/^\s+|\s+$//g; #trim
323
324 next if (/^\s*$/); #skip empty lines
325 #entries have one of the following formats:
326 # name1 <mail1>
327 # <mail1> <mail2>
328 # name1 <mail1> <mail2>
329 # name1 <mail1> name2 <mail2>
330 # (see man git-shortlog)
331 if (/^(.+)<(.+)>$/) {
332 my $real_name = $1;
333 my $address = $2;
334
335 $real_name =~ s/\s+$//;
336 ($real_name, $address) = parse_email("$real_name <$address>");
337 $mailmap->{names}->{$address} = $real_name;
338
339 } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
340 my $real_address = $1;
341 my $wrong_address = $2;
342
343 $mailmap->{addresses}->{$wrong_address} = $real_address;
344
345 } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
346 my $real_name = $1;
347 my $real_address = $2;
348 my $wrong_address = $3;
349
350 $real_name =~ s/\s+$//;
351 ($real_name, $real_address) =
352 parse_email("$real_name <$real_address>");
353 $mailmap->{names}->{$wrong_address} = $real_name;
354 $mailmap->{addresses}->{$wrong_address} = $real_address;
355
356 } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
357 my $real_name = $1;
358 my $real_address = $2;
359 my $wrong_name = $3;
360 my $wrong_address = $4;
361
362 $real_name =~ s/\s+$//;
363 ($real_name, $real_address) =
364 parse_email("$real_name <$real_address>");
365
366 $wrong_name =~ s/\s+$//;
367 ($wrong_name, $wrong_address) =
368 parse_email("$wrong_name <$wrong_address>");
369
370 my $wrong_email = format_email($wrong_name, $wrong_address, 1);
371 $mailmap->{names}->{$wrong_email} = $real_name;
372 $mailmap->{addresses}->{$wrong_email} = $real_address;
278 } 373 }
279 } 374 }
280 close($mailmap); 375 close($mailmap_file);
281} 376}
282 377
283## use the filenames on the command line or find the filenames in the patchfiles 378## use the filenames on the command line or find the filenames in the patchfiles
@@ -302,7 +397,7 @@ foreach my $file (@ARGV) {
302 } 397 }
303 if ($from_filename) { 398 if ($from_filename) {
304 push(@files, $file); 399 push(@files, $file);
305 if (-f $file && ($keywords || $file_emails)) { 400 if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
306 open(my $f, '<', $file) 401 open(my $f, '<', $file)
307 or die "$P: Can't open $file: $!\n"; 402 or die "$P: Can't open $file: $!\n";
308 my $text = do { local($/) ; <$f> }; 403 my $text = do { local($/) ; <$f> };
@@ -357,67 +452,127 @@ foreach my $file (@ARGV) {
357 452
358@file_emails = uniq(@file_emails); 453@file_emails = uniq(@file_emails);
359 454
455my %email_hash_name;
456my %email_hash_address;
360my @email_to = (); 457my @email_to = ();
458my %hash_list_to;
361my @list_to = (); 459my @list_to = ();
362my @scm = (); 460my @scm = ();
363my @web = (); 461my @web = ();
364my @subsystem = (); 462my @subsystem = ();
365my @status = (); 463my @status = ();
464my %deduplicate_name_hash = ();
465my %deduplicate_address_hash = ();
466my $signature_pattern;
366 467
367# Find responsible parties 468my @maintainers = get_maintainers();
368 469
369foreach my $file (@files) { 470if (@maintainers) {
471 @maintainers = merge_email(@maintainers);
472 output(@maintainers);
473}
370 474
371 my %hash; 475if ($scm) {
372 my $tvi = find_first_section(); 476 @scm = uniq(@scm);
373 while ($tvi < @typevalue) { 477 output(@scm);
374 my $start = find_starting_index($tvi); 478}
375 my $end = find_ending_index($tvi); 479
376 my $exclude = 0; 480if ($status) {
377 my $i; 481 @status = uniq(@status);
378 482 output(@status);
379 #Do not match excluded file patterns 483}
380 484
381 for ($i = $start; $i < $end; $i++) { 485if ($subsystem) {
382 my $line = $typevalue[$i]; 486 @subsystem = uniq(@subsystem);
383 if ($line =~ m/^(\C):\s*(.*)/) { 487 output(@subsystem);
384 my $type = $1; 488}
385 my $value = $2; 489
386 if ($type eq 'X') { 490if ($web) {
387 if (file_match_pattern($file, $value)) { 491 @web = uniq(@web);
388 $exclude = 1; 492 output(@web);
389 last; 493}
390 } 494
391 } 495exit($exit);
392 } 496
393 } 497sub get_maintainers {
498 %email_hash_name = ();
499 %email_hash_address = ();
500 %commit_author_hash = ();
501 %commit_signer_hash = ();
502 @email_to = ();
503 %hash_list_to = ();
504 @list_to = ();
505 @scm = ();
506 @web = ();
507 @subsystem = ();
508 @status = ();
509 %deduplicate_name_hash = ();
510 %deduplicate_address_hash = ();
511 if ($email_git_all_signature_types) {
512 $signature_pattern = "(.+?)[Bb][Yy]:";
513 } else {
514 $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
515 }
516
517 # Find responsible parties
518
519 my %exact_pattern_match_hash = ();
520
521 foreach my $file (@files) {
522
523 my %hash;
524 my $tvi = find_first_section();
525 while ($tvi < @typevalue) {
526 my $start = find_starting_index($tvi);
527 my $end = find_ending_index($tvi);
528 my $exclude = 0;
529 my $i;
530
531 #Do not match excluded file patterns
394 532
395 if (!$exclude) {
396 for ($i = $start; $i < $end; $i++) { 533 for ($i = $start; $i < $end; $i++) {
397 my $line = $typevalue[$i]; 534 my $line = $typevalue[$i];
398 if ($line =~ m/^(\C):\s*(.*)/) { 535 if ($line =~ m/^(\C):\s*(.*)/) {
399 my $type = $1; 536 my $type = $1;
400 my $value = $2; 537 my $value = $2;
401 if ($type eq 'F') { 538 if ($type eq 'X') {
402 if (file_match_pattern($file, $value)) { 539 if (file_match_pattern($file, $value)) {
403 my $value_pd = ($value =~ tr@/@@); 540 $exclude = 1;
404 my $file_pd = ($file =~ tr@/@@); 541 last;
405 $value_pd++ if (substr($value,-1,1) ne "/"); 542 }
406 if ($pattern_depth == 0 || 543 }
407 (($file_pd - $value_pd) < $pattern_depth)) { 544 }
408 $hash{$tvi} = $value_pd; 545 }
546
547 if (!$exclude) {
548 for ($i = $start; $i < $end; $i++) {
549 my $line = $typevalue[$i];
550 if ($line =~ m/^(\C):\s*(.*)/) {
551 my $type = $1;
552 my $value = $2;
553 if ($type eq 'F') {
554 if (file_match_pattern($file, $value)) {
555 my $value_pd = ($value =~ tr@/@@);
556 my $file_pd = ($file =~ tr@/@@);
557 $value_pd++ if (substr($value,-1,1) ne "/");
558 $value_pd = -1 if ($value =~ /^\.\*/);
559 if ($value_pd >= $file_pd) {
560 $exact_pattern_match_hash{$file} = 1;
561 }
562 if ($pattern_depth == 0 ||
563 (($file_pd - $value_pd) < $pattern_depth)) {
564 $hash{$tvi} = $value_pd;
565 }
409 } 566 }
410 } 567 }
411 } 568 }
412 } 569 }
413 } 570 }
571 $tvi = $end + 1;
414 } 572 }
415 573
416 $tvi = $end + 1; 574 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
417 } 575 add_categories($line);
418
419 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
420 add_categories($line);
421 if ($sections) { 576 if ($sections) {
422 my $i; 577 my $i;
423 my $start = find_starting_index($line); 578 my $start = find_starting_index($line);
@@ -435,80 +590,71 @@ foreach my $file (@files) {
435 } 590 }
436 print("\n"); 591 print("\n");
437 } 592 }
593 }
438 } 594 }
439 595
440 if ($email && $email_git) { 596 if ($keywords) {
441 vcs_file_signoffs($file); 597 @keyword_tvi = sort_and_uniq(@keyword_tvi);
598 foreach my $line (@keyword_tvi) {
599 add_categories($line);
600 }
442 } 601 }
443 602
444 if ($email && $email_git_blame) { 603 foreach my $email (@email_to, @list_to) {
445 vcs_file_blame($file); 604 $email->[0] = deduplicate_email($email->[0]);
446 } 605 }
447}
448 606
449if ($keywords) { 607 foreach my $file (@files) {
450 @keyword_tvi = sort_and_uniq(@keyword_tvi); 608 if ($email &&
451 foreach my $line (@keyword_tvi) { 609 ($email_git || ($email_git_fallback &&
452 add_categories($line); 610 !$exact_pattern_match_hash{$file}))) {
611 vcs_file_signoffs($file);
612 }
613 if ($email && $email_git_blame) {
614 vcs_file_blame($file);
615 }
453 } 616 }
454}
455 617
456if ($email) { 618 if ($email) {
457 foreach my $chief (@penguin_chief) { 619 foreach my $chief (@penguin_chief) {
458 if ($chief =~ m/^(.*):(.*)/) { 620 if ($chief =~ m/^(.*):(.*)/) {
459 my $email_address; 621 my $email_address;
460 622
461 $email_address = format_email($1, $2, $email_usename); 623 $email_address = format_email($1, $2, $email_usename);
462 if ($email_git_penguin_chiefs) { 624 if ($email_git_penguin_chiefs) {
463 push(@email_to, [$email_address, 'chief penguin']); 625 push(@email_to, [$email_address, 'chief penguin']);
464 } else { 626 } else {
465 @email_to = grep($_->[0] !~ /${email_address}/, @email_to); 627 @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
628 }
466 } 629 }
467 } 630 }
468 }
469 631
470 foreach my $email (@file_emails) { 632 foreach my $email (@file_emails) {
471 my ($name, $address) = parse_email($email); 633 my ($name, $address) = parse_email($email);
472 634
473 my $tmp_email = format_email($name, $address, $email_usename); 635 my $tmp_email = format_email($name, $address, $email_usename);
474 push_email_address($tmp_email, ''); 636 push_email_address($tmp_email, '');
475 add_role($tmp_email, 'in file'); 637 add_role($tmp_email, 'in file');
638 }
476 } 639 }
477}
478 640
479if ($email || $email_list) {
480 my @to = (); 641 my @to = ();
481 if ($email) { 642 if ($email || $email_list) {
482 @to = (@to, @email_to); 643 if ($email) {
483 } 644 @to = (@to, @email_to);
484 if ($email_list) { 645 }
485 @to = (@to, @list_to); 646 if ($email_list) {
647 @to = (@to, @list_to);
648 }
486 } 649 }
487 output(merge_email(@to));
488}
489
490if ($scm) {
491 @scm = uniq(@scm);
492 output(@scm);
493}
494
495if ($status) {
496 @status = uniq(@status);
497 output(@status);
498}
499 650
500if ($subsystem) { 651 if ($interactive) {
501 @subsystem = uniq(@subsystem); 652 @to = interactive_get_maintainers(\@to);
502 output(@subsystem); 653 }
503}
504 654
505if ($web) { 655 return @to;
506 @web = uniq(@web);
507 output(@web);
508} 656}
509 657
510exit($exit);
511
512sub file_match_pattern { 658sub file_match_pattern {
513 my ($file, $pattern) = @_; 659 my ($file, $pattern) = @_;
514 if (substr($pattern, -1) eq "/") { 660 if (substr($pattern, -1) eq "/") {
@@ -537,7 +683,8 @@ MAINTAINER field selection options:
537 --email => print email address(es) if any 683 --email => print email address(es) if any
538 --git => include recent git \*-by: signers 684 --git => include recent git \*-by: signers
539 --git-all-signature-types => include signers regardless of signature type 685 --git-all-signature-types => include signers regardless of signature type
540 or use only ${signaturePattern} signers (default: $email_git_all_signature_types) 686 or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
687 --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
541 --git-chief-penguins => include ${penguin_chiefs} 688 --git-chief-penguins => include ${penguin_chiefs}
542 --git-min-signatures => number of signatures required (default: $email_git_min_signatures) 689 --git-min-signatures => number of signatures required (default: $email_git_min_signatures)
543 --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers) 690 --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
@@ -545,6 +692,7 @@ MAINTAINER field selection options:
545 --git-blame => use git blame to find modified commits for patch or file 692 --git-blame => use git blame to find modified commits for patch or file
546 --git-since => git history to use (default: $email_git_since) 693 --git-since => git history to use (default: $email_git_since)
547 --hg-since => hg history to use (default: $email_hg_since) 694 --hg-since => hg history to use (default: $email_hg_since)
695 --interactive => display a menu (mostly useful if used with the --git option)
548 --m => include maintainer(s) if any 696 --m => include maintainer(s) if any
549 --n => include name 'Full Name <addr\@domain.tld>' 697 --n => include name 'Full Name <addr\@domain.tld>'
550 --l => include list(s) if any 698 --l => include list(s) if any
@@ -565,8 +713,9 @@ Output type options:
565 713
566Other options: 714Other options:
567 --pattern-depth => Number of pattern directory traversals (default: 0 (all)) 715 --pattern-depth => Number of pattern directory traversals (default: 0 (all))
568 --keywords => scan patch for keywords (default: 1 (on)) 716 --keywords => scan patch for keywords (default: $keywords)
569 --sections => print the entire subsystem sections with pattern matches 717 --sections => print all of the subsystem sections with pattern matches
718 --mailmap => use .mailmap file (default: $email_use_mailmap)
570 --version => show version 719 --version => show version
571 --help => show this help information 720 --help => show this help information
572 721
@@ -606,30 +755,30 @@ EOT
606} 755}
607 756
608sub top_of_kernel_tree { 757sub top_of_kernel_tree {
609 my ($lk_path) = @_; 758 my ($lk_path) = @_;
610 759
611 if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") { 760 if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
612 $lk_path .= "/"; 761 $lk_path .= "/";
613 } 762 }
614 if ( (-f "${lk_path}COPYING") 763 if ( (-f "${lk_path}COPYING")
615 && (-f "${lk_path}CREDITS") 764 && (-f "${lk_path}CREDITS")
616 && (-f "${lk_path}Kbuild") 765 && (-f "${lk_path}Kbuild")
617 && (-f "${lk_path}MAINTAINERS") 766 && (-f "${lk_path}MAINTAINERS")
618 && (-f "${lk_path}Makefile") 767 && (-f "${lk_path}Makefile")
619 && (-f "${lk_path}README") 768 && (-f "${lk_path}README")
620 && (-d "${lk_path}Documentation") 769 && (-d "${lk_path}Documentation")
621 && (-d "${lk_path}arch") 770 && (-d "${lk_path}arch")
622 && (-d "${lk_path}include") 771 && (-d "${lk_path}include")
623 && (-d "${lk_path}drivers") 772 && (-d "${lk_path}drivers")
624 && (-d "${lk_path}fs") 773 && (-d "${lk_path}fs")
625 && (-d "${lk_path}init") 774 && (-d "${lk_path}init")
626 && (-d "${lk_path}ipc") 775 && (-d "${lk_path}ipc")
627 && (-d "${lk_path}kernel") 776 && (-d "${lk_path}kernel")
628 && (-d "${lk_path}lib") 777 && (-d "${lk_path}lib")
629 && (-d "${lk_path}scripts")) { 778 && (-d "${lk_path}scripts")) {
630 return 1; 779 return 1;
631 } 780 }
632 return 0; 781 return 0;
633} 782}
634 783
635sub parse_email { 784sub parse_email {
@@ -821,11 +970,19 @@ sub add_categories {
821 } 970 }
822 if ($list_additional =~ m/subscribers-only/) { 971 if ($list_additional =~ m/subscribers-only/) {
823 if ($email_subscriber_list) { 972 if ($email_subscriber_list) {
824 push(@list_to, [$list_address, "subscriber list${list_role}"]); 973 if (!$hash_list_to{lc($list_address)}) {
974 $hash_list_to{lc($list_address)} = 1;
975 push(@list_to, [$list_address,
976 "subscriber list${list_role}"]);
977 }
825 } 978 }
826 } else { 979 } else {
827 if ($email_list) { 980 if ($email_list) {
828 push(@list_to, [$list_address, "open list${list_role}"]); 981 if (!$hash_list_to{lc($list_address)}) {
982 $hash_list_to{lc($list_address)} = 1;
983 push(@list_to, [$list_address,
984 "open list${list_role}"]);
985 }
829 } 986 }
830 } 987 }
831 } elsif ($ptype eq "M") { 988 } elsif ($ptype eq "M") {
@@ -856,15 +1013,12 @@ sub add_categories {
856 } 1013 }
857} 1014}
858 1015
859my %email_hash_name;
860my %email_hash_address;
861
862sub email_inuse { 1016sub email_inuse {
863 my ($name, $address) = @_; 1017 my ($name, $address) = @_;
864 1018
865 return 1 if (($name eq "") && ($address eq "")); 1019 return 1 if (($name eq "") && ($address eq ""));
866 return 1 if (($name ne "") && exists($email_hash_name{$name})); 1020 return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
867 return 1 if (($address ne "") && exists($email_hash_address{$address})); 1021 return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
868 1022
869 return 0; 1023 return 0;
870} 1024}
@@ -882,8 +1036,8 @@ sub push_email_address {
882 push(@email_to, [format_email($name, $address, $email_usename), $role]); 1036 push(@email_to, [format_email($name, $address, $email_usename), $role]);
883 } elsif (!email_inuse($name, $address)) { 1037 } elsif (!email_inuse($name, $address)) {
884 push(@email_to, [format_email($name, $address, $email_usename), $role]); 1038 push(@email_to, [format_email($name, $address, $email_usename), $role]);
885 $email_hash_name{$name}++; 1039 $email_hash_name{lc($name)}++ if ($name ne "");
886 $email_hash_address{$address}++; 1040 $email_hash_address{lc($address)}++;
887 } 1041 }
888 1042
889 return 1; 1043 return 1;
@@ -952,30 +1106,69 @@ sub which {
952 return ""; 1106 return "";
953} 1107}
954 1108
955sub mailmap { 1109sub which_conf {
956 my (@lines) = @_; 1110 my ($conf) = @_;
957 my %hash;
958 1111
959 foreach my $line (@lines) { 1112 foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
960 my ($name, $address) = parse_email($line); 1113 if (-e "$path/$conf") {
961 if (!exists($hash{$name})) { 1114 return "$path/$conf";
962 $hash{$name} = $address;
963 } elsif ($address ne $hash{$name}) {
964 $address = $hash{$name};
965 $line = format_email($name, $address, $email_usename);
966 } 1115 }
967 if (exists($mailmap{$name})) { 1116 }
968 my $obj = $mailmap{$name}; 1117
969 foreach my $map_address (@$obj) { 1118 return "";
970 if (($map_address eq $address) && 1119}
971 ($map_address ne $hash{$name})) { 1120
972 $line = format_email($name, $hash{$name}, $email_usename); 1121sub mailmap_email {
973 } 1122 my ($line) = @_;
974 } 1123
1124 my ($name, $address) = parse_email($line);
1125 my $email = format_email($name, $address, 1);
1126 my $real_name = $name;
1127 my $real_address = $address;
1128
1129 if (exists $mailmap->{names}->{$email} ||
1130 exists $mailmap->{addresses}->{$email}) {
1131 if (exists $mailmap->{names}->{$email}) {
1132 $real_name = $mailmap->{names}->{$email};
1133 }
1134 if (exists $mailmap->{addresses}->{$email}) {
1135 $real_address = $mailmap->{addresses}->{$email};
1136 }
1137 } else {
1138 if (exists $mailmap->{names}->{$address}) {
1139 $real_name = $mailmap->{names}->{$address};
1140 }
1141 if (exists $mailmap->{addresses}->{$address}) {
1142 $real_address = $mailmap->{addresses}->{$address};
975 } 1143 }
976 } 1144 }
1145 return format_email($real_name, $real_address, 1);
1146}
977 1147
978 return @lines; 1148sub mailmap {
1149 my (@addresses) = @_;
1150
1151 my @mapped_emails = ();
1152 foreach my $line (@addresses) {
1153 push(@mapped_emails, mailmap_email($line));
1154 }
1155 merge_by_realname(@mapped_emails) if ($email_use_mailmap);
1156 return @mapped_emails;
1157}
1158
1159sub merge_by_realname {
1160 my %address_map;
1161 my (@emails) = @_;
1162
1163 foreach my $email (@emails) {
1164 my ($name, $address) = parse_email($email);
1165 if (exists $address_map{$name}) {
1166 $address = $address_map{$name};
1167 $email = format_email($name, $address, 1);
1168 } else {
1169 $address_map{$name} = $address;
1170 }
1171 }
979} 1172}
980 1173
981sub git_execute_cmd { 1174sub git_execute_cmd {
@@ -999,10 +1192,30 @@ sub hg_execute_cmd {
999 return @lines; 1192 return @lines;
1000} 1193}
1001 1194
1195sub extract_formatted_signatures {
1196 my (@signature_lines) = @_;
1197
1198 my @type = @signature_lines;
1199
1200 s/\s*(.*):.*/$1/ for (@type);
1201
1202 # cut -f2- -d":"
1203 s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
1204
1205## Reformat email addresses (with names) to avoid badly written signatures
1206
1207 foreach my $signer (@signature_lines) {
1208 $signer = deduplicate_email($signer);
1209 }
1210
1211 return (\@type, \@signature_lines);
1212}
1213
1002sub vcs_find_signers { 1214sub vcs_find_signers {
1003 my ($cmd) = @_; 1215 my ($cmd) = @_;
1004 my @lines = ();
1005 my $commits; 1216 my $commits;
1217 my @lines = ();
1218 my @signatures = ();
1006 1219
1007 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd); 1220 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
1008 1221
@@ -1010,21 +1223,48 @@ sub vcs_find_signers {
1010 1223
1011 $commits = grep(/$pattern/, @lines); # of commits 1224 $commits = grep(/$pattern/, @lines); # of commits
1012 1225
1013 @lines = grep(/^[ \t]*${signaturePattern}.*\@.*$/, @lines); 1226 @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
1227
1228 return (0, @signatures) if !@signatures;
1229
1230 save_commits_by_author(@lines) if ($interactive);
1231 save_commits_by_signer(@lines) if ($interactive);
1232
1233 if (!$email_git_penguin_chiefs) {
1234 @signatures = grep(!/${penguin_chiefs}/i, @signatures);
1235 }
1236
1237 my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
1238
1239 return ($commits, @$signers_ref);
1240}
1241
1242sub vcs_find_author {
1243 my ($cmd) = @_;
1244 my @lines = ();
1245
1246 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
1247
1014 if (!$email_git_penguin_chiefs) { 1248 if (!$email_git_penguin_chiefs) {
1015 @lines = grep(!/${penguin_chiefs}/i, @lines); 1249 @lines = grep(!/${penguin_chiefs}/i, @lines);
1016 } 1250 }
1017 # cut -f2- -d":"
1018 s/.*:\s*(.+)\s*/$1/ for (@lines);
1019 1251
1020## Reformat email addresses (with names) to avoid badly written signatures 1252 return @lines if !@lines;
1021 1253
1254 my @authors = ();
1022 foreach my $line (@lines) { 1255 foreach my $line (@lines) {
1023 my ($name, $address) = parse_email($line); 1256 if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
1024 $line = format_email($name, $address, 1); 1257 my $author = $1;
1258 my ($name, $address) = parse_email($author);
1259 $author = format_email($name, $address, 1);
1260 push(@authors, $author);
1261 }
1025 } 1262 }
1026 1263
1027 return ($commits, @lines); 1264 save_commits_by_author(@lines) if ($interactive);
1265 save_commits_by_signer(@lines) if ($interactive);
1266
1267 return @authors;
1028} 1268}
1029 1269
1030sub vcs_save_commits { 1270sub vcs_save_commits {
@@ -1084,6 +1324,10 @@ sub vcs_blame {
1084 @commits = vcs_save_commits($cmd); 1324 @commits = vcs_save_commits($cmd);
1085 } 1325 }
1086 1326
1327 foreach my $commit (@commits) {
1328 $commit =~ s/^\^//g;
1329 }
1330
1087 return @commits; 1331 return @commits;
1088} 1332}
1089 1333
@@ -1092,7 +1336,7 @@ sub vcs_exists {
1092 %VCS_cmds = %VCS_cmds_git; 1336 %VCS_cmds = %VCS_cmds_git;
1093 return 1 if eval $VCS_cmds{"available"}; 1337 return 1 if eval $VCS_cmds{"available"};
1094 %VCS_cmds = %VCS_cmds_hg; 1338 %VCS_cmds = %VCS_cmds_hg;
1095 return 1 if eval $VCS_cmds{"available"}; 1339 return 2 if eval $VCS_cmds{"available"};
1096 %VCS_cmds = (); 1340 %VCS_cmds = ();
1097 if (!$printed_novcs) { 1341 if (!$printed_novcs) {
1098 warn("$P: No supported VCS found. Add --nogit to options?\n"); 1342 warn("$P: No supported VCS found. Add --nogit to options?\n");
@@ -1104,6 +1348,405 @@ sub vcs_exists {
1104 return 0; 1348 return 0;
1105} 1349}
1106 1350
1351sub vcs_is_git {
1352 vcs_exists();
1353 return $vcs_used == 1;
1354}
1355
1356sub vcs_is_hg {
1357 return $vcs_used == 2;
1358}
1359
1360sub interactive_get_maintainers {
1361 my ($list_ref) = @_;
1362 my @list = @$list_ref;
1363
1364 vcs_exists();
1365
1366 my %selected;
1367 my %authored;
1368 my %signed;
1369 my $count = 0;
1370 my $maintained = 0;
1371 foreach my $entry (@list) {
1372 $maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
1373 $selected{$count} = 1;
1374 $authored{$count} = 0;
1375 $signed{$count} = 0;
1376 $count++;
1377 }
1378
1379 #menu loop
1380 my $done = 0;
1381 my $print_options = 0;
1382 my $redraw = 1;
1383 while (!$done) {
1384 $count = 0;
1385 if ($redraw) {
1386 printf STDERR "\n%1s %2s %-65s",
1387 "*", "#", "email/list and role:stats";
1388 if ($email_git ||
1389 ($email_git_fallback && !$maintained) ||
1390 $email_git_blame) {
1391 print STDERR "auth sign";
1392 }
1393 print STDERR "\n";
1394 foreach my $entry (@list) {
1395 my $email = $entry->[0];
1396 my $role = $entry->[1];
1397 my $sel = "";
1398 $sel = "*" if ($selected{$count});
1399 my $commit_author = $commit_author_hash{$email};
1400 my $commit_signer = $commit_signer_hash{$email};
1401 my $authored = 0;
1402 my $signed = 0;
1403 $authored++ for (@{$commit_author});
1404 $signed++ for (@{$commit_signer});
1405 printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
1406 printf STDERR "%4d %4d", $authored, $signed
1407 if ($authored > 0 || $signed > 0);
1408 printf STDERR "\n %s\n", $role;
1409 if ($authored{$count}) {
1410 my $commit_author = $commit_author_hash{$email};
1411 foreach my $ref (@{$commit_author}) {
1412 print STDERR " Author: @{$ref}[1]\n";
1413 }
1414 }
1415 if ($signed{$count}) {
1416 my $commit_signer = $commit_signer_hash{$email};
1417 foreach my $ref (@{$commit_signer}) {
1418 print STDERR " @{$ref}[2]: @{$ref}[1]\n";
1419 }
1420 }
1421
1422 $count++;
1423 }
1424 }
1425 my $date_ref = \$email_git_since;
1426 $date_ref = \$email_hg_since if (vcs_is_hg());
1427 if ($print_options) {
1428 $print_options = 0;
1429 if (vcs_exists()) {
1430 print STDERR <<EOT
1431
1432Version Control options:
1433g use git history [$email_git]
1434gf use git-fallback [$email_git_fallback]
1435b use git blame [$email_git_blame]
1436bs use blame signatures [$email_git_blame_signatures]
1437c# minimum commits [$email_git_min_signatures]
1438%# min percent [$email_git_min_percent]
1439d# history to use [$$date_ref]
1440x# max maintainers [$email_git_max_maintainers]
1441t all signature types [$email_git_all_signature_types]
1442m use .mailmap [$email_use_mailmap]
1443EOT
1444 }
1445 print STDERR <<EOT
1446
1447Additional options:
14480 toggle all
1449tm toggle maintainers
1450tg toggle git entries
1451tl toggle open list entries
1452ts toggle subscriber list entries
1453f emails in file [$file_emails]
1454k keywords in file [$keywords]
1455r remove duplicates [$email_remove_duplicates]
1456p# pattern match depth [$pattern_depth]
1457EOT
1458 }
1459 print STDERR
1460"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
1461
1462 my $input = <STDIN>;
1463 chomp($input);
1464
1465 $redraw = 1;
1466 my $rerun = 0;
1467 my @wish = split(/[, ]+/, $input);
1468 foreach my $nr (@wish) {
1469 $nr = lc($nr);
1470 my $sel = substr($nr, 0, 1);
1471 my $str = substr($nr, 1);
1472 my $val = 0;
1473 $val = $1 if $str =~ /^(\d+)$/;
1474
1475 if ($sel eq "y") {
1476 $interactive = 0;
1477 $done = 1;
1478 $output_rolestats = 0;
1479 $output_roles = 0;
1480 last;
1481 } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
1482 $selected{$nr - 1} = !$selected{$nr - 1};
1483 } elsif ($sel eq "*" || $sel eq '^') {
1484 my $toggle = 0;
1485 $toggle = 1 if ($sel eq '*');
1486 for (my $i = 0; $i < $count; $i++) {
1487 $selected{$i} = $toggle;
1488 }
1489 } elsif ($sel eq "0") {
1490 for (my $i = 0; $i < $count; $i++) {
1491 $selected{$i} = !$selected{$i};
1492 }
1493 } elsif ($sel eq "t") {
1494 if (lc($str) eq "m") {
1495 for (my $i = 0; $i < $count; $i++) {
1496 $selected{$i} = !$selected{$i}
1497 if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
1498 }
1499 } elsif (lc($str) eq "g") {
1500 for (my $i = 0; $i < $count; $i++) {
1501 $selected{$i} = !$selected{$i}
1502 if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
1503 }
1504 } elsif (lc($str) eq "l") {
1505 for (my $i = 0; $i < $count; $i++) {
1506 $selected{$i} = !$selected{$i}
1507 if ($list[$i]->[1] =~ /^(open list)/i);
1508 }
1509 } elsif (lc($str) eq "s") {
1510 for (my $i = 0; $i < $count; $i++) {
1511 $selected{$i} = !$selected{$i}
1512 if ($list[$i]->[1] =~ /^(subscriber list)/i);
1513 }
1514 }
1515 } elsif ($sel eq "a") {
1516 if ($val > 0 && $val <= $count) {
1517 $authored{$val - 1} = !$authored{$val - 1};
1518 } elsif ($str eq '*' || $str eq '^') {
1519 my $toggle = 0;
1520 $toggle = 1 if ($str eq '*');
1521 for (my $i = 0; $i < $count; $i++) {
1522 $authored{$i} = $toggle;
1523 }
1524 }
1525 } elsif ($sel eq "s") {
1526 if ($val > 0 && $val <= $count) {
1527 $signed{$val - 1} = !$signed{$val - 1};
1528 } elsif ($str eq '*' || $str eq '^') {
1529 my $toggle = 0;
1530 $toggle = 1 if ($str eq '*');
1531 for (my $i = 0; $i < $count; $i++) {
1532 $signed{$i} = $toggle;
1533 }
1534 }
1535 } elsif ($sel eq "o") {
1536 $print_options = 1;
1537 $redraw = 1;
1538 } elsif ($sel eq "g") {
1539 if ($str eq "f") {
1540 bool_invert(\$email_git_fallback);
1541 } else {
1542 bool_invert(\$email_git);
1543 }
1544 $rerun = 1;
1545 } elsif ($sel eq "b") {
1546 if ($str eq "s") {
1547 bool_invert(\$email_git_blame_signatures);
1548 } else {
1549 bool_invert(\$email_git_blame);
1550 }
1551 $rerun = 1;
1552 } elsif ($sel eq "c") {
1553 if ($val > 0) {
1554 $email_git_min_signatures = $val;
1555 $rerun = 1;
1556 }
1557 } elsif ($sel eq "x") {
1558 if ($val > 0) {
1559 $email_git_max_maintainers = $val;
1560 $rerun = 1;
1561 }
1562 } elsif ($sel eq "%") {
1563 if ($str ne "" && $val >= 0) {
1564 $email_git_min_percent = $val;
1565 $rerun = 1;
1566 }
1567 } elsif ($sel eq "d") {
1568 if (vcs_is_git()) {
1569 $email_git_since = $str;
1570 } elsif (vcs_is_hg()) {
1571 $email_hg_since = $str;
1572 }
1573 $rerun = 1;
1574 } elsif ($sel eq "t") {
1575 bool_invert(\$email_git_all_signature_types);
1576 $rerun = 1;
1577 } elsif ($sel eq "f") {
1578 bool_invert(\$file_emails);
1579 $rerun = 1;
1580 } elsif ($sel eq "r") {
1581 bool_invert(\$email_remove_duplicates);
1582 $rerun = 1;
1583 } elsif ($sel eq "m") {
1584 bool_invert(\$email_use_mailmap);
1585 read_mailmap();
1586 $rerun = 1;
1587 } elsif ($sel eq "k") {
1588 bool_invert(\$keywords);
1589 $rerun = 1;
1590 } elsif ($sel eq "p") {
1591 if ($str ne "" && $val >= 0) {
1592 $pattern_depth = $val;
1593 $rerun = 1;
1594 }
1595 } elsif ($sel eq "h" || $sel eq "?") {
1596 print STDERR <<EOT
1597
1598Interactive mode allows you to select the various maintainers, submitters,
1599commit signers and mailing lists that could be CC'd on a patch.
1600
1601Any *'d entry is selected.
1602
1603If you have git or hg installed, you can choose to summarize the commit
1604history of files in the patch. Also, each line of the current file can
1605be matched to its commit author and that commits signers with blame.
1606
1607Various knobs exist to control the length of time for active commit
1608tracking, the maximum number of commit authors and signers to add,
1609and such.
1610
1611Enter selections at the prompt until you are satisfied that the selected
1612maintainers are appropriate. You may enter multiple selections separated
1613by either commas or spaces.
1614
1615EOT
1616 } else {
1617 print STDERR "invalid option: '$nr'\n";
1618 $redraw = 0;
1619 }
1620 }
1621 if ($rerun) {
1622 print STDERR "git-blame can be very slow, please have patience..."
1623 if ($email_git_blame);
1624 goto &get_maintainers;
1625 }
1626 }
1627
1628 #drop not selected entries
1629 $count = 0;
1630 my @new_emailto = ();
1631 foreach my $entry (@list) {
1632 if ($selected{$count}) {
1633 push(@new_emailto, $list[$count]);
1634 }
1635 $count++;
1636 }
1637 return @new_emailto;
1638}
1639
1640sub bool_invert {
1641 my ($bool_ref) = @_;
1642
1643 if ($$bool_ref) {
1644 $$bool_ref = 0;
1645 } else {
1646 $$bool_ref = 1;
1647 }
1648}
1649
1650sub deduplicate_email {
1651 my ($email) = @_;
1652
1653 my $matched = 0;
1654 my ($name, $address) = parse_email($email);
1655 $email = format_email($name, $address, 1);
1656 $email = mailmap_email($email);
1657
1658 return $email if (!$email_remove_duplicates);
1659
1660 ($name, $address) = parse_email($email);
1661
1662 if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
1663 $name = $deduplicate_name_hash{lc($name)}->[0];
1664 $address = $deduplicate_name_hash{lc($name)}->[1];
1665 $matched = 1;
1666 } elsif ($deduplicate_address_hash{lc($address)}) {
1667 $name = $deduplicate_address_hash{lc($address)}->[0];
1668 $address = $deduplicate_address_hash{lc($address)}->[1];
1669 $matched = 1;
1670 }
1671 if (!$matched) {
1672 $deduplicate_name_hash{lc($name)} = [ $name, $address ];
1673 $deduplicate_address_hash{lc($address)} = [ $name, $address ];
1674 }
1675 $email = format_email($name, $address, 1);
1676 $email = mailmap_email($email);
1677 return $email;
1678}
1679
1680sub save_commits_by_author {
1681 my (@lines) = @_;
1682
1683 my @authors = ();
1684 my @commits = ();
1685 my @subjects = ();
1686
1687 foreach my $line (@lines) {
1688 if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
1689 my $author = $1;
1690 $author = deduplicate_email($author);
1691 push(@authors, $author);
1692 }
1693 push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
1694 push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
1695 }
1696
1697 for (my $i = 0; $i < @authors; $i++) {
1698 my $exists = 0;
1699 foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
1700 if (@{$ref}[0] eq $commits[$i] &&
1701 @{$ref}[1] eq $subjects[$i]) {
1702 $exists = 1;
1703 last;
1704 }
1705 }
1706 if (!$exists) {
1707 push(@{$commit_author_hash{$authors[$i]}},
1708 [ ($commits[$i], $subjects[$i]) ]);
1709 }
1710 }
1711}
1712
1713sub save_commits_by_signer {
1714 my (@lines) = @_;
1715
1716 my $commit = "";
1717 my $subject = "";
1718
1719 foreach my $line (@lines) {
1720 $commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
1721 $subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
1722 if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
1723 my @signatures = ($line);
1724 my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
1725 my @types = @$types_ref;
1726 my @signers = @$signers_ref;
1727
1728 my $type = $types[0];
1729 my $signer = $signers[0];
1730
1731 $signer = deduplicate_email($signer);
1732
1733 my $exists = 0;
1734 foreach my $ref(@{$commit_signer_hash{$signer}}) {
1735 if (@{$ref}[0] eq $commit &&
1736 @{$ref}[1] eq $subject &&
1737 @{$ref}[2] eq $type) {
1738 $exists = 1;
1739 last;
1740 }
1741 }
1742 if (!$exists) {
1743 push(@{$commit_signer_hash{$signer}},
1744 [ ($commit, $subject, $type) ]);
1745 }
1746 }
1747 }
1748}
1749
1107sub vcs_assign { 1750sub vcs_assign {
1108 my ($role, $divisor, @lines) = @_; 1751 my ($role, $divisor, @lines) = @_;
1109 1752
@@ -1117,9 +1760,9 @@ sub vcs_assign {
1117 $divisor = 1; 1760 $divisor = 1;
1118 } 1761 }
1119 1762
1120 if ($email_remove_duplicates) { 1763 @lines = mailmap(@lines);
1121 @lines = mailmap(@lines); 1764
1122 } 1765 return if (@lines <= 0);
1123 1766
1124 @lines = sort(@lines); 1767 @lines = sort(@lines);
1125 1768
@@ -1152,12 +1795,18 @@ sub vcs_file_signoffs {
1152 my @signers = (); 1795 my @signers = ();
1153 my $commits; 1796 my $commits;
1154 1797
1155 return if (!vcs_exists()); 1798 $vcs_used = vcs_exists();
1799 return if (!$vcs_used);
1156 1800
1157 my $cmd = $VCS_cmds{"find_signers_cmd"}; 1801 my $cmd = $VCS_cmds{"find_signers_cmd"};
1158 $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd 1802 $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
1159 1803
1160 ($commits, @signers) = vcs_find_signers($cmd); 1804 ($commits, @signers) = vcs_find_signers($cmd);
1805
1806 foreach my $signer (@signers) {
1807 $signer = deduplicate_email($signer);
1808 }
1809
1161 vcs_assign("commit_signer", $commits, @signers); 1810 vcs_assign("commit_signer", $commits, @signers);
1162} 1811}
1163 1812
@@ -1165,29 +1814,114 @@ sub vcs_file_blame {
1165 my ($file) = @_; 1814 my ($file) = @_;
1166 1815
1167 my @signers = (); 1816 my @signers = ();
1817 my @all_commits = ();
1168 my @commits = (); 1818 my @commits = ();
1169 my $total_commits; 1819 my $total_commits;
1820 my $total_lines;
1170 1821
1171 return if (!vcs_exists()); 1822 $vcs_used = vcs_exists();
1823 return if (!$vcs_used);
1172 1824
1173 @commits = vcs_blame($file); 1825 @all_commits = vcs_blame($file);
1174 @commits = uniq(@commits); 1826 @commits = uniq(@all_commits);
1175 $total_commits = @commits; 1827 $total_commits = @commits;
1828 $total_lines = @all_commits;
1176 1829
1177 foreach my $commit (@commits) { 1830 if ($email_git_blame_signatures) {
1178 my $commit_count; 1831 if (vcs_is_hg()) {
1179 my @commit_signers = (); 1832 my $commit_count;
1833 my @commit_signers = ();
1834 my $commit = join(" -r ", @commits);
1835 my $cmd;
1836
1837 $cmd = $VCS_cmds{"find_commit_signers_cmd"};
1838 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
1839
1840 ($commit_count, @commit_signers) = vcs_find_signers($cmd);
1841
1842 push(@signers, @commit_signers);
1843 } else {
1844 foreach my $commit (@commits) {
1845 my $commit_count;
1846 my @commit_signers = ();
1847 my $cmd;
1180 1848
1181 my $cmd = $VCS_cmds{"find_commit_signers_cmd"}; 1849 $cmd = $VCS_cmds{"find_commit_signers_cmd"};
1182 $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd 1850 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
1183 1851
1184 ($commit_count, @commit_signers) = vcs_find_signers($cmd); 1852 ($commit_count, @commit_signers) = vcs_find_signers($cmd);
1185 push(@signers, @commit_signers); 1853
1854 push(@signers, @commit_signers);
1855 }
1856 }
1186 } 1857 }
1187 1858
1188 if ($from_filename) { 1859 if ($from_filename) {
1860 if ($output_rolestats) {
1861 my @blame_signers;
1862 if (vcs_is_hg()) {{ # Double brace for last exit
1863 my $commit_count;
1864 my @commit_signers = ();
1865 @commits = uniq(@commits);
1866 @commits = sort(@commits);
1867 my $commit = join(" -r ", @commits);
1868 my $cmd;
1869
1870 $cmd = $VCS_cmds{"find_commit_author_cmd"};
1871 $cmd =~ s/(\$\w+)/$1/eeg; #substitute variables in $cmd
1872
1873 my @lines = ();
1874
1875 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
1876
1877 if (!$email_git_penguin_chiefs) {
1878 @lines = grep(!/${penguin_chiefs}/i, @lines);
1879 }
1880
1881 last if !@lines;
1882
1883 my @authors = ();
1884 foreach my $line (@lines) {
1885 if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
1886 my $author = $1;
1887 $author = deduplicate_email($author);
1888 push(@authors, $author);
1889 }
1890 }
1891
1892 save_commits_by_author(@lines) if ($interactive);
1893 save_commits_by_signer(@lines) if ($interactive);
1894
1895 push(@signers, @authors);
1896 }}
1897 else {
1898 foreach my $commit (@commits) {
1899 my $i;
1900 my $cmd = $VCS_cmds{"find_commit_author_cmd"};
1901 $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
1902 my @author = vcs_find_author($cmd);
1903 next if !@author;
1904
1905 my $formatted_author = deduplicate_email($author[0]);
1906
1907 my $count = grep(/$commit/, @all_commits);
1908 for ($i = 0; $i < $count ; $i++) {
1909 push(@blame_signers, $formatted_author);
1910 }
1911 }
1912 }
1913 if (@blame_signers) {
1914 vcs_assign("authored lines", $total_lines, @blame_signers);
1915 }
1916 }
1917 foreach my $signer (@signers) {
1918 $signer = deduplicate_email($signer);
1919 }
1189 vcs_assign("commits", $total_commits, @signers); 1920 vcs_assign("commits", $total_commits, @signers);
1190 } else { 1921 } else {
1922 foreach my $signer (@signers) {
1923 $signer = deduplicate_email($signer);
1924 }
1191 vcs_assign("modified commits", $total_commits, @signers); 1925 vcs_assign("modified commits", $total_commits, @signers);
1192 } 1926 }
1193} 1927}
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index e3902fb39afd..60dd3eb9366e 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -107,12 +107,8 @@ static int read_symbol(FILE *in, struct sym_entry *s)
107 107
108 rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str); 108 rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, str);
109 if (rc != 3) { 109 if (rc != 3) {
110 if (rc != EOF) { 110 if (rc != EOF && fgets(str, 500, in) == NULL)
111 /* skip line. sym is used as dummy to 111 fprintf(stderr, "Read error or end of file.\n");
112 * shut of "warn_unused_result" warning.
113 */
114 sym = fgets(str, 500, in);
115 }
116 return -1; 112 return -1;
117 } 113 }
118 114
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 102e1235fd5c..cdb6dc1f6458 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -44,12 +44,13 @@ use strict;
44# Note: This only supports 'c'. 44# Note: This only supports 'c'.
45 45
46# usage: 46# usage:
47# kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ] 47# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
48# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile 48# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
49# or 49# or
50# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile 50# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
51# 51#
52# Set output format using one of -docbook -html -text or -man. Default is man. 52# Set output format using one of -docbook -html -text or -man. Default is man.
53# The -list format is for internal use by docproc.
53# 54#
54# -no-doc-sections 55# -no-doc-sections
55# Do not output DOC: sections 56# Do not output DOC: sections
@@ -210,9 +211,16 @@ my %highlights_text = ( $type_constant, "\$1",
210 $type_param, "\$1" ); 211 $type_param, "\$1" );
211my $blankline_text = ""; 212my $blankline_text = "";
212 213
214# list mode
215my %highlights_list = ( $type_constant, "\$1",
216 $type_func, "\$1",
217 $type_struct, "\$1",
218 $type_param, "\$1" );
219my $blankline_list = "";
213 220
214sub usage { 221sub usage {
215 print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n"; 222 print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
223 print " [ -no-doc-sections ]\n";
216 print " [ -function funcname [ -function funcname ...] ]\n"; 224 print " [ -function funcname [ -function funcname ...] ]\n";
217 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; 225 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
218 print " c source file(s) > outputfile\n"; 226 print " c source file(s) > outputfile\n";
@@ -318,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
318 $output_mode = "xml"; 326 $output_mode = "xml";
319 %highlights = %highlights_xml; 327 %highlights = %highlights_xml;
320 $blankline = $blankline_xml; 328 $blankline = $blankline_xml;
329 } elsif ($cmd eq "-list") {
330 $output_mode = "list";
331 %highlights = %highlights_list;
332 $blankline = $blankline_list;
321 } elsif ($cmd eq "-gnome") { 333 } elsif ($cmd eq "-gnome") {
322 $output_mode = "gnome"; 334 $output_mode = "gnome";
323 %highlights = %highlights_gnome; 335 %highlights = %highlights_gnome;
@@ -1361,6 +1373,42 @@ sub output_blockhead_text(%) {
1361 } 1373 }
1362} 1374}
1363 1375
1376## list mode output functions
1377
1378sub output_function_list(%) {
1379 my %args = %{$_[0]};
1380
1381 print $args{'function'} . "\n";
1382}
1383
1384# output enum in list
1385sub output_enum_list(%) {
1386 my %args = %{$_[0]};
1387 print $args{'enum'} . "\n";
1388}
1389
1390# output typedef in list
1391sub output_typedef_list(%) {
1392 my %args = %{$_[0]};
1393 print $args{'typedef'} . "\n";
1394}
1395
1396# output struct as list
1397sub output_struct_list(%) {
1398 my %args = %{$_[0]};
1399
1400 print $args{'struct'} . "\n";
1401}
1402
1403sub output_blockhead_list(%) {
1404 my %args = %{$_[0]};
1405 my ($parameter, $section);
1406
1407 foreach $section (@{$args{'sectionlist'}}) {
1408 print "DOC: $section\n";
1409 }
1410}
1411
1364## 1412##
1365# generic output function for all types (function, struct/union, typedef, enum); 1413# generic output function for all types (function, struct/union, typedef, enum);
1366# calls the generated, variable output_ function name based on 1414# calls the generated, variable output_ function name based on
@@ -1679,7 +1727,7 @@ sub check_sections($$$$$$) {
1679 foreach $px (0 .. $#prms) { 1727 foreach $px (0 .. $#prms) {
1680 $prm_clean = $prms[$px]; 1728 $prm_clean = $prms[$px];
1681 $prm_clean =~ s/\[.*\]//; 1729 $prm_clean =~ s/\[.*\]//;
1682 $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//; 1730 $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
1683 # ignore array size in a parameter string; 1731 # ignore array size in a parameter string;
1684 # however, the original param string may contain 1732 # however, the original param string may contain
1685 # spaces, e.g.: addr[6 + 2] 1733 # spaces, e.g.: addr[6 + 2]
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 1ec7158b6c1f..33122ca04e7c 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1208,6 +1208,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
1208 * .cpuinit.data => __cpudata 1208 * .cpuinit.data => __cpudata
1209 * .memexitconst => __memconst 1209 * .memexitconst => __memconst
1210 * etc. 1210 * etc.
1211 *
1212 * The memory of returned value has been allocated on a heap. The user of this
1213 * method should free it after usage.
1211*/ 1214*/
1212static char *sec2annotation(const char *s) 1215static char *sec2annotation(const char *s)
1213{ 1216{
@@ -1230,7 +1233,7 @@ static char *sec2annotation(const char *s)
1230 strcat(p, "data "); 1233 strcat(p, "data ");
1231 else 1234 else
1232 strcat(p, " "); 1235 strcat(p, " ");
1233 return r; /* we leak her but we do not care */ 1236 return r;
1234 } else { 1237 } else {
1235 return strdup(""); 1238 return strdup("");
1236 } 1239 }
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
new file mode 100644
index 000000000000..26e1271259ba
--- /dev/null
+++ b/scripts/recordmcount.c
@@ -0,0 +1,363 @@
1/*
2 * recordmcount.c: construct a table of the locations of calls to 'mcount'
3 * so that ftrace can find them quickly.
4 * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
5 * Licensed under the GNU General Public License, version 2 (GPLv2).
6 *
7 * Restructured to fit Linux format, as well as other updates:
8 * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
9 */
10
11/*
12 * Strategy: alter the .o file in-place.
13 *
14 * Append a new STRTAB that has the new section names, followed by a new array
15 * ElfXX_Shdr[] that has the new section headers, followed by the section
16 * contents for __mcount_loc and its relocations. The old shstrtab strings,
17 * and the old ElfXX_Shdr[] array, remain as "garbage" (commonly, a couple
18 * kilobytes.) Subsequent processing by /bin/ld (or the kernel module loader)
19 * will ignore the garbage regions, because they are not designated by the
20 * new .e_shoff nor the new ElfXX_Shdr[]. [In order to remove the garbage,
21 * then use "ld -r" to create a new file that omits the garbage.]
22 */
23
24#include <sys/types.h>
25#include <sys/mman.h>
26#include <sys/stat.h>
27#include <elf.h>
28#include <fcntl.h>
29#include <setjmp.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35static int fd_map; /* File descriptor for file being modified. */
36static int mmap_failed; /* Boolean flag. */
37static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
38static char gpfx; /* prefix for global symbol name (sometimes '_') */
39static struct stat sb; /* Remember .st_size, etc. */
40static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
41
42/* setjmp() return values */
43enum {
44 SJ_SETJMP = 0, /* hardwired first return */
45 SJ_FAIL,
46 SJ_SUCCEED
47};
48
49/* Per-file resource cleanup when multiple files. */
50static void
51cleanup(void)
52{
53 if (!mmap_failed)
54 munmap(ehdr_curr, sb.st_size);
55 else
56 free(ehdr_curr);
57 close(fd_map);
58}
59
60static void __attribute__((noreturn))
61fail_file(void)
62{
63 cleanup();
64 longjmp(jmpenv, SJ_FAIL);
65}
66
67static void __attribute__((noreturn))
68succeed_file(void)
69{
70 cleanup();
71 longjmp(jmpenv, SJ_SUCCEED);
72}
73
74/* ulseek, uread, ...: Check return value for errors. */
75
76static off_t
77ulseek(int const fd, off_t const offset, int const whence)
78{
79 off_t const w = lseek(fd, offset, whence);
80 if ((off_t)-1 == w) {
81 perror("lseek");
82 fail_file();
83 }
84 return w;
85}
86
87static size_t
88uread(int const fd, void *const buf, size_t const count)
89{
90 size_t const n = read(fd, buf, count);
91 if (n != count) {
92 perror("read");
93 fail_file();
94 }
95 return n;
96}
97
98static size_t
99uwrite(int const fd, void const *const buf, size_t const count)
100{
101 size_t const n = write(fd, buf, count);
102 if (n != count) {
103 perror("write");
104 fail_file();
105 }
106 return n;
107}
108
109static void *
110umalloc(size_t size)
111{
112 void *const addr = malloc(size);
113 if (0 == addr) {
114 fprintf(stderr, "malloc failed: %zu bytes\n", size);
115 fail_file();
116 }
117 return addr;
118}
119
120/*
121 * Get the whole file as a programming convenience in order to avoid
122 * malloc+lseek+read+free of many pieces. If successful, then mmap
123 * avoids copying unused pieces; else just read the whole file.
124 * Open for both read and write; new info will be appended to the file.
125 * Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
126 * do not propagate to the file until an explicit overwrite at the last.
127 * This preserves most aspects of consistency (all except .st_size)
128 * for simultaneous readers of the file while we are appending to it.
129 * However, multiple writers still are bad. We choose not to use
130 * locking because it is expensive and the use case of kernel build
131 * makes multiple writers unlikely.
132 */
133static void *mmap_file(char const *fname)
134{
135 void *addr;
136
137 fd_map = open(fname, O_RDWR);
138 if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
139 perror(fname);
140 fail_file();
141 }
142 if (!S_ISREG(sb.st_mode)) {
143 fprintf(stderr, "not a regular file: %s\n", fname);
144 fail_file();
145 }
146 addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
147 fd_map, 0);
148 mmap_failed = 0;
149 if (MAP_FAILED == addr) {
150 mmap_failed = 1;
151 addr = umalloc(sb.st_size);
152 uread(fd_map, addr, sb.st_size);
153 }
154 return addr;
155}
156
157/* w8rev, w8nat, ...: Handle endianness. */
158
159static uint64_t w8rev(uint64_t const x)
160{
161 return ((0xff & (x >> (0 * 8))) << (7 * 8))
162 | ((0xff & (x >> (1 * 8))) << (6 * 8))
163 | ((0xff & (x >> (2 * 8))) << (5 * 8))
164 | ((0xff & (x >> (3 * 8))) << (4 * 8))
165 | ((0xff & (x >> (4 * 8))) << (3 * 8))
166 | ((0xff & (x >> (5 * 8))) << (2 * 8))
167 | ((0xff & (x >> (6 * 8))) << (1 * 8))
168 | ((0xff & (x >> (7 * 8))) << (0 * 8));
169}
170
171static uint32_t w4rev(uint32_t const x)
172{
173 return ((0xff & (x >> (0 * 8))) << (3 * 8))
174 | ((0xff & (x >> (1 * 8))) << (2 * 8))
175 | ((0xff & (x >> (2 * 8))) << (1 * 8))
176 | ((0xff & (x >> (3 * 8))) << (0 * 8));
177}
178
179static uint32_t w2rev(uint16_t const x)
180{
181 return ((0xff & (x >> (0 * 8))) << (1 * 8))
182 | ((0xff & (x >> (1 * 8))) << (0 * 8));
183}
184
185static uint64_t w8nat(uint64_t const x)
186{
187 return x;
188}
189
190static uint32_t w4nat(uint32_t const x)
191{
192 return x;
193}
194
195static uint32_t w2nat(uint16_t const x)
196{
197 return x;
198}
199
200static uint64_t (*w8)(uint64_t);
201static uint32_t (*w)(uint32_t);
202static uint32_t (*w2)(uint16_t);
203
204/* Names of the sections that could contain calls to mcount. */
205static int
206is_mcounted_section_name(char const *const txtname)
207{
208 return 0 == strcmp(".text", txtname) ||
209 0 == strcmp(".sched.text", txtname) ||
210 0 == strcmp(".spinlock.text", txtname) ||
211 0 == strcmp(".irqentry.text", txtname) ||
212 0 == strcmp(".text.unlikely", txtname);
213}
214
215/* 32 bit and 64 bit are very similar */
216#include "recordmcount.h"
217#define RECORD_MCOUNT_64
218#include "recordmcount.h"
219
220static void
221do_file(char const *const fname)
222{
223 Elf32_Ehdr *const ehdr = mmap_file(fname);
224 unsigned int reltype = 0;
225
226 ehdr_curr = ehdr;
227 w = w4nat;
228 w2 = w2nat;
229 w8 = w8nat;
230 switch (ehdr->e_ident[EI_DATA]) {
231 static unsigned int const endian = 1;
232 default: {
233 fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
234 ehdr->e_ident[EI_DATA], fname);
235 fail_file();
236 } break;
237 case ELFDATA2LSB: {
238 if (1 != *(unsigned char const *)&endian) {
239 /* main() is big endian, file.o is little endian. */
240 w = w4rev;
241 w2 = w2rev;
242 w8 = w8rev;
243 }
244 } break;
245 case ELFDATA2MSB: {
246 if (0 != *(unsigned char const *)&endian) {
247 /* main() is little endian, file.o is big endian. */
248 w = w4rev;
249 w2 = w2rev;
250 w8 = w8rev;
251 }
252 } break;
253 } /* end switch */
254 if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
255 || ET_REL != w2(ehdr->e_type)
256 || EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
257 fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
258 fail_file();
259 }
260
261 gpfx = 0;
262 switch (w2(ehdr->e_machine)) {
263 default: {
264 fprintf(stderr, "unrecognized e_machine %d %s\n",
265 w2(ehdr->e_machine), fname);
266 fail_file();
267 } break;
268 case EM_386: reltype = R_386_32; break;
269 case EM_ARM: reltype = R_ARM_ABS32; break;
270 case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
271 case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
272 case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break;
273 case EM_S390: /* reltype: e_class */ gpfx = '_'; break;
274 case EM_SH: reltype = R_SH_DIR32; break;
275 case EM_SPARCV9: reltype = R_SPARC_64; gpfx = '_'; break;
276 case EM_X86_64: reltype = R_X86_64_64; break;
277 } /* end switch */
278
279 switch (ehdr->e_ident[EI_CLASS]) {
280 default: {
281 fprintf(stderr, "unrecognized ELF class %d %s\n",
282 ehdr->e_ident[EI_CLASS], fname);
283 fail_file();
284 } break;
285 case ELFCLASS32: {
286 if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
287 || sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
288 fprintf(stderr,
289 "unrecognized ET_REL file: %s\n", fname);
290 fail_file();
291 }
292 if (EM_S390 == w2(ehdr->e_machine))
293 reltype = R_390_32;
294 do32(ehdr, fname, reltype);
295 } break;
296 case ELFCLASS64: {
297 Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
298 if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
299 || sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
300 fprintf(stderr,
301 "unrecognized ET_REL file: %s\n", fname);
302 fail_file();
303 }
304 if (EM_S390 == w2(ghdr->e_machine))
305 reltype = R_390_64;
306 do64(ghdr, fname, reltype);
307 } break;
308 } /* end switch */
309
310 cleanup();
311}
312
313int
314main(int argc, char const *argv[])
315{
316 const char ftrace[] = "kernel/trace/ftrace.o";
317 int ftrace_size = sizeof(ftrace) - 1;
318 int n_error = 0; /* gcc-4.3.0 false positive complaint */
319
320 if (argc <= 1) {
321 fprintf(stderr, "usage: recordmcount file.o...\n");
322 return 0;
323 }
324
325 /* Process each file in turn, allowing deep failure. */
326 for (--argc, ++argv; 0 < argc; --argc, ++argv) {
327 int const sjval = setjmp(jmpenv);
328 int len;
329
330 /*
331 * The file kernel/trace/ftrace.o references the mcount
332 * function but does not call it. Since ftrace.o should
333 * not be traced anyway, we just skip it.
334 */
335 len = strlen(argv[0]);
336 if (len >= ftrace_size &&
337 strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
338 continue;
339
340 switch (sjval) {
341 default: {
342 fprintf(stderr, "internal error: %s\n", argv[0]);
343 exit(1);
344 } break;
345 case SJ_SETJMP: { /* normal sequence */
346 /* Avoid problems if early cleanup() */
347 fd_map = -1;
348 ehdr_curr = NULL;
349 mmap_failed = 1;
350 do_file(argv[0]);
351 } break;
352 case SJ_FAIL: { /* error in do_file or below */
353 ++n_error;
354 } break;
355 case SJ_SUCCEED: { /* premature success */
356 /* do nothing */
357 } break;
358 } /* end switch */
359 }
360 return !!n_error;
361}
362
363
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
new file mode 100644
index 000000000000..7f39d0943d2d
--- /dev/null
+++ b/scripts/recordmcount.h
@@ -0,0 +1,366 @@
1/*
2 * recordmcount.h
3 *
4 * This code was taken out of recordmcount.c written by
5 * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
6 *
7 * The original code had the same algorithms for both 32bit
8 * and 64bit ELF files, but the code was duplicated to support
9 * the difference in structures that were used. This
10 * file creates a macro of everything that is different between
11 * the 64 and 32 bit code, such that by including this header
12 * twice we can create both sets of functions by including this
13 * header once with RECORD_MCOUNT_64 undefined, and again with
14 * it defined.
15 *
16 * This conversion to macros was done by:
17 * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
18 *
19 * Licensed under the GNU General Public License, version 2 (GPLv2).
20 */
21#undef append_func
22#undef sift_rel_mcount
23#undef find_secsym_ndx
24#undef __has_rel_mcount
25#undef has_rel_mcount
26#undef tot_relsize
27#undef do_func
28#undef Elf_Ehdr
29#undef Elf_Shdr
30#undef Elf_Rel
31#undef Elf_Rela
32#undef Elf_Sym
33#undef ELF_R_SYM
34#undef ELF_R_INFO
35#undef ELF_ST_BIND
36#undef uint_t
37#undef _w
38#undef _align
39#undef _size
40
41#ifdef RECORD_MCOUNT_64
42# define append_func append64
43# define sift_rel_mcount sift64_rel_mcount
44# define find_secsym_ndx find64_secsym_ndx
45# define __has_rel_mcount __has64_rel_mcount
46# define has_rel_mcount has64_rel_mcount
47# define tot_relsize tot64_relsize
48# define do_func do64
49# define Elf_Ehdr Elf64_Ehdr
50# define Elf_Shdr Elf64_Shdr
51# define Elf_Rel Elf64_Rel
52# define Elf_Rela Elf64_Rela
53# define Elf_Sym Elf64_Sym
54# define ELF_R_SYM ELF64_R_SYM
55# define ELF_R_INFO ELF64_R_INFO
56# define ELF_ST_BIND ELF64_ST_BIND
57# define uint_t uint64_t
58# define _w w8
59# define _align 7u
60# define _size 8
61#else
62# define append_func append32
63# define sift_rel_mcount sift32_rel_mcount
64# define find_secsym_ndx find32_secsym_ndx
65# define __has_rel_mcount __has32_rel_mcount
66# define has_rel_mcount has32_rel_mcount
67# define tot_relsize tot32_relsize
68# define do_func do32
69# define Elf_Ehdr Elf32_Ehdr
70# define Elf_Shdr Elf32_Shdr
71# define Elf_Rel Elf32_Rel
72# define Elf_Rela Elf32_Rela
73# define Elf_Sym Elf32_Sym
74# define ELF_R_SYM ELF32_R_SYM
75# define ELF_R_INFO ELF32_R_INFO
76# define ELF_ST_BIND ELF32_ST_BIND
77# define uint_t uint32_t
78# define _w w
79# define _align 3u
80# define _size 4
81#endif
82
83/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
84static void append_func(Elf_Ehdr *const ehdr,
85 Elf_Shdr *const shstr,
86 uint_t const *const mloc0,
87 uint_t const *const mlocp,
88 Elf_Rel const *const mrel0,
89 Elf_Rel const *const mrelp,
90 unsigned int const rel_entsize,
91 unsigned int const symsec_sh_link)
92{
93 /* Begin constructing output file */
94 Elf_Shdr mcsec;
95 char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
96 ? ".rela__mcount_loc"
97 : ".rel__mcount_loc";
98 unsigned const old_shnum = w2(ehdr->e_shnum);
99 uint_t const old_shoff = _w(ehdr->e_shoff);
100 uint_t const old_shstr_sh_size = _w(shstr->sh_size);
101 uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
102 uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
103 uint_t new_e_shoff;
104
105 shstr->sh_size = _w(t);
106 shstr->sh_offset = _w(sb.st_size);
107 t += sb.st_size;
108 t += (_align & -t); /* word-byte align */
109 new_e_shoff = t;
110
111 /* body for new shstrtab */
112 ulseek(fd_map, sb.st_size, SEEK_SET);
113 uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
114 uwrite(fd_map, mc_name, 1 + strlen(mc_name));
115
116 /* old(modified) Elf_Shdr table, word-byte aligned */
117 ulseek(fd_map, t, SEEK_SET);
118 t += sizeof(Elf_Shdr) * old_shnum;
119 uwrite(fd_map, old_shoff + (void *)ehdr,
120 sizeof(Elf_Shdr) * old_shnum);
121
122 /* new sections __mcount_loc and .rel__mcount_loc */
123 t += 2*sizeof(mcsec);
124 mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
125 + old_shstr_sh_size);
126 mcsec.sh_type = w(SHT_PROGBITS);
127 mcsec.sh_flags = _w(SHF_ALLOC);
128 mcsec.sh_addr = 0;
129 mcsec.sh_offset = _w(t);
130 mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
131 mcsec.sh_link = 0;
132 mcsec.sh_info = 0;
133 mcsec.sh_addralign = _w(_size);
134 mcsec.sh_entsize = _w(_size);
135 uwrite(fd_map, &mcsec, sizeof(mcsec));
136
137 mcsec.sh_name = w(old_shstr_sh_size);
138 mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
139 ? w(SHT_RELA)
140 : w(SHT_REL);
141 mcsec.sh_flags = 0;
142 mcsec.sh_addr = 0;
143 mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
144 mcsec.sh_size = _w((void *)mrelp - (void *)mrel0);
145 mcsec.sh_link = w(symsec_sh_link);
146 mcsec.sh_info = w(old_shnum);
147 mcsec.sh_addralign = _w(_size);
148 mcsec.sh_entsize = _w(rel_entsize);
149 uwrite(fd_map, &mcsec, sizeof(mcsec));
150
151 uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
152 uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
153
154 ehdr->e_shoff = _w(new_e_shoff);
155 ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
156 ulseek(fd_map, 0, SEEK_SET);
157 uwrite(fd_map, ehdr, sizeof(*ehdr));
158}
159
160
161/*
162 * Look at the relocations in order to find the calls to mcount.
163 * Accumulate the section offsets that are found, and their relocation info,
164 * onto the end of the existing arrays.
165 */
166static uint_t *sift_rel_mcount(uint_t *mlocp,
167 unsigned const offbase,
168 Elf_Rel **const mrelpp,
169 Elf_Shdr const *const relhdr,
170 Elf_Ehdr const *const ehdr,
171 unsigned const recsym,
172 uint_t const recval,
173 unsigned const reltype)
174{
175 uint_t *const mloc0 = mlocp;
176 Elf_Rel *mrelp = *mrelpp;
177 Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
178 + (void *)ehdr);
179 unsigned const symsec_sh_link = w(relhdr->sh_link);
180 Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
181 Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
182 + (void *)ehdr);
183
184 Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
185 char const *const str0 = (char const *)(_w(strsec->sh_offset)
186 + (void *)ehdr);
187
188 Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
189 + (void *)ehdr);
190 unsigned rel_entsize = _w(relhdr->sh_entsize);
191 unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
192 Elf_Rel const *relp = rel0;
193
194 unsigned mcountsym = 0;
195 unsigned t;
196
197 for (t = nrel; t; --t) {
198 if (!mcountsym) {
199 Elf_Sym const *const symp =
200 &sym0[ELF_R_SYM(_w(relp->r_info))];
201 char const *symname = &str0[w(symp->st_name)];
202
203 if ('.' == symname[0])
204 ++symname; /* ppc64 hack */
205 if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
206 symname))
207 mcountsym = ELF_R_SYM(_w(relp->r_info));
208 }
209
210 if (mcountsym == ELF_R_SYM(_w(relp->r_info))) {
211 uint_t const addend = _w(_w(relp->r_offset) - recval);
212
213 mrelp->r_offset = _w(offbase
214 + ((void *)mlocp - (void *)mloc0));
215 mrelp->r_info = _w(ELF_R_INFO(recsym, reltype));
216 if (sizeof(Elf_Rela) == rel_entsize) {
217 ((Elf_Rela *)mrelp)->r_addend = addend;
218 *mlocp++ = 0;
219 } else
220 *mlocp++ = addend;
221
222 mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
223 }
224 relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
225 }
226 *mrelpp = mrelp;
227 return mlocp;
228}
229
230
231/*
232 * Find a symbol in the given section, to be used as the base for relocating
233 * the table of offsets of calls to mcount. A local or global symbol suffices,
234 * but avoid a Weak symbol because it may be overridden; the change in value
235 * would invalidate the relocations of the offsets of the calls to mcount.
236 * Often the found symbol will be the unnamed local symbol generated by
237 * GNU 'as' for the start of each section. For example:
238 * Num: Value Size Type Bind Vis Ndx Name
239 * 2: 00000000 0 SECTION LOCAL DEFAULT 1
240 */
241static unsigned find_secsym_ndx(unsigned const txtndx,
242 char const *const txtname,
243 uint_t *const recvalp,
244 Elf_Shdr const *const symhdr,
245 Elf_Ehdr const *const ehdr)
246{
247 Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
248 + (void *)ehdr);
249 unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
250 Elf_Sym const *symp;
251 unsigned t;
252
253 for (symp = sym0, t = nsym; t; --t, ++symp) {
254 unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
255
256 if (txtndx == w2(symp->st_shndx)
257 /* avoid STB_WEAK */
258 && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
259 *recvalp = _w(symp->st_value);
260 return symp - sym0;
261 }
262 }
263 fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
264 txtndx, txtname);
265 fail_file();
266}
267
268
269/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
270static char const *
271__has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
272 Elf_Shdr const *const shdr0,
273 char const *const shstrtab,
274 char const *const fname)
275{
276 /* .sh_info depends on .sh_type == SHT_REL[,A] */
277 Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
278 char const *const txtname = &shstrtab[w(txthdr->sh_name)];
279
280 if (0 == strcmp("__mcount_loc", txtname)) {
281 fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
282 fname);
283 succeed_file();
284 }
285 if (SHT_PROGBITS != w(txthdr->sh_type) ||
286 !is_mcounted_section_name(txtname))
287 return NULL;
288 return txtname;
289}
290
291static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
292 Elf_Shdr const *const shdr0,
293 char const *const shstrtab,
294 char const *const fname)
295{
296 if (SHT_REL != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
297 return NULL;
298 return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
299}
300
301
302static unsigned tot_relsize(Elf_Shdr const *const shdr0,
303 unsigned nhdr,
304 const char *const shstrtab,
305 const char *const fname)
306{
307 unsigned totrelsz = 0;
308 Elf_Shdr const *shdrp = shdr0;
309
310 for (; nhdr; --nhdr, ++shdrp) {
311 if (has_rel_mcount(shdrp, shdr0, shstrtab, fname))
312 totrelsz += _w(shdrp->sh_size);
313 }
314 return totrelsz;
315}
316
317
318/* Overall supervision for Elf32 ET_REL file. */
319static void
320do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
321{
322 Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
323 + (void *)ehdr);
324 unsigned const nhdr = w2(ehdr->e_shnum);
325 Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
326 char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
327 + (void *)ehdr);
328
329 Elf_Shdr const *relhdr;
330 unsigned k;
331
332 /* Upper bound on space: assume all relevant relocs are for mcount. */
333 unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
334 Elf_Rel *const mrel0 = umalloc(totrelsz);
335 Elf_Rel * mrelp = mrel0;
336
337 /* 2*sizeof(address) <= sizeof(Elf_Rel) */
338 uint_t *const mloc0 = umalloc(totrelsz>>1);
339 uint_t * mlocp = mloc0;
340
341 unsigned rel_entsize = 0;
342 unsigned symsec_sh_link = 0;
343
344 for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
345 char const *const txtname = has_rel_mcount(relhdr, shdr0,
346 shstrtab, fname);
347 if (txtname) {
348 uint_t recval = 0;
349 unsigned const recsym = find_secsym_ndx(
350 w(relhdr->sh_info), txtname, &recval,
351 &shdr0[symsec_sh_link = w(relhdr->sh_link)],
352 ehdr);
353
354 rel_entsize = _w(relhdr->sh_entsize);
355 mlocp = sift_rel_mcount(mlocp,
356 (void *)mlocp - (void *)mloc0, &mrelp,
357 relhdr, ehdr, recsym, recval, reltype);
358 }
359 }
360 if (mloc0 != mlocp) {
361 append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
362 rel_entsize, symsec_sh_link);
363 }
364 free(mrel0);
365 free(mloc0);
366}
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0171060b5fd6..1d7963f4ee79 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -159,6 +159,7 @@ my $section_regex; # Find the start of a section
159my $function_regex; # Find the name of a function 159my $function_regex; # Find the name of a function
160 # (return offset and func name) 160 # (return offset and func name)
161my $mcount_regex; # Find the call site to mcount (return offset) 161my $mcount_regex; # Find the call site to mcount (return offset)
162my $mcount_adjust; # Address adjustment to mcount offset
162my $alignment; # The .align value to use for $mcount_section 163my $alignment; # The .align value to use for $mcount_section
163my $section_type; # Section header plus possible alignment command 164my $section_type; # Section header plus possible alignment command
164my $can_use_local = 0; # If we can use local function references 165my $can_use_local = 0; # If we can use local function references
@@ -213,6 +214,7 @@ $section_regex = "Disassembly of section\\s+(\\S+):";
213$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; 214$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
214$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; 215$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
215$section_type = '@progbits'; 216$section_type = '@progbits';
217$mcount_adjust = 0;
216$type = ".long"; 218$type = ".long";
217 219
218if ($arch eq "x86_64") { 220if ($arch eq "x86_64") {
@@ -268,6 +270,8 @@ if ($arch eq "x86_64") {
268} elsif ($arch eq "arm") { 270} elsif ($arch eq "arm") {
269 $alignment = 2; 271 $alignment = 2;
270 $section_type = '%progbits'; 272 $section_type = '%progbits';
273 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
274 "\\s+(__gnu_mcount_nc|mcount)\$";
271 275
272} elsif ($arch eq "ia64") { 276} elsif ($arch eq "ia64") {
273 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 277 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
@@ -351,6 +355,9 @@ if ($arch eq "x86_64") {
351} elsif ($arch eq "microblaze") { 355} elsif ($arch eq "microblaze") {
352 # Microblaze calls '_mcount' instead of plain 'mcount'. 356 # Microblaze calls '_mcount' instead of plain 'mcount'.
353 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; 357 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
358} elsif ($arch eq "blackfin") {
359 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
360 $mcount_adjust = -4;
354} else { 361} else {
355 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; 362 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
356} 363}
@@ -511,7 +518,7 @@ while (<IN>) {
511 } 518 }
512 # is this a call site to mcount? If so, record it to print later 519 # is this a call site to mcount? If so, record it to print later
513 if ($text_found && /$mcount_regex/) { 520 if ($text_found && /$mcount_regex/) {
514 push(@offsets, hex $1); 521 push(@offsets, (hex $1) + $mcount_adjust);
515 } 522 }
516} 523}
517 524
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 057b6b3c5dfb..ef8729f48586 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -160,8 +160,10 @@ if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
160 # full scm version string 160 # full scm version string
161 res="$res$(scm_version)" 161 res="$res$(scm_version)"
162else 162else
163 # apped a plus sign if the repository is not in a clean tagged 163 # append a plus sign if the repository is not in a clean
164 # state and LOCALVERSION= is not specified 164 # annotated or signed tagged state (as git describe only
165 # looks at signed or annotated tags - git tag -a/-s) and
166 # LOCALVERSION= is not specified
165 if test "${LOCALVERSION+set}" != "set"; then 167 if test "${LOCALVERSION+set}" != "set"; then
166 scm=$(scm_version --short) 168 scm=$(scm_version --short)
167 res="$res${scm:++}" 169 res="$res${scm:++}"