From 286046df7d052dcb5c2936a82b03611b621ee682 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sat, 27 Oct 2007 02:31:18 +0200
Subject: [PATCH] Changed argument to operand processing to be much more
 flexible.

---
 src/lib-sieve/ext-envelope.c                  | 22 ++---
 src/lib-sieve/ext-fileinto.c                  | 11 +--
 src/lib-sieve/ext-reject.c                    | 12 +--
 src/lib-sieve/plugins/vacation/ext-vacation.c | 18 ++--
 src/lib-sieve/sieve-binary.h                  |  5 +-
 src/lib-sieve/sieve-code.c                    | 48 +++++++++-
 src/lib-sieve/sieve-code.h                    | 17 +++-
 src/lib-sieve/sieve-commands.c                | 94 ++++++++++++++++++
 src/lib-sieve/sieve-commands.h                | 17 ++--
 src/lib-sieve/sieve-generator.c               | 95 ++++---------------
 src/lib-sieve/sieve-generator.h               | 16 +---
 src/lib-sieve/sieve-interpreter.c             |  2 +-
 src/lib-sieve/sieve-validator.c               | 38 +++++---
 src/lib-sieve/sieve-validator.h               |  6 +-
 src/lib-sieve/tst-address.c                   | 14 +--
 src/lib-sieve/tst-exists.c                    | 10 +-
 src/lib-sieve/tst-header.c                    | 16 +---
 src/lib-sieve/tst-size.c                      |  6 +-
 18 files changed, 264 insertions(+), 183 deletions(-)

diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index 924d21657..791029b41 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -52,15 +52,14 @@ static bool tst_envelope_validate(struct sieve_validator *validator, struct siev
 		!sieve_validate_command_subtests(validator, tst, 0) ) {
 		return FALSE;
 	}
-		
-	tst->data = (void *) arg;	
-		
+				
 	if ( sieve_ast_argument_type(arg) != SAAT_STRING && sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
 		sieve_command_validate_error(validator, tst, 
 			"the envelope test expects a string-list as first argument (envelope part), but %s was found", 
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	arg = sieve_ast_argument_next(arg);
 	if ( sieve_ast_argument_type(arg) != SAAT_STRING && sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
@@ -69,6 +68,7 @@ static bool tst_envelope_validate(struct sieve_validator *validator, struct siev
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	return TRUE;
 }
@@ -89,20 +89,12 @@ static bool ext_envelope_validator_load(struct sieve_validator *validator)
 static bool tst_envelope_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	
 	sieve_generator_emit_ext_opcode(generator, &envelope_extension);
 
-	/* Emit envelope-part */  	
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
-		return FALSE;
-		
-	arg = sieve_ast_argument_next(arg);
-	
-	/* Emit key-list */  	
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
-		return FALSE;
-	
+	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;
+
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index 37a752776..20de6ef50 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -39,7 +39,8 @@ static bool cmd_fileinto_validate(struct sieve_validator *validator, struct siev
 		return FALSE;
 	}
 	
-	cmd->data = (void *) arg;
+
+	sieve_validator_argument_activate(validator, arg);
 	
 	return TRUE;
 }
@@ -60,13 +61,11 @@ static bool ext_fileinto_validator_load(struct sieve_validator *validator)
 static bool cmd_fileinto_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	
 	sieve_generator_emit_ext_opcode(generator, &fileinto_extension);
 
-	/* Emit folder string */  	
-	if ( !sieve_generator_emit_string_argument(generator, arg) ) 
-		return FALSE;
+	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index c98a82cf3..610d9a56f 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -39,8 +39,8 @@ static bool cmd_reject_validate(struct sieve_validator *validator, struct sieve_
 	 	
 		return FALSE;
 	}
-	
-	cmd->data = (void *) arg;
+		
+	sieve_validator_argument_activate(validator, arg);
 	
 	return TRUE;
 }
@@ -61,13 +61,11 @@ static bool ext_reject_validator_load(struct sieve_validator *validator)
 static bool cmd_reject_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	
 	sieve_generator_emit_ext_opcode(generator, &reject_extension);
 
-	/* Emit reason string */  	
-	if ( !sieve_generator_emit_string_argument(generator, arg) ) 
-		return FALSE;
+	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index a24ffc338..9638e2e4a 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -198,8 +198,8 @@ static bool cmd_vacation_validate(struct sieve_validator *validator, struct siev
 	
 	/* Check valid syntax: 
 	 *    vacation [":days" number] [":subject" string]
-   *                 [":from" string] [":addresses" string-list]
-   *                 [":mime"] [":handle" string] <reason: string>
+	 *                 [":from" string] [":addresses" string-list]
+	 *                 [":mime"] [":handle" string] <reason: string>
 	 */
 	if ( !sieve_validate_command_arguments(validator, cmd, 1, &arg) ||
 		!sieve_validate_command_subtests(validator, cmd, 0) || 
@@ -207,8 +207,8 @@ static bool cmd_vacation_validate(struct sieve_validator *validator, struct siev
 	 	
 		return FALSE;
 	}
-	
-	cmd->data = (void *) arg;
+
+	sieve_validator_argument_activate(validator, arg);	
 	
 	return TRUE;
 }
@@ -229,14 +229,12 @@ static bool ext_vacation_validator_load(struct sieve_validator *validator)
 static bool cmd_vacation_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	
 	sieve_generator_emit_ext_opcode(generator, &vacation_extension);
 
-	/* Emit folder string */  	
-	if ( !sieve_generator_emit_string_argument(generator, arg) ) 
-		return FALSE;
-	
+	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;	
+
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h
index f27b615df..f731deea8 100644
--- a/src/lib-sieve/sieve-binary.h
+++ b/src/lib-sieve/sieve-binary.h
@@ -1,8 +1,11 @@
 #ifndef __SIEVE_BINARY_H
 #define __SIEVE_BINARY_H
 
-#include "sieve-extensions.h"
+#include "lib.h"
+#include "str.h"
+
 #include "sieve-code.h"
+#include "sieve-extensions.h"
 
 struct sieve_binary;
 
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index b3c6ecde1..d1c13b5fa 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -1,11 +1,55 @@
-#include <stdio.h>
+#include "lib.h"
+#include "str.h"
 
-#include "sieve-code.h"
+#include "sieve-generator.h"
 #include "sieve-interpreter.h"
 
+#include "sieve-code.h"
+
+#include <stdio.h>
+
 /* Operands */
 
+void sieve_operand_number_emit(struct sieve_generator *generator, sieve_size_t number) {
+	(void) sieve_generator_emit_operand(generator, SIEVE_OPERAND_NUMBER);
+  (void) sieve_generator_emit_integer(generator, number);
+}
 
+void sieve_operand_string_emit(struct sieve_generator *generator, string_t *str)
+{
+	(void) sieve_generator_emit_operand(generator, SIEVE_OPERAND_STRING);
+  (void) sieve_generator_emit_string(generator, str);
+}
+
+void sieve_operand_stringlist_emit_start
+	(struct sieve_generator *generator, unsigned int listlen, void **context)
+{
+  sieve_size_t *end_offset = t_new(sieve_size_t, 1);
+
+	/* Emit byte identifying the type of operand */	  
+  (void) sieve_generator_emit_operand(generator, SIEVE_OPERAND_STRING_LIST);
+  
+  /* Give the interpreter an easy way to skip over this string list */
+  *end_offset = sieve_generator_emit_offset(generator, 0);
+	*context = (void *) end_offset;
+
+  /* Emit the length of the list */
+  (void) sieve_generator_emit_integer(generator, (int) listlen);
+}
+
+void sieve_operand_stringlist_emit_item
+	(struct sieve_generator *generator, void *context ATTR_UNUSED, string_t *item)
+{
+	(void) sieve_generator_emit_string(generator, item);
+}
+
+void sieve_operand_stringlist_emit_end
+	(struct sieve_generator *generator, void *context)
+{
+	sieve_size_t *end_offset = (sieve_size_t *) context;
+
+	(void) sieve_generator_resolve_offset(generator, *end_offset);
+}
 
 /* Opcodes */
 
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index c3a2041c1..56389a84d 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -34,8 +34,11 @@ extern const unsigned int sieve_opcode_count;
 
 /* Operand: argument to and opcode */
 struct sieve_operand {
+	/* Code generator */
+	bool (*emit)(struct sieve_generator *generator, struct sieve_ast_argument *arg);
+
+	/* Interpreter */
 	bool (*dump)(struct sieve_interpreter *interpreter);
-	bool (*execute)(struct sieve_interpreter *interpreter);
 };
 
 enum sieve_core_operand {
@@ -47,10 +50,18 @@ enum sieve_core_operand {
   SIEVE_OPERAND_ADDR_PART  
 };
 
+void sieve_operand_number_emit(struct sieve_generator *generator, sieve_size_t number);
+void sieve_operand_string_emit(struct sieve_generator *generator, string_t *str);
+void sieve_operand_stringlist_emit_start
+	(struct sieve_generator *generator, unsigned int listlen, void **context);
+void sieve_operand_stringlist_emit_item
+	(struct sieve_generator *generator, void *context ATTR_UNUSED, string_t *item);
+void sieve_operand_stringlist_emit_end
+	(struct sieve_generator *generator, void *context);
+
 #define SIEVE_OPCODE_CORE_MASK  0x1F
 #define SIEVE_OPCODE_EXT_OFFSET (SIEVE_OPCODE_CORE_MASK + 1)
 
-#define SIEVE_CORE_OPERAND_MASK 0x0F
-#define SIEVE_CORE_OPERAND_BITS 4
+#define SIEVE_OPERAND_CORE_MASK 0x1F
 
 #endif
diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c
index a9959202b..d5030d2df 100644
--- a/src/lib-sieve/sieve-commands.c
+++ b/src/lib-sieve/sieve-commands.c
@@ -8,6 +8,100 @@
 #include "sieve-commands-private.h"
 #include "sieve-interpreter.h"
 
+/* Default arguments implemented in this file */
+
+static bool arg_number_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *context);
+static bool arg_string_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *context);
+static bool arg_string_list_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *context);
+
+const struct sieve_argument number_argument =
+	{ "@number", NULL, arg_number_generate };
+const struct sieve_argument string_argument =
+	{ "@string", NULL, arg_string_generate };
+const struct sieve_argument string_list_argument =
+	{ "@string-list", NULL, arg_string_list_generate };	
+
+static bool arg_number_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *context ATTR_UNUSED)
+{
+	if ( sieve_ast_argument_type(*arg) != SAAT_NUMBER ) {
+		return FALSE;
+	}
+	
+	sieve_operand_number_emit(generator, sieve_ast_argument_number(*arg));
+
+	*arg = sieve_ast_argument_next(*arg);
+
+  return TRUE;
+}
+
+static bool arg_string_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *context ATTR_UNUSED)
+{
+  if ( sieve_ast_argument_type(*arg) != SAAT_STRING ) {
+		return FALSE;
+	} 
+
+	sieve_operand_string_emit(generator, sieve_ast_argument_str(*arg));
+  
+  *arg = sieve_ast_argument_next(*arg);
+  return TRUE;
+}
+
+static void emit_string_list_operand
+	(struct sieve_generator *generator, const struct sieve_ast_argument *strlist)
+{
+	void *list_context;
+  const struct sieve_ast_argument *stritem;
+  
+  t_push();
+  
+  printf("STRLIST: %d\n", sieve_ast_strlist_count(strlist));
+	sieve_operand_stringlist_emit_start
+		(generator, sieve_ast_strlist_count(strlist), &list_context);
+
+	stritem = sieve_ast_strlist_first(strlist);
+	while ( stritem != NULL ) {
+		sieve_operand_stringlist_emit_item
+			(generator, list_context, sieve_ast_strlist_str(stritem));
+		printf("STR: %s\n", sieve_ast_strlist_strc(stritem));
+		stritem = sieve_ast_strlist_next(stritem);
+	}
+
+  sieve_operand_stringlist_emit_end
+		(generator, list_context);
+
+  t_pop();
+}
+
+static bool arg_string_list_generate(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *context ATTR_UNUSED)
+{
+	if ( sieve_ast_argument_type(*arg) == SAAT_STRING ) {
+		
+		sieve_operand_string_emit(generator, sieve_ast_argument_str(*arg));
+		
+		*arg = sieve_ast_argument_next(*arg);
+		return TRUE;
+		
+	} else if ( sieve_ast_argument_type(*arg) == SAAT_STRING_LIST ) {
+
+		if ( sieve_ast_strlist_count(*arg) == 1 ) 
+			sieve_operand_string_emit(generator, 
+				sieve_ast_argument_str(sieve_ast_strlist_first(*arg)));
+		else
+			(void) emit_string_list_operand(generator, *arg);
+		
+		*arg = sieve_ast_argument_next(*arg);
+		return TRUE;
+	}
+	
+	return FALSE;
+}
+
 /* Trivial commands implemented in this file */
 
 const struct sieve_command sieve_core_tests[] = {
diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h
index 42a9efb55..128289ba4 100644
--- a/src/lib-sieve/sieve-commands.h
+++ b/src/lib-sieve/sieve-commands.h
@@ -1,5 +1,5 @@
-#ifndef __SIEVE_COMMANDS_H__
-#define __SIEVE_COMMANDS_H__
+#ifndef __SIEVE_COMMANDS_H
+#define __SIEVE_COMMANDS_H
 
 #include "lib.h"
 
@@ -8,10 +8,7 @@
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 
-struct sieve_test_context;
-struct sieve_command_context;
-
-/* Command */
+/* Argument */
 
 struct sieve_argument {
 	const char *identifier;
@@ -22,6 +19,12 @@ struct sieve_argument {
 		struct sieve_command_context *context);
 };
 
+extern const struct sieve_argument number_argument;
+extern const struct sieve_argument string_argument;
+extern const struct sieve_argument string_list_argument;
+
+/* Command */
+
 enum sieve_command_type {
 	SCT_COMMAND,
 	SCT_TEST
@@ -63,4 +66,4 @@ const char *sieve_command_type_name(const struct sieve_command *command);
 struct sieve_command_context *sieve_command_prev_context	
 	(struct sieve_command_context *context); 
 
-#endif /* __SIEVE_COMMANDS_H__ */
+#endif /* __SIEVE_COMMANDS_H */
diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c
index 5a58a3650..29aa55555 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -127,90 +127,22 @@ inline sieve_size_t sieve_generator_emit_integer(struct sieve_generator *generat
   return sieve_binary_emit_integer(generator->binary, integer);
 }
 
-inline static sieve_size_t sieve_generator_emit_string_item(struct sieve_generator *generator, const string_t *str)
+inline sieve_size_t sieve_generator_emit_string(struct sieve_generator *generator, const string_t *str)
 {
   return sieve_binary_emit_string(generator->binary, str);
 }
 
-/* Operand emission */
+/* Emit operands */
 
-sieve_size_t sieve_generator_emit_number(struct sieve_generator *generator, sieve_size_t number)
+sieve_size_t sieve_generator_emit_operand
+	(struct sieve_generator *generator, int operand)
 {
-  sieve_size_t address = sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_NUMBER);
-  
-  (void) sieve_generator_emit_integer(generator, number);
-
-  return address;
-}
-
-sieve_size_t sieve_generator_emit_string(struct sieve_generator *generator, const string_t *str)
-{
-  sieve_size_t address = sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_STRING);
-  
-  (void) sieve_generator_emit_string_item(generator, str);
-  
-  return address;
-}
-
-bool sieve_generator_emit_stringlist_argument
-	(struct sieve_generator *generator, struct sieve_ast_argument *arg)
-{
-	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
-		(void) sieve_generator_emit_string(generator, sieve_ast_argument_str(arg));
-		return TRUE;
-	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
-		if ( sieve_ast_strlist_count(arg) == 1 )
-			sieve_generator_emit_string(generator, 
-				sieve_ast_argument_str(sieve_ast_strlist_first(arg)));
-		else
-			(void) sieve_generator_emit_string_list(generator, arg);
-		return TRUE;
-	}
+	unsigned char op = operand & SIEVE_OPERAND_CORE_MASK;
 	
