aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-09-11 18:55:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-09-11 19:49:21 -0400
commiteda603f6cdba4b14dbf80531fab2fe545232e7a0 (patch)
tree94e88243e917d55fac8e8ca79f51ea7c8fcc45ed
parent1f3a66889c4c80c821f3eadf899c140e91452f8e (diff)
docbook: warn on unused doc entries
When you don't use !E or !I but only !F, then it's very easy to miss including some functions, structs etc. in documentation. To help finding which ones were missed, allow printing out the unused ones as warnings. For example, using this on mac80211 yields a lot of warnings like this: Warning: didn't use docs for DOC: mac80211 workqueue Warning: didn't use docs for ieee80211_max_queues Warning: didn't use docs for ieee80211_bss_change Warning: didn't use docs for ieee80211_bss_conf when generating the documentation for it. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/kernel-doc-nano-HOWTO.txt5
-rw-r--r--scripts/basic/docproc.c129
-rwxr-xr-xscripts/kernel-doc52
3 files changed, 183 insertions, 3 deletions
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index 27a52b35d55b..3d8a97747f77 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -345,5 +345,10 @@ documentation, in <filename>, for the functions listed.
345section titled <section title> from <filename>. 345section titled <section title> from <filename>.
346Spaces are allowed in <section title>; do not quote the <section title>. 346Spaces are allowed in <section title>; do not quote the <section title>.
347 347
348!C<filename> is replaced by nothing, but makes the tools check that
349all DOC: sections and documented functions, symbols, etc. are used.
350This makes sense to use when you use !F/!P only and want to verify
351that all documentation is included.
352
348Tim. 353Tim.
349*/ <twaugh@redhat.com> 354*/ <twaugh@redhat.com>
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/kernel-doc b/scripts/kernel-doc
index a68240c188f3..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