dte test coverage


Directory: ./
File: src/syntax/merge.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 57 59 96.6%
Functions: 4 4 100.0%
Branches: 21 26 80.8%

Line Branch Exec Source
1 #include <errno.h>
2 #include <stdbool.h>
3 #include <string.h>
4 #include "merge.h"
5 #include "util/debug.h"
6 #include "util/hashmap.h"
7 #include "util/string-view.h"
8 #include "util/xmalloc.h"
9 #include "util/xsnprintf.h"
10
11 enum {
12 FIXBUF_SIZE = 512
13 };
14
15 4331 static const char *fix_name(char *buf, StringView prefix, const char *name)
16 {
17 4331 size_t plen = prefix.length;
18 4331 BUG_ON(plen >= FIXBUF_SIZE);
19 4331 memcpy(buf, prefix.data, plen);
20 4331 char *end = memccpy(buf + plen, name, '\0', FIXBUF_SIZE - plen);
21
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→7) taken 4331 times.
4331 if (unlikely(!end)) {
22 fatal_error(__func__, ENOBUFS);
23 }
24 4331 return buf;
25 }
26
27 3577 static void fix_action(const Syntax *syn, Action *a, StringView prefix, char *buf)
28 {
29
2/2
✓ Branch 0 (2→3) taken 2779 times.
✓ Branch 1 (2→6) taken 798 times.
3577 if (a->destination) {
30 2779 const char *name = fix_name(buf, prefix, a->destination->name);
31 2779 a->destination = find_state(syn, name);
32 }
33 3577 }
34
35 1383 static void fix_conditions (
36 const Syntax *syn,
37 State *s,
38 const SyntaxMerge *m,
39 StringView prefix,
40 char *buf
41 ) {
42
2/2
✓ Branch 0 (11→3) taken 2194 times.
✓ Branch 1 (11→12) taken 1383 times.
3577 for (size_t i = 0, n = s->conds.count; i < n; i++) {
43 2194 Condition *c = s->conds.ptrs[i];
44 2194 fix_action(syn, &c->a, prefix, buf);
45
4/4
✓ Branch 0 (4→5) taken 405 times.
✓ Branch 1 (4→7) taken 1789 times.
✓ Branch 2 (5→6) taken 318 times.
✓ Branch 3 (5→7) taken 87 times.
2194 if (!c->a.destination && cond_type_has_destination(c->type)) {
46 318 c->a.destination = m->return_state;
47 }
48
1/4
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→10) taken 2194 times.
✗ Branch 2 (8→9) not taken.
✗ Branch 3 (8→10) not taken.
2194 if (m->delim && c->type == COND_HEREDOCEND) {
49 c->u.heredocend = string_view(m->delim, m->delim_len);
50 }
51 }
52
53 1383 fix_action(syn, &s->default_action, prefix, buf);
54
2/2
✓ Branch 0 (13→14) taken 393 times.
✓ Branch 1 (13→15) taken 990 times.
1383 if (!s->default_action.destination) {
55 393 s->default_action.destination = m->return_state;
56 }
57 1383 }
58
59 // Merge a sub-syntax into another syntax, copying or updating
60 // pointers and strings as appropriate.
61 // NOTE: string_lists is owned by Syntax, so there's no need to
62 // copy it. Freeing Condition does not free any string lists.
63 169 State *merge_syntax(Syntax *syn, SyntaxMerge *merge, const StyleMap *styles)
64 {
65 // Generate a prefix for merged state names, to avoid clashes
66 169 static unsigned int counter;
67 169 char prefix_buf[DECIMAL_STR_MAX(counter) + 2];
68 169 size_t prefix_len = xsnprintf(prefix_buf, sizeof prefix_buf, "m%u-", counter++);
69 169 StringView prefix = string_view(prefix_buf, prefix_len);
70
71 169 const HashMap *subsyn_states = &merge->subsyn->states;
72 169 HashMap *states = &syn->states;
73 169 char buf[FIXBUF_SIZE];
74
75
2/2
✓ Branch 0 (20→4) taken 1383 times.
✓ Branch 1 (20→21) taken 169 times.
1552 for (HashMapIter it = hashmap_iter(subsyn_states); hashmap_next(&it); ) {
76 1383 State *s = xmemdup(it.entry->value, sizeof(State));
77 1383 s->name = xstrjoin(prefix_buf, s->name);
78 1383 hashmap_insert(states, s->name, s);
79
80
2/2
✓ Branch 0 (7→8) taken 1363 times.
✓ Branch 1 (7→16) taken 20 times.
1383 if (s->conds.count > 0) {
81 // Deep copy conds PointerArray
82 1363 BUG_ON(s->conds.alloc < s->conds.count);
83 1363 void **ptrs = xnew(void*, s->conds.alloc);
84
2/2
✓ Branch 0 (14→12) taken 2194 times.
✓ Branch 1 (14→15) taken 1363 times.
3557 for (size_t i = 0, n = s->conds.count; i < n; i++) {
85 2194 ptrs[i] = xmemdup(s->conds.ptrs[i], sizeof(Condition));
86 }
87 1363 s->conds.ptrs = ptrs;
88 } else {
89 20 BUG_ON(s->conds.alloc != 0);
90 }
91
92 // Mark unvisited, so that return-only states get visited
93 1383 s->visited = false;
94
95 // Don't complain about unvisited, copied states
96 1383 s->copied = true;
97 }
98
99 // Fix conditions and update styles for newly merged states
100
2/2
✓ Branch 0 (33→22) taken 1383 times.
✓ Branch 1 (33→34) taken 169 times.
1721 for (HashMapIter it = hashmap_iter(subsyn_states); hashmap_next(&it); ) {
101 1383 const State *subsyn_state = it.entry->value;
102 1383 BUG_ON(!subsyn_state);
103 1383 const char *new_name = fix_name(buf, prefix, subsyn_state->name);
104 1383 State *new_state = hashmap_get(states, new_name);
105 1383 BUG_ON(!new_state);
106 1383 fix_conditions(syn, new_state, merge, prefix, buf);
107
1/2
✗ Branch 0 (29→30) not taken.
✓ Branch 1 (29→32) taken 1383 times.
1383 if (merge->delim) {
108 update_state_styles(syn, new_state, styles);
109 }
110 }
111
112 169 const char *name = fix_name(buf, prefix, merge->subsyn->start_state->name);
113 169 State *start_state = hashmap_get(states, name);
114 169 BUG_ON(!start_state);
115 169 merge->subsyn->used = true;
116 169 return start_state;
117 }
118