]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-var-expand: Extract var_expand_program_execute_one_real()
authorAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 29 Jan 2026 09:18:58 +0000 (11:18 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 20 Mar 2026 16:11:43 +0000 (16:11 +0000)
Executes one expansion program.

src/lib-var-expand/expansion-program.c
src/lib-var-expand/test-var-expand.c

index b6de8fd0a6408fb924817b51fc3fb7bf69dd0696..0eb63d76e479ff174366a5e6c3530ed954381b5a 100644 (file)
@@ -123,6 +123,49 @@ static void prepare_state(const struct var_expand_params *params,
        state_r->transfer = str_new(default_pool, 32);
 }
 
+static int
+var_expand_program_execute_one_real(const struct var_expand_program *program,
+                                   const struct var_expand_params *params,
+                                   struct var_expand_state *state,
+                                   const char **error_r)
+{
+       int ret = 0;
+       const struct var_expand_statement *stmt = program->first;
+       if (stmt == NULL) {
+               /* skip empty programs */
+               program = program->next;
+               return 0;
+       }
+       T_BEGIN {
+               while (stmt != NULL) {
+                       bool first = stmt == program->first;
+                       if (!var_expand_execute_stmt(state, stmt,
+                                                    first, error_r)) {
+                               ret = -1;
+                               break;
+                       }
+                       stmt = stmt->next;
+               }
+       } T_END_PASS_STR_IF(ret < 0, error_r);
+       if (ret < 0)
+               return ret;
+       if (state->transfer_binary)
+               var_expand_state_set_transfer(state,
+                               binary_to_hex(state->transfer->data, state->transfer->used));
+       if (state->transfer_set) {
+               if (!program->only_literal && params->escape_func != NULL) {
+                       str_append(state->result, params->escape_func(str_c(state->transfer),
+                                                                     params->escape_context));
+                       } else
+                               str_append_str(state->result, state->transfer);
+       } else {
+               *error_r = t_strdup(state->delayed_error);
+               ret = -1;
+       }
+       var_expand_state_unset_transfer(state);
+       return ret;
+}
+
 int var_expand_program_execute(string_t *dest, const struct var_expand_program *program,
                               const struct var_expand_params *params, const char **error_r)
  {
@@ -135,40 +178,9 @@ int var_expand_program_execute(string_t *dest, const struct var_expand_program *
        *error_r = NULL;
 
        while (program != NULL) {
-               const struct var_expand_statement *stmt = program->first;
-               if (stmt == NULL) {
-                       /* skip empty programs */
-                       program = program->next;
-                       continue;
-               }
-               T_BEGIN {
-                       while (stmt != NULL) {
-                               bool first = stmt == program->first;
-                               if (!var_expand_execute_stmt(&state, stmt,
-                                                            first, error_r)) {
-                                       ret = -1;
-                                       break;
-                               }
-                               stmt = stmt->next;
-                       }
-               } T_END_PASS_STR_IF(ret < 0, error_r);
-               if (ret < 0)
-                       break;
-               if (state.transfer_binary)
-                       var_expand_state_set_transfer(&state, binary_to_hex(state.transfer->data, state.transfer->used));
-               if (state.transfer_set) {
-                       if (!program->only_literal && params->escape_func != NULL) {
-                               str_append(state.result,
-                                          params->escape_func(str_c(state.transfer),
-                                                              params->escape_context));
-                       } else
-                               str_append_str(state.result, state.transfer);
-               } else {
-                       *error_r = t_strdup(state.delayed_error);
-                       ret = -1;
+               ret = var_expand_program_execute_one_real(program, params, &state, error_r);
+               if (ret == -1)
                        break;
-               }
-               var_expand_state_unset_transfer(&state);
                program = program->next;
        };
        str_free(&state.transfer);
index 0ca8ff7a7c6ee52a8b5af4d034690811402689bc..a3ddf82bb773db08bd1414d9595d36b51117a10a 100644 (file)
@@ -298,6 +298,10 @@ static void test_var_expand_math(void) {
                { .in = "%{port % 5}", .out = "3", .ret = 0 },
                { .in = "%{port / 0}", .out = "calculate: Division by zero", .ret = -1 },
                { .in = "%{port % 0}", .out = "calculate: Modulo by zero", .ret = -1 },
+               /* multiple programs, first fails */
+               { .in = "%{failure} %{port}", .out = "Unknown variable 'failure'", .ret = -1 },
+               /* second fails */
+               { .in = "%{port} %{failure}", .out = "Unknown variable 'failure'", .ret = -1 },
        };
 
        const struct var_expand_params params = {