doc_extract.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /* This merely extracts, doesn't do XML or anything. */
  2. #include <err.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <stdbool.h>
  11. #include "talloc/talloc.h"
  12. #include "string/string.h"
  13. static char **grab_doc(const char *fname)
  14. {
  15. char *file;
  16. char **lines, **ret;
  17. unsigned int i, num;
  18. bool printing = false, printed = false;
  19. file = grab_file(NULL, fname, NULL);
  20. if (!file)
  21. err(1, "Reading file %s", fname);
  22. lines = strsplit(file, file, "\n", &num);
  23. ret = talloc_array(NULL, char *, num+1);
  24. num = 0;
  25. for (i = 0; lines[i]; i++) {
  26. if (streq(lines[i], "/**")) {
  27. printing = true;
  28. if (printed++)
  29. talloc_append_string(ret[num], "\n");
  30. } else if (streq(lines[i], " */"))
  31. printing = false;
  32. else if (printing) {
  33. if (strstarts(lines[i], " * "))
  34. ret[num++] = talloc_strdup(ret, lines[i]+3);
  35. else if (strstarts(lines[i], " *"))
  36. ret[num++] = talloc_strdup(ret, lines[i]+2);
  37. else
  38. errx(1, "Malformed line %s:%u", fname, i);
  39. }
  40. }
  41. ret[num] = NULL;
  42. talloc_free(file);
  43. return ret;
  44. }
  45. static bool is_blank(const char *line)
  46. {
  47. return line && line[strspn(line, " \t\n")] == '\0';
  48. }
  49. static bool is_section(const char *line, bool maybe_one_liner)
  50. {
  51. unsigned int len;
  52. len = strcspn(line, " \t\n:");
  53. if (len == 0)
  54. return false;
  55. if (line[len] != ':')
  56. return false;
  57. /* If it can be a one-liner, a space is sufficient.*/
  58. if (maybe_one_liner && (line[len+1] == ' ' || line[len+1] == '\t'))
  59. return true;
  60. return line[len] == ':' && is_blank(line+len+1);
  61. }
  62. static bool end_section(const char *line)
  63. {
  64. return !line || is_section(line, true);
  65. }
  66. static unsigned int find_section(char **lines, const char *name,
  67. bool maybe_one_liner)
  68. {
  69. unsigned int i;
  70. for (i = 0; lines[i]; i++) {
  71. if (!is_section(lines[i], maybe_one_liner))
  72. continue;
  73. if (strncasecmp(lines[i], name, strlen(name)) != 0)
  74. continue;
  75. if (lines[i][strlen(name)] == ':')
  76. break;
  77. }
  78. return i;
  79. }
  80. int main(int argc, char *argv[])
  81. {
  82. unsigned int i;
  83. const char *type;
  84. if (argc < 3)
  85. errx(1, "Usage: doc_extract TYPE <file>...\n"
  86. "Where TYPE is author|licence|maintainer|summary|description|example|all");
  87. type = argv[1];
  88. for (i = 2; i < argc; i++) {
  89. unsigned int line;
  90. char **lines = grab_doc(argv[i]);
  91. if (!lines[0])
  92. errx(1, "No documentation in file");
  93. /* Simple one-line fields. */
  94. if (streq(type, "author")
  95. || streq(type, "maintainer")
  96. || streq(type, "licence")) {
  97. line = find_section(lines, type, true);
  98. if (lines[line]) {
  99. const char *p = strchr(lines[line], ':') + 1;
  100. p += strspn(p, " \t\n");
  101. if (p[0] == '\0') {
  102. /* Must be on next line. */
  103. if (end_section(lines[line+1]))
  104. errx(1, "Malformed %s", type);
  105. puts(lines[line+1]);
  106. } else
  107. puts(p);
  108. }
  109. } else if (streq(type, "summary")) {
  110. /* Summary comes after - on first line. */
  111. char *dash;
  112. dash = strchr(lines[0], '-');
  113. if (!dash)
  114. errx(1, "Malformed first line: no -");
  115. dash += strspn(dash, "- ");
  116. puts(dash);
  117. } else if (streq(type, "description")) {
  118. line = 1;
  119. while (is_blank(lines[line]))
  120. line++;
  121. while (!end_section(lines[line]))
  122. puts(lines[line++]);
  123. } else if (streq(type, "example")) {
  124. line = find_section(lines, type, false);
  125. if (lines[line]) {
  126. unsigned int strip;
  127. line++;
  128. while (is_blank(lines[line]))
  129. line++;
  130. /* Examples can be indented. Take cue
  131. * from first non-blank line. */
  132. if (lines[line])
  133. strip = strspn(lines[line], " \t");
  134. while (!end_section(lines[line])) {
  135. if (strspn(lines[line], " \t") >= strip)
  136. puts(lines[line] + strip);
  137. else
  138. puts(lines[line]);
  139. line++;
  140. }
  141. }
  142. } else if (streq(type, "all")) {
  143. for (line = 0; lines[line]; line++)
  144. puts(lines[line]);
  145. } else
  146. errx(1, "Unknown type '%s'", type);
  147. talloc_free(lines);
  148. }
  149. return 0;
  150. }