dte test coverage


Directory: ./
File: src/syntax/merge.c
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 60 62 96.8%
Functions: 4 4 100.0%
Branches: 23 28 82.1%

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