aboutsummaryrefslogtreecommitdiff
path: root/libop/op_parse_event.c
blob: eb99a205b8def51b7fb89bbcc83a989120ca4c02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
 * @file op_parse_event.c
 * event parsing
 *
 * You can have silliness here.
 *
 * @remark Copyright 2002 OProfile authors
 * @remark Read the file COPYING
 *
 * @author John Levon
 * @author Philippe Elie
 */

#include <stdio.h>
#include <stdlib.h>

#include "op_parse_event.h"
#include "op_string.h"

static char * next_part(char const ** str)
{
	char const * c;
	char * ret;

	if ((*str)[0] == '\0')
		return NULL;

	if ((*str)[0] == ':')
		++(*str);

	c = *str;

	while (*c != '\0' && *c != ':')
		++c;

	if (c == *str)
		return NULL;

	ret = op_xstrndup(*str, c - *str);
	*str += c - *str;
	return ret;
}


static int parse_ulong(char const * str)
{
	unsigned long value;
	char * end;
	value = strtoul(str, &end, 0);
	if (end && *end) {
		fprintf(stderr, "Invalid event part %s\n", str);
		exit(EXIT_FAILURE);
	}

	return value;
}


size_t parse_events(struct parsed_event * parsed_events, size_t max_events,
                  char const * const * events)
{
	size_t i = 0;

	while (events[i]) {
		char const * cp = events[i];
		char * part = next_part(&cp);

		if (i >= max_events) {
			fprintf(stderr, "Too many events specified: CPU "
			        "only has %lu counters.\n",
				(unsigned long) max_events);
			exit(EXIT_FAILURE);
		}

		if (!part) {
			fprintf(stderr, "Invalid event %s\n", cp);
			exit(EXIT_FAILURE);
		}

		parsed_events[i].name = part;

		part = next_part(&cp);

		if (!part) {
			fprintf(stderr, "Invalid count for event %s\n", events[i]);
			exit(EXIT_FAILURE);
		}

		parsed_events[i].count = parse_ulong(part);
		free(part);

		parsed_events[i].unit_mask = 0;
		part = next_part(&cp);

		if (part) {
			parsed_events[i].unit_mask_valid = 1;
			parsed_events[i].unit_mask = parse_ulong(part);
			free(part);
		}

		parsed_events[i].kernel = 1;
		part = next_part(&cp);

		if (part) {
			parsed_events[i].kernel = parse_ulong(part);
			free(part);
		}

		parsed_events[i].user = 1;
		part = next_part(&cp);

		if (part) {
			parsed_events[i].user = parse_ulong(part);
			free(part);
		}
	
		++i;
	}

	return i;
}