From 266b5e3891a637dda5a67abefe2fe6484d2b8bad Mon Sep 17 00:00:00 2001 From: Bart House Date: Sat, 15 Dec 2018 14:49:59 -0800 Subject: [PATCH 1/5] Small improvements to fuzzer for NetHackW. Can toggle fuzzer on/off using "Pause" key if attached to debugger. Extended command selected randomly. --- include/func_tab.h | 1 + src/cmd.c | 2 ++ win/win32/mhdlg.c | 9 ++++++ win/win32/mhmain.c | 19 +++++++++--- win/win32/mhmenu.c | 43 +++++++++++++++++++------ win/win32/mhtext.c | 45 ++++++++++++++++----------- win/win32/mswproc.c | 76 +++++++++++++++++++++++---------------------- 7 files changed, 125 insertions(+), 70 deletions(-) diff --git a/include/func_tab.h b/include/func_tab.h index 79daef1de..9747253e1 100644 --- a/include/func_tab.h +++ b/include/func_tab.h @@ -22,5 +22,6 @@ struct ext_func_tab { }; extern struct ext_func_tab extcmdlist[]; +extern int extcmdlist_length; #endif /* FUNC_TAB_H */ diff --git a/src/cmd.c b/src/cmd.c index 2049aec5a..1c66ec439 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -3406,6 +3406,8 @@ struct ext_func_tab extcmdlist[] = { { '\0', (char *) 0, (char *) 0, donull, 0, (char *) 0 } /* sentinel */ }; +int extcmdlist_length = SIZE(extcmdlist) - 1; + const char * key2extcmddesc(key) uchar key; diff --git a/win/win32/mhdlg.c b/win/win32/mhdlg.c index bb92d5318..34d5ce299 100644 --- a/win/win32/mhdlg.c +++ b/win/win32/mhdlg.c @@ -167,6 +167,15 @@ INT_PTR CALLBACK ExtCmdDlgProc(HWND, UINT, WPARAM, LPARAM); int mswin_ext_cmd_window(int *selection) { + if (iflags.debug_fuzzer) { + *selection = rn2(extcmdlist_length + 1) - 1; + + if (*selection != -1) + return IDOK; + else + return IDCANCEL; + } + INT_PTR ret; struct extcmd_data data; diff --git a/win/win32/mhmain.c b/win/win32/mhmain.c index a8742b03f..e775f12a7 100644 --- a/win/win32/mhmain.c +++ b/win/win32/mhmain.c @@ -195,7 +195,7 @@ static const char scanmap[] = { LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - PNHMainWindow data; + PNHMainWindow data = (PNHMainWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); switch (message) { case WM_CREATE: @@ -225,7 +225,6 @@ MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_KEYDOWN: { - data = (PNHMainWindow) GetWindowLongPtr(hWnd, GWLP_USERDATA); /* translate arrow keys into nethack commands */ switch (wParam) { @@ -332,6 +331,15 @@ MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) NHEVENT_KBD(KEYTABLE(KEY_PLUS)); return 0; +#if defined(DEBUG) && defined(_MSC_VER) + case VK_PAUSE: + if (IsDebuggerPresent()) { + iflags.debug_fuzzer = !iflags.debug_fuzzer; + return 0; + } + break; +#endif + case VK_CLEAR: /* This is the '5' key */ NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING)); return 0; @@ -530,9 +538,10 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) child = GetNHApp()->windowlist[msg_param->wid].win; } break; - case MSNH_MSG_RANDOM_INPUT: - nhassert(0); // unexpected - break; + case MSNH_MSG_RANDOM_INPUT: { + nhassert(iflags.debug_fuzzer); + NHEVENT_KBD(randomkey()); + } break; } } diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c index 34fe28a1a..62e78480f 100644 --- a/win/win32/mhmenu.c +++ b/win/win32/mhmenu.c @@ -689,14 +689,8 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) } break; case MSNH_MSG_RANDOM_INPUT: { - char c = randomkey(); - if (c == '\n') - PostMessage(hWnd, WM_COMMAND, MAKELONG(IDOK, 0), 0); - else if (c == '\033') - PostMessage(hWnd, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0); - else - PostMessage(GetDlgItem(hWnd, IDC_TEXT_CONTROL), WM_CHAR, c, 0); - + PostMessage(GetMenuControl(hWnd), + WM_MSNH_COMMAND, MSNH_MSG_RANDOM_INPUT, 0); } break; } @@ -1601,6 +1595,7 @@ reset_menu_count(HWND hwndList, PNHMenuWindow data) LRESULT CALLBACK NHMenuListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + HWND hWndParent = GetParent(hWnd); BOOL bUpdateFocusItem; /* we will redraw focused item whenever horizontal scrolling occurs @@ -1632,6 +1627,20 @@ NHMenuListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetFocus(GetNHApp()->hMainWnd); } return FALSE; + + case WM_MSNH_COMMAND: + if (wParam == MSNH_MSG_RANDOM_INPUT) { + char c = randomkey(); + if (c == '\n') + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0); + else if (c == '\033') + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0); + else + PostMessage(hWnd, WM_CHAR, c, 0); + return 0; + } + break; + } /* update focused item */ @@ -1659,6 +1668,7 @@ NHMenuListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK NHMenuTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + HWND hWndParent = GetParent(hWnd); HDC hDC; RECT rc; @@ -1686,8 +1696,7 @@ NHMenuTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) && (si.nPos + (int) si.nPage) <= (si.nMax - si.nMin)) SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0); else - PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0), - 0); + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0); return 0; } case VK_NEXT: @@ -1726,6 +1735,20 @@ NHMenuTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_SETFOCUS: HideCaret(hWnd); return 0; + + case WM_MSNH_COMMAND: + if (wParam == MSNH_MSG_RANDOM_INPUT) { + char c = randomkey(); + if (c == '\n') + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0); + else if (c == '\033') + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0); + else + PostMessage(hWnd, WM_CHAR, c, 0); + return 0; + } + break; + } if (editControlWndProc) diff --git a/win/win32/mhtext.c b/win/win32/mhtext.c index 14092d52f..0ff816f8a 100644 --- a/win/win32/mhtext.c +++ b/win/win32/mhtext.c @@ -27,7 +27,6 @@ HWND mswin_init_text_window() { HWND ret; - PNHTextWindow data; RECT rt; /* get window position */ @@ -52,13 +51,6 @@ mswin_init_text_window() /* Set window caption */ SetWindowText(ret, "Text"); - /* create and set window data */ - data = (PNHTextWindow) malloc(sizeof(NHTextWindow)); - if (!data) - panic("out of memory"); - ZeroMemory(data, sizeof(NHTextWindow)); - SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR) data); - mswin_apply_window_style(ret); return ret; @@ -88,6 +80,12 @@ NHTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: { + data = (PNHTextWindow)malloc(sizeof(NHTextWindow)); + if (!data) + panic("out of memory"); + ZeroMemory(data, sizeof(NHTextWindow)); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)data); + HWND control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); HDC hdc = GetDC(control); cached_font * font = mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE); @@ -177,7 +175,10 @@ NHTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) 0); } break; + } + + return FALSE; } @@ -214,14 +215,8 @@ onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) } case MSNH_MSG_RANDOM_INPUT: { - char c = randomkey(); - if (c == '\n') - PostMessage(hWnd, WM_COMMAND, MAKELONG(IDOK, 0), 0); - else if (c == '\033') - PostMessage(hWnd, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0); - else - PostMessage(GetDlgItem(hWnd, IDC_TEXT_CONTROL), WM_CHAR, c, 0); - + PostMessage(GetDlgItem(hWnd, IDC_TEXT_CONTROL), + WM_MSNH_COMMAND, MSNH_MSG_RANDOM_INPUT, 0); } break; @@ -278,6 +273,7 @@ LayoutText(HWND hWnd) LRESULT CALLBACK NHEditHookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + HWND hWndParent = GetParent(hWnd); HDC hDC; RECT rc; @@ -305,8 +301,7 @@ NHEditHookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) && (si.nPos + (int) si.nPage) <= (si.nMax - si.nMin)) SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0); else - PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0), - 0); + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0); return 0; } case VK_NEXT: @@ -346,6 +341,20 @@ NHEditHookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_SETFOCUS: HideCaret(hWnd); return 0; + + case WM_MSNH_COMMAND: + if (wParam == MSNH_MSG_RANDOM_INPUT) { + char c = randomkey(); + if (c == '\n') + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDOK, 0), 0); + else if (c == '\033') + PostMessage(hWndParent, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0); + else + PostMessage(hWnd, WM_CHAR, c, 0); + return 0; + } + break; + } if (editControlWndProc) diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c index 0a6cde13d..8393ea3e0 100644 --- a/win/win32/mswproc.c +++ b/win/win32/mswproc.c @@ -2102,24 +2102,25 @@ mswin_main_loop() { MSG msg; - while (!mswin_have_input()) { - if (!iflags.debug_fuzzer || PeekMessage(&msg, NULL, 0, 0, FALSE)) { - if(GetMessage(&msg, NULL, 0, 0) != 0) { - if (GetNHApp()->regNetHackMode - || !TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, - &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } else { - /* WM_QUIT */ - break; - } - } else { - nhassert(iflags.debug_fuzzer); - NHEVENT_KBD(randomkey()); - } - } + while (!mswin_have_input()) { + if (!iflags.debug_fuzzer || PeekMessage(&msg, NULL, 0, 0, FALSE)) { + if(GetMessage(&msg, NULL, 0, 0) != 0) { + if (GetNHApp()->regNetHackMode + || !TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, + &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } else { + /* WM_QUIT */ + break; + } + } else { + nhassert(iflags.debug_fuzzer); + PostMessage(GetNHApp()->hMainWnd, WM_MSNH_COMMAND, + MSNH_MSG_RANDOM_INPUT, 0); + } + } } /* clean up and quit */ @@ -2232,25 +2233,26 @@ mswin_popup_display(HWND hWnd, int *done_indicator) SetFocus(hWnd); /* go into message loop */ - while (IsWindow(hWnd) && (done_indicator == NULL || !*done_indicator)) { - if (!iflags.debug_fuzzer || PeekMessage(&msg, NULL, 0, 0, FALSE)) { - if(GetMessage(&msg, NULL, 0, 0) != 0) { - if (!IsDialogMessage(hWnd, &msg)) { - if (!TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, - &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - } else { - /* WM_QUIT */ - break; - } - } else { - nhassert(iflags.debug_fuzzer); - PostMessage(hWnd, WM_MSNH_COMMAND, MSNH_MSG_RANDOM_INPUT, 0); - } - } + while (IsWindow(hWnd) && (done_indicator == NULL || !*done_indicator)) { + if (!iflags.debug_fuzzer || PeekMessage(&msg, NULL, 0, 0, FALSE)) { + if(GetMessage(&msg, NULL, 0, 0) != 0) { + if (msg.message == WM_MSNH_COMMAND || + !IsDialogMessage(hWnd, &msg)) { + if (!TranslateAccelerator(msg.hwnd, + GetNHApp()->hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + } else { + /* WM_QUIT */ + break; + } + } else { + nhassert(iflags.debug_fuzzer); + PostMessage(hWnd, WM_MSNH_COMMAND, MSNH_MSG_RANDOM_INPUT, 0); + } + } } void From 27a515a4cc4a413d31cc6fcafff05198e1720d1b Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 15 Dec 2018 15:46:49 -0800 Subject: [PATCH 2/5] get_hilite_color() Stop pretending that long and int are the same size when picking status highlight rule for gold or time or experience-points. Also, K&R compilation might lack , so let XXXconf.h define the necessary macro(s) (currently just LONG_MAX) so that it can be skipped. --- doc/fixes36.2 | 2 + src/botl.c | 137 ++++++++++++++++++++++++++++++++------------------ src/end.c | 4 +- src/exper.c | 4 +- 4 files changed, 97 insertions(+), 50 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 6be566c8d..adf63df74 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -297,6 +297,8 @@ fix bit-use collision between WC2_TERM_SIZE and WC2_RESET_STATUS in include/winprocs.h following a recent merge fix foxen pluralization again after underflow remedy reintroduced the problem fix "placing monster over another?" warning for vault guards +status highlighting classified gold, time, and experience-points as data type + 'long' but when selecting hilite rule to use treated them as 'int' tty: turn off an optimization that is the suspected cause of Windows reported partial status lines following level changes tty: ensure that current status fields are always copied to prior status diff --git a/src/botl.c b/src/botl.c index db96c160b..4fea3b64b 100644 --- a/src/botl.c +++ b/src/botl.c @@ -1,10 +1,12 @@ -/* NetHack 3.6 botl.c $NHDT-Date: 1544229439 2018/12/08 00:37:19 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.129 $ */ +/* NetHack 3.6 botl.c $NHDT-Date: 1544917592 2018/12/15 23:46:32 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.131 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +#ifndef LONG_MAX #include +#endif extern const char *hu_stat[]; /* defined in eat.c */ @@ -1394,13 +1396,10 @@ int newcolor; /* * get_hilite_color * - * Figures out, based on the value and the - * direction it is moving, the color that the field - * should be displayed in. + * Figures out, based on the value and the direction it is moving, + * the color that the field should be displayed in. * - * - * Provide get_hilite_color() with the following - * to work with: + * Provide get_hilite_color() with the following to work with: * actual value vp * useful for BL_TH_VAL_ABSOLUTE * indicator of down, up, or the same (-1, 1, 0) chg @@ -1416,7 +1415,6 @@ int newcolor; * color = 0x00FF * attrib= 0xFF00 */ - STATIC_OVL void get_hilite_color(idx, fldidx, vp, chg, pc, colorptr) int idx, fldidx, chg, pc; @@ -1432,14 +1430,21 @@ int *colorptr; return; if (blstats[idx][fldidx].thresholds) { + int dt; /* there are hilites set here */ int max_pc = -1, min_pc = 101; - int max_val = -LARGEST_INT, min_val = LARGEST_INT; + /* LARGEST_INT isn't INT_MAX; it fits within 16 bits, but that + value is big enough to handle all 'int' status fields */ + int max_ival = -LARGEST_INT, min_ival = LARGEST_INT; + /* LONG_MAX comes from which might not be available for + ancient configurations; we don't need LONG_MIN */ + long max_lval = -LONG_MAX, min_lval = LONG_MAX; boolean exactmatch = FALSE, updown = FALSE, changed = FALSE, perc_or_abs = FALSE; /* min_/max_ are used to track best fit */ for (hl = blstats[idx][fldidx].thresholds; hl; hl = hl->next) { + dt = initblstats[fldidx].anytype; /* only needed for 'absolute' */ /* if we've already matched a temporary highlight, it takes precedence over all persistent ones; we still process updown rules to get the last one which qualifies */ @@ -1451,7 +1456,7 @@ int *colorptr; continue; switch (hl->behavior) { - case BL_TH_VAL_PERCENTAGE: + case BL_TH_VAL_PERCENTAGE: /* percent values are always ANY_INT */ if (hl->rel == EQ_VALUE && pc == hl->value.a_int) { merge_bestcolor(&bestcolor, hl->coloridx); min_pc = max_pc = hl->value.a_int; @@ -1484,7 +1489,7 @@ int *colorptr; perc_or_abs = TRUE; } break; - case BL_TH_UPDOWN: + case BL_TH_UPDOWN: /* uses 'chg' (set by caller), not 'dt' */ /* specific 'up' or 'down' takes precedence over general 'changed' regardless of their order in the rule set */ if (chg < 0 && hl->rel == LT_VALUE) { @@ -1498,45 +1503,81 @@ int *colorptr; changed = TRUE; } break; - case BL_TH_VAL_ABSOLUTE: - /* - * TODO: - * This covers data type ANY_INT. We need to handle ANY_LONG - * separately using a_long and new min_lval, max_lval. - */ - if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) { - merge_bestcolor(&bestcolor, hl->coloridx); - min_val = max_val = hl->value.a_int; - exactmatch = perc_or_abs = TRUE; - } else if (exactmatch) { - ; /* already found best fit, skip lt,ge,&c */ - } else if (hl->rel == LT_VALUE - && (value->a_int < hl->value.a_int) - && (hl->value.a_int <= min_val)) { - merge_bestcolor(&bestcolor, hl->coloridx); - min_val = hl->value.a_int; - perc_or_abs = TRUE; - } else if (hl->rel == LE_VALUE - && (value->a_int <= hl->value.a_int) - && (hl->value.a_int <= min_val)) { - merge_bestcolor(&bestcolor, hl->coloridx); - min_val = hl->value.a_int; - perc_or_abs = TRUE; - } else if (hl->rel == GT_VALUE - && (value->a_int > hl->value.a_int) - && (hl->value.a_int >= max_val)) { - merge_bestcolor(&bestcolor, hl->coloridx); - max_val = hl->value.a_int; - perc_or_abs = TRUE; - } else if (hl->rel == GE_VALUE - && (value->a_int >= hl->value.a_int) - && (hl->value.a_int >= max_val)) { - merge_bestcolor(&bestcolor, hl->coloridx); - max_val = hl->value.a_int; - perc_or_abs = TRUE; + case BL_TH_VAL_ABSOLUTE: /* either ANY_INT or ANY_LONG */ + /* + * The int and long variations here are identical aside from + * union field and min_/max_ variable names. If you change + * one, be sure to make a corresponding change in the other. + */ + if (dt == ANY_INT) { + if (hl->rel == EQ_VALUE + && hl->value.a_int == value->a_int) { + merge_bestcolor(&bestcolor, hl->coloridx); + min_ival = max_ival = hl->value.a_int; + exactmatch = perc_or_abs = TRUE; + } else if (exactmatch) { + ; /* already found best fit, skip lt,ge,&c */ + } else if (hl->rel == LT_VALUE + && (value->a_int < hl->value.a_int) + && (hl->value.a_int <= min_ival)) { + merge_bestcolor(&bestcolor, hl->coloridx); + min_ival = hl->value.a_int; + perc_or_abs = TRUE; + } else if (hl->rel == LE_VALUE + && (value->a_int <= hl->value.a_int) + && (hl->value.a_int <= min_ival)) { + merge_bestcolor(&bestcolor, hl->coloridx); + min_ival = hl->value.a_int; + perc_or_abs = TRUE; + } else if (hl->rel == GT_VALUE + && (value->a_int > hl->value.a_int) + && (hl->value.a_int >= max_ival)) { + merge_bestcolor(&bestcolor, hl->coloridx); + max_ival = hl->value.a_int; + perc_or_abs = TRUE; + } else if (hl->rel == GE_VALUE + && (value->a_int >= hl->value.a_int) + && (hl->value.a_int >= max_ival)) { + merge_bestcolor(&bestcolor, hl->coloridx); + max_ival = hl->value.a_int; + perc_or_abs = TRUE; + } + } else { /* ANY_LONG */ + if (hl->rel == EQ_VALUE + && hl->value.a_long == value->a_long) { + merge_bestcolor(&bestcolor, hl->coloridx); + min_lval = max_lval = hl->value.a_long; + exactmatch = perc_or_abs = TRUE; + } else if (exactmatch) { + ; /* already found best fit, skip lt,ge,&c */ + } else if (hl->rel == LT_VALUE + && (value->a_long < hl->value.a_long) + && (hl->value.a_long <= min_lval)) { + merge_bestcolor(&bestcolor, hl->coloridx); + min_lval = hl->value.a_long; + perc_or_abs = TRUE; + } else if (hl->rel == LE_VALUE + && (value->a_long <= hl->value.a_long) + && (hl->value.a_long <= min_lval)) { + merge_bestcolor(&bestcolor, hl->coloridx); + min_lval = hl->value.a_long; + perc_or_abs = TRUE; + } else if (hl->rel == GT_VALUE + && (value->a_long > hl->value.a_long) + && (hl->value.a_long >= max_lval)) { + merge_bestcolor(&bestcolor, hl->coloridx); + max_lval = hl->value.a_long; + perc_or_abs = TRUE; + } else if (hl->rel == GE_VALUE + && (value->a_long >= hl->value.a_long) + && (hl->value.a_long >= max_lval)) { + merge_bestcolor(&bestcolor, hl->coloridx); + max_lval = hl->value.a_long; + perc_or_abs = TRUE; + } } break; - case BL_TH_TEXTMATCH: + case BL_TH_TEXTMATCH: /* ANY_STR */ txtstr = blstats[idx][fldidx].val; if (fldidx == BL_TITLE) /* " the ", skip past " the " */ diff --git a/src/end.c b/src/end.c index e90745cdb..353469a5d 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 end.c $NHDT-Date: 1544666123 2018/12/13 01:55:23 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.157 $ */ +/* NetHack 3.6 end.c $NHDT-Date: 1544917598 2018/12/15 23:46:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.158 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -11,7 +11,9 @@ #include #endif #include +#ifndef LONG_MAX #include +#endif #include "dlb.h" /* add b to long a, convert wraparound to max value */ diff --git a/src/exper.c b/src/exper.c index 5bca20e46..bb13aa901 100644 --- a/src/exper.c +++ b/src/exper.c @@ -1,10 +1,12 @@ -/* NetHack 3.6 exper.c $NHDT-Date: 1541145516 2018/11/02 07:58:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.30 $ */ +/* NetHack 3.6 exper.c $NHDT-Date: 1544917599 2018/12/15 23:46:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.31 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2007. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +#ifndef LONG_MAX #include +#endif STATIC_DCL int FDECL(enermod, (int)); From 594cb5f226c3de7d8f5d39fc8edc93bc2acf92ca Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 15 Dec 2018 16:24:59 -0800 Subject: [PATCH 3/5] tty SIGHUP We still don't know whether this will be of any help against disconnected processes that hog the CPU instead of exiting, but I don't think it imposes significant overhead on ones which aren't disconnected. Install it before it suffers from more bit rot. --- doc/fixes36.2 | 2 ++ win/tty/wintty.c | 69 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index adf63df74..1d8176f7e 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -354,6 +354,8 @@ tty: significant optimizations for performance and per field rendering tty: use WC2_FLUSH_STATUS to buffer changes until BL_FLUSH is received tty: support BL_RESET in status_update to force an update to all status fields tty: stop hitpointbar from jumping to 100% health at zero hit points +tty: try harder to prevent a disconnected terminal (SIGHUP) from running amok + and using up all available CPU time MacOSX: add curses window port MacOSX: add Xcode project to sys/unixNetHack.xcodeproj MacOSX: add Xcode supporting files README.xcode and XCode.xcconfig diff --git a/win/tty/wintty.c b/win/tty/wintty.c index f335ff03c..ca9d60c1d 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 wintty.c $NHDT-Date: 1544842261 2018/12/15 02:51:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.188 $ */ +/* NetHack 3.6 wintty.c $NHDT-Date: 1544919891 2018/12/16 00:24:51 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.189 $ */ /* Copyright (c) David Cohrs, 1991 */ /* NetHack may be freely redistributed. See license for details. */ @@ -45,6 +45,33 @@ extern short glyph2tile[]; #define AVTC_INLINE_SYNC 3 #endif +#ifdef HANGUP_HANDLING +/* + * NetHack's core switches to a dummy windowing interface when it + * detects SIGHUP, but that's no help for any interface routine which + * is already in progress at the time, and there have been reports of + * runaway disconnected processes which use up all available CPU time. + * HUPSKIP() and HUPSKIP_RETURN(x) are used to try to cut them off so + * that they return to the core instead attempting more terminal I/O. + */ +#define HUPSKIP() \ + do { \ + if (program_state.done_hup) { \ + morc = '\033'; \ + return; \ + } \ + } while (0) + /* morc=ESC - in case we bypass xwaitforspace() which sets that */ +#define HUPSKIP_RESULT(RES) \ + do { \ + if (program_state.done_hup) \ + return (RES); \ + } while (0) +#else /* !HANGUP_HANDLING */ +#define HUPSKIP() /*empty*/ +#define HUPSKIP_RESULT(RES) /*empty*/ +#endif /* ?HANGUP_HANDLING */ + extern char mapped_menu_cmds[]; /* from options.c */ /* this is only needed until tty_status_* routines are written */ @@ -208,6 +235,7 @@ void print_vt_code(i, c, d) int i, c, d; { + HUPSKIP(); if (iflags.vt_tiledata) { if (c >= 0) { if (i == AVTC_SELECT_WINDOW) { @@ -1170,8 +1198,7 @@ tty_askname() bail("Giving up after 10 tries.\n"); tty_curs(BASE_WINDOW, 1, wins[BASE_WINDOW]->cury - 1); tty_putstr(BASE_WINDOW, 0, "Enter a name for your character..."); - /* erase previous prompt (in case of ESC after partial response) - */ + /* erase previous prompt (in case of ESC after partial response) */ tty_curs(BASE_WINDOW, 1, wins[BASE_WINDOW]->cury), cl_end(); } tty_putstr(BASE_WINDOW, 0, who_are_you); @@ -1261,6 +1288,7 @@ tty_get_nh_event() STATIC_OVL void getret() { + HUPSKIP(); xputs("\n"); if (flags.standout) standoutbeg(); @@ -1516,6 +1544,7 @@ winid window; { register struct WinDesc *cw = 0; + HUPSKIP(); if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) panic(winpanicstr, window); ttyDisplay->lastwin = window; @@ -1602,6 +1631,7 @@ const char *s; /* valid responses */ const char *prompt = cw->morestr ? cw->morestr : defmorestr; int offset = (cw->type == NHW_TEXT) ? 1 : 2; + HUPSKIP(); tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + offset, (int) ttyDisplay->cury); if (flags.standout) @@ -1622,6 +1652,7 @@ tty_menu_item *item; { char ch = item->selected ? (item->count == -1L ? '+' : '#') : '-'; + HUPSKIP(); tty_curs(window, 4, lineno); term_start_attr(item->attr); (void) putchar(ch); @@ -1789,6 +1820,7 @@ struct WinDesc *cw; /* loop until finished */ while (!finished) { + HUPSKIP(); if (reset_count) { counting = FALSE; count = 0; @@ -2117,6 +2149,7 @@ struct WinDesc *cw; register char *cp; for (n = 0, i = 0; i < cw->maxrow; i++) { + HUPSKIP(); if (!cw->offx && (n + cw->offy == ttyDisplay->rows - 1)) { tty_curs(window, 1, n); cl_end(); @@ -2183,6 +2216,7 @@ boolean blocking; /* with ttys, all windows are blocking */ register struct WinDesc *cw = 0; short s_maxcol; + HUPSKIP(); if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) panic(winpanicstr, window); if (cw->flags & WIN_CANCELLED) @@ -2275,6 +2309,7 @@ winid window; { register struct WinDesc *cw = 0; + HUPSKIP(); if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) panic(winpanicstr, window); @@ -2345,6 +2380,7 @@ register int x, y; /* not xchar: perhaps xchar is unsigned and int cx = ttyDisplay->curx; int cy = ttyDisplay->cury; + HUPSKIP(); if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) panic(winpanicstr, window); ttyDisplay->lastwin = window; @@ -2359,6 +2395,7 @@ register int x, y; /* not xchar: perhaps xchar is unsigned and #ifdef DEBUG if (x < 0 || y < 0 || y >= cw->rows || x > cw->cols) { const char *s = "[unknown type]"; + switch (cw->type) { case NHW_MESSAGE: s = "[topl window]"; @@ -2442,6 +2479,7 @@ char ch; { register struct WinDesc *cw = 0; + HUPSKIP(); if (window == WIN_ERR || (cw = wins[window]) == (struct WinDesc *) 0) panic(winpanicstr, window); @@ -2511,6 +2549,7 @@ const char *str; register long j; #endif + HUPSKIP(); /* Assume there's a real problem if the window is missing -- * probably a panic message */ @@ -2780,6 +2819,7 @@ boolean preselected; /* item is marked as selected */ const char *newstr; char buf[4 + BUFSZ]; + HUPSKIP(); if (str == (const char *) 0) return; @@ -2991,6 +3031,7 @@ char let; int how; const char *mesg; { + HUPSKIP(); /* "menu" without selection; use ordinary pline, no more() */ if (how == PICK_NONE) { pline("%s", mesg); @@ -3026,12 +3067,14 @@ tty_update_inventory() void tty_mark_synch() { + HUPSKIP(); (void) fflush(stdout); } void tty_wait_synch() { + HUPSKIP(); /* we just need to make sure all windows are synch'd */ if (!ttyDisplay || ttyDisplay->rawprint) { getret(); @@ -3061,6 +3104,7 @@ register int xmin, ymax; register int y; register struct WinDesc *cw = wins[WIN_MAP]; + HUPSKIP(); #if 0 /* this optimization is not valuable enough to justify abusing core internals... */ if (u.uswallow) { /* Can be done more efficiently */ @@ -3109,6 +3153,7 @@ register int xmin, ymax; void end_glyphout() { + HUPSKIP(); #if defined(ASCIIGRAPH) && !defined(NO_TERMS) if (GFlag) { GFlag = FALSE; @@ -3130,6 +3175,7 @@ int in_ch; { register char ch = (char) in_ch; + HUPSKIP(); #if defined(ASCIIGRAPH) && !defined(NO_TERMS) if (SYMHANDLING(H_IBM) || iflags.eight_bit_tty) { /* IBM-compatible displays don't need other stuff */ @@ -3174,6 +3220,7 @@ int x, y; extern boolean restoring; int oldx = clipx, oldy = clipy; + HUPSKIP(); if (!clipping) return; if (x < clipx + 5) { @@ -3218,6 +3265,7 @@ int bkglyph UNUSED; int color; unsigned special; + HUPSKIP(); #ifdef CLIPPING if (clipping) { if (x <= clipx || y < clipy || x >= clipxmax || y >= clipymax) @@ -3288,6 +3336,7 @@ void tty_raw_print(str) const char *str; { + HUPSKIP(); if (ttyDisplay) ttyDisplay->rawprint++; print_vt_code2(AVTC_SELECT_WINDOW, NHW_BASE); @@ -3303,6 +3352,7 @@ void tty_raw_print_bold(str) const char *str; { + HUPSKIP(); if (ttyDisplay) ttyDisplay->rawprint++; print_vt_code2(AVTC_SELECT_WINDOW, NHW_BASE); @@ -3335,6 +3385,7 @@ tty_nhgetch() char nestbuf; #endif + HUPSKIP_RESULT('\033'); print_vt_code1(AVTC_INLINE_SYNC); (void) fflush(stdout); /* Note: if raw_print() and wait_synch() get called to report terminal @@ -3366,6 +3417,7 @@ tty_nhgetch() { /* hack to force output of the window select code */ int tmp = vt_tile_current_window; + vt_tile_current_window++; print_vt_code2(AVTC_SELECT_WINDOW, tmp); } @@ -3383,8 +3435,10 @@ int tty_nh_poskey(x, y, mod) int *x, *y, *mod; { -#if defined(WIN32CON) int i; + + HUPSKIP_RESULT('\033'); +#if defined(WIN32CON) (void) fflush(stdout); /* Note: if raw_print() and wait_synch() get called to report terminal * initialization problems, then wins[] and ttyDisplay might not be @@ -3398,14 +3452,14 @@ int *x, *y, *mod; i = '\033'; /* map NUL or EOF to ESC, nethack doesn't expect either */ if (ttyDisplay && ttyDisplay->toplin == 1) ttyDisplay->toplin = 2; - return i; #else /* !WIN32CON */ nhUse(x); nhUse(y); nhUse(mod); - return tty_nhgetch(); + i = tty_nhgetch(); #endif /* ?WIN32CON */ + return i; } void @@ -4182,6 +4236,7 @@ render_status(VOID_ARGS) } for (row = 0; row < 2; ++row) { + HUPSKIP(); curs(WIN_STATUS, 1, row); for (i = 0; fieldorder[row][i] != BL_FLUSH; ++i) { int idx = fieldorder[row][i]; @@ -4359,7 +4414,7 @@ render_status(VOID_ARGS) tty_putstatusfield(nullfield, " ", x++, y); } } - /* reset .redraw, .dirty, .padright now that they've been rendered */ + /* reset .redraw, .dirty, .padright now that they're rendered */ tty_status[NOW][idx].dirty = FALSE; tty_status[NOW][idx].redraw = FALSE; tty_status[NOW][idx].last_on_row = FALSE; From bebc92f6fb75cfbb4d3121604447820b8f006917 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 15 Dec 2018 19:31:07 -0500 Subject: [PATCH 4/5] more win32 gui fuzzer work --- src/cmd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cmd.c b/src/cmd.c index 1c66ec439..0cbcaba66 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 cmd.c $NHDT-Date: 1544748881 2018/12/14 00:54:41 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.319 $ */ +/* NetHack 3.6 cmd.c $NHDT-Date: 1544920233 2018/12/16 00:30:33 $ $NHDT-Branch: win-minor $:$NHDT-Revision: 1.321 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -4461,6 +4461,12 @@ int sz; buf[count] = '\0'; } +int +rnd_extcmd_idx(VOID_ARGS) +{ + return rn2(extcmdlist_length + 1) - 1; +} + int ch2spkeys(c, start, end) char c; From 902f76d1faf310f855a65c81d27c90804c433c4e Mon Sep 17 00:00:00 2001 From: nhmall Date: Sat, 15 Dec 2018 19:31:42 -0500 Subject: [PATCH 5/5] more win32 gui fuzzer work --- include/extern.h | 1 + include/func_tab.h | 1 - win/win32/mhdlg.c | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/extern.h b/include/extern.h index 34feb78e3..67a3d0d0e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -175,6 +175,7 @@ E boolean NDECL(status_hilite_menu); E char NDECL(randomkey); E void FDECL(random_response, (char *, int)); +E int NDECL(rnd_extcmd_idx); E int NDECL(doconduct); E int NDECL(domonability); E char FDECL(cmd_from_func, (int NDECL((*)))); diff --git a/include/func_tab.h b/include/func_tab.h index 9747253e1..79daef1de 100644 --- a/include/func_tab.h +++ b/include/func_tab.h @@ -22,6 +22,5 @@ struct ext_func_tab { }; extern struct ext_func_tab extcmdlist[]; -extern int extcmdlist_length; #endif /* FUNC_TAB_H */ diff --git a/win/win32/mhdlg.c b/win/win32/mhdlg.c index 34d5ce299..51134332c 100644 --- a/win/win32/mhdlg.c +++ b/win/win32/mhdlg.c @@ -168,7 +168,7 @@ int mswin_ext_cmd_window(int *selection) { if (iflags.debug_fuzzer) { - *selection = rn2(extcmdlist_length + 1) - 1; + *selection = rnd_extcmd_idx(); if (*selection != -1) return IDOK;