1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2 
3 #if __WINDOWS__
4 #include <stdlib.h>
5 #endif
6 
7 #include <errno.h>
8 #include <math.h>  /* for ceill */
9 #include <r_util.h>
10 #define R_NUM_USE_CALC 1
11 
12 static ut64 r_num_tailff(RNum *num, const char *hex);
13 
r_num_srand(int seed)14 static void r_num_srand(int seed) {
15 #if HAVE_ARC4RANDOM_UNIFORM
16 	// no-op
17 	(void)seed;
18 #else
19 	srand (seed);
20 #endif
21 }
22 
r_rand(int mod)23 static int r_rand(int mod) {
24 #if HAVE_ARC4RANDOM_UNIFORM
25 	return (int)arc4random_uniform (mod);
26 #else
27 	return rand () % mod;
28 #endif
29 }
30 
31 // This function count bits set on 32bit words
r_num_bit_count(ut32 val)32 R_API size_t r_num_bit_count(ut32 val) {
33 	/* visual studio doesnt supports __buitin_clz */
34 #if defined(_MSC_VER) || defined(__TINYC__)
35 	size_t count = 0;
36 	val = val - ((val >> 1) & 0x55555555);
37 	val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
38 	count = (((val + (val >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
39 	return count;
40 #else
41 	return val? __builtin_clz (val): 0;
42 #endif
43 }
44 
r_num_irand(void)45 R_API void r_num_irand(void) {
46 	r_num_srand (r_time_now ());
47 }
48 
r_num_rand(int max)49 R_API int r_num_rand(int max) {
50 	static bool rand_initialized = false;
51 	if (!rand_initialized) {
52 		r_num_irand ();
53 		rand_initialized = true;
54 	}
55 	if (!max) {
56 		max = 1;
57 	}
58 	return r_rand (max);
59 }
60 
r_num_minmax_swap(ut64 * a,ut64 * b)61 R_API void r_num_minmax_swap(ut64 *a, ut64 *b) {
62 	if (*a > *b) {
63 		ut64 tmp = *a;
64 		*a = *b;
65 		*b = tmp;
66 	}
67 }
68 
r_num_minmax_swap_i(int * a,int * b)69 R_API void r_num_minmax_swap_i(int *a, int *b) {
70 	if (*a > *b) {
71 		ut64 tmp = *a;
72 		*a = *b;
73 		*b = tmp;
74 	}
75 }
76 
r_num_new(RNumCallback cb,RNumCallback2 cb2,void * ptr)77 R_API RNum *r_num_new(RNumCallback cb, RNumCallback2 cb2, void *ptr) {
78 	RNum *num = R_NEW0 (RNum);
79 	if (!num) {
80 		return NULL;
81 	}
82 	num->value = 0LL;
83 	num->callback = cb;
84 	num->cb_from_value = cb2;
85 	num->userptr = ptr;
86 	return num;
87 }
88 
r_num_free(RNum * num)89 R_API void r_num_free(RNum *num) {
90 	free (num);
91 }
92 
93 #define KB (1ULL << 10)
94 #define MB (1ULL << 20)
95 #define GB (1ULL << 30)
96 #define TB (1ULL << 40)
97 #define PB (1ULL << 50)
98 #define EB (1ULL << 60)
99 
100 /**
101  * Convert size in bytes to human-readable string
102  *
103  * Result is stored in buf (buf should be at least 8 bytes in size).
104  * If buf is NULL, memory for the new string is obtained with malloc(3),
105  * and can be freed with free(3).
106  *
107  * On success, returns a pointer to buf. It returns NULL if
108  * insufficient memory was available.
109  */
r_num_units(char * buf,size_t len,ut64 num)110 R_API char *r_num_units(char *buf, size_t len, ut64 num) {
111 	long double fnum;
112 	char unit;
113 	const char *fmt_str;
114 	if (!buf) {
115 		buf = malloc (len + 1);
116 		if (!buf) {
117 			return NULL;
118 		}
119 	}
120 	fnum = num;
121 	if (num >= EB) { unit = 'E'; fnum /= EB; } else
122 	if (num >= PB) { unit = 'P'; fnum /= PB; } else
123 	if (num >= TB) { unit = 'T'; fnum /= TB; } else
124 	if (num >= GB) { unit = 'G'; fnum /= GB; } else
125 	if (num >= MB) { unit = 'M'; fnum /= MB; } else
126 	if (num >= KB) { unit = 'K'; fnum /= KB; } else {
127 		unit = '\0';
128 	}
129 	fmt_str = ((double)ceill (fnum) == (double)fnum)
130 		? "%.0" LDBLFMT "%c"
131 		: "%.1" LDBLFMT "%c";
132 	snprintf (buf, len, fmt_str, fnum, unit);
133 	return buf;
134 }
135 
r_num_get_name(RNum * num,ut64 n)136 R_API const char *r_num_get_name(RNum *num, ut64 n) {
137 	if (num->cb_from_value) {
138 		int ok = 0;
139 		const char *msg = num->cb_from_value (num, n, &ok);
140 		if (msg && *msg) {
141 			return msg;
142 		}
143 		if (ok) {
144 			return msg;
145 		}
146 	}
147 	return NULL;
148 }
149 
error(RNum * num,const char * err_str)150 static void error(RNum *num, const char *err_str) {
151 	if (num) {
152 		num->nc.errors++;
153 #if 0
154 		num->nc.calc_err = err_str;
155 #endif
156 	}
157 }
158 
159 // TODO: try to avoid the use of sscanf
160 /* old get_offset */
r_num_get(RNum * num,const char * str)161 R_API ut64 r_num_get(RNum *num, const char *str) {
162 	int i, j, ok;
163 	char lch, len;
164 	ut64 ret = 0LL;
165 	ut32 s, a;
166 
167 	if (num && !num->nc.under_calc) {
168 		num->nc.errors = 0;
169 	}
170 	if (!str) {
171 		return 0;
172 	}
173 	for (; *str == ' '; ) {
174 		str++;
175 	}
176 	if (!*str) {
177 		return 0;
178 	}
179 	if (!strncmp (str, "1u", 2)) { // '1' is captured by op :(
180 		if (num && num->value == UT64_MAX) {
181 			num->value = 0;
182 		}
183 		switch (atoi (str + 2)) {
184 		case 64: return (ut64)UT64_MAX;
185 		case 32: return (ut64)UT32_MAX;
186 		case 16: return (ut64)UT16_MAX;
187 		case 8: return (ut64)UT8_MAX;
188 		}
189 	}
190 	/* resolve string with an external callback */
191 	if (num && num->callback) {
192 		ok = 0;
193 		ret = num->callback (num->userptr, str, &ok);
194 		if (ok) {
195 			return ret;
196 		}
197 	}
198 
199 	if (str[0] && str[1] && str[2]) {
200 		if (str[0] == '\'' && str[2] == '\'') {
201 			return (ut64)str[1];
202 		}
203 	}
204 
205 	len = strlen (str);
206 	if (len > 3 && str[4] == ':') {
207 		if (sscanf (str, "%04x", &s) == 1) {
208 			if (sscanf (str + 5, "%04x", &a) == 1) {
209 				return (ut64) ((s<<4) + a);
210 			}
211 		}
212 	} else if (len > 6 && str[6] == ':') {
213 		if (sscanf (str, "0x%04x:0x%04x", &s, &a) == 2) {
214 			return (ut64) ((s << 4) + a);
215 		}
216 		if (sscanf (str, "0x%04x:%04x", &s, &a) == 2) {
217 			return (ut64) ((s << 4) + a);
218 		}
219 	}
220 	if (str[0] == '0' && str[1] == 'b') {
221 		ret = 0;
222 		for (j = 0, i = strlen (str) - 1; i > 0; i--, j++) {
223 			if (str[i] == '1') {
224 				ret|=1 << j;
225 			} else if (str[i] != '0') {
226 				break;
227 			}
228 		}
229 		sscanf (str, "0x%"PFMT64x, &ret);
230 	} else if (str[0] == '\'') {
231 		ret = str[1] & 0xff;
232 	// ugly as hell
233 	} else if (!strncmp (str, "0xff..", 6) || !strncmp (str, "0xFF..", 6)) {
234 		ret = r_num_tailff (num, str + 6);
235 	// ugly as hell
236 	} else if (!strncmp (str, "0o", 2)) {
237 		if (sscanf (str + 2, "%"PFMT64o, &ret) != 1) {
238 			error (num, "invalid octal number");
239 		}
240 	} else if (!strncmp (str, "0xf..", 5) || !strncmp (str, "0xF..", 5)) {
241 		ret = r_num_tailff (num, str + 5);
242 	} else if (str[0] == '0' && tolower ((unsigned char)str[1]) == 'x') {
243 		const char *lodash = strchr (str + 2, '_');
244 		if (lodash) {
245 			// Support 0x1000_f000_4000
246 			// TODO: Only take underscores separated every 4 chars starting at the end
247 			char *s = strdup (str + 2);
248 			if (s) {
249 				r_str_replace_char (s, '_', 0);
250 				errno = 0;
251 				ret = strtoull (s, NULL, 16);
252 				free (s);
253 			}
254 		} else {
255 			errno = 0;
256 			ret = strtoull (str + 2, NULL, 16);
257 			// sscanf (str+2, "%"PFMT64x, &ret);
258 		}
259 		if (errno == ERANGE) {
260 			error (num, "number won't fit into 64 bits");
261 		}
262 	} else {
263 		char *endptr;
264 		int len_num = len > 0 ? len - 1 : 0;
265 		int chars_read = len_num;
266 		bool zero_read = false;
267 		lch = str[len > 0 ? len - 1 : 0];
268 		if (*str == '0' && IS_DIGIT (*(str + 1)) && lch != 'b' && lch != 'h') {
269 			lch = 'o';
270 			len_num++;
271 		}
272 		switch (lch) {
273 		case 'h': // hexa
274 			if (!sscanf (str, "%"PFMT64x"%n", &ret, &chars_read)
275 			    || chars_read != len_num) {
276 				error (num, "invalid hex number");
277 			}
278 			break;
279 		case 'o': // octal
280 			if (!sscanf (str, "%"PFMT64o"%n", &ret, &chars_read)
281 			    || chars_read != len_num) {
282 				error (num, "invalid octal number");
283 			}
284 			break;
285 		case 'b': // binary
286 			ret = 0;
287 			ok = true;
288 			if (strlen (str) <= 65) { // 64 bit + the 'b' suffix
289 				for (j = 0, i = strlen (str) - 2; i >= 0; i--, j++) {
290 					if (str[i] == '1') {
291 						ret |= (1ULL << j);
292 					} else if (str[i] != '0') {
293 						// eprintf ("Unexpected char in binary number string '%c'\n", str[i]);
294 						ok = false;
295 						break;
296 					}
297 				}
298 			} else {
299 				ok = false;
300 				// eprintf ("Binary number is too large to fit in ut64\n");
301 			}
302 			if (!ok || !len_num) {
303 				error (num, "invalid binary number");
304 			}
305 			break;
306 		case 't': // ternary
307 			ret = 0;
308 			ok = true;
309 			ut64 x = 1;
310 			for (i = strlen (str) - 2; i >= 0; i--) {
311 				if (str[i] < '0' || '2' < str[i]) {
312 					ok = false;
313 					break;
314 				}
315 				ret += x * (str[i] - '0');
316 				x *= 3;
317 			}
318 			if (!ok || !len_num) {
319 				error (num, "invalid ternary number");
320 			}
321 			break;
322 		case 'K': case 'k':
323 			if (strchr (str, '.')) {
324 				double d = 0;
325 				if (sscanf (str, "%lf%n", &d, &chars_read)) {
326 					ret = (ut64)(d * KB);
327 				} else {
328 					zero_read = true;
329 				}
330 			} else {
331 				if (sscanf (str, "%"PFMT64d"%n", &ret, &chars_read)) {
332 					ret *= KB;
333 				} else {
334 					zero_read = true;
335 				}
336 			}
337 			if (zero_read || chars_read != len_num) {
338 				error (num, "invalid kilobyte number");
339 			}
340 			break;
341 		case 'M': case 'm':
342 			if (strchr (str, '.')) {
343 				double d = 0;
344 				if (sscanf (str, "%lf%n", &d, &chars_read)) {
345 					ret = (ut64)(d * MB);
346 				} else {
347 					zero_read = true;
348 				}
349 			} else {
350 				if (sscanf (str, "%"PFMT64d"%n", &ret, &chars_read)) {
351 					ret *= MB;
352 				} else {
353 					zero_read = true;
354 				}
355 			}
356 			if (zero_read || chars_read != len_num) {
357 				error (num, "invalid megabyte number");
358 			}
359 			break;
360 		case 'G': case 'g':
361 			if (strchr (str, '.')) {
362 				double d = 0;
363 				if (sscanf (str, "%lf%n", &d, &chars_read)) {
364 					ret = (ut64)(d * GB);
365 				} else {
366 					zero_read = true;
367 				}
368 			} else {
369 				if (sscanf (str, "%"PFMT64d"%n", &ret, &chars_read)) {
370 					ret *= GB;
371 				} else {
372 					zero_read = true;
373 				}
374 			}
375 			if (zero_read || chars_read != len_num) {
376 				error (num, "invalid gigabyte number");
377 			}
378 			break;
379 		default:
380 #if 0
381 			// sscanf (str, "%"PFMT64d"%n", &ret, &chars_read);
382 // 32bit chop
383 #if __WINDOWS__
384 			ret = _strtoui64 (str, &endptr, 10);
385 #endif
386 #endif
387 			errno = 0;
388 			ret = strtoull (str, &endptr, 10);
389 			if (errno == ERANGE) {
390 				error (num, "number won't fit into 64 bits");
391 			}
392 			if (!IS_DIGIT (*str) || (*endptr && *endptr != lch)) {
393 				error (num, "unknown symbol");
394 			}
395 			break;
396 		}
397 	}
398 	if (num) {
399 		num->value = ret;
400 	}
401 	return ret;
402 }
403 
404 #if !R_NUM_USE_CALC
r_num_op(RNum * num,char op,ut64 a,ut64 b)405 static ut64 r_num_op(RNum *num, char op, ut64 a, ut64 b) {
406 	switch (op) {
407 	case '+': return a + b;
408 	case '-': return a - b;
409 	case '*': return a * b;
410 	case '/':
411 		if (!b && num) num->dbz = 1;
412 		return b ? a / b : 0;
413 	case '&': return a & b;
414 	case '|': return a | b;
415 	case '^': return a ^ b;
416 	}
417 	return b;
418 }
419 
r_num_math_internal(RNum * num,char * s)420 R_API static ut64 r_num_math_internal(RNum *num, char *s) {
421 	ut64 ret = 0LL;
422 	char *p = s;
423 	int i, nop, op = 0;
424 	for (i=0; s[i]; i++) {
425 		if (r_num_is_op (s[i])) {
426 			nop = s[i]; s[i] = '\0';
427 			ret = r_num_op (num, op, ret, r_num_get (num, p));
428 			op = s[i] = nop; p = s + i + 1;
429 			break;
430 		}
431 	}
432 	return r_num_op (op, ret, r_num_get (num, p));
433 }
434 #endif /* !R_NUM_USE_CALC */
435 
r_num_math(RNum * num,const char * str)436 R_API ut64 r_num_math(RNum *num, const char *str) {
437 #if R_NUM_USE_CALC
438 	ut64 ret;
439 	const char *err = NULL;
440 	if (!str || !*str) {
441 		return 0LL;
442 	}
443 	// if (!str || !*str) return 0LL;
444 	if (num) {
445 		num->dbz = 0;
446 	}
447 	ret = r_num_calc (num, str, &err);
448 	if (err) {
449 		eprintf ("r_num_calc error: (%s) in (%s)\n", err, str);
450 	}
451 	if (num) {
452 		num->value = ret;
453 	}
454 	return ret;
455 #else
456 	ut64 ret = 0LL;
457 	char op = '+';
458 	int len;
459 	char *p, *s, *os;
460 	char *group;
461 	if (!str) return 0LL;
462 
463 	len = strlen (str) + 1;
464 	os = malloc (len + 1);
465 
466 	s = os;
467 	memcpy (s, str, len);
468 	for (; *s == ' '; s++);
469 	p = s;
470 
471 	do {
472 		group = strchr (p, '(');
473 		if (group) {
474 			group[0] = '\0';
475 			ret = r_num_op (op, ret, r_num_math_internal (num, p));
476 			for (; p<group; p += 1) {
477 				if (r_num_is_op (*p)) {
478 					op = *p;
479 					break;
480 				}
481 			}
482 			group[0] = '(';
483 			p = group + 1;
484 			if (r_str_delta (p, '(', ')') < 0) {
485 				char *p2 = strchr (p, '(');
486 				if (p2 != NULL) {
487 					*p2 = '\0';
488 					ret = r_num_op (op, ret, r_num_math_internal (num, p));
489 					ret = r_num_op (op, ret, r_num_math (num, p2 + 1));
490 					p = p2 + 1;
491 					continue;
492 				}
493 				eprintf ("WTF!\n");
494 			} else {
495 				ret = r_num_op (op, ret, r_num_math_internal (num, p));
496 			}
497 		} else {
498 			ret = r_num_op (op, ret, r_num_math_internal (num, p));
499 		}
500 	} while (0);
501 
502 	if (num) {
503 		num->value = ret;
504 	}
505 	free (os);
506 	return ret;
507 #endif
508 }
509 
r_num_is_float(RNum * num,const char * str)510 R_API int r_num_is_float(RNum *num, const char *str) {
511 	return (IS_DIGIT (*str) && (strchr (str, '.') || str[strlen (str) - 1] == 'f'));
512 }
513 
r_num_get_float(RNum * num,const char * str)514 R_API double r_num_get_float(RNum *num, const char *str) {
515 	double d = 0.0f;
516 	(void) sscanf (str, "%lf", &d);
517 	return d;
518 }
519 
r_num_to_bits(char * out,ut64 num)520 R_API int r_num_to_bits(char *out, ut64 num) {
521 	int size = 64, i;
522 
523 	if (num >> 32) {
524 		size = 64;
525 	} else if (num & 0xff000000) {
526 		size = 32;
527 	} else if (num & 0xff0000) {
528 		size = 24;
529 	} else if (num & 0xff00) {
530 		size = 16;
531 	} else if (num & 0xff) {
532 		size = 8;
533 	}
534 	if (out) {
535 		int pos = 0;
536 		int realsize = 0;
537 		int hasbit = 0;
538 		for (i = 0; i < size; i++) {
539 			char bit = ((num >> (size - i - 1)) & 1) ? '1': '0';
540 			if (hasbit || bit == '1') {
541 				out[pos++] = bit; // size - 1 - i] = bit;
542 			}
543 			if (!hasbit && bit == '1') {
544 				hasbit = 1;
545 				realsize = size - i;
546 			}
547 		}
548 		if (realsize == 0) {
549 			out[realsize++] = '0';
550 		}
551 		out[realsize] = '\0'; // Maybe not nesesary?
552 	}
553 	return size;
554 }
555 
r_num_to_ternary(char * out,ut64 num)556 R_API int r_num_to_ternary(char *out, ut64 num) {
557 	if (out == NULL) {
558 		return false;
559 	}
560 	int i;
561 	for (i = 0; num; i++, num /= 3) {
562 		out[i] = (char) ('0' + num % 3);
563 	}
564 	if (i == 0) {
565 		out[0] = '0';
566 		i++;
567 	}
568 	out[i] = '\0';
569 
570 	r_str_reverse (out);
571 	return true;
572 }
573 
r_num_chs(int cylinder,int head,int sector,int sectorsize)574 R_API ut64 r_num_chs(int cylinder, int head, int sector, int sectorsize) {
575 	if (sectorsize < 1) {
576 		sectorsize = 512;
577 	}
578 	return (ut64)cylinder * (ut64)head * (ut64)sector * (ut64)sectorsize;
579 }
580 
r_num_conditional(RNum * num,const char * str)581 R_API int r_num_conditional(RNum *num, const char *str) {
582 	char *lgt, *t, *p, *s = strdup (str);
583 	int res = 0;
584 	ut64 n, a, b;
585 	p = s;
586 	do {
587 		t = strchr (p, ',');
588 		if (t) {
589 			*t = 0;
590 		}
591 		lgt = strchr (p, '<');
592 		if (lgt) {
593 			*lgt = 0;
594 			a = r_num_math (num, p);
595 			if (lgt[1] == '=') {
596 				b = r_num_math (num, lgt + 2);
597 				if (a > b) {
598 					goto fail;
599 				}
600 			} else {
601 				b = r_num_math (num, lgt + 1);
602 				if (a >= b) {
603 					goto fail;
604 				}
605 			}
606 		} else {
607 			lgt = strchr (p, '>');
608 			if (lgt) {
609 				*lgt = 0;
610 				a = r_num_math (num, p);
611 				if (lgt[1] == '=') {
612 					b = r_num_math (num, lgt + 2);
613 					if (a < b) {
614 						goto fail;
615 					}
616 				} else {
617 					b = r_num_math (num, lgt + 1);
618 					if (a <= b) {
619 						goto fail;
620 					}
621 				}
622 			} else {
623 				lgt = strchr (p, '=');
624 				if (lgt && lgt > p) {
625 					lgt--;
626 					if (*lgt == '!') {
627 						r_str_replace_char (p, '!', ' ');
628 						r_str_replace_char (p, '=', '-');
629 						n = r_num_math (num, p);
630 						if (!n) {
631 							goto fail;
632 						}
633 					}
634 				}
635 				lgt = strstr (p, "==");
636 				if (lgt) {
637 					*lgt = ' ';
638 				}
639 				r_str_replace_char (p, '=', '-');
640 				n = r_num_math (num, p);
641 				if (n) {
642 					goto fail;
643 				}
644 			}
645 		}
646 		p = t + 1;
647 	} while (t);
648 	res = 1;
649 fail:
650 	free (s);
651 	return res;
652 }
653 
r_num_is_valid_input(RNum * num,const char * input_value)654 R_API int r_num_is_valid_input(RNum *num, const char *input_value) {
655 	ut64 value = input_value ? r_num_math (num, input_value) : 0;
656 	return !(value == 0 && input_value && *input_value != '0') || !(value == 0 && input_value && *input_value != '@');
657 }
658 
r_num_get_input_value(RNum * num,const char * input_value)659 R_API ut64 r_num_get_input_value(RNum *num, const char *input_value) {
660 	ut64 value = input_value ? r_num_math (num, input_value) : 0;
661 	return value;
662 }
663 
664 #define NIBBLE_TO_HEX(n) (((n) & 0xf) > 9 ? 'a' + ((n) & 0xf) - 10 : '0' + ((n) & 0xf))
escape_char(char * dst,char byte)665 static int escape_char(char* dst, char byte) {
666 	const char escape_map[] = "abtnvfr";
667 	if (byte >= 7 && byte <= 13) {
668 		*(dst++) = '\\';
669 		*(dst++) = escape_map [byte - 7];
670 		*dst = 0;
671 		return 2;
672 	} else if (byte) {
673 		*(dst++) = '\\';
674 		*(dst++) = 'x';
675 		*(dst++) = NIBBLE_TO_HEX (byte >> 4);
676 		*(dst++) = NIBBLE_TO_HEX (byte);
677 		*dst = 0;
678 		return 4;
679 	}
680 	return 0;
681 }
682 
r_num_as_string(RNum * ___,ut64 n,bool printable_only)683 R_API char* r_num_as_string(RNum *___, ut64 n, bool printable_only) {
684 	char str[34]; // 8 byte * 4 chars in \x?? format
685 	int stri, ret = 0, off = 0;
686 	int len = sizeof (ut64);
687 	ut64 num = n;
688 	str[stri=0] = 0;
689 	while (len--) {
690 		char ch = (num & 0xff);
691 		if (ch >= 32 && ch < 127) {
692 			str[stri++] = ch;
693 			str[stri] = 0;
694 		} else if (!printable_only && (off = escape_char (str + stri, ch)) != 0) {
695 			stri += off;
696 		} else {
697 			if (ch) {
698 				return NULL;
699 			}
700 		}
701 		ret |= (num & 0xff);
702 		num >>= 8;
703 	}
704 	if (ret) {
705 		return strdup (str);
706 	}
707 	if (!printable_only) {
708 		return strdup ("\\0");
709 	}
710 	return NULL;
711 }
712 
r_is_valid_input_num_value(RNum * num,const char * input_value)713 R_API bool r_is_valid_input_num_value(RNum *num, const char *input_value) {
714 	if (!input_value) {
715 		return false;
716 	}
717 	ut64 value = r_num_math (num, input_value);
718 	return !(value == 0 && *input_value != '0');
719 }
720 
721 // SHITTY API
r_get_input_num_value(RNum * num,const char * str)722 R_API ut64 r_get_input_num_value(RNum *num, const char *str) {
723 	return (str && *str)? r_num_math (num, str) : 0;
724 }
725 
726 // SHITTY API
__nth_nibble(ut64 n,ut32 i)727 static inline ut64 __nth_nibble(ut64 n, ut32 i) {
728 	int sz = (sizeof (n) << 1) - 1;
729 	int s = (sz - i) * 4;
730 	return (n >> s) & 0xf;
731 }
732 
r_num_tail_base(RNum * num,ut64 addr,ut64 off)733 R_API ut64 r_num_tail_base(RNum *num, ut64 addr, ut64 off) {
734 	int i;
735 	bool ready = false;
736 	ut64 res = 0;
737 	for (i = 0; i < 16; i++) {
738 		ut64 o = __nth_nibble (off, i);
739 		if (!ready) {
740 			bool iseq = __nth_nibble (addr, i) == o;
741 			if (i == 0 && !iseq) {
742 				return UT64_MAX;
743 			}
744 			if (iseq) {
745 				continue;
746 			}
747 		}
748 		ready = true;
749 		ut8 pos = (15 - i) * 4;
750 		res |= (o << pos);
751 	}
752 	return res;
753 }
754 
r_num_tail(RNum * num,ut64 addr,const char * hex)755 R_API ut64 r_num_tail(RNum *num, ut64 addr, const char *hex) {
756 	ut64 mask = 0LL;
757 	ut64 n = 0;
758 	char *p;
759 	int i;
760 
761 	while (*hex && (*hex == ' ' || *hex == '.')) {
762 		hex++;
763 	}
764 	i = strlen (hex) * 4;
765 	p = malloc (strlen (hex) + 10);
766 	if (p) {
767 		strcpy (p, "0x");
768 		strcpy (p + 2, hex);
769 		if (isxdigit ((ut8)hex[0])) {
770 			n = r_num_math (num, p);
771 		} else {
772 			eprintf ("Invalid argument\n");
773 			free (p);
774 			return addr;
775 		}
776 		free (p);
777 	}
778 	mask = UT64_MAX << i;
779 	return (addr & mask) | n;
780 }
781 
r_num_tailff(RNum * num,const char * hex)782 static ut64 r_num_tailff(RNum *num, const char *hex) {
783 	ut64 n = 0;
784 
785 	while (*hex && (*hex == ' ' || *hex == '.')) {
786 		hex++;
787 	}
788 	int i = strlen (hex) * 4;
789 	char *p = malloc (strlen (hex) + 10);
790 	if (p) {
791 		strcpy (p, "0x");
792 		strcpy (p + 2, hex);
793 		if (isxdigit ((ut8)hex[0])) {
794 			n = r_num_get (num, p);
795 		} else {
796 			eprintf ("Invalid argument\n");
797 			free (p);
798 			return UT64_MAX;
799 		}
800 		free (p);
801 	}
802 	ut64 left = ((UT64_MAX >>i) << i);
803 	return left | n;
804 }
805 
r_num_between(RNum * num,const char * input_value)806 R_API int r_num_between(RNum *num, const char *input_value) {
807 	int i;
808 	ut64 ns[3];
809 	char * const str = strdup (input_value);
810 	RList *nums = r_num_str_split_list (str);
811 	int len = r_list_length (nums);
812 	if (len < 3) {
813 		free (str);
814 		r_list_free (nums);
815 		return -1;
816 	}
817 	if (len > 3) {
818 		len = 3;
819 	}
820 	for (i = 0; i < len; i++) {
821 		ns[i] = r_num_math (num, r_list_pop_head (nums));
822 	}
823 	free (str);
824 	r_list_free (nums);
825 	return num->value = R_BETWEEN (ns[0], ns[1], ns[2]);
826 }
827 
r_num_is_op(const char c)828 R_API bool r_num_is_op(const char c) {
829 	return c == '/' || c == '+' || c == '-' || c == '*' ||
830 		c == '%' || c == '&' || c == '^' || c == '|';
831 }
832 
833 // Assumed *str is parsed as an expression correctly
r_num_str_len(const char * str)834 R_API int r_num_str_len(const char *str) {
835 	int i = 0, len = 0, st;
836 	st = 0; // 0: number, 1: op
837 	if (str[0] == '(') {
838 		i++;
839 	}
840 	while (str[i] != '\0') {
841 		switch (st) {
842 		case 0: // number
843 			while (!r_num_is_op (str[i]) && str[i] != ' '
844 			  && str[i] != '\0') {
845 				i++;
846 				if (str[i] == '(') {
847 				  i += r_num_str_len (str+i);
848 				}
849 			}
850 			len = i;
851 			st = 1;
852 			break;
853 		case 1: // op
854 			while (str[i] != '\0' && str[i] == ' ') {
855 				i++;
856 			}
857 			if (!r_num_is_op (str[i])) {
858 				return len;
859 			}
860 			if (str[i] == ')') {
861 				return i + 1;
862 			}
863 			i++;
864 			while (str[i] != '\0' && str[i] == ' ') {
865 				i++;
866 			}
867 			st = 0;
868 			break;
869 		}
870 	}
871 	return len;
872 }
873 
r_num_str_split(char * str)874 R_API int r_num_str_split(char *str) {
875 	int i = 0, count = 0;
876 	const int len = strlen (str);
877 	while (i < len) {
878 		i += r_num_str_len (str + i);
879 		str[i] = '\0';
880 		i++;
881 		count++;
882 	}
883 	return count;
884 }
885 
r_num_str_split_list(char * str)886 R_API RList *r_num_str_split_list(char *str) {
887 	int i, count = r_num_str_split (str);
888 	RList *list = r_list_new ();
889 	for (i = 0; i < count; i++) {
890 		r_list_append (list, str);
891 		str += strlen (str) + 1;
892 	}
893 	return list;
894 }
895 
r_num_dup(ut64 n)896 R_API void *r_num_dup(ut64 n) {
897 	ut64 *hn = malloc (sizeof (ut64));
898 	if (!hn) {
899 		return NULL;
900 	}
901 	*hn = n;
902 	return (void*)hn;
903 }
904 
r_num_cos(double a)905 R_API double r_num_cos(double a) {
906 	return cos (a);
907 }
908 
r_num_sin(double a)909 R_API double r_num_sin(double a) {
910 	return sin (a);
911 }
912