Rizin
unix-like reverse engineering framework and cli tools
cmd_api.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_cmd.h>
5 #include <rz_util.h>
6 #include <stdio.h>
7 #include <rz_cons.h>
8 #include <rz_cmd.h>
9 #include <rz_util.h>
10 #include <rz_core.h>
11 
30 #define MAX_CHILDREN_SHOW 7
31 
32 #define MIN_SUMMARY_WIDTH 6
33 #define MAX_RIGHT_ALIGHNMENT 20
34 
35 // NOTE: this should be in sync with SPECIAL_CHARACTERS in
36 // rizin-shell-parser grammar, except for ", ' and
37 // whitespaces, because we let cmd_substitution_arg create
38 // new arguments
39 static const char *SPECIAL_CHARS_REGULAR = "@;~$#|`\"'()<>";
40 static const char *SPECIAL_CHARS_REGULAR_SINGLE = "@;~$#|`\"'()<> ";
41 static const char *SPECIAL_CHARS_PF = "@;~$#|`\"'<>";
42 static const char *SPECIAL_CHARS_DOUBLE_QUOTED = "\"$()`";
43 static const char *SPECIAL_CHARS_SINGLE_QUOTED = "'";
44 
46  .usage = "Usage not defined",
47  .summary = "Help summary not defined",
48  .description = "Help description not defined.",
49 };
50 
51 static const RzCmdDescHelp root_help = {
52  .usage = "[.][times][cmd][~grep][@[@iter]addr][|>pipe] ; ...",
53  .description = "",
54  .sort_subcommands = true,
55 };
56 
57 static const struct argv_modes_t {
58  const char *suffix;
59  const char *summary_suffix;
61 } argv_modes[] = {
62  { "", "", RZ_OUTPUT_MODE_STANDARD },
63  { "j", " (JSON mode)", RZ_OUTPUT_MODE_JSON },
64  { "*", " (rizin mode)", RZ_OUTPUT_MODE_RIZIN },
65  { "q", " (quiet mode)", RZ_OUTPUT_MODE_QUIET },
66  { "Q", " (quietest mode)", RZ_OUTPUT_MODE_QUIETEST },
67  { "k", " (sdb mode)", RZ_OUTPUT_MODE_SDB },
68  { "l", " (verbose mode)", RZ_OUTPUT_MODE_LONG },
69  { "J", " (verbose JSON mode)", RZ_OUTPUT_MODE_LONG_JSON },
70  { "t", " (table mode)", RZ_OUTPUT_MODE_TABLE },
71 };
72 
74  size_t i;
75  for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
76  if (argv_modes[i].mode == mode) {
77  return argv_modes[i].suffix[0];
78  }
79  }
80  return -1;
81 }
82 
84  size_t i;
85  for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
86  if (argv_modes[i].mode == mode) {
87  return argv_modes[i].summary_suffix;
88  }
89  }
90  return "";
91 }
92 
93 static int value = 0;
94 
95 #define NCMDS (sizeof(cmd->cmds) / sizeof(*cmd->cmds))
97 
98 static void fill_details(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color);
99 
100 static int cd_sort(const void *a, const void *b) {
101  RzCmdDesc *ca = (RzCmdDesc *)a;
102  RzCmdDesc *cb = (RzCmdDesc *)b;
103  return rz_str_casecmp(ca->name, cb->name);
104 }
105 
106 static bool cmd_desc_set_parent(RzCmd *cmd, RzCmdDesc *cd, RzCmdDesc *parent) {
107  rz_return_val_if_fail(cd && !cd->parent, false);
108  if (parent) {
109  switch (parent->type) {
113  break;
119  return false;
120  }
121  }
122  if (parent) {
123  cd->parent = parent;
124  rz_pvector_push(&parent->children, cd);
125  if (!cmd->batch && parent->help->sort_subcommands) {
126  rz_pvector_sort(&parent->children, cd_sort);
127  }
128  parent->n_children++;
129  }
130  return true;
131 }
132 
134  rz_return_if_fail(cd && cd->parent);
135  RzCmdDesc *parent = cd->parent;
137  parent->n_children--;
138  cd->parent = NULL;
139 }
140 
142  void **it_cd;
143  bool res = ht_pp_delete(cmd->ht_cmds, cd->name);
144  rz_return_if_fail(res);
145  rz_cmd_desc_children_foreach(cd, it_cd) {
146  RzCmdDesc *child_cd = *it_cd;
148  }
149 }
150 
151 static void cmd_desc_free(RzCmdDesc *cd) {
152  if (!cd) {
153  return;
154  }
155 
156  rz_pvector_clear(&cd->children);
157  free(cd->name);
158  free(cd);
159 }
160 
161 static RzCmdDesc *create_cmd_desc(RzCmd *cmd, RzCmdDesc *parent, RzCmdDescType type, const char *name, const RzCmdDescHelp *help, bool ht_insert) {
162  RzCmdDesc *res = RZ_NEW0(RzCmdDesc);
163  if (!res) {
164  return NULL;
165  }
166  res->type = type;
167  res->name = strdup(name);
168  if (!res->name) {
169  goto err;
170  }
171  res->n_children = 0;
172  res->help = help ? help : &not_defined_help;
174  if (ht_insert && !ht_pp_insert(cmd->ht_cmds, name, res)) {
175  goto err;
176  }
177  cmd_desc_set_parent(cmd, res, parent);
178  return res;
179 err:
180  cmd_desc_free(res);
181  return NULL;
182 }
183 
185  cmd->aliases.count = 0;
186  cmd->aliases.keys = NULL;
187  cmd->aliases.values = NULL;
188 }
189 
190 RZ_API RzCmd *rz_cmd_new(bool has_cons) {
191  int i;
192  RzCmd *cmd = RZ_NEW0(RzCmd);
193  if (!cmd) {
194  return cmd;
195  }
196  cmd->has_cons = has_cons;
197  for (i = 0; i < NCMDS; i++) {
198  cmd->cmds[i] = NULL;
199  }
200  cmd->nullcallback = cmd->data = NULL;
201  cmd->ht_cmds = ht_pp_new0();
202  cmd->root_cmd_desc = create_cmd_desc(cmd, NULL, RZ_CMD_DESC_TYPE_GROUP, "", &root_help, true);
203  rz_cmd_macro_init(&cmd->macro);
205  return cmd;
206 }
207 
209  int i;
210  if (!cmd) {
211  return NULL;
212  }
213  ht_up_free(cmd->ts_symbols_ht);
215  rz_cmd_macro_fini(&cmd->macro);
216  ht_pp_free(cmd->ht_cmds);
217  for (i = 0; i < NCMDS; i++) {
218  if (cmd->cmds[i]) {
219  RZ_FREE(cmd->cmds[i]);
220  }
221  }
222  cmd_desc_free(cmd->root_cmd_desc);
223  free(cmd);
224  return NULL;
225 }
226 
231  return cmd->root_cmd_desc;
232 }
233 
241  cmd->batch = true;
242 }
243 
244 static void sort_groups(RzCmdDesc *group) {
245  void **it_cd;
246 
247  if (group->help->sort_subcommands) {
248  rz_pvector_sort(&group->children, cd_sort);
249  }
250  rz_cmd_desc_children_foreach(group, it_cd) {
251  RzCmdDesc *cd = *(RzCmdDesc **)it_cd;
252  if (cd->n_children) {
253  sort_groups(cd);
254  }
255  }
256 }
257 
265  cmd->batch = false;
267 }
268 
269 static RzOutputMode suffix2mode(const char *suffix) {
270  size_t i;
271  for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
272  if (!strcmp(suffix, argv_modes[i].suffix)) {
273  return argv_modes[i].mode;
274  }
275  }
276  return 0;
277 }
278 
279 static bool has_cd_submodes(const RzCmdDesc *cd) {
280  return cd->type == RZ_CMD_DESC_TYPE_ARGV_MODES || cd->type == RZ_CMD_DESC_TYPE_ARGV_STATE;
281 }
282 
283 static bool is_valid_argv_modes(RzCmdDesc *cd, char last_letter) {
284  if (!cd || !has_cd_submodes(cd) || last_letter == '\0') {
285  return false;
286  }
287  char suffix[] = { last_letter, '\0' };
288  return cd->d.argv_modes_data.modes & suffix2mode(suffix);
289 }
290 
292  if (!cd) {
293  return NULL;
294  }
295  switch (cd->type) {
297  return cd->d.group_data.exec_cd;
298  default:
299  return cd;
300  }
301 }
302 
303 static RzCmdDesc *cmd_get_desc_best(RzCmd *cmd, const char *cmd_identifier, bool best_match) {
304  rz_return_val_if_fail(cmd && cmd_identifier, NULL);
305  char *cmdid = strdup(cmd_identifier);
306  char *end_cmdid = cmdid + strlen(cmdid);
307  RzCmdDesc *res = NULL;
308  bool is_exact_match = true;
309  char last_letter = '\0', o_last_letter = end_cmdid > cmdid ? *(end_cmdid - 1) : '\0';
310  // match longer commands first
311  while (*cmdid) {
312  RzCmdDesc *cd = ht_pp_find(cmd->ht_cmds, cmdid, NULL);
313  if (cd) {
314  switch (cd->type) {
320  if (!best_match && (!is_exact_match && !is_valid_argv_modes(rz_cmd_desc_get_exec(cd), last_letter))) {
321  break;
322  }
323  res = cd;
324  goto out;
326  res = cd;
327  goto out;
329  break;
330  }
331  }
332  // only the last letter is considered, then we zero last_letter
333  last_letter = o_last_letter;
334  o_last_letter = '\0';
335 
336  is_exact_match = false;
337  *(--end_cmdid) = '\0';
338  }
339 out:
340  free(cmdid);
341  return res;
342 }
343 
355 RZ_API RzCmdDesc *rz_cmd_get_desc_best(RzCmd *cmd, const char *cmd_identifier) {
356  return cmd_get_desc_best(cmd, cmd_identifier, true);
357 }
358 
372 RZ_API RzCmdDesc *rz_cmd_get_desc(RzCmd *cmd, const char *cmd_identifier) {
373  return cmd_get_desc_best(cmd, cmd_identifier, false);
374 }
375 
385  rz_return_val_if_fail(cd, false);
386 
387  switch (cd->type) {
389  if (cd->d.argv_modes_data.modes & RZ_OUTPUT_MODE_STANDARD) {
390  return false;
391  }
392  cd->d.argv_modes_data.default_mode = mode;
393  return true;
395  if (cd->d.argv_state_data.modes & RZ_OUTPUT_MODE_STANDARD) {
396  return false;
397  }
398  cd->d.argv_state_data.default_mode = mode;
399  return true;
400  case RZ_CMD_DESC_TYPE_GROUP: {
401  RzCmdDesc *exec_cd = rz_cmd_desc_get_exec(cd);
402  if (exec_cd) {
403  return rz_cmd_desc_set_default_mode(exec_cd, mode);
404  }
405  return false;
406  }
407  default:
408  return false;
409  }
410 }
411 
412 RZ_API char **rz_cmd_alias_keys(RzCmd *cmd, int *sz) {
413  if (sz) {
414  *sz = cmd->aliases.count;
415  }
416  return cmd->aliases.keys;
417 }
418 
420  int i; // find
421  for (i = 0; i < cmd->aliases.count; i++) {
422  free(cmd->aliases.keys[i]);
423  free(cmd->aliases.values[i]);
424  }
425  cmd->aliases.count = 0;
426  RZ_FREE(cmd->aliases.keys);
427  RZ_FREE(cmd->aliases.values);
428  free(cmd->aliases.remote);
429 }
430 
431 RZ_API bool rz_cmd_alias_del(RzCmd *cmd, const char *k) {
432  int i; // find
433  for (i = 0; i < cmd->aliases.count; i++) {
434  if (!k || !strcmp(k, cmd->aliases.keys[i])) {
435  RZ_FREE(cmd->aliases.values[i]);
436  cmd->aliases.count--;
437  if (cmd->aliases.count > 0) {
438  if (i > 0) {
439  free(cmd->aliases.keys[i]);
440  cmd->aliases.keys[i] = cmd->aliases.keys[0];
441  free(cmd->aliases.values[i]);
442  cmd->aliases.values[i] = cmd->aliases.values[0];
443  }
444  memmove(cmd->aliases.values,
445  cmd->aliases.values + 1,
446  cmd->aliases.count * sizeof(void *));
447  memmove(cmd->aliases.keys,
448  cmd->aliases.keys + 1,
449  cmd->aliases.count * sizeof(void *));
450  }
451  return true;
452  }
453  }
454  return false;
455 }
456 
457 // XXX: use a hashtable or any other standard data structure
458 RZ_API int rz_cmd_alias_set(RzCmd *cmd, const char *k, const char *v, int remote) {
459  void *tofree = NULL;
460  if (!strncmp(v, "base64:", 7)) {
461  ut8 *s = rz_base64_decode_dyn(v + 7, -1);
462  if (s) {
463  tofree = s;
464  v = (const char *)s;
465  }
466  }
467  int i;
468  for (i = 0; i < cmd->aliases.count; i++) {
469  int matches = !strcmp(k, cmd->aliases.keys[i]);
470  if (matches) {
471  free(cmd->aliases.values[i]);
472  cmd->aliases.values[i] = strdup(v);
473  free(tofree);
474  return 1;
475  }
476  }
477 
478  i = cmd->aliases.count++;
479  char **K = (char **)realloc(cmd->aliases.keys,
480  sizeof(char *) * cmd->aliases.count);
481  if (K) {
482  cmd->aliases.keys = K;
483  int *R = (int *)realloc(cmd->aliases.remote,
484  sizeof(int) * cmd->aliases.count);
485  if (R) {
486  cmd->aliases.remote = R;
487  char **V = (char **)realloc(cmd->aliases.values,
488  sizeof(char *) * cmd->aliases.count);
489  if (V) {
490  cmd->aliases.values = V;
491  cmd->aliases.keys[i] = strdup(k);
492  cmd->aliases.values[i] = strdup(v);
493  cmd->aliases.remote[i] = remote;
494  }
495  }
496  }
497  free(tofree);
498  return 0;
499 }
500 
501 RZ_API char *rz_cmd_alias_get(RzCmd *cmd, const char *k, int remote) {
502  int matches, i;
503  if (!cmd || !k) {
504  return NULL;
505  }
506  for (i = 0; i < cmd->aliases.count; i++) {
507  matches = 0;
508  if (remote) {
509  if (cmd->aliases.remote[i]) {
510  matches = !strncmp(k, cmd->aliases.keys[i],
511  strlen(cmd->aliases.keys[i]));
512  }
513  } else {
514  matches = !strcmp(k, cmd->aliases.keys[i]);
515  }
516  if (matches) {
517  return cmd->aliases.values[i];
518  }
519  }
520  return NULL;
521 }
522 
523 RZ_API int rz_cmd_set_data(RzCmd *cmd, void *data) {
524  cmd->data = data;
525  return 1;
526 }
527 
528 RZ_API int rz_cmd_add(RzCmd *c, const char *cmd, RzCmdCb cb) {
529  int idx = (ut8)cmd[0];
530  RzCmdItem *item = c->cmds[idx];
531  if (!item) {
532  item = RZ_NEW0(RzCmdItem);
533  c->cmds[idx] = item;
534  }
535  strncpy(item->cmd, cmd, sizeof(item->cmd) - 1);
536  item->callback = cb;
537  return true;
538 }
539 
540 RZ_API int rz_cmd_del(RzCmd *cmd, const char *command) {
541  int idx = (ut8)command[0];
542  RZ_FREE(cmd->cmds[idx]);
543  return 0;
544 }
545 
546 RZ_API int rz_cmd_call(RzCmd *cmd, const char *input) {
547  struct rz_cmd_item_t *c;
548  int ret = -1;
550  if (!*input) {
551  if (cmd->nullcallback) {
552  ret = cmd->nullcallback(cmd->data);
553  }
554  } else {
555  char *nstr = NULL;
556  const char *ji = rz_cmd_alias_get(cmd, input, 1);
557  if (ji) {
558  if (*ji == '$') {
559  rz_cons_strcat(ji + 1);
560  return true;
561  } else {
562  nstr = rz_str_newf("R! %s", input);
563  input = nstr;
564  }
565  }
566  if (!*input) {
567  free(nstr);
568  return -1;
569  }
570  c = cmd->cmds[((ut8)input[0]) & 0xff];
571  if (c && c->callback) {
572  const char *inp = (*input) ? input + 1 : "";
573  ret = c->callback(cmd->data, inp);
574  } else {
575  ret = -1;
576  }
577  free(nstr);
578  }
579  return ret;
580 }
581 
583  if (v == -2) {
584  return RZ_CMD_STATUS_EXIT;
585  } else if (v < 0) {
586  return RZ_CMD_STATUS_ERROR;
587  } else {
588  return RZ_CMD_STATUS_OK;
589  }
590 }
591 
592 static void get_minmax_argc(RzCmdDesc *cd, int *min_argc, int *max_argc) {
593  *min_argc = 1;
594  *max_argc = 1;
595  const RzCmdDescArg *arg = cd->help->args;
596  while (arg && arg->name && !arg->optional) {
597  if (arg->type == RZ_CMD_ARG_TYPE_FAKE) {
598  arg++;
599  continue;
600  }
601  (*min_argc)++;
602  (*max_argc)++;
603  if (arg->flags & RZ_CMD_ARG_FLAG_LAST) {
604  return;
605  } else if (arg->flags & RZ_CMD_ARG_FLAG_ARRAY) {
606  *max_argc = INT_MAX;
607  return;
608  }
609  arg++;
610  }
611  while (arg && arg->name) {
612  if (arg->type == RZ_CMD_ARG_TYPE_FAKE) {
613  arg++;
614  continue;
615  }
616  (*max_argc)++;
617  if (arg->flags & RZ_CMD_ARG_FLAG_ARRAY) {
618  *max_argc = INT_MAX;
619  return;
620  }
621  arg++;
622  }
623 }
624 
626  switch (cd->type) {
628  return cd->d.argv_modes_data.default_mode;
630  return cd->d.argv_state_data.default_mode;
631  default:
633  }
634 }
635 
638 }
639 
640 static RzOutputMode cd_suffix2mode(RzCmdDesc *cd, const char *cmdid) {
641  if (!has_cd_submodes(cd)) {
642  return 0;
643  }
644  RzOutputMode mode = suffix2mode(cmdid + strlen(cd->name));
647  }
648  return mode;
649 }
650 
668  const RzCmdDescArg *arg;
669  size_t i, j;
670  for (arg = cd->help->args, i = 1; arg && arg->name && i < args->argc - 1; arg++, i++) {
671  char *tmp;
672  if (arg->flags & RZ_CMD_ARG_FLAG_LAST) {
673  if (arg->type == RZ_CMD_ARG_TYPE_CMD) {
674  for (j = i; j < args->argc; j++) {
675  char *s = rz_cmd_escape_arg(args->argv[j], RZ_CMD_ESCAPE_ONE_ARG);
676  if (strcmp(s, args->argv[j])) {
677  free(args->argv[j]);
678  args->argv[j] = s;
679  } else {
680  free(s);
681  }
682  }
683  }
684 
685  tmp = rz_str_array_join((const char **)&args->argv[i], args->argc - i, " ");
686  if (!tmp) {
687  return;
688  }
689  for (j = i; j < args->argc; j++) {
690  free(args->argv[j]);
691  }
692  args->argv[i] = tmp;
693  args->argc = i + 1;
694  return;
695  }
696  }
697  for (; arg && arg->name; arg++, i++) {
698  if (arg->default_value && i >= args->argc) {
699  rz_cmd_parsed_args_addarg(args, arg->default_value);
700  }
701  }
702 }
703 
705  if (!rz_cmd_desc_has_handler(cd)) {
707  }
708 
710 
711  int i;
712  const char *s;
713  rz_cmd_parsed_args_foreach_arg(args, i, s) {
714  RZ_LOG_DEBUG("processed parsed_arg %d: '%s'\n", i, s);
715  }
716 
718  switch (cd->type) {
720  if (args->argc < cd->d.argv_data.min_argc || args->argc > cd->d.argv_data.max_argc) {
722  }
723  return cd->d.argv_data.cb(cmd->data, args->argc, (const char **)args->argv);
726  if (!mode) {
728  }
729  if (args->argc < cd->d.argv_modes_data.min_argc || args->argc > cd->d.argv_modes_data.max_argc) {
731  }
732  return cd->d.argv_modes_data.cb(cmd->data, args->argc, (const char **)args->argv, mode);
735  if (!mode) {
737  }
738  if (args->argc < cd->d.argv_state_data.min_argc || args->argc > cd->d.argv_state_data.max_argc) {
740  }
743  return RZ_CMD_STATUS_INVALID;
744  }
745  RzCmdStatus res = cd->d.argv_state_data.cb(cmd->data, args->argc, (const char **)args->argv, &state);
746  if (args->extra && state.mode == RZ_OUTPUT_MODE_TABLE) {
747  bool res = rz_table_query(state.d.t, args->extra);
748  if (!res) {
750  return RZ_CMD_STATUS_INVALID;
751  }
752  }
753  if (res == RZ_CMD_STATUS_OK) {
755  }
757  return res;
758  default:
759  return RZ_CMD_STATUS_INVALID;
760  }
761 }
762 
764  char *exec_string;
766 
767  int i;
768  const char *s;
769  rz_cmd_parsed_args_foreach_arg(args, i, s) {
770  RZ_LOG_DEBUG("parsed_arg %d: '%s'\n", i, s);
771  }
772 
773  switch (cd->type) {
775  if (!cd->d.group_data.exec_cd) {
777  }
778  return call_cd(cmd, cd->d.group_data.exec_cd, args);
782  return argv_call_cb(cmd, cd, args);
784  exec_string = rz_cmd_parsed_args_execstr(args);
785  res = int2cmdstatus(cd->d.oldinput_data.cb(cmd->data, exec_string + strlen(cd->name)));
786  RZ_FREE(exec_string);
787  return res;
788  default:
789  RZ_LOG_ERROR("RzCmdDesc type not handled\n");
790  return RZ_CMD_STATUS_INVALID;
791  }
792 }
793 
796  if (!cd) {
798  }
799 
800  return call_cd(cmd, cd, args);
801 }
802 
803 static size_t strlen0(const char *s) {
804  return s ? strlen(s) : 0;
805 }
806 
807 static size_t strbuf_append_calc(RzStrBuf *sb, const char *s) {
809  return strlen(s);
810 }
811 
813  // RZ_CMD_DESC_TYPE_ARGV_MODES does not have actual children for
814  // the output modes, so we consider it separately
815  size_t i;
816  for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
817  if (cd->d.argv_modes_data.modes & argv_modes[i].mode) {
819  }
820  }
821 }
822 
823 static size_t fill_children_chars(RzStrBuf *sb, const RzCmdDesc *cd) {
824  if (cd->help->options) {
825  return strbuf_append_calc(sb, cd->help->options);
826  }
827 
828  RzStrBuf csb;
829  rz_strbuf_init(&csb);
830 
831  void **it;
832  bool has_other_commands = false;
833  const RzCmdDesc *exec_cd = rz_cmd_desc_get_exec((RzCmdDesc *)cd);
834  if (exec_cd) {
835  switch (exec_cd->type) {
838  fill_modes_children_chars(&csb, exec_cd);
839  break;
840  default:
841  break;
842  }
843  }
844  rz_cmd_desc_children_foreach(cd, it) {
845  RzCmdDesc *child = *(RzCmdDesc **)it;
846  if (rz_str_startswith(child->name, cd->name) && strlen(child->name) == strlen(cd->name) + 1) {
847  rz_strbuf_appendf(&csb, "%c", child->name[strlen(cd->name)]);
848  } else if (strcmp(child->name, cd->name)) {
849  has_other_commands = true;
850  }
851  }
852 
853  if (rz_strbuf_is_empty(&csb) || rz_strbuf_length(&csb) >= MAX_CHILDREN_SHOW) {
854  rz_strbuf_fini(&csb);
855  rz_strbuf_set(&csb, "?");
856  has_other_commands = false;
857  }
858 
859  if (has_other_commands) {
860  rz_strbuf_append(&csb, "?");
861  }
862 
863  if (!cd->n_children || rz_cmd_desc_has_handler(cd)) {
864  rz_strbuf_prepend(&csb, "[");
865  rz_strbuf_append(&csb, "]");
866  } else {
867  rz_strbuf_prepend(&csb, "<");
868  rz_strbuf_append(&csb, ">");
869  }
870  size_t res = rz_strbuf_length(&csb);
871  char *s = rz_strbuf_drain_nofree(&csb);
873  free(s);
874  return res;
875 }
876 
877 static bool show_children_shortcut(const RzCmdDesc *cd) {
878  return cd->n_children || cd->help->options || cd->type == RZ_CMD_DESC_TYPE_OLDINPUT ||
880 }
881 
882 static void fill_colored_args(RzCmd *cmd, RzStrBuf *sb, const char *line, bool use_color, const char *reset_color) {
883  const char *pal_args_color = "";
884  if (cmd->has_cons && use_color) {
885  RzCons *cons = rz_cons_singleton();
886  pal_args_color = cons->context->pal.args;
887  }
888 
889  while (line) {
890  const char *close_arg = NULL;
891  const char *open_arg = strchr(line, '<');
892  if (!open_arg) {
893  break;
894  }
895  close_arg = strchr(open_arg, '>');
896  if (!close_arg) {
897  break;
898  }
899  rz_strbuf_appendf(sb, "%.*s%s", (int)(open_arg - line), line, pal_args_color);
900  rz_strbuf_appendf(sb, "%.*s%s", (int)(close_arg - open_arg + 1), open_arg, reset_color);
901  line = close_arg + 1;
902  }
904 }
905 
906 static void fill_wrapped_comment(RzCmd *cmd, RzStrBuf *sb, const char *comment, size_t columns, bool use_color) {
907  int rows, cols;
908  bool is_interactive = false;
909  const char *help_color = "";
910  if (cmd->has_cons) {
911  RzCons *cons = rz_cons_singleton();
912  cols = rz_cons_get_size(&rows);
913  is_interactive = rz_cons_is_interactive();
914  help_color = use_color ? cons->context->pal.help : "";
915  }
916  if (is_interactive && cols > 0 && cols - columns > MIN_SUMMARY_WIDTH && !RZ_STR_ISEMPTY(comment)) {
917  char *text = strdup(comment);
918  RzList *wrapped_text = rz_str_wrap(text, cols - columns - 2);
919  RzListIter *it;
920  const char *line;
921  bool first = true;
922  rz_list_foreach (wrapped_text, it, line) {
923  if (!first) {
924  rz_strbuf_appendf(sb, "\n%*s", (int)(columns + 2), "");
925  } else {
926  rz_strbuf_append(sb, "# ");
927  first = false;
928  }
929 
930  fill_colored_args(cmd, sb, line, use_color, help_color);
931  }
932  rz_list_free(wrapped_text);
933  free(text);
934  } else if (!RZ_STR_ISEMPTY(comment)) {
935  rz_strbuf_appendf(sb, "# %s", comment);
936  }
937 }
938 
939 static void close_optionals(size_t *n_optionals, RzStrBuf *sb, size_t *len) {
940  for (; *n_optionals > 0; (*n_optionals)--) {
941  rz_strbuf_append(sb, "]");
942  (*len)++;
943  }
944 }
945 
946 static size_t fill_args(RzStrBuf *sb, const RzCmdDesc *cd) {
947  const RzCmdDescArg *arg;
948  size_t n_optionals = 0;
949  size_t len = 0;
950  bool has_array = false;
951  for (arg = cd->help->args; arg && arg->name; arg++) {
952  if (arg->type == RZ_CMD_ARG_TYPE_FAKE) {
953  if (!arg->optional) {
954  // Assume arg is a closing bracket
955  close_optionals(&n_optionals, sb, &len);
956  }
958  len += strlen(arg->name);
959  continue;
960  }
961 
962  if (has_array) {
964  break;
965  }
966  if (!arg->no_space) {
967  rz_strbuf_append(sb, " ");
968  len++;
969  }
970  if (arg->optional) {
971  rz_strbuf_append(sb, "[");
972  len++;
973  n_optionals++;
974  }
975  if (arg->flags & RZ_CMD_ARG_FLAG_ARRAY) {
976  has_array = true;
977  rz_strbuf_appendf(sb, "<%s1>", arg->name);
978  len += strlen(arg->name) + 3;
979  rz_strbuf_appendf(sb, " <%s2> ...", arg->name);
980  len += strlen(arg->name) + 8;
981  } else if (arg->flags & RZ_CMD_ARG_FLAG_OPTION) {
982  rz_strbuf_appendf(sb, "-%s", arg->name);
983  len += strlen(arg->name) + 1;
984  } else {
985  rz_strbuf_appendf(sb, "<%s>", arg->name);
986  len += strlen(arg->name) + 2;
987  if (arg->default_value) {
988  rz_strbuf_appendf(sb, "=%s", arg->default_value);
989  len += strlen(arg->default_value) + 1;
990  }
991  }
992  }
993  close_optionals(&n_optionals, sb, &len);
994  return len;
995 }
996 
997 static void fill_usage_strbuf(RzCmd *cmd, RzStrBuf *sb, RzCmdDesc *cd, bool use_color) {
998  const char *pal_label_color = "",
999  *pal_args_color = "",
1000  *pal_input_color = "",
1001  *pal_help_color = "",
1002  *pal_reset = "";
1003 
1004  if (cmd->has_cons && use_color) {
1005  RzCons *cons = rz_cons_singleton();
1006  pal_label_color = cons->context->pal.label;
1007  pal_args_color = cons->context->pal.args;
1008  pal_input_color = cons->context->pal.input;
1009  pal_help_color = cons->context->pal.help;
1010  pal_reset = cons->context->pal.reset;
1011  }
1012 
1013  size_t columns = 0;
1014  rz_strbuf_append(sb, pal_label_color);
1015  columns += strbuf_append_calc(sb, "Usage: ");
1016  rz_strbuf_append(sb, pal_reset);
1017  if (cd->help->usage) {
1018  columns += strbuf_append_calc(sb, cd->help->usage);
1019  rz_strbuf_append(sb, pal_reset);
1020  } else {
1021  rz_strbuf_append(sb, pal_input_color);
1022  columns += strbuf_append_calc(sb, cd->name);
1023  if (show_children_shortcut(cd)) {
1024  rz_strbuf_append(sb, pal_reset);
1025  columns += fill_children_chars(sb, cd);
1026  }
1027  rz_strbuf_append(sb, pal_args_color);
1028  if (cd->help->args_str) {
1029  columns += strbuf_append_calc(sb, cd->help->args_str);
1030  } else {
1031  columns += fill_args(sb, cd);
1032  }
1033  rz_strbuf_append(sb, pal_reset);
1034  }
1035  if (cd->help->summary) {
1036  RzStrBuf *summary_sb = rz_strbuf_new(cd->help->summary);
1037  if (summary_sb) {
1038  columns += strbuf_append_calc(sb, " ");
1039  rz_strbuf_append(sb, pal_help_color);
1040  if (has_cd_default_mode(cd)) {
1042  }
1043  fill_wrapped_comment(cmd, sb, rz_strbuf_get(summary_sb), columns, use_color);
1044  rz_strbuf_append(sb, pal_reset);
1045  rz_strbuf_free(summary_sb);
1046  }
1047  }
1048  rz_strbuf_append(sb, "\n");
1049 }
1050 
1051 static size_t calc_padding_len(const RzCmdDesc *cd, const char *name, bool show_children) {
1052  size_t name_len = strlen(name);
1053  size_t args_len = 0;
1054  size_t children_length = 0;
1055  if (show_children && show_children_shortcut(cd)) {
1056  RzStrBuf sb;
1057  rz_strbuf_init(&sb);
1059  children_length += rz_strbuf_length(&sb);
1060  rz_strbuf_fini(&sb);
1061  }
1062  if (cd->help->args_str) {
1063  args_len = strlen0(cd->help->args_str);
1064  } else {
1065  RzStrBuf sb;
1066  rz_strbuf_init(&sb);
1067  fill_args(&sb, cd);
1068  args_len = rz_strbuf_length(&sb);
1069  rz_strbuf_fini(&sb);
1070  }
1071  return name_len + args_len + children_length;
1072 }
1073 
1074 static void update_minmax_len(RzCmdDesc *cd, size_t *max_len, size_t *min_len, bool show_children) {
1075  size_t val = calc_padding_len(cd, cd->name, show_children);
1076  *max_len = val > *max_len ? val : *max_len;
1077  *min_len = val < *min_len ? val : *min_len;
1078 }
1079 
1080 static void do_print_child_help(RzCmd *cmd, RzStrBuf *sb, const RzCmdDesc *cd, const char *name, const char *summary, bool show_children, size_t max_len, bool use_color) {
1081  size_t str_len = calc_padding_len(cd, name, show_children);
1082  int padding = str_len < max_len ? max_len - str_len : 0;
1083  const char *pal_args_color = "",
1084  *pal_opt_color = "",
1085  *pal_help_color = "",
1086  *pal_input_color = "",
1087  *pal_reset = "";
1088 
1089  if (cmd->has_cons && use_color) {
1090  RzCons *cons = rz_cons_singleton();
1091  pal_args_color = cons->context->pal.args;
1092  pal_opt_color = cons->context->pal.reset;
1093  pal_help_color = cons->context->pal.help;
1094  pal_input_color = cons->context->pal.input;
1095  pal_reset = cons->context->pal.reset;
1096  }
1097 
1098  size_t columns = 0;
1099  columns += strbuf_append_calc(sb, "| ");
1100  rz_strbuf_append(sb, pal_input_color);
1101  columns += strbuf_append_calc(sb, name);
1102  if (show_children && show_children_shortcut(cd)) {
1103  rz_strbuf_append(sb, pal_opt_color);
1104  columns += fill_children_chars(sb, cd);
1105  }
1106  rz_strbuf_append(sb, pal_args_color);
1107  if (cd->help->args_str) {
1108  columns += strbuf_append_calc(sb, cd->help->args_str);
1109  } else {
1110  columns += fill_args(sb, cd);
1111  }
1112  rz_strbuf_appendf(sb, " %*s", padding, "");
1113  columns += padding + 1;
1114  rz_strbuf_append(sb, pal_help_color);
1115 
1116  fill_wrapped_comment(cmd, sb, summary, columns, use_color);
1117  rz_strbuf_appendf(sb, "%s\n", pal_reset);
1118 }
1119 
1120 static void print_child_help(RzCmd *cmd, RzStrBuf *sb, RzCmdDesc *cd, size_t max_len, bool use_color) {
1121  do_print_child_help(cmd, sb, cd, cd->name, cd->help->summary ? cd->help->summary : "", true, max_len, use_color);
1122 }
1123 
1124 static char *group_get_help(RzCmd *cmd, RzCmdDesc *cd, bool use_color) {
1126  fill_usage_strbuf(cmd, sb, cd, use_color);
1127 
1128  void **it_cd;
1129  size_t max_len = 0, min_len = SIZE_MAX;
1130 
1131  rz_cmd_desc_children_foreach(cd, it_cd) {
1132  RzCmdDesc *child = *(RzCmdDesc **)it_cd;
1133  update_minmax_len(child, &max_len, &min_len, true);
1134  }
1135  if (max_len - min_len > MAX_RIGHT_ALIGHNMENT) {
1136  max_len = min_len + MAX_RIGHT_ALIGHNMENT;
1137  }
1138 
1139  rz_cmd_desc_children_foreach(cd, it_cd) {
1140  RzCmdDesc *child = *(RzCmdDesc **)it_cd;
1141  print_child_help(cmd, sb, child, max_len, use_color);
1142  }
1143 
1144  fill_details(cmd, cd, sb, use_color);
1145  return rz_strbuf_drain(sb);
1146 }
1147 
1148 static void fill_argv_modes_help_strbuf(RzCmd *cmd, RzStrBuf *sb, RzCmdDesc *cd, bool use_color) {
1149  size_t max_len = 0, min_len = SIZE_MAX;
1150  update_minmax_len(cd, &max_len, &min_len, true);
1151  max_len++; // consider the suffix letter
1152  if (max_len - min_len > MAX_RIGHT_ALIGHNMENT) {
1153  max_len = min_len + MAX_RIGHT_ALIGHNMENT;
1154  }
1155 
1156  size_t i;
1157  for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
1158  if (cd->d.argv_modes_data.modes & argv_modes[i].mode) {
1159  char *name = rz_str_newf("%s%s", cd->name, argv_modes[i].suffix);
1160  char *summary = rz_str_newf("%s%s", cd->help->summary, argv_modes[i].summary_suffix);
1161  do_print_child_help(cmd, sb, cd, name, summary, false, max_len, use_color);
1162  free(name);
1163  free(summary);
1164  }
1165  }
1166 }
1167 
1169  do {
1170  if (cd->help->details) {
1171  return cd->help->details;
1172  }
1173  cd = cd->parent;
1174  } while (cd);
1175  return NULL;
1176 }
1177 
1179  do {
1180  if (cd->help->details || cd->help->details_cb) {
1181  const char *argv[] = { cd->name, NULL };
1182  return cd->help->details_cb ? cd->help->details_cb(cmd->data, 1, argv) : NULL;
1183  }
1184  cd = cd->parent;
1185  } while (cd);
1186  return NULL;
1187 }
1188 
1189 static void fill_details_do(RzCmd *cmd, const RzCmdDescDetail *detail_it, RzStrBuf *sb, bool use_color) {
1190  const char *pal_help_color = "",
1191  *pal_input_color = "",
1192  *pal_label_color = "",
1193  *pal_args_color = "",
1194  *pal_reset = "";
1195  if (cmd->has_cons && use_color) {
1196  RzCons *cons = rz_cons_singleton();
1197  pal_help_color = cons->context->pal.help;
1198  pal_input_color = cons->context->pal.input;
1199  pal_label_color = cons->context->pal.label;
1200  pal_args_color = cons->context->pal.args;
1201  pal_reset = cons->context->pal.reset;
1202  }
1203 
1204  while (detail_it->name) {
1205  if (!RZ_STR_ISEMPTY(detail_it->name)) {
1206  rz_strbuf_appendf(sb, "\n%s%s:%s\n", pal_label_color, detail_it->name, pal_reset);
1207  }
1208  const RzCmdDescDetailEntry *entry_it = detail_it->entries;
1209  size_t max_len = 0, min_len = SIZE_MAX;
1210  while (entry_it && entry_it->text) {
1211  size_t len = strlen(entry_it->text) + strlen0(entry_it->arg_str);
1212  if (max_len < len) {
1213  max_len = len;
1214  }
1215  if (min_len > len) {
1216  min_len = len;
1217  }
1218  entry_it++;
1219  }
1220  if (max_len - min_len > MAX_RIGHT_ALIGHNMENT) {
1221  max_len = min_len + MAX_RIGHT_ALIGHNMENT;
1222  }
1223 
1224  entry_it = detail_it->entries;
1225  while (entry_it && entry_it->text) {
1226  size_t len = strlen(entry_it->text) + strlen0(entry_it->arg_str);
1227  int padding = len < max_len ? max_len - len : 0;
1228  const char *arg_str = entry_it->arg_str ? entry_it->arg_str : "";
1229  rz_strbuf_appendf(sb, "| %s%s%s%s %*s%s",
1230  pal_input_color, entry_it->text,
1231  pal_args_color, arg_str,
1232  padding, "",
1233  pal_help_color);
1234  size_t columns = strlen("| ") + strlen(entry_it->text) +
1235  strlen(" ") + strlen(arg_str) + padding;
1236  fill_wrapped_comment(cmd, sb, entry_it->comment, columns, use_color);
1237  rz_strbuf_appendf(sb, "%s\n", pal_reset);
1238  entry_it++;
1239  }
1240  detail_it++;
1241  }
1242 }
1243 
1244 static void fill_details_static(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color) {
1245  const RzCmdDescDetail *detail_it = get_cd_details(cd);
1246  if (!detail_it) {
1247  return;
1248  }
1249  fill_details_do(cmd, detail_it, sb, use_color);
1250 }
1251 
1252 static void fill_details_cb(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color) {
1253  RzCmdDescDetail *detail_it = get_cd_details_cb(cmd, cd);
1254  if (!detail_it) {
1255  return;
1256  }
1257  fill_details_do(cmd, detail_it, sb, use_color);
1258  rz_cmd_desc_details_free(detail_it);
1259 }
1260 
1261 static void fill_details(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color) {
1262  fill_details_static(cmd, cd, sb, use_color);
1263  fill_details_cb(cmd, cd, sb, use_color);
1264 }
1265 
1266 static char *argv_get_help(RzCmd *cmd, RzCmdDesc *cd, size_t detail, bool use_color) {
1268  const char *pal_reset = "";
1269  if (cmd->has_cons && use_color) {
1270  RzCons *cons = rz_cons_singleton();
1271  pal_reset = cons->context->pal.reset;
1272  }
1273 
1274  fill_usage_strbuf(cmd, sb, cd, use_color);
1275 
1276  if (cd->type == RZ_CMD_DESC_TYPE_ARGV_MODES || cd->type == RZ_CMD_DESC_TYPE_ARGV_STATE) {
1277  fill_argv_modes_help_strbuf(cmd, sb, cd, use_color);
1278  }
1279 
1280  switch (detail) {
1281  case 1:
1282  case 2:
1283  if (cd->help->description) {
1284  rz_strbuf_append(sb, "\n");
1285  fill_colored_args(cmd, sb, cd->help->description, use_color, pal_reset);
1286  rz_strbuf_append(sb, "\n");
1287  }
1288  fill_details(cmd, cd, sb, use_color);
1289  break;
1290  default:
1291  rz_strbuf_free(sb);
1292  return NULL;
1293  }
1294  return rz_strbuf_drain(sb);
1295 }
1296 
1297 static char *fake_get_help(RzCmd *cmd, RzCmdDesc *cd, bool use_color) {
1298  // abuse detail=2 of the argv help as they show essentially the same info
1299  return argv_get_help(cmd, cd, 2, use_color);
1300 }
1301 
1303  if (!cmd->has_cons) {
1304  return NULL;
1305  }
1306 
1307  char *res = NULL;
1308  rz_cons_push();
1309  // rz_cons_push disables flushing, which is going to be a problem if a help menu is
1310  // displayed.
1311  rz_cons_set_flush(true);
1313  if (status == RZ_CMD_STATUS_OK) {
1314  rz_cons_filter();
1315  res = rz_cons_get_buffer_dup();
1316  }
1317  if (!res) {
1318  res = strdup("");
1319  }
1320  rz_cons_pop();
1321  return res;
1322 }
1323 
1324 static char *get_help(RzCmd *cmd, RzCmdDesc *cd, const char *cmdid, RzCmdParsedArgs *args, bool use_color, size_t detail) {
1325  switch (cd->type) {
1327  if (cd->d.group_data.exec_cd && (detail > 1 || (detail == 1 && strcmp(cmdid, cd->name)))) {
1328  return get_help(cmd, cd->d.group_data.exec_cd, cmdid, args, use_color, detail);
1329  }
1330  if (detail == 1) {
1331  // show the group help only when doing <cmd>?
1332  return group_get_help(cmd, cd, use_color);
1333  }
1334  return argv_get_help(cmd, cd, detail, use_color);
1335  case RZ_CMD_DESC_TYPE_ARGV:
1338  return argv_get_help(cmd, cd, detail, use_color);
1339  case RZ_CMD_DESC_TYPE_FAKE:
1340  if (detail != 1) {
1341  return NULL;
1342  }
1343  return fake_get_help(cmd, cd, use_color);
1345  return oldinput_get_help(cmd, cd, args);
1348  return NULL;
1349  }
1350  return NULL;
1351 }
1352 
1353 static void fill_args_json(const RzCmd *cmd, const RzCmdDesc *cd, PJ *j) {
1354  const RzCmdDescArg *arg;
1355  bool has_array = false;
1356  pj_ka(j, "args");
1357  const char *argtype = NULL;
1358  for (arg = cd->help->args; arg && arg->name; arg++) {
1359  if (has_array) {
1361  break;
1362  }
1363  pj_o(j);
1364 #define CASE_TYPE(x, y) \
1365  case (x): \
1366  argtype = (y); \
1367  break
1368  switch (arg->type) {
1370  CASE_TYPE(RZ_CMD_ARG_TYPE_NUM, "number");
1371  CASE_TYPE(RZ_CMD_ARG_TYPE_RZNUM, "expression");
1372  CASE_TYPE(RZ_CMD_ARG_TYPE_STRING, "string");
1373  CASE_TYPE(RZ_CMD_ARG_TYPE_ENV, "environment_variable");
1375  CASE_TYPE(RZ_CMD_ARG_TYPE_FCN, "function");
1376  CASE_TYPE(RZ_CMD_ARG_TYPE_FILE, "filename");
1377  CASE_TYPE(RZ_CMD_ARG_TYPE_OPTION, "option");
1378  CASE_TYPE(RZ_CMD_ARG_TYPE_CMD, "command");
1379  CASE_TYPE(RZ_CMD_ARG_TYPE_MACRO, "macro");
1380  CASE_TYPE(RZ_CMD_ARG_TYPE_EVAL_KEY, "evaluable");
1381  CASE_TYPE(RZ_CMD_ARG_TYPE_EVAL_FULL, "evaluable_full");
1382 #undef CASE_TYPE
1383  default:
1384  argtype = "unknown";
1385  break;
1386  }
1387  pj_ks(j, "type", argtype);
1388  pj_ks(j, "name", arg->name);
1389  if (arg->type == RZ_CMD_ARG_TYPE_FAKE) {
1390  pj_end(j);
1391  continue;
1392  }
1393  if (arg->no_space) {
1394  pj_kb(j, "nospace", true);
1395  }
1396  if (!arg->optional) {
1397  pj_kb(j, "required", true);
1398  }
1399  if (arg->flags & RZ_CMD_ARG_FLAG_LAST) {
1400  pj_kb(j, "is_last", true);
1401  }
1402  if (arg->flags & RZ_CMD_ARG_FLAG_ARRAY) {
1403  pj_kb(j, "is_array", true);
1404  }
1405  if (arg->flags & RZ_CMD_ARG_FLAG_OPTION) {
1406  pj_kb(j, "is_option", true);
1407  }
1408  if (arg->default_value) {
1409  pj_ks(j, "default", arg->default_value);
1410  }
1411  if (arg->type == RZ_CMD_ARG_TYPE_CHOICES) {
1412  pj_ka(j, "choices");
1413  char **ochoice = arg->choices_cb ? arg->choices_cb(cmd->data) : (char **)arg->choices;
1414  for (char **choice = ochoice; *choice; choice++) {
1415  pj_s(j, *choice);
1416  }
1417  pj_end(j);
1418  if (arg->choices_cb) {
1419  for (char **choice = ochoice; *choice; choice++) {
1420  free(*choice);
1421  }
1422  free(ochoice);
1423  }
1424  }
1425  pj_end(j);
1426  }
1427  pj_end(j);
1428 }
1429 
1440  rz_return_val_if_fail(cmd && cd && j, false);
1441  pj_ko(j, cd->name);
1442  pj_ks(j, "cmd", cd->name);
1443  const char *type;
1444  switch (cd->type) {
1445 #define CASE_CDTYPE(x, y) \
1446  case (x): \
1447  type = (y); \
1448  break
1456 #undef CASE_CDTYPE
1457  default:
1458  type = "unknown";
1459  break;
1460  }
1461  pj_ks(j, "type", type);
1462  if (cd->help->args_str) {
1463  pj_ks(j, "args_str", cd->help->args_str);
1464  } else {
1466  fill_args(sb, cd);
1467  char *args = rz_strbuf_drain(sb);
1468  pj_ks(j, "args_str", args);
1469  free(args);
1470  }
1471  fill_args_json(cmd, cd, j);
1472  pj_ks(j, "description", cd->help->description ? cd->help->description : "");
1473  pj_ks(j, "summary", cd->help->summary ? cd->help->summary : "");
1474  pj_end(j);
1475  return true;
1476 }
1477 
1488 RZ_API bool rz_cmd_get_help_strbuf(RzCmd *cmd, const RzCmdDesc *cd, bool use_color, RzStrBuf *sb) {
1489  rz_return_val_if_fail(cmd && cd && sb, false);
1490  do_print_child_help(cmd, sb, cd, cd->name, cd->help->summary, false, MAX_RIGHT_ALIGHNMENT, use_color);
1491  return true;
1492 }
1493 
1495  char *cmdid = strdup(rz_cmd_parsed_args_cmd(args));
1496  if (!cmdid) {
1497  return NULL;
1498  }
1499  char *cmdid_p = cmdid + strlen(cmdid) - 1;
1500  size_t detail = 0;
1501  while (cmdid_p >= cmdid && *cmdid_p == '?' && detail < 2) {
1502  *cmdid_p = '\0';
1503  cmdid_p--;
1504  detail++;
1505  }
1506 
1507  char *res = NULL;
1508  if (detail == 0) {
1509  // there should be at least one `?`
1510  goto err;
1511  }
1512 
1513  RzCmdDesc *cd = cmdid_p >= cmdid ? rz_cmd_get_desc(cmd, cmdid) : rz_cmd_get_root(cmd);
1514  if (!cd || !cd->help) {
1515  goto err;
1516  }
1517 
1518  res = get_help(cmd, cd, cmdid, args, use_color, detail);
1519 err:
1520  free(cmdid);
1521  return res;
1522 }
1523 
1527  return RZ_NEW0(RzCmdMacroItem);
1528 }
1529 
1531  if (!item) {
1532  return;
1533  }
1534  free(item->name);
1535  free(item->args);
1536  free(item->code);
1537  free(item);
1538 }
1539 
1541  mac->counter = 0;
1542  mac->_brk_value = 0;
1543  mac->brk_value = &mac->_brk_value;
1544  mac->cb_printf = (void *)printf;
1545  mac->num = NULL;
1546  mac->user = NULL;
1547  mac->cmd = NULL;
1549 }
1550 
1552  rz_list_free(mac->macros);
1553  mac->macros = NULL;
1554 }
1555 
1556 // XXX add support single line function definitions
1557 // XXX add support for single name multiple nargs macros
1558 RZ_API int rz_cmd_macro_add(RzCmdMacro *mac, const char *oname) {
1559  struct rz_cmd_macro_item_t *macro;
1560  char *name, *args = NULL;
1561  // char buf[RZ_CMD_MAXLEN];
1562  RzCmdMacroItem *m;
1563  int macro_update;
1564  RzListIter *iter;
1565  char *pbody;
1566  // char *bufp;
1567  char *ptr;
1568  int lidx;
1569 
1570  if (!*oname) {
1571  rz_cmd_macro_list(mac);
1572  return 0;
1573  }
1574 
1575  name = strdup(oname);
1576  if (!name) {
1577  perror("strdup");
1578  return 0;
1579  }
1580 
1581  pbody = strchr(name, ';');
1582  if (!pbody) {
1583  eprintf("Invalid macro body\n");
1584  free(name);
1585  return false;
1586  }
1587  *pbody = '\0';
1588  pbody++;
1589 
1590  if (*name && name[1] && name[strlen(name) - 1] == ')') {
1591  eprintf("rz_cmd_macro_add: missing macro body?\n");
1592  free(name);
1593  return -1;
1594  }
1595 
1596  macro = NULL;
1597  ptr = strchr(name, ' ');
1598  if (ptr) {
1599  *ptr = '\0';
1600  args = ptr + 1;
1601  }
1602  macro_update = 0;
1603  rz_list_foreach (mac->macros, iter, m) {
1604  if (!strcmp(name, m->name)) {
1605  macro = m;
1606  free(macro->name);
1607  free(macro->code);
1608  free(macro->args);
1609  macro_update = 1;
1610  break;
1611  }
1612  }
1613  if (ptr) {
1614  *ptr = ' ';
1615  }
1616  if (!macro) {
1618  if (!macro) {
1619  free(name);
1620  return 0;
1621  }
1622  }
1623 
1624  macro->name = strdup(name);
1625  macro->codelen = (pbody[0]) ? strlen(pbody) + 2 : 4096;
1626  macro->code = (char *)malloc(macro->codelen);
1627  *macro->code = '\0';
1628  macro->nargs = 0;
1629  if (!args) {
1630  args = "";
1631  }
1632  macro->args = strdup(args);
1633  ptr = strchr(macro->name, ' ');
1634  if (ptr != NULL) {
1635  *ptr = '\0';
1636  macro->nargs = rz_str_word_set0(ptr + 1);
1637  }
1638 
1639  for (lidx = 0; pbody[lidx]; lidx++) {
1640  if (pbody[lidx] == ';') {
1641  pbody[lidx] = '\n';
1642  } else if (pbody[lidx] == ')' && pbody[lidx - 1] == '\n') {
1643  pbody[lidx] = '\0';
1644  }
1645  }
1646  strncpy(macro->code, pbody, macro->codelen);
1647  macro->code[macro->codelen - 1] = 0;
1648  if (macro_update == 0) {
1649  rz_list_append(mac->macros, macro);
1650  }
1651  free(name);
1652  return 0;
1653 }
1654 
1655 RZ_API int rz_cmd_macro_rm(RzCmdMacro *mac, const char *_name) {
1656  RzListIter *iter;
1657  RzCmdMacroItem *m;
1658  char *name = strdup(_name);
1659  if (!name) {
1660  return false;
1661  }
1662  char *ptr = strchr(name, ')');
1663  if (ptr) {
1664  *ptr = '\0';
1665  }
1666  bool ret = false;
1667  rz_list_foreach (mac->macros, iter, m) {
1668  if (!strcmp(m->name, name)) {
1669  rz_list_delete(mac->macros, iter);
1670  eprintf("Macro '%s' removed.\n", name);
1671  ret = true;
1672  break;
1673  }
1674  }
1675  free(name);
1676  return ret;
1677 }
1678 
1679 // TODO: use mac->cb_printf which is rz_cons_printf at the end
1681  RzCmdMacroItem *m;
1682  int j, idx = 0;
1683  RzListIter *iter;
1684  rz_list_foreach (mac->macros, iter, m) {
1685  mac->cb_printf("%d (%s %s; ", idx, m->name, m->args);
1686  for (j = 0; m->code[j]; j++) {
1687  if (m->code[j] == '\n') {
1688  mac->cb_printf("; ");
1689  } else {
1690  mac->cb_printf("%c", m->code[j]);
1691  }
1692  }
1693  mac->cb_printf(")\n");
1694  idx++;
1695  }
1696 }
1697 
1698 // TODO: use mac->cb_printf which is rz_cons_printf at the end
1700  RzCmdMacroItem *m;
1701  int j;
1702  RzListIter *iter;
1703  rz_list_foreach (mac->macros, iter, m) {
1704  mac->cb_printf("(%s %s, ", m->name, m->args);
1705  for (j = 0; m->code[j]; j++) {
1706  if (m->code[j] == '\n') {
1707  mac->cb_printf("; ");
1708  } else {
1709  mac->cb_printf("%c", m->code[j]);
1710  }
1711  }
1712  mac->cb_printf(")\n");
1713  }
1714 }
1715 
1716 #if 0
1717 (define name value
1718  f $0 @ $1)
1719 
1720 (define loop cmd
1721  loop:
1722  ? $0 == 0
1723  ?? .loop:
1724  )
1725 
1726 .(define patata 3)
1727 #endif
1728 
1729 RZ_API int rz_cmd_macro_cmd_args(RzCmdMacro *mac, const char *ptr, const char *args, int nargs) {
1730  int i, j;
1731  char *pcmd, cmd[RZ_CMD_MAXLEN];
1732  const char *arg = args;
1733 
1734  for (*cmd = i = j = 0; j < RZ_CMD_MAXLEN && ptr[j]; i++, j++) {
1735  if (ptr[j] == '$') {
1736  if (ptr[j + 1] >= '0' && ptr[j + 1] <= '9') {
1737  int wordlen;
1738  int w = ptr[j + 1] - '0';
1739  const char *word = rz_str_word_get0(arg, w);
1740  if (word && *word) {
1741  wordlen = strlen(word);
1742  if ((i + wordlen + 1) >= sizeof(cmd)) {
1743  return -1;
1744  }
1745  memcpy(cmd + i, word, wordlen + 1);
1746  i += wordlen - 1;
1747  j++;
1748  } else {
1749  eprintf("Undefined argument %d\n", w);
1750  }
1751  } else if (ptr[j + 1] == '@') {
1752  char off[32];
1753  int offlen;
1754  offlen = snprintf(off, sizeof(off), "%d",
1755  mac->counter);
1756  if ((i + offlen + 1) >= sizeof(cmd)) {
1757  return -1;
1758  }
1759  memcpy(cmd + i, off, offlen + 1);
1760  i += offlen - 1;
1761  j++;
1762  } else {
1763  cmd[i] = ptr[j];
1764  cmd[i + 1] = '\0';
1765  }
1766  } else {
1767  cmd[i] = ptr[j];
1768  cmd[i + 1] = '\0';
1769  }
1770  }
1771  for (pcmd = cmd; *pcmd && (*pcmd == ' ' || *pcmd == '\t'); pcmd++) {
1772  ;
1773  }
1774  // eprintf ("-pre %d\n", (int)mac->num->value);
1775  int xx = (*pcmd == ')') ? 0 : mac->cmd(mac->user, pcmd);
1776  // eprintf ("-pos %p %d\n", mac->num, (int)mac->num->value);
1777  return xx;
1778 }
1779 
1780 RZ_API char *rz_cmd_macro_label_process(RzCmdMacro *mac, RzCmdMacroLabel *labels, int *labels_n, char *ptr) {
1781  int i;
1782  for (; *ptr == ' '; ptr++) {
1783  ;
1784  }
1785  if (ptr[strlen(ptr) - 1] == ':' && !strchr(ptr, ' ')) {
1786  /* label detected */
1787  if (ptr[0] == '.') {
1788  // eprintf("---> GOTO '%s'\n", ptr+1);
1789  /* goto */
1790  for (i = 0; i < *labels_n; i++) {
1791  // eprintf("---| chk '%s'\n", labels[i].name);
1792  if (!strcmp(ptr + 1, labels[i].name)) {
1793  return labels[i].ptr;
1794  }
1795  }
1796  return NULL;
1797  } else
1798  /* conditional goto */
1799  if (ptr[0] == '?' && ptr[1] == '!' && ptr[2] != '?') {
1800  if (mac->num && mac->num->value != 0) {
1801  char *label = ptr + 3;
1802  for (; *label == ' ' || *label == '.'; label++) {
1803  ;
1804  }
1805  // eprintf("===> GOTO %s\n", label);
1806  /* goto label ptr+3 */
1807  for (i = 0; i < *labels_n; i++) {
1808  if (!strcmp(label, labels[i].name)) {
1809  return labels[i].ptr;
1810  }
1811  }
1812  return NULL;
1813  }
1814  } else
1815  /* conditional goto */
1816  if (ptr[0] == '?' && ptr[1] == '?' && ptr[2] != '?') {
1817  if (mac->num->value == 0) {
1818  char *label = ptr + 3;
1819  for (; label[0] == ' ' || label[0] == '.'; label++) {
1820  ;
1821  }
1822  // eprintf("===> GOTO %s\n", label);
1823  /* goto label ptr+3 */
1824  for (i = 0; i < *labels_n; i++) {
1825  if (!strcmp(label, labels[i].name)) {
1826  return labels[i].ptr;
1827  }
1828  }
1829  return NULL;
1830  }
1831  } else {
1832  for (i = 0; i < *labels_n; i++) {
1833  // eprintf("---| chk '%s'\n", labels[i].name);
1834  if (!strcmp(ptr + 1, labels[i].name)) {
1835  i = 0;
1836  break;
1837  }
1838  }
1839  /* Add label */
1840  // eprintf("===> ADD LABEL(%s)\n", ptr);
1841  if (i == 0) {
1842  strncpy(labels[*labels_n].name, ptr, 64);
1843  labels[*labels_n].ptr = ptr + strlen(ptr) + 1;
1844  *labels_n = *labels_n + 1;
1845  }
1846  }
1847  return ptr + strlen(ptr) + 1;
1848  }
1849  return ptr;
1850 }
1851 
1852 /* TODO: add support for spaced arguments */
1853 static int macro_call(RzCmdMacro *mac, const char *name, bool multiple) {
1854  char *args;
1855  int nargs = 0;
1856  char *str, *ptr, *ptr2;
1857  RzListIter *iter;
1858  static int macro_level = 0;
1859  RzCmdMacroItem *m;
1860  /* labels */
1861  int labels_n = 0;
1862  struct rz_cmd_macro_label_t labels[MACRO_LABELS];
1863 
1864  str = strdup(name);
1865  if (!str) {
1866  perror("strdup");
1867  return false;
1868  }
1869  ptr = strchr(str, ')');
1870  if (!ptr) {
1871  RZ_LOG_ERROR("Missing end ')' parenthesis.\n");
1872  free(str);
1873  return false;
1874  } else {
1875  *ptr = '\0';
1876  }
1877 
1878  args = strchr(str, ' ');
1879  if (args) {
1880  *args = '\0';
1881  args++;
1883  }
1884 
1885  macro_level++;
1886  if (macro_level > MACRO_LIMIT) {
1887  RZ_LOG_ERROR("Maximum macro recursivity reached.\n");
1888  macro_level--;
1889  free(str);
1890  return 0;
1891  }
1892  ptr = strchr(str, ';');
1893  if (ptr) {
1894  *ptr = 0;
1895  }
1896 
1898  rz_list_foreach (mac->macros, iter, m) {
1899  if (!strcmp(str, m->name)) {
1900  char *ptr = m->code;
1901  char *end = strchr(ptr, '\n');
1902  char *init_ptr = ptr;
1903  char *init_end = end;
1904  if ((m->nargs == 0 && nargs != m->nargs) ||
1905  (m->nargs != 0 &&
1906  ((multiple && (nargs % m->nargs != 0 || nargs == 0)) ||
1907  (!multiple && nargs != m->nargs)))) {
1908  if (!multiple || m->nargs == 0 || nargs == 0) {
1909  RZ_LOG_ERROR("Macro '%s' expects %d args, not %d\n", m->name, m->nargs, nargs);
1910  } else {
1911  RZ_LOG_ERROR("Macro '%s' expects %d args and %d is not a multiple of %d\n",
1912  m->name, m->nargs, nargs, m->nargs);
1913  }
1914  macro_level--;
1915  free(str);
1917  return false;
1918  }
1919  mac->brk = 0;
1920  int args_processed = 0;
1921  do {
1922  if (end) {
1923  *end = '\0';
1924  }
1925  if (rz_cons_is_breaked()) {
1926  RZ_LOG_ERROR("Interrupted at (%s)\n", ptr);
1927  if (end) {
1928  *end = '\n';
1929  }
1930  free(str);
1932  return false;
1933  }
1934  rz_cons_flush();
1935  /* Label handling */
1936  ptr2 = rz_cmd_macro_label_process(mac, &(labels[0]), &labels_n, ptr);
1937  if (!ptr2) {
1938  RZ_LOG_ERROR("Oops. invalid label name\n");
1939  break;
1940  } else if (ptr != ptr2) {
1941  ptr = ptr2;
1942  if (end) {
1943  *end = '\n';
1944  }
1945  end = strchr(ptr, '\n');
1946  continue;
1947  }
1948  /* Command execution */
1949  if (*ptr) {
1950  mac->num->value = value;
1951  int r = rz_cmd_macro_cmd_args(mac, ptr, args, nargs);
1952  // TODO: handle quit? r == 0??
1953  // quit, exits the macro. like a break
1954  value = mac->num->value;
1955  if (r < 0) {
1956  free(str);
1958  return r;
1959  }
1960  }
1961  if (end) {
1962  *end = '\n';
1963  ptr = end + 1;
1964  /* Fetch next command */
1965  end = strchr(ptr, '\n');
1966  } else {
1967  args_processed += m->nargs;
1968  if (!multiple || args_processed >= nargs) {
1969  macro_level--;
1970  free(str);
1971  goto out_clean;
1972  }
1973  args = (char *)rz_str_word_get0(args, m->nargs);
1974  ptr = init_ptr;
1975  end = init_end;
1976  }
1977  } while (!mac->brk);
1978  if (mac->brk) {
1979  macro_level--;
1980  free(str);
1981  goto out_clean;
1982  }
1983  }
1984  }
1985  RZ_LOG_ERROR("No macro named '%s'\n", str);
1986  macro_level--;
1987  free(str);
1988 out_clean:
1990  return true;
1991 }
1992 
1993 RZ_API int rz_cmd_macro_call(RzCmdMacro *mac, const char *name) {
1994  return macro_call(mac, name, false);
1995 }
1996 
1998  return macro_call(mac, name, true);
1999 }
2000 
2001 RZ_API int rz_cmd_macro_break(RzCmdMacro *mac, const char *value) {
2002  mac->brk = 1;
2003  mac->brk_value = NULL;
2004  mac->_brk_value = (ut64)rz_num_math(mac->num, value);
2005  if (value && *value) {
2006  mac->brk_value = &mac->_brk_value;
2007  }
2008  return 0;
2009 }
2010 
2011 /* RzCmdParsedArgs */
2012 
2013 RZ_API RzCmdParsedArgs *rz_cmd_parsed_args_new(const char *cmd, int n_args, char **args) {
2014  rz_return_val_if_fail(cmd && n_args >= 0, NULL);
2016  res->has_space_after_cmd = true;
2017  res->argc = n_args + 1;
2018  res->argv = RZ_NEWS0(char *, res->argc + 1);
2019  res->argv[0] = strdup(cmd);
2020  int i;
2021  for (i = 1; i < res->argc; i++) {
2022  res->argv[i] = strdup(args[i - 1]);
2023  }
2024  res->argv[res->argc] = NULL;
2025  return res;
2026 }
2027 
2029  return rz_cmd_parsed_args_new(cmd, 0, NULL);
2030 }
2031 
2033  return rz_cmd_parsed_args_new("", n_args, args);
2034 }
2035 
2037  if (!a) {
2038  return;
2039  }
2040 
2041  int i;
2042  for (i = 0; i < a->argc; i++) {
2043  free(a->argv[i]);
2044  }
2045  free(a->argv);
2046  free(a);
2047 }
2048 
2049 static void free_array(char **arr, int n) {
2050  int i;
2051  for (i = 0; i < n; i++) {
2052  free(arr[i]);
2053  }
2054  free(arr);
2055 }
2056 
2058  rz_return_val_if_fail(a && a->argv && a->argv[0], false);
2059  char **tmp = RZ_NEWS0(char *, n_args + 2);
2060  if (!tmp) {
2061  return false;
2062  }
2063  tmp[0] = strdup(a->argv[0]);
2064  int i;
2065  for (i = 1; i < n_args + 1; i++) {
2066  tmp[i] = strdup(args[i - 1]);
2067  if (!tmp[i]) {
2068  goto err;
2069  }
2070  }
2071  tmp[n_args + 1] = NULL;
2072  free_array(a->argv, a->argc);
2073  a->argv = tmp;
2074  a->argc = n_args + 1;
2075  return true;
2076 err:
2077  free_array(tmp, n_args + 1);
2078  return false;
2079 }
2080 
2082  char **tmp = realloc(a->argv, sizeof(a->argv[0]) * (a->argc + 2));
2083  if (!tmp) {
2084  return false;
2085  }
2086 
2087  a->argv = tmp;
2088  a->argv[a->argc] = strdup(arg);
2089  a->argv[a->argc + 1] = NULL;
2090  a->argc++;
2091  return true;
2092 }
2093 
2095  rz_return_val_if_fail(a && a->argv && a->argv[0], false);
2096  char *tmp = strdup(cmd);
2097  if (!tmp) {
2098  return false;
2099  }
2100  free(a->argv[0]);
2101  a->argv[0] = tmp;
2102  return true;
2103 }
2104 
2106  int i;
2107  for (i = 1; i < a->argc; i++) {
2108  if (i > 1) {
2109  rz_strbuf_append(sb, " ");
2110  }
2111  rz_strbuf_append(sb, a->argv[i]);
2112  }
2113 }
2114 
2116  rz_return_val_if_fail(a && a->argv && a->argv[0], NULL);
2117  RzStrBuf *sb = rz_strbuf_new("");
2119  return rz_strbuf_drain(sb);
2120 }
2121 
2123  rz_return_val_if_fail(a && a->argv && a->argv[0], NULL);
2124  RzStrBuf *sb = rz_strbuf_new(a->argv[0]);
2125  if (a->argc > 1 && a->has_space_after_cmd) {
2126  rz_strbuf_append(sb, " ");
2127  }
2129  if (a->extra) {
2130  rz_strbuf_append(sb, a->extra);
2131  }
2132  return rz_strbuf_drain(sb);
2133 }
2134 
2136  rz_return_val_if_fail(a && a->argv && a->argv[0], NULL);
2137  return a->argv[0];
2138 }
2139 
2140 /* RzCmdDescriptor */
2141 
2142 static RzCmdDesc *argv_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, RzCmdArgvCb cb, const RzCmdDescHelp *help, bool ht_insert) {
2143  RzCmdDesc *res = create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_ARGV, name, help, ht_insert);
2144  if (!res) {
2145  return NULL;
2146  }
2147 
2148  res->d.argv_data.cb = cb;
2149  get_minmax_argc(res, &res->d.argv_data.min_argc, &res->d.argv_data.max_argc);
2150  return res;
2151 }
2152 
2154  rz_return_val_if_fail(cmd && parent && name && help && help->args, NULL);
2155  return argv_new(cmd, parent, name, cb, help, true);
2156 }
2157 
2158 static RzCmdDesc *argv_modes_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvModesCb cb, const RzCmdDescHelp *help, bool ht_insert) {
2159  RzCmdDesc *res = create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_ARGV_MODES, name, help, ht_insert);
2160  if (!res) {
2161  return NULL;
2162  }
2163 
2164  res->d.argv_modes_data.cb = cb;
2165  res->d.argv_modes_data.modes = modes;
2166  res->d.argv_modes_data.default_mode = RZ_OUTPUT_MODE_STANDARD;
2167  get_minmax_argc(res, &res->d.argv_modes_data.min_argc, &res->d.argv_modes_data.max_argc);
2168  return res;
2169 }
2170 
2171 static RzCmdDesc *argv_state_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvStateCb cb, const RzCmdDescHelp *help, bool ht_insert) {
2172  RzCmdDesc *res = create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_ARGV_STATE, name, help, ht_insert);
2173  if (!res) {
2174  return NULL;
2175  }
2176 
2177  res->d.argv_state_data.cb = cb;
2178  res->d.argv_state_data.modes = modes;
2179  res->d.argv_state_data.default_mode = RZ_OUTPUT_MODE_STANDARD;
2180  get_minmax_argc(res, &res->d.argv_state_data.min_argc, &res->d.argv_state_data.max_argc);
2181  return res;
2182 }
2183 
2196  rz_return_val_if_fail(cmd && parent && name && help && help->args && modes, NULL);
2197  return argv_modes_new(cmd, parent, name, modes, cb, help, true);
2198 }
2199 
2213  rz_return_val_if_fail(cmd && parent && name && help && help->args && modes, NULL);
2214  return argv_state_new(cmd, parent, name, modes, cb, help, true);
2215 }
2216 
2218  rz_return_val_if_fail(cmd && parent && name && help, NULL);
2219  return create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_INNER, name, help, false);
2220 }
2221 
2234  rz_return_val_if_fail(cmd && parent && name && group_help, NULL);
2235  RzCmdDesc *res = create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_GROUP, name, group_help, true);
2236  if (!res) {
2237  return NULL;
2238  }
2239 
2240  RzCmdDesc *exec_cd = NULL;
2241  if (cb && help) {
2243  exec_cd = argv_new(cmd, res, name, cb, help, false);
2244  if (!exec_cd) {
2245  rz_cmd_desc_remove(cmd, res);
2246  return NULL;
2247  }
2248  }
2249 
2250  res->d.group_data.exec_cd = exec_cd;
2251  return res;
2252 }
2253 
2268 RZ_API RzCmdDesc *rz_cmd_desc_group_modes_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvModesCb cb, const RzCmdDescHelp *help, const RzCmdDescHelp *group_help) {
2269  rz_return_val_if_fail(cmd && parent && name && group_help && modes && cb && help && help->args, NULL);
2270  RzCmdDesc *res = create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_GROUP, name, group_help, true);
2271  if (!res) {
2272  return NULL;
2273  }
2274 
2275  RzCmdDesc *exec_cd = argv_modes_new(cmd, res, name, modes, cb, help, false);
2276  if (!exec_cd) {
2277  rz_cmd_desc_remove(cmd, res);
2278  return NULL;
2279  }
2280 
2281  res->d.group_data.exec_cd = exec_cd;
2282  return res;
2283 }
2284 
2299 RZ_API RzCmdDesc *rz_cmd_desc_group_state_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvStateCb cb, const RzCmdDescHelp *help, const RzCmdDescHelp *group_help) {
2300  rz_return_val_if_fail(cmd && parent && name && group_help && modes && cb && help && help->args, NULL);
2301  RzCmdDesc *res = create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_GROUP, name, group_help, true);
2302  if (!res) {
2303  return NULL;
2304  }
2305 
2306  RzCmdDesc *exec_cd = argv_state_new(cmd, res, name, modes, cb, help, false);
2307  if (!exec_cd) {
2308  rz_cmd_desc_remove(cmd, res);
2309  return NULL;
2310  }
2311 
2312  res->d.group_data.exec_cd = exec_cd;
2313  return res;
2314 }
2315 
2317  rz_return_val_if_fail(cmd && parent && name && cb, NULL);
2319  if (!res) {
2320  return NULL;
2321  }
2322  res->d.oldinput_data.cb = cb;
2323  return res;
2324 }
2325 
2327  rz_return_val_if_fail(cmd && parent && name && help, NULL);
2328  return create_cmd_desc(cmd, parent, RZ_CMD_DESC_TYPE_FAKE, name, help, true);
2329 }
2330 
2333  return cd->parent;
2334 }
2335 
2337  rz_return_val_if_fail(cd, false);
2338  switch (cd->type) {
2339  case RZ_CMD_DESC_TYPE_ARGV:
2340  return cd->d.argv_data.cb;
2342  return cd->d.argv_modes_data.cb;
2344  return cd->d.argv_state_data.cb;
2346  return cd->d.oldinput_data.cb;
2347  case RZ_CMD_DESC_TYPE_FAKE:
2349  return false;
2351  return cd->d.group_data.exec_cd && rz_cmd_desc_has_handler(cd->d.group_data.exec_cd);
2352  }
2353  return false;
2354 }
2355 
2357  rz_return_val_if_fail(cmd && cd, false);
2358  if (cd->parent) {
2360  }
2362  cmd_desc_free(cd);
2363  return true;
2364 }
2365 
2376  const RzCmdDescArg *arg = cd->help->args;
2377  size_t j = 0;
2378  while (arg && arg->name) {
2379  if (arg->type == RZ_CMD_ARG_TYPE_FAKE) {
2380  arg++;
2381  continue;
2382  }
2383  if (i == j) {
2384  return arg;
2385  }
2386  if ((arg->flags & RZ_CMD_ARG_FLAG_LAST) || (arg->flags & RZ_CMD_ARG_FLAG_ARRAY)) {
2387  return arg;
2388  }
2389  arg++;
2390  j++;
2391  }
2392  return NULL;
2393 }
2394 
2396  dst->summary = rz_str_newf("%s%s", src->summary, suffix);
2397  dst->description = src->description;
2398  dst->args_str = src->args_str;
2399  dst->usage = src->usage;
2400  dst->options = src->options;
2401  dst->details = src->details;
2402  dst->args = src->args;
2403  return dst;
2404 }
2405 
2406 static void cmd_foreach_cmdname_modes(RzCmd *cmd, RzCmdDesc *cd, int modes, RzCmdForeachNameCb cb, void *user) {
2407  size_t i;
2408  for (i = 0; i < RZ_ARRAY_SIZE(argv_modes); i++) {
2409  if (modes & argv_modes[i].mode) {
2410  RzCmdDescHelp mode_help;
2411  const RzCmdDescHelp *copy = cd->help;
2412  cd->help = mode_cmd_desc_help(&mode_help, copy, argv_modes[i].summary_suffix);
2413 
2414  char *name = cd->name;
2415  cd->name = rz_str_newf("%s%s", name, argv_modes[i].suffix);
2416 
2417  cb(cmd, cd, user);
2418 
2419  free(cd->name);
2420  free((char *)mode_help.summary);
2421  cd->name = name;
2422  cd->help = copy;
2423  }
2424  }
2425 }
2426 
2428  if (!cd) {
2429  return;
2430  }
2431 
2432  void **it_cd;
2433 
2434  switch (cd->type) {
2435  case RZ_CMD_DESC_TYPE_ARGV:
2436  if (rz_cmd_desc_has_handler(cd)) {
2437  cb(cmd, cd, user);
2438  }
2439  break;
2441  cmd_foreach_cmdname_modes(cmd, cd, cd->d.argv_state_data.modes, cb, user);
2442  break;
2444  cmd_foreach_cmdname_modes(cmd, cd, cd->d.argv_modes_data.modes, cb, user);
2445  break;
2446  case RZ_CMD_DESC_TYPE_FAKE:
2447  break;
2449  if (rz_cmd_desc_has_handler(cd)) {
2450  cb(cmd, cd, user);
2451  }
2452  // fallthrough
2455  rz_cmd_desc_children_foreach(cd, it_cd) {
2456  RzCmdDesc *child = *it_cd;
2457  cmd_foreach_cmdname(cmd, child, cb, user);
2458  }
2459  break;
2460  }
2461 }
2462 
2475  RzCmdDesc *cd = begin ? begin : rz_cmd_get_root(cmd);
2476  cmd_foreach_cmdname(cmd, cd, cb, user);
2477 }
2478 
2479 static char *escape_special_chars(const char *s, const char *special_chars) {
2480  size_t s_len = strlen(s);
2481  char *d = RZ_NEWS(char, s_len * 2 + 1);
2482  int i, j = 0;
2483  for (i = 0; i < s_len; i++) {
2484  if (strchr(special_chars, s[i])) {
2485  d[j++] = '\\';
2486  }
2487  d[j++] = s[i];
2488  }
2489  d[j++] = '\0';
2490  return d;
2491 }
2492 
2493 static char *unescape_special_chars(const char *s, const char *special_chars) {
2494  char *dst = RZ_NEWS(char, strlen(s) + 1);
2495  int i, j = 0;
2496 
2497  for (i = 0; s[i]; i++) {
2498  if (s[i] != '\\' || !strchr(special_chars, s[i + 1])) {
2499  dst[j++] = s[i];
2500  continue;
2501  }
2502  dst[j++] = s[++i];
2503  if (!s[i]) {
2504  break;
2505  }
2506  }
2507  dst[j++] = '\0';
2508  return dst;
2509 }
2510 
2516 RZ_API char *rz_cmd_escape_arg(const char *arg, RzCmdEscape esc) {
2517  switch (esc) {
2518  case RZ_CMD_ESCAPE_ONE_ARG:
2526  case RZ_CMD_ESCAPE_PF_ARG:
2528  }
2530 }
2531 
2536 RZ_API char *rz_cmd_unescape_arg(const char *arg, RzCmdEscape esc) {
2537  switch (esc) {
2538  case RZ_CMD_ESCAPE_ONE_ARG:
2546  case RZ_CMD_ESCAPE_PF_ARG:
2548  }
2550 }
2551 
2560  if (state->mode == RZ_OUTPUT_MODE_JSON || state->mode == RZ_OUTPUT_MODE_LONG_JSON) {
2561  rz_return_if_fail(state->d.pj);
2562  pj_a(state->d.pj);
2563  }
2564 }
2565 
2574  if (state->mode == RZ_OUTPUT_MODE_JSON || state->mode == RZ_OUTPUT_MODE_LONG_JSON) {
2575  rz_return_if_fail(state->d.pj);
2576  pj_end(state->d.pj);
2577  }
2578 }
2579 
2591  va_list ap;
2592  va_start(ap, fmt);
2593  if (state->mode == RZ_OUTPUT_MODE_TABLE) {
2594  rz_return_if_fail(state->d.t);
2595  rz_table_set_vcolumnsf(state->d.t, fmt, ap);
2596  }
2597  va_end(ap);
2598 }
2599 
2605 
2606  switch (state->mode) {
2607  case RZ_OUTPUT_MODE_JSON:
2609  pj_free(state->d.pj);
2610  state->d.pj = NULL;
2611  break;
2612  case RZ_OUTPUT_MODE_TABLE:
2613  rz_table_free(state->d.t);
2614  state->d.t = NULL;
2615  break;
2616  default:
2617  break;
2618  }
2619 }
2620 
2626 
2628  free(state);
2629 }
2630 
2635  rz_return_val_if_fail(state, false);
2636 
2637  state->mode = mode;
2638  switch (state->mode) {
2639  case RZ_OUTPUT_MODE_TABLE:
2640  state->d.t = rz_table_new();
2641  if (!state->d.t) {
2642  return false;
2643  }
2644  break;
2645  case RZ_OUTPUT_MODE_JSON:
2647  state->d.pj = pj_new();
2648  if (!state->d.pj) {
2649  return false;
2650  }
2651  break;
2652  default:
2653  memset(&state->d, 0, sizeof(state->d));
2654  break;
2655  }
2656  return true;
2657 }
2658 
2670 
2671  char *s;
2672  switch (state->mode) {
2673  case RZ_OUTPUT_MODE_JSON:
2676  break;
2677  case RZ_OUTPUT_MODE_TABLE:
2678  s = rz_table_tostring(state->d.t);
2679  rz_cons_printf("%s", s);
2680  free(s);
2681  break;
2682  default:
2683  break;
2684  }
2685 }
2686 
2699  RzCmdDescDetail *detail_it = details;
2700  while (detail_it->name) {
2701  free((char *)detail_it->name);
2702  RzCmdDescDetailEntry *oentry, *entry;
2703  oentry = entry = (RzCmdDescDetailEntry *)detail_it->entries;
2704  while (entry && entry->text) {
2705  free((char *)entry->text);
2706  free((char *)entry->comment);
2707  free((char *)entry->arg_str);
2708  entry++;
2709  }
2710  free(oentry);
2711  detail_it++;
2712  }
2713  free(details);
2714 }
size_t len
Definition: 6502dis.c:15
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
#define R(x, b, m)
Definition: arc.h:168
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
ut16 val
Definition: armass64_const.h:6
static bool err
Definition: armass.c:435
static csh cd
Definition: asm_mips_cs.c:10
static SblHeader sb
Definition: bin_mbn.c:26
static void rz_cmd(int in, int out, const char *cmd)
Definition: rizin.c:7
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static void print_child_help(RzCmd *cmd, RzStrBuf *sb, RzCmdDesc *cd, size_t max_len, bool use_color)
Definition: cmd_api.c:1120
RZ_IPI int rz_output_mode_to_char(RzOutputMode mode)
Definition: cmd_api.c:73
static void fill_args_json(const RzCmd *cmd, const RzCmdDesc *cd, PJ *j)
Definition: cmd_api.c:1353
static void cmd_desc_remove_from_ht_cmds(RzCmd *cmd, RzCmdDesc *cd)
Definition: cmd_api.c:141
static const RzCmdDescDetail * get_cd_details(RzCmdDesc *cd)
Definition: cmd_api.c:1168
static const RzCmdDescHelp root_help
Definition: cmd_api.c:51
static const char * SPECIAL_CHARS_SINGLE_QUOTED
Definition: cmd_api.c:43
RZ_API void rz_cmd_macro_item_free(RzCmdMacroItem *item)
Definition: cmd_api.c:1530
RZ_API RzCmdParsedArgs * rz_cmd_parsed_args_newargs(int n_args, char **args)
Definition: cmd_api.c:2032
RZ_API void rz_cmd_desc_details_free(RzCmdDescDetail *details)
Free an array of RzCmdDescDetail sections.
Definition: cmd_api.c:2698
RZ_API bool rz_cmd_get_help_json(RzCmd *cmd, const RzCmdDesc *cd, PJ *j)
Generates a JSON output of the given help message description.
Definition: cmd_api.c:1439
RZ_API void rz_cmd_state_output_free(RZ_NONNULL RzCmdStateOutput *state)
Free the RzCmdStateOutput structure and its inner fields appropriately.
Definition: cmd_api.c:2624
static RzCmdDesc * cmd_get_desc_best(RzCmd *cmd, const char *cmd_identifier, bool best_match)
Definition: cmd_api.c:303
static void cmd_foreach_cmdname(RzCmd *cmd, RzCmdDesc *cd, RzCmdForeachNameCb cb, void *user)
Definition: cmd_api.c:2427
RZ_API RzCmdDesc * rz_cmd_get_desc(RzCmd *cmd, const char *cmd_identifier)
Retrieve the command descriptor for the command named cmd_identifier.
Definition: cmd_api.c:372
RZ_API char * rz_cmd_parsed_args_argstr(RzCmdParsedArgs *a)
Definition: cmd_api.c:2115
RZ_API void rz_cmd_batch_end(RzCmd *cmd)
Mark the end of the batched changes to RzCmd.
Definition: cmd_api.c:264
static char * escape_special_chars(const char *s, const char *special_chars)
Definition: cmd_api.c:2479
RZ_API int rz_cmd_macro_call_multiple(RzCmdMacro *mac, const char *name)
Definition: cmd_api.c:1997
#define CASE_TYPE(x, y)
RZ_API char * rz_cmd_parsed_args_execstr(RzCmdParsedArgs *a)
Definition: cmd_api.c:2122
RZ_API bool rz_cmd_desc_set_default_mode(RzCmdDesc *cd, RzOutputMode mode)
Set the default mode of the command descriptor, if the type allows it.
Definition: cmd_api.c:384
RZ_API bool rz_cmd_state_output_init(RZ_NONNULL RzCmdStateOutput *state, RzOutputMode mode)
Initialize a RzCmdStateOutput structure and its inner fields based on the provided mode.
Definition: cmd_api.c:2634
RZ_API RzCmdDesc * rz_cmd_desc_fake_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, const RzCmdDescHelp *help)
Definition: cmd_api.c:2326
RZ_API RzCmdDesc * rz_cmd_desc_argv_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, RzCmdArgvCb cb, const RzCmdDescHelp *help)
Definition: cmd_api.c:2153
RZ_API const char * rz_cmd_parsed_args_cmd(RzCmdParsedArgs *a)
Definition: cmd_api.c:2135
RZ_API void rz_cmd_foreach_cmdname(RzCmd *cmd, RzCmdDesc *begin, RzCmdForeachNameCb cb, void *user)
Execute a callback function on each possible command the user can execute.
Definition: cmd_api.c:2474
RZ_API void rz_cmd_alias_free(RzCmd *cmd)
Definition: cmd_api.c:419
RZ_API RzCmdDesc * rz_cmd_desc_oldinput_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, RzCmdCb cb, const RzCmdDescHelp *help)
Definition: cmd_api.c:2316
#define MIN_SUMMARY_WIDTH
Definition: cmd_api.c:32
static RzCmdDesc * argv_modes_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvModesCb cb, const RzCmdDescHelp *help, bool ht_insert)
Definition: cmd_api.c:2158
static bool show_children_shortcut(const RzCmdDesc *cd)
Definition: cmd_api.c:877
static const char * SPECIAL_CHARS_DOUBLE_QUOTED
Definition: cmd_api.c:42
#define MAX_CHILDREN_SHOW
Definition: cmd_api.c:30
static size_t strlen0(const char *s)
Definition: cmd_api.c:803
static void cmd_desc_free(RzCmdDesc *cd)
Definition: cmd_api.c:151
RZ_API void rz_cmd_state_output_set_columnsf(RzCmdStateOutput *state, const char *fmt,...)
Specify the columns of the command output.
Definition: cmd_api.c:2589
RZ_API bool rz_cmd_alias_del(RzCmd *cmd, const char *k)
Definition: cmd_api.c:431
RZ_API bool rz_cmd_parsed_args_setcmd(RzCmdParsedArgs *a, const char *cmd)
Definition: cmd_api.c:2094
RZ_API int rz_cmd_add(RzCmd *c, const char *cmd, RzCmdCb cb)
Definition: cmd_api.c:528
static RzCmdDescHelp * mode_cmd_desc_help(RzCmdDescHelp *dst, const RzCmdDescHelp *src, const char *suffix)
Definition: cmd_api.c:2395
RZ_API char * rz_cmd_unescape_arg(const char *arg, RzCmdEscape esc)
Definition: cmd_api.c:2536
static RzCmdDesc * argv_state_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvStateCb cb, const RzCmdDescHelp *help, bool ht_insert)
Definition: cmd_api.c:2171
static char * argv_get_help(RzCmd *cmd, RzCmdDesc *cd, size_t detail, bool use_color)
Definition: cmd_api.c:1266
RZ_LIB_VERSION(rz_cmd)
RZ_API int rz_cmd_macro_add(RzCmdMacro *mac, const char *oname)
Definition: cmd_api.c:1558
static const char * SPECIAL_CHARS_REGULAR_SINGLE
Definition: cmd_api.c:40
static void fill_details_do(RzCmd *cmd, const RzCmdDescDetail *detail_it, RzStrBuf *sb, bool use_color)
Definition: cmd_api.c:1189
static bool is_valid_argv_modes(RzCmdDesc *cd, char last_letter)
Definition: cmd_api.c:283
RZ_API void rz_cmd_macro_init(RzCmdMacro *mac)
Definition: cmd_api.c:1540
static char * fake_get_help(RzCmd *cmd, RzCmdDesc *cd, bool use_color)
Definition: cmd_api.c:1297
RZ_API void rz_cmd_state_output_array_start(RzCmdStateOutput *state)
Mark the start of an array of elements in the output.
Definition: cmd_api.c:2558
RZ_API int rz_cmd_call(RzCmd *cmd, const char *input)
Definition: cmd_api.c:546
static void fill_argv_modes_help_strbuf(RzCmd *cmd, RzStrBuf *sb, RzCmdDesc *cd, bool use_color)
Definition: cmd_api.c:1148
static int cd_sort(const void *a, const void *b)
Definition: cmd_api.c:100
static char * group_get_help(RzCmd *cmd, RzCmdDesc *cd, bool use_color)
Definition: cmd_api.c:1124
static const RzCmdDescHelp not_defined_help
Definition: cmd_api.c:45
static void fill_modes_children_chars(RzStrBuf *sb, const RzCmdDesc *cd)
Definition: cmd_api.c:812
RZ_IPI const char * rz_output_mode_to_summary(RzOutputMode mode)
Definition: cmd_api.c:83
static char * unescape_special_chars(const char *s, const char *special_chars)
Definition: cmd_api.c:2493
RZ_API bool rz_cmd_desc_has_handler(const RzCmdDesc *cd)
Definition: cmd_api.c:2336
RZ_API void rz_cmd_state_output_fini(RZ_NONNULL RzCmdStateOutput *state)
Clear the inner fields of RzCmdStateOutput structure, but do not free it.
Definition: cmd_api.c:2603
static void update_minmax_len(RzCmdDesc *cd, size_t *max_len, size_t *min_len, bool show_children)
Definition: cmd_api.c:1074
static bool has_cd_submodes(const RzCmdDesc *cd)
Definition: cmd_api.c:279
static char * get_help(RzCmd *cmd, RzCmdDesc *cd, const char *cmdid, RzCmdParsedArgs *args, bool use_color, size_t detail)
Definition: cmd_api.c:1324
RZ_API bool rz_cmd_get_help_strbuf(RzCmd *cmd, const RzCmdDesc *cd, bool use_color, RzStrBuf *sb)
Generates a text output of the given help message description (summary format)
Definition: cmd_api.c:1488
#define CASE_CDTYPE(x, y)
RZ_API RzCmdParsedArgs * rz_cmd_parsed_args_newcmd(const char *cmd)
Definition: cmd_api.c:2028
static RzCmdDesc * create_cmd_desc(RzCmd *cmd, RzCmdDesc *parent, RzCmdDescType type, const char *name, const RzCmdDescHelp *help, bool ht_insert)
Definition: cmd_api.c:161
RZ_API bool rz_cmd_parsed_args_setargs(RzCmdParsedArgs *a, int n_args, char **args)
Definition: cmd_api.c:2057
static void fill_details(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color)
Definition: cmd_api.c:1261
RZ_API int rz_cmd_alias_set(RzCmd *cmd, const char *k, const char *v, int remote)
Definition: cmd_api.c:458
static void sort_groups(RzCmdDesc *group)
Definition: cmd_api.c:244
static void args_preprocessing(RzCmdDesc *cd, RzCmdParsedArgs *args)
Definition: cmd_api.c:667
static void cmd_foreach_cmdname_modes(RzCmd *cmd, RzCmdDesc *cd, int modes, RzCmdForeachNameCb cb, void *user)
Definition: cmd_api.c:2406
RZ_API int rz_cmd_del(RzCmd *cmd, const char *command)
Definition: cmd_api.c:540
static RzCmdStatus call_cd(RzCmd *cmd, RzCmdDesc *cd, RzCmdParsedArgs *args)
Definition: cmd_api.c:763
RZ_API char * rz_cmd_alias_get(RzCmd *cmd, const char *k, int remote)
Definition: cmd_api.c:501
RZ_API void rz_cmd_macro_fini(RzCmdMacro *mac)
Definition: cmd_api.c:1551
RZ_API bool rz_cmd_desc_remove(RzCmd *cmd, RzCmdDesc *cd)
Definition: cmd_api.c:2356
static size_t strbuf_append_calc(RzStrBuf *sb, const char *s)
Definition: cmd_api.c:807
RZ_API int rz_cmd_macro_cmd_args(RzCmdMacro *mac, const char *ptr, const char *args, int nargs)
Definition: cmd_api.c:1729
#define NCMDS
Definition: cmd_api.c:95
RZ_API RzCmdDesc * rz_cmd_get_root(RzCmd *cmd)
Get the root command descriptor.
Definition: cmd_api.c:230
static void do_print_child_help(RzCmd *cmd, RzStrBuf *sb, const RzCmdDesc *cd, const char *name, const char *summary, bool show_children, size_t max_len, bool use_color)
Definition: cmd_api.c:1080
RZ_API int rz_cmd_macro_call(RzCmdMacro *mac, const char *name)
Definition: cmd_api.c:1993
RZ_API RzCmd * rz_cmd_free(RzCmd *cmd)
Definition: cmd_api.c:208
RZ_API RzCmdDesc * rz_cmd_desc_inner_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, const RzCmdDescHelp *help)
Definition: cmd_api.c:2217
RZ_API void rz_cmd_batch_start(RzCmd *cmd)
Mark the start of the batched changes to RzCmd.
Definition: cmd_api.c:240
RZ_API char * rz_cmd_macro_label_process(RzCmdMacro *mac, RzCmdMacroLabel *labels, int *labels_n, char *ptr)
Definition: cmd_api.c:1780
static RzOutputMode cd_suffix2mode(RzCmdDesc *cd, const char *cmdid)
Definition: cmd_api.c:640
RZ_API RzCmdStatus rz_cmd_call_parsed_args(RzCmd *cmd, RzCmdParsedArgs *args)
Definition: cmd_api.c:794
RZ_API RzCmdDesc * rz_cmd_desc_group_modes_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvModesCb cb, const RzCmdDescHelp *help, const RzCmdDescHelp *group_help)
Create a new command descriptor for a name that is used both as a group but that has a sub-command wi...
Definition: cmd_api.c:2268
RZ_API int rz_cmd_set_data(RzCmd *cmd, void *data)
Definition: cmd_api.c:523
static int macro_call(RzCmdMacro *mac, const char *name, bool multiple)
Definition: cmd_api.c:1853
RZ_API char * rz_cmd_get_help(RzCmd *cmd, RzCmdParsedArgs *args, bool use_color)
Definition: cmd_api.c:1494
RZ_API RzCmdDesc * rz_cmd_desc_argv_modes_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvModesCb cb, const RzCmdDescHelp *help)
Create a new command descriptor for a command that supports multiple output modes (e....
Definition: cmd_api.c:2195
RZ_API void rz_cmd_macro_meta(RzCmdMacro *mac)
Definition: cmd_api.c:1699
RZ_API RzCmd * rz_cmd_new(bool has_cons)
Definition: cmd_api.c:190
static int value
Definition: cmd_api.c:93
RZ_API int rz_cmd_macro_break(RzCmdMacro *mac, const char *value)
Definition: cmd_api.c:2001
RZ_API int rz_cmd_macro_rm(RzCmdMacro *mac, const char *_name)
Definition: cmd_api.c:1655
RZ_API RzCmdDesc * rz_cmd_desc_group_state_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvStateCb cb, const RzCmdDescHelp *help, const RzCmdDescHelp *group_help)
Create a new command descriptor for a name that is used both as a group but that has a sub-command wi...
Definition: cmd_api.c:2299
static void get_minmax_argc(RzCmdDesc *cd, int *min_argc, int *max_argc)
Definition: cmd_api.c:592
static RzCmdStatus int2cmdstatus(int v)
Definition: cmd_api.c:582
RZ_API const RzCmdDescArg * rz_cmd_desc_get_arg(RzCmd *cmd, const RzCmdDesc *cd, size_t i)
Get a reference to the i-th argument of a command descriptor.
Definition: cmd_api.c:2375
static bool cmd_desc_set_parent(RzCmd *cmd, RzCmdDesc *cd, RzCmdDesc *parent)
Definition: cmd_api.c:106
RZ_API RzCmdMacroItem * rz_cmd_macro_item_new(void)
Definition: cmd_api.c:1526
#define MAX_RIGHT_ALIGHNMENT
Definition: cmd_api.c:33
static bool has_cd_default_mode(RzCmdDesc *cd)
Definition: cmd_api.c:636
static size_t fill_children_chars(RzStrBuf *sb, const RzCmdDesc *cd)
Definition: cmd_api.c:823
static RzOutputMode get_cd_default_mode(RzCmdDesc *cd)
Definition: cmd_api.c:625
static const char * SPECIAL_CHARS_REGULAR
Definition: cmd_api.c:39
RZ_API RzCmdDesc * rz_cmd_desc_parent(RzCmdDesc *cd)
Definition: cmd_api.c:2331
RZ_API RzCmdDesc * rz_cmd_get_desc_best(RzCmd *cmd, const char *cmd_identifier)
Retrieve the command descriptor that best matches the name cmd_identifier.
Definition: cmd_api.c:355
RZ_API void rz_cmd_parsed_args_free(RzCmdParsedArgs *a)
Definition: cmd_api.c:2036
static void fill_wrapped_comment(RzCmd *cmd, RzStrBuf *sb, const char *comment, size_t columns, bool use_color)
Definition: cmd_api.c:906
static const char * SPECIAL_CHARS_PF
Definition: cmd_api.c:41
RZ_API RzCmdDesc * rz_cmd_desc_get_exec(RzCmdDesc *cd)
Definition: cmd_api.c:291
RZ_API void rz_cmd_state_output_print(RZ_NONNULL RzCmdStateOutput *state)
Print the output accumulated in state to RzCons, if necessary.
Definition: cmd_api.c:2668
static void free_array(char **arr, int n)
Definition: cmd_api.c:2049
static RzCmdStatus argv_call_cb(RzCmd *cmd, RzCmdDesc *cd, RzCmdParsedArgs *args)
Definition: cmd_api.c:704
static size_t calc_padding_len(const RzCmdDesc *cd, const char *name, bool show_children)
Definition: cmd_api.c:1051
RZ_API char * rz_cmd_escape_arg(const char *arg, RzCmdEscape esc)
Definition: cmd_api.c:2516
RZ_API bool rz_cmd_parsed_args_addarg(RzCmdParsedArgs *a, const char *arg)
Definition: cmd_api.c:2081
RZ_API void rz_cmd_state_output_array_end(RzCmdStateOutput *state)
Mark the end of an array of elements in the output.
Definition: cmd_api.c:2572
static RzCmdDesc * argv_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, RzCmdArgvCb cb, const RzCmdDescHelp *help, bool ht_insert)
Definition: cmd_api.c:2142
static void parsed_args_iterateargs(RzCmdParsedArgs *a, RzStrBuf *sb)
Definition: cmd_api.c:2105
static void fill_details_cb(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color)
Definition: cmd_api.c:1252
static size_t fill_args(RzStrBuf *sb, const RzCmdDesc *cd)
Definition: cmd_api.c:946
static void fill_details_static(RzCmd *cmd, RzCmdDesc *cd, RzStrBuf *sb, bool use_color)
Definition: cmd_api.c:1244
static void close_optionals(size_t *n_optionals, RzStrBuf *sb, size_t *len)
Definition: cmd_api.c:939
static void fill_usage_strbuf(RzCmd *cmd, RzStrBuf *sb, RzCmdDesc *cd, bool use_color)
Definition: cmd_api.c:997
static void fill_colored_args(RzCmd *cmd, RzStrBuf *sb, const char *line, bool use_color, const char *reset_color)
Definition: cmd_api.c:882
static RzCmdDescDetail * get_cd_details_cb(RzCmd *cmd, RzCmdDesc *cd)
Definition: cmd_api.c:1178
RZ_API void rz_cmd_alias_init(RzCmd *cmd)
Definition: cmd_api.c:184
static char * oldinput_get_help(RzCmd *cmd, RzCmdDesc *cd, RzCmdParsedArgs *a)
Definition: cmd_api.c:1302
RZ_API RzCmdDesc * rz_cmd_desc_argv_state_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, int modes, RzCmdArgvStateCb cb, const RzCmdDescHelp *help)
Create a new command descriptor for a command that supports multiple output modes (e....
Definition: cmd_api.c:2212
static RzOutputMode suffix2mode(const char *suffix)
Definition: cmd_api.c:269
RZ_API RzCmdParsedArgs * rz_cmd_parsed_args_new(const char *cmd, int n_args, char **args)
Definition: cmd_api.c:2013
static void cmd_desc_unset_parent(RzCmdDesc *cd)
Definition: cmd_api.c:133
RZ_API void rz_cmd_macro_list(RzCmdMacro *mac)
Definition: cmd_api.c:1680
RZ_API char ** rz_cmd_alias_keys(RzCmd *cmd, int *sz)
Definition: cmd_api.c:412
RZ_API RzCmdDesc * rz_cmd_desc_group_new(RzCmd *cmd, RzCmdDesc *parent, const char *name, RzCmdArgvCb cb, const RzCmdDescHelp *help, const RzCmdDescHelp *group_help)
Create a new command descriptor for a name that is used both as a group but that has a sub-command wi...
Definition: cmd_api.c:2233
static const struct argv_modes_t argv_modes[]
RZ_API void rz_cons_filter(void)
Definition: cons.c:836
RZ_API int rz_cons_get_size(int *rows)
Definition: cons.c:1446
RZ_API RZ_OWN char * rz_cons_get_buffer_dup(void)
Return a newly allocated buffer containing what's currently in RzCons buffer.
Definition: cons.c:827
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
RZ_API void rz_cons_strcat(const char *str)
Definition: cons.c:1263
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API bool rz_cons_is_interactive(void)
Definition: cons.c:365
RZ_API void rz_cons_flush(void)
Definition: cons.c:959
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
RZ_API void rz_cons_println(const char *str)
Definition: cons.c:233
RZ_API void rz_cons_set_flush(bool flush)
Set whether RzCons should flush content to screen or not.
Definition: cons.c:2006
RZ_API void rz_cons_pop(void)
Definition: cons.c:876
RZ_API void rz_cons_push(void)
Definition: cons.c:860
#define RZ_API
#define INT_MAX
Definition: cp-demangle.c:131
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
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 cmd
Definition: sflib.h:79
#define ut8
Definition: dcpu16.h:8
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
unsigned char suffix[65536]
Definition: gun.c:164
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char int mode
Definition: ioapi.h:137
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
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 * realloc(void *ptr, size_t size)
Definition: malloc.c:144
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 argv
Definition: sflib.h:40
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")
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
char * dst
Definition: lz4.h:724
while(len< limit &&buf1[len]==buf2[len])++len
int args
Definition: mipsasm.c:18
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
line
Definition: setup.py:34
int idx
Definition: setup.py:197
const char * name
Definition: op.c:541
int off
Definition: pal.c:13
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define rz_return_val_if_reached(val)
Definition: rz_assert.h:122
RZ_API ut8 * rz_base64_decode_dyn(const char *in, int len)
Definition: ubase64.c:65
#define RZ_CMD_MAXLEN
Definition: rz_cmd.h:18
bool(* RzCmdForeachNameCb)(RzCmd *cmd, const RzCmdDesc *desc, void *user)
Definition: rz_cmd.h:512
#define MACRO_LIMIT
Definition: rz_cmd.h:16
RzCmdStatus(* RzCmdArgvModesCb)(RzCore *core, int argc, const char **argv, RzOutputMode mode)
Definition: rz_cmd.h:109
@ RZ_CMD_ESCAPE_MULTI_ARG
The string should be escaped so that it appears as one or multiple arguments.
Definition: rz_cmd.h:80
@ RZ_CMD_ESCAPE_SINGLE_QUOTED_ARG
The string should be escaped so that it can be wrapped in '....'.
Definition: rz_cmd.h:83
@ RZ_CMD_ESCAPE_PF_ARG
The string should be escaped so that it appears as one or multiple pf arguments.
Definition: rz_cmd.h:81
@ RZ_CMD_ESCAPE_ONE_ARG
The string should be escaped so that it appears as one single argument.
Definition: rz_cmd.h:79
@ RZ_CMD_ESCAPE_DOUBLE_QUOTED_ARG
The string should be escaped so that it can be wrapped in "....".
Definition: rz_cmd.h:82
#define MACRO_LABELS
Definition: rz_cmd.h:17
#define RZ_CMD_ARG_FLAG_ARRAY
Definition: rz_cmd.h:72
int(* RzCmdCb)(void *user, const char *input)
Definition: rz_cmd.h:107
enum rz_cmd_desc_type_t RzCmdDescType
@ RZ_CMD_DESC_TYPE_ARGV_STATE
Definition: rz_cmd.h:403
@ RZ_CMD_DESC_TYPE_GROUP
Definition: rz_cmd.h:368
@ RZ_CMD_DESC_TYPE_ARGV
Definition: rz_cmd.h:361
@ RZ_CMD_DESC_TYPE_FAKE
Definition: rz_cmd.h:384
@ RZ_CMD_DESC_TYPE_ARGV_MODES
Definition: rz_cmd.h:391
@ RZ_CMD_DESC_TYPE_OLDINPUT
Definition: rz_cmd.h:355
@ RZ_CMD_DESC_TYPE_INNER
Definition: rz_cmd.h:376
enum rz_cmd_status_t RzCmdStatus
enum rz_cmd_escape_t RzCmdEscape
#define RZ_CMD_ARG_FLAG_LAST
Definition: rz_cmd.h:67
@ RZ_CMD_ARG_TYPE_FCN
Argument can be the name of an existing function.
Definition: rz_cmd.h:43
@ RZ_CMD_ARG_TYPE_MACRO
Argument is the name of a pre-defined macro.
Definition: rz_cmd.h:47
@ RZ_CMD_ARG_TYPE_CMD
Argument is an rizin command.
Definition: rz_cmd.h:46
@ RZ_CMD_ARG_TYPE_STRING
Argument that can be an arbitrary string.
Definition: rz_cmd.h:40
@ RZ_CMD_ARG_TYPE_EVAL_KEY
Argument is the name of a evaluable variable (e.g. et command)
Definition: rz_cmd.h:48
@ RZ_CMD_ARG_TYPE_EVAL_FULL
Argument is the name+(optional)value of a evaluable variable (e.g. e command)
Definition: rz_cmd.h:49
@ RZ_CMD_ARG_TYPE_OPTION
Argument is an option, prefixed with -. It is present or not. No argument.
Definition: rz_cmd.h:45
@ RZ_CMD_ARG_TYPE_CHOICES
Argument can be one of the provided choices.
Definition: rz_cmd.h:42
@ RZ_CMD_ARG_TYPE_NUM
Argument is a number.
Definition: rz_cmd.h:38
@ RZ_CMD_ARG_TYPE_RZNUM
Argument that can be interpreted by RzNum (numbers, flags, operations, etc.)
Definition: rz_cmd.h:39
@ RZ_CMD_ARG_TYPE_FILE
Argument is a filename.
Definition: rz_cmd.h:44
@ RZ_CMD_ARG_TYPE_ENV
Argument can be the name of an existing rizin variable.
Definition: rz_cmd.h:41
@ RZ_CMD_ARG_TYPE_FAKE
This is not considered a real argument, just used to show something in the help. Name of arg is shown...
Definition: rz_cmd.h:37
RzCmdStatus(* RzCmdArgvCb)(RzCore *core, int argc, const char **argv)
Definition: rz_cmd.h:108
@ RZ_CMD_STATUS_OK
command handler exited in the right way
Definition: rz_cmd.h:24
@ RZ_CMD_STATUS_WRONG_ARGS
command handler could not handle the arguments passed to it
Definition: rz_cmd.h:25
@ RZ_CMD_STATUS_NONEXISTINGCMD
command does not exist
Definition: rz_cmd.h:28
@ RZ_CMD_STATUS_INVALID
command could not be executed (e.g. shell level error, bad expression, etc.)
Definition: rz_cmd.h:27
@ RZ_CMD_STATUS_ERROR
command handler had issues while running (e.g. allocation error, etc.)
Definition: rz_cmd.h:26
@ RZ_CMD_STATUS_EXIT
command handler asks to exit the prompt loop
Definition: rz_cmd.h:29
#define RZ_CMD_ARG_FLAG_OPTION
Definition: rz_cmd.h:76
RzCmdStatus(* RzCmdArgvStateCb)(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state)
Definition: rz_cmd.h:110
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API PJ * pj_ko(PJ *j, const char *k)
Definition: pj.c:156
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
Definition: pj.c:177
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_s(PJ *j, const char *k)
Definition: pj.c:197
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_array_join(const char **a, size_t n, const char *sep)
Definition: str.c:3861
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API RzList * rz_str_wrap(char *str, size_t width)
Definition: str.c:3996
RZ_API int rz_str_word_set0(char *str)
Definition: str.c:423
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 const char * rz_str_word_get0(const char *str, int idx)
Definition: str.c:598
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API bool rz_strbuf_prepend(RzStrBuf *sb, const char *s)
Definition: strbuf.c:201
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RZ_API bool rz_strbuf_is_empty(RzStrBuf *sb)
Definition: strbuf.c:24
RZ_API int rz_strbuf_length(RzStrBuf *sb)
Definition: strbuf.c:28
RZ_API void rz_table_free(RzTable *t)
Definition: table.c:114
RZ_API bool rz_table_query(RzTable *t, const char *q)
Definition: table.c:1050
RZ_API void rz_table_set_vcolumnsf(RzTable *t, const char *fmt, va_list ap)
Specify the types and names of the referenced table.
Definition: table.c:193
RZ_API char * rz_table_tostring(RzTable *t)
Definition: table.c:510
RZ_API RzTable * rz_table_new(void)
Definition: table.c:103
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
RzOutputMode
Enum to describe the way data are printed.
Definition: rz_types.h:38
@ RZ_OUTPUT_MODE_TABLE
Definition: rz_types.h:46
@ RZ_OUTPUT_MODE_LONG
Definition: rz_types.h:44
@ RZ_OUTPUT_MODE_JSON
Definition: rz_types.h:40
@ RZ_OUTPUT_MODE_QUIET
Definition: rz_types.h:42
@ RZ_OUTPUT_MODE_LONG_JSON
Definition: rz_types.h:45
@ RZ_OUTPUT_MODE_SDB
Definition: rz_types.h:43
@ RZ_OUTPUT_MODE_QUIETEST
Definition: rz_types.h:47
@ RZ_OUTPUT_MODE_RIZIN
Definition: rz_types.h:41
@ RZ_OUTPUT_MODE_STANDARD
Definition: rz_types.h:39
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_FREE(x)
Definition: rz_types.h:369
RZ_API void rz_pvector_sort(RzPVector *vec, RzPVectorComparator cmp)
Definition: vector.c:408
RZ_API void rz_pvector_remove_data(RzPVector *vec, void *x)
Definition: vector.c:362
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
#define SIZE_MAX
const char * name
Definition: sparc-opc.c:1838
RzOutputMode mode
Definition: cmd_api.c:60
const char * summary_suffix
Definition: cmd_api.c:59
const char * suffix
Definition: cmd_api.c:58
Definition: zipcmp.c:77
const char * comment
Definition: zipcmp.c:84
Definition: dis.h:35
Definition: z80asm.h:130
char * name
Definition: z80asm.h:132
char ** args
Definition: z80asm.h:134
Definition: z80asm.h:102
Definition: rz_pj.h:12
A detailed entry that can be used to show additional info about a command entry.
Definition: rz_cmd.h:172
const char * comment
Definition: rz_cmd.h:180
const char * text
Definition: rz_cmd.h:176
const char * arg_str
Definition: rz_cmd.h:187
const char * name
Definition: rz_cmd.h:197
const RzCmdDescDetailEntry * entries
Definition: rz_cmd.h:201
const char * summary
Definition: rz_cmd.h:289
const char * usage
Definition: rz_cmd.h:311
bool sort_subcommands
Definition: rz_cmd.h:327
const RzCmdDescHelp * help
Definition: rz_cmd.h:444
RzCmdDescType type
Definition: rz_cmd.h:418
struct rz_cmd_desc_t::@262::@267 argv_state_data
union rz_cmd_desc_t::@262 d
RzPVector children
Definition: rz_cmd.h:440
struct rz_cmd_desc_t::@262::@264 argv_data
int n_children
Definition: rz_cmd.h:436
char * name
Definition: rz_cmd.h:425
struct rz_cmd_desc_t::@262::@265 group_data
struct rz_cmd_desc_t::@262::@263 oldinput_data
struct rz_cmd_desc_t::@262::@266 argv_modes_data
RzCmdCb callback
Definition: rz_cmd.h:153
char cmd[64]
Definition: rz_cmd.h:152
ut64 _brk_value
Definition: rz_cmd.h:139
RzCoreCmd cmd
Definition: rz_cmd.h:142
PrintfCallback cb_printf
Definition: rz_cmd.h:143
ut64 * brk_value
Definition: rz_cmd.h:138
void * user
Definition: rz_cmd.h:144
RzNum * num
Definition: rz_cmd.h:145
RzList * macros
Definition: rz_cmd.h:148
bool has_space_after_cmd
Definition: rz_cmd.h:119
Represent the output state of a command handler.
Definition: rz_cmd.h:91
RzConsPrintablePalette pal
Definition: rz_cons.h:491
RzConsContext * context
Definition: rz_cons.h:502
ut64 value
Definition: rz_num.h:63
Definition: dis.h:43
uv_loop_t * loop
Definition: main.c:7
const char * command
Definition: main.c:7
#define V(handle, symbol)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
int summary
Definition: zipcmp.c:234