4 * This file is part of ktap by Jovi Zhangwei.
6 * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
8 * Copyright (C) 1994-2013 Lua.org, PUC-Rio.
9 * - The part of code in this file is copied from lua initially.
10 * - lua's MIT license is compatible with GPL.
12 * ktap is free software; you can redistribute it and/or modify it
13 * under the terms and conditions of the GNU General Public License,
14 * version 2, as published by the Free Software Foundation.
16 * ktap is distributed in the hope it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 * You should have received a copy of the GNU General Public License along with
22 * this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
31 #include "../include/ktap_types.h"
32 #include "../include/ktap_opcodes.h"
36 * converts an integer to a "floating point byte", represented as
37 * (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
38 * eeeee != 0 and (xxx) otherwise.
40 int ktapc_int2fb(unsigned int x)
42 int e = 0; /* exponent */
50 return ((e+1) << 3) | ((int)x - 8);
54 int ktapc_fb2int(int x)
56 int e = (x >> 3) & 0x1f;
61 return ((x & 7) + 8) << (e - 1);
64 int ktapc_ceillog2(unsigned int x)
66 static const u8 log_2[256] = {
67 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
68 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
69 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
70 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
71 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
72 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
73 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
74 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
86 ktap_number ktapc_arith(int op, ktap_number v1, ktap_number v2)
89 case KTAP_OPADD: return NUMADD(v1, v2);
90 case KTAP_OPSUB: return NUMSUB(v1, v2);
91 case KTAP_OPMUL: return NUMMUL(v1, v2);
92 case KTAP_OPDIV: return NUMDIV(v1, v2);
93 case KTAP_OPMOD: return NUMMOD(v1, v2);
94 //case KTAP_OPPOW: return NUMPOW(v1, v2);
95 case KTAP_OPUNM: return NUMUNM(v1);
96 default: ktap_assert(0); return 0;
100 int ktapc_hexavalue(int c)
105 return tolower(c) - 'a' + 10;
108 int ktapc_str2d(const char *s, size_t len, ktap_number *result)
112 if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
115 *result = (long)strtoul(s, &endptr, 0);
118 return 0; /* nothing recognized */
119 while (isspace((unsigned char)(*endptr)))
121 return (endptr == s + len); /* OK if no trailing characters */
124 /* number of chars of a literal string without the ending \0 */
125 #define LL(x) (sizeof(x)/sizeof(char) - 1)
128 #define PRE "[string \""
131 #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
133 void ktapc_chunkid(char *out, const char *source, size_t bufflen)
135 size_t l = strlen(source);
137 if (*source == '=') { /* 'literal' source */
138 if (l <= bufflen) /* small enough? */
139 memcpy(out, source + 1, l * sizeof(char));
140 else { /* truncate it */
141 addstr(out, source + 1, bufflen - 1);
144 } else if (*source == '@') { /* file name */
145 if (l <= bufflen) /* small enough? */
146 memcpy(out, source + 1, l * sizeof(char));
147 else { /* add '...' before rest of name */
148 addstr(out, RETS, LL(RETS));
150 memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
152 } else { /* string; format as [string "source"] */
153 const char *nl = strchr(source, '\n'); /* find first new line (if any) */
154 addstr(out, PRE, LL(PRE)); /* add prefix */
155 bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
156 if (l < bufflen && nl == NULL) { /* small one-line source? */
157 addstr(out, source, l); /* keep it */
160 l = nl - source; /* stop at first newline */
163 addstr(out, source, l);
164 addstr(out, RETS, LL(RETS));
166 memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
172 * strglobmatch is copyed from perf(linux/tools/perf/util/string.c)
175 /* Character class matching */
176 static bool __match_charclass(const char *pat, char c, const char **npat)
178 bool complement = false, ret = true;
184 if (*pat++ == c) /* First character is special */
187 while (*pat && *pat != ']') { /* Matching */
188 if (*pat == '-' && *(pat + 1) != ']') { /* Range */
189 if (*(pat - 1) <= c && c <= *(pat + 1))
191 if (*(pat - 1) > *(pat + 1))
194 } else if (*pat++ == c)
202 while (*pat && *pat != ']') /* Searching closing */
207 return complement ? !ret : ret;
213 /* Glob/lazy pattern matching */
214 static bool __match_glob(const char *str, const char *pat, bool ignore_space)
216 while (*str && *pat && *pat != '*') {
218 /* Ignore spaces for lazy matching */
228 if (*pat == '?') { /* Matches any single character */
232 } else if (*pat == '[') /* Character classes/Ranges */
233 if (__match_charclass(pat + 1, *str, &pat)) {
238 else if (*pat == '\\') /* Escaped char match as normal char */
240 if (*str++ != *pat++)
243 /* Check wild card */
247 if (!*pat) /* Tail wild card matches all */
250 if (__match_glob(str++, pat, ignore_space))
253 return !*str && !*pat;
257 * strglobmatch - glob expression pattern matching
258 * @str: the target string to match
259 * @pat: the pattern string to match
261 * This returns true if the @str matches @pat. @pat can includes wildcards
262 * ('*','?') and character classes ([CHARS], complementation and ranges are
263 * also supported). Also, this supports escape character ('\') to use special
264 * characters as normal character.
266 * Note: if @pat syntax is broken, this always returns false.
268 bool strglobmatch(const char *str, const char *pat)
270 return __match_glob(str, pat, false);
273 #define handle_error(str) do { perror(str); exit(-1); } while(0)
275 #define KALLSYMS_PATH "/proc/kallsyms"
277 * read kernel symbol from /proc/kallsyms
279 int kallsyms_parse(void *arg,
280 int(*process_symbol)(void *arg, const char *name,
281 char type, unsigned long start))
287 file = fopen(KALLSYMS_PATH, "r");
289 handle_error("open " KALLSYMS_PATH " failed");
291 while (!feof(file)) {
292 char *symbol_addr, *symbol_name;
298 line_len = getline(&line, &n, file);
299 if (line_len < 0 || !line)
302 line[--line_len] = '\0'; /* \n */
304 symbol_addr = strtok(line, " \t");
305 start = strtoul(symbol_addr, NULL, 16);
307 symbol_type = *strtok(NULL, " \t");
308 symbol_name = strtok(NULL, " \t");
310 ret = process_symbol(arg, symbol_name, symbol_type, start);
326 static int symbol_cmp(void *arg, const char *name, char type,
329 struct ksym_addr_t *base = arg;
331 if (strcmp(base->name, name) == 0) {
339 unsigned long find_kernel_symbol(const char *symbol)
342 struct ksym_addr_t arg = {
347 ret = kallsyms_parse(&arg, symbol_cmp);
348 if (ret < 0 || arg.addr == 0) {
349 fprintf(stderr, "cannot read kernel symbol \"%s\" in %s\n",
350 symbol, KALLSYMS_PATH);
358 #define AVAILABLE_EVENTS_PATH "/sys/kernel/debug/tracing/available_events"
360 void list_available_events(const char *match)
365 file = fopen(AVAILABLE_EVENTS_PATH, "r");
367 handle_error("open " AVAILABLE_EVENTS_PATH " failed");
369 while (!feof(file)) {
372 getline(&line, &n, file);
374 if (!match || strglobmatch(line, match))