summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2002-11-07 14:48:23 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2002-11-07 14:48:23 +0000
commit740b1c8401ec6139449ab717b83232afcb60620b (patch)
tree883acb0cafd3ca057290fd14884812d52467f034
parenta250bc91a29211e4792f2098769363a820b16823 (diff)
downloadmailutils-740b1c8401ec6139449ab717b83232afcb60620b.tar.gz
mailutils-740b1c8401ec6139449ab717b83232afcb60620b.tar.bz2
Added to the repository
-rw-r--r--libsieve/.cvsignore9
-rw-r--r--libsieve/Makefile.am36
-rw-r--r--libsieve/sieve.h30
-rw-r--r--libsieve/sieve.l398
-rw-r--r--libsieve/sieve.y119
-rw-r--r--libsieve/sv.c41
-rw-r--r--libsieve/util.c37
7 files changed, 670 insertions, 0 deletions
diff --git a/libsieve/.cvsignore b/libsieve/.cvsignore
new file mode 100644
index 000000000..91f5ca920
--- /dev/null
+++ b/libsieve/.cvsignore
@@ -0,0 +1,9 @@
+Makefile.in
+Makefile
+.deps
+.libs
+.gdbinit
+*.la
+*.lo
+*.output
+*.tab.[ch]
diff --git a/libsieve/Makefile.am b/libsieve/Makefile.am
new file mode 100644
index 000000000..4ce0bd5d6
--- /dev/null
+++ b/libsieve/Makefile.am
@@ -0,0 +1,36 @@
+# This file is part of GNU Mailutils
+# Copyright (C) 2000,2001,2002 Free Software Foundation
+# See file COPYING in the distribution root directory for copying conditions.
+
+INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/lib
+YLWRAP = $(SHELL) $(top_srcdir)/scripts/ylwrap
+AM_YFLAGS = -dtv
+
+lib_LTLIBRARIES = libsieve.la
+
+noinst_PROGRAMS = sv
+
+libsieve_la_SOURCES = sieve-gram.c sieve-gram.h sieve-lex.c util.c
+sv_SOURCES = sv.c
+sv_LDADD = ./libsieve.la ../mailbox/libmailbox.la
+noinst_HEADERS = sieve.h
+
+BUILT_SOURCES= \
+ sieve-gram.c sieve-gram.h \
+ sieve-lex.c
+
+MAINTAINERCLEANFILES=$(BUILT_SOURCES)
+
+EXTRA_DIST = sieve.y sieve.l
+
+sieve-lex.c: $(srcdir)/sieve.l sieve-gram.h
+ $(YLWRAP) "$(LEX) $(AM_LEXFLAGS) $(LEXFLAGS)" \
+ $(srcdir)/sieve.l lex.yy.c sieve-lex.c \
+ -- -yy sieve_yy
+
+sieve-gram.c sieve-gram.h: $(srcdir)/sieve.y
+ $(YLWRAP) "$(YACC) $(AM_YFLAGS) $(YFLAGS)" $(srcdir)/sieve.y \
+ y.tab.c sieve-gram.c y.tab.h sieve-gram.h y.output y.output \
+ -- -yy sieve_yy
+
+
diff --git a/libsieve/sieve.h b/libsieve/sieve.h
new file mode 100644
index 000000000..68c631f94
--- /dev/null
+++ b/libsieve/sieve.h
@@ -0,0 +1,30 @@
+/* GNU mailutils - a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ 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 2, 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+
+#define sieve_error mu_error
+
+extern char *sieve_filename;
+extern int sieve_line_num;
+extern int sieve_yydebug;
+
+void *sieve_alloc (size_t size);
+
+int sieve_open_source (const char *name);
+
+int sieve_parse (const char *name);
diff --git a/libsieve/sieve.l b/libsieve/sieve.l
new file mode 100644
index 000000000..4e1d10dbb
--- /dev/null
+++ b/libsieve/sieve.l
@@ -0,0 +1,398 @@
+%{
+/* GNU mailutils - a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ 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 2, 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <sieve.h>
+#include <sieve-gram.h>
+
+
+char *sieve_filename;
+int sieve_line_num;
+ino_t sieve_source_inode;
+
+#ifdef FLEX_SCANNER
+#define xinput() (yyin ? getc(yyin) : EOF)
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) do { \
+ int i; \
+ for (i = 0; i < max_size; i++) { \
+ int ch = xinput(); \
+ if (ch == EOF) \
+ break; \
+ buf[i] = ch; \
+ } \
+ result = i; \
+} while (0)
+#define LEX_BUFFER_STATE YY_BUFFER_STATE
+#define SET_BUFFER_STATE(s) do { \
+ (s) = YY_CURRENT_BUFFER; \
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); \
+} while (0)
+#define RESTORE_BUFFER_STATE(s) do { \
+ yy_delete_buffer(YY_CURRENT_BUFFER); \
+ yy_switch_to_buffer(s); \
+} while (0)
+
+#else
+/* AT&T Lex */
+
+static void lex_set_buffer __P((FILE *fp));
+static void lex_delete_buffer __P((LEX_BUFFER_STATE buf));
+static int xinput __P((void));
+static int xunput __P((void));
+
+#undef unput
+#define unput(c) xunput(c)
+#undef input
+#define input() xinput()
+
+#define LEX_BUF_SIZE 16384
+#define LEX_PUTBACK_SIZE 32
+
+typedef struct {
+ FILE *yyin;
+ char *buffer;
+ size_t bufsize;
+ size_t level;
+ char *ptr;
+ char *putback;
+ size_t pb_size;
+ size_t pb_level;
+} LEX_BUFFER_STATE;
+LEX_BUFFER_STATE current_buffer;
+
+#define SET_BUFFER_STATE(s) do { \
+ (s) = current_buffer; \
+ lex_set_buffer(yyin); \
+} while (0)
+#define RESTORE_BUFFER_STATE(s) do { \
+ lex_delete_buffer(current_buffer); \
+ current_buffer = (s); \
+ yyin = current_buffer.yyin; \
+} while (0)
+
+void
+lex_set_buffer (FILE *fp)
+{
+ char *buf;
+ size_t size;
+
+ for (size = LEX_BUF_SIZE; size > 1; size /= 2)
+ if (buf = malloc (size))
+ break;
+
+ if (!buf)
+ {
+ sieve_error ("not enough memory");
+ abort ();
+ }
+
+ current_buffer.yyin = yyin;
+ current_buffer.buffer = buf;
+ current_buffer.bufsize = size;
+ current_buffer.level = 0;
+ current_buffer.ptr = current_buffer.buffer;
+ current_buffer.pb_size = current_buffer.pb_level = 0;
+ current_buffer.putback = NULL;
+}
+
+void
+lex_delete_buffer (LEX_BUFFER_STATE buf)
+{
+ free (buf.buffer);
+ if (buf.putback)
+ free (buf.putback);
+}
+
+int
+xinput ()
+{
+ if (!yyin)
+ return EOF;
+
+ if (current_buffer.pb_level)
+ return current_buffer.putback[--current_buffer.pb_level];
+
+ if (current_buffer.level <= 0)
+ {
+ int n;
+
+ if (feof (yyin))
+ return 0;
+ n = fread (current_buffer.buffer, 1,
+ current_buffer.bufsize, yyin);
+ if (n <= 0)
+ return 0;
+ current_buffer.level = n;
+ current_buffer.ptr = current_buffer.buffer;
+ }
+ current_buffer.level--;
+ return *current_buffer.ptr++;
+}
+
+int
+xunput (int c)
+{
+ if (current_buffer.pb_level == current_buffer.pb_size)
+ {
+ char *putback;
+ current_buffer.pb_size += LEX_PUTBACK_SIZE;
+ putback = sieve_alloc (current_buffer.pb_size);
+ memcpy (putback, current_buffer.putback,
+ current_buffer.pb_level);
+ free (current_buffer.putback);
+ current_buffer.putback = putback;
+ }
+ current_buffer.putback[current_buffer.pb_level++] = c;
+ return c;
+}
+
+#endif
+
+struct buffer_ctx {
+ struct buffer_ctx *prev;
+ char *filename;
+ int line;
+ ino_t i_node;
+ FILE *yyin;
+ LEX_BUFFER_STATE state;
+};
+
+static struct buffer_ctx *context_stack;
+
+static struct buffer_ctx *ctx_lookup __P((ino_t ino));
+static int push_source __P((char *name));
+static int pop_source __P((void));
+
+struct buffer_ctx *
+ctx_lookup (ino_t ino)
+{
+ struct buffer_ctx *ctx;
+
+ for (ctx = context_stack; ctx; ctx = ctx->prev)
+ if (ctx->i_node == ino)
+ break;
+ return ctx;
+}
+
+int
+push_source (char *name)
+{
+ FILE *fp;
+ struct buffer_ctx *ctx;
+ struct stat st;
+
+ if (stat (name, &st))
+ {
+ sieve_error ("can't stat `%s': %s", name, strerror (errno));
+ yyerror ("can't include file");
+ return 1;
+ }
+
+ if (sieve_filename && st.st_ino == sieve_source_inode)
+ {
+ yyerror ("recursive inclusion");
+ return 1;
+ }
+ if (ctx = ctx_lookup (st.st_ino))
+ {
+ yyerror ("recursive inclusion");
+ if (ctx->prev)
+ sieve_error ("%s:%d: `%s' already included here",
+ ctx->prev->filename, ctx->prev->line, name);
+ else
+ sieve_error ("`%s' already included at top level",
+ name);
+ return 1;
+ }
+
+ fp = fopen (name, "r");
+ if (!fp)
+ {
+ sieve_error ("can't open `%s': %s", name, strerror (errno));
+ yyerror ("can't include file");
+ return 1;
+ }
+
+ /* Push current context */
+ if (sieve_filename)
+ {
+ ctx = sieve_alloc (sizeof (*ctx));
+ ctx->filename = sieve_filename;
+ ctx->line = sieve_line_num;
+ ctx->i_node = sieve_source_inode;
+ ctx->yyin = yyin;
+ ctx->prev = context_stack;
+ context_stack = ctx;
+
+ /* Switch to the new context */
+ yyin = fp;
+ SET_BUFFER_STATE (ctx->state);
+ }
+ else
+ {
+#ifdef FLEX_SCANNER
+ yyrestart (fp);
+#else
+ yyin = fp;
+ lex_set_buffer (yyin);
+#endif
+ }
+ sieve_filename = strdup (name);
+ sieve_line_num = 1;
+ sieve_source_inode = st.st_ino;
+ return 0;
+}
+
+int
+pop_source ()
+{
+ struct buffer_ctx *ctx;
+
+ fclose (yyin);
+#ifndef FLEX_SCANNER
+ lex_delete_buffer (current_buffer);
+#endif
+ if (!context_stack)
+ {
+ yyin = NULL;
+ return 1;
+ }
+ if (sieve_filename)
+ free (sieve_filename);
+ /* Restore previous context */
+ sieve_filename = context_stack->filename;
+ sieve_line_num = context_stack->line + 1; /* #include rule did not increment
+ it */
+ sieve_source_inode = context_stack->i_node;
+ RESTORE_BUFFER_STATE (context_stack->state);
+ ctx = context_stack->prev;
+ free (context_stack);
+ context_stack = ctx;
+ return 0;
+}
+%}
+%x COMMENT ML
+
+WS [ \t][ \t]*
+IDENT [a-zA-Z_][a-zA-Z_0-9]+
+
+%%
+ /* C-style comments */
+"/*" BEGIN(COMMENT);
+<COMMENT>[^*\n]* /* eat anything that's not a '*' */
+<COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
+<COMMENT>\n ++sieve_line_num;
+<COMMENT>"*"+"/" BEGIN(INITIAL);
+ /* Preprocessor directives (an extension) */
+#[ \t]*include.*\n { sieve_include (); }
+ /* End-of-line comments */
+#.*\n { sieve_line_num++; }
+#.* /* end-of-file comment */;
+ /* Reserved words */
+require return REQUIRE;
+if return IF;
+elsif return ELSIF;
+else return ELSE;
+anyof return ANYOF;
+allof return ALLOF;
+true return TRUE;
+false return FALSE;
+not return NOT;
+ /* Other tokens */
+{IDENT} return IDENT;
+:{IDENT} { return TAG; }
+0[0-7]* { return NUMBER; }
+0x[0-9a-fA-F][0-9a-fA-F]+ { return NUMBER; }
+[1-9][0-9]* { return NUMBER; }
+\"[^"\n]*\" { return STRING; }
+text: { BEGIN(ML); }
+<ML>.[ \t]*\n { BEGIN(INITIAL); sieve_line_num++; return MULTILINE; }
+<ML>.*\n { sieve_line_num++; }
+{WS} ;
+\n { sieve_line_num++; }
+. return yytext[0];
+
+%%
+
+int
+yywrap ()
+{
+ return pop_source();
+}
+
+void
+sieve_include ()
+{
+ char *p, *startp, *endp = yytext + yyleng, exp, *name;
+ int n;
+
+ p = strstr (yytext, "include");
+ for (p += 7; p < endp && isspace (*p); p++)
+ ;
+
+ switch (*p)
+ {
+ case '"':
+ exp = '"';
+ break;
+
+ case '<':
+ exp = '>';
+ break;
+
+ default:
+ yyerror ("include syntax");
+ return;
+ }
+
+ for (startp = ++p; p < endp && *p != exp; p++)
+ ;
+
+ if (*p != exp)
+ {
+ yyerror ("missing closing quote in include statement");
+ return;
+ }
+
+ n = p - startp;
+ name = sieve_alloc (n + 1);
+ memcpy (name, startp, n);
+ name[n] = 0;
+
+ push_source (name);
+ free (name);
+}
+
+int
+sieve_open_source (const char *name)
+{
+ return push_source (name);
+}
+
+
+
diff --git a/libsieve/sieve.y b/libsieve/sieve.y
new file mode 100644
index 000000000..1341a5c0c
--- /dev/null
+++ b/libsieve/sieve.y
@@ -0,0 +1,119 @@
+%{
+/* GNU mailutils - a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ 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 2, 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <assert.h>
+#include <sieve.h>
+
+%}
+
+%token IDENT TAG NUMBER STRING MULTILINE
+%token REQUIRE IF ELSIF ELSE ANYOF ALLOF TRUE FALSE NOT
+%%
+
+input : /* empty */
+ | list
+ ;
+
+list : statement
+ | list statement
+ ;
+
+statement : REQUIRE stringlist ';'
+ | action ';'
+ | IF cond block maybe_elsif maybe_else
+ ;
+
+maybe_elsif : /* empty */
+ | elsif
+ ;
+
+elsif : ELSIF cond block
+ | elsif ELSIF cond block
+ ;
+
+maybe_else : /* empty */
+ | ELSE block
+ ;
+
+block : '{' list '}'
+ ;
+
+
+testlist : test
+ | testlist ',' test
+ ;
+
+cond : test
+ | ANYOF '(' testlist ')'
+ | ALLOF '(' testlist ')'
+ | NOT cond
+ ;
+
+test : FALSE
+ | TRUE
+ | command
+ ;
+
+command : IDENT maybe_arglist
+ ;
+
+action : command
+ ;
+
+maybe_arglist: /* empty */
+ | arglist
+ ;
+
+arglist : arg
+ | arglist arg
+ ;
+
+arg : stringlist
+ | MULTILINE
+ | NUMBER
+ | TAG
+ ;
+
+stringlist : STRING
+ | '[' slist ']'
+ ;
+
+slist : STRING
+ | slist ',' STRING
+ ;
+
+%%
+
+int
+yyerror (char *s)
+{
+ fprintf (stderr, "%s:%d: ", sieve_filename, sieve_line_num);
+ fprintf (stderr, "%s\n", s);
+}
+
+int
+sieve_parse (const char *name)
+{
+ sieve_open_source (name);
+ return yyparse ();
+}
+
diff --git a/libsieve/sv.c b/libsieve/sv.c
new file mode 100644
index 000000000..03a9157ec
--- /dev/null
+++ b/libsieve/sv.c
@@ -0,0 +1,41 @@
+/* GNU mailutils - a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ 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 2, 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is just a test program for libsieve. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <assert.h>
+#include <sieve.h>
+
+int
+main (int argc, char **argv)
+{
+ int n;
+
+ assert (argc > 1);
+ if (strcmp (argv[1], "-d") == 0)
+ {
+ sieve_yydebug++;
+ n = 2;
+ assert (argc > 2);
+ }
+ else
+ n = 1;
+ return sieve_parse (argv[n]);
+}
diff --git a/libsieve/util.c b/libsieve/util.c
new file mode 100644
index 000000000..c432876a3
--- /dev/null
+++ b/libsieve/util.c
@@ -0,0 +1,37 @@
+/* GNU mailutils - a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+
+ 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 2, 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sieve.h>
+
+void *
+sieve_alloc (size_t size)
+{
+ char *p = malloc (size);
+ if (!p)
+ {
+ mu_error ("not enough memory");
+ abort ();
+ }
+ return p;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.