Bochs/bochs/gui/win32config.cc

799 lines
26 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2023 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
#include "win32dialog.h"
#include "bochs.h"
#include "bx_debug/debug.h"
#include "param_names.h"
#include "gui.h"
#include "win32res.h"
#include "win32paramdlg.h"
#include "plugin.h"
#if BX_USE_WIN32CONFIG
static int win32_ci_callback(void *userdata, ci_command_t command);
static BxEvent* win32_notify_callback(void *unused, BxEvent *event);
PLUGIN_ENTRY_FOR_MODULE(win32config)
{
if (mode == PLUGIN_INIT) {
SIM->register_configuration_interface("win32config", win32_ci_callback, NULL);
SIM->set_notify_callback(win32_notify_callback, NULL);
} else if (mode == PLUGIN_PROBE) {
return (int)PLUGTYPE_CI;
}
return 0; // Success
}
diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/bochs.h ./bochs.h --- /home/volker/bochs/bochs/bochs.h 2016-08-12 19:06:18.803209189 +0200 +++ ./bochs.h 2016-12-28 00:41:20.000627252 +0100 @@ -2,7 +2,7 @@ // $Id: bochs.h 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2015 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -276,8 +276,9 @@ void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status); - void ask (int level, const char *prefix, const char *fmt, va_list ap); + void fatal(const char *prefix, const char *fmt, va_list ap, int exit_status); + void warn(int level, const char *prefix, const char *fmt, va_list ap); + void ask(int level, const char *prefix, const char *fmt, va_list ap); void put(const char *p); void put(const char *n, const char *p); void setio(class iofunctions *); @@ -334,7 +335,8 @@ void set_log_action(int loglevel, int action); const char *getlevel(int i) const; const char *getaction(int i) const; - + int isaction(const char *val) const; + protected: int n_logfn; #define MAX_LOGFNS 512 diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/CHANGES ./CHANGES --- /home/volker/bochs/bochs/CHANGES 2016-12-26 10:45:44.000000000 +0100 +++ ./CHANGES 2016-12-28 15:54:25.127088081 +0100 @@ -1,5 +1,8 @@ Changes after 2.6.8 release: +- General + - Added new log action "warn", designed to show a message box on error events. + - Configure and compile - Added Android host platform support. diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/config.cc ./config.cc --- /home/volker/bochs/bochs/config.cc 2016-05-03 21:15:09.158016000 +0200 +++ ./config.cc 2016-12-27 19:53:10.461420368 +0100 @@ -2062,15 +2062,8 @@ actstr = strtok(NULL, ""); if (actstr != NULL) { def_action = !strcmp(module, "action"); - if (!strcmp(actstr, "fatal")) - action = ACT_FATAL; - else if (!strcmp (actstr, "report")) - action = ACT_REPORT; - else if (!strcmp (actstr, "ignore")) - action = ACT_IGNORE; - else if (!strcmp (actstr, "ask")) - action = ACT_ASK; - else { + action = SIM->is_action_name(actstr); + if (action < ACT_IGNORE) { PARSE_ERR(("%s: %s directive malformed.", context, params[0])); free(param); return -1; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/sdl2.cc ./gui/sdl2.cc --- /home/volker/bochs/bochs/gui/sdl2.cc 2016-08-12 19:06:18.811209142 +0200 +++ ./gui/sdl2.cc 2016-12-28 12:33:39.534288819 +0100 @@ -2,7 +2,7 @@ // $Id: sdl2.cc 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2014-2015 The Bochs Project +// Copyright (C) 2014-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1478,20 +1478,16 @@ SDL_MessageBoxData msgboxdata; SDL_MessageBoxButtonData buttondata[4]; int level, retcode; -#if BX_DEBUGGER || BX_GDBSTUB - int defbtn = 3; -#else - int defbtn = 2; -#endif char message[512]; level = event->u.logmsg.level; - sprintf(message, "%s %s", event->u.logmsg.prefix, event->u.logmsg.msg); + sprintf(message, "Device: %s\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); msgboxdata.flags = SDL_MESSAGEBOX_ERROR; msgboxdata.window = window; msgboxdata.title = SIM->get_log_level_name(level); msgboxdata.message = message; - msgboxdata.numbuttons = defbtn + 1; + msgboxdata.numbuttons = 2; msgboxdata.buttons = buttondata; msgboxdata.colorScheme = NULL; buttondata[0].flags = 0; @@ -1500,14 +1496,18 @@ buttondata[1].flags = 0; buttondata[1].buttonid = BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS; buttondata[1].text = "Alwayscont"; + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + msgboxdata.numbuttons = 3; + buttondata[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttondata[2].buttonid = BX_LOG_ASK_CHOICE_DIE; + buttondata[2].text = "Quit"; #if BX_DEBUGGER || BX_GDBSTUB - buttondata[2].flags = 0; - buttondata[2].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; - buttondata[2].text = "Debugger"; -#endif - buttondata[defbtn].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; - buttondata[defbtn].buttonid = BX_LOG_ASK_CHOICE_DIE; - buttondata[defbtn].text = "Quit"; + msgboxdata.numbuttons = 4; + buttondata[3].flags = 0; + buttondata[3].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; + buttondata[3].text = "Debugger"; +#endif + } if (SDL_ShowMessageBox(&msgboxdata, &retcode) < 0) { return -1; } else { diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.cc ./gui/siminterface.cc --- /home/volker/bochs/bochs/gui/siminterface.cc 2016-12-05 19:56:56.729685000 +0100 +++ ./gui/siminterface.cc 2016-12-28 11:14:02.004075717 +0100 @@ -2,7 +2,7 @@ // $Id: siminterface.cc 12981 2016-12-05 18:56:56Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2015 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -100,6 +100,7 @@ virtual int get_log_action(int mod, int level); virtual void set_log_action(int mod, int level, int action); virtual const char *get_action_name(int action); + virtual int is_action_name(const char *val); virtual int get_default_log_action(int level) { return logfunctions::get_default_action(level); } @@ -123,6 +124,7 @@ virtual void set_notify_callback(bxevent_handler func, void *arg); virtual void get_notify_callback(bxevent_handler *func, void **arg); virtual BxEvent* sim_to_ci_event(BxEvent *event); + virtual int log_warn(const char *prefix, int level, const char *msg); virtual int log_ask(const char *prefix, int level, const char *msg); virtual void log_msg(const char *prefix, int level, const char *msg); virtual void set_log_viewer(bx_bool val) { bx_log_viewer = val; } @@ -420,6 +422,11 @@ return io->getaction(action); } +int bx_real_sim_c::is_action_name(const char *val) +{ + return io->isaction(val); +} + const char *bx_real_sim_c::get_log_level_name(int level) { return io->getlevel(level); @@ -575,6 +582,21 @@ } } +int bx_real_sim_c::log_warn(const char *prefix, int level, const char *msg) +{ + BxEvent be; + be.type = BX_SYNC_EVT_LOG_ASK; + be.u.logmsg.prefix = prefix; + be.u.logmsg.level = level; + be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_MSGBOX_WARN; + // default return value in case something goes wrong. + be.retcode = BX_LOG_NOTIFY_FAILED; + // calling notify + sim_to_ci_event(&be); + return be.retcode; +} + // returns 0 for continue, 1 for alwayscontinue, 2 for die. int bx_real_sim_c::log_ask(const char *prefix, int level, const char *msg) { @@ -583,6 +605,7 @@ be.u.logmsg.prefix = prefix; be.u.logmsg.level = level; be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_ASKDLG; // default return value in case something goes wrong. be.retcode = BX_LOG_NOTIFY_FAILED; // calling notify @@ -1157,16 +1180,10 @@ } else if (!strncmp(string, "PANIC=", 6)) { type = LOGLEV_PANIC; } - if (!strcmp(string+j, "ignore")) { - action = ACT_IGNORE; - } else if (!strcmp(string+j, "report")) { - action = ACT_REPORT; - } else if (!strcmp(string+j, "ask")) { - action = ACT_ASK; - } else if (!strcmp(string+j, "fatal")) { - action = ACT_FATAL; + action = is_action_name(string+j); + if (action >= ACT_IGNORE) { + set_log_action(dev, type, action); } - set_log_action(dev, type, action); } else { if (i == 1) { BX_ERROR(("restore_logopts(): log module '%s' not found", devname)); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.h ./gui/siminterface.h --- /home/volker/bochs/bochs/gui/siminterface.h 2016-03-31 19:24:37.451025427 +0200 +++ ./gui/siminterface.h 2016-12-28 11:11:21.036683362 +0100 @@ -168,6 +168,7 @@ typedef enum { ACT_IGNORE = 0, ACT_REPORT, + ACT_WARN, ACT_ASK, ACT_FATAL, N_ACT @@ -178,11 +179,11 @@ // normally all action choices are available for all event types. The exclude // expression allows some choices to be eliminated if they don't make any // sense. For example, it would be stupid to ignore a panic. -#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ - /* can't die or ask, on debug or info events */ \ - (type <= LOGLEV_INFO && (choice == ACT_ASK || choice == ACT_FATAL)) \ - /* can't ignore panics */ \ - || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ +#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ + /* can't die, ask or warn, on debug or info events */ \ + (type <= LOGLEV_INFO && (choice >= ACT_WARN)) \ + /* can't ignore panics */ \ + || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ ) // floppy / cdrom media status @@ -392,6 +393,7 @@ // synchronizing threads, etc. for each. typedef struct { Bit8u level; + Bit8u flag; const char *prefix; const char *msg; } BxLogMsgEvent; @@ -419,6 +421,12 @@ BX_LOG_NOTIFY_FAILED }; +enum { + BX_LOG_ASK_ASKDLG, + BX_LOG_ASK_MSGBOX_WARN, + BX_LOG_ASK_MSGBOX_QUIT +}; + // Event type: BX_SYNC_EVT_GET_DBG_COMMAND // // This is a synchronous event sent from the simulator to the debugger @@ -675,6 +683,7 @@ virtual int get_default_log_action(int level) {return -1;} virtual void set_default_log_action(int level, int action) {} virtual const char *get_action_name(int action) {return NULL;} + virtual int is_action_name(const char *val) {return -1;} virtual const char *get_log_level_name(int level) {return NULL;} virtual int get_max_log_level() {return -1;} @@ -715,6 +724,9 @@ // send an event from the simulator to the CI. virtual BxEvent* sim_to_ci_event(BxEvent *event) {return NULL;} + // called from simulator when it hits errors, to warn the user + // before continuing simulation + virtual int log_warn(const char *prefix, int level, const char *msg) {return -1;} // called from simulator when it hits serious errors, to ask if the user // wants to continue or not virtual int log_ask(const char *prefix, int level, const char *msg) {return -1;} diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/textconfig.cc ./gui/textconfig.cc --- /home/volker/bochs/bochs/gui/textconfig.cc 2016-12-05 20:15:59.112637000 +0100 +++ ./gui/textconfig.cc 2016-12-28 12:44:43.079411258 +0100 @@ -2,7 +2,7 @@ // $Id: textconfig.cc 12983 2016-12-05 19:15:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2013 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -552,8 +552,8 @@ } static const char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] "; -static const char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" }; -static int log_level_n_choices_normal = 4; +static const char *log_level_choices[N_ACT+1] = { "ignore", "report", "warn", "ask", "fatal", "no change" }; +static int log_level_n_choices_normal = N_ACT; void bx_log_options(int individual) { @@ -589,7 +589,7 @@ bx_print_log_action_table(); for (int level=0; level<SIM->get_max_log_level(); level++) { char prompt[1024]; - int action, default_action = 4; // default to no change + int action, default_action = N_ACT; // default to no change sprintf(prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name(level)); // do show the no change choice (choices=4) if (ask_menu(prompt, "", log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0) @@ -718,47 +718,50 @@ event->retcode = event->u.param.param->text_ask(stdin, stderr); return event; case BX_SYNC_EVT_LOG_ASK: - { - int level = event->u.logmsg.level; - fprintf(stderr, "========================================================================\n"); - fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); - fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); - fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); - fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); - fprintf(stderr, " cont - continue execution\n"); - fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); - fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); - fprintf(stderr, " die - stop execution now\n"); - fprintf(stderr, " abort - dump core %s\n", - BX_HAVE_ABORT ? "" : "(Disabled)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + int level = event->u.logmsg.level; + fprintf(stderr, "========================================================================\n"); + fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); + fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); + fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); + fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); + fprintf(stderr, " cont - continue execution\n"); + fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); + fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); + fprintf(stderr, " die - stop execution now\n"); + fprintf(stderr, " abort - dump core %s\n", + BX_HAVE_ABORT ? "" : "(Disabled)"); #if BX_DEBUGGER - fprintf(stderr, " debug - continue and return to bochs debugger\n"); + fprintf(stderr, " debug - continue and return to bochs debugger\n"); #endif #if BX_GDBSTUB - fprintf(stderr, " debug - hand control to gdb\n"); + fprintf(stderr, " debug - hand control to gdb\n"); #endif - int choice; + int choice; ask: - if (ask_menu("Choose one of the actions above: [%s] ", "", - log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) - event->retcode = -1; - // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. - if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; - fflush(stdout); - fflush(stderr); - event->retcode = choice; - } - return event; - case BX_ASYNC_EVT_REFRESH: - case BX_ASYNC_EVT_DBG_MSG: - case BX_ASYNC_EVT_LOG_MSG: - // The text mode interface does not use these events, so just ignore - // them. - return event; - default: - fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); - return event; + if (ask_menu("Choose one of the actions above: [%s] ", "", + log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) + event->retcode = -1; + // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. + if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; + fflush(stdout); + fflush(stderr); + event->retcode = choice; + } else { + // warning prompt not implemented + event->retcode = 0; + } + return event; + case BX_ASYNC_EVT_REFRESH: + case BX_ASYNC_EVT_DBG_MSG: + case BX_ASYNC_EVT_LOG_MSG: + // The text mode interface does not use these events, so just ignore + // them. + return event; + default: + fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); + return event; } assert(0); // switch statement should return } diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/win32dialog.cc ./gui/win32dialog.cc --- /home/volker/bochs/bochs/gui/win32dialog.cc 2014-06-20 11:32:02.034026376 +0200 +++ ./gui/win32dialog.cc 2016-12-28 12:50:14.148888740 +0100 @@ -2,7 +2,7 @@ // $Id: win32dialog.cc 12381 2014-06-20 09:31:56Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2003-2014 The Bochs Project +// Copyright (C) 2003-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include "win32res.h" #include "win32paramdlg.h" -const char log_choices[5][16] = {"ignore", "log", "ask user", "end simulation", "no change"}; +const char log_choices[N_ACT+1][16] = {"ignore", "log", "warn user", "ask user", "end simulation", "no change"}; HWND GetBochsWindow() { @@ -97,12 +97,16 @@ SetWindowText(GetDlgItem(hDlg, IDASKMSG), event->u.logmsg.msg); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue"); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and don't ask again"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); #if BX_DEBUGGER - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); #endif - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + } else { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 0, 0); + } SetFocus(GetDlgItem(hDlg, IDASKLIST)); return FALSE; case WM_CLOSE: diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.cc ./gui/wxdialog.cc --- /home/volker/bochs/bochs/gui/wxdialog.cc 2015-01-07 17:17:40.447882000 +0100 +++ ./gui/wxdialog.cc 2016-12-27 20:30:44.997609007 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.cc 12594 2015-01-07 16:17:40Z sshwarts $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -208,7 +208,6 @@ : wxDialog(parent, id, wxT(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - //static int integers[LOG_OPTS_N_CHOICES_NORMAL] = {0, 1, 2, 3}; static wxString names[] = ADVLOG_OPTS_TYPE_NAMES; SetTitle(ADVLOG_OPTS_TITLE); vertSizer = new wxBoxSizer(wxVERTICAL); @@ -1563,7 +1562,7 @@ bool includeNoChange) { static wxString choices[] = LOG_OPTS_CHOICES; - static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4}; + static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4, 5}; wxChoice *control = new wxChoice(parent, id, wxDefaultPosition, wxDefaultSize); int lastChoice = 0; // remember index of last choice int nchoice = includeNoChange? LOG_OPTS_N_CHOICES : LOG_OPTS_N_CHOICES_NORMAL; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.h ./gui/wxdialog.h --- /home/volker/bochs/bochs/gui/wxdialog.h 2014-12-23 20:30:12.896090221 +0100 +++ ./gui/wxdialog.h 2016-12-27 20:34:28.518389938 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.h 12576 2014-12-23 19:30:03Z vruppert $ //////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -354,10 +354,10 @@ #define LOG_OPTS_PROMPT wxT("How should Bochs respond to each type of event?") #define LOG_OPTS_TYPE_NAMES { wxT("Debug events"), wxT("Info events"), wxT("Error events"), wxT("Panic events") } #define LOG_OPTS_N_TYPES 4 -#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("ask user"), wxT("end simulation"), wxT("no change") } -#define LOG_OPTS_N_CHOICES_NORMAL 4 -#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change" -#define LOG_OPTS_NO_CHANGE 4 // index of "no change" +#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("warn user"), wxT("ask user"), wxT("end simulation"), wxT("no change") } +#define LOG_OPTS_N_CHOICES_NORMAL 5 +#define LOG_OPTS_N_CHOICES 6 // number of choices, including "no change" +#define LOG_OPTS_NO_CHANGE 5 // index of "no change" #define LOG_OPTS_ADV wxT("For additional control over how each device responds to events, use the menu option \"Log ... By Device\".") wxFlexGridSizer *gridSizer; wxChoice *action[LOG_OPTS_N_TYPES]; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxmain.cc ./gui/wxmain.cc --- /home/volker/bochs/bochs/gui/wxmain.cc 2016-12-26 17:12:57.470174541 +0100 +++ ./gui/wxmain.cc 2016-12-28 12:15:26.035961463 +0100 @@ -2,7 +2,7 @@ // $Id: wxmain.cc 13006 2016-12-26 16:12:54Z vruppert $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1158,6 +1158,10 @@ #if !BX_DEBUGGER && !BX_GDBSTUB dlg.EnableButton(dlg.DEBUG, FALSE); #endif + if (be->u.logmsg.flag != BX_LOG_ASK_ASKDLG) { + dlg.EnableButton(dlg.DIE, FALSE); + dlg.EnableButton(dlg.DUMP, FALSE); + } dlg.SetContext(wxString(be->u.logmsg.prefix, wxConvUTF8)); dlg.SetMessage(wxString(be->u.logmsg.msg, wxConvUTF8)); int n = dlg.ShowModal(); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/x.cc ./gui/x.cc --- /home/volker/bochs/bochs/gui/x.cc 2016-12-27 17:26:59.622665119 +0100 +++ ./gui/x.cc 2016-12-28 12:03:10.963351647 +0100 @@ -2687,11 +2687,7 @@ } else { size_x = 30 + maxlen * 6; } - if (lines < 3) { - size_y = 90; - } else { - size_y = 60 + lines * 15; - } + size_y = 70 + lines * 15; x11_dialog_c *xdlg = new x11_dialog_c(name, size_x, size_y, (mode == XDLG_SIMPLE) ? 1 : 2); ypos = 34; @@ -2729,11 +2725,21 @@ bx_param_string_c *sparam; bx_param_enum_c *eparam; bx_list_c *list; + char message[256]; switch (event->type) { case BX_SYNC_EVT_LOG_ASK: - event->retcode = x11_ask_dialog(event); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + event->retcode = x11_ask_dialog(event); + } else if (event->u.logmsg.flag == BX_LOG_ASK_MSGBOX_WARN) { + const char *title = SIM->get_log_level_name(event->u.logmsg.level); + sprintf(message, "Device: %s\n\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); + bx_param_bool_c bparam(NULL, "warn", title, message, 1); + x11_message_box(&bparam, XDLG_SIMPLE); + event->retcode = 0; + } return event; case BX_SYNC_EVT_ASK_PARAM: param = event->u.param.param; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/logio.cc ./logio.cc --- /home/volker/bochs/bochs/logio.cc 2015-05-10 08:55:18.678940963 +0200 +++ ./logio.cc 2016-12-28 00:40:40.395736643 +0100 @@ -2,7 +2,7 @@ // $Id: logio.cc 12759 2015-05-10 06:55:16Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2014 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -50,11 +50,25 @@ else return "?"; } +static const char *act_name[N_ACT] = { "ignore", "report", "warn", "ask", "fatal" }; + const char* iofunctions::getaction(int i) const { - static const char *name[] = { "ignore", "report", "ask", "fatal" }; assert (i>=ACT_IGNORE && i<N_ACT); - return name[i]; + return act_name[i]; +} + +int iofunctions::isaction(const char *val) const +{ + int action = -1; + + for (int i = 0; i < N_ACT; i++) { + if (!strcmp(val, act_name[i])) { + action = ACT_IGNORE + i; + break; + } + } + return action; } void iofunctions::flush(void) @@ -414,6 +428,11 @@ logio->out(LOGLEV_ERROR, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_ERROR] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_ERROR, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_ERROR] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_ERROR, prefix, fmt, ap); @@ -438,6 +457,11 @@ logio->out(LOGLEV_PANIC, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_PANIC] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_PANIC, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_PANIC] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_PANIC, prefix, fmt, ap); @@ -465,6 +489,36 @@ // the actions ask() and fatal() are not supported here } +void logfunctions::warn(int level, const char *prefix, const char *fmt, va_list ap) +{ + // Guard against reentry on warn() function. The danger is that some + // function that's called within warn() could trigger another + // BX_ERROR that could call warn() again, leading to infinite + // recursion and infinite asks. + static char in_warn_already = 0; + char buf1[1024]; + if (in_warn_already) { + fprintf(stderr, "logfunctions::warn() should not reenter!!\n"); + return; + } + in_warn_already = 1; + vsnprintf(buf1, sizeof(buf1), fmt, ap); + // FIXME: facility set to 0 because it's unknown. + + // update vga screen. This is useful because sometimes useful messages + // are printed on the screen just before a panic. It's also potentially + // dangerous if this function calls ask again... That's why I added + // the reentry check above. + SIM->refresh_vga(); + + // ensure the text screen is showing + SIM->set_display_mode(DISP_MODE_CONFIG); + SIM->log_warn(prefix, level, buf1); + // return to simulation mode + SIM->set_display_mode(DISP_MODE_SIM); + in_warn_already = 0; +} + void logfunctions::ask(int level, const char *prefix, const char *fmt, va_list ap) { // Guard against reentry on ask() function. The danger is that some
2016-12-28 18:06:34 +03:00
const char log_choices[N_ACT+1][16] = {"ignore", "log", "warn user", "ask user", "end simulation", "no change"};
HWND GetBochsWindow()
{
HWND hwnd;
hwnd = FindWindow("Bochs for Windows", NULL);
if (hwnd == NULL) {
hwnd = GetForegroundWindow();
}
return hwnd;
}
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
char path[MAX_PATH];
if (uMsg == BFFM_INITIALIZED) {
GetCurrentDirectory(MAX_PATH, path);
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)path);
}
return 0;
}
2006-12-06 18:05:08 +03:00
#ifndef BIF_NEWDIALOGSTYLE
#define BIF_NEWDIALOGSTYLE 0
#endif
int BrowseDir(const char *Title, char *result)
{
BROWSEINFO browseInfo;
LPITEMIDLIST ItemIDList;
int r = -1;
memset(&browseInfo,0,sizeof(BROWSEINFO));
browseInfo.hwndOwner = GetBochsWindow();
browseInfo.pszDisplayName = result;
browseInfo.lpszTitle = (LPCSTR)Title;
browseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
browseInfo.lpfn = BrowseCallbackProc;
ItemIDList = SHBrowseForFolder(&browseInfo);
if (ItemIDList != NULL) {
*result = 0;
if (SHGetPathFromIDList(ItemIDList, result)) {
if (result[0]) r = 0;
}
// free memory used
IMalloc * imalloc = 0;
if (SUCCEEDED(SHGetMalloc(&imalloc))) {
imalloc->Free(ItemIDList);
imalloc->Release();
}
}
return r;
}
static BOOL CALLBACK LogAskProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
BxEvent *event;
int level;
switch (msg) {
case WM_INITDIALOG:
event = (BxEvent*)lParam;
level = event->u.logmsg.level;
SetWindowText(hDlg, SIM->get_log_level_name(level));
SetWindowText(GetDlgItem(hDlg, IDASKDEV), event->u.logmsg.prefix);
SetWindowText(GetDlgItem(hDlg, IDASKMSG), event->u.logmsg.msg);
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue");
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and don't ask again");
if (event->u.logmsg.mode == BX_LOG_DLG_ASK) {
diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/bochs.h ./bochs.h --- /home/volker/bochs/bochs/bochs.h 2016-08-12 19:06:18.803209189 +0200 +++ ./bochs.h 2016-12-28 00:41:20.000627252 +0100 @@ -2,7 +2,7 @@ // $Id: bochs.h 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2015 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -276,8 +276,9 @@ void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status); - void ask (int level, const char *prefix, const char *fmt, va_list ap); + void fatal(const char *prefix, const char *fmt, va_list ap, int exit_status); + void warn(int level, const char *prefix, const char *fmt, va_list ap); + void ask(int level, const char *prefix, const char *fmt, va_list ap); void put(const char *p); void put(const char *n, const char *p); void setio(class iofunctions *); @@ -334,7 +335,8 @@ void set_log_action(int loglevel, int action); const char *getlevel(int i) const; const char *getaction(int i) const; - + int isaction(const char *val) const; + protected: int n_logfn; #define MAX_LOGFNS 512 diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/CHANGES ./CHANGES --- /home/volker/bochs/bochs/CHANGES 2016-12-26 10:45:44.000000000 +0100 +++ ./CHANGES 2016-12-28 15:54:25.127088081 +0100 @@ -1,5 +1,8 @@ Changes after 2.6.8 release: +- General + - Added new log action "warn", designed to show a message box on error events. + - Configure and compile - Added Android host platform support. diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/config.cc ./config.cc --- /home/volker/bochs/bochs/config.cc 2016-05-03 21:15:09.158016000 +0200 +++ ./config.cc 2016-12-27 19:53:10.461420368 +0100 @@ -2062,15 +2062,8 @@ actstr = strtok(NULL, ""); if (actstr != NULL) { def_action = !strcmp(module, "action"); - if (!strcmp(actstr, "fatal")) - action = ACT_FATAL; - else if (!strcmp (actstr, "report")) - action = ACT_REPORT; - else if (!strcmp (actstr, "ignore")) - action = ACT_IGNORE; - else if (!strcmp (actstr, "ask")) - action = ACT_ASK; - else { + action = SIM->is_action_name(actstr); + if (action < ACT_IGNORE) { PARSE_ERR(("%s: %s directive malformed.", context, params[0])); free(param); return -1; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/sdl2.cc ./gui/sdl2.cc --- /home/volker/bochs/bochs/gui/sdl2.cc 2016-08-12 19:06:18.811209142 +0200 +++ ./gui/sdl2.cc 2016-12-28 12:33:39.534288819 +0100 @@ -2,7 +2,7 @@ // $Id: sdl2.cc 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2014-2015 The Bochs Project +// Copyright (C) 2014-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1478,20 +1478,16 @@ SDL_MessageBoxData msgboxdata; SDL_MessageBoxButtonData buttondata[4]; int level, retcode; -#if BX_DEBUGGER || BX_GDBSTUB - int defbtn = 3; -#else - int defbtn = 2; -#endif char message[512]; level = event->u.logmsg.level; - sprintf(message, "%s %s", event->u.logmsg.prefix, event->u.logmsg.msg); + sprintf(message, "Device: %s\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); msgboxdata.flags = SDL_MESSAGEBOX_ERROR; msgboxdata.window = window; msgboxdata.title = SIM->get_log_level_name(level); msgboxdata.message = message; - msgboxdata.numbuttons = defbtn + 1; + msgboxdata.numbuttons = 2; msgboxdata.buttons = buttondata; msgboxdata.colorScheme = NULL; buttondata[0].flags = 0; @@ -1500,14 +1496,18 @@ buttondata[1].flags = 0; buttondata[1].buttonid = BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS; buttondata[1].text = "Alwayscont"; + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + msgboxdata.numbuttons = 3; + buttondata[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttondata[2].buttonid = BX_LOG_ASK_CHOICE_DIE; + buttondata[2].text = "Quit"; #if BX_DEBUGGER || BX_GDBSTUB - buttondata[2].flags = 0; - buttondata[2].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; - buttondata[2].text = "Debugger"; -#endif - buttondata[defbtn].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; - buttondata[defbtn].buttonid = BX_LOG_ASK_CHOICE_DIE; - buttondata[defbtn].text = "Quit"; + msgboxdata.numbuttons = 4; + buttondata[3].flags = 0; + buttondata[3].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; + buttondata[3].text = "Debugger"; +#endif + } if (SDL_ShowMessageBox(&msgboxdata, &retcode) < 0) { return -1; } else { diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.cc ./gui/siminterface.cc --- /home/volker/bochs/bochs/gui/siminterface.cc 2016-12-05 19:56:56.729685000 +0100 +++ ./gui/siminterface.cc 2016-12-28 11:14:02.004075717 +0100 @@ -2,7 +2,7 @@ // $Id: siminterface.cc 12981 2016-12-05 18:56:56Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2015 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -100,6 +100,7 @@ virtual int get_log_action(int mod, int level); virtual void set_log_action(int mod, int level, int action); virtual const char *get_action_name(int action); + virtual int is_action_name(const char *val); virtual int get_default_log_action(int level) { return logfunctions::get_default_action(level); } @@ -123,6 +124,7 @@ virtual void set_notify_callback(bxevent_handler func, void *arg); virtual void get_notify_callback(bxevent_handler *func, void **arg); virtual BxEvent* sim_to_ci_event(BxEvent *event); + virtual int log_warn(const char *prefix, int level, const char *msg); virtual int log_ask(const char *prefix, int level, const char *msg); virtual void log_msg(const char *prefix, int level, const char *msg); virtual void set_log_viewer(bx_bool val) { bx_log_viewer = val; } @@ -420,6 +422,11 @@ return io->getaction(action); } +int bx_real_sim_c::is_action_name(const char *val) +{ + return io->isaction(val); +} + const char *bx_real_sim_c::get_log_level_name(int level) { return io->getlevel(level); @@ -575,6 +582,21 @@ } } +int bx_real_sim_c::log_warn(const char *prefix, int level, const char *msg) +{ + BxEvent be; + be.type = BX_SYNC_EVT_LOG_ASK; + be.u.logmsg.prefix = prefix; + be.u.logmsg.level = level; + be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_MSGBOX_WARN; + // default return value in case something goes wrong. + be.retcode = BX_LOG_NOTIFY_FAILED; + // calling notify + sim_to_ci_event(&be); + return be.retcode; +} + // returns 0 for continue, 1 for alwayscontinue, 2 for die. int bx_real_sim_c::log_ask(const char *prefix, int level, const char *msg) { @@ -583,6 +605,7 @@ be.u.logmsg.prefix = prefix; be.u.logmsg.level = level; be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_ASKDLG; // default return value in case something goes wrong. be.retcode = BX_LOG_NOTIFY_FAILED; // calling notify @@ -1157,16 +1180,10 @@ } else if (!strncmp(string, "PANIC=", 6)) { type = LOGLEV_PANIC; } - if (!strcmp(string+j, "ignore")) { - action = ACT_IGNORE; - } else if (!strcmp(string+j, "report")) { - action = ACT_REPORT; - } else if (!strcmp(string+j, "ask")) { - action = ACT_ASK; - } else if (!strcmp(string+j, "fatal")) { - action = ACT_FATAL; + action = is_action_name(string+j); + if (action >= ACT_IGNORE) { + set_log_action(dev, type, action); } - set_log_action(dev, type, action); } else { if (i == 1) { BX_ERROR(("restore_logopts(): log module '%s' not found", devname)); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.h ./gui/siminterface.h --- /home/volker/bochs/bochs/gui/siminterface.h 2016-03-31 19:24:37.451025427 +0200 +++ ./gui/siminterface.h 2016-12-28 11:11:21.036683362 +0100 @@ -168,6 +168,7 @@ typedef enum { ACT_IGNORE = 0, ACT_REPORT, + ACT_WARN, ACT_ASK, ACT_FATAL, N_ACT @@ -178,11 +179,11 @@ // normally all action choices are available for all event types. The exclude // expression allows some choices to be eliminated if they don't make any // sense. For example, it would be stupid to ignore a panic. -#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ - /* can't die or ask, on debug or info events */ \ - (type <= LOGLEV_INFO && (choice == ACT_ASK || choice == ACT_FATAL)) \ - /* can't ignore panics */ \ - || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ +#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ + /* can't die, ask or warn, on debug or info events */ \ + (type <= LOGLEV_INFO && (choice >= ACT_WARN)) \ + /* can't ignore panics */ \ + || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ ) // floppy / cdrom media status @@ -392,6 +393,7 @@ // synchronizing threads, etc. for each. typedef struct { Bit8u level; + Bit8u flag; const char *prefix; const char *msg; } BxLogMsgEvent; @@ -419,6 +421,12 @@ BX_LOG_NOTIFY_FAILED }; +enum { + BX_LOG_ASK_ASKDLG, + BX_LOG_ASK_MSGBOX_WARN, + BX_LOG_ASK_MSGBOX_QUIT +}; + // Event type: BX_SYNC_EVT_GET_DBG_COMMAND // // This is a synchronous event sent from the simulator to the debugger @@ -675,6 +683,7 @@ virtual int get_default_log_action(int level) {return -1;} virtual void set_default_log_action(int level, int action) {} virtual const char *get_action_name(int action) {return NULL;} + virtual int is_action_name(const char *val) {return -1;} virtual const char *get_log_level_name(int level) {return NULL;} virtual int get_max_log_level() {return -1;} @@ -715,6 +724,9 @@ // send an event from the simulator to the CI. virtual BxEvent* sim_to_ci_event(BxEvent *event) {return NULL;} + // called from simulator when it hits errors, to warn the user + // before continuing simulation + virtual int log_warn(const char *prefix, int level, const char *msg) {return -1;} // called from simulator when it hits serious errors, to ask if the user // wants to continue or not virtual int log_ask(const char *prefix, int level, const char *msg) {return -1;} diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/textconfig.cc ./gui/textconfig.cc --- /home/volker/bochs/bochs/gui/textconfig.cc 2016-12-05 20:15:59.112637000 +0100 +++ ./gui/textconfig.cc 2016-12-28 12:44:43.079411258 +0100 @@ -2,7 +2,7 @@ // $Id: textconfig.cc 12983 2016-12-05 19:15:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2013 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -552,8 +552,8 @@ } static const char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] "; -static const char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" }; -static int log_level_n_choices_normal = 4; +static const char *log_level_choices[N_ACT+1] = { "ignore", "report", "warn", "ask", "fatal", "no change" }; +static int log_level_n_choices_normal = N_ACT; void bx_log_options(int individual) { @@ -589,7 +589,7 @@ bx_print_log_action_table(); for (int level=0; level<SIM->get_max_log_level(); level++) { char prompt[1024]; - int action, default_action = 4; // default to no change + int action, default_action = N_ACT; // default to no change sprintf(prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name(level)); // do show the no change choice (choices=4) if (ask_menu(prompt, "", log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0) @@ -718,47 +718,50 @@ event->retcode = event->u.param.param->text_ask(stdin, stderr); return event; case BX_SYNC_EVT_LOG_ASK: - { - int level = event->u.logmsg.level; - fprintf(stderr, "========================================================================\n"); - fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); - fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); - fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); - fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); - fprintf(stderr, " cont - continue execution\n"); - fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); - fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); - fprintf(stderr, " die - stop execution now\n"); - fprintf(stderr, " abort - dump core %s\n", - BX_HAVE_ABORT ? "" : "(Disabled)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + int level = event->u.logmsg.level; + fprintf(stderr, "========================================================================\n"); + fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); + fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); + fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); + fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); + fprintf(stderr, " cont - continue execution\n"); + fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); + fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); + fprintf(stderr, " die - stop execution now\n"); + fprintf(stderr, " abort - dump core %s\n", + BX_HAVE_ABORT ? "" : "(Disabled)"); #if BX_DEBUGGER - fprintf(stderr, " debug - continue and return to bochs debugger\n"); + fprintf(stderr, " debug - continue and return to bochs debugger\n"); #endif #if BX_GDBSTUB - fprintf(stderr, " debug - hand control to gdb\n"); + fprintf(stderr, " debug - hand control to gdb\n"); #endif - int choice; + int choice; ask: - if (ask_menu("Choose one of the actions above: [%s] ", "", - log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) - event->retcode = -1; - // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. - if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; - fflush(stdout); - fflush(stderr); - event->retcode = choice; - } - return event; - case BX_ASYNC_EVT_REFRESH: - case BX_ASYNC_EVT_DBG_MSG: - case BX_ASYNC_EVT_LOG_MSG: - // The text mode interface does not use these events, so just ignore - // them. - return event; - default: - fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); - return event; + if (ask_menu("Choose one of the actions above: [%s] ", "", + log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) + event->retcode = -1; + // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. + if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; + fflush(stdout); + fflush(stderr); + event->retcode = choice; + } else { + // warning prompt not implemented + event->retcode = 0; + } + return event; + case BX_ASYNC_EVT_REFRESH: + case BX_ASYNC_EVT_DBG_MSG: + case BX_ASYNC_EVT_LOG_MSG: + // The text mode interface does not use these events, so just ignore + // them. + return event; + default: + fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); + return event; } assert(0); // switch statement should return } diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/win32dialog.cc ./gui/win32dialog.cc --- /home/volker/bochs/bochs/gui/win32dialog.cc 2014-06-20 11:32:02.034026376 +0200 +++ ./gui/win32dialog.cc 2016-12-28 12:50:14.148888740 +0100 @@ -2,7 +2,7 @@ // $Id: win32dialog.cc 12381 2014-06-20 09:31:56Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2003-2014 The Bochs Project +// Copyright (C) 2003-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include "win32res.h" #include "win32paramdlg.h" -const char log_choices[5][16] = {"ignore", "log", "ask user", "end simulation", "no change"}; +const char log_choices[N_ACT+1][16] = {"ignore", "log", "warn user", "ask user", "end simulation", "no change"}; HWND GetBochsWindow() { @@ -97,12 +97,16 @@ SetWindowText(GetDlgItem(hDlg, IDASKMSG), event->u.logmsg.msg); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue"); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and don't ask again"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); #if BX_DEBUGGER - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); #endif - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + } else { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 0, 0); + } SetFocus(GetDlgItem(hDlg, IDASKLIST)); return FALSE; case WM_CLOSE: diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.cc ./gui/wxdialog.cc --- /home/volker/bochs/bochs/gui/wxdialog.cc 2015-01-07 17:17:40.447882000 +0100 +++ ./gui/wxdialog.cc 2016-12-27 20:30:44.997609007 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.cc 12594 2015-01-07 16:17:40Z sshwarts $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -208,7 +208,6 @@ : wxDialog(parent, id, wxT(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - //static int integers[LOG_OPTS_N_CHOICES_NORMAL] = {0, 1, 2, 3}; static wxString names[] = ADVLOG_OPTS_TYPE_NAMES; SetTitle(ADVLOG_OPTS_TITLE); vertSizer = new wxBoxSizer(wxVERTICAL); @@ -1563,7 +1562,7 @@ bool includeNoChange) { static wxString choices[] = LOG_OPTS_CHOICES; - static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4}; + static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4, 5}; wxChoice *control = new wxChoice(parent, id, wxDefaultPosition, wxDefaultSize); int lastChoice = 0; // remember index of last choice int nchoice = includeNoChange? LOG_OPTS_N_CHOICES : LOG_OPTS_N_CHOICES_NORMAL; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.h ./gui/wxdialog.h --- /home/volker/bochs/bochs/gui/wxdialog.h 2014-12-23 20:30:12.896090221 +0100 +++ ./gui/wxdialog.h 2016-12-27 20:34:28.518389938 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.h 12576 2014-12-23 19:30:03Z vruppert $ //////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -354,10 +354,10 @@ #define LOG_OPTS_PROMPT wxT("How should Bochs respond to each type of event?") #define LOG_OPTS_TYPE_NAMES { wxT("Debug events"), wxT("Info events"), wxT("Error events"), wxT("Panic events") } #define LOG_OPTS_N_TYPES 4 -#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("ask user"), wxT("end simulation"), wxT("no change") } -#define LOG_OPTS_N_CHOICES_NORMAL 4 -#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change" -#define LOG_OPTS_NO_CHANGE 4 // index of "no change" +#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("warn user"), wxT("ask user"), wxT("end simulation"), wxT("no change") } +#define LOG_OPTS_N_CHOICES_NORMAL 5 +#define LOG_OPTS_N_CHOICES 6 // number of choices, including "no change" +#define LOG_OPTS_NO_CHANGE 5 // index of "no change" #define LOG_OPTS_ADV wxT("For additional control over how each device responds to events, use the menu option \"Log ... By Device\".") wxFlexGridSizer *gridSizer; wxChoice *action[LOG_OPTS_N_TYPES]; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxmain.cc ./gui/wxmain.cc --- /home/volker/bochs/bochs/gui/wxmain.cc 2016-12-26 17:12:57.470174541 +0100 +++ ./gui/wxmain.cc 2016-12-28 12:15:26.035961463 +0100 @@ -2,7 +2,7 @@ // $Id: wxmain.cc 13006 2016-12-26 16:12:54Z vruppert $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1158,6 +1158,10 @@ #if !BX_DEBUGGER && !BX_GDBSTUB dlg.EnableButton(dlg.DEBUG, FALSE); #endif + if (be->u.logmsg.flag != BX_LOG_ASK_ASKDLG) { + dlg.EnableButton(dlg.DIE, FALSE); + dlg.EnableButton(dlg.DUMP, FALSE); + } dlg.SetContext(wxString(be->u.logmsg.prefix, wxConvUTF8)); dlg.SetMessage(wxString(be->u.logmsg.msg, wxConvUTF8)); int n = dlg.ShowModal(); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/x.cc ./gui/x.cc --- /home/volker/bochs/bochs/gui/x.cc 2016-12-27 17:26:59.622665119 +0100 +++ ./gui/x.cc 2016-12-28 12:03:10.963351647 +0100 @@ -2687,11 +2687,7 @@ } else { size_x = 30 + maxlen * 6; } - if (lines < 3) { - size_y = 90; - } else { - size_y = 60 + lines * 15; - } + size_y = 70 + lines * 15; x11_dialog_c *xdlg = new x11_dialog_c(name, size_x, size_y, (mode == XDLG_SIMPLE) ? 1 : 2); ypos = 34; @@ -2729,11 +2725,21 @@ bx_param_string_c *sparam; bx_param_enum_c *eparam; bx_list_c *list; + char message[256]; switch (event->type) { case BX_SYNC_EVT_LOG_ASK: - event->retcode = x11_ask_dialog(event); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + event->retcode = x11_ask_dialog(event); + } else if (event->u.logmsg.flag == BX_LOG_ASK_MSGBOX_WARN) { + const char *title = SIM->get_log_level_name(event->u.logmsg.level); + sprintf(message, "Device: %s\n\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); + bx_param_bool_c bparam(NULL, "warn", title, message, 1); + x11_message_box(&bparam, XDLG_SIMPLE); + event->retcode = 0; + } return event; case BX_SYNC_EVT_ASK_PARAM: param = event->u.param.param; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/logio.cc ./logio.cc --- /home/volker/bochs/bochs/logio.cc 2015-05-10 08:55:18.678940963 +0200 +++ ./logio.cc 2016-12-28 00:40:40.395736643 +0100 @@ -2,7 +2,7 @@ // $Id: logio.cc 12759 2015-05-10 06:55:16Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2014 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -50,11 +50,25 @@ else return "?"; } +static const char *act_name[N_ACT] = { "ignore", "report", "warn", "ask", "fatal" }; + const char* iofunctions::getaction(int i) const { - static const char *name[] = { "ignore", "report", "ask", "fatal" }; assert (i>=ACT_IGNORE && i<N_ACT); - return name[i]; + return act_name[i]; +} + +int iofunctions::isaction(const char *val) const +{ + int action = -1; + + for (int i = 0; i < N_ACT; i++) { + if (!strcmp(val, act_name[i])) { + action = ACT_IGNORE + i; + break; + } + } + return action; } void iofunctions::flush(void) @@ -414,6 +428,11 @@ logio->out(LOGLEV_ERROR, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_ERROR] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_ERROR, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_ERROR] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_ERROR, prefix, fmt, ap); @@ -438,6 +457,11 @@ logio->out(LOGLEV_PANIC, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_PANIC] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_PANIC, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_PANIC] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_PANIC, prefix, fmt, ap); @@ -465,6 +489,36 @@ // the actions ask() and fatal() are not supported here } +void logfunctions::warn(int level, const char *prefix, const char *fmt, va_list ap) +{ + // Guard against reentry on warn() function. The danger is that some + // function that's called within warn() could trigger another + // BX_ERROR that could call warn() again, leading to infinite + // recursion and infinite asks. + static char in_warn_already = 0; + char buf1[1024]; + if (in_warn_already) { + fprintf(stderr, "logfunctions::warn() should not reenter!!\n"); + return; + } + in_warn_already = 1; + vsnprintf(buf1, sizeof(buf1), fmt, ap); + // FIXME: facility set to 0 because it's unknown. + + // update vga screen. This is useful because sometimes useful messages + // are printed on the screen just before a panic. It's also potentially + // dangerous if this function calls ask again... That's why I added + // the reentry check above. + SIM->refresh_vga(); + + // ensure the text screen is showing + SIM->set_display_mode(DISP_MODE_CONFIG); + SIM->log_warn(prefix, level, buf1); + // return to simulation mode + SIM->set_display_mode(DISP_MODE_SIM); + in_warn_already = 0; +} + void logfunctions::ask(int level, const char *prefix, const char *fmt, va_list ap) { // Guard against reentry on ask() function. The danger is that some
2016-12-28 18:06:34 +03:00
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation");
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)");
#if BX_DEBUGGER
diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/bochs.h ./bochs.h --- /home/volker/bochs/bochs/bochs.h 2016-08-12 19:06:18.803209189 +0200 +++ ./bochs.h 2016-12-28 00:41:20.000627252 +0100 @@ -2,7 +2,7 @@ // $Id: bochs.h 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2015 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -276,8 +276,9 @@ void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status); - void ask (int level, const char *prefix, const char *fmt, va_list ap); + void fatal(const char *prefix, const char *fmt, va_list ap, int exit_status); + void warn(int level, const char *prefix, const char *fmt, va_list ap); + void ask(int level, const char *prefix, const char *fmt, va_list ap); void put(const char *p); void put(const char *n, const char *p); void setio(class iofunctions *); @@ -334,7 +335,8 @@ void set_log_action(int loglevel, int action); const char *getlevel(int i) const; const char *getaction(int i) const; - + int isaction(const char *val) const; + protected: int n_logfn; #define MAX_LOGFNS 512 diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/CHANGES ./CHANGES --- /home/volker/bochs/bochs/CHANGES 2016-12-26 10:45:44.000000000 +0100 +++ ./CHANGES 2016-12-28 15:54:25.127088081 +0100 @@ -1,5 +1,8 @@ Changes after 2.6.8 release: +- General + - Added new log action "warn", designed to show a message box on error events. + - Configure and compile - Added Android host platform support. diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/config.cc ./config.cc --- /home/volker/bochs/bochs/config.cc 2016-05-03 21:15:09.158016000 +0200 +++ ./config.cc 2016-12-27 19:53:10.461420368 +0100 @@ -2062,15 +2062,8 @@ actstr = strtok(NULL, ""); if (actstr != NULL) { def_action = !strcmp(module, "action"); - if (!strcmp(actstr, "fatal")) - action = ACT_FATAL; - else if (!strcmp (actstr, "report")) - action = ACT_REPORT; - else if (!strcmp (actstr, "ignore")) - action = ACT_IGNORE; - else if (!strcmp (actstr, "ask")) - action = ACT_ASK; - else { + action = SIM->is_action_name(actstr); + if (action < ACT_IGNORE) { PARSE_ERR(("%s: %s directive malformed.", context, params[0])); free(param); return -1; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/sdl2.cc ./gui/sdl2.cc --- /home/volker/bochs/bochs/gui/sdl2.cc 2016-08-12 19:06:18.811209142 +0200 +++ ./gui/sdl2.cc 2016-12-28 12:33:39.534288819 +0100 @@ -2,7 +2,7 @@ // $Id: sdl2.cc 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2014-2015 The Bochs Project +// Copyright (C) 2014-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1478,20 +1478,16 @@ SDL_MessageBoxData msgboxdata; SDL_MessageBoxButtonData buttondata[4]; int level, retcode; -#if BX_DEBUGGER || BX_GDBSTUB - int defbtn = 3; -#else - int defbtn = 2; -#endif char message[512]; level = event->u.logmsg.level; - sprintf(message, "%s %s", event->u.logmsg.prefix, event->u.logmsg.msg); + sprintf(message, "Device: %s\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); msgboxdata.flags = SDL_MESSAGEBOX_ERROR; msgboxdata.window = window; msgboxdata.title = SIM->get_log_level_name(level); msgboxdata.message = message; - msgboxdata.numbuttons = defbtn + 1; + msgboxdata.numbuttons = 2; msgboxdata.buttons = buttondata; msgboxdata.colorScheme = NULL; buttondata[0].flags = 0; @@ -1500,14 +1496,18 @@ buttondata[1].flags = 0; buttondata[1].buttonid = BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS; buttondata[1].text = "Alwayscont"; + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + msgboxdata.numbuttons = 3; + buttondata[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttondata[2].buttonid = BX_LOG_ASK_CHOICE_DIE; + buttondata[2].text = "Quit"; #if BX_DEBUGGER || BX_GDBSTUB - buttondata[2].flags = 0; - buttondata[2].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; - buttondata[2].text = "Debugger"; -#endif - buttondata[defbtn].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; - buttondata[defbtn].buttonid = BX_LOG_ASK_CHOICE_DIE; - buttondata[defbtn].text = "Quit"; + msgboxdata.numbuttons = 4; + buttondata[3].flags = 0; + buttondata[3].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; + buttondata[3].text = "Debugger"; +#endif + } if (SDL_ShowMessageBox(&msgboxdata, &retcode) < 0) { return -1; } else { diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.cc ./gui/siminterface.cc --- /home/volker/bochs/bochs/gui/siminterface.cc 2016-12-05 19:56:56.729685000 +0100 +++ ./gui/siminterface.cc 2016-12-28 11:14:02.004075717 +0100 @@ -2,7 +2,7 @@ // $Id: siminterface.cc 12981 2016-12-05 18:56:56Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2015 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -100,6 +100,7 @@ virtual int get_log_action(int mod, int level); virtual void set_log_action(int mod, int level, int action); virtual const char *get_action_name(int action); + virtual int is_action_name(const char *val); virtual int get_default_log_action(int level) { return logfunctions::get_default_action(level); } @@ -123,6 +124,7 @@ virtual void set_notify_callback(bxevent_handler func, void *arg); virtual void get_notify_callback(bxevent_handler *func, void **arg); virtual BxEvent* sim_to_ci_event(BxEvent *event); + virtual int log_warn(const char *prefix, int level, const char *msg); virtual int log_ask(const char *prefix, int level, const char *msg); virtual void log_msg(const char *prefix, int level, const char *msg); virtual void set_log_viewer(bx_bool val) { bx_log_viewer = val; } @@ -420,6 +422,11 @@ return io->getaction(action); } +int bx_real_sim_c::is_action_name(const char *val) +{ + return io->isaction(val); +} + const char *bx_real_sim_c::get_log_level_name(int level) { return io->getlevel(level); @@ -575,6 +582,21 @@ } } +int bx_real_sim_c::log_warn(const char *prefix, int level, const char *msg) +{ + BxEvent be; + be.type = BX_SYNC_EVT_LOG_ASK; + be.u.logmsg.prefix = prefix; + be.u.logmsg.level = level; + be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_MSGBOX_WARN; + // default return value in case something goes wrong. + be.retcode = BX_LOG_NOTIFY_FAILED; + // calling notify + sim_to_ci_event(&be); + return be.retcode; +} + // returns 0 for continue, 1 for alwayscontinue, 2 for die. int bx_real_sim_c::log_ask(const char *prefix, int level, const char *msg) { @@ -583,6 +605,7 @@ be.u.logmsg.prefix = prefix; be.u.logmsg.level = level; be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_ASKDLG; // default return value in case something goes wrong. be.retcode = BX_LOG_NOTIFY_FAILED; // calling notify @@ -1157,16 +1180,10 @@ } else if (!strncmp(string, "PANIC=", 6)) { type = LOGLEV_PANIC; } - if (!strcmp(string+j, "ignore")) { - action = ACT_IGNORE; - } else if (!strcmp(string+j, "report")) { - action = ACT_REPORT; - } else if (!strcmp(string+j, "ask")) { - action = ACT_ASK; - } else if (!strcmp(string+j, "fatal")) { - action = ACT_FATAL; + action = is_action_name(string+j); + if (action >= ACT_IGNORE) { + set_log_action(dev, type, action); } - set_log_action(dev, type, action); } else { if (i == 1) { BX_ERROR(("restore_logopts(): log module '%s' not found", devname)); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.h ./gui/siminterface.h --- /home/volker/bochs/bochs/gui/siminterface.h 2016-03-31 19:24:37.451025427 +0200 +++ ./gui/siminterface.h 2016-12-28 11:11:21.036683362 +0100 @@ -168,6 +168,7 @@ typedef enum { ACT_IGNORE = 0, ACT_REPORT, + ACT_WARN, ACT_ASK, ACT_FATAL, N_ACT @@ -178,11 +179,11 @@ // normally all action choices are available for all event types. The exclude // expression allows some choices to be eliminated if they don't make any // sense. For example, it would be stupid to ignore a panic. -#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ - /* can't die or ask, on debug or info events */ \ - (type <= LOGLEV_INFO && (choice == ACT_ASK || choice == ACT_FATAL)) \ - /* can't ignore panics */ \ - || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ +#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ + /* can't die, ask or warn, on debug or info events */ \ + (type <= LOGLEV_INFO && (choice >= ACT_WARN)) \ + /* can't ignore panics */ \ + || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ ) // floppy / cdrom media status @@ -392,6 +393,7 @@ // synchronizing threads, etc. for each. typedef struct { Bit8u level; + Bit8u flag; const char *prefix; const char *msg; } BxLogMsgEvent; @@ -419,6 +421,12 @@ BX_LOG_NOTIFY_FAILED }; +enum { + BX_LOG_ASK_ASKDLG, + BX_LOG_ASK_MSGBOX_WARN, + BX_LOG_ASK_MSGBOX_QUIT +}; + // Event type: BX_SYNC_EVT_GET_DBG_COMMAND // // This is a synchronous event sent from the simulator to the debugger @@ -675,6 +683,7 @@ virtual int get_default_log_action(int level) {return -1;} virtual void set_default_log_action(int level, int action) {} virtual const char *get_action_name(int action) {return NULL;} + virtual int is_action_name(const char *val) {return -1;} virtual const char *get_log_level_name(int level) {return NULL;} virtual int get_max_log_level() {return -1;} @@ -715,6 +724,9 @@ // send an event from the simulator to the CI. virtual BxEvent* sim_to_ci_event(BxEvent *event) {return NULL;} + // called from simulator when it hits errors, to warn the user + // before continuing simulation + virtual int log_warn(const char *prefix, int level, const char *msg) {return -1;} // called from simulator when it hits serious errors, to ask if the user // wants to continue or not virtual int log_ask(const char *prefix, int level, const char *msg) {return -1;} diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/textconfig.cc ./gui/textconfig.cc --- /home/volker/bochs/bochs/gui/textconfig.cc 2016-12-05 20:15:59.112637000 +0100 +++ ./gui/textconfig.cc 2016-12-28 12:44:43.079411258 +0100 @@ -2,7 +2,7 @@ // $Id: textconfig.cc 12983 2016-12-05 19:15:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2013 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -552,8 +552,8 @@ } static const char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] "; -static const char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" }; -static int log_level_n_choices_normal = 4; +static const char *log_level_choices[N_ACT+1] = { "ignore", "report", "warn", "ask", "fatal", "no change" }; +static int log_level_n_choices_normal = N_ACT; void bx_log_options(int individual) { @@ -589,7 +589,7 @@ bx_print_log_action_table(); for (int level=0; level<SIM->get_max_log_level(); level++) { char prompt[1024]; - int action, default_action = 4; // default to no change + int action, default_action = N_ACT; // default to no change sprintf(prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name(level)); // do show the no change choice (choices=4) if (ask_menu(prompt, "", log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0) @@ -718,47 +718,50 @@ event->retcode = event->u.param.param->text_ask(stdin, stderr); return event; case BX_SYNC_EVT_LOG_ASK: - { - int level = event->u.logmsg.level; - fprintf(stderr, "========================================================================\n"); - fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); - fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); - fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); - fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); - fprintf(stderr, " cont - continue execution\n"); - fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); - fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); - fprintf(stderr, " die - stop execution now\n"); - fprintf(stderr, " abort - dump core %s\n", - BX_HAVE_ABORT ? "" : "(Disabled)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + int level = event->u.logmsg.level; + fprintf(stderr, "========================================================================\n"); + fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); + fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); + fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); + fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); + fprintf(stderr, " cont - continue execution\n"); + fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); + fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); + fprintf(stderr, " die - stop execution now\n"); + fprintf(stderr, " abort - dump core %s\n", + BX_HAVE_ABORT ? "" : "(Disabled)"); #if BX_DEBUGGER - fprintf(stderr, " debug - continue and return to bochs debugger\n"); + fprintf(stderr, " debug - continue and return to bochs debugger\n"); #endif #if BX_GDBSTUB - fprintf(stderr, " debug - hand control to gdb\n"); + fprintf(stderr, " debug - hand control to gdb\n"); #endif - int choice; + int choice; ask: - if (ask_menu("Choose one of the actions above: [%s] ", "", - log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) - event->retcode = -1; - // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. - if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; - fflush(stdout); - fflush(stderr); - event->retcode = choice; - } - return event; - case BX_ASYNC_EVT_REFRESH: - case BX_ASYNC_EVT_DBG_MSG: - case BX_ASYNC_EVT_LOG_MSG: - // The text mode interface does not use these events, so just ignore - // them. - return event; - default: - fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); - return event; + if (ask_menu("Choose one of the actions above: [%s] ", "", + log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) + event->retcode = -1; + // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. + if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; + fflush(stdout); + fflush(stderr); + event->retcode = choice; + } else { + // warning prompt not implemented + event->retcode = 0; + } + return event; + case BX_ASYNC_EVT_REFRESH: + case BX_ASYNC_EVT_DBG_MSG: + case BX_ASYNC_EVT_LOG_MSG: + // The text mode interface does not use these events, so just ignore + // them. + return event; + default: + fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); + return event; } assert(0); // switch statement should return } diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/win32dialog.cc ./gui/win32dialog.cc --- /home/volker/bochs/bochs/gui/win32dialog.cc 2014-06-20 11:32:02.034026376 +0200 +++ ./gui/win32dialog.cc 2016-12-28 12:50:14.148888740 +0100 @@ -2,7 +2,7 @@ // $Id: win32dialog.cc 12381 2014-06-20 09:31:56Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2003-2014 The Bochs Project +// Copyright (C) 2003-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include "win32res.h" #include "win32paramdlg.h" -const char log_choices[5][16] = {"ignore", "log", "ask user", "end simulation", "no change"}; +const char log_choices[N_ACT+1][16] = {"ignore", "log", "warn user", "ask user", "end simulation", "no change"}; HWND GetBochsWindow() { @@ -97,12 +97,16 @@ SetWindowText(GetDlgItem(hDlg, IDASKMSG), event->u.logmsg.msg); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue"); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and don't ask again"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); #if BX_DEBUGGER - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); #endif - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + } else { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 0, 0); + } SetFocus(GetDlgItem(hDlg, IDASKLIST)); return FALSE; case WM_CLOSE: diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.cc ./gui/wxdialog.cc --- /home/volker/bochs/bochs/gui/wxdialog.cc 2015-01-07 17:17:40.447882000 +0100 +++ ./gui/wxdialog.cc 2016-12-27 20:30:44.997609007 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.cc 12594 2015-01-07 16:17:40Z sshwarts $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -208,7 +208,6 @@ : wxDialog(parent, id, wxT(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - //static int integers[LOG_OPTS_N_CHOICES_NORMAL] = {0, 1, 2, 3}; static wxString names[] = ADVLOG_OPTS_TYPE_NAMES; SetTitle(ADVLOG_OPTS_TITLE); vertSizer = new wxBoxSizer(wxVERTICAL); @@ -1563,7 +1562,7 @@ bool includeNoChange) { static wxString choices[] = LOG_OPTS_CHOICES; - static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4}; + static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4, 5}; wxChoice *control = new wxChoice(parent, id, wxDefaultPosition, wxDefaultSize); int lastChoice = 0; // remember index of last choice int nchoice = includeNoChange? LOG_OPTS_N_CHOICES : LOG_OPTS_N_CHOICES_NORMAL; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.h ./gui/wxdialog.h --- /home/volker/bochs/bochs/gui/wxdialog.h 2014-12-23 20:30:12.896090221 +0100 +++ ./gui/wxdialog.h 2016-12-27 20:34:28.518389938 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.h 12576 2014-12-23 19:30:03Z vruppert $ //////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -354,10 +354,10 @@ #define LOG_OPTS_PROMPT wxT("How should Bochs respond to each type of event?") #define LOG_OPTS_TYPE_NAMES { wxT("Debug events"), wxT("Info events"), wxT("Error events"), wxT("Panic events") } #define LOG_OPTS_N_TYPES 4 -#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("ask user"), wxT("end simulation"), wxT("no change") } -#define LOG_OPTS_N_CHOICES_NORMAL 4 -#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change" -#define LOG_OPTS_NO_CHANGE 4 // index of "no change" +#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("warn user"), wxT("ask user"), wxT("end simulation"), wxT("no change") } +#define LOG_OPTS_N_CHOICES_NORMAL 5 +#define LOG_OPTS_N_CHOICES 6 // number of choices, including "no change" +#define LOG_OPTS_NO_CHANGE 5 // index of "no change" #define LOG_OPTS_ADV wxT("For additional control over how each device responds to events, use the menu option \"Log ... By Device\".") wxFlexGridSizer *gridSizer; wxChoice *action[LOG_OPTS_N_TYPES]; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxmain.cc ./gui/wxmain.cc --- /home/volker/bochs/bochs/gui/wxmain.cc 2016-12-26 17:12:57.470174541 +0100 +++ ./gui/wxmain.cc 2016-12-28 12:15:26.035961463 +0100 @@ -2,7 +2,7 @@ // $Id: wxmain.cc 13006 2016-12-26 16:12:54Z vruppert $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1158,6 +1158,10 @@ #if !BX_DEBUGGER && !BX_GDBSTUB dlg.EnableButton(dlg.DEBUG, FALSE); #endif + if (be->u.logmsg.flag != BX_LOG_ASK_ASKDLG) { + dlg.EnableButton(dlg.DIE, FALSE); + dlg.EnableButton(dlg.DUMP, FALSE); + } dlg.SetContext(wxString(be->u.logmsg.prefix, wxConvUTF8)); dlg.SetMessage(wxString(be->u.logmsg.msg, wxConvUTF8)); int n = dlg.ShowModal(); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/x.cc ./gui/x.cc --- /home/volker/bochs/bochs/gui/x.cc 2016-12-27 17:26:59.622665119 +0100 +++ ./gui/x.cc 2016-12-28 12:03:10.963351647 +0100 @@ -2687,11 +2687,7 @@ } else { size_x = 30 + maxlen * 6; } - if (lines < 3) { - size_y = 90; - } else { - size_y = 60 + lines * 15; - } + size_y = 70 + lines * 15; x11_dialog_c *xdlg = new x11_dialog_c(name, size_x, size_y, (mode == XDLG_SIMPLE) ? 1 : 2); ypos = 34; @@ -2729,11 +2725,21 @@ bx_param_string_c *sparam; bx_param_enum_c *eparam; bx_list_c *list; + char message[256]; switch (event->type) { case BX_SYNC_EVT_LOG_ASK: - event->retcode = x11_ask_dialog(event); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + event->retcode = x11_ask_dialog(event); + } else if (event->u.logmsg.flag == BX_LOG_ASK_MSGBOX_WARN) { + const char *title = SIM->get_log_level_name(event->u.logmsg.level); + sprintf(message, "Device: %s\n\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); + bx_param_bool_c bparam(NULL, "warn", title, message, 1); + x11_message_box(&bparam, XDLG_SIMPLE); + event->retcode = 0; + } return event; case BX_SYNC_EVT_ASK_PARAM: param = event->u.param.param; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/logio.cc ./logio.cc --- /home/volker/bochs/bochs/logio.cc 2015-05-10 08:55:18.678940963 +0200 +++ ./logio.cc 2016-12-28 00:40:40.395736643 +0100 @@ -2,7 +2,7 @@ // $Id: logio.cc 12759 2015-05-10 06:55:16Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2014 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -50,11 +50,25 @@ else return "?"; } +static const char *act_name[N_ACT] = { "ignore", "report", "warn", "ask", "fatal" }; + const char* iofunctions::getaction(int i) const { - static const char *name[] = { "ignore", "report", "ask", "fatal" }; assert (i>=ACT_IGNORE && i<N_ACT); - return name[i]; + return act_name[i]; +} + +int iofunctions::isaction(const char *val) const +{ + int action = -1; + + for (int i = 0; i < N_ACT; i++) { + if (!strcmp(val, act_name[i])) { + action = ACT_IGNORE + i; + break; + } + } + return action; } void iofunctions::flush(void) @@ -414,6 +428,11 @@ logio->out(LOGLEV_ERROR, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_ERROR] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_ERROR, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_ERROR] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_ERROR, prefix, fmt, ap); @@ -438,6 +457,11 @@ logio->out(LOGLEV_PANIC, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_PANIC] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_PANIC, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_PANIC] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_PANIC, prefix, fmt, ap); @@ -465,6 +489,36 @@ // the actions ask() and fatal() are not supported here } +void logfunctions::warn(int level, const char *prefix, const char *fmt, va_list ap) +{ + // Guard against reentry on warn() function. The danger is that some + // function that's called within warn() could trigger another + // BX_ERROR that could call warn() again, leading to infinite + // recursion and infinite asks. + static char in_warn_already = 0; + char buf1[1024]; + if (in_warn_already) { + fprintf(stderr, "logfunctions::warn() should not reenter!!\n"); + return; + } + in_warn_already = 1; + vsnprintf(buf1, sizeof(buf1), fmt, ap); + // FIXME: facility set to 0 because it's unknown. + + // update vga screen. This is useful because sometimes useful messages + // are printed on the screen just before a panic. It's also potentially + // dangerous if this function calls ask again... That's why I added + // the reentry check above. + SIM->refresh_vga(); + + // ensure the text screen is showing + SIM->set_display_mode(DISP_MODE_CONFIG); + SIM->log_warn(prefix, level, buf1); + // return to simulation mode + SIM->set_display_mode(DISP_MODE_SIM); + in_warn_already = 0; +} + void logfunctions::ask(int level, const char *prefix, const char *fmt, va_list ap) { // Guard against reentry on ask() function. The danger is that some
2016-12-28 18:06:34 +03:00
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger");
#endif
diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/bochs.h ./bochs.h --- /home/volker/bochs/bochs/bochs.h 2016-08-12 19:06:18.803209189 +0200 +++ ./bochs.h 2016-12-28 00:41:20.000627252 +0100 @@ -2,7 +2,7 @@ // $Id: bochs.h 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2015 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -276,8 +276,9 @@ void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status); - void ask (int level, const char *prefix, const char *fmt, va_list ap); + void fatal(const char *prefix, const char *fmt, va_list ap, int exit_status); + void warn(int level, const char *prefix, const char *fmt, va_list ap); + void ask(int level, const char *prefix, const char *fmt, va_list ap); void put(const char *p); void put(const char *n, const char *p); void setio(class iofunctions *); @@ -334,7 +335,8 @@ void set_log_action(int loglevel, int action); const char *getlevel(int i) const; const char *getaction(int i) const; - + int isaction(const char *val) const; + protected: int n_logfn; #define MAX_LOGFNS 512 diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/CHANGES ./CHANGES --- /home/volker/bochs/bochs/CHANGES 2016-12-26 10:45:44.000000000 +0100 +++ ./CHANGES 2016-12-28 15:54:25.127088081 +0100 @@ -1,5 +1,8 @@ Changes after 2.6.8 release: +- General + - Added new log action "warn", designed to show a message box on error events. + - Configure and compile - Added Android host platform support. diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/config.cc ./config.cc --- /home/volker/bochs/bochs/config.cc 2016-05-03 21:15:09.158016000 +0200 +++ ./config.cc 2016-12-27 19:53:10.461420368 +0100 @@ -2062,15 +2062,8 @@ actstr = strtok(NULL, ""); if (actstr != NULL) { def_action = !strcmp(module, "action"); - if (!strcmp(actstr, "fatal")) - action = ACT_FATAL; - else if (!strcmp (actstr, "report")) - action = ACT_REPORT; - else if (!strcmp (actstr, "ignore")) - action = ACT_IGNORE; - else if (!strcmp (actstr, "ask")) - action = ACT_ASK; - else { + action = SIM->is_action_name(actstr); + if (action < ACT_IGNORE) { PARSE_ERR(("%s: %s directive malformed.", context, params[0])); free(param); return -1; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/sdl2.cc ./gui/sdl2.cc --- /home/volker/bochs/bochs/gui/sdl2.cc 2016-08-12 19:06:18.811209142 +0200 +++ ./gui/sdl2.cc 2016-12-28 12:33:39.534288819 +0100 @@ -2,7 +2,7 @@ // $Id: sdl2.cc 12935 2016-08-12 17:06:14Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2014-2015 The Bochs Project +// Copyright (C) 2014-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1478,20 +1478,16 @@ SDL_MessageBoxData msgboxdata; SDL_MessageBoxButtonData buttondata[4]; int level, retcode; -#if BX_DEBUGGER || BX_GDBSTUB - int defbtn = 3; -#else - int defbtn = 2; -#endif char message[512]; level = event->u.logmsg.level; - sprintf(message, "%s %s", event->u.logmsg.prefix, event->u.logmsg.msg); + sprintf(message, "Device: %s\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); msgboxdata.flags = SDL_MESSAGEBOX_ERROR; msgboxdata.window = window; msgboxdata.title = SIM->get_log_level_name(level); msgboxdata.message = message; - msgboxdata.numbuttons = defbtn + 1; + msgboxdata.numbuttons = 2; msgboxdata.buttons = buttondata; msgboxdata.colorScheme = NULL; buttondata[0].flags = 0; @@ -1500,14 +1496,18 @@ buttondata[1].flags = 0; buttondata[1].buttonid = BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS; buttondata[1].text = "Alwayscont"; + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + msgboxdata.numbuttons = 3; + buttondata[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttondata[2].buttonid = BX_LOG_ASK_CHOICE_DIE; + buttondata[2].text = "Quit"; #if BX_DEBUGGER || BX_GDBSTUB - buttondata[2].flags = 0; - buttondata[2].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; - buttondata[2].text = "Debugger"; -#endif - buttondata[defbtn].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; - buttondata[defbtn].buttonid = BX_LOG_ASK_CHOICE_DIE; - buttondata[defbtn].text = "Quit"; + msgboxdata.numbuttons = 4; + buttondata[3].flags = 0; + buttondata[3].buttonid = BX_LOG_ASK_CHOICE_ENTER_DEBUG; + buttondata[3].text = "Debugger"; +#endif + } if (SDL_ShowMessageBox(&msgboxdata, &retcode) < 0) { return -1; } else { diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.cc ./gui/siminterface.cc --- /home/volker/bochs/bochs/gui/siminterface.cc 2016-12-05 19:56:56.729685000 +0100 +++ ./gui/siminterface.cc 2016-12-28 11:14:02.004075717 +0100 @@ -2,7 +2,7 @@ // $Id: siminterface.cc 12981 2016-12-05 18:56:56Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2015 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -100,6 +100,7 @@ virtual int get_log_action(int mod, int level); virtual void set_log_action(int mod, int level, int action); virtual const char *get_action_name(int action); + virtual int is_action_name(const char *val); virtual int get_default_log_action(int level) { return logfunctions::get_default_action(level); } @@ -123,6 +124,7 @@ virtual void set_notify_callback(bxevent_handler func, void *arg); virtual void get_notify_callback(bxevent_handler *func, void **arg); virtual BxEvent* sim_to_ci_event(BxEvent *event); + virtual int log_warn(const char *prefix, int level, const char *msg); virtual int log_ask(const char *prefix, int level, const char *msg); virtual void log_msg(const char *prefix, int level, const char *msg); virtual void set_log_viewer(bx_bool val) { bx_log_viewer = val; } @@ -420,6 +422,11 @@ return io->getaction(action); } +int bx_real_sim_c::is_action_name(const char *val) +{ + return io->isaction(val); +} + const char *bx_real_sim_c::get_log_level_name(int level) { return io->getlevel(level); @@ -575,6 +582,21 @@ } } +int bx_real_sim_c::log_warn(const char *prefix, int level, const char *msg) +{ + BxEvent be; + be.type = BX_SYNC_EVT_LOG_ASK; + be.u.logmsg.prefix = prefix; + be.u.logmsg.level = level; + be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_MSGBOX_WARN; + // default return value in case something goes wrong. + be.retcode = BX_LOG_NOTIFY_FAILED; + // calling notify + sim_to_ci_event(&be); + return be.retcode; +} + // returns 0 for continue, 1 for alwayscontinue, 2 for die. int bx_real_sim_c::log_ask(const char *prefix, int level, const char *msg) { @@ -583,6 +605,7 @@ be.u.logmsg.prefix = prefix; be.u.logmsg.level = level; be.u.logmsg.msg = msg; + be.u.logmsg.flag = BX_LOG_ASK_ASKDLG; // default return value in case something goes wrong. be.retcode = BX_LOG_NOTIFY_FAILED; // calling notify @@ -1157,16 +1180,10 @@ } else if (!strncmp(string, "PANIC=", 6)) { type = LOGLEV_PANIC; } - if (!strcmp(string+j, "ignore")) { - action = ACT_IGNORE; - } else if (!strcmp(string+j, "report")) { - action = ACT_REPORT; - } else if (!strcmp(string+j, "ask")) { - action = ACT_ASK; - } else if (!strcmp(string+j, "fatal")) { - action = ACT_FATAL; + action = is_action_name(string+j); + if (action >= ACT_IGNORE) { + set_log_action(dev, type, action); } - set_log_action(dev, type, action); } else { if (i == 1) { BX_ERROR(("restore_logopts(): log module '%s' not found", devname)); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/siminterface.h ./gui/siminterface.h --- /home/volker/bochs/bochs/gui/siminterface.h 2016-03-31 19:24:37.451025427 +0200 +++ ./gui/siminterface.h 2016-12-28 11:11:21.036683362 +0100 @@ -168,6 +168,7 @@ typedef enum { ACT_IGNORE = 0, ACT_REPORT, + ACT_WARN, ACT_ASK, ACT_FATAL, N_ACT @@ -178,11 +179,11 @@ // normally all action choices are available for all event types. The exclude // expression allows some choices to be eliminated if they don't make any // sense. For example, it would be stupid to ignore a panic. -#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ - /* can't die or ask, on debug or info events */ \ - (type <= LOGLEV_INFO && (choice == ACT_ASK || choice == ACT_FATAL)) \ - /* can't ignore panics */ \ - || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ +#define BX_LOG_OPTS_EXCLUDE(type, choice) ( \ + /* can't die, ask or warn, on debug or info events */ \ + (type <= LOGLEV_INFO && (choice >= ACT_WARN)) \ + /* can't ignore panics */ \ + || (type == LOGLEV_PANIC && choice == ACT_IGNORE) \ ) // floppy / cdrom media status @@ -392,6 +393,7 @@ // synchronizing threads, etc. for each. typedef struct { Bit8u level; + Bit8u flag; const char *prefix; const char *msg; } BxLogMsgEvent; @@ -419,6 +421,12 @@ BX_LOG_NOTIFY_FAILED }; +enum { + BX_LOG_ASK_ASKDLG, + BX_LOG_ASK_MSGBOX_WARN, + BX_LOG_ASK_MSGBOX_QUIT +}; + // Event type: BX_SYNC_EVT_GET_DBG_COMMAND // // This is a synchronous event sent from the simulator to the debugger @@ -675,6 +683,7 @@ virtual int get_default_log_action(int level) {return -1;} virtual void set_default_log_action(int level, int action) {} virtual const char *get_action_name(int action) {return NULL;} + virtual int is_action_name(const char *val) {return -1;} virtual const char *get_log_level_name(int level) {return NULL;} virtual int get_max_log_level() {return -1;} @@ -715,6 +724,9 @@ // send an event from the simulator to the CI. virtual BxEvent* sim_to_ci_event(BxEvent *event) {return NULL;} + // called from simulator when it hits errors, to warn the user + // before continuing simulation + virtual int log_warn(const char *prefix, int level, const char *msg) {return -1;} // called from simulator when it hits serious errors, to ask if the user // wants to continue or not virtual int log_ask(const char *prefix, int level, const char *msg) {return -1;} diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/textconfig.cc ./gui/textconfig.cc --- /home/volker/bochs/bochs/gui/textconfig.cc 2016-12-05 20:15:59.112637000 +0100 +++ ./gui/textconfig.cc 2016-12-28 12:44:43.079411258 +0100 @@ -2,7 +2,7 @@ // $Id: textconfig.cc 12983 2016-12-05 19:15:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2013 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -552,8 +552,8 @@ } static const char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] "; -static const char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" }; -static int log_level_n_choices_normal = 4; +static const char *log_level_choices[N_ACT+1] = { "ignore", "report", "warn", "ask", "fatal", "no change" }; +static int log_level_n_choices_normal = N_ACT; void bx_log_options(int individual) { @@ -589,7 +589,7 @@ bx_print_log_action_table(); for (int level=0; level<SIM->get_max_log_level(); level++) { char prompt[1024]; - int action, default_action = 4; // default to no change + int action, default_action = N_ACT; // default to no change sprintf(prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name(level)); // do show the no change choice (choices=4) if (ask_menu(prompt, "", log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0) @@ -718,47 +718,50 @@ event->retcode = event->u.param.param->text_ask(stdin, stderr); return event; case BX_SYNC_EVT_LOG_ASK: - { - int level = event->u.logmsg.level; - fprintf(stderr, "========================================================================\n"); - fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); - fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); - fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); - fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); - fprintf(stderr, " cont - continue execution\n"); - fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); - fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); - fprintf(stderr, " die - stop execution now\n"); - fprintf(stderr, " abort - dump core %s\n", - BX_HAVE_ABORT ? "" : "(Disabled)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + int level = event->u.logmsg.level; + fprintf(stderr, "========================================================================\n"); + fprintf(stderr, "Event type: %s\n", SIM->get_log_level_name (level)); + fprintf(stderr, "Device: %s\n", event->u.logmsg.prefix); + fprintf(stderr, "Message: %s\n\n", event->u.logmsg.msg); + fprintf(stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); + fprintf(stderr, " cont - continue execution\n"); + fprintf(stderr, " alwayscont - continue execution, and don't ask again.\n"); + fprintf(stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); + fprintf(stderr, " die - stop execution now\n"); + fprintf(stderr, " abort - dump core %s\n", + BX_HAVE_ABORT ? "" : "(Disabled)"); #if BX_DEBUGGER - fprintf(stderr, " debug - continue and return to bochs debugger\n"); + fprintf(stderr, " debug - continue and return to bochs debugger\n"); #endif #if BX_GDBSTUB - fprintf(stderr, " debug - hand control to gdb\n"); + fprintf(stderr, " debug - hand control to gdb\n"); #endif - int choice; + int choice; ask: - if (ask_menu("Choose one of the actions above: [%s] ", "", - log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) - event->retcode = -1; - // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. - if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; - fflush(stdout); - fflush(stderr); - event->retcode = choice; - } - return event; - case BX_ASYNC_EVT_REFRESH: - case BX_ASYNC_EVT_DBG_MSG: - case BX_ASYNC_EVT_LOG_MSG: - // The text mode interface does not use these events, so just ignore - // them. - return event; - default: - fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); - return event; + if (ask_menu("Choose one of the actions above: [%s] ", "", + log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) + event->retcode = -1; + // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. + if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; + fflush(stdout); + fflush(stderr); + event->retcode = choice; + } else { + // warning prompt not implemented + event->retcode = 0; + } + return event; + case BX_ASYNC_EVT_REFRESH: + case BX_ASYNC_EVT_DBG_MSG: + case BX_ASYNC_EVT_LOG_MSG: + // The text mode interface does not use these events, so just ignore + // them. + return event; + default: + fprintf(stderr, "textconfig: notify callback called with event type %04x\n", event->type); + return event; } assert(0); // switch statement should return } diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/win32dialog.cc ./gui/win32dialog.cc --- /home/volker/bochs/bochs/gui/win32dialog.cc 2014-06-20 11:32:02.034026376 +0200 +++ ./gui/win32dialog.cc 2016-12-28 12:50:14.148888740 +0100 @@ -2,7 +2,7 @@ // $Id: win32dialog.cc 12381 2014-06-20 09:31:56Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2003-2014 The Bochs Project +// Copyright (C) 2003-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include "win32res.h" #include "win32paramdlg.h" -const char log_choices[5][16] = {"ignore", "log", "ask user", "end simulation", "no change"}; +const char log_choices[N_ACT+1][16] = {"ignore", "log", "warn user", "ask user", "end simulation", "no change"}; HWND GetBochsWindow() { @@ -97,12 +97,16 @@ SetWindowText(GetDlgItem(hDlg, IDASKMSG), event->u.logmsg.msg); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue"); SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and don't ask again"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Kill simulation"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Abort (dump core)"); #if BX_DEBUGGER - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_ADDSTRING, 0, (LPARAM)"Continue and return to debugger"); #endif - SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0); + } else { + SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 0, 0); + } SetFocus(GetDlgItem(hDlg, IDASKLIST)); return FALSE; case WM_CLOSE: diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.cc ./gui/wxdialog.cc --- /home/volker/bochs/bochs/gui/wxdialog.cc 2015-01-07 17:17:40.447882000 +0100 +++ ./gui/wxdialog.cc 2016-12-27 20:30:44.997609007 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.cc 12594 2015-01-07 16:17:40Z sshwarts $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -208,7 +208,6 @@ : wxDialog(parent, id, wxT(""), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - //static int integers[LOG_OPTS_N_CHOICES_NORMAL] = {0, 1, 2, 3}; static wxString names[] = ADVLOG_OPTS_TYPE_NAMES; SetTitle(ADVLOG_OPTS_TITLE); vertSizer = new wxBoxSizer(wxVERTICAL); @@ -1563,7 +1562,7 @@ bool includeNoChange) { static wxString choices[] = LOG_OPTS_CHOICES; - static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4}; + static int integers[LOG_OPTS_N_CHOICES] = {0, 1, 2, 3, 4, 5}; wxChoice *control = new wxChoice(parent, id, wxDefaultPosition, wxDefaultSize); int lastChoice = 0; // remember index of last choice int nchoice = includeNoChange? LOG_OPTS_N_CHOICES : LOG_OPTS_N_CHOICES_NORMAL; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxdialog.h ./gui/wxdialog.h --- /home/volker/bochs/bochs/gui/wxdialog.h 2014-12-23 20:30:12.896090221 +0100 +++ ./gui/wxdialog.h 2016-12-27 20:34:28.518389938 +0100 @@ -2,7 +2,7 @@ // $Id: wxdialog.h 12576 2014-12-23 19:30:03Z vruppert $ //////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -354,10 +354,10 @@ #define LOG_OPTS_PROMPT wxT("How should Bochs respond to each type of event?") #define LOG_OPTS_TYPE_NAMES { wxT("Debug events"), wxT("Info events"), wxT("Error events"), wxT("Panic events") } #define LOG_OPTS_N_TYPES 4 -#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("ask user"), wxT("end simulation"), wxT("no change") } -#define LOG_OPTS_N_CHOICES_NORMAL 4 -#define LOG_OPTS_N_CHOICES 5 // number of choices, including "no change" -#define LOG_OPTS_NO_CHANGE 4 // index of "no change" +#define LOG_OPTS_CHOICES { wxT("ignore"), wxT("log"), wxT("warn user"), wxT("ask user"), wxT("end simulation"), wxT("no change") } +#define LOG_OPTS_N_CHOICES_NORMAL 5 +#define LOG_OPTS_N_CHOICES 6 // number of choices, including "no change" +#define LOG_OPTS_NO_CHANGE 5 // index of "no change" #define LOG_OPTS_ADV wxT("For additional control over how each device responds to events, use the menu option \"Log ... By Device\".") wxFlexGridSizer *gridSizer; wxChoice *action[LOG_OPTS_N_TYPES]; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/wxmain.cc ./gui/wxmain.cc --- /home/volker/bochs/bochs/gui/wxmain.cc 2016-12-26 17:12:57.470174541 +0100 +++ ./gui/wxmain.cc 2016-12-28 12:15:26.035961463 +0100 @@ -2,7 +2,7 @@ // $Id: wxmain.cc 13006 2016-12-26 16:12:54Z vruppert $ ///////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2014 The Bochs Project +// Copyright (C) 2002-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -1158,6 +1158,10 @@ #if !BX_DEBUGGER && !BX_GDBSTUB dlg.EnableButton(dlg.DEBUG, FALSE); #endif + if (be->u.logmsg.flag != BX_LOG_ASK_ASKDLG) { + dlg.EnableButton(dlg.DIE, FALSE); + dlg.EnableButton(dlg.DUMP, FALSE); + } dlg.SetContext(wxString(be->u.logmsg.prefix, wxConvUTF8)); dlg.SetMessage(wxString(be->u.logmsg.msg, wxConvUTF8)); int n = dlg.ShowModal(); diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/gui/x.cc ./gui/x.cc --- /home/volker/bochs/bochs/gui/x.cc 2016-12-27 17:26:59.622665119 +0100 +++ ./gui/x.cc 2016-12-28 12:03:10.963351647 +0100 @@ -2687,11 +2687,7 @@ } else { size_x = 30 + maxlen * 6; } - if (lines < 3) { - size_y = 90; - } else { - size_y = 60 + lines * 15; - } + size_y = 70 + lines * 15; x11_dialog_c *xdlg = new x11_dialog_c(name, size_x, size_y, (mode == XDLG_SIMPLE) ? 1 : 2); ypos = 34; @@ -2729,11 +2725,21 @@ bx_param_string_c *sparam; bx_param_enum_c *eparam; bx_list_c *list; + char message[256]; switch (event->type) { case BX_SYNC_EVT_LOG_ASK: - event->retcode = x11_ask_dialog(event); + if (event->u.logmsg.flag == BX_LOG_ASK_ASKDLG) { + event->retcode = x11_ask_dialog(event); + } else if (event->u.logmsg.flag == BX_LOG_ASK_MSGBOX_WARN) { + const char *title = SIM->get_log_level_name(event->u.logmsg.level); + sprintf(message, "Device: %s\n\nMessage: %s", event->u.logmsg.prefix, + event->u.logmsg.msg); + bx_param_bool_c bparam(NULL, "warn", title, message, 1); + x11_message_box(&bparam, XDLG_SIMPLE); + event->retcode = 0; + } return event; case BX_SYNC_EVT_ASK_PARAM: param = event->u.param.param; diff -urNX /home/volker/exclude-bochs /home/volker/bochs/bochs/logio.cc ./logio.cc --- /home/volker/bochs/bochs/logio.cc 2015-05-10 08:55:18.678940963 +0200 +++ ./logio.cc 2016-12-28 00:40:40.395736643 +0100 @@ -2,7 +2,7 @@ // $Id: logio.cc 12759 2015-05-10 06:55:16Z vruppert $ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2001-2014 The Bochs Project +// Copyright (C) 2001-2016 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -50,11 +50,25 @@ else return "?"; } +static const char *act_name[N_ACT] = { "ignore", "report", "warn", "ask", "fatal" }; + const char* iofunctions::getaction(int i) const { - static const char *name[] = { "ignore", "report", "ask", "fatal" }; assert (i>=ACT_IGNORE && i<N_ACT); - return name[i]; + return act_name[i]; +} + +int iofunctions::isaction(const char *val) const +{ + int action = -1; + + for (int i = 0; i < N_ACT; i++) { + if (!strcmp(val, act_name[i])) { + action = ACT_IGNORE + i; + break; + } + } + return action; } void iofunctions::flush(void) @@ -414,6 +428,11 @@ logio->out(LOGLEV_ERROR, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_ERROR] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_ERROR, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_ERROR] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_ERROR, prefix, fmt, ap); @@ -438,6 +457,11 @@ logio->out(LOGLEV_PANIC, prefix, fmt, ap); va_end(ap); + if (onoff[LOGLEV_PANIC] == ACT_WARN) { + va_start(ap, fmt); + warn(LOGLEV_PANIC, prefix, fmt, ap); + va_end(ap); + } if (onoff[LOGLEV_PANIC] == ACT_ASK) { va_start(ap, fmt); ask(LOGLEV_PANIC, prefix, fmt, ap); @@ -465,6 +489,36 @@ // the actions ask() and fatal() are not supported here } +void logfunctions::warn(int level, const char *prefix, const char *fmt, va_list ap) +{ + // Guard against reentry on warn() function. The danger is that some + // function that's called within warn() could trigger another + // BX_ERROR that could call warn() again, leading to infinite + // recursion and infinite asks. + static char in_warn_already = 0; + char buf1[1024]; + if (in_warn_already) { + fprintf(stderr, "logfunctions::warn() should not reenter!!\n"); + return; + } + in_warn_already = 1; + vsnprintf(buf1, sizeof(buf1), fmt, ap); + // FIXME: facility set to 0 because it's unknown. + + // update vga screen. This is useful because sometimes useful messages + // are printed on the screen just before a panic. It's also potentially + // dangerous if this function calls ask again... That's why I added + // the reentry check above. + SIM->refresh_vga(); + + // ensure the text screen is showing + SIM->set_display_mode(DISP_MODE_CONFIG); + SIM->log_warn(prefix, level, buf1); + // return to simulation mode + SIM->set_display_mode(DISP_MODE_SIM); + in_warn_already = 0; +} + void logfunctions::ask(int level, const char *prefix, const char *fmt, va_list ap) { // Guard against reentry on ask() function. The danger is that some
2016-12-28 18:06:34 +03:00
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 2, 0);
} else {
SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_SETCURSEL, 0, 0);
}
SetFocus(GetDlgItem(hDlg, IDASKLIST));
return FALSE;
case WM_CLOSE:
EndDialog(hDlg, BX_LOG_ASK_CHOICE_DIE);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hDlg, SendMessage(GetDlgItem(hDlg, IDASKLIST), LB_GETCURSEL, 0, 0));
break;
case IDCANCEL:
EndDialog(hDlg, BX_LOG_ASK_CHOICE_DIE);
break;
}
}
return FALSE;
}
static BOOL CALLBACK StringParamProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static bx_param_string_c *param;
char buffer[512];
const char *title;
switch (msg) {
case WM_INITDIALOG:
param = (bx_param_string_c *)lParam;
title = param->get_label();
if ((title == NULL) || (strlen(title) == 0)) {
title = param->get_name();
}
SetWindowText(hDlg, title);
SetWindowText(GetDlgItem(hDlg, IDSTRING), param->getptr());
SendMessage(GetDlgItem(hDlg, IDSTRING), EM_SETLIMITTEXT, param->get_maxsize(), 0);
return TRUE;
case WM_CLOSE:
EndDialog(hDlg, -1);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
GetDlgItemText(hDlg, IDSTRING, buffer, param->get_maxsize() + 1);
param->set(buffer);
EndDialog(hDlg, 1);
break;
case IDCANCEL:
EndDialog(hDlg, -1);
break;
}
}
return FALSE;
}
void SetStandardLogOptions(HWND hDlg)
{
int level, idx;
int defchoice[5];
for (level=0; level<N_LOGLEV; level++) {
int mod = 0;
int first = SIM->get_log_action (mod, level);
BOOL consensus = true;
// now compare all others to first. If all match, then use "first" as
// the initial value.
for (mod=1; mod<SIM->get_n_log_modules(); mod++) {
if (first != SIM->get_log_action (mod, level)) {
consensus = false;
break;
}
}
if (consensus)
defchoice[level] = first;
else
defchoice[level] = 4;
}
for (level=0; level<N_LOGLEV; level++) {
idx = 0;
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_RESETCONTENT, 0, 0);
for (int action=0; action<5; action++) {
// the exclude expression allows some choices not being available if they
// don't make any sense. For example, it would be stupid to ignore a panic.
if (!BX_LOG_OPTS_EXCLUDE(level, action)) {
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_ADDSTRING, 0, (LPARAM)log_choices[action]);
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETITEMDATA, idx, action);
if (action == defchoice[level]) {
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETCURSEL, idx, 0);
}
idx++;
}
}
}
EnableWindow(GetDlgItem(hDlg, IDDEVLIST), FALSE);
}
void SetAdvancedLogOptions(HWND hDlg)
{
int idx, level, mod;
idx = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETCURSEL, 0, 0);
mod = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETITEMDATA, idx, 0);
for (level=0; level<N_LOGLEV; level++) {
idx = 0;
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_RESETCONTENT, 0, 0);
for (int action=0; action<4; action++) {
// exclude some action / level combinations (see above)
if (!BX_LOG_OPTS_EXCLUDE(level, action)) {
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_ADDSTRING, 0, (LPARAM)log_choices[action]);
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETITEMDATA, idx, action);
if (action == SIM->get_log_action (mod, level)) {
SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_SETCURSEL, idx, 0);
}
idx++;
}
}
}
}
void InitLogOptionsDialog(HWND hDlg, BOOL advanced)
{
int idx, mod;
char name[32];
for (mod=0; mod<SIM->get_n_log_modules(); mod++) {
if (lstrcmp(SIM->get_logfn_name(mod), "?")) {
lstrcpyn(name, SIM->get_logfn_name(mod), 32);
idx = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_ADDSTRING, 0, (LPARAM)name);
SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETITEMDATA, idx, mod);
}
}
if (advanced) {
SendMessage(GetDlgItem(hDlg, IDADVLOGOPT), BM_SETCHECK, BST_CHECKED, 0);
SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETCURSEL, 0, 0);
SetAdvancedLogOptions(hDlg);
} else {
SetStandardLogOptions(hDlg);
}
}
void ApplyLogOptions(HWND hDlg, BOOL advanced)
{
int idx, level, mod, value;
if (advanced) {
idx = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETCURSEL, 0, 0);
mod = SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_GETITEMDATA, idx, 0);
for (level=0; level<N_LOGLEV; level++) {
idx = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETCURSEL, 0, 0);
value = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETITEMDATA, idx, 0);
SIM->set_log_action(mod, level, value);
}
EnableWindow(GetDlgItem(hDlg, IDDEVLIST), TRUE);
} else {
for (level=0; level<N_LOGLEV; level++) {
idx = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETCURSEL, 0, 0);
value = SendMessage(GetDlgItem(hDlg, IDLOGEVT1+level), CB_GETITEMDATA, idx, 0);
if (value < 4) {
// set new default
SIM->set_default_log_action(level, value);
// apply that action to all modules (devices)
SIM->set_log_action(-1, level, value);
}
}
}
EnableWindow(GetDlgItem(hDlg, IDADVLOGOPT), TRUE);
}
static BOOL CALLBACK LogOptDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static BOOL advanced;
static BOOL changed;
long noticode;
switch (msg) {
case WM_INITDIALOG:
advanced = (BOOL)lParam;
InitLogOptionsDialog(hDlg, advanced);
changed = FALSE;
EnableWindow(GetDlgItem(hDlg, IDAPPLY), FALSE);
return TRUE;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_COMMAND:
noticode = HIWORD(wParam);
switch(noticode) {
case CBN_SELCHANGE: /* LBN_SELCHANGE is the same value */
switch (LOWORD(wParam)) {
case IDDEVLIST:
SetAdvancedLogOptions(hDlg);
break;
case IDLOGEVT1:
case IDLOGEVT2:
case IDLOGEVT3:
case IDLOGEVT4:
case IDLOGEVT5:
if (!changed) {
EnableWindow(GetDlgItem(hDlg, IDADVLOGOPT), FALSE);
if (advanced) {
EnableWindow(GetDlgItem(hDlg, IDDEVLIST), FALSE);
}
changed = TRUE;
EnableWindow(GetDlgItem(hDlg, IDAPPLY), TRUE);
}
break;
}
break;
default:
switch (LOWORD(wParam)) {
case IDADVLOGOPT:
if (SendMessage(GetDlgItem(hDlg, IDADVLOGOPT), BM_GETCHECK, 0, 0) == BST_CHECKED) {
EnableWindow(GetDlgItem(hDlg, IDDEVLIST), TRUE);
SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETCURSEL, 0, 0);
SetAdvancedLogOptions(hDlg);
advanced = TRUE;
} else {
SendMessage(GetDlgItem(hDlg, IDDEVLIST), LB_SETCURSEL, (WPARAM)-1, 0);
SetStandardLogOptions(hDlg);
advanced = FALSE;
}
break;
case IDAPPLY:
ApplyLogOptions(hDlg, advanced);
EnableWindow(GetDlgItem(hDlg, IDAPPLY), FALSE);
changed = FALSE;
break;
case IDOK:
if (changed) {
ApplyLogOptions(hDlg, advanced);
}
EndDialog(hDlg, 1);
break;
case IDCANCEL:
EndDialog(hDlg, 0);
break;
}
}
break;
}
return FALSE;
}
void LogOptionsDialog(HWND hwnd, bool runtime)
{
DialogBoxParam(NULL, MAKEINTRESOURCE(LOGOPT_DLG), hwnd, (DLGPROC)LogOptDlgProc, (LPARAM)runtime);
}
static BOOL CALLBACK PluginCtrlDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
int count, i;
long code;
bx_list_c *plugin_ctrl;
bx_param_bool_c *plugin;
char plugname[20], message[80];
switch (msg) {
case WM_INITDIALOG:
plugin_ctrl = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL);
count = plugin_ctrl->get_size();
for (i = 0; i < count; i++) {
plugin = (bx_param_bool_c*)plugin_ctrl->get(i);
if (plugin->get()) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_ADDSTRING, 0, (LPARAM)plugin->get_name());
} else {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_ADDSTRING, 0, (LPARAM)plugin->get_name());
}
}
EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
return TRUE;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_COMMAND:
code = HIWORD(wParam);
switch (LOWORD(wParam)) {
case IDPLUGLIST1:
if (code == LBN_SELCHANGE) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_SETCURSEL, -1, 0);
EnableWindow(GetDlgItem(hDlg, IDLOAD), TRUE);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
}
break;
case IDPLUGLIST2:
if (code == LBN_SELCHANGE) {
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_SETCURSEL, -1, 0);
EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), TRUE);
}
break;
case IDLOAD:
i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_GETCURSEL, 0, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_GETTEXT, i, (LPARAM)plugname);
if (SIM->opt_plugin_ctrl(plugname, 1)) {
wsprintf(message, "Plugin '%s' loaded", plugname);
MessageBox(hDlg, message, "Plugin Control", MB_ICONINFORMATION);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_DELETESTRING, i, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_ADDSTRING, 0, (LPARAM)plugname);
EnableWindow(GetDlgItem(hDlg, IDLOAD), FALSE);
}
break;
case IDUNLOAD:
i = SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_GETCURSEL, 0, 0);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_GETTEXT, i, (LPARAM)plugname);
if (SIM->opt_plugin_ctrl(plugname, 0)) {
wsprintf(message, "Plugin '%s' unloaded", plugname);
MessageBox(hDlg, message, "Plugin Control", MB_ICONINFORMATION);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST1), LB_ADDSTRING, 0, (LPARAM)plugname);
SendMessage(GetDlgItem(hDlg, IDPLUGLIST2), LB_DELETESTRING, i, 0);
EnableWindow(GetDlgItem(hDlg, IDUNLOAD), FALSE);
}
break;
case IDOK:
EndDialog(hDlg, 1);
break;
}
break;
}
return FALSE;
}
void PluginCtrlDialog(HWND hwnd)
{
DialogBox(NULL, MAKEINTRESOURCE(PLUGIN_CTRL_DLG), hwnd, (DLGPROC)PluginCtrlDlgProc);
}
typedef struct {
const char *label;
const char *param;
} edit_opts_t;
edit_opts_t start_options[] = {
{"Plugin Control", "#plugins"},
{"Logfile", "log"},
{"Log Options", "#logopts"},
{"CPU", "cpu"},
#if BX_CPU_LEVEL >= 4
{"CPUID", "cpuid"},
#endif
{"Memory", "memory"},
{"Clock & CMOS", "clock_cmos"},
{"PCI", "pci"},
{"Display & Interface", "display"},
{"Keyboard & Mouse", "keyboard_mouse"},
{"Disk & Boot", BXPN_MENU_DISK_WIN32},
{"Serial / Parallel / USB", "ports"},
{"Network card", "network"},
{"Sound card", "sound"},
{"Other", "misc"},
#if BX_PLUGINS
{"User-defined Options", "user"},
#endif
{NULL, NULL}
};
edit_opts_t runtime_options[] = {
{"CD-ROM", BXPN_MENU_RUNTIME_CDROM},
{"USB", BXPN_MENU_RUNTIME_USB},
{"Misc", BXPN_MENU_RUNTIME_MISC},
{"Log Options", "#logopts"},
{NULL, NULL}
};
static BOOL CALLBACK MainMenuDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static bool runtime;
int choice, code, i;
bx_param_filename_c *rcfile;
char path[BX_PATHNAME_LEN];
const char *pname;
switch (msg) {
case WM_INITDIALOG:
runtime = (bool)lParam;
EnableWindow(GetDlgItem(hDlg, IDEDITCFG), FALSE);
if (runtime) {
SetWindowText(hDlg, "Bochs Runtime Menu");
EnableWindow(GetDlgItem(hDlg, IDREADRC), FALSE);
EnableWindow(GetDlgItem(hDlg, IDRESETCFG), FALSE);
EnableWindow(GetDlgItem(hDlg, IDRESTORE), FALSE);
SetWindowText(GetDlgItem(hDlg, IDOK), "&Continue");
i = 0;
while (runtime_options[i].label != NULL) {
SendMessage(GetDlgItem(hDlg, IDEDITBOX), LB_ADDSTRING, 0, (LPARAM)runtime_options[i].label);
i++;
}
choice = IDOK;
} else {
i = 0;
while (start_options[i].label != NULL) {
SendMessage(GetDlgItem(hDlg, IDEDITBOX), LB_ADDSTRING, 0, (LPARAM)start_options[i].label);
i++;
}
if (SIM->get_param_enum(BXPN_BOCHS_START)->get() == BX_LOAD_START) {
choice = IDREADRC;
} else {
choice = IDOK;
}
}
SetFocus(GetDlgItem(hDlg, choice));
return FALSE;
case WM_CLOSE:
if (runtime) {
EndDialog(hDlg, 1);
} else {
bx_user_quit = 1;
EndDialog(hDlg, -1);
}
break;
case WM_COMMAND:
code = HIWORD(wParam);
switch (LOWORD(wParam)) {
case IDREADRC:
rcfile = new bx_param_filename_c(NULL, "rcfile", "Load Bochs Config File",
"", "bochsrc.bxrc", BX_PATHNAME_LEN);
rcfile->set_extension("bxrc");
if (AskFilename(hDlg, rcfile, NULL) > 0) {
SIM->reset_all_param();
SIM->read_rc(rcfile->getptr());
}
delete rcfile;
break;
case IDWRITERC:
rcfile = new bx_param_filename_c(NULL, "rcfile", "Save Bochs Config File",
"", "bochsrc.bxrc", BX_PATHNAME_LEN);
rcfile->set_extension("bxrc");
rcfile->set_options(rcfile->SAVE_FILE_DIALOG);
if (AskFilename(hDlg, rcfile, NULL) > 0) {
SIM->write_rc(rcfile->getptr(), 1);
}
delete rcfile;
break;
case IDEDITBOX:
if ((code == LBN_SELCHANGE) ||
(code == LBN_DBLCLK)) {
EnableWindow(GetDlgItem(hDlg, IDEDITCFG), TRUE);
}
if (code != LBN_DBLCLK) {
break;
}
case IDEDITCFG:
i = SendMessage(GetDlgItem(hDlg, IDEDITBOX), LB_GETCURSEL, 0, 0);
if (runtime) {
pname = runtime_options[i].param;
} else {
pname = start_options[i].param;
}
if (pname[0] != '#') {
bx_list_c *list = (bx_list_c*)SIM->get_param(pname);
if (list != NULL) {
if (list->get_size() > 0) {
win32ParamDialog(hDlg, pname);
} else {
MessageBox(hDlg, "Nothing to configure in this section", "Warning", MB_ICONEXCLAMATION);
}
} else {
MessageBox(hDlg, "Nothing to configure in this section", "Warning", MB_ICONEXCLAMATION);
}
} else {
if (!lstrcmp(pname, "#logopts")) {
LogOptionsDialog(hDlg, runtime);
} else if (!lstrcmp(pname, "#plugins")) {
PluginCtrlDialog(hDlg);
} else {
MessageBox(hDlg, "Unknown keyword", "Warning", MB_ICONEXCLAMATION);
}
}
break;
case IDRESETCFG:
if (MessageBox(hDlg, "Reset all options back to their factory defaults ?",
"Reset Configuration", MB_ICONEXCLAMATION | MB_YESNO) == IDYES) {
SIM->reset_all_param();
}
break;
case IDRESTORE:
path[0] = 0;
if (BrowseDir("Restore Bochs state from...", path) >= 0) {
SetCurrentDirectory(path);
SIM->get_param_bool(BXPN_RESTORE_FLAG)->set(1);
SIM->get_param_string(BXPN_RESTORE_PATH)->set(path);
if (!SIM->restore_config()) {
MessageBox(hDlg, "Cannot restore configuration!", "ERROR", MB_ICONERROR);
}
EndDialog(hDlg, 1);
}
break;
case IDOK:
if (runtime) {
SIM->update_runtime_options();
}
EndDialog(hDlg, 1);
break;
case IDCANCEL:
if (runtime) {
EndDialog(hDlg, 1);
break;
}
case IDQUIT:
bx_user_quit = 1;
EndDialog(hDlg, -1);
break;
}
}
return FALSE;
}
void LogAskDialog(BxEvent *event)
{
2013-11-10 21:36:13 +04:00
event->retcode = (Bit32s) DialogBoxParam(NULL, MAKEINTRESOURCE(ASK_DLG), GetBochsWindow(),
(DLGPROC)LogAskProc, (LPARAM)event);
}
int AskString(bx_param_string_c *param)
{
2013-11-10 21:36:13 +04:00
return (int) DialogBoxParam(NULL, MAKEINTRESOURCE(STRING_DLG), GetBochsWindow(),
(DLGPROC)StringParamProc, (LPARAM)param);
}
int MainMenuDialog(HWND hwnd, bool runtime)
{
2013-11-10 21:36:13 +04:00
return (int) DialogBoxParam(NULL, MAKEINTRESOURCE(MAINMENU_DLG), hwnd,
(DLGPROC)MainMenuDlgProc, (LPARAM)runtime);
}
Add Modeless MessageBox capabilities (#109) As an example, when saving the state of an emulation, especially one that has large image files and a large memory setting, there is a pause between the time you choose a directory to save to, and the MessageBox that states that the state was saved. During this time, there is no indication that Bochs is doing anything. As far as the user is concerned, Bochs froze. So, this PR adds the capability to display a _Modeless_ message box. To do so, at any point you need a message box shown, allowing other things to continue to happen (SYNCHRONOUS), simply call the following line: `void *hwnd = SIM->ml_message_box("Message Box Title", "Message Box Text");` Then after the task has been performed, remove the message box: `SIM->ml_message_box_kill(hwnd);` The function is implemented in all configurations via virtual calls, however, the creation of the message box is currently only implemented in the Win32 configuration. Other configurations will need this implemented, though I do not have those configurations to test with, except the text only config. I may get around to it :-). This also currently only displays as the state is being saved. To display when the state is being restored should now be a simple task by adding the two lines shown above to the associated function. The only drawback with this is that if the state is considerably small, the save will take just a second or less. If so, this window will show and then instantly be removed, possibly confusing the user. _What was that!!_
2023-10-29 23:47:12 +03:00
#define ML_WIN_WIDTH 400
#define ML_WIN_HEIGHT 150
// Unfortunetly, Win32 Edit Controls must have \r\n for line feeds, and Bochs uses only \n
// We must add \r to every \n to get Windows to drop to the next line in an Edit Control.
void conv_dos2unix(const char *src, char *targ, int max_len)
{
char last = 0;
while (*src && (max_len > 2)) {
if ((*src == '\n') && (last != '\r')) {
*targ++ = '\r';
max_len--;
}
*targ++ = last = *src++;
max_len--;
}
*targ = '\0';
}
BxEvent* win32_notify_callback(void *unused, BxEvent *event)
{
Add Modeless MessageBox capabilities (#109) As an example, when saving the state of an emulation, especially one that has large image files and a large memory setting, there is a pause between the time you choose a directory to save to, and the MessageBox that states that the state was saved. During this time, there is no indication that Bochs is doing anything. As far as the user is concerned, Bochs froze. So, this PR adds the capability to display a _Modeless_ message box. To do so, at any point you need a message box shown, allowing other things to continue to happen (SYNCHRONOUS), simply call the following line: `void *hwnd = SIM->ml_message_box("Message Box Title", "Message Box Text");` Then after the task has been performed, remove the message box: `SIM->ml_message_box_kill(hwnd);` The function is implemented in all configurations via virtual calls, however, the creation of the message box is currently only implemented in the Win32 configuration. Other configurations will need this implemented, though I do not have those configurations to test with, except the text only config. I may get around to it :-). This also currently only displays as the state is being saved. To display when the state is being restored should now be a simple task by adding the two lines shown above to the associated function. The only drawback with this is that if the state is considerably small, the save will take just a second or less. If so, this window will show and then instantly be removed, possibly confusing the user. _What was that!!_
2023-10-29 23:47:12 +03:00
int opts, x = -1, y = -1;
bx_param_c *param;
bx_param_string_c *sparam;
char pname[BX_PATHNAME_LEN];
Add Modeless MessageBox capabilities (#109) As an example, when saving the state of an emulation, especially one that has large image files and a large memory setting, there is a pause between the time you choose a directory to save to, and the MessageBox that states that the state was saved. During this time, there is no indication that Bochs is doing anything. As far as the user is concerned, Bochs froze. So, this PR adds the capability to display a _Modeless_ message box. To do so, at any point you need a message box shown, allowing other things to continue to happen (SYNCHRONOUS), simply call the following line: `void *hwnd = SIM->ml_message_box("Message Box Title", "Message Box Text");` Then after the task has been performed, remove the message box: `SIM->ml_message_box_kill(hwnd);` The function is implemented in all configurations via virtual calls, however, the creation of the message box is currently only implemented in the Win32 configuration. Other configurations will need this implemented, though I do not have those configurations to test with, except the text only config. I may get around to it :-). This also currently only displays as the state is being saved. To display when the state is being restored should now be a simple task by adding the two lines shown above to the associated function. The only drawback with this is that if the state is considerably small, the save will take just a second or less. If so, this window will show and then instantly be removed, possibly confusing the user. _What was that!!_
2023-10-29 23:47:12 +03:00
NONCLIENTMETRICS ncm;
RECT rect;
HWND hwnd;
event->retcode = -1;
switch (event->type)
{
case BX_SYNC_EVT_LOG_DLG:
LogAskDialog(event);
return event;
case BX_SYNC_EVT_MSG_BOX:
MessageBox(GetBochsWindow(), event->u.logmsg.msg, event->u.logmsg.prefix, MB_ICONERROR);
return event;
Add Modeless MessageBox capabilities (#109) As an example, when saving the state of an emulation, especially one that has large image files and a large memory setting, there is a pause between the time you choose a directory to save to, and the MessageBox that states that the state was saved. During this time, there is no indication that Bochs is doing anything. As far as the user is concerned, Bochs froze. So, this PR adds the capability to display a _Modeless_ message box. To do so, at any point you need a message box shown, allowing other things to continue to happen (SYNCHRONOUS), simply call the following line: `void *hwnd = SIM->ml_message_box("Message Box Title", "Message Box Text");` Then after the task has been performed, remove the message box: `SIM->ml_message_box_kill(hwnd);` The function is implemented in all configurations via virtual calls, however, the creation of the message box is currently only implemented in the Win32 configuration. Other configurations will need this implemented, though I do not have those configurations to test with, except the text only config. I may get around to it :-). This also currently only displays as the state is being saved. To display when the state is being restored should now be a simple task by adding the two lines shown above to the associated function. The only drawback with this is that if the state is considerably small, the save will take just a second or less. If so, this window will show and then instantly be removed, possibly confusing the user. _What was that!!_
2023-10-29 23:47:12 +03:00
case BX_SYNC_EVT_ML_MSG_BOX:
// get the coordinates of the screen size
if (SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0)) {
x = (rect.right - rect.left - ML_WIN_WIDTH) / 2;
y = (rect.bottom - rect.top - ML_WIN_HEIGHT) / 2;
}
// if that failed or the screen isn't very big...
if (x < 0) x = 250;
if (y < 0) y = 250;
// create an EDIT window, with the edit control as read only
hwnd = CreateWindow("EDIT", event->u.logmsg.prefix,
WS_VISIBLE | WS_BORDER | ES_READONLY | ES_LEFT | ES_MULTILINE,
x, y, ML_WIN_WIDTH, ML_WIN_HEIGHT, GetBochsWindow(), (HMENU) NULL, NULL, (LPVOID) NULL);
// if we created the window successfully, change the font to the system font and replace the text
if (hwnd) {
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
SendMessage(hwnd, WM_SETFONT, (WPARAM) CreateFontIndirect(&ncm.lfMessageFont), 0);
conv_dos2unix(event->u.logmsg.msg, pname, BX_PATHNAME_LEN);
SendMessage(hwnd, EM_SETSEL, 0, -1);
SendMessage(hwnd, EM_REPLACESEL, 0, (LPARAM) pname);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
event->param0 = hwnd;
}
return event;
case BX_SYNC_EVT_ML_MSG_BOX_KILL:
if (event->param0)
DestroyWindow((HWND) event->param0);
return event;
case BX_SYNC_EVT_ASK_PARAM:
param = event->u.param.param;
if (param->get_type() == BXT_PARAM_STRING || param->get_type() == BXT_PARAM_BYTESTRING) {
sparam = (bx_param_string_c *)param;
opts = sparam->get_options();
if (opts & sparam->IS_FILENAME) {
if (opts & sparam->SELECT_FOLDER_DLG) {
event->retcode = BrowseDir(sparam->get_label(), sparam->getptr());
} else {
event->retcode = AskFilename(GetBochsWindow(), (bx_param_filename_c *)sparam, NULL);
}
return event;
} else {
event->retcode = AskString(sparam);
return event;
}
} else if (param->get_type() == BXT_LIST) {
param->get_param_path(pname, BX_PATHNAME_LEN);
if (!strncmp(pname, "floppy", 6)) {
event->retcode = (Bit32s) win32FloppyParamDialog(GetBochsWindow(), pname);
} else {
event->retcode = (Bit32s) win32ParamDialog(GetBochsWindow(), pname);
}
return event;
} else if (param->get_type() == BXT_PARAM_BOOL) {
UINT flag = MB_YESNO | MB_SETFOREGROUND;
if (((bx_param_bool_c *)param)->get() == 0) {
flag |= MB_DEFBUTTON2;
}
((bx_param_bool_c *)param)->set(MessageBox(GetActiveWindow(), param->get_description(), param->get_label(), flag) == IDYES);
event->retcode = 0;
return event;
}
case BX_SYNC_EVT_TICK: // called periodically by siminterface.
event->retcode = 0;
// fall into default case
default:
return event;
}
}
static int win32_ci_callback(void *userdata, ci_command_t command)
{
switch (command)
{
case CI_START:
if (SIM->get_param_enum(BXPN_BOCHS_START)->get() == BX_QUICK_START) {
SIM->begin_simulation(bx_startup_flags.argc, bx_startup_flags.argv);
// we don't expect it to return, but if it does, quit
SIM->quit_sim(1);
} else {
if (MainMenuDialog(GetActiveWindow(), 0) == 1) {
SIM->begin_simulation(bx_startup_flags.argc, bx_startup_flags.argv);
}
SIM->quit_sim(1);
}
break;
case CI_RUNTIME_CONFIG:
if (!bx_gui->has_gui_console()) {
if (MainMenuDialog(GetBochsWindow(), 1) < 0) {
bx_user_quit = 1;
#if !BX_DEBUGGER
bx_atexit();
SIM->quit_sim(1);
#else
bx_dbg_exit(1);
#endif
return -1;
}
}
break;
case CI_SHUTDOWN:
break;
}
return 0;
}
#endif // BX_USE_WIN32CONFIG