doc_extract.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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)
  50. {
  51. unsigned int len;
  52. len = strcspn(line, " \t\n:");
  53. if (len == 0)
  54. return false;
  55. return line[len] == ':' && is_blank(line+len+1);
  56. }
  57. static bool end_section(const char *line)
  58. {
  59. return !line || is_section(line);
  60. }
  61. static unsigned int find_section(char **lines, const char *name)
  62. {
  63. unsigned int i;
  64. for (i = 0; lines[i]; i++) {
  65. if (!is_section(lines[i]))
  66. continue;
  67. if (strncasecmp(lines[i], name, strlen(name)) != 0)
  68. continue;
  69. if (lines[i][strlen(name)] == ':')
  70. break;
  71. }
  72. return i;
  73. }
  74. int main(int argc, char *argv[])
  75. {
  76. unsigned int i;
  77. const char *type;
  78. if (argc < 3)
  79. errx(1, "Usage: doc_extract TYPE <file>...\n"
  80. "Where TYPE is author|licence|maintainer|summary|description|example|all");
  81. type = argv[1];
  82. for (i = 2; i < argc; i++) {
  83. unsigned int line;
  84. char **lines = grab_doc(argv[i]);
  85. if (!lines[0])
  86. errx(1, "No documentation in file");
  87. /* Simple one-line fields. */
  88. if (streq(type, "author")
  89. || streq(type, "maintainer")
  90. || streq(type, "licence")) {
  91. line = find_section(lines, type);
  92. if (lines[line]) {
  93. if (!lines[line+1])
  94. errx(1, "Malformed %s, end of file",
  95. type);
  96. puts(lines[line+1]);
  97. }
  98. } else if (streq(type, "summary")) {
  99. /* Summary comes after - on first line. */
  100. char *dash;
  101. dash = strchr(lines[0], '-');
  102. if (!dash)
  103. errx(1, "Malformed first line: no -");
  104. dash += strspn(dash, "- ");
  105. puts(dash);
  106. } else if (streq(type, "description")) {
  107. line = 1;
  108. while (is_blank(lines[line]))
  109. line++;
  110. while (!end_section(lines[line]))
  111. puts(lines[line++]);
  112. } else if (streq(type, "example")) {
  113. line = find_section(lines, type);
  114. if (lines[line]) {
  115. unsigned int strip;
  116. line++;
  117. while (is_blank(lines[line]))
  118. line++;
  119. /* Examples can be indented. Take cue
  120. * from first non-blank line. */
  121. if (lines[line])
  122. strip = strspn(lines[line], " \t");
  123. while (!end_section(lines[line])) {
  124. if (strspn(lines[line], " \t") >= strip)
  125. puts(lines[line] + strip);
  126. else
  127. puts(lines[line]);
  128. line++;
  129. }
  130. }
  131. } else if (streq(type, "all")) {
  132. for (line = 0; lines[line]; line++)
  133. puts(lines[line]);
  134. } else
  135. errx(1, "Unknown type '%s'", type);
  136. talloc_free(lines);
  137. }
  138. return 0;
  139. }