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