Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Johannes Berg and committed by
Linus Torvalds
eda603f6 1f3a6688

+183 -3
+5
Documentation/kernel-doc-nano-HOWTO.txt
··· 345 section titled <section title> from <filename>. 346 Spaces are allowed in <section title>; do not quote the <section title>. 347 348 Tim. 349 */ <twaugh@redhat.com>
··· 345 section titled <section title> from <filename>. 346 Spaces are allowed in <section title>; do not quote the <section title>. 347 348 + !C<filename> is replaced by nothing, but makes the tools check that 349 + all DOC: sections and documented functions, symbols, etc. are used. 350 + This makes sense to use when you use !F/!P only and want to verify 351 + that all documentation is included. 352 + 353 Tim. 354 */ <twaugh@redhat.com>
+128 -1
scripts/basic/docproc.c
··· 34 * 35 */ 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <ctype.h> 41 #include <unistd.h> 42 #include <limits.h> 43 #include <sys/types.h> 44 #include <sys/wait.h> 45 ··· 56 FILEONLY *internalfunctions; 57 FILEONLY *externalfunctions; 58 FILEONLY *symbolsonly; 59 60 typedef void FILELINE(char * file, char * line); 61 FILELINE * singlefunctions; ··· 68 #define KERNELDOCPATH "scripts/" 69 #define KERNELDOC "kernel-doc" 70 #define DOCBOOK "-docbook" 71 #define FUNCTION "-function" 72 #define NOFUNCTION "-nofunction" 73 #define NODOCSECTIONS "-no-doc-sections" 74 75 static char *srctree, *kernsrctree; 76 77 static void usage (void) 78 { ··· 269 struct symfile * sym = &symfilelist[i]; 270 for (j=0; j < sym->symbolcnt; j++) { 271 vec[idx++] = type; 272 vec[idx++] = sym->symbollist[j].name; 273 } 274 } ··· 309 vec[idx++] = &line[i]; 310 } 311 } 312 vec[idx++] = filename; 313 vec[idx] = NULL; 314 exec_kernel_doc(vec); ··· 333 if (*s == '\n') 334 *s = '\0'; 335 336 vec[0] = KERNELDOC; 337 vec[1] = DOCBOOK; 338 vec[2] = FUNCTION; ··· 346 exec_kernel_doc(vec); 347 } 348 349 /* 350 * Parse file, calling action specific functions for: 351 * 1) Lines containing !E ··· 431 * 3) Lines containing !D 432 * 4) Lines containing !F 433 * 5) Lines containing !P 434 - * 6) Default lines - lines not matching the above 435 */ 436 static void parse_file(FILE *infile) 437 { ··· 475 s++; 476 docsection(line + 2, s); 477 break; 478 default: 479 defaultline(line); 480 } ··· 496 int main(int argc, char *argv[]) 497 { 498 FILE * infile; 499 500 srctree = getenv("SRCTREE"); 501 if (!srctree) ··· 532 symbolsonly = find_export_symbols; 533 singlefunctions = noaction2; 534 docsection = noaction2; 535 parse_file(infile); 536 537 /* Rewind to start from beginning of file again */ ··· 543 symbolsonly = printline; 544 singlefunctions = singfunc; 545 docsection = docsect; 546 547 parse_file(infile); 548 } 549 else if (strcmp("depend", argv[1]) == 0) 550 { ··· 565 symbolsonly = adddep; 566 singlefunctions = adddep2; 567 docsection = adddep2; 568 parse_file(infile); 569 printf("\n"); 570 }
··· 34 * 35 */ 36 37 + #define _GNU_SOURCE 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <ctype.h> 42 #include <unistd.h> 43 #include <limits.h> 44 + #include <errno.h> 45 #include <sys/types.h> 46 #include <sys/wait.h> 47 ··· 54 FILEONLY *internalfunctions; 55 FILEONLY *externalfunctions; 56 FILEONLY *symbolsonly; 57 + FILEONLY *findall; 58 59 typedef void FILELINE(char * file, char * line); 60 FILELINE * singlefunctions; ··· 65 #define KERNELDOCPATH "scripts/" 66 #define KERNELDOC "kernel-doc" 67 #define DOCBOOK "-docbook" 68 + #define LIST "-list" 69 #define FUNCTION "-function" 70 #define NOFUNCTION "-nofunction" 71 #define NODOCSECTIONS "-no-doc-sections" 72 73 static char *srctree, *kernsrctree; 74 + 75 + static char **all_list = NULL; 76 + static int all_list_len = 0; 77 + 78 + static void consume_symbol(const char *sym) 79 + { 80 + int i; 81 + 82 + for (i = 0; i < all_list_len; i++) { 83 + if (!all_list[i]) 84 + continue; 85 + if (strcmp(sym, all_list[i])) 86 + continue; 87 + all_list[i] = NULL; 88 + break; 89 + } 90 + } 91 92 static void usage (void) 93 { ··· 248 struct symfile * sym = &symfilelist[i]; 249 for (j=0; j < sym->symbolcnt; j++) { 250 vec[idx++] = type; 251 + consume_symbol(sym->symbollist[j].name); 252 vec[idx++] = sym->symbollist[j].name; 253 } 254 } ··· 287 vec[idx++] = &line[i]; 288 } 289 } 290 + for (i = 0; i < idx; i++) { 291 + if (strcmp(vec[i], FUNCTION)) 292 + continue; 293 + consume_symbol(vec[i + 1]); 294 + } 295 vec[idx++] = filename; 296 vec[idx] = NULL; 297 exec_kernel_doc(vec); ··· 306 if (*s == '\n') 307 *s = '\0'; 308 309 + asprintf(&s, "DOC: %s", line); 310 + consume_symbol(s); 311 + free(s); 312 + 313 vec[0] = KERNELDOC; 314 vec[1] = DOCBOOK; 315 vec[2] = FUNCTION; ··· 315 exec_kernel_doc(vec); 316 } 317 318 + static void find_all_symbols(char *filename) 319 + { 320 + char *vec[4]; /* kerneldoc -list file NULL */ 321 + pid_t pid; 322 + int ret, i, count, start; 323 + char real_filename[PATH_MAX + 1]; 324 + int pipefd[2]; 325 + char *data, *str; 326 + size_t data_len = 0; 327 + 328 + vec[0] = KERNELDOC; 329 + vec[1] = LIST; 330 + vec[2] = filename; 331 + vec[3] = NULL; 332 + 333 + if (pipe(pipefd)) { 334 + perror("pipe"); 335 + exit(1); 336 + } 337 + 338 + switch (pid=fork()) { 339 + case -1: 340 + perror("fork"); 341 + exit(1); 342 + case 0: 343 + close(pipefd[0]); 344 + dup2(pipefd[1], 1); 345 + memset(real_filename, 0, sizeof(real_filename)); 346 + strncat(real_filename, kernsrctree, PATH_MAX); 347 + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, 348 + PATH_MAX - strlen(real_filename)); 349 + execvp(real_filename, vec); 350 + fprintf(stderr, "exec "); 351 + perror(real_filename); 352 + exit(1); 353 + default: 354 + close(pipefd[1]); 355 + data = malloc(4096); 356 + do { 357 + while ((ret = read(pipefd[0], 358 + data + data_len, 359 + 4096)) > 0) { 360 + data_len += ret; 361 + data = realloc(data, data_len + 4096); 362 + } 363 + } while (ret == -EAGAIN); 364 + if (ret != 0) { 365 + perror("read"); 366 + exit(1); 367 + } 368 + waitpid(pid, &ret ,0); 369 + } 370 + if (WIFEXITED(ret)) 371 + exitstatus |= WEXITSTATUS(ret); 372 + else 373 + exitstatus = 0xff; 374 + 375 + count = 0; 376 + /* poor man's strtok, but with counting */ 377 + for (i = 0; i < data_len; i++) { 378 + if (data[i] == '\n') { 379 + count++; 380 + data[i] = '\0'; 381 + } 382 + } 383 + start = all_list_len; 384 + all_list_len += count; 385 + all_list = realloc(all_list, sizeof(char *) * all_list_len); 386 + str = data; 387 + for (i = 0; i < data_len && start != all_list_len; i++) { 388 + if (data[i] == '\0') { 389 + all_list[start] = str; 390 + str = data + i + 1; 391 + start++; 392 + } 393 + } 394 + } 395 + 396 /* 397 * Parse file, calling action specific functions for: 398 * 1) Lines containing !E ··· 322 * 3) Lines containing !D 323 * 4) Lines containing !F 324 * 5) Lines containing !P 325 + * 6) Lines containing !C 326 + * 7) Default lines - lines not matching the above 327 */ 328 static void parse_file(FILE *infile) 329 { ··· 365 s++; 366 docsection(line + 2, s); 367 break; 368 + case 'C': 369 + while (*s && !isspace(*s)) s++; 370 + *s = '\0'; 371 + if (findall) 372 + findall(line+2); 373 + break; 374 default: 375 defaultline(line); 376 } ··· 380 int main(int argc, char *argv[]) 381 { 382 FILE * infile; 383 + int i; 384 385 srctree = getenv("SRCTREE"); 386 if (!srctree) ··· 415 symbolsonly = find_export_symbols; 416 singlefunctions = noaction2; 417 docsection = noaction2; 418 + findall = find_all_symbols; 419 parse_file(infile); 420 421 /* Rewind to start from beginning of file again */ ··· 425 symbolsonly = printline; 426 singlefunctions = singfunc; 427 docsection = docsect; 428 + findall = NULL; 429 430 parse_file(infile); 431 + 432 + for (i = 0; i < all_list_len; i++) { 433 + if (!all_list[i]) 434 + continue; 435 + fprintf(stderr, "Warning: didn't use docs for %s\n", 436 + all_list[i]); 437 + } 438 } 439 else if (strcmp("depend", argv[1]) == 0) 440 { ··· 439 symbolsonly = adddep; 440 singlefunctions = adddep2; 441 docsection = adddep2; 442 + findall = adddep; 443 parse_file(infile); 444 printf("\n"); 445 }
+50 -2
scripts/kernel-doc
··· 44 # Note: This only supports 'c'. 45 46 # usage: 47 - # kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ] 48 # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile 49 # or 50 # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile 51 # 52 # Set output format using one of -docbook -html -text or -man. Default is man. 53 # 54 # -no-doc-sections 55 # Do not output DOC: sections ··· 211 $type_param, "\$1" ); 212 my $blankline_text = ""; 213 214 215 sub usage { 216 - print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n"; 217 print " [ -function funcname [ -function funcname ...] ]\n"; 218 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; 219 print " c source file(s) > outputfile\n"; ··· 326 $output_mode = "xml"; 327 %highlights = %highlights_xml; 328 $blankline = $blankline_xml; 329 } elsif ($cmd eq "-gnome") { 330 $output_mode = "gnome"; 331 %highlights = %highlights_gnome; ··· 1370 print " $section:\n"; 1371 print " -> "; 1372 output_highlight($args{'sections'}{$section}); 1373 } 1374 } 1375
··· 44 # Note: This only supports 'c'. 45 46 # usage: 47 + # kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ] 48 # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile 49 # or 50 # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile 51 # 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. 54 # 55 # -no-doc-sections 56 # Do not output DOC: sections ··· 210 $type_param, "\$1" ); 211 my $blankline_text = ""; 212 213 + # list mode 214 + my %highlights_list = ( $type_constant, "\$1", 215 + $type_func, "\$1", 216 + $type_struct, "\$1", 217 + $type_param, "\$1" ); 218 + my $blankline_list = ""; 219 220 sub usage { 221 + print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n"; 222 + print " [ -no-doc-sections ]\n"; 223 print " [ -function funcname [ -function funcname ...] ]\n"; 224 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; 225 print " c source file(s) > outputfile\n"; ··· 318 $output_mode = "xml"; 319 %highlights = %highlights_xml; 320 $blankline = $blankline_xml; 321 + } elsif ($cmd eq "-list") { 322 + $output_mode = "list"; 323 + %highlights = %highlights_list; 324 + $blankline = $blankline_list; 325 } elsif ($cmd eq "-gnome") { 326 $output_mode = "gnome"; 327 %highlights = %highlights_gnome; ··· 1358 print " $section:\n"; 1359 print " -> "; 1360 output_highlight($args{'sections'}{$section}); 1361 + } 1362 + } 1363 + 1364 + ## list mode output functions 1365 + 1366 + sub output_function_list(%) { 1367 + my %args = %{$_[0]}; 1368 + 1369 + print $args{'function'} . "\n"; 1370 + } 1371 + 1372 + # output enum in list 1373 + sub output_enum_list(%) { 1374 + my %args = %{$_[0]}; 1375 + print $args{'enum'} . "\n"; 1376 + } 1377 + 1378 + # output typedef in list 1379 + sub output_typedef_list(%) { 1380 + my %args = %{$_[0]}; 1381 + print $args{'typedef'} . "\n"; 1382 + } 1383 + 1384 + # output struct as list 1385 + sub output_struct_list(%) { 1386 + my %args = %{$_[0]}; 1387 + 1388 + print $args{'struct'} . "\n"; 1389 + } 1390 + 1391 + sub output_blockhead_list(%) { 1392 + my %args = %{$_[0]}; 1393 + my ($parameter, $section); 1394 + 1395 + foreach $section (@{$args{'sectionlist'}}) { 1396 + print "DOC: $section\n"; 1397 } 1398 } 1399