Skip to content

Commit

Permalink
docbook: warn on unused doc entries
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Randy Dunlap <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
jmberg-intel authored and torvalds committed Sep 11, 2010
1 parent 1f3a668 commit eda603f
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 3 deletions.
5 changes: 5 additions & 0 deletions Documentation/kernel-doc-nano-HOWTO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -345,5 +345,10 @@ documentation, in <filename>, for the functions listed.
section titled <section title> from <filename>.
Spaces are allowed in <section title>; do not quote the <section title>.

!C<filename> is replaced by nothing, but makes the tools check that
all DOC: sections and documented functions, symbols, etc. are used.
This makes sense to use when you use !F/!P only and want to verify
that all documentation is included.

Tim.
*/ <[email protected]>
129 changes: 128 additions & 1 deletion scripts/basic/docproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@
*
*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

Expand All @@ -54,6 +56,7 @@ typedef void FILEONLY(char * file);
FILEONLY *internalfunctions;
FILEONLY *externalfunctions;
FILEONLY *symbolsonly;
FILEONLY *findall;

typedef void FILELINE(char * file, char * line);
FILELINE * singlefunctions;
Expand All @@ -65,12 +68,30 @@ FILELINE * docsection;
#define KERNELDOCPATH "scripts/"
#define KERNELDOC "kernel-doc"
#define DOCBOOK "-docbook"
#define LIST "-list"
#define FUNCTION "-function"
#define NOFUNCTION "-nofunction"
#define NODOCSECTIONS "-no-doc-sections"

static char *srctree, *kernsrctree;

static char **all_list = NULL;
static int all_list_len = 0;

static void consume_symbol(const char *sym)
{
int i;

for (i = 0; i < all_list_len; i++) {
if (!all_list[i])
continue;
if (strcmp(sym, all_list[i]))
continue;
all_list[i] = NULL;
break;
}
}

static void usage (void)
{
fprintf(stderr, "Usage: docproc {doc|depend} file\n");
Expand Down Expand Up @@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type)
struct symfile * sym = &symfilelist[i];
for (j=0; j < sym->symbolcnt; j++) {
vec[idx++] = type;
consume_symbol(sym->symbollist[j].name);
vec[idx++] = sym->symbollist[j].name;
}
}
Expand Down Expand Up @@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line)
vec[idx++] = &line[i];
}
}
for (i = 0; i < idx; i++) {
if (strcmp(vec[i], FUNCTION))
continue;
consume_symbol(vec[i + 1]);
}
vec[idx++] = filename;
vec[idx] = NULL;
exec_kernel_doc(vec);
Expand All @@ -306,6 +333,10 @@ static void docsect(char *filename, char *line)
if (*s == '\n')
*s = '\0';

asprintf(&s, "DOC: %s", line);
consume_symbol(s);
free(s);

vec[0] = KERNELDOC;
vec[1] = DOCBOOK;
vec[2] = FUNCTION;
Expand All @@ -315,14 +346,93 @@ static void docsect(char *filename, char *line)
exec_kernel_doc(vec);
}

static void find_all_symbols(char *filename)
{
char *vec[4]; /* kerneldoc -list file NULL */
pid_t pid;
int ret, i, count, start;
char real_filename[PATH_MAX + 1];
int pipefd[2];
char *data, *str;
size_t data_len = 0;

vec[0] = KERNELDOC;
vec[1] = LIST;
vec[2] = filename;
vec[3] = NULL;

if (pipe(pipefd)) {
perror("pipe");
exit(1);
}

switch (pid=fork()) {
case -1:
perror("fork");
exit(1);
case 0:
close(pipefd[0]);
dup2(pipefd[1], 1);
memset(real_filename, 0, sizeof(real_filename));
strncat(real_filename, kernsrctree, PATH_MAX);
strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
PATH_MAX - strlen(real_filename));
execvp(real_filename, vec);
fprintf(stderr, "exec ");
perror(real_filename);
exit(1);
default:
close(pipefd[1]);
data = malloc(4096);
do {
while ((ret = read(pipefd[0],
data + data_len,
4096)) > 0) {
data_len += ret;
data = realloc(data, data_len + 4096);
}
} while (ret == -EAGAIN);
if (ret != 0) {
perror("read");
exit(1);
}
waitpid(pid, &ret ,0);
}
if (WIFEXITED(ret))
exitstatus |= WEXITSTATUS(ret);
else
exitstatus = 0xff;

