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, "*")) {
			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_ref_del (core->anal, ref->addr, ref->at);
					}
					if (from == UT64_MAX) {
						r_anal_ref_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] == '\0') {
				anal_axg (core, input[1] ? input + 2 : NULL, 0, db, 0);
			} else if(input[1] == 'j') {
				anal_axg (core, input[1] ? input + 2 : NULL, 0, db, R_CORE_ANAL_JSON);
			}
			sdb_free (db);
		}
		break;
	case 'k': // "axk"
		if (input[1] == '?') {
			eprintf ("Usage: axk [query]\n");
		} else if (input[1] == ' ') {
			sdb_query (core->anal->sdb_xrefs, input + 2);
		} else {
			r_core_anal_ref_list (core, 'k');
		}
		break;
	case '\0': // "ax"
	case 'j': // "axj"
	case 'q': // "axq"
	case '*': // "ax*"
		r_core_anal_ref_list (core, input[0]);
		break;
	case 't': { // "axt"
		const int size = 12;
		RList *list;
		RAnalFunction *fcn;
		RAnalRef *ref;
		RListIter *iter;
		ut8 buf[12];
		RAsmOp asmop;
		char *buf_asm = NULL;
		char *space = strchr (input, ' ');

		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"
				bool asm_varsub = r_config_get_i (core->config, "asm.varsub");
				core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
				core->parser->localvar_only = r_config_get_i (core->config, "asm.varsub_only");
				r_cons_printf ("[");
				r_list_foreach (list, iter, ref) {
					r_core_read_at (core, ref->addr, buf, size);
					r_asm_set_pc (core->assembler, ref->addr);
					r_asm_disassemble (core->assembler, &asmop, buf, size);
					char str[512];
					fcn = r_anal_get_fcn_in (core->anal, ref->addr, 0);
					if (asm_varsub) {
						r_parse_varsub (core->parser, fcn, ref->addr, asmop.size,
								asmop.buf_asm, asmop.buf_asm, sizeof (asmop.buf_asm));
					}
					r_parse_filter (core->parser, core->flags,
							asmop.buf_asm, str, sizeof (str), core->print->big_endian);

					r_cons_printf ("{\"from\":%" PFMT64u ",\"type\":\"%s\",\"opcode\":\"%s\"", ref->addr, r_anal_ref_to_string (ref->type), str);
					if (fcn) {
						r_cons_printf (",\"fcn_addr\":%"PFMT64d",\"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)) {
							r_cons_printf (",\"realname\":\"%s\"", fi->realname);
						}
					}
					r_cons_printf ("}%s", iter->n? ",": "");
				}
				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
				int has_color = core->print->flags & R_PRINT_FLAGS_COLOR;
				char str[512];
				RAnalFunction *fcn;
				char *comment;
				bool asm_varsub = r_config_get_i (core->config, "asm.varsub");
				core->parser->relsub = r_config_get_i (core->config, "asm.relsub");
				core->parser->localvar_only = r_config_get_i (core->config, "asm.varsub_only");
				if (core->parser->relsub) {
					core->parser->relsub_addr = addr;
				}
				r_list_foreach (list, iter, ref) {
					r_core_read_at (core, ref->addr, buf, size);
					r_asm_set_pc (core->assembler, ref->addr);
					r_asm_disassemble (core->assembler, &asmop, buf, size);

					fcn = r_anal_get_fcn_in (core->anal, ref->addr, 0);
					if (asm_varsub) {
						r_parse_varsub (core->parser, fcn, ref->addr, asmop.size,
								asmop.buf_asm, asmop.buf_asm, sizeof (asmop.buf_asm));
					}
					r_parse_filter (core->parser, core->flags,
							asmop.buf_asm, 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);
					} else {
						buf_asm = r_str_new (str);
					}
					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_ref_to_string (ref->type), buf_asm);
					free (buf_asm);
					free (buf_fcn);
				}
			}
			r_list_free (list);
		} else {
			if (input[1] == 'j') { // "axtj"
				r_cons_print ("[]\n");
			}
		}
	} break;
	case 'f': { // "axf"
		ut8 buf[12];
		RAsmOp asmop;
		char *buf_asm = NULL;
		RList *list, *list_ = NULL;
		RAnalRef *ref;
		RListIter *iter;
		char *space = strchr (input, ' ');

		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) {
				RAnalFunction * fcn = r_anal_get_fcn_in (core->anal, addr, 0);
				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_core_read_at (core, ref->at, buf, 12);
					r_asm_set_pc (core->assembler, ref->at);
					r_asm_disassemble (core->assembler, &asmop, buf, 12);
					r_cons_printf ("{\"from\":%" PFMT64d ",\"to\":%" PFMT64d ",\"type\":\"%s\",\"opcode\":\"%s\"}%s",
						ref->at, ref->addr, r_anal_ref_to_string (ref->type), asmop.buf_asm, 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, asmop.buf_asm, iter->n? ",": "");
				}
			} else { // axf
				char str[512];
				int has_color = core->print->flags & R_PRINT_FLAGS_COLOR;
				r_list_foreach (list, iter, ref) {
					r_core_read_at (core, 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, core->flags,
							asmop.buf_asm, 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);
					} 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_ALL);
						if (aop.type == R_ANAL_OP_TYPE_UCALL) {
							cmd_anal_ucall_ref (core, ref->addr);
						}
					}
					r_cons_newline ();
					free (buf_asm);
				}
			}
			r_list_free (list_);
			r_list_free (list);
		} else {
			if (input[1] == 'j') { // axfj
				r_cons_print ("[]\n");
			}
		}
	} break;
	case 'F':
		find_refs (core, input + 1);
		break;
	case 'C': // "axC"
	case 'c': // "axc"
	case 'd': // "axd"
	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;
		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, input[0], at, addr);
		free (ptr);
		}
	   	break;
	default:
	case '?':
		r_core_cmd_help (core, help_msg_ax);
		break;
	}

	return true;
}