From 2b7788614f102db37e76ac612c148c32c208b623 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 10 Mar 2007 23:50:56 +0200 Subject: [PATCH] Type-check button arguments of msg_box. Don't cast function pointers; calling functions via pointers of incorrect types is not guaranteed to work. Instead, define the functions with the desired types, and make them cast the incoming parameters. Or define wrapper functions if the return types don't match. really_exit_prog wasn't being used outside src/dialogs/menu.c, and I had to change its parameter type, so it's now static. --- src/bfu/hierbox.c | 24 +++++++++++++++--------- src/bfu/msgbox.c | 11 +++++++---- src/bfu/msgbox.h | 25 ++++++++++++++++++++++--- src/config/dialogs.c | 8 ++++---- src/cookies/dialogs.c | 16 ++++++++++++++-- src/dialogs/info.c | 4 ++-- src/dialogs/menu.c | 14 +++++++++----- src/dialogs/menu.h | 1 - src/formhist/formhist.c | 31 +++++++++++++++++++++---------- src/mime/dialogs.c | 4 ++-- src/protocol/protocol.c | 2 +- src/scripting/python/dialogs.c | 2 +- src/session/download.c | 23 +++++++++++++++-------- src/session/session.c | 2 +- src/session/task.c | 12 ++++++++---- src/terminal/tab.c | 14 ++++++++------ 16 files changed, 130 insertions(+), 63 deletions(-) diff --git a/src/bfu/hierbox.c b/src/bfu/hierbox.c index 751d4c574..399ff4d76 100644 --- a/src/bfu/hierbox.c +++ b/src/bfu/hierbox.c @@ -438,7 +438,7 @@ push_hierbox_info_button(struct dialog_data *dlg_data, struct widget_data *butto N_("Info"), ALIGN_LEFT, msg, context, 1, - N_("~OK"), done_listbox_context, B_ESC | B_ENTER); + MSG_BOX_BUTTON(N_("~OK"), done_listbox_context, B_ESC | B_ENTER)); return EVENT_PROCESSED; } @@ -751,8 +751,8 @@ query_delete_selected_item(void *context_) listbox_message(delete_folder_title), ALIGN_CENTER, msg_text(term, listbox_message(delete_folder), text), context, 2, - N_("~Yes"), push_ok_delete_button, B_ENTER, - N_("~No"), done_listbox_context, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), push_ok_delete_button, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), done_listbox_context, B_ESC)); } else { unsigned char *msg = ops->get_info(item, term); @@ -763,8 +763,8 @@ query_delete_selected_item(void *context_) msg_text(term, listbox_message(delete_item), text, empty_string_or_(msg)), context, 2, - N_("~Yes"), push_ok_delete_button, B_ENTER, - N_("~No"), done_listbox_context, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), push_ok_delete_button, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), done_listbox_context, B_ESC)); mem_free_if(msg); } mem_free(text); @@ -772,6 +772,12 @@ query_delete_selected_item(void *context_) return EVENT_PROCESSED; } +static void +dont_delete_marked_items(void *const context_) +{ + query_delete_selected_item(context_); +} + widget_handler_status_T push_hierbox_delete_button(struct dialog_data *dlg_data, struct widget_data *button) @@ -805,8 +811,8 @@ push_hierbox_delete_button(struct dialog_data *dlg_data, listbox_message(delete_marked_items_title), ALIGN_CENTER, listbox_message(delete_marked_items), context, 2, - N_("~Yes"), push_ok_delete_button, B_ENTER, - N_("~No"), query_delete_selected_item, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), push_ok_delete_button, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), dont_delete_marked_items, B_ESC)); return EVENT_PROCESSED; } @@ -867,8 +873,8 @@ push_hierbox_clear_button(struct dialog_data *dlg_data, listbox_message(clear_all_items_title), ALIGN_CENTER, listbox_message(clear_all_items), context, 2, - N_("~Yes"), do_clear_browser, B_ENTER, - N_("~No"), NULL, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), do_clear_browser, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), NULL, B_ESC)); return EVENT_PROCESSED; } diff --git a/src/bfu/msgbox.c b/src/bfu/msgbox.c index 00924cbd0..d7af62be5 100644 --- a/src/bfu/msgbox.c +++ b/src/bfu/msgbox.c @@ -71,7 +71,7 @@ msg_box(struct terminal *term, struct memory_list *ml, enum msgbox_flags flags, int bflags; label = va_arg(ap, unsigned char *); - done = va_arg(ap, void *); + done = va_arg(ap, done_handler_T *); bflags = va_arg(ap, int); if (!label) { @@ -170,7 +170,7 @@ refreshed_msg_box(struct terminal *term, enum msgbox_flags flags, title, align, info, data, 1, - N_("~OK"), NULL, B_ENTER | B_ESC); + MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC)); if (!dlg_data) return; @@ -187,6 +187,9 @@ info_box(struct terminal *term, enum msgbox_flags flags, unsigned char *text) { /* [gettext_accelerator_context(info_box)] */ - return msg_box(term, NULL, flags, title, align, text, - NULL, 1, N_("~OK"), NULL, B_ENTER | B_ESC); + return msg_box(term, NULL, flags, + title, align, + text, + NULL, 1, + MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC)); } diff --git a/src/bfu/msgbox.h b/src/bfu/msgbox.h index 3ed0848b0..2e06fe8ae 100644 --- a/src/bfu/msgbox.h +++ b/src/bfu/msgbox.h @@ -64,7 +64,7 @@ enum msgbox_flags { * @udata Is a reference to any data that should be passed to * the handlers associated with each button. NULL if none. * - * @buttons Denotes the number of buttons given as varadic arguments. + * @buttons Denotes the number of buttons given as variadic arguments. * For each button 3 arguments are extracted: * o First the label text. It is automatically localized * unless MSGBOX_NO_INTL is passed. If NULL, this button @@ -72,6 +72,10 @@ enum msgbox_flags { * o Second pointer to the handler function (taking * one (void *), which is incidentally the udata). * o Third any flags. + * Each triple should be wrapped in the MSG_BOX_BUTTON + * macro, which converts the values to the correct types. + * (The compiler can't do that on its own for variadic + * arguments.) * * Note that you should ALWAYS format the msg_box() call like: * @@ -79,9 +83,9 @@ enum msgbox_flags { * title, align, * text, * udata, M, - * label1, handler1, flags1, + * MSG_BOX_BUTTON(label1, handler1, flags1), * ..., - * labelM, handlerM, flagsM); + * MSG_BOX_BUTTON(labelM, handlerM, flagsM)); * * ...no matter that it could fit on one line in case of a tiny message box. */ struct dialog_data * @@ -89,6 +93,21 @@ msg_box(struct terminal *term, struct memory_list *mem_list, enum msgbox_flags flags, unsigned char *title, enum format_align align, unsigned char *text, void *udata, int buttons, ...); +/* Cast @value to @type and warn if the conversion is suspicious. + * If @value has side effects, this does them only once. + * The expression used here is intended to be standard C, but it is + * somewhat tricky. If it causes trouble on some compiler, you can + * #ifdef an alternative definition that skips the type check. */ +#define MSG_BOX_CAST(type, value) \ + (((void) sizeof(((int (*)(type)) 0)(value))), (type) (value)) + +/* A button in the variadic arguments of msg_box(). + * This macro expands into three arguments. */ +#define MSG_BOX_BUTTON(label, handler, flags) \ + MSG_BOX_CAST(const unsigned char *, label), \ + MSG_BOX_CAST(done_handler_T *, handler), \ + MSG_BOX_CAST(int, flags) + /* msg_text() is basically an equivalent to asprintf(), specifically to be used * inside of message boxes. Please always use msg_text() instead of asprintf() diff --git a/src/config/dialogs.c b/src/config/dialogs.c index 35d893c48..b90add053 100644 --- a/src/config/dialogs.c +++ b/src/config/dialogs.c @@ -54,8 +54,8 @@ write_config_dialog(struct terminal *term, unsigned char *config_file, msg_text(term, N_("Options were saved successfully to config file %s."), config_file), NULL, 2, - N_("~OK"), NULL, B_ENTER | B_ESC, - N_("~Do not show anymore"), disable_success_msgbox, 0); + MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC), + MSG_BOX_BUTTON(N_("~Do not show anymore"), disable_success_msgbox, 0)); return; } @@ -815,8 +815,8 @@ really_add_keybinding(void *data, unsigned char *keystroke) canonical.length ? canonical.source : keystroke, get_action_name(hop->keymap_id, action_id)), new_hop, 2, - N_("~Yes"), really_really_add_keybinding, B_ENTER, - N_("~No"), NULL, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), really_really_add_keybinding, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), NULL, B_ESC)); done_string(&canonical); /* safe even if init failed */ return; diff --git a/src/cookies/dialogs.c b/src/cookies/dialogs.c index 1b8101668..27bcab9f4 100644 --- a/src/cookies/dialogs.c +++ b/src/cookies/dialogs.c @@ -50,6 +50,18 @@ add_cookie_info_to_string(struct string *string, struct cookie *cookie, _(cookie->secure ? N_("yes") : N_("no"), term)); } +static void +accept_cookie_in_msg_box(void *cookie_) +{ + accept_cookie((struct cookie *) cookie_); +} + +static void +reject_cookie_in_msg_box(void *cookie_) +{ + done_cookie((struct cookie *) cookie_); +} + /* TODO: Store cookie in data arg. --jonas*/ void accept_cookie_dialog(struct session *ses, void *data) @@ -78,8 +90,8 @@ accept_cookie_dialog(struct session *ses, void *data) N_("Accept cookie?"), ALIGN_LEFT, string.source, cookie, 2, - N_("~Accept"), accept_cookie, B_ENTER, - N_("~Reject"), done_cookie, B_ESC); + MSG_BOX_BUTTON(N_("~Accept"), accept_cookie_in_msg_box, B_ENTER), + MSG_BOX_BUTTON(N_("~Reject"), reject_cookie_in_msg_box, B_ESC)); } diff --git a/src/dialogs/info.c b/src/dialogs/info.c index f9b6e8b4d..0117418fa 100644 --- a/src/dialogs/info.c +++ b/src/dialogs/info.c @@ -131,8 +131,8 @@ menu_keys(struct terminal *term, void *d_, void *xxx) N_("Keys"), ALIGN_LEFT, keys.source, info, 2, - N_("~OK"), NULL, B_ENTER | B_ESC, - N_("~Toggle display"), push_toggle_keys_display_button, B_ENTER); + MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC), + MSG_BOX_BUTTON(N_("~Toggle display"), push_toggle_keys_display_button, B_ENTER)); } void diff --git a/src/dialogs/menu.c b/src/dialogs/menu.c index 101d97e7d..615e66e3e 100644 --- a/src/dialogs/menu.c +++ b/src/dialogs/menu.c @@ -100,15 +100,19 @@ save_url_as(struct session *ses) NULL); } -void -really_exit_prog(struct session *ses) +static void +really_exit_prog(void *ses_) { + struct session *ses = ses_; + register_bottom_half(destroy_terminal, ses->tab->term); } static inline void -dont_exit_prog(struct session *ses) +dont_exit_prog(void *ses_) { + struct session *ses = ses_; + ses->exit_query = 0; } @@ -124,8 +128,8 @@ query_exit(struct session *ses) "(and terminate all downloads)?") : N_("Do you really want to exit ELinks?"), ses, 2, - N_("~Yes"), (void (*)(void *)) really_exit_prog, B_ENTER, - N_("~No"), (void (*)(void *)) dont_exit_prog, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), really_exit_prog, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), dont_exit_prog, B_ESC)); } void diff --git a/src/dialogs/menu.h b/src/dialogs/menu.h index 4d0077bd1..c5848c600 100644 --- a/src/dialogs/menu.h +++ b/src/dialogs/menu.h @@ -24,7 +24,6 @@ void free_history_lists(void); void query_file(struct session *, struct uri *, void *, void (*)(void *, unsigned char *), void (*)(void *), int); -void really_exit_prog(struct session *ses); void query_exit(struct session *ses); void exit_prog(struct session *ses, int query); diff --git a/src/formhist/formhist.c b/src/formhist/formhist.c index c1227f0ab..cea478a91 100644 --- a/src/formhist/formhist.c +++ b/src/formhist/formhist.c @@ -330,20 +330,31 @@ forget_forms_with_url(unsigned char *url) return count; } -/* Appends form data @form1 (url and submitted_value(s)) to the password file. - * Returns 1 on success, 0 otherwise. */ -static int -remember_form(struct formhist_data *form) +/* Appends form data @form_ (url and submitted_value(s)) to the password file. */ +static void +remember_form(void *form_) { + struct formhist_data *form = form_; + forget_forms_with_url(form->url); add_to_list(saved_forms, form); - return save_formhist_to_file(); + save_formhist_to_file(); } -static int -never_for_this_site(struct formhist_data *form) +static void +dont_remember_form(void *form_) { + struct formhist_data *form = form_; + + done_formhist_item(form); +} + +static void +never_for_this_site(void *form_) +{ + struct formhist_data *form = form_; + form->dontsave = 1; return remember_form(form); } @@ -416,9 +427,9 @@ memorize_form(struct session *ses, struct list_head *submit, "obscured (but unencrypted) in a file on your disk.\n\n" "If you are using a valuable password, answer NO."), form, 3, - N_("~Yes"), remember_form, B_ENTER, - N_("~No"), done_formhist_item, B_ESC, - N_("Ne~ver for this site"), never_for_this_site, NULL); + MSG_BOX_BUTTON(N_("~Yes"), remember_form, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), dont_remember_form, B_ESC), + MSG_BOX_BUTTON(N_("Ne~ver for this site"), never_for_this_site, 0)); return; diff --git a/src/mime/dialogs.c b/src/mime/dialogs.c index fc90cc26e..2a67fcfde 100644 --- a/src/mime/dialogs.c +++ b/src/mime/dialogs.c @@ -67,8 +67,8 @@ menu_del_ext(struct terminal *term, void *fcp, void *xxx2) msg_text(term, N_("Delete extension %s -> %s?"), extension, opt->value.string), extension, 2, - N_("~Yes"), really_del_ext, B_ENTER, - N_("~No"), NULL, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), really_del_ext, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), NULL, B_ESC)); } diff --git a/src/protocol/protocol.c b/src/protocol/protocol.c index 3ffca54c5..d7d2e71af 100644 --- a/src/protocol/protocol.c +++ b/src/protocol/protocol.c @@ -233,7 +233,7 @@ generic_external_protocol_handler(struct session *ses, struct uri *uri) "%s protocol support"), protocol_backends[uri->protocol].name), ses, 1, - N_("~OK"), NULL, B_ENTER | B_ESC); + MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC)); return; } diff --git a/src/scripting/python/dialogs.c b/src/scripting/python/dialogs.c index 009ede76c..da096cb7c 100644 --- a/src/scripting/python/dialogs.c +++ b/src/scripting/python/dialogs.c @@ -83,7 +83,7 @@ python_info_box(PyObject *self, PyObject *args, PyObject *kwargs) title, ALIGN_LEFT, text, NULL, 1, - N_("~OK"), NULL, B_ENTER | B_ESC); + MSG_BOX_BUTTON(N_("~OK"), NULL, B_ENTER | B_ESC)); Py_INCREF(Py_None); return Py_None; diff --git a/src/session/download.c b/src/session/download.c index ee9917024..fdb41a191 100644 --- a/src/session/download.c +++ b/src/session/download.c @@ -493,16 +493,20 @@ struct cdf_hop { }; static void -lun_alternate(struct lun_hop *lun_hop) +lun_alternate(void *lun_hop_) { + struct lun_hop *lun_hop = lun_hop_; + lun_hop->callback(lun_hop->term, lun_hop->file, lun_hop->data, 0); mem_free_if(lun_hop->ofile); mem_free(lun_hop); } static void -lun_cancel(struct lun_hop *lun_hop) +lun_cancel(void *lun_hop_) { + struct lun_hop *lun_hop = lun_hop_; + lun_hop->callback(lun_hop->term, NULL, lun_hop->data, 0); mem_free_if(lun_hop->ofile); mem_free_if(lun_hop->file); @@ -510,8 +514,10 @@ lun_cancel(struct lun_hop *lun_hop) } static void -lun_overwrite(struct lun_hop *lun_hop) +lun_overwrite(void *lun_hop_) { + struct lun_hop *lun_hop = lun_hop_; + lun_hop->callback(lun_hop->term, lun_hop->ofile, lun_hop->data, 0); mem_free_if(lun_hop->file); mem_free(lun_hop); @@ -520,8 +526,9 @@ lun_overwrite(struct lun_hop *lun_hop) static void common_download_do(struct terminal *term, int fd, void *data, int resume); static void -lun_resume(struct lun_hop *lun_hop) +lun_resume(void *lun_hop_) { + struct lun_hop *lun_hop = lun_hop_; struct cdf_hop *cdf_hop = lun_hop->data; int magic = *(int *)cdf_hop->data; @@ -631,10 +638,10 @@ lookup_unique_name(struct terminal *term, unsigned char *ofile, int resume, empty_string_or_(lun_hop->ofile), empty_string_or_(file)), lun_hop, 4, - N_("Sa~ve under the alternative name"), lun_alternate, B_ENTER, - N_("~Overwrite the original file"), lun_overwrite, 0, - N_("~Resume download of the original file"), lun_resume, 0, - N_("~Cancel"), lun_cancel, B_ESC); + MSG_BOX_BUTTON(N_("Sa~ve under the alternative name"), lun_alternate, B_ENTER), + MSG_BOX_BUTTON(N_("~Overwrite the original file"), lun_overwrite, 0), + MSG_BOX_BUTTON(N_("~Resume download of the original file"), lun_resume, 0), + MSG_BOX_BUTTON(N_("~Cancel"), lun_cancel, B_ESC)); } diff --git a/src/session/session.c b/src/session/session.c index 79e4ea8ee..04d3f7c61 100644 --- a/src/session/session.c +++ b/src/session/session.c @@ -804,7 +804,7 @@ setup_first_session(struct session *ses, struct uri *uri) "Press ESC for menu. Documentation is available in " "Help menu."), ses, 1, - N_("~OK"), handler, B_ENTER | B_ESC); + MSG_BOX_BUTTON(N_("~OK"), handler, B_ENTER | B_ESC)); /* If there is no URI the goto dialog will pop up so there is * no need to call setup_session(). */ diff --git a/src/session/task.c b/src/session/task.c index 0595a8468..27e2f55cb 100644 --- a/src/session/task.c +++ b/src/session/task.c @@ -85,8 +85,10 @@ ses_load(struct session *ses, struct uri *uri, unsigned char *target_frame, } static void -post_yes(struct task *task) +post_yes(void *task_) { + struct task *task = task_; + abort_preloading(task->ses, 0); /* XXX: Make the session inherit the URI. */ @@ -96,8 +98,10 @@ post_yes(struct task *task) } static void -post_no(struct task *task) +post_no(void *task_) { + struct task *task = task_; + reload(task->ses, CACHE_MODE_NORMAL); done_uri(task->uri); } @@ -270,8 +274,8 @@ ses_goto(struct session *ses, struct uri *uri, unsigned char *target_frame, N_("Warning"), ALIGN_CENTER, message, task, 2, - N_("~Yes"), post_yes, B_ENTER, - N_("~No"), post_no, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), post_yes, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), post_no, B_ESC)); } diff --git a/src/terminal/tab.c b/src/terminal/tab.c index 24ac7579f..8aaf8a38d 100644 --- a/src/terminal/tab.c +++ b/src/terminal/tab.c @@ -169,8 +169,9 @@ switch_current_tab(struct session *ses, int direction) } static void -really_close_tab(struct session *ses) +really_close_tab(void *ses_) { + struct session *ses = ses_; struct terminal *term = ses->tab->term; struct window *current_tab = get_current_tab(term); @@ -203,13 +204,14 @@ close_tab(struct terminal *term, struct session *ses) N_("Close tab"), ALIGN_CENTER, N_("Do you really want to close the current tab?"), ses, 2, - N_("~Yes"), (void (*)(void *)) really_close_tab, B_ENTER, - N_("~No"), NULL, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), really_close_tab, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), NULL, B_ESC)); } static void -really_close_tabs(struct session *ses) +really_close_tabs(void *ses_) { + struct session *ses = ses_; struct terminal *term = ses->tab->term; struct window *current_tab = get_current_tab(term); struct window *tab; @@ -246,8 +248,8 @@ close_all_tabs_but_current(struct session *ses) N_("Close tab"), ALIGN_CENTER, N_("Do you really want to close all except the current tab?"), ses, 2, - N_("~Yes"), (void (*)(void *)) really_close_tabs, B_ENTER, - N_("~No"), NULL, B_ESC); + MSG_BOX_BUTTON(N_("~Yes"), really_close_tabs, B_ENTER), + MSG_BOX_BUTTON(N_("~No"), NULL, B_ESC)); }