From: Francesco Chemolli Date: Sat, 27 Aug 2011 06:46:52 +0000 (-0600) Subject: Migrate cf_gen tool from C-style to C++ X-Git-Tag: SQUID_3_1_15~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7ca146354b5ffa497cc780933000bdd439247dac;p=thirdparty%2Fsquid.git Migrate cf_gen tool from C-style to C++ --- diff --git a/src/Makefile.am b/src/Makefile.am index 7662fb078c..90d3426bb7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,12 +199,8 @@ libexec_PROGRAMS = \ cf_gen_SOURCES = cf_gen.cc nodist_cf_gen_HEADER = cf_gen_defines.cci -cf_gen_LDADD= \ - ../compat/libcompat.la \ - -L../lib -lmiscutil \ - $(EPOLL_LIBS) \ - $(MINGW_LIBS) \ - $(XTRA_LIBS) +## cf_gen must be stand-alone executable. It is a purely build-time executable. +cf_gen_LDADD= cf_gen.$(OBJEXT): cf_gen_defines.cci ## cf_gen.cc needs src/cf_gen_defines.cci diff --git a/src/cf_gen.cc b/src/cf_gen.cc index c8681ffbba..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/ * ---------------------------------------------------------- @@ -45,18 +47,23 @@ * administrator. *****************************************************************************/ -//#include "squid.h" -#include "config.h" -//#include "SquidTime.h" -#include "util.h" - -#if HAVE_STRING_H -#include -#endif -#if HAVE_STRING_H -#include +/* + * hack around a bug in intel's c++ compiler's libraries which do not + * correctly support 64-bit iostreams + */ +#if defined(__INTEL_COMPILER) && defined(_FILE_OFFSET_BITS) && \ +_FILE_OFFSET_BITS==64 +#undef _FILE_OFFSET_BITS #endif +#include +#include +#include +#include +#include +#include +#include + #include "cf_gen_defines.cci" #define MAX_LINE 1024 /* longest configuration line */ @@ -73,125 +80,123 @@ enum State { sEXIT }; -typedef struct Line { - char *data; - - struct Line *next; -} Line; - -typedef struct EntryAlias { - - struct EntryAlias *next; - char *name; -} EntryAlias; - -typedef struct Entry { - char *name; - EntryAlias *alias; - char *type; - char *loc; - char *default_value; - Line *default_if_none; - char *comment; - char *ifdef; - Line *doc; - Line *nocomment; - int array_flag; +typedef std::list LineList; +typedef std::list TypeDepList; +typedef std::list EntryAliasList; - struct Entry *next; -} Entry; +class DefaultValues +{ +public: + DefaultValues() : preset(), if_none(), docs() {} + ~DefaultValues() {} -typedef struct TypeDep { - char *name; + /// Default config lines to be defined before parsing the config files. + LineList preset; - TypeDep *next; -} TypeDep; + /// 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; -typedef struct Type { - char *name; - TypeDep *depend; + /// Text description to use in documentation for the default. + /// If unset the preset or if-none values will be displayed. + LineList docs; +}; - struct Type *next; -} Type; +class Entry +{ +public: + Entry(const char *str) : + name(str), alias(),type(), loc(), + defaults(), comment(), ifdef(), doc(), nocomment(), + array_flag(0) {} + ~Entry() {} + + std::string name; + EntryAliasList alias; + std::string type; + std::string loc; + DefaultValues defaults; + std::string comment; + std::string ifdef; + LineList doc; + LineList nocomment; + int array_flag; -static const char WS[] = " \t\n"; -static int gen_default(Entry *, FILE *); -static void gen_parse(Entry *, FILE *); -static void gen_parse_entry(Entry *entry, FILE *fp); -static void gen_parse_alias(char *, EntryAlias *, Entry *, FILE *); -static void gen_dump(Entry *, FILE *); -static void gen_free(Entry *, FILE *); -static void gen_conf(Entry *, FILE *, bool verbose_output); -static void gen_default_if_none(Entry *, FILE *); + void genParse(std::ostream &fout) const; +private: + void genParseAlias(const std::string &, std::ostream &) const; +}; -static void -lineAdd(Line ** L, const char *str) +typedef std::list EntryList; + +class Type { - while (*L) - L = &(*L)->next; +public: + Type(const char *str) : name(str) {} + ~Type() {} - *L = (Line *)xcalloc(1, sizeof(Line)); + std::string name; + TypeDepList depend; +}; - (*L)->data = xstrdup(str); -} +typedef std::list TypeList; + +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 char *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 (strcmp(type->name, 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 (strcmp(entry->name, 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) { - fprintf(stderr, "ERROR: '%s' (%s) depends on '%s'\n", directive, name, dep->name); + if (entry == entries.end()) { + std::cerr << "ERROR: '" << directive << "' (" << name << ") depends on '" << *dep << "'\n"; exit(1); } } return; } - fprintf(stderr, "ERROR: Dependencies for cf.data type '%s' used in '%s' not defined\n", name, directive); + std::cerr << "ERROR: Dependencies for cf.data type '" << name << "' used in ' " << directive << "' not defined\n" ; exit(1); } static void usage(const char *program_name) { - fprintf(stderr, "Usage: %s cf.data cf.data.depend\n", program_name); + std::cerr << "Usage: " << program_name << " cf.data cf.data.depend\n"; exit(1); } int main(int argc, char *argv[]) { - FILE *fp; char *input_filename; const char *output_filename = _PATH_PARSER; const char *conf_filename = _PATH_SQUID_CONF; 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; -#ifdef _SQUID_OS2_ - - const char *rmode = "rt"; -#else - - const char *rmode = "r"; -#endif char buff[MAX_LINE]; + std::ifstream fp; if (argc != 3) usage(argv[0]); @@ -202,53 +207,45 @@ main(int argc, char *argv[]) /*-------------------------------------------------------------------* * Parse type dependencies *-------------------------------------------------------------------*/ - if ((fp = fopen(type_depend, rmode)) == NULL) { - perror(input_filename); + fp.open(type_depend, std::ifstream::in); + if (fp.fail()) { + std::cerr << "error while opening type dependencies file '" << + type_depend << "': " << strerror(errno) << std::endl; exit(1); } - while ((NULL != fgets(buff, MAX_LINE, fp))) { + while (fp.good()) { + fp.getline(buff,MAX_LINE); const char *type = strtok(buff, WS); const char *dep; if (!type || type[0] == '#') continue; - Type *t = (Type *)xcalloc(1, sizeof(*t)); - t->name = xstrdup(type); + Type t(type); while ((dep = strtok(NULL, WS)) != NULL) { - TypeDep *d = (TypeDep *)xcalloc(1, sizeof(*d)); - d->name = xstrdup(dep); - d->next = t->depend; - t->depend = d; + t.depend.push_front(dep); } - t->next = types; - types = t; + types.push_front(t); } - fclose(fp); + fp.close(); + fp.clear(); // BSD does not reset flags in close(). /*-------------------------------------------------------------------* * Parse input file *-------------------------------------------------------------------*/ /* Open input file */ - - if ((fp = fopen(input_filename, rmode)) == NULL) { - perror(input_filename); + fp.open(input_filename, std::ifstream::in); + if (fp.fail()) { + std::cerr << "error while opening input file '" << + input_filename << "': " << strerror(errno) << std::endl; exit(1); } -#ifdef _SQUID_WIN32_ - setmode(fileno(fp), O_TEXT); - -#endif - state = sSTART; - while (feof(fp) == 0 && state != sEXIT) { + while (fp.getline(buff,MAX_LINE), fp.good() && state != sEXIT) { char *t; - if (NULL == fgets(buff, MAX_LINE, fp)) - break; - linenum++; if ((t = strchr(buff, '\n'))) @@ -265,37 +262,32 @@ main(int argc, char *argv[]) char *name, *aliasname; if ((name = strtok(buff + 5, WS)) == NULL) { - printf("Error in input file\n"); + std::cerr << "Error in input file\n"; exit(1); } - curr = (Entry *)xcalloc(1, sizeof(Entry)); - curr->name = xstrdup(name); + entries.push_back(name); - while ((aliasname = strtok(NULL, WS)) != NULL) { - EntryAlias *alias = (EntryAlias *)xcalloc(1, sizeof(EntryAlias)); - alias->next = curr->alias; - alias->name = xstrdup(aliasname); - 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 = (Entry *)xcalloc(1, sizeof(Entry)); - curr->name = xstrdup("comment"); - curr->loc = xstrdup("none"); + entries.push_back("comment"); + entries.back().loc = "none"; state = sDOC; } else { - printf("Error on line %d\n", linenum); - printf("--> %s\n", buff); + std::cerr << "Error on line " << linenum << std::endl << + "--> " << buff << std::endl; exit(1); } break; - case s1: + case s1: { + Entry &curr = entries.back(); if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { /* ignore empty and comment lines */ @@ -303,149 +295,103 @@ main(int argc, char *argv[]) } else if (!strncmp(buff, "COMMENT:", 8)) { ptr = buff + 8; - while (xisspace(*ptr)) + while (isspace((unsigned char)*ptr)) ptr++; - curr->comment = xstrdup(ptr); + curr.comment = ptr; } else if (!strncmp(buff, "DEFAULT:", 8)) { ptr = buff + 8; - while (xisspace(*ptr)) + while (isspace((unsigned char)*ptr)) ptr++; - curr->default_value = xstrdup(ptr); + curr.defaults.preset.push_back(ptr); } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { ptr = buff + 16; - while (xisspace(*ptr)) + while (isspace((unsigned char)*ptr)) + ptr++; + + curr.defaults.if_none.push_back(ptr); + } else if (!strncmp(buff, "DEFAULT_DOC:", 12)) { + ptr = buff + 12; + + while (isspace((unsigned char)*ptr)) ptr++; - lineAdd(&curr->default_if_none, ptr); + curr.defaults.docs.push_back(ptr); } else if (!strncmp(buff, "LOC:", 4)) { if ((ptr = strtok(buff + 4, WS)) == NULL) { - printf("Error on line %d\n", linenum); + std::cerr << "Error on line " << linenum << std::endl; exit(1); } - curr->loc = xstrdup(ptr); + curr.loc = ptr; } else if (!strncmp(buff, "TYPE:", 5)) { if ((ptr = strtok(buff + 5, WS)) == NULL) { - printf("Error on line %d\n", linenum); + std::cerr << "Error on line " << linenum << std::endl; exit(1); } /* 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 = xstrdup(ptr); + checkDepend(curr.name, ptr, types, entries); + curr.type = ptr; } else if (!strncmp(buff, "IFDEF:", 6)) { if ((ptr = strtok(buff + 6, WS)) == NULL) { - printf("Error on line %d\n", linenum); + std::cerr << "Error on line " << linenum << std::endl; exit(1); } - curr->ifdef = xstrdup(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 { - printf("Error on line %d\n", linenum); + 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 { - Line *line = (Line *)xcalloc(1, sizeof(Line)); - line->data = xstrdup(buff); - line->next = curr->doc; - curr->doc = line; + } else { // if (buff != NULL) { + assert(buff != NULL); + 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 { - Line *line = (Line *)xcalloc(1, sizeof(Line)); - line->data = xstrdup(buff); - line->next = curr->nocomment; - curr->nocomment = line; + } else { // if (buff != NULL) { + assert(buff != NULL); + entries.back().nocomment.push_back(buff); } - break; case sEXIT: assert(0); /* should never get here */ break; } + } if (state != sEXIT) { - printf("Error unexpected EOF\n"); + 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; } - fclose(fp); + fp.close(); /*-------------------------------------------------------------------* * Generate default_all() @@ -457,434 +403,385 @@ main(int argc, char *argv[]) /* Open output x.c file */ - if ((fp = fopen(output_filename, "w")) == NULL) { - perror(output_filename); + std::ofstream fout(output_filename,std::ostream::out); + if (!fout.good()) { + std::cerr << "error while opening output .c file '" << + output_filename << "': " << strerror(errno) << std::endl; exit(1); } -#ifdef _SQUID_WIN32_ - setmode(fileno(fp), O_TEXT); - -#endif + fout << "/*\n" << + " * Generated automatically from " << input_filename << " by " << + argv[0] << "\n" + " *\n" + " * Abstract: This file contains routines used to configure the\n" + " * variables in the squid server.\n" + " */\n" + "\n"; - fprintf(fp, - "/*\n" - " * Generated automatically from %s by %s\n" - " *\n" - " * Abstract: This file contains routines used to configure the\n" - " * variables in the squid server.\n" - " */\n" - "\n" - "#include \"config.h\"\n" - "\n", - input_filename, argv[0] - ); + rc = gen_default(entries, fout); - rc = gen_default(entries, fp); + gen_default_if_none(entries, fout); - gen_default_if_none(entries, fp); + gen_parse(entries, fout); - gen_parse(entries, fp); + gen_dump(entries, fout); - gen_dump(entries, fp); + gen_free(entries, fout); - gen_free(entries, fp); - - fclose(fp); + fout.close(); /* Open output x.conf file */ - if ((fp = fopen(conf_filename, "w")) == NULL) { - perror(conf_filename); + fout.open(conf_filename,std::ostream::out); + if (!fout.good()) { + std::cerr << "error while opening output conf file '" << + output_filename << "': " << strerror(errno) << std::endl; exit(1); } -#ifdef _SQUID_WIN32_ - setmode(fileno(fp), O_TEXT); - -#endif + gen_conf(entries, fout, 1); - gen_conf(entries, fp, 1); + fout.close(); - fclose(fp); - - if ((fp = fopen(conf_filename_short, "w")) == NULL) { - perror(conf_filename_short); + fout.open(conf_filename_short,std::ostream::out); + if (!fout.good()) { + std::cerr << "error while opening output short conf file '" << + output_filename << "': " << strerror(errno) << std::endl; exit(1); } -#ifdef _SQUID_WIN32_ - setmode(fileno(fp), O_TEXT); -#endif - gen_conf(entries, fp, 0); - fclose(fp); + gen_conf(entries, fout, 0); + fout.close(); return (rc); } static int -gen_default(Entry * head, FILE * fp) +gen_default(const EntryList &head, std::ostream &fout) { - Entry *entry; int rc = 0; - fprintf(fp, - "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" - ); - fprintf(fp, - "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) { - assert(entry->name); - assert(entry != entry->next); - - if (!strcmp(entry->name, "comment")) + 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()); + + if (!entry->name.compare("comment")) continue; - if (!strcmp(entry->type, "obsolete")) + if (!entry->type.compare("obsolete")) continue; - if (entry->loc == NULL) { - fprintf(stderr, "NO LOCATION FOR %s\n", entry->name); + if (!entry->loc.size()) { + std::cerr << "NO LOCATION FOR " << entry->name << std::endl; rc |= 1; continue; } - if (entry->default_value == NULL && entry->default_if_none == NULL) { - fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); + 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 == NULL || strcmp(entry->default_value, "none") == 0) { - fprintf(fp, "\t/* No default for %s */\n", entry->name); + if (!entry->defaults.preset.size() || entry->defaults.preset.front().compare("none") == 0) { + fout << " // No default for " << entry->name << std::endl; } else { - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); + if (entry->ifdef.size()) + fout << "#if " << entry->ifdef << std::endl; - fprintf(fp, "\tdefault_line(\"%s %s\");\n", - entry->name, - entry->default_value); + 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) - fprintf(fp, "#endif\n"); + if (entry->ifdef.size()) + fout << "#endif" << std::endl; } } - fprintf(fp, "\tcfg_filename = NULL;\n"); - fprintf(fp, "}\n\n"); + fout << " cfg_filename = NULL;" << std::endl << + "}" << std::endl << std::endl; return rc; } static void -gen_default_if_none(Entry * head, FILE * fp) +gen_default_if_none(const EntryList &head, std::ostream &fout) { - Entry *entry; - Line *line; - fprintf(fp, - "static void\n" - "defaults_if_none(void)\n" - "{\n" - ); - - for (entry = head; entry != NULL; entry = entry->next) { - assert(entry->name); - - if (!entry->loc) + fout << "static void" << std::endl << + "defaults_if_none(void)" << std::endl << + "{" << std::endl; + + 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->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); + 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->default_if_none) { - fprintf(fp, - "\tif (check_null_%s(%s)) {\n", - entry->type, - entry->loc); + if (entry->ifdef.size()) + fout << "#if " << entry->ifdef << std::endl; - for (line = entry->default_if_none; line; line = line->next) - fprintf(fp, - "\t\tdefault_line(\"%s %s\");\n", - entry->name, - line->data); + 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; - fprintf(fp, "\t}\n"); - } - - if (entry->ifdef) - fprintf(fp, "#endif\n"); + if (entry->ifdef.size()) + fout << "#endif" << std::endl; } - fprintf(fp, "}\n\n"); + fout << "}" << std::endl << std::endl; } void -gen_parse_alias(char *name, EntryAlias *alias, Entry *entry, FILE *fp) +Entry::genParseAlias(const std::string &aName, std::ostream &fout) const { - fprintf(fp, "\tif (!strcmp(token, \"%s\")) {\n", name); - - if (strcmp(entry->type,"obsolete") == 0) { - fprintf(fp, "\t\tdebugs(0, DBG_CRITICAL, \"ERROR: Directive '%s' is obsolete.\");\n", name); - 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 - fprintf(fp, "\t\tdebugs(0, opt_parse_cfg_only?0:1, \"%s : %s\");\n", name, &line->data[1]); + fout << " debugs(0, opt_parse_cfg_only?0:1, \"" << aName << " : " << &(*l)[1] << "\");" << std::endl; } - fprintf(fp, "\t\tparse_obsolete(token);\n"); - } else if (!entry->loc || strcmp(entry->loc, "none") == 0) { - fprintf(fp, - "\t\tparse_%s();\n", - entry->type - ); + fout << " parse_obsolete(token);"; + } else if (!loc.size() || loc.compare("none") == 0) { + fout << "parse_" << type << "();"; } else { - fprintf(fp, - "\t\tparse_%s(&%s%s);\n", - entry->type, entry->loc, - entry->array_flag ? "[0]" : "" - ); + fout << "parse_" << type << "(&" << loc << (array_flag ? "[0]" : "") << ");"; } - - fprintf(fp,"\t\treturn 1;\n"); - fprintf(fp,"\t};\n"); + fout << std::endl; + fout << " return 1;" << std::endl; + fout << " };" << std::endl; } void -gen_parse_entry(Entry *entry, FILE *fp) +Entry::genParse(std::ostream &fout) const { - if (strcmp(entry->name, "comment") == 0) + if (name.compare("comment") == 0) return; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - - char *name = entry->name; - - EntryAlias *alias = entry->alias; + if (ifdef.size()) + fout << "#if " << ifdef << std::endl; - bool more; + // Once for the current directive name + genParseAlias(name, fout); - do { - gen_parse_alias (name, alias,entry, fp); - 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) - fprintf(fp, "#endif\n"); + if (ifdef.size()) + fout << "#endif\n"; } static void -gen_parse(Entry * head, FILE * fp) +gen_parse(const EntryList &head, std::ostream &fout) { - fprintf(fp, - "static int\n" - "parse_line(char *buff)\n" - "{\n" - "\tchar\t*token;\n" - "\tdebugs(0, 10, \"parse_line: \" << buff << \"\\n\" );\n" - "\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, fp); - - fprintf(fp, - "\treturn 0; /* failure */\n" - "}\n\n" - ); + fout << + "static int\n" + "parse_line(char *buff)\n" + "{\n" + "\tchar\t*token;\n" + "\tif ((token = strtok(buff, w_space)) == NULL) \n" + "\t\treturn 1;\t/* ignore empty lines */\n"; + + for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) + e->genParse(fout); + + fout << "\treturn 0; /* failure */\n" + "}\n\n"; + } static void -gen_dump(Entry * head, FILE * fp) +gen_dump(const EntryList &head, std::ostream &fout) { - Entry *entry; - fprintf(fp, - "static void\n" - "dump_config(StoreEntry *entry)\n" - "{\n" - ); + fout << + "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 || strcmp(entry->loc, "none") == 0) + if (!e->loc.size() || e->loc.compare("none") == 0) continue; - if (strcmp(entry->name, "comment") == 0) + if (e->name.compare("comment") == 0) continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); + if (e->ifdef.size()) + fout << "#if " << e->ifdef << std::endl; - fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", - entry->type, - entry->name, - entry->loc); + fout << " dump_" << e->type << "(entry, \"" << e->name << "\", " << e->loc << ");" << std::endl; - if (entry->ifdef) - fprintf(fp, "#endif\n"); + if (e->ifdef.size()) + fout << "#endif" << std::endl; } - fprintf(fp, "}\n\n"); + fout << "}" << std::endl << std::endl; } static void -gen_free(Entry * head, FILE * fp) +gen_free(const EntryList &head, std::ostream &fout) { - Entry *entry; - fprintf(fp, - "static void\n" - "free_all(void)\n" - "{\n" - ); - - for (entry = head; entry != NULL; entry = entry->next) { - if (!entry->loc || strcmp(entry->loc, "none") == 0) + fout << + "static void" << std::endl << + "free_all(void)" << std::endl << + "{" << std::endl << + " debugs(5, 4, HERE);" << std::endl; + + for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) { + if (!e->loc.size() || e->loc.compare("none") == 0) continue; - if (strcmp(entry->name, "comment") == 0) + if (e->name.compare("comment") == 0) continue; - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); + if (e->ifdef.size()) + fout << "#if " << e->ifdef << std::endl; - fprintf(fp, "\tfree_%s(&%s%s);\n", - entry->type, entry->loc, - entry->array_flag ? "[0]" : ""); + fout << " free_" << e->type << "(&" << e->loc << (e->array_flag ? "[0]" : "") << ");" << std::endl; - if (entry->ifdef) - fprintf(fp, "#endif\n"); + if (e->ifdef.size()) + fout << "#endif" << std::endl; } - fprintf(fp, "}\n\n"); + fout << "}" << std::endl << std::endl; } -static int -defined(char *name) +static bool +isDefined(const std::string &name) { - int i = 0; - - if (!name) - return 1; + if (!name.size()) + return true; - for (i = 0; strcmp(defines[i].name, name) != 0; i++) { - assert(defines[i].name); + for (int i = 0; defines[i].name; i++) { + if (name.compare(defines[i].name) == 0) + return defines[i].defined; } - return defines[i].defined; + return false; } static const char * -available_if(char *name) +available_if(const std::string &name) { - int i = 0; - assert(name); + assert(name.size()); - for (i = 0; strcmp(defines[i].name, name) != 0; i++) { - assert(defines[i].name); + for (int i = 0; defines[i].name; i++) { + if (name.compare(defines[i].name) == 0) + return defines[i].enable; } - return defines[i].enable; + return name.c_str(); } static void -gen_conf(Entry * head, FILE * fp, 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; - if (!strcmp(entry->name, "comment")) + // Display TAG: line + if (!entry->name.compare("comment")) (void) 0; - else if (!strcmp(entry->name, "obsolete")) + else if (!entry->name.compare("obsolete")) (void) 0; else if (verbose_output) { - fprintf(fp, "# TAG: %s", entry->name); + fout << "# TAG: " << entry->name; - if (entry->comment) - fprintf(fp, "\t%s", entry->comment); + if (entry->comment.size()) + fout << "\t" << entry->comment; - fprintf(fp, "\n"); + fout << std::endl; } - if (!defined(entry->ifdef)) { + // Display --enable/--disable disclaimer + if (!isDefined(entry->ifdef)) { if (verbose_output) { - fprintf(fp, "# Note: This option is only available if Squid is rebuilt with the\n"); - fprintf(fp, "# %s\n#\n", available_if(entry->ifdef)); + 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) { - fprintf(fp, "#%s\n", line->data); + // 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 && strcmp(entry->default_value, "none") != 0) { - snprintf(buf, sizeof(buf), "%s %s", entry->name, entry->default_value); - lineAdd(&def, buf); - } - - if (entry->default_if_none) { - for (line = entry->default_if_none; line; line = line->next) { - snprintf(buf, sizeof(buf), "%s %s", entry->name, line->data); - 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 && - strcmp(entry->name, "comment") != 0) - lineAdd(&def, "none"); - - if (verbose_output && def && (entry->doc || entry->nocomment)) { - fprintf(fp, "#Default:\n"); - while (def != NULL) { - line = def; - def = line->next; - fprintf(fp, "# %s\n", line->data); - xfree(line->data); - xfree(line); + // 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.size()) { + fout << "#Default:\n"; + 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) - fprintf(fp, "#\n"); + 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) - continue; - if (!enabled && line->data[0] != '#') - fprintf(fp, "#%s\n", line->data); - else - fprintf(fp, "%s\n", line->data); + 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) { - fprintf(fp, "\n"); + if (verbose_output && entry->doc.size()) { + fout << std::endl; } } } diff --git a/src/cf_gen_defines b/src/cf_gen_defines index 86e5d80932..d960fa080c 100644 --- a/src/cf_gen_defines +++ b/src/cf_gen_defines @@ -3,7 +3,7 @@ BEGIN { print "/* Generated automatically from cf.data.pre" print " * DO NOT EDIT" print "*/" - print "#include \"config.h\"" + print "#include \"autoconf.h\"" print "static struct { const char *name; const char *enable; int defined;} defines[] = {" define["DELAY_POOLS"]="--enable-delay-pools" define["FOLLOW_X_FORWARDED_FOR"]="--enable-follow-x-forwarded-for"