| /** |
| * @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 <ctype.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; |
| if (!isdigit(*part)) |
| parsed_events[i].unit_mask_name = part; |
| else { |
| 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; |
| } |