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