Coverage Report

Created: 2026-04-27 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pigeonhole/src/lib-sieve/tst-allof.c
Line
Count
Source
1
/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
2
 */
3
4
#include "sieve-common.h"
5
#include "sieve-commands.h"
6
#include "sieve-validator.h"
7
#include "sieve-generator.h"
8
#include "sieve-binary.h"
9
#include "sieve-code.h"
10
#include "sieve-binary.h"
11
12
/*
13
 * Allof test
14
 *
15
 * Syntax
16
 *   allof <tests: test-list>
17
 */
18
19
static bool tst_allof_generate
20
  (const struct sieve_codegen_env *cgenv, struct sieve_command *ctx,
21
    struct sieve_jumplist *jumps, bool jump_true);
22
static bool tst_allof_validate_const
23
  (struct sieve_validator *valdtr, struct sieve_command *tst,
24
    int *const_current, int const_new);
25
26
const struct sieve_command_def tst_allof = {
27
  .identifier = "allof",
28
  .type = SCT_TEST,
29
  .positional_args = 0,
30
  .subtests = 2,
31
  .block_allowed = FALSE,
32
  .block_required = FALSE,
33
  .validate_const = tst_allof_validate_const,
34
  .control_generate = tst_allof_generate
35
};
36
37
/*
38
 * Code validation
39
 */
40
41
static bool tst_allof_validate_const
42
(struct sieve_validator *valdtr ATTR_UNUSED,
43
  struct sieve_command *tst ATTR_UNUSED, int *const_current, int const_next)
44
0
{
45
0
  if ( const_next == 0 ) {
46
0
    *const_current = 0;
47
0
    return FALSE;
48
0
  }
49
50
0
  if ( *const_current != -1 )
51
0
    *const_current = const_next;
52
0
  return TRUE;
53
0
}
54
55
/*
56
 * Code generation
57
 */
58
59
static bool tst_allof_generate
60
(const struct sieve_codegen_env *cgenv, struct sieve_command *ctx,
61
  struct sieve_jumplist *jumps, bool jump_true)
62
0
{
63
0
  struct sieve_binary_block *sblock = cgenv->sblock;
64
0
  struct sieve_ast_node *test;
65
0
  struct sieve_jumplist false_jumps;
66
67
0
  if ( sieve_ast_test_count(ctx->ast_node) > 1 ) {
68
0
    if ( jump_true ) {
69
      /* Prepare jumplist */
70
0
      sieve_jumplist_init_temp(&false_jumps, sblock);
71
0
    }
72
73
0
    test = sieve_ast_test_first(ctx->ast_node);
74
0
    while ( test != NULL ) {
75
0
      bool result;
76
77
      /* If this test list must jump on false, all sub-tests can simply add their jumps
78
       * to the caller's jump list, otherwise this test redirects all false jumps to the
79
       * end of the currently generated code. This is just after a final jump to the true
80
       * case
81
       */
82
0
      if ( jump_true )
83
0
        result = sieve_generate_test(cgenv, test, &false_jumps, FALSE);
84
0
      else
85
0
        result = sieve_generate_test(cgenv, test, jumps, FALSE);
86
87
0
      if ( !result ) return FALSE;
88
89
0
      test = sieve_ast_test_next(test);
90
0
    }
91
92
0
    if ( jump_true ) {
93
      /* All tests succeeded, jump to case TRUE */
94
0
      sieve_operation_emit(cgenv->sblock, NULL, &sieve_jmp_operation);
95
0
      sieve_jumplist_add(jumps, sieve_binary_emit_offset(sblock, 0));
96
97
      /* All false exits jump here */
98
0
      sieve_jumplist_resolve(&false_jumps);
99
0
    }
100
0
  } else {
101
    /* Script author is being inefficient; we can optimize the allof test away */
102
0
    test = sieve_ast_test_first(ctx->ast_node);
103
0
    sieve_generate_test(cgenv, test, jumps, jump_true);
104
0
  }
105
106
0
  return TRUE;
107
0
}
108