From 95803e31b0a298dfb89a0953943127ec9009276b Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 2 Dec 2007 14:44:01 +0100
Subject: [PATCH] Properly implemented the code dumper. Dumps are now printed
 in a stream. The individual opcode and operand implementations no longer use
 printf()s.

---
 src/lib-sieve/cmd-redirect.c                  |   3 +-
 src/lib-sieve/ext-envelope.c                  |   3 +-
 src/lib-sieve/ext-fileinto.c                  |   3 +-
 src/lib-sieve/ext-reject.c                    |   5 +-
 src/lib-sieve/plugins/copy/ext-copy.c         |  13 +-
 .../plugins/imapflags/ext-imapflags-common.c  |   4 +-
 src/lib-sieve/plugins/imapflags/tag-flags.c   |  16 +--
 src/lib-sieve/plugins/imapflags/tst-hasflag.c |   2 +-
 src/lib-sieve/plugins/vacation/ext-vacation.c |   5 +-
 src/lib-sieve/sieve-actions.c                 |  24 ++++
 src/lib-sieve/sieve-actions.h                 |   6 +-
 src/lib-sieve/sieve-address-parts.c           |   9 +-
 src/lib-sieve/sieve-code-dumper.c             | 127 +++++++++++++-----
 src/lib-sieve/sieve-code-dumper.h             |  23 +++-
 src/lib-sieve/sieve-code.c                    |  74 +++++-----
 src/lib-sieve/sieve-comparators.c             |   9 +-
 src/lib-sieve/sieve-interpreter.c             |   2 +-
 src/lib-sieve/sieve-match-types.c             |   9 +-
 src/lib-sieve/sieve.c                         |   4 +-
 src/lib-sieve/sieve.h                         |   2 +-
 src/lib-sieve/tst-address.c                   |   6 +-
 src/lib-sieve/tst-exists.c                    |   4 +-
 src/lib-sieve/tst-header.c                    |   3 +-
 src/lib-sieve/tst-size.c                      |  10 +-
 src/sieve-bin/sieve-exec.c                    |  10 +-
 src/sieve-bin/sieve-test.c                    |  12 +-
 src/sieve-bin/sievec.c                        |  18 +--
 27 files changed, 260 insertions(+), 146 deletions(-)

diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 76b74d0ab..b06556283 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -121,7 +121,8 @@ static bool cmd_redirect_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("REDIRECT\n");
+	sieve_code_dumpf(denv, "REDIRECT");
+	sieve_code_descend(denv);
 
 	if ( !sieve_code_dumper_print_optional_operands(denv, address) )
 		return FALSE;
diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index acc3dc812..aa0e902e5 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -165,7 +165,8 @@ static bool ext_envelope_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("ENVELOPE\n");
+	sieve_code_dumpf(denv, "ENVELOPE");
+	sieve_code_descend(denv);
 
 	/* Handle any optional arguments */
 	if ( !sieve_addrmatch_default_dump_optionals(denv, address) )
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index 30456beaf..7454f0934 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -131,7 +131,8 @@ static bool ext_fileinto_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("FILEINTO\n");
+	sieve_code_dumpf(denv, "FILEINTO");
+	sieve_code_descend(denv);
 
 	if ( !sieve_code_dumper_print_optional_operands(denv, address) )
 		return FALSE;
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index 09682fdce..30075bf3b 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -168,8 +168,9 @@ static bool ext_reject_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("REJECT\n");
-
+	sieve_code_dumpf(denv, "REJECT");
+	sieve_code_descend(denv);
+	
 	if ( !sieve_code_dumper_print_optional_operands(denv, address) )
         return FALSE;
 	
diff --git a/src/lib-sieve/plugins/copy/ext-copy.c b/src/lib-sieve/plugins/copy/ext-copy.c
index b2478ec8e..506af03fe 100644
--- a/src/lib-sieve/plugins/copy/ext-copy.c
+++ b/src/lib-sieve/plugins/copy/ext-copy.c
@@ -53,9 +53,6 @@ static bool ext_copy_load(int ext_id)
 
 const struct sieve_side_effect_extension ext_copy_side_effect;
 
-static bool seff_copy_dump
-	(const struct sieve_side_effect *seffect,
-    	const struct sieve_dumptime_env *denv, sieve_size_t *address);
 static void seff_copy_print
 	(const struct sieve_side_effect *seffect,	const struct sieve_action *action, 
 		void *se_context, bool *keep);
