diff --git a/src/lib-sieve/cmd-if.c b/src/lib-sieve/cmd-if.c
index 0ba75ad815bb607d992694cfa7592f220cd0c18b..9e93826f8b7b91519aeb3b1c854e58ff40fa5428 100644
--- a/src/lib-sieve/cmd-if.c
+++ b/src/lib-sieve/cmd-if.c
@@ -2,6 +2,7 @@
 #include "sieve-commands-private.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
+#include "sieve-code.h"
 
 /* Context */
 
@@ -149,7 +150,7 @@ bool cmd_if_generate
 	/* Are we the final command in this if-elsif-else structure? */
 	if ( ctx_data->next != NULL ) {
 		/* No, generate jump to end of if-elsif-else structure (resolved later) */
-		sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_JMP);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMP);
 		ctx_data->exit_jump = sieve_generator_emit_offset(generator, 0);
 	} else {
 		/* Yes, Resolve previous exit jumps to this point */
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index 8dc7707c84386be2526ed0d9a7976133bd945f1c..65c92b13840e030755b57887a29b6b853ef4d4ad 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -1,3 +1,5 @@
+#include <stdio.h>
+
 #include "sieve-extensions.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
@@ -6,13 +8,14 @@
 /* Forward declarations */
 
 static bool cmd_reject_validate(struct sieve_validator *validator, struct sieve_command_context *cmd);
-static bool ext_reject_opcode_dump(struct sieve_interpreter *interpreter, int opcode);
+static bool cmd_reject_generate(struct sieve_generator *generator,	struct sieve_command_context *ctx);
+static bool opc_reject_dump(struct sieve_interpreter *interpreter);
 
 /* Extension definitions */
 
 static const struct sieve_command reject_command = 
-	{ "reject", SCT_COMMAND, NULL, cmd_reject_validate, NULL, NULL };
-static const struct sieve_opcode_extension reject_opcode = 
+	{ "reject", SCT_COMMAND, NULL, cmd_reject_validate, cmd_reject_generate, NULL };
+static const struct sieve_opcode reject_opcode = 
 	{ opc_reject_dump, NULL };
 
 /* 
@@ -51,7 +54,7 @@ bool ext_reject_validator_load(struct sieve_validator *validator)
  * Generation
  */
  
-bool cmd_reject_generate
+static bool cmd_reject_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
 	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
@@ -65,6 +68,16 @@ bool cmd_reject_generate
 	return TRUE;
 }
 
+/* Load extension into generator */
+bool ext_reject_generator_load(struct sieve_generator *generator)
+{
+	/* Register new command */
+	sieve_generator_register_opcode(generator, &reject_opcode);
+
+	return TRUE;
+}
+
+
 /* 
  * Code dump
  */
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 20c8c2aa45edee1cc77e558fb833af9bef46b721..96e2597e325d1502151465c40578a98b82cfc7d7 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -1,4 +1,7 @@
+#include <stdio.h>
+
 #include "sieve-code.h"
+#include "sieve-interpreter.h"
 
 /* Code dump for core commands */
 
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index e8f261d3be82700b2eeab4e76ff42cbfd3bd15f2..02c4734ce8075fbf4806a7c85c3c521f0570a823 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -4,13 +4,15 @@
 #include "sieve-common.h"
 #include "sieve-extensions.h"
 
