30#if defined(__INTEL_COMPILER) && defined(_FILE_OFFSET_BITS) && \
32#undef _FILE_OFFSET_BITS
45#include "cf_gen_defines.cci"
48#define _PATH_PARSER "cf_parser.cci"
49#define _PATH_SQUID_CONF "squid.conf.documented"
50#define _PATH_SQUID_CONF_SHORT "squid.conf.default"
51#define _PATH_CF_DEPEND "cf.data.depend"
100 void genParse(std::ostream &fout)
const;
103 void genParseAlias(
const std::string &, std::ostream &)
const;
119static const char WS[] =
" \t\n";
127static bool isDefined(
const std::string &name);
128static const char *
available_if(
const std::string &name);
134 for (
const auto &t : types) {
135 if (t.name.compare(name) != 0)
137 for (
const auto &dep : t.depend) {
138 EntryList::const_iterator entry = entries.begin();
139 for (; entry != entries.end(); ++entry) {
140 if (entry->name.compare(dep) == 0)
143 if (entry == entries.end()) {
144 std::cerr <<
"ERROR: '" << directive <<
"' (" << name <<
") depends on '" << dep <<
"'\n";
150 std::cerr <<
"ERROR: Dependencies for cf.data type '" << name <<
"' used in ' " << directive <<
"' not defined\n" ;
157 std::cerr <<
"Usage: " <<
program_name <<
" cf.data cf.data.depend\n";
162errorMsg(
const char *filename,
int line,
const char *detail)
164 std::cerr <<
"Error in '" << filename <<
"' on line " << line <<
165 "--> " << detail << std::endl;
171 char *input_filename;
175 const char *type_depend;
184 std::stack<std::string> IFDEFS;
189 input_filename = argv[1];
190 type_depend = argv[2];
195 fp.open(type_depend, std::ifstream::in);
197 std::cerr <<
"Error while opening type dependencies file '" <<
198 type_depend <<
"': " <<
strerror(errno) << std::endl;
204 const char *type = strtok(buff,
WS);
206 if (!type || type[0] ==
'#')
209 while ((dep = strtok(
nullptr,
WS)) !=
nullptr) {
222 fp.open(input_filename, std::ifstream::in);
224 std::cerr <<
"Error while opening input file '" <<
225 input_filename <<
"': " <<
strerror(errno) << std::endl;
231 while (fp.getline(buff,
MAX_LINE), fp.good() && state !=
sEXIT) {
236 if ((t = strchr(buff,
'\n')))
239 if (strncmp(buff,
"IF ", 3) == 0) {
240 if ((ptr = strtok(buff + 3,
WS)) ==
nullptr) {
241 errorMsg(input_filename, linenum,
"Missing IF parameter");
246 }
else if (strcmp(buff,
"ENDIF") == 0) {
247 if (IFDEFS.size() == 0) {
248 errorMsg(input_filename, linenum,
"ENDIF without IF first");
252 }
else if (!IFDEFS.size() ||
isDefined(IFDEFS.top()))
257 if ((strlen(buff) == 0) || (!strncmp(buff,
"#", 1))) {
260 }
else if (!strncmp(buff,
"NAME:", 5)) {
261 char *name, *aliasname;
263 if ((name = strtok(buff + 5,
WS)) ==
nullptr) {
264 errorMsg(input_filename, linenum, buff);
268 auto &newEntry = entries.emplace_back(name);
270 while ((aliasname = strtok(
nullptr,
WS)) !=
nullptr)
271 newEntry.alias.push_front(aliasname);
274 }
else if (!strcmp(buff,
"EOF")) {
276 }
else if (!strcmp(buff,
"COMMENT_START")) {
277 auto &newEntry = entries.emplace_back(
"comment");
278 newEntry.loc =
"none";
281 errorMsg(input_filename, linenum, buff);
288 Entry &curr = entries.back();
290 if ((strlen(buff) == 0) || (!strncmp(buff,
"#", 1))) {
293 }
else if (!strncmp(buff,
"COMMENT:", 8)) {
296 while (isspace((
unsigned char)*ptr))
300 }
else if (!strncmp(buff,
"DEFAULT:", 8)) {
303 while (isspace((
unsigned char)*ptr))
307 }
else if (!strncmp(buff,
"DEFAULT_IF_NONE:", 16)) {
310 while (isspace((
unsigned char)*ptr))
314 }
else if (!strncmp(buff,
"POSTSCRIPTUM:", 13)) {
317 while (isspace((
unsigned char)*ptr))
321 }
else if (!strncmp(buff,
"DEFAULT_DOC:", 12)) {
324 while (isspace((
unsigned char)*ptr))
328 }
else if (!strncmp(buff,
"LOC:", 4)) {
329 if ((ptr = strtok(buff + 4,
WS)) ==
nullptr) {
330 errorMsg(input_filename, linenum, buff);
335 }
else if (!strncmp(buff,
"TYPE:", 5)) {
336 if ((ptr = strtok(buff + 5,
WS)) ==
nullptr) {
337 errorMsg(input_filename, linenum, buff);
342 if (strcmp(ptr + strlen(ptr) - 2,
"[]") == 0) {
344 *(ptr + strlen(ptr) - 2) =
'\0';
349 }
else if (!strncmp(buff,
"IFDEF:", 6)) {
350 if ((ptr = strtok(buff + 6,
WS)) ==
nullptr) {
351 errorMsg(input_filename, linenum, buff);
356 }
else if (!strcmp(buff,
"DOC_START")) {
358 }
else if (!strcmp(buff,
"DOC_NONE")) {
361 errorMsg(input_filename, linenum, buff);
368 if (!strcmp(buff,
"DOC_END") || !strcmp(buff,
"COMMENT_END")) {
370 }
else if (strcmp(buff,
"CONFIG_START") == 0) {
373 entries.back().doc.push_back(buff);
378 if (strcmp(buff,
"CONFIG_END") == 0) {
381 entries.back().cfgLines.push_back(buff);
391 if (state !=
sEXIT) {
392 errorMsg(input_filename, linenum,
"Error: unexpected EOF");
408 std::ofstream fout(output_filename,std::ostream::out);
410 std::cerr <<
"Error while opening output .c file '" <<
411 output_filename <<
"': " <<
strerror(errno) << std::endl;
416 " * Generated automatically from " << input_filename <<
" by " <<
419 " * Abstract: This file contains routines used to configure the\n"
420 " * variables in the squid server.\n"
439 fout.open(conf_filename,std::ostream::out);
441 std::cerr <<
"Error while opening output conf file '" <<
442 output_filename <<
"': " <<
strerror(errno) << std::endl;
450 fout.open(conf_filename_short,std::ostream::out);
452 std::cerr <<
"Error while opening output short conf file '" <<
453 output_filename <<
"': " <<
strerror(errno) << std::endl;
466 fout <<
"static void" << std::endl <<
467 "default_line(const char *s)" << std::endl <<
469 " char *tmp_line = xstrdup(s);" << std::endl <<
470 " int len = strlen(tmp_line);" << std::endl <<
471 " ProcessMacros(tmp_line, len);" << std::endl <<
472 " xstrncpy(config_input_line, tmp_line, sizeof(config_input_line));" << std::endl <<
473 " config_lineno++;" << std::endl <<
474 " parse_line(tmp_line);" << std::endl <<
475 " xfree(tmp_line);" << std::endl <<
476 "}" << std::endl << std::endl;
477 fout <<
"static void" << std::endl <<
478 "default_all(void)" << std::endl <<
480 " cfg_filename = \"Default Configuration\";" << std::endl <<
481 " config_lineno = 0;" << std::endl;
483 for (
const auto &entry :
head) {
484 assert(entry.name.size());
486 if (!entry.name.compare(
"comment"))
489 if (!entry.type.compare(
"obsolete"))
492 if (!entry.loc.size()) {
493 std::cerr <<
"NO LOCATION FOR " << entry.name << std::endl;
498 if (!entry.defaults.preset.size() && entry.defaults.if_none.empty()) {
499 std::cerr <<
"NO DEFAULT FOR " << entry.name << std::endl;
504 if (!entry.defaults.preset.size() || entry.defaults.preset.front().compare(
"none") == 0) {
505 fout <<
" // No default for " << entry.name << std::endl;
507 if (entry.ifdef.size())
508 fout <<
"#if " << entry.ifdef << std::endl;
510 for (
const auto &l : entry.defaults.preset)
511 fout <<
" default_line(\"" << entry.name <<
" " <<
gen_quote_escape(l) <<
"\");" << std::endl;
513 if (entry.ifdef.size())
514 fout <<
"#endif" << std::endl;
518 fout <<
" cfg_filename = nullptr;" << std::endl <<
519 "}" << std::endl << std::endl;
526 fout <<
"static void" << std::endl <<
527 "defaults_if_none(void)" << std::endl <<
529 " cfg_filename = \"Default Configuration (if absent)\";" << std::endl <<
530 " config_lineno = 0;" << std::endl;
532 for (
const auto &entry :
head) {
533 assert(entry.name.size());
535 if (!entry.loc.size())
538 if (entry.defaults.if_none.empty())
541 if (!entry.defaults.preset.empty()) {
542 std::cerr <<
"ERROR: " << entry.name <<
" has preset defaults. DEFAULT_IF_NONE cannot be true." << std::endl;
546 if (entry.ifdef.size())
547 fout <<
"#if " << entry.ifdef << std::endl;
549 fout <<
" if (check_null_" << entry.type <<
"(" << entry.loc <<
")) {" << std::endl;
550 for (
const auto &l : entry.defaults.if_none)
551 fout <<
" default_line(\"" << entry.name <<
" " <<
gen_quote_escape(l) <<
"\");" << std::endl;
552 fout <<
" }" << std::endl;
554 if (entry.ifdef.size())
555 fout <<
"#endif" << std::endl;
558 fout <<
" cfg_filename = nullptr;" << std::endl <<
559 "}" << std::endl << std::endl;
566 fout <<
"static void" << std::endl <<
567 "defaults_postscriptum(void)" << std::endl <<
569 " cfg_filename = \"Default Configuration (postscriptum)\";" << std::endl <<
570 " config_lineno = 0;" << std::endl;
572 for (
const auto &entry :
head) {
573 assert(entry.name.size());
575 if (!entry.loc.size())
578 if (entry.defaults.postscriptum.empty())
581 if (entry.ifdef.size())
582 fout <<
"#if " << entry.ifdef << std::endl;
584 for (
const auto &l : entry.defaults.postscriptum)
585 fout <<
" default_line(\"" << entry.name <<
" " << l <<
"\");" << std::endl;
587 if (entry.ifdef.size())
588 fout <<
"#endif" << std::endl;
591 fout <<
" cfg_filename = nullptr;" << std::endl <<
592 "}" << std::endl << std::endl;
598 fout <<
" if (!strcmp(token, \"" << aName <<
"\")) {" << std::endl;
600 fout <<
"#if " <<
ifdef << std::endl;
601 fout <<
" cfg_directive = \"" << aName <<
"\";" << std::endl;
603 if (
type.compare(
"obsolete") == 0) {
604 fout <<
"debugs(0, DBG_CRITICAL, \"ERROR: Directive '" << aName <<
"' is obsolete.\");\n";
605 for (
const auto &l :
doc) {
607 fout <<
" debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"" << aName <<
" : " << &l[1] <<
"\");" << std::endl;
609 fout <<
" parse_obsolete(token);";
610 }
else if (!
loc.size() ||
loc.compare(
"none") == 0) {
611 fout <<
"parse_" <<
type <<
"();";
612 }
else if (
type.find(
"::") != std::string::npos) {
613 fout <<
"ParseDirective<" <<
type <<
">(" <<
loc <<
", LegacyParser);";
618 fout <<
" cfg_directive = nullptr;" << std::endl;
621 "#else" << std::endl <<
622 " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"ERROR: '" <<
name <<
"' requires " <<
available_if(
ifdef) <<
"\");" << std::endl <<
623 "#endif" << std::endl;
625 fout <<
" return 1;" << std::endl;
626 fout <<
" };" << std::endl;
632 if (
name.compare(
"comment") == 0)
639 for (
const auto &a :
alias) {
649 "parse_line(char *buff)\n"
652 "\tif ((token = strtok(buff, w_space)) == NULL) \n"
653 "\t\treturn 1;\t/* ignore empty lines */\n"
654 "\tConfigParser::SetCfgLine(strtok(nullptr, \"\"));\n";
656 for (
const auto &e :
head)
659 fout <<
"\treturn 0; /* failure */\n"
668 "static void" << std::endl <<
669 "dump_config(StoreEntry *entry)" << std::endl <<
671 " debugs(5, 4, MYNAME);" << std::endl;
673 for (
const auto &e :
head) {
675 if (!e.loc.size() || e.loc.compare(
"none") == 0)
678 if (e.name.compare(
"comment") == 0)
682 fout <<
"#if " << e.ifdef << std::endl;
684 if (e.type.find(
"::") != std::string::npos)
685 fout <<
" DumpDirective<" << e.type <<
">(" << e.loc <<
", entry, \"" << e.name <<
"\");\n";
687 fout <<
" dump_" << e.type <<
"(entry, \"" << e.name <<
"\", " << e.loc <<
");" << std::endl;
690 fout <<
"#endif" << std::endl;
693 fout <<
"}" << std::endl << std::endl;
700 "static void" << std::endl <<
701 "free_all(void)" << std::endl <<
703 " debugs(5, 4, MYNAME);" << std::endl;
705 for (
const auto &e :
head) {
706 if (!e.loc.size() || e.loc.compare(
"none") == 0)
709 if (e.name.compare(
"comment") == 0)
713 fout <<
"#if " << e.ifdef << std::endl;
715 if (e.type.find(
"::") != std::string::npos)
716 fout <<
" FreeDirective<" << e.type <<
">(" << e.loc <<
");\n";
718 fout <<
" free_" << e.type <<
"(&" << e.loc << (e.array_flag ?
"[0]" :
"") <<
");" << std::endl;
721 fout <<
"#endif" << std::endl;
724 fout <<
"}" << std::endl << std::endl;
733 for (
int i = 0; defines[i].name; ++i) {
734 if (name.compare(defines[i].name) == 0)
735 return defines[i].defined;
746 for (
int i = 0; defines[i].name; ++i) {
747 if (name.compare(defines[i].name) == 0)
748 return defines[i].enable;
757 for (
const auto &entry :
head) {
763 if (!entry.name.compare(
"comment"))
765 else if (!entry.name.compare(
"obsolete"))
767 else if (verbose_output) {
768 fout <<
"# TAG: " << entry.name;
770 if (entry.comment.size())
771 fout <<
"\t" << entry.comment;
778 if (verbose_output) {
779 fout <<
"# Note: This option is only available if Squid is rebuilt with the" << std::endl <<
787 if (verbose_output && entry.doc.size()) {
788 for (
const auto &line : entry.doc) {
789 fout <<
"#" << line << std::endl;
793 if (entry.defaults.docs.size()) {
795 def = entry.defaults.docs;
797 if (entry.defaults.preset.size() && entry.defaults.preset.front().compare(
"none") != 0) {
799 for (
const auto &l : entry.defaults.preset) {
800 snprintf(buf,
sizeof(buf),
"%s %s", entry.name.c_str(), l.c_str());
803 }
else if (entry.defaults.if_none.size()) {
805 for (
const auto &l : entry.defaults.if_none) {
806 snprintf(buf,
sizeof(buf),
"%s %s", entry.name.c_str(), l.c_str());
813 if (def.empty() && entry.cfgLines.empty() && entry.name.compare(
"comment") != 0)
814 def.push_back(
"none");
816 if (verbose_output && def.size()) {
817 fout <<
"#Default:\n";
819 fout <<
"# " << def.front() << std::endl;
822 if (entry.doc.empty() && entry.cfgLines.empty())
826 if (verbose_output && entry.cfgLines.size())
827 fout <<
"#" << std::endl;
829 if (enabled || verbose_output) {
830 for (
const auto &line : entry.cfgLines) {
831 if (!enabled && line.at(0) !=
'#')
833 fout << line << std::endl;
837 if (verbose_output && entry.doc.size()) {
846 static std::string esc;
849 for (
const auto c : var) {
squidaio_request_t * head
static bool isDefined(const std::string &name)
int main(int argc, char *argv[])
std::list< std::string > EntryAliasList
#define _PATH_SQUID_CONF_SHORT
static void gen_parse(const EntryList &, std::ostream &)
static void checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries)
static void usage(const char *program_name)
std::list< std::string > LineList
static void errorMsg(const char *filename, int line, const char *detail)
static void gen_dump(const EntryList &, std::ostream &)
std::list< class Entry > EntryList
static const char * gen_quote_escape(const std::string &var)
static void gen_default_postscriptum(const EntryList &, std::ostream &)
append configuration options specified by POSTSCRIPTUM lines
static void gen_conf(const EntryList &, std::ostream &, bool verbose_output)
std::list< std::string > TypeDepList
static int gen_default(const EntryList &, std::ostream &)
static void gen_default_if_none(const EntryList &, std::ostream &)
std::list< class Type > TypeList
static const char * available_if(const std::string &name)
static void gen_free(const EntryList &, std::ostream &)
LineList preset
Default config lines to be defined before parsing the config files.
LineList postscriptum
Default config lines to parse and add to any prior settings.
LineList cfgLines
between CONFIG_START and CONFIG_END
void genParseAlias(const std::string &, std::ostream &) const
void genParse(std::ostream &fout) const
int array_flag
TYPE is a raw array[] declaration.