Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_parser.y, revision 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>