From aad9586ee442e92df72dca364af91442cde05362 Mon Sep 17 00:00:00 2001 From: Jean Sirmai Date: Thu, 21 Nov 2024 11:54:13 +0100 Subject: [PATCH] src/util/* include/base.h makes available util_concat(), util_read_file() introduces the enum axis { X_AXIS, Y_AXIS, Z_AXIS } The use of util_concat() modifies the memory indirect leaks (not direct). Doc minor modifications. --- .../2024-11-21 main() graph by Doxygen.png | Bin 0 -> 43711 bytes include/base.h | 86 ++++++------ include/fsm.h | 12 +- include/util.h | 37 +++++ src/fsm/control.c | 17 +-- src/fsm/log/manager.c | 4 +- src/fsm/log/oper.c | 4 +- src/main.c | 10 +- src/util/io.c | 64 +++++++++ src/util/strings.c | 131 ++++++++++++++++++ src/widget/main_window/design.c | 4 +- src/widget/manager.c | 17 +-- 12 files changed, 312 insertions(+), 74 deletions(-) create mode 100644 docs/showcase/2024-11-21 main() graph by Doxygen.png create mode 100644 include/util.h create mode 100644 src/util/io.c create mode 100644 src/util/strings.c diff --git a/docs/showcase/2024-11-21 main() graph by Doxygen.png b/docs/showcase/2024-11-21 main() graph by Doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..c43230988df1ccec24ad9ee94f0ba6329620e23c GIT binary patch literal 43711 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 AlK=n! literal 0 HcmV?d00001 diff --git a/include/base.h b/include/base.h index 365d60f..8afa248 100644 --- a/include/base.h +++ b/include/base.h @@ -1,25 +1,27 @@ -/* - * Gem-graph OpenGL experiments +/** + * @file + * base header * - * Desc: Base header + * This file is part of Gem-graph. * - * Copyright (C) 2023 Arthur Menges - * Copyright (C) 2023 Adrien Bourmault + * @cond LICENSE + * Copyright © 2021 Libre en Communs + * Copyright © 2021-2024 Adrien Bourmault + * Copyright © 2021-2024 Jean Sirmai * - * This file is part of Gem-graph. + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * @endcond */ #pragma once @@ -35,33 +37,39 @@ #include #include #include + //#define G_APPLICATION_DEFAULT_FLAGS 0 -enum { X_AXIS, Y_AXIS, Z_AXIS, N_AXIS }; // < used by : graph_area.h -enum { HOME_MODE, RUN_MODE, EDIT_MODE, PRESENTATION_MODE, N_MODE }; // Gem-graph modes -struct arrow_t { uint load; uint site; uint x; uint y; uint z; }; // describes an arrow -static inline char *read_file(char *filename); // < used by : init.c +struct arrow_t { uint load; uint site; uint x; uint y; uint z; }; +static inline char *read_file(char *filename); -/* I'm standing on Earth (or any spinning spheroid) and looking towards its North pole, then : - X - X = EAST - WEST = rouge - cyan - Y - Y = ZENITH - NADIR = vert - magenta (fuschia) - Z - Z = NORTH - SOUTH = bleu - jaune */ - -#define EAST 0 // + x rouge -#define WEST 1 // - x cyan -#define ZENITH 2 // + y vert -#define NADIR 3 // - y magenta -#define SOUTH 4 // + z bleu -#define NORTH 5 // - z jaune - - -/* - * char *read_file(char *filename) reads a file from filename into a provided buffer +/** + * I'm standing on Earth (or any spinning spheroid) + * and looking towards its North pole, * - * @param filename, file name - * contents, target ptr + * then : * - * @return void + * X - X = EAST - WEST = red - cyan + * Y - Y = ZENITH - NADIR = green - magenta (fuschia) + * Z - Z = SOUTH - NORTH = blue - yellow + */ +enum axis { X_AXIS, Y_AXIS, Z_AXIS, N_AXIS }; + + +#define EAST 0 /**< +x red */ +#define WEST 1 /**< -x cyan */ +#define ZENITH 2 /**< +y green */ +#define NADIR 3 /**< -y magenta or fuschia */ +#define SOUTH 4 /**< +z blue */ +#define NORTH 5 /**< -z yellow */ + + +/** + * char *read_file(char *filename) + * + * reads a file from filename into a provided buffer + * + * @param *filename */ static inline char *read_file(char *filename) { diff --git a/include/fsm.h b/include/fsm.h index 4264187..2276eae 100644 --- a/include/fsm.h +++ b/include/fsm.h @@ -219,8 +219,8 @@ void fsm_clear_log (struct fsm_log_t *); void fsm_clear_log_unit (struct fsm_log_unit_t *); void fsm_add_log_event (struct fsm_log_t *gg_logs, - char *file_source, - char *function_source, + const char *file_source, + const char *function_source, char *string_value); int fsm_get_log_length(struct fsm_log_t *); @@ -236,12 +236,12 @@ long fsm_remove_log (struct fsm_log_t *gg_logs, void fsm_add_log (int severity, int source, - char *file_source, - char *function_source, + const char *file_source, + const char *function_source, char *string_value); void fsm_relay_init_log(); void fsm_relay_close_log(); -void fsm_init (char *initial_message_from_main); -void fsm_close (char *final_message_from_main); +void fsm_init(); +void fsm_close(); diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..96181a8 --- /dev/null +++ b/include/util.h @@ -0,0 +1,37 @@ +/** + * @file + * utilities header + * + * This file is part of Gem-graph. + * + * @cond LICENSE + * Copyright © 2021 Libre en Communs + * Copyright © 2021-2024 Adrien Bourmault + * Copyright © 2021-2024 Jean Sirmai + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * @endcond + */ + + +#pragma once +#include +#include +#include + +#include "../include/fsm.h" + +char *util_read_file (char *filename); +char *util_concat (const char *str, ...); + diff --git a/src/fsm/control.c b/src/fsm/control.c index ce7d1ec..204e055 100644 --- a/src/fsm/control.c +++ b/src/fsm/control.c @@ -140,16 +140,16 @@ static void fsm_structures_close() * * @param *initial_info_from_main */ -void fsm_init (char *initial_info_from_main) +void fsm_init() { fsm_relay_init_log(); - fsm_add_log (INFO, MAIN, "main", initial_info_from_main, + fsm_add_log (INFO, MAIN, "fsm/control", __func__, "👋️ (☕️) Hi everybody ! Here is Gem-Graph."); - fsm_add_log (INFO, FSM, "fsm/control", "fsm initialisation", "has began ✍️"); + fsm_add_log (INFO, FSM, "fsm/control", __func__, "has began ✍️"); fsm_structures_init(); - fsm_add_log (INFO, FSM, "fsm/control", "fsm initialisation", "has ended 😇️"); + fsm_add_log (INFO, FSM, "fsm/control", __func__, "has ended 😇️"); } /** @@ -181,16 +181,17 @@ void fsm_init (char *initial_info_from_main) * * @param *closing_info_from_main */ -void fsm_close (char *closing_info_from_main) +void fsm_close() { - fsm_add_log (INFO, FSM, "fsm/control", "fsm closing", "has began"); + fsm_add_log (INFO, FSM, "fsm/control", __func__, "has began"); fsm_structures_close(); - fsm_add_log (INFO, FSM, "fsm/control", "fsm closing", "has ended"); + fsm_add_log (INFO, FSM, "fsm/control", __func__, "has ended"); - fsm_add_log (INFO, MAIN, "main", closing_info_from_main, + fsm_add_log (INFO, MAIN, "fsm/control", __func__, "👋️😄️ That'all folks !"); fsm_relay_close_log(); /**< fsm_clear_log(() can't be called from here * because static fsm_log_struct gg_logs * is in src/fsm/log/manager.c */ } + diff --git a/src/fsm/log/manager.c b/src/fsm/log/manager.c index b2a8469..658b86c 100644 --- a/src/fsm/log/manager.c +++ b/src/fsm/log/manager.c @@ -94,8 +94,8 @@ static struct fsm_log_t gg_logs = { 0 }; */ void fsm_add_log (int severity, int source, - char *file_source, - char *function_source, + const char *file_source, + const char *function_source, char *string_value) { if diff --git a/src/fsm/log/oper.c b/src/fsm/log/oper.c index da7f3a9..b0c672a 100644 --- a/src/fsm/log/oper.c +++ b/src/fsm/log/oper.c @@ -116,8 +116,8 @@ void fsm_clear_log_unit (struct fsm_log_unit_t *unit) * @param *string_value */ void fsm_add_log_event (struct fsm_log_t *gg_logs, - char *file_source, - char *function_source, + const char *file_source, + const char *function_source, char *string_value) { struct timeval tv; diff --git a/src/main.c b/src/main.c index acd1754..910d806 100644 --- a/src/main.c +++ b/src/main.c @@ -63,15 +63,15 @@ int main (int argc, char **argv) GtkApplication *app; int status; - fsm_init ("first instruction / first log"); + fsm_init(); - fsm_add_log (INFO, MAIN, "main", + fsm_add_log (INFO, MAIN, __func__, "*app = gtk_application_new()", "| 👉️ trigger app initialization"); app = gtk_application_new ("org.gem-graph", G_APPLICATION_DEFAULT_FLAGS); - fsm_add_log (INFO, MAIN, "main", + fsm_add_log (INFO, MAIN, __func__, "g signal connect (activate)", "| 👉️ windows creation requested"); @@ -80,9 +80,9 @@ int main (int argc, char **argv) status = g_application_run (G_APPLICATION (app), argc, argv); g_object_unref (app); - fsm_add_log (INFO, MAIN, "main", "g_object unref (app)", "| 👌️ bye bye app !"); + fsm_add_log (INFO, MAIN, __func__, "g_object unref (app)", "| 👌️ bye bye app !"); - fsm_close("last instruction / last log"); + fsm_close(); return status; } diff --git a/src/util/io.c b/src/util/io.c new file mode 100644 index 0000000..f7a25f0 --- /dev/null +++ b/src/util/io.c @@ -0,0 +1,64 @@ +/** + * @file + * input output + * + * This file is part of Gem-graph. + * + * @cond LICENSE + * Copyright © 2021 Libre en Communs + * Copyright © 2021-2024 Adrien Bourmault + * Copyright © 2021-2024 Jean Sirmai + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * @endcond + */ + + +#include "../../include/util.h" +#include "../../include/base.h" + + +/** + * reads a file from filename into a provided buffer + * + * @param *filename + * + * @returns char + */ +char *util_read_file(char *filename) +{ + int fd; + int filesize; + char *contents; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("Couldn't read file: %s\n",filename); + return NULL; + } + + filesize = lseek(fd, 0, SEEK_END) + 1 ; + contents = g_malloc(filesize * sizeof(char)); + assert (contents); + + lseek(fd, 0, SEEK_SET); + read(fd,contents,filesize); + + contents[filesize-1] = '\0'; + + close(fd); + + return contents; +} + diff --git a/src/util/strings.c b/src/util/strings.c new file mode 100644 index 0000000..6413915 --- /dev/null +++ b/src/util/strings.c @@ -0,0 +1,131 @@ +/** + * @file + * concat + * + * @cond LICENSE + * This file is part of Gem-graph. + * + * Copyright © 2021 Libre en Communs + * Copyright © 2021-2024 Adrien Bourmault + * Copyright © 2021-2024 Jean Sirmai + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * @endcond + */ + + + + +#include +#include +#include + +/** + * Programmers using the strcat function can easily be recognized as lazy and + * reckless 🤨️ (quoted from: The GNU C Library (glibc) manual - 5.5 + * Concatenating Strings). + * + * Whenever a programmer feels the need to use strcat she or he should think twice + * and look through the program to see whether the code cannot be rewritten + * to take advantage of already calculated results. + * The related functions strlcat, strncat, wcscat and wcsncat are almost always unnecessary, too. + * Again: it is almost always unnecessary to use functions like strcat. 😄️ + * + * Before calling vprintf or the other functions listed in this section, + * you must call va_start (see Variadic Functions) to initialize a pointer to the variable arguments. + * Then you can call va_arg to fetch the arguments that you want to handle yourself. + * This advances the pointer past those arguments. + * + * Once your va_list pointer is pointing at the argument of your choice, you are ready to call vprintf. + * That argument and all subsequent arguments that were passed to your function + * are used by vprintf along with the template that you specified separately. + * + * --- + * + * A.2 Variadic Functions + * + * ISO C defines a syntax for declaring a function to take a variable number or type of arguments. + * (Such functions are referred to as varargs functions or variadic functions.) + * However, the language itself provides no mechanism for such functions to access + * their non-required arguments; instead, you use the variable arguments macros defined in stdarg.h. + * + * This section describes how to declare variadic functions, how to write them, + * and how to call them properly. + * + * https://sourceware.org/glibc/manual/latest/html_mono/libc.html#Variadic-Prototypes + * + * see (in glibc/manual) > ellipsis (‘…’) A.2.2.2 Receiving the Argument Values + * + * --- + * + * NB 'at ref' desactivated TODO + * + * @callergraph + * @see on_app_activation() + * + * @param *str + * @param ... + * + * @return * + */ +char * +util_concat (const char *str, ...) +{ + size_t allocated = 100; + char *result = malloc (allocated); + + if (result != NULL) + { + va_list ap; + size_t resultlen = 0; + char *newp; + + va_start (ap, str); + + for (const char *s = str; s != NULL; s = va_arg (ap, const char *)) + { + size_t len = strlen (s); + + /* Resize the allocated memory if necessary. */ + if (resultlen + len + 1 > allocated) + { + allocated += len; + newp = reallocarray (result, allocated, 2); + allocated *= 2; + if (newp == NULL) + { + free (result); + return NULL; + } + result = newp; + } + + memcpy (result + resultlen, s, len); + resultlen += len; + } + + /* Terminate the result string. */ + result[resultlen++] = '\0'; + + /* Resize memory to the optimal size. */ + newp = realloc (result, resultlen); + if (newp != NULL) + result = newp; + + va_end (ap); + } + + return result; +} + diff --git a/src/widget/main_window/design.c b/src/widget/main_window/design.c index 20bb98f..def7ed1 100644 --- a/src/widget/main_window/design.c +++ b/src/widget/main_window/design.c @@ -42,7 +42,7 @@ void widget_design_main_window (GtkWindow *main_window, GtkApplication *app) { fsm_add_log (INFO, TOPBAR, "widget/main_window/design", - "main window", "start of design"); + __func__, "start of design"); /* GtkWidget *topbar = GTK_WIDGET (gtk_header_bar_new ()); */ @@ -58,5 +58,5 @@ void widget_design_main_window (GtkWindow *main_window, GtkApplication *app) // g_object_unref (e_coli); fsm_add_log (INFO, TOPBAR, "widget/main_window/design", - "main window", "ready for presentation"); + __func__, "end of design -> present"); } diff --git a/src/widget/manager.c b/src/widget/manager.c index 95ae579..0a23489 100644 --- a/src/widget/manager.c +++ b/src/widget/manager.c @@ -32,6 +32,7 @@ #include "../../include/widget.h" #include "../../include/fsm.h" +#include "../../include/util.h" #include @@ -57,7 +58,7 @@ static GtkWindow *window; */ void on_app_activation (GtkApplication *app) { - fsm_add_log (INFO, WIDGETS, "widget/manager", "app activation()", "has began"); + fsm_add_log (INFO, WIDGETS, "widget/manager", __func__, "has began"); // on_windows_activation() is in: widget/manager NOT in: src/signal // g_application_activate (G_APPLICATION (app)); < how ? > in main is @@ -82,13 +83,9 @@ void on_app_activation (GtkApplication *app) g_signal_connect(window, "close-request", G_CALLBACK (on_window_close_request), (void *)(long long)window_int_id); - //printf ("gtk_application_window_id = %s = %d\n", window_char_id, window_int_id); - - fsm_add_log (INFO, WIDGETS, "widget/manager", "gtk_application_window_get_id", - window_char_id);//"sprintf(window_id,...) << fails. Why ?"); - - //printf ("gtk_application_window_get_id (main_window) = %d\n", - //gtk_application_window_get_id (GTK_APPLICATION_WINDOW (main_window))); + char *temp = util_concat ("window_get_id = ", window_char_id, NULL); + fsm_add_log (INFO, WIDGETS, "widget/manager", __func__, temp); + free(temp); widget_design_main_window (window, app); @@ -117,14 +114,14 @@ void on_app_activation (GtkApplication *app) g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (act_b)); g_signal_connect (act_b, "activate", G_CALLBACK (action_b), app2);*/ - fsm_add_log (INFO, WIDGETS, "widget/manager", "app activation()", + fsm_add_log (INFO, WIDGETS, "widget/manager", __func__, "has ended 🧐️ | 👉️ a new session starts"); } gboolean on_window_close_request (GtkWindow *window, gpointer user_data) { - fsm_add_log (INFO, WIDGETS, "widget/manager", "window close request()", + fsm_add_log (INFO, WIDGETS, "widget/manager", __func__, "freeing all ressources !"); // free the only child