Better error handling, no zombie process on failure.

This commit is contained in:
KikooDX 2021-03-25 13:44:05 +01:00
parent db95b9c72e
commit db77c25935
3 changed files with 48 additions and 27 deletions

View File

@ -9,6 +9,8 @@ struct Level {
tile_t *data;
};
void level_read(struct Level *, char *path);
/* return -1 if error */
int level_read(struct Level *, char *path);
void level_free(struct Level *);
void level_write(struct Level level, char *path);
/* return -1 if error */
int level_write(struct Level level, char *path);

View File

@ -8,12 +8,12 @@
static const int kble_fmt_version = 0;
static char read_byte(FILE *file);
static int read_byte(FILE *file);
static tile_t read_byte_group(FILE *file, int size);
static void write_byte(FILE *file, char byte);
static void write_byte_group(FILE *file, tile_t value, int size);
static int write_byte(FILE *file, char byte);
static int write_byte_group(FILE *file, tile_t value, int size);
void level_read(struct Level *level, char *path)
int level_read(struct Level *level, char *path)
{
FILE *file = NULL;
char byte = 0;
@ -27,7 +27,7 @@ void level_read(struct Level *level, char *path)
if (file == NULL) {
fprintf(stderr, "ERROR: cannot open input file %s\n",
path);
exit(EXIT_FAILURE);
return -1;
}
/* check KBLE format version */
@ -37,23 +37,26 @@ void level_read(struct Level *level, char *path)
"ERROR: KBLE format version doesn't match ; "
"expected %d, got %d\n",
kble_fmt_version, byte);
exit(EXIT_FAILURE);
return -1;
}
/* get tile size (in bytes) */
tile_size = read_byte(file);
if (tile_size < 0) return -1;
/* check than tile size is in boundaries */
if (tile_size > sizeof(tile_t) / sizeof(char)) {
fprintf(stderr,
"ERROR: tile size is too big ; "
"maximum is %ld, found %d",
sizeof(tile_t), tile_size);
exit(EXIT_FAILURE);
return -1;
}
/* get width */
level->width = read_byte_group(file, 2);
if (level->width == (tile_t)-1) return -1;
/* get height */
level->height = read_byte_group(file, 2);
if (level->height == (tile_t)-1) return -1;
/* allocate memory for data */
level_size = level->width * level->height;
@ -66,7 +69,7 @@ void level_read(struct Level *level, char *path)
/* check for allocation failure */
if (level->data == NULL) {
fprintf(stderr, "ERROR: memory allocation failure\n");
exit(EXIT_FAILURE);
return -1;
}
/* read file content */
@ -77,11 +80,13 @@ void level_read(struct Level *level, char *path)
/* close file */
fclose(file);
return 0;
}
void level_free(struct Level *level) { free(level->data); }
void level_write(struct Level level, char *path)
int level_write(struct Level level, char *path)
{
FILE *file = NULL;
int tile = 0;
@ -95,7 +100,7 @@ void level_write(struct Level level, char *path)
if (file == NULL) {
fprintf(stderr, "ERROR: cannot open output file %s\n",
path);
exit(EXIT_FAILURE);
return -1;
}
/* find longest value in data (in bytes) */
@ -124,50 +129,60 @@ void level_write(struct Level level, char *path)
/* close file */
fclose(file);
return 0;
}
/* Read a single byte safely (handle EOF). */
static char read_byte(FILE *file)
/* Read a single byte safely (handle EOF). Return -1 if error. */
static int read_byte(FILE *file)
{
const int byte = fgetc(file);
if (byte == EOF) {
fprintf(stderr, "ERROR: unexpected EOF\n");
exit(EXIT_FAILURE);
return -1;
}
return (char)byte;
}
/* Read multiple bytes and "merge" them into one integer. */
/* Read multiple bytes and "merge" them into one integer. Return -1 if error. */
static tile_t read_byte_group(FILE *file, int size)
{
int group = 0;
char *byte_ptr = (char *)&group;
int value = 0;
int i = 0;
byte_ptr += size;
for (i = 0; i < size; i += 1) {
byte_ptr -= 1, *byte_ptr = read_byte(file);
value = read_byte(file);
if (value < 0)
return -1;
byte_ptr -= 1, *byte_ptr = value;
}
return group;
}
/* Write a single byte safely (handle EOF). */
static void write_byte(FILE *file, char byte)
/* Write a single byte safely (handle EOF). Return -1 if error. */
static int write_byte(FILE *file, char byte)
{
const int result = fputc(byte, file);
if (result == EOF) {
fprintf(stderr, "ERROR: file write error\n");
exit(EXIT_FAILURE);
return -1;
}
return 0;
}
/* Write an integer as multiple bytes. */
static void write_byte_group(FILE *file, tile_t value, int size)
/* Write an integer as multiple bytes. Return -1 if error. */
static int write_byte_group(FILE *file, tile_t value, int size)
{
char *value_ptr = (char *)&value;
value_ptr += size;
int error;
int i = 0;
for (i = 0; i < size; i += 1) {
value_ptr -= 1;
write_byte(file, *value_ptr);
error = write_byte(file, *value_ptr);
if (error < 0) return -1;
}
return 0;
}

View File

@ -21,6 +21,7 @@ int editing_area_main(int argc, char **argv,
{
int mouse_x;
int mouse_y;
int error;
struct Level level;
level.data = NULL;
@ -36,9 +37,10 @@ int editing_area_main(int argc, char **argv,
if (tileset.width >= TILESET_MIN_WIDTH_PX &&
tileset.height >= TILESET_MIN_HEIGHT_PX) {
/* load level */
level_read(&level, argv[2]);
error = level_read(&level, argv[2]);
printf("%d\n", error);
while (!WindowShouldClose()) {
while ((!WindowShouldClose()) && (error >= 0)) {
/* update */
update_mouse(&mouse_x, &mouse_y, level,
shared_data);
@ -53,8 +55,10 @@ int editing_area_main(int argc, char **argv,
EndDrawing();
}
/* save level */
level_write(level, argv[2]);
if (error >= 0) {
/* save level */
error = level_write(level, argv[2]);
}
} else
fprintf(stderr,
"ERROR: tileset size is invalid, expected at "