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 int
9 parse_regs(const struct option *opt, const char *str, int unset)
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 
16 	if (unset)
17 		return 0;
18 
19 	/*
20 	 * cannot set it twice
21 	 */
22 	if (*mode)
23 		return -1;
24 
25 	/* str may be NULL in case no arg is passed to -I */
26 	if (str) {
27 		/* because str is read-only */
28 		s = os = strdup(str);
29 		if (!s)
30 			return -1;
31 
32 		for (;;) {
33 			p = strchr(s, ',');
34 			if (p)
35 				*p = '\0';
36 
37 			if (!strcmp(s, "?")) {
38 				fprintf(stderr, "available registers: ");
39 				for (r = sample_reg_masks; r->name; r++) {
40 					fprintf(stderr, "%s ", r->name);
41 				}
42 				fputc('\n', stderr);
43 				/* just printing available regs */
44 				return -1;
45 			}
46 			for (r = sample_reg_masks; r->name; r++) {
47 				if (!strcasecmp(s, r->name))
48 					break;
49 			}
50 			if (!r->name) {
51 				ui__warning("unknown register %s,"
52 					    " check man page\n", s);
53 				goto error;
54 			}
55 
56 			*mode |= r->mask;
57 
58 			if (!p)
59 				break;
60 
61 			s = p + 1;
62 		}
63 	}
64 	ret = 0;
65 
66 	/* default to all possible regs */
67 	if (*mode == 0)
68 		*mode = PERF_REGS_MASK;
69 error:
70 	free(os);
71 	return ret;
72 }
73