From e7e4c869100a78bebe70621fc36ff3d24e174f89 Mon Sep 17 00:00:00 2001 From: pancake Date: Mon, 19 Dec 2016 01:33:54 +0100 Subject: [PATCH] Add N key in graph to toggle mini nodes and graph.cmtright --- libr/core/cconfig.c | 3 +- libr/core/graph.c | 311 ++++++++++++++++++++++------------ libr/include/r_cons.h | 5 +- libr/util/graph.c | 91 +++++----- libr/util/str.c | 7 +- sys/release-notes/config.json | 4 +- 6 files changed, 270 insertions(+), 151 deletions(-) diff --git a/libr/core/cconfig.c b/libr/core/cconfig.c index 3fb64cb008..707b6a8d19 100644 --- a/libr/core/cconfig.c +++ b/libr/core/cconfig.c @@ -2055,7 +2055,8 @@ R_API int r_core_config_init(RCore *core) { r_config_desc (cfg, "http.uproot", "Path where files are uploaded"); /* graph */ - SETPREF("graph.comments", "false", "Show disasm comments in graph"); + SETPREF("graph.comments", "true", "Show disasm comments in graph"); + SETPREF("graph.cmtright", "false", "Show comments at right"); SETPREF("graph.format", "dot", "Specify output format for graphs (dot, gml, gmlfcn)"); SETPREF("graph.refs", "false", "Graph references in callgraphs (.agc*;aggi)"); SETPREF("graph.font", "Courier", "Font for dot graphs"); diff --git a/libr/core/graph.c b/libr/core/graph.c index cd32810b6f..abf3a8232e 100644 --- a/libr/core/graph.c +++ b/libr/core/graph.c @@ -22,7 +22,7 @@ static const char *mousemodes[] = { #define HORIZONTAL_NODE_SPACING 6 #define VERTICAL_NODE_SPACING 4 #define MIN_NODE_WIDTH 22 -#define MIN_NODE_HEIGTH BORDER_HEIGHT +#define MIN_NODE_HEIGHT BORDER_HEIGHT #define TITLE_LEN 128 #define DEFAULT_SPEED 1 #define PAGEKEY_SPEED (h/2) @@ -43,7 +43,7 @@ static const char *mousemodes[] = { #define hash_get_rnode(sdb,k) ((RGraphNode *)(size_t)hash_get (sdb, k)) #define hash_get_rlist(sdb,k) ((RList *)(size_t)hash_get (sdb, k)) #define hash_get_int(sdb,k) ((int)hash_get (sdb, k)) - +/* dont use macros for this */ #define get_anode(gn) (gn ? (RANode *)gn->data : NULL) #define graph_foreach_anode(list, it, pos, anode) \ @@ -134,6 +134,8 @@ static char *get_title (ut64 addr) { return r_str_newf ("0x%"PFMT64x, addr); } +static int agraph_refresh(struct agraph_refresh_data *grd); + static void update_node_dimension(const RGraph *g, int is_small, int zoom) { const RList *nodes = r_graph_get_nodes (g); RGraphNode *gn; @@ -148,13 +150,15 @@ static void update_node_dimension(const RGraph *g, int is_small, int zoom) { unsigned int len; n->w = r_str_bounds (n->body, (int *)&n->h); len = strlen (n->title) + MARGIN_TEXT_X; - if (len > INT_MAX) len = INT_MAX; + if (len > INT_MAX) { + len = INT_MAX; + } n->w = R_MAX (n->w, (int)len); n->w += BORDER_WIDTH; n->h += BORDER_HEIGHT; /* scale node by zoom */ n->w = R_MAX (MIN_NODE_WIDTH, (n->w * zoom) / 100); - n->h = R_MAX (MIN_NODE_HEIGTH, (n->h * zoom) / 100); + n->h = R_MAX (MIN_NODE_HEIGHT, (n->h * zoom) / 100); } } } @@ -196,6 +200,33 @@ static void small_RANode_print(const RAGraph *g, const RANode *n, int cur) { return; } +static void mini_RANode_print(const RAGraph *g, const RANode *n, int cur) { + char title[TITLE_LEN]; + int x, delta_x = 0; + + if (!G (n->x + SMALLNODE_CENTER_X, n->y) && + !G (n->x + SMALLNODE_CENTER_X + n->w, n->y)) return; + + x = n->x + SMALLNODE_CENTER_X + g->can->sx; + if (x < 0) { + delta_x = -x; + } + G (n->x + SMALLNODE_CENTER_X + delta_x, n->y); + + if (cur) { + W(&SMALLNODE_TEXT_CUR[delta_x]); + snprintf (title, sizeof (title) - 1, + "[ %s ]", n->title); + W (title); + } else { + W(&SMALLNODE_TEXT_CUR[delta_x]); + snprintf (title, sizeof (title) - 1, + " %s ", n->title); + W (title); + } + return; +} + static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) { unsigned int center_x = 0, center_y = 0; unsigned int delta_x = 0, delta_txt_x = 0; @@ -207,13 +238,15 @@ static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) { x = n->x + g->can->sx; y = n->y + g->can->sy; - if (x + MARGIN_TEXT_X < 0) + if (x + MARGIN_TEXT_X < 0) { delta_x = -(x + MARGIN_TEXT_X); - if (x + n->w < -MARGIN_TEXT_X) + } + if (x + n->w < -MARGIN_TEXT_X) { return; - if (y < -1) + } + if (y < -1) { delta_y = R_MIN (n->h - BORDER_HEIGHT - 1, -y - MARGIN_TEXT_Y); - + } shortcut = sdb_get (g->db, sdb_fmt (2, "agraph.nodes.%s.shortcut", n->title), 0); /* print the title */ if (cur) { @@ -225,7 +258,6 @@ static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) { strncat (title, sdb_fmt (2, " ;[%s]", shortcut), sizeof (title) - strlen (title) - 1); free (shortcut); } - if ((delta_x < strlen (title)) && G(n->x + MARGIN_TEXT_X + delta_x, n->y + 1)) { W(title + delta_x); } @@ -252,7 +284,9 @@ static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) { body_h); if (body) { W (body); - if (g->zoom < ZOOM_DEFAULT) W ("\n"); + if (g->zoom < ZOOM_DEFAULT) { + W ("\n"); + } free (body); } else { W (n->body); @@ -261,7 +295,7 @@ static void normal_RANode_print(const RAGraph *g, const RANode *n, int cur) { /* print some dots when the body is cropped because of zoom */ if (body_y <= body_h && g->zoom < ZOOM_DEFAULT) { char *dots = "..."; - if (delta_x < strlen(dots)) { + if (delta_x < strlen (dots)) { dots += delta_x; W (dots); } @@ -281,24 +315,22 @@ static int **get_crossing_matrix (const RGraph *g, const struct layer_t layers[], int maxlayer, int i, int from_up, int *n_rows) { - int len = layers[i].n_nodes; - int **m; - int j; + int j, **m, len = layers[i].n_nodes; m = R_NEWS0 (int *, len); - if (!m) + if (!m) { return NULL; - - for (j = 0; j < len; ++j) { - m[j] = R_NEWS0 (int, len); - if (!m[j]) - goto err_row; } - + for (j = 0; j < len; j++) { + m[j] = R_NEWS0 (int, len); + if (!m[j]) { + goto err_row; + } + } /* calculate crossings between layer i and layer i-1 */ /* consider the crossings generated by each pair of edges */ if (i > 0 && from_up) { - for (j = 0; j < layers[i - 1].n_nodes; ++j) { + for (j = 0; j < layers[i - 1].n_nodes; j++) { const RGraphNode *gj = layers[i - 1].nodes[j]; const RList *neigh = r_graph_get_neighbours (g, gj); RGraphNode *gk; @@ -307,8 +339,9 @@ static int **get_crossing_matrix (const RGraph *g, r_list_foreach (neigh, itk, gk) { int s; // skip self-loop - if (gj == gk) continue; - + if (gj == gk) { + continue; + } for (s = 0; s < j; ++s) { const RGraphNode *gs = layers[i - 1].nodes[s]; const RList *neigh_s = r_graph_get_neighbours (g, gs); @@ -317,10 +350,9 @@ static int **get_crossing_matrix (const RGraph *g, r_list_foreach (neigh_s, itt, gt) { const RANode *ak, *at; /* k and t should be "indexes" on layer i */ - - if (gt == gk) continue; - // skip self-loop - if (gt == gs) continue; + if (gt == gk || gt == gs) { + continue; + } ak = get_anode (gk); at = get_anode (gt); @@ -993,7 +1025,6 @@ static RGraphNode *get_right_dummy (const RAGraph *g, const RGraphNode *n) { if (ak->is_dummy) return gk; } - return NULL; } @@ -1002,8 +1033,9 @@ static void adjust_directions (const RAGraph *g, int i, int from_up, Sdb *D, Sdb const RANode *vma = NULL, *wma = NULL; int j, d = from_up ? 1 : -1; - if (i + d < 0 || i + d >= g->n_layers) return; - + if (i + d < 0 || i + d >= g->n_layers) { + return; + } for (j = 0; j < g->layers[i + d].n_nodes; ++j) { const RGraphNode *wp, *vp = g->layers[i + d].nodes[j]; const RANode *wpa, *vpa = get_anode (vp); @@ -1030,13 +1062,12 @@ static void adjust_directions (const RAGraph *g, int i, int from_up, Sdb *D, Sdb for (k = vma->pos_in_layer + 1; k < vpa->pos_in_layer; ++k) { const RGraphNode *v = g->layers[vma->layer].nodes[k]; const RANode *av = get_anode (v); - - if (av->is_dummy) + if (av->is_dummy) { hash_set (D, v, from_up); + } } } } - vm = vp; wm = wp; vma = get_anode (vm); @@ -1045,8 +1076,7 @@ static void adjust_directions (const RAGraph *g, int i, int from_up, Sdb *D, Sdb } /* find a placement for a single node */ -static void place_single (const RAGraph *g, int l, const RGraphNode *bm, - const RGraphNode *bp, int from_up, int va) { +static void place_single (const RAGraph *g, int l, const RGraphNode *bm, const RGraphNode *bp, int from_up, int va) { const RGraphNode *gk, *v = g->layers[l].nodes[va]; const RANode *ak; RANode *av = get_anode (v); @@ -1054,14 +1084,14 @@ static void place_single (const RAGraph *g, int l, const RGraphNode *bm, const RListIter *itk; int len; - if (from_up) - neigh = r_graph_innodes (g->graph, v); - else - neigh = r_graph_get_neighbours (g->graph, v); + neigh = from_up + ? r_graph_innodes (g->graph, v) + : r_graph_get_neighbours (g->graph, v); len = r_list_length (neigh); - if (len == 0) + if (len == 0) { return; + } int sum_x = 0; graph_foreach_anode (neigh, itk, gk, ak) { @@ -1069,13 +1099,12 @@ static void place_single (const RAGraph *g, int l, const RGraphNode *bm, len--; continue; } - sum_x += ak->x; } - if (len == 0) + if (len == 0) { return; - + } av->x = sum_x / len; if (bm) { const RANode *bma = get_anode (bm); @@ -1105,18 +1134,20 @@ static void collect_changes(const RAGraph *g, int l, const RGraphNode *b, int fr lcmp = is_left ? (RListComparator)RM_listcmp : (RListComparator)RP_listcmp; for (i = is_left ? s : e - 1; - (is_left && i < e) || (!is_left && i >= s); - i = is_left ? i + 1 : i - 1) { + (is_left && i < e) || (!is_left && i >= s); + i = is_left ? i + 1 : i - 1) { const RGraphNode *v, *vi = g->layers[l].nodes[i]; const RANode *av, *avi = get_anode (vi); const RList *neigh; const RListIter *it; int c = 0; - if (!avi) continue; + if (!avi) { + continue; + } neigh = from_up - ? r_graph_innodes (g->graph, vi) - : r_graph_get_neighbours (g->graph, vi); + ? r_graph_innodes (g->graph, vi) + : r_graph_get_neighbours (g->graph, vi); graph_foreach_anode (neigh, it, v, av) { if ((is_left && av->x >= avi->x) || (!is_left && av->x <= avi->x)) { @@ -1144,12 +1175,14 @@ static void collect_changes(const RAGraph *g, int l, const RGraphNode *b, int fr if (b) { const RANode *ab = get_anode (b); - cx = R_NEW (struct len_pos_t); cx->len = is_left ? INT_MAX : INT_MIN; cx->pos = ab->x; - if (is_left) cx->pos += dist_nodes (g, b, vt); - else cx->pos -= dist_nodes (g, vtp, b); + if (is_left) { + cx->pos += dist_nodes (g, b, vt); + } else { + cx->pos -= dist_nodes (g, vtp, b); + } r_list_add_sorted (list, cx, lcmp); } } @@ -1252,7 +1285,6 @@ static void original_traverse_l (const RAGraph *g, Sdb *D, Sdb *P, int from_up) while (j < g->layers[i].n_nodes && !bm) { const RGraphNode *gn = g->layers[i].nodes[j]; const RANode *an = get_anode (gn); - if (an->is_dummy) { va = 0; vr = j; @@ -1261,19 +1293,17 @@ static void original_traverse_l (const RAGraph *g, Sdb *D, Sdb *P, int from_up) } j++; } - if (!bm) { va = 0; vr = g->layers[i].n_nodes; } - place_sequence (g, i, NULL, bm, from_up, va, vr); - for (k = va; k < vr - 1; ++k) + for (k = va; k < vr - 1; k++) { set_dist_nodes (g, i, k, k + 1); - - if (is_valid_pos (g, i, vr - 1) && bm) + } + if (is_valid_pos (g, i, vr - 1) && bm) { set_dist_nodes (g, i, vr - 1, bma->pos_in_layer); - + } while (bm) { const RGraphNode *bp = get_right_dummy (g, bm); const RANode *bpa = NULL; @@ -1295,10 +1325,8 @@ static void original_traverse_l (const RAGraph *g, Sdb *D, Sdb *P, int from_up) place_sequence (g, i, bm, bp, from_up, va, vr); hash_set (P, bm, true); } - bm = bp; } - adjust_directions (g, i, from_up, D, P); } } @@ -1328,11 +1356,12 @@ static void place_original (RAGraph *g) { } graph_foreach_anode (nodes, itn, gn, an) { - if (!an->is_dummy) continue; + if (!an->is_dummy) { + continue; + } const RGraphNode *right_v = get_right_dummy (g, gn); - if (right_v) { - const RANode *right = get_anode (right_v); - + const RANode *right = get_anode (right_v); + if (right_v && right) { hash_set (D, gn, 0); int dt_eq = right->x - an->x == dist_nodes (g, gn, right_v); hash_set (P, gn, dt_eq); @@ -1374,7 +1403,9 @@ static void create_edge_from_dummies (const RAGraph *g, RANode *an, RList *torem RANode *a_from = get_anode (from); RListIter *(*add_to_list)(RList *, void *) = NULL; AEdge *e = R_NEW0 (AEdge); - if (!e) return; + if (!e) { + return; + } e->x = r_list_new (); e->y = r_list_new (); e->is_reversed = an->is_reversed; @@ -1426,9 +1457,13 @@ static void analyze_back_edges (const RAGraph *g, RANode *an) { AEdge *e; i++; - if (ak->layer > an->layer) continue; + if (ak->layer > an->layer) { + continue; + } e = R_NEW0 (AEdge); - if (!e) return; + if (!e) { + return; + } e->is_reversed = true; e->from = an; e->to = ak; @@ -1493,7 +1528,7 @@ static void remove_dummy_nodes (const RAGraph *g) { static void set_layout(RAGraph *g) { int i, j, k; - if (g->edges) r_list_free (g->edges); + r_list_free (g->edges); g->edges = r_list_new (); remove_cycles (g); @@ -1507,8 +1542,9 @@ static void set_layout(RAGraph *g) { int rh = 0; for (j = 0; j < g->layers[i].n_nodes; ++j) { const RANode *n = get_anode (g->layers[i].nodes[j]); - if (n->h > rh) + if (n->h > rh) { rh = n->h; + } } g->layers[i].height = rh; } @@ -1542,8 +1578,9 @@ static void set_layout(RAGraph *g) { remove_dummy_nodes (g); /* free all temporary structures used during layout */ - for (i = 0; i < g->n_layers; ++i) + for (i = 0; i < g->n_layers; ++i) { free (g->layers[i].nodes); + } free (g->layers); r_list_free (g->long_edges); r_list_free (g->back_edges); @@ -1558,6 +1595,7 @@ static char *get_body(RCore *core, ut64 addr, int size, int opts) { r_config_save_num (hc, "asm.fcnlines", "asm.lines", "asm.bytes", "asm.cmtcol", "asm.marks", "asm.marks", "asm.offset", "asm.comments", NULL); const bool o_comments = r_config_get_i (core->config, "graph.comments"); + const bool o_cmtright = r_config_get_i (core->config, "graph.cmtright"); int o_cursor = core->print->cur_enabled; const char *cmd = (opts & BODY_SUMMARY) ? "pds" : "pD"; @@ -1567,6 +1605,7 @@ static char *get_body(RCore *core, ut64 addr, int size, int opts) { r_config_set_i (core->config, "asm.lines", false); r_config_set_i (core->config, "asm.cmtcol", 0); r_config_set_i (core->config, "asm.marks", false); + r_config_set_i (core->config, "asm.cmtright", o_cmtright); r_config_set_i (core->config, "asm.comments", (opts & BODY_SUMMARY) || o_comments); core->print->cur_enabled = false; @@ -1821,8 +1860,9 @@ static void update_seek(RConsCanvas *can, RANode *n, int force) { int x, y, w, h; int doscroll = false; - if (!n) return; - + if (!n) { + return; + } x = n->x + can->sx; y = n->y + can->sy; w = can->w; @@ -2002,11 +2042,22 @@ static void agraph_update_seek(RAGraph *g, RANode *n, int force) { static void agraph_print_node(const RAGraph *g, RANode *n) { const int cur = g->curnode && get_anode (g->curnode) == n; - if (is_mini (g)) { small_RANode_print (g, n, cur); } else { - normal_RANode_print (g, n, cur); + if (n->mini) { + n->w = strlen (n->title) + 4; +#if 1 + mini_RANode_print (g, n, cur); +#else + small_RANode_print (g, n, cur); +#endif + (void)r_str_bounds ("", (int *)&n->h); + } else { + n->w = r_str_bounds (n->body, (int *)&n->h); + n->h += 3; + normal_RANode_print (g, n, cur); + } } } @@ -2023,7 +2074,9 @@ static void agraph_print_nodes(const RAGraph *g) { } /* draw current node now to make it appear on top */ - if (g->curnode) agraph_print_node (g, get_anode (g->curnode)); + if (g->curnode) { + agraph_print_node (g, get_anode (g->curnode)); + } } static int find_ascii_edge (const AEdge *a, const AEdge *b) { @@ -2140,7 +2193,45 @@ static int agraph_reload_nodes(RAGraph *g, RCore *core, RAnalFunction *fcn) { static void follow_nth(RAGraph *g, int nth) { const RGraphNode *cn = r_graph_nth_neighbour (g->graph, g->curnode, nth); - if (cn) r_agraph_set_curnode (g, get_anode (cn)); + if (cn) { + r_agraph_set_curnode (g, get_anode (cn)); + } +} + +#define K_NEIGHBOURS(x) (sdb_fmt(2, "agraph.nodes.%s.neighbours", x->title)) +static void agraph_merge_child(RAGraph *g, int idx) { + const RGraphNode *nn = r_graph_nth_neighbour (g->graph, g->curnode, idx); + const RGraphNode *cn = g->curnode; + if (cn && nn) { + RANode *ann = get_anode (nn); + RANode *acn = get_anode (cn); + acn->body = r_str_concat (acn->body, ann->title); + acn->body = r_str_concat (acn->body, "\n"); + acn->body = r_str_concat (acn->body, ann->body); + /* remove node from the graph */ + acn->h += ann->h - 3; + free (ann->body); + // TODO: do not merge nodes if those have edges targeting them + // TODO: Add children neighbours to current one + //nn->body + //r_agraph_set_curnode (g, get_anode (cn)); + //agraph_refresh (grd); + //r_agraph_add_edge (g, from, to); + + char *neis = sdb_get (g->db, K_NEIGHBOURS (ann), 0); + sdb_set_owned (g->db, K_NEIGHBOURS (ann), neis, 0); + r_agraph_del_node (g, ann->title); + agraph_print_nodes (g); + agraph_print_edges (g); + } + //agraph_update_seek (g, get_anode (g->curnode), false); +} + +static void agraph_toggle_mini(RAGraph *g) { + RANode *n = get_anode (g->curnode); + n->mini = !n->mini; + agraph_refresh (r_cons_singleton ()->event_data); + agraph_set_layout ((RAGraph *)g, r_cons_singleton() ->is_interactive); } static void agraph_follow_true(RAGraph *g) { @@ -2308,7 +2399,8 @@ static int agraph_refresh(struct agraph_refresh_data *grd) { if (!f) { r_cons_message ("Not in a function. Type 'df' to define it here"); return 0; - } else if (f && f != *fcn) { + } + if (f && f != *fcn) { *fcn = f; g->need_reload_nodes = true; g->force_update_seek = true; @@ -2363,7 +2455,6 @@ static void sdb_set_enc (Sdb *db, const char *key, const char *v, ut32 cas) { static void agraph_sdb_init (const RAGraph *g) { sdb_bool_set (g->db, "agraph.is_callgraph", g->is_callgraph, 0); - sdb_set_enc (g->db, "agraph.color_box", g->color_box, 0); sdb_set_enc (g->db, "agraph.color_box2", g->color_box2, 0); sdb_set_enc (g->db, "agraph.color_box3", g->color_box3, 0); @@ -2380,8 +2471,9 @@ R_API Sdb *r_agraph_get_sdb (RAGraph *g) { R_API void r_agraph_print (RAGraph *g) { agraph_print (g, false, NULL, NULL); - if (g->graph->n_nodes > 0) + if (g->graph->n_nodes > 0) { r_cons_newline (); + } } R_API void r_agraph_set_title (RAGraph *g, const char *title) { @@ -2392,9 +2484,13 @@ R_API void r_agraph_set_title (RAGraph *g, const char *title) { R_API RANode *r_agraph_add_node(const RAGraph *g, const char *title, const char *body) { RANode *res = r_agraph_get_node (g, title); - if (res) return res; + if (res) { + return res; + } res = R_NEW0 (RANode); - if (!res) return NULL; + if (!res) { + return NULL; + } res->title = title ? strdup(title) : strdup (""); res->body = body ? strdup(body) : strdup (""); res->layer = -1; @@ -2428,7 +2524,9 @@ R_API bool r_agraph_del_node(const RAGraph *g, const char *title) { RGraphNode *gn; RListIter *it; - if (!res) return false; + if (!res) { + return false; + } sdb_set (g->nodes, title, NULL, 0); sdb_array_remove (g->db, "agraph.nodes", res->title, 0); sdb_set (g->db, sdb_fmt (2, "agraph.nodes.%s", res->title), NULL, 0); @@ -2437,8 +2535,7 @@ R_API bool r_agraph_del_node(const RAGraph *g, const char *title) { sdb_set (g->db, sdb_fmt (2, "agraph.nodes.%s.y", res->title), NULL, 0); sdb_set (g->db, sdb_fmt (2, "agraph.nodes.%s.w", res->title), NULL, 0); sdb_set (g->db, sdb_fmt (2, "agraph.nodes.%s.h", res->title), NULL, 0); - sdb_set (g->db, sdb_fmt (2, "agraph.nodes.%s.neighbours", res->title), - NULL, 0); + sdb_set (g->db, sdb_fmt (2, "agraph.nodes.%s.neighbours", res->title), NULL, 0); innodes = r_graph_innodes (g->graph, res->gnode); graph_foreach_anode (innodes, it, gn, an) { @@ -2642,11 +2739,9 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int RConsCanvas *can, *o_can = NULL; bool graph_allocated = false; int movspeed; - int w, h; - int ret; - int invscroll; + int ret, invscroll; - w = r_cons_get_size (&h); + int h, w = r_cons_get_size (&h); can = r_cons_canvas_new (w, h); if (!can) { eprintf ("Cannot create RCons.canvas context. Invalid screen size? See scr.columns + scr.rows\n"); @@ -2828,6 +2923,7 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int " hjkl - scroll canvas\n" " HJKL - move node\n" " m/M - change mouse modes\n" + " N - toggle node folding/minification\n" " tab - select next node\n" " TAB - select previous node\n" " t/f - follow true/false edges\n" @@ -2908,13 +3004,13 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int r_core_visual_panels (core); break; case '\'': - if (!fcn) break; - r_config_toggle (core->config, "graph.comments"); - g->need_reload_nodes = true; + if (fcn) { + r_config_toggle (core->config, "graph.comments"); + g->need_reload_nodes = true; + } break; case ';': - { - if (!fcn) break; + if (fcn) { char buf[256]; r_line_set_prompt ("[comment]> "); if (r_cons_fgets (buf, sizeof (buf) - 1, 0, NULL) > 0) { @@ -2971,15 +3067,6 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int get_anode (g->curnode)->y -= movspeed; } break; - case 'F': - if (okey == 27) { - // handle end key - const RGraphNode *gn = find_near_of (g, NULL, false); - g->update_seek_on = get_anode (gn); - } else { - r_core_visual_trackflags (core); - } - break; case 'H': if (okey == 27) { // handle home key @@ -2992,6 +3079,9 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int case 'v': r_core_visual_anal (core); break; + case 'N': + agraph_toggle_mini (g); + break; case 'L': get_anode (g->curnode)->x += movspeed; break; case 'j': can->sy -= movspeed * (invscroll ? -1 : 1); break; case 'k': can->sy += movspeed * (invscroll ? -1 : 1); break; @@ -3003,9 +3093,22 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int case 't': agraph_follow_true (g); break; + case 'T': + // XXX WIP agraph_merge_child (g, 0); + break; case 'f': agraph_follow_false (g); break; + case 'F': + if (okey == 27) { + // handle end key + const RGraphNode *gn = find_near_of (g, NULL, false); + g->update_seek_on = get_anode (gn); + } else { + // agraph_merge_child (g, 1); + r_core_visual_trackflags (core); + } + break; case '/': r_config_set_i (core->config, "scr.interactive", true); r_core_cmd0 (core, "?i highlight;e scr.highlight=`?y`"); @@ -3025,7 +3128,7 @@ R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int case ' ': case 'q': if (g->is_callgraph) { - agraph_toggle_callgraph(g); + agraph_toggle_callgraph (g); } else { exit_graph = true; } diff --git a/libr/include/r_cons.h b/libr/include/r_cons.h index b39ab6225e..866b9af60a 100644 --- a/libr/include/r_cons.h +++ b/libr/include/r_cons.h @@ -635,6 +635,7 @@ typedef struct r_ascii_node_t { int is_dummy; int is_reversed; int klass; + bool mini; } RANode; #define R_AGRAPH_MODE_NORMAL 0 @@ -661,8 +662,8 @@ typedef struct r_ascii_graph_t { int movspeed; RANode *update_seek_on; - int need_reload_nodes; - int need_set_layout; + bool need_reload_nodes; + bool need_set_layout; int need_update_dim; int force_update_seek; diff --git a/libr/util/graph.c b/libr/util/graph.c index f021209055..3de7b89db4 100644 --- a/libr/util/graph.c +++ b/libr/util/graph.c @@ -10,7 +10,9 @@ enum { static RGraphNode *r_graph_node_new (void *data) { RGraphNode *p = R_NEW0 (RGraphNode); - if (!p) return NULL; + if (!p) { + return NULL; + } p->data = data; p->free = NULL; p->out_nodes = r_list_new (); @@ -20,9 +22,12 @@ static RGraphNode *r_graph_node_new (void *data) { } static void r_graph_node_free (RGraphNode *n) { - if (!n) return; - if (n->free) + if (!n) { + return; + } + if (n->free) { n->free (n->data); + } r_list_free (n->out_nodes); r_list_free (n->in_nodes); r_list_free (n->all_neighbours); @@ -34,11 +39,12 @@ static int node_cmp (unsigned int idx, RGraphNode *b) { } static void dfs_node (RGraph *g, RGraphNode *n, RGraphVisitor *vis, int color[]) { - RStack *s; RGraphEdge *edg; - s = r_stack_new (2 * g->n_edges + 1); - if (!s) return; + RStack *s = r_stack_new (2 * g->n_edges + 1); + if (!s) { + return; + } edg = R_NEW0 (RGraphEdge); if (!edg) { r_stack_free (s); @@ -67,12 +73,12 @@ static void dfs_node (RGraph *g, RGraphNode *n, RGraphVisitor *vis, int color[]) color[from->idx] = BLACK_COLOR; } free (cur_edge); - - if (!cur || color[cur->idx] != WHITE_COLOR) + if (!cur || color[cur->idx] != WHITE_COLOR) { continue; - - if (color[cur->idx] == WHITE_COLOR && vis->discover_node) + } + if (color[cur->idx] == WHITE_COLOR && vis->discover_node) { vis->discover_node (cur, vis); + } color[cur->idx] = GRAY_COLOR; edg = R_NEW0 (RGraphEdge); @@ -113,9 +119,9 @@ R_API void r_graph_free (RGraph* t) { R_API RGraphNode *r_graph_get_node (const RGraph *t, unsigned int idx) { RListIter *it = r_list_find (t->nodes, (void *)(size_t)idx, (RListComparator)node_cmp); - if (!it) + if (!it) { return NULL; - + } return (RGraphNode *)it->data; } @@ -125,9 +131,10 @@ R_API RListIter *r_graph_node_iter (const RGraph *t, unsigned int idx) { R_API void r_graph_reset (RGraph *t) { r_list_free (t->nodes); - t->nodes = r_list_new (); - if (!t->nodes) return; + if (!t->nodes) { + return; + } t->nodes->free = (RListFree)r_graph_node_free; t->n_nodes = 0; t->n_edges = 0; @@ -136,7 +143,9 @@ R_API void r_graph_reset (RGraph *t) { R_API RGraphNode *r_graph_add_node (RGraph *t, void *data) { RGraphNode *n = r_graph_node_new (data); - if (!n) return NULL; + if (!n) { + return NULL; + } n->idx = t->last_index++; r_list_append (t->nodes, n); t->n_nodes++; @@ -148,8 +157,9 @@ R_API RGraphNode *r_graph_add_node (RGraph *t, void *data) { R_API void r_graph_del_node(RGraph *t, RGraphNode *n) { RGraphNode *gn; RListIter *it; - - if (!n) return; + if (!n) { + return; + } r_list_foreach (n->in_nodes, it, gn) { r_list_delete_data (gn->out_nodes, n); r_list_delete_data (gn->all_neighbours, n); @@ -171,12 +181,13 @@ R_API void r_graph_add_edge (RGraph *t, RGraphNode *from, RGraphNode *to) { } R_API void r_graph_add_edge_at (RGraph *t, RGraphNode *from, RGraphNode *to, int nth) { - if (!from || !to) return; - r_list_insert(from->out_nodes, nth, to); - r_list_append(from->all_neighbours, to); - r_list_append(to->in_nodes, from); - r_list_append(to->all_neighbours, from); - t->n_edges++; + if (from && to) { + r_list_insert (from->out_nodes, nth, to); + r_list_append (from->all_neighbours, to); + r_list_append (to->in_nodes, from); + r_list_append (to->all_neighbours, from); + t->n_edges++; + } } R_API void r_graph_del_edge (RGraph *t, RGraphNode *from, RGraphNode *to) { @@ -203,19 +214,16 @@ R_API RGraphNode *r_graph_nth_neighbour (const RGraph *g, const RGraphNode *n, i /* returns the list of nodes that can reach `n` */ R_API const RList *r_graph_innodes (const RGraph *g, const RGraphNode *n) { - if (!n) return NULL; - return n->in_nodes; + return n? n->in_nodes: NULL; } /* returns the list of nodes reachable from `n` and that can reach `n`. */ R_API const RList *r_graph_all_neighbours (const RGraph *g, const RGraphNode *n) { - if (!n) return NULL; - return n->all_neighbours; + return n? n->all_neighbours: NULL; } R_API const RList *r_graph_get_nodes (const RGraph *g) { - if (!g) return NULL; - return g->nodes; + return g? g->nodes: NULL; } /* true if there is an edge from the node `from` to the node `to` */ @@ -226,12 +234,14 @@ R_API int r_graph_adjacent (const RGraph *g, const RGraphNode *from, const RGrap R_API void r_graph_dfs_node (RGraph *g, RGraphNode *n, RGraphVisitor *vis) { int *color; - - if (!g || !n || !vis) return; + if (!g || !n || !vis) { + return; + } color = R_NEWS0 (int, g->last_index); - if (!color) return; - dfs_node (g, n, vis, color); - free (color); + if (color) { + dfs_node (g, n, vis, color); + free (color); + } } R_API void r_graph_dfs (RGraph *g, RGraphVisitor *vis) { @@ -239,12 +249,17 @@ R_API void r_graph_dfs (RGraph *g, RGraphVisitor *vis) { RListIter *it; int *color; - if (!g || !vis) return; + if (!g || !vis) { + return; + } color = R_NEWS0 (int, g->last_index); - if (!color) return; + if (!color) { + return; + } r_list_foreach (g->nodes, it, n) { - if (color[n->idx] == WHITE_COLOR) - dfs_node (g, n, vis, color); + if (color[n->idx] == WHITE_COLOR) { + dfs_node (g, n, vis, color); + } } free (color); } diff --git a/libr/util/str.c b/libr/util/str.c index 041ad63635..3a15e8eaed 100644 --- a/libr/util/str.c +++ b/libr/util/str.c @@ -911,8 +911,8 @@ R_API char *r_str_prefix(char *ptr, const char *string) { } R_API char *r_str_concatlen(char *ptr, const char *string, int slen) { - char *ret, *msg = r_str_newlen (string, slen); - ret = r_str_concat (ptr, msg); + char *msg = r_str_newlen (string, slen); + char *ret = r_str_concat (ptr, msg); free (msg); return ret; } @@ -921,7 +921,6 @@ R_API char *r_str_concatlen(char *ptr, const char *string, int slen) { * first argument must be allocated * return: the pointer ptr resized to string size. */ -// TODO: use vararg here? R_API char *r_str_concat(char *ptr, const char *string) { int slen, plen; if (!string && !ptr) { @@ -966,7 +965,7 @@ R_API char *r_str_concatf(char *ptr, const char *fmt, ...) { } R_API char *r_str_concatch(char *x, char y) { - char b[2] = {y, 0}; + char b[2] = { y, 0 }; return r_str_concat (x,b); } diff --git a/sys/release-notes/config.json b/sys/release-notes/config.json index e4a8f25187..f41193fe9e 100644 --- a/sys/release-notes/config.json +++ b/sys/release-notes/config.json @@ -1,5 +1,5 @@ { - "previousRelease": "0.10.6", - "releaseVersion": "1.0.0", + "previousRelease": "1.0.2", + "releaseVersion": "1.1.0", "codeName": "potato" }