static GList* load_bzrep_conf_file(const char *path) { FILE *fp = stdin; if (strcmp(path, "-") != 0) { fp = fopen(path, "r"); if (!fp) return NULL; } GList *sections = NULL; char *line; while ((line = xmalloc_fgetline(fp)) != NULL) { /* Skip comments */ char first = *skip_whitespace(line); if (first == '#') goto free_line; /* Handle trailing backslash continuation */ check_continuation: ; unsigned len = strlen(line); if (len && line[len-1] == '\\') { line[len-1] = '\0'; char *next_line = xmalloc_fgetline(fp); if (next_line) { line = append_to_malloced_string(line, next_line); free(next_line); goto check_continuation; } } /* We are reusing line buffer to form temporary * "key\0values\0..." in its beginning */ bool summary_line = false; char *value = NULL; char *src; char *dst; for (src = dst = line; *src; src++) { char c = *src; /* did we reach the value list? */ if (!value && c == ':' && src[1] == ':') { *dst++ = '\0'; /* terminate key */ src += 2; value = dst; /* remember where value starts */ summary_line = (strcmp(line, "%summary") == 0); if (summary_line) { value = src; break; } continue; } /* skip whitespace in value list */ if (value && isspace(c)) continue; *dst++ = c; /* store next key or value char */ } GList *item_list = NULL; if (summary_line) { /* %summary is special */ item_list = g_list_append(NULL, xstrdup(skip_whitespace(value))); } else { *dst = '\0'; /* terminate value (or key) */ if (value) item_list = split_string_on_char(value, ','); } section_t *sec = xzalloc(sizeof(*sec)); sec->name = xstrdup(line); sec->items = item_list; sections = g_list_prepend(sections, sec); free_line: free(line); } if (fp != stdin) fclose(fp); return g_list_reverse(sections); }
static GList* load_stream(FILE *fp) { assert(fp); GList *sections = NULL; section_t *master = section_new("%description"); section_t *sec = NULL; sections = g_list_append(sections, master); char *line; while ((line = xmalloc_fgetline(fp)) != NULL) { /* Skip comments */ char first = *skip_whitespace(line); if (first == '#') goto free_line; /* Handle trailing backslash continuation */ check_continuation: ; unsigned len = strlen(line); if (len && line[len-1] == '\\') { line[len-1] = '\0'; char *next_line = xmalloc_fgetline(fp); if (next_line) { line = append_to_malloced_string(line, next_line); free(next_line); goto check_continuation; } } /* We are reusing line buffer to form temporary * "key\0values\0..." in its beginning */ bool summary_line = false; char *value = NULL; char *src; char *dst; for (src = dst = line; *src; src++) { char c = *src; /* did we reach the value list? */ if (!value && c == ':' && src[1] == ':') { *dst++ = '\0'; /* terminate key */ src += 1; value = dst; /* remember where value starts */ summary_line = (strcmp(line, "%summary") == 0); if (summary_line) { value = (src + 1); break; } continue; } /* skip whitespace in value list */ if (value && isspace(c)) continue; *dst++ = c; /* store next key or value char */ } GList *item_list = NULL; if (summary_line) { /* %summary is special */ item_list = g_list_append(NULL, xstrdup(skip_whitespace(value))); } else { *dst = '\0'; /* terminate value (or key) */ if (value) item_list = split_string_on_char(value, ','); } sec = section_new(line); sec->items = item_list; if (sec->name[0] == '%') { if (!summary_line && strcmp(sec->name, "%attach") != 0) { master->children = g_list_reverse(master->children); master = sec; } sections = g_list_prepend(sections, sec); } else master->children = g_list_prepend(master->children, sec); free_line: free(line); } /* If master equals sec, then master's children list was not yet reversed. * * %description is the default section (i.e is not explicitly mentioned) * and %summary nor %attach cause its children list to reverse. */ if (master == sec || strcmp(master->name, "%description") == 0) master->children = g_list_reverse(master->children); return sections; }