aboutsummaryrefslogtreecommitdiff
path: root/src/meta1lex.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/meta1lex.l')
-rw-r--r--src/meta1lex.l231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/meta1lex.l b/src/meta1lex.l
new file mode 100644
index 0000000..312a1fd
--- /dev/null
+++ b/src/meta1lex.l
@@ -0,0 +1,231 @@
+%{
+/* 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 <http://www.gnu.org/licenses/>. */
+
+/* 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);
+<COMMENT>[^*\n]* /* eat anything that's not a '*' */
+<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
+<COMMENT>\n ++meta1_locus.line;
+<COMMENT>"*"+"/" 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); }
+<STR>[^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex (yytext, yyleng); }
+<STR>[^\\"\n]*\\. { meta1_line_add_unescape_last (yytext, yyleng); }
+<STR>[^\\"\n]*\" { BEGIN (INITIAL);
+ if (yyleng > 1)
+ meta1_line_add (yytext, yyleng - 1);
+ yylval.string = meta1_line_finish ();
+ return META1_STRING; }
+<STR>[^\\"\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;
+}
+
+
+
+

Return to:

Send suggestions and report system problems to the System administrator.