Annotation of embedaddon/strongswan/src/starter/parser/parser.y, revision 1.1

1.1     ! misho       1: %{
        !             2: /*
        !             3:  * Copyright (C) 2013-2014 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 <utils/parser_helper.h>
        !            21: #include <settings/settings_types.h>
        !            22: #include <parser/conf_parser.h>
        !            23: 
        !            24: #include "parser.h"
        !            25: 
        !            26: #define YYDEBUG 1
        !            27: 
        !            28: /**
        !            29:  * Defined by the lexer
        !            30:  */
        !            31: int conf_parser_lex(YYSTYPE *lvalp, void *scanner);
        !            32: int conf_parser_lex_init_extra(parser_helper_t *extra, void *scanner);
        !            33: int conf_parser_lex_destroy(void *scanner);
        !            34: int conf_parser_set_in(FILE *in, void *scanner);
        !            35: void conf_parser_set_debug(int debug, void *scanner);
        !            36: char *conf_parser_get_text(void *scanner);
        !            37: int conf_parser_get_leng(void *scanner);
        !            38: int conf_parser_get_lineno(void *scanner);
        !            39: /* Custom functions in lexer */
        !            40: bool conf_parser_open_next_file(parser_helper_t *ctx);
        !            41: 
        !            42: /**
        !            43:  * Forward declaration
        !            44:  */
        !            45: static void conf_parser_error(parser_helper_t *ctx, const char *s);
        !            46: 
        !            47: /**
        !            48:  * Make sure to call lexer with the proper context
        !            49:  */
        !            50: #undef yylex
        !            51: static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
        !            52: {
        !            53:        return conf_parser_lex(lvalp, ctx->scanner);
        !            54: }
        !            55: 
        !            56: %}
        !            57: %debug
        !            58: 
        !            59: /* generate verbose error messages */
        !            60: %error-verbose
        !            61: /* generate a reentrant parser */
        !            62: %define api.pure
        !            63: /* prefix function/variable declarations */
        !            64: %name-prefix "conf_parser_"
        !            65: 
        !            66: /* interact properly with the reentrant lexer */
        !            67: %lex-param {parser_helper_t *ctx}
        !            68: %parse-param {parser_helper_t *ctx}
        !            69: 
        !            70: /* types for terminal symbols... */
        !            71: %union {
        !            72:        char *s;
        !            73:        conf_parser_section_t t;
        !            74: }
        !            75: %token <s> STRING
        !            76: %token EQ SPACES NEWLINE CONFIG_SETUP CONN CA STRING_ERROR
        !            77: 
        !            78: /* ...and other symbols */
        !            79: %type <t> section_type
        !            80: %type <s> section_name value
        !            81: 
        !            82: /* make the equal sign left associative */
        !            83: %left EQ
        !            84: 
        !            85: /* properly destroy STRING tokens, which are strdup()ed, on errors */
        !            86: %destructor { free($$); } STRING section_name value
        !            87: 
        !            88: /* there are two shift/reduce conflicts because we allow empty lines (and lines
        !            89:  * with spaces) within settings and anywhere else (i.e. in the beginning) */
        !            90: //%expect 2
        !            91: 
        !            92: %%
        !            93: 
        !            94: /**
        !            95:  * ipsec.conf grammar rules
        !            96:  */
        !            97: statements:
        !            98:        /* empty */
        !            99:        | statements NEWLINE
        !           100:        | statements statement
        !           101:        ;
        !           102: 
        !           103: statement:
        !           104:        section
        !           105:        | SPACES setting
        !           106:        ;
        !           107: 
        !           108: section:
        !           109:        section_type section_name
        !           110:        {
        !           111:                if ($1 != CONF_PARSER_CONFIG_SETUP && (!$2 || !strlen($2)))
        !           112:                {
        !           113:                        PARSER_DBG1(ctx, "section name missing");
        !           114:                        free($2);
        !           115:                        YYERROR;
        !           116:                }
        !           117:                conf_parser_t *parser = (conf_parser_t*)ctx->context;
        !           118:                parser->add_section(parser, $1, $2);
        !           119:        }
        !           120:        ;
        !           121: 
        !           122: section_type:
        !           123:        CONFIG_SETUP
        !           124:        {
        !           125:                $$ = CONF_PARSER_CONFIG_SETUP;
        !           126:        }
        !           127:        |
        !           128:        CONN
        !           129:        {
        !           130:                $$ = CONF_PARSER_CONN;
        !           131:        }
        !           132:        |
        !           133:        CA
        !           134:        {
        !           135:                $$ = CONF_PARSER_CA;
        !           136:        }
        !           137:        ;
        !           138: 
        !           139: section_name:
        !           140:        /* empty */
        !           141:        {
        !           142:                $$ = NULL;
        !           143:        }
        !           144:        | STRING
        !           145:        {
        !           146:                $$ = $1;
        !           147:        }
        !           148:        ;
        !           149: 
        !           150: setting:
        !           151:        /* empty */
        !           152:        |
        !           153:        STRING EQ value
        !           154:        {
        !           155:                if (!strlen($1))
        !           156:                {
        !           157:                        PARSER_DBG1(ctx, "setting name can't be empty");
        !           158:                        free($1);
        !           159:                        free($3);
        !           160:                        YYERROR;
        !           161:                }
        !           162:                conf_parser_t *parser = (conf_parser_t*)ctx->context;
        !           163:                parser->add_setting(parser, $1, $value);
        !           164:        }
        !           165:        |
        !           166:        STRING EQ
        !           167:        {
        !           168:                if (!strlen($1))
        !           169:                {
        !           170:                        PARSER_DBG1(ctx, "setting name can't be empty");
        !           171:                        free($1);
        !           172:                        YYERROR;
        !           173:                }
        !           174:                conf_parser_t *parser = (conf_parser_t*)ctx->context;
        !           175:                parser->add_setting(parser, $1, NULL);
        !           176:        }
        !           177:        |
        !           178:        STRING
        !           179:        {
        !           180:                PARSER_DBG1(ctx, "missing value for setting '%s'", $1);
        !           181:                free($1);
        !           182:                YYERROR;
        !           183:        }
        !           184:        ;
        !           185: 
        !           186: value:
        !           187:        STRING
        !           188:        | value STRING
        !           189:        {       /* just put a single space between them, use strings for more */
        !           190:                if (asprintf(&$$, "%s %s", $1, $2) < 0)
        !           191:                {
        !           192:                        free($1);
        !           193:                        free($2);
        !           194:                        YYERROR;
        !           195:                }
        !           196:                free($1);
        !           197:                free($2);
        !           198:        }
        !           199:        ;
        !           200: 
        !           201: %%
        !           202: 
        !           203: /**
        !           204:  * Referenced by the generated parser
        !           205:  */
        !           206: static void conf_parser_error(parser_helper_t *ctx, const char *s)
        !           207: {
        !           208:        char *text = conf_parser_get_text(ctx->scanner);
        !           209:        int len = conf_parser_get_leng(ctx->scanner);
        !           210: 
        !           211:        if (len && text[len-1] == '\n')
        !           212:        {       /* cut off newline at the end to avoid muti-line log messages */
        !           213:                len--;
        !           214:        }
        !           215:        PARSER_DBG1(ctx, "%s [%.*s]", s, (int)len, text);
        !           216: }
        !           217: 
        !           218: /**
        !           219:  * Parse the given file
        !           220:  */
        !           221: bool conf_parser_parse_file(conf_parser_t *this, char *name)
        !           222: {
        !           223:        parser_helper_t *helper;
        !           224:        bool success = FALSE;
        !           225: 
        !           226:        helper = parser_helper_create(this);
        !           227:        helper->get_lineno = conf_parser_get_lineno;
        !           228:        if (conf_parser_lex_init_extra(helper, &helper->scanner) != 0)
        !           229:        {
        !           230:                helper->destroy(helper);
        !           231:                return FALSE;
        !           232:        }
        !           233:        helper->file_include(helper, name);
        !           234:        if (!conf_parser_open_next_file(helper))
        !           235:        {
        !           236:                DBG1(DBG_CFG, "failed to open config file '%s'", name);
        !           237:        }
        !           238:        else
        !           239:        {
        !           240:                if (getenv("DEBUG_CONF_PARSER"))
        !           241:                {
        !           242:                        yydebug = 1;
        !           243:                        conf_parser_set_debug(1, helper->scanner);
        !           244:                }
        !           245:                success = yyparse(helper) == 0;
        !           246:                if (!success)
        !           247:                {
        !           248:                        DBG1(DBG_CFG, "invalid config file '%s'", name);
        !           249:                }
        !           250:        }
        !           251:        conf_parser_lex_destroy(helper->scanner);
        !           252:        helper->destroy(helper);
        !           253:        return success;
        !           254: }

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