1 /* This merely extracts, doesn't do XML or anything. */
11 #include <ccan/talloc/talloc.h>
12 #include <ccan/str/str.h>
13 #include <ccan/str_talloc/str_talloc.h>
14 #include <ccan/grab_file/grab_file.h>
16 static char **grab_doc(const char *fname)
21 bool printing = false, printed = false;
23 file = grab_file(NULL, fname, NULL);
25 err(1, "Reading file %s", fname);
26 lines = strsplit(file, file, "\n", &num);
27 ret = talloc_array(NULL, char *, num+1);
30 for (i = 0; lines[i]; i++) {
31 if (streq(lines[i], "/**")) {
34 talloc_append_string(ret[num], "\n");
35 } else if (streq(lines[i], " */"))
38 if (strstarts(lines[i], " * "))
39 ret[num++] = talloc_strdup(ret, lines[i]+3);
40 else if (strstarts(lines[i], " *"))
41 ret[num++] = talloc_strdup(ret, lines[i]+2);
43 errx(1, "Malformed line %s:%u", fname, i);
51 static bool is_blank(const char *line)
53 return line && line[strspn(line, " \t\n")] == '\0';
56 static bool is_section(const char *line, bool maybe_one_liner)
60 len = strcspn(line, " \t\n:");
67 /* If it can be a one-liner, a space is sufficient.*/
68 if (maybe_one_liner && (line[len+1] == ' ' || line[len+1] == '\t'))
71 return line[len] == ':' && is_blank(line+len+1);
75 static bool end_section(const char *line)
77 return !line || is_section(line, true);
80 static unsigned int find_section(char **lines, const char *name,
85 for (i = 0; lines[i]; i++) {
86 if (!is_section(lines[i], maybe_one_liner))
88 if (strncasecmp(lines[i], name, strlen(name)) != 0)
90 if (lines[i][strlen(name)] == ':')
96 int main(int argc, char *argv[])
102 errx(1, "Usage: doc_extract TYPE <file>...\n"
103 "Where TYPE is author|licence|maintainer|summary|description|example|all");
106 for (i = 2; i < argc; i++) {
108 char **lines = grab_doc(argv[i]);
111 errx(1, "No documentation in file");
113 /* Simple one-line fields. */
114 if (streq(type, "author")
115 || streq(type, "maintainer")
116 || streq(type, "licence")) {
117 line = find_section(lines, type, true);
119 const char *p = strchr(lines[line], ':') + 1;
120 p += strspn(p, " \t\n");
122 /* Must be on next line. */
123 if (end_section(lines[line+1]))
124 errx(1, "Malformed %s", type);
129 } else if (streq(type, "summary")) {
130 /* Summary comes after - on first line. */
133 dash = strchr(lines[0], '-');
135 errx(1, "Malformed first line: no -");
136 dash += strspn(dash, "- ");
138 } else if (streq(type, "description")) {
140 while (is_blank(lines[line]))
143 while (!end_section(lines[line]))
145 } else if (streq(type, "example")) {
146 line = find_section(lines, type, false);
151 while (is_blank(lines[line]))
154 /* Examples can be indented. Take cue
155 * from first non-blank line. */
157 strip = strspn(lines[line], " \t");
159 while (!end_section(lines[line])) {
160 if (strspn(lines[line], " \t") >= strip)
161 puts(lines[line] + strip);
167 } else if (streq(type, "all")) {
168 for (line = 0; lines[line]; line++)
171 errx(1, "Unknown type '%s'", type);