gol

Implementation of Conway's Game of Life writen in C
git clone git://git.dimitrijedobrota.com/gol.git
Log | Files | Refs | README

commit 1097adf7f863b6563435ade0fac1afccaef8562d
parent 4f55093368c0317d02ece802e39924d02d2c9cce
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Tue,  7 Jun 2022 15:59:47 +0200

General improvement and bug fixing

- Add memory safety
- Better program termination
- Empty file list realloc fixed
- Empty menus display appropriate message
- On Linux system home directory is used as a base of settings dir

Diffstat:
Minclude/utils.h | 8++++++++
Msrc/display.c | 24+++++++++++++-----------
Msrc/file.c | 60++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/game.c | 9++++-----
Msrc/logic.c | 8+++-----
Msrc/main.c | 15++++++++-------
Msrc/window.c | 4+++-
7 files changed, 79 insertions(+), 49 deletions(-)

diff --git a/include/utils.h b/include/utils.h @@ -2,6 +2,7 @@ #define UTILS_H #include <curses.h> +#include "display.h" #define MAX(a, b) ((a > b) ? a : b) #define MIN(a, b) ((a < b) ? a : b) @@ -30,4 +31,11 @@ #define MAX_SCREEN_H 512 #define MAX_SCREEN_W 1888 +#define MEM_CHECK(x) \ + if ((x) == NULL) { \ + display_stop(); \ + printf("MEM GRESKA"); \ + abort(); \ + } + #endif diff --git a/src/display.c b/src/display.c @@ -175,6 +175,17 @@ redraw:; while (TRUE) { CLAMP(current, 0, size - 1); + if (!size) { + char *message = "NOTHING TO DISPLAY HERE!"; + wcenter_horizontal(wind, y_offset, strlen(message)); + waddstr(win, message); + wrefresh(win); + nodelay(stdscr, 0); + getch(); + nodelay(stdscr, 1); + return; + } + for (int i = 0; i < size; i++) { wattrset(win, COLOR_PAIR(i == current ? 1 : 0)); wcenter_horizontal(wind, y_offset + i * 2, maxi); @@ -245,11 +256,6 @@ void curses_start(void) { #endif } -void curses_stop(void) { - window_free(MAIN_w); - endwin(); -} - void handle_winch(int sig) { endwin(); refresh(); @@ -260,10 +266,6 @@ void handle_winch(int sig) { } int display_start(void) { - /* #ifndef _WIN32 */ - /* signal(SIGWINCH, handle_winch); */ - /* #endif */ - curses_start(); MAIN_w = window_init(window_new()); @@ -276,7 +278,8 @@ int display_start(void) { } int display_stop(void) { - curses_stop(); + window_free(MAIN_w); + endwin(); return 1; } @@ -291,7 +294,6 @@ redraw:; WINDOW *win = window_win(wind); int ph = window_height(wind), pw = window_wight(wind); int y, x, maxi, max_x; - int count; x = x_start; for (int i = 0; i < pattern_groups_s; i++) { diff --git a/src/file.c b/src/file.c @@ -1,3 +1,4 @@ +#include <limits.h> #include <stdlib.h> #include <string.h> @@ -15,7 +16,7 @@ #define SETTINGS_DIR "C:\\GoL" // without trailing '\' #define MAKE_DIR(dir) (mkdir(dir)) #else -#define SETTINGS_DIR "/home/magaknuto/GoL" +#define SETTINGS_DIR "GoL" #define MAKE_DIR(dir) (mkdir(dir, 0777)) #endif // _WIN32 @@ -29,14 +30,14 @@ file_T loaded_files; file_T file_new(char *name) { file_T f; - f = malloc(sizeof(*f)); + MEM_CHECK(f = malloc(sizeof(*f))); f->next = NULL; if (name == NULL) { f->name = NULL; return f; } - f->name = malloc((strlen(name) + 1) * sizeof(char)); + MEM_CHECK(f->name = malloc((strlen(name) + 1) * sizeof(char))); strcpy(f->name, name); return f; } @@ -91,13 +92,26 @@ file_T file_find(file_T self, char *name) { } int file_setup(void) { - if (!DirectoryExists(SETTINGS_DIR)) { - if (MAKE_DIR(SETTINGS_DIR) != 0) { + char *dir; + MEM_CHECK(dir = malloc(PATH_MAX * sizeof(char))); + +#ifdef _WIN32 + strcpy(dir, SETTINGS_DIR); +#else + const char *homedir = getenv("HOME"); + sprintf(dir, "%s/%s", homedir, SETTINGS_DIR); +#endif + + if (!DirectoryExists(dir)) { + printf("Directory %s does not exists; Trying to create it...\n", dir); + if (MAKE_DIR(dir) != 0) { + printf("Cannot create the directory\n"); return 0; } } - if (chdir(SETTINGS_DIR) != 0) { + if (chdir(dir) != 0) { + printf("Cannot change the directory\n"); return 0; } return 1; @@ -106,10 +120,10 @@ int file_setup(void) { int file_select(char *ext, char ***buffer) { int maxsize = 4; int size = 0; - char **tmp; + char **tmp = NULL; file_T current = loaded_files; - *buffer = malloc(maxsize * sizeof(char *)); + MEM_CHECK(*buffer = malloc(maxsize * sizeof(char *))); for (; current != NULL; current = current->next) { char *dot = strrchr(current->name, '.'); if (dot == NULL) @@ -119,17 +133,16 @@ int file_select(char *ext, char ***buffer) { (*buffer)[size++] = current->name; if (size == maxsize) { maxsize *= 2; - tmp = realloc(*buffer, maxsize * sizeof(char *)); - if (!tmp) - exit(1); + MEM_CHECK(tmp = realloc(*buffer, maxsize * sizeof(char *))); *buffer = tmp; } } } - tmp = realloc(*buffer, size * sizeof(char *)); - if (!tmp) - exit(1); - *buffer = tmp; + if (size) { + MEM_CHECK(tmp = realloc(*buffer, size * sizeof(char *))); + *buffer = tmp; + } + return size; } @@ -149,7 +162,9 @@ extern int save_cells_s, pos_y, pos_x, evolve_index; extern int width, height; void file_load_pattern(char *name, int index) { - char *fname = malloc((strlen(name) + 5) * sizeof(char)); + char *fname; + + MEM_CHECK(fname = malloc((strlen(name) + 5) * sizeof(char))); sprintf(fname, "%s.part", name); FILE *f = fopen(fname, "r"); @@ -163,7 +178,9 @@ void file_load_pattern(char *name, int index) { } void file_save_pattern(char *name, int index) { - char *fname = malloc((strlen(name) + 5) * sizeof(char)); + char *fname; + + MEM_CHECK(fname = malloc((strlen(name) + 5) * sizeof(char))); sprintf(fname, "%s.part", name); FILE *f = fopen(fname, "w"); @@ -187,9 +204,10 @@ void file_save_pattern(char *name, int index) { } void file_load(char *name, int index) { - int w, h; + char *fname; + int w, h; - char *fname = malloc((strlen(name) + 5) * sizeof(char)); + MEM_CHECK(fname = malloc((strlen(name) + 5) * sizeof(char))); sprintf(fname, "%s.all", name); FILE *f = fopen(fname, "r"); @@ -206,7 +224,9 @@ void file_load(char *name, int index) { } void file_save(char *name, int index) { - char *fname = malloc((strlen(name) + 5) * sizeof(char)); + char *fname; + + MEM_CHECK(fname = malloc((strlen(name) + 5) * sizeof(char))); sprintf(fname, "%s.all", name); FILE *f = fopen(fname, "w"); diff --git a/src/game.c b/src/game.c @@ -159,18 +159,22 @@ int display_select(window_T wind) { // offset selection case 'w': case 'W': + case KEY_UP: current_offset_y--; break; case 's': case 'S': + case KEY_DOWN: current_offset_y++; break; case 'a': case 'A': + case KEY_LEFT: current_offset_x--; break; case 'd': case 'D': + case KEY_RIGHT: current_offset_x++; break; @@ -200,10 +204,6 @@ int display_select(window_T wind) { case 'q': case 'Q': goto end; - - defalut: - flushinp(); - continue; } flushinp(); @@ -229,7 +229,6 @@ end:; void game(int s_h, int s_w, int mode_index) { char *mode_name = evolution_names[mode_index]; - int ncells = evolution_cells[mode_index]; int t_y = 0, t_x = 0, ct_x = 0, ct_y = 0; int gen = 0, gen_step = 1, play = 0, time_const = 100, time_step = 1; diff --git a/src/logic.c b/src/logic.c @@ -28,7 +28,7 @@ void insert(int row, int col, int val, int mod) { c = get(row, col); if (c == NULL) { - c = malloc(sizeof(Cell)); + MEM_CHECK(c = malloc(sizeof(Cell))); c->cord.row = row; c->cord.col = col; c->val = val; @@ -276,7 +276,7 @@ void do_evolution(int steps) { int logic_init(int isWrapping, int index) { save_cells_s = 0; save_cells_sm = 100; - save_cells = malloc(save_cells_sm * sizeof(struct Cell *)); + MEM_CHECK(save_cells = malloc(save_cells_sm * sizeof(struct Cell *))); addToCells = addition_modes[isWrapping]; evolve = evolution_modes[index]; @@ -342,9 +342,7 @@ void saveCell(int i, int j) { if (save_cells_s == save_cells_sm) { Cell **t; save_cells_sm *= 2; - t = realloc(save_cells, save_cells_sm); - if (!t) - exit(1); + MEM_CHECK(t = realloc(save_cells, save_cells_sm)); save_cells = t; } diff --git a/src/main.c b/src/main.c @@ -13,7 +13,7 @@ #include "window.h" extern window_T MAIN_w; -window_T menu_w; +window_T menu_w; void settings(char *pass, int index) { struct imenu_T imenu_items[] = { @@ -38,7 +38,9 @@ void settings(char *pass, int index) { } void mode_select(char *pass, int index) { - struct menu_T *mode_items = malloc(evolution_size * sizeof(struct menu_T)); + struct menu_T *mode_items; + + MEM_CHECK(mode_items = malloc(evolution_size * sizeof(struct menu_T))); for (int i = 0; i < evolution_size; i++) { mode_items[i].name = evolution_names[i]; mode_items[i].callback = settings; @@ -70,13 +72,14 @@ void new_file(char *pass, int index) { struct menu_T *file_menu_list(char *ext, void (*callback)(char *, int), int offset, int *size) { - char **buffer; - int n; + struct menu_T *file_items; + char **buffer; + int n; load_files(); n = file_select(ext, &buffer); - struct menu_T *file_items = malloc((n + offset) * sizeof(struct menu_T)); + MEM_CHECK(file_items = malloc((n + offset) * sizeof(struct menu_T))); for (int i = 0; i < n; i++) { file_items[i + offset].name = buffer[i]; file_items[i + offset].callback = callback; @@ -162,8 +165,6 @@ int main(void) { display_menu(menu_w, "Main menu", menu_items, menu_items_s, 1); } - window_free(MAIN_w); - if (!display_stop()) { printf("Couldn't stop the display!\n"); abort(); diff --git a/src/window.c b/src/window.c @@ -41,7 +41,9 @@ WINDOW *WINDOW_new(T self) { } T window_new(void) { - T self = malloc(sizeof(*self)); + T self; + + MEM_CHECK(self = malloc(sizeof(*self))); self->win = NULL; self->c1 = NULL; self->c2 = NULL;