[PATCH 03/11] perf, tools, list: Update perf list to output descriptions
From: Andi Kleen Add support to perf list to print aliases with descriptions. Support word wrapping for descriptions. Fix up the sorting code to put aliases with descriptions last. Signed-off-by: Andi Kleen --- tools/perf/util/pmu.c | 84 +-- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index f9c7046..baec090 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -737,11 +737,51 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, return buf; } -static int cmp_string(const void *a, const void *b) +struct pair { + char *name; + char *desc; +}; + +static int cmp_pair(const void *a, const void *b) +{ + const struct pair *as = a; + const struct pair *bs = b; + + /* Put downloaded event list last */ + if (!!as->desc != !!bs->desc) + return !!as->desc - !!bs->desc; + return strcmp(as->name, bs->name); +} + +static void wordwrap(char *s, int start, int max, int corr) +{ + int column = start; + int n; + + while (*s) { + int wlen = strcspn(s, " \t"); + + if (column + wlen >= max && column > start) { + printf("\n%*s", start, ""); + column = start + corr; + } + n = printf("%s%.*s", column > start ? " " : "", wlen, s); + if (n <= 0) + break; + s += wlen; + column += n; + while (isspace(*s)) + s++; + } +} + +static int get_columns(void) { - const char * const *as = a; - const char * const *bs = b; - return strcmp(*as, *bs); + /* +* Should ask the terminal with TIOCGWINSZ here, but we +* need the original fd before the pager. +*/ + return 79; } void print_pmu_events(const char *event_glob, bool name_only) @@ -751,21 +791,24 @@ void print_pmu_events(const char *event_glob, bool name_only) char buf[1024]; int printed = 0; int len, j; - char **aliases; + struct pair *aliases; + int numdesc = 0; + int columns = get_columns(); pmu = NULL; len = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) list_for_each_entry(alias, >aliases, list) len++; - aliases = malloc(sizeof(char *) * len); + aliases = malloc(sizeof(struct pair) * len); if (!aliases) return; pmu = NULL; j = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) list_for_each_entry(alias, >aliases, list) { - char *name = format_alias(buf, sizeof(buf), pmu, alias); + char *name = alias->desc ? alias->name : + format_alias(buf, sizeof(buf), pmu, alias); bool is_cpu = !strcmp(pmu->name, "cpu"); if (event_glob != NULL && @@ -773,22 +816,31 @@ void print_pmu_events(const char *event_glob, bool name_only) (!is_cpu && strglobmatch(alias->name, event_glob continue; - aliases[j] = name; - if (is_cpu && !name_only) - aliases[j] = format_alias_or(buf, sizeof(buf), - pmu, alias); - aliases[j] = strdup(aliases[j]); + aliases[j].name = name; + if (is_cpu && !name_only && !alias->desc) + aliases[j].name = format_alias_or(buf, + sizeof(buf), + pmu, alias); + aliases[j].name = strdup(aliases[j].name); + aliases[j].desc = alias->desc; j++; } len = j; - qsort(aliases, len, sizeof(char *), cmp_string); + qsort(aliases, len, sizeof(struct pair), cmp_pair); for (j = 0; j < len; j++) { if (name_only) { - printf("%s ", aliases[j]); + printf("%s ", aliases[j].name); continue; } - printf(" %-50s [Kernel PMU event]\n", aliases[j]); - zfree([j]); + if (aliases[j].desc) { + if (numdesc++ == 0 && printed) + printf("\n"); + printf(" %-50s [", aliases[j].name); + wordwrap(aliases[j].desc, 53, columns, 1); + printf("]\n"); + } else +
[PATCH 03/11] perf, tools, list: Update perf list to output descriptions
From: Andi Kleen a...@linux.intel.com Add support to perf list to print aliases with descriptions. Support word wrapping for descriptions. Fix up the sorting code to put aliases with descriptions last. Signed-off-by: Andi Kleen a...@linux.intel.com --- tools/perf/util/pmu.c | 84 +-- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index f9c7046..baec090 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -737,11 +737,51 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, return buf; } -static int cmp_string(const void *a, const void *b) +struct pair { + char *name; + char *desc; +}; + +static int cmp_pair(const void *a, const void *b) +{ + const struct pair *as = a; + const struct pair *bs = b; + + /* Put downloaded event list last */ + if (!!as-desc != !!bs-desc) + return !!as-desc - !!bs-desc; + return strcmp(as-name, bs-name); +} + +static void wordwrap(char *s, int start, int max, int corr) +{ + int column = start; + int n; + + while (*s) { + int wlen = strcspn(s, \t); + + if (column + wlen = max column start) { + printf(\n%*s, start, ); + column = start + corr; + } + n = printf(%s%.*s, column start ? : , wlen, s); + if (n = 0) + break; + s += wlen; + column += n; + while (isspace(*s)) + s++; + } +} + +static int get_columns(void) { - const char * const *as = a; - const char * const *bs = b; - return strcmp(*as, *bs); + /* +* Should ask the terminal with TIOCGWINSZ here, but we +* need the original fd before the pager. +*/ + return 79; } void print_pmu_events(const char *event_glob, bool name_only) @@ -751,21 +791,24 @@ void print_pmu_events(const char *event_glob, bool name_only) char buf[1024]; int printed = 0; int len, j; - char **aliases; + struct pair *aliases; + int numdesc = 0; + int columns = get_columns(); pmu = NULL; len = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) list_for_each_entry(alias, pmu-aliases, list) len++; - aliases = malloc(sizeof(char *) * len); + aliases = malloc(sizeof(struct pair) * len); if (!aliases) return; pmu = NULL; j = 0; while ((pmu = perf_pmu__scan(pmu)) != NULL) list_for_each_entry(alias, pmu-aliases, list) { - char *name = format_alias(buf, sizeof(buf), pmu, alias); + char *name = alias-desc ? alias-name : + format_alias(buf, sizeof(buf), pmu, alias); bool is_cpu = !strcmp(pmu-name, cpu); if (event_glob != NULL @@ -773,22 +816,31 @@ void print_pmu_events(const char *event_glob, bool name_only) (!is_cpu strglobmatch(alias-name, event_glob continue; - aliases[j] = name; - if (is_cpu !name_only) - aliases[j] = format_alias_or(buf, sizeof(buf), - pmu, alias); - aliases[j] = strdup(aliases[j]); + aliases[j].name = name; + if (is_cpu !name_only !alias-desc) + aliases[j].name = format_alias_or(buf, + sizeof(buf), + pmu, alias); + aliases[j].name = strdup(aliases[j].name); + aliases[j].desc = alias-desc; j++; } len = j; - qsort(aliases, len, sizeof(char *), cmp_string); + qsort(aliases, len, sizeof(struct pair), cmp_pair); for (j = 0; j len; j++) { if (name_only) { - printf(%s , aliases[j]); + printf(%s , aliases[j].name); continue; } - printf( %-50s [Kernel PMU event]\n, aliases[j]); - zfree(aliases[j]); + if (aliases[j].desc) { + if (numdesc++ == 0 printed) + printf(\n); + printf( %-50s [, aliases[j].name); + wordwrap(aliases[j].desc, 53, columns, 1); + printf(]\n); + } else +