- unsigned int max = 16384, size = 0;
- int ret, fd;
- char *buffer;
-
- if (streq(filename, "-"))
- fd = dup(STDIN_FILENO);
- else
- fd = open(filename, O_RDONLY, 0);
-
- if (fd < 0)
- return NULL;
-
- buffer = talloc_array(ctx, char, max+1);
- while ((ret = read(fd, buffer + size, max - size)) > 0) {
- size += ret;
- if (size == max)
- buffer = talloc_realloc(ctx, buffer, char, max*=2 + 1);
+ char *file;
+ char **lines, **ret;
+ unsigned int i, num;
+ bool printing = false;
+
+ file = grab_file(NULL, fname, NULL);
+ if (!file)
+ err(1, "Reading file %s", fname);
+ lines = strsplit(file, file, "\n", &num);
+ 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 %s:%u", fname, i);
+ }
+ }
+ ret[num] = NULL;
+ talloc_free(file);
+ 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 maybe_one_liner)
+{
+ unsigned int len;
+
+ len = strcspn(line, " \t\n:");
+ if (len == 0)
+ return false;
+
+ if (line[len] != ':')
+ return false;
+
+ /* If it can be a one-liner, a space is sufficient.*/
+ if (maybe_one_liner && (line[len+1] == ' ' || line[len+1] == '\t'))
+ return true;
+
+ return line[len] == ':' && is_blank(line+len+1);
+}
+
+/* Summary line is form '<identifier> - ' */
+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 end_section(const char *line)
+{
+ return !line || is_section(line, true) || is_summary_line(line);
+}
+
+static unsigned int find_section(char **lines, const char *name,
+ bool maybe_one_liner)
+{
+ unsigned int i;
+
+ for (i = 0; lines[i]; i++) {
+ if (!is_section(lines[i], maybe_one_liner))
+ continue;
+ if (strncasecmp(lines[i], name, strlen(name)) != 0)
+ continue;
+ if (lines[i][strlen(name)] == ':')
+ break;
+ }
+ return i;
+}
+
+/* function is NULL if we don't care. */
+static unsigned int find_summary(char **lines, const char *function)
+{
+ unsigned int i;
+
+ for (i = 0; lines[i]; i++) {
+ if (!is_summary_line(lines[i]))
+ continue;
+ if (function) {
+ if (!strstarts(lines[i], function))
+ continue;
+ if (!strstarts(lines[i] + strlen(function), " - "))
+ continue;
+ }
+ break;