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"
35 * converts an integer to a "floating point byte", represented as
36 * (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
37 * eeeee != 0 and (xxx) otherwise.
39 int ktapc_int2fb(unsigned int x)
41 int e = 0; /* exponent */
49 return ((e+1) << 3) | ((int)x - 8);
53 int ktapc_fb2int(int x)
55 int e = (x >> 3) & 0x1f;
60 return ((x & 7) + 8) << (e - 1);
63 int ktapc_ceillog2(unsigned int x)
65 static const u8 log_2[256] = {
66 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,
67 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,
68 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,
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 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,
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
85 ktap_number ktapc_arith(int op, ktap_number v1, ktap_number v2)
88 case KTAP_OPADD: return NUMADD(v1, v2);
89 case KTAP_OPSUB: return NUMSUB(v1, v2);
90 case KTAP_OPMUL: return NUMMUL(v1, v2);
91 case KTAP_OPDIV: return NUMDIV(v1, v2);
92 case KTAP_OPMOD: return NUMMOD(v1, v2);
93 //case KTAP_OPPOW: return NUMPOW(v1, v2);
94 case KTAP_OPUNM: return NUMUNM(v1);
95 default: ktap_assert(0); return 0;
99 int ktapc_hexavalue(int c)
104 return tolower(c) - 'a' + 10;
107 static int isneg(const char **s)
112 } else if (**s == '+')
118 static ktap_number readhexa(const char **s, ktap_number r, int *count)
120 for (; isxdigit((unsigned char)(**s)); (*s)++) { /* read integer part */
121 r = (r * 16.0) + (ktap_number)(ktapc_hexavalue((unsigned char)(**s)));
129 * convert an hexadecimal numeric string to a number, following
130 * C99 specification for 'strtod'
132 static ktap_number strx2number(const char *s, char **endptr)
136 int neg = 0; /* 1 if number is negative */
138 *endptr = (char *)s; /* nothing is valid yet */
139 while (isspace((unsigned char)(*s)))
140 s++; /* skip initial spaces */
142 neg = isneg(&s); /* check signal */
143 if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
144 return 0.0; /* invalid format (no '0x') */
146 s += 2; /* skip '0x' */
147 r = readhexa(&s, r, &i); /* read integer part */
150 r = readhexa(&s, r, &e); /* read fractional part */
153 if (i == 0 && e == 0)
154 return 0.0; /* invalid format (no digit) */
155 e *= -4; /* each fractional digit divides value by 2^-4 */
156 *endptr = (char *)s; /* valid up to here */
158 if (*s == 'p' || *s == 'P') { /* exponent part? */
163 neg1 = isneg(&s); /* signal */
164 if (!isdigit((unsigned char)(*s)))
165 goto ret; /* must have at least one digit */
166 while (isdigit((unsigned char)(*s))) /* read exponent */
167 exp1 = exp1 * 10 + *(s++) - '0';
168 if (neg1) exp1 = -exp1;
172 *endptr = (char *)s; /* valid up to here */
180 int ktapc_str2d(const char *s, size_t len, ktap_number *result)
184 if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
186 else if (strpbrk(s, "xX")) /* hexa? */
187 *result = strx2number(s, &endptr);
189 *result = strtod(s, &endptr);
192 return 0; /* nothing recognized */
193 while (isspace((unsigned char)(*endptr)))
195 return (endptr == s + len); /* OK if no trailing characters */
198 /* number of chars of a literal string without the ending \0 */
199 #define LL(x) (sizeof(x)/sizeof(char) - 1)
202 #define PRE "[string \""
205 #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
207 void ktapc_chunkid(char *out, const char *source, size_t bufflen)
209 size_t l = strlen(source);
211 if (*source == '=') { /* 'literal' source */
212 if (l <= bufflen) /* small enough? */
213 memcpy(out, source + 1, l * sizeof(char));
214 else { /* truncate it */
215 addstr(out, source + 1, bufflen - 1);
218 } else if (*source == '@') { /* file name */
219 if (l <= bufflen) /* small enough? */
220 memcpy(out, source + 1, l * sizeof(char));
221 else { /* add '...' before rest of name */
222 addstr(out, RETS, LL(RETS));
224 memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
226 } else { /* string; format as [string "source"] */
227 const char *nl = strchr(source, '\n'); /* find first new line (if any) */
228 addstr(out, PRE, LL(PRE)); /* add prefix */
229 bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
230 if (l < bufflen && nl == NULL) { /* small one-line source? */
231 addstr(out, source, l); /* keep it */
234 l = nl - source; /* stop at first newline */
237 addstr(out, source, l);
238 addstr(out, RETS, LL(RETS));
240 memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
246 * strglobmatch is copyed from perf(linux/tools/perf/util/string.c)
249 /* Character class matching */
250 static bool __match_charclass(const char *pat, char c, const char **npat)
252 bool complement = false, ret = true;
258 if (*pat++ == c) /* First character is special */
261 while (*pat && *pat != ']') { /* Matching */
262 if (*pat == '-' && *(pat + 1) != ']') { /* Range */
263 if (*(pat - 1) <= c && c <= *(pat + 1))
265 if (*(pat - 1) > *(pat + 1))
268 } else if (*pat++ == c)
276 while (*pat && *pat != ']') /* Searching closing */
281 return complement ? !ret : ret;
287 /* Glob/lazy pattern matching */
288 static bool __match_glob(const char *str, const char *pat, bool ignore_space)
290 while (*str && *pat && *pat != '*') {
292 /* Ignore spaces for lazy matching */
302 if (*pat == '?') { /* Matches any single character */
306 } else if (*pat == '[') /* Character classes/Ranges */
307 if (__match_charclass(pat + 1, *str, &pat)) {
312 else if (*pat == '\\') /* Escaped char match as normal char */
314 if (*str++ != *pat++)
317 /* Check wild card */
321 if (!*pat) /* Tail wild card matches all */
324 if (__match_glob(str++, pat, ignore_space))
327 return !*str && !*pat;
331 * strglobmatch - glob expression pattern matching
332 * @str: the target string to match
333 * @pat: the pattern string to match
335 * This returns true if the @str matches @pat. @pat can includes wildcards
336 * ('*','?') and character classes ([CHARS], complementation and ranges are
337 * also supported). Also, this supports escape character ('\') to use special
338 * characters as normal character.
340 * Note: if @pat syntax is broken, this always returns false.
342 bool strglobmatch(const char *str, const char *pat)
344 return __match_glob(str, pat, false);