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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors