Skip to content
Snippets Groups Projects
Commit 53ea2603 authored by Stephan Bosch's avatar Stephan Bosch
Browse files

First successful variable substitutions.

parent 5e2e9f9b
No related branches found
No related tags found
No related merge requests found
......@@ -75,8 +75,6 @@ static bool tag_modifier_validate
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
struct sieve_command_context *cmd)
{
struct sieve_ast_argument *tag = *arg;
/* Skip parameter */
*arg = sieve_ast_argument_next(*arg);
......@@ -165,7 +163,7 @@ static bool cmd_set_validate(struct sieve_validator *validator,
(validator, cmd, arg, "value", 2, SAAT_STRING) ) {
return FALSE;
}
sieve_validator_argument_activate(validator, cmd, arg, TRUE);
sieve_validator_argument_activate(validator, cmd, arg, FALSE);
return TRUE;
}
......@@ -211,11 +209,20 @@ static bool cmd_set_operation_execute
(const struct sieve_operation *op ATTR_UNUSED,
const struct sieve_runtime_env *renv, sieve_size_t *address)
{
struct sieve_variable_storage *storage =
ext_variables_interpreter_get_storage(renv->interp);
struct sieve_variable_storage *storage;
unsigned int var_index;
string_t *value;
printf(">> SET\n");
if ( !ext_variables_opr_variable_read(renv, address, &storage, &var_index) )
return FALSE;
if ( !sieve_opr_string_read(renv, address, &value) )
return FALSE;
sieve_variable_assign(storage, var_index, value);
return TRUE;
}
......
......@@ -14,6 +14,8 @@
#include "ext-variables-common.h"
#include <ctype.h>
/* Forward declarations */
extern const struct ext_variables_set_modifier lower_modifier;
......@@ -223,7 +225,11 @@ struct sieve_variable_storage *ext_variables_interpreter_get_storage
return ctx->local_storage;
}
/* Variable arguments */
/*
* Arguments
*/
/* Variable argument */
static bool arg_variable_generate
(struct sieve_generator *generator, struct sieve_ast_argument *arg,
......@@ -232,6 +238,28 @@ static bool arg_variable_generate
const struct sieve_argument variable_argument =
{ "@variable", NULL, NULL, NULL, arg_variable_generate };
static struct sieve_ast_argument *ext_variables_variable_argument_create
(struct sieve_validator *validator, struct sieve_ast *ast,
unsigned int source_line, const char *variable)
{
struct ext_variables_validator_context *ctx;
struct sieve_variable *var;
struct sieve_ast_argument *arg;
ctx = ext_variables_validator_context_get(validator);
var = sieve_variable_scope_get_variable(ctx->main_scope, variable);
if ( var == NULL )
return NULL;
arg = sieve_ast_argument_create(ast, source_line);
arg->type = SAAT_STRING;
arg->argument = &variable_argument;
arg->context = (void *) var;
return arg;
}
void ext_variables_variable_argument_activate
(struct sieve_validator *validator, struct sieve_ast_argument *arg)
{
......@@ -257,21 +285,219 @@ static bool arg_variable_generate
return TRUE;
}
/* Variable operands */
/* Variable string argument */
static bool arg_variable_string_validate
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
struct sieve_command_context *context);
static bool arg_variable_string_generate
(struct sieve_generator *generator, struct sieve_ast_argument *arg,
struct sieve_command_context *context);
const struct sieve_argument variable_string_argument = {
"@variable-string",
NULL,
arg_variable_string_validate,
NULL,
arg_variable_string_generate,
};
struct _variable_string_data {
struct sieve_ast_arg_list *str_parts;
};
inline static struct sieve_ast_argument *_add_string_element
(struct sieve_ast_arg_list *list, struct sieve_ast_argument *arg)
{
struct sieve_ast_argument *strarg =
sieve_ast_argument_create(arg->ast, arg->source_line);
sieve_ast_arg_list_add(list, strarg);
strarg->type = SAAT_STRING;
return strarg;
}
static bool arg_variable_string_validate
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
struct sieve_command_context *cmd)
{
enum { ST_NONE, ST_OPEN, ST_VARIABLE, ST_CLOSE } state = ST_NONE;
pool_t pool = sieve_ast_pool((*arg)->ast);
struct sieve_ast_arg_list *arglist = NULL;
string_t *str = sieve_ast_argument_str(*arg);
string_t *ident;
const char *p, *mark, *strstart, *substart = NULL;
const char *strval = (const char *) str_data(str);
const char *strend = strval + str_len(str);
struct _variable_string_data *strdata;
bool result = TRUE;
//t_push();
ident = t_str_new(32);
p = strval;
strstart = p;
while ( result && p < strend ) {
switch ( state ) {
case ST_NONE:
if ( *p == '$' ) {
substart = p;
state = ST_OPEN;
}
p++;
break;
case ST_OPEN:
if ( *p == '{' ) {
state = ST_VARIABLE;
p++;
} else
state = ST_NONE;
break;
case ST_VARIABLE:
mark = p;
if ( p < strend ) {
if (*p == '_' || isalpha(*p) ) {
str_append_c(ident, *p);
p++;
while ( p < strend && (*p == '_' || isalnum(*p)) ) {
str_append_c(ident, *p);
p++;
}
state = ST_CLOSE;
} else if ( isdigit(*p) ) {
unsigned int num_variable = *p - '0';
p++;
while ( p < strend && isdigit(*p) ) {
num_variable = num_variable*10 + (*p - '0');
p++;
}
state = ST_CLOSE;
} else
state = ST_NONE;
}
break;
case ST_CLOSE:
if ( *p == '}' ) {
struct sieve_ast_argument *strarg;
/* We now know that the substitution is valid */
if ( arglist == NULL ) {
arglist = sieve_ast_arg_list_create(pool);
}
if ( substart > strstart ) {
strarg = _add_string_element(arglist, *arg);
strarg->_value.str = str_new(pool, substart - strstart);
str_append_n(strarg->_value.str, strstart, substart - strstart);
if ( !sieve_validator_argument_activate_super
(validator, cmd, strarg, FALSE) )
return FALSE;
printf("STR: %s\n", t_strdup_until(strstart, substart));
}
/* Find the variable */
strarg = ext_variables_variable_argument_create
(validator, (*arg)->ast, (*arg)->source_line, str_c(ident));
if ( strarg != NULL )
sieve_ast_arg_list_add(arglist, strarg);
printf("VAR: %s\n", str_c(ident));
str_truncate(ident, 0);
strstart = p + 1;
substart = strstart;
}
state = ST_NONE;
p++;
}
}
//t_pop();
if ( arglist == NULL ) {
printf("STR: %s\n", strval);
return sieve_validator_argument_activate_super
(validator, cmd, *arg, TRUE);
}
if ( substart > strstart ) {
struct sieve_ast_argument *strarg = _add_string_element(arglist, *arg);
strarg->_value.str = str_new(pool, substart - strstart);
str_append_n(strarg->_value.str, strstart, substart - strstart);
if ( !sieve_validator_argument_activate_super
(validator, cmd, strarg, FALSE) )
return FALSE;
printf("STR: %s\n", t_strdup_until(strstart, substart));
}
strdata = p_new(pool, struct _variable_string_data, 1);
strdata->str_parts = arglist;
(*arg)->context = (void *) strdata;
return TRUE;
}
#define _string_data_first(data) __AST_LIST_FIRST((data)->str_parts)
#define _string_data_count(data) __AST_LIST_COUNT((data)->str_parts)
#define _string_data_next(item) __AST_LIST_NEXT(item)
static bool arg_variable_string_generate
(struct sieve_generator *generator, struct sieve_ast_argument *arg,
struct sieve_command_context *cmd)
{
struct sieve_binary *sbin = sieve_generator_get_binary(generator);
struct _variable_string_data *strdata =
(struct _variable_string_data *) arg->context;
struct sieve_ast_argument *strpart;
if ( _string_data_count(strdata) == 1 )
sieve_generate_argument(generator, _string_data_first(strdata), cmd);
else {
ext_variables_opr_variable_string_emit(sbin, _string_data_count(strdata));
strpart = _string_data_first(strdata);
while ( strpart != NULL ) {
if ( !sieve_generate_argument(generator, strpart, cmd) )
return FALSE;
strpart = _string_data_next(strpart);
}
}
return TRUE;
}
/*
* Operands
*/
/* Variable operand */
static bool opr_variable_read
static bool opr_variable_read_value
(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str);
static bool opr_variable_dump
(const struct sieve_dumptime_env *denv, sieve_size_t *address);
const struct sieve_opr_string_interface variable_interface = {
opr_variable_dump,
opr_variable_read
opr_variable_read_value
};
const struct sieve_operand variable_operand = {
"variable",
&variables_extension, 0,
&variables_extension,
EXT_VARIABLES_OPERAND_VARIABLE,
&string_class,
&variable_interface
};
......@@ -297,14 +523,17 @@ static bool opr_variable_dump
return FALSE;
}
static bool opr_variable_read
static bool opr_variable_read_value
(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str)
{
struct sieve_variable_storage *storage;
sieve_size_t index = 0;
storage = ext_variables_interpreter_get_storage(renv->interp);
if ( storage == NULL ) return FALSE;
if (sieve_binary_read_integer(renv->sbin, address, &index) ) {
*str = t_str_new(10);
str_append(*str, "VARIABLE");
sieve_variable_get(storage, index, str);
return TRUE;
}
......@@ -312,20 +541,97 @@ static bool opr_variable_read
return FALSE;
}
bool ext_variables_opr_variable_assign
(struct sieve_binary *sbin, sieve_size_t *address, string_t *str)
bool ext_variables_opr_variable_read
(const struct sieve_runtime_env *renv, sieve_size_t *address,
struct sieve_variable_storage **storage, unsigned int *var_index)
{
sieve_size_t index = 0;
const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
sieve_size_t idx = 0;
if (sieve_binary_read_integer(sbin, address, &index) ) {
/* FIXME: Assign */
if ( operand != &variable_operand )
return FALSE;
*storage = ext_variables_interpreter_get_storage(renv->interp);
if ( *storage == NULL ) return FALSE;
if (sieve_binary_read_integer(renv->sbin, address, &idx) ) {
*var_index = idx;
return TRUE;
}
return FALSE;
}
/* Variable string operand */
static bool opr_variable_string_read
(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str);
static bool opr_variable_string_dump
(const struct sieve_dumptime_env *denv, sieve_size_t *address);
const struct sieve_opr_string_interface variable_string_interface = {
opr_variable_string_dump,
opr_variable_string_read
};
const struct sieve_operand variable_string_operand = {
"variable-string",
&variables_extension,
EXT_VARIABLES_OPERAND_VARIABLE_STRING,
&string_class,
&variable_string_interface
};
void ext_variables_opr_variable_string_emit
(struct sieve_binary *sbin, unsigned int elements)
{
(void) sieve_operand_emit_code
(sbin, &variable_string_operand, ext_variables_my_id);
(void) sieve_binary_emit_integer(sbin, elements);
}
static bool opr_variable_string_dump
(const struct sieve_dumptime_env *denv, sieve_size_t *address)
{
sieve_size_t elements = 0;
unsigned int i;
if (!sieve_binary_read_integer(denv->sbin, address, &elements) )
return FALSE;
sieve_code_dumpf(denv, "VARSTR [%ld]:", (long) elements);
sieve_code_descend(denv);
for ( i = 0; i < (unsigned int) elements; i++ ) {
sieve_opr_string_dump(denv, address);
}
sieve_code_ascend(denv);
return TRUE;
}
static bool opr_variable_string_read
(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str)
{
sieve_size_t elements = 0;
unsigned int i;
if ( !sieve_binary_read_integer(renv->sbin, address, &elements) )
return FALSE;
*str = t_str_new(128);
for ( i = 0; i < (unsigned int) elements; i++ ) {
string_t *strelm;
if ( !sieve_opr_string_read(renv, address, &strelm) )
return FALSE;
str_append_str(*str, strelm);
}
return TRUE;
}
/* Set modifier registration */
const struct ext_variables_set_modifier *ext_variables_set_modifier_find
......
......@@ -14,6 +14,11 @@ enum ext_variables_opcode {
EXT_VARIABLES_OPERATION_STRING
};
enum ext_variables_operand {
EXT_VARIABLES_OPERAND_VARIABLE,
EXT_VARIABLES_OPERAND_VARIABLE_STRING
};
/* Extension */
void ext_variables_validator_initialize(struct sieve_validator *validator);
......@@ -40,12 +45,20 @@ struct ext_variables_set_modifier {
const struct ext_variables_set_modifier *ext_variables_set_modifier_find
(struct sieve_validator *validator, const char *identifier);
/* Arguments */
extern const struct sieve_argument variable_string_argument;
/* Variables */
void ext_variables_opr_variable_emit
(struct sieve_binary *sbin, struct sieve_variable *var);
bool ext_variables_opr_variable_assign
(struct sieve_binary *sbin, sieve_size_t *address, string_t *str);
bool ext_variables_opr_variable_read
(const struct sieve_runtime_env *renv, sieve_size_t *address,
struct sieve_variable_storage **storage, unsigned int *var_index);
void ext_variables_opr_variable_string_emit
(struct sieve_binary *sbin, unsigned int elements);
void ext_variables_variable_argument_activate
(struct sieve_validator *validator, struct sieve_ast_argument *arg);
......
......@@ -43,6 +43,12 @@ const struct sieve_operation *ext_variables_operations[] = {
/* Operands */
extern const struct sieve_operand variable_operand;
extern const struct sieve_operand variable_string_operand;
const struct sieve_operation *ext_variables_operands[] = {
&variable_operand, &variable_string_operand
};
/* Extension definitions */
......@@ -55,7 +61,7 @@ struct sieve_extension variables_extension = {
NULL, NULL,
ext_variables_interpreter_load,
SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations),
SIEVE_EXT_DEFINE_OPERAND(variable_operand)
SIEVE_EXT_DEFINE_OPERANDS(ext_variables_operands)
};
static bool ext_variables_load(int ext_id)
......@@ -64,109 +70,13 @@ static bool ext_variables_load(int ext_id)
return TRUE;
}
/* New argument */
static bool arg_variable_string_validate
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
struct sieve_command_context *context);
const struct sieve_argument variable_string_argument =
{ "@variable-string", NULL, arg_variable_string_validate, NULL, NULL };
static bool arg_variable_string_validate
(struct sieve_validator *validator, struct sieve_ast_argument **arg,
struct sieve_command_context *cmd)
{
bool result = TRUE;
enum { ST_NONE, ST_OPEN, ST_VARIABLE, ST_CLOSE }
state = ST_NONE;
string_t *str = sieve_ast_argument_str(*arg);
string_t *tmpstr, *newstr = NULL;
const char *p, *mark, *strstart, *substart = NULL;
const char *strval = (const char *) str_data(str);
const char *strend = strval + str_len(str);
T_FRAME(
tmpstr = t_str_new(32);
p = strval;
strstart = p;
while ( result && p < strend ) {
switch ( state ) {
case ST_NONE:
if ( *p == '$' ) {
substart = p;
state = ST_OPEN;
}
p++;
break;
case ST_OPEN:
if ( *p == '{' ) {
state = ST_VARIABLE;
p++;
} else
state = ST_NONE;
break;
case ST_VARIABLE:
mark = p;
if ( p < strend ) {
if (*p == '_' || isalpha(*p) ) {
p++;
while ( p < strend && (*p == '_' || isalnum(*p)) ) {
p++;
}
} else if ( isdigit(*p) ) {
unsigned int num_variable = *p - '0';
p++;
while ( p < strend && isdigit(*p) ) {
num_variable = num_variable*10 + (*p - '0');
p++;
}
}
}
break;
case ST_CLOSE:
if ( *p == '}' ) {
/* We now know that the substitution is valid */
if ( newstr == NULL ) {
newstr = str_new(sieve_ast_pool((*arg)->ast), str_len(str)*2);
}
str_append_n(newstr, strstart, substart-strstart);
str_append_str(newstr, tmpstr);
strstart = p + 1;
substart = strstart;
}
state = ST_NONE;
p++;
}
}
);
if ( newstr != NULL ) {
if ( strstart != strend )
str_append_n(newstr, strstart, strend-strstart);
sieve_ast_argument_str_set(*arg, newstr);
}
return sieve_validator_argument_activate_super
(validator, cmd, *arg, TRUE);
}
/* Load extension into validator */
static bool ext_variables_validator_load
(struct sieve_validator *validator)
{
/*sieve_validator_argument_override(validator, SAT_VAR_STRING,
&variable_string_argument);*/
sieve_validator_argument_override(validator, SAT_VAR_STRING,
&variable_string_argument);
sieve_validator_register_command(validator, &cmd_set);
sieve_validator_register_command(validator, &tst_string);
......
require "variables";
require "fileinto";
set :upper "foo" "foosome";
set :lower "bar" "bareable";
fileinto "${foo}.${bar}";
......@@ -135,16 +135,16 @@ static void sieve_ast_list_add( struct sieve_ast_list *list, struct sieve_ast_no
__LIST_ADD(list, node)
/* List of argument AST nodes */
static struct sieve_ast_arg_list *sieve_ast_arg_list_create( pool_t pool )
struct sieve_ast_arg_list *sieve_ast_arg_list_create( pool_t pool )
__LIST_CREATE(pool, struct sieve_ast_arg_list)
static void sieve_ast_arg_list_add
void sieve_ast_arg_list_add
( struct sieve_ast_arg_list *list, struct sieve_ast_argument *argument )
__LIST_ADD(list, argument)
inline static void sieve_ast_arg_list_substitute
(struct sieve_ast_arg_list *list,
struct sieve_ast_argument *argument, struct sieve_ast_argument *replacement)
void sieve_ast_arg_list_substitute
(struct sieve_ast_arg_list *list, struct sieve_ast_argument *argument,
struct sieve_ast_argument *replacement)
{
if ( list->head == argument )
list->head = replacement;
......@@ -269,10 +269,11 @@ static void sieve_ast_argument_substitute
}
/* Argument AST node */
static struct sieve_ast_argument *sieve_ast_argument_create
struct sieve_ast_argument *sieve_ast_argument_create
(struct sieve_ast *ast, unsigned int source_line)
{
struct sieve_ast_argument *arg = p_new(ast->pool, struct sieve_ast_argument, 1);
struct sieve_ast_argument *arg =
p_new(ast->pool, struct sieve_ast_argument, 1);
arg->ast = ast;
......
......@@ -34,13 +34,13 @@
| [number | tag | *string]
.
Tests and commands are defined using the same structure: sieve_ast_node. However, arguments and
string-lists are described using sieve_ast_argument.
Tests and commands are defined using the same structure: sieve_ast_node.
However, arguments and string-lists are described using sieve_ast_argument.
*/
/* IMPORTANT NOTICE: Do not decorate the AST with objects other than those allocated on
* the ast's pool or static const objects. Otherwise it is possible that pointers in the tree
* become dangling which is highly undesirable.
/* IMPORTANT NOTICE: Do not decorate the AST with objects other than those
* allocated on the ast's pool or static const objects. Otherwise it is possible
* that pointers in the tree become dangling which is highly undesirable.
*/
struct sieve_ast_list;
......@@ -166,6 +166,17 @@ void sieve_ast_error
struct sieve_ast_node *node, const char *fmt, va_list args);
/* sieve_ast_argument */
struct sieve_ast_argument *sieve_ast_argument_create
(struct sieve_ast *ast, unsigned int source_line);
struct sieve_ast_arg_list *sieve_ast_arg_list_create(pool_t pool);
void sieve_ast_arg_list_add
(struct sieve_ast_arg_list *list, struct sieve_ast_argument *argument);
void sieve_ast_arg_list_substitute
(struct sieve_ast_arg_list *list, struct sieve_ast_argument *argument,
struct sieve_ast_argument *replacement);
struct sieve_ast_argument *sieve_ast_argument_string_create
(struct sieve_ast_node *node, const string_t *str, unsigned int source_line);
struct sieve_ast_argument *sieve_ast_argument_tag_create
......@@ -186,17 +197,21 @@ const char *sieve_ast_argument_type_name(enum sieve_ast_argument_type arg_type);
sieve_ast_argument_type_name((argument)->type)
void sieve_ast_stringlist_add
(struct sieve_ast_argument *list, const string_t *str, unsigned int source_line);
(struct sieve_ast_argument *list, const string_t *str,
unsigned int source_line);
void sieve_ast_stringlist_add_strc
(struct sieve_ast_argument *list, const char *str, unsigned int source_line);
(struct sieve_ast_argument *list, const char *str,
unsigned int source_line);
/* sieve_ast_test */
struct sieve_ast_node *sieve_ast_test_create
(struct sieve_ast_node *parent, const char *identifier, unsigned int source_line);
(struct sieve_ast_node *parent, const char *identifier,
unsigned int source_line);
/* sieve_ast_command */
struct sieve_ast_node *sieve_ast_command_create
(struct sieve_ast_node *parent, const char *identifier, unsigned int source_line);
(struct sieve_ast_node *parent, const char *identifier,
unsigned int source_line);
/* Debug */
void sieve_ast_unparse(struct sieve_ast *ast);
......@@ -204,45 +219,54 @@ void sieve_ast_unparse(struct sieve_ast *ast);
/* AST access macros */
/* Generic list access macros */
#define __LIST_FIRST(node, list) ((node)->list == NULL ? NULL : (node)->list->head)
#define __LIST_LAST(node, list) ((node)->list == NULL ? NULL : (node)->list->tail)
#define __LIST_NEXT(item) ((item)->next)
#define __LIST_PREV(item) ((item)->prev)
#define __LIST_COUNT(node, list) ((node)->list == NULL || (node)->list->head == NULL ? 0 : (node)->list->len)
#define __AST_LIST_FIRST(list) \
((list) == NULL ? NULL : (list)->head)
#define __AST_LIST_LAST(list) \
((list) == NULL ? NULL : (list)->tail)
#define __AST_LIST_COUNT(list) \
((list) == NULL || (list)->head == NULL ? 0 : (list)->len)
#define __AST_LIST_NEXT(item) ((item)->next)
#define __AST_LIST_PREV(item) ((item)->prev)
#define __AST_NODE_LIST_FIRST(node, list) __AST_LIST_FIRST((node)->list)
#define __AST_NODE_LIST_LAST(node, list) __AST_LIST_LAST((node)->list)
#define __AST_NODE_LIST_COUNT(node, list) __AST_LIST_COUNT((node)->list)
/* AST macros */
/* AST node macros */
#define sieve_ast_node_pool(node) (sieve_ast_pool((node)->ast))
#define sieve_ast_node_parent(node) ((node)->parent)
#define sieve_ast_node_prev(node) __LIST_PREV(node)
#define sieve_ast_node_next(node) __LIST_NEXT(node)
#define sieve_ast_node_prev(node) __AST_LIST_PREV(node)
#define sieve_ast_node_next(node) __AST_LIST_NEXT(node)
#define sieve_ast_node_type(node) ((node) == NULL ? SAT_NONE : (node)->type)
#define sieve_ast_node_line(node) ((node) == NULL ? 0 : (node)->source_line)
/* AST command node macros */
#define sieve_ast_command_first(node) __LIST_FIRST(node, commands)
#define sieve_ast_command_prev(command) __LIST_PREV(command)
#define sieve_ast_command_next(command) __LIST_NEXT(command)
#define sieve_ast_command_count(node) __LIST_COUNT(node, commands)
#define sieve_ast_command_first(node) __AST_NODE_LIST_FIRST(node, commands)
#define sieve_ast_command_count(node) __AST_NODE_LIST_COUNT(node, commands)
#define sieve_ast_command_prev(command) __AST_LIST_PREV(command)
#define sieve_ast_command_next(command) __AST_LIST_NEXT(command)
/* Compare the identifier of the previous command */
#define sieve_ast_prev_cmd_is(cmd, id) \
( (cmd)->prev == NULL ? FALSE : strncasecmp((cmd)->prev->identifier, id, sizeof(id)-1) == 0 )
/* AST test macros */
#define sieve_ast_test_first(node) __LIST_FIRST(node, tests)
#define sieve_ast_test_next(test) __LIST_NEXT(test)
#define sieve_ast_test_count(node) __LIST_COUNT(node, tests)
#define sieve_ast_test_count(node) __AST_NODE_LIST_COUNT(node, tests)
#define sieve_ast_test_first(node) __AST_NODE_LIST_FIRST(node, tests)
#define sieve_ast_test_next(test) __AST_LIST_NEXT(test)
/* AST argument macros */
#define sieve_ast_argument_first(node) __LIST_FIRST(node, arguments)
#define sieve_ast_argument_last(node) __LIST_LAST(node, arguments)
#define sieve_ast_argument_prev(argument) __LIST_PREV(argument)
#define sieve_ast_argument_next(argument) __LIST_NEXT(argument)
#define sieve_ast_argument_count(node) __LIST_COUNT(node, arguments)
#define sieve_ast_argument_type(argument) ((argument) == NULL ? SAAT_NONE : (argument)->type)
#define sieve_ast_argument_line(argument) ((argument) == NULL ? 0 : (argument)->source_line)
#define sieve_ast_argument_first(node) __AST_NODE_LIST_FIRST(node, arguments)
#define sieve_ast_argument_last(node) __AST_NODE_LIST_LAST(node, arguments)
#define sieve_ast_argument_count(node) __AST_NODE_LIST_COUNT(node, arguments)
#define sieve_ast_argument_prev(argument) __AST_LIST_PREV(argument)
#define sieve_ast_argument_next(argument) __AST_LIST_NEXT(argument)
#define sieve_ast_argument_type(argument) \
((argument) == NULL ? SAAT_NONE : (argument)->type)
#define sieve_ast_argument_line(argument) \
((argument) == NULL ? 0 : (argument)->source_line)
#define sieve_ast_argument_str(argument) ((argument)->_value.str)
#define sieve_ast_argument_strc(argument) (str_c((argument)->_value.str))
......@@ -254,12 +278,15 @@ void sieve_ast_unparse(struct sieve_ast *ast);
/* AST string list macros */
// @UNSAFE: should check whether we are actually accessing a string list
#define sieve_ast_strlist_first(list) __LIST_FIRST(list, _value.strlist)
#define sieve_ast_strlist_last(list) __LIST_LAST(list, _value.strlist)
#define sieve_ast_strlist_next(str) __LIST_NEXT(str)
#define sieve_ast_strlist_prev(str) __LIST_PREV(str)
#define sieve_ast_strlist_first(list) \
__AST_NODE_LIST_FIRST(list, _value.strlist)
#define sieve_ast_strlist_last(list) \
__AST_NODE_LIST_LAST(list, _value.strlist)
#define sieve_ast_strlist_count(list) \
__AST_NODE_LIST_COUNT(list, _value.strlist)
#define sieve_ast_strlist_next(str) __AST_LIST_NEXT(str)
#define sieve_ast_strlist_prev(str) __AST_LIST_PREV(str)
#define sieve_ast_strlist_str(str) sieve_ast_argument_str(str)
#define sieve_ast_strlist_strc(str) sieve_ast_argument_strc(str)
#define sieve_ast_strlist_count(list) __LIST_COUNT(list, _value.strlist)
#endif /* __SIEVE_AST_H */
......@@ -37,8 +37,10 @@ struct sieve_validator {
ARRAY_DEFINE(ext_contexts, void *);
/* This is currently a wee bit ugly and needs more thought */
struct sieve_default_argument default_arguments[SAT_COUNT];
struct sieve_default_argument *current_defarg;
enum sieve_argument_type current_defarg_type;
};
/* Predeclared statics */
......@@ -427,12 +429,15 @@ void sieve_validator_argument_override
(struct sieve_validator *validator, enum sieve_argument_type type,
const struct sieve_argument *argument)
{
struct sieve_default_argument *arg =
p_new(validator->pool, struct sieve_default_argument, 1);
struct sieve_default_argument *arg;
*arg = validator->default_arguments[type];
if ( validator->default_arguments[type].argument != NULL ) {
arg = p_new(validator->pool, struct sieve_default_argument, 1);
*arg = validator->default_arguments[type];
validator->default_arguments[type].overrides = arg;
}
validator->default_arguments[type].overrides = arg;
validator->default_arguments[type].argument = argument;
}
......@@ -459,12 +464,29 @@ bool sieve_validator_argument_activate_super
(struct sieve_validator *validator, struct sieve_command_context *cmd,
struct sieve_ast_argument *arg, bool constant ATTR_UNUSED)
{
if ( validator->current_defarg == NULL &&
validator->current_defarg->overrides == NULL )
struct sieve_default_argument *defarg;
if ( validator->current_defarg == NULL )
return FALSE;
if ( validator->current_defarg->overrides == NULL ) {
switch ( validator->current_defarg_type ) {
case SAT_NUMBER:
case SAT_CONST_STRING:
case SAT_STRING_LIST:
return FALSE;
case SAT_VAR_STRING:
validator->current_defarg_type = SAT_CONST_STRING;
defarg = &validator->default_arguments[validator->current_defarg_type];
break;
default:
return FALSE;
}
} else
defarg = validator->current_defarg->overrides;
return sieve_validator_argument_default_activate
(validator, cmd, validator->current_defarg->overrides, arg);
(validator, cmd, defarg, arg);
}
bool sieve_validator_argument_activate
......@@ -474,23 +496,25 @@ bool sieve_validator_argument_activate
struct sieve_default_argument *defarg;
switch ( sieve_ast_argument_type(arg) ) {
case SAAT_NUMBER:
defarg = &validator->default_arguments[SAT_NUMBER];
case SAAT_NUMBER:
validator->current_defarg_type = SAT_NUMBER;
break;
case SAAT_STRING:
if ( validator->default_arguments[SAT_VAR_STRING].argument == NULL ||
constant )
defarg = &validator->default_arguments[SAT_CONST_STRING];
if ( constant ||
validator->default_arguments[SAT_VAR_STRING].argument == NULL )
validator->current_defarg_type = SAT_CONST_STRING;
else
defarg = &validator->default_arguments[SAT_VAR_STRING];
validator->current_defarg_type = SAT_VAR_STRING;
break;
case SAAT_STRING_LIST:
defarg = &validator->default_arguments[SAT_STRING_LIST];
validator->current_defarg_type = SAT_STRING_LIST;
break;
default:
return FALSE;
}
defarg = &validator->default_arguments[validator->current_defarg_type];
return sieve_validator_argument_default_activate(validator, cmd, defarg, arg);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.