home · contact · privacy
Heavy refactoring of all file I/O and some memory handling; also repaired some incons...
authorChristian Heller <c.heller@plomlompom.de>
Thu, 5 Sep 2013 04:08:48 +0000 (06:08 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 5 Sep 2013 04:08:48 +0000 (06:08 +0200)
18 files changed:
config/windows/Win_i
config/windows/Win_k
config/windows/Win_l
config/windows/Win_m
config/windows/toggle_order
src/command_db.c
src/draw_wins.c
src/keybindings.c
src/keybindings.h
src/main.c
src/map.c
src/map_object_actions.c
src/map_objects.c
src/misc.c
src/misc.h
src/readwrite.c
src/readwrite.h
src/wincontrol.c

index 948c2ecfb2823a129b192f4e88207d36266569b3..9751da91f6a4adb3ca89de08ca41b1faca1625d6 100644 (file)
@@ -1,3 +1,3 @@
 Info
 3
-12
+33
index 67c674e6aab800b491c790b1a08f516a7b19ee48..a719bf397ebd866b56abc84e5fa32a620134fef9 100644 (file)
@@ -1,3 +1,3 @@
 Keys
 0
-42
+29
index 023229d284e797e9732419753bdc504f612018d0..d31eb53521a7a222555233ae8f40a8b1e10c3a40 100644 (file)
@@ -1,3 +1,3 @@
 Log
 -4
-12
+33
index cd42830b5e8b613491e5c2a76aa5c8cc65f8c01a..ef4cd118c6b056f3766d725e5515ae075f8921ea 100644 (file)
@@ -1,3 +1,3 @@
 Map
 0
--56
+-64
index e45bc97b8a13335f490234c8fafbddd033fd5fde..0b431e986ec3c367255d43c72b706180aa8a0aeb 100644 (file)
@@ -1,2 +1 @@
 kmil
-\7f
\ No newline at end of file
index 61ae4b11ba718777de7af6292249b687cd8c6cd3..0bf7c84d7aa8b36a69b81f32f7ac31308aaa95a6 100644 (file)
@@ -1,25 +1,24 @@
 /* command.c */
 
 #include "command_db.h"
-#include <stdlib.h> /* for malloc() */
-#include <stdio.h> /* for FILE typedef, fopen(), fclose(), fgets() */
+#include <stdlib.h> /* for free() */
+#include <stdio.h> /* for FILE typedef, fgets() */
 #include <stdint.h> /* for uint8_t */
 #include <string.h> /* for strlen(), strtok() */
 #include "main.h" /* for World struct */
 #include "rexit.h" /* for exit_err() */
-#include "readwrite.h" /* for textfile_sizes() */
+#include "readwrite.h" /* for textfile_sizes(), try_fopen(), try_fclose() */
+#include "misc.h" /* for try_malloc() */
 
 
 
-/* Build string pointed to by "ch_ptr" from next token delimited by "delim",
- * exit_err() with "err" as error message on malloc() failure.
- */
-static void copy_tokenized_string(struct World * world,
-                                 char ** ch_ptr, char * delim, char * err)
+/* Build string pointed to by "ch_ptr" from next token delimited by "delim". */
+static void copy_tokenized_string(struct World * world, char ** ch_ptr,
+                                  char * delim)
 {
+    char * f_name = "copy_tokenized_string()";
     char * dsc_ptr = strtok(NULL, delim);
-    * ch_ptr = malloc(strlen(dsc_ptr) + 1);
-    exit_err(NULL == * ch_ptr, world, err);
+    * ch_ptr = try_malloc(strlen(dsc_ptr) + 1, world, f_name);
     memcpy(* ch_ptr, dsc_ptr, strlen(dsc_ptr) + 1);
 }
 
@@ -77,31 +76,28 @@ extern char * get_command_longdsc(struct World * world, char * dsc_short)
 
 extern void init_command_db(struct World * world)
 {
-    char * err_o = "Trouble in init_cmds() with fopen() on file 'commands'.";
+    char * f_name = "init_command_db()";
     char * err_s = "Trouble in init_cmds() with textfile_sizes().";
-    char * err_m = "Trouble in init_cmds() with malloc().";
-    char * err_c = "Trouble in init_cmds() with fclose() on file 'commands'.";
 
     char * path = "config/commands";
-    FILE * file = fopen(path, "r");
-    exit_err(NULL == file, world, err_o);
+    FILE * file = try_fopen(path, "r", world, f_name);
     uint16_t lines, linemax;
     exit_err(textfile_sizes(file, &linemax, &lines), world, err_s);
     char line[linemax + 1];
 
-    struct Command * cmds = malloc(lines * sizeof(struct Command));
-    exit_err(NULL == line, world, err_m);
+    struct Command * cmds = try_malloc(lines * sizeof(struct Command),
+                                       world, f_name);
     uint8_t i = 0;
     while (fgets(line, linemax + 1, file))
     {
         cmds[i].id = atoi(strtok(line, " "));
-        copy_tokenized_string(world, &cmds[i].dsc_short, " ", err_m);
-        copy_tokenized_string(world, &cmds[i].dsc_long, "\n", err_m);
+        copy_tokenized_string(world, &cmds[i].dsc_short, " ");
+        copy_tokenized_string(world, &cmds[i].dsc_long, "\n");
         i++;
     }
-    exit_err(fclose(file), world, err_c);
+    try_fclose(file, world, f_name);
 
-    world->cmd_db = malloc(sizeof(struct CommandDB));
+    world->cmd_db = try_malloc(sizeof(struct CommandDB), world, f_name);
     world->cmd_db->cmds = cmds;
     world->cmd_db->n = lines;
 }
index b036d12c023f95a42c5962f591471da19ddde53c..5d395f64f8d0e726848ec1d630ba6ef431256583 100644 (file)
@@ -1,7 +1,7 @@
 /* draw_wins.c */
 
 #include "draw_wins.h"
-#include <stdlib.h>      /* for malloc(), free() */
+#include <stdlib.h>      /* for free() */
 #include <stdint.h>      /* for uint16_t */
 #include <string.h>      /* for strlen() */
 #include <ncurses.h>     /* for mvwaddch() */
@@ -214,13 +214,12 @@ extern void draw_info_win(struct Win * win)
     char * dsc_score     = "\nScore: ";
     uint16_t maxl = strlen(dsc_turn) + strlen(dsc_hitpoints) + strlen(dsc_score)
                     + 10 + 5 + 10;       /* max strlens of numbers to be used */
-    char * text = malloc(maxl + 1);
+    char text[maxl + 1];
     sprintf(text, "%s%d%s%d%s%d",
             dsc_turn, world->turn,
             dsc_hitpoints, world->player->hitpoints,
             dsc_score, world->score);
     draw_with_linebreaks(win, text, 0);
-    free(text);
 }
 
 
@@ -232,7 +231,8 @@ extern void draw_keys_win(struct Win * win)
     offset = center_offset(world->keyswindata->select, world->keyswindata->max,
                            win->frame.size.y - 1);
     uint8_t keydescwidth = 9 + 1; /* max length assured by get_keyname() + \0 */
-    char * keydesc = malloc(keydescwidth), * keyname;
+    char keydesc[keydescwidth];
+    char * keyname;
     char * err_hint = "Trouble with draw_scroll_hint() in draw_keys_win().";
     attr_t attri;
     char * cmd_dsc;
