cf_gen.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: none Generate squid.conf.default and cf_parser.cci */
10 
11 /*****************************************************************************
12  * Abstract: This program parses the input file and generates code and
13  * files used to configure the variables in squid.
14  * (ie it creates the squid.conf.default file from the cf.data file)
15  *
16  * The output files are as follows:
17  * cf_parser.cci - this file contains, default_all() which
18  * initializes variables with the default
19  * values, parse_line() that parses line from
20  * squid.conf.default, dump_config that dumps the
21  * current the values of the variables.
22  * squid.conf.default - default configuration file given to the server
23  * administrator.
24  *****************************************************************************/
25 
26 /*
27  * hack around a bug in intel's c++ compiler's libraries which do not
28  * correctly support 64-bit iostreams
29  */
30 #if defined(__INTEL_COMPILER) && defined(_FILE_OFFSET_BITS) && \
31 _FILE_OFFSET_BITS==64
32 #undef _FILE_OFFSET_BITS
33 #endif
34 
35 #include <cassert>
36 #include <cctype>
37 #include <cerrno>
38 #include <cstdlib>
39 #include <cstring>
40 #include <fstream>
41 #include <iostream>
42 #include <list>
43 #include <stack>
44 
45 #include "cf_gen_defines.cci"
46 
47 #define MAX_LINE 1024 /* longest configuration line */
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"
52 
53 enum State {
55  s1,
58  sEXIT
59 };
60 
61 typedef std::list<std::string> LineList;
62 typedef std::list<std::string> TypeDepList;
63 typedef std::list<std::string> EntryAliasList;
64 
66 {
67 public:
70 
75 
78 
82 };
83 
84 class Entry
85 {
86 public:
87  explicit Entry(const char *str) : name(str) {}
88 
89  std::string name;
91  std::string type;
92  std::string loc;
94  std::string comment;
95  std::string ifdef;
98  int array_flag = 0;
99 
100  void genParse(std::ostream &fout) const;
101 
102 private:
103  void genParseAlias(const std::string &, std::ostream &) const;
104 };
105 
106 typedef std::list<class Entry> EntryList;
107 
108 class Type
109 {
110 public:
111  Type(const char *str) : name(str) {}
112 
113  std::string name;
115 };
116 
117 typedef std::list<class Type> TypeList;
118 
119 static const char WS[] = " \t\n";
120 static int gen_default(const EntryList &, std::ostream &);
121 static void gen_parse(const EntryList &, std::ostream &);
122 static void gen_dump(const EntryList &, std::ostream&);
123 static void gen_free(const EntryList &, std::ostream&);
124 static void gen_conf(const EntryList &, std::ostream&, bool verbose_output);
125 static void gen_default_if_none(const EntryList &, std::ostream&);
126 static void gen_default_postscriptum(const EntryList &, std::ostream&);
127 static bool isDefined(const std::string &name);
128 static const char *available_if(const std::string &name);
129 static const char *gen_quote_escape(const std::string &var);
130 
131 static void
132 checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries)
133 {
134  for (const auto &t : types) {
135  if (t.name.compare(name) != 0)
136  continue;
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)
141  break;
142  }
143  if (entry == entries.end()) {
144  std::cerr << "ERROR: '" << directive << "' (" << name << ") depends on '" << dep << "'\n";
145  exit(EXIT_FAILURE);
146  }
147  }
148  return;
149  }
150  std::cerr << "ERROR: Dependencies for cf.data type '" << name << "' used in ' " << directive << "' not defined\n" ;
151  exit(EXIT_FAILURE);
152 }
153 
154 static void
155 usage(const char *program_name)
156 {
157  std::cerr << "Usage: " << program_name << " cf.data cf.data.depend\n";
158  exit(EXIT_FAILURE);
159 }
160 
161 static void
162 errorMsg(const char *filename, int line, const char *detail)
163 {
164  std::cerr << "Error in '" << filename << "' on line " << line <<
165  "--> " << detail << std::endl;
166 }
167 
168 int
169 main(int argc, char *argv[])
170 {
171  char *input_filename;
172  const char *output_filename = _PATH_PARSER;
173  const char *conf_filename = _PATH_SQUID_CONF;
174  const char *conf_filename_short = _PATH_SQUID_CONF_SHORT;
175  const char *type_depend;
176  int linenum = 0;
177  EntryList entries;
178  TypeList types;
179  enum State state;
180  int rc = 0;
181  char *ptr = NULL;
182  char buff[MAX_LINE];
183  std::ifstream fp;
184  std::stack<std::string> IFDEFS;
185 
186  if (argc != 3)
187  usage(argv[0]);
188 
189  input_filename = argv[1];
190  type_depend = argv[2];
191 
192  /*-------------------------------------------------------------------*
193  * Parse type dependencies
194  *-------------------------------------------------------------------*/
195  fp.open(type_depend, std::ifstream::in);
196  if (fp.fail()) {
197  std::cerr << "Error while opening type dependencies file '" <<
198  type_depend << "': " << strerror(errno) << std::endl;
199  exit(EXIT_FAILURE);
200  }
201 
202  while (fp.good()) {
203  fp.getline(buff,MAX_LINE);
204  const char *type = strtok(buff, WS);
205  const char *dep;
206  if (!type || type[0] == '#')
207  continue;
208  Type t(type);
209  while ((dep = strtok(NULL, WS)) != NULL) {
210  t.depend.push_front(dep);
211  }
212  types.push_front(t);
213  }
214  fp.close();
215  fp.clear(); // BSD does not reset flags in close().
216 
217  /*-------------------------------------------------------------------*
218  * Parse input file
219  *-------------------------------------------------------------------*/
220 
221  /* Open input file */
222  fp.open(input_filename, std::ifstream::in);
223  if (fp.fail()) {
224  std::cerr << "Error while opening input file '" <<
225  input_filename << "': " << strerror(errno) << std::endl;
226  exit(EXIT_FAILURE);
227  }
228 
229  state = sSTART;
230 
231  while (fp.getline(buff,MAX_LINE), fp.good() && state != sEXIT) {
232  char *t;
233 
234  ++linenum;
235 
236  if ((t = strchr(buff, '\n')))
237  *t = '\0';
238 
239  if (strncmp(buff, "IF ", 3) == 0) {
240  if ((ptr = strtok(buff + 3, WS)) == NULL) {
241  errorMsg(input_filename, linenum, "Missing IF parameter");
242  exit(EXIT_FAILURE);
243  }
244  IFDEFS.push(ptr);
245  continue;
246  } else if (strcmp(buff, "ENDIF") == 0) {
247  if (IFDEFS.size() == 0) {
248  errorMsg(input_filename, linenum, "ENDIF without IF first");
249  exit(EXIT_FAILURE);
250  }
251  IFDEFS.pop();
252  } else if (!IFDEFS.size() || isDefined(IFDEFS.top()))
253  switch (state) {
254 
255  case sSTART:
256 
257  if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
258  /* ignore empty and comment lines */
259  (void) 0;
260  } else if (!strncmp(buff, "NAME:", 5)) {
261  char *name, *aliasname;
262 
263  if ((name = strtok(buff + 5, WS)) == NULL) {
264  errorMsg(input_filename, linenum, buff);
265  exit(EXIT_FAILURE);
266  }
267 
268  entries.emplace_back(name);
269 
270  while ((aliasname = strtok(NULL, WS)) != NULL)
271  entries.back().alias.push_front(aliasname);
272 
273  state = s1;
274  } else if (!strcmp(buff, "EOF")) {
275  state = sEXIT;
276  } else if (!strcmp(buff, "COMMENT_START")) {
277  entries.emplace_back("comment");
278  entries.back().loc = "none";
279  state = sDOC;
280  } else {
281  errorMsg(input_filename, linenum, buff);
282  exit(EXIT_FAILURE);
283  }
284 
285  break;
286 
287  case s1: {
288  Entry &curr = entries.back();
289 
290  if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
291  /* ignore empty and comment lines */
292  (void) 0;
293  } else if (!strncmp(buff, "COMMENT:", 8)) {
294  ptr = buff + 8;
295 
296  while (isspace((unsigned char)*ptr))
297  ++ptr;
298 
299  curr.comment = ptr;
300  } else if (!strncmp(buff, "DEFAULT:", 8)) {
301  ptr = buff + 8;
302 
303  while (isspace((unsigned char)*ptr))
304  ++ptr;
305 
306  curr.defaults.preset.push_back(ptr);
307  } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) {
308  ptr = buff + 16;
309 
310  while (isspace((unsigned char)*ptr))
311  ++ptr;
312 
313  curr.defaults.if_none.push_back(ptr);
314  } else if (!strncmp(buff, "POSTSCRIPTUM:", 13)) {
315  ptr = buff + 13;
316 
317  while (isspace((unsigned char)*ptr))
318  ++ptr;
319 
320  curr.defaults.postscriptum.push_back(ptr);
321  } else if (!strncmp(buff, "DEFAULT_DOC:", 12)) {
322  ptr = buff + 12;
323 
324  while (isspace((unsigned char)*ptr))
325  ++ptr;
326 
327  curr.defaults.docs.push_back(ptr);
328  } else if (!strncmp(buff, "LOC:", 4)) {
329  if ((ptr = strtok(buff + 4, WS)) == NULL) {
330  errorMsg(input_filename, linenum, buff);
331  exit(EXIT_FAILURE);
332  }
333 
334  curr.loc = ptr;
335  } else if (!strncmp(buff, "TYPE:", 5)) {
336  if ((ptr = strtok(buff + 5, WS)) == NULL) {
337  errorMsg(input_filename, linenum, buff);
338  exit(EXIT_FAILURE);
339  }
340 
341  /* hack to support arrays, rather than pointers */
342  if (strcmp(ptr + strlen(ptr) - 2, "[]") == 0) {
343  curr.array_flag = 1;
344  *(ptr + strlen(ptr) - 2) = '\0';
345  }
346 
347  checkDepend(curr.name, ptr, types, entries);
348  curr.type = ptr;
349  } else if (!strncmp(buff, "IFDEF:", 6)) {
350  if ((ptr = strtok(buff + 6, WS)) == NULL) {
351  errorMsg(input_filename, linenum, buff);
352  exit(EXIT_FAILURE);
353  }
354 
355  curr.ifdef = ptr;
356  } else if (!strcmp(buff, "DOC_START")) {
357  state = sDOC;
358  } else if (!strcmp(buff, "DOC_NONE")) {
359  state = sSTART;
360  } else {
361  errorMsg(input_filename, linenum, buff);
362  exit(EXIT_FAILURE);
363  }
364  }
365  break;
366 
367  case sDOC:
368  if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) {
369  state = sSTART;
370  } else if (strcmp(buff, "CONFIG_START") == 0) {
371  state = sCFGLINES;
372  } else {
373  assert(buff != NULL);
374  entries.back().doc.push_back(buff);
375  }
376  break;
377 
378  case sCFGLINES:
379  if (strcmp(buff, "CONFIG_END") == 0) {
380  state = sDOC;
381  } else {
382  assert(buff != NULL);
383  entries.back().cfgLines.push_back(buff);
384  }
385  break;
386  case sEXIT:
387  assert(0); /* should never get here */
388  break;
389  }
390 
391  }
392 
393  if (state != sEXIT) {
394  errorMsg(input_filename, linenum, "Error: unexpected EOF");
395  exit(EXIT_FAILURE);
396  }
397 
398  fp.close();
399 
400  /*-------------------------------------------------------------------*
401  * Generate default_all()
402  * Generate parse_line()
403  * Generate dump_config()
404  * Generate free_all()
405  * Generate example squid.conf.default file
406  *-------------------------------------------------------------------*/
407 
408  /* Open output x.c file */
409 
410  std::ofstream fout(output_filename,std::ostream::out);
411  if (!fout.good()) {
412  std::cerr << "Error while opening output .c file '" <<
413  output_filename << "': " << strerror(errno) << std::endl;
414  exit(EXIT_FAILURE);
415  }
416 
417  fout << "/*\n" <<
418  " * Generated automatically from " << input_filename << " by " <<
419  argv[0] << "\n"
420  " *\n"
421  " * Abstract: This file contains routines used to configure the\n"
422  " * variables in the squid server.\n"
423  " */\n"
424  "\n";
425 
426  rc = gen_default(entries, fout);
427 
428  gen_default_if_none(entries, fout);
429 
430  gen_default_postscriptum(entries, fout);
431 
432  gen_parse(entries, fout);
433 
434  gen_dump(entries, fout);
435 
436  gen_free(entries, fout);
437 
438  fout.close();
439 
440  /* Open output x.conf file */
441  fout.open(conf_filename,std::ostream::out);
442  if (!fout.good()) {
443  std::cerr << "Error while opening output conf file '" <<
444  output_filename << "': " << strerror(errno) << std::endl;
445  exit(EXIT_FAILURE);
446  }
447 
448  gen_conf(entries, fout, 1);
449 
450  fout.close();
451 
452  fout.open(conf_filename_short,std::ostream::out);
453  if (!fout.good()) {
454  std::cerr << "Error while opening output short conf file '" <<
455  output_filename << "': " << strerror(errno) << std::endl;
456  exit(EXIT_FAILURE);
457  }
458  gen_conf(entries, fout, 0);
459  fout.close();
460 
461  return (rc);
462 }
463 
464 static int
465 gen_default(const EntryList &head, std::ostream &fout)
466 {
467  int rc = 0;
468  fout << "static void" << std::endl <<
469  "default_line(const char *s)" << std::endl <<
470  "{" << std::endl <<
471  " char *tmp_line = xstrdup(s);" << std::endl <<
472  " int len = strlen(tmp_line);" << std::endl <<
473  " ProcessMacros(tmp_line, len);" << std::endl <<
474  " xstrncpy(config_input_line, tmp_line, sizeof(config_input_line));" << std::endl <<
475  " config_lineno++;" << std::endl <<
476  " parse_line(tmp_line);" << std::endl <<
477  " xfree(tmp_line);" << std::endl <<
478  "}" << std::endl << std::endl;
479  fout << "static void" << std::endl <<
480  "default_all(void)" << std::endl <<
481  "{" << std::endl <<
482  " cfg_filename = \"Default Configuration\";" << std::endl <<
483  " config_lineno = 0;" << std::endl;
484 
485  for (const auto &entry : head) {
486  assert(entry.name.size());
487 
488  if (!entry.name.compare("comment"))
489  continue;
490 
491  if (!entry.type.compare("obsolete"))
492  continue;
493 
494  if (!entry.loc.size()) {
495  std::cerr << "NO LOCATION FOR " << entry.name << std::endl;
496  rc |= 1;
497  continue;
498  }
499 
500  if (!entry.defaults.preset.size() && entry.defaults.if_none.empty()) {
501  std::cerr << "NO DEFAULT FOR " << entry.name << std::endl;
502  rc |= 1;
503  continue;
504  }
505 
506  if (!entry.defaults.preset.size() || entry.defaults.preset.front().compare("none") == 0) {
507  fout << " // No default for " << entry.name << std::endl;
508  } else {
509  if (entry.ifdef.size())
510  fout << "#if " << entry.ifdef << std::endl;
511 
512  for (const auto &l : entry.defaults.preset)
513  fout << " default_line(\"" << entry.name << " " << gen_quote_escape(l) << "\");" << std::endl;
514 
515  if (entry.ifdef.size())
516  fout << "#endif" << std::endl;
517  }
518  }
519 
520  fout << " cfg_filename = NULL;" << std::endl <<
521  "}" << std::endl << std::endl;
522  return rc;
523 }
524 
525 static void
526 gen_default_if_none(const EntryList &head, std::ostream &fout)
527 {
528  fout << "static void" << std::endl <<
529  "defaults_if_none(void)" << std::endl <<
530  "{" << std::endl <<
531  " cfg_filename = \"Default Configuration (if absent)\";" << std::endl <<
532  " config_lineno = 0;" << std::endl;
533 
534  for (const auto &entry : head) {
535  assert(entry.name.size());
536 
537  if (!entry.loc.size())
538  continue;
539 
540  if (entry.defaults.if_none.empty())
541  continue;
542 
543  if (!entry.defaults.preset.empty()) {
544  std::cerr << "ERROR: " << entry.name << " has preset defaults. DEFAULT_IF_NONE cannot be true." << std::endl;
545  exit(EXIT_FAILURE);
546  }
547 
548  if (entry.ifdef.size())
549  fout << "#if " << entry.ifdef << std::endl;
550 
551  fout << " if (check_null_" << entry.type << "(" << entry.loc << ")) {" << std::endl;
552  for (const auto &l : entry.defaults.if_none)
553  fout << " default_line(\"" << entry.name << " " << gen_quote_escape(l) <<"\");" << std::endl;
554  fout << " }" << std::endl;
555 
556  if (entry.ifdef.size())
557  fout << "#endif" << std::endl;
558  }
559 
560  fout << " cfg_filename = NULL;" << std::endl <<
561  "}" << std::endl << std::endl;
562 }
563 
565 static void
566 gen_default_postscriptum(const EntryList &head, std::ostream &fout)
567 {
568  fout << "static void" << std::endl <<
569  "defaults_postscriptum(void)" << std::endl <<
570  "{" << std::endl <<
571  " cfg_filename = \"Default Configuration (postscriptum)\";" << std::endl <<
572  " config_lineno = 0;" << std::endl;
573 
574  for (const auto &entry : head) {
575  assert(entry.name.size());
576 
577  if (!entry.loc.size())
578  continue;
579 
580  if (entry.defaults.postscriptum.empty())
581  continue;
582 
583  if (entry.ifdef.size())
584  fout << "#if " << entry.ifdef << std::endl;
585 
586  for (const auto &l : entry.defaults.postscriptum)
587  fout << " default_line(\"" << entry.name << " " << l <<"\");" << std::endl;
588 
589  if (entry.ifdef.size())
590  fout << "#endif" << std::endl;
591  }
592 
593  fout << " cfg_filename = NULL;" << std::endl <<
594  "}" << std::endl << std::endl;
595 }
596 
597 void
598 Entry::genParseAlias(const std::string &aName, std::ostream &fout) const
599 {
600  fout << " if (!strcmp(token, \"" << aName << "\")) {" << std::endl;
601  if (ifdef.size())
602  fout << "#if " << ifdef << std::endl;
603  fout << " cfg_directive = \"" << aName << "\";" << std::endl;
604  fout << " ";
605  if (type.compare("obsolete") == 0) {
606  fout << "debugs(0, DBG_CRITICAL, \"ERROR: Directive '" << aName << "' is obsolete.\");\n";
607  for (const auto &l : doc) {
608  // offset line to strip initial whitespace tab byte
609  fout << " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"" << aName << " : " << &l[1] << "\");" << std::endl;
610  }
611  fout << " parse_obsolete(token);";
612  } else if (!loc.size() || loc.compare("none") == 0) {
613  fout << "parse_" << type << "();";
614  } else if (type.find("::") != std::string::npos) {
615  fout << "ParseDirective<" << type << ">(" << loc << ", LegacyParser);";
616  } else {
617  fout << "parse_" << type << "(&" << loc << (array_flag ? "[0]" : "") << ");";
618  }
619  fout << std::endl;
620  fout << " cfg_directive = NULL;" << std::endl;
621  if (ifdef.size()) {
622  fout <<
623  "#else" << std::endl <<
624  " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"ERROR: '" << name << "' requires " << available_if(ifdef) << "\");" << std::endl <<
625  "#endif" << std::endl;
626  }
627  fout << " return 1;" << std::endl;
628  fout << " };" << std::endl;
629 }
630 
631 void
632 Entry::genParse(std::ostream &fout) const
633 {
634  if (name.compare("comment") == 0)
635  return;
636 
637  // Once for the current directive name
638  genParseAlias(name, fout);
639 
640  // All accepted aliases
641  for (const auto &a : alias) {
642  genParseAlias(a, fout);
643  }
644 }
645 
646 static void
647 gen_parse(const EntryList &head, std::ostream &fout)
648 {
649  fout <<
650  "static int\n"
651  "parse_line(char *buff)\n"
652  "{\n"
653  "\tchar\t*token;\n"
654  "\tif ((token = strtok(buff, w_space)) == NULL) \n"
655  "\t\treturn 1;\t/* ignore empty lines */\n"
656  "\tConfigParser::SetCfgLine(strtok(NULL, \"\"));\n";
657 
658  for (const auto &e : head)
659  e.genParse(fout);
660 
661  fout << "\treturn 0; /* failure */\n"
662  "}\n\n";
663 
664 }
665 
666 static void
667 gen_dump(const EntryList &head, std::ostream &fout)
668 {
669  fout <<
670  "static void" << std::endl <<
671  "dump_config(StoreEntry *entry)" << std::endl <<
672  "{" << std::endl <<
673  " debugs(5, 4, HERE);" << std::endl;
674 
675  for (const auto &e : head) {
676 
677  if (!e.loc.size() || e.loc.compare("none") == 0)
678  continue;
679 
680  if (e.name.compare("comment") == 0)
681  continue;
682 
683  if (e.ifdef.size())
684  fout << "#if " << e.ifdef << std::endl;
685 
686  if (e.type.find("::") != std::string::npos)
687  fout << " DumpDirective<" << e.type << ">(" << e.loc << ", entry, \"" << e.name << "\");\n";
688  else
689  fout << " dump_" << e.type << "(entry, \"" << e.name << "\", " << e.loc << ");" << std::endl;
690 
691  if (e.ifdef.size())
692  fout << "#endif" << std::endl;
693  }
694 
695  fout << "}" << std::endl << std::endl;
696 }
697 
698 static void
699 gen_free(const EntryList &head, std::ostream &fout)
700 {
701  fout <<
702  "static void" << std::endl <<
703  "free_all(void)" << std::endl <<
704  "{" << std::endl <<
705  " debugs(5, 4, HERE);" << std::endl;
706 
707  for (const auto &e : head) {
708  if (!e.loc.size() || e.loc.compare("none") == 0)
709  continue;
710 
711  if (e.name.compare("comment") == 0)
712  continue;
713 
714  if (e.ifdef.size())
715  fout << "#if " << e.ifdef << std::endl;
716 
717  if (e.type.find("::") != std::string::npos)
718  fout << " FreeDirective<" << e.type << ">(" << e.loc << ");\n";
719  else
720  fout << " free_" << e.type << "(&" << e.loc << (e.array_flag ? "[0]" : "") << ");" << std::endl;
721 
722  if (e.ifdef.size())
723  fout << "#endif" << std::endl;
724  }
725 
726  fout << "}" << std::endl << std::endl;
727 }
728 
729 static bool
730 isDefined(const std::string &name)
731 {
732  if (!name.size())
733  return true;
734 
735  for (int i = 0; defines[i].name; ++i) {
736  if (name.compare(defines[i].name) == 0)
737  return defines[i].defined;
738  }
739 
740  return false;
741 }
742 
743 static const char *
744 available_if(const std::string &name)
745 {
746  assert(name.size());
747 
748  for (int i = 0; defines[i].name; ++i) {
749  if (name.compare(defines[i].name) == 0)
750  return defines[i].enable;
751  }
752 
753  return name.c_str();
754 }
755 
756 static void
757 gen_conf(const EntryList &head, std::ostream &fout, bool verbose_output)
758 {
759  for (const auto &entry : head) {
760  char buf[8192];
761  LineList def;
762  int enabled = 1;
763 
764  // Display TAG: line
765  if (!entry.name.compare("comment"))
766  (void) 0;
767  else if (!entry.name.compare("obsolete"))
768  (void) 0;
769  else if (verbose_output) {
770  fout << "# TAG: " << entry.name;
771 
772  if (entry.comment.size())
773  fout << "\t" << entry.comment;
774 
775  fout << std::endl;
776  }
777 
778  // Display --enable/--disable disclaimer
779  if (!isDefined(entry.ifdef)) {
780  if (verbose_output) {
781  fout << "# Note: This option is only available if Squid is rebuilt with the" << std::endl <<
782  "# " << available_if(entry.ifdef) << std::endl <<
783  "#" << std::endl;
784  }
785  enabled = 0;
786  }
787 
788  // Display DOC_START section
789  if (verbose_output && entry.doc.size()) {
790  for (const auto &line : entry.doc) {
791  fout << "#" << line << std::endl;
792  }
793  }
794 
795  if (entry.defaults.docs.size()) {
796  // Display the DEFAULT_DOC line(s)
797  def = entry.defaults.docs;
798  } else {
799  if (entry.defaults.preset.size() && entry.defaults.preset.front().compare("none") != 0) {
800  // Display DEFAULT: line(s)
801  for (const auto &l : entry.defaults.preset) {
802  snprintf(buf, sizeof(buf), "%s %s", entry.name.c_str(), l.c_str());
803  def.push_back(buf);
804  }
805  } else if (entry.defaults.if_none.size()) {
806  // Display DEFAULT_IF_NONE: line(s)
807  for (const auto &l : entry.defaults.if_none) {
808  snprintf(buf, sizeof(buf), "%s %s", entry.name.c_str(), l.c_str());
809  def.push_back(buf);
810  }
811  }
812  }
813 
814  // Display "none" if no default is set or comments to display
815  if (def.empty() && entry.cfgLines.empty() && entry.name.compare("comment") != 0)
816  def.push_back("none");
817 
818  if (verbose_output && def.size()) {
819  fout << "#Default:\n";
820  while (def.size()) {
821  fout << "# " << def.front() << std::endl;
822  def.pop_front();
823  }
824  if (entry.doc.empty() && entry.cfgLines.empty())
825  fout << std::endl;
826  }
827 
828  if (verbose_output && entry.cfgLines.size())
829  fout << "#" << std::endl;
830 
831  if (enabled || verbose_output) {
832  for (const auto &line : entry.cfgLines) {
833  if (!enabled && line.at(0) != '#')
834  fout << "#";
835  fout << line << std::endl;
836  }
837  }
838 
839  if (verbose_output && entry.doc.size()) {
840  fout << std::endl;
841  }
842  }
843 }
844 
845 static const char *
846 gen_quote_escape(const std::string &var)
847 {
848  static std::string esc;
849  esc.clear();
850 
851  for (const auto c : var) {
852  switch (c) {
853  case '"':
854  case '\\':
855  esc += '\\';
856  /* [[fallthrough]] */
857  default:
858  esc += c;
859  }
860  }
861 
862  return esc.c_str();
863 }
864 
static void checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries)
Definition: cf_gen.cc:132
std::list< std::string > EntryAliasList
Definition: cf_gen.cc:63
std::string loc
Definition: cf_gen.cc:92
State
Definition: cf_gen.cc:53
std::list< class Type > TypeList
Definition: cf_gen.cc:117
std::string name
Definition: cf_gen.cc:113
std::string type
Definition: cf_gen.cc:91
static const char WS[]
Definition: cf_gen.cc:119
int main(int argc, char *argv[])
Definition: cf_gen.cc:169
@ s1
Definition: cf_gen.cc:55
#define _PATH_SQUID_CONF_SHORT
Definition: cf_gen.cc:50
LineList postscriptum
Default config lines to parse and add to any prior settings.
Definition: cf_gen.cc:77
#define _PATH_PARSER
Definition: cf_gen.cc:48
#define _PATH_SQUID_CONF
Definition: cf_gen.cc:49
EntryAliasList alias
Definition: cf_gen.cc:90
Entry(const char *str)
Definition: cf_gen.cc:87
std::string name
Definition: cf_gen.cc:89
int type
Definition: errorpage.cc:153
static void gen_free(const EntryList &, std::ostream &)
Definition: cf_gen.cc:699
Definition: cf_gen.cc:85
LineList doc
Definition: cf_gen.cc:96
static const char * gen_quote_escape(const std::string &var)
Definition: cf_gen.cc:846
LineList if_none
Definition: cf_gen.cc:74
static void errorMsg(const char *filename, int line, const char *detail)
Definition: cf_gen.cc:162
std::list< std::string > TypeDepList
Definition: cf_gen.cc:62
char * strerror(int ern)
Definition: strerror.c:22
void genParseAlias(const std::string &, std::ostream &) const
Definition: cf_gen.cc:598
static bool isDefined(const std::string &name)
Definition: cf_gen.cc:730
LineList cfgLines
between CONFIG_START and CONFIG_END
Definition: cf_gen.cc:97
LineList preset
Default config lines to be defined before parsing the config files.
Definition: cf_gen.cc:69
#define NULL
Definition: types.h:166
static void gen_default_if_none(const EntryList &, std::ostream &)
Definition: cf_gen.cc:526
static int gen_default(const EntryList &, std::ostream &)
Definition: cf_gen.cc:465
Definition: cf_gen.cc:109
#define assert(EX)
Definition: assert.h:19
static void usage(const char *program_name)
Definition: cf_gen.cc:155
int array_flag
TYPE is a raw array[] declaration.
Definition: cf_gen.cc:98
@ sEXIT
Definition: cf_gen.cc:58
std::list< std::string > LineList
Definition: cf_gen.cc:61
DefaultValues defaults
Definition: cf_gen.cc:93
void genParse(std::ostream &fout) const
Definition: cf_gen.cc:632
@ sCFGLINES
Definition: cf_gen.cc:57
static void gen_dump(const EntryList &, std::ostream &)
Definition: cf_gen.cc:667
static void gen_default_postscriptum(const EntryList &, std::ostream &)
append configuration options specified by POSTSCRIPTUM lines
Definition: cf_gen.cc:566
@ sDOC
Definition: cf_gen.cc:56
squidaio_request_t * head
Definition: aiops.cc:127
TypeDepList depend
Definition: cf_gen.cc:114
LineList docs
Definition: cf_gen.cc:81
static const char * available_if(const std::string &name)
Definition: cf_gen.cc:744
#define MAX_LINE
Definition: cf_gen.cc:47
std::list< class Entry > EntryList
Definition: cf_gen.cc:106
static void gen_conf(const EntryList &, std::ostream &, bool verbose_output)
Definition: cf_gen.cc:757
@ sSTART
Definition: cf_gen.cc:54
std::string ifdef
Definition: cf_gen.cc:95
char * program_name
Type(const char *str)
Definition: cf_gen.cc:111
std::string comment
Definition: cf_gen.cc:94
static void gen_parse(const EntryList &, std::ostream &)
Definition: cf_gen.cc:647

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors