diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c
index 0e6fcd40b9f33b27d9c3341ec4e1df311c737791..901a3bb897469feba56e71a120c7b4aa3f33d875 100644
--- a/src/lib-sieve/cmd-discard.c
+++ b/src/lib-sieve/cmd-discard.c
@@ -15,8 +15,8 @@ static bool cmd_discard_generate
 	(struct sieve_generator *generator, 
 		struct sieve_command_context *ctx ATTR_UNUSED); 
 
-static bool opc_discard_execute
-	(const struct sieve_opcode *opcode, 
+static bool cmd_discard_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 		
 /* Discard command 
@@ -33,15 +33,14 @@ const struct sieve_command cmd_discard = {
 	NULL 
 };
 
-/* Discard opcode */
+/* Discard operation */
 
-const struct sieve_opcode cmd_discard_opcode = { 
+const struct sieve_operation cmd_discard_operation = { 
 	"DISCARD",
-	SIEVE_OPCODE_DISCARD,
 	NULL,
-	0,
+	SIEVE_OPERATION_DISCARD,
 	NULL, 
-	opc_discard_execute 
+	cmd_discard_operation_execute 
 };
 
 /* discard action */
@@ -72,7 +71,7 @@ static bool cmd_discard_generate
 		struct sieve_command_context *ctx ATTR_UNUSED) 
 {
 	sieve_operation_emit_code(
-        sieve_generator_get_binary(generator), &cmd_discard_opcode);
+        sieve_generator_get_binary(generator), &cmd_discard_operation, -1);
 	return TRUE;
 }
 
@@ -80,8 +79,8 @@ static bool cmd_discard_generate
  * Interpretation
  */
 
