%{ /* MeTA1 configuration lexer for Mailfromd. Copyright (C) 2008 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* This file implements a lexical analyzer for MeTA1 main configuration file. */ #include "pies.h" #include "meta1gram.h" #include "meta1lex.h" mu_cfg_locus_t meta1_locus; size_t meta1_error_count; mu_opool_t meta1_pool; char *meta1_queue_dir; #define yylval meta1lval %} %x COMMENT STR X [0-9a-fA-F] %% /* C-style comments */ "/*" BEGIN (COMMENT); [^*\n]* /* eat anything that's not a '*' */ "*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ \n ++meta1_locus.line; "*"+"/" BEGIN (INITIAL); /* End-of-line comments */ #.*\n { meta1_locus.line++; } #.* /* end-of-file comment */; /* Number */ 0[xX]{X}+ | 0[0-7]+ | [1-9][0-9]+ { meta1_line_begin (); meta1_line_add (yytext, yyleng); yylval.string = meta1_line_finish (); return META1_NUMBER; } /* Identifiers (unquoted strings) */ [a-zA-Z0-9_\./:\*-]+ { meta1_line_begin (); meta1_line_add (yytext, yyleng); yylval.string = meta1_line_finish (); return META1_IDENT; } /* Quoted strings */ \"[^\\"\n]*\" { meta1_line_begin (); meta1_line_add (yytext + 1, yyleng - 2); yylval.string = meta1_line_finish (); return META1_STRING; } \"[^\\"\n]*\\x{X}{1,2} { BEGIN(STR); meta1_line_begin (); meta1_line_add_unescape_hex (yytext + 1, yyleng - 1); } \"[^\\"\n]*\\. { BEGIN(STR); meta1_line_begin (); meta1_line_add_unescape_last (yytext + 1, yyleng - 1); } [^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex (yytext, yyleng); } [^\\"\n]*\\. { meta1_line_add_unescape_last (yytext, yyleng); } [^\\"\n]*\" { BEGIN (INITIAL); if (yyleng > 1) meta1_line_add (yytext, yyleng - 1); yylval.string = meta1_line_finish (); return META1_STRING; } [^\\"\n]*\n { BEGIN (INITIAL); meta1_parse_error (_("newline in a string")); meta1_line_add (yytext, yyleng - 1); yylval.string = meta1_line_finish (); return META1_STRING; } /* Other tokens */ [ \t\f][ \t\f]* ; \n { meta1_locus.line++; } [,;{}=] return yytext[0]; . { if (isascii (yytext[0]) && isprint (yytext[0])) meta1_parse_error (_("stray character %c"), yytext[0]); else meta1_parse_error (_("stray character \\%03o"), (unsigned char) yytext[0]); } %% int yywrap () { return 1; } void meta1_line_add (const char *text, size_t len) { mu_opool_append (meta1_pool, text, len); } static void unescape_to_line (int c) { char t; if (c == 'v') t = '\v'; else { t = mu_argcv_unquote_char (c); if (t == c && t != '\\' && t != '\"') meta1_parse_error (_("unknown escape sequence '\\%c'"), c); } mu_opool_append_char (meta1_pool, t); } void meta1_line_add_unescape_last (const char *text, size_t len) { mu_opool_append (meta1_pool, text, len - 2); unescape_to_line (text[len - 1]); } void meta1_line_add_unescape_hex (const char *text, size_t len) { for (; text[len-1] != 'x' && len > 0; len--) ; mu_opool_append (meta1_pool, text, len - 2); mu_opool_append_char (meta1_pool, (char) strtoul (text + len, NULL, 16)); } void meta1_line_begin () { if (!meta1_pool) mu_opool_create (&meta1_pool, 1); else mu_opool_clear (meta1_pool); } char * meta1_line_finish () { mu_opool_append_char (meta1_pool, 0); return mu_opool_finish (meta1_pool, NULL); } char * meta1_string (const char *str, size_t len) { meta1_line_begin (); meta1_line_add (str, len); return meta1_line_finish (); } void meta1_parse_error (const char *fmt, ...) { va_list ap; mu_debug_t debug; mu_diag_get_debug (&debug); mu_debug_printf (debug, 0, "%s:%lu: ", meta1_locus.file, (unsigned long) meta1_locus.line); va_start (ap, fmt); mu_debug_vprintf (debug, 0, fmt, ap); mu_debug_printf (debug, 0, "\n"); va_end (ap); meta1_error_count++; } void meta1_lexer_set_debug () { mu_log_level_t lev = mu_global_debug_level ("meta1"); yy_flex_debug = (lev & MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE7)); } static int _cfg_default_printer (void *unused, mu_log_level_t level, const char *str) { fprintf (stderr, "%s", str); return 0; } mu_cfg_tree_t *meta1_parse_tree; /* Parse MeTA1 configuration file `name'. Populate `meta1_parse_tree' with the parse tree. */ int meta1_config_parse (const char *name) { int rc; FILE *fp; fp = fopen (name, "r"); if (!fp) { mu_error (_("%s: cannot open file: %s"), name, mu_strerror (errno)); return 1; } meta1_locus.file = meta1_string (name, strlen (name)); meta1_locus.line = 1; meta1_lexer_set_debug (); meta1_parser_set_debug (); yyrestart (fp); rc = meta1parse (); fclose (fp); if (meta1_error_count) rc = 1; if (rc == 0) { meta1_parse_tree = mu_alloc (sizeof (*meta1_parse_tree)); mu_debug_create (&meta1_parse_tree->debug, NULL); mu_debug_set_print (meta1_parse_tree->debug, _cfg_default_printer, NULL); mu_debug_set_level (meta1_parse_tree->debug, mu_global_debug_level ("meta1")); meta1_parse_tree->node = meta1_parse_head; meta1_parse_tree->pool = meta1_pool; } return rc; }