/* This merely extracts, doesn't do XML or anything. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "doc_extract.h" #include "tools.h" static char **grab_doc(char **lines, unsigned int num) { char **ret; unsigned int i; bool printing = false; ret = talloc_array(NULL, char *, num+1); num = 0; for (i = 0; lines[i]; i++) { if (streq(lines[i], "/**")) { printing = true; if (num != 0) talloc_append_string(ret[num-1], "\n"); } else if (streq(lines[i], " */")) printing = false; else if (printing) { if (strstarts(lines[i], " * ")) ret[num++] = talloc_strdup(ret, lines[i]+3); else if (strstarts(lines[i], " *")) ret[num++] = talloc_strdup(ret, lines[i]+2); else errx(1, "Malformed line %u", i); } } ret[num] = NULL; return ret; } static bool is_blank(const char *line) { return line && line[strspn(line, " \t\n")] == '\0'; } static bool is_section(const char *line, bool one_liner) { unsigned int len; if (!isupper(line[0])) return false; len = strspn(line, IDENT_CHARS); if (line[len] != ':') return false; /* If it can be a one-liner, a space is sufficient.*/ if (one_liner) return (line[len+1] == ' ' || line[len+1] == '\t'); return line[len] == ':' && is_blank(line+len+1); } /* Summary line is form ' - ' */ static bool is_summary_line(const char *line) { unsigned int id_len; id_len = strspn(line, IDENT_CHARS); if (id_len == 0) return false; if (!strstarts(line + id_len, " - ")) return false; return true; } static bool empty_section(struct doc_section *d) { unsigned int i; for (i = 0; i < d->num_lines; i++) if (!is_blank(d->lines[i])) return false; return true; } static struct doc_section *new_section(struct list_head *list, const char *function, const char *type) { struct doc_section *d; char *lowertype; unsigned int i; /* If previous section was empty, delete it. */ d = list_tail(list, struct doc_section, list); if (d && empty_section(d)) { list_del(&d->list); talloc_free(d); } d = talloc(list, struct doc_section); d->function = function; lowertype = talloc_size(d, strlen(type) + 1); /* Canonicalize type to lower case. */ for (i = 0; i < strlen(type)+1; i++) lowertype[i] = tolower(type[i]); d->type = lowertype; d->lines = NULL; d->num_lines = 0; list_add_tail(list, &d->list); return d; } static void add_line(struct doc_section *curr, const char *line) { curr->lines = talloc_realloc(curr, curr->lines, char *, curr->num_lines+1); curr->lines[curr->num_lines++] = talloc_strdup(curr->lines, line); } struct list_head *extract_doc_sections(char **rawlines, unsigned int num) { char **lines = grab_doc(rawlines, num); const char *function = NULL; struct doc_section *curr = NULL; unsigned int i; struct list_head *list; list = talloc(NULL, struct list_head); list_head_init(list); for (i = 0; lines[i]; i++) { if (is_summary_line(lines[i])) { function = talloc_strndup(list, lines[i], strcspn(lines[i], " ")); curr = new_section(list, function, "summary"); add_line(curr, strstr(lines[i], " - ") + 3); curr = new_section(list, function, "description"); } else if (is_section(lines[i], false)) { char *type = talloc_strndup(curr, lines[i], strcspn(lines[i], ":")); curr = new_section(list, function, type); } else if (is_section(lines[i], true)) { unsigned int sectlen = strcspn(lines[i], ":"); char *type = talloc_strndup(curr, lines[i], sectlen); curr = new_section(list, function, type); add_line(curr, lines[i] + sectlen + 1 + strspn(lines[i] + sectlen + 1, " \t")); } else { if (!curr) continue; add_line(curr, lines[i]); } } talloc_free(lines); return list; }