static int var_cmd(RCore *core, const char *str) {
	char *p, *ostr;
	int delta, type = *str, res = true;
	RAnalVar *v1;
	RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, -1);
	ostr = p = NULL;
	if (!str[0]) {
		// "afv"
		if (fcn) {
			r_core_cmd0 (core, "afvs");
			r_core_cmd0 (core, "afvb");
			r_core_cmd0 (core, "afvr");
			return true;
		}
		eprintf ("Cannot find function\n");
		return false;
	}
	if (str[0] == 'j') {
		// "afvj"
		if (fcn) {
			r_cons_printf ("{\"sp\":");
			r_core_cmd0 (core, "afvsj");
			r_cons_printf (",\"bp\":");
			r_core_cmd0 (core, "afvbj");
			r_cons_printf (",\"reg\":");
			r_core_cmd0 (core, "afvrj");
			r_cons_printf ("}\n");
			return true;
		}
		eprintf ("Cannot find function\n");
		return false;
	}
	if (!str[0] || str[1] == '?'|| str[0] == '?') {
		var_help (core, *str);
		return res;
	}
	if (!fcn) {
		eprintf ("Cannot find function in 0x%08"PFMT64x"\n", core->offset);
		return false;
	}
	ostr = p = strdup (str);
	/* Variable access CFvs = set fun var */
	switch (str[0]) {
	case '-':
		// "afv"
		if (fcn) {
			r_core_cmdf (core, "afvs-%s", str + 1);
			r_core_cmdf (core, "afvb-%s", str + 1);
			r_core_cmdf (core, "afvr-%s", str + 1);
			return true;
		}
		eprintf ("Cannot find function\n");
		return false;
	case 'R': // "afvR"
	case 'W': // "afvW"
	case '*': // "afv*"
		list_vars (core, fcn, str[0], str + 1);
		break;
	case 'a': // "afva"
		r_anal_var_delete_all (core->anal, fcn->addr, R_ANAL_VAR_KIND_REG);
		r_anal_var_delete_all (core->anal, fcn->addr, R_ANAL_VAR_KIND_BPV);
		r_anal_var_delete_all (core->anal, fcn->addr, R_ANAL_VAR_KIND_SPV);
		fcn_callconv (core, fcn);
		free (p);
		return true;
	case 'n':
		if (str[1]) { // "afvn"
			char *old_name = r_str_trim_head (strchr (ostr, ' '));
			if (!old_name) {
				free (ostr);
				return false;
			}
			char *new_name = strchr (old_name, ' ');
			if (!new_name) {
				free (ostr);
				return false;
			}
			*new_name++ = 0;
			r_str_trim (new_name);
			v1 = r_anal_var_get_byname (core->anal, fcn, old_name);
			if (v1) {
				r_anal_var_rename (core->anal, fcn->addr, R_ANAL_VAR_SCOPE_LOCAL,
						v1->kind, old_name, new_name);
				r_anal_var_free (v1);
			} else {
				eprintf ("Cant find var by name\n");
			}
			free (ostr);
		} else {
			RListIter *iter;
			RAnalVar *v;
			RList *list = r_anal_var_list (core->anal, fcn, 0);
			r_list_foreach (list, iter, v) {
				r_cons_printf ("%s\n", v->name);
			}
		}
		return true;
	case 'd': // "afvd"
		if (str[1]) {
			p = r_str_trim (strchr (ostr, ' '));
			if (!p) {
				free (ostr);
				return false;
			}
			v1 = r_anal_var_get_byname (core->anal, fcn, p);
			if (!v1) {
				free (ostr);
				return false;
			}
			r_anal_var_display (core->anal, v1->delta, v1->kind, v1->type);
			r_anal_var_free (v1);
			free (ostr);
		} else {
			RListIter *iter;
			RAnalVar *p;
			RList *list = r_anal_var_list (core->anal, fcn, 0);
			r_list_foreach (list, iter, p) {
				char *a = r_core_cmd_strf (core, ".afvd %s", p->name);
				if ((a && !*a) || !a) {
					free (a);
					a = strdup ("\n");
				}
				r_cons_printf ("var %s = %s", p->name, a);
				free (a);
			}
			r_list_free (list);
			// args
			list = r_anal_var_list (core->anal, fcn, 1);
			r_list_foreach (list, iter, p) {
				char *a = r_core_cmd_strf (core, ".afvd %s", p->name);
				if ((a && !*a) || !a) {
					free (a);
					a = strdup ("\n");
				}
				r_cons_printf ("arg %s = %s", p->name, a);
				free (a);
			}
			r_list_free (list);
		}
		return true;
	case 't':{ // "afvt"
		p = strchr (ostr, ' ');
		if (!p++) {
			free (ostr);
			return false;
		}

		char *type = strchr (p, ' ');
		if (!type) {
			free (ostr);
			return false;
		}
		*type++ = 0;
		v1 = r_anal_var_get_byname (core->anal, fcn, p);
		if (!v1) {
			eprintf ("Cant find get by name %s\n", p);
			free (ostr);
			return false;
		}
		r_anal_var_retype (core->anal, fcn->addr,
			R_ANAL_VAR_SCOPE_LOCAL, -1, v1->kind, type, -1, p);
		r_anal_var_free (v1);
		free (ostr);
		return true;

	}
	}
	switch (str[1]) {
	case '\0':
	case '*':
	case 'j':
		r_anal_var_list_show (core->anal, fcn, type, str[1]);
		break;
	case '.':
		r_anal_var_list_show (core->anal, fcn, core->offset, 0);
		break;
	case '-': // "afv[bsr]-"
		if (str[2] == '*') {
			r_anal_var_delete_all (core->anal, fcn->addr, type);
		} else {
			if (IS_DIGIT (str[2])) {
				r_anal_var_delete (core->anal, fcn->addr,
						type, 1, (int)r_num_math (core->num, str + 1));
			} else {
				char *name = r_str_trim ( strdup (str + 2));
				r_anal_var_delete_byname (core->anal, fcn, type, name);
				free (name);
			}
		}
		break;
	case 'd':
		eprintf ("This command is deprecated, use afvd instead\n");
		break;
	case 't':
		eprintf ("This command is deprecated use afvt instead\n");
		break;
	case 's':
	case 'g':
		if (str[2] != '\0') {
			int rw = 0; // 0 = read, 1 = write
			RAnalVar *var = r_anal_var_get (core->anal, fcn->addr,
							(char)type, atoi (str + 2), R_ANAL_VAR_SCOPE_LOCAL);
			if (!var) {
				eprintf ("Cannot find variable in: '%s'\n", str);
				res = false;
				break;
			}
			if (var != NULL) {
				int scope = (str[1] == 'g')? 0: 1;
				r_anal_var_access (core->anal, fcn->addr, (char)type,
						scope, atoi (str + 2), rw, core->offset);
				r_anal_var_free (var);
				break;
			}
		} else {
			eprintf ("Missing argument\n");
		}
		break;
	case ' ': {
		const char *name;
		char *vartype;
		int size = 4;
		int scope = 1;
			for (str++; *str == ' ';) str++;
		p = strchr (str, ' ');
		if (!p) {
			var_help (core, type);
			break;
		}
		*p++ = 0;
		if (type == 'r') { //registers
			RRegItem *i = r_reg_get (core->anal->reg, str, -1);
			if (!i) {
				eprintf ("Register not found");
				break;
			}
			delta = i->index;
		} else {
			delta = r_num_math (core->num, str);
		}
		name = p;
		vartype = strchr (name, ' ');
		if (vartype) {
			*vartype++ = 0;
			r_anal_var_add (core->anal, fcn->addr,
					scope, delta, type,
					vartype, size, name);
		} else {
			eprintf ("Missing name\n");
		}
		}
		break;
	};

	free (ostr);
	return res;
}