aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-19 18:07:25 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-19 18:07:25 -0700
commite9ad9b9bd3a3b95c89a29b2a197476e662db4233 (patch)
tree0b5e6c09953edc1a0bfab0b2aa964b80bceb5efd /scripts
parentMerge branch 'i2c/for-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux (diff)
parentdoc: self-protection: provide initial details (diff)
downloadlinux-dev-e9ad9b9bd3a3b95c89a29b2a197476e662db4233.tar.xz
linux-dev-e9ad9b9bd3a3b95c89a29b2a197476e662db4233.zip
Merge tag 'docs-for-linus' of git://git.lwn.net/linux
Pull Documentation updates from Jon Corbet: "A bit busier this time around. The most interesting thing (IMO) this time around is some beginning infrastructural work to allow documents to be written using restructured text. Maybe someday, in a galaxy far far away, we'll be able to eliminate the DocBook dependency and have a much better integrated set of kernel docs. Someday. Beyond that, there's a new document on security hardening from Kees, the movement of some sample code over to samples/, a number of improvements to the serial docs from Geert, and the usual collection of corrections, typo fixes, etc" * tag 'docs-for-linus' of git://git.lwn.net/linux: (55 commits) doc: self-protection: provide initial details serial: doc: Use port->state instead of info serial: doc: Always refer to tty_port->mutex Documentation: vm: Spelling s/paltform/platform/g Documentation/memcg: update kmem limit doc as codes behavior docproc: print a comment about autogeneration for rst output docproc: add support for reStructuredText format via --rst option docproc: abstract terminating lines at first space docproc: abstract docproc directive detection docproc: reduce unnecessary indentation docproc: add variables for subcommand and filename kernel-doc: use rst C domain directives and references for types kernel-doc: produce RestructuredText output kernel-doc: rewrite usage description, remove duplicated comments Doc: correct the location of sysrq.c Documentation: fix common spelling mistakes samples: v4l: from Documentation to samples directory samples: connector: from Documentation to samples directory Documentation: xillybus: fix spelling mistake Documentation: x86: fix spelling mistakes ...
Diffstat (limited to 'scripts')
-rw-r--r--scripts/docproc.c221
-rwxr-xr-xscripts/kernel-doc315
2 files changed, 430 insertions, 106 deletions
diff --git a/scripts/docproc.c b/scripts/docproc.c
index e267e621431a..0a12593b9041 100644
--- a/scripts/docproc.c
+++ b/scripts/docproc.c
@@ -42,8 +42,10 @@
#include <unistd.h>
#include <limits.h>
#include <errno.h>
+#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <time.h>
/* exitstatus is used to keep track of any failing calls to kernel-doc,
* but execution continues. */
@@ -68,12 +70,23 @@ FILELINE * docsection;
#define KERNELDOCPATH "scripts/"
#define KERNELDOC "kernel-doc"
#define DOCBOOK "-docbook"
+#define RST "-rst"
#define LIST "-list"
#define FUNCTION "-function"
#define NOFUNCTION "-nofunction"
#define NODOCSECTIONS "-no-doc-sections"
#define SHOWNOTFOUND "-show-not-found"
+enum file_format {
+ FORMAT_AUTO,
+ FORMAT_DOCBOOK,
+ FORMAT_RST,
+};
+
+static enum file_format file_format = FORMAT_AUTO;
+
+#define KERNELDOC_FORMAT (file_format == FORMAT_RST ? RST : DOCBOOK)
+
static char *srctree, *kernsrctree;
static char **all_list = NULL;
@@ -95,7 +108,7 @@ static void consume_symbol(const char *sym)
static void usage (void)
{
- fprintf(stderr, "Usage: docproc {doc|depend} file\n");
+ fprintf(stderr, "Usage: docproc [{--docbook|--rst}] {doc|depend} file\n");
fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n");
fprintf(stderr, "doc: frontend when generating kernel documentation\n");
fprintf(stderr, "depend: generate list of files referenced within file\n");
@@ -242,7 +255,7 @@ static void find_export_symbols(char * filename)
/*
* Document all external or internal functions in a file.
* Call kernel-doc with following parameters:
- * kernel-doc -docbook -nofunction function_name1 filename
+ * kernel-doc [-docbook|-rst] -nofunction function_name1 filename
* Function names are obtained from all the src files
* by find_export_symbols.
* intfunc uses -nofunction
@@ -263,7 +276,7 @@ static void docfunctions(char * filename, char * type)
exit(1);
}
vec[idx++] = KERNELDOC;
- vec[idx++] = DOCBOOK;
+ vec[idx++] = KERNELDOC_FORMAT;
vec[idx++] = NODOCSECTIONS;
for (i=0; i < symfilecnt; i++) {
struct symfile * sym = &symfilelist[i];
@@ -275,7 +288,10 @@ static void docfunctions(char * filename, char * type)
}
vec[idx++] = filename;
vec[idx] = NULL;
- printf("<!-- %s -->\n", filename);
+ if (file_format == FORMAT_RST)
+ printf(".. %s\n", filename);
+ else
+ printf("<!-- %s -->\n", filename);
exec_kernel_doc(vec);
fflush(stdout);
free(vec);
@@ -294,7 +310,7 @@ static void singfunc(char * filename, char * line)
int i, idx = 0;
int startofsym = 1;
vec[idx++] = KERNELDOC;
- vec[idx++] = DOCBOOK;
+ vec[idx++] = KERNELDOC_FORMAT;
vec[idx++] = SHOWNOTFOUND;
/* Split line up in individual parameters preceded by FUNCTION */
@@ -343,7 +359,7 @@ static void docsect(char *filename, char *line)
free(s);
vec[0] = KERNELDOC;
- vec[1] = DOCBOOK;
+ vec[1] = KERNELDOC_FORMAT;
vec[2] = SHOWNOTFOUND;
vec[3] = FUNCTION;
vec[4] = line;
@@ -431,6 +447,32 @@ static void find_all_symbols(char *filename)
}
/*
+ * Terminate s at first space, if any. If there was a space, return pointer to
+ * the character after that. Otherwise, return pointer to the terminating NUL.
+ */
+static char *chomp(char *s)
+{
+ while (*s && !isspace(*s))
+ s++;
+
+ if (*s)
+ *s++ = '\0';
+
+ return s;
+}
+
+/* Return pointer to directive content, or NULL if not a directive. */
+static char *is_directive(char *line)
+{
+ if (file_format == FORMAT_DOCBOOK && line[0] == '!')
+ return line + 1;
+ else if (file_format == FORMAT_RST && !strncmp(line, ".. !", 4))
+ return line + 4;
+
+ return NULL;
+}
+
+/*
* Parse file, calling action specific functions for:
* 1) Lines containing !E
* 2) Lines containing !I
@@ -443,63 +485,75 @@ static void find_all_symbols(char *filename)
static void parse_file(FILE *infile)
{
char line[MAXLINESZ];
- char * s;
+ char *p, *s;
while (fgets(line, MAXLINESZ, infile)) {
- if (line[0] == '!') {
- s = line + 2;
- switch (line[1]) {
- case 'E':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- externalfunctions(line+2);
- break;
- case 'I':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- internalfunctions(line+2);
- break;
- case 'D':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- symbolsonly(line+2);
- break;
- case 'F':
- /* filename */
- while (*s && !isspace(*s)) s++;
- *s++ = '\0';
- /* function names */
- while (isspace(*s))
- s++;
- singlefunctions(line +2, s);
- break;
- case 'P':
- /* filename */
- while (*s && !isspace(*s)) s++;
- *s++ = '\0';
- /* DOC: section name */
- while (isspace(*s))
- s++;
- docsection(line + 2, s);
- break;
- case 'C':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
- if (findall)
- findall(line+2);
- break;
- default:
- defaultline(line);
- }
- } else {
+ p = is_directive(line);
+ if (!p) {
+ defaultline(line);
+ continue;
+ }
+
+ switch (*p++) {
+ case 'E':
+ chomp(p);
+ externalfunctions(p);
+ break;
+ case 'I':
+ chomp(p);
+ internalfunctions(p);
+ break;
+ case 'D':
+ chomp(p);
+ symbolsonly(p);
+ break;
+ case 'F':
+ /* filename */
+ s = chomp(p);
+ /* function names */
+ while (isspace(*s))
+ s++;
+ singlefunctions(p, s);
+ break;
+ case 'P':
+ /* filename */
+ s = chomp(p);
+ /* DOC: section name */
+ while (isspace(*s))
+ s++;
+ docsection(p, s);
+ break;
+ case 'C':
+ chomp(p);
+ if (findall)
+ findall(p);
+ break;
+ default:
defaultline(line);
}
}
fflush(stdout);
}
+/*
+ * Is this a RestructuredText template? Answer the question by seeing if its
+ * name ends in ".rst".
+ */
+static int is_rst(const char *file)
+{
+ char *dot = strrchr(file, '.');
+
+ return dot && !strcmp(dot + 1, "rst");
+}
+
+enum opts {
+ OPT_DOCBOOK,
+ OPT_RST,
+ OPT_HELP,
+};
int main(int argc, char *argv[])
{
+ const char *subcommand, *filename;
FILE * infile;
int i;
@@ -509,19 +563,66 @@ int main(int argc, char *argv[])
kernsrctree = getenv("KBUILD_SRC");
if (!kernsrctree || !*kernsrctree)
kernsrctree = srctree;
- if (argc != 3) {
+
+ for (;;) {
+ int c;
+ struct option opts[] = {
+ { "docbook", no_argument, NULL, OPT_DOCBOOK },
+ { "rst", no_argument, NULL, OPT_RST },
+ { "help", no_argument, NULL, OPT_HELP },
+ {}
+ };
+
+ c = getopt_long_only(argc, argv, "", opts, NULL);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case OPT_DOCBOOK:
+ file_format = FORMAT_DOCBOOK;
+ break;
+ case OPT_RST:
+ file_format = FORMAT_RST;
+ break;
+ case OPT_HELP:
+ usage();
+ return 0;
+ default:
+ case '?':
+ usage();
+ return 1;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2) {
usage();
exit(1);
}
+
+ subcommand = argv[0];
+ filename = argv[1];
+
+ if (file_format == FORMAT_AUTO)
+ file_format = is_rst(filename) ? FORMAT_RST : FORMAT_DOCBOOK;
+
/* Open file, exit on error */
- infile = fopen(argv[2], "r");
+ infile = fopen(filename, "r");
if (infile == NULL) {
fprintf(stderr, "docproc: ");
- perror(argv[2]);
+ perror(filename);
exit(2);
}
- if (strcmp("doc", argv[1]) == 0) {
+ if (strcmp("doc", subcommand) == 0) {
+ if (file_format == FORMAT_RST) {
+ time_t t = time(NULL);
+ printf(".. generated from %s by docproc %s\n",
+ filename, ctime(&t));
+ }
+
/* Need to do this in two passes.
* First pass is used to collect all symbols exported
* in the various files;
@@ -557,10 +658,10 @@ int main(int argc, char *argv[])
fprintf(stderr, "Warning: didn't use docs for %s\n",
all_list[i]);
}
- } else if (strcmp("depend", argv[1]) == 0) {
+ } else if (strcmp("depend", subcommand) == 0) {
/* Create first part of dependency chain
* file.tmpl */
- printf("%s\t", argv[2]);
+ printf("%s\t", filename);
defaultline = noaction;
internalfunctions = adddep;
externalfunctions = adddep;
@@ -571,7 +672,7 @@ int main(int argc, char *argv[])
parse_file(infile);
printf("\n");
} else {
- fprintf(stderr, "Unknown option: %s\n", argv[1]);
+ fprintf(stderr, "Unknown option: %s\n", subcommand);
exit(1);
}
fclose(infile);
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index c37255bb620d..2fc8fad5195e 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -39,41 +39,44 @@ use strict;
# 25/07/2012 - Added support for HTML5
# -- Dan Luedtke <mail@danrl.de>
-#
-# This will read a 'c' file and scan for embedded comments in the
-# style of gnome comments (+minor extensions - see below).
-#
-
-# Note: This only supports 'c'.
-
-# usage:
-# kernel-doc [ -docbook | -html | -html5 | -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 -html5 -text or -man.
-# Default is man.
-# The -list format is for internal use by docproc.
-#
-# -no-doc-sections
-# Do not output DOC: sections
-#
-# -function funcname
-# If set, then only generate documentation for the given function(s) or
-# DOC: section titles. All other functions and DOC: sections are ignored.
-#
-# -nofunction funcname
-# If set, then only generate documentation for the other function(s)/DOC:
-# sections. Cannot be used together with -function (yes, that's a bug --
-# perl hackers can fix it 8))
-#
-# c files - list of 'c' files to process
-#
-# All output goes to stdout, with errors to stderr.
+sub usage {
+ my $message = <<"EOF";
+Usage: $0 [OPTION ...] FILE ...
+
+Read C language source or header FILEs, extract embedded documentation comments,
+and print formatted documentation to standard output.
+
+The documentation comments are identified by "/**" opening comment mark. See
+Documentation/kernel-doc-nano-HOWTO.txt for the documentation comment syntax.
+
+Output format selection (mutually exclusive):
+ -docbook Output DocBook format.
+ -html Output HTML format.
+ -html5 Output HTML5 format.
+ -list Output symbol list format. This is for use by docproc.
+ -man Output troff manual page format. This is the default.
+ -rst Output reStructuredText format.
+ -text Output plain text format.
+
+Output selection (mutually exclusive):
+ -function NAME Only output documentation for the given function(s)
+ or DOC: section title(s). All other functions and DOC:
+ sections are ignored. May be specified multiple times.
+ -nofunction NAME Do NOT output documentation for the given function(s);
+ only output documentation for the other functions and
+ DOC: sections. May be specified multiple times.
+
+Output selection modifiers:
+ -no-doc-sections Do not output DOC: sections.
+
+Other parameters:
+ -v Verbose output, more warnings and other information.
+ -h Print this help.
+
+EOF
+ print $message;
+ exit 1;
+}
#
# format of comments.
@@ -201,6 +204,8 @@ my $type_param = '\@(\w+)';
my $type_struct = '\&((struct\s*)*[_\w]+)';
my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
my $type_env = '(\$\w+)';
+my $type_enum_full = '\&(enum)\s*([_\w]+)';
+my $type_struct_full = '\&(struct)\s*([_\w]+)';
# Output conversion substitutions.
# One for each output format
@@ -266,6 +271,17 @@ my @highlights_text = (
);
my $blankline_text = "";
+# rst-mode
+my @highlights_rst = (
+ [$type_constant, "``\$1``"],
+ [$type_func, "\\:c\\:func\\:`\$1`"],
+ [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
+ [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"],
+ [$type_struct, "\\:c\\:type\\:`struct \$1 <\$1>`"],
+ [$type_param, "**\$1**"]
+ );
+my $blankline_rst = "\n";
+
# list mode
my @highlights_list = (
[$type_constant, "\$1"],
@@ -402,6 +418,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
$output_mode = "text";
@highlights = @highlights_text;
$blankline = $blankline_text;
+ } elsif ($cmd eq "-rst") {
+ $output_mode = "rst";
+ @highlights = @highlights_rst;
+ $blankline = $blankline_rst;
} elsif ($cmd eq "-docbook") {
$output_mode = "xml";
@highlights = @highlights_xml;
@@ -437,17 +457,6 @@ while ($ARGV[0] =~ m/^-(.*)/) {
# continue execution near EOF;
-sub usage {
- print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
- print " [ -no-doc-sections ]\n";
- print " [ -function funcname [ -function funcname ...] ]\n";
- print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
- print " [ -v ]\n";
- print " c source file(s) > outputfile\n";
- print " -v : verbose output, more warnings & other info listed\n";
- exit 1;
-}
-
# get kernel version from env
sub get_kernel_version() {
my $version = 'unknown kernel version';
@@ -1713,6 +1722,208 @@ sub output_blockhead_text(%) {
}
}
+##
+# output in restructured text
+#
+
+#
+# This could use some work; it's used to output the DOC: sections, and
+# starts by putting out the name of the doc section itself, but that tends
+# to duplicate a header already in the template file.
+#
+sub output_blockhead_rst(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "**$section**\n\n";
+ output_highlight_rst($args{'sections'}{$section});
+ print "\n";
+ }
+}
+
+sub output_highlight_rst {
+ my $contents = join "\n",@_;
+ my $line;
+
+ # undo the evil effects of xml_escape() earlier
+ $contents = xml_unescape($contents);
+
+ eval $dohighlight;
+ die $@ if $@;
+
+ foreach $line (split "\n", $contents) {
+ if ($line eq "") {
+ print $lineprefix, $blankline;
+ } else {
+ $line =~ s/\\\\\\/\&/g;
+ print $lineprefix, $line;
+ }
+ print "\n";
+ }
+}
+
+sub output_function_rst(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $start;
+
+ print ".. c:function:: ";
+ if ($args{'functiontype'} ne "") {
+ $start = $args{'functiontype'} . " " . $args{'function'} . " (";
+ } else {
+ $start = $args{'function'} . " (";
+ }
+ print $start;
+
+ my $count = 0;
+ foreach my $parameter (@{$args{'parameterlist'}}) {
+ if ($count ne 0) {
+ print ", ";
+ }
+ $count++;
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print $1 . $parameter . ") (" . $2;
+ } else {
+ print $type . " " . $parameter;
+ }
+ }
+ print ")\n\n " . $args{'purpose'} . "\n\n";
+
+ print ":Parameters:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ my $parameter_name = $parameter;
+ #$parameter_name =~ s/\[.*//;
+ $type = $args{'parametertypes'}{$parameter};
+
+ if ($type ne "") {
+ print " ``$type $parameter``\n";
+ } else {
+ print " ``$parameter``\n";
+ }
+ if ($args{'parameterdescs'}{$parameter_name} ne $undescribed) {
+ my $oldprefix = $lineprefix;
+ $lineprefix = " ";
+ output_highlight_rst($args{'parameterdescs'}{$parameter_name});
+ $lineprefix = $oldprefix;
+ } else {
+ print "\n _undescribed_\n";
+ }
+ print "\n";
+ }
+ output_section_rst(@_);
+}
+
+sub output_section_rst(%) {
+ my %args = %{$_[0]};
+ my $section;
+ my $oldprefix = $lineprefix;
+ $lineprefix = " ";
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ":$section:\n\n";
+ output_highlight_rst($args{'sections'}{$section});
+ print "\n";
+ }
+ print "\n";
+ $lineprefix = $oldprefix;
+}
+
+sub output_enum_rst(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ my $name = "enum " . $args{'enum'};
+
+ print "\n\n.. c:type:: " . $name . "\n\n";
+ print " " . $args{'purpose'} . "\n\n";
+
+ print "..\n\n:Constants:\n\n";
+ my $oldprefix = $lineprefix;
+ $lineprefix = " ";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print " `$parameter`\n";
+ if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
+ output_highlight_rst($args{'parameterdescs'}{$parameter});
+ } else {
+ print " undescribed\n";
+ }
+ print "\n";
+ }
+ $lineprefix = $oldprefix;
+ output_section_rst(@_);
+}
+
+sub output_typedef_rst(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ my $name = "typedef " . $args{'typedef'};
+
+ ### FIXME: should the name below contain "typedef" or not?
+ print "\n\n.. c:type:: " . $name . "\n\n";
+ print " " . $args{'purpose'} . "\n\n";
+
+ output_section_rst(@_);
+}
+
+sub output_struct_rst(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $name = $args{'type'} . " " . $args{'struct'};
+
+ print "\n\n.. c:type:: " . $name . "\n\n";
+ print " " . $args{'purpose'} . "\n\n";
+
+ print ":Definition:\n\n";
+ print " ::\n\n";
+ print " " . $args{'type'} . " " . $args{'struct'} . " {\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ if ($parameter =~ /^#/) {
+ print " " . "$parameter\n";
+ next;
+ }
+
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print " $1 $parameter) ($2);\n";
+ } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+ # bitfield
+ print " $1 $parameter$2;\n";
+ } else {
+ print " " . $type . " " . $parameter . ";\n";
+ }
+ }
+ print " };\n\n";
+
+ print ":Members:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($parameter =~ /^#/) && next;
+
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
+ print " `$type $parameter`" . "\n";
+ my $oldprefix = $lineprefix;
+ $lineprefix = " ";
+ output_highlight_rst($args{'parameterdescs'}{$parameter_name});
+ $lineprefix = $oldprefix;
+ print "\n";
+ }
+ print "\n";
+ output_section_rst(@_);
+}
+
+
## list mode output functions
sub output_function_list(%) {
@@ -2414,6 +2625,18 @@ sub xml_escape($) {
return $text;
}
+# xml_unescape: reverse the effects of xml_escape
+sub xml_unescape($) {
+ my $text = shift;
+ if (($output_mode eq "text") || ($output_mode eq "man")) {
+ return $text;
+ }
+ $text =~ s/\\\\\\amp;/\&/g;
+ $text =~ s/\\\\\\lt;/</g;
+ $text =~ s/\\\\\\gt;/>/g;
+ return $text;
+}
+
# convert local escape strings to html
# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes)
sub local_unescape($) {