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

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

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