rizin/librz/core/cmd/cmd_eval.c

475 lines
13 KiB
C

// SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <stddef.h>
#include <stdbool.h>
#include <rz_core.h>
#include "../core_private.h"
static bool load_theme(RzCore *core, const char *path) {
if (!rz_file_exists(path)) {
return false;
}
core->cmdfilter = "ec ";
bool res = rz_core_cmd_file(core, path);
if (res) {
rz_cons_pal_update_event();
}
core->cmdfilter = NULL;
return res;
}
static bool pal_seek(RzCore *core, RzConsPalSeekMode mode, const char *file, RzListIter /*<char *>*/ *iter) {
const char *fn = rz_str_lchr(file, '/');
if (!fn) {
fn = file;
}
switch (mode) {
case RZ_CONS_PAL_SEEK_PREVIOUS: {
const char *next_fn = rz_list_iter_get_next_data(iter);
if (!core->curtheme) {
return true;
}
if (next_fn && !strcmp(next_fn, core->curtheme)) {
free(core->curtheme);
core->curtheme = strdup(fn);
return false;
}
break;
}
case RZ_CONS_PAL_SEEK_NEXT: {
const char *prev_fn = rz_list_iter_get_prev_data(iter);
if (!core->curtheme) {
return true;
}
if (prev_fn && !strcmp(prev_fn, core->curtheme)) {
free(core->curtheme);
core->curtheme = strdup(fn);
return false;
}
break;
}
}
return true;
}
RZ_API bool rz_core_theme_load(RzCore *core, const char *name) {
bool failed = false;
if (RZ_STR_ISEMPTY(name)) {
return false;
}
if (!rz_str_cmp(name, "default", strlen(name))) {
core->curtheme = rz_str_dup(core->curtheme, name);
rz_cons_pal_init(core->cons->context);
return true;
}
char *home_themes = rz_path_home_prefix(RZ_THEMES);
char *system_themes = rz_path_system(RZ_THEMES);
char *extra_themes = rz_path_extra(RZ_THEMES);
char *home_file = rz_file_path_join(home_themes, name);
char *system_file = rz_file_path_join(system_themes, name);
char *extra_file = extra_themes ? rz_file_path_join(extra_themes, name) : NULL;
free(system_themes);
free(home_themes);
free(extra_themes);
if (load_theme(core, home_file)) {
goto success;
}
if (load_theme(core, system_file)) {
goto success;
}
if (load_theme(core, extra_file)) {
goto success;
}
if (load_theme(core, name)) {
goto success;
}
RZ_LOG_ERROR("core: cannot open colorscheme profile (%s)\n", name);
failed = true;
goto fail;
success:
core->curtheme = rz_str_dup(core->curtheme, name);
fail:
free(home_file);
free(system_file);
free(extra_file);
return !failed;
}
static void list_themes_in_path(HtPU *themes, const char *path) {
RzListIter *iter;
const char *fn;
RzList *files = rz_sys_dir(path);
rz_list_foreach (files, iter, fn) {
if (*fn && *fn != '.') {
ht_pu_insert(themes, fn, 1);
}
}
rz_list_free(files);
}
RZ_API char *rz_core_theme_get(RzCore *core) {
return core->curtheme;
}
static bool dict2keylist(void *user, const void *key, const ut64 value) {
RzList *list = (RzList *)user;
rz_list_append(list, strdup(key));
return true;
}
/**
* \brief Returns the list of the rizin themes.
*
* \param core The RzCore struct to use
* \return On success, an RzList pointer, otherwise NULL.
*/
RZ_API RZ_OWN RzList /*<char *>*/ *rz_core_theme_list(RZ_NONNULL RzCore *core) {
rz_return_val_if_fail(core, NULL);
HtPU *themes = ht_pu_new0();
if (!themes) {
return NULL;
}
char *path = rz_path_home_prefix(RZ_THEMES);
if (path) {
list_themes_in_path(themes, path);
RZ_FREE(path);
}
path = rz_path_system(RZ_THEMES);
if (path) {
list_themes_in_path(themes, path);
RZ_FREE(path);
}
path = rz_path_extra(RZ_THEMES);
if (path) {
list_themes_in_path(themes, path);
RZ_FREE(path);
}
RzList *list = rz_list_newf(free);
rz_list_append(list, strdup("default"));
ht_pu_foreach(themes, dict2keylist, list);
rz_list_sort(list, (RzListComparator)strcmp);
ht_pu_free(themes);
return list;
}
RZ_API void rz_core_theme_nextpal(RzCore *core, RzConsPalSeekMode mode) {
RzListIter *iter;
const char *fn;
RzList *files = rz_core_theme_list(core);
rz_list_foreach (files, iter, fn) {
if (*fn && *fn != '.') {
if (!pal_seek(core, mode, fn, iter)) {
goto done;
}
}
}
rz_list_free(files);
files = NULL;
done:
rz_core_theme_load(core, core->curtheme);
rz_list_free(files);
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_list_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode) {
if (argc == 3) {
if (!rz_cons_pal_set(argv[1], argv[2])) {
return RZ_CMD_STATUS_ERROR;
}
rz_cons_pal_update_event();
return RZ_CMD_STATUS_OK;
} else if (argc == 2) {
char color[32];
RzColor rcolor = rz_cons_pal_get(argv[1]);
rz_cons_rgb_str(color, sizeof(color), &rcolor);
eprintf("(%s)(%sCOLOR" Color_RESET ")\n", argv[1], color);
return RZ_CMD_STATUS_OK;
}
switch (mode) {
case RZ_OUTPUT_MODE_RIZIN:
rz_cons_pal_list(1, NULL);
break;
case RZ_OUTPUT_MODE_JSON:
rz_cons_pal_list('j', NULL);
break;
case RZ_OUTPUT_MODE_STANDARD:
rz_cons_pal_list(0, NULL);
break;
default:
return RZ_CMD_STATUS_ERROR;
};
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_display_palette_css_handler(RzCore *core, int argc, const char **argv) {
rz_cons_pal_list('c', argv[1]);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_set_default_palette_handler(RzCore *core, int argc, const char **argv) {
rz_cons_pal_init(core->cons->context);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_set_random_palette_handler(RzCore *core, int argc, const char **argv) {
rz_cons_pal_random();
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_set_colorful_palette_handler(RzCore *core, int argc, const char **argv) {
rz_cons_pal_show();
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_load_previous_theme_handler(RzCore *core, int argc, const char **argv) {
rz_core_theme_nextpal(core, RZ_CONS_PAL_SEEK_PREVIOUS);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_load_next_theme_handler(RzCore *core, int argc, const char **argv) {
rz_core_theme_nextpal(core, RZ_CONS_PAL_SEEK_NEXT);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_list_handler(RzCore *core, int argc, const char **argv, RzOutputMode mode) {
RzCmdStateOutput state = { 0 };
rz_cmd_state_output_init(&state, mode);
rz_core_meta_print_list_all(core, RZ_META_TYPE_HIGHLIGHT, &state);
rz_cmd_state_output_print(&state);
rz_cmd_state_output_fini(&state);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_load_theme_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
RzList *themes_list = NULL;
RzListIter *th_iter;
PJ *pj = state->d.pj;
const char *th;
if (argc == 2) {
return bool2status(rz_core_theme_load(core, argv[1]));
}
themes_list = rz_core_theme_list(core);
if (!themes_list) {
return RZ_CMD_STATUS_ERROR;
}
if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_a(pj);
}
rz_list_foreach (themes_list, th_iter, th) {
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON: {
pj_s(pj, th);
break;
}
case RZ_OUTPUT_MODE_QUIET:
rz_cons_printf("%s\n", th);
break;
default:
if (core->curtheme && !strcmp(core->curtheme, th)) {
rz_cons_printf("> %s\n", th);
} else {
rz_cons_printf(" %s\n", th);
}
}
}
if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_end(pj);
}
rz_list_free(themes_list);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_list_current_theme_handler(RzCore *core, int argc, const char **argv) {
rz_cons_println(rz_core_theme_get(core));
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_list_reload_current_handler(RzCore *core, int argc, const char **argv) {
rz_core_theme_load(core, rz_core_theme_get(core));
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_current_instruction_handler(RzCore *core, int argc, const char **argv) {
char *dup = rz_str_newf("bgonly %s", argv[1]);
char *color_code = rz_cons_pal_parse(dup, NULL);
RZ_FREE(dup);
if (!color_code) {
RZ_LOG_ERROR("core: Unknown color %s\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
rz_meta_set_string(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset, "");
const char *str = rz_meta_get_string(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset);
dup = rz_str_newf("%s \"%s\"", str ? str : "", color_code ? color_code : rz_cons_singleton()->context->pal.wordhl);
rz_meta_set_string(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset, dup);
RZ_FREE(color_code);
RZ_FREE(dup);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_instruction_word_handler(RzCore *core, int argc, const char **argv) {
char *color_code = NULL, *dup = NULL;
if (argc == 3) {
dup = rz_str_newf("bgonly %s", argv[2]);
color_code = rz_cons_pal_parse(dup, NULL);
RZ_FREE(dup);
if (!color_code) {
RZ_LOG_ERROR("core: Unknown color %s\n", argv[2]);
return RZ_CMD_STATUS_ERROR;
}
}
rz_meta_set_string(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset, "");
const char *str = rz_meta_get_string(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset);
dup = rz_str_newf("%s \"%s%s\"", str, argv[1], color_code ? color_code : rz_cons_singleton()->context->pal.wordhl);
rz_meta_set_string(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset, dup);
RZ_FREE(dup);
RZ_FREE(color_code);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_list_current_handler(RzCore *core, int argc, const char **argv) {
RzCmdStateOutput state = { 0 };
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_STANDARD);
rz_core_meta_print_list_in_function(core, RZ_META_TYPE_COMMENT, core->offset, &state);
rz_cmd_state_output_print(&state);
rz_cmd_state_output_fini(&state);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_remove_all_handler(RzCore *core, int argc, const char **argv) {
rz_meta_del(core->analysis, RZ_META_TYPE_HIGHLIGHT, 0, UT64_MAX);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_cmd_eval_color_highlight_remove_current_handler(RzCore *core, int argc, const char **argv) {
rz_meta_del(core->analysis, RZ_META_TYPE_HIGHLIGHT, core->offset, 1);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_getset_handler(RzCore *core, int argc, const char **argv) {
int i;
for (i = 1; i < argc; i++) {
RzList *l = rz_str_split_duplist_n(argv[i], "=", 1, false);
if (!l) {
return RZ_CMD_STATUS_ERROR;
}
size_t llen = rz_list_length(l);
if (!llen) {
return RZ_CMD_STATUS_ERROR;
}
char *key = rz_list_get_n(l, 0);
if (RZ_STR_ISEMPTY(key)) {
RZ_LOG_ERROR("core: No string specified before `=`. Make sure to use the format <key>=<value> without spaces.\n");
rz_list_free(l);
continue;
}
if (llen == 1 && rz_str_endswith(key, ".")) {
// no value was set, only key with ".". List possible sub-keys.
RzCmdStateOutput state = { 0 };
rz_cmd_state_output_init(&state, RZ_OUTPUT_MODE_QUIET);
rz_core_config_print_all(core->config, key, &state);
rz_cmd_state_output_print(&state);
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(core->config, 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);
} else if (llen == 2) {
char *value = rz_list_get_n(l, 1);
rz_config_set(core->config, key, value);
}
rz_list_free(l);
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_list_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
const char *arg = argc > 1 ? argv[1] : "";
rz_core_config_print_all(core->config, arg, state);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_reset_handler(RzCore *core, int argc, const char **argv) {
return rz_core_config_init(core) ? RZ_CMD_STATUS_OK : RZ_CMD_STATUS_ERROR;
}
RZ_IPI RzCmdStatus rz_eval_bool_invert_handler(RzCore *core, int argc, const char **argv) {
if (!rz_config_toggle(core->config, argv[1])) {
RZ_LOG_ERROR("core: Cannot toggle config key '%s'\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_editor_handler(RzCore *core, int argc, const char **argv) {
const char *val = rz_config_get(core->config, argv[1]);
if (!val) {
RZ_LOG_ERROR("core: Invalid config key '%s'", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
char *p = rz_core_editor(core, NULL, val);
if (!p) {
return RZ_CMD_STATUS_ERROR;
}
rz_str_replace_char(p, '\n', ';');
rz_config_set(core->config, argv[1], p);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_readonly_handler(RzCore *core, int argc, const char **argv) {
if (!rz_config_readonly(core->config, argv[1])) {
RZ_LOG_ERROR("core: Cannot make eval '%s' readonly.\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_spaces_handler(RzCore *core, int argc, const char **argv) {
const char *arg = argc > 1 ? argv[1] : NULL;
RzList *list = rz_core_config_in_space(core, arg);
if (!list) {
return RZ_CMD_STATUS_ERROR;
}
RzListIter *iter;
char *name;
rz_list_foreach (list, iter, name) {
rz_cons_println(name);
}
rz_list_free(list);
return RZ_CMD_STATUS_OK;
}
RZ_IPI RzCmdStatus rz_eval_type_handler(RzCore *core, int argc, const char **argv) {
RzConfigNode *node = rz_config_node_get(core->config, argv[1]);
if (!node) {
RZ_LOG_ERROR("core: Cannot find eval '%s'.\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
const char *type = rz_config_node_type(node);
if (!type) {
RZ_LOG_ERROR("core: Cannot find type of eval '%s'.\n", argv[1]);
return RZ_CMD_STATUS_ERROR;
}
rz_cons_println(type);
return RZ_CMD_STATUS_OK;
}