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