Rizin
unix-like reverse engineering framework and cli tools
agraph.c File Reference
#include <rz_core.h>
#include <rz_cons.h>
#include <rz_util/rz_graph_drawable.h>
#include <ht_pu.h>
#include <ctype.h>
#include <limits.h>
#include "core_private.h"

Go to the source code of this file.

Classes

struct  len_pos_t
 
struct  dist_t
 
struct  g_cb
 
struct  ascii_edge_t
 
struct  layer_t
 
struct  agraph_refresh_data
 
struct  rz_agraph_location
 
struct  tmplayer
 
struct  tmpbackedgeinfo
 

Macros

#define GRAPH_MERGE_FEATURE   0
 
#define BORDER   3
 
#define BORDER_WIDTH   4
 
#define BORDER_HEIGHT   3
 
#define MARGIN_TEXT_X   2
 
#define MARGIN_TEXT_Y   2
 
#define HORIZONTAL_NODE_SPACING   4
 
#define VERTICAL_NODE_SPACING   2
 
#define MIN_NODE_WIDTH   22
 
#define MIN_NODE_HEIGHT   BORDER_HEIGHT
 
#define TITLE_LEN   128
 
#define DEFAULT_SPEED   1
 
#define PAGEKEY_SPEED   (h / 2)
 
#define MINIGRAPH_NODE_TEXT_CUR   "<@@@@@@>"
 
#define MINIGRAPH_NODE_MIN_WIDTH   12
 
#define MINIGRAPH_NODE_TITLE_LEN   4
 
#define MINIGRAPH_NODE_CENTER_X   3
 
#define MININODE_MIN_WIDTH   16
 
#define ZOOM_STEP   10
 
#define ZOOM_DEFAULT   100
 
#define BODY_OFFSETS   0x1
 
#define BODY_SUMMARY   0x2
 
#define BODY_COMMENTS   0x4
 
#define NORMALIZE_MOV(x)   ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))
 
#define get_anode(gn)   ((gn) ? (RzANode *)(gn)->data : NULL)
 
#define graph_foreach_anode(list, it, pos, anode)
 
#define G(x, y)   rz_cons_canvas_gotoxy(g->can, x, y)
 
#define W(x)   rz_cons_canvas_write(g->can, x)
 
#define F(x, y, x2, y2, c)   rz_cons_canvas_fill(g->can, x, y, x2, y2, c)
 

Typedefs

typedef struct ascii_edge_t AEdge
 

Functions

static bool is_offset (const RzAGraph *g)
 
static bool is_mini (const RzAGraph *g)
 
static bool is_tiny (const RzAGraph *g)
 
static bool is_summary (const RzAGraph *g)
 
static bool is_comments (const RzAGraph *g)
 
static int next_mode (int mode)
 
static int prev_mode (int mode)
 
static RzGraphNodeagraph_get_title (const RzAGraph *g, RzANode *n, bool in)
 
static int mode2opts (const RzAGraph *g)
 
static void rotateAsmemu (RzCore *core)
 
static void showcursor (RzCore *core, int x)
 
static char * get_title (ut64 addr)
 
static void agraph_node_free (RzANode *n)
 
static int agraph_refresh (struct agraph_refresh_data *grd)
 
static void update_node_dimension (const RzGraph *g, int is_mini, int zoom, int edgemode, bool callgraph, int layout)
 
static void append_shortcut (const RzAGraph *g, char *title, char *nodetitle, int left)
 
static void mini_RzANode_print (const RzAGraph *g, const RzANode *n, int cur, bool details)
 
static void tiny_RzANode_print (const RzAGraph *g, const RzANode *n, int cur)
 
static char * get_node_color (int color, int cur)
 
static void normal_RzANode_print (const RzAGraph *g, const RzANode *n, int cur)
 
static int ** get_crossing_matrix (const RzGraph *g, const struct layer_t layers[], int maxlayer, int i, int from_up, int *n_rows)
 
static int layer_sweep (const RzGraph *g, const struct layer_t layers[], int maxlayer, int i, int from_up)
 
static void view_cyclic_edge (const RzGraphEdge *e, const RzGraphVisitor *vis)
 
static void view_dummy (const RzGraphEdge *e, const RzGraphVisitor *vis)
 
static void remove_cycles (RzAGraph *g)
 
static void add_sorted (RzGraphNode *n, RzGraphVisitor *vis)
 
static void assign_layers (const RzAGraph *g)
 
static int find_edge (const RzGraphEdge *a, const RzGraphEdge *b)
 
static bool is_reversed (const RzAGraph *g, const RzGraphEdge *e)
 
static void create_dummy_nodes (RzAGraph *g)
 
static void create_layers (RzAGraph *g)
 
static void minimize_crossings (const RzAGraph *g)
 
static int find_dist (const struct dist_t *a, const struct dist_t *b)
 
static int dist_nodes (const RzAGraph *g, const RzGraphNode *a, const RzGraphNode *b)
 
static void set_dist_nodes (const RzAGraph *g, int l, int cur, int next)
 
static int is_valid_pos (const RzAGraph *g, int l, int pos)
 
static void free_vertical_nodes_kv (HtPPKv *kv)
 
static HtPP * compute_vertical_nodes (const RzAGraph *g)
 
static RzList ** compute_classes (const RzAGraph *g, HtPP *v_nodes, int is_left, int *n_classes)
 
static int cmp_dist (const size_t a, const size_t b)
 
static RzGraphNodeget_sibling (const RzAGraph *g, const RzANode *n, int is_left, int is_adjust_class)
 
static int hash_get_int (HtPU *ht, const void *key)
 
static int adjust_class_val (const RzAGraph *g, const RzGraphNode *gn, const RzGraphNode *sibl, HtPU *res, int is_left)
 
static void adjust_class (const RzAGraph *g, int is_left, RzList **classes, HtPU *res, int c)
 
static int place_nodes_val (const RzAGraph *g, const RzGraphNode *gn, const RzGraphNode *sibl, HtPU *res, int is_left)
 
static int place_nodes_sel_p (int newval, int oldval, int is_first, int is_left)
 
static void place_nodes (const RzAGraph *g, const RzGraphNode *gn, int is_left, HtPP *v_nodes, RzList **classes, HtPU *res, SetP *placed)
 
static HtPU * compute_pos (const RzAGraph *g, int is_left, HtPP *v_nodes)
 
static void place_dummies (const RzAGraph *g)
 
static RzGraphNodeget_right_dummy (const RzAGraph *g, const RzGraphNode *n)
 
static void adjust_directions (const RzAGraph *g, int i, int from_up, HtPU *D, HtPU *P)
 
static void place_single (const RzAGraph *g, int l, const RzGraphNode *bm, const RzGraphNode *bp, int from_up, int va)
 
static int RM_listcmp (const struct len_pos_t *a, const struct len_pos_t *b)
 
static int RP_listcmp (const struct len_pos_t *a, const struct len_pos_t *b)
 
static void collect_changes (const RzAGraph *g, int l, const RzGraphNode *b, int from_up, int s, int e, RzList *list, int is_left)
 
static void combine_sequences (const RzAGraph *g, int l, const RzGraphNode *bm, const RzGraphNode *bp, int from_up, int a, int r)
 
static void place_sequence (const RzAGraph *g, int l, const RzGraphNode *bm, const RzGraphNode *bp, int from_up, int va, int vr)
 
static void original_traverse_l (const RzAGraph *g, HtPU *D, HtPU *P, int from_up)
 
static void place_original (RzAGraph *g)
 
static void set_layer_gap (RzAGraph *g)
 
static void fix_back_edge_dummy_nodes (RzAGraph *g, RzANode *from, RzANode *to)
 
static int get_edge_number (const RzAGraph *g, RzANode *src, RzANode *dst, bool outgoing)
 
static int count_edges (const RzAGraph *g, RzANode *src, RzANode *dst)
 
static void backedge_info (RzAGraph *g)
 
static void agraph_edge_free (AEdge *e)
 
static void set_layout (RzAGraph *g)
 
static char * get_body (RzCore *core, ut64 addr, int size, int opts)
 
static char * get_bb_body (RzCore *core, RzAnalysisBlock *b, int opts, RzAnalysisFunction *fcn, bool emu, ut64 saved_gp, ut8 *saved_arena)
 
static int bbcmp (RzAnalysisBlock *a, RzAnalysisBlock *b)
 