-	return FALSE;
-}
-
-bool sieve_generator_emit_string_argument
-	(struct sieve_generator *generator, struct sieve_ast_argument *arg)
-{
-	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
-		(void) sieve_generator_emit_string(generator, sieve_ast_argument_str(arg));
-		return TRUE;
-	} 
-	
-	return FALSE;
-}
-
-sieve_size_t sieve_generator_emit_string_list
-	(struct sieve_generator *generator, const struct sieve_ast_argument *strlist)
-{
-	sieve_size_t address;
-  const struct sieve_ast_argument *stritem;
-  unsigned int listlen = sieve_ast_strlist_count(strlist);
-  sieve_size_t end_offset = 0;
-
-	/* Emit byte identifying the type of operand */	  
-  address = sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_STRING_LIST);
-  
-  /* Give the interpreter an easy way to skip over this string list */
-  end_offset = sieve_generator_emit_offset(generator, 0);
-
-  /* Emit the length of the list */
-  (void) sieve_generator_emit_integer(generator, (int) listlen);
-
-	stritem = sieve_ast_strlist_first(strlist);
-	while ( stritem != NULL ) {
-		(void) sieve_generator_emit_string_item(generator, sieve_ast_strlist_str(stritem));
-		
-		stritem = sieve_ast_strlist_next(stritem);
-	}
-
-  (void) sieve_generator_resolve_offset(generator, end_offset);
-
-  return address;
+	return sieve_binary_emit_byte(generator->binary, op);
 }
 
