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