static bool cmd_anal_refs(RCore *core, const char *input) {
	ut64 addr = core->offset;
	switch (input[0]) {
	case '-': { // "ax-"
		RList *list;
		RListIter *iter;
		RAnalRef *ref;
		char *cp_inp = strdup (input + 1);
		char *ptr = r_str_trim_head (cp_inp);
		if (!strcmp (ptr, "*")) { // "ax-*"
			r_anal_xrefs_init (core->anal);
		} else {
			int n = r_str_word_set0 (ptr);
			ut64 from = UT64_MAX, to = UT64_MAX;
			switch (n) {
			case 2:
				from = r_num_math (core->num, r_str_word_get0 (ptr, 1));
				//fall through
			case 1: // get addr
				to = r_num_math (core->num, r_str_word_get0 (ptr, 0));
				break;
			default:
				to = core->offset;
				break;
			}
			list = r_anal_xrefs_get (core->anal, to);
			if (list) {
				r_list_foreach (list, iter, ref) {
					if (from != UT64_MAX && from == ref->addr) {
						r_anal_xref_del (core->anal, ref->addr, ref->at);
					}
					if (from == UT64_MAX) {
						r_anal_xref_del (core->anal, ref->addr, ref->at);
					}
				}
			}
			r_list_free (list);
		}
		free (cp_inp);
	} break;
	case 'g': // "axg"
		{
			Sdb *db = sdb_new0 ();
			if (input[1] == '*') {
				anal_axg (core, input + 2, 0, db, R_CORE_ANAL_GRAPHBODY); // r2 commands
			} else if (input[1] == 'j') {
				anal_axg (core, input + 2, 0, db, R_CORE_ANAL_JSON);
			} else {
				anal_axg (core, input[1] ? input + 2 : NULL, 0, db, 0);
			}
			sdb_free (db);
		}
		break;
	case '\0': // "ax"
	case 'j': // "axj"
	case 'q': // "axq"
	case '*': // "ax*"
		r_anal_xrefs_list (core->anal, input[0]);
		break;
	case 't': { // "axt"
		RList *list = NULL;
		RAnalFunction *fcn;
		RAnalRef *ref;
		RListIter *iter;
		char *space = strchr (input, ' ');
		char *tmp = NULL;
		char *name = space ? strdup (space + 1): NULL;

		if (name && (tmp = strchr (name, ' '))) {
			char *varname = tmp + 1;
			*tmp = '\0';
			RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, name);
			if (fcn) {
				RAnalVar *var = r_anal_var_get_byname (core->anal, fcn->addr, varname);
				if (var) {
					const char *rvar = var_ref_list (fcn->addr, var->delta, 'R');
					const char *wvar = var_ref_list (fcn->addr, var->delta, 'W');
					char *res = sdb_get (core->anal->sdb_fcns, rvar, 0);
					char *res1 = sdb_get (core->anal->sdb_fcns, wvar, 0);
					const char *ref;
					RListIter *iter;
					RList *list = (res && *res)? r_str_split_list (res, ","): NULL;
					RList *list1 = (res1 && *res1)? r_str_split_list (res1, ","): NULL;
					r_list_join (list , list1);
					r_list_foreach (list, iter, ref) {
						ut64 addr = r_num_math (NULL, ref);
						char *op = get_buf_asm (core, core->offset, addr, fcn, true);
						r_cons_printf ("%s 0x%"PFMT64x" [DATA] %s\n", fcn?  fcn->name : "(nofunc)", addr, op);
						free (op);

					}
					free (res);
					free (res1);
					free (name);
					r_anal_var_free (var);
					r_list_free (list);
					r_list_free (list1);
					break;
				}
			}
		}
		if (space) {
			addr = r_num_math (core->num, space + 1);
		} else {
			addr = core->offset;
		}
		list = r_anal_xrefs_get (core->anal, addr);
		if (list) {
			if (input[1] == 'q') { // "axtq"
				r_list_foreach (list, iter, ref) {
					r_cons_printf ("0x%" PFMT64x "\n", ref->addr);
				}
			} else if (input[1] == 'j') { // "axtj"
				r_cons_printf ("[");
				r_list_foreach (list, iter, ref) {
					fcn = r_anal_get_fcn_in (core->anal, ref->addr, 0);
					char *str = get_buf_asm (core, addr, ref->addr, fcn, false);
					r_cons_printf ("{\"from\":%" PFMT64u ",\"type\":\"%s\",\"opcode\":\"%s\"",
						ref->addr, r_anal_xrefs_type_tostring (ref->type), str);
					if (fcn) {
						r_cons_printf (",\"fcn_addr\":%"PFMT64u",\"fcn_name\":\"%s\"", fcn->addr, fcn->name);
					}
					RFlagItem *fi = r_flag_get_at (core->flags, fcn? fcn->addr: ref->addr, true);
					if (fi) {
						if (fcn && strcmp (fcn->name, fi->name)) {
							r_cons_printf (",\"flag\":\"%s\"", fi->name);
						}
						if (fi->realname && strcmp (fi->name, fi->realname)) {
							char *escaped = r_str_escape (fi->realname);
							if (escaped) {
								r_cons_printf (",\"realname\":\"%s\"", escaped);
								free (escaped);
							}
						}
					}
					r_cons_printf ("}%s", iter->n? ",": "");
					free (str);
				}
				r_cons_printf ("]");
				r_cons_newline ();
			} else if (input[1] == 'g') { // axtg
				r_list_foreach (list, iter, ref) {
					char *str = r_core_cmd_strf (core, "fd 0x%"PFMT64x, ref->addr);
					if (!str) {
						str = strdup ("?\n");
					}
					r_str_trim_tail (str);
					r_cons_printf ("agn 0x%" PFMT64x " \"%s\"\n", ref->addr, str);
					free (str);
				}
				if (input[2] != '*') {
					RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
					r_cons_printf ("agn 0x%" PFMT64x " \"%s\"\n", addr, fcn?fcn->name: "$$");
				}
				r_list_foreach (list, iter, ref) {
					r_cons_printf ("age 0x%" PFMT64x " 0x%"PFMT64x"\n", ref->addr, addr);
				}
			} else if (input[1] == '*') { // axt*
				// TODO: implement multi-line comments
				r_list_foreach (list, iter, ref)
					r_cons_printf ("CCa 0x%" PFMT64x " \"XREF type %d at 0x%" PFMT64x"%s\n",
						ref->addr, ref->type, addr, iter->n? ",": "");
			} else { // axt
				RAnalFunction *fcn;
				char *comment;
				r_list_foreach (list, iter, ref) {
					fcn = r_anal_get_fcn_in (core->anal, ref->addr, 0);
					char *buf_asm = get_buf_asm (core, addr, ref->addr, fcn, true);
					comment = r_meta_get_string (core->anal, R_META_TYPE_COMMENT, ref->addr);
					char *buf_fcn = comment
						? r_str_newf ("%s; %s", fcn ?  fcn->name : "(nofunc)", strtok (comment, "\n"))
						: r_str_newf ("%s", fcn ? fcn->name : "(nofunc)");
					r_cons_printf ("%s 0x%" PFMT64x " [%s] %s\n",
						buf_fcn, ref->addr, r_anal_xrefs_type_tostring (ref->type), buf_asm);
					free (buf_asm);
					free (buf_fcn);
				}
			}
		} else {
			if (input[1] == 'j') { // "axtj"
				r_cons_print ("[]\n");
			}
		}
		r_list_free (list);
	} break;
	case 'f':
		if (input[1] == 'f') {
			RAnalFunction * fcn = r_anal_get_fcn_in (core->anal, addr, 0);
			RListIter *iter;
			RAnalRef *refi;
			RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
			r_list_foreach (refs, iter, refi) {
				RFlagItem *f = r_flag_get_at (core->flags, refi->addr, true);
				const char *name = f ? f->name: "";
				r_cons_printf ("%c 0x%08"PFMT64x" 0x%08"PFMT64x" %s\n",
					refi->type == R_ANAL_REF_TYPE_CALL?'C':'J',
					refi->at, refi->addr, name);
			}
		} else { // "axf"
			ut8 buf[12];
			RAsmOp asmop;
			char *buf_asm = NULL;
			RList *list, *list_ = NULL;
			RAnalRef *ref;
			RListIter *iter;
			char *space = strchr (input, ' ');
			RAnalFunction * fcn = r_anal_get_fcn_in (core->anal, addr, 0);

			if (space) {
				addr = r_num_math (core->num, space + 1);
			} else {
				addr = core->offset;
			}
			if (input[1] == '.') { // "axf."
				list = list_ = r_anal_xrefs_get_from (core->anal, addr);
				if (!list) {
					list = r_anal_fcn_get_refs (core->anal, fcn);
				}
			} else {
				list = r_anal_refs_get (core->anal, addr);
			}

			if (list) {
				if (input[1] == 'q') { // "axfq"
					r_list_foreach (list, iter, ref) {
						r_cons_printf ("0x%" PFMT64x "\n", ref->at);
					}
				} else if (input[1] == 'j') { // "axfj"
					r_cons_print ("[");
					r_list_foreach (list, iter, ref) {
						r_io_read_at (core->io, ref->at, buf, 12);
						r_asm_set_pc (core->assembler, ref->at);
						r_asm_disassemble (core->assembler, &asmop, buf, 12);
						r_cons_printf ("{\"from\":%" PFMT64u ",\"to\":%" PFMT64u ",\"type\":\"%s\",\"opcode\":\"%s\"}%s",
								ref->at, ref->addr, r_anal_xrefs_type_tostring (ref->type), r_asm_op_get_asm (&asmop), iter->n? ",": "");
					}
					r_cons_print ("]\n");
				} else if (input[1] == '*') { // "axf*"
					// TODO: implement multi-line comments
					r_list_foreach (list, iter, ref) {
						r_cons_printf ("CCa 0x%" PFMT64x " \"XREF from 0x%" PFMT64x "\n",
								ref->at, ref->type, r_asm_op_get_asm (&asmop), iter->n? ",": "");
					}
				} else { // "axf"
					char str[512];
					int has_color = core->print->flags & R_PRINT_FLAGS_COLOR;
					r_list_foreach (list, iter, ref) {
						r_io_read_at (core->io, ref->at, buf, 12);
						r_asm_set_pc (core->assembler, ref->at);
						r_asm_disassemble (core->assembler, &asmop, buf, 12);
						r_parse_filter (core->parser, ref->at, core->flags, r_asm_op_get_asm (&asmop),
								str, sizeof (str), core->print->big_endian);
						if (has_color) {
							buf_asm = r_print_colorize_opcode (core->print, str,
									core->cons->pal.reg, core->cons->pal.num, false, fcn ? fcn->addr : 0);
						} else {
							buf_asm = r_str_new (str);
						}
						r_cons_printf ("%c 0x%" PFMT64x " %s",
								ref->type, ref->at, buf_asm);

						if (ref->type == R_ANAL_REF_TYPE_CALL) {
							RAnalOp aop;
							r_anal_op (core->anal, &aop, ref->at, buf, 12, R_ANAL_OP_MASK_BASIC);
							if (aop.type == R_ANAL_OP_TYPE_UCALL) {
								cmd_anal_ucall_ref (core, ref->addr);
							}
						}
						r_cons_newline ();
						free (buf_asm);
					}
				}
			} else {
				if (input[1] == 'j') { // "axfj"
					r_cons_print ("[]\n");
				}
			}
			r_list_free (list);
		}
		break;
	case 'F': // "axF"
		find_refs (core, input + 1);
		break;
	case 'C': // "axC"
	case 'c': // "axc"
	case 'd': // "axd"
	case 's': // "axs"
	case ' ': // "ax "
		{
		char *ptr = strdup (r_str_trim_head ((char *)input + 1));
		int n = r_str_word_set0 (ptr);
		ut64 at = core->offset;
		ut64 addr = UT64_MAX;
		RAnalRefType reftype = r_anal_xrefs_type (input[0]);
		switch (n) {
		case 2: // get at
			at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
		/* fall through */
		case 1: // get addr
			addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
			break;
		default:
			free (ptr);
			return false;
		}
		r_anal_xrefs_set (core->anal, at, addr, reftype);
		free (ptr);
		}
	   	break;
	default:
	case '?':
		r_core_cmd_help (core, help_msg_ax);
		break;
	}

	return true;
}