-/* Emit commands */
+/* Emit opcodes */
 
 sieve_size_t sieve_generator_emit_opcode
 	(struct sieve_generator *generator, int opcode)
@@ -231,19 +163,24 @@ sieve_size_t sieve_generator_emit_ext_opcode
 /* Generator functions */
 
 bool sieve_generate_arguments(struct sieve_generator *generator, 
-	struct sieve_command_context *cmd, struct sieve_ast_argument **arg)
+	struct sieve_command_context *cmd, struct sieve_ast_argument **last_arg)
 {
+	struct sieve_ast_argument *arg = sieve_ast_argument_first(cmd->ast_node);
+	
 	/* Parse all arguments with assigned generator function */
-	while ( *arg != NULL && (*arg)->argument != NULL) {
-		const struct sieve_argument *argument = (*arg)->argument;
+	while ( arg != NULL && arg->argument != NULL) {
+		const struct sieve_argument *argument = arg->argument;
 		
 		/* Call the generation function for the argument */ 
 		if ( argument->generate != NULL ) { 
-			if ( !argument->generate(generator, arg, cmd) ) 
+			if ( !argument->generate(generator, &arg, cmd) ) 
 				return FALSE;
 		} else break;
 	}
 	
+	if ( last_arg != NULL )
+		*last_arg = arg;
+	
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h
index 1ded70727..0079b5834 100644
--- a/src/lib-sieve/sieve-generator.h
+++ b/src/lib-sieve/sieve-generator.h
@@ -31,6 +31,8 @@ inline void sieve_generator_update_data
 	(struct sieve_generator *generator, sieve_size_t address, void *data, sieve_size_t size);
 inline sieve_size_t sieve_generator_get_current_address(struct sieve_generator *generator);
 
+sieve_size_t sieve_generator_emit_operand
+	(struct sieve_generator *generator, int operand);
 sieve_size_t sieve_generator_emit_opcode
 	(struct sieve_generator *generator, int opcode);
 sieve_size_t sieve_generator_emit_ext_opcode
@@ -45,21 +47,9 @@ inline void sieve_generator_resolve_offset(struct sieve_generator *generator, si
 
 inline sieve_size_t sieve_generator_emit_integer
 	(struct sieve_generator *generator, sieve_size_t integer);
-	
-/* Operand emission */
-	
-sieve_size_t sieve_generator_emit_number
-	(struct sieve_generator *generator, sieve_size_t number);
-sieve_size_t sieve_generator_emit_string
+inline sieve_size_t sieve_generator_emit_string
 	(struct sieve_generator *generator, const string_t *str);
-sieve_size_t sieve_generator_emit_string_list
-	(struct sieve_generator *generator, const struct sieve_ast_argument *strlist);
 	
-bool sieve_generator_emit_string_argument
-	(struct sieve_generator *generator, struct sieve_ast_argument *arg);
-bool sieve_generator_emit_stringlist_argument
-	(struct sieve_generator *generator, struct sieve_ast_argument *arg);
-
 /* AST generation API */
 bool sieve_generate_arguments(struct sieve_generator *generator, 
 	struct sieve_command_context *cmd, struct sieve_ast_argument **arg);
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index a1702edfb..771dcadcc 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -472,7 +472,7 @@ bool sieve_interpreter_dump_operand
 	printf("%08x:   ", interpreter->pc);
   CODE_JUMP(interpreter, 1);
   
-  if ( opcode < SIEVE_CORE_OPERAND_MASK ) {  	
+  if ( opcode < SIEVE_OPERAND_CORE_MASK ) {  	
     switch (opcode) {
     case SIEVE_OPERAND_NUMBER:
     	sieve_interpreter_dump_number(interpreter);
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index 22b501d8c..51e8ef50f 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -269,15 +269,12 @@ static bool sieve_validate_match_type_tag
 	struct sieve_ast_argument **arg, 
 	struct sieve_command_context *cmd ATTR_UNUSED)
 {
-	/* Skip tag */
-	*arg = sieve_ast_argument_next(*arg);
-
-
 	/* Syntax:   
 	 *   ":is" / ":contains" / ":matches"
    */
-
-	/* FIXME: Set appropriate setting somewhere */
+	
+	/* Not implemented, so delete it */
+	*arg = sieve_ast_arguments_delete(*arg, 1);
 		
 	return TRUE;
 }
@@ -304,15 +301,13 @@ static bool sieve_validate_address_part_tag
 	struct sieve_ast_argument **arg, 
 	struct sieve_command_context *cmd ATTR_UNUSED)
 {
-	/* Skip argument */
-	*arg = sieve_ast_argument_next(*arg);
-
 	/* Syntax:   
 	 *   ":localpart" / ":domain" / ":all"
    */
 
-	/* FIXME: Set appropriate setting somewhere */
-		
+	/* Not implemented, so delete it */
+	*arg = sieve_ast_arguments_delete(*arg, 1);		
+
 	return TRUE;
 }
 
@@ -421,6 +416,27 @@ bool sieve_validate_command_arguments
 
 	return TRUE;
 }
+
+void sieve_validator_argument_activate
+	(struct sieve_validator *validator ATTR_UNUSED, struct sieve_ast_argument *arg)
+{
+	switch ( sieve_ast_argument_type(arg) ) {
+	case SAAT_NUMBER:
+		arg->argument = &number_argument;
+		break;
+	case SAAT_STRING:
+		arg->argument = &string_argument;
+		break;
+	case SAAT_STRING_LIST:
+		arg->argument = &string_list_argument;
+		break;
+	case SAAT_TAG:
+		i_error("!!BUG!!: sieve_validator_argument_activate: cannot activate tagged argument.");
+		break;
+	default:
+		break;
+	}
+}
  
 /* Command Validation API */ 
                  
diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h
index 9ee059aee..e3aaf3b80 100644
--- a/src/lib-sieve/sieve-validator.h
+++ b/src/lib-sieve/sieve-validator.h
@@ -45,10 +45,14 @@ void sieve_validator_link_match_type_tags
 void sieve_validator_link_address_part_tags
 	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); 
 
-/* Command validation */
+/* Argument validation */
 bool sieve_validate_command_arguments
 	(struct sieve_validator *validator, struct sieve_command_context *tst, 
 	 const unsigned int count, struct sieve_ast_argument **first_positional);
+void sieve_validator_argument_activate
+	(struct sieve_validator *validator, struct sieve_ast_argument *arg);	 
+
+/* Command validation */	 
 bool sieve_validate_command_subtests
 	(struct sieve_validator *validator, struct sieve_command_context *cmd, const unsigned int count);
 bool sieve_validate_command_block(struct sieve_validator *validator, struct sieve_command_context *cmd, 
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index ed849e8a6..e7957f506 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -48,6 +48,7 @@ bool tst_address_validate(struct sieve_validator *validator, struct sieve_comman
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	arg = sieve_ast_argument_next(arg);
 	if ( sieve_ast_argument_type(arg) != SAAT_STRING && sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
@@ -56,6 +57,7 @@ bool tst_address_validate(struct sieve_validator *validator, struct sieve_comman
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	return TRUE;
 }
@@ -64,18 +66,12 @@ bool tst_address_validate(struct sieve_validator *validator, struct sieve_comman
 
 bool tst_address_generate
 	(struct sieve_generator *generator, 
-		struct sieve_command_context *ctx ATTR_UNUSED) 
+		struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
 	sieve_generator_emit_opcode(generator, SIEVE_OPCODE_ADDRESS);
 	
-	/* Emit header names */  	
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
-		return FALSE;
-	
-	/* Emit key list */
-	arg = sieve_ast_argument_next(arg);
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
+	/* Generate arguments */  	
+	if ( !sieve_generate_arguments(generator, ctx, NULL) )
 		return FALSE;
 	
 	return TRUE;
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index 30f8b25f6..1d08e7081 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -34,6 +34,7 @@ bool tst_exists_validate(struct sieve_validator *validator, struct sieve_command
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	tst->data = arg;
 	
@@ -46,12 +47,11 @@ bool tst_exists_generate
 	(struct sieve_generator *generator, 
 		struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
 	sieve_generator_emit_opcode(generator, SIEVE_OPCODE_EXISTS);
-	
-	/* Emit header names */
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
-		return FALSE;
+
+ 	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;	
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index 3c29357a6..164e958a9 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -39,14 +39,13 @@ bool tst_header_validate(struct sieve_validator *validator, struct sieve_command
 		!sieve_validate_command_subtests(validator, tst, 0) ) 
 		return FALSE;
 	
-	tst->data = arg;
-		
 	if ( sieve_ast_argument_type(arg) != SAAT_STRING && sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
 		sieve_command_validate_error(validator, tst, 
 			"the header test expects a string-list as first argument (header names), but %s was found", 
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	arg = sieve_ast_argument_next(arg);
 	if ( sieve_ast_argument_type(arg) != SAAT_STRING && sieve_ast_argument_type(arg) != SAAT_STRING_LIST ) {
@@ -55,6 +54,7 @@ bool tst_header_validate(struct sieve_validator *validator, struct sieve_command
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	return TRUE;
 }
@@ -64,18 +64,12 @@ bool tst_header_validate(struct sieve_validator *validator, struct sieve_command
 bool tst_header_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
 	sieve_generator_emit_opcode(generator, SIEVE_OPCODE_HEADER);
 
-	/* Emit header names */  	
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
-		return FALSE;
+ 	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;
 	
-	/* Emit key list */
-	arg = sieve_ast_argument_next(arg);
-	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
-		return FALSE;
-
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c
index 4a1bb8288..4af67cb98 100644
--- a/src/lib-sieve/tst-size.c
+++ b/src/lib-sieve/tst-size.c
@@ -116,6 +116,7 @@ bool tst_size_validate(struct sieve_validator *validator, struct sieve_command_c
 			sieve_ast_argument_name(arg));
 		return FALSE; 
 	}
+	sieve_validator_argument_activate(validator, arg);
 	
 	return TRUE;
 }
@@ -126,7 +127,6 @@ bool tst_size_generate
 	(struct sieve_generator *generator, 
 		struct sieve_command_context *ctx) 
 {
-	struct sieve_ast_argument *arg = sieve_ast_argument_first(ctx->ast_node);
 	struct tst_size_context_data *ctx_data = (struct tst_size_context_data *) ctx->data;
 
 	if ( ctx_data->type == SIZE_OVER ) 
@@ -134,7 +134,9 @@ bool tst_size_generate
 	else
 		sieve_generator_emit_opcode(generator, SIEVE_OPCODE_SIZEUNDER);
 
-	sieve_generator_emit_number(generator, sieve_ast_argument_number(arg));
+ 	/* Generate arguments */
+    if ( !sieve_generate_arguments(generator, ctx, NULL) )
+        return FALSE;
 	  
 	return TRUE;
 }
-- 
GitLab