]> git.ipfire.org Git - thirdparty/squid.git/blame - src/cf_gen.cc
Updated copyright
[thirdparty/squid.git] / src / cf_gen.cc
CommitLineData
f740a279 1
934b03fc 2/*
2b6662ba 3 * $Id: cf_gen.cc,v 1.40 2001/01/12 00:37:15 wessels Exp $
934b03fc 4 *
f740a279 5 * DEBUG: none Generate squid.conf and cf_parser.c
934b03fc 6 * AUTHOR: Max Okumoto
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
934b03fc 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
934b03fc 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
934b03fc 34 */
35
36/*****************************************************************************
37 * Abstract: This program parses the input file and generates code and
38 * files used to configure the variables in squid.
3a278cb8 39 * (ie it creates the squid.conf file from the cf.data file)
934b03fc 40 *
41 * The output files are as follows:
42 * cf_parser.c - this file contains, default_all() which
f53b06f9 43 * initializes variables with the default
44 * values, parse_line() that parses line from
45 * squid.conf, dump_config that dumps the
934b03fc 46 * current the values of the variables.
47 * squid.conf - default configuration file given to the server
48 * administrator.
49 *****************************************************************************/
50
6507d007 51#include "config.h"
6b53c392 52#include "cf_gen_defines.h"
6507d007 53
54#if HAVE_STDIO_H
934b03fc 55#include <stdio.h>
6507d007 56#endif
57#if HAVE_STRING_H
934b03fc 58#include <string.h>
6507d007 59#endif
60#if HAVE_STDLIB_H
934b03fc 61#include <stdlib.h>
6507d007 62#endif
63#if HAVE_CTYPE_H
934b03fc 64#include <ctype.h>
6507d007 65#endif
66#if HAVE_ASSERT_H
934b03fc 67#include <assert.h>
6507d007 68#endif
c4aefe96 69#if defined(_SQUID_CYGWIN_)
70#include <io.h>
71#endif
72#if HAVE_FCNTL_H
73#include <fcntl.h>
74#endif
6507d007 75
c68e9c6b 76#include "util.h"
77
934b03fc 78#define MAX_LINE 1024 /* longest configuration line */
79#define _PATH_PARSER "cf_parser.c"
80#define _PATH_SQUID_CONF "squid.conf"
81
82enum State {
83 sSTART,
84 s1,
85 sDOC,
c68e9c6b 86 sNOCOMMENT,
934b03fc 87 sEXIT
88};
89
90typedef struct Line {
91 char *data;
92 struct Line *next;
93} Line;
94
95typedef struct Entry {
96 char *name;
97 char *type;
98 char *loc;
99 char *default_value;
6b53c392 100 Line *default_if_none;
934b03fc 101 char *comment;
1df370e3 102 char *ifdef;
934b03fc 103 Line *doc;
c68e9c6b 104 Line *nocomment;
b3de4c9b 105 int array_flag;
934b03fc 106 struct Entry *next;
107} Entry;
108
109
110static const char WS[] = " \t";
f1dc9b30 111static int gen_default(Entry *, FILE *);
934b03fc 112static void gen_parse(Entry *, FILE *);
113static void gen_dump(Entry *, FILE *);
0153d498 114static void gen_free(Entry *, FILE *);
934b03fc 115static void gen_conf(Entry *, FILE *);
f53b06f9 116static void gen_default_if_none(Entry *, FILE *);
934b03fc 117
a4b8110e 118static void
119lineAdd(Line ** L, char *str)
6b53c392 120{
a4b8110e 121 while (*L)
122 L = &(*L)->next;
123 *L = xcalloc(1, sizeof(Line));
6b53c392 124 (*L)->data = xstrdup(str);
125}
126
934b03fc 127int
128main(int argc, char *argv[])
129{
130 FILE *fp;
131 char *input_filename = argv[1];
132 char *output_filename = _PATH_PARSER;
133 char *conf_filename = _PATH_SQUID_CONF;
134 int linenum = 0;
135 Entry *entries = NULL;
136 Entry *curr = NULL;
137 enum State state;
f1dc9b30 138 int rc = 0;
9906e724 139 char *ptr = NULL;
cd377065 140#ifdef _SQUID_OS2_
141 const char *rmode = "rt";
142#else
143 const char *rmode = "r";
144#endif
934b03fc 145
146 /*-------------------------------------------------------------------*
147 * Parse input file
148 *-------------------------------------------------------------------*/
149
150 /* Open input file */
cd377065 151 if ((fp = fopen(input_filename, rmode)) == NULL) {
934b03fc 152 perror(input_filename);
153 exit(1);
154 }
c4aefe96 155#if defined(_SQUID_CYGWIN_)
156 setmode(fileno(fp), O_TEXT);
157#endif
934b03fc 158 state = sSTART;
159 while (feof(fp) == 0 && state != sEXIT) {
160 char buff[MAX_LINE];
ff11b0ff 161 char *t;
162 if (NULL == fgets(buff, MAX_LINE, fp))
163 break;
934b03fc 164 linenum++;
69d80593 165 if ((t = strchr(buff, '\n')))
ff11b0ff 166 *t = '\0';
934b03fc 167 switch (state) {
168 case sSTART:
169 if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
170 /* ignore empty and comment lines */
79d39a72 171 (void) 0;
934b03fc 172 } else if (!strncmp(buff, "NAME:", 5)) {
173 char *name;
934b03fc 174 if ((name = strtok(buff + 5, WS)) == NULL) {
175 printf("Error in input file\n");
176 exit(1);
177 }
14a31364 178 curr = calloc(1, sizeof(Entry));
c68e9c6b 179 curr->name = xstrdup(name);
934b03fc 180 state = s1;
934b03fc 181 } else if (!strcmp(buff, "EOF")) {
182 state = sEXIT;
0f74202c 183 } else if (!strcmp(buff, "COMMENT_START")) {
184 curr = calloc(1, sizeof(Entry));
c68e9c6b 185 curr->name = xstrdup("comment");
186 curr->loc = xstrdup("none");
0f74202c 187 state = sDOC;
934b03fc 188 } else {
189 printf("Error on line %d\n", linenum);
e0d26b98 190 printf("--> %s\n", buff);
934b03fc 191 exit(1);
192 }
193 break;
194
195 case s1:
196 if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) {
197 /* ignore empty and comment lines */
79d39a72 198 (void) 0;
934b03fc 199 } else if (!strncmp(buff, "COMMENT:", 8)) {
9906e724 200 ptr = buff + 8;
b6a2f15e 201 while (xisspace(*ptr))
9906e724 202 ptr++;
c68e9c6b 203 curr->comment = xstrdup(ptr);
934b03fc 204 } else if (!strncmp(buff, "DEFAULT:", 8)) {
9906e724 205 ptr = buff + 8;
b6a2f15e 206 while (xisspace(*ptr))
9906e724 207 ptr++;
c68e9c6b 208 curr->default_value = xstrdup(ptr);
f53b06f9 209 } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) {
210 ptr = buff + 16;
b6a2f15e 211 while (xisspace(*ptr))
f53b06f9 212 ptr++;
6b53c392 213 lineAdd(&curr->default_if_none, ptr);
934b03fc 214 } else if (!strncmp(buff, "LOC:", 4)) {
934b03fc 215 if ((ptr = strtok(buff + 4, WS)) == NULL) {
216 printf("Error on line %d\n", linenum);
217 exit(1);
218 }
c68e9c6b 219 curr->loc = xstrdup(ptr);
934b03fc 220 } else if (!strncmp(buff, "TYPE:", 5)) {
934b03fc 221 if ((ptr = strtok(buff + 5, WS)) == NULL) {
222 printf("Error on line %d\n", linenum);
223 exit(1);
224 }
b3de4c9b 225 /* hack to support arrays, rather than pointers */
226 if (0 == strcmp(ptr + strlen(ptr) - 2, "[]")) {
227 curr->array_flag = 1;
228 *(ptr + strlen(ptr) - 2) = '\0';
229 }
c68e9c6b 230 curr->type = xstrdup(ptr);
1df370e3 231 } else if (!strncmp(buff, "IFDEF:", 6)) {
232 if ((ptr = strtok(buff + 6, WS)) == NULL) {
233 printf("Error on line %d\n", linenum);
234 exit(1);
235 }
c68e9c6b 236 curr->ifdef = xstrdup(ptr);
934b03fc 237 } else if (!strcmp(buff, "DOC_START")) {
238 state = sDOC;
934b03fc 239 } else if (!strcmp(buff, "DOC_NONE")) {
240 /* add to list of entries */
241 curr->next = entries;
242 entries = curr;
934b03fc 243 state = sSTART;
934b03fc 244 } else {
245 printf("Error on line %d\n", linenum);
246 exit(1);
247 }
248 break;
249
250 case sDOC:
0f74202c 251 if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) {
934b03fc 252 Line *head = NULL;
253 Line *line = curr->doc;
934b03fc 254 /* reverse order of doc lines */
255 while (line != NULL) {
256 Line *tmp;
257 tmp = line->next;
258 line->next = head;
259 head = line;
260 line = tmp;
261 }
262 curr->doc = head;
934b03fc 263 /* add to list of entries */
264 curr->next = entries;
265 entries = curr;
934b03fc 266 state = sSTART;
c68e9c6b 267 } else if (!strcmp(buff, "NOCOMMENT_START")) {
268 state = sNOCOMMENT;
934b03fc 269 } else {
14a31364 270 Line *line = calloc(1, sizeof(Line));
c68e9c6b 271 line->data = xstrdup(buff);
934b03fc 272 line->next = curr->doc;
273 curr->doc = line;
274 }
275 break;
276
c68e9c6b 277 case sNOCOMMENT:
278 if (!strcmp(buff, "NOCOMMENT_END")) {
279 Line *head = NULL;
280 Line *line = curr->nocomment;
281 /* reverse order of lines */
282 while (line != NULL) {
283 Line *tmp;
284 tmp = line->next;
285 line->next = head;
286 head = line;
287 line = tmp;
288 }
289 curr->nocomment = head;
290 state = sDOC;
291 } else {
292 Line *line = calloc(1, sizeof(Line));
293 line->data = xstrdup(buff);
294 line->next = curr->nocomment;
295 curr->nocomment = line;
296 }
297 break;
298
934b03fc 299 case sEXIT:
300 assert(0); /* should never get here */
301 break;
302 }
303 }
304 if (state != sEXIT) {
305 printf("Error unexpected EOF\n");
306 exit(1);
307 } else {
308 /* reverse order of entries */
309 Entry *head = NULL;
310
311 while (entries != NULL) {
312 Entry *tmp;
313
314 tmp = entries->next;
315 entries->next = head;
316 head = entries;
317 entries = tmp;
318 }
319 entries = head;
320 }
321 fclose(fp);
322
323 /*-------------------------------------------------------------------*
324 * Generate default_all()
325 * Generate parse_line()
f53b06f9 326 * Generate dump_config()
0153d498 327 * Generate free_all()
934b03fc 328 * Generate example squid.conf file
329 *-------------------------------------------------------------------*/
330
331 /* Open output x.c file */
332 if ((fp = fopen(output_filename, "w")) == NULL) {
333 perror(output_filename);
334 exit(1);
335 }
c4aefe96 336#if defined(_SQUID_CYGWIN_)
337 setmode(fileno(fp), O_TEXT);
338#endif
934b03fc 339 fprintf(fp,
340 "/*\n"
341 " * Generated automatically from %s by %s\n"
342 " *\n"
343 " * Abstract: This file contains routines used to configure the\n"
344 " * variables in the squid server.\n"
345 " */\n"
346 "\n",
347 input_filename, argv[0]
348 );
f1dc9b30 349 rc = gen_default(entries, fp);
f53b06f9 350 gen_default_if_none(entries, fp);
934b03fc 351 gen_parse(entries, fp);
352 gen_dump(entries, fp);
0153d498 353 gen_free(entries, fp);
934b03fc 354 fclose(fp);
355
356 /* Open output x.conf file */
357 if ((fp = fopen(conf_filename, "w")) == NULL) {
358 perror(conf_filename);
359 exit(1);
360 }
c4aefe96 361#if defined(_SQUID_CYGWIN_)
362 setmode(fileno(fp), O_TEXT);
363#endif
934b03fc 364 gen_conf(entries, fp);
365 fclose(fp);
366
f1dc9b30 367 return (rc);
934b03fc 368}
369
f1dc9b30 370static int
934b03fc 371gen_default(Entry * head, FILE * fp)
372{
373 Entry *entry;
f1dc9b30 374 int rc = 0;
b556b1e9 375 fprintf(fp,
d9586c3c 376 "static void\n"
b556b1e9 377 "default_line(const char *s)\n"
378 "{\n"
379 "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n"
9906e724 380 "\txstrncpy(tmp_line, s, BUFSIZ);\n"
381 "\txstrncpy(config_input_line, s, BUFSIZ);\n"
b556b1e9 382 "\tconfig_lineno++;\n"
9906e724 383 "\tparse_line(tmp_line);\n"
b556b1e9 384 "}\n"
385 );
934b03fc 386 fprintf(fp,
d9586c3c 387 "static void\n"
934b03fc 388 "default_all(void)\n"
389 "{\n"
1273d501 390 "\tcfg_filename = \"Default Configuration\";\n"
b556b1e9 391 "\tconfig_lineno = 0;\n"
934b03fc 392 );
393 for (entry = head; entry != NULL; entry = entry->next) {
394 assert(entry->name);
c68e9c6b 395 assert(entry != entry->next);
3a278cb8 396
0f74202c 397 if (!strcmp(entry->name, "comment"))
3a278cb8 398 continue;
934b03fc 399 if (entry->loc == NULL) {
400 fprintf(stderr, "NO LOCATION FOR %s\n", entry->name);
f1dc9b30 401 rc |= 1;
934b03fc 402 continue;
403 }
404 if (entry->default_value == NULL) {
405 fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name);
f1dc9b30 406 rc |= 1;
934b03fc 407 continue;
408 }
f1dc9b30 409 assert(entry->default_value);
1df370e3 410 if (entry->ifdef)
75339a46 411 fprintf(fp, "#if %s\n", entry->ifdef);
f1dc9b30 412 if (strcmp(entry->default_value, "none") == 0) {
413 fprintf(fp, "\t/* No default for %s */\n", entry->name);
934b03fc 414 } else {
b556b1e9 415 fprintf(fp, "\tdefault_line(\"%s %s\");\n",
934b03fc 416 entry->name,
417 entry->default_value);
f1dc9b30 418 }
1df370e3 419 if (entry->ifdef)
420 fprintf(fp, "#endif\n");
934b03fc 421 }
1273d501 422 fprintf(fp, "\tcfg_filename = NULL;\n");
934b03fc 423 fprintf(fp, "}\n\n");
f1dc9b30 424 return rc;
934b03fc 425}
426
f53b06f9 427static void
428gen_default_if_none(Entry * head, FILE * fp)
429{
430 Entry *entry;
6b53c392 431 Line *line;
f53b06f9 432 fprintf(fp,
d9586c3c 433 "static void\n"
f53b06f9 434 "defaults_if_none(void)\n"
435 "{\n"
436 );
437 for (entry = head; entry != NULL; entry = entry->next) {
438 assert(entry->name);
439 assert(entry->loc);
440 if (entry->default_if_none == NULL)
441 continue;
1df370e3 442 if (entry->ifdef)
75339a46 443 fprintf(fp, "#if %s\n", entry->ifdef);
6b53c392 444 if (entry->default_if_none) {
445 fprintf(fp,
446 "\tif (check_null_%s(%s)) {\n",
447 entry->type,
448 entry->loc);
449 for (line = entry->default_if_none; line; line = line->next)
450 fprintf(fp,
451 "\t\tdefault_line(\"%s %s\");\n",
452 entry->name,
453 line->data);
454 fprintf(fp, "\t}\n");
455 }
1df370e3 456 if (entry->ifdef)
a4b8110e 457 fprintf(fp, "#endif\n");
f53b06f9 458 }
459 fprintf(fp, "}\n\n");
460}
461
934b03fc 462static void
463gen_parse(Entry * head, FILE * fp)
464{
465 Entry *entry;
466
467 fprintf(fp,
f8c4d483 468 "static int\n"
934b03fc 469 "parse_line(char *buff)\n"
470 "{\n"
471 "\tint\tresult = 1;\n"
472 "\tchar\t*token;\n"
1273d501 473 "\tdebug(0,10)(\"parse_line: %%s\\n\", buff);\n"
7b3942d3 474 "\tif ((token = strtok(buff, w_space)) == NULL)\n"
475 "\t\t(void) 0;\t/* ignore empty lines */\n"
934b03fc 476 );
477
478 for (entry = head; entry != NULL; entry = entry->next) {
0f74202c 479 if (strcmp(entry->name, "comment") == 0)
480 continue;
7b3942d3 481 if (entry->ifdef)
482 fprintf(fp, "#if %s\n", entry->ifdef);
483 fprintf(fp, "\telse if (!strcmp(token, \"%s\"))\n",
934b03fc 484 entry->name
485 );
f1dc9b30 486 assert(entry->loc);
487 if (strcmp(entry->loc, "none") == 0) {
934b03fc 488 fprintf(fp,
489 "\t\tparse_%s();\n",
490 entry->type
491 );
0f74202c 492 } else {
934b03fc 493 fprintf(fp,
b3de4c9b 494 "\t\tparse_%s(&%s%s);\n",
495 entry->type, entry->loc,
496 entry->array_flag ? "[0]" : ""
934b03fc 497 );
498 }
1df370e3 499 if (entry->ifdef)
500 fprintf(fp, "#endif\n");
934b03fc 501 }
502
503 fprintf(fp,
7b3942d3 504 "\telse\n"
934b03fc 505 "\t\tresult = 0; /* failure */\n"
934b03fc 506 "\treturn(result);\n"
507 "}\n\n"
508 );
509}
510
511static void
512gen_dump(Entry * head, FILE * fp)
513{
514 Entry *entry;
934b03fc 515 fprintf(fp,
5e29a294 516 "static void\n"
f53b06f9 517 "dump_config(StoreEntry *entry)\n"
934b03fc 518 "{\n"
519 );
934b03fc 520 for (entry = head; entry != NULL; entry = entry->next) {
f1dc9b30 521 assert(entry->loc);
522 if (strcmp(entry->loc, "none") == 0)
523 continue;
0f74202c 524 if (strcmp(entry->name, "comment") == 0)
3a278cb8 525 continue;
1df370e3 526 if (entry->ifdef)
75339a46 527 fprintf(fp, "#if %s\n", entry->ifdef);
f53b06f9 528 fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n",
a7d59104 529 entry->type,
530 entry->name,
531 entry->loc);
1df370e3 532 if (entry->ifdef)
533 fprintf(fp, "#endif\n");
934b03fc 534 }
535 fprintf(fp, "}\n\n");
536}
537
0153d498 538static void
539gen_free(Entry * head, FILE * fp)
540{
541 Entry *entry;
542 fprintf(fp,
d9586c3c 543 "static void\n"
0153d498 544 "free_all(void)\n"
545 "{\n"
546 );
547 for (entry = head; entry != NULL; entry = entry->next) {
f1dc9b30 548 assert(entry->loc);
549 if (strcmp(entry->loc, "none") == 0)
550 continue;
0f74202c 551 if (strcmp(entry->name, "comment") == 0)
3a278cb8 552 continue;
1df370e3 553 if (entry->ifdef)
75339a46 554 fprintf(fp, "#if %s\n", entry->ifdef);
b3de4c9b 555 fprintf(fp, "\tfree_%s(&%s%s);\n",
556 entry->type, entry->loc,
557 entry->array_flag ? "[0]" : "");
1df370e3 558 if (entry->ifdef)
559 fprintf(fp, "#endif\n");
0153d498 560 }
561 fprintf(fp, "}\n\n");
562}
563
a4b8110e 564static int
565defined(char *name)
6b53c392 566{
a4b8110e 567 int i = 0;
568 if (!name)
569 return 1;
570 for (i = 0; strcmp(defines[i].name, name) != 0; i++) {
571 assert(defines[i].name);
572 }
573 return defines[i].defined;
6b53c392 574}
575
a4b8110e 576static const char *
577available_if(char *name)
6b53c392 578{
a4b8110e 579 int i = 0;
580 assert(name);
581 for (i = 0; strcmp(defines[i].name, name) != 0; i++) {
582 assert(defines[i].name);
583 }
584 return defines[i].enable;
6b53c392 585}
586
934b03fc 587static void
588gen_conf(Entry * head, FILE * fp)
589{
590 Entry *entry;
6b53c392 591 char buf[8192];
592 Line *def = NULL;
934b03fc 593
594 for (entry = head; entry != NULL; entry = entry->next) {
595 Line *line;
6b53c392 596 int blank = 1;
934b03fc 597
c68e9c6b 598 if (!strcmp(entry->name, "comment"))
599 (void) 0;
600 else
ea3a2a69 601 fprintf(fp, "# TAG: %s", entry->name);
934b03fc 602 if (entry->comment)
9906e724 603 fprintf(fp, "\t%s", entry->comment);
934b03fc 604 fprintf(fp, "\n");
6b53c392 605 if (!defined(entry->ifdef)) {
606 fprintf(fp, "# Note: This option is only available if Squid is rebuilt with the\n");
607 fprintf(fp, "# %s option\n#\n", available_if(entry->ifdef));
608 }
934b03fc 609 for (line = entry->doc; line != NULL; line = line->next) {
610 fprintf(fp, "#%s\n", line->data);
611 }
a4b8110e 612 if (entry->default_value && strcmp(entry->default_value, "none") != 0) {
6b53c392 613 sprintf(buf, "%s %s", entry->name, entry->default_value);
614 lineAdd(&def, buf);
615 }
616 if (entry->default_if_none) {
617 for (line = entry->default_if_none; line; line = line->next) {
618 sprintf(buf, "%s %s", entry->name, line->data);
619 lineAdd(&def, buf);
620 }
621 }
622 if (entry->nocomment)
623 blank = 0;
624 if (!def && entry->doc && !entry->nocomment &&
a4b8110e 625 strcmp(entry->name, "comment") != 0)
6b53c392 626 lineAdd(&def, "none");
627 if (def && (entry->doc || entry->nocomment)) {
628 if (blank)
629 fprintf(fp, "#\n");
630 fprintf(fp, "#Default:\n");
631 while (def != NULL) {
632 line = def;
633 def = line->next;
634 fprintf(fp, "# %s\n", line->data);
8eb042dc 635 xfree(line->data);
636 xfree(line);
6b53c392 637 }
a4b8110e 638 blank = 1;
6b53c392 639 }
640 if (entry->nocomment && blank)
641 fprintf(fp, "#\n");
c68e9c6b 642 for (line = entry->nocomment; line != NULL; line = line->next) {
643 fprintf(fp, "%s\n", line->data);
644 }
934b03fc 645 if (entry->doc != NULL) {
646 fprintf(fp, "\n");
647 }
648 }
649}