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