cf_gen.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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
53enum State {
58 sEXIT
59};
60
61typedef std::list<std::string> LineList;
62typedef std::list<std::string> TypeDepList;
63typedef std::list<std::string> EntryAliasList;
64
66{
67public:
70
75
78
82};
83
84class Entry
85{
86public:
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
102private:
103 void genParseAlias(const std::string &, std::ostream &) const;
104};
105
106typedef std::list<class Entry> EntryList;
107
108class Type
109{
110public:
111 Type(const char *str) : name(str) {}
112
113 std::string name;
115};
116
117typedef std::list<class Type> TypeList;
118
119static const char WS[] = " \t\n";
120static int gen_default(const EntryList &, std::ostream &);
121static void gen_parse(const EntryList &, std::ostream &);
122static void gen_dump(const EntryList &, std::ostream&);
123static void gen_free(const EntryList &, std::ostream&);
124static void gen_conf(const EntryList &, std::ostream&, bool verbose_output);
125static void gen_default_if_none(const EntryList &, std::ostream&);
126static void gen_default_postscriptum(const EntryList &, std::ostream&);
127static bool isDefined(const std::string &name);
128static const char *available_if(const std::string &name);
129static const char *gen_quote_escape(const std::string &var);
130
131static void
132checkDepend(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
154static void
155usage(const char *program_name)
156{
157 std::cerr << "Usage: " << program_name << " cf.data cf.data.depend\n";
158 exit(EXIT_FAILURE);
159}
160
161static void
162errorMsg(const char *filename, int line, const char *detail)
163{
164 std::cerr << "Error in '" << filename << "' on line " << line <<
165 "--> " << detail << std::endl;
166}
167
168int
169main(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 = nullptr;
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(nullptr, WS)) != nullptr) {
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)) == nullptr) {
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)) == nullptr) {
264 errorMsg(input_filename, linenum, buff);
265 exit(EXIT_FAILURE);
266 }
267
268 auto &newEntry = entries.emplace_back(name);
269
270 while ((aliasname = strtok(nullptr, WS)) != nullptr)
271 newEntry.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 auto &newEntry = entries.emplace_back("comment");
278 newEntry.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)) == nullptr) {
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)) == nullptr) {
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)) == nullptr) {
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 entries.back().doc.push_back(buff);
374 }
375 break;
376
377 case sCFGLINES:
378 if (strcmp(buff, "CONFIG_END") == 0) {
379 state = sDOC;
380 } else {
381 entries.back().cfgLines.push_back(buff);
382 }
383 break;
384 case sEXIT:
385 assert(0); /* should never get here */
386 break;
387 }
388
389 }
390
391 if (state != sEXIT) {
392 errorMsg(input_filename, linenum, "Error: unexpected EOF");
393 exit(EXIT_FAILURE);
394 }
395
396 fp.close();
397
398 /*-------------------------------------------------------------------*
399 * Generate default_all()
400 * Generate parse_line()
401 * Generate dump_config()
402 * Generate free_all()
403 * Generate example squid.conf.default file
404 *-------------------------------------------------------------------*/
405
406 /* Open output x.c file */
407
408 std::ofstream fout(output_filename,std::ostream::out);
409 if (!fout.good()) {
410 std::cerr << "Error while opening output .c file '" <<
411 output_filename << "': " << strerror(errno) << std::endl;
412 exit(EXIT_FAILURE);
413 }
414
415 fout << "/*\n" <<
416 " * Generated automatically from " << input_filename << " by " <<
417 argv[0] << "\n"
418 " *\n"
419 " * Abstract: This file contains routines used to configure the\n"
420 " * variables in the squid server.\n"
421 " */\n"
422 "\n";
423
424 rc = gen_default(entries, fout);
425
426 gen_default_if_none(entries, fout);
427
428 gen_default_postscriptum(entries, fout);
429
430 gen_parse(entries, fout);
431
432 gen_dump(entries, fout);
433
434 gen_free(entries, fout);
435
436 fout.close();
437
438 /* Open output x.conf file */
439 fout.open(conf_filename,std::ostream::out);
440 if (!fout.good()) {
441 std::cerr << "Error while opening output conf file '" <<
442 output_filename << "': " << strerror(errno) << std::endl;
443 exit(EXIT_FAILURE);
444 }
445
446 gen_conf(entries, fout, 1);
447
448 fout.close();
449
450 fout.open(conf_filename_short,std::ostream::out);
451 if (!fout.good()) {
452 std::cerr << "Error while opening output short conf file '" <<
453 output_filename << "': " << strerror(errno) << std::endl;
454 exit(EXIT_FAILURE);
455 }
456 gen_conf(entries, fout, 0);
457 fout.close();
458
459 return (rc);
460}
461
462static int
463gen_default(const EntryList &head, std::ostream &fout)
464{
465 int rc = 0;
466 fout << "static void" << std::endl <<
467 "default_line(const char *s)" << std::endl <<
468 "{" << 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 <<
479 "{" << std::endl <<
480 " cfg_filename = \"Default Configuration\";" << std::endl <<
481 " config_lineno = 0;" << std::endl;
482
483 for (const auto &entry : head) {
484 assert(entry.name.size());
485
486 if (!entry.name.compare("comment"))
487 continue;
488
489 if (!entry.type.compare("obsolete"))
490 continue;
491
492 if (!entry.loc.size()) {
493 std::cerr << "NO LOCATION FOR " << entry.name << std::endl;
494 rc |= 1;
495 continue;
496 }
497
498 if (!entry.defaults.preset.size() && entry.defaults.if_none.empty()) {
499 std::cerr << "NO DEFAULT FOR " << entry.name << std::endl;
500 rc |= 1;
501 continue;
502 }
503
504 if (!entry.defaults.preset.size() || entry.defaults.preset.front().compare("none") == 0) {
505 fout << " // No default for " << entry.name << std::endl;
506 } else {
507 if (entry.ifdef.size())
508 fout << "#if " << entry.ifdef << std::endl;
509
510 for (const auto &l : entry.defaults.preset)
511 fout << " default_line(\"" << entry.name << " " << gen_quote_escape(l) << "\");" << std::endl;
512
513 if (entry.ifdef.size())
514 fout << "#endif" << std::endl;
515 }
516 }
517
518 fout << " cfg_filename = nullptr;" << std::endl <<
519 "}" << std::endl << std::endl;
520 return rc;
521}
522
523static void
524gen_default_if_none(const EntryList &head, std::ostream &fout)
525{
526 fout << "static void" << std::endl <<
527 "defaults_if_none(void)" << std::endl <<
528 "{" << std::endl <<
529 " cfg_filename = \"Default Configuration (if absent)\";" << std::endl <<
530 " config_lineno = 0;" << std::endl;
531
532 for (const auto &entry : head) {
533 assert(entry.name.size());
534
535 if (!entry.loc.size())
536 continue;
537
538 if (entry.defaults.if_none.empty())
539 continue;
540
541 if (!entry.defaults.preset.empty()) {
542 std::cerr << "ERROR: " << entry.name << " has preset defaults. DEFAULT_IF_NONE cannot be true." << std::endl;
543 exit(EXIT_FAILURE);
544 }
545
546 if (entry.ifdef.size())
547 fout << "#if " << entry.ifdef << std::endl;
548
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;
553
554 if (entry.ifdef.size())
555 fout << "#endif" << std::endl;
556 }
557
558 fout << " cfg_filename = nullptr;" << std::endl <<
559 "}" << std::endl << std::endl;
560}
561
563static void
564gen_default_postscriptum(const EntryList &head, std::ostream &fout)
565{
566 fout << "static void" << std::endl <<
567 "defaults_postscriptum(void)" << std::endl <<
568 "{" << std::endl <<
569 " cfg_filename = \"Default Configuration (postscriptum)\";" << std::endl <<
570 " config_lineno = 0;" << std::endl;
571
572 for (const auto &entry : head) {
573 assert(entry.name.size());
574
575 if (!entry.loc.size())
576 continue;
577
578 if (entry.defaults.postscriptum.empty())
579 continue;
580
581 if (entry.ifdef.size())
582 fout << "#if " << entry.ifdef << std::endl;
583
584 for (const auto &l : entry.defaults.postscriptum)
585 fout << " default_line(\"" << entry.name << " " << l <<"\");" << std::endl;
586
587 if (entry.ifdef.size())
588 fout << "#endif" << std::endl;
589 }
590
591 fout << " cfg_filename = nullptr;" << std::endl <<
592 "}" << std::endl << std::endl;
593}
594
595void
596Entry::genParseAlias(const std::string &aName, std::ostream &fout) const
597{
598 fout << " if (!strcmp(token, \"" << aName << "\")) {" << std::endl;
599 if (ifdef.size())
600 fout << "#if " << ifdef << std::endl;
601 fout << " cfg_directive = \"" << aName << "\";" << std::endl;
602 fout << " ";
603 if (type.compare("obsolete") == 0) {
604 fout << "debugs(0, DBG_CRITICAL, \"ERROR: Directive '" << aName << "' is obsolete.\");\n";
605 for (const auto &l : doc) {
606 // offset line to strip initial whitespace tab byte
607 fout << " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"" << aName << " : " << &l[1] << "\");" << std::endl;
608 }
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);";
614 } else {
615 fout << "parse_" << type << "(&" << loc << (array_flag ? "[0]" : "") << ");";
616 }
617 fout << std::endl;
618 fout << " cfg_directive = nullptr;" << std::endl;
619 if (ifdef.size()) {
620 fout <<
621 "#else" << std::endl <<
622 " debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), \"ERROR: '" << name << "' requires " << available_if(ifdef) << "\");" << std::endl <<
623 "#endif" << std::endl;
624 }
625 fout << " return 1;" << std::endl;
626 fout << " };" << std::endl;
627}
628
629void
630Entry::genParse(std::ostream &fout) const
631{
632 if (name.compare("comment") == 0)
633 return;
634
635 // Once for the current directive name
636 genParseAlias(name, fout);
637
638 // All accepted aliases
639 for (const auto &a : alias) {
640 genParseAlias(a, fout);
641 }
642}
643
644static void
645gen_parse(const EntryList &head, std::ostream &fout)
646{
647 fout <<
648 "static int\n"
649 "parse_line(char *buff)\n"
650 "{\n"
651 "\tchar\t*token;\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";
655
656 for (const auto &e : head)
657 e.genParse(fout);
658
659 fout << "\treturn 0; /* failure */\n"
660 "}\n\n";
661
662}
663
664static void
665gen_dump(const EntryList &head, std::ostream &fout)
666{
667 fout <<
668 "static void" << std::endl <<
669 "dump_config(StoreEntry *entry)" << std::endl <<
670 "{" << std::endl <<
671 " debugs(5, 4, MYNAME);" << std::endl;
672
673 for (const auto &e : head) {
674
675 if (!e.loc.size() || e.loc.compare("none") == 0)
676 continue;
677
678 if (e.name.compare("comment") == 0)
679 continue;
680
681 if (e.ifdef.size())
682 fout << "#if " << e.ifdef << std::endl;
683
684 if (e.type.find("::") != std::string::npos)
685 fout << " DumpDirective<" << e.type << ">(" << e.loc << ", entry, \"" << e.name << "\");\n";
686 else
687 fout << " dump_" << e.type << "(entry, \"" << e.name << "\", " << e.loc << ");" << std::endl;
688
689 if (e.ifdef.size())
690 fout << "#endif" << std::endl;
691 }
692
693 fout << "}" << std::endl << std::endl;
694}
695
696static void
697gen_free(const EntryList &head, std::ostream &fout)
698{
699 fout <<
700 "static void" << std::endl <<
701 "free_all(void)" << std::endl <<
702 "{" << std::endl <<
703 " debugs(5, 4, MYNAME);" << std::endl;
704
705 for (const auto &e : head) {
706 if (!e.loc.size() || e.loc.compare("none") == 0)
707 continue;
708
709 if (e.name.compare("comment") == 0)
710 continue;
711
712 if (e.ifdef.size())
713 fout << "#if " << e.ifdef << std::endl;
714
715 if (e.type.find("::") != std::string::npos)
716 fout << " FreeDirective<" << e.type << ">(" << e.loc << ");\n";
717 else
718 fout << " free_" << e.type << "(&" << e.loc << (e.array_flag ? "[0]" : "") << ");" << std::endl;
719
720 if (e.ifdef.size())
721 fout << "#endif" << std::endl;
722 }
723
724 fout << "}" << std::endl << std::endl;
725}
726
727static bool
728isDefined(const std::string &name)
729{
730 if (!name.size())
731 return true;
732
733 for (int i = 0; defines[i].name; ++i) {
734 if (name.compare(defines[i].name) == 0)
735 return defines[i].defined;
736 }
737
738 return false;
739}
740
741static const char *
742available_if(const std::string &name)
743{
744 assert(name.size());
745
746 for (int i = 0; defines[i].name; ++i) {
747 if (name.compare(defines[i].name) == 0)
748 return defines[i].enable;
749 }
750
751 return name.c_str();
752}
753
754static void
755gen_conf(const EntryList &head, std::ostream &fout, bool verbose_output)
756{
757 for (const auto &entry : head) {
758 char buf[8192];
759 LineList def;
760 int enabled = 1;
761
762 // Display TAG: line
763 if (!entry.name.compare("comment"))
764 (void) 0;
765 else if (!entry.name.compare("obsolete"))
766 (void) 0;
767 else if (verbose_output) {
768 fout << "# TAG: " << entry.name;
769
770 if (entry.comment.size())
771 fout << "\t" << entry.comment;
772
773 fout << std::endl;
774 }
775
776 // Display --enable/--disable disclaimer
777 if (!isDefined(entry.ifdef)) {
778 if (verbose_output) {
779 fout << "# Note: This option is only available if Squid is rebuilt with the" << std::endl <<
780 "# " << available_if(entry.ifdef) << std::endl <<
781 "#" << std::endl;
782 }
783 enabled = 0;
784 }
785
786 // Display DOC_START section
787 if (verbose_output && entry.doc.size()) {
788 for (const auto &line : entry.doc) {
789 fout << "#" << line << std::endl;
790 }
791 }
792
793 if (entry.defaults.docs.size()) {
794 // Display the DEFAULT_DOC line(s)
795 def = entry.defaults.docs;
796 } else {
797 if (entry.defaults.preset.size() && entry.defaults.preset.front().compare("none") != 0) {
798 // Display DEFAULT: line(s)
799 for (const auto &l : entry.defaults.preset) {
800 snprintf(buf, sizeof(buf), "%s %s", entry.name.c_str(), l.c_str());
801 def.push_back(buf);
802 }
803 } else if (entry.defaults.if_none.size()) {
804 // Display DEFAULT_IF_NONE: line(s)
805 for (const auto &l : entry.defaults.if_none) {
806 snprintf(buf, sizeof(buf), "%s %s", entry.name.c_str(), l.c_str());
807 def.push_back(buf);
808 }
809 }
810 }
811
812 // Display "none" if no default is set or comments to display
813 if (def.empty() && entry.cfgLines.empty() && entry.name.compare("comment") != 0)
814 def.push_back("none");
815
816 if (verbose_output && def.size()) {
817 fout << "#Default:\n";
818 while (def.size()) {
819 fout << "# " << def.front() << std::endl;
820 def.pop_front();
821 }
822 if (entry.doc.empty() && entry.cfgLines.empty())
823 fout << std::endl;
824 }
825
826 if (verbose_output && entry.cfgLines.size())
827 fout << "#" << std::endl;
828
829 if (enabled || verbose_output) {
830 for (const auto &line : entry.cfgLines) {
831 if (!enabled && line.at(0) != '#')
832 fout << "#";
833 fout << line << std::endl;
834 }
835 }
836
837 if (verbose_output && entry.doc.size()) {
838 fout << std::endl;
839 }
840 }
841}
842
843static const char *
844gen_quote_escape(const std::string &var)
845{
846 static std::string esc;
847 esc.clear();
848
849 for (const auto c : var) {
850 switch (c) {
851 case '"':
852 case '\\':
853 esc += '\\';
854 [[fallthrough]];
855 default:
856 esc += c;
857 }
858 }
859
860 return esc.c_str();
861}
862
squidaio_request_t * head
Definition: aiops.cc:127
#define assert(EX)
Definition: assert.h:17
static bool isDefined(const std::string &name)
Definition: cf_gen.cc:728
int main(int argc, char *argv[])
Definition: cf_gen.cc:169
std::list< std::string > EntryAliasList
Definition: cf_gen.cc:63
#define _PATH_SQUID_CONF_SHORT
Definition: cf_gen.cc:50
#define _PATH_PARSER
Definition: cf_gen.cc:48
static void gen_parse(const EntryList &, std::ostream &)
Definition: cf_gen.cc:645
static void checkDepend(const std::string &directive, const char *name, const TypeList &types, const EntryList &entries)
Definition: cf_gen.cc:132
static void usage(const char *program_name)
Definition: cf_gen.cc:155
std::list< std::string > LineList
Definition: cf_gen.cc:61
static void errorMsg(const char *filename, int line, const char *detail)
Definition: cf_gen.cc:162
State
Definition: cf_gen.cc:53
@ sDOC
Definition: cf_gen.cc:56
@ sCFGLINES
Definition: cf_gen.cc:57
@ s1
Definition: cf_gen.cc:55
@ sEXIT
Definition: cf_gen.cc:58
@ sSTART
Definition: cf_gen.cc:54
static void gen_dump(const EntryList &, std::ostream &)
Definition: cf_gen.cc:665
#define _PATH_SQUID_CONF
Definition: cf_gen.cc:49
std::list< class Entry > EntryList
Definition: cf_gen.cc:106
static const char * gen_quote_escape(const std::string &var)
Definition: cf_gen.cc:844
static void gen_default_postscriptum(const EntryList &, std::ostream &)
append configuration options specified by POSTSCRIPTUM lines
Definition: cf_gen.cc:564
#define MAX_LINE
Definition: cf_gen.cc:47
static const char WS[]
Definition: cf_gen.cc:119
static void gen_conf(const EntryList &, std::ostream &, bool verbose_output)
Definition: cf_gen.cc:755
std::list< std::string > TypeDepList
Definition: cf_gen.cc:62
static int gen_default(const EntryList &, std::ostream &)
Definition: cf_gen.cc:463
static void gen_default_if_none(const EntryList &, std::ostream &)
Definition: cf_gen.cc:524
std::list< class Type > TypeList
Definition: cf_gen.cc:117
static const char * available_if(const std::string &name)
Definition: cf_gen.cc:742
static void gen_free(const EntryList &, std::ostream &)
Definition: cf_gen.cc:697
LineList docs
Definition: cf_gen.cc:81
LineList preset
Default config lines to be defined before parsing the config files.
Definition: cf_gen.cc:69
LineList postscriptum
Default config lines to parse and add to any prior settings.
Definition: cf_gen.cc:77
LineList if_none
Definition: cf_gen.cc:74
Definition: cf_gen.cc:85
LineList cfgLines
between CONFIG_START and CONFIG_END
Definition: cf_gen.cc:97
DefaultValues defaults
Definition: cf_gen.cc:93
std::string ifdef
Definition: cf_gen.cc:95
LineList doc
Definition: cf_gen.cc:96
Entry(const char *str)
Definition: cf_gen.cc:87
EntryAliasList alias
Definition: cf_gen.cc:90
std::string type
Definition: cf_gen.cc:91
void genParseAlias(const std::string &, std::ostream &) const
Definition: cf_gen.cc:596
void genParse(std::ostream &fout) const
Definition: cf_gen.cc:630
int array_flag
TYPE is a raw array[] declaration.
Definition: cf_gen.cc:98
std::string comment
Definition: cf_gen.cc:94
std::string name
Definition: cf_gen.cc:89
std::string loc
Definition: cf_gen.cc:92
Definition: cf_gen.cc:109
Type(const char *str)
Definition: cf_gen.cc:111
TypeDepList depend
Definition: cf_gen.cc:114
std::string name
Definition: cf_gen.cc:113
char * program_name
char * strerror(int ern)
Definition: strerror.c:22

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors