depends_accurate.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include <tools/ccanlint/ccanlint.h>
  2. #include <tools/tools.h>
  3. #include <ccan/talloc/talloc.h>
  4. #include <ccan/str/str.h>
  5. #include <ccan/foreach/foreach.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <limits.h>
  11. #include <errno.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <err.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. static char *strip_spaces(const void *ctx, char *line)
  18. {
  19. char *p = talloc_strdup(ctx, line);
  20. unsigned int i, j;
  21. for (i = 0, j = 0; p[i]; i++) {
  22. if (!isspace(p[i]))
  23. p[j++] = p[i];
  24. }
  25. p[j] = '\0';
  26. return p;
  27. }
  28. static bool has_dep(struct manifest *m, const char *depname)
  29. {
  30. struct manifest *i;
  31. /* We can include ourselves, of course. */
  32. if (streq(depname, m->basename))
  33. return true;
  34. list_for_each(&m->deps, i, list) {
  35. if (streq(i->basename, depname))
  36. return true;
  37. }
  38. return false;
  39. }
  40. static void check_depends_accurate(struct manifest *m,
  41. bool keep,
  42. unsigned int *timeleft, struct score *score)
  43. {
  44. struct list_head *list;
  45. foreach_ptr(list, &m->c_files, &m->h_files,
  46. &m->run_tests, &m->api_tests,
  47. &m->compile_ok_tests, &m->compile_fail_tests,
  48. &m->other_test_c_files) {
  49. struct ccan_file *f;
  50. list_for_each(list, f, list) {
  51. unsigned int i;
  52. char **lines = get_ccan_file_lines(f);
  53. for (i = 0; lines[i]; i++) {
  54. char *p;
  55. if (lines[i][strspn(lines[i], " \t")] != '#')
  56. continue;
  57. p = strip_spaces(f, lines[i]);
  58. if (!strstarts(p, "#include<ccan/")
  59. && !strstarts(p, "#include\"ccan/"))
  60. continue;
  61. p += strlen("#include\"ccan/");
  62. if (!strchr(strchr(p, '/') + 1, '/'))
  63. continue;
  64. *strchr(strchr(p, '/') + 1, '/') = '\0';
  65. if (has_dep(m, p))
  66. continue;
  67. score->error = "Includes a ccan module"
  68. " not listed in _info";
  69. score_file_error(score, f, i+1, lines[i]);
  70. }
  71. }
  72. }
  73. if (!score->error) {
  74. score->pass = true;
  75. score->score = score->total;
  76. }
  77. }
  78. struct ccanlint depends_accurate = {
  79. .key = "depends_accurate",
  80. .name = "Module's CCAN dependencies are the only CCAN files #included",
  81. .check = check_depends_accurate,
  82. .needs = "depends_exist"
  83. };
  84. REGISTER_TEST(depends_accurate);