static void bb_info_print(RzCore *core, RzAnalysisFunction *fcn, RzAnalysisBlock *bb,
	ut64 addr, RzOutputMode mode, PJ *pj, RzTable *t) {
	RzDebugTracepoint *tp = NULL;
	RzListIter *iter;
	RzAnalysisBlock *bb2;
	int outputs = (bb->jump != UT64_MAX) + (bb->fail != UT64_MAX);
	int inputs = 0;
	rz_list_foreach (fcn->bbs, iter, bb2) {
		inputs += (bb2->jump == bb->addr) + (bb2->fail == bb->addr);
	}
	if (bb->switch_op) {
		RzList *unique_cases = rz_list_uniq(bb->switch_op->cases, casecmp);
		outputs += rz_list_length(unique_cases);
		rz_list_free(unique_cases);
	}
	ut64 opaddr = __opaddr(bb, addr);

	switch (mode) {
	case RZ_OUTPUT_MODE_STANDARD:
		tp = rz_debug_trace_get(core->dbg, bb->addr);
		rz_cons_printf("0x%08" PFMT64x " 0x%08" PFMT64x " %02X:%04X %" PFMT64d,
			bb->addr, bb->addr + bb->size,
			tp ? tp->times : 0, tp ? tp->count : 0,
			bb->size);
		if (bb->jump != UT64_MAX) {
			rz_cons_printf(" j 0x%08" PFMT64x, bb->jump);
		}
		if (bb->fail != UT64_MAX) {
			rz_cons_printf(" f 0x%08" PFMT64x, bb->fail);
		}
		if (bb->switch_op) {
			RzAnalysisCaseOp *cop;
			RzListIter *iter;
			RzList *unique_cases = rz_list_uniq(bb->switch_op->cases, casecmp);
			rz_list_foreach (unique_cases, iter, cop) {
				rz_cons_printf(" s 0x%08" PFMT64x, cop->addr);
			}
			rz_list_free(unique_cases);
		}
		rz_cons_newline();
		break;
	case RZ_OUTPUT_MODE_JSON: {
		pj_o(pj);
		if (bb->jump != UT64_MAX) {
			pj_kn(pj, "jump", bb->jump);
		}
		if (bb->fail != UT64_MAX) {
			pj_kn(pj, "fail", bb->fail);
		}
		if (bb->switch_op) {
			pj_k(pj, "switch_op");
			pj_o(pj);
			pj_kn(pj, "addr", bb->switch_op->addr);
			pj_kn(pj, "min_val", bb->switch_op->min_val);
			pj_kn(pj, "def_val", bb->switch_op->def_val);
			pj_kn(pj, "max_val", bb->switch_op->max_val);
			pj_k(pj, "cases");
			pj_a(pj);
			{
				RzListIter *case_op_iter;
				RzAnalysisCaseOp *case_op;
				rz_list_foreach (bb->switch_op->cases, case_op_iter, case_op) {
					pj_o(pj);
					pj_kn(pj, "addr", case_op->addr);
					pj_kn(pj, "jump", case_op->jump);
					pj_kn(pj, "value", case_op->value);
					pj_end(pj);
				}
			}
			pj_end(pj);
			pj_end(pj);
		}
		pj_kn(pj, "opaddr", opaddr);
		pj_kn(pj, "addr", bb->addr);
		pj_ki(pj, "size", bb->size);
		pj_ki(pj, "inputs", inputs);
		pj_ki(pj, "outputs", outputs);
		pj_ki(pj, "ninstr", bb->ninstr);
		pj_kb(pj, "traced", bb->traced);
		pj_end(pj);
		break;
	}
	case RZ_OUTPUT_MODE_TABLE:
		rz_table_add_rowf(t, "xdxx", bb->addr, bb->size, bb->jump, bb->fail);
		break;
	case RZ_OUTPUT_MODE_RIZIN:
		rz_cons_printf("f bb.%05" PFMT64x " = 0x%08" PFMT64x "\n", bb->addr & 0xFFFFF, bb->addr);
		break;
	case RZ_OUTPUT_MODE_QUIET:
		rz_cons_printf("0x%08" PFMT64x "\n", bb->addr);
		break;
	case RZ_OUTPUT_MODE_LONG: {
		if (bb->jump != UT64_MAX) {
			rz_cons_printf("jump: 0x%08" PFMT64x "\n", bb->jump);
		}
		if (bb->fail != UT64_MAX) {
			rz_cons_printf("fail: 0x%08" PFMT64x "\n", bb->fail);
		}
		rz_cons_printf("opaddr: 0x%08" PFMT64x "\n", opaddr);
		rz_cons_printf("addr: 0x%08" PFMT64x "\nsize: %" PFMT64d "\ninputs: %d\noutputs: %d\nninstr: %d\ntraced: %s\n",
			bb->addr, bb->size, inputs, outputs, bb->ninstr, rz_str_bool(bb->traced));
		break;
	}
	default:
		rz_warn_if_reached();
		break;
	}
}