RZ_API void rz_analysis_var_list_show(RzAnalysis *analysis, RzAnalysisFunction *fcn, int kind, int mode, PJ *pj) {
	RzAnalysisVar *var;
	RzListIter *iter;
	if (!pj && mode == 'j') {
		return;
	}
	if (mode == 'j') {
		pj_a(pj);
	}
	RzList *list = rz_analysis_var_list(analysis, fcn, kind);
	if (!list) {
		if (mode == 'j') {
			pj_end(pj);
		}
		return;
	}
	rz_list_sort(list, (RzListComparator)var_comparator);
	rz_list_foreach (list, iter, var) {
		if (var->kind != kind) {
			continue;
		}
		switch (mode) {
		case '*': {
			// we can't express all type info here :(
			char *vartype = rz_type_as_string(analysis->typedb, var->type);
			if (kind == RZ_ANALYSIS_VAR_KIND_REG) { // registers
				RzRegItem *i = rz_reg_index_get(analysis->reg, var->delta);
				if (!i) {
					eprintf("Register not found");
					free(vartype);
					break;
				}
				analysis->cb_printf("afv%c %s %s %s @ 0x%" PFMT64x "\n",
					kind, i->name, var->name, vartype, fcn->addr);
			} else {
				int delta = kind == RZ_ANALYSIS_VAR_KIND_BPV
					? var->delta + fcn->bp_off
					: var->delta;
				analysis->cb_printf("afv%c %d %s %s @ 0x%" PFMT64x "\n",
					kind, delta, var->name, vartype,
					fcn->addr);
			}
			free(vartype);
			break;
		}
		case 'j':
			switch (var->kind) {
			case RZ_ANALYSIS_VAR_KIND_BPV: {
				char *vartype = rz_type_as_string(analysis->typedb, var->type);
				st64 delta = (st64)var->delta + fcn->bp_off;
				pj_o(pj);
				pj_ks(pj, "name", var->name);
				if (var->isarg) {
					pj_ks(pj, "kind", "arg");
				} else {
					pj_ks(pj, "kind", "var");
				}
				pj_ks(pj, "type", vartype);
				pj_k(pj, "ref");
				pj_o(pj);
				pj_ks(pj, "base", analysis->reg->name[RZ_REG_NAME_BP]);
				pj_kN(pj, "offset", delta);
				pj_end(pj);
				pj_end(pj);
				free(vartype);
			} break;
			case RZ_ANALYSIS_VAR_KIND_REG: {
				RzRegItem *i = rz_reg_index_get(analysis->reg, var->delta);
				if (!i) {
					eprintf("Register not found");
					break;
				}
				char *vartype = rz_type_as_string(analysis->typedb, var->type);
				pj_o(pj);
				pj_ks(pj, "name", var->name);
				pj_ks(pj, "kind", "reg");
				pj_ks(pj, "type", vartype);
				pj_ks(pj, "ref", i->name);
				pj_end(pj);
				free(vartype);
			} break;
			case RZ_ANALYSIS_VAR_KIND_SPV: {
				st64 delta = (st64)var->delta + fcn->maxstack;
				pj_o(pj);
				pj_ks(pj, "name", var->name);
				if (var->isarg) {
					pj_ks(pj, "kind", "arg");
				} else {
					pj_ks(pj, "kind", "var");
				}
				char *vartype = rz_type_as_string(analysis->typedb, var->type);
				pj_ks(pj, "type", vartype);
				pj_k(pj, "ref");
				pj_o(pj);
				pj_ks(pj, "base", analysis->reg->name[RZ_REG_NAME_SP]);
				pj_kN(pj, "offset", delta);
				pj_end(pj);
				pj_end(pj);
				free(vartype);
			} break;
			}
			break;
		default:
			switch (kind) {
			case RZ_ANALYSIS_VAR_KIND_BPV: {
				int delta = var->delta + fcn->bp_off;
				char *vartype = rz_type_as_string(analysis->typedb, var->type);
				if (var->isarg) {
					analysis->cb_printf("arg %s %s @ %s+0x%x\n",
						vartype, var->name,
						analysis->reg->name[RZ_REG_NAME_BP],
						delta);
				} else {
					char sign = (-var->delta <= fcn->bp_off) ? '+' : '-';
					analysis->cb_printf("var %s %s @ %s%c0x%x\n",
						vartype, var->name,
						analysis->reg->name[RZ_REG_NAME_BP],
						sign, RZ_ABS(delta));
				}
				free(vartype);
			} break;
			case RZ_ANALYSIS_VAR_KIND_REG: {
				RzRegItem *i = rz_reg_index_get(analysis->reg, var->delta);
				if (!i) {
					eprintf("Register not found");
					break;
				}
				char *vartype = rz_type_as_string(analysis->typedb, var->type);
				analysis->cb_printf("arg %s %s @ %s\n",
					vartype, var->name, i->name);
				free(vartype);
			} break;
			case RZ_ANALYSIS_VAR_KIND_SPV: {
				int delta = fcn->maxstack + var->delta;
				char *vartype = rz_type_as_string(analysis->typedb, var->type);
				if (!var->isarg) {
					char sign = (-var->delta <= fcn->maxstack) ? '+' : '-';
					analysis->cb_printf("var %s %s @ %s%c0x%x\n",
						vartype, var->name,
						analysis->reg->name[RZ_REG_NAME_SP],
						sign, RZ_ABS(delta));
				} else {
					analysis->cb_printf("arg %s %s @ %s+0x%x\n",
						vartype, var->name,
						analysis->reg->name[RZ_REG_NAME_SP],
						delta);
				}
				free(vartype);
			} break;
			}
		}
	}
	if (mode == 'j') {
		pj_end(pj);
	}
	rz_list_free(list);
}