Annotation of embedaddon/lighttpd/src/configparser.y, revision 1.1

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

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