From 2407b8e96d1a772f15eedb264117f20196fe1c51 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 29 Mar 2009 21:25:45 +0000 Subject: [PATCH] Wrote better checks for illegal actions. Added "magic numbers" to the window, stream, and fileref structures, for better checking. Added macros for checking and error reporting in magic.h. git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@35 ddfedd41-794f-dd11-ae45-00112f111e67 --- src/Makefile.am | 9 ++++- src/charset.c | 9 +++-- src/event.c | 3 +- src/fileref.c | 26 ++++++++---- src/fileref.h | 2 +- src/input.c | 15 +++---- src/magic.c | 56 ++++++++++++++++++++++++++ src/magic.h | 41 +++++++++++++++++++ src/main.c | 2 +- src/stream.c | 104 +++++++++++++++++++++++------------------------- src/stream.h | 2 +- src/strio.c | 67 ++++++++++++++++--------------- src/window.c | 55 +++++++++++++------------ src/window.h | 2 +- 14 files changed, 253 insertions(+), 140 deletions(-) create mode 100644 src/magic.c create mode 100644 src/magic.h diff --git a/src/Makefile.am b/src/Makefile.am index e67e206..52b8652 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,7 @@ ## Process this file with automake to produce Makefile.in +AM_CFLAGS = -Wall + data_DATA = chimara.ui noinst_PROGRAMS = test-chimara @@ -9,7 +11,7 @@ test_chimara_CPPFLAGS = \ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \ -DPACKAGE_DATA_DIR=\""$(datadir)"\" -test_chimara_CFLAGS = @TEST_CFLAGS@ +test_chimara_CFLAGS = @TEST_CFLAGS@ $(AM_CFLAGS) test_chimara_LDADD = @TEST_LIBS@ -lchimara lib_LTLIBRARIES = libchimara.la @@ -23,12 +25,15 @@ libchimara_la_SOURCES = \ fileref.c fileref.h \ gestalt.c \ glk.c glk.h \ + magic.c magic.h \ input.c input.h \ stream.c stream.h \ strio.c \ style.c \ window.c window.h -libchimara_la_CFLAGS = @CHIMARA_CFLAGS@ +libchimara_la_CPPFLAGS = \ + -DG_LOG_DOMAIN=\"Chimara\" +libchimara_la_CFLAGS = @CHIMARA_CFLAGS@ $(AM_CFLAGS) libchimara_la_LIBADD = @CHIMARA_LIBS@ libchimara_la_LDFLAGS = -no-undefined -export-symbols-regex "^chimara_glk_|^glk_" libchimara_includedir = $(includedir)/chimara/chimara diff --git a/src/charset.c b/src/charset.c index c060d8c..3f047cc 100644 --- a/src/charset.c +++ b/src/charset.c @@ -1,4 +1,5 @@ #include "charset.h" +#include "magic.h" #include /* Internal function: change illegal (control) characters in a string to a @@ -33,7 +34,7 @@ convert_latin1_to_utf8(const gchar *s, const gsize len) g_free(canonical); if(retval == NULL) - g_warning("Error during latin1->utf8 conversion: %s", error->message); + IO_WARNING("Error during latin1->utf8 conversion of string", s, error->message); return retval; } @@ -63,7 +64,7 @@ convert_utf8_to_latin1(const gchar *s, gsize *bytes_written) gchar *retval = g_convert_with_fallback(s, -1, "ISO-8859-1", "UTF-8", PLACEHOLDER_STRING, NULL, bytes_written, &error); if(retval == NULL) - g_warning("Error during utf8->latin1 conversion: %s", error->message); + IO_WARNING("Error during utf8->latin1 conversion of string", s, error->message); return retval; } @@ -78,7 +79,7 @@ convert_utf8_to_ucs4(const gchar *s, glong *items_written) gunichar *retval = g_utf8_to_ucs4_fast(s, -1, items_written); if(retval == NULL) - g_warning("Error during utf8->unicode conversion"); + WARNING_S("Error during utf8->unicode conversion of string", s); return retval; } @@ -92,7 +93,7 @@ convert_ucs4_to_utf8(const gunichar *buf, const glong len) gchar *retval = g_ucs4_to_utf8(buf, len, NULL, NULL, &error); if(retval == NULL) - g_warning("Error during unicode->utf8 conversion: %s", error->message); + WARNING_S("Error during unicode->utf8 conversion", error->message); return retval; } diff --git a/src/event.c b/src/event.c index 8f34f6f..d7cb659 100644 --- a/src/event.c +++ b/src/event.c @@ -1,4 +1,5 @@ #include "event.h" +#include "magic.h" #include "glk.h" #include @@ -73,7 +74,7 @@ glk_select(event_t *event) if(retrieved_event == NULL) { g_mutex_unlock(glk_data->event_lock); - g_warning("%s: Retrieved NULL event from non-empty event queue", __func__); + WARNING("Retrieved NULL event from non-empty event queue"); return; } memcpy(event, retrieved_event, sizeof(event_t)); diff --git a/src/fileref.c b/src/fileref.c index 1486e14..2b5cf53 100644 --- a/src/fileref.c +++ b/src/fileref.c @@ -1,8 +1,10 @@ +#include #include #include #include #include #include "fileref.h" +#include "magic.h" #include "chimara-glk-private.h" extern ChimaraGlkPrivate *glk_data; @@ -21,6 +23,8 @@ extern ChimaraGlkPrivate *glk_data; frefid_t glk_fileref_iterate(frefid_t fref, glui32 *rockptr) { + VALID_FILEREF_OR_NULL(fref, return NULL); + GList *retnode; if(fref == NULL) @@ -48,7 +52,7 @@ glk_fileref_iterate(frefid_t fref, glui32 *rockptr) glui32 glk_fileref_get_rock(frefid_t fref) { - g_return_val_if_fail(fref != NULL, 0); + VALID_FILEREF(fref, return 0); return fref->rock; } @@ -59,6 +63,7 @@ fileref_new(gchar *filename, glui32 rock, glui32 usage, glui32 orig_filemode) g_return_val_if_fail(filename != NULL, NULL); frefid_t f = g_new0(struct glk_fileref_struct, 1); + f->magic = MAGIC_FILEREF; f->rock = rock; f->filename = g_strdup(filename); f->usage = usage; @@ -100,14 +105,14 @@ glk_fileref_create_temp(glui32 usage, glui32 rock) gint handle = g_file_open_tmp("glkXXXXXX", &filename, &error); if(handle == -1) { - g_warning("Error creating temporary file: %s", error->message); + WARNING_S("Error creating temporary file", error->message); if(filename) g_free(filename); return NULL; } - if(close(handle) == -1) /* There is no g_close()? */ + if(close(handle) == -1) /* There is no g_close() */ { - g_warning("Error closing temporary file."); + IO_WARNING( "Error closing temporary file", filename, g_strerror(errno) ); if(filename) g_free(filename); return NULL; @@ -214,7 +219,7 @@ glk_fileref_create_by_prompt(glui32 usage, glui32 fmode, glui32 rock) GTK_FILE_CHOOSER_ACTION_SAVE); break; default: - g_warning("glk_fileref_create_by_prompt: Unsupported mode"); + ILLEGAL_PARAM("Unknown file mode: %u", fmode); gdk_threads_leave(); return NULL; } @@ -289,7 +294,7 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) &error); if(osname == NULL) { - g_warning("Error during latin1->filename conversion: %s", error->message); + WARNING_S("Error during latin1->filename conversion", error->message); return NULL; } @@ -337,6 +342,7 @@ glk_fileref_create_by_name(glui32 usage, char *name, glui32 rock) frefid_t glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) { + VALID_FILEREF(fref, return NULL); return fileref_new(fref->filename, rock, usage, fref->orig_filemode); } @@ -355,9 +361,13 @@ glk_fileref_create_from_fileref(glui32 usage, frefid_t fref, glui32 rock) void glk_fileref_destroy(frefid_t fref) { + VALID_FILEREF(fref, return); + glk_data->fileref_list = g_list_delete_link(glk_data->fileref_list, fref->fileref_list); if(fref->filename) g_free(fref->filename); + + fref->magic = MAGIC_FREE; g_free(fref); } @@ -370,9 +380,10 @@ glk_fileref_destroy(frefid_t fref) void glk_fileref_delete_file(frefid_t fref) { + VALID_FILEREF(fref, return); if( glk_fileref_does_file_exist(fref) ) if(g_unlink(fref->filename) == -1) - g_warning("Error deleting file %s", fref->filename); + IO_WARNING( "Error deleting file", fref->filename, g_strerror(errno) ); } /** @@ -387,6 +398,7 @@ glk_fileref_delete_file(frefid_t fref) glui32 glk_fileref_does_file_exist(frefid_t fref) { + VALID_FILEREF(fref, return 0); if( g_file_test(fref->filename, G_FILE_TEST_EXISTS) ) return 1; return 0; diff --git a/src/fileref.h b/src/fileref.h index 0ee0c47..cfbdcca 100644 --- a/src/fileref.h +++ b/src/fileref.h @@ -13,7 +13,7 @@ struct glk_fileref_struct { /*< private >*/ - glui32 rock; + glui32 magic, rock; /* Pointer to the list node in the global fileref list that contains this fileref */ GList* fileref_list; diff --git a/src/input.c b/src/input.c index c9775fc..bda5b4f 100644 --- a/src/input.c +++ b/src/input.c @@ -1,4 +1,5 @@ #include "charset.h" +#include "magic.h" #include "input.h" /** @@ -14,7 +15,7 @@ void glk_request_char_event(winid_t win) { - g_return_if_fail(win); + VALID_WINDOW(win, return); g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE); g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid); @@ -32,7 +33,7 @@ glk_request_char_event(winid_t win) void glk_request_char_event_uni(winid_t win) { - g_return_if_fail(win); + VALID_WINDOW(win, return); g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE); g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid); @@ -148,7 +149,7 @@ text_buffer_request_line_event_common(winid_t win, glui32 maxlen, gboolean inser void glk_request_line_event(winid_t win, char* buf, glui32 maxlen, glui32 initlen) { - g_return_if_fail(win); + VALID_WINDOW(win, return); g_return_if_fail(buf); g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE); g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid); @@ -167,8 +168,6 @@ glk_request_line_event(winid_t win, char* buf, glui32 maxlen, glui32 initlen) case wintype_TextGrid: text_grid_request_line_event_common(win, maxlen, (initlen > 0), inserttext); break; - default: - g_assert_not_reached(); } g_free(inserttext); } @@ -194,7 +193,7 @@ glk_request_line_event(winid_t win, char* buf, glui32 maxlen, glui32 initlen) void glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initlen) { - g_return_if_fail(win); + VALID_WINDOW(win, return); g_return_if_fail(buf); g_return_if_fail(win->input_request_type == INPUT_REQUEST_NONE); g_return_if_fail(win->type != wintype_TextBuffer || win->type != wintype_TextGrid); @@ -221,8 +220,6 @@ glk_request_line_event_uni(winid_t win, glui32 *buf, glui32 maxlen, glui32 initl case wintype_TextGrid: text_grid_request_line_event_common(win, maxlen, (initlen > 0), utf8); break; - default: - g_assert_not_reached(); } g_free(utf8); } @@ -364,7 +361,7 @@ end_line_input_request(winid_t win, const gchar *inserted_text) event_throw(evtype_LineInput, win, copycount, 0); } else - g_warning("%s: Wrong input request type.", __func__); + WARNING("Wrong input request type"); win->input_request_type = INPUT_REQUEST_NONE; } diff --git a/src/magic.c b/src/magic.c new file mode 100644 index 0000000..a385b96 --- /dev/null +++ b/src/magic.c @@ -0,0 +1,56 @@ +#include +#include "glk.h" +#include "magic.h" + +/* The "magic" mechanism was stolen from Evin Robertson's GtkGlk. */ + +static gchar * +magic_to_string(glui32 magic) +{ + switch(magic) + { + case MAGIC_WINDOW: + return "winid_t"; + case MAGIC_STREAM: + return "strid_t"; + case MAGIC_FILEREF: + return "frefid_t"; + case MAGIC_SCHANNEL: + return "schanid_t"; + default: + g_return_val_if_reached("unknown"); + } +} + +/* Internal function: check the object's magic number to make sure it is the + right type, and not freed. */ +gboolean +magic_is_valid_or_null(const glui32 goodmagic, const glui32 realmagic, const gchar *function) +{ + if(realmagic != MAGIC_NULL) + { + if(realmagic != goodmagic) + { + if(realmagic == MAGIC_FREE) + g_critical("%s: Using a freed object", function); + else + g_critical( "%s: %s object not a %s", function, magic_to_string(realmagic), magic_to_string(goodmagic) ); + return FALSE; + } + } + return TRUE; +} + + +/* Internal function: check the object's magic number to make sure it is + not NULL, the right type, and not freed. */ +gboolean +magic_is_valid(const void *obj, const glui32 goodmagic, const glui32 realmagic, const gchar *function) +{ + if(obj == NULL) + { + g_critical( "%s: NULL %s pointer", function, magic_to_string(goodmagic) ); + return FALSE; + } + return magic_is_valid_or_null(goodmagic, realmagic, function); +} diff --git a/src/magic.h b/src/magic.h new file mode 100644 index 0000000..155882c --- /dev/null +++ b/src/magic.h @@ -0,0 +1,41 @@ +#ifndef __MAGIC_H__ +#define __MAGIC_H__ + +#include +#include "glk.h" + +#define MAGIC_FREE 0x46524545 /* "FREE" */ +#define MAGIC_NULL 0x4E554C4C /* "NULL" */ +#define MAGIC_WINDOW 0x57494E44 /* "WIND" */ +#define MAGIC_STREAM 0x53545245 /* "STRE" */ +#define MAGIC_FILEREF 0x46494C45 /* "FILE" */ +#define MAGIC_SCHANNEL 0x53434841 /* "SCHA" */ + +gboolean magic_is_valid_or_null(const glui32 goodmagic, const glui32 realmagic, const gchar *function); +gboolean magic_is_valid(const void *obj, const glui32 goodmagic, const glui32 realmagic, const gchar *function); + +#define VALID_MAGIC(obj, goodmagic, die) \ + if( !magic_is_valid(obj, goodmagic, obj->magic, G_STRFUNC) ) die +#define VALID_MAGIC_OR_NULL(obj, goodmagic, die) \ + if( !magic_is_valid_or_null(goodmagic, obj? obj->magic : MAGIC_NULL, G_STRFUNC) ) die + +#define VALID_WINDOW(o, d) VALID_MAGIC(o, MAGIC_WINDOW, d) +#define VALID_WINDOW_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_WINDOW, d) +#define VALID_STREAM(o, d) VALID_MAGIC(o, MAGIC_STREAM, d) +#define VALID_STREAM_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_STREAM, d) +#define VALID_FILEREF(o, d) VALID_MAGIC(o, MAGIC_FILEREF, d) +#define VALID_FILEREF_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_FILEREF, d) +#define VALID_SCHANNEL(o, d) VALID_MAGIC(o, MAGIC_SCHANNEL, d) +#define VALID_SCHANNEL_OR_NULL(o, d) VALID_MAGIC_OR_NULL(o, MAGIC_SCHANNEL, d) + +/* This works with string variables as well as literal strings */ +#define ILLEGAL(str) g_critical("%s: %s", G_STRFUNC, str) +/* This only works with literal strings */ +#define ILLEGAL_PARAM(str, param) g_critical("%s: " str, G_STRFUNC, param) + +#define WARNING(msg) g_warning("%s: %s", G_STRFUNC, msg) +#define WARNING_S(msg, str) g_warning("%s: %s: %s", G_STRFUNC, msg, str) +#define IO_WARNING(msg, str, errmsg) \ + g_warning("%s: %s \"%s\": %s", G_STRFUNC, msg, str, errmsg) + +#endif /* __MAGIC_H__ */ diff --git a/src/main.c b/src/main.c index 6398348..fd2700d 100644 --- a/src/main.c +++ b/src/main.c @@ -115,7 +115,7 @@ main(int argc, char *argv[]) g_object_unref( G_OBJECT(builder) ); - if( !chimara_glk_run(CHIMARA_GLK(glk), ".libs/model.so", &error) ) { + if( !chimara_glk_run(CHIMARA_GLK(glk), ".libs/gridtest.so", &error) ) { error_dialog(GTK_WINDOW(window), error, "Error starting Glk library: "); return 1; } diff --git a/src/stream.c b/src/stream.c index bab5b5a..358d06b 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1,25 +1,38 @@ #include "stream.h" #include "fileref.h" +#include "magic.h" +#include +#include #include #include #include "chimara-glk-private.h" extern ChimaraGlkPrivate *glk_data; -/* Internal function: create a window stream to go with window. */ -strid_t -window_stream_new(winid_t window) +/* Internal function: create a stream with a specified rock value */ +static strid_t +stream_new_common(glui32 rock, glui32 fmode, enum StreamType type) { - /* Create stream and connect it to window */ strid_t str = g_new0(struct glk_stream_struct, 1); - str->file_mode = filemode_Write; - str->type = STREAM_TYPE_WINDOW; - str->window = window; - + str->magic = MAGIC_STREAM; + str->rock = rock; + str->file_mode = fmode; + str->type = type; + /* Add it to the global stream list */ glk_data->stream_list = g_list_prepend(glk_data->stream_list, str); str->stream_list = glk_data->stream_list; + + return str; +} +/* Internal function: create a window stream to go with window. */ +strid_t +window_stream_new(winid_t window) +{ + /* Create stream and connect it to window */ + strid_t str = stream_new_common(0, filemode_Write, STREAM_TYPE_WINDOW); + str->window = window; return str; } @@ -37,6 +50,8 @@ window_stream_new(winid_t window) strid_t glk_stream_iterate(strid_t str, glui32 *rockptr) { + VALID_STREAM_OR_NULL(str, return NULL); + GList *retnode; if(str == NULL) @@ -64,7 +79,7 @@ glk_stream_iterate(strid_t str, glui32 *rockptr) glui32 glk_stream_get_rock(strid_t str) { - g_return_val_if_fail(str != NULL, 0); + VALID_STREAM(str, return 0); return str->rock; } @@ -79,9 +94,11 @@ glk_stream_get_rock(strid_t str) void glk_stream_set_current(strid_t str) { + VALID_STREAM_OR_NULL(str, return); + if(str != NULL && str->file_mode == filemode_Read) { - g_warning("%s: Cannot set current stream to non output stream", __func__); + ILLEGAL("Cannot set current stream to non output stream"); return; } @@ -112,7 +129,7 @@ glk_stream_get_current() void glk_put_char(unsigned char ch) { - g_return_if_fail(glk_data->current_stream != NULL); + VALID_STREAM(glk_data->current_stream, return); glk_put_char_stream(glk_data->current_stream, ch); } @@ -127,7 +144,7 @@ glk_put_char(unsigned char ch) void glk_put_char_uni(glui32 ch) { - g_return_if_fail(glk_data->current_stream != NULL); + VALID_STREAM(glk_data->current_stream, return); glk_put_char_stream_uni(glk_data->current_stream, ch); } @@ -146,7 +163,7 @@ glk_put_char_uni(glui32 ch) void glk_put_string(char *s) { - g_return_if_fail(glk_data->current_stream != NULL); + VALID_STREAM(glk_data->current_stream, return); glk_put_string_stream(glk_data->current_stream, s); } @@ -161,7 +178,7 @@ glk_put_string(char *s) void glk_put_string_uni(glui32 *s) { - g_return_if_fail(glk_data->current_stream != NULL); + VALID_STREAM(glk_data->current_stream, return); glk_put_string_stream_uni(glk_data->current_stream, s); } @@ -181,7 +198,7 @@ glk_put_string_uni(glui32 *s) void glk_put_buffer(char *buf, glui32 len) { - g_return_if_fail(glk_data->current_stream != NULL); + VALID_STREAM(glk_data->current_stream, return); glk_put_buffer_stream(glk_data->current_stream, buf, len); } @@ -196,7 +213,7 @@ glk_put_buffer(char *buf, glui32 len) void glk_put_buffer_uni(glui32 *buf, glui32 len) { - g_return_if_fail(glk_data->current_stream != NULL); + VALID_STREAM(glk_data->current_stream, return); glk_put_buffer_stream_uni(glk_data->current_stream, buf, len); } @@ -222,19 +239,11 @@ glk_stream_open_memory(char *buf, glui32 buflen, glui32 fmode, glui32 rock) { g_return_val_if_fail(fmode != filemode_WriteAppend, NULL); - strid_t str = g_new0(struct glk_stream_struct, 1); - str->rock = rock; - str->file_mode = fmode; - str->type = STREAM_TYPE_MEMORY; + strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY); str->buffer = buf; str->mark = 0; str->buflen = buflen; str->unicode = FALSE; - - /* Add it to the global stream list */ - glk_data->stream_list = g_list_prepend(glk_data->stream_list, str); - str->stream_list = glk_data->stream_list; - return str; } @@ -258,19 +267,11 @@ glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, glui32 fmode, glui32 rock { g_return_val_if_fail(fmode != filemode_WriteAppend, NULL); - strid_t str = g_new0(struct glk_stream_struct, 1); - str->rock = rock; - str->file_mode = fmode; - str->type = STREAM_TYPE_MEMORY; + strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_MEMORY); str->ubuffer = buf; str->mark = 0; str->buflen = buflen; str->unicode = TRUE; - - /* Add it to the global stream list */ - glk_data->stream_list = g_list_prepend(glk_data->stream_list, str); - str->stream_list = glk_data->stream_list; - return str; } @@ -278,7 +279,7 @@ glk_stream_open_memory_uni(glui32 *buf, glui32 buflen, glui32 fmode, glui32 rock static strid_t file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) { - g_return_val_if_fail(fileref != NULL, NULL); + VALID_FILEREF(fileref, return NULL); gchar *modestr; /* Binary mode is 0x000, text mode 0x100 */ @@ -287,8 +288,7 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) { case filemode_Read: if(!g_file_test(fileref->filename, G_FILE_TEST_EXISTS)) { - g_warning("glk_stream_open_file: Tried to open a file in read " - "mode that didn't exist!"); + ILLEGAL_PARAM("Tried to open a nonexistent file, '%s', in read mode", fileref->filename); return NULL; } modestr = g_strdup(binary? "rb" : "r"); @@ -307,14 +307,14 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) } break; default: - g_warning("glk_stream_open_file: Invalid file mode"); + ILLEGAL_PARAM("Invalid file mode: %u", fmode); return NULL; } FILE *fp = g_fopen(fileref->filename, modestr); g_free(modestr); if(fp == NULL) { - g_warning("glk_stream_open_file: Error opening file"); + IO_WARNING( "Error opening file", fileref->filename, g_strerror(errno) ); return NULL; } @@ -325,31 +325,26 @@ file_stream_new(frefid_t fileref, glui32 fmode, glui32 rock, gboolean unicode) GtkWidget *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, - "File %s already exists. Overwrite?", fileref->filename); + "File '%s' already exists. Overwrite?", fileref->filename); gint response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); gdk_threads_leave(); if(response != GTK_RESPONSE_YES) { - fclose(fp); + if(fclose(fp) != 0) + IO_WARNING( "Error closing file", fileref->filename, g_strerror(errno) ); return NULL; } } - strid_t str = g_new0(struct glk_stream_struct, 1); - str->rock = rock; - str->file_mode = fmode; - str->type = STREAM_TYPE_FILE; + strid_t str = stream_new_common(rock, fmode, STREAM_TYPE_FILE); str->file_pointer = fp; str->binary = binary; str->unicode = unicode; str->filename = g_filename_to_utf8(fileref->filename, -1, NULL, NULL, NULL); if(str->filename == NULL) str->filename = g_strdup("Unknown file name"); /* fail silently */ - /* Add it to the global stream list */ - glk_data->stream_list = g_list_prepend(glk_data->stream_list, str); - str->stream_list = glk_data->stream_list; return str; } @@ -426,14 +421,13 @@ glk_stream_open_file_uni(frefid_t fileref, glui32 fmode, glui32 rock) void glk_stream_close(strid_t str, stream_result_t *result) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); /* Free resources associated with one specific type of stream */ switch(str->type) { case STREAM_TYPE_WINDOW: - g_warning("%s: Attempted to close a window stream. Use glk_window_" - "close() instead.", __func__); + ILLEGAL("Attempted to close a window stream. Use glk_window_close() instead."); return; case STREAM_TYPE_MEMORY: @@ -442,13 +436,11 @@ glk_stream_close(strid_t str, stream_result_t *result) case STREAM_TYPE_FILE: if(fclose(str->file_pointer) != 0) - g_warning("%s: Failed to close file '%s'.", __func__, - str->filename); + IO_WARNING( "Failed to close file", str->filename, g_strerror(errno) ); g_free(str->filename); break; default: - g_warning("%s: Closing this type of stream not supported.", - __func__); + ILLEGAL_PARAM("Unknown stream type: %u", str->type); return; } @@ -479,5 +471,7 @@ stream_close_common(strid_t str, stream_result_t *result) result->readcount = str->read_count; result->writecount = str->write_count; } + + str->magic = MAGIC_FREE; g_free(str); } diff --git a/src/stream.h b/src/stream.h index 25c052e..80df9c9 100644 --- a/src/stream.h +++ b/src/stream.h @@ -21,7 +21,7 @@ enum StreamType struct glk_stream_struct { /*< private >*/ - glui32 rock; + glui32 magic, rock; /* Pointer to the list node in the global stream list that contains this stream */ GList* stream_list; diff --git a/src/strio.c b/src/strio.c index 5fa395e..9baaf0f 100644 --- a/src/strio.c +++ b/src/strio.c @@ -1,5 +1,7 @@ #include "charset.h" +#include "magic.h" #include "stream.h" +#include #include #include #include @@ -112,7 +114,7 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) str->write_count += len; break; default: - g_warning("%s: Writing to this kind of window unsupported.", __func__); + ILLEGAL_PARAM("Unknown window type: %u", str->window->type); } /* Now write the same buffer to the window's echo stream */ @@ -165,7 +167,7 @@ write_buffer_to_stream(strid_t str, gchar *buf, glui32 len) str->write_count += len; break; default: - g_warning("%s: Writing to this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Unknown stream type: %u", str->type); } } @@ -213,7 +215,7 @@ write_buffer_to_stream_uni(strid_t str, glui32 *buf, glui32 len) str->write_count += len; break; default: - g_warning("%s: Writing to this kind of window unsupported.", __func__); + ILLEGAL_PARAM("Unknown window type: %u", str->window->type); } /* Now write the same buffer to the window's echo stream */ @@ -270,7 +272,7 @@ write_buffer_to_stream_uni(strid_t str, glui32 *buf, glui32 len) str->write_count += len; break; default: - g_warning("%s: Writing to this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Unknown stream type: %u", str->type); } } @@ -286,7 +288,7 @@ write_buffer_to_stream_uni(strid_t str, glui32 *buf, glui32 len) void glk_put_char_stream(strid_t str, unsigned char ch) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(str->file_mode != filemode_Read); write_buffer_to_stream(str, (gchar *)&ch, 1); @@ -304,7 +306,7 @@ glk_put_char_stream(strid_t str, unsigned char ch) void glk_put_char_stream_uni(strid_t str, glui32 ch) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(str->file_mode != filemode_Read); write_buffer_to_stream_uni(str, &ch, 1); @@ -322,7 +324,7 @@ glk_put_char_stream_uni(strid_t str, glui32 ch) void glk_put_string_stream(strid_t str, char *s) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(str->file_mode != filemode_Read); write_buffer_to_stream(str, s, strlen(s)); @@ -340,7 +342,7 @@ glk_put_string_stream(strid_t str, char *s) void glk_put_string_stream_uni(strid_t str, glui32 *s) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(str->file_mode != filemode_Read); /* An impromptu strlen() for glui32 arrays */ @@ -364,7 +366,7 @@ glk_put_string_stream_uni(strid_t str, glui32 *s) void glk_put_buffer_stream(strid_t str, char *buf, glui32 len) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(str->file_mode != filemode_Read); write_buffer_to_stream(str, buf, len); @@ -383,7 +385,7 @@ glk_put_buffer_stream(strid_t str, char *buf, glui32 len) void glk_put_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(str->file_mode != filemode_Read); write_buffer_to_stream_uni(str, buf, len); @@ -447,7 +449,8 @@ is_unicode_newline(glsi32 ch, FILE *fp, gboolean utf8) glsi32 ch2 = utf8? read_utf8_char_from_file(fp) : read_ucs4be_char_from_file(fp); if(ch2 != 0x0A) - fseek(fp, utf8? -1 : -4, SEEK_CUR); + if(fseek(fp, utf8? -1 : -4, SEEK_CUR) == -1); + WARNING_S("Seek failed on stream", g_strerror(errno) ); return TRUE; } return FALSE; @@ -511,7 +514,7 @@ get_char_stream_common(strid_t str) return ch; } default: - g_warning("%s: Reading from this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type); return -1; } } @@ -547,7 +550,7 @@ get_char_stream_common(strid_t str) glsi32 glk_get_char_stream(strid_t str) { - g_return_val_if_fail(str != NULL, -1); + VALID_STREAM(str, return -1); g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, -1); glsi32 ch = get_char_stream_common(str); @@ -566,7 +569,7 @@ glk_get_char_stream(strid_t str) glsi32 glk_get_char_stream_uni(strid_t str) { - g_return_val_if_fail(str != NULL, -1); + VALID_STREAM(str, return -1); g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, -1); return get_char_stream_common(str); @@ -586,7 +589,7 @@ glk_get_char_stream_uni(strid_t str) glui32 glk_get_buffer_stream(strid_t str, char *buf, glui32 len) { - g_return_val_if_fail(str != NULL, 0); + VALID_STREAM(str, return 0); g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0); g_return_val_if_fail(buf != NULL, 0); @@ -626,7 +629,7 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) if(count % 4 != 0) { count -= count % 4; - g_warning("%s: Incomplete character in binary Unicode file.", __func__); + WARNING("Incomplete character in binary Unicode file"); } int foo; @@ -664,7 +667,7 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) return foo; } default: - g_warning("%s: Reading from this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type); return 0; } } @@ -683,7 +686,7 @@ glk_get_buffer_stream(strid_t str, char *buf, glui32 len) glui32 glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) { - g_return_val_if_fail(str != NULL, 0); + VALID_STREAM(str, return 0); g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0); g_return_val_if_fail(buf != NULL, 0); @@ -723,7 +726,7 @@ glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) if(count % 4 != 0) { count -= count % 4; - g_warning("%s: Incomplete character in binary Unicode file.", __func__); + WARNING("Incomplete character in binary Unicode file"); } int foo; @@ -763,7 +766,7 @@ glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) return foo; } default: - g_warning("%s: Reading from this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type); return 0; } } @@ -789,7 +792,7 @@ glk_get_buffer_stream_uni(strid_t str, glui32 *buf, glui32 len) glui32 glk_get_line_stream(strid_t str, char *buf, glui32 len) { - g_return_val_if_fail(str != NULL, 0); + VALID_STREAM(str, return 0); g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0); g_return_val_if_fail(buf != NULL, 0); @@ -895,7 +898,7 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len) return foo; } default: - g_warning("%s: Reading from this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type); return 0; } } @@ -920,7 +923,7 @@ glk_get_line_stream(strid_t str, char *buf, glui32 len) glui32 glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) { - g_return_val_if_fail(str != NULL, 0); + VALID_STREAM(str, return 0); g_return_val_if_fail(str->file_mode == filemode_Read || str->file_mode == filemode_ReadWrite, 0); g_return_val_if_fail(buf != NULL, 0); @@ -1037,7 +1040,7 @@ glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) return foo; } default: - g_warning("%s: Reading from this kind of stream unsupported.", __func__); + ILLEGAL_PARAM("Reading illegal on stream type: %u", str->type); return 0; } } @@ -1076,7 +1079,7 @@ glk_get_line_stream_uni(strid_t str, glui32 *buf, glui32 len) glui32 glk_stream_get_position(strid_t str) { - g_return_val_if_fail(str != NULL, 0); + VALID_STREAM(str, return 0); switch(str->type) { @@ -1085,8 +1088,7 @@ glk_stream_get_position(strid_t str) case STREAM_TYPE_FILE: return ftell(str->file_pointer); default: - g_warning("%s: Seeking not supported on this type of stream.", - __func__); + ILLEGAL_PARAM("Seeking illegal on stream type: %u", str->type); return 0; } } @@ -1120,7 +1122,7 @@ glk_stream_get_position(strid_t str) void glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) { - g_return_if_fail(str != NULL); + VALID_STREAM(str, return); g_return_if_fail(!(seekmode == seekmode_Start && pos < 0)); g_return_if_fail(!(seekmode == seekmode_End || pos > 0)); @@ -1133,7 +1135,7 @@ glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) case seekmode_Current: str->mark += pos; break; case seekmode_End: str->mark = str->buflen + pos; break; default: - g_assert_not_reached(); + g_return_if_reached(); return; } break; @@ -1146,14 +1148,15 @@ glk_stream_set_position(strid_t str, glsi32 pos, glui32 seekmode) case seekmode_Current: whence = SEEK_CUR; break; case seekmode_End: whence = SEEK_END; break; default: - g_assert_not_reached(); + g_return_if_reached(); return; } - fseek(str->file_pointer, pos, whence); + if(fseek(str->file_pointer, pos, whence) == -1) + WARNING("Seek failed on file stream"); break; } default: - g_warning("%s: Seeking not supported on this type of stream.", __func__); + ILLEGAL_PARAM("Seeking illegal on stream type: %u", str->type); return; } } diff --git a/src/window.c b/src/window.c index f533cc7..364cc14 100644 --- a/src/window.c +++ b/src/window.c @@ -1,4 +1,5 @@ #include "window.h" +#include "magic.h" #include "chimara-glk-private.h" extern ChimaraGlkPrivate *glk_data; @@ -22,6 +23,8 @@ extern ChimaraGlkPrivate *glk_data; winid_t glk_window_iterate(winid_t win, glui32 *rockptr) { + VALID_WINDOW_OR_NULL(win, return NULL); + GNode *retnode; if(win == NULL) @@ -62,7 +65,7 @@ glk_window_iterate(winid_t win, glui32 *rockptr) glui32 glk_window_get_rock(winid_t win) { - g_return_val_if_fail(win != NULL, 0); + VALID_WINDOW(win, return 0); return win->rock; } @@ -78,7 +81,7 @@ glk_window_get_rock(winid_t win) glui32 glk_window_get_type(winid_t win) { - g_return_val_if_fail(win != NULL, 0); + VALID_WINDOW(win, return 0); return win->type; } @@ -96,7 +99,7 @@ glk_window_get_type(winid_t win) winid_t glk_window_get_parent(winid_t win) { - g_return_val_if_fail(win != NULL, NULL); + VALID_WINDOW(win, return NULL); /* Value will also be NULL if win is the root window */ return (winid_t)win->window_node->parent->data; } @@ -113,7 +116,7 @@ glk_window_get_parent(winid_t win) winid_t glk_window_get_sibling(winid_t win) { - g_return_val_if_fail(win != NULL, NULL); + VALID_WINDOW(win, return NULL); if(G_NODE_IS_ROOT(win->window_node)) return NULL; @@ -332,17 +335,11 @@ winid_t glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, glui32 rock) { - /* - if(split) - { - g_warning("glk_window_open: splitting of windows not implemented"); - return NULL; - } - */ + VALID_WINDOW_OR_NULL(split, return NULL); if(split == NULL && glk_data->root_window != NULL) { - g_warning("glk_window_open: there is already a root window"); + ILLEGAL("Tried to open a new root window, but there is already a root window"); return NULL; } @@ -350,6 +347,7 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, /* We only create one window and don't support any more than that */ winid_t win = g_new0(struct glk_window_struct, 1); + win->magic = MAGIC_WINDOW; win->rock = rock; win->type = wintype; win->window_node = g_node_new(win); @@ -452,7 +450,7 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, default: gdk_threads_leave(); - g_warning("%s: unsupported window type", __func__); + ILLEGAL_PARAM("Unknown window type: %u", wintype); g_free(win); g_node_destroy(glk_data->root_window); glk_data->root_window = NULL; @@ -613,10 +611,10 @@ glk_window_open(winid_t split, glui32 method, glui32 size, glui32 wintype, void glk_window_close(winid_t win, stream_result_t *result) { + VALID_WINDOW(win, return); + GNode* parent_node; - g_return_if_fail(win != NULL); - gdk_threads_enter(); switch(win->type) @@ -644,7 +642,7 @@ glk_window_close(winid_t win, stream_result_t *result) break; default: - g_warning("%s: unsupported window type", __func__); + ILLEGAL_PARAM("Unknown window type: %u", win->type); gdk_threads_leave(); return; } @@ -661,7 +659,9 @@ glk_window_close(winid_t win, stream_result_t *result) glk_data->root_window = parent_node->next; else if(parent_node->prev) glk_data->root_window = parent_node->prev; - } else { + } + else + { if(parent_node->next) g_node_append(parent_node->parent, parent_node->next); else if(parent_node->prev) @@ -673,6 +673,7 @@ glk_window_close(winid_t win, stream_result_t *result) } g_node_destroy(win->window_node); + win->magic = MAGIC_FREE; g_free(win); gdk_threads_leave(); @@ -718,7 +719,7 @@ glk_window_close(winid_t win, stream_result_t *result) void glk_window_clear(winid_t win) { - g_return_if_fail(win != NULL); + VALID_WINDOW(win, return); g_return_if_fail(win->input_request_type != INPUT_REQUEST_LINE && win->input_request_type != INPUT_REQUEST_LINE_UNICODE); switch(win->type) @@ -771,7 +772,7 @@ glk_window_clear(winid_t win) break; default: - g_warning("glk_window_clear: unsupported window type"); + ILLEGAL_PARAM("Unknown window type: %d", win->type); } } @@ -785,6 +786,7 @@ glk_window_clear(winid_t win) void glk_set_window(winid_t win) { + VALID_WINDOW_OR_NULL(win, return); glk_stream_set_current( glk_window_get_stream(win) ); } @@ -805,7 +807,7 @@ glk_set_window(winid_t win) */ strid_t glk_window_get_stream(winid_t win) { - g_return_val_if_fail(win != NULL, NULL); + VALID_WINDOW(win, return NULL); return win->window_stream; } @@ -826,7 +828,8 @@ strid_t glk_window_get_stream(winid_t win) void glk_window_set_echo_stream(winid_t win, strid_t str) { - g_return_if_fail(win != NULL); + VALID_WINDOW(win, return); + VALID_STREAM_OR_NULL(str, return); /* Test for an infinite loop */ strid_t next = str; @@ -834,7 +837,7 @@ glk_window_set_echo_stream(winid_t win, strid_t str) { if(next == win->window_stream) { - g_warning("%s: Infinite loop detected", __func__); + ILLEGAL("Infinite loop detected"); win->echo_stream = NULL; return; } @@ -855,7 +858,7 @@ glk_window_set_echo_stream(winid_t win, strid_t str) strid_t glk_window_get_echo_stream(winid_t win) { - g_return_val_if_fail(win != NULL, NULL); + VALID_WINDOW(win, return NULL); return win->echo_stream; } @@ -875,7 +878,7 @@ glk_window_get_echo_stream(winid_t win) void glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) { - g_return_if_fail(win != NULL); + VALID_WINDOW(win, return); switch(win->type) { @@ -923,7 +926,7 @@ glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) break; default: - g_warning("glk_window_get_size: Unsupported window type"); + ILLEGAL_PARAM("Unknown window type: %u", win->type); } } @@ -960,7 +963,7 @@ glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr) void glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos) { - g_return_if_fail(win != NULL); + VALID_WINDOW(win, return); g_return_if_fail(win->type == wintype_TextGrid); /* Calculate actual position if cursor is moved past the right edge */ diff --git a/src/window.h b/src/window.h index 30fe53d..e957de8 100644 --- a/src/window.h +++ b/src/window.h @@ -27,7 +27,7 @@ enum InputRequestType struct glk_window_struct { /*< private >*/ - glui32 rock; + glui32 magic, rock; /* Pointer to the node in the global tree that contains this window */ GNode *window_node; /* Window parameters */ -- 2.30.2