static bool cmd_filter_generate (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd) { sieve_operation_emit(cgenv->sblock, cmd->ext, &cmd_filter_operation); /* Emit is_test flag */ sieve_binary_emit_byte(cgenv->sblock, ( cmd->ast_node->type == SAT_TEST )); /* Generate arguments */ if ( !sieve_generate_arguments(cgenv, cmd, NULL) ) return FALSE; /* Emit a placeholder when the <arguments> argument is missing */ if ( sieve_ast_argument_next(cmd->first_positional) == NULL ) sieve_opr_omitted_emit(cgenv->sblock); return TRUE; }
bool sieve_generate_arguments (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, struct sieve_ast_argument **last_arg_r) { enum { ARG_START, ARG_OPTIONAL, ARG_POSITIONAL } state = ARG_START; struct sieve_ast_argument *arg = sieve_ast_argument_first(cmd->ast_node); /* Generate all arguments with assigned generator function */ while ( arg != NULL ) { const struct sieve_argument *argument; const struct sieve_argument_def *arg_def; if ( arg->argument == NULL || arg->argument->def == NULL ) return FALSE; argument = arg->argument; arg_def = argument->def; switch ( state ) { case ARG_START: if ( argument->id_code == 0 ) state = ARG_POSITIONAL; else { /* Mark start of optional operands with 0 operand identifier */ sieve_binary_emit_byte(cgenv->sblock, SIEVE_OPERAND_OPTIONAL); /* Emit argument id for optional operand */ sieve_binary_emit_byte (cgenv->sblock, (unsigned char) argument->id_code); state = ARG_OPTIONAL; } break; case ARG_OPTIONAL: if ( argument->id_code == 0 ) state = ARG_POSITIONAL; /* Emit argument id for optional operand (0 marks the end of the optionals) */ sieve_binary_emit_byte (cgenv->sblock, (unsigned char) argument->id_code); break; case ARG_POSITIONAL: if ( argument->id_code != 0 ) return FALSE; break; } /* Call the generation function for the argument */ if ( arg_def->generate != NULL ) { sieve_generate_debug_from_ast_argument(cgenv, arg); if ( !arg_def->generate(cgenv, arg, cmd) ) return FALSE; } else if ( state == ARG_POSITIONAL ) break; arg = sieve_ast_argument_next(arg); } /* Mark end of optional list if it is still open */ if ( state == ARG_OPTIONAL ) sieve_binary_emit_byte(cgenv->sblock, 0); if ( last_arg_r != NULL ) *last_arg_r = arg; return TRUE; }