@@ -263,7 +263,7 @@ extern void draw_keys_win(struct Win * win)
                 attri = attri | A_BLINK;
             }
         }
-        keyname = get_keyname(world->keybindings[y + offset].key);
+        keyname = get_keyname(world, world->keybindings[y + offset].key);
         snprintf(keydesc, keydescwidth, "%-9s", keyname);
         free(keyname);
         cmd_dsc = get_command_longdsc(world,
@@ -286,7 +286,6 @@ extern void draw_keys_win(struct Win * win)
             }
         }
     }
-    free(keydesc);
 }
 
 
@@ -317,9 +316,8 @@ extern void draw_winconf(struct Win * win)
     uint16_t maxl = strlen(title)
                     + strlen(h_t_d) + strlen(h_t) + strlen(h_d) + 6
                     + strlen(w_t_d) + strlen(w_t) + strlen(w_d) + 6 + 1;
-    char * text = malloc(maxl + 1);
+    char text[maxl + 1];
     sprintf(text, "%s%s%s%s%d%s%s%s%d", title, h_t_d, h_t, h_d, wcp->height,
                                                w_t_d, w_t, w_d, wcp->width);
     draw_with_linebreaks(win, text, 0);
-    free(text);
 }
index 75fe72826a3ec15cbf642afedac05d08ea90b364..92e4d6dd3c7c2f4920f0962aeaac2ec62fcf69c2 100644 (file)
@@ -1,41 +1,46 @@
 /* keybindings.c */
 
-
-
 #include "keybindings.h"
-#include <stdlib.h>    /* for malloc(), free(), atoi() */
+#include <stdio.h>     /* for FILE typedef*/
+#include <stdlib.h>    /* for free(), atoi() */
 #include <stdint.h>    /* for uint16_t */
 #include <ncurses.h>   /* for keycode defines in get_keyname() */
 #include <string.h>    /* for strchr(), strlen(), strcmp(), memcpy()*/
 #include "windows.h"   /* for draw_all_wins() and WinMeta struct */
-#include "readwrite.h" /* for texfile_sizes() */
+#include "readwrite.h" /* for texfile_sizes(), try_fopen(), try_fclose()
+                        * try_fclose_unlink_rename()
+                        */
 #include "main.h"      /* for World struct */
 #include "rexit.h"     /* for err_exit() */
+#include "misc.h"      /* for try_malloc() */
 
 
 
 extern void init_keybindings(struct World * world)
 {
-    FILE * file = fopen("config/keybindings", "r");
+    char * f_name = "init_keybindings()";
+    char * path = "config/keybindings";
+    FILE * file = try_fopen(path, "r", world, f_name);
     uint16_t lines, linemax;
     char * err = "textfile_sizes() in init_keybindings() returns error.";
     exit_err(textfile_sizes(file, &linemax, &lines), world, err);
-    struct KeyBinding * keybindings = malloc(lines * sizeof(struct KeyBinding));
-    char * command = malloc(linemax + 1);
+    struct KeyBinding * keybindings;
+    keybindings = try_malloc(lines * sizeof(struct KeyBinding), world, f_name);
+    char command[linemax + 1];
     uint16_t commcount = 0;
     char * cmdptr;
     while (fgets(command, linemax + 1, file))
     {
         keybindings[commcount].key = atoi(command);
         cmdptr = strchr(command, ' ') + 1;
-        keybindings[commcount].name = malloc(strlen(cmdptr));
+        keybindings[commcount].name = try_malloc(strlen(cmdptr), world, f_name);
         memcpy(keybindings[commcount].name, cmdptr, strlen(cmdptr) - 1);
         keybindings[commcount].name[strlen(cmdptr) - 1] = '\0';
         commcount++;
     }
-    free(command);
-    fclose(file);
-    struct KeysWinData * keyswindata = malloc(sizeof(struct KeysWinData));
+    try_fclose(file, world, f_name);
+    struct KeysWinData * keyswindata;
+    keyswindata = try_malloc(sizeof(struct KeysWinData), world, f_name);
     keyswindata->max = lines - 1;
     keyswindata->select = 0;
     keyswindata->edit = 0;
@@ -47,10 +52,13 @@ extern void init_keybindings(struct World * world)
 
 extern void save_keybindings(struct World * world)
 {
+    char * f_name = "save_keybindings()";
     struct KeysWinData * keyswindata = (struct KeysWinData *)
                                        world->keyswindata;
     struct KeyBinding * keybindings = world->keybindings;
-    FILE * file = fopen("config/keybindings", "w");
+    char * path     = "config/keybindings";
+    char * path_tmp = "config/keybindings_tmp";
+    FILE * file = try_fopen(path_tmp, "w", world, f_name);
     uint16_t linemax = 0;
     uint16_t i;
     for (i = 0; i <= keyswindata->max; i++)
@@ -61,15 +69,14 @@ extern void save_keybindings(struct World * world)
         }
     }
     linemax = linemax + 6;         /* + 6 = + 3 digits + whitespace + \n + \0 */
-    char * line = malloc(linemax);
+    char line[linemax];
     for (i = 0; i <= keyswindata->max; i++)
     {
         snprintf(line, linemax,
                  "%d %s\n", keybindings[i].key, keybindings[i].name);
         fwrite(line, sizeof(char), strlen(line), file);
     }
-    free(line);
-    fclose(file);
+    try_fclose_unlink_rename(file, path_tmp, path, world, f_name);
 }
 
 
@@ -86,10 +93,10 @@ extern uint16_t get_action_key(struct KeyBinding * keybindings, char * name)
 
 
 
