Annotation of embedaddon/strongswan/src/libstrongswan/settings/settings_lexer.l, 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: #include <utils/parser_helper.h>
! 18:
! 19: #include "settings_parser.h"
! 20:
! 21: bool settings_parser_open_next_file(parser_helper_t *ctx);
! 22:
! 23: static void include_files(parser_helper_t *ctx);
! 24:
! 25: %}
! 26: %option debug
! 27: %option warn
! 28:
! 29: /* use start conditions stack */
! 30: %option stack
! 31:
! 32: /* do not declare unneeded functions */
! 33: %option noinput noyywrap
! 34:
! 35: /* do not include unistd.h as it might conflict with our scanner states */
! 36: %option nounistd
! 37: /* due to that disable interactive mode, which requires isatty() */
! 38: %option never-interactive
! 39:
! 40: /* don't use global variables, and interact properly with bison */
! 41: %option reentrant bison-bridge
! 42:
! 43: /* maintain the line number */
! 44: %option yylineno
! 45:
! 46: /* don't generate a default rule */
! 47: %option nodefault
! 48:
! 49: /* prefix function/variable declarations */
! 50: %option prefix="settings_parser_"
! 51: /* don't change the name of the output file otherwise autotools has issues */
! 52: %option outfile="lex.yy.c"
! 53:
! 54: /* type of our extra data */
! 55: %option extra-type="parser_helper_t*"
! 56:
! 57: /* state used to scan references */
! 58: %x ref
! 59: /* state used to scan values */
! 60: %x val
! 61: /* state used to scan include file patterns */
! 62: %x inc
! 63: /* state used to scan quoted strings */
! 64: %x str
! 65:
! 66: /* pattern for section/key names */
! 67: NAME [^#{}:.,="\r\n\t ]
! 68:
! 69: %%
! 70:
! 71: [\t ]*#[^\r\n]* /* eat comments */
! 72: [\t\r ]+ /* eat whitespace */
! 73: \n|#.*\n /* eat newlines and comments at the end of a line */
! 74:
! 75: "{" |
! 76: "}" return yytext[0];
! 77:
! 78: "." return DOT;
! 79: "," return COMMA;
! 80:
! 81: ":" {
! 82: yy_push_state(ref, yyscanner);
! 83: return COLON;
! 84: }
! 85:
! 86: "=" {
! 87: yy_push_state(val, yyscanner);
! 88: return yytext[0];
! 89: }
! 90:
! 91: "include"[\t ]+/[^=] {
! 92: yyextra->string_init(yyextra);
! 93: yy_push_state(inc, yyscanner);
! 94: }
! 95:
! 96: "\"" {
! 97: PARSER_DBG1(yyextra, "unexpected string detected");
! 98: return STRING_ERROR;
! 99: }
! 100:
! 101: {NAME}+ {
! 102: yylval->s = strdup(yytext);
! 103: return NAME;
! 104: }
! 105:
! 106: <ref>{
! 107: [\t ]*#[^\r\n]* /* eat comments */
! 108: [\t\r ]+ /* eat whitespace */
! 109: \n|#.*\n /* eat newlines and comments at the end of a line */
! 110:
! 111: "," return COMMA;
! 112:
! 113: {NAME}+(\.{NAME}+)* {
! 114: yylval->s = strdup(yytext);
! 115: return NAME;
! 116: }
! 117:
! 118: . {
! 119: unput(yytext[0]);
! 120: yy_pop_state(yyscanner);
! 121: }
! 122: }
! 123:
! 124: <val>{
! 125: \r /* just ignore these */
! 126: [\t ]+
! 127: <<EOF>> |
! 128: [#}\n] {
! 129: if (*yytext)
! 130: {
! 131: switch (yytext[0])
! 132: {
! 133: case '\n':
! 134: /* put the newline back to fix the line numbers */
! 135: unput('\n');
! 136: yy_set_bol(0);
! 137: break;
! 138: case '#':
! 139: case '}':
! 140: /* these are parsed outside of this start condition */
! 141: unput(yytext[0]);
! 142: break;
! 143: }
! 144: }
! 145: yy_pop_state(yyscanner);
! 146: return NEWLINE;
! 147: }
! 148:
! 149: "\"" {
! 150: yyextra->string_init(yyextra);
! 151: yy_push_state(str, yyscanner);
! 152: }
! 153:
! 154: /* same as above, but allow more characters */
! 155: [^#}"\r\n\t ]+ {
! 156: yylval->s = strdup(yytext);
! 157: return NAME;
! 158: }
! 159: }
! 160:
! 161: <inc>{
! 162: \r /* just ignore these */
! 163: /* we allow all characters except #, } and spaces, they can be escaped */
! 164: <<EOF>> |
! 165: [#}\n\t ] {
! 166: if (*yytext)
! 167: {
! 168: switch (yytext[0])
! 169: {
! 170: case '\n':
! 171: /* put the newline back to fix the line numbers */
! 172: unput('\n');
! 173: yy_set_bol(0);
! 174: break;
! 175: case '#':
! 176: case '}':
! 177: /* these are parsed outside of this start condition */
! 178: unput(yytext[0]);
! 179: break;
! 180: }
! 181: }
! 182: include_files(yyextra);
! 183: yy_pop_state(yyscanner);
! 184: }
! 185: "\"" { /* string include */
! 186: yy_push_state(str, yyscanner);
! 187: }
! 188: \\ {
! 189: yyextra->string_add(yyextra, yytext);
! 190: }
! 191: \\["#} ] {
! 192: yyextra->string_add(yyextra, yytext+1);
! 193: }
! 194: [^"\\#}\r\n\t ]+ {
! 195: yyextra->string_add(yyextra, yytext);
! 196: }
! 197: }
! 198:
! 199: <str>{
! 200: \r /* just ignore these */
! 201: "\"" |
! 202: <<EOF>> |
! 203: \\ {
! 204: if (!streq(yytext, "\""))
! 205: {
! 206: PARSER_DBG1(yyextra, "unterminated string detected");
! 207: return STRING_ERROR;
! 208: }
! 209: if (yy_top_state(yyscanner) == inc)
! 210: { /* string include */
! 211: include_files(yyextra);
! 212: yy_pop_state(yyscanner);
! 213: yy_pop_state(yyscanner);
! 214: }
! 215: else
! 216: {
! 217: yy_pop_state(yyscanner);
! 218: yylval->s = yyextra->string_get(yyextra);
! 219: return STRING;
! 220: }
! 221: }
! 222:
! 223: \\n yyextra->string_add(yyextra, "\n");
! 224: \\r yyextra->string_add(yyextra, "\r");
! 225: \\t yyextra->string_add(yyextra, "\t");
! 226: \\\r?\n /* merge lines that end with escaped EOL characters */
! 227: \\. yyextra->string_add(yyextra, yytext+1);
! 228: [^\\\r"]+ {
! 229: yyextra->string_add(yyextra, yytext);
! 230: }
! 231: }
! 232:
! 233: <<EOF>> {
! 234: settings_parser_pop_buffer_state(yyscanner);
! 235: if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
! 236: {
! 237: yyterminate();
! 238: }
! 239: }
! 240:
! 241: %%
! 242:
! 243: /**
! 244: * Open the next file, if any is queued and readable, otherwise returns FALSE.
! 245: */
! 246: bool settings_parser_open_next_file(parser_helper_t *ctx)
! 247: {
! 248: FILE *file;
! 249:
! 250: file = ctx->file_next(ctx);
! 251: if (!file)
! 252: {
! 253: return FALSE;
! 254: }
! 255:
! 256: settings_parser_set_in(file, ctx->scanner);
! 257: settings_parser_push_buffer_state(
! 258: settings_parser__create_buffer(file, YY_BUF_SIZE,
! 259: ctx->scanner), ctx->scanner);
! 260: return TRUE;
! 261: }
! 262:
! 263: /**
! 264: * Assumes that the file pattern to include is currently stored as string on
! 265: * the helper object.
! 266: */
! 267: static void include_files(parser_helper_t *ctx)
! 268: {
! 269: char *pattern = ctx->string_get(ctx);
! 270:
! 271: ctx->file_include(ctx, pattern);
! 272: free(pattern);
! 273:
! 274: settings_parser_open_next_file(ctx);
! 275: }
! 276:
! 277: /**
! 278: * Load the given string to be parsed next
! 279: */
! 280: void settings_parser_load_string(parser_helper_t *ctx, const char *content)
! 281: {
! 282: settings_parser__scan_string(content, ctx->scanner);
! 283: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>