|
@@ -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>
|
|
|
|
|
@@ -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;
|
|
@@ -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");
|
|
@@ -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;
|
|
|
}
|
|
|
}
|
|
@@ -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);
|
|
@@ -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;
|
|
@@ -315,6 +346,84 @@ 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
|
|
@@ -322,7 +431,8 @@ static void docsect(char *filename, char *line)
|
|
|
* 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)
|
|
|
{
|
|
@@ -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);
|
|
|
}
|
|
@@ -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)
|
|
@@ -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 */
|
|
@@ -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)
|
|
|
{
|
|
@@ -439,6 +565,7 @@ int main(int argc, char *argv[])
|
|
|
symbolsonly = adddep;
|
|
|
singlefunctions = adddep2;
|
|
|
docsection = adddep2;
|
|
|
+ findall = adddep;
|
|
|
parse_file(infile);
|
|
|
printf("\n");
|
|
|
}
|