]>
Commit | Line | Data |
---|---|---|
934b03fc | 1 | /* |
0f74202c | 2 | * $Id: cf_gen.cc,v 1.14 1997/11/04 23:21:12 wessels Exp $ |
934b03fc | 3 | * |
4 | * DEBUG: section 1 Startup and Main Loop | |
5 | * AUTHOR: Max Okumoto | |
6 | * | |
7 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
8 | * -------------------------------------------------------- | |
9 | * | |
10 | * Squid is the result of efforts by numerous individuals from the | |
11 | * Internet community. Development is led by Duane Wessels of the | |
12 | * National Laboratory for Applied Network Research and funded by | |
13 | * the National Science Foundation. | |
14 | * | |
15 | * This program is free software; you can redistribute it and/or modify | |
16 | * it under the terms of the GNU General Public License as published by | |
17 | * the Free Software Foundation; either version 2 of the License, or | |
18 | * (at your option) any later version. | |
19 | * | |
20 | * This program is distributed in the hope that it will be useful, | |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
23 | * GNU General Public License for more details. | |
24 | * | |
25 | * You should have received a copy of the GNU General Public License | |
26 | * along with this program; if not, write to the Free Software | |
27 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
28 | * | |
29 | */ | |
30 | ||
31 | /***************************************************************************** | |
32 | * Abstract: This program parses the input file and generates code and | |
33 | * files used to configure the variables in squid. | |
3a278cb8 | 34 | * (ie it creates the squid.conf file from the cf.data file) |
934b03fc | 35 | * |
36 | * The output files are as follows: | |
37 | * cf_parser.c - this file contains, default_all() which | |
f53b06f9 | 38 | * initializes variables with the default |
39 | * values, parse_line() that parses line from | |
40 | * squid.conf, dump_config that dumps the | |
934b03fc | 41 | * current the values of the variables. |
42 | * squid.conf - default configuration file given to the server | |
43 | * administrator. | |
44 | *****************************************************************************/ | |
45 | ||
46 | #include <stdio.h> | |
47 | #include <string.h> | |
48 | #include <stdlib.h> | |
49 | #include <ctype.h> | |
50 | #include <assert.h> | |
51 | ||
52 | #define MAX_LINE 1024 /* longest configuration line */ | |
53 | #define _PATH_PARSER "cf_parser.c" | |
54 | #define _PATH_SQUID_CONF "squid.conf" | |
55 | ||
56 | enum State { | |
57 | sSTART, | |
58 | s1, | |
59 | sDOC, | |
60 | sEXIT | |
61 | }; | |
62 | ||
63 | typedef struct Line { | |
64 | char *data; | |
65 | struct Line *next; | |
66 | } Line; | |
67 | ||
68 | typedef struct Entry { | |
69 | char *name; | |
70 | char *type; | |
71 | char *loc; | |
72 | char *default_value; | |
f53b06f9 | 73 | char *default_if_none; |
934b03fc | 74 | char *comment; |
75 | Line *doc; | |
76 | struct Entry *next; | |
77 | } Entry; | |
78 | ||
79 | ||
80 | static const char WS[] = " \t"; | |
9906e724 | 81 | static const char NS[] = ""; |
f1dc9b30 | 82 | static int gen_default(Entry *, FILE *); |
934b03fc | 83 | static void gen_parse(Entry *, FILE *); |
84 | static void gen_dump(Entry *, FILE *); | |
0153d498 | 85 | static void gen_free(Entry *, FILE *); |
934b03fc | 86 | static void gen_conf(Entry *, FILE *); |
f53b06f9 | 87 | static void gen_default_if_none(Entry *, FILE *); |
934b03fc | 88 | |
89 | int | |
90 | main(int argc, char *argv[]) | |
91 | { | |
92 | FILE *fp; | |
93 | char *input_filename = argv[1]; | |
94 | char *output_filename = _PATH_PARSER; | |
95 | char *conf_filename = _PATH_SQUID_CONF; | |
96 | int linenum = 0; | |
97 | Entry *entries = NULL; | |
98 | Entry *curr = NULL; | |
99 | enum State state; | |
f1dc9b30 | 100 | int rc = 0; |
9906e724 | 101 | char *ptr = NULL; |
934b03fc | 102 | |
103 | /*-------------------------------------------------------------------* | |
104 | * Parse input file | |
105 | *-------------------------------------------------------------------*/ | |
106 | ||
107 | /* Open input file */ | |
108 | if ((fp = fopen(input_filename, "r")) == NULL) { | |
109 | perror(input_filename); | |
110 | exit(1); | |
111 | } | |
112 | state = sSTART; | |
113 | while (feof(fp) == 0 && state != sEXIT) { | |
114 | char buff[MAX_LINE]; | |
115 | ||
116 | fgets(buff, MAX_LINE, fp); | |
117 | linenum++; | |
118 | *(strchr(buff, '\n')) = '\0'; | |
119 | switch (state) { | |
120 | case sSTART: | |
121 | if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { | |
122 | /* ignore empty and comment lines */ | |
934b03fc | 123 | } else if (!strncmp(buff, "NAME:", 5)) { |
124 | char *name; | |
934b03fc | 125 | if ((name = strtok(buff + 5, WS)) == NULL) { |
126 | printf("Error in input file\n"); | |
127 | exit(1); | |
128 | } | |
14a31364 | 129 | curr = calloc(1, sizeof(Entry)); |
934b03fc | 130 | curr->name = strdup(name); |
934b03fc | 131 | state = s1; |
934b03fc | 132 | } else if (!strcmp(buff, "EOF")) { |
133 | state = sEXIT; | |
0f74202c | 134 | } else if (!strcmp(buff, "COMMENT_START")) { |
135 | curr = calloc(1, sizeof(Entry)); | |
136 | curr->name = strdup("comment"); | |
137 | curr->loc = strdup("none"); | |
138 | state = sDOC; | |
934b03fc | 139 | } else { |
140 | printf("Error on line %d\n", linenum); | |
141 | exit(1); | |
142 | } | |
143 | break; | |
144 | ||
145 | case s1: | |
146 | if ((strlen(buff) == 0) || (!strncmp(buff, "#", 1))) { | |
147 | /* ignore empty and comment lines */ | |
934b03fc | 148 | } else if (!strncmp(buff, "COMMENT:", 8)) { |
9906e724 | 149 | ptr = buff + 8; |
150 | while (isspace(*ptr)) | |
151 | ptr++; | |
934b03fc | 152 | curr->comment = strdup(ptr); |
153 | } else if (!strncmp(buff, "DEFAULT:", 8)) { | |
9906e724 | 154 | ptr = buff + 8; |
155 | while (isspace(*ptr)) | |
156 | ptr++; | |
934b03fc | 157 | curr->default_value = strdup(ptr); |
f53b06f9 | 158 | } else if (!strncmp(buff, "DEFAULT_IF_NONE:", 16)) { |
159 | ptr = buff + 16; | |
160 | while (isspace(*ptr)) | |
161 | ptr++; | |
162 | curr->default_if_none = strdup(ptr); | |
934b03fc | 163 | } else if (!strncmp(buff, "LOC:", 4)) { |
934b03fc | 164 | if ((ptr = strtok(buff + 4, WS)) == NULL) { |
165 | printf("Error on line %d\n", linenum); | |
166 | exit(1); | |
167 | } | |
168 | curr->loc = strdup(ptr); | |
934b03fc | 169 | } else if (!strncmp(buff, "TYPE:", 5)) { |
934b03fc | 170 | if ((ptr = strtok(buff + 5, WS)) == NULL) { |
171 | printf("Error on line %d\n", linenum); | |
172 | exit(1); | |
173 | } | |
174 | curr->type = strdup(ptr); | |
934b03fc | 175 | } else if (!strcmp(buff, "DOC_START")) { |
176 | state = sDOC; | |
934b03fc | 177 | } else if (!strcmp(buff, "DOC_NONE")) { |
178 | /* add to list of entries */ | |
179 | curr->next = entries; | |
180 | entries = curr; | |
934b03fc | 181 | state = sSTART; |
934b03fc | 182 | } else { |
183 | printf("Error on line %d\n", linenum); | |
184 | exit(1); | |
185 | } | |
186 | break; | |
187 | ||
188 | case sDOC: | |
0f74202c | 189 | if (!strcmp(buff, "DOC_END") || !strcmp(buff, "COMMENT_END")) { |
934b03fc | 190 | Line *head = NULL; |
191 | Line *line = curr->doc; | |
934b03fc | 192 | /* reverse order of doc lines */ |
193 | while (line != NULL) { | |
194 | Line *tmp; | |
195 | tmp = line->next; | |
196 | line->next = head; | |
197 | head = line; | |
198 | line = tmp; | |
199 | } | |
200 | curr->doc = head; | |
934b03fc | 201 | /* add to list of entries */ |
202 | curr->next = entries; | |
203 | entries = curr; | |
934b03fc | 204 | state = sSTART; |
205 | } else { | |
14a31364 | 206 | Line *line = calloc(1, sizeof(Line)); |
934b03fc | 207 | line->data = strdup(buff); |
208 | line->next = curr->doc; | |
209 | curr->doc = line; | |
210 | } | |
211 | break; | |
212 | ||
213 | case sEXIT: | |
214 | assert(0); /* should never get here */ | |
215 | break; | |
216 | } | |
217 | } | |
218 | if (state != sEXIT) { | |
219 | printf("Error unexpected EOF\n"); | |
220 | exit(1); | |
221 | } else { | |
222 | /* reverse order of entries */ | |
223 | Entry *head = NULL; | |
224 | ||
225 | while (entries != NULL) { | |
226 | Entry *tmp; | |
227 | ||
228 | tmp = entries->next; | |
229 | entries->next = head; | |
230 | head = entries; | |
231 | entries = tmp; | |
232 | } | |
233 | entries = head; | |
234 | } | |
235 | fclose(fp); | |
236 | ||
237 | /*-------------------------------------------------------------------* | |
238 | * Generate default_all() | |
239 | * Generate parse_line() | |
f53b06f9 | 240 | * Generate dump_config() |
0153d498 | 241 | * Generate free_all() |
934b03fc | 242 | * Generate example squid.conf file |
243 | *-------------------------------------------------------------------*/ | |
244 | ||
245 | /* Open output x.c file */ | |
246 | if ((fp = fopen(output_filename, "w")) == NULL) { | |
247 | perror(output_filename); | |
248 | exit(1); | |
249 | } | |
250 | fprintf(fp, | |
251 | "/*\n" | |
252 | " * Generated automatically from %s by %s\n" | |
253 | " *\n" | |
254 | " * Abstract: This file contains routines used to configure the\n" | |
255 | " * variables in the squid server.\n" | |
256 | " */\n" | |
257 | "\n", | |
258 | input_filename, argv[0] | |
259 | ); | |
f1dc9b30 | 260 | rc = gen_default(entries, fp); |
f53b06f9 | 261 | gen_default_if_none(entries, fp); |
934b03fc | 262 | gen_parse(entries, fp); |
263 | gen_dump(entries, fp); | |
0153d498 | 264 | gen_free(entries, fp); |
934b03fc | 265 | fclose(fp); |
266 | ||
267 | /* Open output x.conf file */ | |
268 | if ((fp = fopen(conf_filename, "w")) == NULL) { | |
269 | perror(conf_filename); | |
270 | exit(1); | |
271 | } | |
272 | gen_conf(entries, fp); | |
273 | fclose(fp); | |
274 | ||
f1dc9b30 | 275 | return (rc); |
934b03fc | 276 | } |
277 | ||
f1dc9b30 | 278 | static int |
934b03fc | 279 | gen_default(Entry * head, FILE * fp) |
280 | { | |
281 | Entry *entry; | |
f1dc9b30 | 282 | int rc = 0; |
b556b1e9 | 283 | fprintf(fp, |
d9586c3c | 284 | "static void\n" |
b556b1e9 | 285 | "default_line(const char *s)\n" |
286 | "{\n" | |
287 | "\tLOCAL_ARRAY(char, tmp_line, BUFSIZ);\n" | |
9906e724 | 288 | "\txstrncpy(tmp_line, s, BUFSIZ);\n" |
289 | "\txstrncpy(config_input_line, s, BUFSIZ);\n" | |
b556b1e9 | 290 | "\tconfig_lineno++;\n" |
9906e724 | 291 | "\tparse_line(tmp_line);\n" |
b556b1e9 | 292 | "}\n" |
293 | ); | |
934b03fc | 294 | fprintf(fp, |
d9586c3c | 295 | "static void\n" |
934b03fc | 296 | "default_all(void)\n" |
297 | "{\n" | |
1273d501 | 298 | "\tcfg_filename = \"Default Configuration\";\n" |
b556b1e9 | 299 | "\tconfig_lineno = 0;\n" |
934b03fc | 300 | ); |
301 | for (entry = head; entry != NULL; entry = entry->next) { | |
302 | assert(entry->name); | |
3a278cb8 | 303 | |
0f74202c | 304 | if (!strcmp(entry->name, "comment")) |
3a278cb8 | 305 | continue; |
934b03fc | 306 | if (entry->loc == NULL) { |
307 | fprintf(stderr, "NO LOCATION FOR %s\n", entry->name); | |
f1dc9b30 | 308 | rc |= 1; |
934b03fc | 309 | continue; |
310 | } | |
311 | if (entry->default_value == NULL) { | |
312 | fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); | |
f1dc9b30 | 313 | rc |= 1; |
934b03fc | 314 | continue; |
315 | } | |
f1dc9b30 | 316 | assert(entry->default_value); |
317 | if (strcmp(entry->default_value, "none") == 0) { | |
318 | fprintf(fp, "\t/* No default for %s */\n", entry->name); | |
934b03fc | 319 | } else { |
b556b1e9 | 320 | fprintf(fp, "\tdefault_line(\"%s %s\");\n", |
934b03fc | 321 | entry->name, |
322 | entry->default_value); | |
f1dc9b30 | 323 | } |
934b03fc | 324 | } |
1273d501 | 325 | fprintf(fp, "\tcfg_filename = NULL;\n"); |
934b03fc | 326 | fprintf(fp, "}\n\n"); |
f1dc9b30 | 327 | return rc; |
934b03fc | 328 | } |
329 | ||
f53b06f9 | 330 | static void |
331 | gen_default_if_none(Entry * head, FILE * fp) | |
332 | { | |
333 | Entry *entry; | |
334 | fprintf(fp, | |
d9586c3c | 335 | "static void\n" |
f53b06f9 | 336 | "defaults_if_none(void)\n" |
337 | "{\n" | |
338 | ); | |
339 | for (entry = head; entry != NULL; entry = entry->next) { | |
340 | assert(entry->name); | |
341 | assert(entry->loc); | |
342 | if (entry->default_if_none == NULL) | |
343 | continue; | |
344 | fprintf(fp, | |
345 | "\tif (check_null_%s(%s))\n" | |
346 | "\t\tdefault_line(\"%s %s\");\n", | |
347 | entry->type, | |
348 | entry->loc, | |
349 | entry->name, | |
350 | entry->default_if_none); | |
351 | } | |
352 | fprintf(fp, "}\n\n"); | |
353 | } | |
354 | ||
934b03fc | 355 | static void |
356 | gen_parse(Entry * head, FILE * fp) | |
357 | { | |
358 | Entry *entry; | |
359 | ||
360 | fprintf(fp, | |
f8c4d483 | 361 | "static int\n" |
934b03fc | 362 | "parse_line(char *buff)\n" |
363 | "{\n" | |
364 | "\tint\tresult = 1;\n" | |
365 | "\tchar\t*token;\n" | |
1273d501 | 366 | "\tdebug(0,10)(\"parse_line: %%s\\n\", buff);\n" |
934b03fc | 367 | "\tif ((token = strtok(buff, w_space)) == NULL) {\n" |
368 | "\t\t/* ignore empty lines */\n" | |
369 | ); | |
370 | ||
371 | for (entry = head; entry != NULL; entry = entry->next) { | |
0f74202c | 372 | if (strcmp(entry->name, "comment") == 0) |
373 | continue; | |
934b03fc | 374 | fprintf(fp, |
375 | "\t} else if (!strcmp(token, \"%s\")) {\n", | |
376 | entry->name | |
377 | ); | |
f1dc9b30 | 378 | assert(entry->loc); |
379 | if (strcmp(entry->loc, "none") == 0) { | |
934b03fc | 380 | fprintf(fp, |
381 | "\t\tparse_%s();\n", | |
382 | entry->type | |
383 | ); | |
0f74202c | 384 | } else { |
934b03fc | 385 | fprintf(fp, |
386 | "\t\tparse_%s(&%s);\n", | |
387 | entry->type, entry->loc | |
388 | ); | |
389 | } | |
390 | } | |
391 | ||
392 | fprintf(fp, | |
393 | "\t} else {\n" | |
394 | "\t\tresult = 0; /* failure */\n" | |
395 | "\t}\n" | |
396 | "\treturn(result);\n" | |
397 | "}\n\n" | |
398 | ); | |
399 | } | |
400 | ||
401 | static void | |
402 | gen_dump(Entry * head, FILE * fp) | |
403 | { | |
404 | Entry *entry; | |
934b03fc | 405 | fprintf(fp, |
f8c4d483 | 406 | "void\n" |
f53b06f9 | 407 | "dump_config(StoreEntry *entry)\n" |
934b03fc | 408 | "{\n" |
409 | ); | |
934b03fc | 410 | for (entry = head; entry != NULL; entry = entry->next) { |
f1dc9b30 | 411 | assert(entry->loc); |
412 | if (strcmp(entry->loc, "none") == 0) | |
413 | continue; | |
0f74202c | 414 | if (strcmp(entry->name, "comment") == 0) |
3a278cb8 | 415 | continue; |
f53b06f9 | 416 | fprintf(fp, "\tdump_%s(entry, \"%s\", %s);\n", |
a7d59104 | 417 | entry->type, |
418 | entry->name, | |
419 | entry->loc); | |
934b03fc | 420 | } |
421 | fprintf(fp, "}\n\n"); | |
422 | } | |
423 | ||
0153d498 | 424 | static void |
425 | gen_free(Entry * head, FILE * fp) | |
426 | { | |
427 | Entry *entry; | |
428 | fprintf(fp, | |
d9586c3c | 429 | "static void\n" |
0153d498 | 430 | "free_all(void)\n" |
431 | "{\n" | |
432 | ); | |
433 | for (entry = head; entry != NULL; entry = entry->next) { | |
f1dc9b30 | 434 | assert(entry->loc); |
435 | if (strcmp(entry->loc, "none") == 0) | |
436 | continue; | |
0f74202c | 437 | if (strcmp(entry->name, "comment") == 0) |
3a278cb8 | 438 | continue; |
f1dc9b30 | 439 | fprintf(fp, "\tfree_%s(&%s);\n", entry->type, entry->loc); |
0153d498 | 440 | } |
441 | fprintf(fp, "}\n\n"); | |
442 | } | |
443 | ||
934b03fc | 444 | static void |
445 | gen_conf(Entry * head, FILE * fp) | |
446 | { | |
447 | Entry *entry; | |
448 | ||
449 | for (entry = head; entry != NULL; entry = entry->next) { | |
450 | Line *line; | |
451 | ||
0f74202c | 452 | if (strcmp(entry->name, "comment")) |
ea3a2a69 | 453 | fprintf(fp, "# TAG: %s", entry->name); |
934b03fc | 454 | if (entry->comment) |
9906e724 | 455 | fprintf(fp, "\t%s", entry->comment); |
934b03fc | 456 | fprintf(fp, "\n"); |
457 | for (line = entry->doc; line != NULL; line = line->next) { | |
458 | fprintf(fp, "#%s\n", line->data); | |
459 | } | |
460 | if (entry->doc != NULL) { | |
461 | fprintf(fp, "\n"); | |
462 | } | |
463 | } | |
464 | } |