@@ -69,8 +66,7 @@ const struct sieve_side_effect copy_side_effect = {
 	&act_store,	
 	&ext_copy_side_effect,
 	0,
-	seff_copy_dump,
-	NULL,
+	NULL, NULL,
 	seff_copy_print,
 	NULL, NULL,
 	seff_copy_post_commit, 
@@ -126,13 +122,6 @@ static const struct sieve_argument copy_tag = {
 
 /* Side effect execution */
 
-static bool seff_copy_dump
-(const struct sieve_side_effect *seffect,
-    const struct sieve_dumptime_env *denv, sieve_size_t *address)
-{
-	return TRUE;   
-}
-
 static void seff_copy_print
 	(const struct sieve_side_effect *seffect ATTR_UNUSED, 
 		const struct sieve_action *action ATTR_UNUSED, 
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
index 17eae76bc..4485474f6 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
@@ -5,6 +5,7 @@
 #include "sieve-validator.h" 
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-code-dumper.h"
 
 #include "ext-imapflags-common.h"
 
@@ -83,7 +84,8 @@ bool ext_imapflags_command_opcode_dump
 (const struct sieve_opcode *opcode,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("%s\n", opcode->mnemonic);
+	sieve_code_dumpf(denv, "%s", opcode->mnemonic);
+	sieve_code_descend(denv);
 
 	return 
 		sieve_opr_stringlist_dump(denv, address);
diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c
index cd0636b4b..ad5a0bd0a 100644
--- a/src/lib-sieve/plugins/imapflags/tag-flags.c
+++ b/src/lib-sieve/plugins/imapflags/tag-flags.c
@@ -32,10 +32,10 @@ const struct sieve_argument tag_flags = {
 
 const struct sieve_side_effect_extension ext_flags_side_effect;
 
-static bool seff_flags_dump
+static bool seff_flags_dump_context
 	(const struct sieve_side_effect *seffect,
     	const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static bool seff_flags_read
+static bool seff_flags_read_context
 	(const struct sieve_side_effect *seffect, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address,
 		void **se_context);
@@ -53,8 +53,8 @@ const struct sieve_side_effect flags_side_effect = {
 	
 	&ext_flags_side_effect,
 	0,
-	seff_flags_dump,
-	seff_flags_read,
+	seff_flags_dump_context,
+	seff_flags_read_context,
 	seff_flags_print,
 	NULL,
 	seff_flags_post_execute, 
@@ -126,14 +126,14 @@ struct seff_flags_context {
 	enum mail_flags flags;
 };
 
-static bool seff_flags_dump
-(const struct sieve_side_effect *seffect, 
+static bool seff_flags_dump_context
+(const struct sieve_side_effect *seffect ATTR_UNUSED, 
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	return TRUE;
+	return sieve_opr_stringlist_dump(denv, address);
 }
 
-static bool seff_flags_read
+static bool seff_flags_read_context
 (const struct sieve_side_effect *seffect ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address,
 	void **se_context)
diff --git a/src/lib-sieve/plugins/imapflags/tst-hasflag.c b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
index cb2ec130d..5b1f02fea 100644
--- a/src/lib-sieve/plugins/imapflags/tst-hasflag.c
+++ b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
@@ -168,7 +168,7 @@ static bool tst_hasflag_opcode_dump
 {
 	int opt_code = 1;
 
-	printf("HASFLAG\n");
+	sieve_code_dumpf(denv, "HASFLAG");
 
 	/* Handle any optional arguments */
 	if ( sieve_operand_optional_present(denv->sbin, address) ) {
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index 06f4e5cdb..9ed6c9c91 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -341,8 +341,9 @@ static bool ext_vacation_opcode_dump
 {	
 	int opt_code = 1;
 	
-	printf("VACATION\n");
-	
+	sieve_code_dumpf(denv, "VACATION");
+	sieve_code_descend(denv);	
+
 	if ( sieve_operand_optional_present(denv->sbin, address) ) {
 		while ( opt_code != 0 ) {
 			if ( !sieve_operand_optional_read(denv->sbin, address, &opt_code) ) 
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 6f4854683..45ce31cf9 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -8,6 +8,7 @@
 #include "sieve-extensions.h"
 #include "sieve-binary.h"
 #include "sieve-interpreter.h"
+#include "sieve-code-dumper.h"
 #include "sieve-result.h"
 #include "sieve-actions.h"
 
@@ -97,6 +98,29 @@ void sieve_opr_side_effect_emit
 		seffect->extension->side_effects_count > 1)
 }
 
+bool sieve_opr_side_effect_dump
+(const struct sieve_dumptime_env *denv, sieve_size_t *address)
+{
+	const struct sieve_side_effect *seffect;
+
+    sieve_code_mark(denv);
+	seffect = sieve_opr_side_effect_read(denv->sbin, address);
+
+	if ( seffect == NULL ) 
+		return FALSE;
+
+    sieve_code_dumpf(denv, "SIDE-EFFECT: %s", seffect->name);
+
+	if ( seffect->dump_context != NULL ) {
+		sieve_code_descend(denv);
+		if ( !seffect->dump_context(seffect, denv, address) )
+			return FALSE;	
+		sieve_code_ascend(denv);
+	}
+
+    return TRUE;
+}
+
 /* FIXME: Duplicated */
 const struct sieve_side_effect *sieve_opr_side_effect_read
 (struct sieve_binary *sbin, sieve_size_t *address)
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index a80805122..cc8fe93df 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -61,10 +61,10 @@ struct sieve_side_effect {
 	const struct sieve_side_effect_extension *extension;
 	unsigned int ext_code;
 	
-	bool (*dump)
+	bool (*dump_context)
 		(const struct sieve_side_effect *seffect, 
 			const struct sieve_dumptime_env *renv, sieve_size_t *address);
-	bool (*read)
+	bool (*read_context)
 		(const struct sieve_side_effect *seffect, 
 			const struct sieve_runtime_env *renv, sieve_size_t *address,
 			void **se_context);
@@ -114,6 +114,8 @@ void sieve_side_effect_extension_set
 void sieve_opr_side_effect_emit
 	(struct sieve_binary *sbin, const struct sieve_side_effect *seffect, 
 		int ext_id);
+bool sieve_opr_side_effect_dump
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 const struct sieve_side_effect *sieve_opr_side_effect_read
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 805ccd930..6e72de6bd 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -302,14 +302,15 @@ const struct sieve_address_part *sieve_opr_address_part_read
 bool sieve_opr_address_part_dump
 (const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	sieve_size_t pc = *address;
-	const struct sieve_address_part *addrp = 
-		sieve_opr_address_part_read(denv->sbin, address);
+	const struct sieve_address_part *addrp; 
+		
+	sieve_code_mark(denv);
+	addrp = sieve_opr_address_part_read(denv->sbin, address);
 	
 	if ( addrp == NULL )
 		return FALSE;
 		
-	printf("%08x:   ADDRESS-PART: %s\n", pc, addrp->identifier);
+	sieve_code_dumpf(denv, "ADDRESS-PART: %s", addrp->identifier);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/sieve-code-dumper.c b/src/lib-sieve/sieve-code-dumper.c
index a1db9d687..0d24f9d5f 100644
--- a/src/lib-sieve/sieve-code-dumper.c
+++ b/src/lib-sieve/sieve-code-dumper.c
@@ -2,7 +2,9 @@
 #include <string.h>
 
 #include "lib.h"
+#include "str.h"
 #include "mempool.h"
+#include "ostream.h"
 
 #include "sieve-extensions.h"
 #include "sieve-commands-private.h"
@@ -20,6 +22,10 @@ struct sieve_code_dumper {
 	/* Dump status */
 	sieve_size_t pc;          /* Program counter */
 	
+	const struct sieve_opcode *opcode;
+	sieve_size_t mark_address;
+	unsigned int indent;
+	
 	/* Runtime environment environment */
 	struct sieve_dumptime_env dumpenv; 
 };
@@ -27,30 +33,77 @@ struct sieve_code_dumper {
 struct sieve_code_dumper *sieve_code_dumper_create(struct sieve_binary *sbin) 
 {
 	pool_t pool;
-	struct sieve_code_dumper *dumpr;
+	struct sieve_code_dumper *dumper;
 	
 	pool = pool_alloconly_create("sieve_code_dumper", 4096);	
-	dumpr = p_new(pool, struct sieve_code_dumper, 1);
-	dumpr->pool = pool;
-	dumpr->dumpenv.dumpr = dumpr;
+	dumper = p_new(pool, struct sieve_code_dumper, 1);
+	dumper->pool = pool;
+	dumper->dumpenv.dumper = dumper;
 	
-	dumpr->dumpenv.sbin = sbin;
+	dumper->dumpenv.sbin = sbin;
 	sieve_binary_ref(sbin);
 	
-	dumpr->pc = 0;
+	dumper->pc = 0;
 	
-	return dumpr;
+	return dumper;
 }
 
-void sieve_code_dumper_free(struct sieve_code_dumper *dumpr) 
+void sieve_code_dumper_free(struct sieve_code_dumper *dumper) 
 {
-	sieve_binary_unref(&dumpr->dumpenv.sbin);
-	pool_unref(&(dumpr->pool));
+	sieve_binary_unref(&dumper->dumpenv.sbin);
+	pool_unref(&(dumper->pool));
 }
 
-inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumpr)
+inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper)
 {
-	return dumpr->pool;
+	return dumper->pool;
+}
+
+/* Dump functions */
+
+void sieve_code_dumpf
+(const struct sieve_dumptime_env *denv, const char *fmt, ...)
+{
+	unsigned tab = denv->dumper->indent;
+	 
+	string_t *outbuf = t_str_new(128);
+	va_list args;
+	
+	va_start(args, fmt);	
+	str_printfa(outbuf, "%08x: ", denv->dumper->mark_address);
+	
+	while ( tab > 0 )	{
+		str_append(outbuf, "  ");
+		tab--;
+	}
+	
+	str_vprintfa(outbuf, fmt, args);
+	str_append_c(outbuf, '\n');
+	va_end(args);
+	
+	o_stream_send(denv->stream, str_data(outbuf), str_len(outbuf));
+}
+
+inline void sieve_code_mark(const struct sieve_dumptime_env *denv)
+{
+	denv->dumper->mark_address = denv->dumper->pc;
+}
+
+inline void sieve_code_mark_specific
+(const struct sieve_dumptime_env *denv, sieve_size_t location)
+{
+	denv->dumper->mark_address = location;
+}
+
+inline void sieve_code_descend(const struct sieve_dumptime_env *denv)
+{
+	denv->dumper->indent++;
+}
+
+inline void sieve_code_ascend(const struct sieve_dumptime_env *denv)
+{
+	if ( denv->dumper->indent > 0 )
+		denv->dumper->indent--;
 }
 
 /* Opcodes and operands */
@@ -66,12 +119,7 @@ bool sieve_code_dumper_print_optional_operands
 				return FALSE;
 
 			if ( opt_code == SIEVE_OPT_SIDE_EFFECT ) {
-				const struct sieve_side_effect *seffect = 
-					sieve_opr_side_effect_read(denv->sbin, address);
-
-				if ( seffect == NULL ) return FALSE;
-			
-				if ( seffect->read != NULL && !seffect->dump(seffect, denv, address) )
+				if ( !sieve_opr_side_effect_dump(denv, address) )
 					return FALSE;
 			}
 		}
@@ -82,18 +130,24 @@ bool sieve_code_dumper_print_optional_operands
 /* Code Dump */
 
 static bool sieve_code_dumper_print_operation
-	(struct sieve_code_dumper *dumpr) 
-{
-	const struct sieve_opcode *opcode = 
-		sieve_operation_read(dumpr->dumpenv.sbin, &(dumpr->pc));
+	(struct sieve_code_dumper *dumper) 
+{	
+	const struct sieve_opcode *opcode;
+	
+	/* Mark start address of opcode */
+	dumper->indent = 0;
+	dumper->mark_address = dumper->pc;
 
+	/* Read opcode */
+	dumper->opcode = opcode = 
+		sieve_operation_read(dumper->dumpenv.sbin, &(dumper->pc));
+
+	/* Try to dump it */
 	if ( opcode != NULL ) {
-		printf("%08x: ", dumpr->pc-1);
-	
 		if ( opcode->dump != NULL )
-			return opcode->dump(opcode, &(dumpr->dumpenv), &(dumpr->pc));
+			return opcode->dump(opcode, &(dumper->dumpenv), &(dumper->pc));
 		else if ( opcode->mnemonic != NULL )
-			printf("%s\n", opcode->mnemonic);
+			sieve_code_dumpf(&(dumper->dumpenv), "%s", opcode->mnemonic);
 		else
 			return FALSE;
 			
@@ -103,18 +157,23 @@ static bool sieve_code_dumper_print_operation
 	return FALSE;
 }
 
-void sieve_code_dumper_run(struct sieve_code_dumper *dumpr) 
+void sieve_code_dumper_run
+	(struct sieve_code_dumper *dumper, struct ostream *stream) 
 {
-	dumpr->pc = 0;
+	dumper->pc = 0;
+	dumper->dumpenv.stream = stream;
 	
-	while ( dumpr->pc < 
-		sieve_binary_get_code_size(dumpr->dumpenv.sbin) ) {
-		if ( !sieve_code_dumper_print_operation(dumpr) ) {
-			printf("Binary is corrupt.\n");
+	while ( dumper->pc < 
+		sieve_binary_get_code_size(dumper->dumpenv.sbin) ) {
+		if ( !sieve_code_dumper_print_operation(dumper) ) {
+			sieve_code_dumpf(&(dumper->dumpenv), "Binary is corrupt.");
 			return;
 		}
 	}
 	
-	printf("%08x: [End of code]\n", 
-		sieve_binary_get_code_size(dumpr->dumpenv.sbin));	
+	/* Mark end of the binary */
+	dumper->indent = 0;
+	dumper->mark_address = sieve_binary_get_code_size(dumper->dumpenv.sbin);
+
+	sieve_code_dumpf(&(dumper->dumpenv), "[End of code]");	
 }
diff --git a/src/lib-sieve/sieve-code-dumper.h b/src/lib-sieve/sieve-code-dumper.h
index 18fce6063..71e79237b 100644
--- a/src/lib-sieve/sieve-code-dumper.h
+++ b/src/lib-sieve/sieve-code-dumper.h
@@ -6,17 +6,27 @@
 struct sieve_code_dumper;
 
 struct sieve_dumptime_env {
-	struct sieve_code_dumper *dumpr;
+	struct sieve_code_dumper *dumper;
 	struct sieve_binary *sbin;
 	
-	const struct sieve_opcode *opcode;
-	sieve_size_t *opcode_addr;
+	struct ostream *stream;
 };
 
 struct sieve_code_dumper *sieve_code_dumper_create(struct sieve_binary *sbin);
-void sieve_code_dumper_free(struct sieve_code_dumper *dumpr);
-inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumpr);
+void sieve_code_dumper_free(struct sieve_code_dumper *dumper);
+inline pool_t sieve_code_dumper_pool(struct sieve_code_dumper *dumper);
 	
+/*  */	
+	
+void sieve_code_dumpf
+(const struct sieve_dumptime_env *denv, const char *fmt, ...);
+
+inline void sieve_code_mark(const struct sieve_dumptime_env *denv);
+inline void sieve_code_mark_specific
+	(const struct sieve_dumptime_env *denv, sieve_size_t location);
+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 */
 	
 bool sieve_code_dumper_print_optional_operands
@@ -24,6 +34,7 @@ bool sieve_code_dumper_print_optional_operands
 
 /* Code dump (debugging purposes) */
 
-void sieve_code_dumper_run(struct sieve_code_dumper *dumpr);
+void sieve_code_dumper_run
+	(struct sieve_code_dumper *dumper, struct ostream *stream);
 
 #endif /* __SIEVE_CODE_DUMPER_H */
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 0284423be..d4beb28ad 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -1,5 +1,6 @@
 #include "lib.h"
 #include "str.h"
+#include "str-sanitize.h"
 
 #include "sieve-common.h"
 #include "sieve-extensions.h"
@@ -259,12 +260,13 @@ void sieve_opr_number_emit(struct sieve_binary *sbin, sieve_size_t number)
 bool sieve_opr_number_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
 {
-	sieve_size_t pc = *address;
-	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
+	const struct sieve_operand *operand;
 	const struct sieve_opr_number_interface *intf;
 	
-	printf("%08x:   ", pc);
+	sieve_code_mark(denv);
 	
+	operand = sieve_operand_read(denv->sbin, address);
+
 	if ( operand == NULL || operand->class != &number_class ) 
 		return FALSE;
 		
@@ -299,7 +301,7 @@ static bool opr_number_dump
 	sieve_size_t number = 0;
 	
 	if (sieve_binary_read_integer(denv->sbin, address, &number) ) {
-		printf("NUM: %ld\n", (long) number);
+		sieve_code_dumpf(denv, "NUM: %ld", (long) number);
 
 		return TRUE;
 	}
@@ -318,17 +320,17 @@ static bool opr_number_read
 void sieve_opr_string_emit(struct sieve_binary *sbin, string_t *str)
 {
 	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_STRING);
-  (void) sieve_binary_emit_string(sbin, str);
+	(void) sieve_binary_emit_string(sbin, str);
 }
 
 bool sieve_opr_string_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
 {
-	sieve_size_t pc = *address;
-	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
+	const struct sieve_operand *operand;
 	const struct sieve_opr_string_interface *intf;
 	
-	printf("%08x:   ", pc);
+	sieve_code_mark(denv);
+	operand = sieve_operand_read(denv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &string_class ) 
 		return FALSE;
@@ -359,26 +361,15 @@ bool sieve_opr_string_read
 }
 
 
-static void _print_string(string_t *str) 
+static void _dump_string
+(const struct sieve_dumptime_env *denv, string_t *str) 
 {
-	unsigned int i = 0;
-  const unsigned char *sdata = str_data(str);
-
-	printf("STR[%ld]: \"", (long) str_len(str));
-
-	while ( i < 40 && i < str_len(str) ) {
-		if ( sdata[i] > 31 ) 
-			printf("%c", sdata[i]);
-		else
-			printf(".");
-	    
-	  i++;
-	}
-	
-	if ( str_len(str) < 40 ) 
-		printf("\"\n");
+	if ( str_len(str) > 80 )
+		sieve_code_dumpf(denv, "STR[%ld]: \"%s", 
+			(long) str_len(str), str_sanitize(str_c(str), 80));
 	else
-		printf("...\n");
+		sieve_code_dumpf(denv, "STR[%ld]: \"%s\"", 
+			(long) str_len(str), str_sanitize(str_c(str), 80));		
 }
 
 bool opr_string_dump
@@ -387,7 +378,7 @@ bool opr_string_dump
 	string_t *str; 
 	
 	if ( sieve_binary_read_string(denv->sbin, address, &str) ) {
-		_print_string(str);   		
+		_dump_string(denv, str);   		
 		
 		return TRUE;
 	}
@@ -436,11 +427,11 @@ void sieve_opr_stringlist_emit_end
 bool sieve_opr_stringlist_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
 {
-	sieve_size_t pc = *address;
-	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
-	
-	printf("%08x:   ", pc);
-	
+	const struct sieve_operand *operand;
+
+	sieve_code_mark(denv);
+	operand = sieve_operand_read(denv->sbin, address);
+		
 	if ( operand == NULL )
 		return FALSE;
 	
@@ -493,19 +484,21 @@ static bool opr_stringlist_dump
 	struct sieve_coded_stringlist *strlist;
 	
 	if ( (strlist=opr_stringlist_read(denv->sbin, address)) != NULL ) {
-  		sieve_size_t pc;
 		string_t *stritem;
 		
-		printf("STRLIST [%d] (END %08x)\n", 
+		sieve_code_dumpf(denv, "STRLIST [%d] (END %08x)", 
 			sieve_coded_stringlist_get_length(strlist), 
 			sieve_coded_stringlist_get_end_address(strlist));
 	  	
-	 	pc = sieve_coded_stringlist_get_current_offset(strlist);
+		sieve_code_mark_specific(denv,
+			sieve_coded_stringlist_get_current_offset(strlist));
+		sieve_code_descend(denv);
 		while ( sieve_coded_stringlist_next_item(strlist, &stritem) && stritem != NULL ) {	
-			printf("%08x:      ", pc);
-			_print_string(stritem);
-			pc = sieve_coded_stringlist_get_current_offset(strlist);  
+			_dump_string(denv, stritem);
+			sieve_code_mark_specific(denv,
+				sieve_coded_stringlist_get_current_offset(strlist));  
 		}
+		sieve_code_ascend(denv);
 		
 		return TRUE;
 	}
@@ -703,7 +696,8 @@ static bool opc_jmp_dump
 	int offset;
 	
 	if ( sieve_binary_read_offset(denv->sbin, address, &offset) ) 
-		printf("%s %d [%08x]\n", opcode->mnemonic, offset, pc + offset);
+		sieve_code_dumpf(denv, "%s %d [%08x]", 
+			opcode->mnemonic, offset, pc + offset);
 	else
 		return FALSE;
 	
@@ -716,7 +710,7 @@ bool sieve_opcode_string_dump
 (const struct sieve_opcode *opcode,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("%s\n", opcode->mnemonic);
+	sieve_code_dumpf(denv, "%s", opcode->mnemonic);
 
 	return 
 		sieve_opr_string_dump(denv, address);
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 242a4659c..b338be064 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -342,14 +342,15 @@ const struct sieve_comparator *sieve_opr_comparator_read
 bool sieve_opr_comparator_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	sieve_size_t pc = *address;
-	const struct sieve_comparator *cmp = 
-		sieve_opr_comparator_read(denv->sbin, address);
+	const struct sieve_comparator *cmp;
+
+	sieve_code_mark(denv);
+	cmp = sieve_opr_comparator_read(denv->sbin, address);
 	
 	if ( cmp == NULL )
 		return FALSE;
 		
-	printf("%08x:   COMPARATOR: %s\n", pc, cmp->identifier);
+	sieve_code_dumpf(denv, "COMPARATOR: %s", cmp->identifier);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 5234a48bf..623474e5c 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -222,7 +222,7 @@ bool sieve_interpreter_handle_optional_operands
 				if ( seffect == NULL ) return FALSE;
 			
 				if ( list != NULL ) {
-					if ( seffect->read != NULL && !seffect->read
+					if ( seffect->read_context != NULL && !seffect->read_context
 						(seffect, renv, address, &context) )
 						return FALSE;
 				
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index a33ebdcd4..e2ab77367 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -351,14 +351,15 @@ const struct sieve_match_type *sieve_opr_match_type_read
 bool sieve_opr_match_type_dump
 (const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	sieve_size_t pc = *address;
-	const struct sieve_match_type *mtch = 
-		sieve_opr_match_type_read(denv->sbin, address);
+	const struct sieve_match_type *mtch;
+
+	sieve_code_mark(denv); 
+	mtch = sieve_opr_match_type_read(denv->sbin, address);
 	
 	if ( mtch == NULL )
 		return FALSE;
 		
-	printf("%08x:   MATCH-TYPE: %s\n", pc, mtch->identifier);
+	sieve_code_dumpf(denv, "MATCH-TYPE: %s", mtch->identifier);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 54ebafb23..6843ccd6e 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -141,12 +141,12 @@ struct sieve_binary *sieve_compile(int fd, bool verbose)
 	return result;
 }
 
-void sieve_dump(struct sieve_binary *binary) 
+void sieve_dump(struct sieve_binary *binary, struct ostream *stream) 
 {
 	struct sieve_code_dumper *dumpr = sieve_code_dumper_create(binary);			
 
 	printf("Code Dump:\n\n");
-	sieve_code_dumper_run(dumpr);	
+	sieve_code_dumper_run(dumpr, stream);	
 	
 	sieve_code_dumper_free(dumpr);
 }
diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h
index 2516185b6..2f29e550d 100644
--- a/src/lib-sieve/sieve.h
+++ b/src/lib-sieve/sieve.h
@@ -44,7 +44,7 @@ bool sieve_init(const char *plugins);
 void sieve_deinit(void);
 
 struct sieve_binary *sieve_compile(int fd, bool verbose);
-void sieve_dump(struct sieve_binary *binary);
+void sieve_dump(struct sieve_binary *binary, struct ostream *stream);
 bool sieve_test
 	(struct sieve_binary *binary, const struct sieve_message_data *msgdata, 
 		const struct sieve_mail_environment *menv);
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index 80025fe6c..bd418d84f 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -10,6 +10,7 @@
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-code-dumper.h"
 
 /* Address test
  *
@@ -113,8 +114,9 @@ static bool tst_address_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,	
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	printf("ADDRESS\n");
-
+	sieve_code_dumpf(denv, "ADDRESS");
+	sieve_code_descend(denv);
+	
 	//* Handle any optional arguments */
 	if ( !sieve_addrmatch_default_dump_optionals(denv, address) )
 		return FALSE;
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index 2d204e74a..08b719a1f 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -5,6 +5,7 @@
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-code-dumper.h"
 
 /* Exists test
  *  
@@ -83,7 +84,8 @@ static bool tst_exists_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-    printf("EXISTS\n");
+    sieve_code_dumpf(denv, "EXISTS");
+	sieve_code_descend(denv);
 
 	return
     	sieve_opr_stringlist_dump(denv, address);
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index eb21ecd21..a1b2dd939 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -120,7 +120,8 @@ static bool tst_header_opcode_dump
 {
 	int opt_code = 1;
 
-	printf("HEADER\n");
+	sieve_code_dumpf(denv, "HEADER");
+	sieve_code_descend(denv);
 
 	/* Handle any optional arguments */
 	if ( sieve_operand_optional_present(denv->sbin, address) ) {
diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c
index 0dd70a29b..8d19e804b 100644
--- a/src/lib-sieve/tst-size.c
+++ b/src/lib-sieve/tst-size.c
@@ -1,11 +1,12 @@
-#include <stdio.h>
+#include "lib.h"
 
+#include "sieve-code.h"
 #include "sieve-commands.h"
 #include "sieve-commands-private.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
-#include "sieve-code.h"
+#include "sieve-code-dumper.h"
 
 /* Size test 
  *
@@ -184,8 +185,9 @@ static bool tst_size_opcode_dump
 (const struct sieve_opcode *opcode,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-    printf("%s\n", opcode->mnemonic);
-    
+    sieve_code_dumpf(denv, "%s", opcode->mnemonic);
+	sieve_code_descend(denv);
+	
 	return 
 		sieve_opr_number_dump(denv, address);
 }
diff --git a/src/sieve-bin/sieve-exec.c b/src/sieve-bin/sieve-exec.c
index 447e2d0a6..51c8edb9e 100644
--- a/src/sieve-bin/sieve-exec.c
+++ b/src/sieve-bin/sieve-exec.c
@@ -1,6 +1,7 @@
 /* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "ostream.h"
 #include "mail-storage.h"
 #include "mail-namespace.h"
 #include "env-util.h"
@@ -108,7 +109,14 @@ int main(int argc, char **argv)
 		exit(1);
 	}		 
 		
-	(void) sieve_dump(sbin);
+	if ( sbin != NULL ) { 
+		struct ostream *dumpstream = o_stream_create_fd(1, 0, FALSE);
+
+		if ( dumpstream != NULL ) {
+			(void) sieve_dump(sbin, dumpstream);
+			o_stream_unref(&dumpstream);
+		}
+	}
 
  	close(sfd);
 
diff --git a/src/sieve-bin/sieve-test.c b/src/sieve-bin/sieve-test.c
index d62b28992..a8afb8471 100644
--- a/src/sieve-bin/sieve-test.c
+++ b/src/sieve-bin/sieve-test.c
@@ -1,6 +1,7 @@
 /* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "ostream.h"
 
 #include "bin-common.h"
 #include "mail-raw.h"
@@ -69,8 +70,15 @@ int main(int argc, char **argv)
 		printf("Failed to compile sieve script\n");
 		exit(1);
 	}		 
-		
-	(void) sieve_dump(sbin);
+
+	if ( sbin != NULL ) { 
+		struct ostream *dumpstream = o_stream_create_fd(1, 0, FALSE);
+
+		if ( dumpstream != NULL ) {
+			(void) sieve_dump(sbin, dumpstream);
+			o_stream_unref(&dumpstream);
+		}
+	}		
 
  	close(sfd);
 	
diff --git a/src/sieve-bin/sievec.c b/src/sieve-bin/sievec.c
index e455e65dd..4d3208ba6 100644
--- a/src/sieve-bin/sievec.c
+++ b/src/sieve-bin/sievec.c
@@ -9,15 +9,11 @@
 #include "lib.h"
 #include "str.h"
 #include "istream.h"
+#include "ostream.h"
 #include "buffer.h"
 
 #include "sieve.h"
 
-static int _open_fd(const char *path)
-{
-	return open(path, O_RDONLY);
-}
-
 int main(int argc, char **argv) {
 	int fd;
 	struct sieve_binary *sbin;
@@ -27,7 +23,7 @@ int main(int argc, char **argv) {
  		exit(1);
  	}
   
-	if ( (fd = _open_fd(argv[1])) < 0 ) {
+	if ( (fd = open(argv[1], O_RDONLY)) < 0 ) {
 		perror("open()");
 		exit(1);
 	}
@@ -37,8 +33,14 @@ int main(int argc, char **argv) {
 	if ( sieve_init("") ) {
 		sbin = sieve_compile(fd, TRUE);
 	
-		if ( sbin != NULL ) 
-			(void) sieve_dump(sbin);
+		if ( sbin != NULL ) {
+			struct ostream *dumpstream = o_stream_create_fd(1, 0, FALSE);
+
+			if ( dumpstream != NULL ) {
+				(void) sieve_dump(sbin, dumpstream);
+				o_stream_unref(&dumpstream);
+			}
+		}
 
 		sieve_deinit();
 	} else {
-- 
GitLab