+typedef size_t sieve_size_t;
+
 struct sieve_opcode {
 	bool (*dump)(struct sieve_interpreter *interpreter);
 	bool (*execute)(struct sieve_interpreter *interpreter);
 };
 
 enum sieve_core_operation {
-	SIEVE_OPCODE_LOAD      = 0x01
+	SIEVE_OPCODE_LOAD      = 0x01,
 	SIEVE_OPCODE_JMP       = 0x02,
 	SIEVE_OPCODE_JMPTRUE   = 0x03,
 	SIEVE_OPCODE_JMPFALSE  = 0x04,
diff --git a/src/lib-sieve/sieve-commands-private.h b/src/lib-sieve/sieve-commands-private.h
index ee7a93fdbc11a04449b48bef363b9890c76b04be..36fa6a8d9e3951fe831196a5690d3df26db37e95 100644
--- a/src/lib-sieve/sieve-commands-private.h
+++ b/src/lib-sieve/sieve-commands-private.h
@@ -65,7 +65,9 @@ bool cmd_if_generate(struct sieve_generator *generator, struct sieve_command_con
 bool cmd_else_generate(struct sieve_generator *generator, struct sieve_command_context *ctx);
 
 bool cmd_redirect_validate(struct sieve_validator *validator, struct sieve_command_context *context);
+
 bool cmd_require_validate(struct sieve_validator *validator, struct sieve_command_context *context);
+bool cmd_require_generate(struct sieve_generator *generator, struct sieve_command_context *ctx);
 
 extern const struct sieve_command sieve_core_commands[];
 extern const unsigned int sieve_core_commands_count;
diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c
index 669253bdf08064ae2b79f03cba7617c66aff4686..52952991f025552f7b746728da0c91d5d1d99d81 100644
--- a/src/lib-sieve/sieve-commands.c
+++ b/src/lib-sieve/sieve-commands.c
@@ -79,7 +79,7 @@ bool cmd_stop_generate
 	(struct sieve_generator *generator, 
 		struct sieve_command_context *ctx __attr_unused__) 
 {
-	sieve_generator_emit_opcode(generator, NULL, SIEVE_OPCODE_STOP);\
+	sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_STOP);
 	return TRUE;
 }
 
@@ -87,7 +87,7 @@ bool cmd_keep_generate
 	(struct sieve_generator *generator, 
 		struct sieve_command_context *ctx __attr_unused__) 
 {
-	sieve_generator_emit_opcode(generator, NULL, SIEVE_OPCODE_KEEP);
+	sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_KEEP);
 	return TRUE;
 }
 
@@ -95,7 +95,7 @@ bool cmd_discard_generate
 	(struct sieve_generator *generator, 
 		struct sieve_command_context *ctx __attr_unused__) 
 {
-	sieve_generator_emit_opcode(generator, NULL, SIEVE_OPCODE_DISCARD);
+	sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_DISCARD);
 	return TRUE;
 }
 
@@ -105,7 +105,7 @@ bool tst_false_generate
 		struct sieve_jumplist *jumps, bool jump_true)
 {
 	if ( !jump_true ) {
-		sieve_generator_emit_opcode(generator, NULL, SIEVE_OPCODE_JMP);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMP);
 		sieve_jumplist_add(jumps, sieve_generator_emit_offset(generator, 0));
 	}
 	
@@ -118,7 +118,7 @@ bool tst_true_generate
 		struct sieve_jumplist *jumps, bool jump_true)
 {
 	if ( jump_true ) {
-		sieve_generator_emit_opcode(generator, NULL, SIEVE_OPCODE_JMP);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMP);
 		sieve_jumplist_add(jumps, sieve_generator_emit_offset(generator, 0));
 	}
 	
diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h
index b76389b21c2567285b018aba222f360bca3f5369..15a841b3b4bc8f530fb4c67f07c12906bd29e578 100644
--- a/src/lib-sieve/sieve-extensions.h
+++ b/src/lib-sieve/sieve-extensions.h
@@ -9,9 +9,6 @@ struct sieve_extension {
 	
 	bool (*validator_load)(struct sieve_validator *validator);
 	bool (*generator_load)(struct sieve_generator *generator);
-	
-	bool (*opcode_dump)(struct sieve_interpreter *interpreter);
-	bool (*opcode_execute)(struct sieve_interpreter *interpreter);
 };
 
 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 a91263bc664fd6497d6d4073665b5d986e634d3c..921e90990b5baa58e4fd71c631a6f6e912e041ef 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -7,9 +7,13 @@
 #include "hash.h"
 
 #include "sieve-common.h"
+#include "sieve-extensions.h"
 #include "sieve-commands-private.h"
+#include "sieve-code.h"
+
 #include "sieve-generator.h"
 
