static int fcn_list_table(RzCore *core, const char *q, int fmt) {
	RzAnalysisFunction *fcn;
	RzListIter *iter;
	RzTable *t = rz_core_table(core);
	RzTableColumnType *typeString = rz_table_type("string");
	RzTableColumnType *typeNumber = rz_table_type("number");
	rz_table_add_column(t, typeNumber, "addr", 0);
	rz_table_add_column(t, typeNumber, "size", 0);
	rz_table_add_column(t, typeString, "name", 0);
	rz_table_add_column(t, typeNumber, "nbbs", 0);
	rz_table_add_column(t, typeNumber, "xref", 0);
	rz_table_add_column(t, typeNumber, "calls", 0);
	rz_table_add_column(t, typeNumber, "cc", 0);
	rz_table_add_column(t, typeNumber, "noreturn", 0);
	rz_list_foreach (core->analysis->fcns, iter, fcn) {
		const char *fcnAddr = sdb_fmt("0x%08" PFMT64x, fcn->addr);
		const char *fcnSize = sdb_fmt("%" PFMT64u, rz_analysis_function_linear_size(fcn));
		const char *nbbs = sdb_fmt("%d", rz_list_length(fcn->bbs)); // rz_analysis_fcn_size (fcn));
		RzList *xrefs = rz_analysis_function_get_xrefs_from(fcn);
		char xref[128], ccstr[128];
		snprintf(xref, sizeof(xref), "%d", rz_list_length(xrefs));
		rz_list_free(xrefs);

		RzList *calls = rz_core_analysis_fcn_get_calls(core, fcn);
		// Uniquify the list by ref->addr
		calls = rz_list_uniq(calls, (RzListComparator)RzAnalysisRef_cmp);
		const char *callstr = sdb_fmt("%d", rz_list_length(calls));
		rz_list_free(calls);
		snprintf(ccstr, sizeof(ccstr), "%d", rz_analysis_function_complexity(fcn));
		const char *noret = fcn->is_noreturn ? "yes" : "";
		rz_table_add_row(t, fcnAddr, fcnSize, fcn->name, nbbs, xref, callstr, ccstr, noret, NULL);
	}
	if (rz_table_query(t, q)) {
		char *s = rz_table_tostring(t);
		rz_cons_printf("%s\n", s);
		free(s);
	}
	rz_table_free(t);
	return 0;
}
static int fcn_list_table(RzCore *core, const char *q, int fmt) {
	RzAnalysisFunction *fcn;
	RzListIter *iter;
	RzTable *t = rz_core_table(core);
	RzTableColumnType *typeString = rz_table_type("string");
	RzTableColumnType *typeNumber = rz_table_type("number");
	rz_table_add_column(t, typeNumber, "addr", 0);
	rz_table_add_column(t, typeNumber, "size", 0);
	rz_table_add_column(t, typeString, "name", 0);
	rz_table_add_column(t, typeNumber, "nbbs", 0);
	rz_table_add_column(t, typeNumber, "xref", 0);
	rz_table_add_column(t, typeNumber, "calls", 0);
	rz_table_add_column(t, typeNumber, "cc", 0);
	rz_table_add_column(t, typeNumber, "noreturn", 0);
	rz_list_foreach (core->analysis->fcns, iter, fcn) {
		const char *fcnAddr = sdb_fmt("0x%08" PFMT64x, fcn->addr);
		const char *fcnSize = sdb_fmt("%" PFMT64u, rz_analysis_function_linear_size(fcn));
		const char *nbbs = sdb_fmt("%d", rz_list_length(fcn->bbs));  
		RzList *xrefs = rz_analysis_function_get_xrefs_from(fcn);
		char xref[128], ccstr[128];
		snprintf(xref, sizeof(xref), "%d", rz_list_length(xrefs));
		rz_list_free(xrefs);

		RzList *calls = rz_core_analysis_fcn_get_calls(core, fcn);
		 
		calls = rz_list_uniq(calls, (RzListComparator)RzAnalysisRef_cmp);
		const char *callstr = sdb_fmt("%d", rz_list_length(calls));
		rz_list_free(calls);
		snprintf(ccstr, sizeof(ccstr), "%d", rz_analysis_function_complexity(fcn));
		const char *noret = fcn->is_noreturn ? "yes" : "";
		rz_table_add_row(t, fcnAddr, fcnSize, fcn->name, nbbs, xref, callstr, ccstr, noret, NULL);
	}
	if (rz_table_query(t, q)) {
		char *s = rz_table_tostring(t);
		rz_cons_printf("%s\n", s);
		free(s);
	}
	rz_table_free(t);
	return 0;
}