golImplementation 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 13: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:M | include/utils.h | | | ++++++++ |
M | src/display.c | | | +++++++++++++----------- |
M | src/file.c | | | ++++++++++++++++++++++++++++++++++++++++-------------------- |
M | src/game.c | | | ++++----- |
M | src/logic.c | | | +++----- |
M | src/main.c | | | ++++++++------- |
M | src/window.c | | | +++- |
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;