]>
Commit | Line | Data |
---|---|---|
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 | |
72 | enum 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 |
82 | class Line |
83 | { | |
84 | public: | |
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 |
92 | class EntryAlias |
93 | { | |
94 | public: | |
95 | EntryAlias(const char *str) : name(str), next(NULL) {} | |
96 | ~EntryAlias() {} | |
7af1c5ab | 97 | |
c1f8bbd0 AJ |
98 | std::string name; |
99 | EntryAlias *next; | |
100 | }; | |
101 | ||
102 | class Entry | |
103 | { | |
104 | public: | |
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 |
127 | class TypeDep |
128 | { | |
129 | public: | |
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 |
137 | class Type |
138 | { | |
139 | public: | |
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 | |
148 | static const char WS[] = " \t\n"; | |
7ff7a211 FC |
149 | static int gen_default(Entry *, std::ostream &); |
150 | static void gen_parse(Entry *, std::ostream &); | |
151 | static void gen_parse_entry(Entry *entry, std::ostream&); | |
c1f8bbd0 | 152 | static void gen_parse_alias(const std::string &, EntryAlias *, Entry *, std::ostream &); |
7ff7a211 FC |
153 | static void gen_dump(Entry *, std::ostream&); |
154 | static void gen_free(Entry *, std::ostream&); | |
155 | static void gen_conf(Entry *, std::ostream&, bool verbose_output); | |
156 | static void gen_default_if_none(Entry *, std::ostream&); | |
934b03fc | 157 | |
a4b8110e | 158 | static void |
c193c972 | 159 | lineAdd(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 | 169 | static void |
c1f8bbd0 | 170 | checkDepend(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 |
194 | static void |
195 | usage(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 | 201 | int |
202 | main(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 | 530 | static int |
7ff7a211 | 531 | gen_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 | 591 | static void |
7ff7a211 | 592 | gen_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 | 630 | void |
c1f8bbd0 | 631 | gen_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 | ||
653 | void | |
7ff7a211 | 654 | gen_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 | ||
683 | static void | |
7ff7a211 | 684 | gen_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 | ||
702 | static void | |
7ff7a211 | 703 | gen_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 | 733 | static void |
7ff7a211 | 734 | gen_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 |
763 | static bool |
764 | defined(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 | 777 | static const char * |
c1f8bbd0 | 778 | available_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 | 790 | static void |
7ff7a211 | 791 | gen_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 | } |