diff --git a/Makefile b/Makefile index be2d026..e02e6e7 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,5 @@ CC = gcc CFLAGS = -Wall -Wextra -Werror -O3 -# GCCVERSIONGTE10 := $(shell expr `gcc -dumpversion | cut -f1 -d.` \>= 10) -# -# ifeq "$(GCCVERSIONGTE10)" "1" -# CFLAGS += -fanalyzer -# endif NAME = code-analyzer AUTHOR = Volodymyr_Patuta @@ -28,8 +23,10 @@ distdir = $(AUTHOR)-$(NAME)-$(VERSION) all: $(NAME) graph: - $(DOT) graph.dot > out.pdf - $(DOT) CC.dot > cc.pdf + $(DOT) vgraph.dot > vgragh.pdf + $(DOT) vCC.dot > vCC.pdf + $(DOT) mcgraph.dot > mcgragh.pdf + $(DOT) mcCC.dot > mcCC.pdf debug: CFLAGS += -DDEBUG -g debug: $(NAME) @@ -55,6 +52,7 @@ clean: $(RM) $(OBJS) fclean: clean - $(RM) $(NAME) out.pdf graph.dot + $(RM) $(NAME) vgraph.pdf vgraph.dot mcgraph.pdf mcgraph.dot \ + mcCC.dot mcCC.pdf vCC.dot vCC.pdf .PHONY: all clean fclean re dist distdir debug diff --git a/src/main.c b/src/main.c index a24a999..c6d48f8 100644 --- a/src/main.c +++ b/src/main.c @@ -29,11 +29,21 @@ int main(int argc, char *argv[]) // find_funcs("/home/user/files/dot_files/st/x.c", &gv, &gmc); find_funcs("test.c", &gv, &gmc); // findAndParse("/home/user/files/dot_files/st/", &gv, &gmc); - // vprint_nodes(gv.node[8]); - mcprint_edges(gmc, 8); + // for (int i = 0; i <= gmc.nba; ++i) { + // printf("%d.%s -> %d.%s\n", gmc.vec[i].i, gmc.func[gmc.vec[i].i], gmc.vec[i].j, gmc.func[gmc.vec[i].j]); + // } + // puts("\n"); + vprint(gv.node[8], &gv); + mcprint(gmc, 8); + vfind_cycles(&gv); - mcdelete_graph(&gmc); + mcfind_cycles(&gmc); + vdot_graph(gv, true); + mcdot_graph(gmc, true); + + mcdelete_graph(&gmc); vdelete_graph(&gv); + return 0; } diff --git a/src/matcom.c b/src/matcom.c index 97149ef..93a3cdf 100644 --- a/src/matcom.c +++ b/src/matcom.c @@ -4,7 +4,8 @@ #include #include #include -#include + +enum { NOT_VISITED = 0, IN_STACK = 1, DONE = 2 }; graph_mco mcgragh(void) { @@ -14,6 +15,7 @@ graph_mco mcgragh(void) g.func = malloc((g.fcap = 10) * sizeof(fix_str)); assert(g.func); g.vec = malloc((g.vcap = 10) * sizeof(struct edge)); + g.vu = NULL; assert(g.vec); return g; } @@ -37,7 +39,6 @@ void mcinsert_edge(graph_mco *g, int dep, int arr) assert(g->vec); } e.i = dep; - e.vu = 0; if (arr == -1) e.j = g->nbs; else @@ -51,9 +52,12 @@ void mcdelete_graph(graph_mco *g) free(g->func); if (g->vec) free(g->vec); + if (g->vu) + free(g->vu); g->func = NULL; g->vec = NULL; + g->vu = NULL; } int mcis_in(graph_mco g, fix_str func) @@ -74,13 +78,13 @@ static void mcprint_succ(graph_mco g, int succ) printf(" Succ: %s\n", g.func[succ]); } -void mcprint_edges(graph_mco g, int n) +static void mcprint_edges(graph_mco g, int n) { int i; - if (g.vec[n].vu) + if (g.vu[n]) return; - g.vec[n].vu = 1; - printf("NODE %d: %s\n", n, g.func[n]); + g.vu[n] = 1; + printf("NODE: %s\n", g.func[n]); for (i = 0; i <= g.nba; ++i) { if (g.vec[i].i == n) { mcprint_succ(g, g.vec[i].j); @@ -93,3 +97,142 @@ void mcprint_edges(graph_mco g, int n) } } } + +void mcprint(graph_mco g, int n) +{ + if (g.vu == NULL) { + g.vu = calloc(g.nbs, sizeof(int)); + } + + mcprint_edges(g, n); + + if (g.vu) { + free(g.vu); + } +} + +static void write_node_dot(FILE *fp, graph_mco g) +{ + int i; + for (i = 0; i <= g.nbs; i++) { + fprintf(fp, "\t%s -> %s;\n", g.func[g.vec[i].i], g.func[g.vec[i].j]); + } +} + +static void main_graph(FILE *fp, graph_mco g, int n) +{ + int i; + if (g.vu[n]) + return; + g.vu[n] = 1; + for (i = 0; i <= g.nba; ++i) { + if (g.vec[i].i == n) { + fprintf(fp, "\t%s -> %s;\n", g.func[n], g.func[g.vec[i].j]); + main_graph(fp, g, g.vec[i].j); + } + } +} + +void mcdot_graph(graph_mco g, bool main) +{ + FILE *fp, *fp1; + int i; + + if (g.vu == NULL) { + g.vu = calloc(g.nbs, sizeof(int)); + } else { + for (i = 0; i <= g.nbs; i++) { + g.vu[i] = 0; + } + } + + fp = fopen("mcgraph.dot", "w"); + fp1 = fopen("mcCC.dot", "w"); + + fprintf(fp, "digraph mcCCmain {\n"); + fprintf(fp1, "digraph mcCC {\n"); + + if (main) { + fix_str m = "main"; + int n = mcis_in(g, m); + if (n != -1) { + main_graph(fp, g, n); + } else { + fprintf(stderr, "main not found.\n"); + exit(1); + } + for (i = 0; i <= g.nbs; ++i) { + if (!g.vu[i]) { + main_graph(fp1, g, i); + } + } + + } else { + write_node_dot(fp, g); + } + + fprintf(fp, "}"); + fprintf(fp1, "}"); + + fclose(fp); + fclose(fp1); +} + +// NOTE: https://www.baeldung.com/cs/detecting-cycles-in-directed-graph +static void print_cycle(graph_mco g, stack_t s, int v) +{ + stack_t s2 = init_stack(); + push(&s2, pop(&s)); + while (top(s2) != g.vec[v].j) { + push(&s2, pop(&s)); + } + while (!empty(s2)) { + printf("%s -> ", g.func[pop(&s2)]); + } + printf("%s\n", g.func[g.vec[v].j]); + free_stack(&s2); +} + +static void processDFS(graph_mco g, int node, stack_t *s) +{ + int i; + + for (i = 0; i <= g.nba; ++i) { + if (g.vec[i].i != node) + continue; + int v = g.vec[i].j; + if (g.vu[v] == IN_STACK) { + // puts("found"); + print_cycle(g, *s, i); + } else if (g.vu[v] == NOT_VISITED) { + push(s, v); + g.vu[v] = IN_STACK; + processDFS(g, v, s); + } + } + g.vu[node] = DONE; + pop(s); +} + +void mcfind_cycles(graph_mco *g) +{ + int v, i; + + if (g->vu == NULL) { + g->vu = calloc(g->nbs + 1, sizeof(int)); + } else { + for (i = 0; i <= g->nbs; i++) { + g->vu[i] = 0; + } + } + + for (v = 0; v <= g->nbs; ++v) { + if (g->vu[v] == NOT_VISITED) { + stack_t s = init_stack(); + push(&s, v); + g->vu[v] = IN_STACK; + processDFS(*g, v, &s); + free_stack(&s); + } + } +} diff --git a/src/matcom.h b/src/matcom.h index 35b5cd3..8fdb201 100644 --- a/src/matcom.h +++ b/src/matcom.h @@ -2,13 +2,14 @@ #define MATCOM_H +#include + typedef char fix_str[256]; typedef struct graph_mco graph_mco; struct edge { int i; // noeud de depart int j; // noeud d'arrivé - int vu; }; struct graph_mco { @@ -16,6 +17,7 @@ struct graph_mco { int nba; // nombre d'aretes int vcap; // capacité de vec int fcap; // capacité de func + int *vu; // status de sommets fix_str *func; // noms de fonctions struct edge *vec; // vecteur d'aretes }; @@ -25,6 +27,8 @@ void mcinsert_func(graph_mco *g, fix_str i); void mcinsert_edge(graph_mco *g, int dep, int arr); void mcdelete_graph(graph_mco *g); int mcis_in(graph_mco g, fix_str func); -void mcprint_edges(graph_mco g, int n); +void mcprint(graph_mco g, int n); +void mcdot_graph(graph_mco g, bool main); +void mcfind_cycles(graph_mco *g); #endif /* end of include guard: MATCOM_H */ diff --git a/src/vec.c b/src/vec.c index 4f898d6..d3df220 100644 --- a/src/vec.c +++ b/src/vec.c @@ -28,7 +28,6 @@ void vinsert_node(graph_vec *g, fix_str str) n->num = g->n; n->nbs = 0; n->vu = 0; - n->dvu = 0; n->cap = 5; n->succ = malloc(5 * sizeof(nodept)); strcpy(n->func, str); @@ -70,7 +69,7 @@ static void vprint_succ(nodept node) printf(" Succ: %s\n", node->func); } -void vprint_nodes(nodept node) +static void vprint_nodes(nodept node) { int i; if (node->vu) @@ -86,7 +85,16 @@ void vprint_nodes(nodept node) } } -static void vwrite_node_dot(FILE *fp, graph_vec g) +void vprint(nodept node, graph_vec *g) +{ + int i; + for (i = 0; i <= g->n; i++) { + g->node[i]->vu = 0; + } + vprint_nodes(node); +} + +static void write_node_dot(FILE *fp, graph_vec g) { int i, j; for (i = 0; i <= g.n; i++) { @@ -106,8 +114,6 @@ static void main_graph(FILE *fp, nodept node) // printf("NODE %d: %s\n", node->num, node->func); for (i = 0; i < node->nbs; ++i) { fprintf(fp, "\t%s -> %s;\n", node->func, node->succ[i]->func); - } - for (i = 0; i < node->nbs; ++i) { main_graph(fp, node->succ[i]); } } @@ -117,11 +123,15 @@ void vdot_graph(graph_vec g, bool main) FILE *fp, *fp1; int i; - fp = fopen("graph.dot", "w"); - fp1 = fopen("CC.dot", "w"); + for (i = 0; i <= g.n; i++) { + g.node[i]->vu = 0; + } - fprintf(fp, "digraph CCmain {\n"); - fprintf(fp1, "digraph CC {\n"); + fp = fopen("vgraph.dot", "w"); + fp1 = fopen("vCC.dot", "w"); + + fprintf(fp, "digraph vCCmain {\n"); + fprintf(fp1, "digraph vCC {\n"); if (main) { fix_str m = "main"; @@ -139,7 +149,7 @@ void vdot_graph(graph_vec g, bool main) } } else { - vwrite_node_dot(fp, g); + write_node_dot(fp, g); } fprintf(fp, "}"); @@ -169,26 +179,29 @@ static void processDFS(nodept n, stack_t *s, graph_vec g) int i; for (i = 0; i < n->nbs; ++i) { int v = n->succ[i]->num; - if (n->succ[i]->dvu == IN_STACK) { + if (n->succ[i]->vu == IN_STACK) { print_cycle(g, *s, v); - } else if (n->succ[i]->dvu == NOT_VISITED) { + } else if (n->succ[i]->vu == NOT_VISITED) { push(s, v); - n->succ[i]->dvu = IN_STACK; + n->succ[i]->vu = IN_STACK; processDFS(n->succ[i], s, g); } } - n->dvu = DONE; + n->vu = DONE; pop(s); } void vfind_cycles(graph_vec *g) { int v; + for (v = 0; v <= g->n; v++) { + g->node[v]->vu = 0; + } for (v = 0; v <= g->n; ++v) { - if (g->node[v]->dvu == NOT_VISITED) { + if (g->node[v]->vu == NOT_VISITED) { stack_t s = init_stack(); push(&s, v); - g->node[v]->dvu = IN_STACK; + g->node[v]->vu = IN_STACK; processDFS(g->node[v], &s, *g); free_stack(&s); } diff --git a/src/vec.h b/src/vec.h index 180b07e..78d246d 100644 --- a/src/vec.h +++ b/src/vec.h @@ -15,8 +15,7 @@ struct nodes { }; struct node { - int dvu; - int vu; + int vu; // status de noeud (`vu/en traitement/fini` pour dfs ou `vu/non vu` pour affichage) int num; // le numero de noeud int nbs; // nombre de successeurs fix_str func; // noms de fonctions @@ -29,7 +28,7 @@ void vinsert_node(graph_vec *g, fix_str str); void vdelete_graph(graph_vec *g); int vis_in(graph_vec g, fix_str func); void vdot_graph(graph_vec g, bool main); -void vprint_nodes(nodept node); +void vprint(nodept node, graph_vec *g); void vfind_cycles(graph_vec *g); #endif /* end of include guard: VEC_H */