static bool ext_ihave_binary_open (const struct sieve_extension *ext, struct sieve_binary *sbin, void *context) { struct sieve_instance *svinst = ext->svinst; struct ext_ihave_binary_context *binctx = (struct ext_ihave_binary_context *) context; struct sieve_binary_block *sblock; unsigned int i, count, block_id; sieve_size_t offset; sblock = sieve_binary_extension_get_block(sbin, ext); if ( sblock != NULL ) { binctx->block = sblock; block_id = sieve_binary_block_get_id(sblock); offset = 0; /* Read number of missing extensions to read subsequently */ if ( !sieve_binary_read_unsigned(sblock, &offset, &count) ) { sieve_sys_error(svinst, "ihave: failed to read missing extension count " "from block %d of binary %s", block_id, sieve_binary_path(sbin)); return FALSE; } /* Read dependencies */ for ( i = 0; i < count; i++ ) { string_t *ext_name; const char *name; if ( !sieve_binary_read_string(sblock, &offset, &ext_name) ) { /* Binary is corrupt, recompile */ sieve_sys_error(svinst, "ihave: failed to read missing extension name " "from block %d of binary %s", block_id, sieve_binary_path(sbin)); return FALSE; } name = str_c(ext_name); array_append(&binctx->missing_extensions, &name, 1); } } return TRUE; }
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; }