Rizin
unix-like reverse engineering framework and cli tools
unum.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2007-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <errno.h>
5 #include <math.h> /* for ceill */
6 #include <rz_util.h>
7 #define RZ_NUM_USE_CALC 1
8 
9 static ut64 rz_num_tailff(RzNum *num, const char *hex);
10 
17 RZ_API bool rz_num_is_hex_prefix(const char *p) {
18  rz_return_val_if_fail(p, false);
19  if (!isascii(*p)) {
20  return false; // UTF-8
21  }
22  return (p[0] == '0' && p[1] == 'x');
23 }
24 
25 // TODO: rename to rz_num_srand()
26 static void rz_srand(int seed) {
27 #if HAVE_ARC4RANDOM_UNIFORM
28  // no-op
29  (void)seed;
30 #else
31  srand(seed);
32 #endif
33 }
34 
35 static int rz_rand(int mod) {
36 #if HAVE_ARC4RANDOM_UNIFORM
37  return (int)arc4random_uniform(mod);
38 #else
39  return rand() % mod;
40 #endif
41 }
42 
43 RZ_API void rz_num_irand(void) {
45 }
46 
48  static bool rand_initialized = false;
49  if (!rand_initialized) {
50  rz_num_irand();
51  rand_initialized = true;
52  }
53  if (!max) {
54  max = 1;
55  }
56  return rz_rand(max);
57 }
58 
60  if (*a > *b) {
61  ut64 tmp = *a;
62  *a = *b;
63  *b = tmp;
64  }
65 }
66 
67 RZ_API void rz_num_minmax_swap_i(int *a, int *b) {
68  if (*a > *b) {
69  ut64 tmp = *a;
70  *a = *b;
71  *b = tmp;
72  }
73 }
74 
76  RzNum *num = RZ_NEW0(RzNum);
77  if (!num) {
78  return NULL;
79  }
80  num->value = 0LL;
81  num->callback = cb;
82  num->cb_from_value = cb2;
83  num->userptr = ptr;
84  return num;
85 }
86 
88  free(num);
89 }
90 
91 #define KB (1ULL << 10)
92 #define MB (1ULL << 20)
93 #define GB (1ULL << 30)
94 #define TB (1ULL << 40)
95 #define PB (1ULL << 50)
96 #define EB (1ULL << 60)
97 
108 RZ_API char *rz_num_units(char *buf, size_t len, ut64 num) {
109  long double fnum;
110  char unit;
111  const char *fmt_str;
112  if (!buf) {
113  buf = malloc(len + 1);
114  if (!buf) {
115  return NULL;
116  }
117  }
118  fnum = (long double)num;
119  if (num >= EB) {
120  unit = 'E';
121  fnum /= EB;
122  } else if (num >= PB) {
123  unit = 'P';
124  fnum /= PB;
125  } else if (num >= TB) {
126  unit = 'T';
127  fnum /= TB;
128  } else if (num >= GB) {
129  unit = 'G';
130  fnum /= GB;
131  } else if (num >= MB) {
132  unit = 'M';
133  fnum /= MB;
134  } else if (num >= KB) {
135  unit = 'K';
136  fnum /= KB;
137  } else {
138  unit = '\0';
139  }
140  fmt_str = ((double)ceill(fnum) == (double)fnum)
141  ? "%.0" LDBLFMT "%c"
142  : "%.1" LDBLFMT "%c";
143  snprintf(buf, len, fmt_str, fnum, unit);
144  return buf;
145 }
146 
148  if (num->cb_from_value) {
149  int ok = 0;
150  const char *msg = num->cb_from_value(num, n, &ok);
151  if (msg && *msg) {
152  return msg;
153  }
154  if (ok) {
155  return msg;
156  }
157  }
158  return NULL;
159 }
160 
161 static void error(RzNum *num, const char *err_str) {
162  if (num) {
163  num->nc.errors++;
164 #if 0
165  num->nc.calc_err = err_str;
166 #endif
167  }
168 }
169 
170 // TODO: try to avoid the use of sscanf
171 /* old get_offset */
172 RZ_API ut64 rz_num_get(RzNum *num, const char *str) {
173  int i, j, ok;
174  char lch, len;
175  ut64 ret = 0LL;
176  ut32 s, a;
177 
178  if (num && !num->nc.under_calc) {
179  num->nc.errors = 0;
180  }
181  if (!str) {
182  return 0;
183  }
184  for (; *str == ' ';) {
185  str++;
186  }
187  if (!*str) {
188  return 0;
189  }
190  if (!strncmp(str, "1u", 2)) { // '1' is captured by op :(
191  if (num && num->value == UT64_MAX) {
192  num->value = 0;
193  }
194  switch (atoi(str + 2)) {
195  case 64: return (ut64)UT64_MAX;
196  case 32: return (ut64)UT32_MAX;
197  case 16: return (ut64)UT16_MAX;
198  case 8: return (ut64)UT8_MAX;
199  }
200  }
201  /* resolve string with an external callback */
202  if (num && num->callback) {
203  ok = 0;
204  ret = num->callback(num->userptr, str, &ok);
205  if (ok) {
206  return ret;
207  }
208  }
209 
210  if (str[0] && str[1] && str[2]) {
211  if (str[0] == '\'' && str[2] == '\'') {
212  return (ut64)str[1];
213  }
214  }
215 
216  len = strlen(str);
217  if (len > 3 && str[4] == ':') {
218  if (sscanf(str, "%04x", &s) == 1) {
219  if (sscanf(str + 5, "%04x", &a) == 1) {
220  return (ut64)((s << 4) + a);
221  }
222  }
223  } else if (len > 6 && str[6] == ':') {
224  if (sscanf(str, "0x%04x:0x%04x", &s, &a) == 2) {
225  return (ut64)((s << 4) + a);
226  }
227  if (sscanf(str, "0x%04x:%04x", &s, &a) == 2) {
228  return (ut64)((s << 4) + a);
229  }
230  }
231  if (str[0] == '0' && str[1] == 'b') {
232  ret = 0;
233  for (j = 0, i = strlen(str) - 1; i > 0; i--, j++) {
234  if (str[i] == '1') {
235  ret |= 1 << j;
236  } else if (str[i] != '0') {
237  break;
238  }
239  }
240  sscanf(str, "0x%" PFMT64x, &ret);
241  } else if (str[0] == '\'') {
242  ret = str[1] & 0xff;
243  // needs refactoring
244  } else if (!strncmp(str, "0xff..", 6) || !strncmp(str, "0xFF..", 6)) {
245  ret = rz_num_tailff(num, str + 6);
246  // needs refactoring
247  } else if (!strncmp(str, "0o", 2)) {
248  if (sscanf(str + 2, "%" PFMT64o, &ret) != 1) {
249  error(num, "invalid octal number");
250  }
251  } else if (!strncmp(str, "0xf..", 5) || !strncmp(str, "0xF..", 5)) {
252  ret = rz_num_tailff(num, str + 5);
253  } else if (str[0] == '0' && tolower(str[1]) == 'x') {
254  const char *lodash = strchr(str + 2, '_');
255  if (lodash) {
256  // Support 0x1000_f000_4000
257  // TODO: Only take underscores separated every 4 chars starting at the end
258  char *s = strdup(str + 2);
259  if (s) {
260  rz_str_replace_char(s, '_', 0);
261  errno = 0;
262  ret = strtoull(s, NULL, 16);
263  free(s);
264  }
265  } else {
266  errno = 0;
267  ret = strtoull(str + 2, NULL, 16);
268  // sscanf (str+2, "%"PFMT64x, &ret);
269  }
270  if (errno == ERANGE) {
271  error(num, "number won't fit into 64 bits");
272  }
273  } else {
274  char *endptr;
275  int len_num = len > 0 ? len - 1 : 0;
276  // Trim separators on the right
277  while (len_num > 0 && IS_SEPARATOR(str[len_num])) {
278  len_num--;
279  }
280  int chars_read = len_num;
281  bool zero_read = false;
282  lch = str[len_num];
283  if (*str == '0' && IS_DIGIT(*(str + 1)) && lch != 'b' && lch != 'h' && lch != 'H') {
284  lch = 'o';
285  len_num++;
286  }
287  switch (lch) {
288  case 'H':
289  case 'h': // hexa
290  if (!sscanf(str, "%" PFMT64x "%n", &ret, &chars_read) || chars_read != len_num) {
291  error(num, "invalid hex number");
292  }
293  break;
294  case 'o': // octal
295  if (!sscanf(str, "%" PFMT64o "%n", &ret, &chars_read) || chars_read != len_num) {
296  error(num, "invalid octal number");
297  }
298  break;
299  case 'b': // binary
300  ret = 0;
301  ok = true;
302  if (strlen(str) <= 65) { // 64 bit + the 'b' suffix
303  for (j = 0, i = strlen(str) - 2; i >= 0; i--, j++) {
304  if (str[i] == '1') {
305  ret |= (1ULL << j);
306  } else if (str[i] != '0') {
307  // eprintf ("Unexpected char in binary number string '%c'\n", str[i]);
308  ok = false;
309  break;
310  }
311  }
312  } else {
313  ok = false;
314  // eprintf ("Binary number is too large to fit in ut64\n");
315  }
316  if (!ok || !len_num) {
317  error(num, "invalid binary number");
318  }
319  break;
320  case 't': // ternary
321  ret = 0;
322  ok = true;
323  ut64 x = 1;
324  for (i = strlen(str) - 2; i >= 0; i--) {
325  if (str[i] < '0' || '2' < str[i]) {
326  ok = false;
327  break;
328  }
329  ret += x * (str[i] - '0');
330  x *= 3;
331  }
332  if (!ok || !len_num) {
333  error(num, "invalid ternary number");
334  }
335  break;
336  case 'K':
337  case 'k':
338  if (strchr(str, '.')) {
339  double d = 0;
340  if (sscanf(str, "%lf%n", &d, &chars_read)) {
341  ret = (ut64)(d * KB);
342  } else {
343  zero_read = true;
344  }
345  } else {
346  if (sscanf(str, "%" PFMT64d "%n", &ret, &chars_read)) {
347  ret *= KB;
348  } else {
349  zero_read = true;
350  }
351  }
352  if (zero_read || chars_read != len_num) {
353  error(num, "invalid kilobyte number");
354  }
355  break;
356  case 'M':
357  case 'm':
358  if (strchr(str, '.')) {
359  double d = 0;
360  if (sscanf(str, "%lf%n", &d, &chars_read)) {
361  ret = (ut64)(d * MB);
362  } else {
363  zero_read = true;
364  }
365  } else {
366  if (sscanf(str, "%" PFMT64d "%n", &ret, &chars_read)) {
367  ret *= MB;
368  } else {
369  zero_read = true;
370  }
371  }
372  if (zero_read || chars_read != len_num) {
373  error(num, "invalid megabyte number");
374  }
375  break;
376  case 'G':
377  case 'g':
378  if (strchr(str, '.')) {
379  double d = 0;
380  if (sscanf(str, "%lf%n", &d, &chars_read)) {
381  ret = (ut64)(d * GB);
382  } else {
383  zero_read = true;
384  }
385  } else {
386  if (sscanf(str, "%" PFMT64d "%n", &ret, &chars_read)) {
387  ret *= GB;
388  } else {
389  zero_read = true;
390  }
391  }
392  if (zero_read || chars_read != len_num) {
393  error(num, "invalid gigabyte number");
394  }
395  break;
396  default:
397 #if 0
398  // sscanf (str, "%"PFMT64d"%n", &ret, &chars_read);
399 // 32bit chop
400 #if __WINDOWS__
401  ret = _strtoui64 (str, &endptr, 10);
402 #endif
403 #endif
404  errno = 0;
405  ret = strtoull(str, &endptr, 10);
406  if (errno == ERANGE) {
407  error(num, "number won't fit into 64 bits");
408  }
409  if (!IS_DIGIT(*str) || (*endptr && *endptr != lch)) {
410  error(num, "unknown symbol");
411  }
412  break;
413  }
414  }
415  if (num) {
416  num->value = ret;
417  }
418  return ret;
419 }
420 
421 #if !RZ_NUM_USE_CALC
422 static ut64 rz_num_op(RzNum *num, char op, ut64 a, ut64 b) {
423  switch (op) {
424  case '+': return a + b;
425  case '-': return a - b;
426  case '*': return a * b;
427  case '/':
428  if (!b && num)
429  num->dbz = 1;
430  return b ? a / b : 0;
431  case '&': return a & b;
432  case '|': return a | b;
433  case '^': return a ^ b;
434  }
435  return b;
436 }
437 
438 RZ_API static ut64 rz_num_math_internal(RzNum *num, char *s) {
439  ut64 ret = 0LL;
440  char *p = s;
441  int i, nop, op = 0;
442  for (i = 0; s[i]; i++) {
443  if (rz_num_is_op(s[i])) {
444  nop = s[i];
445  s[i] = '\0';
446  ret = rz_num_op(num, op, ret, rz_num_get(num, p));
447  op = s[i] = nop;
448  p = s + i + 1;
449  break;
450  }
451  }
452  return rz_num_op(op, ret, rz_num_get(num, p));
453 }
454 #endif /* !RZ_NUM_USE_CALC */
455 
456 RZ_API ut64 rz_num_math(RzNum *num, const char *str) {
457 #if RZ_NUM_USE_CALC
458  ut64 ret;
459  const char *err = NULL;
460  if (!str || !*str) {
461  return 0LL;
462  }
463  // if (!str || !*str) return 0LL;
464  if (num) {
465  num->dbz = 0;
466  }
467  ret = rz_num_calc(num, str, &err);
468  if (err) {
469  eprintf("rz_num_calc error: (%s) in (%s)\n", err, str);
470  }
471  if (num) {
472  num->value = ret;
473  }
474  return ret;
475 #else
476  ut64 ret = 0LL;
477  char op = '+';
478  int len;
479  char *p, *s, *os;
480  char *group;
481  if (!str)
482  return 0LL;
483 
484  len = strlen(str) + 1;
485  os = malloc(len + 1);
486 
487  s = os;
488  memcpy(s, str, len);
489  for (; *s == ' '; s++)
490  ;
491  p = s;
492 
493  do {
494  group = strchr(p, '(');
495  if (group) {
496  group[0] = '\0';
497  ret = rz_num_op(op, ret, rz_num_math_internal(num, p));
498  for (; p < group; p += 1) {
499  if (rz_num_is_op(*p)) {
500  op = *p;
501  break;
502  }
503  }
504  group[0] = '(';
505  p = group + 1;
506  if (rz_str_delta(p, '(', ')') < 0) {
507  char *p2 = strchr(p, '(');
508  if (p2 != NULL) {
509  *p2 = '\0';
510  ret = rz_num_op(op, ret, rz_num_math_internal(num, p));
511  ret = rz_num_op(op, ret, rz_num_math(num, p2 + 1));
512  p = p2 + 1;
513  continue;
514  }
515  eprintf("something really bad has happened! can't find '('\n");
516  } else {
517  ret = rz_num_op(op, ret, rz_num_math_internal(num, p));
518  }
519  } else {
520  ret = rz_num_op(op, ret, rz_num_math_internal(num, p));
521  }
522  } while (0);
523 
524  if (num) {
525  num->value = ret;
526  }
527  free(os);
528  return ret;
529 #endif
530 }
531 
532 RZ_API int rz_num_is_float(RzNum *num, const char *str) {
533  return (IS_DIGIT(*str) && (strchr(str, '.') || str[strlen(str) - 1] == 'f'));
534 }
535 
536 RZ_API double rz_num_get_float(RzNum *num, const char *str) {
537  double d = 0.0f;
538  (void)sscanf(str, "%lf", &d);
539  return d;
540 }
541 
543  int size = 64, i;
544 
545  if (num >> 32) {
546  size = 64;
547  } else if (num & 0xff000000) {
548  size = 32;
549  } else if (num & 0xff0000) {
550  size = 24;
551  } else if (num & 0xff00) {
552  size = 16;
553  } else if (num & 0xff) {
554  size = 8;
555  }
556  if (out) {
557  int pos = 0;
558  int realsize = 0;
559  int hasbit = 0;
560  for (i = 0; i < size; i++) {
561  char bit = ((num >> (size - i - 1)) & 1) ? '1' : '0';
562  if (hasbit || bit == '1') {
563  out[pos++] = bit; // size - 1 - i] = bit;
564  }
565  if (!hasbit && bit == '1') {
566  hasbit = 1;
567  realsize = size - i;
568  }
569  }
570  if (realsize == 0) {
571  out[realsize++] = '0';
572  }
573  out[realsize] = '\0'; // Maybe not nesesary?
574  }
575  return size;
576 }
577 
579  if (out == NULL) {
580  return false;
581  }
582  int i;
583  for (i = 0; num; i++, num /= 3) {
584  out[i] = (char)('0' + num % 3);
585  }
586  if (i == 0) {
587  out[0] = '0';
588  i++;
589  }
590  out[i] = '\0';
591 
593  return true;
594 }
595 
596 RZ_API ut64 rz_num_chs(int cylinder, int head, int sector, int sectorsize) {
597  if (sectorsize < 1) {
598  sectorsize = 512;
599  }
600  return (ut64)cylinder * (ut64)head * (ut64)sector * (ut64)sectorsize;
601 }
602 
603 RZ_API int rz_num_conditional(RzNum *num, const char *str) {
604  char *lgt, *t, *p, *s = strdup(str);
605  int res = 0;
606  ut64 n, a, b;
607  p = s;
608  do {
609  t = strchr(p, ',');
610  if (t) {
611  *t = 0;
612  }
613  lgt = strchr(p, '<');
614  if (lgt) {
615  *lgt = 0;
616  a = rz_num_math(num, p);
617  if (lgt[1] == '=') {
618  b = rz_num_math(num, lgt + 2);
619  if (a > b) {
620  goto fail;
621  }
622  } else {
623  b = rz_num_math(num, lgt + 1);
624  if (a >= b) {
625  goto fail;
626  }
627  }
628  } else {
629  lgt = strchr(p, '>');
630  if (lgt) {
631  *lgt = 0;
632  a = rz_num_math(num, p);
633  if (lgt[1] == '=') {
634  b = rz_num_math(num, lgt + 2);
635  if (a < b) {
636  goto fail;
637  }
638  } else {
639  b = rz_num_math(num, lgt + 1);
640  if (a <= b) {
641  goto fail;
642  }
643  }
644  } else {
645  lgt = strchr(p, '=');
646  if (lgt && lgt > p) {
647  lgt--;
648  if (*lgt == '!') {
649  rz_str_replace_char(p, '!', ' ');
650  rz_str_replace_char(p, '=', '-');
651  n = rz_num_math(num, p);
652  if (!n) {
653  goto fail;
654  }
655  }
656  }
657  lgt = strstr(p, "==");
658  if (lgt) {
659  *lgt = ' ';
660  }
661  rz_str_replace_char(p, '=', '-');
662  n = rz_num_math(num, p);
663  if (n) {
664  goto fail;
665  }
666  }
667  }
668  p = t + 1;
669  } while (t);
670  res = 1;
671 fail:
672  free(s);
673  return res;
674 }
675 
676 RZ_API int rz_num_is_valid_input(RzNum *num, const char *input_value) {
677  ut64 value = input_value ? rz_num_math(num, input_value) : 0;
678  return !(value == 0 && input_value && *input_value != '0') || !(value == 0 && input_value && *input_value != '@');
679 }
680 
681 RZ_API ut64 rz_num_get_input_value(RzNum *num, const char *input_value) {
682  ut64 value = input_value ? rz_num_math(num, input_value) : 0;
683  return value;
684 }
685 
686 #define NIBBLE_TO_HEX(n) (((n)&0xf) > 9 ? 'a' + ((n)&0xf) - 10 : '0' + ((n)&0xf))
687 static int escape_char(char *dst, char byte) {
688  const char escape_map[] = "abtnvfr";
689  if (byte >= 7 && byte <= 13) {
690  *(dst++) = '\\';
691  *(dst++) = escape_map[byte - 7];
692  *dst = 0;
693  return 2;
694  } else if (byte) {
695  *(dst++) = '\\';
696  *(dst++) = 'x';
697  *(dst++) = NIBBLE_TO_HEX(byte >> 4);
698  *(dst++) = NIBBLE_TO_HEX(byte);
699  *dst = 0;
700  return 4;
701  }
702  return 0;
703 }
704 
705 RZ_API char *rz_num_as_string(RzNum *___, ut64 n, bool printable_only) {
706  char str[34]; // 8 byte * 4 chars in \x?? format
707  int stri, ret = 0, off = 0;
708  int len = sizeof(ut64);
709  ut64 num = n;
710  str[stri = 0] = 0;
711  while (len--) {
712  char ch = (num & 0xff);
713  if (ch >= 32 && ch < 127) {
714  str[stri++] = ch;
715  str[stri] = 0;
716  } else if (!printable_only && (off = escape_char(str + stri, ch)) != 0) {
717  stri += off;
718  } else {
719  if (ch) {
720  return NULL;
721  }
722  }
723  ret |= (num & 0xff);
724  num >>= 8;
725  }
726  if (ret) {
727  return strdup(str);
728  }
729  if (!printable_only) {
730  return strdup("\\0");
731  }
732  return NULL;
733 }
734 
735 RZ_API bool rz_is_valid_input_num_value(RzNum *num, const char *input_value) {
736  if (!input_value) {
737  return false;
738  }
739  ut64 value = rz_num_math(num, input_value);
740  return !(value == 0 && *input_value != '0');
741 }
742 
744  return (str && *str) ? rz_num_math(num, str) : 0;
745 }
746 
747 static inline ut64 __nth_nibble(ut64 n, ut32 i) {
748  int sz = (sizeof(n) << 1) - 1;
749  int s = (sz - i) * 4;
750  return (n >> s) & 0xf;
751 }
752 
754  int i;
755  bool ready = false;
756  ut64 res = 0;
757  for (i = 0; i < 16; i++) {
758  ut64 o = __nth_nibble(off, i);
759  if (!ready) {
760  bool iseq = __nth_nibble(addr, i) == o;
761  if (i == 0 && !iseq) {
762  return UT64_MAX;
763  }
764  if (iseq) {
765  continue;
766  }
767  }
768  ready = true;
769  ut8 pos = (15 - i) * 4;
770  res |= (o << pos);
771  }
772  return res;
773 }
774 
776  ut64 mask = 0LL;
777  ut64 n = 0;
778  char *p;
779  int i;
780 
781  while (*hex && (*hex == ' ' || *hex == '.')) {
782  hex++;
783  }
784  i = strlen(hex) * 4;
785  p = malloc(strlen(hex) + 10);
786  if (p) {
787  strcpy(p, "0x");
788  strcpy(p + 2, hex);
789  if (isxdigit((ut8)hex[0])) {
790  n = rz_num_math(num, p);
791  } else {
792  eprintf("Invalid argument\n");
793  free(p);
794  return addr;
795  }
796  free(p);
797  }
798  mask = UT64_MAX << i;
799  return (addr & mask) | n;
800 }
801 
802 static ut64 rz_num_tailff(RzNum *num, const char *hex) {
803  ut64 n = 0;
804 
805  while (*hex && (*hex == ' ' || *hex == '.')) {
806  hex++;
807  }
808  int i = strlen(hex) * 4;
809  char *p = malloc(strlen(hex) + 10);
810  if (p) {
811  strcpy(p, "0x");
812  strcpy(p + 2, hex);
813  if (isxdigit((ut8)hex[0])) {
814  n = rz_num_get(num, p);
815  } else {
816  eprintf("Invalid argument\n");
817  free(p);
818  return UT64_MAX;
819  }
820  free(p);
821  }
822  ut64 left = ((UT64_MAX >> i) << i);
823  return left | n;
824 }
825 
826 RZ_API int rz_num_between(RzNum *num, const char *input_value) {
827  int i;
828  ut64 ns[3];
829  char *const str = strdup(input_value);
831  int len = rz_list_length(nums);
832  if (len < 3) {
833  free(str);
834  rz_list_free(nums);
835  return -1;
836  }
837  if (len > 3) {
838  len = 3;
839  }
840  for (i = 0; i < len; i++) {
841  ns[i] = rz_num_math(num, rz_list_pop_head(nums));
842  }
843  free(str);
844  rz_list_free(nums);
845  return num->value = RZ_BETWEEN(ns[0], ns[1], ns[2]);
846 }
847 
848 RZ_API bool rz_num_is_op(const char c) {
849  return c == '/' || c == '+' || c == '-' || c == '*' ||
850  c == '%' || c == '&' || c == '^' || c == '|';
851 }
852 
853 // Assumed *str is parsed as an expression correctly
854 RZ_API int rz_num_str_len(const char *str) {
855  int i = 0, len = 0, st;
856  st = 0; // 0: number, 1: op
857  if (str[0] == '(') {
858  i++;
859  }
860  while (str[i] != '\0') {
861  switch (st) {
862  case 0: // number
863  while (!rz_num_is_op(str[i]) && str[i] != ' ' && str[i] != '\0') {
864  i++;
865  if (str[i] == '(') {
866  i += rz_num_str_len(str + i);
867  }
868  }
869  len = i;
870  st = 1;
871  break;
872  case 1: // op
873  while (str[i] != '\0' && str[i] == ' ') {
874  i++;
875  }
876  if (!rz_num_is_op(str[i])) {
877  return len;
878  }
879  if (str[i] == ')') {
880  return i + 1;
881  }
882  i++;
883  while (str[i] != '\0' && str[i] == ' ') {
884  i++;
885  }
886  st = 0;
887  break;
888  }
889  }
890  return len;
891 }
892 
894  int i = 0, count = 0;
895  const int len = strlen(str);
896  while (i < len) {
897  i += rz_num_str_len(str + i);
898  str[i] = '\0';
899  i++;
900  count++;
901  }
902  return count;
903 }
904 
905 RZ_API RzList /*<char *>*/ *rz_num_str_split_list(char *str) {
906  int i, count = rz_num_str_split(str);
907  RzList *list = rz_list_new();
908  for (i = 0; i < count; i++) {
910  str += strlen(str) + 1;
911  }
912  return list;
913 }
914 
916  ut64 *hn = malloc(sizeof(ut64));
917  if (!hn) {
918  return NULL;
919  }
920  *hn = n;
921  return (void *)hn;
922 }
923 
924 RZ_API double rz_num_cos(double a) {
925  return cos(a);
926 }
927 
928 RZ_API double rz_num_sin(double a) {
929  return sin(a);
930 }
931 
936  rz_return_val_if_fail(num && str, 10);
937  size_t base = 10;
938  if (rz_str_startswith(str, "10u") || rz_str_startswith(str, "du")) {
939  base = 11;
940  } else {
941  switch (str[0]) {
942  case 's':
943  base = 1;
944  break;
945  case 'b':
946  base = 2;
947  break;
948  case 'p':
949  base = 3;
950  break;
951  case 'o':
952  base = 8;
953  break;
954  case 'd':
955  base = 10;
956  break;
957  case 'h':
958  base = 16;
959  break;
960  case 'i':
961  base = 32;
962  break;
963  case 'q':
964  base = 64;
965  break;
966  case 'S':
967  // IPv4 address
968  base = 80;
969  break;
970  default:
971  // syscall
972  base = rz_num_math(num, str);
973  }
974  }
975  return base;
976 }
size_t len
Definition: 6502dis.c:15
#define mask()
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RzCryptoSelector bit
Definition: crypto.c:16
int mod(int a, int b)
Definition: crypto_rot.c:8
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
uint32_t ut32
int max
Definition: enough.c:225
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_OWN void * rz_list_pop_head(RZ_NONNULL RzList *list)
Removes and returns the first element of the list.
Definition: list.c:401
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
@ ok
Definition: lz4.c:1706
char * dst
Definition: lz4.h:724
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
int off
Definition: pal.c:13
static const char hex[16]
Definition: print.c:21
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
ut64(* RzNumCallback)(struct rz_num_t *self, const char *str, int *ok)
Definition: rz_num.h:70
RZ_API ut64 rz_num_calc(RzNum *num, const char *str, const char **err)
Definition: calc.c:482
const char *(* RzNumCallback2)(struct rz_num_t *self, ut64, int *ok)
Definition: rz_num.h:71
RZ_API int rz_str_delta(char *p, char a, char b)
Definition: str.c:394
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API int rz_str_replace_char(char *s, int a, int b)
Definition: str.c:169
RZ_API void rz_str_reverse(char *str)
Definition: str.c:183
#define IS_SEPARATOR(x)
Definition: rz_str_util.h:6
#define IS_DIGIT(x)
Definition: rz_str_util.h:11
RZ_API ut64 rz_time_now(void)
Returns the current time in microseconds.
Definition: time.c:88
#define PFMT64d
Definition: rz_types.h:394
#define LDBLFMT
Definition: rz_types.h:401
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64o
Definition: rz_types.h:396
#define PFMT64x
Definition: rz_types.h:393
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT64_MAX
Definition: rz_types_base.h:86
#define UT8_MAX
#define RZ_BETWEEN(x, y, z)
#define UT16_MAX
#define tolower(c)
Definition: safe-ctype.h:149
#define isxdigit(c)
Definition: safe-ctype.h:145
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
#define ERANGE
Definition: sftypes.h:144
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
int pos
Definition: main.c:11
#define fail(test)
Definition: tests.h:29
Definition: dis.c:32
RZ_API RzList * rz_num_str_split_list(char *str)
Definition: unum.c:905
static ut64 rz_num_tailff(RzNum *num, const char *hex)
Definition: unum.c:802
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API void rz_num_minmax_swap(ut64 *a, ut64 *b)
Definition: unum.c:59
RZ_API bool rz_num_is_op(const char c)
Definition: unum.c:848
static int escape_char(char *dst, char byte)
Definition: unum.c:687
RZ_API ut64 rz_num_tail(RzNum *num, ut64 addr, const char *hex)
Definition: unum.c:775
#define KB
Definition: unum.c:91
RZ_API ut64 rz_get_input_num_value(RzNum *num, const char *str)
Definition: unum.c:743
#define NIBBLE_TO_HEX(n)
Definition: unum.c:686
RZ_API bool rz_is_valid_input_num_value(RzNum *num, const char *input_value)
Definition: unum.c:735
#define PB
Definition: unum.c:95
RZ_API double rz_num_get_float(RzNum *num, const char *str)
Definition: unum.c:536
RZ_API int rz_num_str_len(const char *str)
Definition: unum.c:854
RZ_API RzNum * rz_num_new(RzNumCallback cb, RzNumCallback2 cb2, void *ptr)
Definition: unum.c:75
RZ_API void rz_num_minmax_swap_i(int *a, int *b)
Definition: unum.c:67
#define TB
Definition: unum.c:94
#define GB
Definition: unum.c:93
static ut64 __nth_nibble(ut64 n, ut32 i)
Definition: unum.c:747
RZ_API ut64 rz_num_tail_base(RzNum *num, ut64 addr, ut64 off)
Definition: unum.c:753
RZ_API char * rz_num_units(char *buf, size_t len, ut64 num)
Definition: unum.c:108
RZ_API int rz_num_to_bits(char *out, ut64 num)
Definition: unum.c:542
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API int rz_num_is_valid_input(RzNum *num, const char *input_value)
Definition: unum.c:676
RZ_API int rz_num_conditional(RzNum *num, const char *str)
Definition: unum.c:603
RZ_API int rz_num_to_trits(char *out, ut64 num)
Definition: unum.c:578
RZ_API int rz_num_str_split(char *str)
Definition: unum.c:893
RZ_API double rz_num_cos(double a)
Definition: unum.c:924
RZ_API ut64 rz_num_get_input_value(RzNum *num, const char *input_value)
Definition: unum.c:681
#define EB
Definition: unum.c:96
RZ_API void * rz_num_dup(ut64 n)
Definition: unum.c:915
#define MB
Definition: unum.c:92
RZ_API int rz_num_between(RzNum *num, const char *input_value)
Definition: unum.c:826
RZ_API size_t rz_num_base_of_string(RzNum *num, RZ_NONNULL const char *str)
Convert the base suffix to the numeric value.
Definition: unum.c:935
RZ_API char * rz_num_as_string(RzNum *___, ut64 n, bool printable_only)
Definition: unum.c:705
static int rz_rand(int mod)
Definition: unum.c:35
RZ_API int rz_num_rand(int max)
Definition: unum.c:47
RZ_API void rz_num_free(RzNum *num)
Definition: unum.c:87
RZ_API void rz_num_irand(void)
Definition: unum.c:43
RZ_API double rz_num_sin(double a)
Definition: unum.c:928
static void error(RzNum *num, const char *err_str)
Definition: unum.c:161
static void rz_srand(int seed)
Definition: unum.c:26
RZ_API const char * rz_num_get_name(RzNum *num, ut64 n)
Definition: unum.c:147
RZ_API bool rz_num_is_hex_prefix(const char *p)
Checks if the first two chars of p equal "0x".
Definition: unum.c:17
RZ_API ut64 rz_num_chs(int cylinder, int head, int sector, int sectorsize)
Definition: unum.c:596
RZ_API int rz_num_is_float(RzNum *num, const char *str)
Definition: unum.c:532
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176
static int addr
Definition: z80asm.c:58