2009-06-02 09:31:03 +08:00
|
|
|
#include "string.h"
|
2009-11-15 19:36:53 +08:00
|
|
|
#include "util.h"
|
2009-06-02 09:31:03 +08:00
|
|
|
|
|
|
|
static int hex(char ch)
|
|
|
|
{
|
|
|
|
if ((ch >= '0') && (ch <= '9'))
|
|
|
|
return ch - '0';
|
|
|
|
if ((ch >= 'a') && (ch <= 'f'))
|
|
|
|
return ch - 'a' + 10;
|
|
|
|
if ((ch >= 'A') && (ch <= 'F'))
|
|
|
|
return ch - 'A' + 10;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* While we find nice hex chars, build a long_val.
|
|
|
|
* Return number of chars processed.
|
|
|
|
*/
|
perf_counter tools: Define and use our own u64, s64 etc. definitions
On 64-bit powerpc, __u64 is defined to be unsigned long rather than
unsigned long long. This causes compiler warnings every time we
print a __u64 value with %Lx.
Rather than changing __u64, we define our own u64 to be unsigned long
long on all architectures, and similarly s64 as signed long long.
For consistency we also define u32, s32, u16, s16, u8 and s8. These
definitions are put in a new header, types.h, because these definitions
are needed in util/string.h and util/symbol.h.
The main change here is the mechanical change of __[us]{64,32,16,8}
to remove the "__". The other changes are:
* Create types.h
* Include types.h in perf.h, util/string.h and util/symbol.h
* Add types.h to the LIB_H definition in Makefile
* Added (u64) casts in process_overflow_event() and print_sym_table()
to kill two remaining warnings.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: benh@kernel.crashing.org
LKML-Reference: <19003.33494.495844.956580@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-06-19 20:21:42 +08:00
|
|
|
int hex2u64(const char *ptr, u64 *long_val)
|
2009-06-02 09:31:03 +08:00
|
|
|
{
|
|
|
|
const char *p = ptr;
|
|
|
|
*long_val = 0;
|
|
|
|
|
|
|
|
while (*p) {
|
|
|
|
const int hex_val = hex(*p);
|
|
|
|
|
|
|
|
if (hex_val < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
*long_val = (*long_val << 4) | hex_val;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p - ptr;
|
|
|
|
}
|
2009-10-06 01:26:18 +08:00
|
|
|
|
|
|
|
char *strxfrchar(char *s, char from, char to)
|
|
|
|
{
|
|
|
|
char *p = s;
|
|
|
|
|
|
|
|
while ((p = strchr(p, from)) != NULL)
|
|
|
|
*p++ = to;
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
2009-11-15 19:36:53 +08:00
|
|
|
|
|
|
|
#define K 1024LL
|
|
|
|
/*
|
|
|
|
* perf_atoll()
|
|
|
|
* Parse (\d+)(b|B|kb|KB|mb|MB|gb|GB|tb|TB) (e.g. "256MB")
|
|
|
|
* and return its numeric value
|
|
|
|
*/
|
|
|
|
s64 perf_atoll(const char *str)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
s64 length = -1, unit = 1;
|
|
|
|
|
|
|
|
if (!isdigit(str[0]))
|
|
|
|
goto out_err;
|
|
|
|
|
|
|
|
for (i = 1; i < strlen(str); i++) {
|
|
|
|
switch (str[i]) {
|
|
|
|
case 'B':
|
|
|
|
case 'b':
|
|
|
|
break;
|
|
|
|
case 'K':
|
|
|
|
if (str[i + 1] != 'B')
|
|
|
|
goto out_err;
|
|
|
|
else
|
|
|
|
goto kilo;
|
|
|
|
case 'k':
|
|
|
|
if (str[i + 1] != 'b')
|
|
|
|
goto out_err;
|
|
|
|
kilo:
|
|
|
|
unit = K;
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
if (str[i + 1] != 'B')
|
|
|
|
goto out_err;
|
|
|
|
else
|
|
|
|
goto mega;
|
|
|
|
case 'm':
|
|
|
|
if (str[i + 1] != 'b')
|
|
|
|
goto out_err;
|
|
|
|
mega:
|
|
|
|
unit = K * K;
|
|
|
|
break;
|
|
|
|
case 'G':
|
|
|
|
if (str[i + 1] != 'B')
|
|
|
|
goto out_err;
|
|
|
|
else
|
|
|
|
goto giga;
|
|
|
|
case 'g':
|
|
|
|
if (str[i + 1] != 'b')
|
|
|
|
goto out_err;
|
|
|
|
giga:
|
|
|
|
unit = K * K * K;
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
if (str[i + 1] != 'B')
|
|
|
|
goto out_err;
|
|
|
|
else
|
|
|
|
goto tera;
|
|
|
|
case 't':
|
|
|
|
if (str[i + 1] != 'b')
|
|
|
|
goto out_err;
|
|
|
|
tera:
|
|
|
|
unit = K * K * K * K;
|
|
|
|
break;
|
|
|
|
case '\0': /* only specified figures */
|
|
|
|
unit = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (!isdigit(str[i]))
|
|
|
|
goto out_err;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
length = atoll(str) * unit;
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
out_err:
|
|
|
|
length = -1;
|
|
|
|
out:
|
|
|
|
return length;
|
|
|
|
}
|
2009-12-01 08:20:05 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper function for splitting a string into an argv-like array.
|
|
|
|
* originaly copied from lib/argv_split.c
|
|
|
|
*/
|
|
|
|
static const char *skip_sep(const char *cp)
|
|
|
|
{
|
|
|
|
while (*cp && isspace(*cp))
|
|
|
|
cp++;
|
|
|
|
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *skip_arg(const char *cp)
|
|
|
|
{
|
|
|
|
while (*cp && !isspace(*cp))
|
|
|
|
cp++;
|
|
|
|
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int count_argc(const char *str)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
while (*str) {
|
|
|
|
str = skip_sep(str);
|
|
|
|
if (*str) {
|
|
|
|
count++;
|
|
|
|
str = skip_arg(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* argv_free - free an argv
|
|
|
|
* @argv - the argument vector to be freed
|
|
|
|
*
|
|
|
|
* Frees an argv and the strings it points to.
|
|
|
|
*/
|
|
|
|
void argv_free(char **argv)
|
|
|
|
{
|
|
|
|
char **p;
|
|
|
|
for (p = argv; *p; p++)
|
|
|
|
free(*p);
|
|
|
|
|
|
|
|
free(argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* argv_split - split a string at whitespace, returning an argv
|
|
|
|
* @str: the string to be split
|
|
|
|
* @argcp: returned argument count
|
|
|
|
*
|
|
|
|
* Returns an array of pointers to strings which are split out from
|
|
|
|
* @str. This is performed by strictly splitting on white-space; no
|
|
|
|
* quote processing is performed. Multiple whitespace characters are
|
|
|
|
* considered to be a single argument separator. The returned array
|
|
|
|
* is always NULL-terminated. Returns NULL on memory allocation
|
|
|
|
* failure.
|
|
|
|
*/
|
|
|
|
char **argv_split(const char *str, int *argcp)
|
|
|
|
{
|
|
|
|
int argc = count_argc(str);
|
|
|
|
char **argv = zalloc(sizeof(*argv) * (argc+1));
|
|
|
|
char **argvp;
|
|
|
|
|
|
|
|
if (argv == NULL)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (argcp)
|
|
|
|
*argcp = argc;
|
|
|
|
|
|
|
|
argvp = argv;
|
|
|
|
|
|
|
|
while (*str) {
|
|
|
|
str = skip_sep(str);
|
|
|
|
|
|
|
|
if (*str) {
|
|
|
|
const char *p = str;
|
|
|
|
char *t;
|
|
|
|
|
|
|
|
str = skip_arg(str);
|
|
|
|
|
|
|
|
t = strndup(p, str-p);
|
|
|
|
if (t == NULL)
|
|
|
|
goto fail;
|
|
|
|
*argvp++ = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*argvp = NULL;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return argv;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
argv_free(argv);
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-12-15 23:32:10 +08:00
|
|
|
|
2010-01-06 06:47:24 +08:00
|
|
|
/* Character class matching */
|
|
|
|
static bool __match_charclass(const char *pat, char c, const char **npat)
|
|
|
|
{
|
|
|
|
bool complement = false, ret = true;
|
|
|
|
|
|
|
|
if (*pat == '!') {
|
|
|
|
complement = true;
|
|
|
|
pat++;
|
|
|
|
}
|
|
|
|
if (*pat++ == c) /* First character is special */
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
while (*pat && *pat != ']') { /* Matching */
|
|
|
|
if (*pat == '-' && *(pat + 1) != ']') { /* Range */
|
|
|
|
if (*(pat - 1) <= c && c <= *(pat + 1))
|
|
|
|
goto end;
|
|
|
|
if (*(pat - 1) > *(pat + 1))
|
|
|
|
goto error;
|
|
|
|
pat += 2;
|
|
|
|
} else if (*pat++ == c)
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (!*pat)
|
|
|
|
goto error;
|
|
|
|
ret = false;
|
|
|
|
|
|
|
|
end:
|
|
|
|
while (*pat && *pat != ']') /* Searching closing */
|
|
|
|
pat++;
|
|
|
|
if (!*pat)
|
|
|
|
goto error;
|
|
|
|
*npat = pat + 1;
|
|
|
|
return complement ? !ret : ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-02-25 21:36:12 +08:00
|
|
|
/* Glob/lazy pattern matching */
|
|
|
|
static bool __match_glob(const char *str, const char *pat, bool ignore_space)
|
2009-12-15 23:32:10 +08:00
|
|
|
{
|
|
|
|
while (*str && *pat && *pat != '*') {
|
2010-02-25 21:36:12 +08:00
|
|
|
if (ignore_space) {
|
|
|
|
/* Ignore spaces for lazy matching */
|
|
|
|
if (isspace(*str)) {
|
|
|
|
str++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (isspace(*pat)) {
|
|
|
|
pat++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2010-01-06 06:47:24 +08:00
|
|
|
if (*pat == '?') { /* Matches any single character */
|
2009-12-15 23:32:10 +08:00
|
|
|
str++;
|
|
|
|
pat++;
|
2010-01-06 06:47:24 +08:00
|
|
|
continue;
|
|
|
|
} else if (*pat == '[') /* Character classes/Ranges */
|
|
|
|
if (__match_charclass(pat + 1, *str, &pat)) {
|
|
|
|
str++;
|
|
|
|
continue;
|
|
|
|
} else
|
2009-12-15 23:32:10 +08:00
|
|
|
return false;
|
2010-01-06 06:47:24 +08:00
|
|
|
else if (*pat == '\\') /* Escaped char match as normal char */
|
|
|
|
pat++;
|
|
|
|
if (*str++ != *pat++)
|
|
|
|
return false;
|
2009-12-15 23:32:10 +08:00
|
|
|
}
|
|
|
|
/* Check wild card */
|
|
|
|
if (*pat == '*') {
|
|
|
|
while (*pat == '*')
|
|
|
|
pat++;
|
|
|
|
if (!*pat) /* Tail wild card matches all */
|
|
|
|
return true;
|
|
|
|
while (*str)
|
|
|
|
if (strglobmatch(str++, pat))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return !*str && !*pat;
|
|
|
|
}
|
|
|
|
|
2010-02-25 21:36:12 +08:00
|
|
|
/**
|
|
|
|
* strglobmatch - glob expression pattern matching
|
|
|
|
* @str: the target string to match
|
|
|
|
* @pat: the pattern string to match
|
|
|
|
*
|
|
|
|
* This returns true if the @str matches @pat. @pat can includes wildcards
|
|
|
|
* ('*','?') and character classes ([CHARS], complementation and ranges are
|
|
|
|
* also supported). Also, this supports escape character ('\') to use special
|
|
|
|
* characters as normal character.
|
|
|
|
*
|
|
|
|
* Note: if @pat syntax is broken, this always returns false.
|
|
|
|
*/
|
|
|
|
bool strglobmatch(const char *str, const char *pat)
|
|
|
|
{
|
|
|
|
return __match_glob(str, pat, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* strlazymatch - matching pattern strings lazily with glob pattern
|
|
|
|
* @str: the target string to match
|
|
|
|
* @pat: the pattern string to match
|
|
|
|
*
|
|
|
|
* This is similar to strglobmatch, except this ignores spaces in
|
|
|
|
* the target string.
|
|
|
|
*/
|
|
|
|
bool strlazymatch(const char *str, const char *pat)
|
|
|
|
{
|
|
|
|
return __match_glob(str, pat, true);
|
|
|
|
}
|