From: Amos Jeffries Date: Sun, 21 Aug 2011 06:34:26 +0000 (+1200) Subject: Update cf_gen objects to use STL containers and extend syntax for DEFAULT* X-Git-Tag: take08~43^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=576b1e98c872a128504bb734ed00023c539179d4;p=thirdparty%2Fsquid.git Update cf_gen objects to use STL containers and extend syntax for DEFAULT* Removes all need for explicit memory management of the parsed tree. Alters DEFAULT: tag to allow multiple line values to be pre-defined. Adds DEFAULT_DOC: tag to allow text description of a default in the documented versions of config file instead of explicit code-level values. Also updates the output slightly so cf_parser.cci conforms to the current coding style gidelines. --- diff --git a/src/cf_gen.cc b/src/cf_gen.cc index 3b38486958..adbafa6414 100644 --- a/src/cf_gen.cc +++ b/src/cf_gen.cc @@ -1,6 +1,8 @@ /* * DEBUG: none Generate squid.conf.default and cf_parser.cci * AUTHOR: Max Okumoto + * AUTHOR: Francesco Chemolli + * AUTHOR: Amos Jeffries * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- @@ -60,6 +62,7 @@ _FILE_OFFSET_BITS==64 #include #include #include +#include #include "cf_gen_defines.cci" @@ -77,111 +80,91 @@ enum State { sEXIT }; -// TODO: inherit all these from link lists. +typedef std::list LineList; +typedef std::list TypeDepList; +typedef std::list EntryAliasList; -class Line +class DefaultValues { public: - Line(const char *str) : data(str), next(NULL) {} - ~Line() {} + DefaultValues() : preset(), if_none(), docs() {} + ~DefaultValues() {} - std::string data; - Line *next; -}; + /// Default config lines to be defined before parsing the config files. + LineList preset; -class EntryAlias -{ -public: - EntryAlias(const char *str) : name(str), next(NULL) {} - ~EntryAlias() {} + /// Default config lines to parse if the directive has no prior settings. + /// This is mutually exclusive with preset values. + /// An error will be printed during build if they clash. + LineList if_none; - std::string name; - EntryAlias *next; + /// Text description to use in documentation for the default. + /// If unset the preset or if-none values will be displayed. + LineList docs; }; class Entry { public: Entry(const char *str) : - name(str), alias(), type(), loc(), - default_value(), default_if_none(), - comment(), ifdef(), doc(), nocomment(), - next(NULL) {} + name(str), alias(),type(), loc(), + defaults(), comment(), ifdef(), doc(), nocomment(), + array_flag(0) {} ~Entry() {} std::string name; - EntryAlias *alias; + EntryAliasList alias; std::string type; std::string loc; - std::string default_value; - Line *default_if_none; + DefaultValues defaults; std::string comment; std::string ifdef; - Line *doc; - Line *nocomment; + LineList doc; + LineList nocomment; int array_flag; - Entry *next; -}; + void genParse(std::ostream &fout) const; -class TypeDep -{ -public: - TypeDep(const char *str) : name(str), next(NULL) {} - ~TypeDep() {} - - std::string name; - TypeDep *next; +private: + void genParseAlias(const std::string &, std::ostream &) const; }; +typedef std::list EntryList; + class Type { public: - Type(const char *str) : name(str), next(NULL) {} + Type(const char *str) : name(str) {} ~Type() {} std::string name; - TypeDep *depend; - Type *next; + TypeDepList depend; }; -static const char WS[] = " \t\n"; -static int gen_default(Entry *, std::ostream &); -static void gen_parse(Entry *, std::ostream &); -static void gen_parse_entry(Entry *entry, std::ostream&); -static void gen_parse_alias(const std::string &, EntryAlias *, Entry *, std::ostream &); -static void gen_dump(Entry *, std::ostream&); -static void gen_free(Entry *, std::ostream&); -static void gen_conf(Entry *, std::ostream&, bool verbose_output); -static void gen_default_if_none(Entry *, std::ostream&); - -static void -lineAdd(Line ** L, const char *str) -{ - assert(str); +typedef std::list TypeList; - while (*L) - L = &(*L)->next; - - *L = new Line(str); -} +static const char WS[] = " \t\n"; +static int gen_default(const EntryList &, std::ostream &); +static void gen_parse(const EntryList &, std::ostream &); +static void gen_dump(const EntryList &, std::ostream&); +static void gen_free(const EntryList &, std::ostream&); +static void gen_conf(const EntryList &, std::ostream&, bool verbose_output); +static void gen_default_if_none(const EntryList &, std::ostream&); static void -checkDepend(const std::string &directive, const char *name, const Type *types, const Entry *entries) +checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries) { - const Type *type; - for (type = types; type; type = type->next) { - const TypeDep *dep; - if (type->name.compare(name) != 0) + for (TypeList::const_iterator t = types.begin(); t != types.end(); ++t) { + if (t->name.compare(name) != 0) continue; - for (dep = type->depend; dep; dep = dep->next) { - const Entry *entry; - for (entry = entries; entry; entry = entry->next) { - if (entry->name.compare(dep->name) == 0) + for (TypeDepList::const_iterator dep = t->depend.begin(); dep != t->depend.end(); ++dep) { + EntryList::const_iterator entry = entries.begin(); + for (; entry != entries.end(); ++entry) { + if (entry->name.compare(*dep) == 0) break; } - if (!entry) { - std::cerr << "ERROR: '" << directive << "' (" << name << ") depends on '" << dep->name << "'\n"; + if (entry == entries.end()) { + std::cerr << "ERROR: '" << directive << "' (" << name << ") depends on '" << *dep << "'\n"; exit(1); } } @@ -207,9 +190,8 @@ main(int argc, char *argv[]) const char *conf_filename_short = _PATH_SQUID_CONF_SHORT; const char *type_depend; int linenum = 0; - Entry *entries = NULL; - Entry *curr = NULL; - Type *types = NULL; + EntryList entries; + TypeList types; enum State state; int rc = 0; char *ptr = NULL; @@ -238,14 +220,11 @@ main(int argc, char *argv[]) const char *dep; if (!type || type[0] == '#') continue; - Type *t = new Type(type); + Type t(type); while ((dep = strtok(NULL, WS)) != NULL) { - TypeDep *d = new TypeDep(dep); - d->next = t->depend; - t->depend = d; + t.depend.push_front(dep); } - t->next = types; - types = t; + types.push_front(t); } fp.close(); fp.clear(); // BSD does not reset flags in close(). @@ -287,20 +266,17 @@ main(int argc, char *argv[]) exit(1); } - curr = new Entry(name); + entries.push_back(name); - while ((aliasname = strtok(NULL, WS)) != NULL) { - EntryAlias *alias = new EntryAlias(aliasname); - alias->next = curr->alias; - curr->alias = alias; - } + while ((aliasname = strtok(NULL, WS)) != NULL) + entries.back().alias.push_front(aliasname); state = s1; } else if (!strcmp(buff, "EOF")) { state = sEXIT; } else if (!strcmp(buff, "COMMENT_START")) { - curr = new Entry("comment"); - curr->loc = "none"; + entries.push_back("comment"); + entries.back().loc = "none"; state = sDOC; } else { std::cerr << "Error on line " << linenum << std::endl << @@ -310,7 +286,8 @@ main(int argc, char *argv[]) break; - case s1: + case s1: { + Entry &curr = entries.back(); if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { /* ignore empty and comment lines */ @@ -321,28 +298,35 @@ main(int argc, char *argv[]) while (isspace((unsigned char)*ptr)) ptr++; - curr->comment = ptr; + curr.comment = ptr; } else if (!strncmp(buff, "DEFAULT:", 8)) { ptr = buff + 8; while (isspace((unsigned char)*ptr)) ptr++; - curr->default_value = ptr; + curr.defaults.preset.push_back(ptr); } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { ptr = buff + 16; while (isspace((unsigned char)*ptr)) ptr++; - lineAdd(&curr->default_if_none, ptr); + curr.defaults.if_none.push_back(ptr); + } else if (!strncmp(buff, "DEFAULT_DOC:", 12)) { + ptr = buff + 12; + + while (isspace((unsigned char)*ptr)) + ptr++; + + curr.defaults.docs.push_back(ptr); } else if (!strncmp(buff, "LOC:", 4)) { if ((ptr = strtok(buff + 4, WS)) == NULL) { std::cerr << "Error on line " << linenum << std::endl; exit(1); } - curr->loc = ptr; + curr.loc = ptr; } else if (!strncmp(buff, "TYPE:", 5)) { if ((ptr = strtok(buff + 5, WS)) == NULL) { std::cerr << "Error on line " << linenum << std::endl; @@ -351,88 +335,48 @@ main(int argc, char *argv[]) /* hack to support arrays, rather than pointers */ if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) { - curr->array_flag = 1; + curr.array_flag = 1; *(ptr + strlen(ptr) - 2) = '\0'; } - checkDepend(curr->name, ptr, types, entries); - curr->type = ptr; + checkDepend(curr.name, ptr, types, entries); + curr.type = ptr; } else if (!strncmp(buff, "IFDEF:", 6)) { if ((ptr = strtok(buff + 6, WS)) == NULL) { std::cerr << "Error on line " << linenum << std::endl; exit(1); } - curr->ifdef = ptr; + curr.ifdef = ptr; } else if (!strcmp(buff, "DOC_START")) { state = sDOC; } else if (!strcmp(buff, "DOC_NONE")) { - /* add to list of entries */ - curr->next = entries; - entries = curr; state = sSTART; } else { std::cerr << "Error on line " << linenum << std::endl; exit(1); } - - break; + } + break; case sDOC: - if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) { - Line *head = NULL; - Line *line = curr->doc; - /* reverse order of doc lines */ - - while (line != NULL) { - Line *tmp; - tmp = line->next; - line->next = head; - head = line; - line = tmp; - } - - curr->doc = head; - /* add to list of entries */ - curr->next = entries; - entries = curr; state = sSTART; } else if (!strcmp(buff, "NOCOMMENT_START")) { state = sNOCOMMENT; } else { // if (buff != NULL) { assert(buff != NULL); - Line *line = new Line(buff); - line->next = curr->doc; - curr->doc = line; + entries.back().doc.push_back(buff); } - break; case sNOCOMMENT: - if (!strcmp(buff, "NOCOMMENT_END")) { - Line *head = NULL; - Line *line = curr->nocomment; - /* reverse order of lines */ - - while (line != NULL) { - Line *tmp; - tmp = line->next; - line->next = head; - head = line; - line = tmp; - } - - curr->nocomment = head; state = sDOC; } else { // if (buff != NULL) { assert(buff != NULL); - Line *line = new Line(buff); - line->next = curr->nocomment; - curr->nocomment = line; + entries.back().nocomment.push_back(buff); } - break; case sEXIT: @@ -445,20 +389,6 @@ main(int argc, char *argv[]) if (state != sEXIT) { std::cerr << "Error: unexpected EOF\n"; exit(1); - } else { - /* reverse order of entries */ - Entry *head = NULL; - - while (entries != NULL) { - Entry *tmp; - - tmp = entries->next; - entries->next = head; - head = entries; - entries = tmp; - } - - entries = head; } fp.close(); @@ -487,8 +417,6 @@ main(int argc, char *argv[]) " * Abstract: This file contains routines used to configure the\n" " * variables in the squid server.\n" " */\n" - "\n" - "#include \"config.h\"\n" "\n"; rc = gen_default(entries, fout); @@ -528,28 +456,26 @@ main(int argc, char *argv[]) } static int -gen_default(Entry * head, std::ostream &fout) +gen_default(const EntryList &head, std::ostream &fout) { - Entry *entry; int rc = 0; - fout << "static void\n" - "default_line(const char *s)\n" - "{\n" - "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n" - "\txstrncpy(tmp_line, s, BUFSIZ);\n" - "\txstrncpy(config_input_line, s, BUFSIZ);\n" - "\tconfig_lineno++;\n" - "\tparse_line(tmp_line);\n" - "}\n"; - fout << "static void\n" - "default_all(void)\n" - "{\n" - "\tcfg_filename = \"Default Configuration\";\n" - "\tconfig_lineno = 0;\n"; - - for (entry = head; entry != NULL; entry = entry->next) { + fout << "static void" << std::endl << + "default_line(const char *s)" << std::endl << + "{" << std::endl << + " LOCAL_ARRAY(char, tmp_line, BUFSIZ);" << std::endl << + " xstrncpy(tmp_line, s, BUFSIZ);" << std::endl << + " xstrncpy(config_input_line, s, BUFSIZ);" << std::endl << + " config_lineno++;" << std::endl << + " parse_line(tmp_line);" << std::endl << + "}" << std::endl << std::endl; + fout << "static void" << std::endl << + "default_all(void)" << std::endl << + "{" << std::endl << + " cfg_filename = \"Default Configuration\";" << std::endl << + " config_lineno = 0;" << std::endl; + + for (EntryList::const_iterator entry = head.begin(); entry != head.end(); ++entry) { assert(entry->name.size()); - assert(entry != entry->next); if (!entry->name.compare("comment")) continue; @@ -563,125 +489,113 @@ gen_default(Entry * head, std::ostream &fout) continue; } - if (!entry->default_value.size() && entry->default_if_none == NULL) { + if (!entry->defaults.preset.size() && entry->defaults.if_none.empty()) { std::cerr << "NO DEFAULT FOR " << entry->name << std::endl; rc |= 1; continue; } - if (!entry->default_value.size() || entry->default_value.compare("none") == 0) { - fout << "\t/* No default for " << entry->name << " */\n"; + if (!entry->defaults.preset.size() || entry->defaults.preset.front().compare("none") == 0) { + fout << " // No default for " << entry->name << std::endl; } else { if (entry->ifdef.size()) fout << "#if " << entry->ifdef << std::endl; - fout << "\tdefault_line(\"" << entry->name << " " << - entry->default_value << "\");\n"; + for (LineList::const_iterator l = entry->defaults.preset.begin(); l != entry->defaults.preset.end(); ++l) { + fout << " default_line(\"" << entry->name << " " << *l << "\");" << std::endl; + } if (entry->ifdef.size()) - fout << "#endif\n"; + fout << "#endif" << std::endl; } } - fout << "\tcfg_filename = NULL;\n" - "}\n\n"; + fout << " cfg_filename = NULL;" << std::endl << + "}" << std::endl << std::endl; return rc; } static void -gen_default_if_none(Entry * head, std::ostream &fout) +gen_default_if_none(const EntryList &head, std::ostream &fout) { - Entry *entry; - Line *line; - fout << "static void\n" - "defaults_if_none(void)\n" - "{\n"; + fout << "static void" << std::endl << + "defaults_if_none(void)" << std::endl << + "{" << std::endl; - for (entry = head; entry != NULL; entry = entry->next) { + for (EntryList::const_iterator entry = head.begin(); entry != head.end(); ++entry) { assert(entry->name.size()); if (!entry->loc.size()) continue; - if (entry->default_if_none == NULL) + if (entry->defaults.if_none.empty()) continue; + if (!entry->defaults.preset.empty()) { + std::cerr << "ERROR: " << entry->name << " has preset defaults. DEFAULT_IF_NONE cannot be true." << std::endl; + exit(1); + } + if (entry->ifdef.size()) fout << "#if " << entry->ifdef << std::endl; - if (entry->default_if_none) { - fout << "\tif (check_null_" << entry->type << "(" << - entry->loc << ")) {\n"; - - for (line = entry->default_if_none; line; line = line->next) - fout << "\t\tdefault_line(\"" << entry->name << " " << - line->data <<"\");\n"; - - fout << "\t}\n"; - } + fout << " if (check_null_" << entry->type << "(" << entry->loc << ")) {" << std::endl; + for (LineList::const_iterator l = entry->defaults.if_none.begin(); l != entry->defaults.if_none.end(); ++l) + fout << " default_line(\"" << entry->name << " " << *l <<"\");" << std::endl; + fout << " }" << std::endl; if (entry->ifdef.size()) - fout << "#endif\n"; + fout << "#endif" << std::endl; } - fout << "}\n\n"; + fout << "}" << std::endl << std::endl; } void -gen_parse_alias(const std::string &name, EntryAlias *alias, Entry *entry, std::ostream &fout) +Entry::genParseAlias(const std::string &aName, std::ostream &fout) const { - fout << "\tif (!strcmp(token, \"" << name << "\")) {\n"; - - if (entry->type.compare("obsolete") == 0) { - fout << "\t\tdebugs(0, DBG_CRITICAL, \"ERROR: Directive '" << name << "' is obsolete.\");\n"; - for (Line *line = entry->doc; line != NULL; line = line->next) { + fout << " if (!strcmp(token, \"" << aName << "\")) {" << std::endl; + fout << " "; + if (type.compare("obsolete") == 0) { + fout << "debugs(0, DBG_CRITICAL, \"ERROR: Directive '" << aName << "' is obsolete.\");\n"; + for (LineList::const_iterator l = doc.begin(); l != doc.end(); ++l) { // offset line to strip initial whitespace tab byte - fout << "\t\tdebugs(0, opt_parse_cfg_only?0:1, \"" << name << " : " << &line->data[1] << "\");\n"; + fout << " debugs(0, opt_parse_cfg_only?0:1, \"" << aName << " : " << &(*l)[1] << "\");" << std::endl; } - fout << "\t\tparse_obsolete(token);\n"; - } else if (!entry->loc.size() || entry->loc.compare("none") == 0) { - fout << "\t\tparse_" << entry->type << "();\n"; + fout << " parse_obsolete(token);"; + } else if (!loc.size() || loc.compare("none") == 0) { + fout << "parse_" << type << "();"; } else { - fout << "\t\tparse_" << entry->type << "(&" << entry->loc << - (entry->array_flag ? "[0]" : "") << ");\n"; + fout << "parse_" << type << "(&" << loc << (array_flag ? "[0]" : "") << ");"; } - - fout << "\t\treturn 1;\n"; - fout << "\t};\n"; + fout << std::endl; + fout << " return 1;" << std::endl; + fout << " };" << std::endl; } void -gen_parse_entry(Entry *entry, std::ostream &fout) +Entry::genParse(std::ostream &fout) const { - if (entry->name.compare("comment") == 0) + if (name.compare("comment") == 0) return; - if (entry->ifdef.size()) - fout << "#if " << entry->ifdef << std::endl; + if (ifdef.size()) + fout << "#if " << ifdef << std::endl; - std::string &name = entry->name; + // Once for the current directive name + genParseAlias(name, fout); - EntryAlias *alias = entry->alias; - - bool more; - - do { - gen_parse_alias(name, alias, entry, fout); - more = false; - - if (alias) { - name = alias->name; - alias = alias->next; - more = true; - } - } while (more); + // All accepted aliases + for (EntryAliasList::const_iterator a = alias.begin(); a != alias.end(); ++a) { + genParseAlias(*a, fout); + } - if (entry->ifdef.size()) + if (ifdef.size()) fout << "#endif\n"; } static void -gen_parse(Entry * head, std::ostream &fout) +gen_parse(const EntryList &head, std::ostream &fout) { fout << "static int\n" @@ -691,8 +605,8 @@ gen_parse(Entry * head, std::ostream &fout) "\tif ((token = strtok(buff, w_space)) == NULL) \n" "\t\treturn 1;\t/* ignore empty lines */\n"; - for (Entry *entry = head; entry != NULL; entry = entry->next) - gen_parse_entry (entry, fout); + for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) + e->genParse(fout); fout << "\treturn 0; /* failure */\n" "}\n\n"; @@ -700,68 +614,64 @@ gen_parse(Entry * head, std::ostream &fout) } static void -gen_dump(Entry * head, std::ostream &fout) +gen_dump(const EntryList &head, std::ostream &fout) { - Entry *entry; fout << - "static void\n" - "dump_config(StoreEntry *entry)\n" - "{\n" - " debugs(5, 4, HERE);\n"; + "static void" << std::endl << + "dump_config(StoreEntry *entry)" << std::endl << + "{" << std::endl << + " debugs(5, 4, HERE);" << std::endl; - for (entry = head; entry != NULL; entry = entry->next) { + for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) { - if (!entry->loc.size() || entry->loc.compare("none") == 0) + if (!e->loc.size() || e->loc.compare("none") == 0) continue; - if (entry->name.compare("comment") == 0) + if (e->name.compare("comment") == 0) continue; - if (entry->ifdef.size()) - fout << "#if " << entry->ifdef << std::endl; + if (e->ifdef.size()) + fout << "#if " << e->ifdef << std::endl; - fout << "\tdump_" << entry->type << "(entry, \"" << entry->name << - "\", " << entry->loc << ");\n"; + fout << " dump_" << e->type << "(entry, \"" << e->name << "\", " << e->loc << ");" << std::endl; - if (entry->ifdef.size()) - fout << "#endif\n"; + if (e->ifdef.size()) + fout << "#endif" << std::endl; } - fout << "}\n\n"; + fout << "}" << std::endl << std::endl; } static void -gen_free(Entry * head, std::ostream &fout) +gen_free(const EntryList &head, std::ostream &fout) { - Entry *entry; fout << - "static void\n" - "free_all(void)\n" - "{\n" - " debugs(5, 4, HERE);\n"; + "static void" << std::endl << + "free_all(void)" << std::endl << + "{" << std::endl << + " debugs(5, 4, HERE);" << std::endl; - for (entry = head; entry != NULL; entry = entry->next) { - if (!entry->loc.size() || entry->loc.compare("none") == 0) + for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) { + if (!e->loc.size() || e->loc.compare("none") == 0) continue; - if (entry->name.compare("comment") == 0) + if (e->name.compare("comment") == 0) continue; - if (entry->ifdef.size()) - fout << "#if " << entry->ifdef << std::endl; + if (e->ifdef.size()) + fout << "#if " << e->ifdef << std::endl; - fout << "\tfree_" << entry->type << "(&" << entry->loc << - (entry->array_flag ? "[0]" : "") << ");\n"; + fout << " free_" << e->type << "(&" << e->loc << (e->array_flag ? "[0]" : "") << ");" << std::endl; - if (entry->ifdef.size()) - fout << "#endif\n"; + if (e->ifdef.size()) + fout << "#endif" << std::endl; } - fout << "}\n\n"; + fout << "}" << std::endl << std::endl; } static bool -defined(const std::string &name) +isDefined(const std::string &name) { if (!name.size()) return true; @@ -780,7 +690,7 @@ available_if(const std::string &name) assert(name.size()); for (int i = 0; defines[i].name; i++) { - if (name.compare(defines[i].name) != 0) + if (name.compare(defines[i].name) == 0) return defines[i].enable; } @@ -788,16 +698,14 @@ available_if(const std::string &name) } static void -gen_conf(Entry * head, std::ostream &fout, bool verbose_output) +gen_conf(const EntryList &head, std::ostream &fout, bool verbose_output) { - Entry *entry; - char buf[8192]; - Line *def = NULL; - - for (entry = head; entry != NULL; entry = entry->next) { - Line *line; + for (EntryList::const_iterator entry = head.begin(); entry != head.end(); ++entry) { + char buf[8192]; + LineList def; int enabled = 1; + // Display TAG: line if (!entry->name.compare("comment")) (void) 0; else if (!entry->name.compare("obsolete")) @@ -811,64 +719,68 @@ gen_conf(Entry * head, std::ostream &fout, bool verbose_output) fout << std::endl; } - if (!defined(entry->ifdef)) { + // Display --enable/--disable disclaimer + if (!isDefined(entry->ifdef)) { if (verbose_output) { - - fout << "# Note: This option is only available if " - "Squid is rebuilt with the\n" << - "# " << available_if(entry->ifdef) << "\n#\n"; + fout << "# Note: This option is only available if Squid is rebuilt with the" << std::endl << + "# " << available_if(entry->ifdef) << std::endl << + "#" << std::endl; } enabled = 0; } - if (verbose_output) { - for (line = entry->doc; line != NULL; line = line->next) { - fout << "#" << line->data << std::endl; + // Display DOC_START section + if (verbose_output && entry->doc.size()) { + for (LineList::const_iterator line = entry->doc.begin(); line != entry->doc.end(); ++line) { + fout << "#" << *line << std::endl; } } - if (entry->default_value.size() && entry->default_value.compare("none") != 0) { - snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), entry->default_value.c_str()); - lineAdd(&def, buf); - } - - if (entry->default_if_none) { - for (line = entry->default_if_none; line != NULL; line = line->next) { - snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), line->data.c_str()); - lineAdd(&def, buf); + if (entry->defaults.docs.size()) { + // Display the DEFAULT_DOC line(s) + def = entry->defaults.docs; + } else { + if (entry->defaults.preset.size() && entry->defaults.preset.front().compare("none") != 0) { + // Display DEFAULT: line(s) + for (LineList::const_iterator l = entry->defaults.preset.begin(); l != entry->defaults.preset.end(); ++l) { + snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), l->c_str()); + def.push_back(buf); + } + } else if (entry->defaults.if_none.size()) { + // Display DEFAULT_IF_NONE: line(s) + for (LineList::const_iterator l = entry->defaults.if_none.begin(); l != entry->defaults.if_none.end(); ++l) { + snprintf(buf, sizeof(buf), "%s %s", entry->name.c_str(), l->c_str()); + def.push_back(buf); + } } } - if (!def && entry->doc && !entry->nocomment && - entry->name.compare("comment") != 0) - lineAdd(&def, "none"); + // Display "none" if no default is set or comments to display + if (def.empty() && entry->nocomment.empty() && entry->name.compare("comment") != 0) + def.push_back("none"); - if (verbose_output && def && (entry->doc || entry->nocomment)) { + if (verbose_output && def.size()) { fout << "#Default:\n"; - while (def != NULL) { - line = def; - def = line->next; - line->next = NULL; // unlink to simplify delete - fout << "# " << line->data << std::endl; - delete line; + while (def.size()) { + fout << "# " << def.front() << std::endl; + def.pop_front(); } + if (entry->doc.empty() && entry->nocomment.empty()) + fout << std::endl; } - if (verbose_output && entry->nocomment) + if (verbose_output && entry->nocomment.size()) fout << "#" << std::endl; if (enabled || verbose_output) { - for (line = entry->nocomment; line != NULL; line = line->next) { - if (!line->data.size()) - continue; - if (!enabled && line->data[0] != '#') - fout << "#" << line->data << std::endl; - else - fout << line->data << std::endl; + for (LineList::const_iterator line = entry->nocomment.begin(); line != entry->nocomment.end(); ++line) { + if (!enabled && line->at(0) != '#') + fout << "#"; + fout << *line << std::endl; } } - if (verbose_output && entry->doc != NULL) { + if (verbose_output && entry->doc.size()) { fout << std::endl; } }