1 /* Driver template for the LEMON parser generator.
2 ** The author disclaims copyright to this source code.
3 */
4 /* First off, code is include which follows the "include" declaration
5 ** in the input file. */
6 #include <stdio.h>
7 #line 5 "./configparser.y"
8
9 #include "configfile.h"
10 #include "buffer.h"
11 #include "array.h"
12
13 #include <assert.h>
14 #include <stdio.h>
15 #include <string.h>
16
configparser_push(config_t * ctx,data_config * dc,int isnew)17 static void configparser_push(config_t *ctx, data_config *dc, int isnew) {
18 if (isnew) {
19 dc->context_ndx = ctx->all_configs->used;
20 assert(dc->context_ndx > ctx->current->context_ndx);
21 array_insert_unique(ctx->all_configs, (data_unset *)dc);
22 dc->parent = ctx->current;
23 array_insert_unique(dc->parent->childs, (data_unset *)dc);
24 }
25 if (ctx->configs_stack->used > 0 && ctx->current->context_ndx == 0) {
26 fprintf(stderr, "Cannot use conditionals inside a global { ... } block\n");
27 exit(-1);
28 }
29 array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
30 ctx->current = dc;
31 }
32
configparser_pop(config_t * ctx)33 static data_config *configparser_pop(config_t *ctx) {
34 data_config *old = ctx->current;
35 ctx->current = (data_config *) array_pop(ctx->configs_stack);
36 return old;
37 }
38
39 /* return a copied variable */
configparser_get_variable(config_t * ctx,const buffer * key)40 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
41 data_unset *du;
42 data_config *dc;
43
44 #if 0
45 fprintf(stderr, "get var %s\n", key->ptr);
46 #endif
47 for (dc = ctx->current; dc; dc = dc->parent) {
48 #if 0
49 fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
50 array_print(dc->value, 0);
51 #endif
52 if (NULL != (du = array_get_element(dc->value, key->ptr))) {
53 return du->copy(du);
54 }
55 }
56 return NULL;
57 }
58
59 /* op1 is to be eat/return by this function if success, op1->key is not cared
60 op2 is left untouch, unreferenced
61 */
configparser_merge_data(data_unset * op1,const data_unset * op2)62 data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
63 /* type mismatch */
64 if (op1->type != op2->type) {
65 if (op1->type == TYPE_STRING && op2->type == TYPE_INTEGER) {
66 data_string *ds = (data_string *)op1;
67 buffer_append_long(ds->value, ((data_integer*)op2)->value);
68 return op1;
69 } else if (op1->type == TYPE_INTEGER && op2->type == TYPE_STRING) {
70 data_string *ds = data_string_init();
71 buffer_append_long(ds->value, ((data_integer*)op1)->value);
72 buffer_append_string_buffer(ds->value, ((data_string*)op2)->value);
73 op1->free(op1);
74 return (data_unset *)ds;
75 } else {
76 fprintf(stderr, "data type mismatch, cannot merge\n");
77 return NULL;
78 }
79 }
80
81 switch (op1->type) {
82 case TYPE_STRING:
83 buffer_append_string_buffer(((data_string *)op1)->value, ((data_string *)op2)->value);
84 break;
85 case TYPE_INTEGER:
86 ((data_integer *)op1)->value += ((data_integer *)op2)->value;
87 break;
88 case TYPE_ARRAY: {
89 array *dst = ((data_array *)op1)->value;
90 array *src = ((data_array *)op2)->value;
91 data_unset *du;
92 size_t i;
93
94 for (i = 0; i < src->used; i ++) {
95 du = (data_unset *)src->data[i];
96 if (du) {
97 array_insert_unique(dst, du->copy(du));
98 }
99 }
100 break;
101 default:
102 assert(0);
103 break;
104 }
105 }
106 return op1;
107 }
108
109
110 #line 111 "configparser.c"
111 /* Next is all token values, in a form suitable for use by makeheaders.
112 ** This section will be null unless lemon is run with the -m switch.
113 */
114 /*
115 ** These constants (all generated automatically by the parser generator)
116 ** specify the various kinds of tokens (terminals) that the parser
117 ** understands.
118 **
119 ** Each symbol here is a terminal symbol in the grammar.
120 */
121 /* Make sure the INTERFACE macro is defined.
122 */
123 #ifndef INTERFACE
124 # define INTERFACE 1
125 #endif
126 /* The next thing included is series of defines which control
127 ** various aspects of the generated parser.
128 ** YYCODETYPE is the data type used for storing terminal
129 ** and nonterminal numbers. "unsigned char" is
130 ** used if there are fewer than 250 terminals
131 ** and nonterminals. "int" is used otherwise.
132 ** YYNOCODE is a number of type YYCODETYPE which corresponds
133 ** to no legal terminal or nonterminal number. This
134 ** number is used to fill in empty slots of the hash
135 ** table.
136 ** YYFALLBACK If defined, this indicates that one or more tokens
137 ** have fall-back values which should be used if the
138 ** original value of the token will not parse.
139 ** YYACTIONTYPE is the data type used for storing terminal
140 ** and nonterminal numbers. "unsigned char" is
141 ** used if there are fewer than 250 rules and
142 ** states combined. "int" is used otherwise.
143 ** configparserTOKENTYPE is the data type used for minor tokens given
144 ** directly to the parser from the tokenizer.
145 ** YYMINORTYPE is the data type used for all minor tokens.
146 ** This is typically a union of many types, one of
147 ** which is configparserTOKENTYPE. The entry in the union
148 ** for base tokens is called "yy0".
149 ** YYSTACKDEPTH is the maximum depth of the parser's stack.
150 ** configparserARG_SDECL A static variable declaration for the %extra_argument
151 ** configparserARG_PDECL A parameter declaration for the %extra_argument
152 ** configparserARG_STORE Code to store %extra_argument into yypParser
153 ** configparserARG_FETCH Code to extract %extra_argument from yypParser
154 ** YYNSTATE the combined number of states.
155 ** YYNRULE the number of rules in the grammar
156 ** YYERRORSYMBOL is the code number of the error symbol. If not
157 ** defined, then do no error processing.
158 */
159 /* */
160 #define YYCODETYPE unsigned char
161 #define YYNOCODE 48
162 #define YYACTIONTYPE unsigned char
163 #define configparserTOKENTYPE buffer *
164 typedef union {
165 configparserTOKENTYPE yy0;
166 config_cond_t yy27;
167 array * yy40;
168 data_unset * yy41;
169 buffer * yy43;
170 data_config * yy78;
171 int yy95;
172 } YYMINORTYPE;
173 #define YYSTACKDEPTH 100
174 #define configparserARG_SDECL config_t *ctx;
175 #define configparserARG_PDECL ,config_t *ctx
176 #define configparserARG_FETCH config_t *ctx = yypParser->ctx
177 #define configparserARG_STORE yypParser->ctx = ctx
178 #define YYNSTATE 63
179 #define YYNRULE 40
180 #define YYERRORSYMBOL 26
181 #define YYERRSYMDT yy95
182 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
183 #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
184 #define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
185
186 /* Next are that tables used to determine what action to take based on the
187 ** current state and lookahead token. These tables are used to implement
188 ** functions that take a state number and lookahead value and return an
189 ** action integer.
190 **
191 ** Suppose the action integer is N. Then the action is determined as
192 ** follows
193 **
194 ** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
195 ** token onto the stack and goto state N.
196 **
197 ** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
198 **
199 ** N == YYNSTATE+YYNRULE A syntax error has occurred.
200 **
201 ** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
202 **
203 ** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
204 ** slots in the yy_action[] table.
205 **
206 ** The action table is constructed as a single large table named yy_action[].
207 ** Given state S and lookahead X, the action is computed as
208 **
209 ** yy_action[ yy_shift_ofst[S] + X ]
210 **
211 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
212 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
213 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
214 ** and that yy_default[S] should be used instead.
215 **
216 ** The formula above is for computing the action when the lookahead is
217 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
218 ** a reduce action) then the yy_reduce_ofst[] array is used in place of
219 ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
220 ** YY_SHIFT_USE_DFLT.
221 **
222 ** The following are the tables generated in this section:
223 **
224 ** yy_action[] A single table containing all actions.
225 ** yy_lookahead[] A table containing the lookahead for each entry in
226 ** yy_action. Used to detect hash collisions.
227 ** yy_shift_ofst[] For each state, the offset into yy_action for
228 ** shifting terminals.
229 ** yy_reduce_ofst[] For each state, the offset into yy_action for
230 ** shifting non-terminals after a reduce.
231 ** yy_default[] Default action for each state.
232 */
233 static YYACTIONTYPE yy_action[] = {
234 /* 0 */ 2, 3, 4, 5, 13, 14, 63, 15, 7, 45,
235 /* 10 */ 20, 88, 16, 46, 28, 49, 41, 10, 40, 25,
236 /* 20 */ 22, 50, 46, 8, 15, 104, 1, 20, 28, 18,
237 /* 30 */ 58, 60, 6, 25, 22, 40, 47, 62, 11, 46,
238 /* 40 */ 20, 9, 23, 24, 26, 29, 89, 58, 60, 10,
239 /* 50 */ 17, 38, 28, 27, 37, 19, 30, 25, 22, 34,
240 /* 60 */ 15, 100, 20, 20, 23, 24, 26, 12, 19, 31,
241 /* 70 */ 32, 40, 19, 44, 43, 46, 95, 35, 90, 89,
242 /* 80 */ 28, 49, 42, 58, 60, 25, 22, 59, 28, 27,
243 /* 90 */ 33, 48, 52, 25, 22, 34, 28, 49, 51, 28,
244 /* 100 */ 36, 25, 22, 61, 25, 22, 89, 28, 39, 89,
245 /* 110 */ 89, 89, 25, 22, 54, 55, 56, 57, 89, 28,
246 /* 120 */ 53, 21, 89, 89, 25, 22, 25, 22,
247 };
248 static YYCODETYPE yy_lookahead[] = {
249 /* 0 */ 29, 30, 31, 32, 33, 34, 0, 1, 44, 38,
250 /* 10 */ 4, 15, 41, 16, 35, 36, 45, 46, 12, 40,
251 /* 20 */ 41, 42, 16, 15, 1, 27, 28, 4, 35, 36,
252 /* 30 */ 24, 25, 1, 40, 41, 12, 17, 14, 13, 16,
253 /* 40 */ 4, 38, 6, 7, 8, 9, 15, 24, 25, 46,
254 /* 50 */ 2, 3, 35, 36, 37, 5, 39, 40, 41, 42,
255 /* 60 */ 1, 11, 4, 4, 6, 7, 8, 28, 5, 9,
256 /* 70 */ 10, 12, 5, 14, 28, 16, 13, 11, 13, 47,
257 /* 80 */ 35, 36, 13, 24, 25, 40, 41, 42, 35, 36,
258 /* 90 */ 37, 18, 43, 40, 41, 42, 35, 36, 19, 35,
259 /* 100 */ 36, 40, 41, 42, 40, 41, 47, 35, 36, 47,
260 /* 110 */ 47, 47, 40, 41, 20, 21, 22, 23, 47, 35,
261 /* 120 */ 36, 35, 47, 47, 40, 41, 40, 41,
262 };
263 #define YY_SHIFT_USE_DFLT (-5)
264 static signed char yy_shift_ofst[] = {
265 /* 0 */ -5, 6, -5, -5, -5, 31, -4, 8, -3, -5,
266 /* 10 */ 25, -5, 23, -5, -5, -5, 48, 58, 67, 58,
267 /* 20 */ -5, -5, -5, -5, -5, -5, 36, 50, -5, -5,
268 /* 30 */ 60, -5, 58, -5, 66, 58, 67, -5, 58, 67,
269 /* 40 */ 65, 69, -5, 59, -5, -5, 19, 73, 58, 67,
270 /* 50 */ 79, 94, 58, 63, -5, -5, -5, -5, 58, -5,
271 /* 60 */ 58, -5, -5,
272 };
273 #define YY_REDUCE_USE_DFLT (-37)
274 static signed char yy_reduce_ofst[] = {
275 /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 3, -37,
276 /* 10 */ -37, 39, -29, -37, -37, -37, -37, -7, -37, 86,
277 /* 20 */ -37, -37, -37, -37, -37, -37, 17, -37, -37, -37,
278 /* 30 */ -37, -37, 53, -37, -37, 64, -37, -37, 72, -37,
279 /* 40 */ -37, -37, 46, -29, -37, -37, -37, -37, -21, -37,
280 /* 50 */ -37, 49, 84, -37, -37, -37, -37, -37, 45, -37,
281 /* 60 */ 61, -37, -37,
282 };
283 static YYACTIONTYPE yy_default[] = {
284 /* 0 */ 65, 103, 64, 66, 67, 103, 68, 103, 103, 92,
285 /* 10 */ 103, 65, 103, 69, 70, 71, 103, 103, 72, 103,
286 /* 20 */ 74, 75, 77, 78, 79, 80, 103, 86, 76, 81,
287 /* 30 */ 103, 82, 84, 83, 103, 103, 87, 85, 103, 73,
288 /* 40 */ 103, 103, 65, 103, 91, 93, 103, 103, 103, 100,
289 /* 50 */ 103, 103, 103, 103, 96, 97, 98, 99, 103, 101,
290 /* 60 */ 103, 102, 94,
291 };
292 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
293
294 /* The next table maps tokens into fallback tokens. If a construct
295 ** like the following:
296 **
297 ** %fallback ID X Y Z.
298 **
299 ** appears in the grammer, then ID becomes a fallback token for X, Y,
300 ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
301 ** but it does not parse, the type of the token is changed to ID and
302 ** the parse is retried before an error is thrown.
303 */
304 #ifdef YYFALLBACK
305 static const YYCODETYPE yyFallback[] = {
306 };
307 #endif /* YYFALLBACK */
308
309 /* The following structure represents a single element of the
310 ** parser's stack. Information stored includes:
311 **
312 ** + The state number for the parser at this level of the stack.
313 **
314 ** + The value of the token stored at this level of the stack.
315 ** (In other words, the "major" token.)
316 **
317 ** + The semantic value stored at this level of the stack. This is
318 ** the information used by the action routines in the grammar.
319 ** It is sometimes called the "minor" token.
320 */
321 struct yyStackEntry {
322 int stateno; /* The state-number */
323 int major; /* The major token value. This is the code
324 ** number for the token at this stack level */
325 YYMINORTYPE minor; /* The user-supplied minor token value. This
326 ** is the value of the token */
327 };
328 typedef struct yyStackEntry yyStackEntry;
329
330 /* The state of the parser is completely contained in an instance of
331 ** the following structure */
332 struct yyParser {
333 int yyidx; /* Index of top element in stack */
334 int yyerrcnt; /* Shifts left before out of the error */
335 configparserARG_SDECL /* A place to hold %extra_argument */
336 yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
337 };
338 typedef struct yyParser yyParser;
339
340 #ifndef NDEBUG
341 #include <stdio.h>
342 static FILE *yyTraceFILE = NULL;
343 static char *yyTracePrompt = NULL;
344 #endif /* NDEBUG */
345
346 #ifndef NDEBUG
347 /*
348 ** Turn parser tracing on by giving a stream to which to write the trace
349 ** and a prompt to preface each trace message. Tracing is turned off
350 ** by making either argument NULL
351 **
352 ** Inputs:
353 ** <ul>
354 ** <li> A FILE* to which trace output should be written.
355 ** If NULL, then tracing is turned off.
356 ** <li> A prefix string written at the beginning of every
357 ** line of trace output. If NULL, then tracing is
358 ** turned off.
359 ** </ul>
360 **
361 ** Outputs:
362 ** None.
363 */
364 #if 0
365 void configparserTrace(FILE *TraceFILE, char *zTracePrompt){
366 yyTraceFILE = TraceFILE;
367 yyTracePrompt = zTracePrompt;
368 if( yyTraceFILE==0 ) yyTracePrompt = 0;
369 else if( yyTracePrompt==0 ) yyTraceFILE = 0;
370 }
371 #endif
372 #endif /* NDEBUG */
373
374 #ifndef NDEBUG
375 /* For tracing shifts, the names of all terminals and nonterminals
376 ** are required. The following table supplies these names */
377 static const char *yyTokenName[] = {
378 "$", "EOL", "ASSIGN", "APPEND",
379 "LKEY", "PLUS", "STRING", "INTEGER",
380 "LPARAN", "RPARAN", "COMMA", "ARRAY_ASSIGN",
381 "GLOBAL", "LCURLY", "RCURLY", "ELSE",
382 "DOLLAR", "SRVVARNAME", "LBRACKET", "RBRACKET",
383 "EQ", "MATCH", "NE", "NOMATCH",
384 "INCLUDE", "INCLUDE_SHELL", "error", "input",
385 "metalines", "metaline", "varline", "global",
386 "condlines", "include", "include_shell", "value",
387 "expression", "aelement", "condline", "aelements",
388 "array", "key", "stringop", "cond",
389 "eols", "globalstart", "context",
390 };
391 #endif /* NDEBUG */
392
393 #ifndef NDEBUG
394 /* For tracing reduce actions, the names of all rules are required.
395 */
396 static const char *yyRuleName[] = {
397 /* 0 */ "input ::= metalines",
398 /* 1 */ "metalines ::= metalines metaline",
399 /* 2 */ "metalines ::=",
400 /* 3 */ "metaline ::= varline",
401 /* 4 */ "metaline ::= global",
402 /* 5 */ "metaline ::= condlines EOL",
403 /* 6 */ "metaline ::= include",
404 /* 7 */ "metaline ::= include_shell",
405 /* 8 */ "metaline ::= EOL",
406 /* 9 */ "varline ::= key ASSIGN expression",
407 /* 10 */ "varline ::= key APPEND expression",
408 /* 11 */ "key ::= LKEY",
409 /* 12 */ "expression ::= expression PLUS value",
410 /* 13 */ "expression ::= value",
411 /* 14 */ "value ::= key",
412 /* 15 */ "value ::= STRING",
413 /* 16 */ "value ::= INTEGER",
414 /* 17 */ "value ::= array",
415 /* 18 */ "array ::= LPARAN RPARAN",
416 /* 19 */ "array ::= LPARAN aelements RPARAN",
417 /* 20 */ "aelements ::= aelements COMMA aelement",
418 /* 21 */ "aelements ::= aelements COMMA",
419 /* 22 */ "aelements ::= aelement",
420 /* 23 */ "aelement ::= expression",
421 /* 24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
422 /* 25 */ "eols ::= EOL",
423 /* 26 */ "eols ::=",
424 /* 27 */ "globalstart ::= GLOBAL",
425 /* 28 */ "global ::= globalstart LCURLY metalines RCURLY",
426 /* 29 */ "condlines ::= condlines eols ELSE condline",
427 /* 30 */ "condlines ::= condline",
428 /* 31 */ "condline ::= context LCURLY metalines RCURLY",
429 /* 32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
430 /* 33 */ "cond ::= EQ",
431 /* 34 */ "cond ::= MATCH",
432 /* 35 */ "cond ::= NE",
433 /* 36 */ "cond ::= NOMATCH",
434 /* 37 */ "stringop ::= expression",
435 /* 38 */ "include ::= INCLUDE stringop",
436 /* 39 */ "include_shell ::= INCLUDE_SHELL stringop",
437 };
438 #endif /* NDEBUG */
439
440 /*
441 ** This function returns the symbolic name associated with a token
442 ** value.
443 */
444 #if 0
445 const char *configparserTokenName(int tokenType){
446 #ifndef NDEBUG
447 if( tokenType>0 && (size_t)tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
448 return yyTokenName[tokenType];
449 }else{
450 return "Unknown";
451 }
452 #else
453 return "";
454 #endif
455 }
456 #endif
457
458 /*
459 ** This function allocates a new parser.
460 ** The only argument is a pointer to a function which works like
461 ** malloc.
462 **
463 ** Inputs:
464 ** A pointer to the function used to allocate memory.
465 **
466 ** Outputs:
467 ** A pointer to a parser. This pointer is used in subsequent calls
468 ** to configparser and configparserFree.
469 */
configparserAlloc(void * (* mallocProc)(size_t))470 void *configparserAlloc(void *(*mallocProc)(size_t)){
471 yyParser *pParser;
472 pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
473 if( pParser ){
474 pParser->yyidx = -1;
475 }
476 return pParser;
477 }
478
479 /* The following function deletes the value associated with a
480 ** symbol. The symbol can be either a terminal or nonterminal.
481 ** "yymajor" is the symbol code, and "yypminor" is a pointer to
482 ** the value.
483 */
yy_destructor(YYCODETYPE yymajor,YYMINORTYPE * yypminor)484 static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
485 switch( yymajor ){
486 /* Here is inserted the actions which take place when a
487 ** terminal or non-terminal is destroyed. This can happen
488 ** when the symbol is popped from the stack during a
489 ** reduce or during error processing or when a parser is
490 ** being destroyed before it is finished parsing.
491 **
492 ** Note: during a reduce, the only symbols destroyed are those
493 ** which appear on the RHS of the rule, but which are not used
494 ** inside the C code.
495 */
496 case 1:
497 case 2:
498 case 3:
499 case 4:
500 case 5:
501 case 6:
502 case 7:
503 case 8:
504 case 9:
505 case 10:
506 case 11:
507 case 12:
508 case 13:
509 case 14:
510 case 15:
511 case 16:
512 case 17:
513 case 18:
514 case 19:
515 case 20:
516 case 21:
517 case 22:
518 case 23:
519 case 24:
520 case 25:
521 #line 144 "./configparser.y"
522 { buffer_free((yypminor->yy0)); }
523 #line 523 "configparser.c"
524 break;
525 case 35:
526 #line 135 "./configparser.y"
527 { (yypminor->yy41)->free((yypminor->yy41)); }
528 #line 528 "configparser.c"
529 break;
530 case 36:
531 #line 136 "./configparser.y"
532 { (yypminor->yy41)->free((yypminor->yy41)); }
533 #line 533 "configparser.c"
534 break;
535 case 37:
536 #line 137 "./configparser.y"
537 { (yypminor->yy41)->free((yypminor->yy41)); }
538 #line 538 "configparser.c"
539 break;
540 case 39:
541 #line 138 "./configparser.y"
542 { array_free((yypminor->yy40)); }
543 #line 543 "configparser.c"
544 break;
545 case 40:
546 #line 139 "./configparser.y"
547 { array_free((yypminor->yy40)); }
548 #line 548 "configparser.c"
549 break;
550 case 41:
551 #line 140 "./configparser.y"
552 { buffer_free((yypminor->yy43)); }
553 #line 553 "configparser.c"
554 break;
555 case 42:
556 #line 141 "./configparser.y"
557 { buffer_free((yypminor->yy43)); }
558 #line 558 "configparser.c"
559 break;
560 default: break; /* If no destructor action specified: do nothing */
561 }
562 }
563
564 /*
565 ** Pop the parser's stack once.
566 **
567 ** If there is a destructor routine associated with the token which
568 ** is popped from the stack, then call it.
569 **
570 ** Return the major token number for the symbol popped.
571 */
yy_pop_parser_stack(yyParser * pParser)572 static int yy_pop_parser_stack(yyParser *pParser){
573 YYCODETYPE yymajor;
574 yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
575
576 if( pParser->yyidx<0 ) return 0;
577 #ifndef NDEBUG
578 if( yyTraceFILE && pParser->yyidx>=0 ){
579 fprintf(yyTraceFILE,"%sPopping %s\n",
580 yyTracePrompt,
581 yyTokenName[yytos->major]);
582 }
583 #endif
584 yymajor = yytos->major;
585 yy_destructor( yymajor, &yytos->minor);
586 pParser->yyidx--;
587 return yymajor;
588 }
589
590 /*
591 ** Deallocate and destroy a parser. Destructors are all called for
592 ** all stack elements before shutting the parser down.
593 **
594 ** Inputs:
595 ** <ul>
596 ** <li> A pointer to the parser. This should be a pointer
597 ** obtained from configparserAlloc.
598 ** <li> A pointer to a function used to reclaim memory obtained
599 ** from malloc.
600 ** </ul>
601 */
configparserFree(void * p,void (* freeProc)(void *))602 void configparserFree(
603 void *p, /* The parser to be deleted */
604 void (*freeProc)(void*) /* Function used to reclaim memory */
605 ){
606 yyParser *pParser = (yyParser*)p;
607 if( pParser==NULL ) return;
608 while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
609 (*freeProc)((void*)pParser);
610 }
611
612 /*
613 ** Find the appropriate action for a parser given the terminal
614 ** look-ahead token iLookAhead.
615 **
616 ** If the look-ahead token is YYNOCODE, then check to see if the action is
617 ** independent of the look-ahead. If it is, return the action, otherwise
618 ** return YY_NO_ACTION.
619 */
yy_find_shift_action(yyParser * pParser,int iLookAhead)620 static int yy_find_shift_action(
621 yyParser *pParser, /* The parser */
622 int iLookAhead /* The look-ahead token */
623 ){
624 int i;
625 int stateno = pParser->yystack[pParser->yyidx].stateno;
626
627 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
628 i = yy_shift_ofst[stateno];
629 if( i==YY_SHIFT_USE_DFLT ){
630 return yy_default[stateno];
631 }
632 if( iLookAhead==YYNOCODE ){
633 return YY_NO_ACTION;
634 }
635 i += iLookAhead;
636 if( i<0 || (size_t)i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
637 #ifdef YYFALLBACK
638 int iFallback; /* Fallback token */
639 if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
640 && (iFallback = yyFallback[iLookAhead])!=0 ){
641 #ifndef NDEBUG
642 if( yyTraceFILE ){
643 fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
644 yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
645 }
646 #endif
647 return yy_find_shift_action(pParser, iFallback);
648 }
649 #endif
650 return yy_default[stateno];
651 }else{
652 return yy_action[i];
653 }
654 }
655
656 /*
657 ** Find the appropriate action for a parser given the non-terminal
658 ** look-ahead token iLookAhead.
659 **
660 ** If the look-ahead token is YYNOCODE, then check to see if the action is
661 ** independent of the look-ahead. If it is, return the action, otherwise
662 ** return YY_NO_ACTION.
663 */
yy_find_reduce_action(yyParser * pParser,int iLookAhead)664 static int yy_find_reduce_action(
665 yyParser *pParser, /* The parser */
666 int iLookAhead /* The look-ahead token */
667 ){
668 int i;
669 int stateno = pParser->yystack[pParser->yyidx].stateno;
670
671 i = yy_reduce_ofst[stateno];
672 if( i==YY_REDUCE_USE_DFLT ){
673 return yy_default[stateno];
674 }
675 if( iLookAhead==YYNOCODE ){
676 return YY_NO_ACTION;
677 }
678 i += iLookAhead;
679 if( i<0 || (size_t)i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
680 return yy_default[stateno];
681 }else{
682 return yy_action[i];
683 }
684 }
685
686 /*
687 ** Perform a shift action.
688 */
yy_shift(yyParser * yypParser,int yyNewState,int yyMajor,YYMINORTYPE * yypMinor)689 static void yy_shift(
690 yyParser *yypParser, /* The parser to be shifted */
691 int yyNewState, /* The new state to shift in */
692 int yyMajor, /* The major token to shift in */
693 YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
694 ){
695 yyStackEntry *yytos;
696 yypParser->yyidx++;
697 if( yypParser->yyidx>=YYSTACKDEPTH ){
698 configparserARG_FETCH;
699 yypParser->yyidx--;
700 #ifndef NDEBUG
701 if( yyTraceFILE ){
702 fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
703 }
704 #endif
705 while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
706 /* Here code is inserted which will execute if the parser
707 ** stack every overflows */
708 configparserARG_STORE; /* Suppress warning about unused %extra_argument var */
709 return;
710 }
711 yytos = &yypParser->yystack[yypParser->yyidx];
712 yytos->stateno = yyNewState;
713 yytos->major = yyMajor;
714 yytos->minor = *yypMinor;
715 #ifndef NDEBUG
716 if( yyTraceFILE && yypParser->yyidx>0 ){
717 int i;
718 fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
719 fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
720 for(i=1; i<=yypParser->yyidx; i++)
721 fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
722 fprintf(yyTraceFILE,"\n");
723 }
724 #endif
725 }
726
727 /* The following table contains information about every rule that
728 ** is used during the reduce.
729 */
730 static struct {
731 YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
732 unsigned char nrhs; /* Number of right-hand side symbols in the rule */
733 } yyRuleInfo[] = {
734 { 27, 1 },
735 { 28, 2 },
736 { 28, 0 },
737 { 29, 1 },
738 { 29, 1 },
739 { 29, 2 },
740 { 29, 1 },
741 { 29, 1 },
742 { 29, 1 },
743 { 30, 3 },
744 { 30, 3 },
745 { 41, 1 },
746 { 36, 3 },
747 { 36, 1 },
748 { 35, 1 },
749 { 35, 1 },
750 { 35, 1 },
751 { 35, 1 },
752 { 40, 2 },
753 { 40, 3 },
754 { 39, 3 },
755 { 39, 2 },
756 { 39, 1 },
757 { 37, 1 },
758 { 37, 3 },
759 { 44, 1 },
760 { 44, 0 },
761 { 45, 1 },
762 { 31, 4 },
763 { 32, 4 },
764 { 32, 1 },
765 { 38, 4 },
766 { 46, 7 },
767 { 43, 1 },
768 { 43, 1 },
769 { 43, 1 },
770 { 43, 1 },
771 { 42, 1 },
772 { 33, 2 },
773 { 34, 2 },
774 };
775
776 static void yy_accept(yyParser*); /* Forward Declaration */
777
778 /*
779 ** Perform a reduce action and the shift that must immediately
780 ** follow the reduce.
781 */
yy_reduce(yyParser * yypParser,int yyruleno)782 static void yy_reduce(
783 yyParser *yypParser, /* The parser */
784 int yyruleno /* Number of the rule by which to reduce */
785 ){
786 int yygoto; /* The next state */
787 int yyact; /* The next action */
788 YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
789 yyStackEntry *yymsp; /* The top of the parser's stack */
790 int yysize; /* Amount to pop the stack */
791 configparserARG_FETCH;
792 yymsp = &yypParser->yystack[yypParser->yyidx];
793 #ifndef NDEBUG
794 if( yyTraceFILE && yyruleno>=0
795 && (size_t)yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
796 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
797 yyRuleName[yyruleno]);
798 }
799 #endif /* NDEBUG */
800
801 switch( yyruleno ){
802 /* Beginning here are the reduction cases. A typical example
803 ** follows:
804 ** case 0:
805 ** #line <lineno> <grammarfile>
806 ** { ... } // User supplied code
807 ** #line <lineno> <thisfile>
808 ** break;
809 */
810 case 0:
811 /* No destructor defined for metalines */
812 break;
813 case 1:
814 /* No destructor defined for metalines */
815 /* No destructor defined for metaline */
816 break;
817 case 2:
818 break;
819 case 3:
820 /* No destructor defined for varline */
821 break;
822 case 4:
823 /* No destructor defined for global */
824 break;
825 case 5:
826 #line 117 "./configparser.y"
827 { yymsp[-1].minor.yy78 = NULL; }
828 #line 828 "configparser.c"
829 yy_destructor(1,&yymsp[0].minor);
830 break;
831 case 6:
832 /* No destructor defined for include */
833 break;
834 case 7:
835 /* No destructor defined for include_shell */
836 break;
837 case 8:
838 yy_destructor(1,&yymsp[0].minor);
839 break;
840 case 9:
841 #line 146 "./configparser.y"
842 {
843 if (ctx->ok) {
844 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
845 if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
846 fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
847 ctx->current->context_ndx,
848 ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
849 ctx->ok = 0;
850 } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
851 array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
852 yymsp[0].minor.yy41 = NULL;
853 } else {
854 fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
855 ctx->current->context_ndx,
856 ctx->current->key->ptr, yymsp[0].minor.yy41->key->ptr);
857 ctx->ok = 0;
858 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
859 yymsp[0].minor.yy41 = NULL;
860 }
861 }
862 buffer_free(yymsp[-2].minor.yy43);
863 yymsp[-2].minor.yy43 = NULL;
864 }
865 #line 865 "configparser.c"
866 yy_destructor(2,&yymsp[-1].minor);
867 break;
868 case 10:
869 #line 170 "./configparser.y"
870 {
871 array *vars = ctx->current->value;
872 data_unset *du;
873
874 if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
875 fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
876 ctx->current->context_ndx,
877 ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
878 ctx->ok = 0;
879 } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
880 /* exists in current block */
881 du = configparser_merge_data(du, yymsp[0].minor.yy41);
882 if (NULL == du) {
883 ctx->ok = 0;
884 }
885 else {
886 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
887 array_replace(vars, du);
888 }
889 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
890 } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
891 du = configparser_merge_data(du, yymsp[0].minor.yy41);
892 if (NULL == du) {
893 ctx->ok = 0;
894 }
895 else {
896 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
897 array_insert_unique(ctx->current->value, du);
898 }
899 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
900 } else {
901 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
902 array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
903 }
904 buffer_free(yymsp[-2].minor.yy43);
905 yymsp[-2].minor.yy43 = NULL;
906 yymsp[0].minor.yy41 = NULL;
907 }
908 #line 908 "configparser.c"
909 yy_destructor(3,&yymsp[-1].minor);
910 break;
911 case 11:
912 #line 209 "./configparser.y"
913 {
914 if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
915 yygotominor.yy43 = buffer_init_string("var.");
916 buffer_append_string_buffer(yygotominor.yy43, yymsp[0].minor.yy0);
917 buffer_free(yymsp[0].minor.yy0);
918 yymsp[0].minor.yy0 = NULL;
919 } else {
920 yygotominor.yy43 = yymsp[0].minor.yy0;
921 yymsp[0].minor.yy0 = NULL;
922 }
923 }
924 #line 924 "configparser.c"
925 break;
926 case 12:
927 #line 221 "./configparser.y"
928 {
929 yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
930 if (NULL == yygotominor.yy41) {
931 ctx->ok = 0;
932 }
933 yymsp[-2].minor.yy41 = NULL;
934 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
935 yymsp[0].minor.yy41 = NULL;
936 }
937 #line 937 "configparser.c"
938 yy_destructor(5,&yymsp[-1].minor);
939 break;
940 case 13:
941 #line 231 "./configparser.y"
942 {
943 yygotominor.yy41 = yymsp[0].minor.yy41;
944 yymsp[0].minor.yy41 = NULL;
945 }
946 #line 946 "configparser.c"
947 break;
948 case 14:
949 #line 236 "./configparser.y"
950 {
951 yygotominor.yy41 = NULL;
952 if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
953 char *env;
954
955 if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
956 data_string *ds;
957 ds = data_string_init();
958 buffer_append_string(ds->value, env);
959 yygotominor.yy41 = (data_unset *)ds;
960 }
961 else {
962 fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
963 ctx->ok = 0;
964 }
965 } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
966 fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
967 ctx->ok = 0;
968 }
969 if (!yygotominor.yy41) {
970 /* make a dummy so it won't crash */
971 yygotominor.yy41 = (data_unset *)data_string_init();
972 }
973 buffer_free(yymsp[0].minor.yy43);
974 yymsp[0].minor.yy43 = NULL;
975 }
976 #line 976 "configparser.c"
977 break;
978 case 15:
979 #line 263 "./configparser.y"
980 {
981 yygotominor.yy41 = (data_unset *)data_string_init();
982 buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
983 buffer_free(yymsp[0].minor.yy0);
984 yymsp[0].minor.yy0 = NULL;
985 }
986 #line 986 "configparser.c"
987 break;
988 case 16:
989 #line 270 "./configparser.y"
990 {
991 yygotominor.yy41 = (data_unset *)data_integer_init();
992 ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
993 buffer_free(yymsp[0].minor.yy0);
994 yymsp[0].minor.yy0 = NULL;
995 }
996 #line 996 "configparser.c"
997 break;
998 case 17:
999 #line 276 "./configparser.y"
1000 {
1001 yygotominor.yy41 = (data_unset *)data_array_init();
1002 array_free(((data_array *)(yygotominor.yy41))->value);
1003 ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
1004 yymsp[0].minor.yy40 = NULL;
1005 }
1006 #line 1006 "configparser.c"
1007 break;
1008 case 18:
1009 #line 282 "./configparser.y"
1010 {
1011 yygotominor.yy40 = array_init();
1012 }
1013 #line 1013 "configparser.c"
1014 yy_destructor(8,&yymsp[-1].minor);
1015 yy_destructor(9,&yymsp[0].minor);
1016 break;
1017 case 19:
1018 #line 285 "./configparser.y"
1019 {
1020 yygotominor.yy40 = yymsp[-1].minor.yy40;
1021 yymsp[-1].minor.yy40 = NULL;
1022 }
1023 #line 1023 "configparser.c"
1024 yy_destructor(8,&yymsp[-2].minor);
1025 yy_destructor(9,&yymsp[0].minor);
1026 break;
1027 case 20:
1028 #line 290 "./configparser.y"
1029 {
1030 if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
1031 NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
1032 array_insert_unique(yymsp[-2].minor.yy40, yymsp[0].minor.yy41);
1033 yymsp[0].minor.yy41 = NULL;
1034 } else {
1035 fprintf(stderr, "Duplicate array-key: %s\n",
1036 yymsp[0].minor.yy41->key->ptr);
1037 ctx->ok = 0;
1038 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
1039 yymsp[0].minor.yy41 = NULL;
1040 }
1041
1042 yygotominor.yy40 = yymsp[-2].minor.yy40;
1043 yymsp[-2].minor.yy40 = NULL;
1044 }
1045 #line 1045 "configparser.c"
1046 yy_destructor(10,&yymsp[-1].minor);
1047 break;
1048 case 21:
1049 #line 307 "./configparser.y"
1050 {
1051 yygotominor.yy40 = yymsp[-1].minor.yy40;
1052 yymsp[-1].minor.yy40 = NULL;
1053 }
1054 #line 1054 "configparser.c"
1055 yy_destructor(10,&yymsp[0].minor);
1056 break;
1057 case 22:
1058 #line 312 "./configparser.y"
1059 {
1060 yygotominor.yy40 = array_init();
1061 array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
1062 yymsp[0].minor.yy41 = NULL;
1063 }
1064 #line 1064 "configparser.c"
1065 break;
1066 case 23:
1067 #line 318 "./configparser.y"
1068 {
1069 yygotominor.yy41 = yymsp[0].minor.yy41;
1070 yymsp[0].minor.yy41 = NULL;
1071 }
1072 #line 1072 "configparser.c"
1073 break;
1074 case 24:
1075 #line 322 "./configparser.y"
1076 {
1077 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
1078 buffer_free(yymsp[-2].minor.yy43);
1079 yymsp[-2].minor.yy43 = NULL;
1080
1081 yygotominor.yy41 = yymsp[0].minor.yy41;
1082 yymsp[0].minor.yy41 = NULL;
1083 }
1084 #line 1084 "configparser.c"
1085 yy_destructor(11,&yymsp[-1].minor);
1086 break;
1087 case 25:
1088 yy_destructor(1,&yymsp[0].minor);
1089 break;
1090 case 26:
1091 break;
1092 case 27:
1093 #line 334 "./configparser.y"
1094 {
1095 data_config *dc;
1096 dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
1097 assert(dc);
1098 configparser_push(ctx, dc, 0);
1099 }
1100 #line 1100 "configparser.c"
1101 yy_destructor(12,&yymsp[0].minor);
1102 break;
1103 case 28:
1104 #line 341 "./configparser.y"
1105 {
1106 data_config *cur;
1107
1108 cur = ctx->current;
1109 configparser_pop(ctx);
1110
1111 assert(cur && ctx->current);
1112
1113 yygotominor.yy78 = cur;
1114 }
1115 #line 1115 "configparser.c"
1116 /* No destructor defined for globalstart */
1117 yy_destructor(13,&yymsp[-2].minor);
1118 /* No destructor defined for metalines */
1119 yy_destructor(14,&yymsp[0].minor);
1120 break;
1121 case 29:
1122 #line 352 "./configparser.y"
1123 {
1124 if (yymsp[-3].minor.yy78->context_ndx >= yymsp[0].minor.yy78->context_ndx) {
1125 fprintf(stderr, "unreachable else condition\n");
1126 ctx->ok = 0;
1127 }
1128 yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
1129 yymsp[-3].minor.yy78->next = yymsp[0].minor.yy78;
1130 yygotominor.yy78 = yymsp[0].minor.yy78;
1131 yymsp[-3].minor.yy78 = NULL;
1132 yymsp[0].minor.yy78 = NULL;
1133 }
1134 #line 1134 "configparser.c"
1135 /* No destructor defined for eols */
1136 yy_destructor(15,&yymsp[-1].minor);
1137 break;
1138 case 30:
1139 #line 364 "./configparser.y"
1140 {
1141 yygotominor.yy78 = yymsp[0].minor.yy78;
1142 yymsp[0].minor.yy78 = NULL;
1143 }
1144 #line 1144 "configparser.c"
1145 break;
1146 case 31:
1147 #line 369 "./configparser.y"
1148 {
1149 data_config *cur;
1150
1151 cur = ctx->current;
1152 configparser_pop(ctx);
1153
1154 assert(cur && ctx->current);
1155
1156 yygotominor.yy78 = cur;
1157 }
1158 #line 1158 "configparser.c"
1159 /* No destructor defined for context */
1160 yy_destructor(13,&yymsp[-2].minor);
1161 /* No destructor defined for metalines */
1162 yy_destructor(14,&yymsp[0].minor);
1163 break;
1164 case 32:
1165 #line 380 "./configparser.y"
1166 {
1167 data_config *dc;
1168 buffer *b, *rvalue, *op;
1169
1170 if (ctx->ok && yymsp[0].minor.yy41->type != TYPE_STRING) {
1171 fprintf(stderr, "rvalue must be string");
1172 ctx->ok = 0;
1173 }
1174
1175 switch(yymsp[-1].minor.yy27) {
1176 case CONFIG_COND_NE:
1177 op = buffer_init_string("!=");
1178 break;
1179 case CONFIG_COND_EQ:
1180 op = buffer_init_string("==");
1181 break;
1182 case CONFIG_COND_NOMATCH:
1183 op = buffer_init_string("!~");
1184 break;
1185 case CONFIG_COND_MATCH:
1186 op = buffer_init_string("=~");
1187 break;
1188 default:
1189 assert(0);
1190 return;
1191 }
1192
1193 b = buffer_init();
1194 buffer_copy_string_buffer(b, ctx->current->key);
1195 buffer_append_string(b, "/");
1196 buffer_append_string_buffer(b, yymsp[-5].minor.yy0);
1197 buffer_append_string_buffer(b, yymsp[-3].minor.yy43);
1198 buffer_append_string_buffer(b, op);
1199 rvalue = ((data_string*)yymsp[0].minor.yy41)->value;
1200 buffer_append_string_buffer(b, rvalue);
1201
1202 if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) {
1203 configparser_push(ctx, dc, 0);
1204 } else {
1205 struct {
1206 comp_key_t comp;
1207 char *comp_key;
1208 size_t len;
1209 } comps[] = {
1210 { COMP_SERVER_SOCKET, CONST_STR_LEN("SERVER[\"socket\"]" ) },
1211 { COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) },
1212 { COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) },
1213 { COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) },
1214 { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) },
1215 { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"user-agent\"]" ) },
1216 { COMP_HTTP_LANGUAGE, CONST_STR_LEN("HTTP[\"language\"]" ) },
1217 { COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) },
1218 { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) },
1219 { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) },
1220 { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") },
1221 { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") },
1222 { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") },
1223 { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) },
1224 { COMP_UNSET, NULL, 0 },
1225 };
1226 size_t i;
1227
1228 dc = data_config_init();
1229
1230 buffer_copy_string_buffer(dc->key, b);
1231 buffer_copy_string_buffer(dc->op, op);
1232 buffer_copy_string_buffer(dc->comp_key, yymsp[-5].minor.yy0);
1233 buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\""));
1234 buffer_append_string_buffer(dc->comp_key, yymsp[-3].minor.yy43);
1235 buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]"));
1236 dc->cond = yymsp[-1].minor.yy27;
1237
1238 for (i = 0; comps[i].comp_key; i ++) {
1239 if (buffer_is_equal_string(
1240 dc->comp_key, comps[i].comp_key, comps[i].len)) {
1241 dc->comp = comps[i].comp;
1242 break;
1243 }
1244 }
1245 if (COMP_UNSET == dc->comp) {
1246 fprintf(stderr, "error comp_key %s", dc->comp_key->ptr);
1247 ctx->ok = 0;
1248 }
1249
1250 switch(yymsp[-1].minor.yy27) {
1251 case CONFIG_COND_NE:
1252 case CONFIG_COND_EQ:
1253 dc->string = buffer_init_buffer(rvalue);
1254 break;
1255 case CONFIG_COND_NOMATCH:
1256 case CONFIG_COND_MATCH: {
1257 #ifdef HAVE_PCRE_H
1258 const char *errptr;
1259 int erroff, captures;
1260
1261 if (NULL == (dc->regex =
1262 pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) {
1263 dc->string = buffer_init_string(errptr);
1264 dc->cond = CONFIG_COND_UNSET;
1265
1266 fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n",
1267 rvalue->ptr, errptr, erroff);
1268
1269 ctx->ok = 0;
1270 } else if (NULL == (dc->regex_study =
1271 pcre_study(dc->regex, 0, &errptr)) &&
1272 errptr != NULL) {
1273 fprintf(stderr, "studying regex failed: %s -> %s\n",
1274 rvalue->ptr, errptr);
1275 ctx->ok = 0;
1276 } else if (0 != (pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, &captures))) {
1277 fprintf(stderr, "getting capture count for regex failed: %s\n",
1278 rvalue->ptr);
1279 ctx->ok = 0;
1280 } else if (captures > 9) {
1281 fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n",
1282 rvalue->ptr);
1283 ctx->ok = 0;
1284 } else {
1285 dc->string = buffer_init_buffer(rvalue);
1286 }
1287 #else
1288 fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n"
1289 "(perhaps just a missing pcre-devel package ?) \n",
1290 yymsp[-5].minor.yy0->ptr, yymsp[-3].minor.yy43->ptr);
1291 ctx->ok = 0;
1292 #endif
1293 break;
1294 }
1295
1296 default:
1297 fprintf(stderr, "unknown condition for $%s[%s]\n",
1298 yymsp[-5].minor.yy0->ptr, yymsp[-3].minor.yy43->ptr);
1299 ctx->ok = 0;
1300 break;
1301 }
1302
1303 configparser_push(ctx, dc, 1);
1304 }
1305
1306 buffer_free(b);
1307 buffer_free(op);
1308 buffer_free(yymsp[-5].minor.yy0);
1309 yymsp[-5].minor.yy0 = NULL;
1310 buffer_free(yymsp[-3].minor.yy43);
1311 yymsp[-3].minor.yy43 = NULL;
1312 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
1313 yymsp[0].minor.yy41 = NULL;
1314 }
1315 #line 1315 "configparser.c"
1316 yy_destructor(16,&yymsp[-6].minor);
1317 yy_destructor(18,&yymsp[-4].minor);
1318 yy_destructor(19,&yymsp[-2].minor);
1319 break;
1320 case 33:
1321 #line 529 "./configparser.y"
1322 {
1323 yygotominor.yy27 = CONFIG_COND_EQ;
1324 }
1325 #line 1325 "configparser.c"
1326 yy_destructor(20,&yymsp[0].minor);
1327 break;
1328 case 34:
1329 #line 532 "./configparser.y"
1330 {
1331 yygotominor.yy27 = CONFIG_COND_MATCH;
1332 }
1333 #line 1333 "configparser.c"
1334 yy_destructor(21,&yymsp[0].minor);
1335 break;
1336 case 35:
1337 #line 535 "./configparser.y"
1338 {
1339 yygotominor.yy27 = CONFIG_COND_NE;
1340 }
1341 #line 1341 "configparser.c"
1342 yy_destructor(22,&yymsp[0].minor);
1343 break;
1344 case 36:
1345 #line 538 "./configparser.y"
1346 {
1347 yygotominor.yy27 = CONFIG_COND_NOMATCH;
1348 }
1349 #line 1349 "configparser.c"
1350 yy_destructor(23,&yymsp[0].minor);
1351 break;
1352 case 37:
1353 #line 542 "./configparser.y"
1354 {
1355 yygotominor.yy43 = NULL;
1356 if (ctx->ok) {
1357 if (yymsp[0].minor.yy41->type == TYPE_STRING) {
1358 yygotominor.yy43 = buffer_init_buffer(((data_string*)yymsp[0].minor.yy41)->value);
1359 } else if (yymsp[0].minor.yy41->type == TYPE_INTEGER) {
1360 yygotominor.yy43 = buffer_init();
1361 buffer_copy_long(yygotominor.yy43, ((data_integer *)yymsp[0].minor.yy41)->value);
1362 } else {
1363 fprintf(stderr, "operand must be string");
1364 ctx->ok = 0;
1365 }
1366 }
1367 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
1368 yymsp[0].minor.yy41 = NULL;
1369 }
1370 #line 1370 "configparser.c"
1371 break;
1372 case 38:
1373 #line 559 "./configparser.y"
1374 {
1375 if (ctx->ok) {
1376 if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
1377 ctx->ok = 0;
1378 }
1379 buffer_free(yymsp[0].minor.yy43);
1380 yymsp[0].minor.yy43 = NULL;
1381 }
1382 }
1383 #line 1383 "configparser.c"
1384 yy_destructor(24,&yymsp[-1].minor);
1385 break;
1386 case 39:
1387 #line 569 "./configparser.y"
1388 {
1389 if (ctx->ok) {
1390 if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
1391 ctx->ok = 0;
1392 }
1393 buffer_free(yymsp[0].minor.yy43);
1394 yymsp[0].minor.yy43 = NULL;
1395 }
1396 }
1397 #line 1397 "configparser.c"
1398 yy_destructor(25,&yymsp[-1].minor);
1399 break;
1400 };
1401 yygoto = yyRuleInfo[yyruleno].lhs;
1402 yysize = yyRuleInfo[yyruleno].nrhs;
1403 yypParser->yyidx -= yysize;
1404 yyact = yy_find_reduce_action(yypParser,yygoto);
1405 if( yyact < YYNSTATE ){
1406 yy_shift(yypParser,yyact,yygoto,&yygotominor);
1407 }else if( yyact == YYNSTATE + YYNRULE + 1 ){
1408 yy_accept(yypParser);
1409 }
1410 }
1411
1412 /*
1413 ** The following code executes when the parse fails
1414 */
yy_parse_failed(yyParser * yypParser)1415 static void yy_parse_failed(
1416 yyParser *yypParser /* The parser */
1417 ){
1418 configparserARG_FETCH;
1419 #ifndef NDEBUG
1420 if( yyTraceFILE ){
1421 fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
1422 }
1423 #endif
1424 while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
1425 /* Here code is inserted which will be executed whenever the
1426 ** parser fails */
1427 #line 108 "./configparser.y"
1428
1429 ctx->ok = 0;
1430
1431 #line 1431 "configparser.c"
1432 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
1433 }
1434
1435 /*
1436 ** The following code executes when a syntax error first occurs.
1437 */
yy_syntax_error(yyParser * yypParser,int yymajor,YYMINORTYPE yyminor)1438 static void yy_syntax_error(
1439 yyParser *yypParser, /* The parser */
1440 int yymajor, /* The major type of the error token */
1441 YYMINORTYPE yyminor /* The minor type of the error token */
1442 ){
1443 configparserARG_FETCH;
1444 UNUSED(yymajor);
1445 UNUSED(yyminor);
1446 #define TOKEN (yyminor.yy0)
1447 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
1448 }
1449
1450 /*
1451 ** The following is executed when the parser accepts
1452 */
yy_accept(yyParser * yypParser)1453 static void yy_accept(
1454 yyParser *yypParser /* The parser */
1455 ){
1456 configparserARG_FETCH;
1457 #ifndef NDEBUG
1458 if( yyTraceFILE ){
1459 fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
1460 }
1461 #endif
1462 while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
1463 /* Here code is inserted which will be executed whenever the
1464 ** parser accepts */
1465 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
1466 }
1467
1468 /* The main parser program.
1469 ** The first argument is a pointer to a structure obtained from
1470 ** "configparserAlloc" which describes the current state of the parser.
1471 ** The second argument is the major token number. The third is
1472 ** the minor token. The fourth optional argument is whatever the
1473 ** user wants (and specified in the grammar) and is available for
1474 ** use by the action routines.
1475 **
1476 ** Inputs:
1477 ** <ul>
1478 ** <li> A pointer to the parser (an opaque structure.)
1479 ** <li> The major token number.
1480 ** <li> The minor token number.
1481 ** <li> An option argument of a grammar-specified type.
1482 ** </ul>
1483 **
1484 ** Outputs:
1485 ** None.
1486 */
configparser(void * yyp,int yymajor,configparserTOKENTYPE yyminor configparserARG_PDECL)1487 void configparser(
1488 void *yyp, /* The parser */
1489 int yymajor, /* The major token code number */
1490 configparserTOKENTYPE yyminor /* The value for the token */
1491 configparserARG_PDECL /* Optional %extra_argument parameter */
1492 ){
1493 YYMINORTYPE yyminorunion;
1494 int yyact; /* The parser action. */
1495 int yyendofinput; /* True if we are at the end of input */
1496 int yyerrorhit = 0; /* True if yymajor has invoked an error */
1497 yyParser *yypParser; /* The parser */
1498
1499 /* (re)initialize the parser, if necessary */
1500 yypParser = (yyParser*)yyp;
1501 if( yypParser->yyidx<0 ){
1502 if( yymajor==0 ) return;
1503 yypParser->yyidx = 0;
1504 yypParser->yyerrcnt = -1;
1505 yypParser->yystack[0].stateno = 0;
1506 yypParser->yystack[0].major = 0;
1507 }
1508 yyminorunion.yy0 = yyminor;
1509 yyendofinput = (yymajor==0);
1510 configparserARG_STORE;
1511
1512 #ifndef NDEBUG
1513 if( yyTraceFILE ){
1514 fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
1515 }
1516 #endif
1517
1518 do{
1519 yyact = yy_find_shift_action(yypParser,yymajor);
1520 if( yyact<YYNSTATE ){
1521 yy_shift(yypParser,yyact,yymajor,&yyminorunion);
1522 yypParser->yyerrcnt--;
1523 if( yyendofinput && yypParser->yyidx>=0 ){
1524 yymajor = 0;
1525 }else{
1526 yymajor = YYNOCODE;
1527 }
1528 }else if( yyact < YYNSTATE + YYNRULE ){
1529 yy_reduce(yypParser,yyact-YYNSTATE);
1530 }else if( yyact == YY_ERROR_ACTION ){
1531 int yymx;
1532 #ifndef NDEBUG
1533 if( yyTraceFILE ){
1534 fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
1535 }
1536 #endif
1537 #ifdef YYERRORSYMBOL
1538 /* A syntax error has occurred.
1539 ** The response to an error depends upon whether or not the
1540 ** grammar defines an error token "ERROR".
1541 **
1542 ** This is what we do if the grammar does define ERROR:
1543 **
1544 ** * Call the %syntax_error function.
1545 **
1546 ** * Begin popping the stack until we enter a state where
1547 ** it is legal to shift the error symbol, then shift
1548 ** the error symbol.
1549 **
1550 ** * Set the error count to three.
1551 **
1552 ** * Begin accepting and shifting new tokens. No new error
1553 ** processing will occur until three tokens have been
1554 ** shifted successfully.
1555 **
1556 */
1557 if( yypParser->yyerrcnt<0 ){
1558 yy_syntax_error(yypParser,yymajor,yyminorunion);
1559 }
1560 yymx = yypParser->yystack[yypParser->yyidx].major;
1561 if( yymx==YYERRORSYMBOL || yyerrorhit ){
1562 #ifndef NDEBUG
1563 if( yyTraceFILE ){
1564 fprintf(yyTraceFILE,"%sDiscard input token %s\n",
1565 yyTracePrompt,yyTokenName[yymajor]);
1566 }
1567 #endif
1568 yy_destructor(yymajor,&yyminorunion);
1569 yymajor = YYNOCODE;
1570 }else{
1571 while(
1572 yypParser->yyidx >= 0 &&
1573 yymx != YYERRORSYMBOL &&
1574 (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
1575 ){
1576 yy_pop_parser_stack(yypParser);
1577 }
1578 if( yypParser->yyidx < 0 || yymajor==0 ){
1579 yy_destructor(yymajor,&yyminorunion);
1580 yy_parse_failed(yypParser);
1581 yymajor = YYNOCODE;
1582 }else if( yymx!=YYERRORSYMBOL ){
1583 YYMINORTYPE u2;
1584 u2.YYERRSYMDT = 0;
1585 yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
1586 }
1587 }
1588 yypParser->yyerrcnt = 3;
1589 yyerrorhit = 1;
1590 #else /* YYERRORSYMBOL is not defined */
1591 /* This is what we do if the grammar does not define ERROR:
1592 **
1593 ** * Report an error message, and throw away the input token.
1594 **
1595 ** * If the input token is $, then fail the parse.
1596 **
1597 ** As before, subsequent error messages are suppressed until
1598 ** three input tokens have been successfully shifted.
1599 */
1600 if( yypParser->yyerrcnt<=0 ){
1601 yy_syntax_error(yypParser,yymajor,yyminorunion);
1602 }
1603 yypParser->yyerrcnt = 3;
1604 yy_destructor(yymajor,&yyminorunion);
1605 if( yyendofinput ){
1606 yy_parse_failed(yypParser);
1607 }
1608 yymajor = YYNOCODE;
1609 #endif
1610 }else{
1611 yy_accept(yypParser);
1612 yymajor = YYNOCODE;
1613 }
1614 }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
1615 return;
1616 }
1617