Add new implementation of RzConfig (#5820)
This commit is contained in:
parent
d3a97d5ef8
commit
bd44250fd6
57 changed files with 3853 additions and 1321 deletions
|
|
@ -141,54 +141,46 @@ static struct {
|
|||
};
|
||||
|
||||
int disass_6502(ut64 pc, RzAsmOp *op, const ut8 *buf, ut64 len) {
|
||||
int i;
|
||||
for (i = 0; ops[i].name != NULL; i++) {
|
||||
if (ops[i].op == buf[0]) {
|
||||
int len = ops[i].len;
|
||||
switch (ops[i].len) {
|
||||
case 1:
|
||||
rz_asm_op_setf_asm(op, "%s", ops[i].name);
|
||||
break;
|
||||
case 2:
|
||||
if (len > 1) {
|
||||
rz_asm_op_setf_asm(op, ops[i].name, buf[1]);
|
||||
} else {
|
||||
rz_asm_op_set_asm(op, "truncated");
|
||||
len = -1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (len > 2) {
|
||||
rz_asm_op_setf_asm(op, ops[i].name, buf[1] + 0x100 * buf[2]);
|
||||
} else {
|
||||
rz_asm_op_set_asm(op, "truncated");
|
||||
len = -1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (len > 3) {
|
||||
rz_asm_op_setf_asm(op, ops[i].name, buf[1] + 0x100 * buf[2] + 0x10000 * buf[3]);
|
||||
} else {
|
||||
rz_asm_op_set_asm(op, "truncated");
|
||||
len = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rz_asm_op_set_asm(op, "invalid");
|
||||
goto beach;
|
||||
}
|
||||
return len;
|
||||
for (size_t i = 0; ops[i].name != NULL; i++) {
|
||||
if (ops[i].op != buf[0]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int len = ops[i].len;
|
||||
switch (len) {
|
||||
case 1:
|
||||
rz_asm_op_set_asm(op, ops[i].name);
|
||||
break;
|
||||
case 2:
|
||||
if (len > 1) {
|
||||
rz_asm_op_setf_asm(op, ops[i].name, buf[1]);
|
||||
} else {
|
||||
rz_asm_op_set_asm(op, "truncated");
|
||||
len = -1;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (len > 2) {
|
||||
rz_asm_op_setf_asm(op, ops[i].name, buf[1] + 0x100 * buf[2]);
|
||||
} else {
|
||||
rz_asm_op_set_asm(op, "truncated");
|
||||
len = -1;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (len > 3) {
|
||||
rz_asm_op_setf_asm(op, ops[i].name, buf[1] + 0x100 * buf[2] + 0x10000 * buf[3]);
|
||||
} else {
|
||||
rz_asm_op_set_asm(op, "truncated");
|
||||
len = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rz_asm_op_set_asm(op, "invalid");
|
||||
goto beach;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
beach:
|
||||
return snesDisass(1, 1, pc, op, buf, len);
|
||||
}
|
||||
|
||||
_6502State *_6502_state_new() {
|
||||
_6502State *state = RZ_NEW0(_6502State);
|
||||
if (!state) {
|
||||
RZ_LOG_ERROR("Could not allocate memory for _6502State!");
|
||||
return NULL;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
|
@ -5,10 +5,9 @@
|
|||
#define DISASSEMBLE_6502_H
|
||||
|
||||
typedef struct {
|
||||
RzConfig *cfg;
|
||||
ut8 magic;
|
||||
} _6502State;
|
||||
|
||||
_6502State *_6502_state_new();
|
||||
int disass_6502(ut64 pc, RzAsmOp *op, const ut8 *buf, ut64 len);
|
||||
|
||||
#endif /* DISASSEMBLE_6502_H */
|
||||
|
|
|
|||
|
|
@ -266,10 +266,14 @@ typedef struct {
|
|||
bool just_init; ///< Flag indicates if IL VM was just initialized.
|
||||
HexPkt pkts[HEXAGON_STATE_PKTS]; // buffered instructions
|
||||
RzList /*<HexConstExt *>*/ *const_ext_l; // Constant extender values.
|
||||
RzConfig *cfg;
|
||||
RzPVector /*<RzAsmTokenPattern *>*/ *token_patterns; ///< PVector with token patterns. Priority ordered.
|
||||
bool utf8_enabled; ///< If set, print UTF-8 characters.
|
||||
bool might_have_jumped; ///< Is set if a previous IL packet was a branch. Indicates the next decoded packet is valid.
|
||||
|
||||
bool imm_hash; ///< Display ## before 32bit immediates and # before immidiates with other width.
|
||||
bool imm_sign; ///< True: Print them with sign. False: Print signed immediates in unsigned representation.
|
||||
bool sdk; ///< Print packet syntax in objdump style.
|
||||
bool reg_alias; ///< Print the alias of registers (Alias from C0 = SA0).
|
||||
} HexState;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ RZ_IPI void hexagon_state_fini(RZ_NULLABLE HexState *state) {
|
|||
if (!state) {
|
||||
return;
|
||||
}
|
||||
rz_config_free(state->cfg);
|
||||
rz_pvector_free(state->token_patterns);
|
||||
rz_list_free(state->const_ext_l);
|
||||
for (size_t i = 0; i < HEXAGON_STATE_PKTS; ++i) {
|
||||
|
|
@ -537,7 +536,7 @@ static void hex_set_pkt_info(RZ_INOUT HexInsnContainer *hic, const HexPkt *pkt,
|
|||
rz_return_if_fail(hic && pkt && state);
|
||||
bool is_first = (k == 0);
|
||||
HexPktInfo *hi_pi = &hic->pkt_info;
|
||||
bool sdk_form = rz_config_get_b(state->cfg, "plugins.hexagon.sdk");
|
||||
bool sdk_form = state->sdk;
|
||||
|
||||
strncpy(hi_pi->text_postfix, "", 16);
|
||||
// Parse instr. position in pkt
|
||||
|
|
|
|||
|
|
@ -36562,9 +36562,9 @@ static int get_jmp_target_imm_op_index(const HexInsnTemplate *tpl) {
|
|||
}
|
||||
|
||||
static void hex_disasm_with_templates(const HexInsnTemplate *tpl, HexState *state, ut32 hi_u32, RZ_INOUT HexInsn *hi, HexInsnContainer *hic, ut64 addr, HexPkt *pkt) {
|
||||
bool print_reg_alias = rz_config_get_b(state->cfg, "plugins.hexagon.reg.alias");
|
||||
bool show_hash = rz_config_get_b(state->cfg, "plugins.hexagon.imm.hash");
|
||||
bool sign_nums = rz_config_get_b(state->cfg, "plugins.hexagon.imm.sign");
|
||||
bool print_reg_alias = state->reg_alias;
|
||||
bool show_hash = state->imm_hash;
|
||||
bool sign_nums = state->imm_sign;
|
||||
char signed_imm[HEX_MAX_OPERANDS][32];
|
||||
// Find the right template
|
||||
for (; tpl->id; tpl++) {
|
||||
|
|
|
|||
|
|
@ -439,6 +439,7 @@ static int _6502_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8
|
|||
_6502ILAddr il_addr = { 0 };
|
||||
_6502ILAddr *il_addr_ptr = (mask & RZ_ANALYSIS_OP_MASK_IL) ? &il_addr : NULL;
|
||||
_6502State *cfg_state = (_6502State *)analysis->plugin_data;
|
||||
ut8 magic = cfg_state ? cfg_state->magic : 0xee;
|
||||
|
||||
switch (data[0]) {
|
||||
// SLO
|
||||
|
|
@ -838,12 +839,8 @@ static int _6502_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8
|
|||
op->cycles = 2;
|
||||
op->size = 2;
|
||||
if (mask & RZ_ANALYSIS_OP_MASK_IL) {
|
||||
ut8 magic = 0xee;
|
||||
_6502ILAddr addr;
|
||||
_6502_il_immediate(&addr, data[1]);
|
||||
if (cfg_state && cfg_state->cfg) {
|
||||
magic = (ut8)rz_config_get_i(cfg_state->cfg, "plugins.6502.magic");
|
||||
}
|
||||
op->il_op = _6502_il_op_laximm(&addr, magic);
|
||||
}
|
||||
break;
|
||||
|
|
@ -1132,12 +1129,8 @@ static int _6502_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8
|
|||
op->size = 2;
|
||||
op->cycles = 2;
|
||||
if (mask & RZ_ANALYSIS_OP_MASK_IL) {
|
||||
ut8 magic = 0xee;
|
||||
_6502ILAddr addr;
|
||||
_6502_il_immediate(&addr, data[1]);
|
||||
if (cfg_state && cfg_state->cfg) {
|
||||
magic = (ut8)rz_config_get_i(cfg_state->cfg, "plugins.6502.magic");
|
||||
}
|
||||
op->il_op = _6502_il_op_ane(&addr, magic);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -15,52 +15,57 @@ static int _6520_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int le
|
|||
return op->size = RZ_MAX(dlen, 0);
|
||||
}
|
||||
|
||||
RzConfig *_6502_get_config(void *plugin_data) {
|
||||
rz_return_val_if_fail(plugin_data, NULL);
|
||||
_6502State *state = (_6502State *)plugin_data;
|
||||
return rz_config_clone(state->cfg);
|
||||
static bool _6520_config_magic_get(void *user, void *data) {
|
||||
ut64 *value = data;
|
||||
_6502State *state = user;
|
||||
if (!state) {
|
||||
return false;
|
||||
}
|
||||
*value = state->magic;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _6502_cfg_set(void *user, void *data) {
|
||||
rz_return_val_if_fail(user && data, false);
|
||||
static bool _6520_config_magic_set(void *user, const void *data) {
|
||||
const ut64 *value = data;
|
||||
_6502State *state = user;
|
||||
RzConfig *pcfg = state->cfg;
|
||||
if (!state) {
|
||||
return false;
|
||||
}
|
||||
state->magic = *value;
|
||||
return true;
|
||||
}
|
||||
|
||||
RzConfigNode *cnode = (RzConfigNode *)data; // Config node from core.
|
||||
RzConfigNode *pnode = rz_config_node_get(pcfg, cnode->name); // Config node of plugin.
|
||||
if (pnode == cnode) {
|
||||
return true;
|
||||
static RzConfig *_6502_get_config(void *plugin_data) {
|
||||
rz_return_val_if_fail(plugin_data, NULL);
|
||||
_6502State *state = (_6502State *)plugin_data;
|
||||
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
if (!cfg) {
|
||||
return NULL;
|
||||
}
|
||||
if (cnode) {
|
||||
pnode->i_value = cnode->i_value;
|
||||
free(pnode->value);
|
||||
pnode->value = rz_str_dup(cnode->value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
// Add nodes
|
||||
rz_config_add_integer_bind(cfg,
|
||||
"plugins.6502.magic",
|
||||
"Determines the magic number certain illegal opcodes use.",
|
||||
_6520_config_magic_get,
|
||||
_6520_config_magic_set,
|
||||
NULL, state);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static bool _6502_init(void **user) {
|
||||
_6502State *state = _6502_state_new();
|
||||
rz_return_val_if_fail(state, false);
|
||||
RzConfig *cfg = state->cfg = rz_config_new(state);
|
||||
rz_return_val_if_fail(state->cfg, false);
|
||||
|
||||
SETICB("plugins.6502.magic", 0xee, &_6502_cfg_set, "Determines the magic number certain illegal opcodes use.");
|
||||
_6502State *state = RZ_NEW0(_6502State);
|
||||
if (!state) {
|
||||
return false;
|
||||
}
|
||||
state->magic = 0xee;
|
||||
*user = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _6502State_fini(_6502State *state) {
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
rz_config_free(state->cfg);
|
||||
return;
|
||||
}
|
||||
|
||||
static bool _6502_fini(void *user) {
|
||||
_6502State_fini(user);
|
||||
free(user);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,53 +85,51 @@ static RZ_OWN RzPVector /*<RzAsmTokenPattern *>*/ *get_token_patterns() {
|
|||
return pvec;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the plugins RzConfig nodes.
|
||||
*
|
||||
* \param user The user of the RzConfig node. If this callback is called by Core \p user = RzCore.
|
||||
* If it is called by the plugins config setup \p user = HexState.
|
||||
* \param data The node to set. Again, if called by RzCore \p date = Node from RzCore config.
|
||||
* If it is called by the plugins config setup \p data = a plugins config node.
|
||||
* \return bool True if the config was set. False otherwise.
|
||||
*/
|
||||
static bool hex_cfg_set(void *user, void *data) {
|
||||
rz_return_val_if_fail(user && data, false);
|
||||
HexState *state = user;
|
||||
RzConfig *pcfg = state->cfg;
|
||||
|
||||
RzConfigNode *cnode = (RzConfigNode *)data; // Config node from core.
|
||||
RzConfigNode *pnode = rz_config_node_get(pcfg, cnode->name); // Config node of plugin.
|
||||
if (pnode == cnode) {
|
||||
return true;
|
||||
}
|
||||
if (cnode) {
|
||||
pnode->i_value = cnode->i_value;
|
||||
free(pnode->value);
|
||||
pnode->value = rz_str_dup(cnode->value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hexagon_fini(void *user) {
|
||||
hexagon_state_fini(user);
|
||||
free(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define hexagon_getter_config(name, variable) \
|
||||
static bool hexagon_##name(void *user, void *data) { \
|
||||
bool *value = data; \
|
||||
HexState *state = user; \
|
||||
if (!state) { \
|
||||
return false; \
|
||||
} \
|
||||
*value = state->variable; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define hexagon_setter_config(name, variable) \
|
||||
static bool hexagon_##name(void *user, const void *data) { \
|
||||
const bool *value = data; \
|
||||
HexState *state = user; \
|
||||
if (!state) { \
|
||||
return false; \
|
||||
} \
|
||||
state->variable = *value; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define hexagon_config_callbacks(variable) \
|
||||
hexagon_setter_config(config_##variable##_set, variable); \
|
||||
hexagon_getter_config(config_##variable##_get, variable)
|
||||
|
||||
hexagon_config_callbacks(imm_hash);
|
||||
hexagon_config_callbacks(imm_sign);
|
||||
hexagon_config_callbacks(sdk);
|
||||
hexagon_config_callbacks(reg_alias);
|
||||
|
||||
static bool hexagon_init(void **plugin_data) {
|
||||
HexState *state = hexagon_state_new();
|
||||
rz_return_val_if_fail(state, false);
|
||||
|
||||
state->cfg = rz_config_new(state);
|
||||
rz_return_val_if_fail(state->cfg, false);
|
||||
|
||||
RzConfig *cfg = state->cfg; // Rename for SETCB macros.
|
||||
// Add nodes
|
||||
SETCB("plugins.hexagon.imm.hash", "true", &hex_cfg_set, "Display ## before 32bit immediates and # before immidiates with other width.");
|
||||
SETCB("plugins.hexagon.imm.sign", "true", &hex_cfg_set, "True: Print them with sign. False: Print signed immediates in unsigned representation.");
|
||||
SETCB("plugins.hexagon.sdk", "false", &hex_cfg_set, "Print packet syntax in objdump style.");
|
||||
SETCB("plugins.hexagon.reg.alias", "true", &hex_cfg_set, "Print the alias of registers (Alias from C0 = SA0).");
|
||||
state->imm_hash = true;
|
||||
state->imm_sign = true;
|
||||
state->sdk = false;
|
||||
state->reg_alias = true;
|
||||
|
||||
if (!state->token_patterns) {
|
||||
state->token_patterns = get_token_patterns();
|
||||
|
|
@ -145,7 +143,35 @@ static bool hexagon_init(void **plugin_data) {
|
|||
RZ_API RZ_OWN RzConfig *hexagon_get_config(void *plugin_data) {
|
||||
rz_return_val_if_fail(plugin_data, NULL);
|
||||
HexState *state = plugin_data;
|
||||
return rz_config_clone(state->cfg);
|
||||
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
if (!cfg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add nodes
|
||||
rz_config_add_bool_bind(cfg, "plugins.hexagon.imm.hash",
|
||||
"Display ## before 32bit immediates and # before immidiates with other width.",
|
||||
hexagon_config_imm_hash_get,
|
||||
hexagon_config_imm_hash_set,
|
||||
NULL, state);
|
||||
rz_config_add_bool_bind(cfg, "plugins.hexagon.imm.sign",
|
||||
"True: Print them with sign. False: Print signed immediates in unsigned representation.",
|
||||
hexagon_config_imm_sign_get,
|
||||
hexagon_config_imm_sign_set,
|
||||
NULL, state);
|
||||
rz_config_add_bool_bind(cfg, "plugins.hexagon.sdk",
|
||||
"Print packet syntax in objdump style.",
|
||||
hexagon_config_sdk_get,
|
||||
hexagon_config_sdk_set,
|
||||
NULL, state);
|
||||
rz_config_add_bool_bind(cfg, "plugins.hexagon.reg.alias",
|
||||
"Print the alias of registers (Alias from C0 = SA0).",
|
||||
hexagon_config_reg_alias_get,
|
||||
hexagon_config_reg_alias_set,
|
||||
NULL, state);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
76
librz/config/config_internal.h
Normal file
76
librz/config/config_internal.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// SPDX-FileCopyrightText: 2026 deroad <deroad@kumo.xn--q9jyb4c>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef CONFIG_INTERNAL_H
|
||||
#define CONFIG_INTERNAL_H
|
||||
|
||||
#include <rz_config.h>
|
||||
#include <rz_util.h>
|
||||
#include <rz_vector.h>
|
||||
|
||||
typedef struct config_value_t {
|
||||
const char *name; ///< Variable name
|
||||
ut32 flags; ///< Copy of the variable flags (see RzConfigVarFlags)
|
||||
union {
|
||||
char *string;
|
||||
ut64 integer;
|
||||
bool boolean;
|
||||
RzList /*<char *>*/ *list;
|
||||
RzInterval interval;
|
||||
} value; ///< Copy of the variable value
|
||||
} ConfigValue;
|
||||
|
||||
struct rz_config_hold_t {
|
||||
RzConfig *cfg;
|
||||
RzVector /*<ConfigValue>*/ variables;
|
||||
};
|
||||
|
||||
static int find_variable(const char *a_name, const RzConfigEntry *b, void *user) {
|
||||
const char *b_name = rz_config_entry_get_name(b);
|
||||
return strcmp(a_name, b_name);
|
||||
}
|
||||
|
||||
static inline RzConfigEntry *config_find_entry(RzConfig *cfg, const char *name) {
|
||||
size_t length = rz_vector_len(&cfg->sorted_vars);
|
||||
size_t index = rz_vector_find_sorted(&cfg->sorted_vars, (void *)name, (RzVectorComparator)find_variable, NULL);
|
||||
if (index >= length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rz_vector_index_ptr(&cfg->sorted_vars, index);
|
||||
}
|
||||
|
||||
#define config_find_entry_ro(cfg, name) ((const RzConfigEntry *)config_find_entry((RzConfig *)cfg, name))
|
||||
|
||||
static int sort_variables(const RzConfigEntry *a, const RzConfigEntry *b, void *user) {
|
||||
const char *a_name = rz_config_entry_get_name(a);
|
||||
const char *b_name = rz_config_entry_get_name(b);
|
||||
return strcmp(a_name, b_name);
|
||||
}
|
||||
|
||||
static inline void config_add_entry(RzConfig *cfg, const char *name, RzConfigEntry *entry, bool is_var) {
|
||||
entry->is_variable = is_var;
|
||||
|
||||
rz_vector_insert_sorted(&cfg->sorted_vars, entry, (RzVectorComparator)sort_variables, NULL);
|
||||
}
|
||||
|
||||
RZ_IPI RZ_OWN RzList /*<char *>*/ *rz_config_dup_list(RZ_NULLABLE const RzList /*<const char *>*/ *list);
|
||||
|
||||
RZ_IPI bool rz_config_var_set_bool(RzConfigVar *var, bool value);
|
||||
RZ_IPI bool rz_config_var_set_integer(RzConfigVar *var, ut64 value);
|
||||
RZ_IPI bool rz_config_var_set_string(RzConfigVar *var, const char *value);
|
||||
RZ_IPI bool rz_config_var_set_list(RzConfigVar *var, const RzList /*<const char *>*/ *value);
|
||||
RZ_IPI bool rz_config_var_set_list2(RzConfigVar *var, RZ_OWN RzList /*<char *>*/ *value);
|
||||
RZ_IPI bool rz_config_var_set_interval(RzConfigVar *var, RzInterval value);
|
||||
RZ_IPI bool rz_config_var_set_any(RzConfigVar *var, const char *value);
|
||||
RZ_IPI bool rz_config_toggle_var_bool(RzConfigVar *var);
|
||||
|
||||
/* old implementation */
|
||||
RZ_IPI void rz_config_node_fini(RZ_NULLABLE RzConfigNode *node);
|
||||
RZ_IPI bool rz_config_node_is_readonly(const RzConfigNode *node);
|
||||
RZ_IPI bool rz_config_node_set_readonly(RzConfigNode *node, bool read_only);
|
||||
RZ_IPI bool rz_config_node_set_string(RzConfigNode *node, const char *value, void *user);
|
||||
RZ_IPI bool rz_config_node_set_integer(RzConfigNode *node, ut64 i, void *user);
|
||||
RZ_IPI bool rz_config_node_set_bool(RzConfigNode *node, bool value, void *user);
|
||||
|
||||
#endif /* CONFIG_INTERNAL_H */
|
||||
|
|
@ -1,110 +1,112 @@
|
|||
// SPDX-FileCopyrightText: 2006-2021 pancake <pancake@nopcode.org>
|
||||
// SPDX-FileCopyrightText: 2026 deroad <deroad@kumo.xn--q9jyb4c>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_config.h>
|
||||
#include "config_internal.h"
|
||||
|
||||
static void rz_config_hold_char_free(RzConfigHoldChar *hc) {
|
||||
free(hc->key);
|
||||
free(hc->value);
|
||||
free(hc);
|
||||
static RzList /*<char *>*/ *config_hold_dup_safe_list(RzConfigVar *var) {
|
||||
// we do not know if the strings returned are
|
||||
// safe or not to be owned, so we just dup them
|
||||
RzList /*<const char *>*/ *list = rz_config_var_get_list(var);
|
||||
RzList *safe_list = rz_config_dup_list(list);
|
||||
rz_list_free(list);
|
||||
return safe_list;
|
||||
}
|
||||
|
||||
static void rz_config_hold_num_free(RzConfigHoldNum *hc) {
|
||||
free(hc->key);
|
||||
free(hc);
|
||||
static void config_hold_value_init_from_node(ConfigValue *cv, RzConfigNode *node) {
|
||||
cv->name = node->name;
|
||||
if (rz_config_node_is_bool(node)) {
|
||||
cv->flags = RZ_CONFIG_VAR_TYPE_BOOL;
|
||||
cv->value.boolean = rz_str_is_true(node->value);
|
||||
return;
|
||||
} else if (rz_config_node_is_int(node)) {
|
||||
cv->flags = RZ_CONFIG_VAR_TYPE_INT;
|
||||
cv->value.integer = node->i_value;
|
||||
return;
|
||||
}
|
||||
cv->flags = RZ_CONFIG_VAR_TYPE_STR;
|
||||
cv->value.string = rz_str_dup(node->value);
|
||||
}
|
||||
|
||||
static int key_cmp_hold_s(const void *a, const void *b, void *user) {
|
||||
const char *a_s = (const char *)a;
|
||||
const RzConfigHoldChar *b_s = (const RzConfigHoldChar *)b;
|
||||
return strcmp(a_s, b_s->key);
|
||||
static void config_hold_value_init_from_var(ConfigValue *cv, RzConfigVar *var) {
|
||||
cv->name = var->name;
|
||||
cv->flags = var->flags & RZ_CONFIG_VAR_TYPE_MASK;
|
||||
if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_BOOL)) {
|
||||
cv->value.boolean = rz_config_var_get_bool(var);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_STR)) {
|
||||
const char *str = rz_config_var_get_string(var);
|
||||
cv->value.string = rz_str_dup(str);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_LIST)) {
|
||||
cv->value.list = config_hold_dup_safe_list(var);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(var->flags, RZ_CONFIG_VAR_TYPE_INT)) {
|
||||
cv->value.integer = rz_config_var_get_integer(var);
|
||||
} else {
|
||||
cv->value.interval = rz_config_var_get_interval(var);
|
||||
}
|
||||
}
|
||||
|
||||
static int key_cmp_hold_i(const void *a, const void *b, void *user) {
|
||||
const char *a_s = (const char *)a;
|
||||
const RzConfigHoldNum *b_s = (const RzConfigHoldNum *)b;
|
||||
return strcmp(a_s, b_s->key);
|
||||
static bool config_hold_is_readonly(const RzConfigEntry *entry) {
|
||||
if (entry->is_variable) {
|
||||
return rz_config_var_is_readonly(&entry->var);
|
||||
}
|
||||
return rz_config_node_is_readonly(&entry->node);
|
||||
}
|
||||
|
||||
static void config_hold_variable_add(RzConfigHold *hold, const char *name) {
|
||||
RzConfigEntry *entry = config_find_entry(hold->cfg, name);
|
||||
if (!entry) {
|
||||
RZ_LOG_WARN("config-hold: failed to get '%s'\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (config_hold_is_readonly(entry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigValue cv = { 0 };
|
||||
if (entry->is_variable) {
|
||||
config_hold_value_init_from_var(&cv, &entry->var);
|
||||
} else {
|
||||
config_hold_value_init_from_node(&cv, &entry->node);
|
||||
}
|
||||
|
||||
rz_vector_push(&hold->variables, &cv);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Save the current values of a list of config options that have string values.
|
||||
* \brief Save a copy of the current config options.
|
||||
*
|
||||
* Get the current values of a list of config variables (terminated by NULL) and
|
||||
* save them in the RzConfigHold object \p h . \p rz_config_get is used to
|
||||
* retrieve the current config values.
|
||||
* Get the current values of the config and save them in the RzConfigHold object \p h .
|
||||
*
|
||||
* \param h Reference to RzConfigHold instance
|
||||
* \param ... List of config variables to save, terminated by NULL.
|
||||
* \return true if at least one variable is correctly saved, false otherwise
|
||||
* \param hold Reference to RzConfigHold instance
|
||||
* \param ... List of config variables to save, terminated by NULL.
|
||||
* \return Returns true if at least one variable is correctly saved, false otherwise
|
||||
*/
|
||||
RZ_API bool rz_config_hold_s(RzConfigHold *h, ...) {
|
||||
RZ_API bool rz_config_hold_var(RZ_NONNULL RzConfigHold *hold, ...) {
|
||||
rz_return_val_if_fail(hold, false);
|
||||
|
||||
va_list ap;
|
||||
char *key;
|
||||
va_start(ap, h);
|
||||
if (!h->list_char) {
|
||||
h->list_char = rz_list_newf((RzListFree)rz_config_hold_char_free);
|
||||
if (!h->list_char) {
|
||||
va_end(ap);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while ((key = va_arg(ap, char *))) {
|
||||
if (rz_list_find(h->list_char, key, key_cmp_hold_s, NULL)) {
|
||||
continue;
|
||||
}
|
||||
const char *val = rz_config_get(h->cfg, key);
|
||||
if (!val) {
|
||||
continue;
|
||||
}
|
||||
RzConfigHoldChar *hc = RZ_NEW0(RzConfigHoldChar);
|
||||
if (hc) {
|
||||
hc->key = rz_str_dup(key);
|
||||
hc->value = rz_str_dup(val);
|
||||
rz_list_append(h->list_char, hc);
|
||||
}
|
||||
const char *name;
|
||||
va_start(ap, hold);
|
||||
|
||||
while ((name = va_arg(ap, const char *))) {
|
||||
config_hold_variable_add(hold, name);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
return true;
|
||||
return rz_vector_len(&hold->variables) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Save the current values of a list of config options that have integer values.
|
||||
*
|
||||
* Get the current values of a list of config variables (terminated by NULL) and
|
||||
* save them in the RzConfigHold object \p h . \p rz_config_get_i is used to
|
||||
* retrieve the current config values.
|
||||
*
|
||||
* \param h Reference to RzConfigHold instance
|
||||
* \param ... List of config variables to save, terminated by NULL.
|
||||
* \return true if at least one variable is correctly saved, false otherwise
|
||||
*/
|
||||
RZ_API bool rz_config_hold_i(RzConfigHold *h, ...) {
|
||||
va_list ap;
|
||||
char *key;
|
||||
if (!h) {
|
||||
return false;
|
||||
static void config_hold_value_fini(void *e, void *user) {
|
||||
if (!e) {
|
||||
return;
|
||||
}
|
||||
if (!h->list_num) {
|
||||
h->list_num = rz_list_newf((RzListFree)rz_config_hold_num_free);
|
||||
if (!h->list_num) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConfigValue *cv = (ConfigValue *)e;
|
||||
if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_STR)) {
|
||||
free(cv->value.string);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_LIST)) {
|
||||
rz_list_free(cv->value.list);
|
||||
}
|
||||
va_start(ap, h);
|
||||
while ((key = va_arg(ap, char *))) {
|
||||
if (rz_list_find(h->list_num, key, key_cmp_hold_i, NULL)) {
|
||||
continue;
|
||||
}
|
||||
RzConfigHoldNum *hc = RZ_NEW0(RzConfigHoldNum);
|
||||
if (!hc) {
|
||||
continue;
|
||||
}
|
||||
hc->key = rz_str_dup(key);
|
||||
hc->value = rz_config_get_i(h->cfg, key);
|
||||
rz_list_append(h->list_num, hc);
|
||||
}
|
||||
va_end(ap);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,15 +115,69 @@ RZ_API bool rz_config_hold_i(RzConfigHold *h, ...) {
|
|||
* \param cfg RzConfig reference
|
||||
* \return RzConfigHold allocated object
|
||||
*/
|
||||
RZ_API RzConfigHold *rz_config_hold_new(RzConfig *cfg) {
|
||||
if (cfg) {
|
||||
RzConfigHold *hold = RZ_NEW0(RzConfigHold);
|
||||
if (hold) {
|
||||
hold->cfg = cfg;
|
||||
return hold;
|
||||
}
|
||||
RZ_API RzConfigHold *rz_config_hold_new(RZ_NONNULL RzConfig *cfg) {
|
||||
rz_return_val_if_fail(cfg, NULL);
|
||||
|
||||
RzConfigHold *hold = RZ_NEW0(RzConfigHold);
|
||||
if (!hold) {
|
||||
return false;
|
||||
}
|
||||
return NULL;
|
||||
hold->cfg = cfg;
|
||||
rz_vector_init(&hold->variables, sizeof(ConfigValue), config_hold_value_fini, NULL);
|
||||
return hold;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create an opaque object to save/restore some configuration options and saves the given variables.
|
||||
*
|
||||
* \param cfg RzConfig reference
|
||||
* \param ... List of config variables to save, terminated by NULL.
|
||||
* \return RzConfigHold allocated object
|
||||
*/
|
||||
RZ_API RzConfigHold *rz_config_hold_new2(RZ_NONNULL RzConfig *cfg, ...) {
|
||||
rz_return_val_if_fail(cfg, NULL);
|
||||
RzConfigHold *hold = rz_config_hold_new(cfg);
|
||||
if (!hold) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
const char *name;
|
||||
va_start(ap, cfg);
|
||||
|
||||
while ((name = va_arg(ap, const char *))) {
|
||||
config_hold_variable_add(hold, name);
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if (rz_vector_len(&hold->variables) < 1) {
|
||||
rz_config_hold_free(hold);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hold;
|
||||
}
|
||||
|
||||
static bool config_hold_set_bool(RzConfigEntry *entry, bool value, void *user) {
|
||||
if (entry->is_variable) {
|
||||
return rz_config_var_set_bool(&entry->var, value);
|
||||
}
|
||||
return rz_config_node_set_bool(&entry->node, value, user);
|
||||
}
|
||||
|
||||
static bool config_hold_set_integer(RzConfigEntry *entry, ut64 value, void *user) {
|
||||
if (entry->is_variable) {
|
||||
return rz_config_var_set_integer(&entry->var, value);
|
||||
}
|
||||
return rz_config_node_set_integer(&entry->node, value, user);
|
||||
}
|
||||
|
||||
static bool config_hold_set_string(RzConfigEntry *entry, const char *value, void *user) {
|
||||
if (entry->is_variable) {
|
||||
return rz_config_var_set_string(&entry->var, value);
|
||||
}
|
||||
return rz_config_node_set_string(&entry->node, value, user);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,17 +185,38 @@ RZ_API RzConfigHold *rz_config_hold_new(RzConfig *cfg) {
|
|||
*
|
||||
* \param h Reference to RzConfigHold
|
||||
*/
|
||||
RZ_API void rz_config_hold_restore(RzConfigHold *h) {
|
||||
RzListIter *iter;
|
||||
RzConfigHoldChar *hchar;
|
||||
RzConfigHoldNum *hnum;
|
||||
if (h) {
|
||||
RzConfig *cfg = h->cfg;
|
||||
rz_list_foreach (h->list_num, iter, hnum) {
|
||||
(void)rz_config_set_i(cfg, hnum->key, hnum->value);
|
||||
RZ_API void rz_config_hold_restore(RZ_NULLABLE RzConfigHold *hold) {
|
||||
if (!hold) {
|
||||
return;
|
||||
}
|
||||
|
||||
void *cfg_user = hold->cfg->user;
|
||||
|
||||
ConfigValue *cv;
|
||||
// we iterate from the last to the first as order matters.
|
||||
rz_vector_foreach_prev (&hold->variables, cv) {
|
||||
if (!cv->name) {
|
||||
continue;
|
||||
}
|
||||
rz_list_foreach (h->list_char, iter, hchar) {
|
||||
(void)rz_config_set(cfg, hchar->key, hchar->value);
|
||||
|
||||
RzConfigEntry *entry = config_find_entry(hold->cfg, cv->name);
|
||||
if (!entry) {
|
||||
RZ_LOG_WARN("config-hold: failed to get node named '%s'\n", cv->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_BOOL)) {
|
||||
config_hold_set_bool(entry, cv->value.boolean, cfg_user);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_INT)) {
|
||||
config_hold_set_integer(entry, cv->value.integer, cfg_user);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_STR)) {
|
||||
config_hold_set_string(entry, cv->value.string, cfg_user);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(cv->flags, RZ_CONFIG_VAR_TYPE_LIST)) {
|
||||
// ownership of list moved to var.
|
||||
rz_config_var_set_list(&entry->var, cv->value.list);
|
||||
cv->value.list = NULL;
|
||||
} else { /// RZ_CONFIG_VAR_TYPE_ITV
|
||||
rz_config_var_set_interval(&entry->var, cv->value.interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,10 +226,18 @@ RZ_API void rz_config_hold_restore(RzConfigHold *h) {
|
|||
*
|
||||
* \param h Reference to RzConfigHold
|
||||
*/
|
||||
RZ_API void rz_config_hold_free(RzConfigHold *h) {
|
||||
if (h) {
|
||||
rz_list_free(h->list_num);
|
||||
rz_list_free(h->list_char);
|
||||
RZ_FREE(h);
|
||||
RZ_API void rz_config_hold_free(RZ_NULLABLE RzConfigHold *h) {
|
||||
if (!h) {
|
||||
return;
|
||||
}
|
||||
rz_vector_fini(&h->variables);
|
||||
free(h);
|
||||
}
|
||||
|
||||
RZ_API void rz_config_hold_restore_and_free(RZ_NULLABLE RzConfigHold *hold) {
|
||||
if (!hold) {
|
||||
return;
|
||||
}
|
||||
rz_config_hold_restore(hold);
|
||||
rz_config_hold_free(hold);
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
rz_config_sources = [
|
||||
'old_config.c',
|
||||
'serialize_config.c',
|
||||
'config.c',
|
||||
'hold.c',
|
||||
'serialize_config.c'
|
||||
]
|
||||
|
||||
rz_config = library('rz_config', rz_config_sources,
|
||||
|
|
|
|||
526
librz/config/old_config.c
Normal file
526
librz/config/old_config.c
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
// SPDX-FileCopyrightText: 2006-2021 pancake <pancake@nopcode.org>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include "config_internal.h"
|
||||
|
||||
static bool config_node_init(RzConfigNode *node, RZ_NONNULL const char *name, RZ_NONNULL const char *value) {
|
||||
if (RZ_STR_ISEMPTY(name) || !value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
node->name = rz_str_dup(name);
|
||||
node->value = rz_str_dup(value);
|
||||
node->flags = CN_STR;
|
||||
node->i_value = rz_num_get(NULL, value);
|
||||
node->options = rz_list_new();
|
||||
|
||||
return node->name && node->value && node->options;
|
||||
}
|
||||
|
||||
RZ_IPI void rz_config_node_fini(RZ_NULLABLE RzConfigNode *node) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
free(node->name);
|
||||
free(node->desc);
|
||||
free(node->value);
|
||||
rz_list_free(node->options);
|
||||
}
|
||||
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL);
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (!entry || entry->is_variable) {
|
||||
return NULL;
|
||||
}
|
||||
return &entry->node;
|
||||
}
|
||||
|
||||
static const char *config_node_get(RzConfigNode *node) {
|
||||
if (rz_config_node_is_bool(node)) {
|
||||
return rz_str_bool(rz_str_is_true(node->value));
|
||||
}
|
||||
return node->value;
|
||||
}
|
||||
|
||||
static ut64 config_node_get_i(RzConfigNode *node) {
|
||||
if (node->i_value || !strcmp(node->value, "false")) {
|
||||
return node->i_value;
|
||||
}
|
||||
// TODO: Remove it once the switch to `rz_config_get_b()` is complete
|
||||
if (!strcmp(node->value, "true")) {
|
||||
return 1;
|
||||
}
|
||||
return (ut64)rz_num_math(NULL, node->value);
|
||||
}
|
||||
|
||||
static bool config_node_get_b(RzConfigNode *node) {
|
||||
if (!rz_config_node_is_bool(node)) {
|
||||
RZ_LOG_DEBUG("error: '%s' is not a boolean variable\n", node->name);
|
||||
return false;
|
||||
}
|
||||
return rz_str_is_true(node->value);
|
||||
}
|
||||
|
||||
static bool config_node_toggle(RzConfigNode *node, void *user) {
|
||||
if (!rz_config_node_is_bool(node)) {
|
||||
RZ_LOG_DEBUG("error: '%s' is not a boolean variable\n", node->name);
|
||||
return false;
|
||||
} else if (rz_config_node_is_ro(node)) {
|
||||
RZ_LOG_DEBUG("error: '%s' config key is read only\n", node->name);
|
||||
return false;
|
||||
}
|
||||
(void)rz_config_node_set_integer(node, !node->i_value, user);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the config variable of \p name as a string
|
||||
*/
|
||||
RZ_API RZ_BORROW const char *rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL);
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (!entry) {
|
||||
RZ_LOG_DEBUG("config: variable '%s' not found\n", name);
|
||||
return NULL;
|
||||
} else if (entry->is_variable) {
|
||||
return rz_config_var_get_string(&entry->var);
|
||||
}
|
||||
return config_node_get(&entry->node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value of the config variable of \p name only and only if
|
||||
* the variable is boolean, then tries to write back the inverted value.
|
||||
* Returns true in case of success.
|
||||
*/
|
||||
RZ_API bool rz_config_toggle(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), false);
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (!entry) {
|
||||
return false;
|
||||
} else if (entry->is_variable) {
|
||||
return rz_config_toggle_var_bool(&entry->var);
|
||||
}
|
||||
|
||||
return config_node_toggle(&entry->node, cfg->user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value of the config variable of \p name only and only if
|
||||
* the variable is integer.
|
||||
*/
|
||||
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), 0);
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (!entry) {
|
||||
RZ_LOG_DEBUG("config: variable '%s' not found\n", name);
|
||||
return 0;
|
||||
} else if (entry->is_variable) {
|
||||
return rz_config_var_get_integer(&entry->var);
|
||||
}
|
||||
return config_node_get_i(&entry->node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the value of the config variable of \p name only and only if
|
||||
* the variable is boolean. Returns false in case of the failure.
|
||||
*/
|
||||
RZ_API bool rz_config_get_b(RzConfig *cfg, RZ_NONNULL const char *name) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), false);
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (!entry) {
|
||||
RZ_LOG_DEBUG("config: variable '%s' not found\n", name);
|
||||
return NULL;
|
||||
} else if (entry->is_variable) {
|
||||
return rz_config_var_get_integer(&entry->var);
|
||||
}
|
||||
return config_node_get_b(&entry->node);
|
||||
}
|
||||
|
||||
RZ_API const char *rz_config_node_type(RzConfigNode *node) {
|
||||
rz_return_val_if_fail(node, "");
|
||||
|
||||
if (rz_config_node_is_bool(node)) {
|
||||
return "bool";
|
||||
}
|
||||
if (rz_config_node_is_str(node)) {
|
||||
return "str";
|
||||
}
|
||||
if (rz_config_node_is_int(node)) {
|
||||
return "int";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_cb(RZ_BORROW RzConfig *cfg, const char *name, const char *value, RzConfigCallback cb) {
|
||||
RzConfigNode *node = rz_config_set(cfg, name, value);
|
||||
if (node && (node->setter = cb)) {
|
||||
node->setter(cfg->user, node);
|
||||
}
|
||||
// it's not guaranteed that node is still pointing to the same object.
|
||||
// as this old config method will call the callback which may add new
|
||||
// config variables which will move or realloc the entry in the vector.
|
||||
return rz_config_node_get(cfg, name);
|
||||
}
|
||||
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i_cb(RZ_BORROW RzConfig *cfg, const char *name, st64 ivalue, RzConfigCallback cb) {
|
||||
RzConfigNode *node = rz_config_set_i(cfg, name, ivalue);
|
||||
if (node && (node->setter = cb)) {
|
||||
node->setter(cfg->user, node);
|
||||
}
|
||||
// it's not guaranteed that node is still pointing to the same object.
|
||||
// as this old config method will call the callback which may add new
|
||||
// config variables which will move or realloc the entry in the vector.
|
||||
return rz_config_node_get(cfg, name);
|
||||
}
|
||||
|
||||
static bool __is_true_or_false(const char *s) {
|
||||
return s && (!rz_str_casecmp(s, "true") || !rz_str_casecmp(s, "false"));
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_config_node_set_bool(RzConfigNode *node, bool value, void *user) {
|
||||
char *ov = NULL;
|
||||
ut64 oi = 0;
|
||||
if (rz_config_node_is_ro(node)) {
|
||||
RZ_LOG_ERROR("error: '%s' config key is read only\n", node->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
oi = node->i_value;
|
||||
if (node->value) {
|
||||
ov = rz_str_dup(node->value);
|
||||
}
|
||||
if (rz_config_node_is_bool(node)) {
|
||||
node->i_value = value ? 1 : 0;
|
||||
char *svalue = rz_str_dup(rz_str_bool(value));
|
||||
if (svalue) {
|
||||
free(node->value);
|
||||
node->value = svalue;
|
||||
}
|
||||
} else {
|
||||
RZ_LOG_ERROR("error: '%s' is not a boolean variable\n", node->name);
|
||||
free(ov);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node && node->setter) {
|
||||
if (!node->setter(user, node)) {
|
||||
if (oi != UT64_MAX) {
|
||||
node->i_value = oi;
|
||||
}
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(ov ? ov : "");
|
||||
}
|
||||
}
|
||||
|
||||
free(ov);
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_config_node_set_integer(RzConfigNode *node, ut64 i, void *user) {
|
||||
char buf[128], *ov = NULL;
|
||||
if (rz_config_node_is_ro(node)) {
|
||||
return false;
|
||||
}
|
||||
if (node->value) {
|
||||
ov = rz_str_dup(node->value);
|
||||
}
|
||||
rz_config_node_value_format_i(buf, sizeof(buf), i, NULL);
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(buf);
|
||||
if (!node->value) {
|
||||
free(ov);
|
||||
return false;
|
||||
}
|
||||
node->i_value = i;
|
||||
|
||||
if (node && node->setter) {
|
||||
ut64 oi = node->i_value;
|
||||
if (!node->setter(user, node)) {
|
||||
node->i_value = oi;
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(ov ? ov : "");
|
||||
free(ov);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
free(ov);
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_config_node_set_string(RzConfigNode *node, const char *value, void *user) {
|
||||
char *ov = NULL;
|
||||
ut64 oi;
|
||||
if (rz_config_node_is_ro(node)) {
|
||||
RZ_LOG_ERROR("error: '%s' config key is read only\n", node->name);
|
||||
return false;
|
||||
}
|
||||
if (node->value == value) {
|
||||
return true;
|
||||
}
|
||||
oi = node->i_value;
|
||||
if (node->value) {
|
||||
ov = rz_str_dup(node->value);
|
||||
if (!ov) {
|
||||
free(ov);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
free(node->value);
|
||||
node->value = rz_str_dup("");
|
||||
}
|
||||
if (rz_config_node_is_bool(node)) {
|
||||
bool b = rz_str_is_true(value);
|
||||
node->i_value = b ? 1 : 0;
|
||||
char *value = rz_str_dup(rz_str_bool(b));
|
||||
if (value) {
|
||||
free(node->value);
|
||||
node->value = value;
|
||||
}
|
||||
} else if (rz_config_node_is_str(node)) {
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(rz_str_get(value));
|
||||
} else {
|
||||
if (!value) {
|
||||
free(node->value);
|
||||
node->value = rz_str_dup("0");
|
||||
node->i_value = 0;
|
||||
} else {
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(value);
|
||||
if (IS_DIGIT(*value) || (value[0] == '-' && IS_DIGIT(value[1]))) {
|
||||
if (strchr(value, '/')) {
|
||||
node->i_value = rz_num_get(NULL, value);
|
||||
} else {
|
||||
node->i_value = rz_num_math(NULL, value);
|
||||
}
|
||||
} else {
|
||||
node->i_value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node && node->setter) {
|
||||
if (!node->setter(user, node)) {
|
||||
if (oi != UT64_MAX) {
|
||||
node->i_value = oi;
|
||||
}
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(ov ? ov : "");
|
||||
free(ov);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
free(ov);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the boolean \p value in the config variable of \p name only and only if
|
||||
* the variable is boolean.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_b(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, bool value) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL);
|
||||
|
||||
RzConfigNode *node = NULL;
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (entry) {
|
||||
if (entry->is_variable) {
|
||||
rz_config_var_set_bool(&entry->var, value);
|
||||
return NULL;
|
||||
}
|
||||
node = &entry->node;
|
||||
} else {
|
||||
if (cfg->lock) {
|
||||
return NULL;
|
||||
}
|
||||
RzConfigEntry new_entry = { 0 };
|
||||
if (!config_node_init(&new_entry.node, name, rz_str_bool(value))) {
|
||||
rz_config_node_fini(&new_entry.node);
|
||||
return NULL;
|
||||
}
|
||||
new_entry.node.flags = CN_BOOL;
|
||||
new_entry.node.i_value = value ? 1 : 0;
|
||||
config_add_entry(cfg, name, &new_entry, false);
|
||||
node = rz_config_node_get(cfg, name);
|
||||
}
|
||||
|
||||
if (!rz_config_node_set_bool(node, value, cfg->user)) {
|
||||
return NULL;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/* TODO: reduce number of strdups here */
|
||||
/**
|
||||
* Writes the string \p value in the config variable of \p name.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const char *value) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL);
|
||||
|
||||
RzConfigNode *node = NULL;
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (entry) {
|
||||
if (entry->is_variable) {
|
||||
rz_config_var_set_any(&entry->var, value);
|
||||
return NULL;
|
||||
}
|
||||
node = &entry->node;
|
||||
} else {
|
||||
if (cfg->lock) {
|
||||
return NULL;
|
||||
}
|
||||
RzConfigEntry new_entry = { 0 };
|
||||
if (!config_node_init(&new_entry.node, name, value)) {
|
||||
rz_config_node_fini(&new_entry.node);
|
||||
return NULL;
|
||||
}
|
||||
if (__is_true_or_false(value)) {
|
||||
new_entry.node.flags = CN_BOOL;
|
||||
new_entry.node.i_value = rz_str_is_true(value) ? 1 : 0;
|
||||
}
|
||||
config_add_entry(cfg, name, &new_entry, false);
|
||||
node = rz_config_node_get(cfg, name);
|
||||
}
|
||||
|
||||
if (!rz_config_node_set_string(node, value, cfg->user)) {
|
||||
return NULL;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/* rz_config_desc takes a RzConfig and a name,
|
||||
* rz_config_node_desc takes a RzConfigNode
|
||||
* Both set and return node->desc */
|
||||
RZ_API const char *rz_config_desc(RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc) {
|
||||
rz_return_val_if_fail(RZ_STR_ISNOTEMPTY(name), NULL);
|
||||
RzConfigNode *node = rz_config_node_get(cfg, name);
|
||||
return rz_config_node_desc(node, desc);
|
||||
}
|
||||
|
||||
RZ_API const char *rz_config_node_desc(RzConfigNode *node, RZ_NULLABLE const char *desc) {
|
||||
rz_return_val_if_fail(node, NULL);
|
||||
if (desc) {
|
||||
free(node->desc);
|
||||
node->desc = rz_str_dup(desc);
|
||||
}
|
||||
return node->desc;
|
||||
}
|
||||
|
||||
RZ_API void rz_config_node_value_format_i(RZ_OUT char *buf, size_t buf_size, const ut64 i, RZ_NULLABLE RzConfigNode *node) {
|
||||
if (node && rz_config_node_is_bool(node)) {
|
||||
rz_str_ncpy(buf, rz_str_bool((int)i), buf_size);
|
||||
return;
|
||||
}
|
||||
if (i < 1024) {
|
||||
snprintf(buf, buf_size, "%" PFMT64d, i);
|
||||
} else {
|
||||
snprintf(buf, buf_size, "0x%08" PFMT64x, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the integer \p value in the config variable of \p name only and only if
|
||||
* the variable is integer.
|
||||
*/
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i) {
|
||||
rz_return_val_if_fail(cfg && RZ_STR_ISNOTEMPTY(name), NULL);
|
||||
|
||||
RzConfigNode *node = NULL;
|
||||
RzConfigEntry *entry = config_find_entry(cfg, name);
|
||||
if (entry) {
|
||||
if (entry->is_variable) {
|
||||
rz_config_var_set_integer(&entry->var, i);
|
||||
return NULL;
|
||||
}
|
||||
node = &entry->node;
|
||||
} else {
|
||||
if (cfg->lock) {
|
||||
return NULL;
|
||||
}
|
||||
char buf[128];
|
||||
RzConfigEntry new_entry = { 0 };
|
||||
rz_config_node_value_format_i(buf, sizeof(buf), i, NULL);
|
||||
|
||||
if (!config_node_init(&new_entry.node, name, buf)) {
|
||||
rz_config_node_fini(&new_entry.node);
|
||||
return NULL;
|
||||
}
|
||||
new_entry.node.flags = CN_INT;
|
||||
new_entry.node.i_value = i;
|
||||
config_add_entry(cfg, name, &new_entry, false);
|
||||
node = rz_config_node_get(cfg, name);
|
||||
}
|
||||
|
||||
if (!rz_config_node_set_integer(node, i, cfg->user)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_config_node_is_readonly(const RzConfigNode *n) {
|
||||
return n->flags & CN_RO;
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_config_node_set_readonly(RzConfigNode *n, bool read_only) {
|
||||
if (read_only) {
|
||||
n->flags |= CN_RO;
|
||||
} else {
|
||||
n->flags &= ~CN_RO;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_API void rz_config_visual_hit_i(RzConfig *cfg, const char *name, int delta) {
|
||||
RzConfigNode *node = rz_config_node_get(cfg, name);
|
||||
if (node && rz_config_node_is_int(node)) {
|
||||
(void)rz_config_set_i(cfg, name, rz_config_get_i(cfg, name) + delta);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets the configuration variable and its value passed as argument
|
||||
*
|
||||
* \param cfg reference to RzConfig
|
||||
* \param str reference the configuration variable string (eg, 'asm.arch=x86')
|
||||
*/
|
||||
RZ_API bool rz_config_eval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *str) {
|
||||
rz_return_val_if_fail(str, false);
|
||||
|
||||
char *name = rz_str_trim_dup(str);
|
||||
char *value = strchr(name, '=');
|
||||
if (!value) {
|
||||
free(name);
|
||||
return false;
|
||||
}
|
||||
*value++ = 0;
|
||||
rz_config_set(cfg, name, value);
|
||||
free(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_API ut32 rz_config_node_get_var_flags(RZ_NONNULL const RzConfigNode *node) {
|
||||
rz_return_val_if_fail(node, 0);
|
||||
ut32 flags = 0;
|
||||
|
||||
if (!(node->flags & CN_RO)) {
|
||||
flags |= RZ_CONFIG_VAR_FLAG_WRITABLE;
|
||||
}
|
||||
if (node->flags & CN_BOOL) {
|
||||
flags |= RZ_CONFIG_VAR_TYPE_BOOL;
|
||||
}
|
||||
if (node->flags & CN_INT) {
|
||||
flags |= RZ_CONFIG_VAR_TYPE_INT;
|
||||
}
|
||||
if (node->flags & CN_STR) {
|
||||
flags |= RZ_CONFIG_VAR_TYPE_STR;
|
||||
}
|
||||
if (node->setter) {
|
||||
flags |= RZ_CONFIG_VAR_FLAG_BIND;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
|
@ -1,8 +1,22 @@
|
|||
// SPDX-FileCopyrightText: 2026 deroad <deroad@kumo.xn--q9jyb4c>
|
||||
// SPDX-FileCopyrightText: 2020 Florian Märkl <info@florianmaerkl.de>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_util/rz_serialize.h>
|
||||
#include <rz_config.h>
|
||||
#include "config_internal.h"
|
||||
|
||||
static bool config_serialize_to_sdb(const RzConfigEntry *entry, void *user) {
|
||||
Sdb *db = user;
|
||||
if (entry->is_variable) {
|
||||
char *value = rz_config_var_as_string(&entry->var);
|
||||
sdb_set(db, entry->var.name, value);
|
||||
free(value);
|
||||
} else {
|
||||
const RzConfigNode *node = &entry->node;
|
||||
sdb_set(db, node->name, node->value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -15,39 +29,43 @@
|
|||
* ...
|
||||
*
|
||||
*/
|
||||
|
||||
RZ_API void rz_serialize_config_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config) {
|
||||
RzListIter *iter;
|
||||
RzConfigNode *node;
|
||||
rz_list_foreach (config->nodes, iter, node) {
|
||||
sdb_set(db, node->name, node->value);
|
||||
}
|
||||
rz_config_iterate_over(config, config_serialize_to_sdb, db);
|
||||
}
|
||||
|
||||
typedef struct load_config_ctx_t {
|
||||
typedef struct deserialize_ctx_s {
|
||||
RzConfig *config;
|
||||
HtSP *exclude;
|
||||
} LoadConfigCtx;
|
||||
} DeserializeCtx;
|
||||
|
||||
static bool load_config_cb(void *user, const SdbKv *kv) {
|
||||
LoadConfigCtx *ctx = user;
|
||||
if (ctx->exclude && ht_sp_find_kv(ctx->exclude, sdbkv_key(kv), NULL)) {
|
||||
static bool config_deserialize_from_sdb(void *user, const SdbKv *kv) {
|
||||
DeserializeCtx *ctx = user;
|
||||
const char *key = sdbkv_key(kv);
|
||||
if (ctx->exclude && ht_sp_find_kv(ctx->exclude, key, NULL)) {
|
||||
return true;
|
||||
}
|
||||
RzConfigNode *node = rz_config_node_get(ctx->config, sdbkv_key(kv));
|
||||
if (!node) {
|
||||
return 1;
|
||||
|
||||
RzConfigEntry *entry = config_find_entry(ctx->config, key);
|
||||
if (!entry) {
|
||||
return true;
|
||||
}
|
||||
rz_config_set(ctx->config, sdbkv_key(kv), sdbkv_value(kv));
|
||||
return 1;
|
||||
|
||||
const char *value = sdbkv_value(kv);
|
||||
if (entry->is_variable) {
|
||||
rz_config_var_set_any(&entry->var, value);
|
||||
} else {
|
||||
rz_config_set(ctx->config, key, value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param exclude NULL-terminated array of keys to not load from the sdb.
|
||||
*/
|
||||
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config,
|
||||
RZ_NULLABLE const char *const *exclude, RZ_NULLABLE RzSerializeResultInfo *res) {
|
||||
LoadConfigCtx ctx = { config, NULL };
|
||||
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config, RZ_NULLABLE const char **exclude) {
|
||||
rz_return_val_if_fail(db && config, false);
|
||||
|
||||
DeserializeCtx ctx = { config, NULL };
|
||||
if (exclude) {
|
||||
ctx.exclude = ht_sp_new(HT_STR_DUP, NULL, NULL);
|
||||
if (!ctx.exclude) {
|
||||
|
|
@ -57,7 +75,7 @@ RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *co
|
|||
ht_sp_insert(ctx.exclude, *exclude, NULL);
|
||||
}
|
||||
}
|
||||
sdb_foreach(db, load_config_cb, &ctx);
|
||||
sdb_foreach(db, config_deserialize_from_sdb, &ctx);
|
||||
ht_sp_free(ctx.exclude);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2844,7 +2844,7 @@ static char *get_body(RzCore *core, ut64 addr, int size, int opts) {
|
|||
if (!hc) {
|
||||
return NULL;
|
||||
}
|
||||
rz_config_hold_i(hc, "asm.lines", "asm.bytes",
|
||||
rz_config_hold_var(hc, "asm.lines", "asm.bytes",
|
||||
"asm.cmt.col", "asm.marks", "asm.offset",
|
||||
"asm.comments", "asm.cmt.right", "asm.bb.line", NULL);
|
||||
const bool o_comments = rz_config_get_i(core->config, "graph.comments");
|
||||
|
|
@ -5103,7 +5103,7 @@ RZ_IPI int rz_core_visual_graph(RzCore *core, RzAGraph *g, RzAnalysisFunction *_
|
|||
if (!hc) {
|
||||
return false;
|
||||
}
|
||||
rz_config_hold_i(hc, "asm.pseudo", "asm.esil", "asm.cmt.right", NULL);
|
||||
rz_config_hold_var(hc, "asm.pseudo", "asm.esil", "asm.cmt.right", NULL);
|
||||
|
||||
int h, w = rz_cons_get_size(&h);
|
||||
can = rz_cons_canvas_new(w, h);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ static bool analysis_emul_init(RzCore *core, RzConfigHold *hc, RzDebugTrace **dt
|
|||
core->dbg->trace = rz_debug_trace_new();
|
||||
esil->trace = rz_analysis_esil_trace_new(esil);
|
||||
|
||||
rz_config_hold_i(hc, "esil.romem", "dbg.trace",
|
||||
rz_config_hold_var(hc, "esil.romem", "dbg.trace",
|
||||
"esil.nonull", "dbg.follow", NULL);
|
||||
rz_config_set(core->config, "esil.romem", "true");
|
||||
rz_config_set(core->config, "dbg.trace", "true");
|
||||
|
|
|
|||
|
|
@ -4559,7 +4559,7 @@ RZ_IPI bool rz_core_analysis_types_propagation(RzCore *core) {
|
|||
return false;
|
||||
}
|
||||
RzConfigHold *hold = rz_config_hold_new(core->config);
|
||||
rz_config_hold_i(hold, "io.va", "io.pcache.write", NULL);
|
||||
rz_config_hold_var(hold, "io.va", "io.pcache.write", NULL);
|
||||
bool io_cache = rz_config_get_b(core->config, "io.pcache.write");
|
||||
if (!io_cache) {
|
||||
// XXX. we shouldnt need this, but it breaks 'rizin -c aaa -w ls'
|
||||
|
|
@ -4854,7 +4854,7 @@ static void sdb_concat_by_path(Sdb *s, const char *path) {
|
|||
}
|
||||
|
||||
RZ_API void rz_core_analysis_cc_init_by_path(RzCore *core, RZ_NULLABLE const char *path, RZ_NULLABLE const char *homepath) {
|
||||
const char *analysis_arch = rz_config_get(core->config, "analysis.arch");
|
||||
const char *analysis_arch = rz_analysis_get_arch(core->analysis);
|
||||
Sdb *cc = rz_analysis_get_sdb_cc(core->analysis);
|
||||
if (!strcmp(analysis_arch, "null")) {
|
||||
sdb_reset(cc);
|
||||
|
|
|
|||
|
|
@ -325,7 +325,6 @@ static void core_set_asm_plugin_configs(RZ_BORROW RzCore *core) {
|
|||
return;
|
||||
}
|
||||
|
||||
rz_config_lock(pcfg, 1);
|
||||
if (!ht_sp_insert(core->plugin_configs, arch, pcfg)) {
|
||||
RZ_LOG_WARN("core: plugin '%s' was already added.\n", arch);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,22 +549,33 @@ static void autocmplt_cmd_arg_choices(RzCore *core, RzLineNSCompletionResult *re
|
|||
}
|
||||
}
|
||||
|
||||
static void autocmplt_cmd_arg_eval_key(RzCore *core, RzLineNSCompletionResult *res, const char *s, size_t len) {
|
||||
RzListIter *iter;
|
||||
RzConfigNode *bt;
|
||||
rz_list_foreach (core->config->nodes, iter, bt) {
|
||||
if (!strncmp(bt->name, s, len)) {
|
||||
rz_line_ns_completion_result_add(res, bt->name);
|
||||
}
|
||||
typedef struct autocmplt_context_s {
|
||||
RzLineNSCompletionResult *res;
|
||||
const char *prefix; ///< Prefix to search
|
||||
size_t len; ///< Prefix length
|
||||
} autocmplt_ctx_t;
|
||||
|
||||
static bool autocmplt_cmd_arg_eval_key_iterator(const RzConfigEntry *entry, void *user) {
|
||||
autocmplt_ctx_t *ctx = user;
|
||||
const char *e_name = rz_config_entry_get_name(entry);
|
||||
if (!strncmp(ctx->prefix, e_name, ctx->len)) {
|
||||
rz_line_ns_completion_result_add(ctx->res, e_name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void autocmplt_cmd_arg_eval_key(RzCore *core, RzLineNSCompletionResult *res, const char *prefix, size_t len) {
|
||||
autocmplt_ctx_t ctx = {
|
||||
res,
|
||||
prefix,
|
||||
len,
|
||||
};
|
||||
rz_config_iterate_over(core->config, autocmplt_cmd_arg_eval_key_iterator, &ctx);
|
||||
|
||||
RzConfig **plugin_cfg;
|
||||
RzIterator *it = ht_sp_as_iter(core->plugin_configs);
|
||||
rz_iterator_foreach(it, plugin_cfg) {
|
||||
rz_list_foreach ((*plugin_cfg)->nodes, iter, bt) {
|
||||
if (!strncmp(bt->name, s, len)) {
|
||||
rz_line_ns_completion_result_add(res, bt->name);
|
||||
}
|
||||
}
|
||||
rz_config_iterate_over((*plugin_cfg), autocmplt_cmd_arg_eval_key_iterator, &ctx);
|
||||
}
|
||||
rz_iterator_free(it);
|
||||
}
|
||||
|
|
@ -580,25 +591,26 @@ static void autocmplt_cmd_arg_eval_full(RzCore *core, RzLineNSCompletionResult *
|
|||
|
||||
char *k = rz_str_ndup(s, eq - s);
|
||||
char *v = NULL;
|
||||
RzConfigNode *node = rz_config_node_get(core->config, k);
|
||||
if (!node) {
|
||||
const RzList *options = rz_config_get_options(core->config, k);
|
||||
if (!options) {
|
||||
goto err;
|
||||
}
|
||||
const ut32 flags = rz_config_get_flags(core->config, k);
|
||||
|
||||
v = rz_str_ndup(eq + 1, len - (eq - s) - 1);
|
||||
len = strlen(v);
|
||||
|
||||
res->start += strlen(k) + 1;
|
||||
|
||||
if (node->options && rz_list_length(node->options)) {
|
||||
RzListIter *iter;
|
||||
char *opt;
|
||||
rz_list_foreach (node->options, iter, opt) {
|
||||
if (rz_list_length(options) > 0) {
|
||||
const RzListIter *iter;
|
||||
const char *opt;
|
||||
rz_list_foreach (options, iter, opt) {
|
||||
if (!strncmp(opt, v, len)) {
|
||||
rz_line_ns_completion_result_add(res, opt);
|
||||
}
|
||||
}
|
||||
} else if (rz_config_node_is_bool(node)) {
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_BOOL)) {
|
||||
if (!strncmp("true", v, len)) {
|
||||
rz_line_ns_completion_result_add(res, "true");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1135,36 +1135,30 @@ static bool cb_scrnull(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cb_color(void *user, void *data) {
|
||||
static bool core_scr_color_set(void *user, const void *pvalue) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
RzConfigNode *node = (RzConfigNode *)data;
|
||||
if (node->i_value) {
|
||||
ut64 value = *((const ut64 *)pvalue);
|
||||
|
||||
// ensure is never greater than COLOR_MODE_16M
|
||||
value = RZ_MIN(value, COLOR_MODE_16M);
|
||||
|
||||
if (value > 0) {
|
||||
core->print->flags |= RZ_PRINT_FLAGS_COLOR;
|
||||
} else {
|
||||
core->print->flags &= (~RZ_PRINT_FLAGS_COLOR);
|
||||
}
|
||||
if (!strcmp(node->value, "true")) {
|
||||
node->i_value = 1;
|
||||
} else if (!strcmp(node->value, "false")) {
|
||||
node->i_value = 0;
|
||||
}
|
||||
rz_cons_singleton()->context->color_mode = (node->i_value > COLOR_MODE_16M)
|
||||
? COLOR_MODE_16M
|
||||
: node->i_value;
|
||||
|
||||
core->cons->context->color_mode = value;
|
||||
rz_cons_pal_update_event();
|
||||
rz_print_set_flags(core->print, core->print->flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cb_color_getter(void *user, RzConfigNode *node) {
|
||||
(void)user;
|
||||
node->i_value = rz_cons_singleton()->context->color_mode;
|
||||
char buf[128];
|
||||
rz_config_node_value_format_i(buf, sizeof(buf), rz_cons_singleton()->context->color_mode, node);
|
||||
if (!node->value || strcmp(node->value, buf) != 0) {
|
||||
free(node->value);
|
||||
node->value = rz_str_dup(buf);
|
||||
}
|
||||
static bool core_scr_color_get(void *user, void *pvalue) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
ut64 *value = (ut64 *)pvalue;
|
||||
|
||||
*value = core->cons->context->color_mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1613,124 +1607,177 @@ static bool cb_iopcachewrite(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
RZ_API bool rz_core_esil_cmd(RzAnalysisEsil *esil, const char *cmd, ut64 a1, ut64 a2) {
|
||||
if (cmd && *cmd) {
|
||||
RzCore *core = (RzCore *)esil->pcore;
|
||||
rz_core_cmdf(core, "%s %" PFMT64d " %" PFMT64d, cmd, a1, a2);
|
||||
return core->num->value;
|
||||
static void config_print_options_as_json(PJ *pj, const RzList /*<char *>*/ *options) {
|
||||
RzListIter *iter;
|
||||
const char *option;
|
||||
pj_ka(pj, "options");
|
||||
rz_list_foreach (options, iter, option) {
|
||||
pj_s(pj, option);
|
||||
}
|
||||
return false;
|
||||
pj_end(pj);
|
||||
}
|
||||
|
||||
static void config_print_node(RzConfig *cfg, RzConfigNode *node, RzCmdStateOutput *state) {
|
||||
rz_return_if_fail(cfg && node && state);
|
||||
char *option;
|
||||
bool isFirst;
|
||||
RzOutputMode mode = state->mode;
|
||||
PJ *pj = state->d.pj;
|
||||
RzListIter *iter;
|
||||
char *es = NULL;
|
||||
static void config_print_node_value_as_json(const RzConfigNode *node, PJ *pj, const char *key) {
|
||||
if (rz_str_isnumber(node->value)) {
|
||||
pj_kn(pj, key, rz_num_math(NULL, node->value));
|
||||
return;
|
||||
} else if (rz_str_is_bool(node->value)) {
|
||||
pj_kb(pj, key, (node->value));
|
||||
return;
|
||||
} else {
|
||||
pj_ks(pj, key, node->value);
|
||||
}
|
||||
}
|
||||
|
||||
static void config_print_long_json(PJ *pj, const char *name, const char *desc, ut32 flags) {
|
||||
char *s_flags = rz_config_var_flags_as_string(flags);
|
||||
pj_ks(pj, "name", name);
|
||||
pj_ks(pj, "desc", rz_str_get(desc));
|
||||
pj_ks(pj, "flags", rz_str_get(s_flags));
|
||||
free(s_flags);
|
||||
}
|
||||
|
||||
static void config_print_node_as_long_json(const RzConfigNode *node, PJ *pj) {
|
||||
ut32 flags = rz_config_node_get_var_flags(node);
|
||||
pj_o(pj);
|
||||
config_print_long_json(pj, node->name, node->desc, flags);
|
||||
config_print_options_as_json(pj, node->options);
|
||||
config_print_node_value_as_json(node, pj, "value");
|
||||
pj_end(pj);
|
||||
}
|
||||
|
||||
static void config_print_var_as_long_json(const RzConfigVar *var, PJ *pj) {
|
||||
const char *name = rz_config_var_get_name(var);
|
||||
const char *desc = rz_config_var_get_desc(var);
|
||||
const RzList *options = rz_config_var_get_options(var);
|
||||
ut32 flags = rz_config_var_get_flags(var);
|
||||
pj_o(pj);
|
||||
config_print_long_json(pj, name, desc, flags);
|
||||
config_print_options_as_json(pj, options);
|
||||
rz_config_var_as_json(var, pj, "value");
|
||||
pj_end(pj);
|
||||
}
|
||||
|
||||
typedef struct core_config_print_s {
|
||||
RzCmdStateOutput *state;
|
||||
const char *str;
|
||||
char color_name[32];
|
||||
char color_value[32];
|
||||
char color_meta[32];
|
||||
char reset_str[32];
|
||||
} CoreConfigPrint;
|
||||
|
||||
static void core_config_print_array_as_string(const RzList /*<char *>*/ *list, bool allow_empty) {
|
||||
const char *entry;
|
||||
const RzListIter *it;
|
||||
if (rz_list_empty(list) && !allow_empty) {
|
||||
return;
|
||||
}
|
||||
rz_cons_print("[");
|
||||
rz_list_foreach (list, it, entry) {
|
||||
if (rz_list_head(list) != it) {
|
||||
rz_cons_printf(", %s", entry);
|
||||
} else {
|
||||
rz_cons_print(entry);
|
||||
}
|
||||
}
|
||||
rz_cons_print("]");
|
||||
}
|
||||
|
||||
static void core_config_print_var_as_string(const RzConfigEntry *entry, ut32 flags) {
|
||||
if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_INT)) {
|
||||
ut64 value = rz_config_entry_get_integer(entry);
|
||||
if (value > 0x1000) {
|
||||
rz_cons_printf("0x%" PFMT64x, value);
|
||||
} else {
|
||||
rz_cons_printf("%" PFMT64u, value);
|
||||
}
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_BOOL)) {
|
||||
bool value = rz_config_entry_get_bool(entry);
|
||||
rz_cons_print(rz_str_bool(value));
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_STR)) {
|
||||
const char *value = rz_config_entry_get_string(entry);
|
||||
rz_cons_print(value);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_LIST)) {
|
||||
RzList *list = rz_config_var_get_list(&entry->var);
|
||||
core_config_print_array_as_string(list, true);
|
||||
rz_list_free(list);
|
||||
} else if (RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_ITV)) {
|
||||
RzInterval itv = rz_config_var_get_interval(&entry->var);
|
||||
rz_cons_printf("[0x%08" PFMT64x ",0x%08" PFMT64x "]", rz_itv_begin(itv), rz_itv_end(itv));
|
||||
}
|
||||
}
|
||||
|
||||
static bool core_config_print_iterator(const RzConfigEntry *entry, void *user) {
|
||||
CoreConfigPrint *ccp = (CoreConfigPrint *)user;
|
||||
const char *e_name = rz_config_entry_get_name(entry);
|
||||
if (RZ_STR_ISNOTEMPTY(ccp->str) && !rz_str_startswith(e_name, ccp->str)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *name = NULL;
|
||||
const char *desc = "";
|
||||
const RzList *options = NULL;
|
||||
ut32 e_flags = 0;
|
||||
RzOutputMode mode = ccp->state->mode;
|
||||
PJ *pj = ccp->state->d.pj;
|
||||
|
||||
if (entry->is_variable) {
|
||||
name = rz_config_var_get_name(&entry->var);
|
||||
desc = rz_config_var_get_desc(&entry->var);
|
||||
options = rz_config_var_get_options(&entry->var);
|
||||
e_flags = rz_config_var_get_flags(&entry->var);
|
||||
} else {
|
||||
name = entry->node.name;
|
||||
desc = rz_str_get(entry->node.desc);
|
||||
options = entry->node.options;
|
||||
e_flags = rz_config_node_get_var_flags(&entry->node);
|
||||
}
|
||||
|
||||
char *s_flags = rz_config_var_flags_as_string(e_flags);
|
||||
|
||||
switch (mode) {
|
||||
case RZ_OUTPUT_MODE_JSON:
|
||||
if (rz_str_isnumber(node->value)) {
|
||||
pj_kn(pj, node->name, rz_num_math(NULL, node->value));
|
||||
return;
|
||||
} else if (rz_str_is_bool(node->value)) {
|
||||
pj_kb(pj, node->name, (node->value));
|
||||
return;
|
||||
if (entry->is_variable) {
|
||||
rz_config_var_as_json(&entry->var, pj, name);
|
||||
} else {
|
||||
pj_ks(pj, node->name, node->value);
|
||||
config_print_node_value_as_json(&entry->node, pj, name);
|
||||
}
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_LONG_JSON:
|
||||
pj_o(pj);
|
||||
pj_ks(pj, "name", node->name);
|
||||
if (rz_str_isnumber(node->value)) {
|
||||
pj_kn(pj, "value", rz_num_math(NULL, node->value));
|
||||
} else if (rz_str_is_bool(node->value)) {
|
||||
pj_kb(pj, "value", (node->value));
|
||||
if (entry->is_variable) {
|
||||
config_print_var_as_long_json(&entry->var, pj);
|
||||
} else {
|
||||
pj_ks(pj, "value", node->value);
|
||||
config_print_node_as_long_json(&entry->node, pj);
|
||||
}
|
||||
pj_ks(pj, "type", rz_config_node_type(node));
|
||||
es = rz_str_escape(node->desc);
|
||||
if (es) {
|
||||
pj_ks(pj, "desc", es);
|
||||
free(es);
|
||||
}
|
||||
pj_kb(pj, "ro", rz_config_node_is_ro(node));
|
||||
if (!rz_list_empty(node->options)) {
|
||||
pj_ka(pj, "options");
|
||||
rz_list_foreach (node->options, iter, option) {
|
||||
pj_s(pj, option);
|
||||
}
|
||||
pj_end(pj);
|
||||
}
|
||||
pj_end(pj);
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_LONG: {
|
||||
bool color_enabled = rz_config_get_i(cfg, "scr.color") > 0;
|
||||
char color_name[32], color_value[32], color_meta[32], reset_str[32];
|
||||
|
||||
if (color_enabled) {
|
||||
RzColor color_name_val = rz_cons_pal_get("label");
|
||||
RzColor color_value_val = rz_cons_pal_get("args");
|
||||
RzColor color_meta_val = rz_cons_pal_get("comment");
|
||||
RzColor reset_val = rz_cons_pal_get("help");
|
||||
rz_cons_rgb_str(color_name, sizeof(color_name), &color_name_val);
|
||||
rz_cons_rgb_str(color_value, sizeof(color_value), &color_value_val);
|
||||
rz_cons_rgb_str(color_meta, sizeof(color_meta), &color_meta_val);
|
||||
rz_cons_rgb_str(reset_str, sizeof(reset_str), &reset_val);
|
||||
} else {
|
||||
color_name[0] = color_value[0] = color_meta[0] = reset_str[0] = '\0';
|
||||
}
|
||||
const char *ro_str = rz_config_node_is_ro(node) ? "(ro)" : "";
|
||||
rz_cons_printf("%s%20s = %s%s %s%s; %s%s", color_name, node->name, color_value, node->value, color_meta, ro_str, reset_str, node->desc);
|
||||
if (!rz_list_empty(node->options)) {
|
||||
isFirst = true;
|
||||
rz_cons_printf(" [");
|
||||
rz_list_foreach (node->options, iter, option) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
rz_cons_printf(", ");
|
||||
}
|
||||
rz_cons_printf("%s", option);
|
||||
}
|
||||
rz_cons_printf("]");
|
||||
}
|
||||
rz_cons_printf("%s%20s = %s", ccp->color_name, name, ccp->color_value);
|
||||
core_config_print_var_as_string(entry, e_flags);
|
||||
rz_cons_printf(" %s(%s); %s%s ", ccp->color_meta, s_flags, ccp->reset_str, desc);
|
||||
core_config_print_array_as_string(options, false);
|
||||
rz_cons_println("");
|
||||
break;
|
||||
}
|
||||
case RZ_OUTPUT_MODE_QUIET:
|
||||
rz_cons_printf("%s=%s\n", node->name, node->value);
|
||||
rz_cons_printf("%s=", name);
|
||||
core_config_print_var_as_string(entry, e_flags);
|
||||
rz_cons_println("");
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_STANDARD: {
|
||||
bool color_enabled = rz_config_get_i(cfg, "scr.color") > 0;
|
||||
char color_str[32], reset_str[32];
|
||||
|
||||
if (color_enabled) {
|
||||
RzColor color_val = rz_cons_pal_get("label");
|
||||
RzColor reset_val = rz_cons_pal_get("help");
|
||||
rz_cons_rgb_str(color_str, sizeof(color_str), &color_val);
|
||||
rz_cons_rgb_str(reset_str, sizeof(reset_str), &reset_val);
|
||||
} else {
|
||||
color_str[0] = reset_str[0] = '\0';
|
||||
}
|
||||
|
||||
rz_cons_printf("%s%20s: %s%s\n", color_str, node->name, reset_str, node->desc ? node->desc : "");
|
||||
rz_cons_printf("%s%20s: %s%s\n", ccp->color_name, name, ccp->reset_str, desc);
|
||||
break;
|
||||
}
|
||||
case RZ_OUTPUT_MODE_STR_BUF:
|
||||
rz_strbuf_appendf(state->d.sbuf, "%20s: %10s - %s\n", node->name,
|
||||
rz_config_node_type(node),
|
||||
node->desc ? node->desc : "");
|
||||
rz_strbuf_appendf(ccp->state->d.sbuf, "%20s: %10s - %s\n", name, s_flags, desc);
|
||||
break;
|
||||
default:
|
||||
rz_warn_if_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
free(s_flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1742,25 +1789,47 @@ static void config_print_node(RzConfig *cfg, RzConfigNode *node, RzCmdStateOutpu
|
|||
*/
|
||||
RZ_API void rz_core_config_print_all(RzConfig *cfg, const char *str, RzCmdStateOutput *state) {
|
||||
rz_return_if_fail(cfg);
|
||||
RzConfigNode *node;
|
||||
RzListIter *iter;
|
||||
PJ *pj = state->d.pj;
|
||||
RzOutputMode mode = state->mode;
|
||||
CoreConfigPrint ccp = { 0 };
|
||||
ccp.state = state;
|
||||
ccp.str = str;
|
||||
const bool color_enabled = rz_config_get_i(cfg, "scr.color") > 0;
|
||||
|
||||
if (mode == RZ_OUTPUT_MODE_LONG_JSON) {
|
||||
pj_a(pj);
|
||||
} else if (mode == RZ_OUTPUT_MODE_JSON) {
|
||||
pj_o(pj);
|
||||
}
|
||||
|
||||
rz_list_foreach (cfg->nodes, iter, node) {
|
||||
if (rz_str_startswith(node->name, str)) {
|
||||
config_print_node(cfg, node, state);
|
||||
// begin
|
||||
switch (state->mode) {
|
||||
case RZ_OUTPUT_MODE_LONG_JSON:
|
||||
pj_a(state->d.pj);
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_JSON:
|
||||
pj_o(state->d.pj);
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_LONG:
|
||||
if (color_enabled) {
|
||||
RzColor color_name_val = rz_cons_pal_get("label");
|
||||
RzColor color_value_val = rz_cons_pal_get("args");
|
||||
RzColor color_meta_val = rz_cons_pal_get("comment");
|
||||
RzColor reset_val = rz_cons_pal_get("help");
|
||||
rz_cons_rgb_str(ccp.color_name, sizeof(ccp.color_name), &color_name_val);
|
||||
rz_cons_rgb_str(ccp.color_value, sizeof(ccp.color_value), &color_value_val);
|
||||
rz_cons_rgb_str(ccp.color_meta, sizeof(ccp.color_meta), &color_meta_val);
|
||||
rz_cons_rgb_str(ccp.reset_str, sizeof(ccp.reset_str), &reset_val);
|
||||
}
|
||||
break;
|
||||
case RZ_OUTPUT_MODE_STANDARD:
|
||||
if (color_enabled) {
|
||||
RzColor color_val = rz_cons_pal_get("label");
|
||||
RzColor reset_val = rz_cons_pal_get("help");
|
||||
rz_cons_rgb_str(ccp.color_name, sizeof(ccp.color_name), &color_val);
|
||||
rz_cons_rgb_str(ccp.reset_str, sizeof(ccp.reset_str), &reset_val);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode == RZ_OUTPUT_MODE_LONG_JSON || mode == RZ_OUTPUT_MODE_JSON) {
|
||||
pj_end(pj);
|
||||
rz_config_iterate_over(cfg, core_config_print_iterator, &ccp);
|
||||
|
||||
if (state->mode == RZ_OUTPUT_MODE_LONG_JSON || state->mode == RZ_OUTPUT_MODE_JSON) {
|
||||
pj_end(state->d.pj);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2247,14 +2316,6 @@ static bool cb_scrprompt(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cb_scrrows(void *user, void *data) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
RzConfigNode *node = (RzConfigNode *)data;
|
||||
int n = atoi(node->value);
|
||||
core->cons->force_rows = n;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cb_contiguous(void *user, void *data) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
RzConfigNode *node = (RzConfigNode *)data;
|
||||
|
|
@ -2307,10 +2368,16 @@ static bool cb_scr_prompt_popup(void *user, void *data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool cb_swstep(void *user, void *data) {
|
||||
static bool core_dbg_swstep_set(void *user, const void *pvalue) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
RzConfigNode *node = (RzConfigNode *)data;
|
||||
core->dbg->swstep = node->i_value;
|
||||
core->dbg->swstep = *((const bool *)pvalue);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool core_dbg_swstep_get(void *user, void *pvalue) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
bool *value = (bool *)pvalue;
|
||||
*value = core->dbg->swstep;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2557,12 +2624,6 @@ static bool cb_zoom_in(void *user, void *data) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static int __dbg_swstep_getter(void *user, RzConfigNode *node) {
|
||||
RzCore *core = (RzCore *)user;
|
||||
node->i_value = core->dbg->swstep;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cb_analysis_roregs(RzCore *core, RzConfigNode *node) {
|
||||
RzReg *rreg = rz_analysis_get_reg(core->analysis);
|
||||
if (rreg) {
|
||||
|
|
@ -2873,7 +2934,6 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
if (!cfg) {
|
||||
return 0;
|
||||
}
|
||||
cfg->num = core->num;
|
||||
/* dir.prefix is used in other modules, set it first */
|
||||
{
|
||||
char *pfx = rz_sys_getenv("RZ_PREFIX");
|
||||
|
|
@ -3403,7 +3463,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
}
|
||||
rz_config_desc(cfg, "dbg.follow", "Follow program counter when pc >= core->offset + dbg.follow");
|
||||
SETBPREF("dbg.rebase", "true", "Rebase analysis/meta/comments/flags when reopening file in debugger");
|
||||
SETCB("dbg.swstep", "false", &cb_swstep, "Force use of software steps (code analysis+breakpoint)");
|
||||
rz_config_add_bool_bind(cfg, "dbg.swstep", "Force use of software steps (code analysis+breakpoint)", core_dbg_swstep_get, core_dbg_swstep_set, NULL, core);
|
||||
SETBPREF("dbg.trace.inrange", "false", "While tracing, avoid following calls outside specified range");
|
||||
SETBPREF("dbg.trace.libs", "true", "Trace library code too");
|
||||
SETBPREF("dbg.exitkills", "true", "Kill process on exit");
|
||||
|
|
@ -3413,8 +3473,6 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
SETICB("dbg.gdb.retries", 10, &cb_dbg_gdb_retries, "Number of retries before gdb packet read times out");
|
||||
SETCB("dbg.consbreak", "false", &cb_consbreak, "SIGINT handle for attached processes");
|
||||
|
||||
rz_config_set_getter(cfg, "dbg.swstep", (RzConfigCallback)__dbg_swstep_getter);
|
||||
|
||||
SETBPREF("dbg.bpsysign", "false", "Ignore system breakpoints");
|
||||
SETICB("dbg.btdepth", 128, &cb_dbgbtdepth, "Depth of backtrace");
|
||||
SETCB("dbg.trace", "false", &cb_trace, "Trace program execution (see asm.trace)");
|
||||
|
|
@ -3599,8 +3657,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
SETBPREF("scr.panelborder", "false", "Specify panels border active area (0 by default)");
|
||||
SETICB("scr.columns", 0, &cb_scrcolumns, "Force console column count (width)");
|
||||
SETBPREF("scr.dumpcols", "false", "Prefer pC commands before p ones");
|
||||
SETCB("scr.rows", "0", &cb_scrrows, "Force console row count (height) ");
|
||||
SETICB("scr.rows", 0, &cb_rows, "Force console row count (height) (duplicate?)");
|
||||
SETICB("scr.rows", 0, &cb_rows, "Force console row count (height)");
|
||||
SETICB("scr.fix.rows", 0, &cb_fixrows, "Workaround for Linux TTY");
|
||||
SETICB("scr.fix.columns", 0, &cb_fixcolumns, "Workaround for Prompt iOS SSH client");
|
||||
SETCB("scr.highlight", "", &cb_scrhighlight, "Highlight that word at RzCons level");
|
||||
|
|
@ -3624,8 +3681,10 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
SETCB("scr.prompt", "true", &cb_scrprompt, "Show user prompt (used by rizin -q)");
|
||||
SETCB("scr.tee", "", &cb_teefile, "Pipe output to file of this name");
|
||||
SETPREF("scr.seek", "", "Seek to the specified address on startup");
|
||||
SETICB("scr.color", (core->print->flags & RZ_PRINT_FLAGS_COLOR) ? COLOR_MODE_16 : COLOR_MODE_DISABLED, &cb_color, "Enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)");
|
||||
rz_config_set_getter(cfg, "scr.color", (RzConfigCallback)cb_color_getter);
|
||||
|
||||
rz_config_add_integer_bind(cfg, "scr.color", "Enable colors (0: none, 1: ansi, 2: 256 colors, 3: truecolor)", core_scr_color_get, core_scr_color_set, NULL, core);
|
||||
rz_config_set_i(cfg, "scr.color", (core->print->flags & RZ_PRINT_FLAGS_COLOR) ? COLOR_MODE_16 : COLOR_MODE_DISABLED);
|
||||
|
||||
SETCB("scr.color.grep", "false", &cb_scr_color_grep, "Enable colors when using ~grep");
|
||||
SETBPREF("scr.color.pipe", "false", "Enable colors when using pipes");
|
||||
SETBPREF("scr.color.ops", "true", "Colorize numbers and registers in opcodes");
|
||||
|
|
@ -3803,7 +3862,7 @@ RZ_API int rz_core_config_init(RzCore *core) {
|
|||
SETB("flirt.sigdb.load.extra", true, "Load signatures from the extra path");
|
||||
SETB("flirt.sigdb.load.home", true, "Load signatures from the home path");
|
||||
|
||||
rz_config_lock(cfg, true);
|
||||
cfg->lock = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -3856,6 +3915,38 @@ RZ_API void rz_core_parse_rizinrc(RzCore *r) {
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct cconfig_space_s {
|
||||
RzList /*<char *>*/ *list;
|
||||
const char *space;
|
||||
} cconfig_space_t;
|
||||
|
||||
static bool core_config_in_space(const RzConfigEntry *entry, void *user) {
|
||||
cconfig_space_t *ctx = user;
|
||||
const char *e_name = rz_config_entry_get_name(entry);
|
||||
|
||||
char *name = rz_str_dup(e_name);
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *dot = strchr(name, '.');
|
||||
if (dot) {
|
||||
*dot = 0;
|
||||
}
|
||||
|
||||
if (RZ_STR_ISNOTEMPTY(ctx->space)) {
|
||||
if (0 == strcmp(name, ctx->space) && dot && !rz_list_find(ctx->list, dot + 1, (RzListComparator)strcmp, NULL)) {
|
||||
rz_list_append(ctx->list, rz_str_dup(dot + 1));
|
||||
}
|
||||
} else {
|
||||
if (!rz_list_find(ctx->list, name, (RzListComparator)strcmp, NULL)) {
|
||||
rz_list_append(ctx->list, rz_str_dup(name));
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get config variable spaces
|
||||
* \param core The RzCore instance
|
||||
|
|
@ -3868,28 +3959,9 @@ RZ_API RZ_OWN RzList /*<char *>*/ *rz_core_config_in_space(RZ_NONNULL RzCore *co
|
|||
if (!list) {
|
||||
return NULL;
|
||||
}
|
||||
RzConfigNode *node;
|
||||
RzListIter *iter;
|
||||
rz_list_foreach (core->config->nodes, iter, node) {
|
||||
char *name = rz_str_dup(node->name);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
char *dot = strchr(name, '.');
|
||||
if (dot) {
|
||||
*dot = 0;
|
||||
}
|
||||
|
||||
if (RZ_STR_ISNOTEMPTY(space)) {
|
||||
if (0 == strcmp(name, space) && dot && !rz_list_find(list, dot + 1, (RzListComparator)strcmp, NULL)) {
|
||||
rz_list_append(list, rz_str_dup(dot + 1));
|
||||
}
|
||||
} else {
|
||||
if (!rz_list_find(list, name, (RzListComparator)strcmp, NULL)) {
|
||||
rz_list_append(list, rz_str_dup(name));
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
cconfig_space_t ctx = { list, space };
|
||||
rz_config_iterate_over(core->config, core_config_in_space, &ctx);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,15 @@
|
|||
#include <rz_util/rz_graph_drawable.h>
|
||||
#include "core_private.h"
|
||||
|
||||
RZ_API bool rz_core_esil_cmd(RzAnalysisEsil *esil, const char *cmd, ut64 a1, ut64 a2) {
|
||||
if (cmd && *cmd) {
|
||||
RzCore *core = (RzCore *)esil->pcore;
|
||||
rz_core_cmdf(core, "%s %" PFMT64d " %" PFMT64d, cmd, a1, a2);
|
||||
return core->num->value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static ut64 initializeEsil(RzCore *core) {
|
||||
ut64 addr = 0;
|
||||
int romem = rz_config_get_i(core->config, "esil.romem");
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ RZ_API void rz_core_sysenv_begin(RzCore *core) {
|
|||
}
|
||||
|
||||
Sdb *config_sdb = sdb_new(NULL, config_sdb_path, 0);
|
||||
rz_config_serialize(core->config, config_sdb);
|
||||
rz_serialize_config_save(config_sdb, core->config);
|
||||
sdb_sync(config_sdb);
|
||||
sdb_free(config_sdb);
|
||||
rz_sys_setenv("RZ_CONFIG", config_sdb_path);
|
||||
|
|
@ -1295,7 +1295,7 @@ RZ_API RZ_BORROW RzCoreFile *rz_core_file_open(RZ_NONNULL RzCore *r, RZ_NONNULL
|
|||
if (r->dbg->cur && r->dbg->cur->canstep) {
|
||||
swstep = false;
|
||||
}
|
||||
rz_config_set_i(r->config, "dbg.swstep", swstep);
|
||||
rz_config_set_bool(r->config, "dbg.swstep", swstep);
|
||||
// Set the correct debug handle
|
||||
if (fd->plugin && fd->plugin->isdbg) {
|
||||
char *dh = rz_str_ndup(file, (strstr(file, "://") - file));
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ static RZ_OWN RzGraph /*<RzGraphNodeInfo *, None *>*/ *rz_core_graph_function_bb
|
|||
goto fail;
|
||||
}
|
||||
|
||||
rz_config_hold_i(hc, "asm.xrefs.max", "asm.lines", "asm.lines.fcn", "asm.bytes", "asm.debuginfo", "asm.offset", "asm.marks",
|
||||
rz_config_hold_var(hc, "asm.xrefs.max", "asm.lines", "asm.lines.fcn", "asm.bytes", "asm.debuginfo", "asm.offset", "asm.marks",
|
||||
"asm.cmt.right", "asm.cmt.col", "asm.bb.middle", NULL);
|
||||
rz_config_set_i(core->config, "asm.xrefs.max", 3);
|
||||
rz_config_set_i(core->config, "asm.lines", 0);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ RZ_API int rz_core_setup_debugger(RzCore *r, const char *debugbackend, bool atta
|
|||
rz_debug_attach(r->dbg, pid);
|
||||
rz_debug_select(r->dbg, r->dbg->pid, r->dbg->tid);
|
||||
}
|
||||
rz_config_set_i(r->config, "dbg.swstep", (r->dbg->cur && !r->dbg->cur->canstep));
|
||||
rz_config_set_bool(r->config, "dbg.swstep", (r->dbg->cur && !r->dbg->cur->canstep));
|
||||
rz_io_system(r->io, rz_strf(buf, "pid %d", r->dbg->pid));
|
||||
|
||||
// this makes to attach twice showing warnings in the output
|
||||
|
|
|
|||
|
|
@ -1597,11 +1597,11 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(tmp_fromto_op) {
|
|||
RzConfigHold *hc = rz_config_hold_new(core->config);
|
||||
int i;
|
||||
for (i = 0; fromvars[i]; i++) {
|
||||
rz_config_hold_i(hc, fromvars[i], NULL);
|
||||
rz_config_hold_var(hc, fromvars[i], NULL);
|
||||
rz_config_set_i(core->config, fromvars[i], from_val);
|
||||
}
|
||||
for (i = 0; tovars[i]; i++) {
|
||||
rz_config_hold_i(hc, tovars[i], NULL);
|
||||
rz_config_hold_var(hc, tovars[i], NULL);
|
||||
rz_config_set_i(core->config, tovars[i], to_val);
|
||||
}
|
||||
|
||||
|
|
@ -1724,8 +1724,8 @@ DEFINE_HANDLE_TS_FCN_AND_SYMBOL(tmp_eval_op) {
|
|||
char *eq = strchr(arg_str, '=');
|
||||
if (eq) {
|
||||
*eq = 0;
|
||||
rz_config_hold_s(hc, arg_str, NULL);
|
||||
rz_config_set(core->config, arg_str, eq + 1);
|
||||
rz_config_hold_var(hc, arg_str, NULL);
|
||||
rz_config_set_any(core->config, arg_str, eq + 1);
|
||||
} else {
|
||||
RZ_LOG_ERROR("core: Missing '=' in e: expression (%s)\n", arg_str);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5358,7 +5358,7 @@ RZ_IPI RzCmdStatus rz_analyze_cycles_handler(RzCore *core, int argc, const char
|
|||
st32 ccl = 0;
|
||||
RzConfigHold *hc = rz_config_hold_new(core->config);
|
||||
|
||||
rz_config_hold_i(hc, "asm.cmt.right", "asm.functions", "asm.lines", "asm.xrefs", NULL);
|
||||
rz_config_hold_var(hc, "asm.cmt.right", "asm.functions", "asm.lines", "asm.xrefs", NULL);
|
||||
|
||||
if (argc > 1) {
|
||||
ccl = (st32)rz_num_get(core->num, argv[1]);
|
||||
|
|
|
|||
|
|
@ -2806,7 +2806,7 @@ RZ_IPI RzCmdStatus rz_cmd_debug_process_profile_handler(RzCore *core, int argc,
|
|||
rz_list_append(list, (void *)argv[i]);
|
||||
rz_list_free(l);
|
||||
}
|
||||
char *str = rz_list_to_str(list, '\n');
|
||||
char *str = rz_list_to_str(list, '\n', true);
|
||||
set_profile_string(core, str);
|
||||
free(str);
|
||||
rz_list_free(list);
|
||||
|
|
|
|||
|
|
@ -504,16 +504,17 @@ RZ_IPI RzCmdStatus rz_eval_getset_handler(RzCore *core, int argc, const char **a
|
|||
rz_cmd_state_output_fini(&state);
|
||||
} else if (llen == 1) {
|
||||
// no value was set, show the value of the key
|
||||
const char *v = rz_config_get(cfg, key);
|
||||
char *v = rz_config_get_as_string(cfg, key);
|
||||
if (!v) {
|
||||
RZ_LOG_ERROR("core: Invalid config key '%s'\n", key);
|
||||
rz_list_free(l);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
rz_cons_printf("%s\n", v);
|
||||
free(v);
|
||||
} else if (llen == 2) {
|
||||
char *value = rz_list_get_n(l, 1);
|
||||
rz_config_set(cfg, key, value);
|
||||
rz_config_set_any(cfg, key, value);
|
||||
}
|
||||
rz_list_free(l);
|
||||
}
|
||||
|
|
@ -554,7 +555,7 @@ RZ_IPI RzCmdStatus rz_eval_editor_handler(RzCore *core, int argc, const char **a
|
|||
print_all_plugin_configs(core);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
const char *val = rz_config_get(cfg, argv[1]);
|
||||
char *val = rz_config_get_as_string(cfg, argv[1]);
|
||||
if (!val) {
|
||||
RZ_LOG_ERROR("core: Invalid config key '%s'\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
|
|
@ -564,7 +565,8 @@ RZ_IPI RzCmdStatus rz_eval_editor_handler(RzCore *core, int argc, const char **a
|
|||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
rz_str_replace_char(p, '\n', ';');
|
||||
rz_config_set(cfg, argv[1], p);
|
||||
rz_config_set_any(cfg, argv[1], p);
|
||||
free(val);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +576,8 @@ RZ_IPI RzCmdStatus rz_eval_readonly_handler(RzCore *core, int argc, const char *
|
|||
print_all_plugin_configs(core);
|
||||
return RZ_CMD_STATUS_OK;
|
||||
}
|
||||
if (!rz_config_readonly(cfg, argv[1])) {
|
||||
|
||||
if (!rz_config_set_readonly(cfg, argv[1], true)) {
|
||||
RZ_LOG_ERROR("core: Cannot make eval '%s' readonly.\n", argv[1]);
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4268,11 +4268,11 @@ RZ_IPI RzCmdStatus rz_print_calls_function_handler(RzCore *core, int argc, const
|
|||
|
||||
// store current configurations
|
||||
RzConfigHold *hc = rz_config_hold_new(core->config);
|
||||
rz_config_hold_i(hc, "asm.offset", NULL);
|
||||
rz_config_hold_i(hc, "asm.comments", NULL);
|
||||
rz_config_hold_i(hc, "asm.tabs", NULL);
|
||||
rz_config_hold_i(hc, "asm.bytes", NULL);
|
||||
rz_config_hold_i(hc, "emu.str", NULL);
|
||||
rz_config_hold_var(hc, "asm.offset", NULL);
|
||||
rz_config_hold_var(hc, "asm.comments", NULL);
|
||||
rz_config_hold_var(hc, "asm.tabs", NULL);
|
||||
rz_config_hold_var(hc, "asm.bytes", NULL);
|
||||
rz_config_hold_var(hc, "emu.str", NULL);
|
||||
|
||||
// temporarily replace configurations
|
||||
rz_config_set_i(core->config, "asm.offset", false);
|
||||
|
|
@ -4616,7 +4616,7 @@ RZ_IPI RzCmdStatus rz_print_columns_disassembly_handler(RzCore *core, int argc,
|
|||
int rows = user_rows > 0 ? user_rows : h - 2;
|
||||
|
||||
RzConfigHold *ch = rz_config_hold_new(core->config);
|
||||
rz_config_hold_i(ch, "asm.offset", "asm.bytes", NULL);
|
||||
rz_config_hold_var(ch, "asm.offset", "asm.bytes", NULL);
|
||||
if (rz_config_get_i(core->config, "asm.minicols")) {
|
||||
rz_config_set_b(core->config, "asm.offset", false);
|
||||
}
|
||||
|
|
@ -4756,7 +4756,7 @@ static bool print_hexdump_columns(RzCore *core, int user_rows, bool has_header,
|
|||
int rows = user_rows > 0 ? user_rows : h - 2;
|
||||
|
||||
RzConfigHold *ch = rz_config_hold_new(core->config);
|
||||
rz_config_hold_i(ch, "hex.cols", NULL);
|
||||
rz_config_hold_var(ch, "hex.cols", NULL);
|
||||
rz_config_set_i(core->config, "hex.cols", colwidth / 5);
|
||||
|
||||
// Add one more line for the hexdump header
|
||||
|
|
@ -5136,7 +5136,7 @@ static RzCmdStatus print_visual_bytes(RzCore *core, RZ_NONNULL const unsigned ch
|
|||
if (!hc) {
|
||||
return false;
|
||||
}
|
||||
rz_config_hold_i(hc, "asm.pseudo", "asm.esil", "asm.cmt.right", NULL);
|
||||
rz_config_hold_var(hc, "asm.pseudo", "asm.esil", "asm.cmt.right", NULL);
|
||||
|
||||
int h, w = rz_cons_get_size(&h);
|
||||
can = rz_cons_canvas_new(w, h);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ static char *config_path(RzCore *core) {
|
|||
free(path);
|
||||
return NULL;
|
||||
}
|
||||
rz_config_serialize(core->config, sdb);
|
||||
rz_serialize_config_save(sdb, core->config);
|
||||
sdb_sync(sdb);
|
||||
sdb_free(sdb);
|
||||
|
||||
|
|
@ -55,15 +55,15 @@ static int system_exec(RzCore *core, int argc, const char **argv, char **output,
|
|||
char file_size[32];
|
||||
char core_offset[32];
|
||||
char block_size[32];
|
||||
const char *file_path = rz_config_get(core->config, "file.path");
|
||||
const char *asm_arch = rz_config_get(core->config, "asm.arch");
|
||||
const char *asm_bits = rz_config_get(core->config, "asm.bits");
|
||||
const char *bin_demangle = rz_config_get(core->config, "bin.demangle");
|
||||
const char *bin_lang = rz_config_get(core->config, "bin.lang");
|
||||
const char *cfg_debug = rz_config_get(core->config, "cfg.debug");
|
||||
const char *io_va = rz_config_get(core->config, "io.va");
|
||||
const char *pdb_server = rz_config_get(core->config, "pdb.server");
|
||||
const char *scr_color = rz_config_get(core->config, "scr.color");
|
||||
char *file_path = rz_config_get_as_string(core->config, "file.path");
|
||||
char *asm_arch = rz_config_get_as_string(core->config, "asm.arch");
|
||||
char *asm_bits = rz_config_get_as_string(core->config, "asm.bits");
|
||||
char *bin_demangle = rz_config_get_as_string(core->config, "bin.demangle");
|
||||
char *bin_lang = rz_config_get_as_string(core->config, "bin.lang");
|
||||
char *cfg_debug = rz_config_get_as_string(core->config, "cfg.debug");
|
||||
char *io_va = rz_config_get_as_string(core->config, "io.va");
|
||||
char *pdb_server = rz_config_get_as_string(core->config, "pdb.server");
|
||||
char *scr_color = rz_config_get_as_string(core->config, "scr.color");
|
||||
const char *endian = rz_str_bool(rz_asm_is_big_endian_set(core->rasm));
|
||||
char *cfg_path = config_path(core);
|
||||
|
||||
|
|
@ -180,6 +180,15 @@ args_err:
|
|||
alloc_err:
|
||||
rz_file_rm(cfg_path);
|
||||
free(cfg_path);
|
||||
free(file_path);
|
||||
free(asm_arch);
|
||||
free(asm_bits);
|
||||
free(bin_demangle);
|
||||
free(bin_lang);
|
||||
free(cfg_debug);
|
||||
free(io_va);
|
||||
free(pdb_server);
|
||||
free(scr_color);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,7 +629,7 @@ RZ_API RZ_OWN char *rz_core_print_disasm_strings(RZ_NONNULL RzCore *core, RzCore
|
|||
rz_config_hold_free(hc);
|
||||
return NULL;
|
||||
}
|
||||
rz_config_hold_i(hc,
|
||||
rz_config_hold_var(hc,
|
||||
"asm.offset",
|
||||
"asm.debuginfo",
|
||||
"asm.tabs",
|
||||
|
|
|
|||
|
|
@ -4727,7 +4727,7 @@ static void ds_print_esil_analysis(RzDisasmState *ds) {
|
|||
rz_analysis_esil_parse(esil, esilstr);
|
||||
}
|
||||
rz_analysis_esil_stack_free(esil);
|
||||
rz_config_hold_i(hc, "io.cache", NULL);
|
||||
rz_config_hold_var(hc, "io.cache", NULL);
|
||||
rz_config_set(core->config, "io.cache", "true");
|
||||
if (!ds->show_comments) {
|
||||
goto beach;
|
||||
|
|
@ -5263,8 +5263,7 @@ RZ_API int rz_core_print_disasm(RZ_NONNULL RzCore *core, ut64 addr, RZ_NONNULL u
|
|||
if (!rch) {
|
||||
return 0;
|
||||
}
|
||||
rz_config_hold_s(rch, "asm.arch", NULL);
|
||||
rz_config_hold_i(rch, "asm.bits", NULL);
|
||||
rz_config_hold_var(rch, "asm.arch", "asm.bits", NULL);
|
||||
|
||||
// TODO: All those ds must be print flags
|
||||
RzReg *rreg = rz_analysis_get_reg(core->analysis);
|
||||
|
|
@ -6457,7 +6456,7 @@ RZ_API int rz_core_disasm_pde(RzCore *core, int nb_opcodes, RzCmdStateOutput *st
|
|||
}
|
||||
rz_reg_arena_push(reg);
|
||||
RzConfigHold *chold = rz_config_hold_new(core->config);
|
||||
rz_config_hold_i(chold, "io.cache", "asm.lines", NULL);
|
||||
rz_config_hold_var(chold, "io.cache", "asm.lines", NULL);
|
||||
rz_config_set_i(core->config, "io.cache", true);
|
||||
rz_config_set_i(core->config, "asm.lines", false);
|
||||
const char *strip = rz_config_get(core->config, "asm.strip");
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ static int rz_core_rtr_http_run(RzCore *core, bool open_browser) {
|
|||
if (!hc) {
|
||||
return 0;
|
||||
}
|
||||
rz_config_hold_i(hc, "scr.color", "scr.html", "scr.interactive", "asm.cmt.right", "asm.bytes", NULL);
|
||||
rz_config_hold_var(hc, "scr.color", "scr.html", "scr.interactive", "asm.cmt.right", "asm.bytes", NULL);
|
||||
|
||||
// set new configs
|
||||
rz_config_set(core->config, "asm.cmt.right", "false");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ RZ_API void rz_serialize_core_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core,
|
|||
sdb_set(db, "blocksize", buf);
|
||||
}
|
||||
|
||||
static const char *const config_exclude[] = {
|
||||
static const char *config_exclude[] = {
|
||||
"dir.home",
|
||||
"dir.libs",
|
||||
"dir.magic",
|
||||
|
|
@ -79,7 +79,7 @@ RZ_API bool rz_serialize_core_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzCore *core,
|
|||
if (load_bin_io) {
|
||||
SUB("file", file_load(subdb, core, prj_file, res));
|
||||
}
|
||||
SUB("config", rz_serialize_config_load(subdb, core->config, config_exclude, res));
|
||||
SUB("config", rz_serialize_config_load(subdb, core->config, config_exclude));
|
||||
SUB("flags", rz_serialize_flag_load(subdb, core->flags, res));
|
||||
SUB("marks", rz_serialize_mark_load(subdb, core->marks, res));
|
||||
SUB("analysis", rz_serialize_analysis_load(subdb, core->analysis, res));
|
||||
|
|
|
|||
|
|
@ -12,156 +12,189 @@
|
|||
#include <rz_util/rz_strbuf.h>
|
||||
#include <cmd_descs.h>
|
||||
|
||||
typedef struct config_visual_ctx {
|
||||
const char *fs;
|
||||
const char *fs2;
|
||||
const char *desc;
|
||||
int i;
|
||||
int j;
|
||||
int hit;
|
||||
int show;
|
||||
int option;
|
||||
int _option;
|
||||
char old[1024];
|
||||
int delta;
|
||||
int menu;
|
||||
RzCore *core;
|
||||
} ConfigVisualCtx;
|
||||
|
||||
static void config_visual_hit_i(RzCore *core, const char *name, int delta) {
|
||||
struct rz_config_node_t *node;
|
||||
node = rz_config_node_get(core->config, name);
|
||||
if (node && rz_config_node_is_int(node)) {
|
||||
int hitDelta = rz_config_get_i(core->config, name) + delta;
|
||||
(void)rz_config_set_i(core->config, name, hitDelta);
|
||||
const ut32 flags = rz_config_get_flags(core->config, name);
|
||||
if (!(RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_INT))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ut64 value = rz_config_get_i(core->config, name);
|
||||
value += delta;
|
||||
rz_config_set_i(core->config, name, value);
|
||||
}
|
||||
|
||||
/* Visually activate the config variable */
|
||||
static void config_visual_hit(RzCore *core, const char *name, int editor) {
|
||||
char buf[1024];
|
||||
RzConfigNode *node;
|
||||
RzLine *line = core->cons->line;
|
||||
|
||||
if (!(node = rz_config_node_get(core->config, name))) {
|
||||
const ut32 flags = rz_config_get_flags(core->config, name);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
if (rz_config_node_is_bool(node)) {
|
||||
rz_config_set_i(core->config, name, node->i_value ? 0 : 1);
|
||||
} else {
|
||||
// XXX: must use config_set () to run callbacks!
|
||||
if (editor) {
|
||||
char *buf = rz_core_editor(core, NULL, node->value);
|
||||
char *tmp = rz_str_dup(buf);
|
||||
free(node->value);
|
||||
node->value = tmp;
|
||||
free(buf);
|
||||
} else {
|
||||
// FGETS AND SO
|
||||
rz_cons_printf("New value (old=%s): \n", node->value);
|
||||
rz_cons_show_cursor(true);
|
||||
rz_cons_flush();
|
||||
rz_cons_set_raw(0);
|
||||
rz_line_set_prompt(line, ":> ");
|
||||
rz_cons_fgets(buf, sizeof(buf), 0, 0);
|
||||
rz_cons_set_raw(1);
|
||||
rz_cons_show_cursor(false);
|
||||
rz_config_set(core->config, name, buf);
|
||||
// node->value = rz_str_dup (node->value, buf);
|
||||
}
|
||||
|
||||
if ((RZ_CONFIG_VAR_IS_TYPE(flags, RZ_CONFIG_VAR_TYPE_BOOL))) {
|
||||
rz_config_toggle_bool(core->config, name);
|
||||
return;
|
||||
}
|
||||
|
||||
char *value = rz_config_get_as_string(core->config, name);
|
||||
if (editor) {
|
||||
char *buf = rz_core_editor(core, NULL, value);
|
||||
rz_config_set_any(core->config, name, buf);
|
||||
free(buf);
|
||||
free(value);
|
||||
return;
|
||||
}
|
||||
|
||||
rz_cons_printf("New value (old=%s): \n", value);
|
||||
rz_cons_show_cursor(true);
|
||||
rz_cons_flush();
|
||||
rz_cons_set_raw(0);
|
||||
rz_line_set_prompt(line, ":> ");
|
||||
rz_cons_fgets(buf, sizeof(buf), 0, 0);
|
||||
rz_cons_set_raw(1);
|
||||
rz_cons_show_cursor(false);
|
||||
rz_config_set_any(core->config, name, buf);
|
||||
free(value);
|
||||
}
|
||||
|
||||
static void show_config_options(RzCore *core, const char *opt) {
|
||||
RzConfigNode *node = rz_config_node_get(core->config, opt);
|
||||
if (node && !rz_list_empty(node->options)) {
|
||||
int h, w = rz_cons_get_size(&h);
|
||||
const char *item;
|
||||
RzListIter *iter;
|
||||
RzStrBuf *sb = rz_strbuf_new(" Options: ");
|
||||
rz_list_foreach (node->options, iter, item) {
|
||||
rz_strbuf_appendf(sb, "%s%s", rz_list_has_prev(iter) ? ", " : "", item);
|
||||
if (rz_strbuf_length(sb) + 5 >= w) {
|
||||
char *s = rz_strbuf_drain(sb);
|
||||
rz_cons_println(s);
|
||||
free(s);
|
||||
sb = rz_strbuf_new("");
|
||||
}
|
||||
}
|
||||
char *s = rz_strbuf_drain(sb);
|
||||
rz_cons_println(s);
|
||||
free(s);
|
||||
static void show_config_options(RzCore *core, const char *name) {
|
||||
const RzList *options = rz_config_get_options(core->config, name);
|
||||
if (rz_list_empty(options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int w = rz_cons_get_size(NULL);
|
||||
const char *item;
|
||||
const RzListIter *iter;
|
||||
RzStrBuf *sb = rz_strbuf_new(" Options: ");
|
||||
rz_list_foreach (options, iter, item) {
|
||||
rz_strbuf_appendf(sb, "%s%s", rz_list_val(iter) ? ", " : "", item);
|
||||
if (rz_strbuf_length(sb) + 5 >= w) {
|
||||
char *s = rz_strbuf_drain(sb);
|
||||
rz_cons_println(s);
|
||||
free(s);
|
||||
sb = rz_strbuf_new("");
|
||||
}
|
||||
}
|
||||
char *s = rz_strbuf_drain(sb);
|
||||
rz_cons_println(s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static bool core_visual_config_flag_space(const RzConfigEntry *entry, void *user) {
|
||||
ConfigVisualCtx *ctx = (ConfigVisualCtx *)user;
|
||||
const char *name = rz_config_entry_get_name(entry);
|
||||
|
||||
if (ctx->option == ctx->i) {
|
||||
ctx->fs = name;
|
||||
}
|
||||
if (!ctx->old[0]) {
|
||||
rz_str_ccpy(ctx->old, name, '.');
|
||||
ctx->show = 1;
|
||||
} else if (rz_str_ccmp(ctx->old, name, '.')) {
|
||||
rz_str_ccpy(ctx->old, name, '.');
|
||||
ctx->show = 1;
|
||||
} else {
|
||||
ctx->show = 0;
|
||||
}
|
||||
if (ctx->show) {
|
||||
if (ctx->option == ctx->i) {
|
||||
ctx->hit = 1;
|
||||
}
|
||||
if ((ctx->i >= ctx->option - ctx->delta) &&
|
||||
((ctx->i < ctx->option + ctx->delta) || ((ctx->option < ctx->delta) && (ctx->i < (ctx->delta << 1))))) {
|
||||
rz_cons_printf(" %c %s\n", (ctx->option == ctx->i) ? '>' : ' ', ctx->old);
|
||||
ctx->j++;
|
||||
}
|
||||
ctx->i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool core_visual_config_flag_selection(const RzConfigEntry *entry, void *user) {
|
||||
ConfigVisualCtx *ctx = (ConfigVisualCtx *)user;
|
||||
const char *name = rz_config_entry_get_name(entry);
|
||||
const char *desc = rz_config_entry_get_desc(entry);
|
||||
|
||||
if (!rz_str_ccmp(name, ctx->fs, '.')) {
|
||||
if (ctx->option == ctx->i) {
|
||||
ctx->fs2 = name;
|
||||
ctx->desc = desc;
|
||||
ctx->hit = 1;
|
||||
}
|
||||
if ((ctx->i >= ctx->option - ctx->delta) &&
|
||||
((ctx->i < ctx->option + ctx->delta) || ((ctx->option < ctx->delta) && (ctx->i < (ctx->delta << 1))))) {
|
||||
// TODO: Better align
|
||||
char *value = rz_config_get_as_string(ctx->core->config, name);
|
||||
rz_cons_printf(" %c %s = %s\n", (ctx->option == ctx->i) ? '>' : ' ', name, value);
|
||||
free(value);
|
||||
ctx->j++;
|
||||
}
|
||||
ctx->i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_IPI void rz_core_visual_config(RzCore *core) {
|
||||
char *fs = NULL, *fs2 = NULL, *desc = NULL;
|
||||
int i, j, ch, hit, show;
|
||||
int option, _option = 0;
|
||||
RzListIter *iter;
|
||||
RzConfigNode *bt;
|
||||
char old[1024];
|
||||
int delta = 9;
|
||||
int menu = 0;
|
||||
old[0] = '\0';
|
||||
int ch = 0;
|
||||
ConfigVisualCtx ctx = { 0 };
|
||||
ctx._option = 0;
|
||||
ctx.delta = 9;
|
||||
ctx.menu = 0;
|
||||
ctx.core = core;
|
||||
|
||||
option = 0;
|
||||
for (;;) {
|
||||
rz_cons_clear00();
|
||||
rz_cons_get_size(&delta);
|
||||
delta /= 4;
|
||||
rz_cons_get_size(&ctx.delta);
|
||||
ctx.delta /= 4;
|
||||
|
||||
switch (menu) {
|
||||
switch (ctx.menu) {
|
||||
case 0: // flag space
|
||||
rz_cons_printf("[EvalSpace]\n\n");
|
||||
hit = j = i = 0;
|
||||
rz_list_foreach (core->config->nodes, iter, bt) {
|
||||
if (option == i) {
|
||||
fs = bt->name;
|
||||
}
|
||||
if (!old[0]) {
|
||||
rz_str_ccpy(old, bt->name, '.');
|
||||
show = 1;
|
||||
} else if (rz_str_ccmp(old, bt->name, '.')) {
|
||||
rz_str_ccpy(old, bt->name, '.');
|
||||
show = 1;
|
||||
} else {
|
||||
show = 0;
|
||||
}
|
||||
if (show) {
|
||||
if (option == i) {
|
||||
hit = 1;
|
||||
}
|
||||
if ((i >= option - delta) && ((i < option + delta) || ((option < delta) && (i < (delta << 1))))) {
|
||||
rz_cons_printf(" %c %s\n", (option == i) ? '>' : ' ', old);
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!hit && j > 0) {
|
||||
option--;
|
||||
ctx.hit = ctx.j = ctx.i = 0;
|
||||
rz_config_iterate_over(core->config, core_visual_config_flag_space, &ctx);
|
||||
if (!ctx.hit && ctx.j > 0) {
|
||||
ctx.option--;
|
||||
continue;
|
||||
}
|
||||
rz_cons_printf("\n Sel: %s \n\n", fs);
|
||||
rz_cons_printf("\n Sel: %s \n\n", ctx.fs);
|
||||
break;
|
||||
case 1: // flag selection
|
||||
rz_cons_printf("[EvalSpace < Variables: %s]\n\n", fs);
|
||||
hit = 0;
|
||||
j = i = 0;
|
||||
// TODO: cut -d '.' -f 1 | sort | uniq !!!
|
||||
rz_list_foreach (core->config->nodes, iter, bt) {
|
||||
if (!rz_str_ccmp(bt->name, fs, '.')) {
|
||||
if (option == i) {
|
||||
fs2 = bt->name;
|
||||
desc = bt->desc;
|
||||
hit = 1;
|
||||
}
|
||||
if ((i >= option - delta) && ((i < option + delta) || ((option < delta) && (i < (delta << 1))))) {
|
||||
// TODO: Better align
|
||||
rz_cons_printf(" %c %s = %s\n", (option == i) ? '>' : ' ', bt->name, bt->value);
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!hit && j > 0) {
|
||||
option = i - 1;
|
||||
rz_cons_printf("[EvalSpace < Variables: %s]\n\n", ctx.fs);
|
||||
ctx.hit = 0;
|
||||
ctx.j = ctx.i = 0;
|
||||
rz_config_iterate_over(core->config, core_visual_config_flag_selection, &ctx);
|
||||
|
||||
if (!ctx.hit && ctx.j > 0) {
|
||||
ctx.option = ctx.i - 1;
|
||||
continue;
|
||||
}
|
||||
if (fs2) {
|
||||
if (ctx.fs2) {
|
||||
// TODO: Break long lines.
|
||||
rz_cons_printf("\n Selected: %s (%s)\n", fs2, desc);
|
||||
show_config_options(core, fs2);
|
||||
rz_cons_printf("\n Selected: %s (%s)\n", ctx.fs2, ctx.desc);
|
||||
show_config_options(core, ctx.fs2);
|
||||
rz_cons_newline();
|
||||
}
|
||||
}
|
||||
|
||||
if (fs && !strncmp(fs, "asm.", 4)) {
|
||||
if (ctx.fs && !strncmp(ctx.fs, "asm.", 4)) {
|
||||
rz_core_cmd(core, "pd $r", 0);
|
||||
}
|
||||
rz_cons_visual_flush();
|
||||
|
|
@ -172,25 +205,25 @@ RZ_IPI void rz_core_visual_config(RzCore *core) {
|
|||
ch = rz_cons_arrow_to_hjkl(ch); // get ESC+char, return 'hjkl' char
|
||||
|
||||
switch (ch) {
|
||||
case 'j': option++; break;
|
||||
case 'k': option = (option <= 0) ? 0 : option - 1; break;
|
||||
case 'J': option += 4; break;
|
||||
case 'K': option = (option <= 3) ? 0 : option - 4; break;
|
||||
case 'j': ctx.option++; break;
|
||||
case 'k': ctx.option = (ctx.option <= 0) ? 0 : ctx.option - 1; break;
|
||||
case 'J': ctx.option += 4; break;
|
||||
case 'K': ctx.option = (ctx.option <= 3) ? 0 : ctx.option - 4; break;
|
||||
case 'h':
|
||||
case 'b': // back
|
||||
menu = 0;
|
||||
option = _option;
|
||||
ctx.menu = 0;
|
||||
ctx.option = ctx._option;
|
||||
break;
|
||||
case '_':
|
||||
rz_core_visual_config_hud(core);
|
||||
break;
|
||||
case 'Q':
|
||||
case 'q':
|
||||
if (menu <= 0) {
|
||||
if (ctx.menu <= 0) {
|
||||
return;
|
||||
}
|
||||
menu--;
|
||||
option = _option;
|
||||
ctx.menu--;
|
||||
ctx.option = ctx._option;
|
||||
break;
|
||||
case '$':
|
||||
rz_list_rizin_vars_handler(core, 0, NULL);
|
||||
|
|
@ -198,11 +231,11 @@ RZ_IPI void rz_core_visual_config(RzCore *core) {
|
|||
break;
|
||||
case '*':
|
||||
case '+':
|
||||
fs2 ? config_visual_hit_i(core, fs2, +1) : 0;
|
||||
ctx.fs2 ? config_visual_hit_i(core, ctx.fs2, +1) : 0;
|
||||
continue;
|
||||
case '/':
|
||||
case '-':
|
||||
fs2 ? config_visual_hit_i(core, fs2, -1) : 0;
|
||||
ctx.fs2 ? config_visual_hit_i(core, ctx.fs2, -1) : 0;
|
||||
continue;
|
||||
case 'l':
|
||||
case 'E': // edit value
|
||||
|
|
@ -210,12 +243,12 @@ RZ_IPI void rz_core_visual_config(RzCore *core) {
|
|||
case ' ':
|
||||
case '\r':
|
||||
case '\n': // never happens
|
||||
if (menu == 1) {
|
||||
fs2 ? config_visual_hit(core, fs2, (ch == 'E')) : 0;
|
||||
if (ctx.menu == 1) {
|
||||
ctx.fs2 ? config_visual_hit(core, ctx.fs2, (ch == 'E')) : 0;
|
||||
} else {
|
||||
menu = 1;
|
||||
_option = option;
|
||||
option = 0;
|
||||
ctx.menu = 1;
|
||||
ctx._option = ctx.option;
|
||||
ctx.option = 0;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
|
|
|
|||
|
|
@ -64,11 +64,10 @@ RZ_IPI bool rz_core_visual_hudclasses(RzCore *core) {
|
|||
RzBinSymbol *m;
|
||||
ut64 addr;
|
||||
char *res;
|
||||
RzList *list = rz_list_new();
|
||||
RzList *list = rz_list_newf(free);
|
||||
if (!list) {
|
||||
return false;
|
||||
}
|
||||
list->free = free;
|
||||
RzBinObject *bin_obj = rz_bin_cur_object(core->bin);
|
||||
const RzPVector *classes = rz_bin_object_get_classes(bin_obj);
|
||||
if (!classes) {
|
||||
|
|
@ -110,11 +109,10 @@ static bool hudstuff_append(RzFlagItem *fi, void *user) {
|
|||
RZ_IPI bool rz_core_visual_hudstuff(RzCore *core) {
|
||||
ut64 addr;
|
||||
char *res;
|
||||
RzList *list = rz_list_new();
|
||||
RzList *list = rz_list_newf(free);
|
||||
if (!list) {
|
||||
return false;
|
||||
}
|
||||
list->free = free;
|
||||
rz_flag_foreach(core->flags, hudstuff_append, list);
|
||||
RzIntervalTreeIter it;
|
||||
RzAnalysisMetaItem *mi;
|
||||
|
|
@ -141,17 +139,26 @@ RZ_IPI bool rz_core_visual_hudstuff(RzCore *core) {
|
|||
return res != NULL;
|
||||
}
|
||||
|
||||
bool core_visual_config_hud_append(const RzConfigEntry *entry, void *user) {
|
||||
RzList *list = (RzList *)user;
|
||||
const char *name = rz_config_entry_get_name(entry);
|
||||
char *value = rz_config_entry_get_as_string(entry);
|
||||
char *str = rz_str_newf("%s %s", name, value);
|
||||
if (!str || !rz_list_append(list, str)) {
|
||||
free(str);
|
||||
}
|
||||
free(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
RZ_IPI bool rz_core_visual_config_hud(RzCore *core) {
|
||||
RzListIter *iter;
|
||||
RzConfigNode *bt;
|
||||
RzList *list = rz_list_new();
|
||||
RzList *list = rz_list_newf(free);
|
||||
if (!list) {
|
||||
return false;
|
||||
}
|
||||
list->free = free;
|
||||
rz_list_foreach (core->config->nodes, iter, bt) {
|
||||
rz_list_append(list, rz_str_newf("%s %s", bt->name, bt->value));
|
||||
}
|
||||
|
||||
rz_config_iterate_over(core->config, core_visual_config_hud_append, list);
|
||||
|
||||
char *res = rz_cons_hud(list, NULL);
|
||||
if (res) {
|
||||
const char *oldvalue = NULL;
|
||||
|
|
|
|||
|
|
@ -4417,7 +4417,9 @@ void __init_menu_disasm_settings_layout(void *_core, const char *parent) {
|
|||
} else {
|
||||
rz_strbuf_set(rsb, pos);
|
||||
rz_strbuf_append(rsb, ": ");
|
||||
rz_strbuf_append(rsb, rz_config_get(core->config, pos));
|
||||
char *val = rz_config_get_as_string(core->config, pos);
|
||||
rz_strbuf_append(rsb, val);
|
||||
free(val);
|
||||
__add_menu(core, parent, rz_strbuf_get(rsb), __config_toggle_cb);
|
||||
}
|
||||
}
|
||||
|
|
@ -4434,7 +4436,9 @@ static void __init_menu_disasm_asm_settings_layout(void *_core, const char *pare
|
|||
char *pos = *iter;
|
||||
rz_strbuf_set(rsb, pos);
|
||||
rz_strbuf_append(rsb, ": ");
|
||||
rz_strbuf_append(rsb, rz_config_get(core->config, pos));
|
||||
char *val = rz_config_get_as_string(core->config, pos);
|
||||
rz_strbuf_append(rsb, val);
|
||||
free(val);
|
||||
if (!strcmp(pos, "asm.var.summary") ||
|
||||
!strcmp(pos, "asm.arch") ||
|
||||
!strcmp(pos, "asm.bits") ||
|
||||
|
|
@ -4456,7 +4460,9 @@ static void __init_menu_screen_settings_layout(void *_core, const char *parent)
|
|||
const char *menu = menus_settings_screen[i];
|
||||
rz_strbuf_set(rsb, menu);
|
||||
rz_strbuf_append(rsb, ": ");
|
||||
rz_strbuf_append(rsb, rz_config_get(core->config, menu));
|
||||
char *val = rz_config_get_as_string(core->config, menu);
|
||||
rz_strbuf_append(rsb, val);
|
||||
free(val);
|
||||
if (!strcmp(menus_settings_screen[i], "scr.color")) {
|
||||
__add_menu(core, parent, rz_strbuf_get(rsb), __config_value_cb);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ RZ_IPI void rz_core_visual_toggle_decompiler_disasm(RzCore *core, bool for_graph
|
|||
return;
|
||||
}
|
||||
hold = rz_config_hold_new(core->config);
|
||||
rz_config_hold_s(hold, "asm.hint.pos", "asm.cmt.col", "asm.offset", "asm.lines",
|
||||
rz_config_hold_var(hold, "asm.hint.pos", "asm.cmt.col", "asm.offset", "asm.lines",
|
||||
"asm.indent", "asm.bytes", "asm.comments", "asm.debuginfo", "asm.usercomments", "asm.instr", NULL);
|
||||
if (for_graph) {
|
||||
rz_config_set(core->config, "asm.hint.pos", "-2");
|
||||
|
|
@ -1264,7 +1264,7 @@ repeat:
|
|||
if (!hc) {
|
||||
return RZ_CMD_STATUS_ERROR;
|
||||
}
|
||||
rz_config_hold_i(hc, "asm.flags.limit", NULL);
|
||||
rz_config_hold_var(hc, "asm.flags.limit", NULL);
|
||||
rz_config_set_i(core->config, "asm.flags.limit", 1);
|
||||
char *res = rz_core_print_cons_disassembly(core, xaddr2, 4, 0);
|
||||
rz_config_hold_restore(hc);
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ RZ_IPI int __core_visual_view_graph_update(RzCore *core, RzCoreVisualViewGraph *
|
|||
if (!hc) {
|
||||
return 0;
|
||||
}
|
||||
rz_config_hold_i(hc, "asm.flags", NULL);
|
||||
rz_config_hold_var(hc, "asm.flags", NULL);
|
||||
rz_config_set_i(core->config, "asm.flags", 0);
|
||||
char *output1 = rz_core_print_cons_disassembly(core, status->addr, 32, 0);
|
||||
rz_config_hold_restore(hc);
|
||||
|
|
|
|||
|
|
@ -393,7 +393,6 @@ static RzDebugReasonType rz_debug_gdb_wait(RzDebug *dbg, int pid) {
|
|||
static int rz_debug_gdb_attach(RzDebug *dbg, int pid) {
|
||||
RzDebugGdbCtx *ctx = dbg->plugin_data;
|
||||
RzIODesc *d = dbg->iob.io->desc;
|
||||
// TODO: the core must update the dbg.swstep config var when this var is changed
|
||||
dbg->swstep = false;
|
||||
// eprintf ("XWJSTEP TOFALSE\n");
|
||||
if (!(d && d->plugin && d->plugin->name && d->data)) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
// SPDX-FileCopyrightText: 2026 deroad <deroad@kumo.xn--q9jyb4c>
|
||||
// SPDX-FileCopyrightText: 2006-2021 pancake <pancake@nopcode.org>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef RZ_CONFIG_H
|
||||
#define RZ_CONFIG_H
|
||||
|
||||
|
|
@ -13,12 +17,8 @@ RZ_LIB_VERSION_HEADER(rz_config);
|
|||
|
||||
#define CN_BOOL 0x000001
|
||||
#define CN_INT 0x000002
|
||||
// NOTE: removed because this is redundant and it does not add any value
|
||||
// compared to CN_INT. Use that instead for consistency
|
||||
// #define CN_OFFT 0x000004
|
||||
#define CN_STR 0x000008
|
||||
#define CN_RO 0x000010
|
||||
#define CN_RW 0x000020
|
||||
#define CN_STR 0x000008
|
||||
#define CN_RO 0x000010
|
||||
|
||||
#define NODECB(w, x, y) rz_config_set_cb(cfg, w, x, y)
|
||||
#define NODEICB(w, x, y) rz_config_set_i_cb(cfg, w, x, y)
|
||||
|
|
@ -41,97 +41,193 @@ typedef struct rz_config_node_t {
|
|||
ut64 *cb_ptr_q;
|
||||
int *cb_ptr_i;
|
||||
char **cb_ptr_s;
|
||||
RzConfigCallback getter;
|
||||
RzConfigCallback setter;
|
||||
char *desc;
|
||||
RzList /*<char *>*/ *options;
|
||||
} RzConfigNode;
|
||||
|
||||
RZ_API const char *rz_config_node_type(RzConfigNode *node);
|
||||
typedef enum {
|
||||
RZ_CONFIG_VAR_TYPE_NONE = 0,
|
||||
// these are types
|
||||
RZ_CONFIG_VAR_TYPE_BOOL = 1,
|
||||
RZ_CONFIG_VAR_TYPE_INT = 2,
|
||||
RZ_CONFIG_VAR_TYPE_STR = 3,
|
||||
RZ_CONFIG_VAR_TYPE_LIST = 4,
|
||||
RZ_CONFIG_VAR_TYPE_ITV = 5,
|
||||
// these are flags
|
||||
RZ_CONFIG_VAR_FLAG_BIND = 0x40000000,
|
||||
RZ_CONFIG_VAR_FLAG_WRITABLE = 0x80000000,
|
||||
} RzConfigVarFlags;
|
||||
|
||||
#define RZ_CONFIG_VAR_TYPE_MASK 0x0000ffff
|
||||
#define RZ_CONFIG_VAR_FLAGS_MASK 0xffff0000
|
||||
|
||||
#define RZ_CONFIG_VAR_IS_TYPE(flags, expected) (((flags) & RZ_CONFIG_VAR_TYPE_MASK) == (expected))
|
||||
#define RZ_CONFIG_VAR_HAS_FLAG(flags, expected) (((flags) & RZ_CONFIG_VAR_FLAGS_MASK) & (expected))
|
||||
|
||||
typedef bool (*RzConfigBindGet)(void *user, void *value);
|
||||
typedef bool (*RzConfigBindSet)(void *user, const void *value);
|
||||
typedef bool (*RzConfigBindOpts)(void *user, RzList /*<char *>*/ **options);
|
||||
|
||||
typedef struct rz_config_bind_t {
|
||||
void *user;
|
||||
RzConfigBindGet get_value;
|
||||
RzConfigBindSet set_value;
|
||||
RzConfigBindOpts get_options;
|
||||
} RzConfigBind;
|
||||
|
||||
typedef struct rz_config_var_t {
|
||||
char *name; ///< Variable name
|
||||
char *desc; ///< Description of the variable
|
||||
RzList /*<char *>*/ *options; ///< Variable possible values
|
||||
ut32 flags; ///< Define the type of the data via RzConfigVar (see RzConfigVarFlags)
|
||||
union {
|
||||
union {
|
||||
bool boolean;
|
||||
ut64 integer;
|
||||
char *string;
|
||||
RzList /*<char *>*/ *list;
|
||||
RzInterval interval;
|
||||
} value; ///< owned value
|
||||
RzConfigBind bind; ///< bind value
|
||||
};
|
||||
} RzConfigVar;
|
||||
|
||||
typedef struct rz_config_entry_t {
|
||||
bool is_variable;
|
||||
union {
|
||||
RzConfigVar var;
|
||||
RzConfigNode node;
|
||||
};
|
||||
} RzConfigEntry;
|
||||
|
||||
typedef struct rz_config_t {
|
||||
int lock;
|
||||
void *user;
|
||||
RzNum *num;
|
||||
RzList /*<RzConfigNode *>*/ *nodes;
|
||||
HtSP *ht;
|
||||
void *user; ///< DEPRECATED
|
||||
bool lock; ///< DEPRECATED
|
||||
RzVector /*<RzConfigEntry>*/ sorted_vars; ///< Sorted owned variables
|
||||
} RzConfig;
|
||||
|
||||
typedef struct rz_config_hold_num_t {
|
||||
char *key;
|
||||
ut64 value;
|
||||
} RzConfigHoldNum;
|
||||
|
||||
typedef struct rz_config_hold_char_t {
|
||||
char *key;
|
||||
char *value;
|
||||
} RzConfigHoldChar;
|
||||
|
||||
typedef struct rz_config_hold_t {
|
||||
RzConfig *cfg;
|
||||
RzList /*<RzConfigHoldNum *>*/ *list_num; // holds numeric values
|
||||
RzList /*<RzConfigHoldChar *>*/ *list_char; // holds char values
|
||||
} RzConfigHold;
|
||||
typedef struct rz_config_hold_t RzConfigHold;
|
||||
typedef bool (*RzConfigIterator)(const RzConfigEntry *entry, void *user);
|
||||
|
||||
#ifdef RZ_API
|
||||
RZ_API RzConfigHold *rz_config_hold_new(RzConfig *cfg);
|
||||
RZ_API void rz_config_hold_free(RzConfigHold *h);
|
||||
|
||||
RZ_API bool rz_config_hold_i(RzConfigHold *h, ...);
|
||||
RZ_API bool rz_config_hold_s(RzConfigHold *h, ...);
|
||||
RZ_API bool rz_config_hold_var(RZ_NONNULL RzConfigHold *hold, ...);
|
||||
RZ_API RzConfigHold *rz_config_hold_new(RZ_NONNULL RzConfig *cfg);
|
||||
RZ_API RzConfigHold *rz_config_hold_new2(RZ_NONNULL RzConfig *cfg, ...);
|
||||
RZ_API void rz_config_hold_restore(RZ_NULLABLE RzConfigHold *hold);
|
||||
RZ_API void rz_config_hold_free(RZ_NULLABLE RzConfigHold *h);
|
||||
RZ_API void rz_config_hold_restore_and_free(RZ_NULLABLE RzConfigHold *hold);
|
||||
|
||||
RZ_API void rz_config_hold_restore(RzConfigHold *h);
|
||||
RZ_API RZ_OWN RzConfig *rz_config_new(RZ_DEPRECATE RZ_BORROW void *user);
|
||||
RZ_API void rz_config_free(RZ_NULLABLE RzConfig *cfg);
|
||||
|
||||
RZ_API RZ_OWN RzConfig *rz_config_new(RZ_BORROW void *user);
|
||||
RZ_API RZ_OWN RzConfig *rz_config_clone(RZ_BORROW RzConfig *cfg);
|
||||
RZ_API void rz_config_free(RZ_OWN RzConfig *cfg);
|
||||
RZ_API void rz_config_lock(RZ_BORROW RzConfig *cfg, int l);
|
||||
RZ_API void rz_config_bump(RZ_BORROW RzConfig *cfg, const char *key);
|
||||
RZ_API bool rz_config_set_readonly(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, bool read_only);
|
||||
RZ_API bool rz_config_is_readonly(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API void rz_config_iterate_over(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL RzConfigIterator iterator, RZ_NULLABLE void *user);
|
||||
|
||||
RZ_API bool rz_config_add_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, bool value);
|
||||
RZ_API bool rz_config_add_integer(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ut64 value);
|
||||
RZ_API bool rz_config_add_string(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, RZ_NULLABLE const char *value);
|
||||
RZ_API bool rz_config_add_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...);
|
||||
RZ_API bool rz_config_add_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ...);
|
||||
RZ_API bool rz_config_add_interval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ut64 from, ut64 to);
|
||||
|
||||
RZ_API bool rz_config_add_bind(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc, ut32 type, RZ_NONNULL RzConfigBindGet get, RZ_NULLABLE RzConfigBindSet set, RZ_NULLABLE RzConfigBindOpts opts, RZ_NULLABLE void *user);
|
||||
#define rz_config_add_bool_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_BOOL, get, set, opts, user)
|
||||
#define rz_config_add_integer_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_INT, get, set, opts, user)
|
||||
#define rz_config_add_string_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_STR, get, set, opts, user)
|
||||
#define rz_config_add_list_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_LIST, get, set, opts, user)
|
||||
#define rz_config_add_interval_bind(cfg, name, desc, get, set, opts, user) rz_config_add_bind(cfg, name, desc, RZ_CONFIG_VAR_TYPE_ITV, get, set, opts, user)
|
||||
|
||||
RZ_API bool rz_config_set_string(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *value);
|
||||
RZ_API bool rz_config_set_integer(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ut64 value);
|
||||
RZ_API bool rz_config_set_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, bool value);
|
||||
RZ_API bool rz_config_toggle_bool(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API bool rz_config_set_list(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const RzList /*<const char *>*/ *value);
|
||||
RZ_API bool rz_config_set_list2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...);
|
||||
RZ_API bool rz_config_set_list3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_list);
|
||||
RZ_API bool rz_config_set_interval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RzInterval value);
|
||||
RZ_API bool rz_config_set_interval2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ut64 from, ut64 to);
|
||||
RZ_API bool rz_config_set_interval3(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *comma_itv);
|
||||
RZ_API bool rz_config_set_any(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *value);
|
||||
RZ_API bool rz_config_set_options(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE RZ_OWN RzList /*<char *>*/ *options);
|
||||
RZ_API bool rz_config_set_options2(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *name, ...);
|
||||
|
||||
RZ_API bool rz_config_get_bool(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API ut64 rz_config_get_integer(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API const char *rz_config_get_string(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API RZ_OWN RzList /*<const char *>*/ *rz_config_get_list(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API RzInterval rz_config_get_interval(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
|
||||
RZ_API RZ_OWN char *rz_config_get_as_string(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API const RzList /*<char *>*/ *rz_config_get_options(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API ut32 rz_config_get_flags(RZ_NONNULL const RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
|
||||
RZ_API bool rz_config_var_as_json(RZ_NONNULL const RzConfigVar *var, RZ_NONNULL PJ *pj, RZ_NONNULL const char *key);
|
||||
RZ_API RZ_OWN char *rz_config_var_as_string(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API bool rz_config_var_is_readonly(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API bool rz_config_var_get_bool(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API ut64 rz_config_var_get_integer(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API const char *rz_config_var_get_string(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API RZ_OWN RzList /*<const char *>*/ *rz_config_var_get_list(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API RzInterval rz_config_var_get_interval(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API bool rz_config_var_has_type(RZ_NONNULL const RzConfigVar *var, ut32 etype);
|
||||
RZ_API bool rz_config_var_has_flags(RZ_NONNULL const RzConfigVar *var, ut32 eflags);
|
||||
RZ_API RZ_OWN char *rz_config_var_flags_as_string(ut32 flags);
|
||||
RZ_API ut32 rz_config_var_get_flags(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API const char *rz_config_var_get_name(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API const char *rz_config_var_get_desc(RZ_NONNULL const RzConfigVar *var);
|
||||
RZ_API const RzList /*<char *>*/ *rz_config_var_get_options(RZ_NONNULL const RzConfigVar *var);
|
||||
|
||||
/* to deprecate */
|
||||
RZ_API const char *rz_config_entry_get_name(RZ_NONNULL const RzConfigEntry *entry);
|
||||
RZ_API const char *rz_config_entry_get_desc(RZ_NONNULL const RzConfigEntry *entry);
|
||||
|
||||
RZ_API ut64 rz_config_entry_get_integer(RZ_NONNULL const RzConfigEntry *entry);
|
||||
RZ_API bool rz_config_entry_get_bool(RZ_NONNULL const RzConfigEntry *entry);
|
||||
RZ_API const char *rz_config_entry_get_string(RZ_NONNULL const RzConfigEntry *entry);
|
||||
RZ_API RZ_OWN char *rz_config_entry_get_as_string(RZ_NONNULL const RzConfigEntry *entry);
|
||||
|
||||
/* old apis, deprecated */
|
||||
|
||||
RZ_API const char *rz_config_node_type(RzConfigNode *node);
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i);
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_b(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, bool value);
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_cb(RZ_BORROW RzConfig *cfg, const char *name, const char *value, bool (*callback)(void *user, void *data));
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set_i_cb(RZ_BORROW RzConfig *cfg, const char *name, st64 ivalue, bool (*callback)(void *user, void *data));
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_set(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name, const char *value);
|
||||
RZ_API bool rz_config_add_node(RZ_BORROW RzConfig *cfg, RZ_OWN RzConfigNode *node);
|
||||
RZ_API bool rz_config_rm(RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API bool rz_config_get_b(RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API RZ_BORROW const char *rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API const char *rz_config_desc(RzConfig *cfg, RZ_NONNULL const char *name, RZ_NULLABLE const char *desc);
|
||||
RZ_API const char *rz_config_node_desc(RzConfigNode *node, RZ_NULLABLE const char *desc);
|
||||
RZ_API RZ_BORROW RzConfigNode *rz_config_node_get(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API RZ_OWN RzConfigNode *rz_config_node_new(RZ_NONNULL const char *name, RZ_NONNULL const char *value);
|
||||
RZ_API RZ_OWN RzConfigNode *rz_config_node_clone(RZ_BORROW RzConfigNode *n);
|
||||
RZ_API void rz_config_node_free(RZ_NULLABLE void *n);
|
||||
RZ_API void rz_config_node_value_format_i(RZ_OUT char *buf, size_t buf_size, const ut64 i, RZ_NULLABLE RzConfigNode *node);
|
||||
RZ_API bool rz_config_toggle(RZ_BORROW RzConfig *cfg, RZ_NONNULL const char *name);
|
||||
RZ_API bool rz_config_readonly(RZ_BORROW RzConfig *cfg, const char *key);
|
||||
RZ_API bool rz_config_eval(RZ_NONNULL RzConfig *cfg, RZ_NONNULL const char *str);
|
||||
RZ_API ut32 rz_config_node_get_var_flags(RZ_NONNULL const RzConfigNode *node);
|
||||
|
||||
RZ_API bool rz_config_set_setter(RzConfig *cfg, const char *key, RzConfigCallback cb);
|
||||
RZ_API bool rz_config_set_getter(RzConfig *cfg, const char *key, RzConfigCallback cb);
|
||||
|
||||
RZ_API void rz_config_serialize(RZ_NONNULL RzConfig *config, RZ_NONNULL Sdb *db);
|
||||
RZ_API bool rz_config_unserialize(RZ_NONNULL RzConfig *config, RZ_NONNULL Sdb *db, RZ_NULLABLE char **err);
|
||||
|
||||
static inline bool rz_config_node_is_bool(RzConfigNode *node) {
|
||||
static inline bool rz_config_node_is_bool(const RzConfigNode *node) {
|
||||
return node->flags & CN_BOOL;
|
||||
}
|
||||
static inline bool rz_config_node_is_int(RzConfigNode *node) {
|
||||
|
||||
static inline bool rz_config_node_is_int(const RzConfigNode *node) {
|
||||
return node->flags & CN_INT;
|
||||
}
|
||||
static inline bool rz_config_node_is_ro(RzConfigNode *node) {
|
||||
|
||||
static inline bool rz_config_node_is_ro(const RzConfigNode *node) {
|
||||
return node->flags & CN_RO;
|
||||
}
|
||||
static inline bool rz_config_node_is_str(RzConfigNode *node) {
|
||||
|
||||
static inline bool rz_config_node_is_str(const RzConfigNode *node) {
|
||||
return node->flags & CN_STR;
|
||||
}
|
||||
|
||||
/* serialize */
|
||||
|
||||
RZ_API void rz_serialize_config_save(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config);
|
||||
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config,
|
||||
RZ_NULLABLE const char *const *exclude, RZ_NULLABLE RzSerializeResultInfo *res);
|
||||
RZ_API bool rz_serialize_config_load(RZ_NONNULL Sdb *db, RZ_NONNULL RzConfig *config, RZ_NULLABLE const char **exclude);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ typedef struct rz_debug_t {
|
|||
char *btalgo; /* select backtrace algorithm */
|
||||
int btdepth; /* backtrace depth */
|
||||
int regcols; /* display columns */
|
||||
int swstep; /* steps with software traps */
|
||||
bool swstep; /* when true, steps with software traps */
|
||||
int stop_all_threads; /* stop all threads at any stop */
|
||||
int trace_forks; /* stop on new children */
|
||||
int trace_execs; /* stop on new execs */
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ RZ_API RZ_OWN void *rz_list_pop(RZ_NONNULL RzList *list);
|
|||
RZ_API RZ_OWN void *rz_list_pop_head(RZ_NONNULL RzList *list);
|
||||
RZ_API void rz_list_reverse(RZ_NONNULL RzList *list);
|
||||
RZ_API RZ_OWN RzList *rz_list_clone(RZ_NONNULL const RzList *list);
|
||||
RZ_API RZ_OWN char *rz_list_to_str(RZ_NONNULL RzList *list, char ch);
|
||||
RZ_API RZ_OWN char *rz_list_to_str(RZ_NONNULL RzList /*<const char *>*/ *list, char ch, bool append_last);
|
||||
|
||||
/* hashlike api */
|
||||
RZ_API RZ_BORROW bool rz_list_contains(RZ_NONNULL const RzList *list, RZ_NONNULL const void *val);
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ RZ_API bool rz_str_cmp_list(const char *list, const char *item, char sep);
|
|||
RZ_API int rz_str_cmp(RZ_NULLABLE const char *dst, RZ_NULLABLE const char *orig, int len);
|
||||
RZ_API int rz_str_casecmp(const char *dst, const char *orig);
|
||||
RZ_API int rz_str_ncasecmp(const char *dst, const char *orig, size_t n);
|
||||
RZ_API int rz_str_ccpy(char *dst, char *orig, int ch);
|
||||
RZ_API int rz_str_ccpy(char *dst, const char *orig, int ch);
|
||||
static inline const char *rz_str_get(const char *str) {
|
||||
return str ? str : "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -736,7 +736,7 @@ RZ_API int rz_main_rz_bin(int argc, const char **argv) {
|
|||
if ((tmp = rz_sys_getenv("RZ_CONFIG"))) {
|
||||
Sdb *config_sdb = sdb_new(NULL, tmp, 0);
|
||||
if (config_sdb) {
|
||||
rz_config_unserialize(core.config, config_sdb, NULL);
|
||||
rz_serialize_config_load(config_sdb, core.config, NULL);
|
||||
sdb_free(config_sdb);
|
||||
} else {
|
||||
eprintf("Cannot open file specified in RZ_CONFIG\n");
|
||||
|
|
|
|||
|
|
@ -1513,10 +1513,10 @@ static char *basic_block_opcodes(RzCore *core, RzAnalysisBlock *bbi) {
|
|||
RzConfigHold *hc = NULL;
|
||||
ut8 *block = NULL;
|
||||
|
||||
if (!(hc = rz_config_hold_new(core->config))) {
|
||||
hc = rz_config_hold_new2(core->config, "scr.color", "scr.utf8", "asm.offset", "asm.lines", "asm.cmt.right", "asm.lines.fcn", "asm.bytes", "asm.comments", NULL);
|
||||
if (!hc) {
|
||||
return NULL;
|
||||
}
|
||||
rz_config_hold_i(hc, "scr.color", "scr.utf8", "asm.offset", "asm.lines", "asm.cmt.right", "asm.lines.fcn", "asm.bytes", "asm.comments", NULL);
|
||||
rz_config_set_i(core->config, "scr.utf8", 0);
|
||||
rz_config_set_i(core->config, "asm.offset", 0);
|
||||
rz_config_set_i(core->config, "asm.lines", 0);
|
||||
|
|
|
|||
|
|
@ -871,20 +871,30 @@ RZ_API void rz_list_sorted_uniq(RZ_NONNULL RzList *list, RZ_NONNULL RzListCompar
|
|||
/**
|
||||
* \brief Casts a RzList containing strings into a concatenated string
|
||||
*
|
||||
* \param list The list of strings to concatenate.
|
||||
* \param ch char to separate the match strings.
|
||||
* \param list The list of strings to concatenate.
|
||||
* \param ch Char to separate the match strings.
|
||||
* \param append_last When true appends `ch` at the end.
|
||||
*
|
||||
* \return The concatenated string.
|
||||
**/
|
||||
RZ_API RZ_OWN char *rz_list_to_str(RZ_NONNULL RzList *list, char ch) {
|
||||
RZ_API RZ_OWN char *rz_list_to_str(RZ_NONNULL RzList /*<const char *>*/ *list, char ch, bool append_last) {
|
||||
rz_return_val_if_fail(list && ch > 0, NULL);
|
||||
|
||||
RzListIter *iter;
|
||||
RzStrBuf *buf = rz_strbuf_new("");
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
char *item;
|
||||
const char *item;
|
||||
rz_list_foreach (list, iter, item) {
|
||||
rz_strbuf_appendf(buf, "%s%c", item, ch);
|
||||
if (rz_strbuf_length(buf) > 0) {
|
||||
rz_strbuf_appendf(buf, "%c%s", ch, item);
|
||||
} else {
|
||||
rz_strbuf_append(buf, item);
|
||||
}
|
||||
}
|
||||
if (append_last) {
|
||||
rz_strbuf_appendf(buf, "%c", ch);
|
||||
}
|
||||
return rz_strbuf_drain(buf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1070,7 +1070,7 @@ RZ_API int rz_str_cmp(RZ_NULLABLE const char *a, RZ_NULLABLE const char *b, int
|
|||
}
|
||||
|
||||
// Copies all characters from src to dst up until the character 'ch'.
|
||||
RZ_API int rz_str_ccpy(char *dst, char *src, int ch) {
|
||||
RZ_API int rz_str_ccpy(char *dst, const char *src, int ch) {
|
||||
int i;
|
||||
for (i = 0; src[i] && src[i] != ch; i++) {
|
||||
dst[i] = src[i];
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ RZ_API RZ_OWN char *rz_syscmd_sort_str(RZ_NONNULL const char *input) {
|
|||
|
||||
rz_list_sort(list, cmpstr, NULL);
|
||||
rz_list_del_n(list, 0);
|
||||
char *sorted_str = rz_list_to_str(list, '\n');
|
||||
char *sorted_str = rz_list_to_str(list, '\n', true);
|
||||
|
||||
rz_list_free(list);
|
||||
free(data);
|
||||
|
|
@ -224,7 +224,7 @@ RZ_API RZ_OWN char *rz_syscmd_uniq_str(RZ_NONNULL const char *input) {
|
|||
return NULL;
|
||||
}
|
||||
rz_list_del_n(uniq_list, rz_list_length(uniq_list) - 1);
|
||||
char *return_str = rz_list_to_str(uniq_list, '\n');
|
||||
char *return_str = rz_list_to_str(uniq_list, '\n', true);
|
||||
|
||||
rz_list_free(uniq_list);
|
||||
rz_list_free(list);
|
||||
|
|
@ -293,7 +293,7 @@ RZ_API RZ_OWN char *rz_syscmd_join(RZ_NONNULL const char *file1, RZ_NONNULL cons
|
|||
}
|
||||
free(field);
|
||||
}
|
||||
data = rz_list_to_str(list, '\n');
|
||||
data = rz_list_to_str(list, '\n', true);
|
||||
rz_list_free(list2);
|
||||
rz_list_free(list1);
|
||||
rz_list_free(list);
|
||||
|
|
|
|||
|
|
@ -380,7 +380,9 @@ static bool bin_search_range(RZ_NONNULL RzVector *vec, RZ_NONNULL void *elem, Rz
|
|||
*/
|
||||
RZ_API void *rz_vector_insert_sorted(RZ_NONNULL RzVector *vec, RZ_NONNULL void *elem, RzVectorComparator cmp, void *user) {
|
||||
rz_return_val_if_fail(vec && elem, NULL);
|
||||
if (rz_vector_empty(vec)) {
|
||||
|
||||
size_t len = rz_vector_len(vec);
|
||||
if (len < 1) {
|
||||
return rz_vector_push(vec, elem);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ nodup
|
|||
false
|
||||
true
|
||||
false
|
||||
true
|
||||
1
|
||||
false
|
||||
EOF
|
||||
RUN
|
||||
|
|
|
|||
|
|
@ -174,17 +174,17 @@ elq zoom
|
|||
EOF
|
||||
EXPECT=<<EOF
|
||||
{"zoom.byte":"h","zoom.from":0,"zoom.in":"io.map","zoom.maxsz":512,"zoom.to":0}
|
||||
[{"name":"zoom.byte","value":"h","type":"str","desc":"Zoom callback to calculate each byte (See pz? for help)","ro":false},{"name":"zoom.from","value":0,"type":"int","desc":"Zoom start address","ro":false},{"name":"zoom.in","value":"io.map","type":"str","desc":"Specify boundaries for zoom","ro":false,"options":["raw","block","bin.section","bin.sections","bin.sections.rwx","bin.sections.r","bin.sections.rw","bin.sections.rx","bin.sections.wx","bin.sections.x","io.map","io.maps","io.maps.rwx","io.maps.r","io.maps.rw","io.maps.rx","io.maps.wx","io.maps.x","dbg.stack","dbg.heap","dbg.map","dbg.maps","dbg.maps.rwx","dbg.maps.r","dbg.maps.rw","dbg.maps.rx","dbg.maps.wx","dbg.maps.x","analysis.fcn","analysis.bb"]},{"name":"zoom.maxsz","value":512,"type":"int","desc":"Zoom max size of block","ro":false},{"name":"zoom.to","value":0,"type":"int","desc":"Zoom end address","ro":false}]
|
||||
[{"name":"zoom.byte","desc":"Zoom callback to calculate each byte (See pz? for help)","flags":"string,bind","options":[],"value":"h"},{"name":"zoom.from","desc":"Zoom start address","flags":"integer","options":[],"value":0},{"name":"zoom.in","desc":"Specify boundaries for zoom","flags":"string,bind","options":["raw","block","bin.section","bin.sections","bin.sections.rwx","bin.sections.r","bin.sections.rw","bin.sections.rx","bin.sections.wx","bin.sections.x","io.map","io.maps","io.maps.rwx","io.maps.r","io.maps.rw","io.maps.rx","io.maps.wx","io.maps.x","dbg.stack","dbg.heap","dbg.map","dbg.maps","dbg.maps.rwx","dbg.maps.r","dbg.maps.rw","dbg.maps.rx","dbg.maps.wx","dbg.maps.x","analysis.fcn","analysis.bb"],"value":"io.map"},{"name":"zoom.maxsz","desc":"Zoom max size of block","flags":"integer","options":[],"value":512},{"name":"zoom.to","desc":"Zoom end address","flags":"integer","options":[],"value":0}]
|
||||
zoom.byte: Zoom callback to calculate each byte (See pz? for help)
|
||||
zoom.from: Zoom start address
|
||||
zoom.in: Specify boundaries for zoom
|
||||
zoom.maxsz: Zoom max size of block
|
||||
zoom.to: Zoom end address
|
||||
zoom.byte = h ; Zoom callback to calculate each byte (See pz? for help)
|
||||
zoom.from = 0 ; Zoom start address
|
||||
zoom.in = io.map ; Specify boundaries for zoom [raw, block, bin.section, bin.sections, bin.sections.rwx, bin.sections.r, bin.sections.rw, bin.sections.rx, bin.sections.wx, bin.sections.x, io.map, io.maps, io.maps.rwx, io.maps.r, io.maps.rw, io.maps.rx, io.maps.wx, io.maps.x, dbg.stack, dbg.heap, dbg.map, dbg.maps, dbg.maps.rwx, dbg.maps.r, dbg.maps.rw, dbg.maps.rx, dbg.maps.wx, dbg.maps.x, analysis.fcn, analysis.bb]
|
||||
zoom.maxsz = 512 ; Zoom max size of block
|
||||
zoom.to = 0 ; Zoom end address
|
||||
zoom.byte = h (string,bind); Zoom callback to calculate each byte (See pz? for help)
|
||||
zoom.from = 0 (integer); Zoom start address
|
||||
zoom.in = io.map (string,bind); Specify boundaries for zoom [raw, block, bin.section, bin.sections, bin.sections.rwx, bin.sections.r, bin.sections.rw, bin.sections.rx, bin.sections.wx, bin.sections.x, io.map, io.maps, io.maps.rwx, io.maps.r, io.maps.rw, io.maps.rx, io.maps.wx, io.maps.x, dbg.stack, dbg.heap, dbg.map, dbg.maps, dbg.maps.rwx, dbg.maps.r, dbg.maps.rw, dbg.maps.rx, dbg.maps.wx, dbg.maps.x, analysis.fcn, analysis.bb]
|
||||
zoom.maxsz = 512 (integer); Zoom max size of block
|
||||
zoom.to = 0 (integer); Zoom end address
|
||||
zoom.byte=h
|
||||
zoom.from=0
|
||||
zoom.in=io.map
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ EOF
|
|||
EXPECT=<<EOF
|
||||
[?25l[0m[2J
[0;0H0> | [0m[2J
[0;0H0> |
|
||||
- analysis.apply.signature: bool - enables/disables auto-applying signatures to the loaded binary (see also flirt[0J
[0m
|
||||
analysis.arch: str - Select the architecture to use [?25h
|
||||
analysis.arch: string,bind - Select the architecture to use [?25h
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ NAME=@e:
|
|||
FILE==
|
||||
CMDS=<<EOF
|
||||
e scr.color=false
|
||||
e scr.color @e:scr.color=true
|
||||
e scr.color @e:scr.color=1
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
1
|
||||
|
|
@ -36,8 +36,8 @@ FILE==
|
|||
CMDS=<<EOF
|
||||
e scr.color=false
|
||||
s 0
|
||||
e scr.color @e:scr.color=true @ 0x1337
|
||||
s @e:scr.color=true @ 0x1337
|
||||
e scr.color @e:scr.color=1 @ 0x1337
|
||||
s @e:scr.color=1 @ 0x1337
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
1
|
||||
|
|
@ -49,9 +49,9 @@ NAME=@ addr @e
|
|||
FILE==
|
||||
CMDS=<<EOF
|
||||
e scr.color @ 0x42 @e:scr.color=false
|
||||
e scr.color @ 0x1337 @e:scr.color=true
|
||||
e scr.color @ 0x1337 @e:scr.color=1
|
||||
s @ 0x42 @e:scr.color=false
|
||||
s @ 0x1337 @e:scr.color=true
|
||||
s @ 0x1337 @e:scr.color=1
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
0
|
||||
|
|
@ -65,11 +65,11 @@ NAME=@a: @ addr @e:
|
|||
FILE==
|
||||
CMDS=<<EOF
|
||||
e asm.arch @a:x86 @ 0x42 @e:scr.color=false
|
||||
e asm.arch @a:arm @ 0x1337 @e:scr.color=true
|
||||
e asm.arch @a:arm @ 0x1337 @e:scr.color=1
|
||||
s @a:x86 @ 0x42 @e:scr.color=false
|
||||
s @a:arm @ 0x1337 @e:scr.color=true
|
||||
s @a:arm @ 0x1337 @e:scr.color=1
|
||||
e scr.color @a:x86 @ 0x42 @e:scr.color=false
|
||||
e scr.color @a:arm @ 0x1337 @e:scr.color=true
|
||||
e scr.color @a:arm @ 0x1337 @e:scr.color=1
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
x86
|
||||
|
|
|
|||
|
|
@ -86,13 +86,13 @@ void snprint_mem(char *out, size_t out_size, const ut8 *buf, size_t len) {
|
|||
|
||||
#define mu_ignore \
|
||||
do { \
|
||||
printf(TYELLOW "IGN\n" TRESET); \
|
||||
printf(TYELLOW "IGN" TRESET "\n"); \
|
||||
return MU_PASSED; \
|
||||
} while (0)
|
||||
|
||||
#define mu_end \
|
||||
do { \
|
||||
printf(TGREEN "OK\n" TRESET); \
|
||||
printf(TGREEN "OK" TRESET "\n"); \
|
||||
return MU_PASSED; \
|
||||
} while (0)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,60 +1,544 @@
|
|||
// SPDX-FileCopyrightText: 2026 deroad <deroad@kumo.xn--q9jyb4c>
|
||||
// SPDX-FileCopyrightText: 2021 Anton Kochkov <anton.kochkov@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_config.h>
|
||||
#include "minunit.h"
|
||||
|
||||
bool test_config() {
|
||||
bool test_config_strings() {
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
bool ret = false;
|
||||
const char *bla = NULL;
|
||||
|
||||
// string variables
|
||||
rz_config_set(cfg, "foo.bar", "bla");
|
||||
const char *bla = rz_config_get(cfg, "foo.bar");
|
||||
mu_assert_streq(bla, "bla", "String variable");
|
||||
// normal string
|
||||
ret = rz_config_add_string(cfg, "foo.bar", "is foo.bar desc", "bla");
|
||||
mu_assert_true(ret, "added foo.bar");
|
||||
|
||||
// integer variables
|
||||
rz_config_set_i(cfg, "universe.question", 42);
|
||||
int answer = rz_config_get_i(cfg, "universe.question");
|
||||
mu_assert_eq(answer, 42, "Integer variable");
|
||||
ret = rz_config_is_readonly(cfg, "foo.bar");
|
||||
mu_assert_false(ret, "foo.bar is not readonly");
|
||||
|
||||
// boolean variables
|
||||
rz_config_set_b(cfg, "true.or.false", true);
|
||||
bool what = rz_config_get_b(cfg, "true.or.false");
|
||||
mu_assert_eq(what, true, "Boolean variable");
|
||||
rz_config_toggle(cfg, "true.or.false");
|
||||
what = rz_config_get_b(cfg, "true.or.false");
|
||||
mu_assert_eq(what, false, "Boolean variable (toggle)");
|
||||
bla = rz_config_get_string(cfg, "foo.bar");
|
||||
mu_assert_streq(bla, "bla", "String variable 1");
|
||||
|
||||
ret = rz_config_set_string(cfg, "foo.bar", "woff");
|
||||
mu_assert_true(ret, "set foo.bar (rw)");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.bar");
|
||||
mu_assert_streq(bla, "woff", "String variable 2");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "foo.bar", true);
|
||||
mu_assert_true(ret, "foo.bar set as readonly");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "foo.bar");
|
||||
mu_assert_true(ret, "foo.bar is readonly");
|
||||
|
||||
ret = rz_config_set_string(cfg, "foo.bar", "oink");
|
||||
mu_assert_false(ret, "set foo.bar (ro) 1");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.bar");
|
||||
mu_assert_streq(bla, "woff", "String variable 3");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "foo.bar", false);
|
||||
mu_assert_true(ret, "foo.bar set not readonly");
|
||||
|
||||
ret = rz_config_set_string(cfg, "foo.bar", NULL);
|
||||
mu_assert_true(ret, "set foo.bar (rw) 2");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.bar");
|
||||
mu_assert_notnull(bla, "foo.bar is not null");
|
||||
mu_assert_streq(bla, "", "String variable 4");
|
||||
|
||||
ret = rz_config_set_any(cfg, "foo.bar", "this is a string");
|
||||
mu_assert_true(ret, "set ANY foo.bar");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.bar");
|
||||
mu_assert_streq(bla, "this is a string", "String variable 5");
|
||||
|
||||
// options string
|
||||
|
||||
ret = rz_config_add_options(cfg, "foo.options", "is foo.options desc", "option1", "option2", "option3", "option4", NULL);
|
||||
mu_assert_true(ret, "added foo.options");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.options");
|
||||
mu_assert_streq(bla, "option1", "options variable 1");
|
||||
|
||||
ret = rz_config_set_string(cfg, "foo.options", "jjjjjjj");
|
||||
mu_assert_false(ret, "set foo.options to invalid");
|
||||
|
||||
ret = rz_config_set_string(cfg, "foo.options", "");
|
||||
mu_assert_false(ret, "set foo.options to invalid");
|
||||
|
||||
ret = rz_config_set_string(cfg, "foo.options", "option2");
|
||||
mu_assert_true(ret, "set foo.options to option2");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.options");
|
||||
mu_assert_streq(bla, "option2", "options variable 2");
|
||||
|
||||
ret = rz_config_set_any(cfg, "foo.options", "option3");
|
||||
mu_assert_true(ret, "set ANY foo.options");
|
||||
|
||||
bla = rz_config_get_string(cfg, "foo.options");
|
||||
mu_assert_streq(bla, "option3", "options variable 3");
|
||||
|
||||
char *s = rz_config_get_as_string(cfg, "foo.options");
|
||||
mu_assert_streq(s, "option3", "get as string foo.options");
|
||||
free(s);
|
||||
|
||||
rz_config_free(cfg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_config_lock() {
|
||||
bool test_config_intergers() {
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
cfg->lock = 1;
|
||||
|
||||
// string variables
|
||||
rz_config_set(cfg, "foo.bar", "bla");
|
||||
const char *bla = rz_config_get(cfg, "foo.bar");
|
||||
mu_assert_null(bla, "String variable (locked)");
|
||||
bool ret = false;
|
||||
|
||||
// integer variables
|
||||
rz_config_set_i(cfg, "universe.question", 42);
|
||||
int answer = rz_config_get_i(cfg, "universe.question");
|
||||
mu_assert_neq(answer, 42, "Integer variable (locked)");
|
||||
ret = rz_config_add_integer(cfg, "universe.question", "is universe.question desc", 42);
|
||||
mu_assert_true(ret, "added universe.question");
|
||||
|
||||
// boolean variables
|
||||
rz_config_set_b(cfg, "true.or.false", true);
|
||||
bool what = rz_config_get_b(cfg, "true.or.false");
|
||||
mu_assert_false(what, "Boolean variable (locked)");
|
||||
ut64 answer = rz_config_get_integer(cfg, "universe.question");
|
||||
mu_assert_eq(answer, 42, "Integer variable 1");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "universe.question");
|
||||
mu_assert_false(ret, "universe.question is not readonly");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "universe.question", true);
|
||||
mu_assert_true(ret, "universe.question set as readonly");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "universe.question");
|
||||
mu_assert_true(ret, "universe.question is readonly");
|
||||
|
||||
ret = rz_config_set_integer(cfg, "universe.question", 99);
|
||||
mu_assert_false(ret, "set universe.question (ro)");
|
||||
|
||||
answer = rz_config_get_integer(cfg, "universe.question");
|
||||
mu_assert_eq(answer, 42, "Integer variable 2");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "universe.question", false);
|
||||
mu_assert_true(ret, "universe.question is not readonly");
|
||||
|
||||
ret = rz_config_set_any(cfg, "universe.question", "2000");
|
||||
mu_assert_true(ret, "set ANY universe.question");
|
||||
|
||||
answer = rz_config_get_integer(cfg, "universe.question");
|
||||
mu_assert_eq(answer, 2000, "Integer variable 3");
|
||||
|
||||
char *s = rz_config_get_as_string(cfg, "universe.question");
|
||||
mu_assert_streq(s, "2000", "get as string universe.question");
|
||||
free(s);
|
||||
|
||||
rz_config_free(cfg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_config_booleans() {
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
bool ret = false;
|
||||
|
||||
// boolean variables
|
||||
ret = rz_config_add_bool(cfg, "true.or.false", "is true.or.false desc", true);
|
||||
mu_assert_true(ret, "added true.or.false");
|
||||
|
||||
bool what = rz_config_get_bool(cfg, "true.or.false");
|
||||
mu_assert_true(what, "Boolean variable");
|
||||
|
||||
ret = rz_config_toggle_bool(cfg, "true.or.false");
|
||||
mu_assert_true(ret, "toggle true.or.false");
|
||||
|
||||
what = rz_config_get_bool(cfg, "true.or.false");
|
||||
mu_assert_false(what, "Boolean variable (toggle)");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "true.or.false");
|
||||
mu_assert_false(ret, "true.or.false is not readonly");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "true.or.false", true);
|
||||
mu_assert_true(ret, "true.or.false set as readonly");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "true.or.false");
|
||||
mu_assert_true(ret, "true.or.false is readonly");
|
||||
|
||||
ret = rz_config_set_b(cfg, "true.or.false", true);
|
||||
mu_assert_false(ret, "set true.or.false (ro)");
|
||||
|
||||
what = rz_config_get_bool(cfg, "true.or.false");
|
||||
mu_assert_false(what, "Boolean variable 2");
|
||||
|
||||
ret = rz_config_toggle_bool(cfg, "true.or.false");
|
||||
mu_assert_false(ret, "toggle fails true.or.false");
|
||||
|
||||
what = rz_config_get_bool(cfg, "true.or.false");
|
||||
mu_assert_false(what, "Boolean variable 2");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "true.or.false", false);
|
||||
mu_assert_true(ret, "true.or.false is not readonly");
|
||||
|
||||
ret = rz_config_set_any(cfg, "true.or.false", "yes");
|
||||
mu_assert_true(ret, "set ANY true.or.false");
|
||||
|
||||
what = rz_config_get_bool(cfg, "true.or.false");
|
||||
mu_assert_true(what, "Boolean variable 2");
|
||||
|
||||
char *s = rz_config_get_as_string(cfg, "true.or.false");
|
||||
mu_assert_streq(s, "true", "get as string true.or.false");
|
||||
free(s);
|
||||
|
||||
rz_config_free(cfg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_config_lists() {
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
bool ret = false;
|
||||
const char *elem = NULL;
|
||||
RzList *list = NULL;
|
||||
RzListIter *it;
|
||||
|
||||
// list variables
|
||||
ret = rz_config_add_list(cfg, "thy.list", "is thy.list desc", "r1", "r2", "r3", NULL);
|
||||
mu_assert_true(ret, "added thy.list");
|
||||
|
||||
list = rz_config_get_list(cfg, "thy.list");
|
||||
mu_assert_notnull(list, "List is not null variable");
|
||||
mu_assert_eq(rz_list_length(list), 3, "List size is 3");
|
||||
|
||||
it = rz_list_head(list);
|
||||
elem = rz_list_val(it);
|
||||
mu_assert_streq(elem, "r1", "list[0] is r1");
|
||||
|
||||
it = rz_list_next(it);
|
||||
elem = rz_list_val(it);
|
||||
mu_assert_streq(elem, "r2", "list[1] is r2");
|
||||
|
||||
it = rz_list_next(it);
|
||||
elem = rz_list_val(it);
|
||||
mu_assert_streq(elem, "r3", "list[2] is r3");
|
||||
rz_list_free(list);
|
||||
|
||||
ret = rz_config_set_list2(cfg, "thy.list", "x0", "x1", "x2", "x3", "x4", NULL);
|
||||
mu_assert_true(ret, "set thy.list");
|
||||
|
||||
list = rz_config_get_list(cfg, "thy.list");
|
||||
mu_assert_notnull(list, "List is not null variable");
|
||||
mu_assert_eq(rz_list_length(list), 5, "List size is 5");
|
||||
|
||||
char *s = rz_config_get_as_string(cfg, "thy.list");
|
||||
mu_assert_streq(s, "x0,x1,x2,x3,x4", "get as string thy.list");
|
||||
free(s);
|
||||
|
||||
elem = rz_list_first_val(list);
|
||||
mu_assert_streq(elem, "x0", "list[first] is x0");
|
||||
|
||||
elem = rz_list_last_val(list);
|
||||
mu_assert_streq(elem, "x4", "list[last] is x4");
|
||||
rz_list_free(list);
|
||||
|
||||
ret = rz_config_set_list3(cfg, "thy.list", "rax,rbx");
|
||||
mu_assert_true(ret, "set thy.list as string");
|
||||
|
||||
list = rz_config_get_list(cfg, "thy.list");
|
||||
mu_assert_notnull(list, "List is not null variable");
|
||||
mu_assert_eq(rz_list_length(list), 2, "List size is 2");
|
||||
rz_list_free(list);
|
||||
|
||||
ret = rz_config_set_list(cfg, "thy.list", NULL);
|
||||
mu_assert_true(ret, "set thy.list as string");
|
||||
|
||||
list = rz_config_get_list(cfg, "thy.list");
|
||||
mu_assert_notnull(list, "List is not null variable");
|
||||
mu_assert_eq(rz_list_length(list), 0, "List is empty");
|
||||
rz_list_free(list);
|
||||
|
||||
rz_config_free(cfg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_config_itv() {
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
bool ret = false;
|
||||
RzInterval itv = { 0 };
|
||||
|
||||
// interval variables
|
||||
ret = rz_config_add_interval(cfg, "this.limit", "is this.limit desc", 0x230, 0x4fff);
|
||||
mu_assert_true(ret, "added this.limit [0x230, 0x4fff]");
|
||||
|
||||
itv = rz_config_get_interval(cfg, "this.limit");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x230, "interval starts at 0x230 (inclusive)");
|
||||
mu_assert_eq(rz_itv_end(itv), 0x4fff, "interval ends at 0x4fff (inclusive)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0x4dcf, "interval size at 0x4dcf");
|
||||
|
||||
itv.addr = 0x1000;
|
||||
itv.size = 0x4f;
|
||||
ret = rz_config_set_interval(cfg, "this.limit", itv);
|
||||
mu_assert_true(ret, "set this.limit [0x1000, 0x104f]");
|
||||
|
||||
itv = rz_config_get_interval(cfg, "this.limit");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x1000, "interval starts at 0x1000 (inclusive)");
|
||||
mu_assert_eq(rz_itv_end(itv), 0x104f, "interval ends at 0x104f (inclusive)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0x4f, "interval size at 0x4f");
|
||||
|
||||
ret = rz_config_set_interval2(cfg, "this.limit", 0x80000000, 0x8fffffff);
|
||||
mu_assert_true(ret, "set this.limit [0x80000000, 0x8fffffff]");
|
||||
|
||||
itv = rz_config_get_interval(cfg, "this.limit");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x80000000, "interval starts at 0x80000000 (inclusive)");
|
||||
mu_assert_eq(rz_itv_end(itv), 0x8fffffff, "interval ends at 0x8fffffff (inclusive)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0xfffffff, "interval size at 0xfffffff");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "this.limit");
|
||||
mu_assert_false(ret, "this.limit is not readonly");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "this.limit", true);
|
||||
mu_assert_true(ret, "this.limit set as readonly");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "this.limit");
|
||||
mu_assert_true(ret, "this.limit is readonly");
|
||||
|
||||
ret = rz_config_set_interval2(cfg, "this.limit", 0, 1);
|
||||
mu_assert_false(ret, "set this.limit [0, 1] RO");
|
||||
|
||||
itv = rz_config_get_interval(cfg, "this.limit");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x80000000, "interval starts at 0x80000000 (inclusive)");
|
||||
mu_assert_eq(rz_itv_end(itv), 0x8fffffff, "interval ends at 0x8fffffff (inclusive)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0xfffffff, "interval size at 0xfffffff");
|
||||
|
||||
ret = rz_config_set_readonly(cfg, "this.limit", false);
|
||||
mu_assert_true(ret, "this.limit set as readonly");
|
||||
|
||||
ret = rz_config_is_readonly(cfg, "this.limit");
|
||||
mu_assert_false(ret, "this.limit is not readonly");
|
||||
|
||||
ret = rz_config_set_interval3(cfg, "this.limit", " 0x11111 , 0x22222 ");
|
||||
mu_assert_true(ret, "set this.limit [0x11111, 0x22222]");
|
||||
|
||||
itv = rz_config_get_interval(cfg, "this.limit");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x11111, "interval starts at 0x11111 (inclusive)");
|
||||
mu_assert_eq(rz_itv_end(itv), 0x22222, "interval ends at 0x22222 (inclusive)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0x11111, "interval size at 0x11111");
|
||||
|
||||
ret = rz_config_set_interval2(cfg, "this.limit", 0x80000000, 0x100);
|
||||
mu_assert_false(ret, "cannot set this.limit [0x80000000, 0x100]");
|
||||
|
||||
ret = rz_config_set_interval3(cfg, "this.limit", "0x500000,0x8888");
|
||||
mu_assert_false(ret, "cannot set this.limit [0x500000, 0x8888]");
|
||||
|
||||
ret = rz_config_add_interval(cfg, "bad.limit", NULL, 0x9999, 0);
|
||||
mu_assert_false(ret, "cannot set bad.limit [0x9999, 0]");
|
||||
|
||||
char *s = rz_config_get_as_string(cfg, "this.limit");
|
||||
mu_assert_streq(s, "0x00011111,0x00022222", "get as string this.limit");
|
||||
free(s);
|
||||
|
||||
rz_config_free(cfg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool test_config_invalid() {
|
||||
RzInterval itv = { 0x1000, 0x2000 };
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
|
||||
mu_assert_null(rz_config_get_string(cfg, "string.here"), "string.here does not exist");
|
||||
mu_assert_null(rz_config_get_list(cfg, "list.here"), "list.here does not exist");
|
||||
mu_assert_eq(rz_config_get_integer(cfg, "int.here"), 0, "int.here does not exist");
|
||||
mu_assert_false(rz_config_get_bool(cfg, "bool.here"), "bool.here does not exist");
|
||||
itv = rz_config_get_interval(cfg, "itv.here");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0, "itv.here does not exist (addr = 0)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0, "itv.here does not exist (size = 0)");
|
||||
|
||||
rz_config_free(cfg);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
typedef struct bind_test_s {
|
||||
ut32 get;
|
||||
ut32 set;
|
||||
ut32 opts;
|
||||
ut32 bind;
|
||||
const void *set_val;
|
||||
RzList *list;
|
||||
} bind_test_t;
|
||||
|
||||
static bool any_get(void *user, void *p) {
|
||||
bind_test_t *bt = user;
|
||||
switch (bt->bind) {
|
||||
case RZ_CONFIG_VAR_TYPE_BOOL: {
|
||||
bool *value = p;
|
||||
*value = true;
|
||||
bt->get++;
|
||||
return true;
|
||||
}
|
||||
case RZ_CONFIG_VAR_TYPE_INT: {
|
||||
ut64 *value = p;
|
||||
*value = 42;
|
||||
bt->get++;
|
||||
return true;
|
||||
}
|
||||
case RZ_CONFIG_VAR_TYPE_STR: {
|
||||
const char **value = p;
|
||||
*value = "what";
|
||||
bt->get++;
|
||||
return true;
|
||||
}
|
||||
case RZ_CONFIG_VAR_TYPE_LIST: {
|
||||
const RzList **value = p;
|
||||
*value = bt->list;
|
||||
bt->get++;
|
||||
return true;
|
||||
}
|
||||
case RZ_CONFIG_VAR_TYPE_ITV: {
|
||||
RzInterval *value = p;
|
||||
value->addr = 0x2222;
|
||||
value->size = 0x1111;
|
||||
bt->get++;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool any_set(void *user, const void *p) {
|
||||
bind_test_t *bt = user;
|
||||
switch (bt->bind) {
|
||||
case RZ_CONFIG_VAR_TYPE_BOOL:
|
||||
bt->set_val = NULL;
|
||||
bt->set++;
|
||||
return true;
|
||||
case RZ_CONFIG_VAR_TYPE_INT:
|
||||
bt->set_val = (void *)5555;
|
||||
bt->set++;
|
||||
return true;
|
||||
case RZ_CONFIG_VAR_TYPE_STR:
|
||||
/* fall-thru */
|
||||
case RZ_CONFIG_VAR_TYPE_LIST:
|
||||
bt->set_val = p;
|
||||
bt->set++;
|
||||
return true;
|
||||
case RZ_CONFIG_VAR_TYPE_ITV: {
|
||||
const RzInterval *itv = p;
|
||||
RzInterval *v = (void *)bt->set_val;
|
||||
*v = *itv;
|
||||
bt->set++;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool any_opts(void *user, RzList /*<char *>*/ **options) {
|
||||
bind_test_t *bt = user;
|
||||
switch (bt->bind) {
|
||||
case RZ_CONFIG_VAR_TYPE_STR:
|
||||
*options = rz_str_split_duplist("foo,bar", ",", true);
|
||||
bt->opts++;
|
||||
return true;
|
||||
case RZ_CONFIG_VAR_TYPE_BOOL:
|
||||
/* fall-thru */
|
||||
case RZ_CONFIG_VAR_TYPE_INT:
|
||||
/* fall-thru */
|
||||
case RZ_CONFIG_VAR_TYPE_LIST:
|
||||
/* fall-thru */
|
||||
case RZ_CONFIG_VAR_TYPE_ITV:
|
||||
bt->opts++;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool test_config_binds() {
|
||||
bool ret = false;
|
||||
bind_test_t bt = { 0 };
|
||||
RzInterval itv = { 0x1000, 0x2000 };
|
||||
|
||||
RzConfig *cfg = rz_config_new(NULL);
|
||||
mu_assert_notnull(cfg, "alloc RzConfig");
|
||||
|
||||
bt.list = rz_str_split_duplist("init,fini", ",", true);
|
||||
mu_assert_notnull(bt.list, "alloc list");
|
||||
|
||||
// add binds
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_BOOL;
|
||||
ret = rz_config_add_bool_bind(cfg, "bind.bool", "is bind.bool desc", any_get, any_set, any_opts, &bt);
|
||||
mu_assert_true(ret, "added bind.bool");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_INT;
|
||||
ret = rz_config_add_integer_bind(cfg, "bind.integer", "is bind.integer desc", any_get, any_set, any_opts, &bt);
|
||||
mu_assert_true(ret, "added bind.integer");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_STR;
|
||||
ret = rz_config_add_string_bind(cfg, "bind.string", "is bind.string desc", any_get, any_set, any_opts, &bt);
|
||||
mu_assert_true(ret, "added bind.string");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_LIST;
|
||||
ret = rz_config_add_list_bind(cfg, "bind.list", "is bind.list desc", any_get, any_set, any_opts, &bt);
|
||||
mu_assert_true(ret, "added bind.list");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_ITV;
|
||||
ret = rz_config_add_interval_bind(cfg, "bind.interval", "is bind.interval desc", any_get, any_set, any_opts, &bt);
|
||||
mu_assert_true(ret, "added bind.interval");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_BOOL;
|
||||
mu_assert_true(rz_config_get_bool(cfg, "bind.bool"), "get bind.bool");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_INT;
|
||||
mu_assert_eq(rz_config_get_integer(cfg, "bind.integer"), 42, "get bind.integer");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_STR;
|
||||
mu_assert_streq(rz_config_get_string(cfg, "bind.string"), "what", "get bind.string");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_LIST;
|
||||
mu_assert_ptreq(rz_config_get_list(cfg, "bind.list"), bt.list, "get bind.list");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_ITV;
|
||||
itv = rz_config_get_interval(cfg, "bind.interval");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x2222, "bind.interval does not exist (addr = 0x2222)");
|
||||
mu_assert_eq(rz_itv_size(itv), 0x1111, "bind.interval does not exist (size = 0x1111)");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_BOOL;
|
||||
ret = rz_config_set_bool(cfg, "bind.bool", false);
|
||||
mu_assert_true(ret, "set bind.bool");
|
||||
mu_assert_null(bt.set_val, "has actually set bind.bool");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_INT;
|
||||
ret = rz_config_set_integer(cfg, "bind.integer", 5555);
|
||||
mu_assert_true(ret, "set bind.integer");
|
||||
mu_assert_ptreq(bt.set_val, (void *)5555, "has actually set bind.integer");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_STR;
|
||||
ret = rz_config_set_string(cfg, "bind.string", "foo");
|
||||
mu_assert_true(ret, "set bind.string");
|
||||
mu_assert_streq(bt.set_val, "foo", "has actually set bind.string");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_LIST;
|
||||
ret = rz_config_set_list(cfg, "bind.list", bt.list);
|
||||
mu_assert_true(ret, "set bind.list");
|
||||
mu_assert_ptreq(bt.set_val, bt.list, "has actually set bind.list");
|
||||
|
||||
bt.bind = RZ_CONFIG_VAR_TYPE_ITV;
|
||||
bt.set_val = &itv;
|
||||
ret = rz_config_set_interval2(cfg, "bind.interval", 0x80000000, 0x8fffffff);
|
||||
mu_assert_true(ret, "set bind.interval");
|
||||
mu_assert_eq(rz_itv_begin(itv), 0x80000000, "bind.interval does not exist (beg = 0x80000000)");
|
||||
mu_assert_eq(rz_itv_end(itv), 0x8fffffff, "bind.interval does not exist (end = 0x8fffffff)");
|
||||
|
||||
mu_assert_eq(bt.opts, 5, "called bind.get_options");
|
||||
mu_assert_eq(bt.get, 5, "called bind.get_value");
|
||||
mu_assert_eq(bt.set, 5, "called bind.set_value");
|
||||
|
||||
rz_config_free(cfg);
|
||||
rz_list_free(bt.list);
|
||||
mu_end;
|
||||
}
|
||||
|
||||
bool all_tests() {
|
||||
mu_run_test(test_config);
|
||||
mu_run_test(test_config_lock);
|
||||
mu_run_test(test_config_strings);
|
||||
mu_run_test(test_config_intergers);
|
||||
mu_run_test(test_config_booleans);
|
||||
mu_run_test(test_config_lists);
|
||||
mu_run_test(test_config_itv);
|
||||
mu_run_test(test_config_invalid);
|
||||
mu_run_test(test_config_binds);
|
||||
return tests_passed != tests_run;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ bool test_config_save() {
|
|||
rz_config_set(config, "somestring", "somevalue");
|
||||
rz_config_set_i(config, "someint", 42);
|
||||
rz_config_set_i(config, "somebiggerint", 0x1337);
|
||||
rz_config_lock(config, true);
|
||||
|
||||
Sdb *db = sdb_new0();
|
||||
rz_serialize_config_save(db, config);
|
||||
|
|
@ -36,15 +35,14 @@ bool test_config_load() {
|
|||
rz_config_set(config, "somestring", "someoldvalue");
|
||||
rz_config_set_i(config, "someint", 0);
|
||||
rz_config_set_i(config, "somebiggerint", 0);
|
||||
rz_config_lock(config, true);
|
||||
|
||||
Sdb *db = ref_db();
|
||||
sdb_set(db, "sneaky", "not part of config");
|
||||
bool loaded = rz_serialize_config_load(db, config, NULL, NULL);
|
||||
bool loaded = rz_serialize_config_load(db, config, NULL);
|
||||
sdb_free(db);
|
||||
mu_assert("load success", loaded);
|
||||
|
||||
mu_assert_eq(rz_list_length(config->nodes), 3, "count after load");
|
||||
mu_assert_eq(rz_vector_len(&config->sorted_vars), 3, "count after load");
|
||||
mu_assert_streq(rz_config_get(config, "somestring"), "somevalue", "loaded config string");
|
||||
mu_assert_eq_fmt(rz_config_get_i(config, "someint"), (ut64)42, "loaded config int", "%" PFMT64u);
|
||||
mu_assert_eq_fmt(rz_config_get_i(config, "somebiggerint"), (ut64)0x1337, "loaded config bigger int", "0x%" PFMT64x);
|
||||
|
|
@ -53,7 +51,7 @@ bool test_config_load() {
|
|||
}
|
||||
|
||||
bool test_config_load_exclude() {
|
||||
static const char *const exclude[] = {
|
||||
static const char *exclude[] = {
|
||||
"somestring",
|
||||
"someint",
|
||||
NULL
|
||||
|
|
@ -62,14 +60,13 @@ bool test_config_load_exclude() {
|
|||
rz_config_set(config, "somestring", "someoldvalue");
|
||||
rz_config_set_i(config, "someint", 123);
|
||||
rz_config_set_i(config, "somebiggerint", 0);
|
||||
rz_config_lock(config, true);
|
||||
|
||||
Sdb *db = ref_db();
|
||||
bool loaded = rz_serialize_config_load(db, config, exclude, NULL);
|
||||
bool loaded = rz_serialize_config_load(db, config, exclude);
|
||||
sdb_free(db);
|
||||
mu_assert("load success", loaded);
|
||||
|
||||
mu_assert_eq(rz_list_length(config->nodes), 3, "count after load");
|
||||
mu_assert_eq(rz_vector_len(&config->sorted_vars), 3, "count after load");
|
||||
mu_assert_streq(rz_config_get(config, "somestring"), "someoldvalue", "excluded config string");
|
||||
mu_assert_eq_fmt(rz_config_get_i(config, "someint"), (ut64)123, "excluded config int", "%" PFMT64u);
|
||||
mu_assert_eq_fmt(rz_config_get_i(config, "somebiggerint"), (ut64)0x1337, "loaded config bigger int", "0x%" PFMT64x);
|
||||
|
|
|
|||
Loading…
Reference in a new issue