Commit 9e863ef5 9e863ef5b4acb7d30672a7313fa04c4f329f8a7a by Sergey Poznyakoff

sieve: rewrite lexer to use MU streams API.

* libmu_sieve/sieve.l (input_string_ptr, input_string_level): Remove.
(input_stream): New static variable.
(fillbuf): Use mu_stream_read
(buffer_ctx)<yyin>: Replace with mu_stream_t input;
(push_source, pop_source): Use stream API.
(mu_sv_lex_begin_string): Likewise.
* sieve/sieve.c (options): New option --expression.
(expression_option): New variable.
(parser): Handle the --expression option.
(main): Treat SCRIPT as program text if given the --expression option.
1 parent c70959ca
......@@ -98,7 +98,7 @@ thunderbird, roundcube.
** implement AUTHENTICATE KERBEROS_V4 and SKEY and SRP?
* Implement extensions:
** Implement extensions:
- QUOTA : RFC 2087
- ACL : RFC 4314
......
......@@ -57,45 +57,44 @@ static void sieve_searchpath (void);
static char *str_unescape (char *text, size_t len);
static int isemptystr (char *text);
static const char *input_string_ptr;
static int input_string_level;
static mu_stream_t input_stream;
static int
fillbuf(char *buf, int max_size)
fillbuf (char *buf, size_t max_size)
{
if (input_string_ptr)
int rc;
if (!input_stream)
return 0;
rc = mu_stream_read (input_stream, buf, max_size, &max_size);
if (rc)
{
int n = input_string_level;
if (n > max_size)
n = max_size;
memcpy (buf, input_string_ptr, n);
input_string_ptr += n;
input_string_level -= n;
return n;
mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read",
mu_sieve_locus.source_file, rc);
return 0;
}
else if (feof (yyin))
return 0;
else
return fread (buf, 1, max_size, yyin);
}
return max_size;
}
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result = fillbuf(buf, max_size)
#define YY_INPUT(buf,result,max_size) result = fillbuf (buf, max_size)
#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)); \
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); \
yy_delete_buffer (YY_CURRENT_BUFFER); \
yy_switch_to_buffer (s); \
} while (0)
struct buffer_ctx {
struct buffer_ctx
{
struct buffer_ctx *prev;
mu_sieve_locus_t locus;
ino_t i_node;
FILE *yyin;
mu_stream_t input;
LEX_BUFFER_STATE state;
};
......@@ -119,7 +118,8 @@ ctx_lookup (ino_t ino)
int
push_source (const char *name)
{
FILE *fp;
int rc;
mu_stream_t stream;
struct buffer_ctx *ctx;
struct stat st;
......@@ -148,13 +148,13 @@ push_source (const char *name)
name);
return 1;
}
fp = fopen (name, "r");
if (!fp)
rc = mu_file_stream_create (&stream, name, MU_STREAM_READ);
if (rc)
{
mu_sv_compile_error (&mu_sieve_locus,
_("cannot open file `%s': %s"),
name, strerror (errno));
name, mu_strerror (rc));
return 1;
}
......@@ -164,16 +164,14 @@ push_source (const char *name)
ctx = mu_sieve_alloc (sizeof (*ctx));
ctx->locus = mu_sieve_locus;
ctx->i_node = sieve_source_inode;
ctx->yyin = yyin;
ctx->input = input_stream;
ctx->prev = context_stack;
context_stack = ctx;
/* Switch to the new context */
yyin = fp;
SET_BUFFER_STATE (ctx->state);
}
else
yyrestart (fp);
input_stream = stream;
mu_sieve_locus.source_file = strdup (name);
mu_sieve_locus.source_line = 1;
......@@ -189,14 +187,13 @@ pop_source ()
{
struct buffer_ctx *ctx;
if (yyin)
fclose (yyin);
mu_stream_destroy (&input_stream);
if (mu_sieve_locus.source_file)
free (mu_sieve_locus.source_file);
if (!context_stack)
{
yyin = NULL;
input_stream = NULL;
mu_sieve_locus.source_file = NULL;
return 1;
}
......@@ -429,12 +426,20 @@ int
mu_sv_lex_begin_string (const char *buf, int bufsize,
const char *fname, int line)
{
int rc;
if (!fname)
return 1;
yyrestart (NULL);
input_string_ptr = buf;
input_string_level = bufsize;
rc = mu_static_memory_stream_create (&input_stream, buf, bufsize);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_static_memory_stream_create",
NULL, rc);
return 1;
}
mu_sieve_locus.source_file = strdup (fname);
mu_sieve_locus.source_line = line;
sieve_source_inode = 0;
......
......@@ -92,7 +92,9 @@ static struct argp_option options[] =
{"email", 'e', N_("ADDRESS"), 0,
N_("override user email address"), 0},
{"expression", 'E', NULL, 0,
N_("treat SCRIPT as Sieve program text"), 0},
{"no-program-name", ARG_NO_PROGRAM_NAME, NULL, 0,
N_("do not prefix diagnostic messages with the program name"), 0},
......@@ -106,6 +108,7 @@ int debug_level;
int sieve_debug;
int verbose;
char *script;
int expression_option;
static int sieve_print_locus = 1; /* Should the log messages include the
locus */
......@@ -172,6 +175,10 @@ parser (int key, char *arg, struct argp_state *state)
switch (key)
{
case 'E':
expression_option = 1;
break;
case 'e':
mu_argp_node_list_new (lst, "email", arg);
break;
......@@ -510,8 +517,12 @@ main (int argc, char *argv[])
mu_sieve_set_debug (mach, _sieve_debug_printer);
if (verbose)
mu_sieve_set_logger (mach, _sieve_action_log);
rc = mu_sieve_compile (mach, script);
if (expression_option)
rc = mu_sieve_compile_buffer (mach, script, strlen (script),
"stdin", 1);
else
rc = mu_sieve_compile (mach, script);
if (rc)
return EX_CONFIG;
......