#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. */
#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;
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");
/*
* 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
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];
}
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);
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 */
free(s);
vec[0] = KERNELDOC;
- vec[1] = DOCBOOK;
+ vec[1] = KERNELDOC_FORMAT;
vec[2] = SHOWNOTFOUND;
vec[3] = FUNCTION;
vec[4] = line;
}
}
+/*
+ * 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 (line[0] == '!')
+ if (file_format == FORMAT_DOCBOOK && line[0] == '!')
return line + 1;
+ else if (file_format == FORMAT_RST && !strncmp(line, ".. !", 4))
+ return line + 4;
return NULL;
}
continue;
}
- s = p + 1;
switch (*p++) {
case 'E':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
+ chomp(p);
externalfunctions(p);
break;
case 'I':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
+ chomp(p);
internalfunctions(p);
break;
case 'D':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
+ chomp(p);
symbolsonly(p);
break;
case 'F':
/* filename */
- while (*s && !isspace(*s)) s++;
- *s++ = '\0';
+ s = chomp(p);
/* function names */
while (isspace(*s))
s++;
break;
case 'P':
/* filename */
- while (*s && !isspace(*s)) s++;
- *s++ = '\0';
+ s = chomp(p);
/* DOC: section name */
while (isspace(*s))
s++;
docsection(p, s);
break;
case 'C':
- while (*s && !isspace(*s)) s++;
- *s = '\0';
+ chomp(p);
if (findall)
findall(p);
break;
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[])
{
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[1];
- filename = argv[2];
+ 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(filename, "r");
}
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;