+
 /* Jump list */
 void sieve_jumplist_init(struct sieve_jumplist *jlist)
 {
@@ -34,6 +38,13 @@ void sieve_jumplist_resolve(struct sieve_jumplist *jlist, struct sieve_generator
 	array_free(&jlist->jumps);
 }
 
+/* Opcode */
+
+struct sieve_opcode_registration {
+	const struct sieve_opcode *opcode;
+	unsigned int code;
+};
+
 /* Generator */
 
 struct sieve_generator {
@@ -74,18 +85,25 @@ void sieve_generator_free(struct sieve_generator *generator)
 
 /* Registration functions */
 
-void sieve_generator_register_extension
-	(struct sieve_validator *generator, const struct sieve_extension *extension) 
+void sieve_generator_register_opcode
+	(struct sieve_generator *generator, const struct sieve_opcode *opcode) 
 {
-	unsigned int index = hash_size(generator->extensions);
-	 
-	hash_insert(generator->extension, (void *) extension, (void *) index);
+	struct sieve_opcode_registration *reg;
+	
+	reg = p_new(generator->pool, struct sieve_opcode_registration, 1);
+	reg->opcode = opcode;
+	reg->code = hash_size(generator->opcodes);
+	
+	hash_insert(generator->opcodes, (void *) opcode, (void *) reg);
 }
 
 unsigned int sieve_generator_find_opcode
-		(struct sieve_validator *generator, const struct sieve_opcode *opcode) 
+		(struct sieve_generator *generator, const struct sieve_opcode *opcode) 
 {
-  return 	(unsigned int) hash_lookup(generator->opcodes, opcode);
+  struct sieve_opcode_registration *reg = 
+    (struct sieve_opcode_registration *) hash_lookup(generator->opcodes, opcode);
+    
+  return reg->code;
 }
 
 /* Emission functions */
@@ -233,7 +251,8 @@ sieve_size_t sieve_generator_emit_string_list
   const struct sieve_ast_argument *stritem;
   unsigned int listlen = sieve_ast_strlist_count(strlist);
   sieve_size_t end_offset = 0;
-  
+
+	/* Emit byte identifying the type of operand */	  
   sieve_size_t address = sieve_generator_emit_byte(generator, SIEVE_OPERAND_STRING_LIST);
   
   /* Give the interpreter an easy way to skip over this string list */
@@ -263,7 +282,8 @@ sieve_size_t sieve_generator_emit_core_opcode(struct sieve_generator *generator,
 	return sieve_generator_emit_data(generator, (void *) &op, 1);
 }
 
-sieve_size_t sieve_generator_emit_opcode(struct sieve_generator *generator, struct sieve_opcode *opcode) 
+sieve_size_t sieve_generator_emit_opcode
+	(struct sieve_generator *generator, const struct sieve_opcode *opcode) 
 {
 	unsigned char op = (1 << 6) + sieve_generator_find_opcode(generator, opcode);
 	
@@ -291,9 +311,9 @@ bool sieve_generate_test
 		if ( tst_node->context->command->generate(generator, tst_node->context) ) {
 			
 			if ( jump_true ) 
-				sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_JMPTRUE);
+				sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMPTRUE);
 			else
-				sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_JMPFALSE);
+				sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMPFALSE);
 			sieve_jumplist_add(jlist, sieve_generator_emit_offset(generator, 0));
 						
 			return TRUE;
diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h
index d529636461024a50d9541557a7eee04d7ec7e42e..808dc76480a73ad5506648252c8471bafffac029 100644
--- a/src/lib-sieve/sieve-generator.h
+++ b/src/lib-sieve/sieve-generator.h
@@ -2,14 +2,18 @@
 #define __SIEVE_GENERATOR_H__
 
 #include "sieve-ast.h"
-
-typedef size_t sieve_size_t;
+#include "sieve-code.h"
 
 struct sieve_generator;
 
 struct sieve_generator *sieve_generator_create(struct sieve_ast *ast);
 void sieve_generator_free(struct sieve_generator *generator);
 