-extern char * get_keyname(uint16_t keycode)
+extern char * get_keyname(struct World * world, uint16_t keycode)
 {
-    char * keyname;
-    keyname = malloc(15);
+    char * f_name = "get_keyname()";
+    char * keyname = try_malloc(15, world, f_name);
     if (32 < keycode && keycode < 127)
     {
         sprintf(keyname, "%c", keycode);
index 085de9af4532447f156c9d8d8c05ccd620490ccc..e0fdadb7a0818b9826f246d3e85c16e0862935cd 100644 (file)
@@ -45,7 +45,7 @@ extern uint16_t get_action_key(struct KeyBinding * keybindings, char * name);
 
 
 /* Translate keycode to readable names of max 9 chars where possible. */
-extern char * get_keyname(uint16_t keycode);
+extern char * get_keyname(struct World * world, uint16_t keycode);
 
 
 
index fcf677ea4c55c92ff34710c21132accbde34cf40..0cdcaf16293db6472075f472c6ac09aacf29b1a9 100644 (file)
@@ -1,13 +1,12 @@
 /* main.c */
 
 #include "main.h"
-#include <stdlib.h> /* for atoi(), exit(), EXIT_FAILURE, calloc() */
-#include <stdio.h> /* for FILE typedef, F_OK, rename() */
+#include <stdlib.h> /* for atoi(), exit(), EXIT_FAILURE */
+#include <stdio.h> /* for FILE typedef, F_OK */
 #include <ncurses.h> /* for initscr(), noecho(), curs_set(), keypad(), raw() */
 #include <time.h> /* for time() */
 #include <unistd.h> /* for getopt(), optarg */
 #include <stdint.h> /* for uint16_t, uint32_t */
-#include <errno.h> /* for errno */
 #include "windows.h" /* for structs WinMeta, Win, init_win(), init_win_meta(),
                       * draw_all_wins()
                       */
                         * draw_log_win()
                         */
 #include "keybindings.h" /* for init_keybindings(), get_action_key() */
-#include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian]() */
+#include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian](),
+                        * try_fopen(), try_fclose(), try_fclose_unlink_renmae()
+                        */
 #include "map_objects.h" /* for structs Monster, Item, Player,
                           * init_map_object_defs(), read_map_objects(),
                           * build_map_objects()
                           */
 #include "map.h" /* for struct Map, init_map() */
-#include "misc.h" /* for update_log(), find_passable_pos(), save_game() */
+#include "misc.h" /* for update_log(), find_passable_pos(), save_game(),
+                   * try_calloc(), check_tempfile(), check_xor_files()
+                   */
 #include "wincontrol.h" /* for create_winconfs(), init_winconfs(), init_wins(),
                          * sorted_wintoggle()
                          */
 #include "rrand.h" /* for rrand(), rrand_seed() */
-#include "rexit.h" /* for exit_game() */
+#include "rexit.h" /* for exit_game(), exit_err() */
 #include "control.h" /* for meta_control() */
 #include "command_db.h" /* for init_command_db() */
 
@@ -34,6 +37,7 @@
 
 int main(int argc, char *argv[])
 {
+    char * f_name = "main()";
     struct World world;
     world.turn = 0;        /* Turns to 1 when map and objects are initalized. */
 
@@ -45,30 +49,14 @@ int main(int argc, char *argv[])
     char * savefile = "savefile";
     char * recordfile_tmp = "record_tmp";
     char * savefile_tmp   = "savefile_tmp";
-    char * err_x = "A file 'record' exists, but no 'savefile'. If everything "
-                   "was in order, both or none would exist. I won't start "
-                   "until this is corrected.";
-    if (!access(recordfile, F_OK) && access(savefile, F_OK))
-    {
-        errno = 0;
-        exit_err(1, &world, err_x);
-    }
-    err_x        = "A 'savefile' exists, but no file 'record'. If everything "
-                   "was in order, both or none would exist. I won't start "
-                   "until this is corrected.";
-    if (!access(savefile, F_OK) && access(recordfile, F_OK))
-    {
-        errno = 0;
-        exit_err(1, &world, err_x);
-    }
-    err_x        = "A file 'recordfile_tmp' exists, probably from a corrupted "
-                   "previous record saving process. To avoid game record "
-                   "corruption, I won't start until it is removed or renamed.";
-    exit_err(!access(recordfile_tmp, F_OK), &world, err_x);
-    err_x        = "A file 'savefile_tmp' exists, probably from a corrupted "
-                   "previous game saving process. To avoid savegame "
-                   "corruption, I won't start until it is removed or renamed.";
-    exit_err(!access(savefile_tmp,   F_OK), &world, err_x);
+    check_files_xor(savefile, recordfile, &world);
+    check_tempfile(recordfile_tmp, &world);
+    check_tempfile(savefile_tmp, &world);
+    check_tempfile("config/windows/Win_tmp_k", &world);
+    check_tempfile("config/windows/Win_tmp_m", &world);
+    check_tempfile("config/windows/Win_tmp_i", &world);
+    check_tempfile("config/windows/Win_tmp_l", &world);
+    check_tempfile("config/windows/toggle_order_tmp", &world);
 
     /* Read in startup options (i.e. replay option and replay start turn). */
     int opt;
@@ -97,7 +85,7 @@ int main(int argc, char *argv[])
 
     /* Initialize log, player, monster/item definitions and monsters/items. */
     world.score = 0;
-    world.log = calloc(1, sizeof(char));
+    world.log = try_calloc(1, sizeof(char), &world, f_name);
     set_cleanup_flag(CLEANUP_LOG);
     update_log(&world, " ");
     struct Player player;
@@ -109,17 +97,12 @@ int main(int argc, char *argv[])
     set_cleanup_flag(CLEANUP_MAP_OBJECT_DEFS);
 
     /* For interactive mode, try to load world state from savefile. */
-    char * err_o = "Trouble loading game (fopen() in main()) / "
-                   "opening 'savefile' for reading.";
     char * err_r = "Trouble loading game (in main()) / "
                    "reading from opened 'savefile'.";
-    char * err_c = "Trouble loading game (fclose() in main()) / "
-                   "closing opened 'savefile'.";
     FILE * file;
     if (1 == world.interactive && 0 == access(savefile, F_OK))
     {
-        file = fopen(savefile, "r");
-        exit_err(0 == file, &world, err_o);
+        file = try_fopen(savefile, "r", &world, f_name);
         if (   read_uint32_bigendian(file, &world.seed)
             || read_uint32_bigendian(file, &world.turn)
             || read_uint16_bigendian(file, &world.score)
@@ -132,7 +115,7 @@ int main(int argc, char *argv[])
             exit_err(1, &world, err_r);
         }
         set_cleanup_flag(CLEANUP_MAP_OBJECTS);
-        exit_err(fclose(file), &world, err_c);
+        try_fclose(file, &world, f_name);
         player.pos.y--;
         player.pos.x--;
     }
@@ -140,14 +123,11 @@ int main(int argc, char *argv[])
     /* For non-interactive mode, try to load world state from record file. */
     else
     {
-        err_o = "Trouble loading record file (fopen() in main()) / "
-                "opening file 'record' for reading.";
-        err_r = "Trouble loading record file (read_uint32_bigendian() in "
-                "main()) / reading from opened file 'record'.";
+        err_r = "Trouble reading from 'record' file (read_uint32_bigendian() in "
+                "main()).";
         if (0 == world.interactive)
         {
-            file = fopen(recordfile, "r");
-            exit_err(NULL == file, &world, err_o);
+            file = try_fopen(recordfile, "r", &world, f_name);
             exit_err(read_uint32_bigendian(file, &world.seed), &world, err_r);
         }
 
@@ -158,20 +138,13 @@ int main(int argc, char *argv[])
         {
             world.seed = time(NULL);
 
-            err_o        = "Trouble recording new seed (fopen() in main()) / "
-                           "opening 'record_tmp' file for writing.";
             char * err_w = "Trouble recording new seed "
                            "(write_uint32_bigendian() in main()) / writing to "
-                           "opened file 'record_tmp'.";
-            err_c        = "Trouble recording new seed (fclose() in main()) / "
-                           "closing opened file 'record_tmp'.";
-            char * err_m = "Trouble recording new seed (rename() in main()) : "
-                           "renaming file 'record_tmp' to 'record'.";
-            file = fopen(recordfile_tmp, "w");
-            exit_err(0 == file, &world, err_o);
+                           "file 'record_tmp'.";
+            file = try_fopen(recordfile_tmp, "w", &world, f_name);
             exit_err(write_uint32_bigendian(world.seed, file), &world, err_w);
-            exit_err(fclose(file), &world, err_c);
-            exit_err(rename(recordfile_tmp, recordfile), &world, err_m);
+            try_fclose_unlink_rename(file, recordfile_tmp, recordfile,
+                                    &world, f_name);
         }
     }
 
@@ -207,7 +180,6 @@ int main(int argc, char *argv[])
     char * err_winmem = "Trouble with init_win_meta() in main ().";
     exit_err(init_win_meta(screen, &world.wmeta), &world, err_winmem);
     set_cleanup_flag(CLEANUP_WIN_META);
-    // create_winconfs(&world);
     init_winconfs(&world);
     set_cleanup_flag(CLEANUP_WINCONFS);
     init_wins(&world);
@@ -247,8 +219,7 @@ int main(int argc, char *argv[])
             }
             else if (meta_control(key, &world))
             {
-                err_c = "Trouble closing 'record' file (fclose() in main()).";
-                exit_err(fclose(file), &world, err_c);
+                try_fclose(file, &world, f_name);
                 exit_game(&world);
             }
         }
index a9750434281c32d97ac2679b6ba074747ae7b631..94def7631c69527f0163847db13027eef0f54e84 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -1,22 +1,23 @@
 #include "map.h"
-#include <stdlib.h>      /* for malloc() */
 #include <stdint.h>      /* for uint16_t, uint32_t */
-#include "misc.h"        /* for center_offset() */
+#include "misc.h"        /* for try_malloc(), center_offset() */
 #include "map_objects.h" /* for Player struct */
 #include "yx_uint16.h"   /* for yx_uint16 and dir enums */
 #include "rrand.h"       /* for rrand() */
+struct World;
 
 
 
-struct Map init_map ()
+struct Map init_map(struct World * world)
 {
+    char * f_name = "init_map()";
     struct Map map;
     map.size.x = 64;
     map.size.y = 64;
     map.offset.x = 0;
     map.offset.y = 0;
     uint32_t size = map.size.x * map.size.y;
-    map.cells = malloc(size);
+    map.cells = try_malloc(size, world, f_name);
     uint16_t y, x;
     for (y = 0; y < map.size.y; y++)
     {
index 97f33d6e4eb947074f8c60ff30ce308c72303a3e..1b1433949599d5792cf7f1540bc56347d3b87663 100644 (file)
@@ -1,10 +1,10 @@
 /* map_object_actions.c */
 
 #include "map_object_actions.h"
-#include <stdlib.h> /* for malloc(), calloc(), free() */
+#include <stdlib.h> /* for free() */
 #include <string.h> /* for strlen() */
 #include "yx_uint16.h" /* for yx_uint16 struct, mv_yx_in_dir(), yx_uint16_cmp */
-#include "misc.h" /* for update_log(), turn_over()*/
+#include "misc.h" /* for update_log(), turn_over(), try_malloc() */
 #include "map.h" /* for Map struct */
 #include "main.h" /* for World struct */
 #include "map_objects.h" /* for map object (definition) structs */
@@ -41,11 +41,9 @@ static void monster_bumps_monster(struct World * world, char * dsc_monster1,
 {
     char * bump_dsc = " bumps into ";
     struct MapObjDef * mod = get_map_obj_def(world, monster2->map_obj.type);
-    char * msg = malloc(strlen(dsc_monster1) + strlen(bump_dsc)
-                        + strlen(mod->desc) + 3);
+    char msg[strlen(dsc_monster1) + strlen(bump_dsc) + strlen(mod->desc) + 3];
     sprintf(msg, "\n%s%s%s.", dsc_monster1, bump_dsc, mod->desc);
     update_log(world, msg);
-    free(msg);
 }
 
 
@@ -53,10 +51,9 @@ static void monster_bumps_monster(struct World * world, char * dsc_monster1,
 static void monster_hits_player(struct World * world, char * dsc_monster)
 {
     char * hit_dsc = " hits you";
-    char * msg = malloc(strlen(dsc_monster) + strlen(hit_dsc) + 3);
+    char msg[strlen(dsc_monster) + strlen(hit_dsc) + 3];
     sprintf(msg, "\n%s%s.", dsc_monster, hit_dsc);
     update_log(world, msg);
-    free(msg);
     world->player->hitpoints--;
     if (0 == world->player->hitpoints)
     {
@@ -68,23 +65,22 @@ static void monster_hits_player(struct World * world, char * dsc_monster)
 
 static void player_hits_monster(struct World * world, struct Monster * monster)
 {
+    char * f_name = "player_hits_monster()";
     struct MapObjDef * mod = get_map_obj_def(world, monster->map_obj.type);
     char * hit_dsc = "You hit the ";
     char * monster_dsc = mod->desc;
-    char * msg = malloc(strlen(hit_dsc) + strlen(monster_dsc) + 3);
-    sprintf(msg, "\n%s%s.", hit_dsc, monster_dsc);
-    update_log(world, msg);
-    free(msg);
+    char hitmsg[strlen(hit_dsc) + strlen(monster_dsc) + 3];
+    sprintf(hitmsg, "\n%s%s.", hit_dsc, monster_dsc);
+    update_log(world, hitmsg);
     monster->hitpoints--;
     if (0 == monster->hitpoints)
     {
         hit_dsc = "You kill the ";
-        msg = malloc(strlen(hit_dsc) + strlen(monster_dsc) + 3);
-        sprintf(msg, "\n%s%s.", hit_dsc, monster_dsc);
-        update_log(world, msg);
-        free(msg);
+        char kill_msg[strlen(hit_dsc) + strlen(monster_dsc) + 3];
+        sprintf(kill_msg, "\n%s%s.", hit_dsc, monster_dsc);
+        update_log(world, kill_msg);
         struct MonsterDef * md = (struct MonsterDef * ) mod;
-        struct Item * corpse = malloc(sizeof(struct Item));
+        struct Item * corpse = try_malloc(sizeof(struct Item), world, f_name);
         corpse->map_obj.type = md->corpse_id;
         corpse->map_obj.pos = monster->map_obj.pos;
         corpse->map_obj.next = world->item;
@@ -137,10 +133,9 @@ static void try_player_move(struct World * world,
         dsc_move = "You move ";
         world->player->pos = target;
     }
-    char * msg = malloc(strlen(dsc_move) + strlen (dsc_dir) + 3);
+    char msg[strlen(dsc_move) + strlen (dsc_dir) + 3];
     sprintf(msg, "\n%s%s.", dsc_move, dsc_dir);
     update_log(world, msg);
-    free(msg);
 }
 
 
@@ -183,7 +178,7 @@ extern void move_player(struct World * world, enum dir d)
 {
     char * action_dsc_prototype = "player_";
     uint8_t len = strlen(action_dsc_prototype);
-    char * action_dsc = malloc(len + 2);
+    char action_dsc[len + 2];
     memcpy(action_dsc, action_dsc_prototype, len);
     if      (NORTH == d)
     {
index 2edb31d43464b071e5bc7be43fa773ee0754d821..8d08ae04db1832e3222799df73278984aff731fb 100644 (file)
@@ -1,14 +1,14 @@
 /* map_objects.c */
 
 #include "map_objects.h"
-#include <stdlib.h> /* for malloc(), calloc(), free(), atoi() */
+#include <stdlib.h> /* for free(), atoi() */
 #include <stdint.h> /* for uint8_t */
 #include <stdio.h> /* for FILE typedef */
 #include <string.h> /* for strchr(), strlen(), memcpy(), strtok() */
-#include "readwrite.h" /* for textfile_sizes(),
+#include "readwrite.h" /* for get_linemax(), try_fopen(), try_fclose()
                         * [read/write]_uint[8/16/23][_bigendian]()
                         */
-#include "misc.h" /* for find_passable_pos() */
+#include "misc.h" /* for try_malloc(), try_calloc(), find_passable_pos() */
 #include "main.h" /* for World struct */
 #include "rexit.h" /* for err_exit() */
 
 
 /* Return pointer to newly allocated map object struct of size "size". If first
  * in map object chain ("first" pointing to !0), point "start" to it.
- *
- * Returns NULL instead of MapObj pointer if malloc() failed.
  */
-static struct MapObj * get_next_map_obj(void * start, char * first,
+static struct MapObj * get_next_map_obj(struct World * world,
+                                        void * start, char * first,
                                         size_t size, struct MapObj * map_obj);
 
 
@@ -34,19 +33,21 @@ static uint8_t read_map_objects_monsterdata( void * start, FILE * file);
 
 
 
-static struct MapObj * get_next_map_obj(void * start, char * first,
+static struct MapObj * get_next_map_obj(struct World * world,
+                                        void * start, char * first,
                                         size_t size, struct MapObj * map_obj)
 {
+    char * f_name = "get_next_map_obj()";
     if (* first)
     {
         struct MapObj * * z = start;
-        map_obj = malloc(size);
+        map_obj = try_malloc(size, world, f_name);
         * z = map_obj;
         * first = 0;
     }
     else
     {
-        map_obj->next = malloc(size);
+        map_obj->next = try_malloc(size, world, f_name);
         map_obj = map_obj->next;
     }
     return map_obj;
@@ -92,16 +93,9 @@ static uint8_t read_map_objects_monsterdata (void * start, FILE * file)
 
 extern void init_map_object_defs(struct World * world, char * filename)
 {
-    char * err_o = "Trouble in init_map_object_defs() with fopen().";
-    char * err_s = "Trouble in init_map_object_defs() with textfile_sizes().";
-    char * err_m = "Trouble in init_map_object_defs() with malloc()/calloc().";
-    char * err_c = "Trouble in init_map_object_defs() with fclose().";
-
-    FILE * file = fopen(filename, "r");
-    exit_err(NULL == file, world, err_o);
-    uint16_t linemax;
-    exit_err(textfile_sizes(file, &linemax, NULL), world, err_s);
-
+    char * f_name = "init_map_object_defs()";
+    FILE * file = try_fopen(filename, "r", world, f_name);
+    uint16_t linemax = get_linemax(file, world, f_name);
     struct MapObjDef  mod;
     struct ItemDef    id;
     struct MonsterDef md;
@@ -128,28 +122,24 @@ extern void init_map_object_defs(struct World * world, char * filename)
             md.hitpoints_start = atoi(strtok(NULL, delim));
             line_p             = strtok(NULL, delim);
         }
-        mod.desc = calloc(strlen(line_p), sizeof(char));
-        exit_err(NULL == mod.desc, world, err_m);
+        mod.desc = try_calloc(strlen(line_p), sizeof(char), world, f_name);
         memcpy(mod.desc, line_p, strlen(line_p) - 1);
         if ('i' == mod.m_or_i)
         {
             id.map_obj_def = mod;
-            * p_p_id       = malloc(sizeof(struct ItemDef));
-            exit_err(NULL == p_p_id, world, err_m);
+            * p_p_id       = try_malloc(sizeof(struct ItemDef), world, f_name);
             * * p_p_id     = id;
             p_p_id         = (struct ItemDef    * *) * p_p_id;
         }
         else
         {
             md.map_obj_def = mod;
-            * p_p_md       = malloc(sizeof(struct MonsterDef));
-            exit_err(NULL == p_p_md, world, err_m);
+            * p_p_md     = try_malloc(sizeof(struct MonsterDef), world, f_name);
             * * p_p_md     = md;
             p_p_md         = (struct MonsterDef * *) * p_p_md;
         }
     }
-
-    exit_err(fclose(file), world, err_c);
+    try_fclose(file, world, f_name);
 }
 
 
@@ -241,7 +231,7 @@ extern uint8_t read_map_objects(struct World * world, void * start, FILE * file)
         {
             size = sizeof(struct Item);
         }
-        map_obj = get_next_map_obj(start, &first, size, map_obj);
+        map_obj = get_next_map_obj(world, start, &first, size, map_obj);
         exit_err(NULL == map_obj, world, err);
         map_obj->type = type;
         if (   read_uint16_bigendian(file, &map_obj->pos.y)
@@ -287,7 +277,7 @@ extern void * build_map_objects(struct World * world, void * start, char def_id,
     }
     for (i = 0; i < n; i++)
     {
-        mo = get_next_map_obj(start, &first, size, mo);
+        mo = get_next_map_obj(world, start, &first, size, mo);
         exit_err(NULL == mo, world, err);
         mo->pos = find_passable_pos(world->map);
         if ('i' == mod->m_or_i)
index 4632a0bccadefd2e2b45b2010643f4241f05b164..50fee6407854469819a691ccb8826943f55fd08a 100644 (file)
@@ -1,12 +1,14 @@
 /* misc.c */
 
 #include "misc.h"
-#include <stdio.h> /* for rename() */
+#include <errno.h> /* for errno */
 #include <unistd.h> /* for unlink(), acess() */
-#include <stdlib.h> /* for calloc(), free() */
+#include <stdlib.h> /* for size_t, calloc(), free() */
 #include <string.h> /* for strlen(), strcmp(), memcpy() */
 #include <stdint.h> /* for uint8_t, uint16_t */
-#include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian]() */
+#include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian](),
+                        * try_fopen(), try_fclose()
+                        */
 #include "map_objects.h" /* for struct Monster, write_map_objects(), */
 #include "map_object_actions.h" /* for is_passable(), move_monster() */
 #include "map.h" /* for Map struct */
 
 
 
+extern char * trouble_msg(struct World * w, char * parent, char * child)
+{
+    char * p1 = "Trouble in ";
+    char * p2 = " with ";
+    char * p3 = ".";
+    uint16_t size = strlen(p1) + strlen(parent) + strlen(p2) + strlen(child)
+                    + strlen(p3) + 1;
+    char * msg = malloc(size);
+    exit_err(NULL == msg, w, "malloc() in trouble_msg() failed.");
+    sprintf(msg, "%s%s%s%s%s", p1, parent, p2, child, p3);
+    return msg;
+}
+
+
+
+extern void * try_malloc(size_t size, struct World * w, char * f)
+{
+    char * msg = trouble_msg(w, f, "malloc()");
+    void * p = malloc(size);
+    exit_err(NULL == p, w, msg);
+    free(msg);
+    return p;
+}
+
+
+
+extern void * try_calloc(size_t size1, size_t size2, struct World * w, char * f)
+{
+    char * msg = trouble_msg(w, f, "calloc()");
+    void * p = calloc(size1, size2);
+    exit_err(NULL == p, w, msg);
+    free(msg);
+    return p;
+}
+
+
+
+extern void check_files_xor(char * p1, char * p2, struct World * w)
+{
+    char * msg1 = "A file '";
+    char * msg2 = "' exists, but no file '";
+    char * msg3 = "'. If everything was in order, both or noe would exist. "
+                  "The game won't start until this is corrected.";
+    uint16_t size = strlen(msg1) + strlen(p1) + strlen(msg2) + strlen(p2)
+                    + strlen(msg3);
+    char msg[size];
+    if      (!access(p1, F_OK) && access(p2, F_OK))
+    {
+        sprintf(msg, "%s%s%s%s%s", msg1, p1, msg2, p2, msg3);
+        errno = 0;
+        exit_err(1, w, msg);
+    }
+    else if (access(p1, F_OK) && !access(p2, F_OK))
+    {
+        sprintf(msg, "%s%s%s%s%s", msg1, p2, msg2, p1, msg3);
+        errno = 0;
+        exit_err(1, w, msg);
+    }
+}
+
+
+
+extern void check_tempfile(char * path, struct World * w)
+{
+    char * msg1 = "A file '";
+    char * msg2 = "' exists, probably from a corrupted previous file saving "
+                "process. To avoid corruption of game files, the game won't  "
+                "start until it is removed or renamed.";
+    uint16_t size = strlen(msg1) + strlen(path) + strlen(msg2);
+    char msg[size];
+    sprintf(msg, "%s%s%s", msg1, path, msg2);
+    exit_err(!access(path, F_OK), w, msg);
+}
+
+
+
 extern void update_log(struct World * world, char * text)
 {
+    char * f_name = "update_log()";
     static char * last_msg;                 /* TODO: valgrind is dissatisfied */
-    if (0 == last_msg)                      /* with this calloc'd pointer     */
-    {                                       /* never being freed.             */
-        last_msg = calloc(1, sizeof(char)); /* Rectify this ?                 */
+    if (0 == last_msg)                      /* with this calloc'd pointer not */
+    {                                       /* being freed. Rectify this?     */
+        last_msg = try_calloc(1, sizeof(char), world, f_name);
     }
     char * new_text;
     uint16_t len_old = strlen(world->log);
     if (0 == strcmp(last_msg, text))
     {
         uint16_t len_whole = len_old + 1;
-        new_text = calloc(len_whole + 1, sizeof(char));
+        new_text = try_calloc(len_whole + 1, sizeof(char), world, f_name);
         memcpy(new_text, world->log, len_old);
         memcpy(new_text + len_old, ".", 1);
     }
@@ -37,10 +116,10 @@ extern void update_log(struct World * world, char * text)
     {
         uint16_t len_new = strlen(text);
         uint16_t len_whole = len_old + len_new + 1;
-        new_text = calloc(len_whole, sizeof(char));
+        new_text = try_calloc(len_whole, sizeof(char), world, f_name);
         memcpy(new_text, world->log, len_old);
         memcpy(new_text + len_old, text, len_new);
-        last_msg = calloc(len_new + 1, sizeof(char));
+        last_msg = try_calloc(len_new + 1, sizeof(char), world, f_name);
         memcpy(last_msg, text, len_new);
     }
     free(world->log);
@@ -74,36 +153,26 @@ extern uint16_t center_offset(uint16_t pos, uint16_t mapsize,
 
 extern void turn_over(struct World * world, char action)
 {
-    char * err_open  = "Trouble in turn_over() with fopen() "
-                       "opening file 'record_tmp' for appending.";
+    char * f_name = "turn_over()";
     char * err_write = "Trouble in turn_over() with write_uint8() "
                        "writing to opened file 'record_tmp'.";
-    char * err_close = "Trouble in turn_over() with fclose() "
-                       "closing opened file 'record'.";
-    char * err_unl   = "Trouble in turn_over() with unlink() "
-                       "unlinking old file 'record'.";
-    char * err_move  = "Trouble in turn_over() with rename() "
-                       "renaming file 'record_tmp' to 'record'.";
+
     char * recordfile_tmp = "record_tmp";
     char * recordfile     = "record";
     if (1 == world->interactive)
     {
-        FILE * file_old = fopen(recordfile, "r");
-        FILE * file_new = fopen(recordfile_tmp, "w");
-        exit_err(0 == file_old, world, err_open);
+        FILE * file_old = try_fopen(recordfile,     "r", world, f_name);
+        FILE * file_new = try_fopen(recordfile_tmp, "w", world, f_name);
         char c = fgetc(file_old);
         while (EOF != c)
         {
             exit_err(write_uint8(c, file_new), world, err_write);
             c = fgetc(file_old);
         }
-        exit_err(fclose(file_old), world, err_close);
+        try_fclose(file_old, world, f_name);
         exit_err(write_uint8(action, file_new), world, err_write);
-        err_close = "Trouble in turn_over() with fclose() "
-                    "closing opened file 'record_tmp'.";
-        exit_err(fclose(file_new), world, err_close);
-        exit_err(unlink(recordfile), world, err_unl);
-        exit_err(rename(recordfile_tmp, recordfile), world, err_move);
+        try_fclose_unlink_rename(file_new, recordfile_tmp, recordfile,
+                                 world, f_name);
     }
     world->turn++;
     rrand_seed(world->seed * world->turn);
@@ -120,20 +189,13 @@ extern void turn_over(struct World * world, char action)
 
 extern void save_game(struct World * world)
 {
-    char * err_open  = "Trouble in save_game() with fopen() "
-                       "opening file 'savefile_tmp' for writing.";
+    char * f_name = "save_game()";
     char * err_write = "Trouble in save_game() "
                        "writing to opened file 'savefile_tmp'.";
-    char * err_close = "Trouble in save_game() with fclose() "
-                       "closing opened file 'savefile_tmp'.";
-    char * err_unl   = "Trouble in save_game() with unlink() "
-                       "unlinking old 'savefile' file.";
-    char * err_move  = "Trouble in save_game() with rename() "
-                       "renaming 'file savefile_tmp' to 'savefile'.";
+
     char * savefile_tmp = "savefile_tmp";
     char * savefile     = "savefile";
-    FILE * file = fopen(savefile_tmp, "w");
-    exit_err(0 == file, world, err_open);
+    FILE * file = try_fopen(savefile_tmp, "w", world, f_name);
     if (   write_uint32_bigendian(world->seed, file)
         || write_uint32_bigendian(world->turn, file)
         || write_uint16_bigendian(world->score, file)
@@ -145,12 +207,7 @@ extern void save_game(struct World * world)
     {
         exit_err(1, world, err_write);
     }
-    exit_err(fclose(file), world, err_close);
-    if (!access(savefile, F_OK))
-    {
-        exit_err(unlink(savefile), world, err_unl);
-    }
-    exit_err(rename(savefile_tmp, savefile), world, err_move);
+    try_fclose_unlink_rename(file, savefile_tmp, savefile, world, f_name);
 }
 
 
index c7b88557285caa9e636ede24406ab262989a4403..5101e473521916bbfa16aa24c40249d8240f0f30 100644 (file)
@@ -9,6 +9,7 @@
 
 
 
+#include <stdlib.h>    /* for size_t */
 #include <stdint.h>    /* for uint16_t */
 #include "yx_uint16.h" /* for yx_uint16 coordinates */
 struct World;
@@ -16,6 +17,26 @@ struct Map;
 
 
 
+/* Returns message: "Trouble in ".parent." with ".child."." (try_*() helper) */
+extern char * trouble_msg(struct World * w, char * parent, char * child);
+
+/* Wrappers to malloc(), calloc() from function called "f" calling exit_err()
+ * with trouble_msg() error message if necessary.
+ */
+extern void * try_malloc(size_t size, struct World * w, char * f);
+extern void * try_calloc(size_t nmemb, size_t size,
+                         struct World * w, char * f);
+
+
+
+/* Check if tempfile "path" exists, and if so, exit with explanation that. */
+extern void check_tempfile(char * path, struct World * f);
+
+/* If one and only one of files at "p1", "p2" exists, fail with explanation. */
+extern void check_files_xor(char * p1, char * p2, struct World * w);
+
+
+
 /* Update game log by appending "text", or by appending a "." if "text" is the
  * same as the last one passed.
  */
index 96505adf4387cc52f4a83241f03098869b0a67d9..4b2f2a6af37628511c2e1dcc5fbc5327a06d9a68 100644 (file)
@@ -1,8 +1,15 @@
 /* readwrite.c */
 
 #include "readwrite.h"
-#include <stdio.h> /* for FILE typedef, fgetc(), fputc(), fseek() */
+#include <stdio.h>  /* for FILE typedef, fopen(), fgetc(), fputc(), fseek(),
+                     * sprintf()
+                     */
 #include <stdint.h> /* for uint8_t, uint16_t, uint32_t */
+#include <string.h> /* for strlen()*/
+#include <unistd.h> /* for unlink() */
+#include "rexit.h"  /* for exit_err() */
+#include "misc.h"   /* for trouble_msg() */
+struct World;
 
 
 
@@ -26,6 +33,79 @@ static uint8_t write_uintX_bigendian(FILE * file, uint32_t x, uint8_t size);
 
 
 
+extern FILE * try_fopen(char * path, char * mode, struct World * w, char * f)
+{
+    char * msg1 = "Trouble in ";
+    char * msg2 = " with fopen() (mode '";
+    char * msg3 = "') on path '";
+    char * msg4 = "'.";
+    uint16_t size = strlen(msg1) + strlen(msg2) + strlen(msg3) + strlen(msg4)
+                    + strlen(f) + strlen(path) + strlen(mode) + 1;
+    char msg[size];
+    sprintf(msg, "%s%s%s%s%s%s%s", msg1, f, msg2, mode, msg3, path, msg4);
+    FILE * file_p = fopen(path, mode);
+    exit_err(NULL == file_p, w, msg);
+    return file_p;
+}
+
+
+
+extern void try_fclose(FILE * file, struct World * w, char * f)
+{
+    char * msg = trouble_msg(w, f, "fclose()");
+    exit_err(fclose(file), w, msg);
+    free(msg);
+}
+
+
+
+extern void try_fgets(char * line, int linemax, FILE * file,
+                      struct World * w, char * f)
+{
+    char * msg = trouble_msg(w, f, "fgets()");
+    exit_err(NULL == fgets(line, linemax, file), w, msg);
+    free(msg);
+}
+
+
+
+extern void try_fclose_unlink_rename(FILE * file, char * p1, char * p2,
+                                     struct World * w, char * f)
+{
+    try_fclose(file, w, f);
+    char * msg1 = "Trouble in ";
+    char * msg4 = "'.";
+    if (!access(p2, F_OK))
+    {
+        char * msg2 = " with unlink() on path '";
+        uint16_t size = strlen(msg1) + strlen(msg2) + strlen(msg4)
+                        + strlen(f) + strlen(p2) + 1;
+        char msg[size];
+        sprintf(msg, "%s%s%s%s%s", msg1, f, msg2, p2, msg4);
+        exit_err(unlink(p2), w, msg);
+    }
+    char * msg2 = " with rename() from '";
+    char * msg3 = "' to '";
+    uint16_t size = strlen(msg1) + strlen(f) + strlen(msg2) + strlen(p1)
+                    + strlen(msg3) + strlen(p2) + strlen(msg4) + 1;
+    char msg[size];
+    sprintf(msg, "%s%s%s%s%s%s%s", msg1, f, msg2, p1, msg3, p2, msg4);
+    exit_err(rename(p1, p2), w, msg);
+}
+
+
+
+extern uint16_t get_linemax(FILE * file, struct World * w, char * f)
+{
+    char * msg = trouble_msg(w, f, "textfile_sizes()");
+    uint16_t linemax;
+    exit_err(textfile_sizes(file, &linemax, NULL), w, msg);
+    free(msg);
+    return linemax;
+}
+
+
+
 extern uint8_t textfile_sizes(FILE * file, uint16_t * linemax_p,
                               uint16_t * n_lines_p)
 {
index 128e44a8a3e5534e40c7a98fa8feba800d53788f..bcdf10eb20632caada30e8ee02fb35cd586ee8cf 100644 (file)
 
 #include <stdio.h> /* for FILE typedef */
 #include <stdint.h> /* for uint8_t, uint16_t, uint32_t */
+struct World;
+
+
+
+/* Wrappers to calling from function called "f" of fopen(), fclose() and fgets()
+ * and calling exit_err() with appropriate error messages.
+ */
+extern FILE * try_fopen(char * path, char * mode, struct World * w, char * f);
+extern void try_fclose(FILE * file, struct World * w, char * f);
+extern void try_fgets(char * line, int size, FILE * file,
+                      struct World * w, char * f);
+
+
+
+/* Wrapper to successive call of fclose() from function called "f" on "file",
+ * then unlink() on file at "p2" if it exists, then rename() on "p1" to "p2".
+ * Used for handling atomic saving of files via temp files.
+ */
+extern void try_fclose_unlink_rename(FILE * file, char * p1, char * p2,
+                                     struct World * w, char * f);
+
+
+
+/* Wrapper: Call textfile_sizes() from function called "f" to get max line
+ * length of "file", exit via exit_err() with trouble_msg()-generated error
+ * message on failure.
+ */
+extern uint16_t get_linemax(FILE * file, struct World * w, char * f);
 
 
 
index aeae7b229c27a36766cd5fd3ccf49d8a41b81535..d8cb40f9c3552cdf77d40d026da3f24790175eda 100644 (file)
@@ -1,10 +1,10 @@
 /* wincontrol.c */
 
 #include "wincontrol.h"
-#include <stdlib.h> /* for malloc(), free() */
+#include <stdlib.h> /* for free() */
 #include <string.h> /* for strlen() */
 #include <stdint.h> /* for uint8_t, uint16_t */
-#include <stdio.h> /* for fopen(), fclose(), fwrite() */
+#include <stdio.h> /* for fwrite() */
 #include <unistd.h> /* for access(), unlink() */
 #include "windows.h" /* for suspend_win(), append_win(), reset_pad_offset(),
                       * resize_active_win(), init_win(), free_win(),
                       */
 #include "yx_uint16.h" /* for yx_uint16 struct */
 #include "main.h" /* for Wins struct */
-#include "readwrite.h" /* for textfile_sizes() */
+#include "readwrite.h" /* for get_linemax(), try_fopen(), try_fclose(),
+                        * try_fgets(), try_fclose_unlink_rename()
+                        */
 #include "rexit.h" /* for exit_err() */
 #include "main.h" /* for World, Wins structs */
 #include "draw_wins.h" /* for draw_keys_win(), draw_info_win(), draw_log_win(),
                         * draw_map_win
                         */
-
+#include "misc.h" /* for try_malloc() */
 
 
 /* Return string "prefix" + "id"; malloc()'s string, remember to call free()! */
@@ -26,7 +28,7 @@ static char * string_prefixed_id(struct World * world, char * prefix, char id);
 
 
 
-/* Create Winconf, initialize ->iew/height_type/width_type to 0, ->id to "id"
+/* Create Winconf, initialize ->view/height_type/width_type to 0, ->id to "id"
  * and ->draw to f.
  */
 static void create_winconf(char id, struct WinConf * wcp,
@@ -58,10 +60,8 @@ static char get_id_by_win(struct World * world, struct Win * win);
 
 static char * string_prefixed_id(struct World * world, char * prefix, char id)
 {
-    char * err = "Trouble in string_prefixed_id() with malloc().";
     uint8_t size = strlen(prefix) + 2;
-    char * path = malloc(size);
-    exit_err(NULL == path, world, err);
+    char * path = try_malloc(size, world, "string_prefixed_id()");
     sprintf(path, "%s_", prefix);
     path[size - 2] = id;
     return path;
@@ -83,39 +83,33 @@ static void create_winconf(char id, struct WinConf * wcp,
 
 static void init_winconf_from_file(struct World * world, char id)
 {
-    char * err_o = "Trouble in init_win_from_file() with fopen().";
-    char * err_m = "Trouble in init_win_from_file() with malloc().";
-    char * err_s = "Trouble in init_win_from_file() with textfile_sizes().";
-    char * err_g = "Trouble in init_win_from_file() with fgets().";
-    char * err_c = "Trouble in init_win_from_file() with fclose().";
+    char * f_name = "init_winconf_from_file()";
 
     char * path = string_prefixed_id(world, "config/windows/Win_", id);
-    FILE * file = fopen(path, "r");
-    exit_err(NULL == file, world, err_o);
+    FILE * file = try_fopen(path, "r", world, f_name);
     free(path);
-    uint16_t linemax;
-    exit_err(textfile_sizes(file, &linemax, NULL), world, err_s);
+    uint16_t linemax = get_linemax(file, world, f_name);
     char line[linemax + 1];
 
     struct WinConf * winconf = get_winconf_by_id(world, id);
-    exit_err(NULL == fgets(line, linemax + 1, file), world, err_g);
-    exit_err(NULL == (winconf->title = malloc(strlen(line))), world, err_m);
+    try_fgets(line, linemax + 1, file, world, f_name);
+    winconf->title = try_malloc(strlen(line), world, f_name);
     memcpy(winconf->title, line, strlen(line) - 1); /* Eliminate newline char */
     winconf->title[strlen(line) - 1] = '\0';        /* char at end of string. */
-    exit_err(NULL == fgets(line, linemax + 1, file), world, err_g);
+    try_fgets(line, linemax + 1, file, world, f_name);
     winconf->height = atoi(line);
     if (0 >= winconf->height)
     {
         winconf->height_type = 1;
     }
-    exit_err(NULL == fgets(line, linemax + 1, file), world, err_g);
+    try_fgets(line, linemax + 1, file, world, f_name);
     winconf->width = atoi(line);
     if (0 >= winconf->width)
     {
         winconf->width_type = 1;
     }
 
-    exit_err(fclose(file), world, err_c);
+    try_fclose(file, world, f_name);
 }
 
 
@@ -133,14 +127,10 @@ static void init_win_from_winconf(struct World * world, char id)
 
 extern void save_win_config(struct World * world, char id)
 {
-    char * err_o = "Trouble in save_win_config() with fopen().";
-    char * err_c = "Trouble in save_win_config() with fclose().";
-    char * err_u = "Trouble in save_win_config() with unlink().";
-    char * err_r = "Trouble in save_win_config() with rename().";
+    char * f_name = "save_win_config()";
 
     char * path_tmp = string_prefixed_id(world, "config/windows/Win_tmp_", id);
-    FILE * file = fopen(path_tmp, "w");
-    exit_err(NULL == file, world, err_o);
+    FILE * file = try_fopen(path_tmp, "w", world, f_name);
 
     struct WinConf * wc = get_winconf_by_id(world, id);
     uint8_t size = strlen(wc->title) + 2;
@@ -156,13 +146,8 @@ extern void save_win_config(struct World * world, char id)
     sprintf(line, "%d\n", wc->width);
     fwrite(line, sizeof(char), strlen(line), file);
 
-    exit_err(fclose(file), world, err_c);
     char * path = string_prefixed_id(world, "config/windows/Win_", id);
-    if (!access(path, F_OK))
-    {
-        exit_err(unlink(path), world, err_u);
-    }
-    exit_err(rename(path_tmp, path), world, err_r);
+    try_fclose_unlink_rename(file, path_tmp, path, world, f_name);
     free(path);
     free(path_tmp);
 }
@@ -242,9 +227,9 @@ extern struct Win * get_win_by_id(struct World * world, char id)
 
 extern void init_winconfs(struct World * world)
 {
-    char * err = "Trouble with malloc() in init_winconfs().";
-    struct WinConf * winconfs = malloc(4 * sizeof(struct WinConf));
-    exit_err(NULL == winconfs, world, err);
+    char * f_name = "init_winconfs()";
+    struct WinConf * winconfs = try_malloc(4 * sizeof(struct WinConf),
+                                           world, f_name);
     create_winconf('i', &winconfs[0], draw_info_win);
     create_winconf('k', &winconfs[1], draw_keys_win);
     create_winconf('l', &winconfs[2], draw_log_win);
@@ -299,21 +284,13 @@ extern void free_wins(struct World * world)
 
 extern void sorted_wintoggle(struct World * world)
 {
-    char * err_o = "Trouble in sorted_wintoggle() with fopen().";
-    char * err_s = "Trouble in sorted_wintoggle() with textfile_sizes().";
-    char * err_g = "Trouble in sorted_wintoggle() with fgets().";
-    char * err_c = "Trouble in sorted_wintoggle() with fclose().";
-
+    char * f_name = "sorted_wintoggle()";
     char * path = "config/windows/toggle_order";
-    FILE * file = fopen(path, "r");
-    exit_err(NULL == file, world, err_o);
-    uint16_t linemax;
-    exit_err(textfile_sizes(file, &linemax, NULL), world, err_s);
+    FILE * file = try_fopen(path, "r", world, f_name);
+    uint16_t linemax = get_linemax(file, world, f_name);
     char win_order[linemax + 1];
-
-    exit_err(NULL == fgets(win_order, linemax + 1, file), world, err_g);
-    exit_err(fclose(file), world, err_c);
-
+    try_fgets(win_order, linemax + 1, file, world, f_name);
+    try_fclose(file, world, f_name);
     uint8_t i = 0;
     for (; i < linemax - 1; i++)
     {
@@ -340,20 +317,16 @@ extern void reload_win_config(struct World * world)
 
 extern void save_win_configs(struct World * world)
 {
+    char * f_name = "save_win_configs()";
+
     save_win_config(world, 'i');
     save_win_config(world, 'k');
     save_win_config(world, 'l');
     save_win_config(world, 'm');
 
-    char * err_o = "Trouble in save_win_configs() with fopen().";
-    char * err_c = "Trouble in save_win_configs() with fclose().";
-    char * err_u = "Trouble in save_win_configs() with unlink().";
-    char * err_r = "Trouble in save_win_configs() with rename().";
-
     char * path     = "config/windows/toggle_order";
     char * path_tmp = "config/windows/toggle_order_tmp";
-    FILE * file = fopen(path_tmp, "w");
-    exit_err(NULL == file, world, err_o);
+    FILE * file = try_fopen(path_tmp, "w", world, f_name);
 
     char line[6];
     struct Win * w_p = world->wmeta->_chain_start;
@@ -367,12 +340,7 @@ extern void save_win_configs(struct World * world)
     line[i] = '\n';
     fwrite(line, sizeof(char), strlen(line), file);
 
-    exit_err(fclose(file), world, err_c);
-    if (!access(path, F_OK))
-    {
-        exit_err(unlink(path), world, err_u);
-    }
-    exit_err(rename(path_tmp, path), world, err_r);
+    try_fclose_unlink_rename(file, path_tmp, path, world, f_name);
 }