Line | Branch | Exec | Source |
---|---|---|---|
1 | #include <stdlib.h> | ||
2 | #include <string.h> | ||
3 | #include "cache.h" | ||
4 | #include "args.h" | ||
5 | #include "parse.h" | ||
6 | #include "trace.h" | ||
7 | #include "util/log.h" | ||
8 | #include "util/ptr-array.h" | ||
9 | #include "util/str-array.h" | ||
10 | #include "util/xmalloc.h" | ||
11 | |||
12 | // Takes a command string and returns a struct containing the resolved | ||
13 | // Command and pre-parsed arguments, or a NULL Command if uncacheable. | ||
14 | // In both cases, CachedCommand::cmd_str is filled with a copy of the | ||
15 | // original string. This caching is done to allow handle_binding() to | ||
16 | // avoid repeated parsing/allocation each time a key binding is used. | ||
17 | 1385 | CachedCommand *cached_command_new(const CommandRunner *runner, const char *cmd_str) | |
18 | { | ||
19 | 1385 | const size_t cmd_str_len = strlen(cmd_str); | |
20 | 1385 | CachedCommand *cached = xmalloc(sizeof(*cached) + cmd_str_len + 1); | |
21 | 1385 | memcpy(cached->cmd_str, cmd_str, cmd_str_len + 1); | |
22 | |||
23 | 1385 | const char *reason; | |
24 | 1385 | PointerArray array = PTR_ARRAY_INIT; | |
25 |
2/2✓ Branch 0 (4→5) taken 3 times.
✓ Branch 1 (4→6) taken 1382 times.
|
1385 | if (parse_commands(runner, &array, cmd_str) != CMDERR_NONE) { |
26 | 3 | reason = "parsing failed"; | |
27 | 3 | goto nocache; | |
28 | } | ||
29 | |||
30 | 1382 | ptr_array_trim_nulls(&array); | |
31 | 1382 | size_t n = array.count; | |
32 |
4/4✓ Branch 0 (7→8) taken 1381 times.
✓ Branch 1 (7→10) taken 1 times.
✓ Branch 2 (9→10) taken 1 times.
✓ Branch 3 (9→11) taken 1380 times.
|
1382 | if (n < 2 || ptr_array_xindex(&array, NULL) != n - 1) { |
33 | 2 | reason = "multiple commands"; | |
34 | 2 | goto nocache; | |
35 | } | ||
36 | |||
37 | 1380 | const Command *cmd = runner->cmds->lookup(array.ptrs[0]); | |
38 |
2/2✓ Branch 0 (12→13) taken 8 times.
✓ Branch 1 (12→14) taken 1372 times.
|
1380 | if (!cmd) { |
39 | // Aliases and non-existent commands can't be cached, because the | ||
40 | // command they expand to could later be invalidated by cmd_alias(). | ||
41 | 8 | reason = "contains aliases"; | |
42 | 8 | goto nocache; | |
43 | } | ||
44 | |||
45 | // TODO: Make this condition more precise | ||
46 |
2/2✓ Branch 0 (14→15) taken 1 times.
✓ Branch 1 (14→16) taken 1371 times.
|
1372 | if (memchr(cmd_str, '$', cmd_str_len)) { |
47 | 1 | reason = "may contain variables"; | |
48 | 1 | goto nocache; | |
49 | } | ||
50 | |||
51 | 1371 | free(ptr_array_remove_index(&array, 0)); | |
52 | 1371 | CommandArgs cmdargs = cmdargs_new((char**)array.ptrs); | |
53 |
2/2✓ Branch 0 (18→19) taken 3 times.
✓ Branch 1 (18→20) taken 1368 times.
|
1371 | if (do_parse_args(cmd, &cmdargs) != ARGERR_NONE) { |
54 | 3 | reason = "argument parsing failed"; | |
55 | 3 | goto nocache; | |
56 | } | ||
57 | |||
58 | // Command can be cached; cache takes ownership of args array | ||
59 | 1368 | cached->cmd = cmd; | |
60 | 1368 | cached->a = cmdargs; | |
61 | 1368 | return cached; | |
62 | |||
63 | 17 | nocache: | |
64 | 17 | TRACE_CMD("skipping command cache (%s): %s", reason, cmd_str); | |
65 | 17 | ptr_array_free(&array); | |
66 | 17 | cached->cmd = NULL; | |
67 | 17 | return cached; | |
68 | } | ||
69 | |||
70 | 2760 | void cached_command_free(CachedCommand *cc) | |
71 | { | ||
72 |
2/2✓ Branch 0 (2→3) taken 1385 times.
✓ Branch 1 (2→6) taken 1375 times.
|
2760 | if (!cc) { |
73 | return; | ||
74 | } | ||
75 |
2/2✓ Branch 0 (3→4) taken 1368 times.
✓ Branch 1 (3→5) taken 17 times.
|
1385 | if (cc->cmd) { |
76 | 1368 | free_string_array(cc->a.args); | |
77 | } | ||
78 | 1385 | free(cc); | |
79 | } | ||
80 |