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