Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_parser.y, revision 1.1.1.1

1.1       misho       1: %{
                      2: /*
                      3:  * Copyright (C) 2014-2018 Tobias Brunner
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #define _GNU_SOURCE /* for asprintf() */
                     18: #include <stdio.h>
                     19: 
                     20: #include <library.h>
                     21: #include <collections/array.h>
                     22: #include <settings/settings_types.h>
                     23: #include <utils/parser_helper.h>
                     24: 
                     25: #include "settings_parser.h"
                     26: 
                     27: #define YYDEBUG 1
                     28: 
                     29: /**
                     30:  * Defined by the lexer
                     31:  */
                     32: int settings_parser_lex(YYSTYPE *lvalp, void *scanner);
                     33: int settings_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
                     34: int settings_parser_lex_destroy(void *scanner);
                     35: int settings_parser_set_in(FILE *in, void *scanner);
                     36: void settings_parser_set_debug(int debug, void *scanner);
                     37: char *settings_parser_get_text(void *scanner);
                     38: int settings_parser_get_leng(void *scanner);
                     39: int settings_parser_get_lineno(void *scanner);
                     40: /* Custom functions in lexer */
                     41: bool settings_parser_open_next_file(parser_helper_t *ctx);
                     42: bool settings_parser_load_string(parser_helper_t *ctx, const char *content);
                     43: 
                     44: /**
                     45:  * Forward declarations
                     46:  */
                     47: static void settings_parser_error(parser_helper_t *ctx, const char *s);
                     48: static section_t *push_section(parser_helper_t *ctx, char *name);
                     49: static section_t *pop_section(parser_helper_t *ctx);
                     50: static void add_section(parser_helper_t *ctx, section_t *section);
                     51: static void add_setting(parser_helper_t *ctx, kv_t *kv);
                     52: static void add_references(parser_helper_t *ctx, array_t *references);
                     53: 
                     54: /**
                     55:  * Make sure to call lexer with the proper context
                     56:  */
                     57: #undef yylex
                     58: static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
                     59: {
                     60:        return settings_parser_lex(lvalp, ctx->scanner);
                     61: }
                     62: 
                     63: %}
                     64: %debug
                     65: 
                     66: /* generate verbose error messages */
                     67: %error-verbose
                     68: /* generate a reentrant parser */
                     69: %define api.pure
                     70: /* prefix function/variable declarations */
                     71: %name-prefix "settings_parser_"
                     72: 
                     73: /* interact properly with the reentrant lexer */
                     74: %lex-param {parser_helper_t *ctx}
                     75: %parse-param {parser_helper_t *ctx}
                     76: 
                     77: /* types for terminal symbols... (can't use the typedef'd types) */
                     78: %union {
                     79:        char *s;
                     80:        struct section_t *sec;
                     81:        struct kv_t *kv;
                     82:        array_t *refs;
                     83: }
                     84: %token <s> NAME STRING
                     85: %token DOT "."
                     86: %token COMMA ","
                     87: %token COLON ":"
                     88: %token NEWLINE STRING_ERROR
                     89: 
                     90: /* ...and other symbols */
                     91: %type <s> value valuepart
                     92: %type <sec> section_start section
                     93: %type <kv> setting
                     94: %type <refs> references
                     95: 
                     96: /* properly destroy string tokens that are strdup()ed on error */
                     97: %destructor { free($$); } NAME STRING value valuepart
                     98: /* properly destroy parse results on error */
                     99: %destructor { pop_section(ctx); settings_section_destroy($$, NULL); } section_start section
                    100: %destructor { settings_kv_destroy($$, NULL); } setting
                    101: %destructor { array_destroy_function($$, (void*)free, NULL); } references
                    102: 
                    103: /* there are two shift/reduce conflicts because of the "NAME = NAME" and
                    104:  * "NAME {" ambiguity, and the "NAME =" rule) */
                    105: %expect 2
                    106: 
                    107: %%
                    108: 
                    109: /**
                    110:  * strongswan.conf grammar rules
                    111:  */
                    112: statements:
                    113:        /* empty */
                    114:        | statements NEWLINE
                    115:        | statements statement
                    116:        ;
                    117: 
                    118: statement:
                    119:        section
                    120:        {
                    121:                add_section(ctx, $section);
                    122:        }
                    123:        | setting
                    124:        {
                    125:                add_setting(ctx, $setting);
                    126:        }
                    127:        ;
                    128: 
                    129: section:
                    130:        section_start statements '}'
                    131:        {
                    132:                pop_section(ctx);
                    133:                $$ = $section_start;
                    134:        }
                    135:        ;
                    136: 
                    137: section_start:
                    138:        NAME '{'
                    139:        {
                    140:                $$ = push_section(ctx, $NAME);
                    141:        }
                    142:        |
                    143:        NAME ":" references '{'
                    144:        {
                    145:                $$ = push_section(ctx, $NAME);
                    146:                add_references(ctx, $references);
                    147:                array_destroy($references);
                    148:        }
                    149:        ;
                    150: 
                    151: references:
                    152:        NAME
                    153:        {
                    154:                $$ = array_create(0, 0);
                    155:                array_insert($$, ARRAY_TAIL, $1);
                    156:        }
                    157:        | references "," NAME
                    158:        {
                    159:                array_insert($1, ARRAY_TAIL, $3);
                    160:                $$ = $1;
                    161:        }
                    162:        ;
                    163: 
                    164: setting:
                    165:        NAME '=' value
                    166:        {
                    167:                $$ = settings_kv_create($NAME, $value);
                    168:        }
                    169:        |
                    170:        NAME '='
                    171:        {
                    172:                $$ = settings_kv_create($NAME, NULL);
                    173:        }
                    174:        ;
                    175: 
                    176: value:
                    177:        valuepart
                    178:        | value valuepart
                    179:        {       /* just put a single space between them, use strings for more */
                    180:                if (asprintf(&$$, "%s %s", $1, $2) < 0)
                    181:                {
                    182:                        free($1);
                    183:                        free($2);
                    184:                        YYERROR;
                    185:                }
                    186:                free($1);
                    187:                free($2);
                    188:        }
                    189:        ;
                    190: 
                    191: valuepart:
                    192:        NAME
                    193:        | STRING
                    194:        ;
                    195: 
                    196: %%
                    197: 
                    198: /**
                    199:  * Referenced by the generated parser
                    200:  */
                    201: static void settings_parser_error(parser_helper_t *ctx, const char *s)
                    202: {
                    203:        char *text = settings_parser_get_text(ctx->scanner);
                    204:        int len = settings_parser_get_leng(ctx->scanner);
                    205: 
                    206:        if (len && text[len-1] == '\n')
                    207:        {       /* cut off newline at the end to avoid muti-line log messages */
                    208:                len--;
                    209:        }
                    210:        PARSER_DBG1(ctx, "%s [%.*s]", s, len, text);
                    211: }
                    212: 
                    213: /**
                    214:  * Create a section and push it to the stack (the name is adopted), returns
                    215:  * the created section
                    216:  */
                    217: static section_t *push_section(parser_helper_t *ctx, char *name)
                    218: {
                    219:        array_t *sections = (array_t*)ctx->context;
                    220:        section_t *section;
                    221: 
                    222:        section = settings_section_create(name);
                    223:        array_insert(sections, ARRAY_TAIL, section);
                    224:        return section;
                    225: }
                    226: 
                    227: /**
                    228:  * Removes the top section of the stack and returns it
                    229:  */
                    230: static section_t *pop_section(parser_helper_t *ctx)
                    231: {
                    232:        array_t *sections = (array_t*)ctx->context;
                    233:        section_t *section;
                    234: 
                    235:        array_remove(sections, ARRAY_TAIL, &section);
                    236:        return section;
                    237: }
                    238: 
                    239: /**
                    240:  * Adds the given section to the section on top of the stack
                    241:  */
                    242: static void add_section(parser_helper_t *ctx, section_t *section)
                    243: {
                    244:        array_t *sections = (array_t*)ctx->context;
                    245:        section_t *parent;
                    246: 
                    247:        array_get(sections, ARRAY_TAIL, &parent);
                    248:        settings_section_add(parent, section, NULL);
                    249: }
                    250: 
                    251: /**
                    252:  * Adds the given key/value pair to the section on top of the stack
                    253:  */
                    254: static void add_setting(parser_helper_t *ctx, kv_t *kv)
                    255: {
                    256:        array_t *sections = (array_t*)ctx->context;
                    257:        section_t *section;
                    258: 
                    259:        array_get(sections, ARRAY_TAIL, &section);
                    260:        settings_kv_add(section, kv, NULL);
                    261: }
                    262: 
                    263: /**
                    264:  * Adds the given references to the section on top of the stack
                    265:  */
                    266: static void add_references(parser_helper_t *ctx, array_t *references)
                    267: {
                    268:        array_t *sections = (array_t*)ctx->context;
                    269:        section_t *section;
                    270:        enumerator_t *refs;
                    271:        char *ref;
                    272: 
                    273:        array_get(sections, ARRAY_TAIL, &section);
                    274: 
                    275:        refs = array_create_enumerator(references);
                    276:        while (refs->enumerate(refs, &ref))
                    277:        {
                    278:                settings_reference_add(section, ref, FALSE);
                    279:                array_remove_at(references, refs);
                    280:        }
                    281:        refs->destroy(refs);
                    282: }
                    283: 
                    284: /**
                    285:  * Parse the given file and add all sections and key/value pairs to the
                    286:  * given section.
                    287:  */
                    288: bool settings_parser_parse_file(section_t *root, char *name)
                    289: {
                    290:        parser_helper_t *helper;
                    291:        array_t *sections = NULL;
                    292:        bool success = FALSE;
                    293: 
                    294:        array_insert_create(&sections, ARRAY_TAIL, root);
                    295:        helper = parser_helper_create(sections);
                    296:        helper->get_lineno = settings_parser_get_lineno;
                    297:        if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
                    298:        {
                    299:                helper->destroy(helper);
                    300:                array_destroy(sections);
                    301:                return FALSE;
                    302:        }
                    303:        helper->file_include(helper, name);
                    304:        if (!settings_parser_open_next_file(helper))
                    305:        {
                    306:                if (lib->conf && streq(name, lib->conf))
                    307:                {
                    308:                        DBG2(DBG_CFG, "failed to open config file '%s'", name);
                    309:                }
                    310:                else
                    311:                {
                    312:                        DBG1(DBG_CFG, "failed to open config file '%s'", name);
                    313:                }
                    314:        }
                    315:        else
                    316:        {
                    317:                if (getenv("DEBUG_SETTINGS_PARSER"))
                    318:                {
                    319:                        yydebug = 1;
                    320:                        settings_parser_set_debug(1, helper->scanner);
                    321:                }
                    322:                success = yyparse(helper) == 0;
                    323:                if (!success)
                    324:                {
                    325:                        DBG1(DBG_CFG, "invalid config file '%s'", name);
                    326:                }
                    327:        }
                    328:        array_destroy(sections);
                    329:        settings_parser_lex_destroy(helper->scanner);
                    330:        helper->destroy(helper);
                    331:        return success;
                    332: }
                    333: 
                    334: /**
                    335:  * Parse the given string and add all sections and key/value pairs to the
                    336:  * given section.
                    337:  */
                    338: bool settings_parser_parse_string(section_t *root, char *settings)
                    339: {
                    340:        parser_helper_t *helper;
                    341:        array_t *sections = NULL;
                    342:        bool success = FALSE;
                    343: 
                    344:        array_insert_create(&sections, ARRAY_TAIL, root);
                    345:        helper = parser_helper_create(sections);
                    346:        helper->get_lineno = settings_parser_get_lineno;
                    347:        if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
                    348:        {
                    349:                helper->destroy(helper);
                    350:                array_destroy(sections);
                    351:                return FALSE;
                    352:        }
                    353:        settings_parser_load_string(helper, settings);
                    354:        if (getenv("DEBUG_SETTINGS_PARSER"))
                    355:        {
                    356:                yydebug = 1;
                    357:                settings_parser_set_debug(1, helper->scanner);
                    358:        }
                    359:        success = yyparse(helper) == 0;
                    360:        if (!success)
                    361:        {
                    362:                DBG1(DBG_CFG, "failed to parse settings '%s'", settings);
                    363:        }
                    364:        array_destroy(sections);
                    365:        settings_parser_lex_destroy(helper->scanner);
                    366:        helper->destroy(helper);
                    367:        return success;
                    368: }

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