flag panic() and terminate() as "no return"
Mark panic() as never returning so that code analysis might be able to do a smarter job. It required splitting done() into two routines since the first part really can return (but not if PANICKED was the reason it got called). done() is now much shorter and ends with a call to new really_done(), and panic() skips done()'s might-return part by calling really_done() directly. Noticed in passing: the "report error to <list of SYSCF WIZARDS>" code calls a routine which uses alloc(), which won't work very well if the reason for panic was because malloc() ran out of memory.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.6 extern.h $NHDT-Date: 1447653422 2015/11/16 05:57:02 $ $NHDT-Branch: master $:$NHDT-Revision: 1.517 $ */
|
/* NetHack 3.6 extern.h $NHDT-Date: 1448210010 2015/11/22 16:33:30 $ $NHDT-Branch: master $:$NHDT-Revision: 1.519 $ */
|
||||||
/* Copyright (c) Steve Creps, 1988. */
|
/* Copyright (c) Steve Creps, 1988. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -636,12 +636,12 @@ E void FDECL(done_intr, (int));
|
|||||||
#endif
|
#endif
|
||||||
E void FDECL(done_in_by, (struct monst *, int));
|
E void FDECL(done_in_by, (struct monst *, int));
|
||||||
#endif /* !MAKEDEFS_C && !LEV_LEX_C */
|
#endif /* !MAKEDEFS_C && !LEV_LEX_C */
|
||||||
E void VDECL(panic, (const char *, ...)) PRINTF_F(1, 2);
|
E void VDECL(panic, (const char *, ...)) PRINTF_F(1, 2) NORETURN;
|
||||||
#if !defined(MAKEDEFS_C) && !defined(LEV_LEX_C)
|
#if !defined(MAKEDEFS_C) && !defined(LEV_LEX_C)
|
||||||
E void FDECL(done, (int));
|
E void FDECL(done, (int));
|
||||||
E void FDECL(container_contents,
|
E void FDECL(container_contents, (struct obj *, BOOLEAN_P,
|
||||||
(struct obj *, BOOLEAN_P, BOOLEAN_P, BOOLEAN_P));
|
BOOLEAN_P, BOOLEAN_P));
|
||||||
E void FDECL(terminate, (int));
|
E void FDECL(terminate, (int)) NORETURN;
|
||||||
E int NDECL(dovanquished);
|
E int NDECL(dovanquished);
|
||||||
E int NDECL(num_genocides);
|
E int NDECL(num_genocides);
|
||||||
E void FDECL(delayed_killer, (int, int, const char *));
|
E void FDECL(delayed_killer, (int, int, const char *));
|
||||||
@@ -2526,8 +2526,8 @@ E boolean NDECL(authorize_wizard_mode);
|
|||||||
|
|
||||||
/* ### vmsmisc.c ### */
|
/* ### vmsmisc.c ### */
|
||||||
|
|
||||||
E void NDECL(vms_abort);
|
E void NDECL(vms_abort) NORETURN;
|
||||||
E void FDECL(vms_exit, (int));
|
E void FDECL(vms_exit, (int)) NORETURN;
|
||||||
#ifdef PANICTRACE
|
#ifdef PANICTRACE
|
||||||
E void FDECL(vms_traceback, (int));
|
E void FDECL(vms_traceback, (int));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.6 tradstdc.h $NHDT-Date: 1447755973 2015/11/17 10:26:13 $ $NHDT-Branch: master $:$NHDT-Revision: 1.26 $ */
|
/* NetHack 3.6 tradstdc.h $NHDT-Date: 1448210011 2015/11/22 16:33:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.27 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -385,6 +385,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
|
|||||||
#endif
|
#endif
|
||||||
#if __GNUC__ >= 3
|
#if __GNUC__ >= 3
|
||||||
#define UNUSED __attribute__((unused))
|
#define UNUSED __attribute__((unused))
|
||||||
|
#define NORETURN __attribute__((noreturn))
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -394,5 +395,8 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
|
|||||||
#ifndef UNUSED
|
#ifndef UNUSED
|
||||||
#define UNUSED
|
#define UNUSED
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef NORETURN
|
||||||
|
#define NORETURN
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* TRADSTDC_H */
|
#endif /* TRADSTDC_H */
|
||||||
|
|||||||
83
src/end.c
83
src/end.c
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.6 end.c $NHDT-Date: 1448094339 2015/11/21 08:25:39 $ $NHDT-Branch: master $:$NHDT-Revision: 1.105 $ */
|
/* NetHack 3.6 end.c $NHDT-Date: 1448210011 2015/11/22 16:33:31 $ $NHDT-Branch: master $:$NHDT-Revision: 1.107 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ STATIC_DCL void FDECL(disclose, (int, BOOLEAN_P));
|
|||||||
STATIC_DCL void FDECL(get_valuables, (struct obj *));
|
STATIC_DCL void FDECL(get_valuables, (struct obj *));
|
||||||
STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *, int));
|
STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *, int));
|
||||||
STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
|
STATIC_DCL void FDECL(artifact_score, (struct obj *, BOOLEAN_P, winid));
|
||||||
|
STATIC_DCL void FDECL(really_done, (int)) NORETURN;
|
||||||
STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
|
STATIC_DCL boolean FDECL(odds_and_ends, (struct obj *, int));
|
||||||
STATIC_DCL void FDECL(savelife, (int));
|
STATIC_DCL void FDECL(savelife, (int));
|
||||||
STATIC_DCL void FDECL(list_vanquished, (CHAR_P, BOOLEAN_P));
|
STATIC_DCL void FDECL(list_vanquished, (CHAR_P, BOOLEAN_P));
|
||||||
@@ -535,23 +536,25 @@ VA_DECL(const char *, str)
|
|||||||
raw_print("\nError save file being written.\n");
|
raw_print("\nError save file being written.\n");
|
||||||
#else
|
#else
|
||||||
if (!wizard) {
|
if (!wizard) {
|
||||||
|
const char *maybe_rebuild = !program_state.something_worth_saving
|
||||||
|
? "."
|
||||||
|
: " and it may be possible to rebuild.";
|
||||||
|
char *tmp = 0;
|
||||||
|
|
||||||
if (sysopt.support)
|
if (sysopt.support)
|
||||||
raw_printf("To report this error, %s%s", sysopt.support,
|
raw_printf("To report this error, %s%s", sysopt.support,
|
||||||
!program_state.something_worth_saving
|
maybe_rebuild);
|
||||||
? "."
|
else if (sysopt.wizards && strcmp(sysopt.wizards, "*") != 0
|
||||||
: " and it may be possible to rebuild.");
|
/* this is risky; panic might be due to malloc failure */
|
||||||
else if (sysopt.wizards) {
|
&& (tmp = build_english_list(sysopt.wizards)) != 0)
|
||||||
char *tmp = build_english_list(sysopt.wizards);
|
|
||||||
raw_printf("To report this error, contact %s%s", tmp,
|
raw_printf("To report this error, contact %s%s", tmp,
|
||||||
!program_state.something_worth_saving
|
maybe_rebuild);
|
||||||
? "."
|
else
|
||||||
: " and it may be possible to rebuild.");
|
|
||||||
free(tmp);
|
|
||||||
} else
|
|
||||||
raw_printf("Report error to \"%s\"%s", WIZARD_NAME,
|
raw_printf("Report error to \"%s\"%s", WIZARD_NAME,
|
||||||
!program_state.something_worth_saving
|
maybe_rebuild);
|
||||||
? "."
|
|
||||||
: " and it may be possible to rebuild.");
|
if (tmp)
|
||||||
|
free((genericptr_t) tmp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* XXX can we move this above the prints? Then we'd be able to
|
/* XXX can we move this above the prints? Then we'd be able to
|
||||||
@@ -568,6 +571,7 @@ VA_DECL(const char *, str)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
|
|
||||||
Vsprintf(buf, str, VA_ARGS);
|
Vsprintf(buf, str, VA_ARGS);
|
||||||
raw_print(buf);
|
raw_print(buf);
|
||||||
paniclog("panic", buf);
|
paniclog("panic", buf);
|
||||||
@@ -580,7 +584,7 @@ VA_DECL(const char *, str)
|
|||||||
NH_abort(); /* generate core dump */
|
NH_abort(); /* generate core dump */
|
||||||
#endif
|
#endif
|
||||||
VA_END();
|
VA_END();
|
||||||
done(PANICKED);
|
really_done(PANICKED);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC_OVL boolean
|
STATIC_OVL boolean
|
||||||
@@ -862,15 +866,6 @@ void
|
|||||||
done(how)
|
done(how)
|
||||||
int how;
|
int how;
|
||||||
{
|
{
|
||||||
boolean taken;
|
|
||||||
char pbuf[BUFSZ];
|
|
||||||
winid endwin = WIN_ERR;
|
|
||||||
boolean bones_ok, have_windows = iflags.window_inited;
|
|
||||||
struct obj *corpse = (struct obj *) 0;
|
|
||||||
time_t endtime;
|
|
||||||
long umoney;
|
|
||||||
long tmp;
|
|
||||||
|
|
||||||
if (how == TRICKED) {
|
if (how == TRICKED) {
|
||||||
if (killer.name[0]) {
|
if (killer.name[0]) {
|
||||||
paniclog("trickery", killer.name);
|
paniclog("trickery", killer.name);
|
||||||
@@ -882,8 +877,6 @@ int how;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pbuf: holds Sprintf'd output for raw_print and putstr
|
|
||||||
*/
|
|
||||||
if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED))
|
if (how == ASCENDED || (!killer.name[0] && how == GENOCIDED))
|
||||||
killer.format = NO_KILLER_PREFIX;
|
killer.format = NO_KILLER_PREFIX;
|
||||||
/* Avoid killed by "a" burning or "a" starvation */
|
/* Avoid killed by "a" burning or "a" starvation */
|
||||||
@@ -907,34 +900,48 @@ int how;
|
|||||||
|
|
||||||
(void) adjattrib(A_CON, -1, TRUE);
|
(void) adjattrib(A_CON, -1, TRUE);
|
||||||
savelife(how);
|
savelife(how);
|
||||||
if (how == GENOCIDED)
|
if (how == GENOCIDED) {
|
||||||
pline("Unfortunately you are still genocided...");
|
pline("Unfortunately you are still genocided...");
|
||||||
else {
|
} else {
|
||||||
killer.name[0] = 0;
|
killer.name[0] = 0;
|
||||||
killer.format = 0;
|
killer.format = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((wizard || discover) && (how <= GENOCIDED)) {
|
if ((wizard || discover) && (how <= GENOCIDED) &&
|
||||||
if (paranoid_query(ParanoidDie, "Die?"))
|
!paranoid_query(ParanoidDie, "Die?")) {
|
||||||
goto die;
|
|
||||||
pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die");
|
pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die");
|
||||||
savelife(how);
|
savelife(how);
|
||||||
killer.name[0] = 0;
|
killer.name[0] = 0;
|
||||||
killer.format = 0;
|
killer.format = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
really_done(how);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* separated from done() in order to specify the __noreturn__ attribute */
|
||||||
* The game is now over...
|
STATIC_OVL void
|
||||||
*/
|
really_done(how)
|
||||||
|
int how;
|
||||||
|
{
|
||||||
|
boolean taken;
|
||||||
|
char pbuf[BUFSZ];
|
||||||
|
winid endwin = WIN_ERR;
|
||||||
|
boolean bones_ok, have_windows = iflags.window_inited;
|
||||||
|
struct obj *corpse = (struct obj *) 0;
|
||||||
|
time_t endtime;
|
||||||
|
long umoney;
|
||||||
|
long tmp;
|
||||||
|
|
||||||
die:
|
/*
|
||||||
|
* The game is now over...
|
||||||
|
*/
|
||||||
program_state.gameover = 1;
|
program_state.gameover = 1;
|
||||||
/* in case of a subsequent panic(), there's no point trying to save */
|
/* in case of a subsequent panic(), there's no point trying to save */
|
||||||
program_state.something_worth_saving = 0;
|
program_state.something_worth_saving = 0;
|
||||||
/* render vision subsystem inoperative */
|
/* render vision subsystem inoperative */
|
||||||
iflags.vision_inited = 0;
|
iflags.vision_inited = 0;
|
||||||
|
|
||||||
/* might have been killed while using a disposable item, so make sure
|
/* might have been killed while using a disposable item, so make sure
|
||||||
it's gone prior to inventory disclosure and creation of bones data */
|
it's gone prior to inventory disclosure and creation of bones data */
|
||||||
inven_inuse(TRUE);
|
inven_inuse(TRUE);
|
||||||
@@ -1039,6 +1046,7 @@ die:
|
|||||||
formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how);
|
formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how);
|
||||||
make_grave(u.ux, u.uy, pbuf);
|
make_grave(u.ux, u.uy, pbuf);
|
||||||
}
|
}
|
||||||
|
pbuf[0] = '\0'; /* clear grave text; also lint suppression */
|
||||||
|
|
||||||
/* calculate score, before creating bones [container gold] */
|
/* calculate score, before creating bones [container gold] */
|
||||||
{
|
{
|
||||||
@@ -1388,6 +1396,11 @@ int status;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VMS
|
#ifdef VMS
|
||||||
|
/*
|
||||||
|
* This is liable to draw a warning if compiled with gcc, but it's
|
||||||
|
* more important to flag panic() -> really_done() -> terminate()
|
||||||
|
* as __noreturn__ then to avoid the warning.
|
||||||
|
*/
|
||||||
/* don't call exit() if already executing within an exit handler;
|
/* don't call exit() if already executing within an exit handler;
|
||||||
that would cancel any other pending user-mode handlers */
|
that would cancel any other pending user-mode handlers */
|
||||||
if (program_state.exiting)
|
if (program_state.exiting)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* NetHack 3.6 panic.c $NHDT-Date: 1432512785 2015/05/25 00:13:05 $ $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
|
/* NetHack 3.6 panic.c $NHDT-Date: 1448210012 2015/11/22 16:33:32 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This code was adapted from the code in end.c to run in a standalone
|
* This code was adapted from the code in end.c to run in a standalone
|
||||||
* mode for the makedefs / drg code.
|
* mode for the makedefs / drg code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NEED_VARARGS
|
#define NEED_VARARGS
|
||||||
@@ -43,7 +43,6 @@ VA_DECL(char *, str)
|
|||||||
#endif
|
#endif
|
||||||
VA_END();
|
VA_END();
|
||||||
exit(EXIT_FAILURE); /* redundant */
|
exit(EXIT_FAILURE); /* redundant */
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ALLOCA_HACK
|
#ifdef ALLOCA_HACK
|
||||||
|
|||||||
Reference in New Issue
Block a user