File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / configparser.y
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:35:00 2016 UTC (7 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_41p8, HEAD
lighttpd 1.4.41

    1: %token_prefix TK_
    2: %extra_argument {config_t *ctx}
    3: %name configparser
    4: 
    5: %include {
    6: #include "first.h"
    7: #include "configfile.h"
    8: #include "buffer.h"
    9: #include "array.h"
   10: #include "request.h" /* http_request_host_normalize() */
   11: 
   12: #include <assert.h>
   13: #include <ctype.h>
   14: #include <errno.h>
   15: #include <stdio.h>
   16: #include <string.h>
   17: 
   18: static void configparser_push(config_t *ctx, data_config *dc, int isnew) {
   19:   if (isnew) {
   20:     dc->context_ndx = ctx->all_configs->used;
   21:     force_assert(dc->context_ndx > ctx->current->context_ndx);
   22:     array_insert_unique(ctx->all_configs, (data_unset *)dc);
   23:     dc->parent = ctx->current;
   24:     vector_config_weak_push(&dc->parent->children, dc);
   25:   }
   26:   if (ctx->configs_stack.used > 0 && ctx->current->context_ndx == 0) {
   27:     fprintf(stderr, "Cannot use conditionals inside a global { ... } block\n");
   28:     exit(-1);
   29:   }
   30:   vector_config_weak_push(&ctx->configs_stack, ctx->current);
   31:   ctx->current = dc;
   32: }
   33: 
   34: static data_config *configparser_pop(config_t *ctx) {
   35:   data_config *old = ctx->current;
   36:   ctx->current = vector_config_weak_pop(&ctx->configs_stack);
   37:   return old;
   38: }
   39: 
   40: /* return a copied variable */
   41: static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
   42:   data_unset *du;
   43:   data_config *dc;
   44: 
   45: #if 0
   46:   fprintf(stderr, "get var %s\n", key->ptr);
   47: #endif
   48:   for (dc = ctx->current; dc; dc = dc->parent) {
   49: #if 0
   50:     fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
   51:     array_print(dc->value, 0);
   52: #endif
   53:     if (NULL != (du = array_get_element(dc->value, key->ptr))) {
   54:       return du->copy(du);
   55:     }
   56:   }
   57:   return NULL;
   58: }
   59: 
   60: /* op1 is to be eat/return by this function if success, op1->key is not cared
   61:    op2 is left untouch, unreferenced
   62:  */
   63: data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) {
   64:   /* type mismatch */
   65:   if (op1->type != op2->type) {
   66:     if (op1->type == TYPE_STRING && op2->type == TYPE_INTEGER) {
   67:       data_string *ds = (data_string *)op1;
   68:       buffer_append_int(ds->value, ((data_integer*)op2)->value);
   69:       return op1;
   70:     } else if (op1->type == TYPE_INTEGER && op2->type == TYPE_STRING) {
   71:       data_string *ds = data_string_init();
   72:       buffer_append_int(ds->value, ((data_integer*)op1)->value);
   73:       buffer_append_string_buffer(ds->value, ((data_string*)op2)->value);
   74:       op1->free(op1);
   75:       return (data_unset *)ds;
   76:     } else {
   77:       fprintf(stderr, "data type mismatch, cannot merge\n");
   78:       op1->free(op1);
   79:       return NULL;
   80:     }
   81:   }
   82: 
   83:   switch (op1->type) {
   84:     case TYPE_STRING:
   85:       buffer_append_string_buffer(((data_string *)op1)->value, ((data_string *)op2)->value);
   86:       break;
   87:     case TYPE_INTEGER:
   88:       ((data_integer *)op1)->value += ((data_integer *)op2)->value;
   89:       break;
   90:     case TYPE_ARRAY: {
   91:       array *dst = ((data_array *)op1)->value;
   92:       array *src = ((data_array *)op2)->value;
   93:       data_unset *du;
   94:       size_t i;
   95: 
   96:       for (i = 0; i < src->used; i ++) {
   97:         du = (data_unset *)src->data[i];
   98:         if (du) {
   99:           if (du->is_index_key || buffer_is_empty(du->key) || !array_get_element(dst, du->key->ptr)) {
  100:             array_insert_unique(dst, du->copy(du));
  101:           } else {
  102:             fprintf(stderr, "Duplicate array-key '%s'\n", du->key->ptr);
  103:             op1->free(op1);
  104:             return NULL;
  105:           }
  106:         }
  107:       }
  108:       break;
  109:     default:
  110:       force_assert(0);
  111:       break;
  112:     }
  113:   }
  114:   return op1;
  115: }
  116: 
  117: static int configparser_remoteip_normalize_compat(buffer *rvalue) {
  118:   /* $HTTP["remoteip"] IPv6 accepted with or without '[]' for config compat
  119:    * http_request_host_normalize() expects IPv6 with '[]',
  120:    * and config processing at runtime expects COMP_HTTP_REMOTE_IP
  121:    * compared without '[]', so strip '[]' after normalization */
  122:   buffer *b = buffer_init();
  123:   int rc;
  124: 
  125:   if (rvalue->ptr[0] != '[') {
  126:       buffer_append_string_len(b, CONST_STR_LEN("["));
  127:       buffer_append_string_buffer(b, rvalue);
  128:       buffer_append_string_len(b, CONST_STR_LEN("]"));
  129:   } else {
  130:       buffer_append_string_buffer(b, rvalue);
  131:   }
  132: 
  133:   rc = http_request_host_normalize(b);
  134: 
  135:   if (0 == rc) {
  136:     /* remove surrounding '[]' */
  137:     size_t blen = buffer_string_length(b);
  138:     if (blen > 1) buffer_copy_string_len(rvalue, b->ptr+1, blen-2);
  139:   }
  140: 
  141:   buffer_free(b);
  142:   return rc;
  143: }
  144: 
  145: }
  146: 
  147: %parse_failure {
  148:   ctx->ok = 0;
  149: }
  150: 
  151: input ::= metalines.
  152: metalines ::= metalines metaline.
  153: metalines ::= .
  154: metaline ::= varline.
  155: metaline ::= global.
  156: metaline ::= condlines(A) EOL. { A = NULL; }
  157: metaline ::= include.
  158: metaline ::= include_shell.
  159: metaline ::= EOL.
  160: 
  161: %type       value                  {data_unset *}
  162: %type       expression             {data_unset *}
  163: %type       aelement               {data_unset *}
  164: %type       condline               {data_config *}
  165: %type       condlines              {data_config *}
  166: %type       aelements              {array *}
  167: %type       array                  {array *}
  168: %type       key                    {buffer *}
  169: %type       stringop               {buffer *}
  170: 
  171: %type       cond                   {config_cond_t }
  172: 
  173: %destructor value                  { if ($$) $$->free($$); }
  174: %destructor expression             { if ($$) $$->free($$); }
  175: %destructor aelement               { if ($$) $$->free($$); }
  176: %destructor aelements              { array_free($$); }
  177: %destructor array                  { array_free($$); }
  178: %destructor key                    { buffer_free($$); }
  179: %destructor stringop               { buffer_free($$); }
  180: 
  181: %token_type                        {buffer *}
  182: %token_destructor                  { buffer_free($$); }
  183: 
  184: varline ::= key(A) ASSIGN expression(B). {
  185:   if (ctx->ok) {
  186:     buffer_copy_buffer(B->key, A);
  187:     if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
  188:       fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
  189:           ctx->current->context_ndx,
  190:           ctx->current->key->ptr, A->ptr);
  191:       ctx->ok = 0;
  192:     } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
  193:       array_insert_unique(ctx->current->value, B);
  194:       B = NULL;
  195:     } else {
  196:       fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n",
  197:               ctx->current->context_ndx,
  198:               ctx->current->key->ptr, B->key->ptr);
  199:       ctx->ok = 0;
  200:       B->free(B);
  201:       B = NULL;
  202:     }
  203:   }
  204:   buffer_free(A);
  205:   A = NULL;
  206: }
  207: 
  208: varline ::= key(A) APPEND expression(B). {
  209:   if (ctx->ok) {
  210:     array *vars = ctx->current->value;
  211:     data_unset *du;
  212: 
  213:     if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
  214:       fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
  215:           ctx->current->context_ndx,
  216:           ctx->current->key->ptr, A->ptr);
  217:       ctx->ok = 0;
  218:     } else if (NULL != (du = array_extract_element(vars, A->ptr)) || NULL != (du = configparser_get_variable(ctx, A))) {
  219:       du = configparser_merge_data(du, B);
  220:       if (NULL == du) {
  221:         ctx->ok = 0;
  222:       }
  223:       else {
  224:         buffer_copy_buffer(du->key, A);
  225:         array_insert_unique(ctx->current->value, du);
  226:       }
  227:       B->free(B);
  228:     } else {
  229:       buffer_copy_buffer(B->key, A);
  230:       array_insert_unique(ctx->current->value, B);
  231:     }
  232:     buffer_free(A);
  233:     A = NULL;
  234:     B = NULL;
  235:   }
  236: }
  237: 
  238: key(A) ::= LKEY(B). {
  239:   if (strchr(B->ptr, '.') == NULL) {
  240:     A = buffer_init_string("var.");
  241:     buffer_append_string_buffer(A, B);
  242:     buffer_free(B);
  243:     B = NULL;
  244:   } else {
  245:     A = B;
  246:     B = NULL;
  247:   }
  248: }
  249: 
  250: expression(A) ::= expression(B) PLUS value(C). {
  251:   A = NULL;
  252:   if (ctx->ok) {
  253:     A = configparser_merge_data(B, C);
  254:     if (NULL == A) {
  255:       ctx->ok = 0;
  256:     }
  257:     B = NULL;
  258:     C->free(C);
  259:     C = NULL;
  260:   }
  261: }
  262: 
  263: expression(A) ::= value(B). {
  264:   A = B;
  265:   B = NULL;
  266: }
  267: 
  268: value(A) ::= key(B). {
  269:   A = NULL;
  270:   if (ctx->ok) {
  271:     if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
  272:       char *env;
  273: 
  274:       if (NULL != (env = getenv(B->ptr + 4))) {
  275:         data_string *ds;
  276:         ds = data_string_init();
  277:         buffer_append_string(ds->value, env);
  278:         A = (data_unset *)ds;
  279:       }
  280:       else {
  281:         fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
  282:         ctx->ok = 0;
  283:       }
  284:     } else if (NULL == (A = configparser_get_variable(ctx, B))) {
  285:       fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
  286:       ctx->ok = 0;
  287:     }
  288:     buffer_free(B);
  289:     B = NULL;
  290:   }
  291: }
  292: 
  293: value(A) ::= STRING(B). {
  294:   A = (data_unset *)data_string_init();
  295:   buffer_copy_buffer(((data_string *)(A))->value, B);
  296:   buffer_free(B);
  297:   B = NULL;
  298: }
  299: 
  300: value(A) ::= INTEGER(B). {
  301:   char *endptr;
  302:   A = (data_unset *)data_integer_init();
  303:   errno = 0;
  304:   ((data_integer *)(A))->value = strtol(B->ptr, &endptr, 10);
  305:   /* skip trailing whitespace */
  306:   if (endptr != B->ptr) while (isspace(*endptr)) endptr++;
  307:   if (0 != errno || *endptr != '\0') {
  308:     fprintf(stderr, "error parsing number: '%s'\n", B->ptr);
  309:     ctx->ok = 0;
  310:   }
  311:   buffer_free(B);
  312:   B = NULL;
  313: }
  314: value(A) ::= array(B). {
  315:   A = (data_unset *)data_array_init();
  316:   array_free(((data_array *)(A))->value);
  317:   ((data_array *)(A))->value = B;
  318:   B = NULL;
  319: }
  320: array(A) ::= LPARAN RPARAN. {
  321:   A = array_init();
  322: }
  323: array(A) ::= LPARAN aelements(B) RPARAN. {
  324:   A = B;
  325:   B = NULL;
  326: }
  327: 
  328: aelements(A) ::= aelements(C) COMMA aelement(B). {
  329:   A = NULL;
  330:   if (ctx->ok) {
  331:     if (buffer_is_empty(B->key) ||
  332:         NULL == array_get_element(C, B->key->ptr)) {
  333:       array_insert_unique(C, B);
  334:       B = NULL;
  335:     } else {
  336:       fprintf(stderr, "Error: duplicate array-key: %s. Please get rid of the duplicate entry.\n",
  337:               B->key->ptr);
  338:       ctx->ok = 0;
  339:       B->free(B);
  340:       B = NULL;
  341:     }
  342: 
  343:     A = C;
  344:     C = NULL;
  345:   }
  346: }
  347: 
  348: aelements(A) ::= aelements(C) COMMA. {
  349:   A = C;
  350:   C = NULL;
  351: }
  352: 
  353: aelements(A) ::= aelement(B). {
  354:   A = NULL;
  355:   if (ctx->ok) {
  356:     A = array_init();
  357:     array_insert_unique(A, B);
  358:     B = NULL;
  359:   }
  360: }
  361: 
  362: aelement(A) ::= expression(B). {
  363:   A = B;
  364:   B = NULL;
  365: }
  366: aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). {
  367:   A = NULL;
  368:   if (ctx->ok) {
  369:     buffer_copy_buffer(C->key, B);
  370:     buffer_free(B);
  371:     B = NULL;
  372: 
  373:     A = C;
  374:     C = NULL;
  375:   }
  376: }
  377: 
  378: eols ::= EOL.
  379: eols ::= .
  380: 
  381: globalstart ::= GLOBAL. {
  382:   data_config *dc;
  383:   dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
  384:   force_assert(dc);
  385:   configparser_push(ctx, dc, 0);
  386: }
  387: 
  388: global ::= globalstart LCURLY metalines RCURLY. {
  389:   force_assert(ctx->current);
  390:   configparser_pop(ctx);
  391:   force_assert(ctx->current);
  392: }
  393: 
  394: condlines(A) ::= condlines(B) eols ELSE condline(C). {
  395:   A = NULL;
  396:   if (ctx->ok) {
  397:     if (B->context_ndx >= C->context_ndx) {
  398:       fprintf(stderr, "unreachable else condition\n");
  399:       ctx->ok = 0;
  400:     }
  401:     C->prev = B;
  402:     B->next = C;
  403:     A = C;
  404:     B = NULL;
  405:     C = NULL;
  406:   }
  407: }
  408: 
  409: condlines(A) ::= condline(B). {
  410:   A = B;
  411:   B = NULL;
  412: }
  413: 
  414: condline(A) ::= context LCURLY metalines RCURLY. {
  415:   A = NULL;
  416:   if (ctx->ok) {
  417:     data_config *cur;
  418: 
  419:     cur = ctx->current;
  420:     configparser_pop(ctx);
  421: 
  422:     force_assert(cur && ctx->current);
  423: 
  424:     A = cur;
  425:   }
  426: }
  427: 
  428: context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expression(D). {
  429:   data_config *dc;
  430:   buffer *b, *rvalue, *op;
  431: 
  432:   if (ctx->ok && D->type != TYPE_STRING) {
  433:     fprintf(stderr, "rvalue must be string");
  434:     ctx->ok = 0;
  435:   }
  436: 
  437:   if (ctx->ok) {
  438:     switch(E) {
  439:     case CONFIG_COND_NE:
  440:       op = buffer_init_string("!=");
  441:       break;
  442:     case CONFIG_COND_EQ:
  443:       op = buffer_init_string("==");
  444:       break;
  445:     case CONFIG_COND_NOMATCH:
  446:       op = buffer_init_string("!~");
  447:       break;
  448:     case CONFIG_COND_MATCH:
  449:       op = buffer_init_string("=~");
  450:       break;
  451:     default:
  452:       force_assert(0);
  453:       return; /* unreachable */
  454:     }
  455: 
  456:     b = buffer_init();
  457:     buffer_copy_buffer(b, ctx->current->key);
  458:     buffer_append_string(b, "/");
  459:     buffer_append_string_buffer(b, B);
  460:     buffer_append_string_buffer(b, C);
  461:     buffer_append_string_buffer(b, op);
  462:     rvalue = ((data_string*)D)->value;
  463:     buffer_append_string_buffer(b, rvalue);
  464: 
  465:     if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) {
  466:       configparser_push(ctx, dc, 0);
  467:     } else {
  468:       static const struct {
  469:         comp_key_t comp;
  470:         char *comp_key;
  471:         size_t len;
  472:       } comps[] = {
  473:         { COMP_SERVER_SOCKET,      CONST_STR_LEN("SERVER[\"socket\"]"   ) },
  474:         { COMP_HTTP_URL,           CONST_STR_LEN("HTTP[\"url\"]"        ) },
  475:         { COMP_HTTP_HOST,          CONST_STR_LEN("HTTP[\"host\"]"       ) },
  476:         { COMP_HTTP_REFERER,       CONST_STR_LEN("HTTP[\"referer\"]"    ) },
  477:         { COMP_HTTP_USER_AGENT,    CONST_STR_LEN("HTTP[\"useragent\"]"  ) },
  478:         { COMP_HTTP_USER_AGENT,    CONST_STR_LEN("HTTP[\"user-agent\"]"  ) },
  479:         { COMP_HTTP_LANGUAGE,      CONST_STR_LEN("HTTP[\"language\"]"   ) },
  480:         { COMP_HTTP_COOKIE,        CONST_STR_LEN("HTTP[\"cookie\"]"     ) },
  481:         { COMP_HTTP_REMOTE_IP,     CONST_STR_LEN("HTTP[\"remoteip\"]"   ) },
  482:         { COMP_HTTP_REMOTE_IP,     CONST_STR_LEN("HTTP[\"remote-ip\"]"   ) },
  483:         { COMP_HTTP_QUERY_STRING,  CONST_STR_LEN("HTTP[\"querystring\"]") },
  484:         { COMP_HTTP_QUERY_STRING,  CONST_STR_LEN("HTTP[\"query-string\"]") },
  485:         { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") },
  486:         { COMP_HTTP_SCHEME,        CONST_STR_LEN("HTTP[\"scheme\"]"     ) },
  487:         { COMP_UNSET, NULL, 0 },
  488:       };
  489:       size_t i;
  490: 
  491:       dc = data_config_init();
  492: 
  493:       buffer_copy_buffer(dc->key, b);
  494:       buffer_copy_buffer(dc->op, op);
  495:       buffer_copy_buffer(dc->comp_key, B);
  496:       buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\""));
  497:       buffer_append_string_buffer(dc->comp_key, C);
  498:       buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]"));
  499:       dc->cond = E;
  500: 
  501:       for (i = 0; comps[i].comp_key; i ++) {
  502:         if (buffer_is_equal_string(
  503:               dc->comp_key, comps[i].comp_key, comps[i].len)) {
  504:           dc->comp = comps[i].comp;
  505:           break;
  506:         }
  507:       }
  508:       if (COMP_UNSET == dc->comp) {
  509:         fprintf(stderr, "error comp_key %s", dc->comp_key->ptr);
  510:         ctx->ok = 0;
  511:       }
  512:       else if (COMP_HTTP_REMOTE_IP == dc->comp
  513:                && (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE)) {
  514:         char * const slash = strchr(rvalue->ptr, '/'); /* CIDR mask */
  515:         char * const colon = strchr(rvalue->ptr, ':'); /* IPv6 */
  516:         if (NULL != slash && slash == rvalue->ptr){/*(skip AF_UNIX /path/file)*/
  517:         }
  518:         else if (NULL != slash) {
  519:           char *nptr;
  520:           const unsigned long nm_bits = strtoul(slash + 1, &nptr, 10);
  521:           if (*nptr || 0 == nm_bits || nm_bits > (NULL != colon ? 128 : 32)) {
  522:             /*(also rejects (slash+1 == nptr) which results in nm_bits = 0)*/
  523:             fprintf(stderr, "invalid or missing netmask: %s\n", rvalue->ptr);
  524:             ctx->ok = 0;
  525:           }
  526:           else {
  527:             int rc;
  528:             buffer_string_set_length(rvalue, (size_t)(slash - rvalue->ptr)); /*(truncate)*/
  529:             rc = (NULL == colon)
  530:               ? http_request_host_normalize(rvalue)
  531:               : configparser_remoteip_normalize_compat(rvalue);
  532:             buffer_append_string_len(rvalue, CONST_STR_LEN("/"));
  533:             buffer_append_int(rvalue, (int)nm_bits);
  534:             if (0 != rc) {
  535:               fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
  536:               ctx->ok = 0;
  537:             }
  538:           }
  539:         }
  540:         else {
  541:           int rc = (NULL == colon)
  542:             ? http_request_host_normalize(rvalue)
  543:             : configparser_remoteip_normalize_compat(rvalue);
  544:           if (0 != rc) {
  545:             fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
  546:             ctx->ok = 0;
  547:           }
  548:         }
  549:       }
  550:       else if (COMP_SERVER_SOCKET == dc->comp) {
  551:         /*(redundant with parsing in network.c; not actually required here)*/
  552:         if (rvalue->ptr[0] != ':' /*(network.c special-cases ":" and "[]")*/
  553:             && !(rvalue->ptr[0] == '[' && rvalue->ptr[1] == ']')) {
  554:           if (http_request_host_normalize(rvalue)) {
  555:             fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
  556:             ctx->ok = 0;
  557:           }
  558:         }
  559:       }
  560:       else if (COMP_HTTP_HOST == dc->comp) {
  561:         if (dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE) {
  562:           if (http_request_host_normalize(rvalue)) {
  563:             fprintf(stderr, "invalid IP addr: %s\n", rvalue->ptr);
  564:             ctx->ok = 0;
  565:           }
  566:         }
  567:       }
  568: 
  569:       if (ctx->ok) switch(E) {
  570:       case CONFIG_COND_NE:
  571:       case CONFIG_COND_EQ:
  572:         dc->string = buffer_init_buffer(rvalue);
  573:         break;
  574:       case CONFIG_COND_NOMATCH:
  575:       case CONFIG_COND_MATCH: {
  576: #ifdef HAVE_PCRE_H
  577:         const char *errptr;
  578:         int erroff, captures;
  579: 
  580:         if (NULL == (dc->regex =
  581:             pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) {
  582:           dc->string = buffer_init_string(errptr);
  583:           dc->cond = CONFIG_COND_UNSET;
  584: 
  585:           fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n",
  586:               rvalue->ptr, errptr, erroff);
  587: 
  588:           ctx->ok = 0;
  589:         } else if (NULL == (dc->regex_study =
  590:             pcre_study(dc->regex, 0, &errptr)) &&
  591:                    errptr != NULL) {
  592:           fprintf(stderr, "studying regex failed: %s -> %s\n",
  593:               rvalue->ptr, errptr);
  594:           ctx->ok = 0;
  595:         } else if (0 != (pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, &captures))) {
  596:           fprintf(stderr, "getting capture count for regex failed: %s\n",
  597:               rvalue->ptr);
  598:           ctx->ok = 0;
  599:         } else if (captures > 9) {
  600:           fprintf(stderr, "Too many captures in regex, use (?:...) instead of (...): %s\n",
  601:               rvalue->ptr);
  602:           ctx->ok = 0;
  603:         } else {
  604:           dc->string = buffer_init_buffer(rvalue);
  605:         }
  606: #else
  607:         fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n"
  608:                         "(perhaps just a missing pcre-devel package ?) \n",
  609:                         B->ptr, C->ptr);
  610:         ctx->ok = 0;
  611:  #endif
  612:         break;
  613:       }
  614: 
  615:       default:
  616:         fprintf(stderr, "unknown condition for $%s[%s]\n",
  617:                         B->ptr, C->ptr);
  618:         ctx->ok = 0;
  619:         break;
  620:       }
  621: 
  622:       if (ctx->ok) {
  623:         configparser_push(ctx, dc, 1);
  624:       } else {
  625:         dc->free((data_unset*) dc);
  626:       }
  627:     }
  628: 
  629:     buffer_free(b);
  630:     buffer_free(op);
  631:     buffer_free(B);
  632:     B = NULL;
  633:     buffer_free(C);
  634:     C = NULL;
  635:     D->free(D);
  636:     D = NULL;
  637:   }
  638: }
  639: cond(A) ::= EQ. {
  640:   A = CONFIG_COND_EQ;
  641: }
  642: cond(A) ::= MATCH. {
  643:   A = CONFIG_COND_MATCH;
  644: }
  645: cond(A) ::= NE. {
  646:   A = CONFIG_COND_NE;
  647: }
  648: cond(A) ::= NOMATCH. {
  649:   A = CONFIG_COND_NOMATCH;
  650: }
  651: 
  652: stringop(A) ::= expression(B). {
  653:   A = NULL;
  654:   if (ctx->ok) {
  655:     if (B->type == TYPE_STRING) {
  656:       A = buffer_init_buffer(((data_string*)B)->value);
  657:     } else if (B->type == TYPE_INTEGER) {
  658:       A = buffer_init();
  659:       buffer_copy_int(A, ((data_integer *)B)->value);
  660:     } else {
  661:       fprintf(stderr, "operand must be string");
  662:       ctx->ok = 0;
  663:     }
  664:   }
  665:   B->free(B);
  666:   B = NULL;
  667: }
  668: 
  669: include ::= INCLUDE stringop(A). {
  670:   if (ctx->ok) {
  671:     if (0 != config_parse_file(ctx->srv, ctx, A->ptr)) {
  672:       ctx->ok = 0;
  673:     }
  674:     buffer_free(A);
  675:     A = NULL;
  676:   }
  677: }
  678: 
  679: include_shell ::= INCLUDE_SHELL stringop(A). {
  680:   if (ctx->ok) {
  681:     if (0 != config_parse_cmd(ctx->srv, ctx, A->ptr)) {
  682:       ctx->ok = 0;
  683:     }
  684:     buffer_free(A);
  685:     A = NULL;
  686:   }
  687: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>