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