-static bool opc_discard_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_discard_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv ATTR_UNUSED, 
 	sieve_size_t *address ATTR_UNUSED)
 {	
diff --git a/src/lib-sieve/cmd-if.c b/src/lib-sieve/cmd-if.c
index 06bbfa07d111a737e0849652feb0538457022e21..279f694bd37eb0ffc4b1194e4b8e0d756cbbdb34 100644
--- a/src/lib-sieve/cmd-if.c
+++ b/src/lib-sieve/cmd-if.c
@@ -165,7 +165,7 @@ static bool cmd_if_generate
 		 * anyway. 
 		 */
 		if ( !sieve_command_block_exits_unconditionally(ctx) ) {
-			sieve_operation_emit_code(sbin, &sieve_jmp_opcode);
+			sieve_operation_emit_code(sbin, &sieve_jmp_operation, -1);
 			ctx_data->exit_jump = sieve_binary_emit_offset(sbin, 0);
 			ctx_data->jump_generated = TRUE;
 		}
diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c
index 7834f2056dd461e21980227db06aa57b0592a4e4..982e49e349d26ff9e0fa401d22217618273ddbc0 100644
--- a/src/lib-sieve/cmd-keep.c
+++ b/src/lib-sieve/cmd-keep.c
@@ -11,8 +11,8 @@
 
 /* Forward declarations */
 
-static bool opc_keep_execute
-	(const struct sieve_opcode *opcode, 
+static bool cmd_keep_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_keep_generate
@@ -33,15 +33,14 @@ const struct sieve_command cmd_keep = {
 	NULL
 };
 
-/* Keep opcode */
+/* Keep operation */
 
-const struct sieve_opcode cmd_keep_opcode = { 
+const struct sieve_operation cmd_keep_operation = { 
 	"KEEP",
-	SIEVE_OPCODE_KEEP,
 	NULL,
-	0,
+	SIEVE_OPERATION_KEEP,
 	NULL, 
-	opc_keep_execute 
+	cmd_keep_operation_execute 
 };
 
 /*
@@ -53,7 +52,7 @@ static bool cmd_keep_generate
 		struct sieve_command_context *ctx ATTR_UNUSED) 
 {
 	sieve_operation_emit_code(
-        sieve_generator_get_binary(generator), &cmd_keep_opcode);
+        sieve_generator_get_binary(generator), &cmd_keep_operation, -1);
 	return TRUE;
 }
 
@@ -61,8 +60,8 @@ static bool cmd_keep_generate
  * Interpretation
  */
 
-static bool opc_keep_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_keep_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv ATTR_UNUSED, 
 	sieve_size_t *address ATTR_UNUSED)
 {	
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index d0557d4a42e7446982f27c0acbe77f41dc42ea1d..e374e8bafaacb2b812bb4fc0bdd1e28d22a31c0b 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -22,11 +22,11 @@
 
 /* Forward declarations */
 
-static bool cmd_redirect_opcode_dump
-	(const struct sieve_opcode *opcode,
+static bool cmd_redirect_operation_dump
+	(const struct sieve_operation *op,
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool cmd_redirect_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool cmd_redirect_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_redirect_validate
@@ -50,14 +50,14 @@ const struct sieve_command cmd_redirect = {
 	NULL 
 };
 
-/* Redirect opcode */
+/* Redirect operation */
 
-const struct sieve_opcode cmd_redirect_opcode = { 
+const struct sieve_operation cmd_redirect_operation = { 
 	"REDIRECT",
-	SIEVE_OPCODE_REDIRECT,
-	NULL, 0,
-	cmd_redirect_opcode_dump, 
-	cmd_redirect_opcode_execute 
+	NULL, 
+	SIEVE_OPERATION_REDIRECT,
+	cmd_redirect_operation_dump, 
+	cmd_redirect_operation_execute 
 };
 
 /* Redirect action */
@@ -110,7 +110,7 @@ static bool cmd_redirect_validate
 static bool cmd_redirect_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode(generator, &cmd_redirect_opcode);
+	sieve_generator_emit_operation(generator, &cmd_redirect_operation);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -123,8 +123,8 @@ static bool cmd_redirect_generate
  * Code dump
  */
  
-static bool cmd_redirect_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_redirect_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	sieve_code_dumpf(denv, "REDIRECT");
@@ -141,8 +141,8 @@ static bool cmd_redirect_opcode_dump
  * Intepretation
  */
 
-static bool cmd_redirect_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_redirect_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	struct sieve_side_effects_list *slist = NULL;
diff --git a/src/lib-sieve/ext-encoded-character.c b/src/lib-sieve/ext-encoded-character.c
index 96f017897595bd5f4a5915cbc35d56d3efc9acac..8733ec93abf6a4db4a987d22cbc362702dc930b1 100644
--- a/src/lib-sieve/ext-encoded-character.c
+++ b/src/lib-sieve/ext-encoded-character.c
@@ -11,7 +11,7 @@
 #include "lib.h"
 #include "unichar.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
 
@@ -29,8 +29,8 @@ struct sieve_extension encoded_character_extension = {
 	ext_encoded_character_load,
 	ext_encoded_character_validator_load, 
 	NULL, NULL, NULL, 
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL 
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_encoded_character_load(int ext_id) 
diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index b776f7c7921c89679b7800c93aa66e5a97ed2d7c..641eeaccb3d894c2ca0270c3dd370f50dc60a4c8 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -13,7 +13,7 @@
 #include "lib.h"
 #include "array.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-code.h"
 #include "sieve-comparators.h"
@@ -30,11 +30,11 @@
 static bool ext_envelope_load(int ext_id);
 static bool ext_envelope_validator_load(struct sieve_validator *validator);
 
-static bool ext_envelope_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool ext_envelope_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool ext_envelope_opcode_execute
-	(const struct sieve_opcode *opcode,
+static bool ext_envelope_operation_execute
+	(const struct sieve_operation *op,
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool tst_envelope_registered
@@ -48,15 +48,15 @@ static bool tst_envelope_generate
 
 static int ext_my_id;
 
-const struct sieve_opcode envelope_opcode;
+const struct sieve_operation envelope_operation;
 
 const struct sieve_extension envelope_extension = { 
 	"envelope", 
 	ext_envelope_load,
 	ext_envelope_validator_load, 
 	NULL, NULL, NULL, 
-	SIEVE_EXT_DEFINE_OPCODE(envelope_opcode), 
-	NULL 
+	SIEVE_EXT_DEFINE_OPERATION(envelope_operation), 
+	SIEVE_EXT_DEFINE_NO_OPERANDS 
 };
 
 static bool ext_envelope_load(int ext_id) 
@@ -82,15 +82,14 @@ static const struct sieve_command envelope_test = {
 	NULL 
 };
 
-/* Envelope opcode */
+/* Envelope operation */
 
-const struct sieve_opcode envelope_opcode = { 
+const struct sieve_operation envelope_operation = { 
 	"ENVELOPE",
-	SIEVE_OPCODE_CUSTOM,
 	&envelope_extension,
 	0,
-	ext_envelope_opcode_dump, 
-	ext_envelope_opcode_execute 
+	ext_envelope_operation_dump, 
+	ext_envelope_operation_execute 
 };
 
 /* Command Registration */
@@ -148,8 +147,8 @@ static bool ext_envelope_validator_load(struct sieve_validator *validator)
 static bool tst_envelope_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	(void)sieve_generator_emit_opcode_ext
-		(generator, &envelope_opcode, ext_my_id);
+	(void)sieve_generator_emit_operation_ext
+		(generator, &envelope_operation, ext_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -162,8 +161,8 @@ static bool tst_envelope_generate
  * Code dump 
  */
  
-static bool ext_envelope_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool ext_envelope_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	sieve_code_dumpf(denv, "ENVELOPE");
@@ -203,8 +202,8 @@ static int ext_envelope_get_fields
 	return 0;
 }
 
-static bool ext_envelope_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_envelope_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index f53cae6ffed5224b8288b61127db48d9a1d33f23..e4e3c5b76335fe356b094d4f9ee75bc626bb445d 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -10,7 +10,7 @@
 
 #include <stdio.h>
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-code.h"
 #include "sieve-actions.h"
@@ -25,11 +25,11 @@
 static bool ext_fileinto_load(int ext_id);
 static bool ext_fileinto_validator_load(struct sieve_validator *validator);
 
-static bool ext_fileinto_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool ext_fileinto_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool ext_fileinto_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool ext_fileinto_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address); 
 
 static bool cmd_fileinto_validate
@@ -41,15 +41,15 @@ static bool cmd_fileinto_generate
 
 static int ext_my_id;
 
-const struct sieve_opcode fileinto_opcode;
+const struct sieve_operation fileinto_operation;
 
 const struct sieve_extension fileinto_extension = { 
 	"fileinto", 
 	ext_fileinto_load,
 	ext_fileinto_validator_load, 
 	NULL, NULL, NULL,
-	SIEVE_EXT_DEFINE_OPCODE(fileinto_opcode), 
-	NULL	
+	SIEVE_EXT_DEFINE_OPERATION(fileinto_operation), 
+	SIEVE_EXT_DEFINE_NO_OPERANDS	
 };
 
 static bool ext_fileinto_load(int ext_id) 
@@ -73,15 +73,14 @@ static const struct sieve_command fileinto_command = {
 	NULL 
 };
 
-/* Fileinto opcode */
+/* Fileinto operation */
 
-const struct sieve_opcode fileinto_opcode = { 
+const struct sieve_operation fileinto_operation = { 
 	"FILEINTO",
-	SIEVE_OPCODE_CUSTOM,
 	&fileinto_extension,
 	0,
-	ext_fileinto_opcode_dump, 
-	ext_fileinto_opcode_execute 
+	ext_fileinto_operation_dump, 
+	ext_fileinto_operation_execute 
 };
 
 /* Validation */
@@ -115,7 +114,7 @@ static bool ext_fileinto_validator_load(struct sieve_validator *validator)
 static bool cmd_fileinto_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &fileinto_opcode, ext_my_id);
+	sieve_generator_emit_operation_ext(generator, &fileinto_operation, ext_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -128,8 +127,8 @@ static bool cmd_fileinto_generate
  * Code dump
  */
  
-static bool ext_fileinto_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_fileinto_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	sieve_code_dumpf(denv, "FILEINTO");
@@ -146,8 +145,8 @@ static bool ext_fileinto_opcode_dump
  * Execution
  */
 
-static bool ext_fileinto_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_fileinto_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	struct sieve_side_effects_list *slist = NULL; 
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index e9fc70b26a9a8a641d16bac7309829b09c715d07..88765aa37fa114dec6e761946ffc21746f554e0f 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -16,7 +16,7 @@
 #include "istream.h"
 #include "istream-header-filter.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-code.h"
 #include "sieve-actions.h"
@@ -37,26 +37,26 @@ static bool cmd_reject_validate
 static bool cmd_reject_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx); 
 
-static bool ext_reject_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool ext_reject_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool ext_reject_opcode_execute
-	(const struct sieve_opcode *opcode,
+static bool ext_reject_operation_execute
+	(const struct sieve_operation *op,
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Extension definitions */
 
 static int ext_my_id;
 
-struct sieve_opcode reject_opcode;
+struct sieve_operation reject_operation;
 	
 struct sieve_extension reject_extension = { 
 	"reject", 
 	ext_reject_load,
 	ext_reject_validator_load, 
 	NULL, NULL, NULL, 
-	SIEVE_EXT_DEFINE_OPCODE(reject_opcode), 
-	NULL 
+	SIEVE_EXT_DEFINE_OPERATION(reject_operation), 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_reject_load(int ext_id) 
@@ -80,15 +80,14 @@ static const struct sieve_command reject_command = {
 	NULL 
 };
 
-/* Reject opcode */
+/* Reject operation */
 
-struct sieve_opcode reject_opcode = { 
+struct sieve_operation reject_operation = { 
 	"REJECT",
-	SIEVE_OPCODE_CUSTOM,
 	&reject_extension, 
 	0,
-	ext_reject_opcode_dump, 
-	ext_reject_opcode_execute 
+	ext_reject_operation_dump, 
+	ext_reject_operation_execute 
 };
 
 /* Reject action */
@@ -153,7 +152,8 @@ static bool ext_reject_validator_load(struct sieve_validator *validator)
 static bool cmd_reject_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &reject_opcode, ext_my_id);
+	sieve_generator_emit_operation_ext
+		(generator, &reject_operation, ext_my_id);
 
 	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -166,8 +166,8 @@ static bool cmd_reject_generate
  * Code dump
  */
  
-static bool ext_reject_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_reject_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	sieve_code_dumpf(denv, "REJECT");
@@ -184,8 +184,8 @@ static bool ext_reject_opcode_dump
  * Execution
  */
 
-static bool ext_reject_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_reject_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	struct sieve_side_effects_list *slist = NULL;
diff --git a/src/lib-sieve/plugins/body/ext-body.c b/src/lib-sieve/plugins/body/ext-body.c
index c39e486571a6d8ccec14230573a7eb029074ab41..8fba4e08b81ba7aa0420979b1389581317fec118 100644
--- a/src/lib-sieve/plugins/body/ext-body.c
+++ b/src/lib-sieve/plugins/body/ext-body.c
@@ -27,7 +27,7 @@
 #include "lib.h"
 #include "array.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-comparators.h"
 #include "sieve-match-types.h"
@@ -48,10 +48,10 @@
 extern const struct sieve_command body_test;
  
 /*
- * Opcodes
+ * Operations
  */
 
-extern const struct sieve_opcode body_opcode;
+extern const struct sieve_operation body_operation;
 
 /* 
  * Extension definitions 
@@ -67,8 +67,8 @@ const struct sieve_extension body_extension = {
 	ext_body_load,
 	ext_body_validator_load, 
 	NULL, NULL, NULL, 
-	SIEVE_EXT_DEFINE_OPCODE(body_opcode), 
-	NULL 
+	SIEVE_EXT_DEFINE_OPERATION(body_operation), 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_body_load(int ext_id) 
diff --git a/src/lib-sieve/plugins/body/tst-body.c b/src/lib-sieve/plugins/body/tst-body.c
index f0c0e0a3da7a0cd00f1c6668af467af6d71de0a1..f40d249a32447a132af438612667a49e41c49071 100644
--- a/src/lib-sieve/plugins/body/tst-body.c
+++ b/src/lib-sieve/plugins/body/tst-body.c
@@ -17,11 +17,11 @@
  * Forward declarations 
  */
 
-static bool ext_body_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool ext_body_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool ext_body_opcode_execute
-	(const struct sieve_opcode *opcode,
+static bool ext_body_operation_execute
+	(const struct sieve_operation *op,
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool tst_body_registered
@@ -48,15 +48,14 @@ const struct sieve_command body_test = {
 	NULL 
 };
 
-/* body opcode */
+/* Body operation */
 
-const struct sieve_opcode body_opcode = { 
+const struct sieve_operation body_operation = { 
 	"body",
-	SIEVE_OPCODE_CUSTOM,
 	&body_extension,
 	0,
-	ext_body_opcode_dump, 
-	ext_body_opcode_execute 
+	ext_body_operation_dump, 
+	ext_body_operation_execute 
 };
 
 enum tst_body_optional {	
@@ -208,7 +207,8 @@ static bool tst_body_validate
 static bool tst_body_generate
 	(struct sieve_generator *gentr,	struct sieve_command_context *ctx) 
 {
-	(void)sieve_generator_emit_opcode_ext(gentr, &body_opcode, ext_body_my_id);
+	(void)sieve_generator_emit_operation_ext
+		(gentr, &body_operation, ext_body_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(gentr, ctx, NULL) )
@@ -234,8 +234,8 @@ static bool tag_body_transform_generate
  * Code dump 
  */
  
-static bool ext_body_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool ext_body_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	int opt_code = 1;
@@ -292,8 +292,8 @@ static bool ext_body_opcode_dump
 		sieve_opr_stringlist_dump(denv, address);
 }
 
-static bool ext_body_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_body_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c b/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c
index 360cadb92899d80cb86c3f198456bf31736a0fb0..6d02802985852ace3d09426f895436cf1898c4f4 100644
--- a/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c
+++ b/src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c
@@ -11,7 +11,7 @@
 #include "sieve-common.h"
 
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-comparators.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
@@ -36,8 +36,8 @@ const struct sieve_extension comparator_i_ascii_numeric_extension = {
 	NULL, 
 	ext_cmp_i_ascii_numeric_binary_load,  
 	NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_cmp_i_ascii_numeric_load(int ext_id)
diff --git a/src/lib-sieve/plugins/copy/copy.sieve b/src/lib-sieve/plugins/copy/copy.sieve
index ddcd14808a35a0dee04430b7af9a9154d5fa96c4..972ec15047f2a0861c8d6a6bc2c99bc644766730 100644
--- a/src/lib-sieve/plugins/copy/copy.sieve
+++ b/src/lib-sieve/plugins/copy/copy.sieve
@@ -1,5 +1,5 @@
 require ["copy", "fileinto"];
 
-redirect :copy "sirius@rename-it.nl";
 fileinto :copy "frop";
+redirect :copy "sirius@rename-it.nl";
 
diff --git a/src/lib-sieve/plugins/copy/ext-copy.c b/src/lib-sieve/plugins/copy/ext-copy.c
index 506af03fe772cb266f1a08ca5c43d3557ffdad88..f25cf894afcf15cdd0ea0689095328e2a75a4698 100644
--- a/src/lib-sieve/plugins/copy/ext-copy.c
+++ b/src/lib-sieve/plugins/copy/ext-copy.c
@@ -13,7 +13,7 @@
 #include "sieve-common.h"
 
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-actions.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
@@ -38,8 +38,8 @@ const struct sieve_extension copy_extension = {
 	NULL, 
 	ext_copy_binary_load, 
 	NULL, 
-	SIEVE_EXT_DEFINE_NO_OPCODES,
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS,
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_copy_load(int ext_id)
diff --git a/src/lib-sieve/plugins/imapflags/cmd-addflag.c b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
index fa727c41e9a6bd17b2c344f9e21e1ad00eb31cfd..7acf3700f1f556c404a4961244d877c82b6c3a41 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-addflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
@@ -13,8 +13,8 @@
 static bool cmd_addflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 	
-static bool cmd_addflag_opcode_execute
-	(const struct sieve_opcode *opcode,	
+static bool cmd_addflag_operation_execute
+	(const struct sieve_operation *op,	
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 
@@ -35,15 +35,14 @@ const struct sieve_command cmd_addflag = {
 	NULL 
 };
 
-/* Addflag opcode */
+/* Addflag operation */
 
-const struct sieve_opcode addflag_opcode = { 
+const struct sieve_operation addflag_operation = { 
 	"ADDFLAG",
-	SIEVE_OPCODE_CUSTOM,
 	&imapflags_extension,
-	EXT_IMAPFLAGS_OPCODE_ADDFLAG,
-	ext_imapflags_command_opcode_dump,
-	cmd_addflag_opcode_execute
+	EXT_IMAPFLAGS_OPERATION_ADDFLAG,
+	ext_imapflags_command_operation_dump,
+	cmd_addflag_operation_execute
 };
 
 /* Code generation */
@@ -51,8 +50,8 @@ const struct sieve_opcode addflag_opcode = {
 static bool cmd_addflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx)
 {
-	sieve_generator_emit_opcode_ext	
-		(generator, &addflag_opcode, ext_imapflags_my_id);
+	sieve_generator_emit_operation_ext	
+		(generator, &addflag_operation, ext_imapflags_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -65,8 +64,8 @@ static bool cmd_addflag_generate
  * Execution
  */
 
-static bool cmd_addflag_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_addflag_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
index 93e31e99a85717006c55ab456dbe98932ce89e2a..f1739153bf021525859b030f93888e2b25f997d4 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
@@ -13,8 +13,8 @@
 static bool cmd_removeflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
-static bool cmd_removeflag_opcode_execute
-	(const struct sieve_opcode *opcode,	
+static bool cmd_removeflag_operation_execute
+	(const struct sieve_operation *op,	
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Removeflag command 
@@ -34,15 +34,14 @@ const struct sieve_command cmd_removeflag = {
 	NULL 
 };
 
-/* Removeflag opcode */
+/* Removeflag operation */
 
-const struct sieve_opcode removeflag_opcode = { 
+const struct sieve_operation removeflag_operation = { 
 	"REMOVEFLAG",
-	SIEVE_OPCODE_CUSTOM,
 	&imapflags_extension,
-	EXT_IMAPFLAGS_OPCODE_REMOVEFLAG,
-	ext_imapflags_command_opcode_dump, 
-	cmd_removeflag_opcode_execute 
+	EXT_IMAPFLAGS_OPERATION_REMOVEFLAG,
+	ext_imapflags_command_operation_dump, 
+	cmd_removeflag_operation_execute 
 };
 
 /* 
@@ -52,8 +51,8 @@ const struct sieve_opcode removeflag_opcode = {
 static bool cmd_removeflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx)
 {
-	sieve_generator_emit_opcode_ext
-		(generator, &removeflag_opcode, ext_imapflags_my_id);
+	sieve_generator_emit_operation_ext
+		(generator, &removeflag_operation, ext_imapflags_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -66,8 +65,8 @@ static bool cmd_removeflag_generate
  * Execution
  */
 
-static bool cmd_removeflag_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_removeflag_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/plugins/imapflags/cmd-setflag.c b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
index 246e3b7c12d5d2ac65d0cb0c11dd63490eff4489..3b0adba792fe9378cb48dd5d7b0da0b63d251356 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-setflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
@@ -13,8 +13,8 @@
 static bool cmd_setflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
-static bool cmd_setflag_opcode_execute
-	(const struct sieve_opcode *opcode,
+static bool cmd_setflag_operation_execute
+	(const struct sieve_operation *op,
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Setflag command 
@@ -34,15 +34,14 @@ const struct sieve_command cmd_setflag = {
 	NULL 
 };
 
-/* Setflag opcode */
+/* Setflag operation */
 
-const struct sieve_opcode setflag_opcode = { 
+const struct sieve_operation setflag_operation = { 
 	"SETFLAG",
-	SIEVE_OPCODE_CUSTOM,
 	&imapflags_extension,
-	EXT_IMAPFLAGS_OPCODE_SETFLAG,
-	ext_imapflags_command_opcode_dump,
-	cmd_setflag_opcode_execute
+	EXT_IMAPFLAGS_OPERATION_SETFLAG,
+	ext_imapflags_command_operation_dump,
+	cmd_setflag_operation_execute
 };
 
 /* Code generation */
@@ -50,8 +49,8 @@ const struct sieve_opcode setflag_opcode = {
 static bool cmd_setflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx)
 {
-	sieve_generator_emit_opcode_ext
-		(generator, &setflag_opcode, ext_imapflags_my_id);
+	sieve_generator_emit_operation_ext
+		(generator, &setflag_operation, ext_imapflags_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -64,8 +63,8 @@ static bool cmd_setflag_generate
  * Execution
  */
 
-static bool cmd_setflag_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_setflag_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
index a4a7473ba0a924224402125c20d0bb726c757f0d..6160db49d41bcd515e5e2599490da2a8f4ab149e 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
@@ -78,11 +78,11 @@ bool ext_imapflags_command_validate
 	return TRUE;
 }
 
-bool ext_imapflags_command_opcode_dump
-(const struct sieve_opcode *opcode,
+bool ext_imapflags_command_operation_dump
+(const struct sieve_operation *op,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	sieve_code_dumpf(denv, "%s", opcode->mnemonic);
+	sieve_code_dumpf(denv, "%s", op->mnemonic);
 	sieve_code_descend(denv);
 
 	return 
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
index 267fc97b9e5b9ad81dc90d93f78767141c60046a..94812fbd679a3510605254938617ba329e57a5b3 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
@@ -7,17 +7,17 @@ extern int ext_imapflags_my_id;
 extern const struct sieve_extension imapflags_extension;
 
 enum ext_imapflags_opcode {
-	EXT_IMAPFLAGS_OPCODE_SETFLAG,
-	EXT_IMAPFLAGS_OPCODE_ADDFLAG,
-	EXT_IMAPFLAGS_OPCODE_REMOVEFLAG,
-	EXT_IMAPFLAGS_OPCODE_HASFLAG
+	EXT_IMAPFLAGS_OPERATION_SETFLAG,
+	EXT_IMAPFLAGS_OPERATION_ADDFLAG,
+	EXT_IMAPFLAGS_OPERATION_REMOVEFLAG,
+	EXT_IMAPFLAGS_OPERATION_HASFLAG
 };
 
 bool ext_imapflags_command_validate
 	(struct sieve_validator *validator, struct sieve_command_context *cmd);
 
-bool ext_imapflags_command_opcode_dump
-(const struct sieve_opcode *opcode,	
+bool ext_imapflags_command_operation_dump
+(const struct sieve_operation *op,	
 	const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
 /* Flag registration */
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags.c b/src/lib-sieve/plugins/imapflags/ext-imapflags.c
index 2ec9c823a54e8c87e193ba0cc67cbe05d1afa565..e9da7d5a3d5a685aa12a7f9ca47e727d26ffe6cc 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags.c
@@ -49,15 +49,15 @@ extern const struct sieve_command tst_hasflag;
 
 extern const struct sieve_argument tag_flags;
 
-/* Opcodes */
+/* Operations */
 
-extern const struct sieve_opcode setflag_opcode;
-extern const struct sieve_opcode addflag_opcode;
-extern const struct sieve_opcode removeflag_opcode;
-extern const struct sieve_opcode hasflag_opcode;
+extern const struct sieve_operation setflag_operation;
+extern const struct sieve_operation addflag_operation;
+extern const struct sieve_operation removeflag_operation;
+extern const struct sieve_operation hasflag_operation;
 
-const struct sieve_opcode *imapflags_opcodes[] = 
-	{ &setflag_opcode, &addflag_opcode, &removeflag_opcode, &hasflag_opcode };
+const struct sieve_operation *imapflags_operations[] = 
+	{ &setflag_operation, &addflag_operation, &removeflag_operation, &hasflag_operation };
 
 /* Extension definitions */
 
@@ -70,8 +70,8 @@ const struct sieve_extension imapflags_extension = {
 	NULL, 
 	ext_imapflags_binary_load,
 	ext_imapflags_interpreter_load, 
-	SIEVE_EXT_DEFINE_OPCODES(imapflags_opcodes), 
-	NULL
+	SIEVE_EXT_DEFINE_OPERATIONS(imapflags_operations), 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_imapflags_load(int ext_id)
diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c
index 943b6ce2f02a5c4a64edc26bbd38a917770ab5e7..b1f061a8a05427afc0228d9445d1b4c8d1904cb7 100644
--- a/src/lib-sieve/plugins/imapflags/tag-flags.c
+++ b/src/lib-sieve/plugins/imapflags/tag-flags.c
@@ -2,14 +2,14 @@
 #include "array.h"
 #include "mail-storage.h"
 
-#include "sieve-extensions.h"
-#include "sieve-commands.h"
 #include "sieve-code.h"
-#include "sieve-actions.h"
+#include "sieve-extensions-private.h"
+#include "sieve-commands.h"
 #include "sieve-result.h"
 #include "sieve-validator.h" 
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-actions.h"
 
 #include "ext-imapflags-common.h"
 
diff --git a/src/lib-sieve/plugins/imapflags/tst-hasflag.c b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
index 8c81ed7029a41d48a35d2944c0c4276004cf3afd..19eda59053991d77ad521f8309b9e8a5e5abfec1 100644
--- a/src/lib-sieve/plugins/imapflags/tst-hasflag.c
+++ b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
@@ -21,11 +21,11 @@ static bool tst_hasflag_validate
 static bool tst_hasflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
-static bool tst_hasflag_opcode_dump
-	(const struct sieve_opcode *opcode,	
+static bool tst_hasflag_operation_dump
+	(const struct sieve_operation *op,	
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool tst_hasflag_opcode_execute
-	(const struct sieve_opcode *opcode,	
+static bool tst_hasflag_operation_execute
+	(const struct sieve_operation *op,	
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Hasflag test
@@ -47,15 +47,14 @@ const struct sieve_command tst_hasflag = {
 	NULL 
 };
 
-/* Hasflag opcode */
+/* Hasflag operation */
 
-const struct sieve_opcode hasflag_opcode = { 
+const struct sieve_operation hasflag_operation = { 
 	"HASFLAG",
-	SIEVE_OPCODE_CUSTOM,
 	&imapflags_extension,
-	EXT_IMAPFLAGS_OPCODE_HASFLAG,
-	tst_hasflag_opcode_dump,
-	tst_hasflag_opcode_execute
+	EXT_IMAPFLAGS_OPERATION_HASFLAG,
+	tst_hasflag_operation_dump,
+	tst_hasflag_operation_execute
 };
 
 /* Optional arguments */
@@ -150,8 +149,8 @@ static bool tst_hasflag_validate
 static bool tst_hasflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx)
 {
-	sieve_generator_emit_opcode_ext
-		(generator, &hasflag_opcode, ext_imapflags_my_id);
+	sieve_generator_emit_operation_ext
+		(generator, &hasflag_operation, ext_imapflags_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -164,13 +163,14 @@ static bool tst_hasflag_generate
  * Code dump 
  */
  
-static bool tst_hasflag_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,	
+static bool tst_hasflag_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,	
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	int opt_code = 1;
 
 	sieve_code_dumpf(denv, "HASFLAG");
+	sieve_code_descend(denv);
 
 	/* Handle any optional arguments */
 	if ( sieve_operand_optional_present(denv->sbin, address) ) {
@@ -201,8 +201,8 @@ static bool tst_hasflag_opcode_dump
  * Execution
  */
 
-static bool tst_hasflag_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool tst_hasflag_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	int opt_code = 1;
diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c
index fb248341926dfb6a3e068aba2042feff13648ded..3e9b03a13ea2dd215e25b17399fb8328b27d4244 100644
--- a/src/lib-sieve/plugins/include/cmd-include.c
+++ b/src/lib-sieve/plugins/include/cmd-include.c
@@ -17,10 +17,10 @@
 /* Forward declarations */
 
 static bool opc_include_dump
-	(const struct sieve_opcode *opcode,	
+	(const struct sieve_operation *op,	
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
 static bool opc_include_execute
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_include_registered
@@ -53,13 +53,12 @@ const struct sieve_command cmd_include = {
 	NULL 
 };
 
-/* Include opcode */
+/* Include operation */
 
-const struct sieve_opcode include_opcode = { 
+const struct sieve_operation include_operation = { 
 	"include",
-	SIEVE_OPCODE_CUSTOM,
 	&include_extension,
-	EXT_INCLUDE_OPCODE_INCLUDE,
+	EXT_INCLUDE_OPERATION_INCLUDE,
 	opc_include_dump, 
 	opc_include_execute
 };
@@ -195,8 +194,8 @@ static bool cmd_include_generate
 		(gentr, cmd, ctx_data->location, ctx_data->script_name, &block_id) ) 
  		return FALSE;
  		
- 	sieve_generator_emit_opcode_ext	
-		(gentr, &include_opcode, ext_include_my_id);
+ 	sieve_generator_emit_operation_ext	
+		(gentr, &include_operation, ext_include_my_id);
 	sieve_binary_emit_offset(sbin, block_id); 
  	 		
 	return TRUE;
@@ -207,7 +206,7 @@ static bool cmd_include_generate
  */
  
 static bool opc_include_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	int block;
@@ -225,7 +224,7 @@ static bool opc_include_dump
  */
  
 static bool opc_include_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	int block;
diff --git a/src/lib-sieve/plugins/include/cmd-return.c b/src/lib-sieve/plugins/include/cmd-return.c
index d684de2e26d49d21866efd73125c97ad899d1a3f..ea7db1a7001b41c84e0418b771c155f9bc69ba52 100644
--- a/src/lib-sieve/plugins/include/cmd-return.c
+++ b/src/lib-sieve/plugins/include/cmd-return.c
@@ -11,7 +11,7 @@
 /* Forward declarations */
 
 static bool opc_return_execute
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_return_generate
@@ -32,13 +32,12 @@ const struct sieve_command cmd_return = {
 	NULL
 };
 
-/* Return opcode */
+/* Return operation */
 
-const struct sieve_opcode return_opcode = { 
+const struct sieve_operation return_operation = { 
 	"return",
-	SIEVE_OPCODE_CUSTOM,
 	&include_extension,
-	EXT_INCLUDE_OPCODE_RETURN,
+	EXT_INCLUDE_OPERATION_RETURN,
 	NULL, 
 	opc_return_execute 
 };
@@ -50,8 +49,8 @@ const struct sieve_opcode return_opcode = {
 static bool cmd_return_generate
 (struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) 
 {
-	sieve_generator_emit_opcode_ext	
-		(gentr, &return_opcode, ext_include_my_id);
+	sieve_generator_emit_operation_ext	
+		(gentr, &return_operation, ext_include_my_id);
 
 	return TRUE;
 }
@@ -61,7 +60,7 @@ static bool cmd_return_generate
  */
 
 static bool opc_return_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, 
 	sieve_size_t *address ATTR_UNUSED)
 {	
diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h
index 309086619eaa8c575d21573dd9e2164815af309a..107367faaeb710e4cc1a6304f7ed26ac4e08b80c 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.h
+++ b/src/lib-sieve/plugins/include/ext-include-common.h
@@ -18,8 +18,8 @@ extern const struct sieve_extension include_extension;
 /* Types */
 
 enum ext_include_opcode {
-	EXT_INCLUDE_OPCODE_INCLUDE,
-	EXT_INCLUDE_OPCODE_RETURN
+	EXT_INCLUDE_OPERATION_INCLUDE,
+	EXT_INCLUDE_OPERATION_RETURN
 };
 
 enum ext_include_script_location { 
diff --git a/src/lib-sieve/plugins/include/ext-include.c b/src/lib-sieve/plugins/include/ext-include.c
index 593c695807e590ad6ba8512af3be50cbd866ecbf..622ba1d2bc5d6da5061ef5fd599b3551978dcda5 100644
--- a/src/lib-sieve/plugins/include/ext-include.c
+++ b/src/lib-sieve/plugins/include/ext-include.c
@@ -21,7 +21,7 @@
 
 #include "sieve-common.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
@@ -42,13 +42,13 @@ static bool ext_include_interpreter_load(struct sieve_interpreter *interp);
 extern const struct sieve_command cmd_include;
 extern const struct sieve_command cmd_return;
 
-/* Opcodes */
+/* Operations */
 
-extern const struct sieve_opcode include_opcode;
-extern const struct sieve_opcode return_opcode;
+extern const struct sieve_operation include_operation;
+extern const struct sieve_operation return_operation;
 
-static const struct sieve_opcode *ext_include_opcodes[] =
-	{ &include_opcode, &return_opcode };
+static const struct sieve_operation *ext_include_operations[] =
+	{ &include_operation, &return_operation };
 
 /* Extension definitions */
 
@@ -61,8 +61,8 @@ const struct sieve_extension include_extension = {
 	ext_include_generator_load,
 	ext_include_binary_load, 
 	ext_include_interpreter_load, 
-	SIEVE_EXT_DEFINE_OPCODES(ext_include_opcodes),
-	NULL
+	SIEVE_EXT_DEFINE_OPERATIONS(ext_include_operations),
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_include_load(int ext_id)
diff --git a/src/lib-sieve/plugins/regex/ext-regex.c b/src/lib-sieve/plugins/regex/ext-regex.c
index e1d13144c89dbcc178c24957abc06dfcb8be8158..6fcb32a629c2ac789ef2dbdbeffbd28169a20f69 100644
--- a/src/lib-sieve/plugins/regex/ext-regex.c
+++ b/src/lib-sieve/plugins/regex/ext-regex.c
@@ -21,7 +21,7 @@
 #include "sieve-common.h"
 
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 
 #include "sieve-comparators.h"
@@ -58,8 +58,8 @@ const struct sieve_extension regex_extension = {
 	NULL, 
 	ext_regex_binary_load,
 	NULL,  
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_regex_load(int ext_id)
diff --git a/src/lib-sieve/plugins/relational/ext-relational.c b/src/lib-sieve/plugins/relational/ext-relational.c
index cd748dfaa076cfc6f3ef7b241d91ddfbe80b93d5..12426b05f1e86114a828dacbafa934e8b38b0229 100644
--- a/src/lib-sieve/plugins/relational/ext-relational.c
+++ b/src/lib-sieve/plugins/relational/ext-relational.c
@@ -23,7 +23,7 @@
 
 #include "sieve-ast.h"
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-comparators.h"
 #include "sieve-match-types.h"
@@ -40,8 +40,8 @@ static bool ext_relational_binary_load(struct sieve_binary *sbin);
 /* Types */
 
 enum ext_relational_match_type {
-  RELATIONAL_VALUE,
-  RELATIONAL_COUNT
+	RELATIONAL_VALUE,
+	RELATIONAL_COUNT
 };
 
 enum relational_match {
@@ -72,8 +72,8 @@ const struct sieve_extension relational_extension = {
 	NULL, 
 	ext_relational_binary_load,  
 	NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_relational_load(int ext_id)
diff --git a/src/lib-sieve/plugins/subaddress/ext-subaddress.c b/src/lib-sieve/plugins/subaddress/ext-subaddress.c
index d706d65d2d7960c40b73d39d211fc373ba3c3bd8..180f0558acba440781e0f14990de7f360e9baaf0 100644
--- a/src/lib-sieve/plugins/subaddress/ext-subaddress.c
+++ b/src/lib-sieve/plugins/subaddress/ext-subaddress.c
@@ -14,7 +14,7 @@
 #include "sieve-common.h"
 
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-address-parts.h"
 #include "sieve-validator.h"
@@ -44,8 +44,8 @@ const struct sieve_extension subaddress_extension = {
 	NULL, 
 	ext_subaddress_binary_load,
 	NULL,  
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_subaddress_load(int ext_id)
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index 6ba0d53941812b2ed8a82fe2f84ec598b548d172..236004509217971d29831f1f507ddadbf52471d8 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -20,7 +20,7 @@
 #include "sieve-common.h"
 
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-actions.h"
 #include "sieve-validator.h"
@@ -36,11 +36,11 @@
 static bool ext_vacation_load(int ext_id);
 static bool ext_vacation_validator_load(struct sieve_validator *validator);
 
-static bool ext_vacation_opcode_dump
-	(const struct sieve_opcode *opcode,	
+static bool ext_vacation_operation_dump
+	(const struct sieve_operation *op,	
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool ext_vacation_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool ext_vacation_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_vacation_registered
@@ -54,15 +54,15 @@ static bool cmd_vacation_generate
 
 int ext_my_id;
 
-const struct sieve_opcode vacation_opcode;
+const struct sieve_operation vacation_operation;
 
 const struct sieve_extension vacation_extension = { 
 	"vacation", 
 	ext_vacation_load,
 	ext_vacation_validator_load, 
 	NULL, NULL, NULL, 
-	SIEVE_EXT_DEFINE_OPCODE(vacation_opcode),
-	NULL
+	SIEVE_EXT_DEFINE_OPERATION(vacation_operation),
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_vacation_load(int ext_id)
@@ -90,14 +90,13 @@ static const struct sieve_command vacation_command = {
 	NULL 
 };
 
-/* Vacation opcode */
-const struct sieve_opcode vacation_opcode = { 
+/* Vacation operation */
+const struct sieve_operation vacation_operation = { 
 	"VACATION",
-	SIEVE_OPCODE_CUSTOM,
 	&vacation_extension,
 	0,
-	ext_vacation_opcode_dump, 
-	ext_vacation_opcode_execute
+	ext_vacation_operation_dump, 
+	ext_vacation_operation_execute
 };
 
 /* Vacation action */
@@ -309,7 +308,7 @@ static bool ext_vacation_validator_load(struct sieve_validator *validator)
 static bool cmd_vacation_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &vacation_opcode, ext_my_id);
+	sieve_generator_emit_operation_ext(generator, &vacation_operation, ext_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -322,8 +321,8 @@ static bool cmd_vacation_generate
  * Code dump
  */
  
-static bool ext_vacation_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_vacation_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {	
 	int opt_code = 1;
@@ -372,8 +371,8 @@ static bool ext_vacation_opcode_dump
  * Code execution
  */
  
-static bool ext_vacation_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool ext_vacation_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
 	struct sieve_side_effects_list *slist = NULL;
diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c
index b05747b269c0eafb2d42f63b756d4d236ffb3417..8dbc976e10c2e11a42d1cbcbe93ca7d36190f9fb 100644
--- a/src/lib-sieve/plugins/variables/cmd-set.c
+++ b/src/lib-sieve/plugins/variables/cmd-set.c
@@ -13,11 +13,11 @@
 
 /* Forward declarations */
 
-static bool opc_set_dump
-	(const struct sieve_opcode *opcode,	
+static bool cmd_set_operation_dump
+	(const struct sieve_operation *op,	
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool opc_set_execute
-	(const struct sieve_opcode *opcode, 
+static bool cmd_set_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_set_registered
@@ -43,14 +43,13 @@ const struct sieve_command cmd_set = {
 	NULL 
 };
 
-/* set opcode */
-const struct sieve_opcode cmd_set_opcode = { 
+/* Set operation */
+const struct sieve_operation cmd_set_operation = { 
 	"SET",
-	SIEVE_OPCODE_CUSTOM,
 	&variables_extension,
-	EXT_VARIABLES_OPCODE_SET,
-	opc_set_dump, 
-	opc_set_execute
+	EXT_VARIABLES_OPERATION_SET,
+	cmd_set_operation_dump, 
+	cmd_set_operation_execute
 };
 
 /* Tag validation */
@@ -63,9 +62,10 @@ const struct sieve_opcode cmd_set_opcode = {
  */
  
 static bool tag_modifier_is_instance_of
-	(struct sieve_validator *validator, const char *tag)
+	(struct sieve_validator *validator, struct sieve_ast_argument *arg)
 {
-	return ext_variables_set_modifier_find(validator, tag) != NULL;
+	return ext_variables_set_modifier_find
+		(validator, sieve_ast_argument_tag(arg)) != NULL;
 }
 
 static bool tag_modifier_validate
@@ -174,8 +174,8 @@ static bool cmd_set_validate(struct sieve_validator *validator,
 static bool cmd_set_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext
-		(generator, &cmd_set_opcode, ext_variables_my_id);
+	sieve_generator_emit_operation_ext
+		(generator, &cmd_set_operation, ext_variables_my_id);
 
 	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -188,8 +188,8 @@ static bool cmd_set_generate
  * Code dump
  */
  
-static bool opc_set_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_set_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {	
 	sieve_code_dumpf(denv, "SET");
@@ -204,8 +204,8 @@ static bool opc_set_dump
  * Code execution
  */
  
-static bool opc_set_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool cmd_set_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
 	return TRUE;
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index b86c242ada1508214980fc03e75e32f242aa3fa8..738b2a71305b523b763b6f791c7b23b5eaabe6fe 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -8,8 +8,8 @@ extern int ext_variables_my_id;
 extern struct sieve_extension variables_extension;
 
 enum ext_variables_opcode {
-	EXT_VARIABLES_OPCODE_SET,
-	EXT_VARIABLES_OPCODE_STRING
+	EXT_VARIABLES_OPERATION_SET,
+	EXT_VARIABLES_OPERATION_STRING
 };
 
 /* Extension */
diff --git a/src/lib-sieve/plugins/variables/ext-variables.c b/src/lib-sieve/plugins/variables/ext-variables.c
index d836a82fbfa6a580a3841d6f575bc0f58c5e384d..367be81297772bb303d8a5eede5f8d326705840e 100644
--- a/src/lib-sieve/plugins/variables/ext-variables.c
+++ b/src/lib-sieve/plugins/variables/ext-variables.c
@@ -11,7 +11,7 @@
 #include "lib.h"
 #include "unichar.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
 
@@ -29,13 +29,13 @@ static bool ext_variables_validator_load(struct sieve_validator *validator);
 extern const struct sieve_command cmd_set;
 extern const struct sieve_command tst_string;
 
-/* Opcodes */
+/* Operations */
 
-extern const struct sieve_opcode cmd_set_opcode;
-extern const struct sieve_opcode tst_string_opcode;
+extern const struct sieve_operation cmd_set_operation;
+extern const struct sieve_operation tst_string_operation;
 
-const struct sieve_opcode *ext_variables_opcodes[] = {
-	&cmd_set_opcode, &tst_string_opcode
+const struct sieve_operation *ext_variables_operations[] = {
+	&cmd_set_operation, &tst_string_operation
 };
 
 /* Extension definitions */
@@ -47,8 +47,8 @@ struct sieve_extension variables_extension = {
 	ext_variables_load,
 	ext_variables_validator_load, 
 	NULL, NULL, NULL, 
-	SIEVE_EXT_DEFINE_OPCODES(ext_variables_opcodes), 
-	NULL 
+	SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations), 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static bool ext_variables_load(int ext_id) 
diff --git a/src/lib-sieve/plugins/variables/tst-string.c b/src/lib-sieve/plugins/variables/tst-string.c
index 23e01d6190d0b9f780bde310a926755646e64f82..44f800eb072c8402a0706878fdcbe74b17d406f5 100644
--- a/src/lib-sieve/plugins/variables/tst-string.c
+++ b/src/lib-sieve/plugins/variables/tst-string.c
@@ -37,22 +37,21 @@ const struct sieve_command tst_string = {
 	NULL 
 };
 
-/* Opcode */
+/* Operations */
 
-static bool tst_string_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool tst_string_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool tst_string_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool tst_string_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode tst_string_opcode = { 
+const struct sieve_operation tst_string_operation = { 
 	"string",
-	SIEVE_OPCODE_CUSTOM,
 	&variables_extension, 
-	EXT_VARIABLES_OPCODE_STRING, 
-	tst_string_opcode_dump, 
-	tst_string_opcode_execute 
+	EXT_VARIABLES_OPERATION_STRING, 
+	tst_string_operation_dump, 
+	tst_string_operation_execute 
 };
 
 /* Optional arguments */
@@ -107,7 +106,7 @@ static bool tst_string_validate
 static bool tst_string_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode(generator, &tst_string_opcode);
+	sieve_generator_emit_operation(generator, &tst_string_operation);
 
  	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -118,8 +117,8 @@ static bool tst_string_generate
 
 /* Code dump */
 
-static bool tst_string_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool tst_string_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	int opt_code = 1;
@@ -155,8 +154,8 @@ static bool tst_string_opcode_dump
 
 /* Code execution */
 
-static bool tst_string_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool tst_string_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 52e3311aae981432c1efa6da9a5653ab976f6e47..bdccc318acb073b47962a0b53f9a051e5461eb4b 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -5,7 +5,7 @@
 #include "mail-namespace.h"
 
 #include "sieve-code.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-binary.h"
 #include "sieve-interpreter.h"
 #include "sieve-code-dumper.h"
@@ -43,8 +43,8 @@ const struct sieve_extension side_effects_extension = {
 	NULL, NULL, 
 	seffect_binary_load,
 	NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES, /* Opcode is hardcoded */
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, /* Opcode is hardcoded */
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 	
 static bool seffect_extension_load(int ext_id) 
@@ -93,9 +93,12 @@ void sieve_opr_side_effect_emit
 	(struct sieve_binary *sbin, const struct sieve_side_effect *seffect, 
 		int ext_id)
 { 
-	sieve_binary_emit_extension
-		(sbin, seffect, ext_id, 0, SIEVE_OPERAND_SIDE_EFFECT, 
-		seffect->extension->side_effects_count > 1)
+	sieve_size_t address;
+
+	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_SIDE_EFFECT);
+
+	sieve_extension_emit_object
+		(seffect, side_effects, sbin, ext_id, 0, address); 
 }
 
 bool sieve_opr_side_effect_dump
@@ -127,13 +130,15 @@ const struct sieve_side_effect *sieve_opr_side_effect_read
 {
 	unsigned int seffect_code;
 	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
-	
+
 	if ( operand == NULL || operand->class != &side_effect_class ) 
 		return NULL;
+		
 	
 	if ( sieve_binary_read_byte(sbin, address, &seffect_code) ) {
 		int ext_id = -1;
 		const struct sieve_side_effect_extension *se_ext;
+		const struct sieve_side_effect *seffect;
 
 		if ( sieve_binary_extension_get_by_index(sbin,
 			seffect_code, &ext_id) == NULL )
@@ -141,16 +146,11 @@ const struct sieve_side_effect *sieve_opr_side_effect_read
 
 		se_ext = sieve_side_effect_extension_get(sbin, ext_id); 
 
-		if ( se_ext != NULL ) {  	
-			unsigned int code;
-			if ( se_ext->side_effects_count == 1 )
-				return se_ext->side_effects.single;
-	  	
-			if ( sieve_binary_read_byte(sbin, address, &code) )
-				return se_ext->side_effects.list[code];
-		} else {
-			i_info("Unknown action side-effect %d.", seffect_code); 
-		}
+		sieve_extension_read_object 
+			(se_ext, struct sieve_side_effect, side_effects, sbin, 
+			address, seffect)
+
+		return seffect;
 	}		
 		
 	return NULL; 
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index eff494e7ca100a50f037af13c7bdbe98c5805e9e..2d879769f7dde51c55f67e67609f22cb164590e4 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -5,6 +5,7 @@
 #include "mail-storage.h"
 
 #include "sieve-common.h"
+#include "sieve-extensions-private.h"
 
 /* Sieve action */
 
@@ -59,7 +60,7 @@ struct sieve_side_effect {
 	const struct sieve_action *to_action;
 	
 	const struct sieve_side_effect_extension *extension;
-	unsigned int ext_code;
+	unsigned int code;
 	
 	bool (*dump_context)
 		(const struct sieve_side_effect *seffect, 
@@ -94,12 +95,7 @@ struct sieve_side_effect {
 struct sieve_side_effect_extension {
 	const struct sieve_extension *extension;
 
-	/* Extension can introduce a single or multiple action side effects */
-	union {
-		const struct sieve_side_effect **list;
-		const struct sieve_side_effect *single;
-	} side_effects;
-	unsigned int side_effects_count;
+	struct sieve_extension_obj_registry side_effects;
 };
 
 #define SIEVE_EXT_DEFINE_SIDE_EFFECT(SEF) SIEVE_EXT_DEFINE_OBJECT(SEF)
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 79e6a40242e06c64031d83519f61f204d31a7bfd..0eeced2c3dcbbe279f804dc6d650229b9b9b2f56 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -7,7 +7,7 @@
 #include "array.h"
 #include "message-address.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-code.h"
 #include "sieve-commands.h"
 #include "sieve-binary.h"
@@ -49,8 +49,8 @@ const struct sieve_extension address_part_extension = {
 	NULL, 
 	addrp_binary_load,
 	NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES,
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS,
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 	
 static bool addrp_extension_load(int ext_id) 
diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c
index be358a8589ff3ff92d3993c03f6ba12eb4a96829..35c11d74a5ab73161d5fb0199db8adbae034c3e5 100644
--- a/src/lib-sieve/sieve-binary.c
+++ b/src/lib-sieve/sieve-binary.c
@@ -6,7 +6,7 @@
 #include "array.h"
 #include "ostream.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-code.h"
 #include "sieve-script.h"
 
diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h
index 8ff12743569b9262f27fa6a60233a152fcf7d690..003ae11e7605ee0f5ecf29aa04722aa73ea1b015 100644
--- a/src/lib-sieve/sieve-binary.h
+++ b/src/lib-sieve/sieve-binary.h
@@ -150,15 +150,4 @@ void sieve_binary_registry_set_object
 	(struct sieve_binary *sbin, int ext_id, int id, const void *object);
 void sieve_binary_registry_init(struct sieve_binary *sbin, int ext_id);
 
-/* These macros are not a very nice solution to the code duplication. I really
- * need to think about this more */
-
-#define sieve_binary_emit_extension(sbin, obj, ext_id, base, operand, mult)   \
-	unsigned char code = base + sieve_binary_extension_get_index(sbin, ext_id); \
-	                                                                            \
-	(void) sieve_operand_emit_code(sbin, operand);                              \
-	(void) sieve_binary_emit_byte(sbin, code);                                  \
-	if ( mult )                                                                 \
-		(void) sieve_binary_emit_byte(sbin, obj->ext_code);                       
-
 #endif
diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c
index b85846361ca41908f96db56e1e8b16cd34808f32..64b406fd1f555ba008ddb4ee3ff8c74ed597049d 100644
--- a/src/lib-sieve/sieve-code-dumper.c
+++ b/src/lib-sieve/sieve-code-dumper.c
@@ -23,7 +23,7 @@ struct sieve_code_dumper {
 	/* Dump status */
 	sieve_size_t pc;          /* Program counter */
 	
-	const struct sieve_opcode *opcode;
+	const struct sieve_operation *operation;
 	sieve_size_t mark_address;
 	unsigned int indent;
 	
@@ -107,7 +107,7 @@ inline void sieve_code_ascend(const struct sieve_dumptime_env *denv)
 		denv->dumper->indent--;
 }
 
-/* Opcodes and operands */
+/* Operations and operands */
 
 bool sieve_code_dumper_print_optional_operands
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address)
@@ -133,22 +133,22 @@ bool sieve_code_dumper_print_optional_operands
 static bool sieve_code_dumper_print_operation
 	(struct sieve_code_dumper *dumper) 
 {	
-	const struct sieve_opcode *opcode;
+	const struct sieve_operation *op;
 	
-	/* Mark start address of opcode */
+	/* Mark start address of operation */
 	dumper->indent = 0;
 	dumper->mark_address = dumper->pc;
 
-	/* Read opcode */
-	dumper->opcode = opcode = 
+	/* Read operation */
+	dumper->operation = op = 
 		sieve_operation_read(dumper->dumpenv.sbin, &(dumper->pc));
 
 	/* Try to dump it */
-	if ( opcode != NULL ) {
-		if ( opcode->dump != NULL )
-			return opcode->dump(opcode, &(dumper->dumpenv), &(dumper->pc));
-		else if ( opcode->mnemonic != NULL )
-			sieve_code_dumpf(&(dumper->dumpenv), "%s", opcode->mnemonic);
+	if ( op != NULL ) {
+		if ( op->dump != NULL )
+			return op->dump(op, &(dumper->dumpenv), &(dumper->pc));
+		else if ( op->mnemonic != NULL )
+			sieve_code_dumpf(&(dumper->dumpenv), "%s", op->mnemonic);
 		else
 			return FALSE;
 			
diff --git a/src/lib-sieve/sieve-code-dumper.h b/src/lib-sieve/sieve-code-dumper.h
index ae7dee47a691a51d56754ca3f70f82cc2169a314..4a2781f4763caf091050d8fcccb9dec6458c0d4c 100644
--- a/src/lib-sieve/sieve-code-dumper.h
+++ b/src/lib-sieve/sieve-code-dumper.h
@@ -28,7 +28,7 @@ inline void sieve_code_mark_specific
 inline void sieve_code_descend(const struct sieve_dumptime_env *denv);
 inline void sieve_code_ascend(const struct sieve_dumptime_env *denv);
 
-/* Opcodes and operands */
+/* Operations and operands */
 	
 bool sieve_code_dumper_print_optional_operands
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 50c8b195058d0c133760398ba8bad1e9d32f212b..b298ed1d8d6e44eb885be17503108c1ad2cb571e 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -142,14 +142,14 @@ const struct sieve_operand *sieve_operand_read
 			else
 				return NULL;
 		} else {
-			int ext_id = -1;
+/*			int ext_id = -1;
 		  const struct sieve_extension *ext = 
 		  	sieve_binary_extension_get_by_index
 		  		(sbin, operand - SIEVE_OPERAND_CUSTOM, &ext_id);
 		  
 		  if ( ext != NULL )
 		  	return ext->operand;	
-		  else
+		  else*/
 		  	return NULL;
 		}
 	}		
@@ -580,58 +580,32 @@ static struct sieve_coded_stringlist *opr_stringlist_read
 }  
 
 /* 
- * Opcodes
+ * Operations
  */
 
-/* Opcode functions */
+/* Operation functions */
 
 inline sieve_size_t sieve_operation_emit_code
-	(struct sieve_binary *sbin, const struct sieve_opcode *op)
-{
-	return sieve_binary_emit_byte(sbin, op->code);
-}
-
-inline sieve_size_t sieve_operation_emit_code_ext
-	(struct sieve_binary *sbin, const struct sieve_opcode *op, int ext_id)
+	(struct sieve_binary *sbin, const struct sieve_operation *op, int ext_id)
 {	
-	sieve_size_t address;
-	unsigned char opcode = SIEVE_OPCODE_CUSTOM + 
-		sieve_binary_extension_get_index(sbin, ext_id);
-	
-	address = sieve_binary_emit_byte(sbin, opcode);
-	if ( op->extension->opcodes_count > 1 ) 
-		(void) sieve_binary_emit_byte(sbin, op->ext_code);
-		
-	return address;
+	return sieve_extension_emit_operation
+		(op, sbin, ext_id, SIEVE_OPERATION_CUSTOM);
 }
 
-const struct sieve_opcode *sieve_operation_read
+const struct sieve_operation *sieve_operation_read
 	(struct sieve_binary *sbin, sieve_size_t *address) 
 {
 	unsigned int opcode;
 	
 	if ( sieve_binary_read_byte(sbin, address, &opcode) ) {
-		if ( opcode < SIEVE_OPCODE_CUSTOM ) {
-			if ( opcode < sieve_opcode_count )
-				return sieve_opcodes[opcode];
+		if ( opcode < SIEVE_OPERATION_CUSTOM ) {
+			if ( opcode < sieve_operations_count )
+				return sieve_operations[opcode];
 			else
 				return NULL;
 		} else {
-			int ext_id = -1;
-			const struct sieve_extension *ext = 
-			sieve_binary_extension_get_by_index
-				(sbin, opcode - SIEVE_OPCODE_CUSTOM, &ext_id);
-		  
-			if ( ext != NULL && ext->opcodes_count != 0 ) {
-				unsigned int code;
-				
-				if ( ext->opcodes_count == 1 ) 
-					return ext->opcodes.single;
-				
-				if ( sieve_binary_read_byte(sbin, address, &code) && 
-					code < ext->opcodes_count ) 
-					return ext->opcodes.list[code];
-			} 
+			return sieve_extension_read_operation
+				(opcode - SIEVE_OPERATION_CUSTOM, sbin, address);
 		}
 	}		
 	
@@ -641,83 +615,80 @@ const struct sieve_opcode *sieve_operation_read
 /* Declaration of opcodes defined in this file */
 
 static bool opc_jmp_dump
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
 static bool opc_jmp_execute
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool opc_jmptrue_execute
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool opc_jmpfalse_execute
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode sieve_jmp_opcode = { 
+const struct sieve_operation sieve_jmp_operation = { 
 	"JMP",
-	SIEVE_OPCODE_JMP,
 	NULL,
-	0,
+	SIEVE_OPERATION_JMP,
 	opc_jmp_dump, 
 	opc_jmp_execute 
 };
 
-const struct sieve_opcode sieve_jmptrue_opcode = { 
+const struct sieve_operation sieve_jmptrue_operation = { 
 	"JMPTRUE",
-	SIEVE_OPCODE_JMPTRUE,
 	NULL,
-	0,
+	SIEVE_OPERATION_JMPTRUE,
 	opc_jmp_dump, 
 	opc_jmptrue_execute 
 };
 
-const struct sieve_opcode sieve_jmpfalse_opcode = { 
+const struct sieve_operation sieve_jmpfalse_operation = { 
 	"JMPFALSE",
-	SIEVE_OPCODE_JMPFALSE,
 	NULL,
-	0,
+	SIEVE_OPERATION_JMPFALSE,
 	opc_jmp_dump, 
 	opc_jmpfalse_execute 
 };
 	
-extern const struct sieve_opcode cmd_stop_opcode;
-extern const struct sieve_opcode cmd_keep_opcode;
-extern const struct sieve_opcode cmd_discard_opcode;
-extern const struct sieve_opcode cmd_redirect_opcode;
+extern const struct sieve_operation cmd_stop_operation;
+extern const struct sieve_operation cmd_keep_operation;
+extern const struct sieve_operation cmd_discard_operation;
+extern const struct sieve_operation cmd_redirect_operation;
 
-extern const struct sieve_opcode tst_address_opcode;
-extern const struct sieve_opcode tst_header_opcode;
-extern const struct sieve_opcode tst_exists_opcode;
-extern const struct sieve_opcode tst_size_over_opcode;
-extern const struct sieve_opcode tst_size_under_opcode;
+extern const struct sieve_operation tst_address_operation;
+extern const struct sieve_operation tst_header_operation;
+extern const struct sieve_operation tst_exists_operation;
+extern const struct sieve_operation tst_size_over_operation;
+extern const struct sieve_operation tst_size_under_operation;
 
-const struct sieve_opcode *sieve_opcodes[] = {
+const struct sieve_operation *sieve_operations[] = {
 	NULL, 
 	
-	&sieve_jmp_opcode,
-	&sieve_jmptrue_opcode, 
-	&sieve_jmpfalse_opcode,
+	&sieve_jmp_operation,
+	&sieve_jmptrue_operation, 
+	&sieve_jmpfalse_operation,
 	
-	&cmd_stop_opcode,
-	&cmd_keep_opcode,
-	&cmd_discard_opcode,
-	&cmd_redirect_opcode,
+	&cmd_stop_operation,
+	&cmd_keep_operation,
+	&cmd_discard_operation,
+	&cmd_redirect_operation,
 
-	&tst_address_opcode,
-	&tst_header_opcode,
-	&tst_exists_opcode,
-	&tst_size_over_opcode,
-	&tst_size_under_opcode
+	&tst_address_operation,
+	&tst_header_operation,
+	&tst_exists_operation,
+	&tst_size_over_operation,
+	&tst_size_under_operation
 }; 
 
-const unsigned int sieve_opcode_count =
-	N_ELEMENTS(sieve_opcodes);
+const unsigned int sieve_operations_count =
+	N_ELEMENTS(sieve_operations);
 
 /* Code dump for core commands */
 
 static bool opc_jmp_dump
-(const struct sieve_opcode *opcode,
+(const struct sieve_operation *op,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	unsigned int pc = *address;
@@ -725,20 +696,20 @@ static bool opc_jmp_dump
 	
 	if ( sieve_binary_read_offset(denv->sbin, address, &offset) ) 
 		sieve_code_dumpf(denv, "%s %d [%08x]", 
-			opcode->mnemonic, offset, pc + offset);
+			op->mnemonic, offset, pc + offset);
 	else
 		return FALSE;
 	
 	return TRUE;
 }	
 			
-/* Code dump for trivial opcodes */
+/* Code dump for trivial operations */
 
-bool sieve_opcode_string_dump
-(const struct sieve_opcode *opcode,
+bool sieve_operation_string_dump
+(const struct sieve_operation *op,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	sieve_code_dumpf(denv, "%s", opcode->mnemonic);
+	sieve_code_dumpf(denv, "%s", op->mnemonic);
 
 	return 
 		sieve_opr_string_dump(denv, address);
@@ -747,7 +718,7 @@ bool sieve_opcode_string_dump
 /* Code execution for core commands */
 
 static bool opc_jmp_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) 
 {
 	printf("JMP\n");
@@ -758,7 +729,7 @@ static bool opc_jmp_execute
 }	
 		
 static bool opc_jmptrue_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED)
 {	
 	if ( !sieve_interpreter_program_jump(renv->interp,
@@ -771,7 +742,7 @@ static bool opc_jmptrue_execute
 }
 
 static bool opc_jmpfalse_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED)
 {	
 	if ( !sieve_interpreter_program_jump(renv->interp,
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index 7c91174450fda21a017c594a2a2ab40a31a152c7..1c817c2224768a74596f27071407a40e92162721 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -27,7 +27,7 @@ inline sieve_size_t sieve_coded_stringlist_get_end_address
 inline sieve_size_t sieve_coded_stringlist_get_current_offset
 	(struct sieve_coded_stringlist *strlist);
 
-/* Operand: argument to an opcode */
+/* Operand: argument to an operation */
 
 struct sieve_operand_class {
 	const char *name;
@@ -114,60 +114,56 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
 
-/* Opcode: identifies what's to be done */
+/* Operation: identifies what's to be done */
 
 enum sieve_operation_code {
-	SIEVE_OPCODE_INVALID,
-	SIEVE_OPCODE_JMP,
-	SIEVE_OPCODE_JMPTRUE,
-	SIEVE_OPCODE_JMPFALSE,
+	SIEVE_OPERATION_INVALID,
+	SIEVE_OPERATION_JMP,
+	SIEVE_OPERATION_JMPTRUE,
+	SIEVE_OPERATION_JMPFALSE,
 	
-	SIEVE_OPCODE_STOP,
-	SIEVE_OPCODE_KEEP,
-	SIEVE_OPCODE_DISCARD,
-	SIEVE_OPCODE_REDIRECT,
+	SIEVE_OPERATION_STOP,
+	SIEVE_OPERATION_KEEP,
+	SIEVE_OPERATION_DISCARD,
+	SIEVE_OPERATION_REDIRECT,
 	
-	SIEVE_OPCODE_ADDRESS,
-	SIEVE_OPCODE_HEADER, 
-	SIEVE_OPCODE_EXISTS, 
-	SIEVE_OPCODE_SIZE_OVER,
-	SIEVE_OPCODE_SIZE_UNDER,
+	SIEVE_OPERATION_ADDRESS,
+	SIEVE_OPERATION_HEADER, 
+	SIEVE_OPERATION_EXISTS, 
+	SIEVE_OPERATION_SIZE_OVER,
+	SIEVE_OPERATION_SIZE_UNDER,
 	
-	SIEVE_OPCODE_CUSTOM
+	SIEVE_OPERATION_CUSTOM
 };
 
-struct sieve_opcode {
+struct sieve_operation {
 	const char *mnemonic;
 	
-	enum sieve_operation_code code;
-	
 	const struct sieve_extension *extension;
-	unsigned int ext_code;
+	unsigned int code;
 	
 	bool (*dump)
-		(const struct sieve_opcode *opcode, 
+		(const struct sieve_operation *op, 
 			const struct sieve_dumptime_env *denv, sieve_size_t *address);
 	bool (*execute)
-		(const struct sieve_opcode *opcode, 
+		(const struct sieve_operation *op, 
 			const struct sieve_runtime_env *renv, sieve_size_t *address);
 };
 
-extern const struct sieve_opcode *sieve_opcodes[];
-extern const unsigned int sieve_opcode_count;
+extern const struct sieve_operation *sieve_operations[];
+extern const unsigned int sieve_operations_count;
 
-extern const struct sieve_opcode sieve_jmp_opcode;
-extern const struct sieve_opcode sieve_jmptrue_opcode;
-extern const struct sieve_opcode sieve_jmpfalse_opcode; 
+extern const struct sieve_operation sieve_jmp_operation;
+extern const struct sieve_operation sieve_jmptrue_operation;
+extern const struct sieve_operation sieve_jmpfalse_operation; 
 
 inline sieve_size_t sieve_operation_emit_code
-	(struct sieve_binary *sbin, const struct sieve_opcode *op);
-inline sieve_size_t sieve_operation_emit_code_ext
-	(struct sieve_binary *sbin, const struct sieve_opcode *op, int ext_id);	
-const struct sieve_opcode *sieve_operation_read
+	(struct sieve_binary *sbin, const struct sieve_operation *op, int ext_id);	
+const struct sieve_operation *sieve_operation_read
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
-bool sieve_opcode_string_dump
-	(const struct sieve_opcode *opcode,
+bool sieve_operation_string_dump
+	(const struct sieve_operation *op,
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
 /* Core operands */
diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c
index 0ab71477d0561a77f243218619bda5ba43987612..1b83e518bd4747e6400b3bd504ee6c8b187be85d 100644
--- a/src/lib-sieve/sieve-commands.c
+++ b/src/lib-sieve/sieve-commands.c
@@ -243,23 +243,22 @@ inline bool sieve_command_block_exits_unconditionally
 	return ( cmd->block_exit_command != NULL );
 }
 
-/* Opcodes */
+/* Operations */
 
 static bool opc_stop_execute
-	(const struct sieve_opcode *opcode, 
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode cmd_stop_opcode = { 
+const struct sieve_operation cmd_stop_operation = { 
 	"STOP",
-	SIEVE_OPCODE_STOP,
 	NULL,
-	0,
+	SIEVE_OPERATION_STOP,
 	NULL, 
 	opc_stop_execute 
 };
 
 static bool opc_stop_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv,  
 	sieve_size_t *address ATTR_UNUSED)
 {	
@@ -287,7 +286,7 @@ static bool cmd_stop_generate
 		struct sieve_command_context *ctx ATTR_UNUSED) 
 {
 	sieve_operation_emit_code(
-		sieve_generator_get_binary(generator), &cmd_stop_opcode);
+		sieve_generator_get_binary(generator), &cmd_stop_operation, -1);
 	return TRUE;
 }
 
@@ -299,7 +298,7 @@ static bool tst_false_generate
 	struct sieve_binary *sbin = sieve_generator_get_binary(generator);
 
 	if ( !jump_true ) {
-		sieve_operation_emit_code(sbin, &sieve_jmp_opcode);
+		sieve_operation_emit_code(sbin, &sieve_jmp_operation, -1);
 		sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0));
 	}
 	
@@ -314,7 +313,7 @@ static bool tst_true_generate
 	struct sieve_binary *sbin = sieve_generator_get_binary(generator);
 
 	if ( jump_true ) {
-		sieve_operation_emit_code(sbin, &sieve_jmp_opcode);
+		sieve_operation_emit_code(sbin, &sieve_jmp_operation, -1);
 		sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0));
 	}
 	
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index 2d6660d055302c078f4151621fe08604cecadacf..4e851c5b28f122a54af5406e06a5e8e60ee0aed7 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -61,7 +61,7 @@ struct sieve_extension;
 
 /* sieve-code.h */
 struct sieve_operand;
-struct sieve_opcode;
+struct sieve_operation;
 struct sieve_coded_stringlist;
 
 /* sieve-binary.h */
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 341196ac8e3dda3590ada78838edf0628b96e05c..e1d33e37ebe54893a57e4e813e2d384b08f0deee 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -3,7 +3,7 @@
 #include "hash.h"
 #include "array.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-code.h"
 #include "sieve-commands.h"
 #include "sieve-binary.h"
@@ -63,8 +63,8 @@ const struct sieve_extension comparator_extension = {
 	NULL, 
 	cmp_binary_load,
 	NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES,
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS,
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 	
 static bool cmp_extension_load(int ext_id) 
@@ -272,8 +272,12 @@ void sieve_comparators_link_tag
 inline bool sieve_comparator_tag_is
 (struct sieve_ast_argument *tag, const struct sieve_comparator *cmp)
 {
-	return (tag->argument == &comparator_tag && 
-		((const struct sieve_comparator *) tag->context) == cmp);
+	const struct sieve_comparator_context *cmpctx = 
+		(const struct sieve_comparator_context *) tag->context;
+
+	if ( cmpctx == NULL ) return FALSE;
+	
+	return ( tag->argument == &comparator_tag && cmpctx->comparator == cmp );
 }
 
 inline const struct sieve_comparator *sieve_comparator_tag_get
diff --git a/src/lib-sieve/sieve-extensions-private.h b/src/lib-sieve/sieve-extensions-private.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e18dc3240a28945537512abcd8fd57ac25716dd
--- /dev/null
+++ b/src/lib-sieve/sieve-extensions-private.h
@@ -0,0 +1,140 @@
+#ifndef __SIEVE_EXTENSIONS_PRIVATE_H
+#define __SIEVE_EXTENSIONS_PRIVATE_H
+
+#include "sieve-common.h"
+#include "sieve-code.h"
+#include "sieve-extensions.h"
+#include "sieve-binary.h"
+
+/* 
+ * Per-extension object declaration
+ */
+
+struct sieve_extension_obj_registry {
+	const void *objects;
+	unsigned int count;
+};
+
+#define SIEVE_EXT_DEFINE_NO_OBJECTS \
+	{ NULL, 0 }
+#define SIEVE_EXT_DEFINE_OBJECT(OBJ) \
+	{ &OBJ, 1 }
+#define SIEVE_EXT_DEFINE_OBJECTS(OBJS) \
+	{ OBJS, N_ELEMENTS(OBJS) }
+
+#define SIEVE_EXT_GET_OBJECTS_COUNT(ext, field) \
+	ext->field->count;
+
+static inline const void *_sieve_extension_read_object
+(const struct sieve_extension_obj_registry *reg, struct sieve_binary *sbin, 
+	sieve_size_t *address)
+{ 		
+	unsigned int code; 	
+		
+	if ( reg->count == 1 ) 
+		return reg->objects; 
+	
+	if ( sieve_binary_read_byte(sbin, address, &code) && code < reg->count ) {
+		const void * const *objects = (const void * const *) reg->objects;
+		return objects[code]; 
+	}
+	return NULL;
+}
+
+#define sieve_extension_read_object\
+(ext, type, field, sbin, address, result) \
+{ \
+	result = NULL; \
+	\
+	if ( ext != NULL && ext->field.count != 0 ) \
+		result = (type *) _sieve_extension_read_object \
+			(&ext->field, sbin, address); \
+} 
+
+static inline sieve_size_t _sieve_extension_emit_object
+(struct sieve_binary *sbin, int ext_id, unsigned char offset)
+{
+	unsigned char code = offset + 
+		sieve_binary_extension_get_index(sbin, ext_id);
+
+	return sieve_binary_emit_byte(sbin, code);
+}
+#define sieve_extension_emit_object\
+(obj, ext_field, sbin, ext_id, offset, address_r) \
+{ \
+	address_r = _sieve_extension_emit_object(sbin, ext_id, offset); \
+	\
+	if ( obj->extension->ext_field.count > 1 ) \
+		(void) sieve_binary_emit_byte(sbin, obj->code); \
+}
+
+/*
+ * Extension object
+ */
+
+struct sieve_extension {
+	const char *name;
+	
+	bool (*load)(int ext_id);
+
+	bool (*validator_load)(struct sieve_validator *validator);	
+	bool (*generator_load)(struct sieve_generator *generator);
+	bool (*binary_load)(struct sieve_binary *binary);
+	bool (*interpreter_load)(struct sieve_interpreter *interpreter);
+
+	struct sieve_extension_obj_registry opcodes;
+	struct sieve_extension_obj_registry operands;
+};
+
+/*  
+ * Opcode access
+ */
+ 
+#define SIEVE_EXT_DEFINE_NO_OPERATIONS SIEVE_EXT_DEFINE_NO_OBJECTS
+#define SIEVE_EXT_DEFINE_OPERATION(OP) SIEVE_EXT_DEFINE_OBJECT(OP)
+#define SIEVE_EXT_DEFINE_OPERATIONS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS)
+
+static inline const struct sieve_operation *sieve_extension_read_operation
+(unsigned int ext_code, struct sieve_binary *sbin, sieve_size_t *address) 
+{
+	struct sieve_operation *op;
+	int ext_id = -1; 
+	const struct sieve_extension *ext = sieve_binary_extension_get_by_index
+		(sbin, ext_code, &ext_id);
+	
+	sieve_extension_read_object 
+		(ext, struct sieve_operation, opcodes, sbin, address, op)
+
+	return op;
+}
+
+static inline sieve_size_t sieve_extension_emit_operation
+(const struct sieve_operation *op, struct sieve_binary *sbin, int ext_id, 
+	unsigned int offset)
+{
+	if ( ext_id >= 0 ) {
+		sieve_size_t address;
+		
+		sieve_extension_emit_object
+			(op, opcodes, sbin, ext_id, offset, address); 
+		
+		return address;
+	} 
+	
+	return sieve_binary_emit_byte(sbin, op->code);
+}
+
+/* 
+ * Operand access 
+ */
+
+#define SIEVE_EXT_DEFINE_NO_OPERANDS SIEVE_EXT_DEFINE_NO_OBJECTS
+
+/* 
+ * Pre-loaded extensions
+ */
+
+extern const struct sieve_extension *sieve_preloaded_extensions[];
+extern const unsigned int sieve_preloaded_extensions_count;
+
+#endif /* __SIEVE_EXTENSIONS_PRIVATE_H */
diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index 642214fb0ca0eb40283fe343e1cf46c8d900105b..d6c86b47b1df3a047deab9b4c08ed945c45572e6 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -3,7 +3,7 @@
 #include "hash.h"
 #include "array.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 
 /* Static pre-declarations */
 
@@ -32,15 +32,15 @@ ARRAY_DEFINE(sieve_preloaded_ext_ids, int);
 static const struct sieve_extension comparator_i_octet_extension = {
 	"comparator-i;octet",
 	NULL, NULL, NULL, NULL, NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 static const struct sieve_extension comparator_i_ascii_casemap_extension = {
 	"comparator-i;ascii-casemap",
 	NULL, NULL, NULL, NULL, NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES, 
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
 /* Base extensions */
diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h
index e41bd11c0389382af37043b9e9b4fa04d5c9f9f7..e1327af3ebedca78a5626d6eb6a3776b40df4ade 100644
--- a/src/lib-sieve/sieve-extensions.h
+++ b/src/lib-sieve/sieve-extensions.h
@@ -4,43 +4,7 @@
 #include "lib.h"
 #include "sieve-common.h"
 
-struct sieve_extension {
-	const char *name;
-	
-	bool (*load)(int ext_id);
-
-	bool (*validator_load)(struct sieve_validator *validator);	
-	bool (*generator_load)(struct sieve_generator *generator);
-	bool (*binary_load)(struct sieve_binary *binary);
-	bool (*interpreter_load)(struct sieve_interpreter *interpreter);
-
-	/* Extension can introduce a single or multiple opcodes */
-	union {
-		const struct sieve_opcode **list;
-		const struct sieve_opcode *single;
-	} opcodes;
-	unsigned int opcodes_count;
-
-	/* Extension can introduce a single or multiple operands (FIXME) */
-	const struct sieve_operand *operand;
-};
-
-/* FIXME: This is not ANSI-compliant C, so it might break on some targets.
- * We'll see, otherwise do an ugly typecast to first union element type. 
- */
-#define SIEVE_EXT_DEFINE_NO_OBJECTS \
-	{ list: NULL }, 0
-#define SIEVE_EXT_DEFINE_OBJECT(OBJ) \
-	{ single: &OBJ }, 1
-#define SIEVE_EXT_DEFINE_OBJECTS(OBJS) \
-	{ list: OBJS }, N_ELEMENTS(OBJS)
-
-#define SIEVE_EXT_DEFINE_NO_OPCODES SIEVE_EXT_DEFINE_NO_OBJECTS
-#define SIEVE_EXT_DEFINE_OPCODE(OP) SIEVE_EXT_DEFINE_OBJECT(OP)
-#define SIEVE_EXT_DEFINE_OPCODES(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS)
-
-extern const struct sieve_extension *sieve_preloaded_extensions[];
-extern const unsigned int sieve_preloaded_extensions_count;
+struct sieve_extension;
 
 const struct sieve_extension *sieve_extension_acquire(const char *extension);
 
diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c
index 44cf3a52cb282cd25546e7af93597e11c4626716..447ff2d1e26df946378a6b621d1a42d851b606ff 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -4,7 +4,7 @@
 #include "mempool.h"
 
 #include "sieve-common.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands-private.h"
 #include "sieve-code.h"
 #include "sieve-binary.h"
@@ -179,16 +179,16 @@ inline struct sieve_binary *sieve_generator_get_binary
 	return gentr->binary;
 }
 
-inline sieve_size_t sieve_generator_emit_opcode
-	(struct sieve_generator *gentr, const struct sieve_opcode *opcode)
+inline sieve_size_t sieve_generator_emit_operation
+	(struct sieve_generator *gentr, const struct sieve_operation *op)
 {
-	return sieve_operation_emit_code(gentr->binary, opcode);
+	return sieve_operation_emit_code(gentr->binary, op, -1);
 }
 
-inline sieve_size_t sieve_generator_emit_opcode_ext
-	(struct sieve_generator *gentr, const struct sieve_opcode *opcode, int ext_id)
+inline sieve_size_t sieve_generator_emit_operation_ext
+	(struct sieve_generator *gentr, const struct sieve_operation *op, int ext_id)
 {	
-	return sieve_operation_emit_code_ext(gentr->binary, opcode, ext_id);
+	return sieve_operation_emit_code(gentr->binary, op, ext_id);
 }
 
 /* Generator functions */
@@ -289,9 +289,9 @@ bool sieve_generate_test
 		if ( tst_node->context->command->generate(generator, tst_node->context) ) {
 			
 			if ( jump_true ) 
-				sieve_operation_emit_code(generator->binary, &sieve_jmptrue_opcode);
+				sieve_operation_emit_code(generator->binary, &sieve_jmptrue_operation, -1);
 			else
-				sieve_operation_emit_code(generator->binary, &sieve_jmpfalse_opcode);
+				sieve_operation_emit_code(generator->binary, &sieve_jmpfalse_operation, -1);
 			sieve_jumplist_add(jlist, sieve_binary_emit_offset(generator->binary, 0));
 						
 			return TRUE;
diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h
index 8b832dbb7b1984a9cd782b9629ecab108e96943f..57fec8d524c880bf9ab29cdddd2161589edf3a01 100644
--- a/src/lib-sieve/sieve-generator.h
+++ b/src/lib-sieve/sieve-generator.h
@@ -59,10 +59,10 @@ inline sieve_size_t sieve_generator_get_current_address
 
 inline struct sieve_binary *sieve_generator_get_binary
 	(struct sieve_generator *gentr);
-inline sieve_size_t sieve_generator_emit_opcode
-	(struct sieve_generator *gentr, const struct sieve_opcode *opcode);
-inline sieve_size_t sieve_generator_emit_opcode_ext
-	(struct sieve_generator *gentr, const struct sieve_opcode *opcode, int ext_id);
+inline sieve_size_t sieve_generator_emit_operation
+	(struct sieve_generator *gentr, const struct sieve_operation *op);
+inline sieve_size_t sieve_generator_emit_operation_ext
+	(struct sieve_generator *gentr, const struct sieve_operation *op, int ext_id);
 
 /* Offset emission */
 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 1a4d7cb44a529e9b82fbd16e29b4f1a04c776858..fe85abf2982ea41c6e923a2bcfd2f8e8a8917229 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -106,8 +106,8 @@ struct sieve_interpreter {
 	bool interrupted;         /* Interpreter interrupt requested */
 	bool test_result;         /* Result of previous test command */
 
-	const struct sieve_opcode *current_op; /* Current opcode */ 
-	sieve_size_t current_op_addr;          /* Start address of current opcode */
+	const struct sieve_operation *current_op; /* Current operation */ 
+	sieve_size_t current_op_addr;             /* Start address of current operation */
 	
 	/* Runtime environment environment */
 	struct sieve_runtime_env runenv; 
@@ -307,7 +307,7 @@ inline bool sieve_interpreter_get_test_result
 	return interp->test_result;
 }
 
-/* Opcodes and operands */
+/* Operations and operands */
 
 bool sieve_interpreter_handle_optional_operands
 	(const struct sieve_runtime_env *renv, sieve_size_t *address,
@@ -349,15 +349,15 @@ bool sieve_interpreter_handle_optional_operands
 bool sieve_interpreter_execute_operation
 	(struct sieve_interpreter *interp) 
 {
-	const struct sieve_opcode *opcode;
+	const struct sieve_operation *op;
 
 	interp->current_op_addr = interp->pc;
-	interp->current_op = opcode =
+	interp->current_op = op =
 		sieve_operation_read(interp->runenv.sbin, &(interp->pc));
 
-	if ( opcode != NULL ) {
-		if ( opcode->execute != NULL )
-			return opcode->execute(opcode, &(interp->runenv), &(interp->pc));
+	if ( op != NULL ) {
+		if ( op->execute != NULL )
+			return op->execute(op, &(interp->runenv), &(interp->pc));
 		else
 			return FALSE;
 			
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index 967948309b66a0c499ce83abbc4215fb403d5f01..feece92ce49856baeb5237371d4f01f7d9b76533 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -6,7 +6,7 @@
 #include "hash.h"
 #include "array.h"
 
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 #include "sieve-commands.h"
 #include "sieve-code.h"
 #include "sieve-binary.h"
@@ -46,8 +46,8 @@ const struct sieve_extension match_type_extension = {
 	NULL,
 	mtch_binary_load,
 	NULL,
-	SIEVE_EXT_DEFINE_NO_OPCODES,
-	NULL
+	SIEVE_EXT_DEFINE_NO_OPERATIONS,
+	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 	
 static bool mtch_extension_load(int ext_id) 
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index 6c70f2a90f509fabdeb9b95c1b2b1180b86a11b5..a1c679e80bfbe945897d3b0aaf1ee9bce664212a 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -9,7 +9,7 @@
 #include "sieve-commands.h"
 #include "sieve-commands-private.h"
 #include "sieve-validator.h"
-#include "sieve-extensions.h"
+#include "sieve-extensions-private.h"
 
 #include "sieve-comparators.h"
 #include "sieve-address-parts.h"
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index ea1d611e5bc238a844990c98256e98445c3f62e4..14d3cf7f5b211b47d8170741fc2383bbc2638593 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -161,7 +161,9 @@ struct sieve_binary *sieve_open
 		
 		if ( sbin == NULL ) {	
 			sbin = sieve_compile_script(script, ehandler);
-			(void) sieve_binary_save(sbin, binpath);	
+
+			if ( sbin != NULL )
+				(void) sieve_binary_save(sbin, binpath);	
 		}
 	);
 	
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index fd4cb1b735ecd1c92720d720f899182a5865ac60..9040e10a3691ebc75c8e55bf4034746d9e69e55a 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -38,21 +38,21 @@ const struct sieve_command tst_address = {
 	NULL 
 };
 
-/* Opcode */
+/* Operands */
 
-static bool tst_address_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool tst_address_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool tst_address_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool tst_address_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode tst_address_opcode = { 
+const struct sieve_operation tst_address_operation = { 
 	"ADDRESS",
-	SIEVE_OPCODE_ADDRESS,
-	NULL, 0,
-	tst_address_opcode_dump, 
-	tst_address_opcode_execute 
+	NULL,
+	SIEVE_OPERATION_ADDRESS,
+	tst_address_operation_dump, 
+	tst_address_operation_execute 
 };
 
 /* Test registration */
@@ -100,7 +100,7 @@ static bool tst_address_validate
 static bool tst_address_generate
 	(struct sieve_generator *generator, struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode(generator, &tst_address_opcode);
+	sieve_generator_emit_operation(generator, &tst_address_operation);
 	
 	/* Generate arguments */  	
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -111,8 +111,8 @@ static bool tst_address_generate
 
 /* Code dump */
 
-static bool tst_address_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,	
+static bool tst_address_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,	
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	sieve_code_dumpf(denv, "ADDRESS");
@@ -129,8 +129,8 @@ static bool tst_address_opcode_dump
 
 /* Code execution */
 
-static bool tst_address_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool tst_address_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
 	bool result = TRUE;
diff --git a/src/lib-sieve/tst-allof.c b/src/lib-sieve/tst-allof.c
index fb16b86ea6515c3577617e83b5e0b3e3e9d0833b..05f078dfa8c5c5da63d8df5c9e01f4b5c9269ee7 100644
--- a/src/lib-sieve/tst-allof.c
+++ b/src/lib-sieve/tst-allof.c
@@ -58,7 +58,7 @@ static bool tst_allof_generate
 	
 	if ( jump_true ) {
 		/* All tests succeeded, jump to case TRUE */
-		sieve_generator_emit_opcode(generator, &sieve_jmp_opcode);
+		sieve_generator_emit_operation(generator, &sieve_jmp_operation);
 		sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0));
 		
 		/* All false exits jump here */
diff --git a/src/lib-sieve/tst-anyof.c b/src/lib-sieve/tst-anyof.c
index 687a7a2bdf33dec4a5dde4ed6f64d1ca9a1da0c2..f9f6f25da5f2c2b34133318dfb628cb70bcb7ea3 100644
--- a/src/lib-sieve/tst-anyof.c
+++ b/src/lib-sieve/tst-anyof.c
@@ -56,7 +56,7 @@ static bool tst_anyof_generate
 	
 	if ( !jump_true ) {
 		/* All tests failed, jump to case FALSE */
-		sieve_operation_emit_code(sbin, &sieve_jmp_opcode);
+		sieve_operation_emit_code(sbin, &sieve_jmp_operation, -1);
 		sieve_jumplist_add(jumps, sieve_binary_emit_offset(sbin, 0));
 		
 		/* All true exits jump here */
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index d1d403706824c4c6063be2f58d53429ffa3227fd..149f9c94e656ac82e44d14e648c52a9917908471 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -30,21 +30,21 @@ const struct sieve_command tst_exists = {
 	NULL 
 };
 
-/* Opcodes */
+/* Operations */
 
-static bool tst_exists_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool tst_exists_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool tst_exists_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool tst_exists_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode tst_exists_opcode = { 
+const struct sieve_operation tst_exists_operation = { 
 	"EXISTS",
-	SIEVE_OPCODE_EXISTS,
-	NULL, 0, 
-	tst_exists_opcode_dump, 
-	tst_exists_opcode_execute 
+	NULL,
+	SIEVE_OPERATION_EXISTS,
+	tst_exists_operation_dump, 
+	tst_exists_operation_execute 
 };
 
 /* Test validation */
@@ -70,7 +70,7 @@ static bool tst_exists_validate
 static bool tst_exists_generate
 	(struct sieve_generator *generator, struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode(generator, &tst_exists_opcode);
+	sieve_generator_emit_operation(generator, &tst_exists_operation);
 
  	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -81,8 +81,8 @@ static bool tst_exists_generate
 
 /* Code dump */
 
-static bool tst_exists_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool tst_exists_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
     sieve_code_dumpf(denv, "EXISTS");
@@ -94,8 +94,8 @@ static bool tst_exists_opcode_dump
 
 /* Code execution */
 
-static bool tst_exists_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool tst_exists_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index b29d3b442799778d73d4fe19346327a146a821e8..d74f40527e9cf84356ddfe8ad75b1e84550699fe 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -35,21 +35,21 @@ const struct sieve_command tst_header = {
 	NULL 
 };
 
-/* Opcode */
+/* Operation */
 
-static bool tst_header_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool tst_header_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool tst_header_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool tst_header_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode tst_header_opcode = { 
+const struct sieve_operation tst_header_operation = { 
 	"HEADER",
-	SIEVE_OPCODE_HEADER,
-	NULL, 0, 
-	tst_header_opcode_dump, 
-	tst_header_opcode_execute 
+	NULL,
+	SIEVE_OPERATION_HEADER,
+	tst_header_operation_dump, 
+	tst_header_operation_execute 
 };
 
 /* Optional arguments */
@@ -104,7 +104,7 @@ static bool tst_header_validate
 static bool tst_header_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode(generator, &tst_header_opcode);
+	sieve_generator_emit_operation(generator, &tst_header_operation);
 
  	/* Generate arguments */
 	if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -115,8 +115,8 @@ static bool tst_header_generate
 
 /* Code dump */
 
-static bool tst_header_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,
+static bool tst_header_operation_dump
+(const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
 	int opt_code = 1;
@@ -152,8 +152,8 @@ static bool tst_header_opcode_dump
 
 /* Code execution */
 
-static bool tst_header_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
+static bool tst_header_operation_execute
+(const struct sieve_operation *op ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	bool result = TRUE;
diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c
index 92e4082046bc2d0cabb3d084ad051398fddbf8fd..4f4656ead05115ba37f4ddd90eff73f67769d219 100644
--- a/src/lib-sieve/tst-size.c
+++ b/src/lib-sieve/tst-size.c
@@ -34,29 +34,29 @@ const struct sieve_command tst_size = {
 	NULL 
 };
 
-/* Opcodes */
+/* Operations */
 
-static bool tst_size_opcode_dump
-	(const struct sieve_opcode *opcode, 
+static bool tst_size_operation_dump
+	(const struct sieve_operation *op, 
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool tst_size_opcode_execute
-	(const struct sieve_opcode *opcode, 
+static bool tst_size_operation_execute
+	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
-const struct sieve_opcode tst_size_over_opcode = { 
+const struct sieve_operation tst_size_over_operation = { 
 	"SIZE-OVER",
-	SIEVE_OPCODE_SIZE_OVER,
-	NULL, 0,
-	tst_size_opcode_dump, 
-	tst_size_opcode_execute 
+	NULL, 
+	SIEVE_OPERATION_SIZE_OVER,
+	tst_size_operation_dump, 
+	tst_size_operation_execute 
 };
 
-const struct sieve_opcode tst_size_under_opcode = {
+const struct sieve_operation tst_size_under_operation = {
 	"SIZE-UNDER",
-	SIEVE_OPCODE_SIZE_UNDER,
-	NULL, 0, 
-	tst_size_opcode_dump, 
-	tst_size_opcode_execute 
+	NULL, 
+	SIEVE_OPERATION_SIZE_UNDER,
+	tst_size_operation_dump, 
+	tst_size_operation_execute 
 };
 
 /* Context structures */
@@ -168,9 +168,9 @@ bool tst_size_generate
 	struct tst_size_context_data *ctx_data = (struct tst_size_context_data *) ctx->data;
 
 	if ( ctx_data->type == SIZE_OVER ) 
-		sieve_generator_emit_opcode(generator, &tst_size_over_opcode);
+		sieve_generator_emit_operation(generator, &tst_size_over_operation);
 	else
-		sieve_generator_emit_opcode(generator, &tst_size_under_opcode);
+		sieve_generator_emit_operation(generator, &tst_size_under_operation);
 
  	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
@@ -181,11 +181,11 @@ bool tst_size_generate
 
 /* Code dump */
 
-static bool tst_size_opcode_dump
-(const struct sieve_opcode *opcode,
+static bool tst_size_operation_dump
+(const struct sieve_operation *op,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-    sieve_code_dumpf(denv, "%s", opcode->mnemonic);
+    sieve_code_dumpf(denv, "%s", op->mnemonic);
 	sieve_code_descend(denv);
 	
 	return 
@@ -207,13 +207,13 @@ static bool tst_size_get
 	return TRUE;
 }
 
-static bool tst_size_opcode_execute
-(const struct sieve_opcode *opcode,
+static bool tst_size_operation_execute
+(const struct sieve_operation *op,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	sieve_size_t mail_size, limit;
 	
-	printf("%s\n", opcode->mnemonic);
+	printf("%s\n", op->mnemonic);
 	
 	if ( !sieve_opr_number_read(renv->sbin, address, &limit) ) 
 		return FALSE;	
@@ -221,7 +221,7 @@ static bool tst_size_opcode_execute
 	if ( !tst_size_get(renv, &mail_size) )
 		return FALSE;
 	
-	if ( opcode == &tst_size_over_opcode )
+	if ( op == &tst_size_over_operation )
 		sieve_interpreter_set_test_result(renv->interp, (mail_size > limit));
 	else
 		sieve_interpreter_set_test_result(renv->interp, (mail_size < limit));