Commit 740b1c84 740b1c8401ec6139449ab717b83232afcb60620b by Sergey Poznyakoff

Added to the repository

1 parent a250bc91
Makefile.in
Makefile
.deps
.libs
.gdbinit
*.la
*.lo
*.output
*.tab.[ch]
# 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
/* 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);
%{
/* 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);
}
%{
/* 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 ();
}
/* 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]);
}
/* 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;
}