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