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.
Showing the changes to scripts/basic (1 of 3 files). Show all
Unified · Split
| @@ -34,12 +34,14 @@ · 33 unmodified lines | ||
| 34 | 34 | * |
| 35 | 35 | */ |
| 36 | 36 | |
| 37 | +#define _GNU_SOURCE | |
| 37 | 38 | #include <stdio.h> |
| 38 | 39 | #include <stdlib.h> |
| 39 | 40 | #include <string.h> |
| 40 | 41 | #include <ctype.h> |
| 41 | 42 | #include <unistd.h> |
| 42 | 43 | #include <limits.h> |
| 44 | +#include <errno.h> | |
| 43 | 45 | #include <sys/types.h> |
| 44 | 46 | #include <sys/wait.h> |
| 45 | 47 | |
| @@ -54,6 +56,7 @@ typedef void FILEONLY(char * file); · 8 unmodified lines | ||
| 54 | 56 | FILEONLY *internalfunctions; |
| 55 | 57 | FILEONLY *externalfunctions; |
| 56 | 58 | FILEONLY *symbolsonly; |
| 59 | +FILEONLY *findall; | |
| 57 | 60 | |
| 58 | 61 | typedef void FILELINE(char * file, char * line); |
| 59 | 62 | FILELINE * singlefunctions; |
| @@ -65,12 +68,30 @@ FILELINE * docsection; · 5 unmodified lines | ||
| 65 | 68 | #define KERNELDOCPATH "scripts/" |
| 66 | 69 | #define KERNELDOC "kernel-doc" |
| 67 | 70 | #define DOCBOOK "-docbook" |
| 71 | +#define LIST "-list" | |
| 68 | 72 | #define FUNCTION "-function" |
| 69 | 73 | #define NOFUNCTION "-nofunction" |
| 70 | 74 | #define NODOCSECTIONS "-no-doc-sections" |
| 71 | 75 | |
| 72 | 76 | static char *srctree, *kernsrctree; |
| 73 | 77 | |
| 78 | +static char **all_list = NULL; | |
| 79 | +static int all_list_len = 0; | |
| 80 | + | |
| 81 | +static void consume_symbol(const char *sym) | |
| 82 | +{ | |
| 83 | + int i; | |
| 84 | + | |
| 85 | + for (i = 0; i < all_list_len; i++) { | |
| 86 | + if (!all_list[i]) | |
| 87 | + continue; | |
| 88 | + if (strcmp(sym, all_list[i])) | |
| 89 | + continue; | |
| 90 | + all_list[i] = NULL; | |
| 91 | + break; | |
| 92 | + } | |
| 93 | +} | |
| 94 | + | |
| 74 | 95 | static void usage (void) |
| 75 | 96 | { |
| 76 | 97 | fprintf(stderr, "Usage: docproc {doc|depend} file\n"); |
| @@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type) · 171 unmodified lines | ||
| 248 | 269 | struct symfile * sym = &symfilelist[i]; |
| 249 | 270 | for (j=0; j < sym->symbolcnt; j++) { |
| 250 | 271 | vec[idx++] = type; |
| 272 | + consume_symbol(sym->symbollist[j].name); | |
| 251 | 273 | vec[idx++] = sym->symbollist[j].name; |
| 252 | 274 | } |
| 253 | 275 | } |
| @@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line) · 33 unmodified lines | ||
| 287 | 309 | vec[idx++] = &line[i]; |
| 288 | 310 | } |
| 289 | 311 | } |
| 312 | + for (i = 0; i < idx; i++) { | |
| 313 | + if (strcmp(vec[i], FUNCTION)) | |
| 314 | + continue; | |
| 315 | + consume_symbol(vec[i + 1]); | |
| 316 | + } | |
| 290 | 317 | vec[idx++] = filename; |
| 291 | 318 | vec[idx] = NULL; |
| 292 | 319 | exec_kernel_doc(vec); |
| @@ -306,6 +333,10 @@ static void docsect(char *filename, char *line) · 13 unmodified lines | ||
| 306 | 333 | if (*s == '\n') |
| 307 | 334 | *s = '\0'; |
| 308 | 335 | |
| 336 | + asprintf(&s, "DOC: %s", line); | |
| 337 | + consume_symbol(s); | |
| 338 | + free(s); | |
| 339 | + | |
| 309 | 340 | vec[0] = KERNELDOC; |
| 310 | 341 | vec[1] = DOCBOOK; |
| 311 | 342 | vec[2] = FUNCTION; |
| @@ -315,6 +346,84 @@ static void docsect(char *filename, char *line) · 3 unmodified lines | ||
| 315 | 346 | exec_kernel_doc(vec); |
| 316 | 347 | } |
| 317 | 348 | |
| 349 | +static void find_all_symbols(char *filename) | |
| 350 | +{ | |
| 351 | + char *vec[4]; /* kerneldoc -list file NULL */ | |
| 352 | + pid_t pid; | |
| 353 | + int ret, i, count, start; | |
| 354 | + char real_filename[PATH_MAX + 1]; | |
| 355 | + int pipefd[2]; | |
| 356 | + char *data, *str; | |
| 357 | + size_t data_len = 0; | |
| 358 | + | |
| 359 | + vec[0] = KERNELDOC; | |
| 360 | + vec[1] = LIST; | |
| 361 | + vec[2] = filename; | |
| 362 | + vec[3] = NULL; | |
| 363 | + | |
| 364 | + if (pipe(pipefd)) { | |
| 365 | + perror("pipe"); | |
| 366 | + exit(1); | |
| 367 | + } | |
| 368 | + | |
| 369 | + switch (pid=fork()) { | |
| 370 | + case -1: | |
| 371 | + perror("fork"); | |
| 372 | + exit(1); | |
| 373 | + case 0: | |
| 374 | + close(pipefd[0]); | |
| 375 | + dup2(pipefd[1], 1); | |
| 376 | + memset(real_filename, 0, sizeof(real_filename)); | |
| 377 | + strncat(real_filename, kernsrctree, PATH_MAX); | |
| 378 | + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, | |
| 379 | + PATH_MAX - strlen(real_filename)); | |
| 380 | + execvp(real_filename, vec); | |
| 381 | + fprintf(stderr, "exec "); | |
| 382 | + perror(real_filename); | |
| 383 | + exit(1); | |
| 384 | + default: | |
| 385 | + close(pipefd[1]); | |
| 386 | + data = malloc(4096); | |
| 387 | + do { | |
| 388 | + while ((ret = read(pipefd[0], | |
| 389 | + data + data_len, | |
| 390 | + 4096)) > 0) { | |
| 391 | + data_len += ret; | |
| 392 | + data = realloc(data, data_len + 4096); | |
| 393 | + } | |
| 394 | + } while (ret == -EAGAIN); | |
| 395 | + if (ret != 0) { | |
| 396 | + perror("read"); | |
| 397 | + exit(1); | |
| 398 | + } | |
| 399 | + waitpid(pid, &ret ,0); | |
| 400 | + } | |
| 401 | + if (WIFEXITED(ret)) | |
| 402 | + exitstatus |= WEXITSTATUS(ret); | |
| 403 | + else | |
| 404 | + exitstatus = 0xff; | |
| 405 | + | |
| 406 | + count = 0; | |
| 407 | + /* poor man's strtok, but with counting */ | |
| 408 | + for (i = 0; i < data_len; i++) { | |
| 409 | + if (data[i] == '\n') { | |
| 410 | + count++; | |
| 411 | + data[i] = '\0'; | |
| 412 | + } | |
| 413 | + } | |
| 414 | + start = all_list_len; | |
| 415 | + all_list_len += count; | |
| 416 | + all_list = realloc(all_list, sizeof(char *) * all_list_len); | |
| 417 | + str = data; | |
| 418 | + for (i = 0; i < data_len && start != all_list_len; i++) { | |
| 419 | + if (data[i] == '\0') { | |
| 420 | + all_list[start] = str; | |
| 421 | + str = data + i + 1; | |
| 422 | + start++; | |
| 423 | + } | |
| 424 | + } | |
| 425 | +} | |
| 426 | + | |
| 318 | 427 | /* |
| 319 | 428 | * Parse file, calling action specific functions for: |
| 320 | 429 | * 1) Lines containing !E |
| @@ -322,7 +431,8 @@ static void docsect(char *filename, char *line) · 1 unmodified line | ||
| 322 | 431 | * 3) Lines containing !D |
| 323 | 432 | * 4) Lines containing !F |
| 324 | 433 | * 5) Lines containing !P |
| 325 | − * 6) Default lines - lines not matching the above | |
| 434 | + * 6) Lines containing !C | |
| 435 | + * 7) Default lines - lines not matching the above | |
| 326 | 436 | */ |
| 327 | 437 | static void parse_file(FILE *infile) |
| 328 | 438 | { |
| @@ -365,6 +475,12 @@ static void parse_file(FILE *infile) · 36 unmodified lines | ||
| 365 | 475 | s++; |
| 366 | 476 | docsection(line + 2, s); |
| 367 | 477 | break; |
| 478 | + case 'C': | |
| 479 | + while (*s && !isspace(*s)) s++; | |
| 480 | + *s = '\0'; | |
| 481 | + if (findall) | |
| 482 | + findall(line+2); | |
| 483 | + break; | |
| 368 | 484 | default: |
| 369 | 485 | defaultline(line); |
| 370 | 486 | } |
| @@ -380,6 +496,7 @@ static void parse_file(FILE *infile) · 9 unmodified lines | ||
| 380 | 496 | int main(int argc, char *argv[]) |
| 381 | 497 | { |
| 382 | 498 | FILE * infile; |
| 499 | + int i; | |
| 383 | 500 | |
| 384 | 501 | srctree = getenv("SRCTREE"); |
| 385 | 502 | if (!srctree) |
| @@ -415,6 +532,7 @@ int main(int argc, char *argv[]) · 29 unmodified lines | ||
| 415 | 532 | symbolsonly = find_export_symbols; |
| 416 | 533 | singlefunctions = noaction2; |
| 417 | 534 | docsection = noaction2; |
| 535 | + findall = find_all_symbols; | |
| 418 | 536 | parse_file(infile); |
| 419 | 537 | |
| 420 | 538 | /* Rewind to start from beginning of file again */ |
| @@ -425,8 +543,16 @@ int main(int argc, char *argv[]) · 4 unmodified lines | ||
| 425 | 543 | symbolsonly = printline; |
| 426 | 544 | singlefunctions = singfunc; |
| 427 | 545 | docsection = docsect; |
| 546 | + findall = NULL; | |
| 428 | 547 | |
| 429 | 548 | parse_file(infile); |
| 549 | + | |
| 550 | + for (i = 0; i < all_list_len; i++) { | |
| 551 | + if (!all_list[i]) | |
| 552 | + continue; | |
| 553 | + fprintf(stderr, "Warning: didn't use docs for %s\n", | |
| 554 | + all_list[i]); | |
| 555 | + } | |
| 430 | 556 | } |
| 431 | 557 | else if (strcmp("depend", argv[1]) == 0) |
| 432 | 558 | { |
| @@ -439,6 +565,7 @@ int main(int argc, char *argv[]) · 6 unmodified lines | ||
| 439 | 565 | symbolsonly = adddep; |
| 440 | 566 | singlefunctions = adddep2; |
| 441 | 567 | docsection = adddep2; |
| 568 | + findall = adddep; | |
| 442 | 569 | parse_file(infile); |
| 443 | 570 | printf("\n"); |
| 444 | 571 | } |