RZ_API int rz_core_print_bb_gml(RzCore *core, RzAnalysisFunction *fcn) {
	RzAnalysisBlock *bb;
	RzListIter *iter;
	if (!fcn) {
		return false;
	}
	int id = 0;
	HtUUOptions opt = { 0 };
	HtUU *ht = ht_uu_new_opt(&opt);

	rz_cons_printf("graph\n[\n"
		       "hierarchic 1\n"
		       "label \"\"\n"
		       "directed 1\n");

	rz_list_foreach (fcn->bbs, iter, bb) {
		RzFlagItem *flag = rz_flag_get_i(core->flags, bb->addr);
		char *msg = flag ? strdup(flag->name) : rz_str_newf("0x%08" PFMT64x, bb->addr);
#if USE_ID
		ht_uu_insert(ht, bb->addr, id);
		rz_cons_printf("  node [\n"
			       "    id  %d\n"
			       "    label  \"%s\"\n"
			       "  ]\n",
			id, msg);
		id++;
#else
		rz_cons_printf("  node [\n"
			       "    id  %" PFMT64d "\n"
			       "    label  \"%s\"\n"
			       "  ]\n",
			bb->addr, msg);
#endif
		free(msg);
	}

	rz_list_foreach (fcn->bbs, iter, bb) {
		if (bb->addr == UT64_MAX) {
			continue;
		}

#if USE_ID
		if (bb->jump != UT64_MAX) {
			bool found;
			int i = ht_uu_find(ht, bb->addr, &found);
			if (found) {
				int i2 = ht_uu_find(ht, bb->jump, &found);
				if (found) {
					rz_cons_printf("  edge [\n"
						       "    source  %d\n"
						       "    target  %d\n"
						       "  ]\n",
						i, i2);
				}
			}
		}
		if (bb->fail != UT64_MAX) {
			bool found;
			int i = ht_uu_find(ht, bb->addr, &found);
			if (found) {
				int i2 = ht_uu_find(ht, bb->fail, &found);
				if (found) {
					rz_cons_printf("  edge [\n"
						       "    source  %d\n"
						       "    target  %d\n"
						       "  ]\n",
						i, i2);
				}
			}
		}
		if (bb->switch_op) {
			RzListIter *it;
			RzAnalysisCaseOp *cop;
			rz_list_foreach (bb->switch_op->cases, it, cop) {
				bool found;
				int i = ht_uu_find(ht, bb->addr, &found);
				if (found) {
					int i2 = ht_uu_find(ht, cop->addr, &found);
					if (found) {
						rz_cons_printf("  edge [\n"
							       "    source  %d\n"
							       "    target  %d\n"
							       "  ]\n",
							i, i2);
					}
				}
			}
		}
#else
		if (bb->jump != UT64_MAX) {
			rz_cons_printf("  edge [\n"
				       "    source  %" PFMT64d "\n"
				       "    target  %" PFMT64d "\n"
				       "  ]\n",
				bb->addr, bb->jump);
		}
		if (bb->fail != UT64_MAX) {
			rz_cons_printf("  edge [\n"
				       "    source  %" PFMT64d "\n"
				       "    target  %" PFMT64d "\n"
				       "  ]\n",
				bb->addr, bb->fail);
		}
		if (bb->switch_op) {
			RzListIter *it;
			RzAnalysisCaseOp *cop;
			rz_list_foreach (bb->switch_op->cases, it, cop) {
				rz_cons_printf("  edge [\n"
					       "    source  %" PFMT64d "\n"
					       "    target  %" PFMT64d "\n"
					       "  ]\n",
					bb->addr, cop->addr);
			}
		}
#endif
	}
	rz_cons_printf("]\n");
	ht_uu_free(ht);
	return true;
}
RZ_API int rz_core_print_bb_gml(RzCore *core, RzAnalysisFunction *fcn) {
	RzAnalysisBlock *bb;
	RzListIter *iter;
	if (!fcn) {
		return false;
	}
	int id = 0;
	HtUUOptions opt = { 0 };
	HtUU *ht = ht_uu_new_opt(&opt);

	rz_cons_printf("graph\n[\n"
		       "hierarchic 1\n"
		       "label \"\"\n"
		       "directed 1\n");

	rz_list_foreach (fcn->bbs, iter, bb) {
		RzFlagItem *flag = rz_flag_get_i(core->flags, bb->addr);
		char *msg = flag ? strdup(flag->name) : rz_str_newf("0x%08" PFMT64x, bb->addr);
#if USE_ID
		ht_uu_insert(ht, bb->addr, id);
		rz_cons_printf("  node [\n"
			       "    id  %d\n"
			       "    label  \"%s\"\n"
			       "  ]\n",
			id, msg);
		id++;
#else
		rz_cons_printf("  node [\n"
			       "    id  %" PFMT64d "\n"
			       "    label  \"%s\"\n"
			       "  ]\n",
			bb->addr, msg);
#endif
		free(msg);
	}

	rz_list_foreach (fcn->bbs, iter, bb) {
		if (bb->addr == UT64_MAX) {
			continue;
		}

#if USE_ID
		if (bb->jump != UT64_MAX) {
			bool found;
			int i = ht_uu_find(ht, bb->addr, &found);
			if (found) {
				int i2 = ht_uu_find(ht, bb->jump, &found);
				if (found) {
					rz_cons_printf("  edge [\n"
						       "    source  %d\n"
						       "    target  %d\n"
						       "  ]\n",
						i, i2);
				}
			}
		}
		if (bb->fail != UT64_MAX) {
			bool found;
			int i = ht_uu_find(ht, bb->addr, &found);
			if (found) {
				int i2 = ht_uu_find(ht, bb->fail, &found);
				if (found) {
					rz_cons_printf("  edge [\n"
						       "    source  %d\n"
						       "    target  %d\n"
						       "  ]\n",
						i, i2);
				}
			}
		}
		if (bb->switch_op) {
			RzListIter *it;
			RzAnalysisCaseOp *cop;
			rz_list_foreach (bb->switch_op->cases, it, cop) {
				bool found;
				int i = ht_uu_find(ht, bb->addr, &found);
				if (found) {
					int i2 = ht_uu_find(ht, cop->addr, &found);
					if (found) {
						rz_cons_printf("  edge [\n"
							       "    source  %d\n"
							       "    target  %d\n"
							       "  ]\n",
							i, i2);
					}
				}
			}
		}
#else
		if (bb->jump != UT64_MAX) {
			rz_cons_printf("  edge [\n"
				       "    source  %" PFMT64d "\n"
				       "    target  %" PFMT64d "\n"
				       "  ]\n",
				bb->addr, bb->jump);
		}
		if (bb->fail != UT64_MAX) {
			rz_cons_printf("  edge [\n"
				       "    source  %" PFMT64d "\n"
				       "    target  %" PFMT64d "\n"
				       "  ]\n",
				bb->addr, bb->fail);
		}
		if (bb->switch_op) {
			RzListIter *it;
			RzAnalysisCaseOp *cop;
			rz_list_foreach (bb->switch_op->cases, it, cop) {
				rz_cons_printf("  edge [\n"
					       "    source  %" PFMT64d "\n"
					       "    target  %" PFMT64d "\n"
					       "  ]\n",
					bb->addr, cop->addr);
			}
		}
#endif
	}
	rz_cons_printf("]\n");
	ht_uu_free(ht);
	return true;
}