dte test coverage


Directory: ./
File: src/command/run.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 66 66 100.0%
Functions: 3 3 100.0%
Branches: 31 32 96.9%

Line Branch Exec Source
1 #include "run.h"
2 #include "args.h"
3 #include "parse.h"
4 #include "change.h"
5 #include "util/debug.h"
6 #include "util/ptr-array.h"
7 #include "util/xmalloc.h"
8
9 static bool run_commands(CommandRunner *runner, const PointerArray *array);
10
11 // NOLINTNEXTLINE(misc-no-recursion)
12 6588 static bool run_command(CommandRunner *runner, char **av)
13 {
14 6588 const CommandSet *cmds = runner->cmds;
15 6588 const Command *cmd = cmds->lookup(av[0]);
16 6588 struct EditorState *e = runner->e;
17 6588 ErrorBuffer *ebuf = runner->ebuf;
18
19
2/2
✓ Branch 0 (3→4) taken 32 times.
✓ Branch 1 (3→24) taken 6556 times.
6588 if (!cmd) {
20 32 const char *name = av[0];
21
2/2
✓ Branch 0 (4→5) taken 1 times.
✓ Branch 1 (4→6) taken 31 times.
32 if (!runner->lookup_alias) {
22 1 return error_msg_for_cmd(ebuf, NULL, "No such command: %s", name);
23 }
24
25 31 const char *alias_value = runner->lookup_alias(e, name);
26
2/2
✓ Branch 0 (7→8) taken 1 times.
✓ Branch 1 (7→9) taken 30 times.
31 if (unlikely(!alias_value)) {
27 1 return error_msg_for_cmd(ebuf, NULL, "No such command or alias: %s", name);
28 }
29
30 30 PointerArray array = PTR_ARRAY_INIT;
31 30 CommandParseError err = parse_commands(runner, &array, alias_value);
32
2/2
✓ Branch 0 (10→11) taken 1 times.
✓ Branch 1 (10→14) taken 29 times.
30 if (unlikely(err != CMDERR_NONE)) {
33 1 const char *err_msg = command_parse_error_to_string(err);
34 1 ptr_array_free(&array);
35 1 return error_msg_for_cmd(ebuf, NULL, "Parsing alias %s: %s", name, err_msg);
36 }
37
38 // Remove NULL
39 29 array.count--;
40
41
2/2
✓ Branch 0 (18→15) taken 35 times.
✓ Branch 1 (18→19) taken 29 times.
64 for (size_t i = 1; av[i]; i++) {
42 35 ptr_array_append(&array, xstrdup(av[i]));
43 }
44 29 ptr_array_append(&array, NULL);
45
46 29 bool r = run_commands(runner, &array);
47 29 ptr_array_free(&array);
48 29 return r;
49 }
50
51
4/4
✓ Branch 0 (24→25) taken 5954 times.
✓ Branch 1 (24→27) taken 602 times.
✓ Branch 2 (25→26) taken 1 times.
✓ Branch 3 (25→27) taken 5953 times.
6556 if (unlikely(ebuf->config_filename && !(cmd->cmdopts & CMDOPT_ALLOW_IN_RC))) {
52 1 return error_msg_for_cmd(ebuf, NULL, "Command %s not allowed in config file", cmd->name);
53 }
54
55 // Record command in macro buffer, if recording (this needs to be done
56 // before parse_args() mutates the array)
57
3/4
✓ Branch 0 (27→28) taken 5 times.
✓ Branch 1 (27→30) taken 6550 times.
✓ Branch 2 (28→29) taken 5 times.
✗ Branch 3 (28→30) not taken.
6555 if (runner->allow_recording && runner->cmds->macro_record) {
58 5 runner->cmds->macro_record(e, cmd, av + 1);
59 }
60
61 // By default change can't be merged with previous one.
62 // Any command can override this by calling begin_change() again.
63 6555 begin_change(CHANGE_MERGE_NONE);
64
65 6555 CommandArgs a = cmdargs_new(av + 1);
66
4/4
✓ Branch 0 (32→33) taken 6548 times.
✓ Branch 1 (32→36) taken 7 times.
✓ Branch 2 (34→35) taken 126 times.
✓ Branch 3 (34→36) taken 6422 times.
6555 bool r = likely(parse_args(cmd, &a, ebuf)) && command_func_call(e, ebuf, cmd, &a);
67
68 6555 end_change();
69 6555 return r;
70 }
71
72 // NOLINTNEXTLINE(misc-no-recursion)
73 7900 static bool run_commands(CommandRunner *runner, const PointerArray *array)
74 {
75
2/2
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→4) taken 7899 times.
7900 if (unlikely(runner->recursion_count > 16)) {
76 1 return error_msg_for_cmd(runner->ebuf, NULL, "alias recursion limit reached");
77 }
78
79 7899 void **ptrs = array->ptrs;
80 7899 size_t len = array->count;
81 7899 size_t nfailed = 0;
82 7899 BUG_ON(len == 0);
83 7899 BUG_ON(ptrs[len - 1] != NULL);
84 7899 runner->recursion_count++;
85
86
2/2
✓ Branch 0 (17→11) taken 7958 times.
✓ Branch 1 (17→18) taken 7899 times.
15857 for (size_t s = 0, e = 0; s < len; ) {
87 // Iterate over strings, until a terminating NULL is encountered
88 31078 while (ptrs[e]) {
89 23120 e++;
90 31078 BUG_ON(e >= len);
91 }
92
93 // If the value of `e` (end) changed, there's a run of at least
94 // 1 string, which is a command followed by 0 or more arguments
95
2/2
✓ Branch 0 (12→13) taken 6588 times.
✓ Branch 1 (12→16) taken 1370 times.
7958 if (e != s) {
96
2/2
✓ Branch 0 (14→15) taken 154 times.
✓ Branch 1 (14→16) taken 6434 times.
6588 if (!run_command(runner, (char**)ptrs + s)) {
97 154 nfailed++;
98 }
99 }
100
101 // Skip past the NULL, onto the next command (if any)
102 7958 s = ++e;
103 }
104
105 7899 runner->recursion_count--;
106 7899 return (nfailed == 0);
107 }
108
109 7876 bool handle_command(CommandRunner *runner, const char *cmd)
110 {
111 7876 BUG_ON(runner->recursion_count != 0);
112 7876 PointerArray array = PTR_ARRAY_INIT;
113 7876 CommandParseError err = parse_commands(runner, &array, cmd);
114 7876 bool r;
115
2/2
✓ Branch 0 (5→6) taken 7871 times.
✓ Branch 1 (5→9) taken 5 times.
7876 if (likely(err == CMDERR_NONE)) {
116 7871 r = run_commands(runner, &array);
117 7871 BUG_ON(runner->recursion_count != 0);
118 } else {
119 5 const char *str = command_parse_error_to_string(err);
120 5 error_msg_for_cmd(runner->ebuf, NULL, "Command syntax error: %s", str);
121 5 r = false;
122 }
123 7876 ptr_array_free(&array);
124 7876 return r;
125 }
126