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