mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-26 17:15:38 +00:00
Added ev and evj command
This commit is contained in:
parent
5398cc78f8
commit
ca56112550
@ -16,6 +16,7 @@ R_API RConfigNode* r_config_node_new(const char *name, const char *value) {
|
||||
node->value = strdup (value? value: "");
|
||||
node->flags = CN_RW | CN_STR;
|
||||
node->i_value = r_num_get (NULL, value);
|
||||
node->options = r_list_new ();
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -30,6 +31,7 @@ R_API RConfigNode* r_config_node_clone(RConfigNode *n) {
|
||||
cn->i_value = n->i_value;
|
||||
cn->flags = n->flags;
|
||||
cn->setter = n->setter;
|
||||
cn->options = r_list_clone (n->options);
|
||||
return cn;
|
||||
}
|
||||
|
||||
@ -41,15 +43,108 @@ R_API void r_config_node_free(void *n) {
|
||||
free (node->name);
|
||||
free (node->desc);
|
||||
free (node->value);
|
||||
r_list_free (node->options);
|
||||
free (node);
|
||||
}
|
||||
|
||||
static void config_print_value_json(RConfig *cfg, RConfigNode *node) {
|
||||
const char *val = node->value;
|
||||
if (node->flags & CN_BOOL || node->flags & CN_INT || node->flags & CN_OFFT) {
|
||||
if (!val) {
|
||||
val = "0";
|
||||
}
|
||||
if (!strncmp (val, "0x", 2)) {
|
||||
ut64 n = r_num_get (NULL, val);
|
||||
cfg->cb_printf ("%"PFMT64d, n);
|
||||
} else if (r_str_isnumber (val) || !strcmp (val, "true") || !strcmp (val, "false")) {
|
||||
cfg->cb_printf ("%s", val);
|
||||
} else {
|
||||
char *sval = r_str_escape (val);
|
||||
cfg->cb_printf ("\"%s\"", sval);
|
||||
free (sval);
|
||||
}
|
||||
} else {
|
||||
cfg->cb_printf ("\"%s\"", val);
|
||||
}
|
||||
}
|
||||
|
||||
static void config_print_node(RConfig *cfg, RConfigNode *node, const char *pfx, const char *sfx, bool verbose, bool json) {
|
||||
char *option;
|
||||
bool is_first;
|
||||
RListIter *iter;
|
||||
char *es = NULL;
|
||||
|
||||
if (json) {
|
||||
if (verbose) {
|
||||
cfg->cb_printf ("{");
|
||||
cfg->cb_printf ("\"name\":\"%s\",", node->name);
|
||||
cfg->cb_printf ("\"value\":");
|
||||
config_print_value_json (cfg, node);
|
||||
cfg->cb_printf (",\"type\":\"%s\",", r_config_node_type (node));
|
||||
es = r_str_escape (node->desc);
|
||||
if (es) {
|
||||
cfg->cb_printf ("\"desc\":\"%s\",", es);
|
||||
free (es);
|
||||
}
|
||||
cfg->cb_printf ("\"ro\":%s", node->flags & CN_RO ? "true" : "false");
|
||||
if (!r_list_empty (node->options)) {
|
||||
is_first = true;
|
||||
cfg->cb_printf (",\"options\":[");
|
||||
r_list_foreach (node->options, iter, option) {
|
||||
es = r_str_escape (option);
|
||||
if (es) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
} else {
|
||||
cfg->cb_printf (",");
|
||||
}
|
||||
cfg->cb_printf ("\"%s\"", es);
|
||||
free (es);
|
||||
}
|
||||
}
|
||||
cfg->cb_printf ("]");
|
||||
}
|
||||
cfg->cb_printf ("}");
|
||||
} else {
|
||||
cfg->cb_printf ("\"%s\":", node->name);
|
||||
config_print_value_json (cfg, node);
|
||||
}
|
||||
} else {
|
||||
if (verbose) {
|
||||
cfg->cb_printf ("%s%s = %s%s %s; %s", pfx,
|
||||
node->name, node->value, sfx,
|
||||
node->flags & CN_RO ? "(ro)" : "",
|
||||
node->desc);
|
||||
if (!r_list_empty (node->options)) {
|
||||
is_first = true;
|
||||
cfg->cb_printf(" [");
|
||||
r_list_foreach (node->options, iter, option) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
} else {
|
||||
cfg->cb_printf(", ");
|
||||
}
|
||||
cfg->cb_printf("%s", option);
|
||||
}
|
||||
cfg->cb_printf("]");
|
||||
}
|
||||
cfg->cb_printf ("\n");
|
||||
} else {
|
||||
cfg->cb_printf ("%s%s = %s%s\n", pfx,
|
||||
node->name, node->value, sfx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
|
||||
RConfigNode *node;
|
||||
RListIter *iter;
|
||||
const char *sfx = "";
|
||||
const char *pfx = "";
|
||||
int len = 0;
|
||||
bool verbose = false;
|
||||
bool json = false;
|
||||
bool json_is_first = false;
|
||||
|
||||
if (!STRNULL (str)) {
|
||||
str = r_str_chop_ro (str);
|
||||
@ -60,11 +155,12 @@ R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
|
||||
pfx = "\"e ";
|
||||
sfx = "\"";
|
||||
/* fallthrou */
|
||||
case 'v':
|
||||
verbose = true;
|
||||
case 0:
|
||||
r_list_foreach (cfg->nodes, iter, node) {
|
||||
if (!str || (str && (!strncmp (str, node->name, len)))) {
|
||||
cfg->cb_printf ("%s%s = %s%s\n", pfx,
|
||||
node->name, node->value, sfx);
|
||||
config_print_node (cfg, node, pfx, sfx, verbose, json);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -83,39 +179,33 @@ R_API void r_config_list(RConfig *cfg, const char *str, int rad) {
|
||||
cfg->cb_printf ("%s\n", node->name);
|
||||
}
|
||||
break;
|
||||
case 'J':
|
||||
verbose = true;
|
||||
case 'j':
|
||||
cfg->cb_printf ("{");
|
||||
json = true;
|
||||
json_is_first = true;
|
||||
if (verbose) {
|
||||
cfg->cb_printf ("[");
|
||||
} else {
|
||||
cfg->cb_printf ("{");
|
||||
}
|
||||
r_list_foreach (cfg->nodes, iter, node) {
|
||||
if (!str || (str && (!strncmp (str, node->name, len)))) {
|
||||
if (!str || !strncmp (str, node->name, len)) {
|
||||
const char *val = node->value;
|
||||
if (node->flags & CN_BOOL || node->flags & CN_INT || node->flags & CN_OFFT) {
|
||||
if (!val) {
|
||||
val = "0";
|
||||
}
|
||||
if (!strncmp (val, "0x", 2)) {
|
||||
ut64 n = r_num_get (NULL, val);
|
||||
cfg->cb_printf ("\"%s\":%"PFMT64d,
|
||||
node->name, n);
|
||||
} else if (r_str_isnumber (val) || !strcmp (val, "true") || !strcmp (val, "false")) {
|
||||
cfg->cb_printf ("\"%s\":%s",
|
||||
node->name, val);
|
||||
} else {
|
||||
char *sval = r_str_escape (val);
|
||||
cfg->cb_printf ("\"%s\":\"%s\"", node->name, sval);
|
||||
free (sval);
|
||||
}
|
||||
} else {
|
||||
cfg->cb_printf ("\"%s\":\"%s\"",
|
||||
node->name, val);
|
||||
}
|
||||
if (iter->n) {
|
||||
if (!json_is_first) {
|
||||
cfg->cb_printf (",");
|
||||
} else {
|
||||
json_is_first = false;
|
||||
}
|
||||
config_print_node (cfg, node, pfx, sfx, verbose, json);
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg->cb_printf ("}\n");
|
||||
if (verbose) {
|
||||
cfg->cb_printf ("]\n");
|
||||
} else {
|
||||
cfg->cb_printf ("}\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,14 @@
|
||||
|
||||
#include <r_core.h>
|
||||
|
||||
#define SETI(x,y,z) r_config_node_desc(r_config_set_i(cfg,x,y), z);
|
||||
#define SETICB(w,x,y,z) r_config_node_desc(r_config_set_i_cb(cfg,w,x,y), z);
|
||||
#define SETPREF(x,y,z) r_config_node_desc(r_config_set(cfg,x,y), z);
|
||||
#define SETCB(w,x,y,z) r_config_node_desc(r_config_set_cb(cfg,w,x,y), z);
|
||||
#define NODECB(w,x,y) r_config_set_cb(cfg,w,x,y)
|
||||
#define NODEICB(w,x,y) r_config_set_i_cb(cfg,w,x,y)
|
||||
#define SETDESC(x,y) r_config_node_desc(x,y)
|
||||
#define SETOPTION(x,y) r_list_append((x)->options,strdup(y))
|
||||
#define SETI(x,y,z) SETDESC(r_config_set_i(cfg,x,y), z);
|
||||
#define SETICB(w,x,y,z) SETDESC(NODEICB(w,x,y), z);
|
||||
#define SETPREF(x,y,z) SETDESC(r_config_set(cfg,x,y), z);
|
||||
#define SETCB(w,x,y,z) SETDESC(NODECB(w,x,y), z);
|
||||
|
||||
/* TODO: use loop here */
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
@ -788,7 +792,11 @@ static int cb_dbg_btalgo(void *user, void *data) {
|
||||
RCore *core = (RCore*) user;
|
||||
RConfigNode *node = (RConfigNode*) data;
|
||||
if (*node->value == '?') {
|
||||
r_cons_printf ("default\nfuzzy\nanal\n");
|
||||
RListIter *iter;
|
||||
char *option;
|
||||
r_list_foreach (node->options, iter, option) {
|
||||
r_cons_printf ("%s\n", option);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
free (core->dbg->btalgo);
|
||||
@ -1733,6 +1741,7 @@ static char *getViewerPath() {
|
||||
R_API int r_core_config_init(RCore *core) {
|
||||
int i;
|
||||
char buf[128], *p, *tmpdir;
|
||||
RConfigNode *n;
|
||||
RConfig *cfg = core->config = r_config_new (core);
|
||||
if (!cfg) {
|
||||
return 0;
|
||||
@ -1998,7 +2007,11 @@ R_API int r_core_config_init(RCore *core) {
|
||||
|
||||
SETPREF("dbg.bpinmaps", "true", "Force breakpoints to be inside a valid map");
|
||||
SETCB("dbg.forks", "false", &cb_dbg_forks, "Stop execution if fork() is done (see dbg.threads)");
|
||||
SETCB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo, "Select backtrace algorithm");
|
||||
n = NODECB("dbg.btalgo", "fuzzy", &cb_dbg_btalgo);
|
||||
SETDESC(n, "Select backtrace algorithm");
|
||||
SETOPTION(n, "default");
|
||||
SETOPTION(n, "fuzzy");
|
||||
SETOPTION(n, "anal");
|
||||
SETCB("dbg.threads", "false", &cb_stopthreads, "Stop all threads when debugger breaks (see dbg.forks)");
|
||||
SETCB("dbg.clone", "false", &cb_dbg_clone, "Stop execution if new thread is created");
|
||||
SETCB("dbg.aftersyscall", "true", &cb_dbg_aftersc, "Stop execution before the syscall is executed (see dcs)");
|
||||
|
@ -214,6 +214,24 @@ static int cmd_eval(void *data, const char *input) {
|
||||
case 'j': // json
|
||||
r_config_list (core->config, NULL, 'j');
|
||||
break;
|
||||
case 'v': // verbose
|
||||
switch (input[1]) {
|
||||
default:
|
||||
if (strlen (input) > 2) {
|
||||
r_config_list (core->config, input + 2, 'v');
|
||||
} else {
|
||||
r_config_list (core->config, NULL, 'v');
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
if (strlen (input) > 3) {
|
||||
r_config_list (core->config, input + 3, 'J');
|
||||
} else {
|
||||
r_config_list (core->config, NULL, 'J');
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'q': // quiet list of eval keys
|
||||
r_config_list (core->config, NULL, 'q');
|
||||
break;
|
||||
@ -351,7 +369,6 @@ static int cmd_eval(void *data, const char *input) {
|
||||
r_core_config_init (core);
|
||||
//eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
|
||||
break;
|
||||
case 'v': eprintf ("Invalid command '%s'. Use 'e?'\n", input); break;
|
||||
case '*': r_config_list (core->config, NULL, 1); break;
|
||||
case '?':
|
||||
switch (input[1]) {
|
||||
@ -362,7 +379,7 @@ static int cmd_eval(void *data, const char *input) {
|
||||
"Usage:", "e [var[=value]]", "Evaluable vars",
|
||||
"e","?asm.bytes", "show description",
|
||||
"e", "??", "list config vars with description",
|
||||
"e", "", "list config vars",
|
||||
"e|ej", "", "list config vars (in JSON)",
|
||||
"e-", "", "reset config vars",
|
||||
"e*", "", "dump config vars in r commands",
|
||||
"e!", "a", "invert the boolean value of 'a' var",
|
||||
@ -370,6 +387,7 @@ static int cmd_eval(void *data, const char *input) {
|
||||
"er", " [key]", "set config key as readonly. no way back",
|
||||
"ec", " [k] [color]", "set color for given key (prompt, offset, ...)",
|
||||
"et", " [key]", "show type of given config variable",
|
||||
"ev|evj", " [key]", "list config vars in verbose format (in JSON)",
|
||||
"e", " a", "get value of var 'a'",
|
||||
"e", " a=b", "set var 'a' the 'b' value",
|
||||
"e var=?", "", "print all valid values of var",
|
||||
|
@ -30,6 +30,7 @@ typedef struct r_config_node_t {
|
||||
RConfigCallback getter;
|
||||
RConfigCallback setter;
|
||||
char *desc;
|
||||
RList *options;
|
||||
} RConfigNode;
|
||||
|
||||
R_API const char *r_config_node_type(RConfigNode *node);
|
||||
|
Loading…
x
Reference in New Issue
Block a user