Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / tools / perf / util / parse-regs-options.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include "perf.h"
3 #include "util/util.h"
4 #include "util/debug.h"
5 #include <subcmd/parse-options.h>
6 #include "util/parse-regs-options.h"
7
8 static int
9 __parse_regs(const struct option *opt, const char *str, int unset, bool intr)
10 {
11         uint64_t *mode = (uint64_t *)opt->value;
12         const struct sample_reg *r;
13         char *s, *os = NULL, *p;
14         int ret = -1;
15         uint64_t mask;
16
17         if (unset)
18                 return 0;
19
20         /*
21          * cannot set it twice
22          */
23         if (*mode)
24                 return -1;
25
26         if (intr)
27                 mask = arch__intr_reg_mask();
28         else
29                 mask = arch__user_reg_mask();
30
31         /* str may be NULL in case no arg is passed to -I */
32         if (str) {
33                 /* because str is read-only */
34                 s = os = strdup(str);
35                 if (!s)
36                         return -1;
37
38                 for (;;) {
39                         p = strchr(s, ',');
40                         if (p)
41                                 *p = '\0';
42
43                         if (!strcmp(s, "?")) {
44                                 fprintf(stderr, "available registers: ");
45                                 for (r = sample_reg_masks; r->name; r++) {
46                                         if (r->mask & mask)
47                                                 fprintf(stderr, "%s ", r->name);
48                                 }
49                                 fputc('\n', stderr);
50                                 /* just printing available regs */
51                                 return -1;
52                         }
53                         for (r = sample_reg_masks; r->name; r++) {
54                                 if ((r->mask & mask) && !strcasecmp(s, r->name))
55                                         break;
56                         }
57                         if (!r->name) {
58                                 ui__warning("Unknown register \"%s\", check man page or run \"perf record %s?\"\n",
59                                             s, intr ? "-I" : "--user-regs=");
60                                 goto error;
61                         }
62
63                         *mode |= r->mask;
64
65                         if (!p)
66                                 break;
67
68                         s = p + 1;
69                 }
70         }
71         ret = 0;
72
73         /* default to all possible regs */
74         if (*mode == 0)
75                 *mode = mask;
76 error:
77         free(os);
78         return ret;
79 }
80
81 int
82 parse_user_regs(const struct option *opt, const char *str, int unset)
83 {
84         return __parse_regs(opt, str, unset, false);
85 }
86
87 int
88 parse_intr_regs(const struct option *opt, const char *str, int unset)
89 {
90         return __parse_regs(opt, str, unset, true);
91 }