/*
- * 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/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
*
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
*/
+/* DEBUG: none Generate squid.conf.default and cf_parser.cci */
+
/*****************************************************************************
- * Abstract: This program parses the input file and generates code and
- * files used to configure the variables in squid.
- * (ie it creates the squid.conf.default file from the cf.data file)
+ * Abstract: This program parses the input file and generates code and
+ * files used to configure the variables in squid.
+ * (ie it creates the squid.conf.default file from the cf.data file)
*
- * The output files are as follows:
- * cf_parser.cci - this file contains, default_all() which
- * initializes variables with the default
- * values, parse_line() that parses line from
- * squid.conf.default, dump_config that dumps the
- * current the values of the variables.
- * squid.conf.default - default configuration file given to the server
- * administrator.
+ * The output files are as follows:
+ * cf_parser.cci - this file contains, default_all() which
+ * initializes variables with the default
+ * values, parse_line() that parses line from
+ * squid.conf.default, dump_config that dumps the
+ * current the values of the variables.
+ * squid.conf.default - default configuration file given to the server
+ * administrator.
*****************************************************************************/
/*
#include <fstream>
#include <iostream>
#include <list>
+#include <stack>
#include "cf_gen_defines.cci"
-#define MAX_LINE 1024 /* longest configuration line */
-#define _PATH_PARSER "cf_parser.cci"
-#define _PATH_SQUID_CONF "squid.conf.documented"
-#define _PATH_SQUID_CONF_SHORT "squid.conf.default"
-#define _PATH_CF_DEPEND "cf.data.depend"
+#define MAX_LINE 1024 /* longest configuration line */
+#define _PATH_PARSER "cf_parser.cci"
+#define _PATH_SQUID_CONF "squid.conf.documented"
+#define _PATH_SQUID_CONF_SHORT "squid.conf.default"
+#define _PATH_CF_DEPEND "cf.data.depend"
enum State {
sSTART,
s1,
sDOC,
- sNOCOMMENT,
+ sCFGLINES,
sEXIT
};
class DefaultValues
{
public:
- DefaultValues() : preset(), if_none(), docs() {}
- ~DefaultValues() {}
-
/// Default config lines to be defined before parsing the config files.
LineList preset;
/// An error will be printed during build if they clash.
LineList if_none;
+ /// Default config lines to parse and add to any prior settings.
+ LineList postscriptum;
+
/// 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(),
- defaults(), comment(), ifdef(), doc(), nocomment(),
- array_flag(0) {}
- ~Entry() {}
+ explicit Entry(const char *str) : name(str) {}
std::string name;
EntryAliasList alias;
std::string comment;
std::string ifdef;
LineList doc;
- LineList nocomment;
- int array_flag;
+ LineList cfgLines; ///< between CONFIG_START and CONFIG_END
+ int array_flag = 0; ///< TYPE is a raw array[] declaration
void genParse(std::ostream &fout) const;
{
public:
Type(const char *str) : name(str) {}
- ~Type() {}
std::string name;
TypeDepList depend;
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 gen_default_postscriptum(const EntryList &, std::ostream&);
+static bool isDefined(const std::string &name);
+static const char *available_if(const std::string &name);
+static const char *gen_quote_escape(const std::string &var);
static void
checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries)
{
- for (TypeList::const_iterator t = types.begin(); t != types.end(); ++t) {
- if (t->name.compare(name) != 0)
+ for (const auto &t : types) {
+ if (t.name.compare(name) != 0)
continue;
- for (TypeDepList::const_iterator dep = t->depend.begin(); dep != t->depend.end(); ++dep) {
+ for (const auto &dep : t.depend) {
EntryList::const_iterator entry = entries.begin();
for (; entry != entries.end(); ++entry) {
- if (entry->name.compare(*dep) == 0)
+ if (entry->name.compare(dep) == 0)
break;
}
if (entry == entries.end()) {
- std::cerr << "ERROR: '" << directive << "' (" << name << ") depends on '" << *dep << "'\n";
- exit(1);
+ std::cerr << "ERROR: '" << directive << "' (" << name << ") depends on '" << dep << "'\n";
+ exit(EXIT_FAILURE);
}
}
return;
}
std::cerr << "ERROR: Dependencies for cf.data type '" << name << "' used in ' " << directive << "' not defined\n" ;
- exit(1);
+ exit(EXIT_FAILURE);
}
static void
usage(const char *program_name)
{
std::cerr << "Usage: " << program_name << " cf.data cf.data.depend\n";
- exit(1);
+ exit(EXIT_FAILURE);
+}
+
+static void
+errorMsg(const char *filename, int line, const char *detail)
+{
+ std::cerr << "Error in '" << filename << "' on line " << line <<
+ "--> " << detail << std::endl;
}
int
TypeList types;
enum State state;
int rc = 0;
- char *ptr = NULL;
+ char *ptr = nullptr;
char buff[MAX_LINE];
std::ifstream fp;
+ std::stack<std::string> IFDEFS;
if (argc != 3)
usage(argv[0]);
*-------------------------------------------------------------------*/
fp.open(type_depend, std::ifstream::in);
if (fp.fail()) {
- std::cerr << "error while opening type dependencies file '" <<
+ std::cerr << "Error while opening type dependencies file '" <<
type_depend << "': " << strerror(errno) << std::endl;
- exit(1);
+ exit(EXIT_FAILURE);
}
while (fp.good()) {
if (!type || type[0] == '#')
continue;
Type t(type);
- while ((dep = strtok(NULL, WS)) != NULL) {
+ while ((dep = strtok(nullptr, WS)) != nullptr) {
t.depend.push_front(dep);
}
types.push_front(t);
/* Open input file */
fp.open(input_filename, std::ifstream::in);
if (fp.fail()) {
- std::cerr << "error while opening input file '" <<
+ std::cerr << "Error while opening input file '" <<
input_filename << "': " << strerror(errno) << std::endl;
- exit(1);
+ exit(EXIT_FAILURE);
}
state = sSTART;
while (fp.getline(buff,MAX_LINE), fp.good() && state != sEXIT) {
char *t;
- linenum++;
+ ++linenum;
if ((t = strchr(buff, '\n')))
*t = '\0';
- switch (state) {
-
- case sSTART:
-
- if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
- /* ignore empty and comment lines */
- (void) 0;
- } else if (!strncmp(buff, "NAME:", 5)) {
- char *name, *aliasname;
-
- if ((name = strtok(buff + 5, WS)) == NULL) {
- std::cerr << "Error in input file\n";
- exit(1);
- }
-
- entries.push_back(name);
-
- 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")) {
- entries.push_back("comment");
- entries.back().loc = "none";
- state = sDOC;
- } else {
- std::cerr << "Error on line " << linenum << std::endl <<
- "--> " << buff << std::endl;
- exit(1);
+ if (strncmp(buff, "IF ", 3) == 0) {
+ if ((ptr = strtok(buff + 3, WS)) == nullptr) {
+ errorMsg(input_filename, linenum, "Missing IF parameter");
+ exit(EXIT_FAILURE);
}
-
- break;
-
- case s1: {
- Entry &curr = entries.back();
-
- if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
- /* ignore empty and comment lines */
- (void) 0;
- } else if (!strncmp(buff, "COMMENT:", 8)) {
- ptr = buff + 8;
-
- while (isspace((unsigned char)*ptr))
- ptr++;
-
- curr.comment = ptr;
- } else if (!strncmp(buff, "DEFAULT:", 8)) {
- ptr = buff + 8;
-
- while (isspace((unsigned char)*ptr))
- ptr++;
-
- curr.defaults.preset.push_back(ptr);
- } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) {
- ptr = buff + 16;
-
- 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++;
-
- 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);
+ IFDEFS.push(ptr);
+ continue;
+ } else if (strcmp(buff, "ENDIF") == 0) {
+ if (IFDEFS.size() == 0) {
+ errorMsg(input_filename, linenum, "ENDIF without IF first");
+ exit(EXIT_FAILURE);
+ }
+ IFDEFS.pop();
+ } else if (!IFDEFS.size() || isDefined(IFDEFS.top()))
+ switch (state) {
+
+ case sSTART:
+
+ if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
+ /* ignore empty and comment lines */
+ (void) 0;
+ } else if (!strncmp(buff, "NAME:", 5)) {
+ char *name, *aliasname;
+
+ if ((name = strtok(buff + 5, WS)) == nullptr) {
+ errorMsg(input_filename, linenum, buff);
+ exit(EXIT_FAILURE);
+ }
+
+ auto &newEntry = entries.emplace_back(name);
+
+ while ((aliasname = strtok(nullptr, WS)) != nullptr)
+ newEntry.alias.push_front(aliasname);
+
+ state = s1;
+ } else if (!strcmp(buff, "EOF")) {
+ state = sEXIT;
+ } else if (!strcmp(buff, "COMMENT_START")) {
+ auto &newEntry = entries.emplace_back("comment");
+ newEntry.loc = "none";
+ state = sDOC;
+ } else {
+ errorMsg(input_filename, linenum, buff);
+ exit(EXIT_FAILURE);
}
- curr.loc = ptr;
- } else if (!strncmp(buff, "TYPE:", 5)) {
- if ((ptr = strtok(buff + 5, WS)) == NULL) {
- std::cerr << "Error on line " << linenum << std::endl;
- exit(1);
+ break;
+
+ case s1: {
+ Entry &curr = entries.back();
+
+ if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
+ /* ignore empty and comment lines */
+ (void) 0;
+ } else if (!strncmp(buff, "COMMENT:", 8)) {
+ ptr = buff + 8;
+
+ while (isspace((unsigned char)*ptr))
+ ++ptr;
+
+ curr.comment = ptr;
+ } else if (!strncmp(buff, "DEFAULT:", 8)) {
+ ptr = buff + 8;
+
+ while (isspace((unsigned char)*ptr))
+ ++ptr;
+
+ curr.defaults.preset.push_back(ptr);
+ } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) {
+ ptr = buff + 16;
+
+ while (isspace((unsigned char)*ptr))
+ ++ptr;
+
+ curr.defaults.if_none.push_back(ptr);
+ } else if (!strncmp(buff, "POSTSCRIPTUM:", 13)) {
+ ptr = buff + 13;
+
+ while (isspace((unsigned char)*ptr))
+ ++ptr;
+
+ curr.defaults.postscriptum.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)) == nullptr) {
+ errorMsg(input_filename, linenum, buff);
+ exit(EXIT_FAILURE);
+ }
+
+ curr.loc = ptr;
+ } else if (!strncmp(buff, "TYPE:", 5)) {
+ if ((ptr = strtok(buff + 5, WS)) == nullptr) {
+ errorMsg(input_filename, linenum, buff);
+ exit(EXIT_FAILURE);
+ }
+
+ /* hack to support arrays, rather than pointers */
+ if (strcmp(ptr + strlen(ptr) - 2, "[]") == 0) {
+ curr.array_flag = 1;
+ *(ptr + strlen(ptr) - 2) = '\0';
+ }
+
+ checkDepend(curr.name, ptr, types, entries);
+ curr.type = ptr;
+ } else if (!strncmp(buff, "IFDEF:", 6)) {
+ if ((ptr = strtok(buff + 6, WS)) == nullptr) {
+ errorMsg(input_filename, linenum, buff);
+ exit(EXIT_FAILURE);
+ }
+
+ curr.ifdef = ptr;
+ } else if (!strcmp(buff, "DOC_START")) {
+ state = sDOC;
+ } else if (!strcmp(buff, "DOC_NONE")) {
+ state = sSTART;
+ } else {
+ errorMsg(input_filename, linenum, buff);
+ exit(EXIT_FAILURE);
}
+ }
+ break;
- /* hack to support arrays, rather than pointers */
- if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) {
- curr.array_flag = 1;
- *(ptr + strlen(ptr) - 2) = '\0';
+ case sDOC:
+ if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) {
+ state = sSTART;
+ } else if (strcmp(buff, "CONFIG_START") == 0) {
+ state = sCFGLINES;
+ } else {
+ entries.back().doc.push_back(buff);
}
+ break;
- 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);
+ case sCFGLINES:
+ if (strcmp(buff, "CONFIG_END") == 0) {
+ state = sDOC;
+ } else {
+ entries.back().cfgLines.push_back(buff);
}
-
- curr.ifdef = ptr;
- } else if (!strcmp(buff, "DOC_START")) {
- state = sDOC;
- } else if (!strcmp(buff, "DOC_NONE")) {
- state = sSTART;
- } else {
- std::cerr << "Error on line " << linenum << std::endl;
- exit(1);
- }
- }
- break;
-
- case sDOC:
- if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) {
- state = sSTART;
- } else if (!strcmp(buff, "NOCOMMENT_START")) {
- state = sNOCOMMENT;
- } else { // if (buff != NULL) {
- assert(buff != NULL);
- entries.back().doc.push_back(buff);
+ break;
+ case sEXIT:
+ assert(0); /* should never get here */
+ break;
}
- break;
-
- case sNOCOMMENT:
- if (!strcmp(buff, "NOCOMMENT_END")) {
- state = sDOC;
- } 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) {
- std::cerr << "Error: unexpected EOF\n";
- exit(1);
+ errorMsg(input_filename, linenum, "Error: unexpected EOF");
+ exit(EXIT_FAILURE);
}
fp.close();
std::ofstream fout(output_filename,std::ostream::out);
if (!fout.good()) {
- std::cerr << "error while opening output .c file '" <<
+ std::cerr << "Error while opening output .c file '" <<
output_filename << "': " << strerror(errno) << std::endl;
- exit(1);
+ exit(EXIT_FAILURE);
}
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";
+ " * 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";
rc = gen_default(entries, fout);
gen_default_if_none(entries, fout);
+ gen_default_postscriptum(entries, fout);
+
gen_parse(entries, fout);
gen_dump(entries, fout);
/* Open output x.conf file */
fout.open(conf_filename,std::ostream::out);
if (!fout.good()) {
- std::cerr << "error while opening output conf file '" <<
+ std::cerr << "Error while opening output conf file '" <<
output_filename << "': " << strerror(errno) << std::endl;
- exit(1);
+ exit(EXIT_FAILURE);
}
gen_conf(entries, fout, 1);
fout.open(conf_filename_short,std::ostream::out);
if (!fout.good()) {
- std::cerr << "error while opening output short conf file '" <<
+ std::cerr << "Error while opening output short conf file '" <<
output_filename << "': " << strerror(errno) << std::endl;
- exit(1);
+ exit(EXIT_FAILURE);
}
gen_conf(entries, fout, 0);
fout.close();
{
int rc = 0;
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;
+ "default_line(const char *s)" << std::endl <<
+ "{" << std::endl <<
+ " char *tmp_line = xstrdup(s);" << std::endl <<
+ " int len = strlen(tmp_line);" << std::endl <<
+ " ProcessMacros(tmp_line, len);" << std::endl <<
+ " xstrncpy(config_input_line, tmp_line, sizeof(config_input_line));" << std::endl <<
+ " config_lineno++;" << std::endl <<
+ " parse_line(tmp_line);" << std::endl <<
+ " xfree(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;
+ "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());
+ for (const auto &entry : head) {
+ assert(entry.name.size());
- if (!entry->name.compare("comment"))
+ if (!entry.name.compare("comment"))
continue;
- if (!entry->type.compare("obsolete"))
+ if (!entry.type.compare("obsolete"))
continue;
- if (!entry->loc.size()) {
- std::cerr << "NO LOCATION FOR " << entry->name << std::endl;
+ if (!entry.loc.size()) {
+ std::cerr << "NO LOCATION FOR " << entry.name << std::endl;
rc |= 1;
continue;
}
- if (!entry->defaults.preset.size() && entry->defaults.if_none.empty()) {
- std::cerr << "NO DEFAULT FOR " << entry->name << std::endl;
+ if (!entry.defaults.preset.size() && entry.defaults.if_none.empty()) {
+ std::cerr << "NO DEFAULT FOR " << entry.name << std::endl;
rc |= 1;
continue;
}
- if (!entry->defaults.preset.size() || entry->defaults.preset.front().compare("none") == 0) {
- fout << " // No default for " << entry->name << std::endl;
+ 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;
+ if (entry.ifdef.size())
+ fout << "#if " << entry.ifdef << std::endl;
- for (LineList::const_iterator l = entry->defaults.preset.begin(); l != entry->defaults.preset.end(); ++l) {
- fout << " default_line(\"" << entry->name << " " << *l << "\");" << std::endl;
- }
+ for (const auto &l : entry.defaults.preset)
+ fout << " default_line(\"" << entry.name << " " << gen_quote_escape(l) << "\");" << std::endl;
- if (entry->ifdef.size())
+ if (entry.ifdef.size())
fout << "#endif" << std::endl;
}
}
fout << " cfg_filename = NULL;" << std::endl <<
- "}" << std::endl << std::endl;
+ "}" << std::endl << std::endl;
return rc;
}
gen_default_if_none(const EntryList &head, std::ostream &fout)
{
fout << "static void" << std::endl <<
- "defaults_if_none(void)" << std::endl <<
- "{" << std::endl;
+ "defaults_if_none(void)" << std::endl <<
+ "{" << std::endl <<
+ " cfg_filename = \"Default Configuration (if absent)\";" << std::endl <<
+ " config_lineno = 0;" << std::endl;
- for (EntryList::const_iterator entry = head.begin(); entry != head.end(); ++entry) {
- assert(entry->name.size());
+ for (const auto &entry : head) {
+ assert(entry.name.size());
- if (!entry->loc.size())
+ if (!entry.loc.size())
continue;
- if (entry->defaults.if_none.empty())
+ 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.defaults.preset.empty()) {
+ std::cerr << "ERROR: " << entry.name << " has preset defaults. DEFAULT_IF_NONE cannot be true." << std::endl;
+ exit(EXIT_FAILURE);
}
- if (entry->ifdef.size())
- fout << "#if " << entry->ifdef << std::endl;
+ if (entry.ifdef.size())
+ fout << "#if " << entry.ifdef << std::endl;
- 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 << " if (check_null_" << entry.type << "(" << entry.loc << ")) {" << std::endl;
+ for (const auto &l : entry.defaults.if_none)
+ fout << " default_line(\"" << entry.name << " " << gen_quote_escape(l) <<"\");" << std::endl;
fout << " }" << std::endl;
- if (entry->ifdef.size())
+ if (entry.ifdef.size())
fout << "#endif" << std::endl;
}
- fout << "}" << std::endl << std::endl;
+ fout << " cfg_filename = NULL;" << std::endl <<
+ "}" << std::endl << std::endl;
+}
+
+/// append configuration options specified by POSTSCRIPTUM lines
+static void
+gen_default_postscriptum(const EntryList &head, std::ostream &fout)
+{
+ fout << "static void" << std::endl <<
+ "defaults_postscriptum(void)" << std::endl <<
+ "{" << std::endl <<
+ " cfg_filename = \"Default Configuration (postscriptum)\";" << std::endl <<
+ " config_lineno = 0;" << std::endl;
+
+ for (const auto &entry : head) {
+ assert(entry.name.size());
+
+ if (!entry.loc.size())
+ continue;
+
+ if (entry.defaults.postscriptum.empty())
+ continue;
+
+ if (entry.ifdef.size())
+ fout << "#if " << entry.ifdef << std::endl;
+
+ for (const auto &l : entry.defaults.postscriptum)
+ fout << " default_line(\"" << entry.name << " " << l <<"\");" << std::endl;
+
+ if (entry.ifdef.size())
+ fout << "#endif" << std::endl;
+ }
+
+ fout << " cfg_filename = NULL;" << std::endl <<
+ "}" << std::endl << std::endl;
}
void
Entry::genParseAlias(const std::string &aName, std::ostream &fout) const
{
fout << " if (!strcmp(token, \"" << aName << "\")) {" << std::endl;
+ if (ifdef.size())
+ fout << "#if " << ifdef << std::endl;
+ fout << " cfg_directive = \"" << 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) {
+ for (const auto &l : doc) {
// offset line to strip initial whitespace tab byte
- fout << " debugs(0, opt_parse_cfg_only?0:1, \"" << aName << " : " << &(*l)[1] << "\");" << std::endl;
+ fout << " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"" << aName << " : " << &l[1] << "\");" << std::endl;
}
fout << " parse_obsolete(token);";
} else if (!loc.size() || loc.compare("none") == 0) {
fout << "parse_" << type << "();";
+ } else if (type.find("::") != std::string::npos) {
+ fout << "ParseDirective<" << type << ">(" << loc << ", LegacyParser);";
} else {
fout << "parse_" << type << "(&" << loc << (array_flag ? "[0]" : "") << ");";
}
fout << std::endl;
+ fout << " cfg_directive = NULL;" << std::endl;
+ if (ifdef.size()) {
+ fout <<
+ "#else" << std::endl <<
+ " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"ERROR: '" << name << "' requires " << available_if(ifdef) << "\");" << std::endl <<
+ "#endif" << std::endl;
+ }
fout << " return 1;" << std::endl;
fout << " };" << std::endl;
}
if (name.compare("comment") == 0)
return;
- if (ifdef.size())
- fout << "#if " << ifdef << std::endl;
-
// Once for the current directive name
genParseAlias(name, fout);
// All accepted aliases
- for (EntryAliasList::const_iterator a = alias.begin(); a != alias.end(); ++a) {
- genParseAlias(*a, fout);
+ for (const auto &a : alias) {
+ genParseAlias(a, fout);
}
-
- if (ifdef.size())
- fout << "#endif\n";
}
static void
gen_parse(const EntryList &head, std::ostream &fout)
{
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";
+ "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"
+ "\tConfigParser::SetCfgLine(strtok(NULL, \"\"));\n";
- for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e)
- e->genParse(fout);
+ for (const auto &e : head)
+ e.genParse(fout);
fout << "\treturn 0; /* failure */\n"
- "}\n\n";
+ "}\n\n";
}
gen_dump(const EntryList &head, std::ostream &fout)
{
fout <<
- "static void" << std::endl <<
- "dump_config(StoreEntry *entry)" << std::endl <<
- "{" << std::endl <<
- " debugs(5, 4, HERE);" << std::endl;
+ "static void" << std::endl <<
+ "dump_config(StoreEntry *entry)" << std::endl <<
+ "{" << std::endl <<
+ " debugs(5, 4, MYNAME);" << std::endl;
- for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) {
+ for (const auto &e : head) {
- if (!e->loc.size() || e->loc.compare("none") == 0)
+ if (!e.loc.size() || e.loc.compare("none") == 0)
continue;
- if (e->name.compare("comment") == 0)
+ if (e.name.compare("comment") == 0)
continue;
- if (e->ifdef.size())
- fout << "#if " << e->ifdef << std::endl;
+ if (e.ifdef.size())
+ fout << "#if " << e.ifdef << std::endl;
- fout << " dump_" << e->type << "(entry, \"" << e->name << "\", " << e->loc << ");" << std::endl;
+ if (e.type.find("::") != std::string::npos)
+ fout << " DumpDirective<" << e.type << ">(" << e.loc << ", entry, \"" << e.name << "\");\n";
+ else
+ fout << " dump_" << e.type << "(entry, \"" << e.name << "\", " << e.loc << ");" << std::endl;
- if (e->ifdef.size())
+ if (e.ifdef.size())
fout << "#endif" << std::endl;
}
gen_free(const EntryList &head, std::ostream &fout)
{
fout <<
- "static void" << std::endl <<
- "free_all(void)" << std::endl <<
- "{" << std::endl <<
- " debugs(5, 4, HERE);" << std::endl;
+ "static void" << std::endl <<
+ "free_all(void)" << std::endl <<
+ "{" << std::endl <<
+ " debugs(5, 4, MYNAME);" << std::endl;
- for (EntryList::const_iterator e = head.begin(); e != head.end(); ++e) {
- if (!e->loc.size() || e->loc.compare("none") == 0)
+ for (const auto &e : head) {
+ if (!e.loc.size() || e.loc.compare("none") == 0)
continue;
- if (e->name.compare("comment") == 0)
+ if (e.name.compare("comment") == 0)
continue;
- if (e->ifdef.size())
- fout << "#if " << e->ifdef << std::endl;
+ if (e.ifdef.size())
+ fout << "#if " << e.ifdef << std::endl;
- fout << " free_" << e->type << "(&" << e->loc << (e->array_flag ? "[0]" : "") << ");" << std::endl;
+ if (e.type.find("::") != std::string::npos)
+ fout << " FreeDirective<" << e.type << ">(" << e.loc << ");\n";
+ else
+ fout << " free_" << e.type << "(&" << e.loc << (e.array_flag ? "[0]" : "") << ");" << std::endl;
- if (e->ifdef.size())
+ if (e.ifdef.size())
fout << "#endif" << std::endl;
}
if (!name.size())
return true;
- for (int i = 0; defines[i].name; i++) {
+ for (int i = 0; defines[i].name; ++i) {
if (name.compare(defines[i].name) == 0)
return defines[i].defined;
}
{
assert(name.size());
- for (int i = 0; defines[i].name; i++) {
+ for (int i = 0; defines[i].name; ++i) {
if (name.compare(defines[i].name) == 0)
return defines[i].enable;
}
static void
gen_conf(const EntryList &head, std::ostream &fout, bool verbose_output)
{
- for (EntryList::const_iterator entry = head.begin(); entry != head.end(); ++entry) {
+ for (const auto &entry : head) {
char buf[8192];
LineList def;
int enabled = 1;
// Display TAG: line
- if (!entry->name.compare("comment"))
+ if (!entry.name.compare("comment"))
(void) 0;
- else if (!entry->name.compare("obsolete"))
+ else if (!entry.name.compare("obsolete"))
(void) 0;
else if (verbose_output) {
- fout << "# TAG: " << entry->name;
+ fout << "# TAG: " << entry.name;
- if (entry->comment.size())
- fout << "\t" << entry->comment;
+ if (entry.comment.size())
+ fout << "\t" << entry.comment;
fout << std::endl;
}
// Display --enable/--disable disclaimer
- if (!isDefined(entry->ifdef)) {
+ if (!isDefined(entry.ifdef)) {
if (verbose_output) {
fout << "# Note: This option is only available if Squid is rebuilt with the" << std::endl <<
- "# " << available_if(entry->ifdef) << std::endl <<
- "#" << std::endl;
+ "# " << available_if(entry.ifdef) << std::endl <<
+ "#" << std::endl;
}
enabled = 0;
}
// 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 (verbose_output && entry.doc.size()) {
+ for (const auto &line : entry.doc) {
+ fout << "#" << line << std::endl;
}
}
- if (entry->defaults.docs.size()) {
+ if (entry.defaults.docs.size()) {
// Display the DEFAULT_DOC line(s)
- def = entry->defaults.docs;
+ def = entry.defaults.docs;
} else {
- if (entry->defaults.preset.size() && entry->defaults.preset.front().compare("none") != 0) {
+ 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());
+ for (const auto &l : entry.defaults.preset) {
+ snprintf(buf, sizeof(buf), "%s %s", entry.name.c_str(), l.c_str());
def.push_back(buf);
}
- } else if (entry->defaults.if_none.size()) {
+ } 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());
+ for (const auto &l : entry.defaults.if_none) {
+ snprintf(buf, sizeof(buf), "%s %s", entry.name.c_str(), l.c_str());
def.push_back(buf);
}
}
}
// Display "none" if no default is set or comments to display
- if (def.empty() && entry->nocomment.empty() && entry->name.compare("comment") != 0)
+ if (def.empty() && entry.cfgLines.empty() && entry.name.compare("comment") != 0)
def.push_back("none");
if (verbose_output && def.size()) {
fout << "# " << def.front() << std::endl;
def.pop_front();
}
- if (entry->doc.empty() && entry->nocomment.empty())
+ if (entry.doc.empty() && entry.cfgLines.empty())
fout << std::endl;
}
- if (verbose_output && entry->nocomment.size())
+ if (verbose_output && entry.cfgLines.size())
fout << "#" << std::endl;
if (enabled || verbose_output) {
- for (LineList::const_iterator line = entry->nocomment.begin(); line != entry->nocomment.end(); ++line) {
- if (!enabled && line->at(0) != '#')
+ for (const auto &line : entry.cfgLines) {
+ if (!enabled && line.at(0) != '#')
fout << "#";
- fout << *line << std::endl;
+ fout << line << std::endl;
}
}
- if (verbose_output && entry->doc.size()) {
+ if (verbose_output && entry.doc.size()) {
fout << std::endl;
}
}
}
+
+static const char *
+gen_quote_escape(const std::string &var)
+{
+ static std::string esc;
+ esc.clear();
+
+ for (const auto c : var) {
+ switch (c) {
+ case '"':
+ case '\\':
+ esc += '\\';
+ [[fallthrough]];
+ default:
+ esc += c;
+ }
+ }
+
+ return esc.c_str();
+}
+