+void sieve_generator_register_opcode
+	(struct sieve_generator *generator, const struct sieve_opcode *opcode);
+unsigned int sieve_generator_find_opcode
+		(struct sieve_generator *generator, const struct sieve_opcode *opcode); 
+		
 /* Jump list */
 
 struct sieve_jumplist {
@@ -27,7 +31,9 @@ inline void sieve_generator_update_data
 	(struct sieve_generator *generator, sieve_size_t address, void *data, sieve_size_t size);
 inline sieve_size_t sieve_generator_get_current_address(struct sieve_generator *generator);
 
-sieve_size_t sieve_generator_emit_opcode(struct sieve_generator *generator, const char *extension, int opcode);
+sieve_size_t sieve_generator_emit_core_opcode(struct sieve_generator *generator, int opcode);
+sieve_size_t sieve_generator_emit_opcode(struct sieve_generator *generator, const struct sieve_opcode *opcode);
+
 sieve_size_t sieve_generator_emit_offset(struct sieve_generator *generator, int offset);
 void sieve_generator_resolve_offset(struct sieve_generator *generator, sieve_size_t address); 
 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index d58d6d6a6546813e7996e6c1e7c43d9256367ec5..1961e8852c9ca45a0cf317d7b38dd2ad836d9e3c 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -3,6 +3,7 @@
 
 #include "lib.h"
 #include "mempool.h"
+#include "array.h"
 
 #include "sieve-commands-private.h"
 #include "sieve-generator.h"
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index 82a614ac1f9ca8b1b741de91d55edc7896dab18b..71938e38a899ecbfa3ad5ecc6dcf4bdefe5546f0 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -55,7 +55,7 @@ bool tst_address_generate
 		struct sieve_command_context *ctx __attr_unused__) 
 {
 	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_ADDRESS);
+	sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_ADDRESS);
 	
 	/* Emit header names */  	
 	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
diff --git a/src/lib-sieve/tst-allof.c b/src/lib-sieve/tst-allof.c
index aa0d61d343764e243eca1931bd8f312b898b346e..1d708c50d5d2746169410bb0eff78010db6a87c7 100644
--- a/src/lib-sieve/tst-allof.c
+++ b/src/lib-sieve/tst-allof.c
@@ -44,7 +44,7 @@ bool tst_allof_generate
 	
 	if ( jump_true ) {
 		/* All tests succeeded, jump to case TRUE */
-		sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_JMP);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMP);
 		sieve_jumplist_add(jumps, sieve_generator_emit_offset(generator, 0));
 		
 		/* All false exits jump here */
diff --git a/src/lib-sieve/tst-anyof.c b/src/lib-sieve/tst-anyof.c
index 46f9ac910dc8d5940b69b2526a97f0fc2611a020..0be2dba06eed6ccadfad3dd3c9a8de3496a648b1 100644
--- a/src/lib-sieve/tst-anyof.c
+++ b/src/lib-sieve/tst-anyof.c
@@ -43,7 +43,7 @@ bool tst_anyof_generate
 	
 	if ( !jump_true ) {
 		/* All tests failed, jump to case FALSE */
-		sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_JMP);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_JMP);
 		sieve_jumplist_add(jumps, sieve_generator_emit_offset(generator, 0));
 		
 		/* All true exits jump here */
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index 9e77fe7245d660d8c16d9f0366108a69e8616283..752dff2cda1c30e66169eb5acc8347fc88fd7c00 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -35,7 +35,7 @@ bool tst_exists_generate
 		struct sieve_command_context *ctx) 
 {
 	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_EXISTS);
+	sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_EXISTS);
 	
 	/* Emit header names */
 	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index c402e823729e2ef67fa25df8689ae52f39bb320a..9f3aad8ef54b3886f3c7646b9891f3e83840f481 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -52,7 +52,7 @@ bool tst_header_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
 	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
-	sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_HEADER);
+	sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_HEADER);
 
 	/* Emit header names */  	
 	if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) 
diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c
index fee84f398fa1159a03c5ba71cf7f31e00c5c0185..69a1994be331b0cf94b00f95ee3a54c817dcb84d 100644
--- a/src/lib-sieve/tst-size.c
+++ b/src/lib-sieve/tst-size.c
@@ -1,6 +1,7 @@
 #include "sieve-commands.h"
 #include "sieve-commands-private.h"
 #include "sieve-validator.h"
+#include "sieve-code.h"
 
 struct tst_size_context_data {
 	enum { SIZE_UNASSIGNED, SIZE_UNDER, SIZE_OVER } type;
@@ -104,9 +105,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_core_opcode(generator, NULL, SIEVE_OPCODE_SIZEOVER);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_SIZEOVER);
 	else
-		sieve_generator_emit_core_opcode(generator, NULL, SIEVE_OPCODE_SIZEUNDER);
+		sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_SIZEUNDER);
 
 	sieve_generator_emit_number(generator, ctx_data->limit);