Rewrite RSpaces to use RBTree and remove use of indices everywhere (#12904)

* Rewrite RSpaces to use RBTree and remove use of indixes everywhere
* Use RSpace in r_meta_space_unset_for
* Use r_str_ndup instead of strndup because windows does not support it
* Add some comments
This commit is contained in:
Riccardo Schirone 2019-01-28 16:41:42 +01:00 committed by GitHub
parent a8f5b045c4
commit 54d5cc3ae0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 451 additions and 361 deletions

View File

@ -25,34 +25,40 @@ R_API void r_anal_unset_limits(RAnal *anal) {
R_FREE (anal->limit);
}
static void meta_unset_for(void *user, int idx) {
RSpaces *s = (RSpaces*)user;
RAnal *anal = (RAnal*)s->user;
r_meta_space_unset_for (anal, idx);
static void meta_unset_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RAnal *anal = container_of (s, RAnal, meta_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
r_meta_space_unset_for (anal, se->data.unset.space);
}
static int meta_count_for(void *user, int idx) {
RSpaces *s = (RSpaces*)user;
RAnal *anal = (RAnal*)s->user;
return r_meta_space_count_for (anal, idx);
static void meta_count_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RAnal *anal = container_of (s, RAnal, meta_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
se->res = r_meta_space_count_for (anal, se->data.count.space);
}
static void zign_unset_for(void *user, int idx) {
RSpaces *s = (RSpaces*)user;
RAnal *anal = (RAnal*)s->user;
r_sign_space_unset_for (anal, idx);
static void zign_unset_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RAnal *anal = container_of (s, RAnal, zign_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
r_sign_space_unset_for (anal, se->data.unset.space);
}
static int zign_count_for(void *user, int idx) {
RSpaces *s = (RSpaces*)user;
RAnal *anal = (RAnal*)s->user;
return r_sign_space_count_for (anal, idx);
static void zign_count_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RAnal *anal = container_of (s, RAnal, zign_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
se->res = r_sign_space_count_for (anal, se->data.count.space);
}
static void zign_rename_for(void *user, int idx, const char *oname, const char *nname) {
RSpaces *s = (RSpaces*)user;
RAnal *anal = (RAnal*)s->user;
r_sign_space_rename_for (anal, idx, oname, nname);
static void zign_rename_for(REvent *ev, int type, void *user, void *data) {
RSpaces *s = (RSpaces *)user;
RAnal *anal = container_of (s, RAnal, zign_spaces);
RSpaceEvent *se = (RSpaceEvent *)data;
r_sign_space_rename_for (anal, se->data.rename.space,
se->data.rename.oldname, se->data.rename.newname);
}
//not used
@ -160,8 +166,14 @@ R_API RAnal *r_anal_new() {
anal->cpp_abi = R_ANAL_CPP_ABI_ITANIUM;
anal->opt.depth = 32;
anal->opt.noncode = false; // do not analyze data by default
r_space_new (&anal->meta_spaces, "CS", meta_unset_for, meta_count_for, NULL, anal);
r_space_new (&anal->zign_spaces, "zs", zign_unset_for, zign_count_for, zign_rename_for, anal);
r_spaces_init (&anal->meta_spaces, "CS");
r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_UNSET, meta_unset_for);
r_event_hook (anal->meta_spaces.event, R_SPACE_EVENT_COUNT, meta_count_for);
r_spaces_init (&anal->zign_spaces, "zs");
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_UNSET, zign_unset_for);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_COUNT, zign_count_for);
r_event_hook (anal->zign_spaces.event, R_SPACE_EVENT_RENAME, zign_rename_for);
anal->sdb_fcns = sdb_ns (anal->sdb, "fcns", 1);
anal->sdb_meta = sdb_ns (anal->sdb, "meta", 1);
anal->sdb_hints = sdb_ns (anal->sdb, "hints", 1);
@ -217,8 +229,8 @@ R_API RAnal *r_anal_free(RAnal *a) {
r_list_free (a->plugins);
a->fcns->free = r_anal_fcn_free;
r_list_free (a->fcns);
r_space_free (&a->meta_spaces);
r_space_free (&a->zign_spaces);
r_spaces_fini (&a->meta_spaces);
r_spaces_fini (&a->zign_spaces);
r_anal_pin_fini (a);
r_list_free (a->refs);
r_syscall_free (a->syscall);

View File

@ -111,7 +111,7 @@ R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) {
char key[100], val[2048], *e_str;
int ret;
ut64 size;
int space_idx = a->meta_spaces.space_idx;
const char *space = r_spaces_current_name (&a->meta_spaces);
meta_type_add (a, type, addr);
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, addr);
@ -129,7 +129,7 @@ R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) {
free (msg);
}
e_str = sdb_encode ((const void*)s, -1);
snprintf (val, sizeof (val)-1, "%d,%d,%s", (int)size, space_idx, e_str);
snprintf (val, sizeof (val)-1, "%d,%s,%s", (int)size, space, e_str);
sdb_set (DB, key, val, 0);
free ((void*)e_str);
@ -148,7 +148,7 @@ R_API int r_meta_set_var_comment(RAnal *a, int type, ut64 idx, ut64 addr, const
char key[100], val[2048], *e_str;
int ret;
ut64 size;
int space_idx = a->meta_spaces.space_idx;
const char *space = r_spaces_current_name (&a->meta_spaces);
meta_type_add (a, type, addr);
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x".0x%"PFMT64x, type, addr, idx);
@ -161,7 +161,7 @@ R_API int r_meta_set_var_comment(RAnal *a, int type, ut64 idx, ut64 addr, const
ret = false;
}
e_str = sdb_encode ((const void*)s, -1);
snprintf (val, sizeof (val)-1, "%d,%d,%s", (int)size, space_idx, e_str);
snprintf (val, sizeof (val)-1, "%d,%s,%s", (int)size, space, e_str);
sdb_set (DB, key, val, 0);
free ((void*)e_str);
return ret;
@ -308,8 +308,13 @@ R_API int r_meta_cleanup(RAnal *a, ut64 from, ut64 to) {
return r_meta_del (a, R_META_TYPE_ANY, from, (to-from));
}
static void r_meta_item_fini(RAnalMetaItem *item) {
free (item->str);
}
R_API void r_meta_item_free(void *_item) {
RAnalMetaItem *item = _item;
r_meta_item_fini (item);
free (item);
}
@ -323,24 +328,25 @@ R_API RAnalMetaItem *r_meta_item_new(int type) {
static void meta_serialize(RAnalMetaItem *it, char *k, size_t k_size, char *v, size_t v_size) {
snprintf (k, k_size, "meta.%c.0x%" PFMT64x, it->type, it->from);
const char *name = it->space? it->space->name: "*";
if (it->subtype) {
snprintf (v, v_size, "%d,%d,%c,%s", (int)it->size, it->space, it->subtype, it->str);
snprintf (v, v_size, "%d,%s,%c,%s", (int)it->size, name, it->subtype, it->str);
} else {
snprintf (v, v_size, "%d,%d,%s", (int)it->size, it->space, it->str);
snprintf (v, v_size, "%d,%s,%s", (int)it->size, name, it->str);
}
}
static bool meta_deserialize(RAnalMetaItem *it, const char *k, const char *v) {
static bool meta_deserialize(RAnal *a, RAnalMetaItem *it, const char *k, const char *v) {
if (strlen (k) < 8) {
return false;
}
if (memcmp (k + 6, ".0x", 3)) {
return false;
}
return r_meta_deserialize_val (it, k[5], sdb_atoi (k + 7), v);
return r_meta_deserialize_val (a, it, k[5], sdb_atoi (k + 7), v);
}
R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const char *v) {
R_API bool r_meta_deserialize_val(RAnal *a, RAnalMetaItem *it, int type, ut64 from, const char *v) {
const char *v2;
char *v3;
it->type = type;
@ -352,7 +358,13 @@ R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const
if (!v2) {
return false;
}
it->space = atoi (v2 + 1);
v3 = strchr (v2 + 1, ',');
if (!v3) {
return false;
}
char *tmp = r_str_ndup (v2 + 1, v3 - v2 - 1);
it->space = r_spaces_add (&a->meta_spaces, tmp);
free (tmp);
it->str = strchr (v2 + 1, ',');
if (it->str) {
if (it->type == R_META_TYPE_STRING) {
@ -368,7 +380,7 @@ R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const
}
static int meta_add(RAnal *a, int type, int subtype, ut64 from, ut64 to, const char *str) {
int space_idx = a->meta_spaces.space_idx;
const RSpace *space = r_spaces_current (&a->meta_spaces);
char key[100], val[2048];
if (from > to) {
return false;
@ -381,7 +393,7 @@ static int meta_add(RAnal *a, int type, int subtype, ut64 from, ut64 to, const c
}
/* set entry */
char *e_str = sdb_encode ((const void*)str, -1);
RAnalMetaItem mi = {from, to, (int)(to - from), type, subtype, e_str, space_idx};
RAnalMetaItem mi = {from, to, (int)(to - from), type, subtype, e_str, space};
meta_serialize (&mi, key, sizeof (key), val, sizeof (val));
bool exists = sdb_exists (DB, key);
@ -447,7 +459,7 @@ static RAnalMetaItem *r_meta_find_(RAnal *a, ut64 at, int type, int where, int e
snprintf (key, sizeof (key), "meta.%c.0x%" PFMT64x, *infos, at);
metas = sdb_const_get (s, key, 0);
if (metas) {
if (!r_meta_deserialize_val (&mi, *infos, at, metas)) {
if (!r_meta_deserialize_val (a, &mi, *infos, at, metas)) {
continue;
}
return &mi;
@ -508,11 +520,9 @@ R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full) {
char *pstr, *str, *base64_str;
RCore *core = a->coreb.core;
bool esc_bslash = core ? core->print->esc_bslash : false;
//eprintf ("%d %d\n", d->space, a->meta_spaces.space_idx);
if (a->meta_spaces.space_idx != -1) {
if (a->meta_spaces.space_idx != d->space) {
return;
}
if (r_spaces_current (&a->meta_spaces) &&
r_spaces_current (&a->meta_spaces) != d->space) {
return;
}
if (d->type == 's') {
if (d->subtype == R_STRING_ENC_UTF8) {
@ -716,7 +726,7 @@ R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full) {
static int meta_print_item(void *user, const char *k, const char *v) {
RAnalMetaUserItem *ui = user;
RAnalMetaItem it;
if (!meta_deserialize (&it, k, v)) {
if (!meta_deserialize (ui->anal, &it, k, v)) {
return 1;
}
if (ui->fcn && !r_anal_fcn_in (ui->fcn, it.from)) {
@ -815,7 +825,7 @@ static int meta_enumerate_cb(void *user, const char *k, const char *v) {
if (!it) {
return 0;
}
if (!meta_deserialize (it, k, v)) {
if (!meta_deserialize (ui->anal, it, k, v)) {
free (it);
goto beach;
}
@ -842,23 +852,24 @@ static int meta_unset_cb(void *user, const char *k, const char *v) {
if (!strstr (k, ".0x")) {
return 1;
}
meta_deserialize (&it, k, v);
if (it.space != -1) {
it.space = -1;
meta_deserialize (ui->anal, &it, k, v);
if (it.space && it.space == ui->user) {
it.space = NULL;
meta_serialize (&it, nk, sizeof (nk), nv, sizeof (nv));
sdb_set (DB, nk, nv, 0);
}
return 1;
}
R_API void r_meta_space_unset_for(RAnal *a, int type) {
r_meta_list_cb (a, type, 0, meta_unset_cb, NULL, UT64_MAX);
R_API void r_meta_space_unset_for(RAnal *a, const RSpace *space) {
RAnalMetaUserItem ui = { .anal = a, .user = (void *)space };
r_meta_list_cb (a, R_META_TYPE_ANY, 0, meta_unset_cb, &ui, UT64_MAX);
}
typedef struct {
int count;
int index;
int ctx;
const RSpace *ctx;
} myMetaUser;
static int meta_count_cb(void *user, const char *k, const char *v) {
@ -868,17 +879,16 @@ static int meta_count_cb(void *user, const char *k, const char *v) {
if (!strstr (k, ".0x")) {
return 1;
}
meta_deserialize (&it, k, v);
if (mu) {
if (it.space == mu->ctx) {
mu->count++;
}
meta_deserialize (ui->anal, &it, k, v);
if (mu && it.space == mu->ctx) {
mu->count++;
}
r_meta_item_fini (&it);
return 1;
}
R_API int r_meta_space_count_for(RAnal *a, int space_idx) {
myMetaUser mu = {.ctx = space_idx};
R_API int r_meta_space_count_for(RAnal *a, const RSpace *space) {
myMetaUser mu = { .ctx = space };
r_meta_list_cb (a, R_META_TYPE_ANY, 0, meta_count_cb, &mu, UT64_MAX);
return mu.count;
}

View File

@ -113,7 +113,7 @@ static bool deserialize(RAnal *a, RSignItem *it, const char *k, const char *v) {
}
// space (1)
it->space = r_space_add (&a->zign_spaces, r_str_word_get0 (k2, 1));
it->space = r_spaces_add (&a->zign_spaces, r_str_word_get0 (k2, 1));
// name (2)
it->name = r_str_new (r_str_word_get0 (k2, 2));
@ -210,13 +210,14 @@ out:
free (k2);
free (v2);
free (refs);
free (vars);
return retval;
}
static void serializeKey(RAnal *a, int space, const char* name, char *k) {
static void serializeKey(RAnal *a, const RSpace *space, const char* name, char *k) {
snprintf (k, R_SIGN_KEY_MAXSZ, "zign|%s|%s",
space >= 0? a->zign_spaces.spaces[space]: "*", name);
space? space->name: "*", name);
}
static void serializeKeySpaceStr(RAnal *a, const char *space, const char* name, char *k) {
@ -464,7 +465,7 @@ static bool addBytes(RAnal *a, const char *name, ut64 size, const ut8 *bytes, co
free (it);
return false;
}
it->space = a->zign_spaces.space_idx;
it->space = r_spaces_current (&a->zign_spaces);
it->bytes = R_NEW0 (RSignBytes);
if (!it->bytes) {
goto fail;
@ -550,7 +551,7 @@ R_API bool r_sign_add_graph(RAnal *a, const char *name, RSignGraph graph) {
free (it);
return false;
}
it->space = a->zign_spaces.space_idx;
it->space = r_spaces_current (&a->zign_spaces);
it->graph = R_NEW0 (RSignGraph);
if (!it->graph) {
free (it->name);
@ -572,7 +573,7 @@ R_API bool r_sign_add_addr(RAnal *a, const char *name, ut64 addr) {
return NULL;
}
it->name = r_str_new (name);
it->space = a->zign_spaces.space_idx;
it->space = r_spaces_current (&a->zign_spaces);
it->addr = addr;
bool retval = addItem (a, it);
@ -597,7 +598,7 @@ R_API bool r_sign_add_vars(RAnal *a, const char *name, RList *vars) {
r_sign_item_free (it);
return false;
}
it->space = a->zign_spaces.space_idx;
it->space = r_spaces_current (&a->zign_spaces);
it->vars = r_list_newf ((RListFree) free);
r_list_foreach (vars, iter, var) {
r_list_append (it->vars, strdup (var));
@ -622,7 +623,7 @@ R_API bool r_sign_add_refs(RAnal *a, const char *name, RList *refs) {
free (it);
return false;
}
it->space = a->zign_spaces.space_idx;
it->space = r_spaces_current (&a->zign_spaces);
it->refs = r_list_newf ((RListFree) free);
r_list_foreach (refs, iter, ref) {
r_list_append (it->refs, strdup (ref));
@ -657,17 +658,17 @@ R_API bool r_sign_delete(RAnal *a, const char *name) {
}
// Remove all zigns
if (*name == '*') {
if (a->zign_spaces.space_idx == -1) {
if (!r_spaces_current (&a->zign_spaces)) {
sdb_reset (a->sdb_zigns);
return true;
}
ctx.anal = a;
serializeKey (a, a->zign_spaces.space_idx, "", ctx.buf);
serializeKey (a, r_spaces_current (&a->zign_spaces), "", ctx.buf);
sdb_foreach (a->sdb_zigns, deleteBySpaceCB, &ctx);
return true;
}
// Remove specific zign
serializeKey (a, a->zign_spaces.space_idx, name, k);
serializeKey (a, r_spaces_current (&a->zign_spaces), name, k);
return sdb_remove (a->sdb_zigns, k, 0);
}
@ -843,7 +844,8 @@ static int listCB(void *user, const char *k, const char *v) {
goto out;
}
if (a->zign_spaces.space_idx != it->space && a->zign_spaces.space_idx != -1) {
RSpace *cur = r_spaces_current (&a->zign_spaces);
if (cur != it->space && cur) {
goto out;
}
@ -857,19 +859,19 @@ static int listCB(void *user, const char *k, const char *v) {
// Zignspace and name (except for radare format)
if (ctx->format == '*') {
if (it->space >= 0) {
a->cb_printf ("zs %s\n", a->zign_spaces.spaces[it->space]);
if (it->space) {
a->cb_printf ("zs %s\n", it->space->name);
} else {
a->cb_printf ("zs *\n");
}
} else if (ctx->format == 'j') {
if (it->space >= 0) {
a->cb_printf ("{\"zignspace\":\"%s\",", a->zign_spaces.spaces[it->space]);
if (it->space) {
a->cb_printf ("{\"zignspace\":\"%s\",", it->space->name);
}
a->cb_printf ("\"name\":\"%s\",", it->name);
} else {
if (a->zign_spaces.space_idx == -1 && it->space >= 0) {
a->cb_printf ("(%s) ", a->zign_spaces.spaces[it->space]);
if (!r_spaces_current (&a->zign_spaces) && it->space) {
a->cb_printf ("(%s) ", it->space->name);
}
a->cb_printf ("%s:\n", it->name);
}
@ -1006,7 +1008,7 @@ beach:
struct ctxCountForCB {
RAnal *anal;
int idx;
const RSpace *space;
int count;
};
@ -1019,7 +1021,7 @@ static int countForCB(void *user, const char *k, const char *v) {
goto out;
}
if (it->space == ctx->idx) {
if (it->space == ctx->space) {
ctx->count++;
}
@ -1029,8 +1031,8 @@ out:
return 1;
}
R_API int r_sign_space_count_for(RAnal *a, int idx) {
struct ctxCountForCB ctx = { a, idx, 0 };
R_API int r_sign_space_count_for(RAnal *a, const RSpace *space) {
struct ctxCountForCB ctx = { a, space, 0 };
if (!a) {
return 0;
@ -1043,7 +1045,7 @@ R_API int r_sign_space_count_for(RAnal *a, int idx) {
struct ctxUnsetForCB {
RAnal *anal;
int idx;
const RSpace *space;
};
static int unsetForCB(void *user, const char *k, const char *v) {
@ -1058,12 +1060,12 @@ static int unsetForCB(void *user, const char *k, const char *v) {
goto out;
}
if (it->space != ctx->idx) {
if (it->space != ctx->space) {
goto out;
}
if (it->space != -1) {
it->space = -1;
if (it->space) {
it->space = NULL;
serialize (a, it, nk, nv);
sdb_remove (db, k, 0);
sdb_set (db, nk, nv, 0);
@ -1075,8 +1077,8 @@ out:
return 1;
}
R_API void r_sign_space_unset_for(RAnal *a, int idx) {
struct ctxUnsetForCB ctx = { a, idx };
R_API void r_sign_space_unset_for(RAnal *a, const RSpace *space) {
struct ctxUnsetForCB ctx = { a, space };
if (!a) {
return;
@ -1108,7 +1110,7 @@ static int renameForCB(void *user, const char *k, const char *v) {
return 1;
}
R_API void r_sign_space_rename_for(RAnal *a, int idx, const char *oname, const char *nname) {
R_API void r_sign_space_rename_for(RAnal *a, const RSpace *space, const char *oname, const char *nname) {
struct ctxRenameForCB ctx;
if (!a || !oname || !nname) {
@ -1139,7 +1141,8 @@ static int foreachCB(void *user, const char *k, const char *v) {
goto out;
}
if (a->zign_spaces.space_idx != it->space && a->zign_spaces.space_idx != -1) {
RSpace *cur = r_spaces_current (&a->zign_spaces);
if (cur != it->space && cur) {
goto out;
}
@ -1486,7 +1489,7 @@ R_API RSignItem *r_sign_item_new() {
RSignItem *ret = R_NEW0 (RSignItem);
if (ret) {
ret->addr = UT64_MAX;
ret->space = -1;
ret->space = NULL;
}
return ret;
}

View File

@ -1885,7 +1885,7 @@ static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const ch
const char *lang = bin_demangle ? r_config_get (r->config, "bin.lang") : NULL;
RList *symbols = r_bin_get_symbols (r->bin);
r_space_set (&r->anal->meta_spaces, "bin");
r_spaces_push (&r->anal->meta_spaces, "bin");
if (IS_MODE_JSON (mode) && !printHere) {
r_cons_printf ("[");
@ -2146,7 +2146,7 @@ static int bin_symbols(RCore *r, int mode, ut64 laddr, int va, ut64 at, const ch
r_cons_printf ("]");
}
r_space_set (&r->anal->meta_spaces, NULL);
r_spaces_pop (&r->anal->meta_spaces);
return true;
}

View File

@ -686,7 +686,7 @@ static int cmd_meta_others(RCore *core, const char *input) {
if (!val) {
break;
}
if (!r_meta_deserialize_val (&mi, type, addr, val)) {
if (!r_meta_deserialize_val (core->anal, &mi, type, addr, val)) {
break;
}
if (!mi.str) {
@ -1070,11 +1070,11 @@ static int cmd_meta(void *data, const char *input) {
r_core_cmd_help (core, help_msg_CS);
break;
case '+': // "CS+"
r_space_push (ms, input + 2);
r_spaces_push (ms, input + 2);
break;
case 'r': // "CSr"
if (input[2] == ' ') {
r_space_rename (ms, NULL, input+2);
r_spaces_rename (ms, NULL, input+2);
} else {
eprintf ("Usage: CSr [newname]\n");
}
@ -1082,44 +1082,32 @@ static int cmd_meta(void *data, const char *input) {
case '-': // "CS-"
if (input[2]) {
if (input[2]=='*') {
r_space_unset (ms, NULL);
r_spaces_unset (ms, NULL);
} else {
r_space_unset (ms, input+2);
r_spaces_unset (ms, input+2);
}
} else {
r_space_pop (ms);
r_spaces_pop (ms);
}
break;
case 'j': // "CSj"
case '\0': // "CS"
case '*': // "CS*"
r_space_list (ms, input[1]);
spaces_list (ms, input[1]);
break;
case ' ': // "CS "
r_space_set (ms, input + 2);
r_spaces_set (ms, input + 2);
break;
#if 0
case 'm':
{ RFlagItem *f;
ut64 off = core->offset;
if (input[2] == ' ')
off = r_num_math (core->num, input+2);
f = r_flag_get_i (core->flags, off);
if (f) {
f->space = core->flags->space_idx;
} else eprintf ("Cannot find any flag at 0x%"PFMT64x".\n", off);
default: {
RSpace *s;
RBIter it;
const RSpace *cur = r_spaces_current (ms);
r_rbtree_foreach (ms->spaces, it, s, RSpace, rb) {
r_cons_printf ("%c %s\n", (s == cur)? '*': ' ',
s->name);
}
break;
#endif
default: {
int i, j = 0;
for (i = 0; i < R_FLAG_SPACES_MAX; i++) {
if (!ms->spaces[i]) continue;
r_cons_printf ("%02d %c %s\n", j++,
(i == ms->space_idx)?'*':' ',
ms->spaces[i]);
}
} break;
}
}
break;
}

View File

@ -6,6 +6,7 @@
#include <r_list.h>
#include <r_cons.h>
#include <r_util.h>
#include "i/private.h"
static const char *help_msg_z[] = {
"Usage:", "z[*j-aof/cs] [args] ", "# Manage zignatures",
@ -148,13 +149,13 @@ static bool addFcnVars(RCore *core, RAnalFunction *fcn, const char *name) {
static void addFcnZign(RCore *core, RAnalFunction *fcn, const char *name) {
char *zigname = NULL;
int curspace = core->anal->zign_spaces.space_idx;
const RSpace *curspace = r_spaces_current (&core->anal->zign_spaces);
if (name) {
zigname = r_str_new (name);
} else {
if (curspace != -1) {
zigname = r_str_newf ("%s.", core->anal->zign_spaces.spaces[curspace]);
if (curspace) {
zigname = r_str_newf ("%s.", curspace->name);
}
zigname = r_str_appendf (zigname, "%s", fcn->name);
}
@ -508,35 +509,35 @@ static int cmdSpace(void *data, const char *input) {
eprintf ("usage: zs+zignspace\n");
return false;
}
r_space_push (zs, input + 1);
r_spaces_push (zs, input + 1);
break;
case 'r':
if (input[1] != ' ' || !input[2]) {
eprintf ("usage: zsr newname\n");
return false;
}
r_space_rename (zs, NULL, input + 2);
r_spaces_rename (zs, NULL, input + 2);
break;
case '-':
if (input[1] == '\x00') {
r_space_pop (zs);
r_spaces_pop (zs);
} else if (input[1] == '*') {
r_space_unset (zs, NULL);
r_spaces_unset (zs, NULL);
} else {
r_space_unset (zs, input + 1);
r_spaces_unset (zs, input + 1);
}
break;
case 'j':
case '*':
case '\0':
r_space_list (zs, input[0]);
spaces_list (zs, input[0]);
break;
case ' ':
if (!input[1]) {
eprintf ("usage: zs zignspace\n");
return false;
}
r_space_set (zs, input + 1);
r_spaces_set (zs, input + 1);
break;
case '?':
r_core_cmd_help (core, help_msg_zs);

View File

@ -7,6 +7,7 @@
#if __UNIX__
#include <signal.h>
#endif
#include "i/private.h"
#define DB core->sdb
@ -1170,20 +1171,22 @@ static void autocomplete_zignatures(RLine* line, const char* msg) {
return;
}
int length = strlen (msg);
RSpaces zs = core->anal->zign_spaces;
int j, i = 0;
for (j = 0; j < R_SPACES_MAX; j++) {
if (zs.spaces[j]) {
if (i == TMP_ARGV_SZ - 1) {
break;
}
if (!strncmp (msg, zs.spaces[j], length)) {
if (i + 1 < TMP_ARGV_SZ) {
tmp_argv[i++] = zs.spaces[j];
}
RSpaces *zs = &core->anal->zign_spaces;
RSpace *s;
RBIter it;
int i = 0;
r_rbtree_foreach (zs->spaces, it, s, RSpace, rb) {
if (i == TMP_ARGV_SZ - 1) {
break;
}
if (!strncmp (msg, s->name, length)) {
if (i + 1 < TMP_ARGV_SZ) {
tmp_argv[i++] = s->name;
}
}
}
if (strlen (msg) == 0 && i + 1 < TMP_ARGV_SZ) {
tmp_argv[i++] = "*";
}
@ -2205,7 +2208,38 @@ static char *get_comments_cb(void *user, ut64 addr) {
return r_core_anal_get_comments ((RCore *)user, addr);
}
static void cb_event_handler(REvent *ev, REventType event_type, void *data) {
R_IPI void spaces_list(RSpaces *sp, int mode) {
RBIter it;
RSpace *s;
bool first = true;
const RSpace *cur = r_spaces_current (sp);
if (mode == 'j') {
r_cons_printf ("[");
}
r_rbtree_foreach (sp->spaces, it, s, RSpace, rb) {
int count = r_spaces_count (sp, s->name);
if (mode == 'j') {
r_cons_printf ("%s{\"name\":\"%s\"%s,\"count\":%d}",
!first? ",": "", s->name,
cur == s? ",\"selected\":true": "",
count);
} else if (mode == '*') {
r_cons_printf ("%s %s\n", sp->name, s->name);
} else {
r_cons_printf ("%d %c %s\n", count, cur == s? '*': '.',
s->name);
}
first = false;
}
if (mode == '*' && r_spaces_current (sp)) {
r_cons_printf ("%s %s # current\n", sp->name, r_spaces_current_name (sp));
}
if (mode == 'j') {
r_cons_printf ("]\n");
}
}
static void cb_event_handler(REvent *ev, int event_type, void *user, void *data) {
RCore *core = (RCore *)ev->user;
if (!core->log_events) {
return;
@ -2362,7 +2396,6 @@ R_API bool r_core_init(RCore *core) {
core->anal->ev = core->ev;
core->anal->log = r_core_anal_log;
core->anal->read_at = r_core_anal_read_at;
core->anal->meta_spaces.cb_printf = r_cons_printf;
core->anal->cb.on_fcn_new = on_fcn_new;
core->anal->cb.on_fcn_delete = on_fcn_delete;
core->anal->cb.on_fcn_rename = on_fcn_rename;

View File

@ -2693,7 +2693,7 @@ static int ds_print_meta_infos(RDisasmState *ds, ut8* buf, int len, int idx) {
if (!metas) {
continue;
}
if (!r_meta_deserialize_val (mi, *infos, ds->at, metas)) {
if (!r_meta_deserialize_val (core->anal, mi, *infos, ds->at, metas)) {
continue;
}
// TODO: implement ranged meta find (if not at the begging of function..

10
libr/core/i/private.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef R_CORE_PRIVATE_H_
#define R_CORE_PRIVATE_H_
#include <r_core.h>
#include <r_util.h>
#include <r_types.h>
R_IPI void spaces_list(RSpaces *sp, int mode);
#endif

View File

@ -1817,14 +1817,14 @@ R_API int r_core_visual_trackflags(RCore *core) {
}
return true;
}
static bool meta_deserialize(RAnalMetaItem *it, const char *k, const char *v) {
static bool meta_deserialize(RAnal *a, RAnalMetaItem *it, const char *k, const char *v) {
if (strlen (k) < 8) {
return false;
}
if (memcmp (k + 6, ".0x", 3)) {
return false;
}
return r_meta_deserialize_val (it, k[5], sdb_atoi (k + 7), v);
return r_meta_deserialize_val (a, it, k[5], sdb_atoi (k + 7), v);
}
static int meta_enumerate_cb(void *user, const char *k, const char *v) {
@ -1834,7 +1834,7 @@ static int meta_enumerate_cb(void *user, const char *k, const char *v) {
if (!it) {
return 0;
}
if (!meta_deserialize (it, k, v)) {
if (!meta_deserialize (ui->anal, it, k, v)) {
free (it);
goto beach;
}

View File

@ -47,7 +47,7 @@ typedef struct r_anal_meta_item_t {
int type;
int subtype;
char *str;
int space;
const RSpace *space;
} RAnalMetaItem;
typedef struct {
@ -1612,8 +1612,8 @@ R_API void r_anal_data_free (RAnalData *d);
R_API char *r_anal_data_to_string(RAnalData *d, RConsPrintablePalette *pal);
R_API void r_meta_free(RAnal *m);
R_API void r_meta_space_unset_for(RAnal *a, int type);
R_API int r_meta_space_count_for(RAnal *a, int space_idx);
R_API void r_meta_space_unset_for(RAnal *a, const RSpace *space);
R_API int r_meta_space_count_for(RAnal *a, const RSpace *space_name);
R_API RList *r_meta_enumerate(RAnal *a, int type);
R_API int r_meta_count(RAnal *m, int type, ut64 from, ut64 to);
R_API char *r_meta_get_string(RAnal *m, int type, ut64 addr);
@ -1636,7 +1636,7 @@ R_API int r_meta_list_cb(RAnal *m, int type, int rad, SdbForeachCallback cb, voi
R_API void r_meta_list_offset(RAnal *m, ut64 addr, char input);
R_API void r_meta_item_free(void *_item);
R_API RAnalMetaItem *r_meta_item_new(int type);
R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const char *v);
R_API bool r_meta_deserialize_val(RAnal *a, RAnalMetaItem *it, int type, ut64 from, const char *v);
R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full);
/* hints */
@ -1733,9 +1733,9 @@ R_API int r_anal_noreturn_drop(RAnal *anal, const char *expr);
R_API bool r_anal_noreturn_at_addr(RAnal *anal, ut64 addr);
/* zign spaces */
R_API int r_sign_space_count_for(RAnal *a, int idx);
R_API void r_sign_space_unset_for(RAnal *a, int idx);
R_API void r_sign_space_rename_for(RAnal *a, int idx, const char *oname, const char *nname);
R_API int r_sign_space_count_for(RAnal *a, const RSpace *space);
R_API void r_sign_space_unset_for(RAnal *a, const RSpace *space);
R_API void r_sign_space_rename_for(RAnal *a, const RSpace *space, const char *oname, const char *nname);
/* vtables */
typedef struct {

View File

@ -47,7 +47,7 @@ typedef struct r_sign_hash_t {
typedef struct r_sign_item_t {
char *name;
int space;
const RSpace *space;
RSignBytes *bytes;
RSignGraph *graph;

View File

@ -29,13 +29,13 @@ typedef struct r_event_meta_t {
const char *string;
} REventMeta;
typedef void (*REventCallback)(REvent *ev, REventType type, void *data);
typedef void (*REventCallback)(REvent *ev, int type, void *user, void *data);
R_API REvent *r_event_new(void *user);
R_API void r_event_free(REvent *ev);
R_API void r_event_hook(REvent *ev, REventType type, REventCallback cb);
R_API void r_event_unhook(REvent *ev, REventType type, REventCallback cb);
R_API void r_event_send(REvent *ev, REventType type, void *data);
R_API void r_event_hook(REvent *ev, int type, REventCallback cb);
R_API void r_event_unhook(REvent *ev, int type, REventCallback cb);
R_API void r_event_send(REvent *ev, int type, void *data);
#ifdef __cplusplus
}

View File

@ -3,33 +3,94 @@
#define R_SPACES_MAX 512
#include "r_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* RSpaces represents a set of Spaces.
* A Space is used to group similar objects and it can have a name. Name
* "*"/""/NULL is reserved to indicate "all spaces".
*
* You can have groups of "meta" (e.g. bin meta, format meta, etc.), groups of
* zign info, groups of flags, etc.
*
* It is possible to hook into the RSpaces functions by using REvent.
* R_SPACE_EVENT_COUNT: called when you need to count how many elements there are in a given RSpace
* R_SPACE_EVENT_RENAME: called when renaming a RSpace with an oldname to a newname
* R_SPACE_EVENT_UNSET: called when deleting a RSpace with a given name
*/
typedef struct r_space_t {
char *name;
int space_idx;
char *spaces[R_SPACES_MAX];
RBNode rb;
} RSpace;
typedef enum {
R_SPACE_EVENT_COUNT = 1,
R_SPACE_EVENT_RENAME,
R_SPACE_EVENT_UNSET,
} RSpaceEventType;
typedef struct r_space_event_t {
union {
struct {
const RSpace *space;
} count;
struct {
const RSpace *space;
} unset;
struct {
const RSpace *space;
const char *oldname;
const char *newname;
} rename;
} data;
int res;
} RSpaceEvent;
typedef struct r_spaces_t {
const char *name;
RSpace *current;
RBTree spaces;
RList *spacestack;
PrintfCallback cb_printf;
void (*unset_for)(void *user, int idx);
int (*count_for)(void *user, int idx);
void (*rename_for)(void *user, int idx, const char *oname, const char *nname);
void *user;
REvent *event;
} RSpaces;
R_API void r_space_new(RSpaces *s, const char *name, void (*unset_for)(void*,int), int (*count_for)(void*,int), void (*rename_for)(void*,int,const char*,const char*), void *user);
R_API void r_space_free(RSpaces *s);
R_API int r_space_get(RSpaces *s, const char *name);
R_API const char *r_space_get_i(RSpaces *s, int idx);
R_API int r_space_add(RSpaces *s, const char *name);
R_API bool r_space_push(RSpaces *s, const char *name);
R_API bool r_space_pop(RSpaces *s);
R_API int r_space_set(RSpaces *s, const char *name);
R_API int r_space_unset (RSpaces *s, const char *name);
R_API int r_space_list(RSpaces *s, int mode);
R_API bool r_space_rename (RSpaces *s, const char *oname, const char *nname);
// Create a new RSpaces with the given name
R_API RSpaces *r_spaces_new(const char *name);
// Initialize an existing RSpaces with the given name
R_API bool r_spaces_init(RSpaces *sp, const char *name);
// Finalize an existing RSpaces
R_API void r_spaces_fini(RSpaces *sp);
// Finalize and free an existing RSpaces
R_API void r_spaces_free(RSpaces *sp);
// Get the RSpace with the given name
R_API RSpace *r_spaces_get(RSpaces *sp, const char *name);
// Add a new RSpace if one does not already exist, otherwise return the existing one
R_API RSpace *r_spaces_add(RSpaces *sp, const char *name);
// Add and select a new RSpace if one does not already exist, otherwise return and select the existing one
R_API RSpace *r_spaces_set(RSpaces *sp, const char *name);
// Remove the RSpace with the given name
R_API bool r_spaces_unset(RSpaces *sp, const char *name);
// Change the name of RSpace with oname to nname
R_API bool r_spaces_rename(RSpaces *sp, const char *oname, const char *nname);
// Count the elements that belong to the RSpace with the given name
R_API int r_spaces_count(RSpaces *sp, const char *name);
// Add/Select the RSpace with the given name and save the current one in the history
R_API bool r_spaces_push(RSpaces *sp, const char *name);
// Select the RSpace that was set before the current one
R_API bool r_spaces_pop(RSpaces *sp);
static inline RSpace *r_spaces_current(RSpaces *sp) {
return sp->current;
}
static inline const char *r_spaces_current_name(RSpaces *sp) {
return sp->current? sp->current->name: "*";
}
#ifdef __cplusplus
}

View File

@ -41,7 +41,7 @@ static bool add_hook(void *cb, const ut64 k, const void *v) {
return true;
}
R_API void r_event_hook(REvent *ev, REventType type, REventCallback cb) {
R_API void r_event_hook(REvent *ev, int type, REventCallback cb) {
r_return_if_fail (ev);
if (type == R_EVENT_ALL) {
ht_up_foreach (ev->callbacks, add_hook, cb);
@ -58,7 +58,7 @@ static bool del_hook(void *cb, const ut64 k, const void *v) {
return true;
}
R_API void r_event_unhook(REvent *ev, REventType type, REventCallback cb) {
R_API void r_event_unhook(REvent *ev, int type, REventCallback cb) {
r_return_if_fail (ev);
if (type == R_EVENT_ALL) {
ht_up_foreach (ev->callbacks, del_hook, cb);
@ -68,7 +68,7 @@ R_API void r_event_unhook(REvent *ev, REventType type, REventCallback cb) {
}
}
R_API void r_event_send(REvent *ev, REventType type, void *data) {
R_API void r_event_send(REvent *ev, int type, void *data) {
r_return_if_fail (ev && !ev->incall);
void **it;
@ -77,7 +77,7 @@ R_API void r_event_send(REvent *ev, REventType type, void *data) {
ev->incall = true;
r_pvector_foreach (cbs, it) {
REventCallback cb = *it;
cb (ev, type, data);
cb (ev, type, ev->user, data);
}
ev->incall = false;
}

View File

@ -1,213 +1,185 @@
/* radare - LGPL - Copyright 2015 - pancake */
/* radare - LGPL - Copyright 2019 - pancake, ret2libc */
#include <r_anal.h>
#include "r_util/r_spaces.h"
R_API void r_space_new(RSpaces *s, const char *name, void (*unset_for)(void*,int), int (*count_for)(void*,int), void (*rename_for)(void*,int,const char*,const char*), void *user) {
int i;
s->name = r_str_new (name);
s->space_idx = -1;
s->spacestack = r_list_new ();
s->cb_printf = (PrintfCallback)printf;
s->unset_for = unset_for;
s->count_for = count_for;
s->rename_for = rename_for;
s->user = user;
for (i = 0; i < R_SPACES_MAX; i++) {
s->spaces[i] = NULL;
R_API RSpaces *r_spaces_new(const char *name) {
RSpaces *sp = R_NEW0 (RSpaces);
if (!sp || !r_spaces_init (sp, name)) {
return NULL;
}
return sp;
}
R_API void r_space_free(RSpaces *s) {
int i;
for (i = 0; i < R_SPACES_MAX; i++) {
R_FREE (s->spaces[i]);
R_API bool r_spaces_init(RSpaces *sp, const char *name) {
r_return_val_if_fail (sp && name, false);
sp->name = strdup (name);
if (!sp->name) {
goto fail;
}
r_list_free (s->spacestack);
free (s->name);
}
R_API int r_space_get(RSpaces *s, const char *name) {
int i;
if (!name || *name == '*') {
return -1;
sp->spaces = NULL;
sp->current = NULL;
sp->spacestack = r_list_new ();
if (!sp->spacestack) {
goto fail;
}
for (i = 0; i < R_SPACES_MAX; i++) {
if (s->spaces[i] && !strcmp (name, s->spaces[i])) {
return i;
}
}
return -1;
}
R_API const char *r_space_get_i(RSpaces *s, int idx) {
if (idx==-1 || idx>=R_SPACES_MAX) {
return "";
sp->event = r_event_new (sp);
if (!sp->event) {
goto fail;
}
return s->spaces[idx];
}
R_API int r_space_add(RSpaces *s, const char *name) {
int i;
if (!name || *name == '*') {
return -1;
}
for (i = 0; i < R_SPACES_MAX; i++) {
if (s->spaces[i] && !strcmp (name, s->spaces[i])) {
return i;
}
}
// not found
for (i = 0; i < R_SPACES_MAX; i++) {
if (!s->spaces[i]) {
s->spaces[i] = strdup (name);
return i;
}
}
return -1;
}
return true;
R_API bool r_space_push(RSpaces *s, const char *name) {
int ret = false;
if (name && *name) {
if (s->space_idx >= 0 && s->spaces[s->space_idx]) {
r_list_push (s->spacestack, s->spaces[s->space_idx]);
} else {
r_list_push (s->spacestack, "*");
}
r_space_set (s, name);
ret = true;
}
return ret;
}
R_API bool r_space_pop(RSpaces *s) {
char *p = r_list_pop (s->spacestack);
if (p) {
if (*p) {
r_space_set (s, p);
}
return true;
}
fail:
r_spaces_free (sp);
return false;
}
R_API int r_space_set(RSpaces *s, const char *name) {
s->space_idx = r_space_add (s, name);
return s->space_idx;
R_API void r_spaces_free(RSpaces *sp) {
r_spaces_fini (sp);
free (sp);
}
R_API int r_space_unset (RSpaces *s, const char *name) {
int i, count = 0;
static void space_free(RSpace *s) {
if (s) {
free (s->name);
free (s);
}
}
static void space_node_free(RBNode *n) {
RSpace *s = container_of (n, RSpace, rb);
space_free (s);
}
R_API void r_spaces_fini(RSpaces *sp) {
r_list_free (sp->spacestack);
sp->spacestack = NULL;
r_rbtree_free (sp->spaces, space_node_free);
sp->spaces = NULL;
r_event_free (sp->event);
sp->event = NULL;
R_FREE (sp->name);
}
static int name_space_cmp(const void *incoming, const RBNode *rb) {
const RSpace *s = container_of (rb, const RSpace, rb);
return strcmp (incoming, s->name);
}
R_API RSpace *r_spaces_get(RSpaces *sp, const char *name) {
RBNode *n = r_rbtree_find (sp->spaces, (void *)name, name_space_cmp);
return n? container_of (n, RSpace, rb): NULL;
}
static int space_cmp(const void *incoming, const RBNode *rb) {
const RSpace *a = (const RSpace *)incoming;
const RSpace *b = container_of (rb, const RSpace, rb);
return strcmp (a->name, b->name);
}
R_API RSpace *r_spaces_add(RSpaces *sp, const char *name) {
r_return_val_if_fail (sp, NULL);
if (!name || !*name || *name == '*') {
return NULL;
}
RSpace *s = r_spaces_get (sp, name);
if (s) {
return s;
}
s = R_NEW0 (RSpace);
if (!s) {
return NULL;
}
s->name = strdup (name);
if (!s->name) {
free (s);
return NULL;
}
r_rbtree_insert (&sp->spaces, s, &s->rb, space_cmp);
return s;
}
R_API RSpace *r_spaces_set(RSpaces *sp, const char *name) {
sp->current = r_spaces_add (sp, name);
return sp->current;
}
R_API bool r_spaces_unset(RSpaces *sp, const char *name) {
RSpace *space = r_spaces_get (sp, name);
if (!space) {
return false;
}
RSpaceEvent ev = { .data.unset.space = space };
r_event_send (sp->event, R_SPACE_EVENT_UNSET, &ev);
return r_rbtree_delete (&sp->spaces, (void *)name, name_space_cmp, space_node_free);
}
R_API int r_spaces_count(RSpaces *sp, const char *name) {
RSpace *s = r_spaces_get (sp, name);
if (!s) {
return 0;
}
RSpaceEvent ev = { .data.count.space = s, .res = 0 };
r_event_send (sp->event, R_SPACE_EVENT_COUNT, &ev);
return ev.res;
}
R_API bool r_spaces_push(RSpaces *sp, const char *name) {
r_return_val_if_fail (sp, false);
r_list_push (sp->spacestack, sp->current? sp->current->name: "*");
r_spaces_set (sp, name);
return true;
}
R_API bool r_spaces_pop(RSpaces *sp) {
char *name = r_list_pop (sp->spacestack);
if (!name) {
r_space_set (s, NULL);
return false;
}
for (i = 0; i < R_SPACES_MAX; i++) {
if (!s->spaces[i]) {
continue;
}
if (!name || !strcmp (name, s->spaces[i])) {
if (s->space_idx == i) {
s->space_idx = -1;
}
R_FREE (s->spaces[i]);
if (s->unset_for) {
s->unset_for (s, i);
}
count++;
}
}
return count;
RSpace *s = r_spaces_get (sp, name);
r_spaces_set (sp, s? s->name: NULL);
return true;
}
static int r_space_count (RSpaces *s, int n) {
if (s->count_for) {
return s->count_for (s, n);
R_API bool r_spaces_rename(RSpaces *sp, const char *oname, const char *nname) {
if (!oname && !sp->current) {
return false;
}
return 0;
}
R_API int r_space_list(RSpaces *s, int mode) {
const char *defspace = NULL;
int count, len, i, j = 0;
if (mode == 'j') {
s->cb_printf ("[");
}
for (i = 0; i < R_SPACES_MAX; i++) {
if (!s->spaces[i]) {
continue;
}
count = r_space_count (s, i);
if (mode == 'j') {
s->cb_printf ("%s{\"name\":\"%s\"%s,\"count\":%d}",
j? ",": "", s->spaces[i],
(i == s->space_idx)? ",\"selected\":true": "",
count);
} else if (mode == '*') {
s->cb_printf ("%s %s\n", s->name, s->spaces[i]);
if (i == s->space_idx) {
defspace = s->spaces[i];
}
} else {
#define INDENT 5
char num0[64], num1[64], spaces[32];
snprintf (num0, sizeof (num0), "%d", i);
snprintf (num1, sizeof (num1), "%d", count);
memset (spaces, ' ', sizeof (spaces));
len = strlen (num0) + strlen (num1);
if (len < INDENT) {
spaces[INDENT-len] = 0;
} else {
spaces[0] = 0;
}
s->cb_printf ("%s%s %s %c %s\n", num0, spaces, num1,
(i == s->space_idx)? '*': '.',
s->spaces[i]);
}
j++;
}
if (defspace) {
s->cb_printf ("%s %s # current\n", s->name, defspace);
}
if (mode == 'j') {
s->cb_printf ("]\n");
}
return j;
}
R_API bool r_space_rename (RSpaces *s, const char *oname, const char *nname) {
int i;
if (!oname) {
if (s->space_idx == -1) {
RSpace *s;
if (oname) {
s = r_spaces_get (sp, oname);
if (!s) {
return false;
}
oname = s->spaces[s->space_idx];
} else {
s = sp->current;
}
if (!nname) {
RSpace *sn = r_spaces_get (sp, nname);
if (sn) {
return false;
}
while (*oname==' ') {
oname++;
}
while (*nname==' ') {
nname++;
}
RSpaceEvent ev = {
.data.rename.oldname = s->name,
.data.rename.newname = nname,
.data.rename.space = s
};
r_event_send (sp->event, R_SPACE_EVENT_RENAME, &ev);
if (r_space_get (s, nname) != -1) {
eprintf ("error: dupplicated name\n");
return false;
}
for (i = 0; i < R_SPACES_MAX; i++) {
if (s->spaces[i] && !strcmp (oname, s->spaces[i])) {
if (s->rename_for) {
s->rename_for (s, i, oname, nname);
}
free (s->spaces[i]);
s->spaces[i] = strdup (nname);
return true;
}
}
return false;
r_rbtree_delete (&sp->spaces, (void *)s->name, name_space_cmp, NULL);
free (s->name);
s->name = strdup (nname);
r_rbtree_insert (&sp->spaces, s, &s->rb, space_cmp);
return true;
}