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>