static void get_bbupdate (RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
 
static void fold_asm_trace (RzCore *core, RzAGraph *g)
 
static void delete_dup_edges (RzAGraph *g)
 
static bool isbbfew (RzAnalysisBlock *curbb, RzAnalysisBlock *bb)
 
static int get_bbnodes (RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
 
static bool get_cgnodes (RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
 
static bool reload_nodes (RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
 
static void update_seek (RzConsCanvas *can, RzANode *n, int force)
 
static int is_near (const RzANode *n, int x, int y, int is_next)
 
static int is_near_h (const RzANode *n, int x, int y, int is_next)
 XXX is wrong. More...
 
static const RzGraphNodefind_near_of (const RzAGraph *g, const RzGraphNode *cur, int is_next)
 
static void update_graph_sizes (RzAGraph *g)
 
RZ_API void rz_agraph_set_curnode (RzAGraph *g, RzANode *a)
 
static ut64 rebase (RzAGraph *g, int v)
 
static void agraph_set_layout (RzAGraph *g)
 
static void agraph_update_seek (RzAGraph *g, RzANode *n, int force)
 
static void agraph_print_node (const RzAGraph *g, RzANode *n)
 
static void agraph_print_nodes (const RzAGraph *g)
 
int tmplayercmp (const void *a, const void *b)
 
static void agraph_print_edges_simple (RzAGraph *g)
 
static int first_x_cmp (const void *_a, const void *_b)
 
static void agraph_print_edges (RzAGraph *g)
 
static void agraph_toggle_callgraph (RzAGraph *g)
 
static void agraph_set_zoom (RzAGraph *g, int v)
 
static bool agraph_reload_nodes (RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
 
static void follow_nth (RzAGraph *g, int nth)
 
static void move_current_node (RzAGraph *g, int xdiff, int ydiff)
 
static void agraph_toggle_tiny (RzAGraph *g)
 
static void agraph_toggle_mini (RzAGraph *g)
 
static void agraph_follow_innodes (RzAGraph *g, bool in)
 
static void agraph_follow_true (RzAGraph *g)
 
static void agraph_follow_false (RzAGraph *g)
 
static void agraph_next_node (RzAGraph *g)
 
static void agraph_prev_node (RzAGraph *g)
 
static void agraph_update_title (RzCore *core, RzAGraph *g, RzAnalysisFunction *fcn)
 
static bool check_changes (RzAGraph *g, int is_interactive, RzCore *core, RzAnalysisFunction *fcn)
 
static int agraph_print (RzAGraph *g, int is_interactive, RzCore *core, RzAnalysisFunction *fcn)
 
static void check_function_modified (RzCore *core, RzAnalysisFunction *fcn)
 
static void agraph_refresh_oneshot (struct agraph_refresh_data *grd)
 
static void agraph_set_need_reload_nodes (struct agraph_refresh_data *grd)
 
static void agraph_toggle_speed (RzAGraph *g, RzCore *core)
 
static void free_nodes_kv (HtPPKv *kv)
 
static void agraph_init (RzAGraph *g)
 
static void graphNodeMove (RzAGraph *g, int dir, int speed)
 
static void sdb_set_enc (Sdb *db, const char *key, const char *v, ut32 cas)
 
static void agraph_sdb_init (const RzAGraph *g)
 
RZ_API Sdbrz_agraph_get_sdb (RzAGraph *g)
 
RZ_API void rz_agraph_print (RzAGraph *g)
 
RZ_API void rz_agraph_print_json (RzAGraph *g, PJ *pj)
 
RZ_API void rz_agraph_set_title (RzAGraph *g, const char *title)
 
RZ_API RzANoderz_agraph_add_node_with_color (const RzAGraph *g, const char *title, const char *body, int color)
 
RZ_API RzANoderz_agraph_add_node (const RzAGraph *g, const char *title, const char *body)
 
RZ_API bool rz_agraph_del_node (const RzAGraph *g, const char *title)
 
static bool user_node_cb (struct g_cb *user, RZ_UNUSED const void *k, const void *v)
 
static bool user_edge_cb (struct g_cb *user, RZ_UNUSED const void *k, const void *v)
 
RZ_API void rz_agraph_foreach (RzAGraph *g, RzANodeCallback cb, void *user)
 
RZ_API void rz_agraph_foreach_edge (RzAGraph *g, RAEdgeCallback cb, void *user)
 
RZ_API RzANoderz_agraph_get_first_node (const RzAGraph *g)
 
RZ_API RzANoderz_agraph_get_node (const RzAGraph *g, const char *title)
 
RZ_API void rz_agraph_add_edge (const RzAGraph *g, RzANode *a, RzANode *b)
 
RZ_API void rz_agraph_add_edge_at (const RzAGraph *g, RzANode *a, RzANode *b, int nth)
 
RZ_API void rz_agraph_del_edge (const RzAGraph *g, RzANode *a, RzANode *b)
 
RZ_API void rz_agraph_reset (RzAGraph *g)
 
RZ_API void rz_agraph_free (RzAGraph *g)
 
RZ_API RzAGraphrz_agraph_new (RzConsCanvas *can)
 
static void visual_offset (RzAGraph *g, RzCore *core)
 
static void goto_asmqjmps (RzAGraph *g, RzCore *core)
 
static void seek_to_node (RzANode *n, RzCore *core)
 
static void graph_single_step_in (RzCore *core, RzAGraph *g)
 
static void graph_single_step_over (RzCore *core, RzAGraph *g)
 
static void graph_breakpoint (RzCore *core)
 
static void graph_continue (RzCore *core)
 
static void applyDisMode (RzCore *core)
 
static void rotateColor (RzCore *core)
 
static char * get_graph_string (RzCore *core, RzAGraph *g)
 
static void nextword (RzCore *core, RzAGraph *g, const char *word)
 
RZ_API int rz_core_visual_graph (RzCore *core, RzAGraph *g, RzAnalysisFunction *_fcn, int is_interactive)
 
RZ_API RzAGraphcreate_agraph_from_graph (const RzGraph *graph)
 Create RzAGraph from generic RzGraph with RzGraphNodeInfo as node data. More...
 

Variables

static int mousemode = 0
 
static int disMode = 0
 
static int discroll = 0
 
static bool graphCursor = false
 
static const char * mousemodes []
 
static HtPPOptions nodes_opt
 

Macro Definition Documentation

◆ BODY_COMMENTS

#define BODY_COMMENTS   0x4

Definition at line 51 of file agraph.c.

◆ BODY_OFFSETS

#define BODY_OFFSETS   0x1

Definition at line 49 of file agraph.c.

◆ BODY_SUMMARY

#define BODY_SUMMARY   0x2

Definition at line 50 of file agraph.c.

◆ BORDER

#define BORDER   3

Definition at line 27 of file agraph.c.

◆ BORDER_HEIGHT

#define BORDER_HEIGHT   3

Definition at line 29 of file agraph.c.

◆ BORDER_WIDTH

#define BORDER_WIDTH   4

Definition at line 28 of file agraph.c.

◆ DEFAULT_SPEED

#define DEFAULT_SPEED   1

Definition at line 37 of file agraph.c.

◆ F

#define F (   x,
  y,
  x2,
  y2,
  c 
)    rz_cons_canvas_fill(g->can, x, y, x2, y2, c)

Definition at line 111 of file agraph.c.

◆ G

#define G (   x,
 
)    rz_cons_canvas_gotoxy(g->can, x, y)

Definition at line 109 of file agraph.c.

◆ get_anode

#define get_anode (   gn)    ((gn) ? (RzANode *)(gn)->data : NULL)

Definition at line 56 of file agraph.c.

◆ graph_foreach_anode

#define graph_foreach_anode (   list,
  it,
  pos,
  anode 
)
Value:
if (list) \
for ((it) = (list)->head; (it) && ((pos) = (it)->data) && (pos) && ((anode) = (RzANode *)(pos)->data); (it) = (it)->n)
static void list(RzEgg *egg)
Definition: rz-gg.c:52
int pos
Definition: main.c:11

Definition at line 58 of file agraph.c.

◆ GRAPH_MERGE_FEATURE

#define GRAPH_MERGE_FEATURE   0

Definition at line 25 of file agraph.c.

◆ HORIZONTAL_NODE_SPACING

#define HORIZONTAL_NODE_SPACING   4

Definition at line 32 of file agraph.c.

◆ MARGIN_TEXT_X

#define MARGIN_TEXT_X   2

Definition at line 30 of file agraph.c.

◆ MARGIN_TEXT_Y

#define MARGIN_TEXT_Y   2

Definition at line 31 of file agraph.c.

◆ MIN_NODE_HEIGHT

#define MIN_NODE_HEIGHT   BORDER_HEIGHT

Definition at line 35 of file agraph.c.

◆ MIN_NODE_WIDTH

#define MIN_NODE_WIDTH   22

Definition at line 34 of file agraph.c.

◆ MINIGRAPH_NODE_CENTER_X

#define MINIGRAPH_NODE_CENTER_X   3

Definition at line 43 of file agraph.c.

◆ MINIGRAPH_NODE_MIN_WIDTH

#define MINIGRAPH_NODE_MIN_WIDTH   12

Definition at line 41 of file agraph.c.

◆ MINIGRAPH_NODE_TEXT_CUR

#define MINIGRAPH_NODE_TEXT_CUR   "<@@@@@@>"

Definition at line 40 of file agraph.c.

◆ MINIGRAPH_NODE_TITLE_LEN

#define MINIGRAPH_NODE_TITLE_LEN   4

Definition at line 42 of file agraph.c.

◆ MININODE_MIN_WIDTH

#define MININODE_MIN_WIDTH   16

Definition at line 44 of file agraph.c.

◆ NORMALIZE_MOV

#define NORMALIZE_MOV (   x)    ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))

Definition at line 53 of file agraph.c.

◆ PAGEKEY_SPEED

#define PAGEKEY_SPEED   (h / 2)

Definition at line 38 of file agraph.c.

◆ TITLE_LEN

#define TITLE_LEN   128

Definition at line 36 of file agraph.c.

◆ VERTICAL_NODE_SPACING

#define VERTICAL_NODE_SPACING   2

Definition at line 33 of file agraph.c.

◆ W

#define W (   x)    rz_cons_canvas_write(g->can, x)

Definition at line 110 of file agraph.c.

◆ ZOOM_DEFAULT

#define ZOOM_DEFAULT   100

Definition at line 47 of file agraph.c.

◆ ZOOM_STEP

#define ZOOM_STEP   10

Definition at line 46 of file agraph.c.

Typedef Documentation

◆ AEdge

typedef struct ascii_edge_t AEdge

Function Documentation

◆ add_sorted()

static void add_sorted ( RzGraphNode n,
RzGraphVisitor vis 
)
static

Definition at line 649 of file agraph.c.

649  {
650  RzList *l = (RzList *)vis->data;
651  rz_list_prepend(l, n);
652 }
RZ_API RZ_BORROW RzListIter * rz_list_prepend(RZ_NONNULL RzList *list, void *data)
Appends at the beginning of the list a new element.
Definition: list.c:316
int n
Definition: mipsasm.c:19

References rz_graph_visitor_t::data, n, and rz_list_prepend().

Referenced by assign_layers().

◆ adjust_class()

static void adjust_class ( const RzAGraph g,
int  is_left,
RzList **  classes,
HtPU *  res,
int  c 
)
static

Definition at line 1047 of file agraph.c.

1047  {
1048  const RzGraphNode *gn;
1049  const RzListIter *it;
1050  const RzANode *an;
1051  int dist = INT_MAX, v, is_first = true;
1052 
1053  graph_foreach_anode (classes[c], it, gn, an) {
1054  const RzGraphNode *sibling;
1055  const RzANode *sibl_anode;
1056 
1057  sibling = get_sibling(g, an, is_left, true);
1058  if (!sibling) {
1059  continue;
1060  }
1061  sibl_anode = get_anode(sibling);
1062  if (sibl_anode->klass == c) {
1063  continue;
1064  }
1065  v = adjust_class_val(g, gn, sibling, res, is_left);
1066  dist = is_first ? v : RZ_MIN(dist, v);
1067  is_first = false;
1068  }
1069 
1070  if (is_first) {
1071  RzList *heap = rz_list_new();
1072  int len;
1073 
1074  graph_foreach_anode (classes[c], it, gn, an) {
1075  const RzList *neigh = rz_graph_all_neighbours(g->graph, gn);
1076  const RzGraphNode *gk;
1077  const RzListIter *itk;
1078  const RzANode *ak;
1079 
1080  graph_foreach_anode (neigh, itk, gk, ak) {
1081  if (ak->klass < c) {
1082  size_t d = (ak->x - an->x);
1083  if (d > 0) {
1084  rz_list_append(heap, (void *)d);
1085  }
1086  }
1087  }
1088  }
1089 
1090  len = rz_list_length(heap);
1091  if (len == 0) {
1092  dist = 0;
1093  } else {
1095  dist = (int)(size_t)rz_list_get_n(heap, len / 2);
1096  }
1097 
1098  rz_list_free(heap);
1099  }
1100 
1101  graph_foreach_anode (classes[c], it, gn, an) {
1102  const int old_val = hash_get_int(res, gn);
1103  const int new_val = is_left ? old_val + dist : old_val - dist;
1104  ht_pu_update(res, gn, (ut64)(size_t)new_val);
1105  }
1106 }
size_t len
Definition: 6502dis.c:15
static int hash_get_int(HtPU *ht, const void *key)
Definition: agraph.c:1029
#define graph_foreach_anode(list, it, pos, anode)
Definition: agraph.c:58
static int cmp_dist(const size_t a, const size_t b)
Definition: agraph.c:1009
static RzGraphNode * get_sibling(const RzAGraph *g, const RzANode *n, int is_left, int is_adjust_class)
Definition: agraph.c:1013
#define get_anode(gn)
Definition: agraph.c:56
static int adjust_class_val(const RzAGraph *g, const RzGraphNode *gn, const RzGraphNode *sibl, HtPU *res, int is_left)
Definition: agraph.c:1038
static RzList * classes(RzBinFile *bf)
Definition: bin_dex.c:71
#define INT_MAX
Definition: cp-demangle.c:131
const char * v
Definition: dsignal.c:12
struct @667 g
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API const RzList * rz_graph_all_neighbours(const RzGraph *g, const RzGraphNode *n)
Definition: graph.c:261
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
#define RZ_MIN(x, y)
static int
Definition: sfsocketcall.h:114
#define d(i)
Definition: sha256.c:44
#define c(i)
Definition: sha256.c:43
Definition: heap-inl.h:40
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References adjust_class_val(), c, classes(), cmp_dist(), d, dist_t::dist, g, get_anode, get_sibling(), graph_foreach_anode, hash_get_int(), int, INT_MAX, rz_ascii_node_t::klass, len, rz_graph_all_neighbours(), rz_list_append(), rz_list_free(), rz_list_get_n(), rz_list_length(), rz_list_new(), rz_list_sort(), RZ_MIN, ut64(), v, and rz_ascii_node_t::x.

Referenced by compute_pos().

◆ adjust_class_val()

static int adjust_class_val ( const RzAGraph g,
const RzGraphNode gn,
const RzGraphNode sibl,
HtPU *  res,
int  is_left 
)
static

Definition at line 1038 of file agraph.c.

1038  {
1039  if (is_left) {
1040  return hash_get_int(res, sibl) - hash_get_int(res, gn) - dist_nodes(g, gn, sibl);
1041  }
1042  return hash_get_int(res, gn) - hash_get_int(res, sibl) - dist_nodes(g, sibl, gn);
1043 }
static int dist_nodes(const RzAGraph *g, const RzGraphNode *a, const RzGraphNode *b)
Definition: agraph.c:825

References dist_nodes(), g, and hash_get_int().

Referenced by adjust_class().

◆ adjust_directions()

static void adjust_directions ( const RzAGraph g,
int  i,
int  from_up,
HtPU *  D,
HtPU *  P 
)
static

Definition at line 1259 of file agraph.c.

1259  {
1260  const RzGraphNode *vm = NULL, *wm = NULL;
1261  const RzANode *vma = NULL, *wma = NULL;
1262  int j, d = from_up ? 1 : -1;
1263 
1264  if (i + d < 0 || i + d >= g->n_layers) {
1265  return;
1266  }
1267  for (j = 0; j < g->layers[i + d].n_nodes; j++) {
1268  const RzGraphNode *wp, *vp = g->layers[i + d].nodes[j];
1269  const RzANode *wpa, *vpa = get_anode(vp);
1270 
1271  if (!vpa || !vpa->is_dummy) {
1272  continue;
1273  }
1274  if (from_up) {
1275  wp = rz_list_get_n(rz_graph_innodes(g->graph, vp), 0);
1276  } else {
1277  wp = rz_graph_nth_neighbour(g->graph, vp, 0);
1278  }
1279  wpa = get_anode(wp);
1280  if (!wpa || !wpa->is_dummy) {
1281  continue;
1282  }
1283  if (vm) {
1284  int p = hash_get_int(P, wm);
1285  int k;
1286 
1287  for (k = wma->pos_in_layer + 1; k < wpa->pos_in_layer; k++) {
1288  const RzGraphNode *w = g->layers[wma->layer].nodes[k];
1289  const RzANode *aw = get_anode(w);
1290  if (aw && aw->is_dummy) {
1291  p &= hash_get_int(P, w);
1292  }
1293  }
1294  if (p) {
1295  ht_pu_update(D, vm, (ut64)(size_t)from_up);
1296  for (k = vma->pos_in_layer + 1; k < vpa->pos_in_layer; k++) {
1297  const RzGraphNode *v = g->layers[vma->layer].nodes[k];
1298  const RzANode *av = get_anode(v);
1299  if (av && av->is_dummy) {
1300  ht_pu_update(D, v, (ut64)(size_t)from_up);
1301  }
1302  }
1303  }
1304  }
1305  vm = vp;
1306  wm = wp;
1307  vma = get_anode(vm);
1308  wma = get_anode(wm);
1309  }
1310 }
lzma_index ** i
Definition: index.h:629
#define D
Definition: block.c:38
#define P
#define NULL
Definition: cris-opc.c:27
#define w
Definition: crypto_rc6.c:13
const char * k
Definition: dsignal.c:11
void * p
Definition: libc.cpp:67
RZ_API RzGraphNode * rz_graph_nth_neighbour(const RzGraph *g, const RzGraphNode *n, int nth)
Definition: graph.c:251
RZ_API const RzList * rz_graph_innodes(const RzGraph *g, const RzGraphNode *n)
Definition: graph.c:256

References D, d, g, get_anode, hash_get_int(), i, rz_ascii_node_t::is_dummy, k, rz_ascii_node_t::layer, NULL, P, p, rz_ascii_node_t::pos_in_layer, rz_graph_innodes(), rz_graph_nth_neighbour(), rz_list_get_n(), ut64(), v, and w.

Referenced by original_traverse_l().

◆ agraph_edge_free()

static void agraph_edge_free ( AEdge e)
static

Definition at line 1946 of file agraph.c.

1946  {
1947  rz_list_free(e->x);
1948  rz_list_free(e->y);
1949  free(e);
1950 }
#define e(frag)
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References e, free(), and rz_list_free().

Referenced by set_layout().

◆ agraph_follow_false()

static void agraph_follow_false ( RzAGraph g)
static

Definition at line 3325 of file agraph.c.

3325  {
3326  follow_nth(g, 1);
3327  agraph_update_seek(g, get_anode(g->curnode), false);
3328 }
static void agraph_update_seek(RzAGraph *g, RzANode *n, int force)
Definition: agraph.c:2738
static void follow_nth(RzAGraph *g, int nth)
Definition: agraph.c:3183

References agraph_update_seek(), follow_nth(), g, and get_anode.

Referenced by rz_core_visual_graph().

◆ agraph_follow_innodes()

static void agraph_follow_innodes ( RzAGraph g,
bool  in 
)
static

Definition at line 3258 of file agraph.c.

3258  {
3259  int count = 0;
3260  RzListIter *iter;
3261  RzANode *an = get_anode(g->curnode);
3262  if (!an) {
3263  return;
3264  }
3265  const RzList *list = in ? an->gnode->in_nodes : an->gnode->out_nodes;
3266  int nth = -1;
3267  if (rz_list_length(list) == 0) {
3268  return;
3269  }
3270  rz_cons_gotoxy(0, 2);
3271  rz_cons_printf(in ? "Input nodes:\n" : "Output nodes:\n");
3273  RzList *gnodes = in ? an->gnode->in_nodes : an->gnode->out_nodes;
3274  RzGraphNode *gn;
3275  rz_list_foreach (gnodes, iter, gn) {
3276  RzANode *an = get_anode(gn);
3277  RzGraphNode *gnn = agraph_get_title(g, an, in);
3278  if (gnn) {
3279  RzANode *nnn = gnn->data;
3280  RzANode *o;
3281  RzListIter *iter2;
3282  // avoid dupes
3283  rz_list_foreach (options, iter2, o) {
3284  if (!strcmp(o->title, nnn->title)) {
3285  continue;
3286  }
3287  }
3288  rz_cons_printf("%d %s\n", count, nnn->title);
3289  rz_list_append(options, nnn);
3290  count++;
3291  }
3292  }
3293  rz_cons_flush();
3294  if (rz_list_length(list) == 1) {
3295  nth = 0;
3296  } else if (rz_list_length(list) < 10) {
3297  // just 1 key
3298  char ch = rz_cons_readchar();
3299  if (ch >= '0' && ch <= '9') {
3300  nth = ch - '0';
3301  }
3302  } else {
3303  rz_cons_show_cursor(true);
3304  rz_cons_enable_mouse(false);
3305  char *nth_string = rz_cons_input("index> ");
3306  nth = atoi(nth_string);
3307  if (nth == 0 && *nth_string != '0') {
3308  nth = -1;
3309  }
3310  free(nth_string);
3311  }
3312  if (nth != -1) {
3313  RzANode *selected_node = rz_list_get_n(options, nth);
3314  rz_agraph_set_curnode(g, selected_node);
3315  }
3317  agraph_update_seek(g, get_anode(g->curnode), false);
3318 }
static RzGraphNode * agraph_get_title(const RzAGraph *g, RzANode *n, bool in)
Definition: agraph.c:141
RZ_API void rz_agraph_set_curnode(RzAGraph *g, RzANode *a)
Definition: agraph.c:2696
const lzma_allocator const uint8_t * in
Definition: block.h:527
RZ_API bool rz_cons_enable_mouse(const bool enable)
Definition: cons.c:500
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
RZ_API void rz_cons_show_cursor(int cursor)
Definition: cons.c:1581
RZ_API void rz_cons_flush(void)
Definition: cons.c:959
RZ_API void rz_cons_gotoxy(int x, int y)
Definition: cons.c:724
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
RZ_API char * rz_cons_input(const char *msg)
Definition: input.c:696
RZ_API int rz_cons_readchar(void)
Definition: input.c:619
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
char * title
Definition: rz_agraph.h:10
RzGraphNode * gnode
Definition: rz_agraph.h:9
void * data
Definition: rz_graph.h:12
RzList * out_nodes
Definition: rz_graph.h:13
RzList * in_nodes
Definition: rz_graph.h:14

References agraph_get_title(), agraph_update_seek(), count, rz_graph_node_t::data, free(), g, get_anode, rz_ascii_node_t::gnode, in, rz_graph_node_t::in_nodes, list(), NULL, options, rz_graph_node_t::out_nodes, rz_agraph_set_curnode(), rz_cons_enable_mouse(), rz_cons_flush(), rz_cons_gotoxy(), rz_cons_input(), rz_cons_printf(), rz_cons_readchar(), rz_cons_show_cursor(), rz_list_append(), rz_list_free(), rz_list_get_n(), rz_list_length(), rz_list_newf(), and rz_ascii_node_t::title.

Referenced by rz_core_visual_graph().

◆ agraph_follow_true()

static void agraph_follow_true ( RzAGraph g)
static

Definition at line 3320 of file agraph.c.

3320  {
3321  follow_nth(g, 0);
3322  agraph_update_seek(g, get_anode(g->curnode), false);
3323 }

References agraph_update_seek(), follow_nth(), g, and get_anode.

Referenced by rz_core_visual_graph().

◆ agraph_get_title()

static RzGraphNode* agraph_get_title ( const RzAGraph g,
RzANode n,
bool  in 
)
static

Definition at line 141 of file agraph.c.

141  {
142  if (!n) {
143  return NULL;
144  }
145  if (n->title && *n->title) {
146  return n->gnode;
147  }
148  const RzList *outnodes = in ? n->gnode->in_nodes : n->gnode->out_nodes;
149  RzGraphNode *gn;
150  RzListIter *iter;
151 
152  rz_list_foreach (outnodes, iter, gn) {
153  RzANode *an = gn->data;
154  return agraph_get_title(g, an, in);
155  }
156  return NULL;
157 }

References rz_graph_node_t::data, g, in, n, and NULL.

Referenced by agraph_follow_innodes().

◆ agraph_init()

static void agraph_init ( RzAGraph g)
static

Definition at line 3619 of file agraph.c.

3619  {
3620  g->is_callgraph = false;
3621  g->is_instep = false;
3622  g->need_reload_nodes = true;
3623  g->show_node_titles = true;
3624  g->show_node_body = true;
3625  g->force_update_seek = true;
3626  g->graph = rz_graph_new();
3627  g->nodes = ht_pp_new_opt(&nodes_opt);
3628  g->dummy_nodes = rz_list_newf((RzListFree)agraph_node_free);
3629  g->edgemode = 2;
3630  g->zoom = ZOOM_DEFAULT;
3631  g->hints = 1;
3632  g->movspeed = DEFAULT_SPEED;
3633  g->db = sdb_new0();
3634  rz_vector_init(&g->ghits.word_list, sizeof(struct rz_agraph_location), NULL, NULL);
3635 }
#define ZOOM_DEFAULT
Definition: agraph.c:47
static void agraph_node_free(RzANode *n)
Definition: agraph.c:204
static HtPPOptions nodes_opt
Definition: agraph.c:3608
#define DEFAULT_SPEED
Definition: agraph.c:37
RZ_API RzGraph * rz_graph_new(void)
Definition: graph.c:108
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
RZ_API Sdb * sdb_new0(void)
Definition: sdb.c:43

References agraph_node_free(), DEFAULT_SPEED, g, nodes_opt, NULL, rz_graph_new(), rz_list_newf(), rz_vector_init(), sdb_new0(), and ZOOM_DEFAULT.

Referenced by rz_agraph_new().

◆ agraph_next_node()

static void agraph_next_node ( RzAGraph g)
static

Definition at line 3331 of file agraph.c.

3331  {
3332  RzANode *a = get_anode(find_near_of(g, g->curnode, true));
3333  while (a && a->is_dummy) {
3334  a = get_anode(find_near_of(g, a->gnode, true));
3335  }
3337  agraph_update_seek(g, get_anode(g->curnode), false);
3338 }
static const RzGraphNode * find_near_of(const RzAGraph *g, const RzGraphNode *cur, int is_next)
Definition: agraph.c:2550
#define a(i)
Definition: sha256.c:41

References a, agraph_update_seek(), find_near_of(), g, get_anode, and rz_agraph_set_curnode().

Referenced by rz_core_visual_graph().

◆ agraph_node_free()

static void agraph_node_free ( RzANode n)
static

Definition at line 204 of file agraph.c.

204  {
205  free(n->title);
206  free(n->body);
207  free(n);
208 }

References free(), and n.

Referenced by agraph_init(), free_nodes_kv(), and rz_agraph_reset().

◆ agraph_prev_node()

static void agraph_prev_node ( RzAGraph g)
static

Definition at line 3341 of file agraph.c.

3341  {
3342  RzANode *a = get_anode(find_near_of(g, g->curnode, false));
3343  while (a && a->is_dummy) {
3344  a = get_anode(find_near_of(g, a->gnode, false));
3345  }
3347  agraph_update_seek(g, get_anode(g->curnode), false);
3348 }

References a, agraph_update_seek(), find_near_of(), g, get_anode, and rz_agraph_set_curnode().

Referenced by rz_core_visual_graph().

◆ agraph_print()

static int agraph_print ( RzAGraph g,
int  is_interactive,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 3431 of file agraph.c.

3431  {
3432  int h, w = rz_cons_get_size(&h);
3433  bool ret = check_changes(g, is_interactive, core, fcn);
3434  if (!ret) {
3435  return false;
3436  }
3437 
3438  if (is_interactive) {
3439  rz_cons_clear00();
3440  } else {
3441  /* TODO: limit to screen size when the output is not redirected to file */
3443  }
3444 
3445  h = is_interactive ? h : g->h + 1;
3446  w = is_interactive ? w : g->w + 2;
3447  if (!rz_cons_canvas_resize(g->can, w, h)) {
3448  return false;
3449  }
3450  // rz_cons_canvas_clear (g->can);
3451  if (!is_interactive) {
3452  g->can->sx = -g->x;
3453  g->can->sy = -g->y - 1;
3454  }
3455  if (g->is_dis) {
3456  (void)G(-g->can->sx + 1, -g->can->sy + 2);
3457  int scr_utf8 = rz_config_get_i(core->config, "scr.utf8");
3458  int asm_bytes = rz_config_get_i(core->config, "asm.bytes");
3459  int asm_cmt_right = rz_config_get_i(core->config, "asm.cmt.right");
3460  rz_config_set_i(core->config, "scr.utf8", 0);
3461  rz_config_set_i(core->config, "asm.bytes", 0);
3462  rz_config_set_i(core->config, "asm.cmt.right", 0);
3463  char *str = rz_core_cmd_str(core, "pd $r");
3464  if (str) {
3465  W(str);
3466  free(str);
3467  }
3468  rz_config_set_i(core->config, "scr.utf8", scr_utf8);
3469  rz_config_set_i(core->config, "asm.bytes", asm_bytes);
3470  rz_config_set_i(core->config, "asm.cmt.right", asm_cmt_right);
3471  }
3472  if (g->title && *g->title) {
3473  g->can->sy++;
3474  }
3477  if (g->title && *g->title) {
3478  g->can->sy--;
3479  }
3480  /* print the graph title */
3481  (void)G(-g->can->sx, -g->can->sy);
3482  if (!g->is_tiny) {
3483  W(g->title);
3484  }
3485  if (is_interactive && g->title) {
3486  int title_len = strlen(g->title);
3487  rz_cons_canvas_fill(g->can, -g->can->sx + title_len, -g->can->sy,
3488  w - title_len, 1, ' ');
3489  }
3490 
3492 
3493  if (is_interactive) {
3494  rz_cons_newline();
3495  const char *cmdv = rz_config_get(core->config, "cmd.gprompt");
3496  bool mustFlush = false;
3498  if (cmdv && *cmdv) {
3499  rz_cons_gotoxy(0, 2);
3501  rz_core_cmd0(core, cmdv);
3502  mustFlush = true;
3503  }
3504  if (core && core->scr_gadgets) {
3505  rz_core_gadget_print(core);
3506  }
3507  if (mustFlush) {
3508  rz_cons_flush();
3509  }
3510  }
3511  return true;
3512 }
static void agraph_print_edges(RzAGraph *g)
Definition: agraph.c:2849
static bool check_changes(RzAGraph *g, int is_interactive, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:3364
static void update_graph_sizes(RzAGraph *g)
Definition: agraph.c:2588
static void agraph_print_nodes(const RzAGraph *g)
Definition: agraph.c:2758
#define W(x)
Definition: agraph.c:110
#define G(x, y)
Definition: agraph.c:109
RZ_API void rz_cons_canvas_print_region(RzConsCanvas *c)
Definition: canvas.c:410
RZ_API void rz_cons_canvas_fill(RzConsCanvas *c, int x, int y, int w, int h, char ch)
Definition: canvas.c:551
RZ_API int rz_cons_canvas_resize(RzConsCanvas *c, int w, int h)
Definition: canvas.c:432
RZ_API int rz_core_cmd0(RzCore *core, const char *cmd)
Definition: cmd.c:5428
RZ_API char * rz_core_cmd_str(RzCore *core, const char *cmd)
Executes a rizin command and returns the stdout as a string.
Definition: cmd.c:5513
RZ_API void rz_core_gadget_print(RzCore *core)
Prints or displays the print gadgets while in visual mode.
Definition: cmd_print.c:1185
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
RZ_API RzConfigNode * rz_config_set_i(RzConfig *cfg, RZ_NONNULL const char *name, const ut64 i)
Definition: config.c:419
RZ_API RZ_BORROW const char * rz_config_get(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:75
RZ_API void rz_cons_clear00(void)
Definition: cons.c:778
RZ_API int rz_cons_get_size(int *rows)
Definition: cons.c:1446
RZ_API void rz_cons_strcat(const char *str)
Definition: cons.c:1263
RZ_API void rz_cons_newline(void)
Definition: cons.c:1274
RZ_API void rz_cons_visual_flush(void)
Definition: cons.c:1067
#define Color_RESET
Definition: rz_cons.h:617
#define h(i)
Definition: sha256.c:48
bool scr_gadgets
Definition: rz_core.h:385
RzConfig * config
Definition: rz_core.h:300

References agraph_print_edges(), agraph_print_nodes(), check_changes(), Color_RESET, rz_core_t::config, free(), G, g, h, rz_config_get(), rz_config_get_i(), rz_config_set_i(), rz_cons_canvas_fill(), rz_cons_canvas_print_region(), rz_cons_canvas_resize(), rz_cons_clear00(), rz_cons_flush(), rz_cons_get_size(), rz_cons_gotoxy(), rz_cons_newline(), rz_cons_strcat(), rz_cons_visual_flush(), rz_core_cmd0(), rz_core_cmd_str(), rz_core_gadget_print(), rz_core_t::scr_gadgets, cmd_descs_generate::str, update_graph_sizes(), W, and w.

Referenced by agraph_refresh(), and rz_agraph_print().

◆ agraph_print_edges()

static void agraph_print_edges ( RzAGraph g)
static

Definition at line 2849 of file agraph.c.

2849  {
2850  if (!g->edgemode) {
2851  return;
2852  }
2853  if (g->edgemode == 1) {
2855  return;
2856  }
2857  int out_nth, in_nth, bendpoint;
2858  RzListIter *itn, *itm, *ito;
2859  RzCanvasLineStyle style = { 0 };
2860  const RzList *nodes = rz_graph_get_nodes(g->graph);
2861  RzGraphNode *ga;
2862  RzANode *a;
2863 
2864  RzList *lyr = rz_list_new();
2865  RzList *bckedges = rz_list_new();
2866  struct tmplayer *tl, *tm;
2867 
2868  graph_foreach_anode (nodes, itm, ga, a) {
2869  const RzGraphNode *gb;
2870  RzANode *b;
2871  RzList *neighbours = (RzList *)rz_graph_get_neighbours(g->graph, ga);
2872  int ax, ay, bx, by, a_x_inc, b_x_inc;
2873  tl = tm = NULL;
2874  if (rz_cons_is_breaked()) {
2875  break;
2876  }
2877 
2878  rz_list_foreach (lyr, ito, tl) {
2879  if (tl->layer == a->layer) {
2880  tm = tl;
2881  if (g->layout == 0) { // vertical layout
2882  if (tm->minx > a->x) {
2883  tm->minx = a->x;
2884  }
2885  if (tm->maxx < a->x + a->w) {
2886  tm->maxx = a->x + a->w;
2887  }
2888  } else {
2889  if (tm->minx > a->y) {
2890  tm->minx = a->y;
2891  }
2892  if (tm->maxx < a->y + a->h) {
2893  tm->maxx = a->y + a->h;
2894  }
2895  }
2896  break;
2897  }
2898  }
2899 
2900  if (!tm) {
2901  tm = RZ_NEW0(struct tmplayer);
2902  if (tm) {
2903  tm->layer = a->layer;
2904  tm->edgectr = 0;
2905  tm->revedgectr = 0;
2906  if (g->layout == 0) { // vertical layout
2907  tm->minx = a->x;
2908  tm->maxx = a->x + a->w;
2909  } else {
2910  tm->minx = a->y;
2911  tm->maxx = a->y + a->h;
2912  }
2913  rz_list_add_sorted(lyr, tm, tmplayercmp);
2914  }
2915  }
2916 
2917  bool many = rz_list_length(neighbours) > 2;
2918 
2919  if (many && !g->is_callgraph) {
2920  ga->out_nodes->sorted = false;
2921  rz_list_sort(neighbours, first_x_cmp);
2922  }
2923 
2924  graph_foreach_anode (neighbours, itn, gb, b) {
2925  out_nth = get_edge_number(g, a, b, true);
2926  in_nth = get_edge_number(g, a, b, false);
2927 
2928  bool parent_many = false;
2929  if (a->is_dummy) {
2930  RzANode *in = (RzANode *)(((RzGraphNode *)rz_list_first(ga->in_nodes))->data);
2931  while (in && in->is_dummy) {
2932  in = (RzANode *)(((RzGraphNode *)rz_list_first((in->gnode)->in_nodes))->data);
2933  }
2934  if (in && in->gnode) {
2935  parent_many = rz_list_length(in->gnode->out_nodes) > 2;
2936  } else {
2937  parent_many = false;
2938  }
2939  }
2940 
2941  style.dot_style = DOT_STYLE_NORMAL;
2942  if (many || parent_many) {
2943  style.color = LINE_UNCJMP;
2944  } else {
2945  switch (out_nth) {
2946  case 0:
2947  style.color = LINE_TRUE;
2949  break;
2950  case 1:
2951  style.color = LINE_FALSE;
2953  break;
2954  case -1:
2955  style.color = LINE_UNCJMP;
2956  break;
2957  default:
2958  style.color = LINE_NONE;
2959  break;
2960  }
2961  }
2962 
2963  switch (g->layout) {
2964  case 0:
2965  default:
2966  style.symbol = (!g->hints || a->is_dummy) ? LINE_NOSYM_VERT : style.color;
2967  if (a->y + a->h > b->y) {
2968  style.dot_style = DOT_STYLE_BACKEDGE;
2969  }
2970 
2971  a_x_inc = RZ_EDGES_X_INC + 2 * (out_nth + 1);
2972  b_x_inc = RZ_EDGES_X_INC + 2 * (in_nth + 1);
2973 
2974  bx = b->is_dummy ? b->x : (b->x + b_x_inc);
2975  ay = a->y + a->h;
2976  by = b->y - 1;
2977 
2978  if (many && !g->is_callgraph) {
2979  int t = RZ_EDGES_X_INC + 2 * (neighbours->length + 1);
2980  ax = a->is_dummy ? a->x : (a->x + a->w / 2 + (t / 2 - a_x_inc));
2981  bendpoint = bx < ax ? neighbours->length - out_nth : out_nth;
2982  } else {
2983  ax = a->is_dummy ? a->x : (a->x + a_x_inc);
2984  bendpoint = tm->edgectr;
2985  }
2986 
2987  if (!a->is_dummy && itn == neighbours->head && out_nth == 0 && bx > ax) {
2988  ax += (many && !g->is_callgraph) ? 0 : 4;
2989  }
2990  if (a->h < a->layer_height) {
2991  rz_cons_canvas_line(g->can, ax, ay, ax, ay + a->layer_height - a->h, &style);
2992  ay = a->y + a->layer_height;
2993  style.symbol = LINE_NOSYM_VERT;
2994  }
2995  if (by >= ay) {
2996  rz_cons_canvas_line_square_defined(g->can, ax, ay, bx, by, &style, bendpoint, true);
2997  } else {
2998  struct tmpbackedgeinfo *tmp = calloc(1, sizeof(struct tmpbackedgeinfo));
2999  tmp->ax = ax;
3000  tmp->bx = bx;
3001  tmp->ay = ay;
3002  tmp->by = by;
3003  tmp->edgectr = bendpoint;
3004  tmp->fromlayer = a->layer;
3005  tmp->tolayer = b->layer;
3006  tmp->style = style;
3007  rz_list_append(bckedges, tmp);
3008  }
3009  if (b->is_dummy) {
3011  rz_cons_canvas_line(g->can, bx, by, bx, b->y + b->h, &style);
3012  }
3013  if (b->x != a->x || b->layer <= a->layer || (!a->is_dummy && b->is_dummy) || (a->is_dummy && !b->is_dummy)) {
3014  if (tm) {
3015  tm->edgectr++;
3016  }
3017  }
3018  break;
3019  case 1:
3020  style.symbol = (!g->hints || a->is_dummy) ? LINE_NOSYM_HORIZ : style.color;
3021  if (a->x + a->w > b->x) {
3023  }
3024 
3025  ax = a->x;
3026  if (g->zoom > 0) {
3027  ax += a->w;
3028  } else {
3029  ax++;
3030  }
3031  ay = a->y;
3032  if (!a->is_dummy && g->zoom > 0) {
3033  ay += RZ_EDGES_X_INC + out_nth;
3034  }
3035  bx = b->x - 1;
3036  by = b->y;
3037  if (!b->is_dummy && g->zoom > 0) {
3038  by += RZ_EDGES_X_INC + out_nth;
3039  }
3040 
3041  if (a->w < a->layer_width) {
3042  rz_cons_canvas_line_square_defined(g->can, ax, ay, a->x + a->layer_width, ay, &style, 0, false);
3043  ax = a->x;
3044  if (g->zoom > 1) {
3045  ax += a->layer_width;
3046  } else {
3047  ax += 1;
3048  }
3050  }
3051  if (bx >= ax) {
3052  rz_cons_canvas_line_square_defined(g->can, ax, ay, bx, by, &style, tm->edgectr, false);
3053  } else {
3054  struct tmpbackedgeinfo *tmp = calloc(1, sizeof(struct tmpbackedgeinfo));
3055  if (tmp) {
3056  tmp->ax = ax;
3057  tmp->bx = bx;
3058  tmp->ay = ay;
3059  tmp->by = by;
3060  tmp->edgectr = tm->edgectr;
3061  tmp->fromlayer = a->layer;
3062  tmp->tolayer = b->layer;
3063  tmp->style = style;
3064  rz_list_append(bckedges, tmp);
3065  }
3066  }
3067  if (b->is_dummy) {
3069  rz_cons_canvas_line_square_defined(g->can, bx, by, bx + b->layer_width, by, &style, 0, false);
3070  }
3071  if ((b->y == a->y && b->h != a->h) || b->y != a->y || b->layer <= a->layer || (!a->is_dummy && b->is_dummy) || (a->is_dummy && !b->is_dummy)) {
3072  tm->edgectr += 1;
3073  }
3074  break;
3075  }
3076  }
3077  }
3078 
3079  struct tmpbackedgeinfo *temp;
3080  rz_list_foreach (bckedges, itm, temp) {
3081  int leftlen, rightlen;
3082  int minx = 0, maxx = 0;
3083  struct tmplayer *tt = NULL;
3084  if (rz_cons_is_breaked()) {
3085  break;
3086  }
3087 
3088  rz_list_foreach (lyr, ito, tl) {
3089  if (tl->layer <= temp->tolayer) {
3090  tt = tl;
3091  minx = tl->minx;
3092  maxx = tl->maxx;
3093  continue;
3094  }
3095  minx = minx < tl->minx ? minx : tl->minx;
3096  maxx = maxx > tl->maxx ? maxx : tl->maxx;
3097  if (tl->layer >= temp->fromlayer) {
3098  break;
3099  }
3100  }
3101 
3102  if (tt) {
3103  tt->revedgectr += 1;
3104  }
3105  if (g->layout == 0) {
3106  leftlen = (temp->ax - minx) + (temp->bx - minx);
3107  rightlen = (maxx - temp->ax) + (maxx - temp->bx);
3108  } else {
3109  leftlen = (temp->ay - minx) + (temp->by - minx);
3110  rightlen = (maxx - temp->ay) + (maxx - temp->by);
3111  }
3112 
3113  if (tt) {
3114  int arg = (rightlen < leftlen) ? maxx + 1 : minx - 1;
3115  rz_cons_canvas_line_back_edge(g->can, temp->ax, temp->ay, temp->bx, temp->by, &(temp->style), temp->edgectr, arg, tt->revedgectr, !g->layout);
3116  }
3117 
3118  rz_list_foreach (lyr, ito, tl) {
3119  if (tl->layer < temp->tolayer) {
3120  continue;
3121  }
3122  if (rightlen < leftlen) {
3123  tl->maxx = maxx + 1;
3124  } else {
3125  tl->minx = minx - 1;
3126  }
3127  if (tl->layer >= temp->fromlayer) {
3128  break;
3129  }
3130  }
3131  }
3132 
3133  rz_list_foreach (lyr, ito, tl) {
3134  free(tl);
3135  }
3136 
3137  rz_list_foreach (bckedges, ito, tl) {
3138  free(tl);
3139  }
3140 
3141  rz_list_free(lyr);
3142  rz_list_free(bckedges);
3144 }
static int get_edge_number(const RzAGraph *g, RzANode *src, RzANode *dst, bool outgoing)
Definition: agraph.c:1738
static void agraph_print_edges_simple(RzAGraph *g)
Definition: agraph.c:2798
static int first_x_cmp(const void *_a, const void *_b)
Definition: agraph.c:2829
int tmplayercmp(const void *a, const void *b)
Definition: agraph.c:2794
RZ_API void rz_cons_canvas_line(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style)
Definition: canvas.c:570
RZ_API void rz_cons_canvas_line_square_defined(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int bendpoint, int isvert)
Definition: canvas_line.c:401
RZ_API void rz_cons_canvas_line_back_edge(RzConsCanvas *c, int x, int y, int x2, int y2, RzCanvasLineStyle *style, int ybendpoint1, int xbendpoint, int ybendpoint2, int isvert)
Definition: canvas_line.c:454
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
RZ_API RZ_BORROW void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
RZ_API RZ_BORROW RzListIter * rz_list_add_sorted(RZ_NONNULL RzList *list, void *data, RZ_NONNULL RzListComparator cmp)
Adds an element to a sorted list via the RzListComparator.
Definition: list.c:518
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
#define DOT_STYLE_CONDITIONAL
Definition: rz_cons.h:784
#define DOT_STYLE_NORMAL
Definition: rz_cons.h:783
#define RZ_EDGES_X_INC
Definition: rz_cons.h:994
#define DOT_STYLE_BACKEDGE
Definition: rz_cons.h:785
@ LINE_NOSYM_HORIZ
Definition: rz_cons.h:775
@ LINE_NOSYM_VERT
Definition: rz_cons.h:774
@ LINE_TRUE
Definition: rz_cons.h:771
@ LINE_NONE
Definition: rz_cons.h:770
@ LINE_FALSE
Definition: rz_cons.h:772
@ LINE_UNCJMP
Definition: rz_cons.h:773
RZ_API const RzList * rz_graph_get_nodes(const RzGraph *g)
Definition: graph.c:265
RZ_API const RzList * rz_graph_get_neighbours(const RzGraph *g, const RzGraphNode *n)
Definition: graph.c:245
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define b(i)
Definition: sha256.c:42
RzListIter * head
Definition: rz_list.h:19
bool sorted
Definition: rz_list.h:23
ut32 length
Definition: rz_list.h:22
RzCanvasLineStyle style
Definition: agraph.c:2791
int maxx
Definition: agraph.c:2781
int revedgectr
Definition: agraph.c:2779
int layer
Definition: agraph.c:2777
int edgectr
Definition: agraph.c:2778
int minx
Definition: agraph.c:2780
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References a, agraph_print_edges_simple(), tmpbackedgeinfo::ax, ax, tmpbackedgeinfo::ay, b, tmpbackedgeinfo::bx, tmpbackedgeinfo::by, calloc(), rz_cons_canvas_line_style_t::color, rz_cons_canvas_line_style_t::dot_style, DOT_STYLE_BACKEDGE, DOT_STYLE_CONDITIONAL, DOT_STYLE_NORMAL, tmplayer::edgectr, tmpbackedgeinfo::edgectr, first_x_cmp(), free(), tmpbackedgeinfo::fromlayer, g, get_edge_number(), graph_foreach_anode, rz_list_t::head, if(), in, rz_graph_node_t::in_nodes, tmplayer::layer, rz_list_t::length, LINE_FALSE, LINE_NONE, LINE_NOSYM_HORIZ, LINE_NOSYM_VERT, LINE_TRUE, LINE_UNCJMP, tmplayer::maxx, tmplayer::minx, NULL, rz_graph_node_t::out_nodes, tmplayer::revedgectr, rz_cons_break_pop(), rz_cons_canvas_line(), rz_cons_canvas_line_back_edge(), rz_cons_canvas_line_square_defined(), rz_cons_is_breaked(), RZ_EDGES_X_INC, rz_graph_get_neighbours(), rz_graph_get_nodes(), rz_list_add_sorted(), rz_list_append(), rz_list_first(), rz_list_free(), rz_list_length(), rz_list_new(), rz_list_sort(), RZ_NEW0, rz_list_t::sorted, tmpbackedgeinfo::style, rz_cons_canvas_line_style_t::symbol, autogen_x86imm::tmp, tmplayercmp(), and tmpbackedgeinfo::tolayer.

Referenced by agraph_print().

◆ agraph_print_edges_simple()

static void agraph_print_edges_simple ( RzAGraph g)
static

Definition at line 2798 of file agraph.c.

2798  {
2799  RzCanvasLineStyle style = { 0 };
2800  RzANode *n, *n2;
2801  RzGraphNode *gn, *gn2;
2802  RzListIter *iter, *iter2;
2803  const RzList *nodes = rz_graph_get_nodes(g->graph);
2804  graph_foreach_anode (nodes, iter, gn, n) {
2805  const RzList *outnodes = n->gnode->out_nodes;
2806  graph_foreach_anode (outnodes, iter2, gn2, n2) {
2807  int sx = n->w / 2;
2808  int sy = n->h;
2809  int sx2 = n2->w / 2;
2810  if (g->is_tiny) {
2811  sx = 0;
2812  sy = 0;
2813  sx2 = 0;
2814  }
2815  // TODO: better alignments here
2816  rz_cons_canvas_line(g->can,
2817  n->x + sx, n->y + sy,
2818  n2->x + sx2, n2->y, &style);
2819 
2820  if (n2->is_dummy) {
2821  rz_cons_canvas_line(g->can,
2822  n2->x + sx2, n2->y - 1,
2823  n2->x + sx2, n2->y + n2->h, &style);
2824  }
2825  }
2826  }
2827 }

References g, graph_foreach_anode, rz_ascii_node_t::h, rz_ascii_node_t::is_dummy, n, rz_cons_canvas_line(), rz_graph_get_nodes(), rz_ascii_node_t::w, rz_ascii_node_t::x, and rz_ascii_node_t::y.

Referenced by agraph_print_edges().

◆ agraph_print_node()

static void agraph_print_node ( const RzAGraph g,
RzANode n 
)
static

Definition at line 2743 of file agraph.c.

2743  {
2744  if (n->is_dummy) {
2745  return;
2746  }
2747  const int cur = g->curnode && get_anode(g->curnode) == n;
2748  const bool isMini = is_mini(g);
2749  if (g->is_tiny) {
2750  tiny_RzANode_print(g, n, cur);
2751  } else if (isMini || n->is_mini) {
2752  mini_RzANode_print(g, n, cur, isMini);
2753  } else {
2754  normal_RzANode_print(g, n, cur);
2755  }
2756 }
static void mini_RzANode_print(const RzAGraph *g, const RzANode *n, int cur, bool details)
Definition: agraph.c:265
static void tiny_RzANode_print(const RzAGraph *g, const RzANode *n, int cur)
Definition: agraph.c:323
static void normal_RzANode_print(const RzAGraph *g, const RzANode *n, int cur)
Definition: agraph.c:345
static bool is_mini(const RzAGraph *g)
Definition: agraph.c:117

References g, get_anode, is_mini(), mini_RzANode_print(), n, normal_RzANode_print(), and tiny_RzANode_print().

Referenced by agraph_print_nodes().

◆ agraph_print_nodes()

static void agraph_print_nodes ( const RzAGraph g)
static

Definition at line 2758 of file agraph.c.

2758  {
2759  const RzList *nodes = rz_graph_get_nodes(g->graph);
2760  RzGraphNode *gn;
2761  RzListIter *it;
2762  RzANode *n;
2763 
2764  graph_foreach_anode (nodes, it, gn, n) {
2765  if (gn != g->curnode) {
2766  agraph_print_node(g, n);
2767  }
2768  }
2769 
2770  /* draw current node now to make it appear on top */
2771  if (g->curnode) {
2772  agraph_print_node(g, get_anode(g->curnode));
2773  }
2774 }
static void agraph_print_node(const RzAGraph *g, RzANode *n)
Definition: agraph.c:2743

References agraph_print_node(), g, get_anode, graph_foreach_anode, n, and rz_graph_get_nodes().

Referenced by agraph_print().

◆ agraph_refresh()

static int agraph_refresh ( struct agraph_refresh_data grd)
static

Definition at line 3522 of file agraph.c.

3522  {
3523  if (!grd) {
3524  return 0;
3525  }
3526  rz_cons_singleton()->event_data = grd;
3527  RzCore *core = grd->core;
3528  RzAGraph *g = grd->g;
3530  RzAnalysisFunction **fcn = grd->fcn;
3531 
3532  if (!fcn) {
3533  return agraph_print(g, grd->fs, core, NULL);
3534  }
3535 
3536  // allow to change the current function during debugging
3537  if (g->is_instep && core->bin->is_debugger) {
3538  // seek only when the graph node changes
3539  const char *pc = rz_reg_get_name(core->dbg->reg, RZ_REG_NAME_PC);
3540  RzRegItem *r = rz_reg_get(core->dbg->reg, pc, -1);
3541  ut64 addr = rz_reg_get_value(core->dbg->reg, r);
3542  RzANode *acur = get_anode(g->curnode);
3543 
3545  char *title = get_title(block ? block->addr : addr);
3546  if (!acur || strcmp(acur->title, title)) {
3547  rz_core_seek_to_register(core, "PC", false);
3548  }
3549  free(title);
3550  g->is_instep = false;
3551  }
3552 
3553  if (grd->follow_offset) {
3554  if (rz_io_is_valid_offset(core->io, core->offset, 0)) {
3555  f = rz_analysis_get_fcn_in(core->analysis, core->offset, 0);
3556  if (!f) {
3557  if (!g->is_dis) {
3558  if (!rz_cons_yesno('y', "\rNo function at 0x%08" PFMT64x ". Define it here (Y/n)? ", core->offset)) {
3559  return 0;
3560  }
3561  rz_core_analysis_function_add(core, NULL, core->offset, false);
3562  }
3563  f = rz_analysis_get_fcn_in(core->analysis, core->offset, 0);
3564  g->need_reload_nodes = true;
3565  }
3566  if (f && fcn && f != *fcn) {
3567  *fcn = f;
3568  check_function_modified(core, *fcn);
3569  g->need_reload_nodes = true;
3570  g->force_update_seek = true;
3571  }
3572  } else {
3573  // TODO: maybe go back to avoid seeking from graph view to an scary place?
3574  rz_cons_message("This is not a valid offset\n");
3575  rz_cons_flush();
3576  }
3577  }
3578 
3579  int res = agraph_print(g, grd->fs, core, *fcn);
3580 
3581  if (rz_config_get_i(core->config, "scr.scrollbar")) {
3583  }
3584 
3585  return res;
3586 }
static char * get_title(ut64 addr)
Definition: agraph.c:200
static int agraph_print(RzAGraph *g, int is_interactive, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:3431
static void check_function_modified(RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:3514
RZ_API RzAnalysisBlock * rz_analysis_find_most_relevant_block_in(RzAnalysis *analysis, ut64 off)
Definition: block.c:997
RZ_API bool rz_core_analysis_function_add(RzCore *core, const char *name, ut64 addr, bool analyze_recursively)
Definition: canalysis.c:5298
RZ_IPI bool rz_core_seek_to_register(RzCore *core, const char *regname, bool is_silent)
Definition: cmd_seek.c:22
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
#define r
Definition: crypto_rc6.c:12
RZ_DEPRECATE RZ_API RzAnalysisFunction * rz_analysis_get_fcn_in(RzAnalysis *analysis, ut64 addr, int type)
Definition: fcn.c:1687
RZ_API void rz_cons_message(RZ_NONNULL const char *msg)
Definition: hud.c:321
RZ_API bool rz_cons_yesno(int def, const char *fmt,...)
Definition: input.c:666
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API ut64 rz_reg_get_value(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:114
RZ_API bool rz_io_is_valid_offset(RzIO *io, ut64 offset, int hasperm)
Definition: ioutils.c:20
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
#define PFMT64x
Definition: rz_types.h:393
#define f(i)
Definition: sha256.c:46
RzAnalysisFunction ** fcn
Definition: agraph.c:99
RzAGraph * g
Definition: agraph.c:98
RzCore * core
Definition: agraph.c:97
int is_debugger
Definition: rz_bin.h:350
void * event_data
Definition: rz_cons.h:523
RzBin * bin
Definition: rz_core.h:298
ut64 offset
Definition: rz_core.h:301
RzAnalysis * analysis
Definition: rz_core.h:322
RzDebug * dbg
Definition: rz_core.h:329
RzIO * io
Definition: rz_core.h:313
RzReg * reg
Definition: rz_debug.h:286
RZ_API void rz_core_print_scrollbar(RzCore *core)
Definition: visual.c:3541
static int addr
Definition: z80asm.c:58

References addr, rz_analysis_bb_t::addr, agraph_print(), rz_core_t::analysis, rz_core_t::bin, check_function_modified(), rz_core_t::config, agraph_refresh_data::core, rz_core_t::dbg, rz_cons_t::event_data, f, agraph_refresh_data::fcn, agraph_refresh_data::follow_offset, free(), agraph_refresh_data::fs, agraph_refresh_data::g, g, get_anode, get_title(), rz_core_t::io, rz_bin_t::is_debugger, NULL, rz_core_t::offset, pc, PFMT64x, r, rz_debug_t::reg, rz_analysis_find_most_relevant_block_in(), rz_analysis_get_fcn_in(), rz_config_get_i(), rz_cons_flush(), rz_cons_message(), rz_cons_singleton(), rz_cons_yesno(), rz_core_analysis_function_add(), rz_core_print_scrollbar(), rz_core_seek_to_register(), rz_io_is_valid_offset(), rz_reg_get(), rz_reg_get_name(), rz_reg_get_value(), RZ_REG_NAME_PC, rz_ascii_node_t::title, and ut64().

Referenced by agraph_refresh_oneshot(), agraph_toggle_mini(), agraph_toggle_tiny(), and rz_core_visual_graph().

◆ agraph_refresh_oneshot()

static void agraph_refresh_oneshot ( struct agraph_refresh_data grd)
static

Definition at line 3588 of file agraph.c.

3588  {
3589  rz_core_task_enqueue_oneshot(&grd->core->tasks, (RzCoreTaskOneShot)agraph_refresh, grd);
3590 }
static int agraph_refresh(struct agraph_refresh_data *grd)
Definition: agraph.c:3522
RzCoreTaskScheduler tasks
Definition: rz_core.h:362
RZ_API void rz_core_task_enqueue_oneshot(RzCoreTaskScheduler *scheduler, RzCoreTaskOneShot func, void *user)
Definition: task.c:391

References agraph_refresh(), agraph_refresh_data::core, rz_core_task_enqueue_oneshot(), and rz_core_t::tasks.

Referenced by rz_core_visual_graph().

◆ agraph_reload_nodes()

static bool agraph_reload_nodes ( RzAGraph g,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 3178 of file agraph.c.

3178  {
3179  rz_agraph_reset(g);
3180  return reload_nodes(g, core, fcn);
3181 }
static bool reload_nodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:2506
RZ_API void rz_agraph_reset(RzAGraph *g)
Definition: agraph.c:3889

References g, reload_nodes(), and rz_agraph_reset().

Referenced by check_changes().

◆ agraph_sdb_init()

static void agraph_sdb_init ( const RzAGraph g)
static

Definition at line 3669 of file agraph.c.

3669  {
3670  sdb_bool_set(g->db, "agraph.is_callgraph", g->is_callgraph, 0);
3671  RzCons *cons = rz_cons_singleton();
3672  sdb_set_enc(g->db, "agraph.color_box", cons->context->pal.graph_box, 0);
3673  sdb_set_enc(g->db, "agraph.color_box2", cons->context->pal.graph_box2, 0);
3674  sdb_set_enc(g->db, "agraph.color_box3", cons->context->pal.graph_box3, 0);
3675  sdb_set_enc(g->db, "agraph.color_true", cons->context->pal.graph_true, 0);
3676  sdb_set_enc(g->db, "agraph.color_false", cons->context->pal.graph_false, 0);
3677 }
static void sdb_set_enc(Sdb *db, const char *key, const char *v, ut32 cas)
Definition: agraph.c:3663
RZ_API int sdb_bool_set(Sdb *db, const char *str, bool v, ut32 cas)
Definition: num.c:72
RzConsPrintablePalette pal
Definition: rz_cons.h:491
RzConsContext * context
Definition: rz_cons.h:502

References rz_cons_t::context, g, rz_cons_printable_palette_t::graph_box, rz_cons_printable_palette_t::graph_box2, rz_cons_printable_palette_t::graph_box3, rz_cons_printable_palette_t::graph_false, rz_cons_printable_palette_t::graph_true, rz_cons_context_t::pal, rz_cons_singleton(), sdb_bool_set(), and sdb_set_enc().

Referenced by rz_agraph_new(), and rz_agraph_reset().

◆ agraph_set_layout()

static void agraph_set_layout ( RzAGraph g)
static

Definition at line 2713 of file agraph.c.

2713  {
2714  RzListIter *it;
2715  RzGraphNode *n;
2716  RzANode *a;
2717 
2718  set_layout(g);
2719 
2721  graph_foreach_anode (rz_graph_get_nodes(g->graph), it, n, a) {
2722  if (a->is_dummy) {
2723  continue;
2724  }
2725  const char *k;
2726  k = sdb_fmt("agraph.nodes.%s.x", a->title);
2727  sdb_num_set(g->db, k, rebase(g, a->x), 0);
2728  k = sdb_fmt("agraph.nodes.%s.y", a->title);
2729  sdb_num_set(g->db, k, rebase(g, a->y), 0);
2730  k = sdb_fmt("agraph.nodes.%s.w", a->title);
2731  sdb_num_set(g->db, k, a->w, 0);
2732  k = sdb_fmt("agraph.nodes.%s.h", a->title);
2733  sdb_num_set(g->db, k, a->h, 0);
2734  }
2735 }
static void set_layout(RzAGraph *g)
Definition: agraph.c:1958
static ut64 rebase(RzAGraph *g, int v)
Definition: agraph.c:2709
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25

References a, g, graph_foreach_anode, k, n, rebase(), rz_graph_get_nodes(), sdb_fmt(), sdb_num_set(), set_layout(), and update_graph_sizes().

Referenced by agraph_toggle_mini(), agraph_toggle_tiny(), and check_changes().

◆ agraph_set_need_reload_nodes()

static void agraph_set_need_reload_nodes ( struct agraph_refresh_data grd)
static

Definition at line 3592 of file agraph.c.

3592  {
3593  grd->g->need_reload_nodes = true;
3594 }
bool need_reload_nodes
Definition: rz_agraph.h:68

References agraph_refresh_data::g, and rz_ascii_graph_t::need_reload_nodes.

Referenced by rz_core_visual_graph().

◆ agraph_set_zoom()

static void agraph_set_zoom ( RzAGraph g,
int  v 
)
static

Definition at line 3152 of file agraph.c.

3152  {
3153  if (v >= -10) {
3154  g->is_tiny = false;
3155  if (v == 0) {
3156  g->mode = RZ_AGRAPH_MODE_MINI;
3157  } else if (v < 0) {
3158  g->mode = RZ_AGRAPH_MODE_TINY;
3159  g->is_tiny = true;
3160  } else {
3161  g->mode = RZ_AGRAPH_MODE_NORMAL;
3162  }
3163  const int K = 920;
3164  if (g->zoom < v) {
3165  g->can->sy = (g->can->sy * K) / 1000;
3166  } else {
3167  g->can->sy = (g->can->sy * 1000) / K;
3168  }
3169  g->zoom = v;
3170  g->need_update_dim = true;
3171  g->need_set_layout = true;
3172  }
3173 }
#define RZ_AGRAPH_MODE_NORMAL
Definition: rz_agraph.h:35
#define RZ_AGRAPH_MODE_MINI
Definition: rz_agraph.h:37
#define RZ_AGRAPH_MODE_TINY
Definition: rz_agraph.h:38

References g, RZ_AGRAPH_MODE_MINI, RZ_AGRAPH_MODE_NORMAL, RZ_AGRAPH_MODE_TINY, and v.

Referenced by rz_core_visual_graph().

◆ agraph_toggle_callgraph()

static void agraph_toggle_callgraph ( RzAGraph g)
static

Definition at line 3146 of file agraph.c.

3146  {
3147  g->is_callgraph = !g->is_callgraph;
3148  g->need_reload_nodes = true;
3149  g->force_update_seek = true;
3150 }

References g.

Referenced by rz_core_visual_graph().

◆ agraph_toggle_mini()

static void agraph_toggle_mini ( RzAGraph g)
static

Definition at line 3248 of file agraph.c.

3248  {
3249  RzANode *n = get_anode(g->curnode);
3250  if (n) {
3251  n->is_mini = !n->is_mini;
3252  }
3253  g->need_update_dim = 1;
3254  agraph_refresh(rz_cons_singleton()->event_data);
3256 }
static void agraph_set_layout(RzAGraph *g)
Definition: agraph.c:2713

References agraph_refresh(), agraph_set_layout(), g, get_anode, n, and rz_cons_singleton().

Referenced by rz_core_visual_graph().

◆ agraph_toggle_speed()

static void agraph_toggle_speed ( RzAGraph g,
RzCore core 
)
static

Definition at line 3596 of file agraph.c.

3596  {
3597  const int alt = rz_config_get_i(core->config, "graph.scroll");
3598  g->movspeed = g->movspeed == DEFAULT_SPEED ? alt : DEFAULT_SPEED;
3599 }

References rz_core_t::config, DEFAULT_SPEED, g, and rz_config_get_i().

Referenced by rz_core_visual_graph().

◆ agraph_toggle_tiny()

static void agraph_toggle_tiny ( RzAGraph g)
static

Definition at line 3240 of file agraph.c.

3240  {
3241  g->is_tiny = !g->is_tiny;
3242  g->need_update_dim = 1;
3243  agraph_refresh(rz_cons_singleton()->event_data);
3245  // remove_dummy_nodes (g);
3246 }

References agraph_refresh(), agraph_set_layout(), g, and rz_cons_singleton().

Referenced by rz_core_visual_graph().

◆ agraph_update_seek()

static void agraph_update_seek ( RzAGraph g,
RzANode n,
int  force 
)
static

Definition at line 2738 of file agraph.c.

2738  {
2739  g->update_seek_on = n;
2740  g->force_update_seek = force;
2741 }

References g, and n.

Referenced by agraph_follow_false(), agraph_follow_innodes(), agraph_follow_true(), agraph_next_node(), agraph_prev_node(), goto_asmqjmps(), and rz_core_visual_graph().

◆ agraph_update_title()

static void agraph_update_title ( RzCore core,
RzAGraph g,
RzAnalysisFunction fcn 
)
static

Definition at line 3350 of file agraph.c.

3350  {
3351  RzANode *a = get_anode(g->curnode);
3353  char *new_title = rz_str_newf(
3354  "%s[0x%08" PFMT64x "]> %s # %s ",
3355  graphCursor ? "(cursor)" : "",
3356  fcn->addr, a ? a->title : "", sig);
3357  rz_agraph_set_title(g, new_title);
3358  free(new_title);
3359  free(sig);
3360 }
RZ_API void rz_agraph_set_title(RzAGraph *g, const char *title)
Definition: agraph.c:3720
static bool graphCursor
Definition: agraph.c:16
RZ_IPI char * rz_core_analysis_function_signature(RzCore *core, RzOutputMode mode, char *fcn_name)
Definition: canalysis.c:5382
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
@ RZ_OUTPUT_MODE_STANDARD
Definition: rz_types.h:39

References a, rz_analysis_function_t::addr, free(), g, get_anode, graphCursor, NULL, PFMT64x, rz_agraph_set_title(), rz_core_analysis_function_signature(), RZ_OUTPUT_MODE_STANDARD, and rz_str_newf().

Referenced by check_changes().

◆ append_shortcut()

static void append_shortcut ( const RzAGraph g,
char *  title,
char *  nodetitle,
int  left 
)
static

Definition at line 253 of file agraph.c.

253  {
254  const char *shortcut = sdb_const_get(g->db, sdb_fmt("agraph.nodes.%s.shortcut", nodetitle), 0);
255  if (shortcut) {
256  if (g->can->color) {
257  // XXX: do not hardcode color here
258  strncat(title, sdb_fmt(Color_YELLOW "[o%s]" Color_RESET, shortcut), left);
259  } else {
260  strncat(title, sdb_fmt("[o%s]", shortcut), left);
261  }
262  }
263 }
#define Color_YELLOW
Definition: rz_cons.h:631
RZ_API const char * sdb_const_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:279

References Color_RESET, Color_YELLOW, g, sdb_const_get(), and sdb_fmt().

Referenced by mini_RzANode_print(), and normal_RzANode_print().

◆ applyDisMode()

static void applyDisMode ( RzCore core)
static

Definition at line 4027 of file agraph.c.

4027  {
4028  switch (disMode) {
4029  case 0:
4030  rz_config_set(core->config, "asm.pseudo", "false");
4031  rz_config_set(core->config, "asm.esil", "false");
4032  break;
4033  case 1:
4034  rz_config_set(core->config, "asm.pseudo", "true");
4035  rz_config_set(core->config, "asm.esil", "false");
4036  break;
4037  case 2:
4038  rz_config_set(core->config, "asm.pseudo", "false");
4039  rz_config_set(core->config, "asm.esil", "true");
4040  break;
4041  }
4042 }
static int disMode
Definition: agraph.c:14
RZ_API RzConfigNode * rz_config_set(RzConfig *cfg, RZ_NONNULL const char *name, const char *value)
Definition: config.c:267

References rz_core_t::config, disMode, and rz_config_set().

Referenced by rz_core_visual_graph().

◆ assign_layers()

static void assign_layers ( const RzAGraph g)
static

Definition at line 660 of file agraph.c.

660  {
661  RzGraphVisitor layer_vis = {
662  NULL, NULL, NULL, NULL, NULL, NULL
663  };
664  const RzGraphNode *gn;
665  const RzListIter *it;
666  RzANode *n;
667  RzList *topological_sort = rz_list_new();
668 
669  layer_vis.data = topological_sort;
671  rz_graph_dfs(g->graph, &layer_vis);
672 
673  graph_foreach_anode (topological_sort, it, gn, n) {
674  const RzList *innodes = rz_graph_innodes(g->graph, gn);
675  RzListIter *it;
676  RzGraphNode *prev;
677  RzANode *preva;
678 
679  n->layer = 0;
680  graph_foreach_anode (innodes, it, prev, preva) {
681  if (preva->layer + 1 > n->layer) {
682  n->layer = preva->layer + 1;
683  }
684  }
685  }
686 
687  rz_list_free(topological_sort);
688 }
static void add_sorted(RzGraphNode *n, RzGraphVisitor *vis)
Definition: agraph.c:649
RZ_API void rz_graph_dfs(RzGraph *g, RzGraphVisitor *vis)
Definition: graph.c:299
void(* RzGraphNodeCallback)(RzGraphNode *n, RzGraphVisitor *vis)
Definition: rz_graph.h:40
void(* finish_node)(RzGraphNode *n, struct rz_graph_visitor_t *vis)
Definition: rz_graph.h:34

References add_sorted(), rz_graph_visitor_t::data, rz_graph_visitor_t::finish_node, g, graph_foreach_anode, rz_ascii_node_t::layer, n, NULL, rz_graph_dfs(), rz_graph_innodes(), rz_list_free(), and rz_list_new().

Referenced by set_layout().

◆ backedge_info()

static void backedge_info ( RzAGraph g)
static

Definition at line 1776 of file agraph.c.

1776  {
1777  int i, j, k;
1778  int min, max;
1779  int inedge = 0;
1780  int outedge = 0;
1781 
1782  int **arr = RZ_NEWS0(int *, g->n_layers);
1783  if (!arr) {
1784  return;
1785  }
1786  for (i = 0; i < g->n_layers; i++) {
1787  arr[i] = RZ_NEWS0(int, 2);
1788  if (!arr[i]) {
1789  goto err;
1790  }
1791  }
1792 
1793  for (i = 0; i < g->n_layers; i++) {
1794  for (j = 0; j < g->layers[i].n_nodes; j++) {
1795  RzGraphNode *gt = g->layers[i].nodes[j];
1796  if (!gt) {
1797  continue;
1798  }
1799  RzANode *t = (RzANode *)gt->data;
1800  if (!t) {
1801  continue;
1802  }
1803  int tc = g->layout == 0 ? t->x : t->y;
1804  int tl = g->layout == 0 ? t->w : t->h;
1805  if (!j) {
1806  arr[i][0] = tc;
1807  arr[i][1] = tc + tl;
1808  }
1809 
1810  if (arr[i][0] > tc) {
1811  arr[i][0] = tc;
1812  }
1813 
1814  if (arr[i][1] < tc + tl) {
1815  arr[i][1] = tc + tl;
1816  }
1817  }
1818 
1819  for (j = 0; j < g->layers[i].n_nodes; j++) {
1820  RzANode *a = get_anode(g->layers[i].nodes[j]);
1821  if (!a || a->is_dummy) {
1822  continue;
1823  }
1824 
1825  const RzList *neighbours = rz_graph_get_neighbours(g->graph, a->gnode);
1826  RzGraphNode *gb;
1827  RzANode *b;
1828  RzListIter *itm;
1829 
1830  if (i == 0) {
1831  inedge += rz_list_length(rz_graph_innodes(g->graph, a->gnode));
1832  } else if (i == g->n_layers - 1) {
1833  outedge += rz_list_length(neighbours);
1834  }
1835 
1836  graph_foreach_anode (neighbours, itm, gb, b) {
1837  if (b->layer > a->layer) {
1838  continue;
1839  }
1840 
1841  int nth = count_edges(g, a, b);
1842  int xinc = RZ_EDGES_X_INC + 2 * (nth + 1);
1843 
1844  int ax = g->layout == 0 ? a->x + xinc : a->y + (a->h / 2) + nth;
1845  int bx = g->layout == 0 ? b->x + xinc : b->y + (b->h / 2) + nth;
1846 
1847  if (g->layout == 0 && nth == 0 && bx > ax) {
1848  ax += 4;
1849  }
1850 
1851  min = arr[b->layer][0];
1852  max = arr[b->layer][1];
1853  for (k = b->layer; k <= a->layer; k++) {
1854  if (min > arr[k][0]) {
1855  min = arr[k][0];
1856  }
1857 
1858  if (max < arr[k][1]) {
1859  max = arr[k][1];
1860  }
1861  }
1862 
1863  int l = (ax - min) + (bx - min);
1864  int r = (max - ax) + (max - bx);
1865 
1866  for (k = b->layer; k <= a->layer; k++) {
1867  if (r < l) {
1868  arr[k][1] = max + 1;
1869  } else {
1870  arr[k][0] = min - 1;
1871  }
1872  }
1873 
1874  AEdge *e = RZ_NEW0(AEdge);
1875  if (!e) {
1876  free(arr);
1877  return;
1878  }
1879 
1880  e->is_reversed = true;
1881  e->from = a;
1882  e->to = b;
1883  e->x = rz_list_new();
1884  e->y = rz_list_new();
1885 
1886  if (r < l) {
1887  rz_list_append((g->layout == 0 ? e->x : e->y), (void *)(size_t)(max + 1));
1888  } else {
1889  rz_list_append((g->layout == 0 ? e->x : e->y), (void *)(size_t)(min - 1));
1890  }
1891 
1892  rz_list_append(g->edges, e);
1893  }
1894  }
1895  }
1896 
1897  // Assumption: layer layout is not changed w.r.t x-coordinate/y-coordinate for horizontal/vertical layout respectively.
1898  if (inedge) {
1899  RzANode *n = (RzANode *)g->layers[0].nodes[0]->data;
1900  AEdge *e = RZ_NEW0(AEdge);
1901  if (!e) {
1902  free(arr);
1903  return;
1904  }
1905  e->is_reversed = true;
1906  e->from = NULL;
1907  e->to = NULL;
1908  e->x = rz_list_new();
1909  e->y = rz_list_new();
1910  if (g->layout == 0) {
1911  rz_list_append(e->y, (void *)(size_t)(n->y - 1 - inedge));
1912  } else {
1913  rz_list_append(e->x, (void *)(size_t)(n->x - 1 - inedge));
1914  }
1915  rz_list_append(g->edges, e);
1916  }
1917 
1918  if (outedge) {
1919  RzANode *n = (RzANode *)g->layers[g->n_layers - 1].nodes[0]->data;
1920  AEdge *e = RZ_NEW0(AEdge);
1921  if (!e) {
1922  free(arr);
1923  return;
1924  }
1925 
1926  e->is_reversed = true;
1927  e->from = NULL;
1928  e->to = NULL;
1929  e->x = rz_list_new();
1930  e->y = rz_list_new();
1931  if (g->layout == 0) {
1932  rz_list_append(e->y, (void *)(size_t)(n->y + g->layers[g->n_layers - 1].height + 2 + outedge));
1933  } else {
1934  rz_list_append(e->x, (void *)(size_t)(n->x + g->layers[g->n_layers - 1].width + 2 + outedge));
1935  }
1936  rz_list_append(g->edges, e);
1937  }
1938 err:
1939  for (i = i - 1; i >= 0; i--) {
1940  free(arr[i]);
1941  }
1942  free(arr);
1943  return;
1944 }
static int count_edges(const RzAGraph *g, RzANode *src, RzANode *dst)
Definition: agraph.c:1772
static bool err
Definition: armass.c:435
int max
Definition: enough.c:225
#define min(a, b)
Definition: qsort.h:83
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282

References a, syscall_preprocessing::arr, ax, b, count_edges(), e, err, free(), g, get_anode, graph_foreach_anode, gt, rz_ascii_node_t::h, i, if(), k, max, min, n, NULL, r, RZ_EDGES_X_INC, rz_graph_get_neighbours(), rz_graph_innodes(), rz_list_append(), rz_list_length(), rz_list_new(), RZ_NEW0, RZ_NEWS0, rz_ascii_node_t::w, rz_ascii_node_t::x, and rz_ascii_node_t::y.

Referenced by set_layout().

◆ bbcmp()

static int bbcmp ( RzAnalysisBlock a,
RzAnalysisBlock b 
)
static

Definition at line 2214 of file agraph.c.

2214  {
2215  return a->addr - b->addr;
2216 }

References a, and b.

Referenced by get_bbnodes(), and get_bbupdate().

◆ check_changes()

static bool check_changes ( RzAGraph g,
int  is_interactive,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 3364 of file agraph.c.

3364  {
3365  int oldpos[2] = {
3366  0, 0
3367  };
3368  if (g->need_reload_nodes && core) {
3369  if (!g->update_seek_on && !g->force_update_seek) {
3370  // save scroll here
3371  oldpos[0] = g->can->sx;
3372  oldpos[1] = g->can->sy;
3373  }
3374  if (!agraph_reload_nodes(g, core, fcn)) {
3375  return false;
3376  }
3377  }
3378  if (fcn) {
3379  agraph_update_title(core, g, fcn);
3380  }
3381  if (core && core->config) {
3382  if (rz_config_get_i(core->config, "graph.trace")) {
3383  // fold all bbs not traced
3384  fold_asm_trace(core, g);
3385  }
3386  }
3387  if (g->need_update_dim || g->need_reload_nodes || !is_interactive) {
3388  update_node_dimension(g->graph, is_mini(g), g->zoom, g->edgemode, g->is_callgraph, g->layout);
3389  }
3390  if (g->need_set_layout || g->need_reload_nodes || !is_interactive) {
3392  }
3393  if (core) {
3395  if (block) {
3396  char *title = get_title(block->addr);
3397  RzANode *cur_anode = get_anode(g->curnode);
3398  if (fcn && ((is_interactive && !cur_anode) || (cur_anode && strcmp(cur_anode->title, title)))) {
3399  g->update_seek_on = rz_agraph_get_node(g, title);
3400  if (g->update_seek_on) {
3401  rz_agraph_set_curnode(g, g->update_seek_on);
3402  g->force_update_seek = true;
3403  }
3404  }
3405  free(title);
3406  }
3407  g->can->color = rz_config_get_i(core->config, "scr.color");
3408  g->hints = rz_config_get_i(core->config, "graph.hints");
3409  }
3410  if (g->update_seek_on || g->force_update_seek) {
3411  RzANode *n = g->update_seek_on;
3412  if (!n && g->curnode) {
3413  n = get_anode(g->curnode);
3414  }
3415  if (n) {
3416  update_seek(g->can, n, g->force_update_seek);
3417  }
3418  }
3419  if (oldpos[0] || oldpos[1]) {
3420  g->can->sx = oldpos[0];
3421  g->can->sy = oldpos[1];
3422  }
3423  g->need_reload_nodes = false;
3424  g->need_update_dim = false;
3425  g->need_set_layout = false;
3426  g->update_seek_on = NULL;
3427  g->force_update_seek = false;
3428  return true;
3429 }
static void fold_asm_trace(RzCore *core, RzAGraph *g)
Definition: agraph.c:2274
RZ_API RzANode * rz_agraph_get_node(const RzAGraph *g, const char *title)
Definition: agraph.c:3852
static void agraph_update_title(RzCore *core, RzAGraph *g, RzAnalysisFunction *fcn)
Definition: agraph.c:3350
static void update_seek(RzConsCanvas *can, RzANode *n, int force)
Definition: agraph.c:2511
static bool agraph_reload_nodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:3178
static void update_node_dimension(const RzGraph *g, int is_mini, int zoom, int edgemode, bool callgraph, int layout)
Definition: agraph.c:212

References rz_analysis_bb_t::addr, agraph_reload_nodes(), agraph_set_layout(), agraph_update_title(), rz_core_t::analysis, rz_core_t::config, fold_asm_trace(), free(), g, get_anode, get_title(), is_mini(), n, NULL, rz_core_t::offset, rz_agraph_get_node(), rz_agraph_set_curnode(), rz_analysis_find_most_relevant_block_in(), rz_config_get_i(), rz_ascii_node_t::title, update_node_dimension(), and update_seek().

Referenced by agraph_print(), and rz_agraph_get_sdb().

◆ check_function_modified()

static void check_function_modified ( RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 3514 of file agraph.c.

3514  {
3516  if (rz_config_get_i(core->config, "analysis.detectwrites") || rz_cons_yesno('y', "Function was modified. Reanalyze? (Y/n)")) {
3518  }
3519  }
3520 }
RZ_API bool rz_analysis_function_was_modified(RzAnalysisFunction *fcn)
Definition: function.c:366
RZ_API void rz_analysis_function_update_analysis(RzAnalysisFunction *fcn)
Definition: fcn.c:2435

References rz_core_t::config, rz_analysis_function_update_analysis(), rz_analysis_function_was_modified(), rz_config_get_i(), and rz_cons_yesno().

Referenced by agraph_refresh(), and rz_core_visual_graph().

◆ cmp_dist()

static int cmp_dist ( const size_t  a,
const size_t  b 
)
static

Definition at line 1009 of file agraph.c.

1009  {
1010  return (a < b) - (a > b);
1011 }

References a, and b.

Referenced by adjust_class().

◆ collect_changes()

static void collect_changes ( const RzAGraph g,
int  l,
const RzGraphNode b,
int  from_up,
int  s,
int  e,
RzList list,
int  is_left 
)
static

Definition at line 1364 of file agraph.c.

1364  {
1365  const RzGraphNode *vt = g->layers[l].nodes[e - 1];
1366  const RzGraphNode *vtp = g->layers[l].nodes[s];
1367  struct len_pos_t *cx;
1368  int i;
1369 
1371 
1372  for (i = is_left ? s : e - 1; (is_left && i < e) || (!is_left && i >= s); i = is_left ? i + 1 : i - 1) {
1373  const RzGraphNode *v, *vi = g->layers[l].nodes[i];
1374  const RzANode *av, *avi = get_anode(vi);
1375  const RzList *neigh;
1376  const RzListIter *it;
1377  int c = 0;
1378 
1379  if (!avi) {
1380  continue;
1381  }
1382  neigh = from_up
1383  ? rz_graph_innodes(g->graph, vi)
1384  : rz_graph_get_neighbours(g->graph, vi);
1385 
1386  graph_foreach_anode (neigh, it, v, av) {
1387  if ((is_left && av->x >= avi->x) || (!is_left && av->x <= avi->x)) {
1388  c++;
1389  } else {
1390  cx = RZ_NEW(struct len_pos_t);
1391  c--;
1392  cx->len = 2;
1393  cx->pos = av->x;
1394  if (is_left) {
1395  cx->pos += dist_nodes(g, vi, vt);
1396  } else {
1397  cx->pos -= dist_nodes(g, vtp, vi);
1398  }
1399  rz_list_add_sorted(list, cx, lcmp);
1400  }
1401  }
1402 
1403  cx = RZ_NEW0(struct len_pos_t);
1404  cx->len = c;
1405  cx->pos = avi->x;
1406  if (is_left) {
1407  cx->pos += dist_nodes(g, vi, vt);
1408  } else {
1409  cx->pos -= dist_nodes(g, vtp, vi);
1410  }
1411  rz_list_add_sorted(list, cx, lcmp);
1412  }
1413 
1414  if (b) {
1415  const RzANode *ab = get_anode(b);
1416  cx = RZ_NEW(struct len_pos_t);
1417  if (cx) {
1418  cx->len = is_left ? INT_MAX : INT_MIN;
1419  cx->pos = ab->x;
1420  if (is_left) {
1421  cx->pos += dist_nodes(g, b, vt);
1422  } else {
1423  cx->pos -= dist_nodes(g, vtp, b);
1424  }
1425  rz_list_add_sorted(list, cx, lcmp);
1426  }
1427  }
1428 }
static int RM_listcmp(const struct len_pos_t *a, const struct len_pos_t *b)
Definition: agraph.c:1356
static int RP_listcmp(const struct len_pos_t *a, const struct len_pos_t *b)
Definition: agraph.c:1360
static RzSocket * s
Definition: rtr.c:28
#define RZ_NEW(x)
Definition: rz_types.h:285
int pos
Definition: agraph.c:64
int len
Definition: agraph.c:63

References b, c, dist_nodes(), e, g, get_anode, graph_foreach_anode, i, INT_MAX, len_pos_t::len, list(), len_pos_t::pos, RM_listcmp(), RP_listcmp(), rz_graph_get_neighbours(), rz_graph_innodes(), rz_list_add_sorted(), RZ_NEW, RZ_NEW0, s, v, and rz_ascii_node_t::x.

Referenced by combine_sequences().

◆ combine_sequences()

static void combine_sequences ( const RzAGraph g,
int  l,
const RzGraphNode bm,
const RzGraphNode bp,
int  from_up,
int  a,
int  r 
)
static

Definition at line 1430 of file agraph.c.

1430  {
1431  RzList *Rm = rz_list_new(), *Rp = rz_list_new();
1432  const RzGraphNode *vt, *vtp;
1433  RzANode *at, *atp;
1434  int rm, rp, t, m, i;
1435  Rm->free = (RzListFree)free;
1436  Rp->free = (RzListFree)free;
1437 
1438  t = (a + r) / 2;
1439  vt = g->layers[l].nodes[t - 1];
1440  vtp = g->layers[l].nodes[t];
1441  at = get_anode(vt);
1442  atp = get_anode(vtp);
1443 
1444  collect_changes(g, l, bm, from_up, a, t, Rm, true);
1445  collect_changes(g, l, bp, from_up, t, r, Rp, false);
1446  rm = rp = 0;
1447 
1448  m = dist_nodes(g, vt, vtp);
1449  if (at && atp) {
1450  while (atp->x - at->x < m) {
1451  if (atp->x == at->x) {
1452  int step = m / 2;
1453  at->x -= step;
1454  atp->x += m - step;
1455  } else {
1456  if (rm < rp) {
1457  if (rz_list_empty(Rm)) {
1458  at->x = atp->x - m;
1459  } else {
1460  struct len_pos_t *cx = (struct len_pos_t *)rz_list_pop(Rm);
1461  rm = rm + cx->len;
1462  at->x = RZ_MAX(cx->pos, atp->x - m);
1463  free(cx);
1464  }
1465  } else {
1466  if (rz_list_empty(Rp)) {
1467  atp->x = at->x + m;
1468  } else {
1469  struct len_pos_t *cx = (struct len_pos_t *)rz_list_pop(Rp);
1470  rp = rp + cx->len;
1471  atp->x = RZ_MIN(cx->pos, at->x + m);
1472  free(cx);
1473  }
1474  }
1475  }
1476  }
1477  }
1478 
1479  rz_list_free(Rm);
1480  rz_list_free(Rp);
1481 
1482  for (i = t - 2; i >= a; i--) {
1483  const RzGraphNode *gv = g->layers[l].nodes[i];
1484  RzANode *av = get_anode(gv);
1485  if (av && at) {
1486  av->x = RZ_MIN(av->x, at->x - dist_nodes(g, gv, vt));
1487  }
1488  }
1489 
1490  for (i = t + 1; i < r; i++) {
1491  const RzGraphNode *gv = g->layers[l].nodes[i];
1492  RzANode *av = get_anode(gv);
1493  if (av && atp) {
1494  av->x = RZ_MAX(av->x, atp->x + dist_nodes(g, vtp, gv));
1495  }
1496  }
1497 }
static void collect_changes(const RzAGraph *g, int l, const RzGraphNode *b, int from_up, int s, int e, RzList *list, int is_left)
Definition: agraph.c:1364
static states step(struct re_guts *, sopno, sopno, states, int, states)
Definition: engine.c:888
static char * rp[]
Definition: i8080dis.c:36
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
Definition: list.c:376
#define RZ_MAX(x, y)
RzListFree free
Definition: rz_list.h:21

References a, collect_changes(), dist_nodes(), rz_list_t::free, free(), g, get_anode, i, len_pos_t::len, regress::m, len_pos_t::pos, r, rp, rz_list_free(), rz_list_new(), rz_list_pop(), RZ_MAX, RZ_MIN, step(), and rz_ascii_node_t::x.

Referenced by place_sequence().

◆ compute_classes()

static RzList** compute_classes ( const RzAGraph g,
HtPP *  v_nodes,
int  is_left,
int n_classes 
)
static

Definition at line 967 of file agraph.c.

967  {
968  int i, j, c;
969  RzList **res = RZ_NEWS0(RzList *, g->n_layers);
970  RzGraphNode *gn;
971  const RzListIter *it;
972  RzANode *n;
973 
974  graph_foreach_anode (rz_graph_get_nodes(g->graph), it, gn, n) {
975  n->klass = -1;
976  }
977 
978  for (i = 0; i < g->n_layers; i++) {
979  c = i;
980 
981  for (j = is_left ? 0 : g->layers[i].n_nodes - 1;
982  (is_left && j < g->layers[i].n_nodes) || (!is_left && j >= 0);
983  j = is_left ? j + 1 : j - 1) {
984  const RzGraphNode *gj = g->layers[i].nodes[j];
985  const RzANode *aj = get_anode(gj);
986 
987  if (aj->klass == -1) {
988  const RzList *laj = ht_pp_find(v_nodes, gj, NULL);
989 
990  if (!res[c]) {
991  res[c] = rz_list_new();
992  }
993  graph_foreach_anode (laj, it, gn, n) {
994  rz_list_append(res[c], gn);
995  n->klass = c;
996  }
997  } else {
998  c = aj->klass;
999  }
1000  }
1001  }
1002 
1003  if (n_classes) {
1004  *n_classes = g->n_layers;
1005  }
1006  return res;
1007 }

References c, g, get_anode, graph_foreach_anode, i, rz_ascii_node_t::klass, n, NULL, rz_graph_get_nodes(), rz_list_append(), rz_list_new(), and RZ_NEWS0.

Referenced by compute_pos().

◆ compute_pos()

static HtPU* compute_pos ( const RzAGraph g,
int  is_left,
HtPP *  v_nodes 
)
static

Definition at line 1164 of file agraph.c.

1164  {
1165  int n_classes, i;
1166 
1167  RzList **classes = compute_classes(g, v_nodes, is_left, &n_classes);
1168  if (!classes) {
1169  return NULL;
1170  }
1171 
1172  HtPUOptions pu_opt = { 0 };
1173  HtPPOptions pp_opt = { 0 };
1174  HtPU *res = ht_pu_new_opt(&pu_opt);
1175  SetP *placed = (SetP *)ht_pp_new_opt(&pp_opt);
1176  if (!res || !placed) {
1177  ht_pu_free(res);
1178  set_p_free(placed);
1179  return NULL;
1180  }
1181  for (i = 0; i < n_classes; i++) {
1182  const RzGraphNode *gn;
1183  const RzListIter *it;
1184 
1185  rz_list_foreach (classes[i], it, gn) {
1186  if (!set_p_contains(placed, gn)) {
1187  place_nodes(g, gn, is_left, v_nodes, classes, res, placed);
1188  }
1189  }
1190 
1191  adjust_class(g, is_left, classes, res, i);
1192  }
1193 
1194  set_p_free(placed);
1195  for (i = 0; i < n_classes; i++) {
1196  if (classes[i]) {
1198  }
1199  }
1200  free(classes);
1201  return res;
1202 }
static void adjust_class(const RzAGraph *g, int is_left, RzList **classes, HtPU *res, int c)
Definition: agraph.c:1047
static RzList ** compute_classes(const RzAGraph *g, HtPP *v_nodes, int is_left, int *n_classes)
Definition: agraph.c:967
static void place_nodes(const RzAGraph *g, const RzGraphNode *gn, int is_left, HtPP *v_nodes, RzList **classes, HtPU *res, SetP *placed)
Definition: agraph.c:1126
RZ_API void set_p_free(SetP *p)
Definition: set.c:24
RZ_API bool set_p_contains(SetP *s, const void *u)
Definition: set.c:16
HtPP SetP
Definition: set.h:14

References adjust_class(), classes(), compute_classes(), free(), g, i, NULL, place_nodes(), rz_list_free(), set_p_contains(), and set_p_free().

Referenced by place_dummies().

◆ compute_vertical_nodes()

static HtPP* compute_vertical_nodes ( const RzAGraph g)
static

Definition at line 924 of file agraph.c.

924  {
925  HtPPOptions ht_opt = { 0 };
926  ht_opt.freefn = free_vertical_nodes_kv;
927  HtPP *res = ht_pp_new_opt(&ht_opt);
928  if (!res) {
929  return NULL;
930  }
931  for (int i = 0; i < g->n_layers; i++) {
932  for (int j = 0; j < g->layers[i].n_nodes; j++) {
933  RzGraphNode *gn = g->layers[i].nodes[j];
934  const RzList *Ln = ht_pp_find(res, gn, NULL);
935  const RzANode *an = get_anode(gn);
936 
937  if (!Ln) {
938  RzList *vert = rz_list_new();
939  ht_pp_insert(res, gn, vert);
940  if (an->is_dummy) {
941  RzGraphNode *next = gn;
942  const RzANode *anext = get_anode(next);
943 
944  while (anext->is_dummy) {
945  rz_list_append(vert, next);
946  next = rz_graph_nth_neighbour(g->graph, next, 0);
947  if (!next) {
948  break;
949  }
950  anext = get_anode(next);
951  }
952  } else {
953  rz_list_append(vert, gn);
954  }
955  }
956  }
957  }
958 
959  return res;
960 }
static void free_vertical_nodes_kv(HtPPKv *kv)
Definition: agraph.c:916

References free_vertical_nodes_kv(), g, get_anode, i, rz_ascii_node_t::is_dummy, NULL, rz_graph_nth_neighbour(), rz_list_append(), and rz_list_new().

Referenced by place_dummies().

◆ count_edges()

static int count_edges ( const RzAGraph g,
RzANode src,
RzANode dst 
)
static

Definition at line 1772 of file agraph.c.

1772  {
1773  return get_edge_number(g, src, dst, true);
1774 }
lzma_index * src
Definition: index.h:567
char * dst
Definition: lz4.h:724

References dst, g, get_edge_number(), and src.

Referenced by backedge_info().

◆ create_agraph_from_graph()

RZ_API RzAGraph* create_agraph_from_graph ( const RzGraph graph)

Create RzAGraph from generic RzGraph with RzGraphNodeInfo as node data.

Parameters
graph<RzGraphNodeInfo>
Returns
RzAGraph* NULL if failure

Definition at line 4916 of file agraph.c.

4916  {
4917  rz_return_val_if_fail(graph, NULL);
4918 
4919  RzAGraph *result_agraph = rz_agraph_new(rz_cons_canvas_new(1, 1));
4920  if (!result_agraph) {
4921  return NULL;
4922  }
4923  result_agraph->need_reload_nodes = false;
4924  // Cache lookup to build edges
4925  HtPPOptions pointer_options = { 0 };
4926  HtPP /*<RzGraphNode *node, RzANode *anode>*/ *hashmap = ht_pp_new_opt(&pointer_options);
4927 
4928  if (!hashmap) {
4929  rz_agraph_free(result_agraph);
4930  return NULL;
4931  }
4932  // List of the new RzANodes
4933  RzListIter *iter;
4934  RzGraphNode *node;
4935  // Traverse the list, create new ANode for each Node
4936  rz_list_foreach (graph->nodes, iter, node) {
4937  RzGraphNodeInfo *info = node->data;
4938  RzANode *a_node = rz_agraph_add_node(result_agraph, info->title, info->body);
4939  if (!a_node) {
4940  goto failure;
4941  }
4942  ht_pp_insert(hashmap, node, a_node);
4943  }
4944 
4945  // Traverse the nodes again, now build up the edges
4946  rz_list_foreach (graph->nodes, iter, node) {
4947  RzANode *a_node = ht_pp_find(hashmap, node, NULL);
4948  if (!a_node) {
4949  goto failure; // shouldn't happen in correct graph state
4950  }
4951 
4952  RzListIter *neighbour_iter;
4953  RzGraphNode *neighbour;
4954  rz_list_foreach (node->in_nodes, neighbour_iter, neighbour) {
4955  RzANode *a_neighbour = ht_pp_find(hashmap, neighbour, NULL);
4956  if (!a_neighbour) {
4957  goto failure;
4958  }
4959  rz_agraph_add_edge(result_agraph, a_neighbour, a_node);
4960  }
4961  }
4962 
4963  ht_pp_free(hashmap);
4964  return result_agraph;
4965 failure:
4966  ht_pp_free(hashmap);
4967  rz_agraph_free(result_agraph);
4968  return NULL;
4969 }
RZ_API void rz_agraph_free(RzAGraph *g)
Definition: agraph.c:3909
RZ_API RzAGraph * rz_agraph_new(RzConsCanvas *can)
Definition: agraph.c:3922
RZ_API RzANode * rz_agraph_add_node(const RzAGraph *g, const char *title, const char *body)
Definition: agraph.c:3765
RZ_API void rz_agraph_add_edge(const RzAGraph *g, RzANode *a, RzANode *b)
Definition: agraph.c:3862
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
RZ_API RzConsCanvas * rz_cons_canvas_new(int w, int h)
Definition: canvas.c:223
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
Generic drawable graph node.
RzList * nodes
Definition: rz_graph.h:29

References rz_graph_node_t::data, rz_graph_node_t::in_nodes, info(), rz_ascii_graph_t::need_reload_nodes, rz_graph_t::nodes, NULL, rz_agraph_add_edge(), rz_agraph_add_node(), rz_agraph_free(), rz_agraph_new(), rz_cons_canvas_new(), and rz_return_val_if_fail.

Referenced by rz_core_graph_print().

◆ create_dummy_nodes()

static void create_dummy_nodes ( RzAGraph g)
static

Definition at line 699 of file agraph.c.

699  {
700  if (!g->dummy) {
701  return;
702  }
703  RzGraphVisitor dummy_vis = {
704  NULL, NULL, NULL, NULL, NULL, NULL
705  };
706  const RzListIter *it;
707  const RzGraphEdge *e;
708 
709  g->long_edges = rz_list_newf((RzListFree)free);
710  dummy_vis.data = g->long_edges;
713  rz_graph_dfs(g->graph, &dummy_vis);
714 
715  rz_list_foreach (g->long_edges, it, e) {
716  RzANode *from = get_anode(e->from);
717  RzANode *to = get_anode(e->to);
718  int diff_layer = RZ_ABS(from->layer - to->layer);
719  RzANode *prev = get_anode(e->from);
720  int i, nth = e->nth;
721 
723  for (i = 1; i < diff_layer; i++) {
724  RzANode *dummy = rz_agraph_add_node(g, NULL, NULL);
725  if (!dummy) {
726  return;
727  }
728  dummy->is_dummy = true;
729  dummy->layer = from->layer + i;
730  dummy->is_reversed = is_reversed(g, e);
731  dummy->w = 1;
732  rz_agraph_add_edge_at(g, prev, dummy, nth);
733  rz_list_append(g->dummy_nodes, dummy);
734 
735  prev = dummy;
736  nth = -1;
737  }
738  rz_graph_add_edge(g->graph, prev->gnode, e->to);
739  }
740 }
RZ_API void rz_agraph_del_edge(const RzAGraph *g, RzANode *a, RzANode *b)
Definition: agraph.c:3880
static bool is_reversed(const RzAGraph *g, const RzGraphEdge *e)
Definition: agraph.c:694
RZ_API void rz_agraph_add_edge_at(const RzAGraph *g, RzANode *a, RzANode *b, int nth)
Definition: agraph.c:3871
static void view_dummy(const RzGraphEdge *e, const RzGraphVisitor *vis)
Definition: agraph.c:606
@ RZ_ABS
void(* RzGraphEdgeCallback)(const RzGraphEdge *e, RzGraphVisitor *vis)
Definition: rz_graph.h:41
RZ_API void rz_graph_add_edge(RzGraph *g, RzGraphNode *from, RzGraphNode *to)
Definition: graph.c:199
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
void(* tree_edge)(const RzGraphEdge *e, struct rz_graph_visitor_t *vis)
Definition: rz_graph.h:35
void(* fcross_edge)(const RzGraphEdge *e, struct rz_graph_visitor_t *vis)
Definition: rz_graph.h:37

References rz_graph_visitor_t::data, e, rz_graph_visitor_t::fcross_edge, free(), from, g, get_anode, rz_ascii_node_t::gnode, i, rz_ascii_node_t::is_dummy, is_reversed(), rz_ascii_node_t::is_reversed, rz_ascii_node_t::layer, NULL, RZ_ABS, rz_agraph_add_edge_at(), rz_agraph_add_node(), rz_agraph_del_edge(), rz_graph_add_edge(), rz_graph_dfs(), rz_list_append(), rz_list_newf(), to, rz_graph_visitor_t::tree_edge, view_dummy(), and rz_ascii_node_t::w.

Referenced by set_layout().

◆ create_layers()

static void create_layers ( RzAGraph g)
static

Definition at line 743 of file agraph.c.

743  {
744  const RzList *nodes = rz_graph_get_nodes(g->graph);
745  RzGraphNode *gn;
746  const RzListIter *it;
747  RzANode *n;
748  int i;
749 
750  /* identify max layer */
751  g->n_layers = 0;
752  graph_foreach_anode (nodes, it, gn, n) {
753  if (n->layer > g->n_layers) {
754  g->n_layers = n->layer;
755  }
756  }
757 
758  /* create a starting ordering of nodes for each layer */
759  g->n_layers++;
760  if (sizeof(struct layer_t) * g->n_layers < g->n_layers) {
761  return;
762  }
763  g->layers = RZ_NEWS0(struct layer_t, g->n_layers);
764 
765  graph_foreach_anode (nodes, it, gn, n) {
766  g->layers[n->layer].n_nodes++;
767  }
768 
769  for (i = 0; i < g->n_layers; i++) {
770  if (sizeof(RzGraphNode *) * g->layers[i].n_nodes < g->layers[i].n_nodes) {
771  continue;
772  }
773  g->layers[i].nodes = RZ_NEWS0(RzGraphNode *,
774  1 + g->layers[i].n_nodes);
775  g->layers[i].position = 0;
776  }
777  graph_foreach_anode (nodes, it, gn, n) {
778  n->pos_in_layer = g->layers[n->layer].position;
779  g->layers[n->layer].nodes[g->layers[n->layer].position++] = gn;
780  }
781 }
Definition: agraph.c:87

References g, graph_foreach_anode, i, n, rz_graph_get_nodes(), and RZ_NEWS0.

Referenced by set_layout().

◆ delete_dup_edges()

static void delete_dup_edges ( RzAGraph g)
static

Definition at line 2295 of file agraph.c.

2295  {
2296  RzListIter *it, *in_it, *in_it2, *in_it2_tmp;
2297  RzGraphNode *n, *a, *b;
2298  rz_list_foreach (g->graph->nodes, it, n) {
2299  rz_list_foreach (n->out_nodes, in_it, a) {
2300  for (in_it2 = in_it->n; in_it2 && (b = in_it2->data, in_it2_tmp = in_it2->n, 1); in_it2 = in_it2_tmp) {
2301  if (a->idx == b->idx) {
2302  rz_list_delete(n->out_nodes, in_it2);
2303  rz_list_delete_data(n->all_neighbours, b);
2304  rz_list_delete_data(b->in_nodes, n);
2305  rz_list_delete_data(b->all_neighbours, n);
2306  g->graph->n_edges--;
2307  }
2308  }
2309  }
2310  }
2311 }
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
RZ_API bool rz_list_delete_data(RZ_NONNULL RzList *list, void *ptr)
Deletes an entry in the list by searching for a pointer.
Definition: list.c:148
struct rz_list_iter_t * n
Definition: rz_list.h:15
void * data
Definition: rz_list.h:14

References a, b, rz_list_iter_t::data, g, n, rz_list_iter_t::n, rz_list_delete(), and rz_list_delete_data().

Referenced by get_bbnodes().

◆ dist_nodes()

static int dist_nodes ( const RzAGraph g,
const RzGraphNode a,
const RzGraphNode b 
)
static

Definition at line 825 of file agraph.c.

825  {
826  struct dist_t d;
827  const RzANode *aa, *ab;
828  RzListIter *it;
829  int res = 0;
830 
831  if (g->dists) {
832  d.from = a;
833  d.to = b;
834  it = rz_list_find(g->dists, &d, (RzListComparator)find_dist);
835  if (it) {
836  struct dist_t *old = (struct dist_t *)rz_list_iter_get_data(it);
837  return old->dist;
838  }
839  }
840 
841  aa = get_anode(a);
842  ab = get_anode(b);
843  if (aa && ab && aa->layer == ab->layer) {
844  int i;
845 
846  res = aa == ab && !aa->is_reversed ? HORIZONTAL_NODE_SPACING : 0;
847  for (i = aa->pos_in_layer; i < ab->pos_in_layer; i++) {
848  const RzGraphNode *cur = g->layers[aa->layer].nodes[i];
849  const RzGraphNode *next = g->layers[aa->layer].nodes[i + 1];
850  const RzANode *anext = get_anode(next);
851  const RzANode *acur = get_anode(cur);
852  int found = false;
853 
854  if (g->dists) {
855  d.from = cur;
856  d.to = next;
857  it = rz_list_find(g->dists, &d, (RzListComparator)find_dist);
858  if (it) {
859  struct dist_t *old = (struct dist_t *)rz_list_iter_get_data(it);
860  res += old->dist;
861  found = true;
862  }
863  }
864 
865  if (acur && anext && !found) {
866  int space = HORIZONTAL_NODE_SPACING;
867  if (acur->is_reversed && anext->is_reversed) {
868  if (!acur->is_reversed) {
869  res += acur->w / 2;
870  } else if (!anext->is_reversed) {
871  res += anext->w / 2;
872  }
873  res += 1;
874  } else {
875  res += acur->w / 2 + anext->w / 2 + space;
876  }
877  }
878  }
879  }
880 
881  return res;
882 }
#define HORIZONTAL_NODE_SPACING
Definition: agraph.c:32
static int find_dist(const struct dist_t *a, const struct dist_t *b)
Definition: agraph.c:818
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
RZ_API void * rz_list_iter_get_data(RzListIter *list)
returns the value stored in the list element
Definition: list.c:42
Definition: agraph.c:67
int dist
Definition: agraph.c:70

References a, b, d, dist_t::dist, find_dist(), found, g, get_anode, HORIZONTAL_NODE_SPACING, i, rz_ascii_node_t::is_reversed, rz_list_find(), rz_list_iter_get_data(), and rz_ascii_node_t::w.

Referenced by adjust_class_val(), collect_changes(), combine_sequences(), place_nodes_val(), place_original(), and place_single().

◆ find_dist()

static int find_dist ( const struct dist_t a,
const struct dist_t b 
)
static

Definition at line 818 of file agraph.c.

818  {
819  return a->from == b->from && a->to == b->to ? 0 : 1;
820 }

References a, and b.

Referenced by dist_nodes(), and set_dist_nodes().

◆ find_edge()

static int find_edge ( const RzGraphEdge a,
const RzGraphEdge b 
)
static

Definition at line 690 of file agraph.c.

690  {
691  return a->from == b->to && a->to == b->from ? 0 : 1;
692 }

References a, and b.

Referenced by is_reversed().

◆ find_near_of()

static const RzGraphNode* find_near_of ( const RzAGraph g,
const RzGraphNode cur,
int  is_next 
)
static

Definition at line 2550 of file agraph.c.

2550  {
2551  /* XXX: it's slow */
2552  const RzList *nodes = rz_graph_get_nodes(g->graph);
2553  const RzListIter *it;
2554  const RzGraphNode *gn, *resgn = NULL;
2555  const RzANode *n, *acur = cur ? get_anode(cur) : NULL;
2556  const int default_v = is_next ? INT_MIN : INT_MAX;
2557  const int start_x = acur ? acur->x : default_v;
2558  const int start_y = acur ? acur->y : default_v;
2559 
2560  graph_foreach_anode (nodes, it, gn, n) {
2561  // tab in horizontal layout is not correct, lets force vertical nextnode for now (g->layout == 0)
2562  bool isNear = true
2563  ? is_near(n, start_x, start_y, is_next)
2564  : is_near_h(n, start_x, start_y, is_next);
2565  if (isNear) {
2566  const RzANode *resn;
2567 
2568  if (!resgn) {
2569  resgn = gn;
2570  continue;
2571  }
2572 
2573  resn = get_anode(resgn);
2574  if ((is_next && resn->y > n->y) || (!is_next && resn->y < n->y)) {
2575  resgn = gn;
2576  } else if ((is_next && resn->y == n->y && resn->x > n->x) ||
2577  (!is_next && resn->y == n->y && resn->x < n->x)) {
2578  resgn = gn;
2579  }
2580  }
2581  }
2582  if (!resgn && cur) {
2583  resgn = find_near_of(g, NULL, is_next);
2584  }
2585  return resgn;
2586 }
static int is_near_h(const RzANode *n, int x, int y, int is_next)
XXX is wrong.
Definition: agraph.c:2543
static int is_near(const RzANode *n, int x, int y, int is_next)
Definition: agraph.c:2535

References g, get_anode, graph_foreach_anode, INT_MAX, is_near(), is_near_h(), n, NULL, rz_graph_get_nodes(), rz_ascii_node_t::x, and rz_ascii_node_t::y.

Referenced by agraph_next_node(), agraph_prev_node(), and rz_core_visual_graph().

◆ first_x_cmp()

static int first_x_cmp ( const void *  _a,
const void *  _b 
)
static

Definition at line 2829 of file agraph.c.

2829  {
2830  RzGraphNode *ga = (RzGraphNode *)_a;
2831  RzGraphNode *gb = (RzGraphNode *)_b;
2832  RzANode *a = (RzANode *)ga->data;
2833  RzANode *b = (RzANode *)gb->data;
2834  if (b->y < a->y) {
2835  return -1;
2836  }
2837  if (b->y > a->y) {
2838  return 1;
2839  }
2840  if (a->x < b->x) {
2841  return 1;
2842  }
2843  if (a->x > b->x) {
2844  return -1;
2845  }
2846  return 0;
2847 }

References a, b, and rz_graph_node_t::data.

Referenced by agraph_print_edges().

◆ fix_back_edge_dummy_nodes()

static void fix_back_edge_dummy_nodes ( RzAGraph g,
RzANode from,
RzANode to 
)
static

Definition at line 1698 of file agraph.c.

1698  {
1699  RzANode *v, *tmp = NULL;
1700  RzGraphNode *gv = NULL;
1701  RzListIter *it;
1702  int i;
1703  rz_return_if_fail(g && from && to);
1704  const RzList *neighbours = rz_graph_get_neighbours(g->graph, to->gnode);
1705  graph_foreach_anode (neighbours, it, gv, v) {
1706  tmp = v;
1707  while (tmp->is_dummy) {
1708  tmp = (RzANode *)(((RzGraphNode *)rz_list_first(tmp->gnode->out_nodes))->data);
1709  }
1710  if (tmp->gnode->idx == from->gnode->idx) {
1711  break;
1712  }
1713  tmp = NULL;
1714  }
1715  if (tmp) {
1716  tmp = v;
1717  while (tmp->gnode->idx != from->gnode->idx) {
1718  v = tmp;
1719  tmp = (RzANode *)(((RzGraphNode *)rz_list_first(v->gnode->out_nodes))->data);
1720 
1721  i = 0;
1722  while (v->gnode->idx != g->layers[v->layer].nodes[i]->idx) {
1723  i += 1;
1724  }
1725 
1726  while (i + 1 < g->layers[v->layer].n_nodes) {
1727  g->layers[v->layer].nodes[i] = g->layers[v->layer].nodes[i + 1];
1728  i++;
1729  }
1730  g->layers[v->layer].nodes[g->layers[v->layer].n_nodes - 1] = 0;
1731  g->layers[v->layer].n_nodes -= 1;
1732 
1733  rz_graph_del_node(g->graph, v->gnode);
1734  }
1735  }
1736 }
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
RZ_API void rz_graph_del_node(RzGraph *g, RzGraphNode *n)
Definition: graph.c:177

References from, g, graph_foreach_anode, i, NULL, rz_graph_del_node(), rz_graph_get_neighbours(), rz_list_first(), rz_return_if_fail, autogen_x86imm::tmp, to, and v.

Referenced by set_layout().

◆ fold_asm_trace()

static void fold_asm_trace ( RzCore core,
RzAGraph g 
)
static

Definition at line 2274 of file agraph.c.

2274  {
2275  const RzList *nodes = rz_graph_get_nodes(g->graph);
2276  RzGraphNode *gn;
2277  RzListIter *it;
2278  RzANode *n;
2279 
2280  RzANode *curnode = get_anode(g->curnode);
2281  graph_foreach_anode (nodes, it, gn, n) {
2282  if (curnode == n) {
2283  n->is_mini = false;
2284  g->need_reload_nodes = true;
2285  continue;
2286  }
2287  ut64 addr = rz_num_get(NULL, n->title);
2289  n->is_mini = (tp == NULL);
2290  }
2291  g->need_update_dim = 1;
2292  // agraph_refresh (rz_cons_singleton ()->event_data);
2293 }
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API RzDebugTracepoint * rz_debug_trace_get(RzDebug *dbg, ut64 addr)
Definition: trace.c:200

References addr, rz_core_t::dbg, g, get_anode, graph_foreach_anode, n, NULL, rz_debug_trace_get(), rz_graph_get_nodes(), rz_num_get(), and ut64().

Referenced by check_changes().

◆ follow_nth()

static void follow_nth ( RzAGraph g,
int  nth 
)
static

Definition at line 3183 of file agraph.c.

3183  {
3184  const RzGraphNode *cn = rz_graph_nth_neighbour(g->graph, g->curnode, nth);
3185  RzANode *a = get_anode(cn);
3186 
3187  while (a && a->is_dummy) {
3188  cn = rz_graph_nth_neighbour(g->graph, a->gnode, 0);
3189  a = get_anode(cn);
3190  }
3191  if (a) {
3193  }
3194 }

References a, g, get_anode, rz_agraph_set_curnode(), and rz_graph_nth_neighbour().

Referenced by agraph_follow_false(), and agraph_follow_true().

◆ free_nodes_kv()

static void free_nodes_kv ( HtPPKv *  kv)
static

Definition at line 3601 of file agraph.c.

3601  {
3602  RzANode *n = (RzANode *)kv->value;
3603  if (!n->is_dummy) {
3605  }
3606 }

References agraph_node_free(), if(), and n.

◆ free_vertical_nodes_kv()

static void free_vertical_nodes_kv ( HtPPKv *  kv)
static

Definition at line 916 of file agraph.c.

916  {
917  rz_list_free(kv->value);
918 }

References rz_list_free().

Referenced by compute_vertical_nodes().

◆ get_bb_body()

static char* get_bb_body ( RzCore core,
RzAnalysisBlock b,
int  opts,
RzAnalysisFunction fcn,
bool  emu,
ut64  saved_gp,
ut8 saved_arena 
)
static

Definition at line 2167 of file agraph.c.

2167  {
2168  if (emu) {
2169  core->analysis->gp = saved_gp;
2170  if (b->parent_reg_arena) {
2171  rz_reg_arena_poke(core->analysis->reg, b->parent_reg_arena);
2172  RZ_FREE(b->parent_reg_arena);
2173  ut64 gp = rz_reg_getv(core->analysis->reg, "gp");
2174  if (gp) {
2175  core->analysis->gp = gp;
2176  }
2177  } else {
2178  rz_reg_arena_poke(core->analysis->reg, saved_arena);
2179  }
2180  }
2181  if (b->parent_stackptr != INT_MAX) {
2182  core->analysis->stackptr = b->parent_stackptr;
2183  }
2184  char *body = get_body(core, b->addr, b->size, opts);
2185  if (b->jump != UT64_MAX) {
2186  if (b->jump > b->addr) {
2187  RzAnalysisBlock *jumpbb = rz_analysis_get_block_at(b->analysis, b->jump);
2188  if (jumpbb && rz_list_contains(jumpbb->fcns, fcn)) {
2189  if (emu && core->analysis->last_disasm_reg != NULL && !jumpbb->parent_reg_arena) {
2191  }
2192  if (jumpbb->parent_stackptr == INT_MAX) {
2193  jumpbb->parent_stackptr = core->analysis->stackptr + b->stackptr;
2194  }
2195  }
2196  }
2197  }
2198  if (b->fail != UT64_MAX) {
2199  if (b->fail > b->addr) {
2200  RzAnalysisBlock *failbb = rz_analysis_get_block_at(b->analysis, b->fail);
2201  if (failbb && rz_list_contains(failbb->fcns, fcn)) {
2202  if (emu && core->analysis->last_disasm_reg != NULL && !failbb->parent_reg_arena) {
2204  }
2205  if (failbb->parent_stackptr == INT_MAX) {
2206  failbb->parent_stackptr = core->analysis->stackptr + b->stackptr;
2207  }
2208  }
2209  }
2210  }
2211  return body;
2212 }
static char * get_body(RzCore *core, ut64 addr, int size, int opts)
Definition: agraph.c:2104
RZ_API ut8 * rz_reg_arena_dup(RzReg *reg, const ut8 *source)
Definition: arena.c:301
RZ_API void rz_reg_arena_poke(RzReg *reg, const ut8 *ret)
Definition: arena.c:293
RZ_API RzAnalysisBlock * rz_analysis_get_block_at(RzAnalysis *analysis, ut64 addr)
Definition: block.c:90
RZ_API RZ_BORROW RzListIter * rz_list_contains(RZ_NONNULL const RzList *list, RZ_NONNULL const void *ptr)
Returns the RzListIter of the given pointer, if found.
Definition: list.c:592
RZ_API ut64 rz_reg_getv(RzReg *reg, const char *name)
Definition: reg.c:332
#define RZ_FREE(x)
Definition: rz_types.h:369
#define UT64_MAX
Definition: rz_types_base.h:86
ut8 * parent_reg_arena
Definition: rz_analysis.h:877
ut8 * last_disasm_reg
Definition: rz_analysis.h:569

References rz_core_t::analysis, b, rz_analysis_bb_t::fcns, get_body(), rz_analysis_t::gp, INT_MAX, rz_analysis_t::last_disasm_reg, NULL, rz_analysis_bb_t::parent_reg_arena, rz_analysis_bb_t::parent_stackptr, rz_analysis_t::reg, rz_analysis_get_block_at(), RZ_FREE, rz_list_contains(), rz_reg_arena_dup(), rz_reg_arena_poke(), rz_reg_getv(), rz_analysis_t::stackptr, ut64(), and UT64_MAX.

Referenced by get_bbnodes(), and get_bbupdate().

◆ get_bbnodes()

static int get_bbnodes ( RzAGraph g,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 2331 of file agraph.c.

2331  {
2332  RzAnalysisBlock *bb;
2333  RzListIter *iter;
2334  char *shortcut = NULL;
2335  int shortcuts = 0;
2336  bool emu = rz_config_get_i(core->config, "asm.emu");
2337  bool few = rz_config_get_i(core->config, "graph.few");
2338  int ret = false;
2339  ut64 saved_gp = core->analysis->gp;
2340  ut8 *saved_arena = NULL;
2341  int saved_stackptr = core->analysis->stackptr;
2342  core->keep_asmqjmps = false;
2343 
2344  if (!fcn) {
2345  return false;
2346  }
2347  if (emu) {
2348  saved_arena = rz_reg_arena_peek(core->analysis->reg);
2349  }
2351  RzAnalysisBlock *curbb = NULL;
2352  if (few) {
2353  rz_list_foreach (fcn->bbs, iter, bb) {
2354  if (!curbb) {
2355  curbb = bb;
2356  }
2357  if (rz_analysis_block_contains(bb, core->offset)) {
2358  curbb = bb;
2359  break;
2360  }
2361  }
2362  }
2363 
2364  core->keep_asmqjmps = false;
2365  rz_list_foreach (fcn->bbs, iter, bb) {
2366  if (bb->addr == UT64_MAX) {
2367  continue;
2368  }
2369  if (few && !isbbfew(curbb, bb)) {
2370  continue;
2371  }
2372  char *body = get_bb_body(core, bb, mode2opts(g), fcn, emu, saved_gp, saved_arena);
2373  char *title = get_title(bb->addr);
2374 
2375  RzANode *node = rz_agraph_add_node(g, title, body);
2376  shortcuts = g->is_interactive ? rz_config_get_i(core->config, "graph.nodejmps") : false;
2377 
2378  if (shortcuts) {
2379  shortcut = rz_core_add_asmqjmp(core, bb->addr);
2380  if (shortcut) {
2381  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.shortcut", title), shortcut, 0);
2382  free(shortcut);
2383  }
2384  }
2385  free(body);
2386  free(title);
2387  if (!node) {
2388  goto cleanup;
2389  }
2390  core->keep_asmqjmps = true;
2391  }
2392 
2393  rz_list_foreach (fcn->bbs, iter, bb) {
2394  if (bb->addr == UT64_MAX) {
2395  continue;
2396  }
2397  if (few && !isbbfew(curbb, bb)) {
2398  continue;
2399  }
2400 
2401  char *title = get_title(bb->addr);
2402  RzANode *u = rz_agraph_get_node(g, title);
2403  RzANode *v;
2404  free(title);
2405  if (bb->jump != UT64_MAX) {
2406  title = get_title(bb->jump);
2407  v = rz_agraph_get_node(g, title);
2408  free(title);
2409  rz_agraph_add_edge(g, u, v);
2410  }
2411  if (bb->fail != UT64_MAX) {
2412  title = get_title(bb->fail);
2413  v = rz_agraph_get_node(g, title);
2414  free(title);
2415  rz_agraph_add_edge(g, u, v);
2416  }
2417  if (bb->switch_op) {
2418  RzListIter *it;
2419  RzAnalysisCaseOp *cop;
2420  rz_list_foreach (bb->switch_op->cases, it, cop) {
2421  title = get_title(cop->addr);
2422  v = rz_agraph_get_node(g, title);
2423  free(title);
2424  rz_agraph_add_edge(g, u, v);
2425  }
2426  }
2427  }
2428 
2430  ret = true;
2431 
2432 cleanup:
2433  if (emu) {
2434  core->analysis->gp = saved_gp;
2435  if (saved_arena) {
2436  rz_reg_arena_poke(core->analysis->reg, saved_arena);
2437  RZ_FREE(saved_arena);
2438  }
2439  }
2440  core->analysis->stackptr = saved_stackptr;
2441  return ret;
2442 }
static bool isbbfew(RzAnalysisBlock *curbb, RzAnalysisBlock *bb)
Definition: agraph.c:2313
static int mode2opts(const RzAGraph *g)
Definition: agraph.c:159
static int bbcmp(RzAnalysisBlock *a, RzAnalysisBlock *b)
Definition: agraph.c:2214
static void delete_dup_edges(RzAGraph *g)
Definition: agraph.c:2295
static char * get_bb_body(RzCore *core, RzAnalysisBlock *b, int opts, RzAnalysisFunction *fcn, bool emu, ut64 saved_gp, ut8 *saved_arena)
Definition: agraph.c:2167
RZ_API ut8 * rz_reg_arena_peek(RzReg *reg)
Definition: arena.c:280
#define false
void cleanup(void)
Definition: enough.c:244
uint8_t ut8
Definition: lh5801.h:11
RZ_API char * rz_core_add_asmqjmp(RzCore *core, ut64 addr)
Definition: core.c:238
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RzAnalysisSwitchOp * switch_op
Definition: rz_analysis.h:874
bool keep_asmqjmps
Definition: rz_core.h:350

References rz_analysis_case_obj_t::addr, rz_analysis_bb_t::addr, rz_core_t::analysis, bbcmp(), rz_analysis_function_t::bbs, rz_analysis_switch_obj_t::cases, cleanup(), rz_core_t::config, delete_dup_edges(), rz_analysis_bb_t::fail, free(), g, get_bb_body(), get_title(), rz_analysis_t::gp, isbbfew(), rz_analysis_bb_t::jump, rz_core_t::keep_asmqjmps, mode2opts(), NULL, rz_core_t::offset, rz_analysis_t::reg, rz_agraph_add_edge(), rz_agraph_add_node(), rz_agraph_get_node(), rz_config_get_i(), rz_core_add_asmqjmp(), RZ_FREE, rz_list_sort(), rz_reg_arena_peek(), rz_reg_arena_poke(), sdb_fmt(), sdb_set(), rz_analysis_t::stackptr, rz_analysis_bb_t::switch_op, ut64(), UT64_MAX, and v.

Referenced by reload_nodes().

◆ get_bbupdate()

static void get_bbupdate ( RzAGraph g,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 2218 of file agraph.c.

2218  {
2219  RzAnalysisBlock *bb;
2220  RzListIter *iter;
2221  bool emu = rz_config_get_i(core->config, "asm.emu");
2222  ut64 saved_gp = core->analysis->gp;
2223  ut8 *saved_arena = NULL;
2224  int saved_stackptr = core->analysis->stackptr;
2225  char *shortcut = 0;
2226  int shortcuts = 0;
2227  core->keep_asmqjmps = false;
2228 
2229  if (emu) {
2230  saved_arena = rz_reg_arena_peek(core->analysis->reg);
2231  }
2232  if (!fcn) {
2233  RZ_FREE(saved_arena);
2234  return;
2235  }
2237 
2238  shortcuts = rz_config_get_i(core->config, "graph.nodejmps");
2239  rz_list_foreach (fcn->bbs, iter, bb) {
2240  if (bb->addr == UT64_MAX) {
2241  continue;
2242  }
2243  char *body = get_bb_body(core, bb, mode2opts(g), fcn, emu, saved_gp, saved_arena);
2244  char *title = get_title(bb->addr);
2245 
2246  if (shortcuts) {
2247  shortcut = rz_core_add_asmqjmp(core, bb->addr);
2248  if (shortcut) {
2249  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.shortcut", title), shortcut, 0);
2250  free(shortcut);
2251  }
2252  }
2253  RzANode *node = rz_agraph_get_node(g, title);
2254  if (node) {
2255  free(node->body);
2256  node->body = body;
2257  } else {
2258  free(body);
2259  }
2260  free(title);
2261  core->keep_asmqjmps = true;
2262  }
2263 
2264  if (emu) {
2265  core->analysis->gp = saved_gp;
2266  if (saved_arena) {
2267  rz_reg_arena_poke(core->analysis->reg, saved_arena);
2268  RZ_FREE(saved_arena);
2269  }
2270  }
2271  core->analysis->stackptr = saved_stackptr;
2272 }

References rz_analysis_bb_t::addr, rz_core_t::analysis, bbcmp(), rz_analysis_function_t::bbs, rz_ascii_node_t::body, rz_core_t::config, free(), g, get_bb_body(), get_title(), rz_analysis_t::gp, rz_core_t::keep_asmqjmps, mode2opts(), NULL, rz_analysis_t::reg, rz_agraph_get_node(), rz_config_get_i(), rz_core_add_asmqjmp(), RZ_FREE, rz_list_sort(), rz_reg_arena_peek(), rz_reg_arena_poke(), sdb_fmt(), sdb_set(), rz_analysis_t::stackptr, ut64(), and UT64_MAX.

Referenced by rz_core_visual_graph().

◆ get_body()

static char* get_body ( RzCore core,
ut64  addr,
int  size,
int  opts 
)
static

Definition at line 2104 of file agraph.c.

2104  {
2105  char *body;
2106  RzConfigHold *hc = rz_config_hold_new(core->config);
2107  if (!hc) {
2108  return NULL;
2109  }
2110  rz_config_hold_i(hc, "asm.lines", "asm.bytes",
2111  "asm.cmt.col", "asm.marks", "asm.offset",
2112  "asm.comments", "asm.cmt.right", "asm.bb.line", NULL);
2113  const bool o_comments = rz_config_get_i(core->config, "graph.comments");
2114  const bool o_cmtright = rz_config_get_i(core->config, "graph.cmtright");
2115  const bool o_bytes = rz_config_get_i(core->config, "graph.bytes");
2116  const bool o_flags_in_bytes = rz_config_get_i(core->config, "asm.flags.inbytes");
2117  const bool o_graph_offset = rz_config_get_i(core->config, "graph.offset");
2118  int o_cursor = core->print->cur_enabled;
2119  if (opts & BODY_COMMENTS) {
2120  rz_core_visual_toggle_decompiler_disasm(core, true, false);
2121  char *res = rz_core_cmd_strf(core, "pD %d @ 0x%08" PFMT64x, size, addr);
2122  res = rz_str_replace(res, "; ", "", true);
2123  // res = rz_str_replace (res, "\n", "(\n)", true);
2124  rz_str_trim(res);
2125  res = rz_str_trim_lines(res);
2126  rz_core_visual_toggle_decompiler_disasm(core, true, false);
2128  rz_config_hold_free(hc);
2129  return res;
2130  }
2131  const char *cmd = (opts & BODY_SUMMARY) ? "pds" : "pD";
2132 
2133  // configure options
2134  rz_config_set_i(core->config, "asm.bb.line", false);
2135  rz_config_set_i(core->config, "asm.lines", false);
2136  rz_config_set_i(core->config, "asm.cmt.col", 0);
2137  rz_config_set_i(core->config, "asm.marks", false);
2138  rz_config_set_i(core->config, "asm.cmt.right", (opts & BODY_SUMMARY) || o_cmtright);
2139  rz_config_set_i(core->config, "asm.comments", (opts & BODY_SUMMARY) || o_comments);
2140  rz_config_set_i(core->config, "asm.bytes",
2141  (opts & (BODY_SUMMARY | BODY_OFFSETS)) || o_bytes || o_flags_in_bytes);
2142  rz_config_set_i(core->config, "asm.bb.middle", false);
2143  core->print->cur_enabled = false;
2144 
2145  if (opts & BODY_OFFSETS || opts & BODY_SUMMARY || o_graph_offset) {
2146  rz_config_set_i(core->config, "asm.offset", true);
2147  } else {
2148  rz_config_set_i(core->config, "asm.offset", false);
2149  }
2150 
2151  bool html = rz_config_get_i(core->config, "scr.html");
2152  rz_config_set_i(core->config, "scr.html", 0);
2153  if (rz_config_get_i(core->config, "graph.aeab")) {
2154  body = rz_core_cmd_strf(core, "%s 0x%08" PFMT64x, "aeab", addr);
2155  } else {
2156  body = rz_core_cmd_strf(core, "%s %d @ 0x%08" PFMT64x, cmd, size, addr);
2157  }
2158  rz_config_set_i(core->config, "scr.html", html);
2159 
2160  // restore original options
2161  core->print->cur_enabled = o_cursor;
2163  rz_config_hold_free(hc);
2164  return body;
2165 }
#define BODY_COMMENTS
Definition: agraph.c:51
#define BODY_SUMMARY
Definition: agraph.c:50
#define BODY_OFFSETS
Definition: agraph.c:49
RZ_API char * rz_core_cmd_strf(RzCore *core, const char *fmt,...)
Definition: cmd.c:5472
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
RZ_API void rz_config_hold_restore(RzConfigHold *h)
Restore whatever config options were previously saved in h.
Definition: hold.c:132
RZ_API RzConfigHold * rz_config_hold_new(RzConfig *cfg)
Create an opaque object to save/restore some configuration options.
Definition: hold.c:116
RZ_API bool rz_config_hold_i(RzConfigHold *h,...)
Save the current values of a list of config options that have integer values.
Definition: hold.c:81
RZ_API void rz_config_hold_free(RzConfigHold *h)
Free a RzConfigHold object h.
Definition: hold.c:152
voidpf void uLong size
Definition: ioapi.h:138
RZ_API char * rz_str_trim_lines(char *str)
Definition: str_trim.c:60
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190
RzPrint * print
Definition: rz_core.h:327
bool cur_enabled
Definition: rz_print.h:130
RZ_API void rz_core_visual_toggle_decompiler_disasm(RzCore *core, bool for_graph, bool reset)
Definition: visual.c:127

References addr, BODY_COMMENTS, BODY_OFFSETS, BODY_SUMMARY, cmd, rz_core_t::config, rz_print_t::cur_enabled, make_dist_html::html, NULL, PFMT64x, rz_core_t::print, rz_config_get_i(), rz_config_hold_free(), rz_config_hold_i(), rz_config_hold_new(), rz_config_hold_restore(), rz_config_set_i(), rz_core_cmd_strf(), rz_core_visual_toggle_decompiler_disasm(), rz_str_replace(), rz_str_trim(), and rz_str_trim_lines().

Referenced by get_bb_body(), and get_cgnodes().

◆ get_cgnodes()

static bool get_cgnodes ( RzAGraph g,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 2446 of file agraph.c.

2446  {
2448  RzANode *node, *fcn_anode;
2449  RzListIter *iter;
2450  RzAnalysisXRef *xref;
2451  if (!f) {
2452  return false;
2453  }
2454  if (!fcn) {
2455  fcn = f;
2456  }
2457 
2458  rz_core_seek(core, f->addr, true);
2459 
2460  char *title = get_title(fcn->addr);
2461  fcn_anode = rz_agraph_add_node(g, title, "");
2462 
2463  free(title);
2464  if (!fcn_anode) {
2465  return false;
2466  }
2467 
2468  fcn_anode->x = 10;
2469  fcn_anode->y = 3;
2470 
2472  rz_list_foreach (xrefs, iter, xref) {
2473  title = get_title(xref->to);
2474  if (rz_agraph_get_node(g, title) != NULL) {
2475  continue;
2476  }
2477  free(title);
2478 
2479  int size = 0;
2481  if (bb) {
2482  size = bb->size;
2483  }
2484 
2485  char *body = get_body(core, xref->to, size, mode2opts(g));
2486  title = get_title(xref->to);
2487 
2488  node = rz_agraph_add_node(g, title, body);
2489  if (!node) {
2490  return false;
2491  }
2492 
2493  free(title);
2494  free(body);
2495 
2496  node->x = 10;
2497  node->y = 10;
2498 
2499  rz_agraph_add_edge(g, fcn_anode, node);
2500  }
2501  rz_list_free(xrefs);
2502 
2503  return true;
2504 }
RZ_API bool rz_core_seek(RzCore *core, ut64 addr, bool rb)
Seek to addr.
Definition: seek.c:116
RZ_API RzList * rz_analysis_function_get_xrefs_from(RzAnalysisFunction *fcn)
Definition: xrefs.c:297

References rz_analysis_function_t::addr, rz_core_t::analysis, f, free(), g, get_body(), get_title(), mode2opts(), NULL, rz_core_t::offset, rz_agraph_add_edge(), rz_agraph_add_node(), rz_agraph_get_node(), rz_analysis_find_most_relevant_block_in(), rz_analysis_function_get_xrefs_from(), rz_analysis_get_fcn_in(), rz_core_seek(), rz_list_free(), rz_analysis_bb_t::size, rz_analysis_ref_t::to, rz_ascii_node_t::x, and rz_ascii_node_t::y.

Referenced by reload_nodes().

◆ get_crossing_matrix()

static int** get_crossing_matrix ( const RzGraph g,
const struct layer_t  layers[],
int  maxlayer,
int  i,
int  from_up,
int n_rows 
)
static

Definition at line 433 of file agraph.c.

436  {
437  int j, len = layers[i].n_nodes;
438 
439  int **m = RZ_NEWS0(int *, len);
440  if (!m) {
441  return NULL;
442  }
443  for (j = 0; j < len; j++) {
444  m[j] = RZ_NEWS0(int, len);
445  if (!m[j]) {
446  goto err_row;
447  }
448  }
449  /* calculate crossings between layer i and layer i-1 */
450  /* consider the crossings generated by each pair of edges */
451  if (i > 0 && from_up) {
452  if (rz_cons_is_breaked()) {
453  goto err_row;
454  }
455  for (j = 0; j < layers[i - 1].n_nodes; j++) {
456  const RzGraphNode *gj = layers[i - 1].nodes[j];
457  const RzList *neigh = rz_graph_get_neighbours(g, gj);
458  RzGraphNode *gk;
459  RzListIter *itk;
460 
461  rz_list_foreach (neigh, itk, gk) {
462  int s;
463  // skip self-loop
464  if (gj == gk) {
465  continue;
466  }
467  for (s = 0; s < j; s++) {
468  const RzGraphNode *gs = layers[i - 1].nodes[s];
469  const RzList *neigh_s = rz_graph_get_neighbours(g, gs);
470  RzGraphNode *gt;
471  RzListIter *itt;
472 
473  rz_list_foreach (neigh_s, itt, gt) {
474  const RzANode *ak, *at; /* k and t should be "indexes" on layer i */
475  if (gt == gk || gt == gs) {
476  continue;
477  }
478  ak = get_anode(gk);
479  at = get_anode(gt);
480  if (ak->layer != i || at->layer != i) {
481  // this should never happen
482  // but it happens if we do graph.dummy = false, so better hide it for now
483 #if 0
484  eprintf ("(WARNING) \"%s\" (%d) or \"%s\" (%d) are not on the right layer (%d)\n",
485  ak->title, ak->layer,
486  at->title, at->layer,
487  i);
488 #endif
489  continue;
490  }
491  m[ak->pos_in_layer][at->pos_in_layer]++;
492  }
493  }
494  }
495  }
496  }
497 
498  /* calculate crossings between layer i and layer i+1 */
499  if (i < maxlayer - 1 && !from_up) {
500  if (rz_cons_is_breaked()) {
501  goto err_row;
502  }
503  for (j = 0; j < layers[i].n_nodes; j++) {
504  const RzGraphNode *gj = layers[i].nodes[j];
505  const RzList *neigh = rz_graph_get_neighbours(g, gj);
506  const RzANode *ak, *aj = get_anode(gj);
507  RzGraphNode *gk;
508  RzListIter *itk;
509 
510  if (rz_cons_is_breaked()) {
511  goto err_row;
512  }
513  graph_foreach_anode (neigh, itk, gk, ak) {
514  int s;
515  for (s = 0; s < layers[i].n_nodes; s++) {
516  const RzGraphNode *gs = layers[i].nodes[s];
517  const RzList *neigh_s;
518  RzGraphNode *gt;
519  RzListIter *itt;
520  const RzANode *at, *as = get_anode(gs);
521 
522  if (gs == gj) {
523  continue;
524  }
525  neigh_s = rz_graph_get_neighbours(g, gs);
526  graph_foreach_anode (neigh_s, itt, gt, at) {
527  if (at->pos_in_layer < ak->pos_in_layer) {
528  m[aj->pos_in_layer][as->pos_in_layer]++;
529  }
530  }
531  }
532  }
533  }
534  }
535 
536  if (n_rows) {
537  *n_rows = len;
538  }
539  return m;
540 
541 err_row:
542  for (i = 0; i < len; i++) {
543  free(m[i]);
544  }
545  free(m);
546  return NULL;
547 }
static RzSocket * gs
Definition: io_winedbg.c:11
#define eprintf(x, y...)
Definition: rlcc.c:7
int n_nodes
Definition: agraph.c:88
RzGraphNode ** nodes
Definition: agraph.c:89

References eprintf, free(), g, get_anode, graph_foreach_anode, gs, gt, i, rz_ascii_node_t::layer, len, regress::m, layer_t::n_nodes, layer_t::nodes, NULL, rz_ascii_node_t::pos_in_layer, rz_cons_is_breaked(), rz_graph_get_neighbours(), RZ_NEWS0, s, and rz_ascii_node_t::title.

Referenced by layer_sweep().

◆ get_edge_number()

static int get_edge_number ( const RzAGraph g,
RzANode src,
RzANode dst,
bool  outgoing 
)
static

Definition at line 1738 of file agraph.c.

1738  {
1739  RzListIter *itn;
1740  RzGraphNode *gv;
1741  int cur_nth = 0;
1742  int nth = 0;
1743  RzANode *v;
1744 
1745  if (outgoing && src->is_dummy) {
1746  RzANode *in = (RzANode *)(((RzGraphNode *)rz_list_first((src->gnode)->in_nodes))->data);
1747  cur_nth = get_edge_number(g, in, src, outgoing);
1748  } else {
1749  const RzList *neighbours = outgoing
1750  ? rz_graph_get_neighbours(g->graph, src->gnode)
1751  : rz_graph_innodes(g->graph, dst->gnode);
1752  const int exit_edges = rz_list_length(neighbours);
1753  graph_foreach_anode (neighbours, itn, gv, v) {
1754  cur_nth = nth;
1755  if (g->is_callgraph) {
1756  cur_nth = 0;
1757  } else if (exit_edges == 1) {
1758  cur_nth = -1;
1759  }
1760  if (outgoing && gv->idx == (dst->gnode)->idx) {
1761  break;
1762  }
1763  if (!outgoing && gv->idx == (src->gnode)->idx) {
1764  break;
1765  }
1766  nth++;
1767  }
1768  }
1769  return cur_nth;
1770 }
unsigned int idx
Definition: rz_graph.h:11

References dst, g, graph_foreach_anode, rz_graph_node_t::idx, in, rz_graph_get_neighbours(), rz_graph_innodes(), rz_list_first(), rz_list_length(), src, and v.

Referenced by agraph_print_edges(), and count_edges().

◆ get_graph_string()

static char* get_graph_string ( RzCore core,
RzAGraph g 
)
static

Definition at line 4052 of file agraph.c.

4052  {
4053  int c = rz_config_get_i(core->config, "scr.color");
4054  int u = rz_config_get_i(core->config, "scr.utf8");
4055  rz_config_set_i(core->config, "scr.color", 0);
4056  rz_config_set_i(core->config, "scr.utf8", 0);
4057  rz_core_visual_graph(core, g, NULL, false);
4058  char *s = rz_cons_get_buffer_dup();
4059  rz_cons_reset();
4060  rz_config_set_i(core->config, "scr.color", c);
4061  rz_config_set_i(core->config, "scr.utf8", u);
4062  return s;
4063 }
RZ_API int rz_core_visual_graph(RzCore *core, RzAGraph *g, RzAnalysisFunction *_fcn, int is_interactive)
Definition: agraph.c:4114
RZ_API RZ_OWN char * rz_cons_get_buffer_dup(void)
Return a newly allocated buffer containing what's currently in RzCons buffer.
Definition: cons.c:827
RZ_API void rz_cons_reset(void)
Definition: cons.c:804

References c, rz_core_t::config, g, NULL, rz_config_get_i(), rz_config_set_i(), rz_cons_get_buffer_dup(), rz_cons_reset(), rz_core_visual_graph(), and s.

Referenced by nextword().

◆ get_node_color()

static char* get_node_color ( int  color,
int  cur 
)
static

◆ get_right_dummy()

static RzGraphNode* get_right_dummy ( const RzAGraph g,
const RzGraphNode n 
)
static

Definition at line 1238 of file agraph.c.

1238  {
1239  const RzANode *an = get_anode(n);
1240  if (!an) {
1241  return NULL;
1242  }
1243  int k, layer = an->layer;
1244 
1245  for (k = an->pos_in_layer + 1; k < g->layers[layer].n_nodes; k++) {
1246  RzGraphNode *gk = g->layers[layer].nodes[k];
1247  const RzANode *ak = get_anode(gk);
1248  if (!ak) {
1249  break;
1250  }
1251 
1252  if (ak->is_dummy) {
1253  return gk;
1254  }
1255  }
1256  return NULL;
1257 }

References g, get_anode, rz_ascii_node_t::is_dummy, k, rz_ascii_node_t::layer, n, NULL, and rz_ascii_node_t::pos_in_layer.

Referenced by original_traverse_l(), and place_original().

◆ get_sibling()

static RzGraphNode* get_sibling ( const RzAGraph g,
const RzANode n,
int  is_left,
int  is_adjust_class 
)
static

Definition at line 1013 of file agraph.c.

1013  {
1014  RzGraphNode *res = NULL;
1015  int pos = n->pos_in_layer;
1016 
1017  if ((is_left && is_adjust_class) || (!is_left && !is_adjust_class)) {
1018  pos++;
1019  } else {
1020  pos--;
1021  }
1022 
1023  if (is_valid_pos(g, n->layer, pos)) {
1024  res = g->layers[n->layer].nodes[pos];
1025  }
1026  return res;
1027 }
static int is_valid_pos(const RzAGraph *g, int l, int pos)
Definition: agraph.c:912

References g, is_valid_pos(), n, NULL, and pos.

Referenced by adjust_class(), and place_nodes().

◆ get_title()

static char* get_title ( ut64  addr)
static

Definition at line 200 of file agraph.c.

200  {
201  return rz_str_newf("0x%" PFMT64x, addr);
202 }

References addr, PFMT64x, and rz_str_newf().

Referenced by agraph_refresh(), check_changes(), get_bbnodes(), get_bbupdate(), get_cgnodes(), goto_asmqjmps(), and seek_to_node().

◆ goto_asmqjmps()

static void goto_asmqjmps ( RzAGraph g,
RzCore core 
)
static

Definition at line 3954 of file agraph.c.

3954  {
3955  const char *h = "[Fast goto call/jmp]> ";
3957  int rows, i = 0;
3958  bool cont;
3959 
3960  rz_cons_get_size(&rows);
3961  rz_cons_gotoxy(0, rows);
3962  rz_cons_clear_line(0);
3963  rz_cons_print(Color_RESET);
3964  rz_cons_print(h);
3965  rz_cons_flush();
3966 
3967  do {
3968  char ch = rz_cons_readchar();
3969  obuf[i++] = ch;
3970  rz_cons_printf("%c", ch);
3971  cont = isalpha((ut8)ch) && !islower((ut8)ch);
3972  } while (i < RZ_CORE_ASMQJMPS_LEN_LETTERS && cont);
3973  rz_cons_flush();
3974 
3975  obuf[i] = '\0';
3977  if (addr != UT64_MAX) {
3978  char *title = get_title(addr);
3979  RzANode *addr_node = rz_agraph_get_node(g, title);
3980  if (addr_node) {
3981  rz_agraph_set_curnode(g, addr_node);
3982  rz_core_seek(core, addr, false);
3983  agraph_update_seek(g, addr_node, true);
3984  } else {
3985  rz_core_seek_and_save(core, addr, false);
3986  }
3987  free(title);
3988  }
3989 }
RZ_API void rz_cons_clear_line(int std_err)
Definition: cons.c:756
RZ_API ut64 rz_core_get_asmqjmps(RzCore *core, const char *str)
Definition: core.c:203
#define RZ_CORE_ASMQJMPS_LEN_LETTERS
Definition: rz_core.h:186
#define islower(c)
Definition: safe-ctype.h:135
#define isalpha(c)
Definition: safe-ctype.h:125
RZ_API bool rz_core_seek_and_save(RzCore *core, ut64 addr, bool rb)
Save currently marked state in seek history and seek to addr .
Definition: seek.c:101
static unsigned char * obuf
Definition: z80asm.c:36

References addr, agraph_update_seek(), Color_RESET, free(), g, get_title(), h, i, isalpha, islower, obuf, rz_agraph_get_node(), rz_agraph_set_curnode(), rz_cons_clear_line(), rz_cons_flush(), rz_cons_get_size(), rz_cons_gotoxy(), rz_cons_printf(), rz_cons_readchar(), RZ_CORE_ASMQJMPS_LEN_LETTERS, rz_core_get_asmqjmps(), rz_core_seek(), rz_core_seek_and_save(), ut64(), and UT64_MAX.

Referenced by rz_core_visual_graph().

◆ graph_breakpoint()

static void graph_breakpoint ( RzCore core)
static

Definition at line 4019 of file agraph.c.

4019  {
4020  ut64 addr = core->print->cur_enabled ? core->offset + core->print->cur : core->offset;
4022 }
RZ_API void rz_core_debug_breakpoint_toggle(RZ_NONNULL RzCore *core, ut64 addr)
Toggle breakpoint.
Definition: cdebug.c:235

References addr, rz_print_t::cur, rz_print_t::cur_enabled, rz_core_t::offset, rz_core_t::print, rz_core_debug_breakpoint_toggle(), and ut64().

Referenced by rz_core_visual_graph().

◆ graph_continue()

static void graph_continue ( RzCore core)
static

Definition at line 4024 of file agraph.c.

4024  {
4025  rz_core_debug_continue(core);
4026 }
RZ_IPI void rz_core_debug_continue(RzCore *core)
Definition: cdebug.c:81

References rz_core_debug_continue().

Referenced by rz_core_visual_graph().

◆ graph_single_step_in()

static void graph_single_step_in ( RzCore core,
RzAGraph g 
)
static

Definition at line 4007 of file agraph.c.

4007  {
4009  g->is_instep = true;
4010  g->need_reload_nodes = true;
4011 }
RZ_IPI void rz_core_debug_single_step_in(RzCore *core)
Definition: cdebug.c:193

References g, and rz_core_debug_single_step_in().

Referenced by rz_core_visual_graph().

◆ graph_single_step_over()

static void graph_single_step_over ( RzCore core,
RzAGraph g 
)
static

Definition at line 4013 of file agraph.c.

4013  {
4015  g->is_instep = true;
4016  g->need_reload_nodes = true;
4017 }
RZ_IPI void rz_core_debug_single_step_over(RzCore *core)
Definition: cdebug.c:207

References g, and rz_core_debug_single_step_over().

Referenced by rz_core_visual_graph().

◆ graphNodeMove()

static void graphNodeMove ( RzAGraph g,
int  dir,
int  speed 
)
static

Definition at line 3637 of file agraph.c.

3637  {
3638  int delta = (dir == 'k') ? -1 : 1;
3639  if (dir == 'H') {
3640  return;
3641  }
3642  if (dir == 'h' || dir == 'l') {
3643  // horizontal scroll
3644  if (is_mini(g)) {
3645  discroll = 0;
3646  } else {
3647  int delta = (dir == 'l') ? 1 : -1;
3648  move_current_node(g, speed * delta, 0);
3649  }
3650  return;
3651  }
3652  RzCore *core = NULL;
3653  // vertical scroll
3654  if (is_mini(g)) {
3655  discroll += (delta * speed);
3656  } else if (g->is_dis) {
3657  rz_core_seek_opcode(core, (delta * 4) * speed, false);
3658  } else {
3659  move_current_node(g, 0, delta * speed);
3660  }
3661 }
static int discroll
Definition: agraph.c:15
static void move_current_node(RzAGraph *g, int xdiff, int ydiff)
Definition: agraph.c:3196
RZ_IPI int rz_core_seek_opcode(RzCore *core, int n, bool silent)
Definition: cmd_seek.c:86
static st64 delta
Definition: vmenus.c:2425

References delta, discroll, g, is_mini(), move_current_node(), NULL, and rz_core_seek_opcode().

Referenced by rz_core_visual_graph().

◆ hash_get_int()

static int hash_get_int ( HtPU *  ht,
const void *  key 
)
static

Definition at line 1029 of file agraph.c.

1029  {
1030  bool found;
1031  int val = (int)(size_t)ht_pu_find(ht, key, &found);
1032  if (!found) {
1033  val = 0;
1034  }
1035  return val;
1036 }
ut16 val
Definition: armass64_const.h:6
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118

References found, int, key, and val.

Referenced by adjust_class(), adjust_class_val(), adjust_directions(), original_traverse_l(), place_dummies(), and place_nodes_val().

◆ is_comments()

static bool is_comments ( const RzAGraph g)
static

Definition at line 129 of file agraph.c.

129  {
130  return g->mode == RZ_AGRAPH_MODE_COMMENTS;
131 }
#define RZ_AGRAPH_MODE_COMMENTS
Definition: rz_agraph.h:40

References g, and RZ_AGRAPH_MODE_COMMENTS.

Referenced by mode2opts().

◆ is_mini()

static bool is_mini ( const RzAGraph g)
static

Definition at line 117 of file agraph.c.

117  {
118  return g->mode == RZ_AGRAPH_MODE_MINI;
119 }

References g, and RZ_AGRAPH_MODE_MINI.

Referenced by agraph_print_node(), check_changes(), graphNodeMove(), and update_node_dimension().

◆ is_near()

static int is_near ( const RzANode n,
int  x,
int  y,
int  is_next 
)
static

Definition at line 2535 of file agraph.c.

2535  {
2536  if (is_next) {
2537  return (n->y == y && n->x > x) || n->y > y;
2538  }
2539  return (n->y == y && n->x < x) || n->y < y;
2540 }
int x
Definition: mipsasm.c:20

References n, and x.

Referenced by find_near_of(), and rz_core_hack_x86().

◆ is_near_h()

static int is_near_h ( const RzANode n,
int  x,
int  y,
int  is_next 
)
static

XXX is wrong.

Definition at line 2543 of file agraph.c.

2543  {
2544  if (is_next) {
2545  return (n->x == x && n->y > y) || n->x > x;
2546  }
2547  return (n->x == x && n->y < y) || n->x < x;
2548 }

References n, and x.

Referenced by find_near_of().

◆ is_offset()

static bool is_offset ( const RzAGraph g)
static

Definition at line 113 of file agraph.c.

113  {
114  return g->mode == RZ_AGRAPH_MODE_OFFSET;
115 }
#define RZ_AGRAPH_MODE_OFFSET
Definition: rz_agraph.h:36

References g, and RZ_AGRAPH_MODE_OFFSET.

Referenced by mode2opts().

◆ is_reversed()

static bool is_reversed ( const RzAGraph g,
const RzGraphEdge e 
)
static

Definition at line 694 of file agraph.c.

694  {
695  return (bool)rz_list_find(g->back_edges, e, (RzListComparator)find_edge);
696 }
static int find_edge(const RzGraphEdge *a, const RzGraphEdge *b)
Definition: agraph.c:690

References e, find_edge(), g, and rz_list_find().

Referenced by create_dummy_nodes().

◆ is_summary()

static bool is_summary ( const RzAGraph g)
static

Definition at line 125 of file agraph.c.

125  {
126  return g->mode == RZ_AGRAPH_MODE_SUMMARY;
127 }
#define RZ_AGRAPH_MODE_SUMMARY
Definition: rz_agraph.h:39

References g, and RZ_AGRAPH_MODE_SUMMARY.

Referenced by mode2opts().

◆ is_tiny()

static bool is_tiny ( const RzAGraph g)
static

Definition at line 121 of file agraph.c.

121  {
122  return g->is_tiny || g->mode == RZ_AGRAPH_MODE_TINY;
123 }

References g, and RZ_AGRAPH_MODE_TINY.

Referenced by move_current_node().

◆ is_valid_pos()

static int is_valid_pos ( const RzAGraph g,
int  l,
int  pos 
)
static

Definition at line 912 of file agraph.c.

912  {
913  return pos >= 0 && pos < g->layers[l].n_nodes;
914 }

References g, and pos.

Referenced by get_sibling(), and original_traverse_l().

◆ isbbfew()

static bool isbbfew ( RzAnalysisBlock curbb,
RzAnalysisBlock bb 
)
static

Definition at line 2313 of file agraph.c.

2313  {
2314  if (bb->addr == curbb->addr || bb->addr == curbb->jump || bb->addr == curbb->fail) {
2315  // do nothing
2316  return true;
2317  }
2318  if (curbb->switch_op) {
2319  RzListIter *it;
2320  RzAnalysisCaseOp *cop;
2321  rz_list_foreach (curbb->switch_op->cases, it, cop) {
2322  if (cop->addr == bb->addr) {
2323  return true;
2324  }
2325  }
2326  }
2327  return false;
2328 }

References rz_analysis_case_obj_t::addr, rz_analysis_bb_t::addr, rz_analysis_switch_obj_t::cases, rz_analysis_bb_t::fail, rz_analysis_bb_t::jump, and rz_analysis_bb_t::switch_op.

Referenced by get_bbnodes().

◆ layer_sweep()

static int layer_sweep ( const RzGraph g,
const struct layer_t  layers[],
int  maxlayer,
int  i,
int  from_up 
)
static

Definition at line 549 of file agraph.c.

550  {
551  RzGraphNode *u, *v;
552  const RzANode *au, *av;
553  int n_rows, j, changed = false;
554  int len = layers[i].n_nodes;
555 
556  int **cross_matrix = get_crossing_matrix(g, layers, maxlayer, i, from_up, &n_rows);
557  if (!cross_matrix) {
558  return -1; // ERROR HAPPENS
559  }
560 
561  for (j = 0; j < len - 1; j++) {
562  int auidx, avidx;
563 
564  u = layers[i].nodes[j];
565  v = layers[i].nodes[j + 1];
566  au = get_anode(u);
567  av = get_anode(v);
568  auidx = au->pos_in_layer;
569  avidx = av->pos_in_layer;
570 
571  if (cross_matrix[auidx][avidx] > cross_matrix[avidx][auidx]) {
572  /* swap elements */
573  layers[i].nodes[j] = v;
574  layers[i].nodes[j + 1] = u;
575  changed = true;
576  }
577  }
578 
579  /* update position in the layer of each node. During the swap of some
580  * elements we didn't swap also the pos_in_layer because the cross_matrix
581  * is indexed by it, so do it now! */
582  for (j = 0; j < layers[i].n_nodes; j++) {
583  RzANode *n = get_anode(layers[i].nodes[j]);
584  n->pos_in_layer = j;
585  }
586 
587  for (j = 0; j < n_rows; j++) {
588  free(cross_matrix[j]);
589  }
590  free(cross_matrix);
591  return changed;
592 }
static int ** get_crossing_matrix(const RzGraph *g, const struct layer_t layers[], int maxlayer, int i, int from_up, int *n_rows)
Definition: agraph.c:433

References free(), g, get_anode, get_crossing_matrix(), i, len, n, layer_t::n_nodes, layer_t::nodes, rz_ascii_node_t::pos_in_layer, and v.

Referenced by minimize_crossings().

◆ mini_RzANode_print()

static void mini_RzANode_print ( const RzAGraph g,
const RzANode n,
int  cur,
bool  details 
)
static

Definition at line 265 of file agraph.c.

265  {
266  char title[TITLE_LEN];
267  int x, delta_x = 0;
268 
269  if (!G(n->x + MINIGRAPH_NODE_CENTER_X, n->y) &&
270  !G(n->x + MINIGRAPH_NODE_CENTER_X + n->w, n->y)) {
271  return;
272  }
273 
274  x = n->x + MINIGRAPH_NODE_CENTER_X + g->can->sx;
275  if (x < 0) {
276  delta_x = -x;
277  }
278  if (!G(n->x + MINIGRAPH_NODE_CENTER_X + delta_x, n->y)) {
279  return;
280  }
281 
282  if (details) {
283  if (cur) {
284  W(&MINIGRAPH_NODE_TEXT_CUR[delta_x]);
285  (void)G(-g->can->sx, -g->can->sy + 2);
286  snprintf(title, sizeof(title) - 1,
287  "[ %s ]", n->title);
288  W(title);
289  if (discroll > 0) {
290  char *body = rz_str_ansi_crop(n->body, 0, discroll, -1, -1);
291  (void)G(-g->can->sx, -g->can->sy + 3);
292  W(body);
293  free(body);
294  } else {
295  (void)G(-g->can->sx, -g->can->sy + 3);
296  W(n->body);
297  }
298  } else {
299  char *str = "____";
300  if (n->title) {
301  int l = strlen(n->title);
302  str = n->title;
303  if (l > MINIGRAPH_NODE_TITLE_LEN) {
305  }
306  }
307  if (g->can->color) {
308  snprintf(title, sizeof(title) - 1, "%s__%s__", Color_RESET, str);
309  } else {
310  snprintf(title, sizeof(title) - 1, "__%s__", str);
311  }
312  append_shortcut(g, title, n->title, sizeof(title) - strlen(title) - 1);
313  W(rz_str_ansi_crop(title, delta_x, 0, 20, 1));
314  }
315  } else {
316  snprintf(title, sizeof(title) - 1,
317  cur ? "[ %s ]" : " %s ", n->title);
318  W(title);
319  }
320  return;
321 }
static void append_shortcut(const RzAGraph *g, char *title, char *nodetitle, int left)
Definition: agraph.c:253
#define MINIGRAPH_NODE_TITLE_LEN
Definition: agraph.c:42
#define MINIGRAPH_NODE_TEXT_CUR
Definition: agraph.c:40
#define MINIGRAPH_NODE_CENTER_X
Definition: agraph.c:43
#define TITLE_LEN
Definition: agraph.c:36
snprintf
Definition: kernel.h:364
RZ_API char * rz_str_ansi_crop(const char *str, unsigned int x, unsigned int y, unsigned int x2, unsigned int y2)
Definition: str.c:2174

References append_shortcut(), Color_RESET, discroll, free(), G, g, MINIGRAPH_NODE_CENTER_X, MINIGRAPH_NODE_TEXT_CUR, MINIGRAPH_NODE_TITLE_LEN, n, rz_str_ansi_crop(), snprintf, cmd_descs_generate::str, TITLE_LEN, W, and x.

Referenced by agraph_print_node().

◆ minimize_crossings()

static void minimize_crossings ( const RzAGraph g)
static

Definition at line 786 of file agraph.c.

786  {
787  int i, cross_changed, max_changes = 4096;
788 
789  do {
790  cross_changed = false;
791  max_changes--;
792 
793  for (i = 0; i < g->n_layers; i++) {
794  int rc = layer_sweep(g->graph, g->layers, g->n_layers, i, true);
795  if (rc == -1) {
796  return;
797  }
798  cross_changed |= !!rc;
799  }
800  } while (cross_changed && max_changes);
801 
802  max_changes = 4096;
803 
804  do {
805  cross_changed = false;
806  max_changes--;
807 
808  for (i = g->n_layers - 1; i >= 0; i--) {
809  int rc = layer_sweep(g->graph, g->layers, g->n_layers, i, false);
810  if (rc == -1) {
811  return;
812  }
813  cross_changed |= !!rc;
814  }
815  } while (cross_changed && max_changes);
816 }
static int layer_sweep(const RzGraph *g, const struct layer_t layers[], int maxlayer, int i, int from_up)
Definition: agraph.c:549

References g, i, and layer_sweep().

Referenced by set_layout().

◆ mode2opts()

static int mode2opts ( const RzAGraph g)
static

Definition at line 159 of file agraph.c.

159  {
160  int opts = 0;
161  if (is_offset(g)) {
162  opts |= BODY_OFFSETS;
163  }
164  if (is_comments(g)) {
165  opts |= BODY_COMMENTS;
166  }
167  if (is_summary(g)) {
168  opts |= BODY_SUMMARY;
169  }
170  return opts;
171 }
static bool is_offset(const RzAGraph *g)
Definition: agraph.c:113
static bool is_comments(const RzAGraph *g)
Definition: agraph.c:129
static bool is_summary(const RzAGraph *g)
Definition: agraph.c:125

References BODY_COMMENTS, BODY_OFFSETS, BODY_SUMMARY, g, is_comments(), is_offset(), and is_summary().

Referenced by get_bbnodes(), get_bbupdate(), and get_cgnodes().

◆ move_current_node()

static void move_current_node ( RzAGraph g,
int  xdiff,
int  ydiff 
)
static

Definition at line 3196 of file agraph.c.

3196  {
3197  RzANode *n = get_anode(g->curnode);
3198  if (n) {
3199  if (is_tiny(g)) {
3200  xdiff = NORMALIZE_MOV(xdiff);
3201  ydiff = NORMALIZE_MOV(ydiff);
3202  }
3203  n->x += xdiff;
3204  n->y += ydiff;
3205  }
3206 }
#define NORMALIZE_MOV(x)
Definition: agraph.c:53
static bool is_tiny(const RzAGraph *g)
Definition: agraph.c:121

References g, get_anode, is_tiny(), n, and NORMALIZE_MOV.

Referenced by graphNodeMove().

◆ next_mode()

static int next_mode ( int  mode)
static

Definition at line 133 of file agraph.c.

133  {
134  return (mode + 1) % RZ_AGRAPH_MODE_MAX;
135 }
const char int mode
Definition: ioapi.h:137
#define RZ_AGRAPH_MODE_MAX
Definition: rz_agraph.h:41

References RZ_AGRAPH_MODE_MAX.

Referenced by rz_core_visual_graph().

◆ nextword()

static void nextword ( RzCore core,
RzAGraph g,
const char *  word 
)
static

Definition at line 4065 of file agraph.c.

4065  {
4066  rz_return_if_fail(core && core->graph && g && g->can && word);
4067  if (RZ_STR_ISEMPTY(word)) {
4068  return;
4069  }
4070  RzAGraphHits *gh = &g->ghits;
4071  RzConsCanvas *can = g->can;
4072  if (gh->word_list.len && gh->old_word && !strcmp(word, gh->old_word)) {
4073  if (gh->word_nth >= gh->word_list.len) {
4074  gh->word_nth = 0;
4075  }
4076 
4078  gh->word_nth++;
4079  if (pos) {
4080  can->sx = -pos->x + can->w / 2;
4081  can->sy = -pos->y + can->h / 2;
4082  }
4083  return;
4084  } else {
4085  rz_vector_clear(&gh->word_list);
4086  }
4087  char *s = get_graph_string(core, g);
4088  rz_cons_clear00();
4089  rz_cons_flush();
4090  const size_t MAX_COUNT = 4096;
4091  const char *a = NULL;
4092  size_t count = 0;
4093  int x = 0, y = 0;
4094  for (count = 0; count < MAX_COUNT; count++) {
4095  a = rz_str_str_xy(s, word, a, &x, &y);
4096  if (!a) {
4097  break;
4098  }
4100  if (pos) {
4101  pos->x = x + g->x;
4102  pos->y = y + g->y;
4103  }
4104  }
4105  free(gh->old_word);
4106  gh->old_word = strdup(word);
4107  free(s);
4108  if (!a && count == 0) {
4109  return;
4110  }
4111  nextword(core, g, word);
4112 }
static void nextword(RzCore *core, RzAGraph *g, const char *word)
Definition: agraph.c:4065
static char * get_graph_string(RzCore *core, RzAGraph *g)
Definition: agraph.c:4052
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API const char * rz_str_str_xy(const char *s, const char *word, const char *prev, int *x, int *y)
Definition: str.c:3964
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68
RzVector word_list
Definition: rz_agraph.h:31
RzAGraph * graph
Definition: rz_core.h:333
size_t len
Definition: rz_vector.h:47

References a, count, free(), g, get_graph_string(), rz_core_t::graph, rz_cons_canvas_t::h, rz_vector_t::len, NULL, rz_core_graph_hits_t::old_word, pos, rz_cons_clear00(), rz_cons_flush(), rz_return_if_fail, RZ_STR_ISEMPTY, rz_str_str_xy(), rz_vector_clear(), rz_vector_index_ptr(), rz_vector_push(), s, strdup(), rz_cons_canvas_t::sx, rz_cons_canvas_t::sy, rz_cons_canvas_t::w, rz_core_graph_hits_t::word_list, rz_core_graph_hits_t::word_nth, x, and rz_agraph_location::y.

Referenced by rz_core_visual_graph().

◆ normal_RzANode_print()

static void normal_RzANode_print ( const RzAGraph g,
const RzANode n,
int  cur 
)
static

Definition at line 345 of file agraph.c.

345  {
346  ut32 center_x = 0, center_y = 0;
347  ut32 delta_x = 0, delta_txt_x = 0;
348  ut32 delta_y = 0, delta_txt_y = 0;
349  char title[TITLE_LEN];
350  char *body;
351  int x, y;
352  int color = n->difftype;
353  const bool showTitle = g->show_node_titles;
354  const bool showBody = g->show_node_body;
355 
356  x = n->x + g->can->sx;
357  y = n->y + g->can->sy;
358  if (x + MARGIN_TEXT_X < 0) {
359  delta_x = -(x + MARGIN_TEXT_X);
360  }
361  if (x + n->w < -MARGIN_TEXT_X) {
362  return;
363  }
364  if (y < -1) {
365  delta_y = RZ_MIN(n->h - BORDER_HEIGHT - 1, -y - MARGIN_TEXT_Y);
366  }
367  /* print the title */
368  if (showTitle) {
369  if (cur) {
370  snprintf(title, sizeof(title) - 1, "[%s]", n->title);
371  } else {
372  char *color = g->can->color ? Color_RESET : "";
373  snprintf(title, sizeof(title) - 1, " %s%s ", color, n->title);
374  append_shortcut(g, title, n->title, sizeof(title) - strlen(title) - 1);
375  }
376  if ((delta_x < strlen(title)) && G(n->x + MARGIN_TEXT_X + delta_x, n->y + 1)) {
377  char *res = rz_str_ansi_crop(title, delta_x, 0, n->w - BORDER_WIDTH, 1);
378  W(res);
379  free(res);
380  }
381  }
382 
383  /* print the body */
384  if (g->zoom > ZOOM_DEFAULT) {
385  center_x = (g->zoom - ZOOM_DEFAULT) / 10;
386  center_y = (g->zoom - ZOOM_DEFAULT) / 30;
387  delta_txt_x = RZ_MIN(delta_x, center_x);
388  delta_txt_y = RZ_MIN(delta_y, center_y);
389  }
390  if (showBody) {
391  if (G(n->x + MARGIN_TEXT_X + delta_x + center_x - delta_txt_x,
392  n->y + MARGIN_TEXT_Y + delta_y + center_y - delta_txt_y)) {
393  ut32 body_x = center_x >= delta_x ? 0 : delta_x - center_x;
394  ut32 body_y = center_y >= delta_y ? 0 : delta_y - center_y;
395  ut32 body_h = BORDER_HEIGHT >= n->h ? 1 : n->h - BORDER_HEIGHT;
396 
397  if (g->zoom < ZOOM_DEFAULT) {
398  body_h--;
399  }
400  if (body_y + 1 <= body_h) {
401  body = rz_str_ansi_crop(n->body,
402  body_x, body_y,
403  n->w - BORDER_WIDTH,
404  body_h);
405  if (body) {
406  W(body);
407  if (g->zoom < ZOOM_DEFAULT) {
408  W("\n");
409  }
410  free(body);
411  } else {
412  W(n->body);
413  }
414  }
415  /* print some dots when the body is cropped because of zoom */
416  if (n->body && *n->body) {
417  if (body_y <= body_h && g->zoom < ZOOM_DEFAULT) {
418  char *dots = "...";
419  if (delta_x < strlen(dots)) {
420  dots += delta_x;
421  W(dots);
422  }
423  }
424  }
425  }
426  }
427 
428  // TODO: check if node is traced or not and show proper color
429  // This info must be stored inside RzANode* from RzCore*
430  rz_cons_canvas_box(g->can, n->x, n->y, n->w, n->h, get_node_color(color, cur));
431 }
#define BORDER_WIDTH
Definition: agraph.c:28
#define MARGIN_TEXT_X
Definition: agraph.c:30
#define BORDER_HEIGHT
Definition: agraph.c:29
static char * get_node_color(int color, int cur)
Definition: agraph.c:334
#define MARGIN_TEXT_Y
Definition: agraph.c:31
RZ_API void rz_cons_canvas_box(RzConsCanvas *c, int x, int y, int w, int h, const char *color)
Definition: canvas.c:486
uint32_t ut32
static int zoom
Definition: visual.c:22

References append_shortcut(), BORDER_HEIGHT, BORDER_WIDTH, color, Color_RESET, free(), G, g, get_node_color(), MARGIN_TEXT_X, MARGIN_TEXT_Y, n, rz_cons_canvas_box(), RZ_MIN, rz_str_ansi_crop(), snprintf, TITLE_LEN, W, x, zoom, and ZOOM_DEFAULT.

Referenced by agraph_print_node().

◆ original_traverse_l()

static void original_traverse_l ( const RzAGraph g,
HtPU *  D,
HtPU *  P,
int  from_up 
)
static

Definition at line 1518 of file agraph.c.

1518  {
1519  int i, k, va, vr;
1520 
1521  for (i = from_up ? 0 : g->n_layers - 1;
1522  (from_up && i < g->n_layers) || (!from_up && i >= 0);
1523  i = from_up ? i + 1 : i - 1) {
1524  int j;
1525  const RzGraphNode *bm = NULL;
1526  const RzANode *bma = NULL;
1527 
1528  j = 0;
1529  while (j < g->layers[i].n_nodes && !bm) {
1530  const RzGraphNode *gn = g->layers[i].nodes[j];
1531  const RzANode *an = get_anode(gn);
1532  if (an && an->is_dummy) {
1533  va = 0;
1534  vr = j;
1535  bm = gn;
1536  bma = an;
1537  }
1538  j++;
1539  }
1540  if (!bm) {
1541  va = 0;
1542  vr = g->layers[i].n_nodes;
1543  }
1544  place_sequence(g, i, NULL, bm, from_up, va, vr);
1545  for (k = va; k < vr - 1; k++) {
1546  set_dist_nodes(g, i, k, k + 1);
1547  }
1548  if (is_valid_pos(g, i, vr - 1) && bm) {
1549  set_dist_nodes(g, i, vr - 1, bma->pos_in_layer);
1550  }
1551  while (bm) {
1552  const RzGraphNode *bp = get_right_dummy(g, bm);
1553  const RzANode *bpa = NULL;
1554  bma = get_anode(bm);
1555 
1556  if (!bp) {
1557  va = bma->pos_in_layer + 1;
1558  vr = g->layers[bma->layer].n_nodes;
1559  place_sequence(g, i, bm, NULL, from_up, va, vr);
1560  for (k = va; k < vr - 1; k++) {
1561  set_dist_nodes(g, i, k, k + 1);
1562  }
1563 
1564  if (is_valid_pos(g, i, va)) {
1565  set_dist_nodes(g, i, bma->pos_in_layer, va);
1566  }
1567  } else if (hash_get_int(D, bm) == from_up) {
1568  bpa = get_anode(bp);
1569  va = bma->pos_in_layer + 1;
1570  vr = bpa->pos_in_layer;
1571  place_sequence(g, i, bm, bp, from_up, va, vr);
1572  ht_pu_update(P, bm, 1);
1573  }
1574  bm = bp;
1575  }
1576  adjust_directions(g, i, from_up, D, P);
1577  }
1578 }
static RzGraphNode * get_right_dummy(const RzAGraph *g, const RzGraphNode *n)
Definition: agraph.c:1238
static void set_dist_nodes(const RzAGraph *g, int l, int cur, int next)
Definition: agraph.c:885
static void place_sequence(const RzAGraph *g, int l, const RzGraphNode *bm, const RzGraphNode *bp, int from_up, int va, int vr)
Definition: agraph.c:1504
static void adjust_directions(const RzAGraph *g, int i, int from_up, HtPU *D, HtPU *P)
Definition: agraph.c:1259

References adjust_directions(), D, g, get_anode, get_right_dummy(), hash_get_int(), i, rz_ascii_node_t::is_dummy, is_valid_pos(), k, rz_ascii_node_t::layer, NULL, P, place_sequence(), rz_ascii_node_t::pos_in_layer, and set_dist_nodes().

Referenced by place_original().

◆ place_dummies()

static void place_dummies ( const RzAGraph g)
static

Definition at line 1207 of file agraph.c.

1207  {
1208  const RzList *nodes;
1209  const RzGraphNode *gn;
1210  const RzListIter *it;
1211  RzANode *n;
1212 
1213  HtPP *vertical_nodes = compute_vertical_nodes(g);
1214  if (!vertical_nodes) {
1215  return;
1216  }
1217  HtPU *xminus = compute_pos(g, true, vertical_nodes);
1218  if (!xminus) {
1219  goto xminus_err;
1220  }
1221  HtPU *xplus = compute_pos(g, false, vertical_nodes);
1222  if (!xplus) {
1223  goto xplus_err;
1224  }
1225 
1226  nodes = rz_graph_get_nodes(g->graph);
1227  graph_foreach_anode (nodes, it, gn, n) {
1228  n->x = (hash_get_int(xminus, gn) + hash_get_int(xplus, gn)) / 2;
1229  }
1230 
1231  ht_pu_free(xplus);
1232 xplus_err:
1233  ht_pu_free(xminus);
1234 xminus_err:
1235  ht_pp_free(vertical_nodes);
1236 }
static HtPU * compute_pos(const RzAGraph *g, int is_left, HtPP *v_nodes)
Definition: agraph.c:1164
static HtPP * compute_vertical_nodes(const RzAGraph *g)
Definition: agraph.c:924

References compute_pos(), compute_vertical_nodes(), g, graph_foreach_anode, hash_get_int(), n, and rz_graph_get_nodes().

Referenced by set_layout().

◆ place_nodes()

static void place_nodes ( const RzAGraph g,
const RzGraphNode gn,
int  is_left,
HtPP *  v_nodes,
RzList **  classes,
HtPU *  res,
SetP placed 
)
static

Definition at line 1126 of file agraph.c.

1126  {
1127  const RzList *lv = ht_pp_find(v_nodes, gn, NULL);
1128  int p = 0, v, is_first = true;
1129  const RzGraphNode *gk;
1130  const RzListIter *itk;
1131  const RzANode *ak;
1132 
1133  graph_foreach_anode (lv, itk, gk, ak) {
1134  const RzGraphNode *sibling;
1135  const RzANode *sibl_anode;
1136 
1137  sibling = get_sibling(g, ak, is_left, false);
1138  if (!sibling) {
1139  continue;
1140  }
1141  sibl_anode = get_anode(sibling);
1142  if (ak->klass == sibl_anode->klass) {
1143  if (!set_p_contains(placed, sibling)) {
1144  place_nodes(g, sibling, is_left, v_nodes, classes, res, placed);
1145  }
1146 
1147  v = place_nodes_val(g, gk, sibling, res, is_left);
1148  p = place_nodes_sel_p(v, p, is_first, is_left);
1149  is_first = false;
1150  }
1151  }
1152 
1153  if (is_first) {
1154  p = is_left ? 0 : 50;
1155  }
1156 
1157  graph_foreach_anode (lv, itk, gk, ak) {
1158  ht_pu_update(res, gk, (ut64)(size_t)p);
1159  set_p_add(placed, gk);
1160  }
1161 }
static int place_nodes_val(const RzAGraph *g, const RzGraphNode *gn, const RzGraphNode *sibl, HtPU *res, int is_left)
Definition: agraph.c:1108
static int place_nodes_sel_p(int newval, int oldval, int is_first, int is_left)
Definition: agraph.c:1115
RZ_API void set_p_add(SetP *s, const void *u)
Definition: set.c:12

References classes(), g, get_anode, get_sibling(), graph_foreach_anode, rz_ascii_node_t::klass, NULL, p, place_nodes_sel_p(), place_nodes_val(), set_p_add(), set_p_contains(), ut64(), and v.

Referenced by compute_pos().

◆ place_nodes_sel_p()

static int place_nodes_sel_p ( int  newval,
int  oldval,
int  is_first,
int  is_left 
)
static

Definition at line 1115 of file agraph.c.

1115  {
1116  if (is_first) {
1117  return newval;
1118  }
1119  if (is_left) {
1120  return RZ_MAX(oldval, newval);
1121  }
1122  return RZ_MIN(oldval, newval);
1123 }

References RZ_MAX, and RZ_MIN.

Referenced by place_nodes().

◆ place_nodes_val()

static int place_nodes_val ( const RzAGraph g,
const RzGraphNode gn,
const RzGraphNode sibl,
HtPU *  res,
int  is_left 
)
static

Definition at line 1108 of file agraph.c.

1108  {
1109  if (is_left) {
1110  return hash_get_int(res, sibl) + dist_nodes(g, sibl, gn);
1111  }
1112  return hash_get_int(res, sibl) - dist_nodes(g, gn, sibl);
1113 }

References dist_nodes(), g, and hash_get_int().

Referenced by place_nodes().

◆ place_original()

static void place_original ( RzAGraph g)
static

Definition at line 1583 of file agraph.c.

1583  {
1584  const RzList *nodes = rz_graph_get_nodes(g->graph);
1585  const RzGraphNode *gn;
1586  const RzListIter *itn;
1587  const RzANode *an;
1588  HtPUOptions opt = { 0 };
1589 
1590  HtPU *D = ht_pu_new_opt(&opt);
1591  if (!D) {
1592  return;
1593  }
1594  HtPU *P = ht_pu_new_opt(&opt);
1595  if (!P) {
1596  ht_pu_free(D);
1597  return;
1598  }
1599  g->dists = rz_list_newf((RzListFree)free);
1600  if (!g->dists) {
1601  ht_pu_free(D);
1602  ht_pu_free(P);
1603  return;
1604  }
1605 
1606  graph_foreach_anode (nodes, itn, gn, an) {
1607  if (!an->is_dummy) {
1608  continue;
1609  }
1610  const RzGraphNode *right_v = get_right_dummy(g, gn);
1611  const RzANode *right = get_anode(right_v);
1612  if (right_v && right) {
1613  ht_pu_update(D, gn, 0);
1614  int dt_eq = right->x - an->x == dist_nodes(g, gn, right_v);
1615  ht_pu_update(P, gn, (ut64)(size_t)dt_eq);
1616  }
1617  }
1618 
1619  original_traverse_l(g, D, P, true);
1620  original_traverse_l(g, D, P, false);
1621 
1622  rz_list_free(g->dists);
1623  g->dists = NULL;
1624  ht_pu_free(P);
1625  ht_pu_free(D);
1626 }
static void original_traverse_l(const RzAGraph *g, HtPU *D, HtPU *P, int from_up)
Definition: agraph.c:1518

References D, dist_nodes(), free(), g, get_anode, get_right_dummy(), graph_foreach_anode, rz_ascii_node_t::is_dummy, NULL, original_traverse_l(), P, rz_graph_get_nodes(), rz_list_free(), rz_list_newf(), ut64(), and rz_ascii_node_t::x.

Referenced by set_layout().

◆ place_sequence()

static void place_sequence ( const RzAGraph g,
int  l,
const RzGraphNode bm,
const RzGraphNode bp,
int  from_up,
int  va,
int  vr 
)
static

Definition at line 1504 of file agraph.c.

1504  {
1505  if (vr == va + 1) {
1506  place_single(g, l, bm, bp, from_up, va);
1507  } else if (vr > va + 1) {
1508  int vt = (vr + va) / 2;
1509  place_sequence(g, l, bm, bp, from_up, va, vt);
1510  place_sequence(g, l, bm, bp, from_up, vt, vr);
1511  combine_sequences(g, l, bm, bp, from_up, va, vr);
1512  }
1513 }
static void place_single(const RzAGraph *g, int l, const RzGraphNode *bm, const RzGraphNode *bp, int from_up, int va)
Definition: agraph.c:1313
static void combine_sequences(const RzAGraph *g, int l, const RzGraphNode *bm, const RzGraphNode *bp, int from_up, int a, int r)
Definition: agraph.c:1430

References combine_sequences(), g, and place_single().

Referenced by original_traverse_l().

◆ place_single()

static void place_single ( const RzAGraph g,
int  l,
const RzGraphNode bm,
const RzGraphNode bp,
int  from_up,
int  va 
)
static

Definition at line 1313 of file agraph.c.

1313  {
1314  const RzGraphNode *gk, *v = g->layers[l].nodes[va];
1315  const RzANode *ak;
1316  RzANode *av = get_anode(v);
1317  if (!av) {
1318  return;
1319  }
1320  const RzListIter *itk;
1321 
1322  const RzList *neigh = from_up
1323  ? rz_graph_innodes(g->graph, v)
1324  : rz_graph_get_neighbours(g->graph, v);
1325 
1326  int len = rz_list_length(neigh);
1327  if (len == 0) {
1328  return;
1329  }
1330 
1331  int sum_x = 0;
1332  graph_foreach_anode (neigh, itk, gk, ak) {
1333  if (ak->is_reversed) {
1334  len--;
1335  continue;
1336  }
1337  sum_x += ak->x;
1338  }
1339 
1340  if (len == 0) {
1341  return;
1342  }
1343  if (av) {
1344  av->x = sum_x / len;
1345  }
1346  if (bm) {
1347  const RzANode *bma = get_anode(bm);
1348  av->x = RZ_MAX(av->x, bma->x + dist_nodes(g, bm, v));
1349  }
1350  if (bp) {
1351  const RzANode *bpa = get_anode(bp);
1352  av->x = RZ_MIN(av->x, bpa->x - dist_nodes(g, v, bp));
1353  }
1354 }

References dist_nodes(), g, get_anode, graph_foreach_anode, rz_ascii_node_t::is_reversed, len, rz_graph_get_neighbours(), rz_graph_innodes(), rz_list_length(), RZ_MAX, RZ_MIN, v, and rz_ascii_node_t::x.

Referenced by place_sequence().

◆ prev_mode()

static int prev_mode ( int  mode)
static

Definition at line 137 of file agraph.c.

137  {
138  return (mode + RZ_AGRAPH_MODE_MAX - 1) % RZ_AGRAPH_MODE_MAX;
139 }

References RZ_AGRAPH_MODE_MAX.

Referenced by rz_core_visual_graph().

◆ rebase()

static ut64 rebase ( RzAGraph g,
int  v 
)
static

Definition at line 2709 of file agraph.c.

2709  {
2710  return g->x < 0 ? -g->x + v : v;
2711 }

References g, and v.

Referenced by agraph_set_layout().

◆ reload_nodes()

static bool reload_nodes ( RzAGraph g,
RzCore core,
RzAnalysisFunction fcn 
)
static

Definition at line 2506 of file agraph.c.

2506  {
2507  const bool is_c = g->is_callgraph;
2508  return is_c ? get_cgnodes(g, core, fcn) : get_bbnodes(g, core, fcn);
2509 }
static int get_bbnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:2331
static bool get_cgnodes(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:2446

References g, get_bbnodes(), and get_cgnodes().

Referenced by agraph_reload_nodes().

◆ remove_cycles()

static void remove_cycles ( RzAGraph g)
static

Definition at line 627 of file agraph.c.

627  {
628  RzGraphVisitor cyclic_vis = {
629  NULL, NULL, NULL, NULL, NULL, NULL
630  };
631  const RzGraphEdge *e;
632  const RzListIter *it;
633 
634  g->back_edges = rz_list_newf(free);
636  cyclic_vis.data = g;
637  rz_graph_dfs(g->graph, &cyclic_vis);
638 
639  rz_list_foreach (g->back_edges, it, e) {
640  RzANode *from = e->from ? get_anode(e->from) : NULL;
641  RzANode *to = e->to ? get_anode(e->to) : NULL;
642  if (from && to) {
644  rz_agraph_add_edge_at(g, to, from, e->nth);
645  }
646  }
647 }
static void view_cyclic_edge(const RzGraphEdge *e, const RzGraphVisitor *vis)
Definition: agraph.c:594
void(* back_edge)(const RzGraphEdge *e, struct rz_graph_visitor_t *vis)
Definition: rz_graph.h:36

References rz_graph_visitor_t::back_edge, rz_graph_visitor_t::data, e, free(), from, g, get_anode, NULL, rz_agraph_add_edge_at(), rz_agraph_del_edge(), rz_graph_dfs(), rz_list_newf(), to, and view_cyclic_edge().

Referenced by set_layout().

◆ RM_listcmp()

static int RM_listcmp ( const struct len_pos_t a,
const struct len_pos_t b 
)
static

Definition at line 1356 of file agraph.c.

1356  {
1357  return (a->pos < b->pos) - (a->pos > b->pos);
1358 }

References a, and b.

Referenced by collect_changes().

◆ rotateAsmemu()

static void rotateAsmemu ( RzCore core)
static

Definition at line 174 of file agraph.c.

174  {
175  const bool isEmuStr = rz_config_get_i(core->config, "emu.str");
176  const bool isEmu = rz_config_get_i(core->config, "asm.emu");
177  if (isEmu) {
178  if (isEmuStr) {
179  rz_config_set(core->config, "emu.str", "false");
180  } else {
181  rz_config_set(core->config, "asm.emu", "false");
182  }
183  } else {
184  rz_config_set(core->config, "emu.str", "true");
185  }
186 }

References rz_core_t::config, rz_config_get_i(), and rz_config_set().

Referenced by rz_core_visual_graph().

◆ rotateColor()

static void rotateColor ( RzCore core)
static

Definition at line 4044 of file agraph.c.

4044  {
4045  int color = rz_config_get_i(core->config, "scr.color");
4046  if (++color > 2) {
4047  color = 0;
4048  }
4049  rz_config_set_i(core->config, "scr.color", color);
4050 }

References color, rz_core_t::config, rz_config_get_i(), and rz_config_set_i().

Referenced by rz_core_visual_graph().

◆ RP_listcmp()

static int RP_listcmp ( const struct len_pos_t a,
const struct len_pos_t b 
)
static

Definition at line 1360 of file agraph.c.

1360  {
1361  return (a->pos > b->pos) - (a->pos < b->pos);
1362 }

References a, and b.

Referenced by collect_changes().

◆ rz_agraph_add_edge()

RZ_API void rz_agraph_add_edge ( const RzAGraph g,
RzANode a,
RzANode b 
)

Definition at line 3862 of file agraph.c.

3862  {
3863  rz_return_if_fail(g && a && b);
3864  rz_graph_add_edge(g->graph, a->gnode, b->gnode);
3865  if (a->title && b->title) {
3866  char *k = sdb_fmt("agraph.nodes.%s.neighbours", a->title);
3867  sdb_array_add(g->db, k, b->title, 0);
3868  }
3869 }
RZ_API int sdb_array_add(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: array.c:224

References a, b, g, k, rz_graph_add_edge(), rz_return_if_fail, sdb_array_add(), and sdb_fmt().

Referenced by create_agraph_from_graph(), get_bbnodes(), get_cgnodes(), print_double_linked_list_bin_graph(), rz_cmd_heap_chunks_print_handler(), and rz_core_agraph_add_edge().

◆ rz_agraph_add_edge_at()

RZ_API void rz_agraph_add_edge_at ( const RzAGraph g,
RzANode a,
RzANode b,
int  nth 
)

Definition at line 3871 of file agraph.c.

3871  {
3872  rz_return_if_fail(g && a && b);
3873  if (a->title && b->title) {
3874  char *k = sdb_fmt("agraph.nodes.%s.neighbours", a->title);
3875  sdb_array_insert(g->db, k, nth, b->title, 0);
3876  }
3877  rz_graph_add_edge_at(g->graph, a->gnode, b->gnode, nth);
3878 }
RZ_API int sdb_array_insert(Sdb *s, const char *key, int idx, const char *val, ut32 cas)
Definition: array.c:139
RZ_API void rz_graph_add_edge_at(RzGraph *g, RzGraphNode *from, RzGraphNode *to, int nth)
Definition: graph.c:203

References a, b, g, k, rz_graph_add_edge_at(), rz_return_if_fail, sdb_array_insert(), and sdb_fmt().

Referenced by create_dummy_nodes(), remove_cycles(), and set_layout().

◆ rz_agraph_add_node()

RZ_API RzANode* rz_agraph_add_node ( const RzAGraph g,
const char *  title,
const char *  body 
)

Definition at line 3765 of file agraph.c.

3765  {
3766  return rz_agraph_add_node_with_color(g, title, body, -1);
3767 }
RZ_API RzANode * rz_agraph_add_node_with_color(const RzAGraph *g, const char *title, const char *body, int color)
Definition: agraph.c:3726

References g, and rz_agraph_add_node_with_color().

Referenced by create_agraph_from_graph(), create_dummy_nodes(), get_bbnodes(), get_cgnodes(), print_double_linked_list_bin_graph(), and rz_cmd_heap_chunks_print_handler().

◆ rz_agraph_add_node_with_color()

RZ_API RzANode* rz_agraph_add_node_with_color ( const RzAGraph g,
const char *  title,
const char *  body,
int  color 
)

Definition at line 3726 of file agraph.c.

3726  {
3727  RzANode *res = rz_agraph_get_node(g, title);
3728  if (res) {
3729  return res;
3730  }
3731  res = RZ_NEW0(RzANode);
3732  if (!res) {
3733  return NULL;
3734  }
3735 
3736  res->title = title ? rz_str_trunc_ellipsis(title, 255) : strdup("");
3737  res->body = body ? strdup(body) : strdup("");
3738  res->layer = -1;
3739  res->pos_in_layer = -1;
3740  res->is_dummy = false;
3741  res->is_reversed = false;
3742  res->klass = -1;
3743  res->difftype = color;
3744  res->gnode = rz_graph_add_node(g->graph, res);
3745  if (RZ_STR_ISNOTEMPTY(res->title)) {
3746  ht_pp_update(g->nodes, res->title, res);
3747  char *s, *estr, *b;
3748  size_t len;
3749  sdb_array_add(g->db, "agraph.nodes", res->title, 0);
3750  b = strdup(res->body);
3751  len = strlen(b);
3752  if (len > 0 && b[len - 1] == '\n') {
3753  b[len - 1] = '\0';
3754  }
3755  estr = sdb_encode((const void *)b, -1);
3756  // s = sdb_fmt ("base64:%s", estr);
3757  s = rz_str_newf("base64:%s", estr);
3758  free(estr);
3759  free(b);
3760  sdb_set_owned(g->db, sdb_fmt("agraph.nodes.%s.body", res->title), s, 0);
3761  }
3762  return res;
3763 }
RZ_API char * sdb_encode(const ut8 *bin, int len)
Definition: base64.c:18
RZ_API RzGraphNode * rz_graph_add_node(RzGraph *g, void *data)
Definition: graph.c:153
#define RZ_STR_ISNOTEMPTY(x)
Definition: rz_str.h:68
RZ_API char * rz_str_trunc_ellipsis(const char *str, int len)
Definition: str.c:883
RZ_API int sdb_set_owned(Sdb *s, const char *key, char *val, ut32 cas)
Definition: sdb.c:607

References b, rz_ascii_node_t::body, color, rz_ascii_node_t::difftype, free(), g, rz_ascii_node_t::gnode, rz_ascii_node_t::is_dummy, rz_ascii_node_t::is_reversed, rz_ascii_node_t::klass, rz_ascii_node_t::layer, len, NULL, rz_ascii_node_t::pos_in_layer, rz_agraph_get_node(), rz_graph_add_node(), RZ_NEW0, RZ_STR_ISNOTEMPTY, rz_str_newf(), rz_str_trunc_ellipsis(), s, sdb_array_add(), sdb_encode(), sdb_fmt(), sdb_set_owned(), strdup(), and rz_ascii_node_t::title.

Referenced by rz_agraph_add_node(), and rz_core_agraph_add_node().

◆ rz_agraph_del_edge()

RZ_API void rz_agraph_del_edge ( const RzAGraph g,
RzANode a,
RzANode b 
)

Definition at line 3880 of file agraph.c.

3880  {
3881  rz_return_if_fail(g && a && b);
3882  if (a->title && b->title) {
3883  const char *k = sdb_fmt("agraph.nodes.%s.neighbours", a->title);
3884  sdb_array_remove(g->db, k, b->title, 0);
3885  }
3886  rz_graph_del_edge(g->graph, a->gnode, b->gnode);
3887 }
RZ_API int sdb_array_remove(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: array.c:436
RZ_API void rz_graph_del_edge(RzGraph *g, RzGraphNode *from, RzGraphNode *to)
Definition: graph.c:232

References a, b, g, k, rz_graph_del_edge(), rz_return_if_fail, sdb_array_remove(), and sdb_fmt().

Referenced by create_dummy_nodes(), remove_cycles(), rz_core_agraph_del_edge(), and set_layout().

◆ rz_agraph_del_node()

RZ_API bool rz_agraph_del_node ( const RzAGraph g,
const char *  title 
)

Definition at line 3769 of file agraph.c.

3769  {
3770  char *title_trunc = rz_str_trunc_ellipsis(title, 255);
3771  RzANode *an, *res = rz_agraph_get_node(g, title_trunc);
3772  free(title_trunc);
3773  RzGraphNode *gn;
3774  RzListIter *it;
3775 
3776  if (!res) {
3777  return false;
3778  }
3779  sdb_array_remove(g->db, "agraph.nodes", res->title, 0);
3780  sdb_set(g->db, sdb_fmt("agraph.nodes.%s", res->title), NULL, 0);
3781  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.body", res->title), 0, 0);
3782  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.x", res->title), NULL, 0);
3783  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.y", res->title), NULL, 0);
3784  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.w", res->title), NULL, 0);
3785  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.h", res->title), NULL, 0);
3786  sdb_set(g->db, sdb_fmt("agraph.nodes.%s.neighbours", res->title), NULL, 0);
3787 
3788  const RzList *innodes = rz_graph_innodes(g->graph, res->gnode);
3789  graph_foreach_anode (innodes, it, gn, an) {
3790  const char *key = sdb_fmt("agraph.nodes.%s.neighbours", an->title);
3791  sdb_array_remove(g->db, key, res->title, 0);
3792  }
3793 
3794  rz_graph_del_node(g->graph, res->gnode);
3795  res->gnode = NULL;
3796 
3797  ht_pp_delete(g->nodes, res->title);
3798  return true;
3799 }

References free(), g, rz_ascii_node_t::gnode, graph_foreach_anode, key, NULL, rz_agraph_get_node(), rz_graph_del_node(), rz_graph_innodes(), rz_str_trunc_ellipsis(), sdb_array_remove(), sdb_fmt(), sdb_set(), and rz_ascii_node_t::title.

Referenced by rz_core_agraph_del_node().

◆ rz_agraph_foreach()

RZ_API void rz_agraph_foreach ( RzAGraph g,
RzANodeCallback  cb,
void *  user 
)

Definition at line 3829 of file agraph.c.

3829  {
3830  struct g_cb u = {
3831  .node_cb = cb,
3832  .data = user
3833  };
3834  ht_pp_foreach(g->nodes, (HtPPForeachCallback)user_node_cb, &u);
3835 }
static bool user_node_cb(struct g_cb *user, RZ_UNUSED const void *k, const void *v)
Definition: agraph.c:3801
Definition: agraph.c:73
RzANodeCallback node_cb
Definition: agraph.c:75
static const char * cb[]
Definition: z80_tab.h:176

References cb, g, g_cb::node_cb, and user_node_cb().

Referenced by rz_core_agraph_print_dot(), rz_core_agraph_print_gml(), and rz_core_agraph_print_rizin().

◆ rz_agraph_foreach_edge()

RZ_API void rz_agraph_foreach_edge ( RzAGraph g,
RAEdgeCallback  cb,
void *  user 
)

Definition at line 3837 of file agraph.c.

3837  {
3838  struct g_cb u = {
3839  .graph = g,
3840  .edge_cb = cb,
3841  .data = user
3842  };
3843  ht_pp_foreach(g->nodes, (HtPPForeachCallback)user_edge_cb, &u);
3844 }
static bool user_edge_cb(struct g_cb *user, RZ_UNUSED const void *k, const void *v)
Definition: agraph.c:3811
RzAGraph * graph
Definition: agraph.c:74

References cb, g, g_cb::graph, and user_edge_cb().

Referenced by rz_core_agraph_print_dot(), rz_core_agraph_print_gml(), and rz_core_agraph_print_rizin().

◆ rz_agraph_free()

RZ_API void rz_agraph_free ( RzAGraph g)

Definition at line 3909 of file agraph.c.

3909  {
3910  if (g) {
3911  ht_pp_free(g->nodes);
3912  rz_list_free(g->dummy_nodes);
3913  rz_graph_free(g->graph);
3914  rz_list_free(g->edges);
3916  sdb_free(g->db);
3917  rz_cons_canvas_free(g->can);
3918  free(g);
3919  }
3920 }
RZ_API void rz_cons_canvas_free(RzConsCanvas *c)
Definition: canvas.c:150
RZ_API void rz_graph_free(RzGraph *g)
Definition: graph.c:124
RZ_API bool sdb_free(Sdb *s)
Definition: sdb.c:206

References free(), g, NULL, rz_agraph_set_title(), rz_cons_canvas_free(), rz_graph_free(), rz_list_free(), and sdb_free().

Referenced by create_agraph_from_graph(), print_double_linked_list_bin_graph(), rz_core_fini(), and rz_core_visual_graph().

◆ rz_agraph_get_first_node()

RZ_API RzANode* rz_agraph_get_first_node ( const RzAGraph g)

Definition at line 3846 of file agraph.c.

3846  {
3847  const RzList *l = rz_graph_get_nodes(g->graph);
3848  RzGraphNode *rgn = rz_list_first(l);
3849  return get_anode(rgn);
3850 }

References g, get_anode, rz_graph_get_nodes(), and rz_list_first().

Referenced by rz_core_agraph_print_interactive(), and rz_core_graph_print().

◆ rz_agraph_get_node()

RZ_API RzANode* rz_agraph_get_node ( const RzAGraph g,
const char *  title 
)

Definition at line 3852 of file agraph.c.

3852  {
3853  char *title_trunc = title ? rz_str_trunc_ellipsis(title, 255) : NULL;
3854  if (!title_trunc) {
3855  return NULL;
3856  }
3857  RzANode *node = ht_pp_find(g->nodes, title_trunc, NULL);
3858  free(title_trunc);
3859  return node;
3860 }

References free(), g, NULL, and rz_str_trunc_ellipsis().

Referenced by check_changes(), get_bbnodes(), get_bbupdate(), get_cgnodes(), goto_asmqjmps(), rz_agraph_add_node_with_color(), rz_agraph_del_node(), rz_core_agraph_add_edge(), and rz_core_agraph_del_edge().

◆ rz_agraph_get_sdb()

RZ_API Sdb* rz_agraph_get_sdb ( RzAGraph g)

Definition at line 3679 of file agraph.c.

3679  {
3680  g->need_update_dim = true;
3681  g->need_set_layout = true;
3682  (void)check_changes(g, false, NULL, NULL);
3683  // remove_dummy_nodes (g);
3684  return g->db;
3685 }

References check_changes(), g, and NULL.

Referenced by rz_core_agraph_print_sdb(), and rz_core_graph_print().

◆ rz_agraph_new()

RZ_API RzAGraph* rz_agraph_new ( RzConsCanvas can)

Definition at line 3922 of file agraph.c.

3922  {
3923  RzAGraph *g = RZ_NEW0(RzAGraph);
3924  if (!g) {
3925  return NULL;
3926  }
3927  g->can = can;
3928  g->dummy = true;
3929  agraph_init(g);
3930  agraph_sdb_init(g);
3931  return g;
3932 }
static void agraph_sdb_init(const RzAGraph *g)
Definition: agraph.c:3669
static void agraph_init(RzAGraph *g)
Definition: agraph.c:3619

References agraph_init(), agraph_sdb_init(), g, NULL, and RZ_NEW0.

Referenced by create_agraph_from_graph(), print_double_linked_list_bin_graph(), rz_cmd_heap_chunks_print_handler(), rz_core_init(), and rz_core_visual_graph().

◆ rz_agraph_print()

RZ_API void rz_agraph_print ( RzAGraph g)

Definition at line 3687 of file agraph.c.

3687  {
3688  agraph_print(g, false, NULL, NULL);
3689  if (g->graph->n_nodes > 0) {
3690  rz_cons_newline();
3691  }
3692 }

References agraph_print(), g, NULL, and rz_cons_newline().

Referenced by print_double_linked_list_bin_graph(), rz_cmd_heap_chunks_print_handler(), rz_core_agraph_print_ascii(), and rz_core_graph_print().

◆ rz_agraph_print_json()

RZ_API void rz_agraph_print_json ( RzAGraph g,
PJ pj 
)

Definition at line 3694 of file agraph.c.

3694  {
3695  RzList *nodes = g->graph->nodes, *neighbours = NULL;
3696  RzListIter *it, *itt;
3697  RzGraphNode *node = NULL, *neighbour = NULL;
3698  if (!pj) {
3699  return;
3700  }
3701  rz_list_foreach (nodes, it, node) {
3702  RzANode *anode = (RzANode *)node->data;
3703  char *label = strdup(anode->body);
3704  pj_o(pj);
3705  pj_ki(pj, "id", anode->gnode->idx);
3706  pj_ks(pj, "title", anode->title);
3707  pj_ks(pj, "body", label);
3708  pj_k(pj, "out_nodes");
3709  pj_a(pj);
3710  neighbours = anode->gnode->out_nodes;
3711  rz_list_foreach (neighbours, itt, neighbour) {
3712  pj_i(pj, neighbour->idx);
3713  }
3714  pj_end(pj);
3715  pj_end(pj);
3716  free(label);
3717  }
3718 }
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
Definition: pj.c:149
RZ_API PJ * pj_k(PJ *j, const char *k)
Definition: pj.c:104
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_i(PJ *j, int d)
Definition: pj.c:284
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
Definition: dis.h:35

References rz_ascii_node_t::body, rz_graph_node_t::data, free(), g, rz_ascii_node_t::gnode, rz_graph_node_t::idx, NULL, rz_graph_node_t::out_nodes, pj_a(), pj_end(), pj_i(), pj_k(), pj_ki(), pj_ks(), pj_o(), strdup(), and rz_ascii_node_t::title.

Referenced by rz_core_agraph_print_json().

◆ rz_agraph_reset()

RZ_API void rz_agraph_reset ( RzAGraph g)

Definition at line 3889 of file agraph.c.

3889  {
3890  ht_pp_free(g->nodes);
3891  rz_list_free(g->dummy_nodes);
3892  rz_graph_reset(g->graph);
3894  sdb_reset(g->db);
3895  if (g->edges) {
3896  rz_list_purge(g->edges);
3897  }
3898  g->nodes = ht_pp_new_opt(&nodes_opt);
3899  g->dummy_nodes = rz_list_newf((RzListFree)agraph_node_free);
3900  g->update_seek_on = NULL;
3901  g->need_reload_nodes = false;
3902  g->need_set_layout = true;
3903  g->need_update_dim = true;
3904  g->x = g->y = g->w = g->h = 0;
3905  agraph_sdb_init(g);
3906  g->curnode = NULL;
3907 }
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
RZ_API void rz_graph_reset(RzGraph *g)
Definition: graph.c:141
RZ_API void sdb_reset(Sdb *s)
Definition: sdb.c:433

References agraph_node_free(), agraph_sdb_init(), g, nodes_opt, NULL, rz_agraph_set_title(), rz_graph_reset(), rz_list_free(), rz_list_newf(), rz_list_purge(), and sdb_reset().

Referenced by agraph_reload_nodes(), and rz_core_agraph_reset().

◆ rz_agraph_set_curnode()

RZ_API void rz_agraph_set_curnode ( RzAGraph g,
RzANode a 
)

Definition at line 2696 of file agraph.c.

2696  {
2697  if (!a) {
2698  return;
2699  }
2700  g->curnode = a->gnode;
2701  if (a->title) {
2702  sdb_set(g->db, "agraph.curnode", a->title, 0);
2703  if (g->on_curnode_change) {
2704  g->on_curnode_change(a, g->on_curnode_change_data);
2705  }
2706  }
2707 }

References a, g, and sdb_set().

Referenced by agraph_follow_innodes(), agraph_next_node(), agraph_prev_node(), check_changes(), follow_nth(), goto_asmqjmps(), rz_core_agraph_print_interactive(), and rz_core_graph_print().

◆ rz_agraph_set_title()

RZ_API void rz_agraph_set_title ( RzAGraph g,
const char *  title 
)

Definition at line 3720 of file agraph.c.

3720  {
3721  free(g->title);
3722  g->title = title ? strdup(title) : NULL;
3723  sdb_set(g->db, "agraph.title", g->title, 0);
3724 }

References free(), g, NULL, sdb_set(), and strdup().

Referenced by agraph_update_title(), rz_agraph_free(), rz_agraph_reset(), rz_cmd_heap_chunks_print_handler(), rz_core_agraph_print_ascii(), rz_core_agraph_print_interactive(), and rz_core_graph_print().

◆ rz_core_visual_graph()

RZ_API int rz_core_visual_graph ( RzCore core,
RzAGraph g,
RzAnalysisFunction _fcn,
int  is_interactive 
)

Definition at line 4114 of file agraph.c.

4114  {
4115  if (is_interactive && !rz_cons_is_interactive()) {
4116  eprintf("Interactive graph mode requires scr.interactive=true.\n");
4117  return 0;
4118  }
4119  int o_asmqjmps_letter = core->is_asmqjmps_letter;
4120  int o_vmode = core->vmode;
4121  int exit_graph = false, is_error = false;
4122  int update_seek = false;
4123  struct agraph_refresh_data *grd;
4124  int okey, key;
4126  const char *key_s;
4127  RzConsCanvas *can, *o_can = NULL;
4128  bool graph_allocated = false;
4129  int movspeed;
4130  int ret, invscroll;
4132  if (!hc) {
4133  return false;
4134  }
4135  rz_config_hold_i(hc, "asm.pseudo", "asm.esil", "asm.cmt.right", NULL);
4136 
4137  int h, w = rz_cons_get_size(&h);
4138  can = rz_cons_canvas_new(w, h);
4139  if (!can) {
4140  w = 80;
4141  h = 25;
4142  can = rz_cons_canvas_new(w, h);
4143  if (!can) {
4144  eprintf("Cannot create RzCons.canvas context. Invalid screen "
4145  "size? See scr.columns + scr.rows\n");
4146  rz_config_hold_free(hc);
4147  return false;
4148  }
4149  }
4150  can->linemode = rz_config_get_i(core->config, "graph.linemode");
4151  can->color = rz_config_get_i(core->config, "scr.color");
4152 
4153  if (!g) {
4154  graph_allocated = true;
4155  fcn = _fcn ? _fcn : rz_analysis_get_fcn_in(core->analysis, core->offset, 0);
4156  if (!fcn) {
4158  rz_config_hold_free(hc);
4159  rz_cons_canvas_free(can);
4160  return false;
4161  }
4163  g = rz_agraph_new(can);
4164  if (!g) {
4165  rz_cons_canvas_free(can);
4167  rz_config_hold_free(hc);
4168  return false;
4169  }
4170  g->is_tiny = is_interactive == 2;
4171  g->layout = rz_config_get_i(core->config, "graph.layout");
4172  g->dummy = rz_config_get_i(core->config, "graph.dummy");
4173  g->show_node_titles = rz_config_get_i(core->config, "graph.ntitles");
4174  } else {
4175  o_can = g->can;
4176  }
4177  g->can = can;
4178  g->movspeed = rz_config_get_i(core->config, "graph.scroll");
4179  g->show_node_titles = rz_config_get_i(core->config, "graph.ntitles");
4180  g->show_node_body = rz_config_get_i(core->config, "graph.body");
4181  g->on_curnode_change = (RzANodeCallback)seek_to_node;
4182  g->on_curnode_change_data = core;
4183  g->edgemode = rz_config_get_i(core->config, "graph.edges");
4184  g->hints = rz_config_get_i(core->config, "graph.hints");
4185  g->is_interactive = is_interactive;
4186  bool asm_comments = rz_config_get_i(core->config, "asm.comments");
4187  rz_config_set(core->config, "asm.comments",
4188  rz_str_bool(rz_config_get_i(core->config, "graph.comments")));
4189 
4190  /* we want letters as shortcuts for call/jmps */
4191  core->is_asmqjmps_letter = true;
4192  core->vmode = true;
4193 
4194  grd = RZ_NEW0(struct agraph_refresh_data);
4195  if (!grd) {
4196  rz_cons_canvas_free(can);
4198  rz_config_hold_free(hc);
4199  rz_agraph_free(g);
4200  return false;
4201  }
4202  grd->g = g;
4203  grd->fs = is_interactive == 1;
4204  grd->core = core;
4205  grd->follow_offset = _fcn == NULL;
4206  grd->fcn = fcn != NULL ? &fcn : NULL;
4207  ret = agraph_refresh(grd);
4208  if (!ret || is_interactive != 1) {
4209  rz_cons_newline();
4210  exit_graph = true;
4211  is_error = !ret;
4212  }
4213 
4214  core->cons->event_resize = NULL; // avoid running old event with new data
4215  core->cons->event_data = grd;
4217 
4219 
4220  while (!exit_graph && !is_error && !rz_cons_is_breaked()) {
4221  rz_cons_get_size(&h);
4222  invscroll = rz_config_get_i(core->config, "graph.invscroll");
4223  ret = agraph_refresh(grd);
4224 
4225  if (!ret) {
4226  is_error = true;
4227  break;
4228  }
4229  showcursor(core, false);
4230 
4231  // rz_core_graph_inputhandle()
4232  okey = rz_cons_readchar();
4233  key = rz_cons_arrow_to_hjkl(okey);
4234 
4235  if (core->cons->mouse_event) {
4236  movspeed = rz_config_get_i(core->config, "scr.wheel.speed");
4237  switch (key) {
4238  case 'j':
4239  case 'k':
4240  switch (mousemode) {
4241  case 0: break;
4242  case 1: key = key == 'k' ? 'h' : 'l'; break;
4243  case 2: key = key == 'k' ? 'J' : 'K'; break;
4244  case 3: key = key == 'k' ? 'L' : 'H'; break;
4245  }
4246  break;
4247  }
4248  } else {
4249  movspeed = g->movspeed;
4250  }
4251  const char *cmd;
4252  switch (key) {
4253  case '-':
4254  agraph_set_zoom(g, g->zoom - ZOOM_STEP);
4255  g->force_update_seek = true;
4256  break;
4257  case '+':
4258  agraph_set_zoom(g, g->zoom + ZOOM_STEP);
4259  g->force_update_seek = true;
4260  break;
4261  case '0':
4263  agraph_update_seek(g, get_anode(g->curnode), true);
4264  // update scroll (with minor shift)
4265  break;
4266  case '=': { // TODO: edit
4267  showcursor(core, true);
4268  const char *cmd = rz_config_get(core->config, "cmd.gprompt");
4269  rz_line_set_prompt("cmd.gprompt> ");
4270  core->cons->line->contents = strdup(cmd);
4271  const char *buf = rz_line_readline();
4272  core->cons->line->contents = NULL;
4273  rz_config_set(core->config, "cmd.gprompt", buf);
4274  showcursor(core, false);
4275  } break;
4276  case '|': {
4277  int e = rz_config_get_i(core->config, "graph.layout");
4278  if (++e > 1) {
4279  e = 0;
4280  }
4281  rz_config_set_i(core->config, "graph.layout", e);
4282  g->layout = rz_config_get_i(core->config, "graph.layout");
4283  g->need_update_dim = true;
4284  g->need_set_layout = true;
4285  }
4286  discroll = 0;
4287  agraph_update_seek(g, get_anode(g->curnode), true);
4288  break;
4289  case 'e': {
4290  int e = rz_config_get_i(core->config, "graph.edges");
4291  e++;
4292  if (e > 2) {
4293  e = 0;
4294  }
4295  rz_config_set_i(core->config, "graph.edges", e);
4296  g->edgemode = e;
4297  g->need_update_dim = true;
4298  get_bbupdate(g, core, fcn);
4299  } break;
4300  case '\\':
4301  nextword(core, g, rz_config_get(core->config, "scr.highlight"));
4302  break;
4303  case 'b':
4305  break;
4306  case 'E': {
4307  int e = rz_config_get_i(core->config, "graph.linemode");
4308  e--;
4309  if (e < 0) {
4310  e = 1;
4311  }
4312  rz_config_set_i(core->config, "graph.linemode", e);
4313  g->can->linemode = e;
4314  get_bbupdate(g, core, fcn);
4315  } break;
4316  case 13:
4317  agraph_update_seek(g, get_anode(g->curnode), true);
4318  update_seek = true;
4319  exit_graph = true;
4320  break;
4321  case '>':
4322  if (fcn && rz_cons_yesno('y', "Compute function callgraph? (Y/n)")) {
4324  rz_core_cmd0(core, ".agc* @$FB;.axfg @$FB");
4326  }
4327  break;
4328  case '<':
4329  // rz_core_visual_xrefs (core, true, false);
4330  if (fcn) {
4332  rz_core_cmd0(core, ".axtg $FB");
4334  }
4335  break;
4336  case 'G':
4338  rz_core_cmd0(core, ".dtg*");
4340  break;
4341  case 'V':
4342  if (fcn) {
4344  }
4345  break;
4346  case 'Z':
4347  if (okey == 27) { // shift-tab
4349  }
4350  break;
4351  case 's':
4352  if (!fcn) {
4353  break;
4354  }
4355  key_s = rz_config_get(core->config, "key.s");
4356  if (key_s && *key_s) {
4357  rz_core_cmd0(core, key_s);
4358  } else {
4360  }
4361  discroll = 0;
4362  agraph_update_seek(g, get_anode(g->curnode), true);
4363  break;
4364  case 'S':
4365  if (fcn) {
4367  }
4368  break;
4369  case 'x':
4370  case 'X': {
4371  if (!fcn) {
4372  break;
4373  }
4374  ut64 old_off = core->offset;
4376  if (block) {
4377  rz_core_seek(core, block->addr, false);
4378  }
4379  if ((key == 'x' && !rz_core_visual_xrefs(core, true, true)) ||
4380  (key == 'X' && !rz_core_visual_xrefs(core, false, true))) {
4381  rz_core_seek(core, old_off, false);
4382  }
4383  break;
4384  }
4385  case 9: // tab
4387  discroll = 0;
4388  break;
4389  case '?':
4390  rz_cons_clear00();
4391  rz_cons_printf("Visual Ascii Art graph keybindings:\n"
4392  " :e cmd.gprompt = agft - show tinygraph in one side\n"
4393  " +/-/0 - zoom in/out/default\n"
4394  " ; - add comment in current basic block\n"
4395  " . (dot) - center graph to the current node\n"
4396  " , (comma) - toggle graph.few\n"
4397  " ^ - seek to the first bb of the function\n"
4398  " = - toggle graph.layout\n"
4399  " :cmd - run rizin command\n"
4400  " ' - toggle graph.comments\n"
4401  " \" - toggle graph.refs\n"
4402  " # - toggle graph.hints\n"
4403  " / - highlight text\n"
4404  " \\ - scroll the graph canvas to the next highlight location\n"
4405  " | - set cmd.gprompt\n"
4406  " _ - enter hud selector\n"
4407  " > - show function callgraph (see graph.refs)\n"
4408  " < - show program callgraph (see graph.refs)\n"
4409  " ( - reverse conditional branch of last instruction in bb\n"
4410  " ) - rotate asm.emu and emu.str\n"
4411  " Home/End - go to the top/bottom of the canvas\n"
4412  " Page-UP/DOWN - scroll canvas up/down\n"
4413  " b - visual browse things\n"
4414  " c - toggle graph cursor mode\n"
4415  " C - toggle scr.colors\n"
4416  " d - rename function\n"
4417  " D - toggle the mixed graph+disasm mode\n"
4418  " e - rotate graph.edges (show/hide edges)\n"
4419  " E - rotate graph.linemode (square/diagonal lines)\n"
4420  " F - enter flag selector\n"
4421  " g - go/seek to given offset\n"
4422  " G - debug trace callgraph (generated with dtc)\n"
4423  " hjkl/HJKL - scroll canvas or node depending on graph cursor (uppercase for faster)\n"
4424  " i - select input nodes by index\n"
4425  " I - select output node by index\n"
4426  " m/M - change mouse modes\n"
4427  " n/N - next/previous scr.nkey (function/flag..)\n"
4428  " o([A-Za-z]*) - follow jmp/call identified by shortcut (like ;[oa])\n"
4429  " O - toggle asm.pseudo and asm.esil\n"
4430  " p/P - rotate graph modes (normal, display offsets, minigraph, summary)\n"
4431  " q - back to Visual mode\n"
4432  " r - toggle jmphints/leahints\n"
4433  " R - randomize colors\n"
4434  " s/S - step / step over\n"
4435  " tab - select next node\n"
4436  " TAB - select previous node\n"
4437  " t/f - follow true/false edges\n"
4438  " u/U - undo/redo seek\n"
4439  " V - toggle basicblock / call graphs\n"
4440  " w - toggle between movements speed 1 and graph.scroll\n"
4441  " x/X - jump to xref/ref\n"
4442  " Y - toggle tiny graph\n"
4443  " z - toggle node folding\n"
4444  " Z - toggle basic block folding");
4445  rz_cons_less();
4447  break;
4448  case '"':
4449  rz_config_toggle(core->config, "graph.refs");
4450  break;
4451  case '#':
4452  if (g->mode == RZ_AGRAPH_MODE_COMMENTS) {
4453  g->mode = RZ_AGRAPH_MODE_NORMAL;
4454  } else {
4455  g->mode = RZ_AGRAPH_MODE_COMMENTS;
4456  }
4457  g->need_reload_nodes = true;
4458  discroll = 0;
4459  agraph_update_seek(g, get_anode(g->curnode), true);
4460  // rz_config_toggle (core->config, "graph.hints");
4461  break;
4462  case 'p':
4463  g->mode = next_mode(g->mode);
4464  g->need_reload_nodes = true;
4465  agraph_update_seek(g, get_anode(g->curnode), true);
4466  break;
4467  case 'P':
4468  if (!fcn) {
4469  break;
4470  }
4471  g->mode = prev_mode(g->mode);
4472  g->need_reload_nodes = true;
4473  agraph_update_seek(g, get_anode(g->curnode), true);
4474  break;
4475  case 'o':
4476  goto_asmqjmps(g, core);
4477  break;
4478  case 'g':
4479  showcursor(core, true);
4480  visual_offset(g, core);
4481  showcursor(core, false);
4482  break;
4483  case 'O':
4484  if (!fcn) {
4485  break;
4486  }
4487  disMode = (disMode + 1) % 3;
4488  applyDisMode(core);
4489  g->need_reload_nodes = true;
4490  get_bbupdate(g, core, fcn);
4491  break;
4492  case 'u': {
4493  if (!fcn) {
4494  break;
4495  }
4496  if (!rz_core_seek_undo(core)) {
4497  eprintf("Cannot undo\n");
4498  }
4499  if (rz_config_get_i(core->config, "graph.few")) {
4500  g->need_reload_nodes = true;
4501  }
4502  break;
4503  }
4504  case 'U': {
4505  if (!fcn) {
4506  break;
4507  }
4508  if (!rz_core_seek_redo(core)) {
4509  eprintf("Cannot redo\n");
4510  }
4511  break;
4512  }
4513  case 'r':
4514  if (fcn) {
4515  g->layout = rz_config_get_i(core->config, "graph.layout");
4516  g->need_reload_nodes = true;
4517  }
4518  // TODO: toggle shortcut hotkeys
4520  break;
4521  case '$': {
4522  ut64 dst =
4524  ? core->offset + core->print->cur
4525  : core->offset;
4527  rz_core_seek_to_register(core, "PC", false);
4528  g->need_reload_nodes = true;
4529  break;
4530  }
4531  case 'R':
4532  if (rz_config_get_i(core->config, "scr.randpal")) {
4534  } else {
4536  }
4537  if (!fcn) {
4538  break;
4539  }
4540  g->edgemode = rz_config_get_i(core->config, "graph.edges");
4541  get_bbupdate(g, core, fcn);
4542  break;
4543  case '!':
4545  break;
4546  case '\'':
4547  if (fcn) {
4548  rz_config_toggle(core->config, "graph.comments");
4549  g->need_reload_nodes = true;
4550  }
4551  break;
4552  case ';':
4553  if (fcn) {
4554  showcursor(core, true);
4555  char buf[256];
4556  rz_line_set_prompt("[comment]> ");
4557  if (rz_cons_fgets(buf, sizeof(buf), 0, NULL) > 0) {
4559  }
4560  g->need_reload_nodes = true;
4561  showcursor(core, false);
4562  }
4563  break;
4564  case 'C':
4565  rotateColor(core);
4566  break;
4567  case 'm':
4568  mousemode++;
4569  if (!mousemodes[mousemode]) {
4570  mousemode = 0;
4571  }
4572  break;
4573  case 'M':
4574  mousemode--;
4575  if (mousemode < 0) {
4576  mousemode = 3;
4577  }
4578  break;
4579  case '(': {
4580  if (!fcn) {
4581  break;
4582  }
4583  if (!rz_core_seek_bb_instruction(core, -1)) {
4584  break;
4585  }
4586  ut64 oldseek = core->offset;
4587  core->tmpseek = true;
4588  rz_core_hack(core, "recj");
4589  core->tmpseek = false;
4590  rz_core_seek(core, oldseek, true);
4591  g->need_reload_nodes = true;
4592  break;
4593  }
4594  case ')':
4595  if (fcn) {
4596  rotateAsmemu(core);
4597  g->need_reload_nodes = true;
4598  }
4599  break;
4600  case 'd': {
4601  showcursor(core, true);
4602  rz_core_visual_define(core, "", 0);
4603  get_bbupdate(g, core, fcn);
4604  showcursor(core, false);
4605  } break;
4606  case 'D':
4607  g->is_dis = !g->is_dis;
4608  break;
4609  case 'n':
4610  rz_core_seek_next(core, rz_config_get(core->config, "scr.nkey"), true);
4611  break;
4612  case 'N':
4613  rz_core_seek_prev(core, rz_config_get(core->config, "scr.nkey"), true);
4614  break;
4615  case 'Y':
4617  agraph_update_seek(g, get_anode(g->curnode), true);
4618  break;
4619  case 'z':
4621  discroll = 0;
4622  agraph_update_seek(g, get_anode(g->curnode), true);
4623  break;
4624  case 'v':
4626  break;
4627  case 'J':
4628  // copypaste from 'j'
4629  if (graphCursor) {
4630  int speed = (okey == 27) ? PAGEKEY_SPEED : movspeed;
4631  graphNodeMove(g, 'j', speed * 2);
4632  } else {
4633  can->sy -= (5 * movspeed) * (invscroll ? -1 : 1);
4634  }
4635  break;
4636  case 'K':
4637  if (graphCursor) {
4638  int speed = (okey == 27) ? PAGEKEY_SPEED : movspeed;
4639  graphNodeMove(g, 'k', speed * 2);
4640  } else {
4641  can->sy += (5 * movspeed) * (invscroll ? -1 : 1);
4642  }
4643  break;
4644  case 'H':
4645  if (graphCursor) {
4646  // move node canvas faster
4647  graphNodeMove(g, 'h', movspeed * 2);
4648  } else {
4649  // scroll canvas faster
4650  if (okey == 27) {
4651  // handle home key
4652  const RzGraphNode *gn = find_near_of(g, NULL, true);
4653  g->update_seek_on = get_anode(gn);
4654  } else {
4655  can->sx += (5 * movspeed) * (invscroll ? -1 : 1);
4656  }
4657  }
4658  break;
4659  case 'L':
4660  if (graphCursor) {
4661  graphNodeMove(g, 'l', movspeed * 2);
4662  } else {
4663  can->sx -= (5 * movspeed) * (invscroll ? -1 : 1);
4664  }
4665  break;
4666  case 'c':
4668  break;
4669  case 'j':
4670  if (g->is_dis) {
4671  rz_core_seek_opcode(core, 1, false);
4672  } else {
4673  if (graphCursor) {
4674  int speed = (okey == 27) ? PAGEKEY_SPEED : movspeed;
4675  graphNodeMove(g, 'j', speed);
4676  } else {
4677  // scroll canvas
4678  can->sy -= movspeed * (invscroll ? -1 : 1);
4679  }
4680  }
4681  break;
4682  case 'k':
4683  if (g->is_dis) {
4684  rz_core_seek_opcode(core, -1, false);
4685  } else {
4686  if (graphCursor) {
4687  int speed = (okey == 27) ? PAGEKEY_SPEED : movspeed;
4688  graphNodeMove(g, 'k', speed);
4689  } else {
4690  // scroll canvas
4691  can->sy += movspeed * (invscroll ? -1 : 1);
4692  }
4693  }
4694  break;
4695  case 'l':
4696  if (graphCursor) {
4697  int speed = (okey == 27) ? PAGEKEY_SPEED : movspeed;
4698  graphNodeMove(g, 'l', speed);
4699  } else {
4700  can->sx -= movspeed * (invscroll ? -1 : 1);
4701  }
4702  break;
4703  case 'h':
4704  if (graphCursor) {
4705  int speed = (okey == 27) ? PAGEKEY_SPEED : movspeed;
4706  graphNodeMove(g, 'h', speed);
4707  } else {
4708  can->sx += movspeed * (invscroll ? -1 : 1);
4709  }
4710  break;
4711  case '^': {
4713  if (fcn) {
4714  rz_core_seek(core, fcn->addr, false);
4715  }
4716  }
4717  agraph_update_seek(g, get_anode(g->curnode), true);
4718  break;
4719  case ',':
4720  rz_config_toggle(core->config, "graph.few");
4721  g->need_reload_nodes = true;
4722  agraph_update_seek(g, get_anode(g->curnode), true);
4723  break;
4724  case '.':
4725  discroll = 0;
4726  agraph_update_seek(g, get_anode(g->curnode), true);
4727  break;
4728  case 'i':
4729  agraph_follow_innodes(g, true);
4730  if (rz_config_get_i(core->config, "graph.few")) {
4731  g->need_reload_nodes = true;
4732  }
4733  break;
4734  case 'I':
4735  agraph_follow_innodes(g, false);
4736  if (rz_config_get_i(core->config, "graph.few")) {
4737  g->need_reload_nodes = true;
4738  }
4739  break;
4740  case 't':
4742  if (rz_config_get_i(core->config, "graph.few")) {
4743  g->need_reload_nodes = true;
4744  }
4745  break;
4746  case 'T':
4747  // XXX WIP agraph_merge_child (g, 0);
4748  break;
4749  case 'f':
4751  if (rz_config_get_i(core->config, "graph.few")) {
4752  g->need_reload_nodes = true;
4753  }
4754  break;
4755  case 'F':
4756  if (okey == 27) {
4757  // handle end key
4758  const RzGraphNode *gn = find_near_of(g, NULL, false);
4759  g->update_seek_on = get_anode(gn);
4760  } else {
4761  // agraph_merge_child (g, 1);
4763  }
4764  break;
4765  case '/':
4766  showcursor(core, true);
4767  rz_core_cmd0(core, "?i highlight;e scr.highlight=`yp`");
4768  showcursor(core, false);
4769  break;
4770  case ':':
4774  if (!g) {
4775  g->need_reload_nodes = true; // maybe too slow and unnecessary sometimes? better be safe and reload
4776  get_bbupdate(g, core, fcn);
4777  }
4778  break;
4779  case 'w':
4781  break;
4782  case '_':
4784  break;
4785  case RZ_CONS_KEY_F1:
4786  cmd = rz_config_get(core->config, "key.f1");
4787  if (cmd && *cmd) {
4788  (void)rz_core_cmd0(core, cmd);
4789  }
4790  break;
4791  case RZ_CONS_KEY_F2:
4792  cmd = rz_config_get(core->config, "key.f2");
4793  if (cmd && *cmd) {
4794  (void)rz_core_cmd0(core, cmd);
4795  } else {
4797  }
4798  break;
4799  case RZ_CONS_KEY_F3:
4800  cmd = rz_config_get(core->config, "key.f3");
4801  if (cmd && *cmd) {
4802  (void)rz_core_cmd0(core, cmd);
4803  }
4804  break;
4805  case RZ_CONS_KEY_F4:
4806  cmd = rz_config_get(core->config, "key.f4");
4807  if (cmd && *cmd) {
4808  (void)rz_core_cmd0(core, cmd);
4809  }
4810  break;
4811  case RZ_CONS_KEY_F5:
4812  cmd = rz_config_get(core->config, "key.f5");
4813  if (cmd && *cmd) {
4814  (void)rz_core_cmd0(core, cmd);
4815  }
4816  break;
4817  case RZ_CONS_KEY_F6:
4818  cmd = rz_config_get(core->config, "key.f6");
4819  if (cmd && *cmd) {
4820  (void)rz_core_cmd0(core, cmd);
4821  }
4822  break;
4823  case RZ_CONS_KEY_F7:
4824  cmd = rz_config_get(core->config, "key.f7");
4825  if (cmd && *cmd) {
4826  (void)rz_core_cmd0(core, cmd);
4827  } else {
4829  }
4830  break;
4831  case RZ_CONS_KEY_F8:
4832  cmd = rz_config_get(core->config, "key.f8");
4833  if (cmd && *cmd) {
4834  (void)rz_core_cmd0(core, cmd);
4835  } else {
4837  }
4838  break;
4839  case RZ_CONS_KEY_F9:
4840  cmd = rz_config_get(core->config, "key.f9");
4841  if (cmd && *cmd) {
4842  (void)rz_core_cmd0(core, cmd);
4843  } else {
4845  }
4846  break;
4847  case RZ_CONS_KEY_F10:
4848  cmd = rz_config_get(core->config, "key.f10");
4849  if (cmd && *cmd) {
4850  (void)rz_core_cmd0(core, cmd);
4851  }
4852  break;
4853  case RZ_CONS_KEY_F11:
4854  cmd = rz_config_get(core->config, "key.f11");
4855  if (cmd && *cmd) {
4856  (void)rz_core_cmd0(core, cmd);
4857  }
4858  break;
4859  case RZ_CONS_KEY_F12:
4860  cmd = rz_config_get(core->config, "key.f12");
4861  if (cmd && *cmd) {
4862  (void)rz_core_cmd0(core, cmd);
4863  }
4864  break;
4865  case -1: // EOF
4866  case ' ':
4867  case 'Q':
4868  case 'q':
4869  if (g->is_callgraph) {
4871  } else {
4872  exit_graph = true;
4873  }
4874  break;
4875  case 27: // ESC
4876  if (rz_cons_readchar() == 91) {
4877  if (rz_cons_readchar() == 90) {
4879  }
4880  }
4881  break;
4882  default:
4883  break;
4884  }
4885  }
4886  rz_vector_fini(&g->ghits.word_list);
4888  rz_config_set(core->config, "asm.comments", rz_str_bool(asm_comments));
4889  core->cons->event_resize = NULL;
4890  core->cons->event_data = NULL;
4891  core->vmode = o_vmode;
4892  core->is_asmqjmps_letter = o_asmqjmps_letter;
4893  core->keep_asmqjmps = false;
4894 
4895  free(grd);
4896  if (graph_allocated) {
4897  rz_agraph_free(g);
4898  } else {
4899  rz_cons_canvas_free(g->can);
4900  g->can = o_can;
4901  }
4903  rz_config_hold_free(hc);
4904  if (update_seek) {
4905  return -1;
4906  }
4907  return !is_error;
4908 }
static void rotateAsmemu(RzCore *core)
Definition: agraph.c:174
static void goto_asmqjmps(RzAGraph *g, RzCore *core)
Definition: agraph.c:3954
#define PAGEKEY_SPEED
Definition: agraph.c:38
static void graph_single_step_in(RzCore *core, RzAGraph *g)
Definition: agraph.c:4007
static void agraph_refresh_oneshot(struct agraph_refresh_data *grd)
Definition: agraph.c:3588
static void visual_offset(RzAGraph *g, RzCore *core)
Definition: agraph.c:3934
static void agraph_toggle_callgraph(RzAGraph *g)
Definition: agraph.c:3146
static void agraph_set_need_reload_nodes(struct agraph_refresh_data *grd)
Definition: agraph.c:3592
static int next_mode(int mode)
Definition: agraph.c:133
static void graph_breakpoint(RzCore *core)
Definition: agraph.c:4019
static const char * mousemodes[]
Definition: agraph.c:17
static void agraph_next_node(RzAGraph *g)
Definition: agraph.c:3331
static void graphNodeMove(RzAGraph *g, int dir, int speed)
Definition: agraph.c:3637
static void agraph_toggle_mini(RzAGraph *g)
Definition: agraph.c:3248
static void agraph_follow_true(RzAGraph *g)
Definition: agraph.c:3320
#define ZOOM_STEP
Definition: agraph.c:46
static int mousemode
Definition: agraph.c:13
static void agraph_set_zoom(RzAGraph *g, int v)
Definition: agraph.c:3152
static void graph_single_step_over(RzCore *core, RzAGraph *g)
Definition: agraph.c:4013
static void applyDisMode(RzCore *core)
Definition: agraph.c:4027
static void agraph_follow_innodes(RzAGraph *g, bool in)
Definition: agraph.c:3258
static void agraph_prev_node(RzAGraph *g)
Definition: agraph.c:3341
static void agraph_toggle_speed(RzAGraph *g, RzCore *core)
Definition: agraph.c:3596
static void seek_to_node(RzANode *n, RzCore *core)
Definition: agraph.c:3991
static void rotateColor(RzCore *core)
Definition: agraph.c:4044
static void graph_continue(RzCore *core)
Definition: agraph.c:4024
static void get_bbupdate(RzAGraph *g, RzCore *core, RzAnalysisFunction *fcn)
Definition: agraph.c:2218
static void showcursor(RzCore *core, int x)
Definition: agraph.c:188
static int prev_mode(int mode)
Definition: agraph.c:137
static void agraph_toggle_tiny(RzAGraph *g)
Definition: agraph.c:3240
static void agraph_follow_false(RzAGraph *g)
Definition: agraph.c:3325
RZ_IPI void rz_core_agraph_print_interactive(RzCore *core)
Definition: cagraph.c:88
RZ_IPI void rz_core_agraph_reset(RzCore *core)
Definition: cagraph.c:8
RZ_API void rz_core_theme_nextpal(RzCore *core, RzConsPalSeekMode mode)
Definition: cmd_eval.c:148
RZ_API bool rz_config_toggle(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:97
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API bool rz_cons_is_interactive(void)
Definition: cons.c:365
RZ_IPI bool rz_core_seek_bb_instruction(RzCore *core, int index)
Definition: seek.c:453
RZ_API bool rz_core_reg_set_by_role_or_name(RzCore *core, const char *name, ut64 num)
set on rz_core_reg_default()
Definition: creg.c:39
RZ_API const char * rz_line_readline(void)
Definition: dietline.c:913
RZ_API bool rz_core_hack(RzCore *core, const char *op)
Write/Modify instructions at current offset based on op.
Definition: hack.c:280
RZ_API int rz_cons_arrow_to_hjkl(int ch)
Definition: input.c:78
RZ_API int rz_cons_any_key(const char *msg)
Definition: input.c:393
RZ_API int rz_cons_fgets(char *buf, int len, int argc, const char **argv)
Definition: input.c:339
voidpf void * buf
Definition: ioapi.h:138
RZ_API void rz_cons_less(void)
Definition: less.c:171
RZ_API void rz_line_set_prompt(const char *prompt)
Definition: line.c:56
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
RZ_API void rz_cons_pal_random(void)
Definition: pal.c:270
RZ_API bool rz_core_visual_panels_root(RzCore *core, RzPanelsRoot *panels_root)
Definition: panels.c:5947
void(* RzANodeCallback)(RzANode *n, void *user)
Definition: rz_agraph.h:43
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
#define RZ_CONS_KEY_F12
Definition: rz_cons.h:589
#define RZ_CONS_KEY_F11
Definition: rz_cons.h:588
#define RZ_CONS_KEY_F10
Definition: rz_cons.h:587
#define RZ_CONS_KEY_F6
Definition: rz_cons.h:583
#define RZ_CONS_KEY_F7
Definition: rz_cons.h:584
#define RZ_CONS_KEY_F3
Definition: rz_cons.h:580
#define RZ_CONS_KEY_F2
Definition: rz_cons.h:579
void(* RzConsEvent)(void *)
Definition: rz_cons.h:346
#define RZ_CONS_KEY_F1
Definition: rz_cons.h:578
#define RZ_CONS_KEY_F5
Definition: rz_cons.h:582
#define RZ_CONS_KEY_F4
Definition: rz_cons.h:581
#define RZ_CONS_KEY_F9
Definition: rz_cons.h:586
#define RZ_CONS_KEY_F8
Definition: rz_cons.h:585
RZ_API const char * rz_str_bool(int b)
Definition: str.c:3896
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API bool rz_core_seek_redo(RzCore *core)
Definition: seek.c:316
RZ_API bool rz_core_seek_next(RzCore *core, const char *type, bool save)
Seek to the next type of item from current offset.
Definition: seek.c:203
RZ_API bool rz_core_seek_prev(RzCore *core, const char *type, bool save)
Seek to the previous type of item from current offset.
Definition: seek.c:241
RZ_API bool rz_core_seek_undo(RzCore *core)
Definition: seek.c:301
struct rz_line_t * line
Definition: rz_cons.h:553
RzConsEvent event_resize
Definition: rz_cons.h:522
int mouse_event
Definition: rz_cons.h:524
bool vmode
Definition: rz_core.h:309
RzCons * cons
Definition: rz_core.h:312
bool tmpseek
Definition: rz_core.h:308
RzPanelsRoot * panels_root
Definition: rz_core.h:334
bool is_asmqjmps_letter
Definition: rz_core.h:349
char * contents
Definition: rz_cons.h:1111
RZ_API void rz_core_visual_prompt_input(RzCore *core)
Definition: visual.c:733
RZ_API void rz_core_visual_browse(RzCore *core, const char *input)
Definition: visual.c:2067
RZ_API int rz_core_visual_xrefs(RzCore *core, bool xref_to, bool fcnInsteadOfAddr)
Definition: visual.c:1312
RZ_API void rz_core_visual_toggle_hints(RzCore *core)
Definition: visual.c:109
RZ_API void rz_core_visual_define(RzCore *core, const char *args, int distance)
Definition: vmenus.c:3149
RZ_API void rz_core_visual_analysis(RzCore *core, const char *input)
Definition: vmenus.c:2739
RZ_API int rz_core_visual_trackflags(RzCore *core)
Definition: vmenus.c:1485
RZ_API bool rz_core_visual_hudstuff(RzCore *core)
Definition: vmenus.c:539

References rz_analysis_function_t::addr, rz_analysis_bb_t::addr, agraph_follow_false(), agraph_follow_innodes(), agraph_follow_true(), agraph_next_node(), agraph_prev_node(), agraph_refresh(), agraph_refresh_oneshot(), agraph_set_need_reload_nodes(), agraph_set_zoom(), agraph_toggle_callgraph(), agraph_toggle_mini(), agraph_toggle_speed(), agraph_toggle_tiny(), agraph_update_seek(), rz_core_t::analysis, applyDisMode(), check_function_modified(), cmd, rz_cons_canvas_t::color, rz_core_t::config, rz_core_t::cons, rz_line_t::contents, agraph_refresh_data::core, rz_print_t::cur, rz_print_t::cur_enabled, discroll, disMode, dst, e, eprintf, rz_cons_t::event_data, rz_cons_t::event_resize, agraph_refresh_data::fcn, find_near_of(), agraph_refresh_data::follow_offset, free(), agraph_refresh_data::fs, agraph_refresh_data::g, g, get_anode, get_bbupdate(), goto_asmqjmps(), graph_breakpoint(), graph_continue(), graph_single_step_in(), graph_single_step_over(), graphCursor, graphNodeMove(), h, rz_core_t::is_asmqjmps_letter, rz_core_t::keep_asmqjmps, key, rz_cons_t::line, rz_cons_canvas_t::linemode, rz_cons_t::mouse_event, mousemode, mousemodes, next_mode(), nextword(), NULL, rz_core_t::offset, PAGEKEY_SPEED, rz_core_t::panels_root, prev_mode(), rz_core_t::print, rotateAsmemu(), rotateColor(), rz_agraph_free(), RZ_AGRAPH_MODE_COMMENTS, RZ_AGRAPH_MODE_NORMAL, rz_agraph_new(), rz_analysis_find_most_relevant_block_in(), rz_analysis_get_fcn_in(), rz_config_get(), rz_config_get_i(), rz_config_hold_free(), rz_config_hold_i(), rz_config_hold_new(), rz_config_hold_restore(), rz_config_set(), rz_config_set_i(), rz_config_toggle(), rz_cons_any_key(), rz_cons_arrow_to_hjkl(), rz_cons_break_pop(), rz_cons_break_push(), rz_cons_canvas_free(), rz_cons_canvas_new(), rz_cons_clear00(), rz_cons_fgets(), rz_cons_get_size(), rz_cons_is_breaked(), rz_cons_is_interactive(), RZ_CONS_KEY_F1, RZ_CONS_KEY_F10, RZ_CONS_KEY_F11, RZ_CONS_KEY_F12, RZ_CONS_KEY_F2, RZ_CONS_KEY_F3, RZ_CONS_KEY_F4, RZ_CONS_KEY_F5, RZ_CONS_KEY_F6, RZ_CONS_KEY_F7, RZ_CONS_KEY_F8, RZ_CONS_KEY_F9, rz_cons_less(), rz_cons_newline(), rz_cons_pal_random(), rz_cons_printf(), rz_cons_readchar(), rz_cons_yesno(), rz_core_agraph_print_interactive(), rz_core_agraph_reset(), rz_core_cmd0(), rz_core_hack(), rz_core_reg_set_by_role_or_name(), rz_core_seek(), rz_core_seek_bb_instruction(), rz_core_seek_next(), rz_core_seek_opcode(), rz_core_seek_prev(), rz_core_seek_redo(), rz_core_seek_to_register(), rz_core_seek_undo(), rz_core_theme_nextpal(), rz_core_visual_analysis(), rz_core_visual_browse(), rz_core_visual_define(), rz_core_visual_hudstuff(), rz_core_visual_panels_root(), rz_core_visual_prompt_input(), rz_core_visual_toggle_hints(), rz_core_visual_trackflags(), rz_core_visual_xrefs(), rz_line_readline(), rz_line_set_prompt(), rz_meta_set_string(), RZ_META_TYPE_COMMENT, RZ_NEW0, rz_str_bool(), rz_vector_fini(), seek_to_node(), showcursor(), strdup(), rz_cons_canvas_t::sx, rz_cons_canvas_t::sy, rz_core_t::tmpseek, update_seek(), ut64(), visual_offset(), rz_core_t::vmode, w, ZOOM_DEFAULT, and ZOOM_STEP.

Referenced by __call_visual_graph(), cmd_analysis_graph(), get_graph_string(), rz_core_agraph_print_interactive(), rz_core_agraph_print_tiny(), rz_core_graph_print(), and rz_core_visual_cmd().

◆ sdb_set_enc()

static void sdb_set_enc ( Sdb db,
const char *  key,
const char *  v,
ut32  cas 
)
static

Definition at line 3663 of file agraph.c.

3663  {
3664  char *estr = sdb_encode((const void *)v, -1);
3665  sdb_set(db, key, estr, cas);
3666  free(estr);
3667 }

References free(), key, sdb_encode(), sdb_set(), and v.

Referenced by agraph_sdb_init().

◆ seek_to_node()

static void seek_to_node ( RzANode n,
RzCore core 
)
static

Definition at line 3991 of file agraph.c.

3991  {
3993  char *title = get_title(block ? block->addr : core->offset);
3994 
3995  if (title && strcmp(title, n->title)) {
3996  char *cmd = rz_str_newf("s %s", n->title);
3997  if (cmd) {
3998  if (*cmd) {
3999  rz_core_cmd0(core, cmd);
4000  }
4001  free(cmd);
4002  }
4003  }
4004  free(title);
4005 }

References rz_analysis_bb_t::addr, rz_core_t::analysis, cmd, free(), get_title(), n, rz_core_t::offset, rz_analysis_find_most_relevant_block_in(), rz_core_cmd0(), and rz_str_newf().

Referenced by rz_core_visual_graph().

◆ set_dist_nodes()

static void set_dist_nodes ( const RzAGraph g,
int  l,
int  cur,
int  next 
)
static

Definition at line 885 of file agraph.c.

885  {
886  struct dist_t *d, find_el;
887  const RzGraphNode *vi, *vip;
888  const RzANode *avi, *avip;
889  RzListIter *it;
890 
891  if (!g->dists) {
892  return;
893  }
894  vi = g->layers[l].nodes[cur];
895  vip = g->layers[l].nodes[next];
896  avi = get_anode(vi);
897  avip = get_anode(vip);
898 
899  find_el.from = vi;
900  find_el.to = vip;
901  it = rz_list_find(g->dists, &find_el, (RzListComparator)find_dist);
902  d = it ? (struct dist_t *)rz_list_iter_get_data(it) : RZ_NEW0(struct dist_t);
903 
904  d->from = vi;
905  d->to = vip;
906  d->dist = (avip && avi) ? avip->x - avi->x : 0;
907  if (!it) {
908  rz_list_push(g->dists, d);
909  }
910 }
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
const RzGraphNode * from
Definition: agraph.c:68
const RzGraphNode * to
Definition: agraph.c:69

References d, find_dist(), dist_t::from, g, get_anode, if(), rz_list_find(), rz_list_iter_get_data(), rz_list_push(), RZ_NEW0, dist_t::to, and rz_ascii_node_t::x.

Referenced by original_traverse_l().

◆ set_layer_gap()

static void set_layer_gap ( RzAGraph g)
static

Definition at line 1645 of file agraph.c.

1645  {
1646  int gap = 0;
1647  int i = 0, j = 0;
1648  RzListIter *itn;
1649  RzGraphNode *ga, *gb;
1650  RzANode *a, *b;
1651  const RzList *outnodes;
1652 
1653  g->layers[0].gap = 0;
1654  for (i = 0; i < g->n_layers; i++) {
1655  gap = 0;
1656  if (i + 1 < g->n_layers) {
1657  g->layers[i + 1].gap = gap;
1658  }
1659  for (j = 0; j < g->layers[i].n_nodes; j++) {
1660  ga = g->layers[i].nodes[j];
1661  if (!ga) {
1662  continue;
1663  }
1664  a = (RzANode *)ga->data;
1665  outnodes = ga->out_nodes;
1666 
1667  if (!outnodes || !a) {
1668  continue;
1669  }
1670  graph_foreach_anode (outnodes, itn, gb, b) {
1671  if (g->layout == 0) { // vertical layout
1672  if ((b->x != a->x) || b->layer <= a->layer) {
1673  gap += 1;
1674  if (b->layer <= a->layer) {
1675  g->layers[b->layer].gap += 1;
1676  }
1677  } else if ((!a->is_dummy && b->is_dummy) || (a->is_dummy && !b->is_dummy)) {
1678  gap += 1;
1679  }
1680  } else {
1681  if ((b->y == a->y && b->h != a->h) || b->y != a->y || b->layer <= a->layer) {
1682  gap += 1;
1683  if (b->layer <= a->layer) {
1684  g->layers[b->layer].gap += 1;
1685  }
1686  } else if ((!a->is_dummy && b->is_dummy) || (a->is_dummy && !b->is_dummy)) {
1687  gap += 1;
1688  }
1689  }
1690  }
1691  }
1692  if (i + 1 < g->n_layers) {
1693  g->layers[i + 1].gap += gap;
1694  }
1695  }
1696 }

References a, b, rz_graph_node_t::data, g, graph_foreach_anode, i, if(), and rz_graph_node_t::out_nodes.

Referenced by set_layout().

◆ set_layout()

static void set_layout ( RzAGraph g)
static

Definition at line 1958 of file agraph.c.

1958  {
1959  int i, j, k;
1960 
1961  rz_list_free(g->edges);
1963 
1964  remove_cycles(g);
1965  assign_layers(g);
1967  create_layers(g);
1969 
1970  if (rz_cons_is_breaked()) {
1972  return;
1973  }
1974  /* identify row height */
1975  for (i = 0; i < g->n_layers; i++) {
1976  int rh = 0;
1977  int rw = 0;
1978  for (j = 0; j < g->layers[i].n_nodes; j++) {
1979  const RzANode *n = get_anode(g->layers[i].nodes[j]);
1980  if (n->h > rh) {
1981  rh = n->h;
1982  }
1983  if (n->w > rw) {
1984  rw = n->w;
1985  }
1986  }
1987  g->layers[i].height = rh;
1988  g->layers[i].width = rw;
1989  }
1990 
1991  for (i = 0; i < g->n_layers; i++) {
1992  for (j = 0; j < g->layers[i].n_nodes; j++) {
1993  RzANode *a = (RzANode *)g->layers[i].nodes[j]->data;
1994  if (a->is_dummy) {
1995  if (g->layout == 0) {
1996  a->h = g->layers[i].height;
1997  } else {
1998  a->w = g->layers[i].width;
1999  }
2000  }
2001  a->layer_height = g->layers[i].height;
2002  a->layer_width = g->layers[i].width;
2003  }
2004  }
2005 
2006  /* x-coordinate assignment: algorithm based on:
2007  * A Fast Layout Algorithm for k-Level Graphs
2008  * by C. Buchheim, M. Junger, S. Leipert */
2009  place_dummies(g);
2010  place_original(g);
2011 
2012  /* IDEA: need to put this hack because of the way algorithm is implemented.
2013  * I think backedges should be restored to their original state instead of
2014  * converting them to longedges and adding dummy nodes. */
2015  const RzListIter *it;
2016  const RzGraphEdge *e;
2017  rz_list_foreach (g->back_edges, it, e) {
2018  RzANode *from = e->from ? get_anode(e->from) : NULL;
2019  RzANode *to = e->to ? get_anode(e->to) : NULL;
2022  rz_agraph_add_edge_at(g, from, to, e->nth);
2023  }
2024 
2025  switch (g->layout) {
2026  default:
2027  case 0: // vertical layout
2028  /* horizontal finalize x coordinate */
2029  for (i = 0; i < g->n_layers; i++) {
2030  for (j = 0; j < g->layers[i].n_nodes; j++) {
2031  RzANode *n = get_anode(g->layers[i].nodes[j]);
2032  if (n) {
2033  n->x -= n->w / 2;
2034  if (g->is_tiny) {
2035  n->x /= 8;
2036  }
2037  }
2038  }
2039  }
2040 
2041  set_layer_gap(g);
2042 
2043  /* vertical align */
2044  for (i = 0; i < g->n_layers; i++) {
2045  int tmp_y = 0;
2046  tmp_y = g->layers[0].gap; // TODO: XXX: set properly
2047  for (k = 1; k <= i; k++) {
2048  tmp_y += g->layers[k - 1].height + g->layers[k].gap + 3; // XXX: should be 4?
2049  }
2050  if (g->is_tiny) {
2051  tmp_y = i;
2052  }
2053  for (j = 0; j < g->layers[i].n_nodes; j++) {
2054  RzANode *n = get_anode(g->layers[i].nodes[j]);
2055  if (n) {
2056  n->y = tmp_y;
2057  }
2058  }
2059  }
2060  break;
2061  /* experimental */
2062  case 1: // horizontal layout
2063  /* vertical y coordinate */
2064  for (i = 0; i < g->n_layers; i++) {
2065  for (j = 0; j < g->layers[i].n_nodes; j++) {
2066  RzANode *n = get_anode(g->layers[i].nodes[j]);
2067  n->y = 1;
2068  for (k = 0; k < j; k++) {
2069  RzANode *m = get_anode(g->layers[i].nodes[k]);
2070  n->y -= (m->h + VERTICAL_NODE_SPACING);
2071  }
2072  }
2073  }
2074 
2075  set_layer_gap(g);
2076 
2077  /* horizontal align */
2078  for (i = 0; i < g->n_layers; i++) {
2079  int xval = 1 + g->layers[0].gap + 1;
2080  for (k = 1; k <= i; k++) {
2081  xval += g->layers[k - 1].width + g->layers[k].gap + 3;
2082  }
2083  for (j = 0; j < g->layers[i].n_nodes; j++) {
2084  RzANode *n = get_anode(g->layers[i].nodes[j]);
2085  n->x = xval;
2086  }
2087  }
2088  break;
2089  }
2090 
2091  backedge_info(g);
2092 
2093  /* free all temporary structures used during layout */
2094  for (i = 0; i < g->n_layers; i++) {
2095  free(g->layers[i].nodes);
2096  }
2097 
2098  free(g->layers);
2099  rz_list_free(g->long_edges);
2100  rz_list_free(g->back_edges);
2102 }
static void minimize_crossings(const RzAGraph *g)
Definition: agraph.c:786
static void assign_layers(const RzAGraph *g)
Definition: agraph.c:660
static void agraph_edge_free(AEdge *e)
Definition: agraph.c:1946
static void create_dummy_nodes(RzAGraph *g)
Definition: agraph.c:699
static void remove_cycles(RzAGraph *g)
Definition: agraph.c:627
static void place_dummies(const RzAGraph *g)
Definition: agraph.c:1207
static void place_original(RzAGraph *g)
Definition: agraph.c:1583
static void set_layer_gap(RzAGraph *g)
Definition: agraph.c:1645
static void create_layers(RzAGraph *g)
Definition: agraph.c:743
#define VERTICAL_NODE_SPACING
Definition: agraph.c:33
static void fix_back_edge_dummy_nodes(RzAGraph *g, RzANode *from, RzANode *to)
Definition: agraph.c:1698
static void backedge_info(RzAGraph *g)
Definition: agraph.c:1776
RZ_API void rz_cons_break_end(void)
Definition: cons.c:427

References a, agraph_edge_free(), assign_layers(), backedge_info(), create_dummy_nodes(), create_layers(), e, fix_back_edge_dummy_nodes(), free(), from, g, get_anode, i, if(), k, regress::m, minimize_crossings(), n, NULL, place_dummies(), place_original(), remove_cycles(), rz_agraph_add_edge_at(), rz_agraph_del_edge(), rz_cons_break_end(), rz_cons_break_pop(), rz_cons_is_breaked(), rz_list_free(), rz_list_newf(), set_layer_gap(), to, and VERTICAL_NODE_SPACING.

Referenced by agraph_set_layout().

◆ showcursor()

static void showcursor ( RzCore core,
int  x 
)
static

Definition at line 188 of file agraph.c.

188  {
189  if (!x) {
190  int wheel = rz_config_get_i(core->config, "scr.wheel");
191  if (wheel) {
192  rz_cons_enable_mouse(true);
193  }
194  } else {
195  rz_cons_enable_mouse(false);
196  }
198 }

References rz_core_t::config, rz_config_get_i(), rz_cons_enable_mouse(), rz_cons_show_cursor(), and x.

Referenced by rtr_visual(), and rz_core_visual_graph().

◆ tiny_RzANode_print()

static void tiny_RzANode_print ( const RzAGraph g,
const RzANode n,
int  cur 
)
static

Definition at line 323 of file agraph.c.

323  {
324  G(n->x, n->y);
325  RzCons *cons = rz_cons_singleton();
326  char *circle = cons->use_utf8 ? UTF_CIRCLE : "()";
327  if (cur) {
328  W("##");
329  } else {
330  W(circle);
331  }
332 }
#define UTF_CIRCLE
Definition: rz_cons.h:418
bool use_utf8
Definition: rz_cons.h:559

References G, n, rz_cons_singleton(), rz_cons_t::use_utf8, UTF_CIRCLE, and W.

Referenced by agraph_print_node().

◆ tmplayercmp()

int tmplayercmp ( const void *  a,
const void *  b 
)

Definition at line 2794 of file agraph.c.

2794  {
2795  return ((struct tmplayer *)a)->layer > ((struct tmplayer *)b)->layer;
2796 }

References a, and b.

Referenced by agraph_print_edges().

◆ update_graph_sizes()

static void update_graph_sizes ( RzAGraph g)
static

Definition at line 2588 of file agraph.c.

2588  {
2589  RzListIter *it;
2590  RzGraphNode *gk;
2591  RzANode *ak, *min_gn, *max_gn;
2592  int max_x, max_y;
2593  int delta_x, delta_y;
2594  AEdge *e;
2595 
2596  g->x = g->y = INT_MAX;
2597  max_x = max_y = INT_MIN;
2598  min_gn = max_gn = NULL;
2599 
2600  graph_foreach_anode (rz_graph_get_nodes(g->graph), it, gk, ak) {
2601  const RzList *nd = NULL;
2602  int len;
2603  if (ak->x < g->x) {
2604  g->x = ak->x;
2605  }
2606 
2607  nd = rz_graph_innodes(g->graph, gk);
2608  len = nd ? rz_list_length(nd) + 1 : 0;
2609  if (ak->y - len < g->y) {
2610  g->y = ak->y - len;
2611  min_gn = ak;
2612  }
2613 
2614  if (ak->x + ak->w > max_x) {
2615  max_x = ak->x + ak->w;
2616  }
2617 
2618  nd = NULL;
2619  nd = rz_graph_get_neighbours(g->graph, gk);
2620  len = nd ? rz_list_length(nd) + 2 : 0;
2621  if (ak->y + ak->h + len > max_y) {
2622  max_y = ak->y + ak->h + len;
2623  max_gn = ak;
2624  }
2625  }
2626  /* while calculating the graph size, take into account long edges */
2627  rz_list_foreach (g->edges, it, e) {
2628  RzListIter *kt;
2629  void *vv;
2630  int v;
2631  if (rz_cons_is_breaked()) {
2632  break;
2633  }
2634  rz_list_foreach (e->x, kt, vv) {
2635  v = (int)(size_t)vv;
2636  if (v < g->x) {
2637  g->x = v;
2638  }
2639  if (v + 1 > max_x) {
2640  max_x = v + 1;
2641  }
2642  }
2643  rz_list_foreach (e->y, kt, vv) {
2644  v = (int)(size_t)vv;
2645  if (v < g->y) {
2646  g->y = v;
2647  }
2648  if (v + 1 > max_y) {
2649  max_y = v + 1;
2650  }
2651  }
2652  }
2654 
2655  if (min_gn) {
2656  const RzList *neigh = rz_graph_innodes(g->graph, min_gn->gnode);
2657  if (rz_list_length(neigh) > 0) {
2658  g->y--;
2659  max_y++;
2660  }
2661  if (max_gn) {
2662  const RzList *neigh = rz_graph_get_neighbours(g->graph, min_gn->gnode);
2663  if (rz_list_length(neigh) > 0) {
2664  max_y++;
2665  }
2666  }
2667  }
2668 
2669  if (g->x != INT_MAX && g->y != INT_MAX) {
2670  g->w = max_x - g->x;
2671  if (g->title) {
2672  size_t len = strlen(g->title);
2673  if (len > INT_MAX) {
2674  g->w = INT_MAX;
2675  }
2676  if ((int)len > g->w) {
2677  g->w = len;
2678  }
2679  }
2680  g->h = max_y - g->y;
2681  } else {
2682  g->x = g->y = 0;
2683  g->w = g->h = 0;
2684  }
2685 
2686  sdb_num_set(g->db, "agraph.w", g->w, 0);
2687  sdb_num_set(g->db, "agraph.h", g->h, 0);
2688  /* delta_x, delta_y are needed to make every other x,y coordinates
2689  * unsigned, so that we can use sdb_num_ API */
2690  delta_x = g->x < 0 ? -g->x : 0;
2691  delta_y = g->y < 0 ? -g->y : 0;
2692  sdb_num_set(g->db, "agraph.delta_x", delta_x, 0);
2693  sdb_num_set(g->db, "agraph.delta_y", delta_y, 0);
2694 }

References e, g, rz_ascii_node_t::gnode, graph_foreach_anode, rz_ascii_node_t::h, int, INT_MAX, len, NULL, rz_cons_break_pop(), rz_cons_is_breaked(), rz_graph_get_neighbours(), rz_graph_get_nodes(), rz_graph_innodes(), rz_list_length(), sdb_num_set(), v, rz_ascii_node_t::w, x, rz_ascii_node_t::x, and rz_ascii_node_t::y.

Referenced by agraph_print(), and agraph_set_layout().

◆ update_node_dimension()

static void update_node_dimension ( const RzGraph g,
int  is_mini,
int  zoom,
int  edgemode,
bool  callgraph,
int  layout 
)
static

Definition at line 212 of file agraph.c.

212  {
213  const RzList *nodes = rz_graph_get_nodes(g);
214  RzGraphNode *gn;
215  RzListIter *it;
216  RzANode *n;
217  graph_foreach_anode (nodes, it, gn, n) {
218  if (is_mini) {
219  n->h = 1;
221  } else if (n->is_mini) {
222  n->h = 1;
223  n->w = MININODE_MIN_WIDTH;
224  } else {
225  n->w = rz_str_bounds(n->body, (int *)&n->h);
226  ut32 len = strlen(n->title) + MARGIN_TEXT_X;
227  if (len > INT_MAX) {
228  len = INT_MAX;
229  }
230  if (len > n->w) {
231  n->w = len;
232  }
233  // n->w = n->w; //RZ_MIN (n->w, (int)len);
234  n->w += BORDER_WIDTH;
235  n->h += BORDER_HEIGHT;
236  /* scale node by zoom */
237  n->w = RZ_MAX(MIN_NODE_WIDTH, (n->w * zoom) / 100);
238  n->h = RZ_MAX(MIN_NODE_HEIGHT, (n->h * zoom) / 100);
239 
240  if (edgemode == 2 && !callgraph) {
241  if (!layout) {
242  n->w = RZ_MAX(n->w, (rz_list_length(n->gnode->out_nodes) * 2 + 1) + RZ_EDGES_X_INC * 2);
243  n->w = RZ_MAX(n->w, (rz_list_length(n->gnode->in_nodes) * 2 + 1) + RZ_EDGES_X_INC * 2);
244  } else {
245  n->h = RZ_MAX(n->h, (rz_list_length(n->gnode->out_nodes) + 1) + RZ_EDGES_X_INC);
246  n->h = RZ_MAX(n->h, (rz_list_length(n->gnode->in_nodes) + 1) + RZ_EDGES_X_INC);
247  }
248  }
249  }
250  }
251 }
#define MIN_NODE_HEIGHT
Definition: agraph.c:35
#define MINIGRAPH_NODE_MIN_WIDTH
Definition: agraph.c:41
#define MININODE_MIN_WIDTH
Definition: agraph.c:44
#define MIN_NODE_WIDTH
Definition: agraph.c:34
RZ_API int rz_str_bounds(const char *str, int *h)
Definition: str.c:3124

References BORDER_HEIGHT, BORDER_WIDTH, g, graph_foreach_anode, INT_MAX, is_mini(), len, MARGIN_TEXT_X, MIN_NODE_HEIGHT, MIN_NODE_WIDTH, MINIGRAPH_NODE_MIN_WIDTH, MININODE_MIN_WIDTH, n, RZ_EDGES_X_INC, rz_graph_get_nodes(), rz_list_length(), RZ_MAX, rz_str_bounds(), and zoom.

Referenced by check_changes().

◆ update_seek()

static void update_seek ( RzConsCanvas can,
RzANode n,
int  force 
)
static

Definition at line 2511 of file agraph.c.

2511  {
2512  if (!n) {
2513  return;
2514  }
2515  int x = n->x + can->sx;
2516  int y = n->y + can->sy;
2517  int w = can->w;
2518  int h = can->h;
2519 
2520  const bool doscroll = force || y < 0 || y + 5 > h || x + 5 > w || x + n->w + 5 < 0;
2521  if (doscroll) {
2522  if (n->w > w) { // too big for centering
2523  can->sx = -n->x;
2524  } else {
2525  can->sx = -n->x - n->w / 2 + w / 2;
2526  }
2527  if (n->h > h) { // too big for centering
2528  can->sy = -n->y;
2529  } else {
2530  can->sy = -n->y - n->h / 8 + h / 4;
2531  }
2532  }
2533 }

References rz_cons_canvas_t::h, h, n, rz_cons_canvas_t::sx, rz_cons_canvas_t::sy, w, rz_cons_canvas_t::w, and x.

Referenced by check_changes(), rz_core_agraph_print_interactive(), rz_core_graph_print(), and rz_core_visual_graph().

◆ user_edge_cb()

static bool user_edge_cb ( struct g_cb user,
RZ_UNUSED const void *  k,
const void *  v 
)
static

Definition at line 3811 of file agraph.c.

3811  {
3812  RAEdgeCallback cb = user->edge_cb;
3813  RzAGraph *g = user->graph;
3814  void *user_data = user->data;
3815  RzANode *an, *n = (RzANode *)v;
3816  if (!n) {
3817  return false;
3818  }
3819  const RzList *neigh = rz_graph_get_neighbours(g->graph, n->gnode);
3820  RzListIter *it;
3821  RzGraphNode *gn;
3822 
3823  graph_foreach_anode (neigh, it, gn, an) {
3824  cb(n, an, user_data);
3825  }
3826  return true;
3827 }
void(* RAEdgeCallback)(RzANode *from, RzANode *to, void *user)
Definition: rz_agraph.h:44
void * data
Definition: agraph.c:77
RAEdgeCallback edge_cb
Definition: agraph.c:76

References cb, g_cb::data, g_cb::edge_cb, g, g_cb::graph, graph_foreach_anode, n, rz_graph_get_neighbours(), and v.

Referenced by rz_agraph_foreach_edge().

◆ user_node_cb()

static bool user_node_cb ( struct g_cb user,
RZ_UNUSED const void *  k,
const void *  v 
)
static

Definition at line 3801 of file agraph.c.

3801  {
3802  RzANodeCallback cb = user->node_cb;
3803  void *user_data = user->data;
3804  RzANode *n = (RzANode *)v;
3805  if (n) {
3806  cb(n, user_data);
3807  }
3808  return true;
3809 }

References cb, g_cb::data, n, g_cb::node_cb, and v.

Referenced by rz_agraph_foreach().

◆ view_cyclic_edge()

static void view_cyclic_edge ( const RzGraphEdge e,
const RzGraphVisitor vis 
)
static

Definition at line 594 of file agraph.c.

594  {
595  const RzAGraph *g = (RzAGraph *)vis->data;
596  RzGraphEdge *new_e = RZ_NEW0(RzGraphEdge);
597  if (!new_e) {
598  return;
599  }
600  new_e->from = e->from;
601  new_e->to = e->to;
602  new_e->nth = e->nth;
603  rz_list_append(g->back_edges, new_e);
604 }

References rz_graph_visitor_t::data, e, g, rz_list_append(), and RZ_NEW0.

Referenced by remove_cycles().

◆ view_dummy()

static void view_dummy ( const RzGraphEdge e,
const RzGraphVisitor vis 
)
static

Definition at line 606 of file agraph.c.

606  {
607  const RzANode *a = get_anode(e->from);
608  const RzANode *b = get_anode(e->to);
609  RzList *long_edges = (RzList *)vis->data;
610  if (!a || !b) {
611  return;
612  }
613  if (RZ_ABS(a->layer - b->layer) > 1) {
614  RzGraphEdge *new_e = RZ_NEW0(RzGraphEdge);
615  if (!new_e) {
616  return;
617  }
618  new_e->from = e->from;
619  new_e->to = e->to;
620  new_e->nth = e->nth;
621  rz_list_append(long_edges, new_e);
622  }
623 }
RzGraphNode * to
Definition: rz_graph.h:21
RzGraphNode * from
Definition: rz_graph.h:20

References a, b, rz_graph_visitor_t::data, e, rz_graph_edge_t::from, get_anode, if(), rz_graph_edge_t::nth, RZ_ABS, rz_list_append(), RZ_NEW0, and rz_graph_edge_t::to.

Referenced by create_dummy_nodes().

◆ visual_offset()

static void visual_offset ( RzAGraph g,
RzCore core 
)
static

Definition at line 3934 of file agraph.c.

3934  {
3935  char buf[256];
3936  int rows;
3937  rz_cons_get_size(&rows);
3938  rz_cons_gotoxy(0, rows);
3939  rz_cons_flush();
3942  rz_line_set_prompt("[offset]> ");
3943  strcpy(buf, "s ");
3944  if (rz_cons_fgets(buf + 2, sizeof(buf) - 2, 0, NULL) > 0) {
3945  if (buf[2] == '.') {
3946  buf[1] = '.';
3947  }
3948  rz_core_cmd0(core, buf);
3950  }
3952 }
RZ_API int rz_line_hist_cmd_down(RzLine *line)
Definition: dietline.c:346
RZ_API int rz_line_hist_cmd_up(RzLine *line)
Definition: dietline.c:316
RZ_API int rz_line_set_hist_callback(RzLine *line, RzLineHistoryUpCb up, RzLineHistoryDownCb down)
Definition: dietline.c:292
@ RZ_LINE_PROMPT_DEFAULT
Definition: rz_cons.h:1037
@ RZ_LINE_PROMPT_OFFSET
Definition: rz_cons.h:1038
RzLinePromptType prompt_type
Definition: rz_cons.h:1116
RZ_API int rz_line_hist_offset_up(RzLine *line)
Definition: visual.c:1222
RZ_API int rz_line_hist_offset_down(RzLine *line)
Definition: visual.c:1235

References rz_core_t::cons, rz_cons_t::line, NULL, rz_line_t::prompt_type, rz_cons_fgets(), rz_cons_flush(), rz_cons_get_size(), rz_cons_gotoxy(), rz_core_cmd0(), rz_line_hist_cmd_down(), rz_line_hist_cmd_up(), rz_line_hist_offset_down(), rz_line_hist_offset_up(), RZ_LINE_PROMPT_DEFAULT, RZ_LINE_PROMPT_OFFSET, rz_line_set_hist_callback(), and rz_line_set_prompt().

Referenced by rz_core_visual_graph().

Variable Documentation

◆ discroll

int discroll = 0
static

Definition at line 15 of file agraph.c.

Referenced by graphNodeMove(), mini_RzANode_print(), and rz_core_visual_graph().

◆ disMode

int disMode = 0
static

Definition at line 14 of file agraph.c.

Referenced by applyDisMode(), and rz_core_visual_graph().

◆ graphCursor

bool graphCursor = false
static

Definition at line 16 of file agraph.c.

Referenced by agraph_update_title(), and rz_core_visual_graph().

◆ mousemode

int mousemode = 0
static

Definition at line 13 of file agraph.c.

Referenced by rz_core_visual_graph().

◆ mousemodes

const char* mousemodes[]
static
Initial value:
= {
"canvas-y",
"canvas-x",
"node-y",
"node-x",
}

Definition at line 17 of file agraph.c.

Referenced by rz_core_visual_graph().

◆ nodes_opt

HtPPOptions nodes_opt
static
Initial value:
= {
.cmp = (HtPPListComparator)strcmp,
.hashfn = (HtPPHashFunction)sdb_hash,
.dupkey = NULL,
.dupvalue = NULL,
.calcsizeK = (HtPPCalcSizeK)strlen,
.calcsizeV = NULL,
.elem_size = sizeof(HtPPKv),
}
static void free_nodes_kv(HtPPKv *kv)
Definition: agraph.c:3601
static void freefn(HtName_(Ht) *ht, HT_(Kv) *kv)
Definition: ht_inc.c:46
static ut32 hashfn(HtName_(Ht) *ht, const KEY_TYPE k)
Definition: ht_inc.c:22
RZ_API ut32 sdb_hash(const char *key)
Definition: util.c:22

Definition at line 3608 of file agraph.c.

Referenced by agraph_init(), and rz_agraph_reset().