count = 0;
/* poor man's strtok, but with counting */
for (i = 0; i < data_len; i++) {
if (data[i] == '\n') {
count++;
data[i] = '\0';
}
}
start = all_list_len;
all_list_len += count;
all_list = realloc(all_list, sizeof(char *) * all_list_len);
str = data;
for (i = 0; i < data_len && start != all_list_len; i++) {
if (data[i] == '\0') {
all_list[start] = str;
str = data + i + 1;
start++;
}
}
}

/*
* Parse file, calling action specific functions for:
* 1) Lines containing !E
* 2) Lines containing !I
* 3) Lines containing !D
* 4) Lines containing !F
* 5) Lines containing !P
* 6) Default lines - lines not matching the above
* 6) Lines containing !C
* 7) Default lines - lines not matching the above
*/
static void parse_file(FILE *infile)
{
Expand Down Expand Up @@ -365,6 +475,12 @@ static void parse_file(FILE *infile)
s++;
docsection(line + 2, s);
break;
case 'C':
while (*s && !isspace(*s)) s++;
*s = '\0';
if (findall)
findall(line+2);
break;
default:
defaultline(line);
}
Expand All @@ -380,6 +496,7 @@ static void parse_file(FILE *infile)
int main(int argc, char *argv[])
{
FILE * infile;
int i;

srctree = getenv("SRCTREE");
if (!srctree)
Expand Down Expand Up @@ -415,6 +532,7 @@ int main(int argc, char *argv[])
symbolsonly = find_export_symbols;
singlefunctions = noaction2;
docsection = noaction2;
findall = find_all_symbols;
parse_file(infile);

/* Rewind to start from beginning of file again */
Expand All @@ -425,8 +543,16 @@ int main(int argc, char *argv[])
symbolsonly = printline;
singlefunctions = singfunc;
docsection = docsect;
findall = NULL;

parse_file(infile);

for (i = 0; i < all_list_len; i++) {
if (!all_list[i])
continue;
fprintf(stderr, "Warning: didn't use docs for %s\n",
all_list[i]);
}
}
else if (strcmp("depend", argv[1]) == 0)
{
Expand All @@ -439,6 +565,7 @@ int main(int argc, char *argv[])
symbolsonly = adddep;
singlefunctions = adddep2;
docsection = adddep2;
findall = adddep;
parse_file(infile);
printf("\n");
}
Expand Down
52 changes: 50 additions & 2 deletions scripts/kernel-doc
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ use strict;
# Note: This only supports 'c'.

# usage:
# kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ]
# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
# or
# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
#
# Set output format using one of -docbook -html -text or -man. Default is man.
# The -list format is for internal use by docproc.
#
# -no-doc-sections
# Do not output DOC: sections
Expand Down Expand Up @@ -210,9 +211,16 @@ my %highlights_text = ( $type_constant, "\$1",
$type_param, "\$1" );
my $blankline_text = "";

# list mode
my %highlights_list = ( $type_constant, "\$1",
$type_func, "\$1",
$type_struct, "\$1",
$type_param, "\$1" );
my $blankline_list = "";

sub usage {
print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n";
print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
print " [ -no-doc-sections ]\n";
print " [ -function funcname [ -function funcname ...] ]\n";
print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
print " c source file(s) > outputfile\n";
Expand Down Expand Up @@ -318,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
$output_mode = "xml";
%highlights = %highlights_xml;
$blankline = $blankline_xml;
} elsif ($cmd eq "-list") {
$output_mode = "list";
%highlights = %highlights_list;
$blankline = $blankline_list;
} elsif ($cmd eq "-gnome") {
$output_mode = "gnome";
%highlights = %highlights_gnome;
Expand Down Expand Up @@ -1361,6 +1373,42 @@ sub output_blockhead_text(%) {
}
}

## list mode output functions

sub output_function_list(%) {
my %args = %{$_[0]};

print $args{'function'} . "\n";
}

# output enum in list
sub output_enum_list(%) {
my %args = %{$_[0]};
print $args{'enum'} . "\n";
}

# output typedef in list
sub output_typedef_list(%) {
my %args = %{$_[0]};
print $args{'typedef'} . "\n";
}

# output struct as list
sub output_struct_list(%) {
my %args = %{$_[0]};

print $args{'struct'} . "\n";
}

sub output_blockhead_list(%) {
my %args = %{$_[0]};
my ($parameter, $section);

foreach $section (@{$args{'sectionlist'}}) {
print "DOC: $section\n";
}
}

##
# generic output function for all types (function, struct/union, typedef, enum);
# calls the generated, variable output_ function name based on
Expand Down

0 comments on commit eda603f

Please sign in to comment.