示例#1
0
static bool cmd_global_generate
(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd)
{
	struct sieve_ast_argument *arg = cmd->first_positional;

	sieve_operation_emit(cgenv->sblock, cmd->ext, &global_operation);

	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
		/* Single string */
		struct sieve_variable *var = (struct sieve_variable *) arg->argument->data;

		(void)sieve_binary_emit_unsigned(cgenv->sblock, 1);
		(void)sieve_binary_emit_unsigned(cgenv->sblock, var->index);

	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
		/* String list */
		struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg);

		(void)sieve_binary_emit_unsigned
			(cgenv->sblock, sieve_ast_strlist_count(arg));

		while ( stritem != NULL ) {
			struct sieve_variable *var =
				(struct sieve_variable *) stritem->argument->data;

			(void)sieve_binary_emit_unsigned(cgenv->sblock, var->index);

			stritem = sieve_ast_strlist_next(stritem);
		}
	} else {
		i_unreached();
	}

	return TRUE;
}
bool ext_include_variables_save
(struct sieve_binary_block *sblock,
	struct sieve_variable_scope_binary *global_vars)
{
	struct sieve_variable_scope *global_scope =
		sieve_variable_scope_binary_get(global_vars);
	unsigned int count = sieve_variable_scope_size(global_scope);
	sieve_size_t jump;

	sieve_binary_emit_unsigned(sblock, count);

	jump = sieve_binary_emit_offset(sblock, 0);

	if ( count > 0 ) {
		unsigned int size, i;
		struct sieve_variable *const *vars =
			sieve_variable_scope_get_variables(global_scope, &size);

		for ( i = 0; i < size; i++ ) {
			sieve_binary_emit_cstring(sblock, vars[i]->identifier);
		}
	}

	sieve_binary_resolve_offset(sblock, jump);

