]> granicus.if.org Git - nethack/commitdiff
flag panic() and terminate() as "no return"
authorPatR <rankin@nethack.org>
Sun, 22 Nov 2015 16:33:42 +0000 (08:33 -0800)
committerPatR <rankin@nethack.org>
Sun, 22 Nov 2015 16:33:42 +0000 (08:33 -0800)
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.

include/extern.h
include/tradstdc.h
src/end.c
util/panic.c

index 660fa416386103e1787eb5251d5f003be62c9955..2d081587baf4abf27b3a7adc165fd84f6ba68192 100644 (file)
@@ -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.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -636,12 +636,12 @@ E void FDECL(done_intr, (int));
 #endif
 E void FDECL(done_in_by, (struct monst *, int));
 #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)
 E void FDECL(done, (int));
-E void FDECL(container_contents,
-             (struct obj *, BOOLEAN_P, BOOLEAN_P, BOOLEAN_P));
-E void FDECL(terminate, (int));
+E void FDECL(container_contents, (struct obj *, BOOLEAN_P,
+                                  BOOLEAN_P, BOOLEAN_P));
+E void FDECL(terminate, (int)) NORETURN;
 E int NDECL(dovanquished);
 E int NDECL(num_genocides);
 E void FDECL(delayed_killer, (int, int, const char *));
@@ -2526,8 +2526,8 @@ E boolean NDECL(authorize_wizard_mode);
 
 /* ### vmsmisc.c ### */
 
-E void NDECL(vms_abort);
-E void FDECL(vms_exit, (int));
+E void NDECL(vms_abort) NORETURN;
+E void FDECL(vms_exit, (int)) NORETURN;
 #ifdef PANICTRACE
 E void FDECL(vms_traceback, (int));
 #endif
index 69798241143215f8f7cea871c06e864d9f3ab90b..26ce81ad5e2903af9de1d299961edd1738f562bb 100644 (file)
@@ -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. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -385,6 +385,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
 #endif
 #if __GNUC__ >= 3
 #define UNUSED __attribute__((unused))
+#define NORETURN __attribute__((noreturn))
 #endif
 #endif
 
@@ -394,5 +395,8 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */
 #ifndef UNUSED
 #define UNUSED
 #endif
+#ifndef NORETURN
+#define NORETURN
+#endif
 
 #endif /* TRADSTDC_H */
index 324e0a4407594a2863ad3275de21fec7d05bdcf5..191e78308f64d9ac95d28a1d9fe15a588a5d6e84 100644 (file)
--- a/src/end.c
+++ b/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. */
 /* 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(sort_valuables, (struct valuable_data *, int));
 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 void FDECL(savelife, (int));
 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");
 #else
     if (!wizard) {
+        const char *maybe_rebuild = !program_state.something_worth_saving
+                                      ? "."
+                                      : " and it may be possible to rebuild.";
+        char *tmp = 0;
+
         if (sysopt.support)
             raw_printf("To report this error, %s%s", sysopt.support,
-                       !program_state.something_worth_saving
-                           ? "."
-                           : " and it may be possible to rebuild.");
-        else if (sysopt.wizards) {
-            char *tmp = build_english_list(sysopt.wizards);
+                       maybe_rebuild);
+        else if (sysopt.wizards && strcmp(sysopt.wizards, "*") != 0
+                   /* this is risky; panic might be due to malloc failure */
+                   && (tmp = build_english_list(sysopt.wizards)) != 0)
             raw_printf("To report this error, contact %s%s", tmp,
-                       !program_state.something_worth_saving
-                           ? "."
-                           : " and it may be possible to rebuild.");
-            free(tmp);
-        } else
+                       maybe_rebuild);
+        else
             raw_printf("Report error to \"%s\"%s", WIZARD_NAME,
-                       !program_state.something_worth_saving
-                           ? "."
-                           : " and it may be possible to rebuild.");
+                       maybe_rebuild);
+
+        if (tmp)
+            free((genericptr_t) tmp);
     }
 #endif
     /* XXX can we move this above the prints?  Then we'd be able to
@@ -568,6 +571,7 @@ VA_DECL(const char *, str)
 #endif
     {
         char buf[BUFSZ];
+
         Vsprintf(buf, str, VA_ARGS);
         raw_print(buf);
         paniclog("panic", buf);
@@ -580,7 +584,7 @@ VA_DECL(const char *, str)
         NH_abort(); /* generate core dump */
 #endif
     VA_END();
-    done(PANICKED);
+    really_done(PANICKED);
 }
 
 STATIC_OVL boolean
@@ -862,15 +866,6 @@ void
 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;
-
     if (how == TRICKED) {
         if (killer.name[0]) {
             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))
         killer.format = NO_KILLER_PREFIX;
     /* Avoid killed by "a" burning or "a" starvation */
@@ -907,34 +900,48 @@ int how;
 
         (void) adjattrib(A_CON, -1, TRUE);
         savelife(how);
-        if (how == GENOCIDED)
+        if (how == GENOCIDED) {
             pline("Unfortunately you are still genocided...");
-        else {
+        else {
             killer.name[0] = 0;
             killer.format = 0;
             return;
         }
     }
-    if ((wizard || discover) && (how <= GENOCIDED)) {
-        if (paranoid_query(ParanoidDie, "Die?"))
-            goto die;
+    if ((wizard || discover) && (how <= GENOCIDED) &&
+        !paranoid_query(ParanoidDie, "Die?")) {
         pline("OK, so you don't %s.", (how == CHOKING) ? "choke" : "die");
         savelife(how);
         killer.name[0] = 0;
         killer.format = 0;
         return;
     }
+    really_done(how);
+}
 
-/*
- *      The game is now over...
- */
+/* separated from done() in order to specify the __noreturn__ attribute */
+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;
     /* in case of a subsequent panic(), there's no point trying to save */
     program_state.something_worth_saving = 0;
     /* render vision subsystem inoperative */
     iflags.vision_inited = 0;
+
     /* might have been killed while using a disposable item, so make sure
        it's gone prior to inventory disclosure and creation of bones data */
     inven_inuse(TRUE);
@@ -1039,6 +1046,7 @@ die:
         formatkiller(eos(pbuf), sizeof pbuf - strlen(pbuf), how);
         make_grave(u.ux, u.uy, pbuf);
     }
+    pbuf[0] = '\0'; /* clear grave text; also lint suppression */
 
     /* calculate score, before creating bones [container gold] */
     {
@@ -1388,6 +1396,11 @@ int status;
     }
 
 #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;
        that would cancel any other pending user-mode handlers */
     if (program_state.exiting)
index 852a3e24f56851762fe6725fe1dd4449f219a5f3..f5a0837d013b50e1596a314d31ea9f58e3b918e0 100644 (file)
@@ -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. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
- *     This code was adapted from the code in end.c to run in a standalone
- *     mode for the makedefs / drg code.
+ *      This code was adapted from the code in end.c to run in a standalone
+ *      mode for the makedefs / drg code.
  */
 
 #define NEED_VARARGS
@@ -43,7 +43,6 @@ VA_DECL(char *, str)
 #endif
     VA_END();
     exit(EXIT_FAILURE); /* redundant */
-    return;
 }
 
 #ifdef ALLOCA_HACK