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

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
1.1.1.2 ! misho      58: static int yylex(SETTINGS_PARSER_STYPE *yylval, parser_helper_t *ctx)
1.1       misho      59: {
1.1.1.2 ! misho      60:        return settings_parser_lex(yylval, ctx->scanner);
1.1       misho      61: }
                     62: 
                     63: %}
                     64: %debug
                     65: 
                     66: /* generate verbose error messages */
1.1.1.2 ! misho      67: %define parse.error verbose
1.1       misho      68: /* generate a reentrant parser */
                     69: %define api.pure
                     70: /* prefix function/variable declarations */
1.1.1.2 ! misho      71: %define api.prefix {settings_parser_}
        !            72: /* make sure flex uses the right definition */
        !            73: %code provides
        !            74: {
        !            75:        #define YY_DECL \
        !            76:                int settings_parser_lex(SETTINGS_PARSER_STYPE *yylval, void *yyscanner)
        !            77:        YY_DECL;
        !            78: }
1.1       misho      79: 
                     80: /* interact properly with the reentrant lexer */
                     81: %lex-param {parser_helper_t *ctx}
                     82: %parse-param {parser_helper_t *ctx}
                     83: 
                     84: /* types for terminal symbols... (can't use the typedef'd types) */
                     85: %union {
                     86:        char *s;
                     87:        struct section_t *sec;
                     88:        struct kv_t *kv;
                     89:        array_t *refs;
                     90: }
                     91: %token <s> NAME STRING
                     92: %token DOT "."
                     93: %token COMMA ","
                     94: %token COLON ":"
                     95: %token NEWLINE STRING_ERROR
                     96: 
                     97: /* ...and other symbols */
                     98: %type <s> value valuepart
                     99: %type <sec> section_start section
                    100: %type <kv> setting
                    101: %type <refs> references
                    102: 
                    103: /* properly destroy string tokens that are strdup()ed on error */
                    104: %destructor { free($$); } NAME STRING value valuepart
                    105: /* properly destroy parse results on error */
                    106: %destructor { pop_section(ctx); settings_section_destroy($$, NULL); } section_start section
                    107: %destructor { settings_kv_destroy($$, NULL); } setting
                    108: %destructor { array_destroy_function($$, (void*)free, NULL); } references
                    109: 
                    110: /* there are two shift/reduce conflicts because of the "NAME = NAME" and
                    111:  * "NAME {" ambiguity, and the "NAME =" rule) */
                    112: %expect 2
                    113: 
                    114: %%
                    115: 
                    116: /**
                    117:  * strongswan.conf grammar rules
                    118:  */
                    119: statements:
                    120:        /* empty */
                    121:        | statements NEWLINE
                    122:        | statements statement
                    123:        ;
                    124: 
                    125: statement:
                    126:        section
                    127:        {
                    128:                add_section(ctx, $section);
                    129:        }
                    130:        | setting
                    131:        {
                    132:                add_setting(ctx, $setting);
                    133:        }
                    134:        ;
                    135: 
                    136: section:
                    137:        section_start statements '}'
                    138:        {
                    139:                pop_section(ctx);
                    140:                $$ = $section_start;
                    141:        }
                    142:        ;
                    143: 
                    144: section_start:
                    145:        NAME '{'
                    146:        {
                    147:                $$ = push_section(ctx, $NAME);
                    148:        }
                    149:        |
                    150:        NAME ":" references '{'
                    151:        {
                    152:                $$ = push_section(ctx, $NAME);
                    153:                add_references(ctx, $references);
                    154:                array_destroy($references);
                    155:        }
                    156:        ;
                    157: 
                    158: references:
                    159:        NAME
                    160:        {
                    161:                $$ = array_create(0, 0);
                    162:                array_insert($$, ARRAY_TAIL, $1);
                    163:        }
                    164:        | references "," NAME
                    165:        {
                    166:                array_insert($1, ARRAY_TAIL, $3);
                    167:                $$ = $1;
                    168:        }
                    169:        ;
                    170: 
                    171: setting:
                    172:        NAME '=' value
                    173:        {
                    174:                $$ = settings_kv_create($NAME, $value);
                    175:        }
                    176:        |
                    177:        NAME '='
                    178:        {
                    179:                $$ = settings_kv_create($NAME, NULL);
                    180:        }
                    181:        ;
                    182: 
                    183: value:
                    184:        valuepart
                    185:        | value valuepart
                    186:        {       /* just put a single space between them, use strings for more */
                    187:                if (asprintf(&$$, "%s %s", $1, $2) < 0)
                    188:                {
                    189:                        free($1);
                    190:                        free($2);
                    191:                        YYERROR;
                    192:                }
                    193:                free($1);
                    194:                free($2);
                    195:        }
                    196:        ;
                    197: 
                    198: valuepart:
                    199:        NAME
                    200:        | STRING
                    201:        ;
                    202: 
                    203: %%
                    204: 
                    205: /**
                    206:  * Referenced by the generated parser
                    207:  */
                    208: static void settings_parser_error(parser_helper_t *ctx, const char *s)
                    209: {
                    210:        char *text = settings_parser_get_text(ctx->scanner);
                    211:        int len = settings_parser_get_leng(ctx->scanner);
                    212: 
                    213:        if (len && text[len-1] == '\n')
                    214:        {       /* cut off newline at the end to avoid muti-line log messages */
                    215:                len--;
                    216:        }
                    217:        PARSER_DBG1(ctx, "%s [%.*s]", s, len, text);
                    218: }
                    219: 
                    220: /**
                    221:  * Create a section and push it to the stack (the name is adopted), returns
                    222:  * the created section
                    223:  */
                    224: static section_t *push_section(parser_helper_t *ctx, char *name)
                    225: {
                    226:        array_t *sections = (array_t*)ctx->context;
                    227:        section_t *section;
                    228: 
                    229:        section = settings_section_create(name);
                    230:        array_insert(sections, ARRAY_TAIL, section);
                    231:        return section;
                    232: }
                    233: 
                    234: /**
                    235:  * Removes the top section of the stack and returns it
                    236:  */
                    237: static section_t *pop_section(parser_helper_t *ctx)
                    238: {
                    239:        array_t *sections = (array_t*)ctx->context;
                    240:        section_t *section;
                    241: 
                    242:        array_remove(sections, ARRAY_TAIL, &section);
                    243:        return section;
                    244: }
                    245: 
                    246: /**
                    247:  * Adds the given section to the section on top of the stack
                    248:  */
                    249: static void add_section(parser_helper_t *ctx, section_t *section)
                    250: {
                    251:        array_t *sections = (array_t*)ctx->context;
                    252:        section_t *parent;
                    253: 
                    254:        array_get(sections, ARRAY_TAIL, &parent);
                    255:        settings_section_add(parent, section, NULL);
                    256: }
                    257: 
                    258: /**
                    259:  * Adds the given key/value pair to the section on top of the stack
                    260:  */
                    261: static void add_setting(parser_helper_t *ctx, kv_t *kv)
                    262: {
                    263:        array_t *sections = (array_t*)ctx->context;
                    264:        section_t *section;
                    265: 
                    266:        array_get(sections, ARRAY_TAIL, &section);
                    267:        settings_kv_add(section, kv, NULL);
                    268: }
                    269: 
                    270: /**
                    271:  * Adds the given references to the section on top of the stack
                    272:  */
                    273: static void add_references(parser_helper_t *ctx, array_t *references)
                    274: {
                    275:        array_t *sections = (array_t*)ctx->context;
                    276:        section_t *section;
                    277:        enumerator_t *refs;
                    278:        char *ref;
                    279: 
                    280:        array_get(sections, ARRAY_TAIL, &section);
                    281: 
                    282:        refs = array_create_enumerator(references);
                    283:        while (refs->enumerate(refs, &ref))
                    284:        {
                    285:                settings_reference_add(section, ref, FALSE);
                    286:                array_remove_at(references, refs);
                    287:        }
                    288:        refs->destroy(refs);
                    289: }
                    290: 
                    291: /**
                    292:  * Parse the given file and add all sections and key/value pairs to the
                    293:  * given section.
                    294:  */
                    295: bool settings_parser_parse_file(section_t *root, char *name)
                    296: {
                    297:        parser_helper_t *helper;
                    298:        array_t *sections = NULL;
                    299:        bool success = FALSE;
                    300: 
                    301:        array_insert_create(&sections, ARRAY_TAIL, root);
                    302:        helper = parser_helper_create(sections);
                    303:        helper->get_lineno = settings_parser_get_lineno;
                    304:        if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
                    305:        {
                    306:                helper->destroy(helper);
                    307:                array_destroy(sections);
                    308:                return FALSE;
                    309:        }
                    310:        helper->file_include(helper, name);
                    311:        if (!settings_parser_open_next_file(helper))
                    312:        {
                    313:                if (lib->conf && streq(name, lib->conf))
                    314:                {
                    315:                        DBG2(DBG_CFG, "failed to open config file '%s'", name);
                    316:                }
                    317:                else
                    318:                {
                    319:                        DBG1(DBG_CFG, "failed to open config file '%s'", name);
                    320:                }
                    321:        }
                    322:        else
                    323:        {
                    324:                if (getenv("DEBUG_SETTINGS_PARSER"))
                    325:                {
                    326:                        yydebug = 1;
                    327:                        settings_parser_set_debug(1, helper->scanner);
                    328:                }
                    329:                success = yyparse(helper) == 0;
                    330:                if (!success)
                    331:                {
                    332:                        DBG1(DBG_CFG, "invalid config file '%s'", name);
                    333:                }
                    334:        }
                    335:        array_destroy(sections);
                    336:        settings_parser_lex_destroy(helper->scanner);
                    337:        helper->destroy(helper);
                    338:        return success;
                    339: }
                    340: 
                    341: /**
                    342:  * Parse the given string and add all sections and key/value pairs to the
                    343:  * given section.
                    344:  */
                    345: bool settings_parser_parse_string(section_t *root, char *settings)
                    346: {
                    347:        parser_helper_t *helper;
                    348:        array_t *sections = NULL;
                    349:        bool success = FALSE;
                    350: 
                    351:        array_insert_create(&sections, ARRAY_TAIL, root);
                    352:        helper = parser_helper_create(sections);
                    353:        helper->get_lineno = settings_parser_get_lineno;
                    354:        if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
                    355:        {
                    356:                helper->destroy(helper);
                    357:                array_destroy(sections);
                    358:                return FALSE;
                    359:        }
                    360:        settings_parser_load_string(helper, settings);
                    361:        if (getenv("DEBUG_SETTINGS_PARSER"))
                    362:        {
                    363:                yydebug = 1;
                    364:                settings_parser_set_debug(1, helper->scanner);
                    365:        }
                    366:        success = yyparse(helper) == 0;
                    367:        if (!success)
                    368:        {
                    369:                DBG1(DBG_CFG, "failed to parse settings '%s'", settings);
                    370:        }
                    371:        array_destroy(sections);
                    372:        settings_parser_lex_destroy(helper->scanner);
                    373:        helper->destroy(helper);
                    374:        return success;
                    375: }

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