	return TRUE;
}
static bool ext_ihave_binary_save
(const struct sieve_extension *ext, struct sieve_binary *sbin, void *context)
{
	struct ext_ihave_binary_context *binctx =
		(struct ext_ihave_binary_context *) context;
	const char *const *exts;
	unsigned int count, i;

	exts = array_get(&binctx->missing_extensions, &count);

	if ( binctx->block != NULL )
		sieve_binary_block_clear(binctx->block);

	if ( count > 0 ) {
		if ( binctx->block == NULL )
			binctx->block = sieve_binary_extension_create_block(sbin, ext);

		sieve_binary_emit_unsigned(binctx->block, count);

		for ( i = 0; i < count; i++ ) {
			sieve_binary_emit_cstring(binctx->block, exts[i]);
		}
	}

	return TRUE;
}
示例#4
0
struct sieve_binary *sieve_generator_run
(struct sieve_generator *gentr, struct sieve_binary_block **sblock_r)
{
	bool topmost = ( sblock_r == NULL || *sblock_r == NULL );
	struct sieve_binary *sbin;
	struct sieve_binary_block *sblock, *debug_block;
	const struct sieve_extension *const *extensions;
	unsigned int i, ext_count;
	bool result = TRUE;

	/* Initialize */

	if ( topmost ) {
		sbin = sieve_binary_create_new(sieve_ast_script(gentr->genenv.ast));
		sblock = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM);
	} else {
		sblock = *sblock_r;
		sbin = sieve_binary_block_get_binary(sblock);
	}

	i_assert(sbin != NULL);

	sieve_binary_ref(sbin);
	gentr->genenv.sbin = sbin;
	gentr->genenv.sblock = sblock;

	/* Create debug block */
	debug_block = sieve_binary_block_create(sbin);
	gentr->dwriter = sieve_binary_debug_writer_init(debug_block);
	(void)sieve_binary_emit_unsigned
		(sblock, sieve_binary_block_get_id(debug_block));

	/* Load extensions linked to the AST and emit a list in code */
	extensions = sieve_ast_extensions_get(gentr->genenv.ast, &ext_count);
	(void) sieve_binary_emit_unsigned(sblock, ext_count);
	for ( i = 0; i < ext_count; i++ ) {
		const struct sieve_extension *ext = extensions[i];

		/* Link to binary */
		(void)sieve_binary_extension_link(sbin, ext);

		/* Emit */
		sieve_binary_emit_extension(sblock, ext, 0);

		/* Load */
		if ( ext->def != NULL && ext->def->generator_load != NULL &&
			!ext->def->generator_load(ext, &gentr->genenv) )
			result = FALSE;
	}

	/* Generate code */

	if ( result ) {
		if ( !sieve_generate_block
			(&gentr->genenv, sieve_ast_root(gentr->genenv.ast)))
			result = FALSE;
		else if ( topmost )
			sieve_binary_activate(sbin);
	}

	/* Cleanup */

	gentr->genenv.sbin = NULL;
	gentr->genenv.sblock = NULL;
	sieve_binary_unref(&sbin);

	if ( !result ) {
		if ( topmost ) {
			sieve_binary_unref(&sbin);
			if ( sblock_r != NULL )
				*sblock_r = NULL;
		}
		sbin = NULL;
	} else {
		if ( sblock_r != NULL )
			*sblock_r = sblock;
	}

	return sbin;
}
static bool _sieve_binary_save
(struct sieve_binary *sbin, struct ostream *stream)
{
	struct sieve_binary_header header;
	struct sieve_binary_extension_reg *const *regs;
	struct sieve_binary_block *ext_block;
	unsigned int ext_count, blk_count, i;
	uoff_t block_index;

	blk_count = sieve_binary_block_count(sbin);

	/* Signal all extensions to finish generating their blocks */

	regs = array_get(&sbin->extensions, &ext_count);
	for ( i = 0; i < ext_count; i++ ) {
		const struct sieve_binary_extension *binext = regs[i]->binext;

		if ( binext != NULL && binext->binary_save != NULL )
			binext->binary_save(regs[i]->extension, sbin, regs[i]->context);
	}

	/* Create header */

	header.magic = SIEVE_BINARY_MAGIC;
	header.version_major = SIEVE_BINARY_VERSION_MAJOR;
	header.version_minor = SIEVE_BINARY_VERSION_MINOR;
	header.blocks = blk_count;

	if ( !_save_aligned(sbin, stream, &header, sizeof(header), NULL) ) {
		sieve_sys_error(sbin->svinst, "binary save: failed to save header");
		return FALSE;
	}

	/* Skip block index for now */

	if ( !_save_skip_aligned(sbin, stream,
		sizeof(struct sieve_binary_block_index) * blk_count, &block_index) )
		return FALSE;

	/* Create block containing all used extensions */

	ext_block = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_EXTENSIONS);
	i_assert( ext_block != NULL );
	sieve_binary_block_clear(ext_block);

	ext_count = array_count(&sbin->linked_extensions);
	sieve_binary_emit_unsigned(ext_block, ext_count);

	for ( i = 0; i < ext_count; i++ ) {
		struct sieve_binary_extension_reg * const *ext
			= array_idx(&sbin->linked_extensions, i);

		sieve_binary_emit_cstring
			(ext_block, sieve_extension_name((*ext)->extension));
		sieve_binary_emit_unsigned
			(ext_block, sieve_extension_version((*ext)->extension));
		sieve_binary_emit_unsigned(ext_block, (*ext)->block_id);
	}

	/* Save all blocks into the binary */

	for ( i = 0; i < blk_count; i++ ) {
		if ( !_save_block(sbin, stream, i) )
			return FALSE;
	}

	/* Create the block index */
	o_stream_seek(stream, block_index);
	for ( i = 0; i < blk_count; i++ ) {
		if ( !_save_block_index_record(sbin, stream, i) )
			return FALSE;
	}

	return TRUE;
}