Difference between revisions of "Source:NetHack 3.6.1/src/pline.c"

From NetHackWiki
Jump to navigation Jump to search
(beep boop)
 
m (beep boop)
Line 25: Line 25:
 
  <span id="line21">21. char *saved_plines[DUMPLOG_MSG_COUNT] = { (char *) 0 };</span>
 
  <span id="line21">21. char *saved_plines[DUMPLOG_MSG_COUNT] = { (char *) 0 };</span>
 
  <span id="line22">22. </span>
 
  <span id="line22">22. </span>
 +
 +
== dumplogmsg ==
 +
 
  <span id="line23">23. /* keep the most recent DUMPLOG_MSG_COUNT messages */</span>
 
  <span id="line23">23. /* keep the most recent DUMPLOG_MSG_COUNT messages */</span>
 
  <span id="line24">24. void</span>
 
  <span id="line24">24. void</span>
Line 52: Line 55:
 
  <span id="line48">48. }</span>
 
  <span id="line48">48. }</span>
 
  <span id="line49">49. </span>
 
  <span id="line49">49. </span>
 +
 +
== dumplogfreemessages ==
 +
 
  <span id="line50">50. /* called during save (unlike the interface-specific message history,</span>
 
  <span id="line50">50. /* called during save (unlike the interface-specific message history,</span>
 
  <span id="line51">51.   this data isn't saved and restored); end-of-game releases saved_pline[]</span>
 
  <span id="line51">51.   this data isn't saved and restored); end-of-game releases saved_pline[]</span>
Line 68: Line 74:
 
  <span id="line64">64. </span>
 
  <span id="line64">64. </span>
 
  <span id="line65">65. /*VARARGS1*/</span>
 
  <span id="line65">65. /*VARARGS1*/</span>
 +
 +
== pline ==
 +
 
  <span id="line66">66. /* Note that these declarations rely on knowledge of the internals</span>
 
  <span id="line66">66. /* Note that these declarations rely on knowledge of the internals</span>
 
  <span id="line67">67.  * of the variable argument handling stuff in "tradstdc.h"</span>
 
  <span id="line67">67.  * of the variable argument handling stuff in "tradstdc.h"</span>
Line 199: Line 208:
 
  <span id="line195">195. }</span>
 
  <span id="line195">195. }</span>
 
  <span id="line196">196. </span>
 
  <span id="line196">196. </span>
 +
 +
== custompline ==
 +
 
  <span id="line197">197. /* pline() variant which can override MSGTYPE handling or suppress</span>
 
  <span id="line197">197. /* pline() variant which can override MSGTYPE handling or suppress</span>
 
  <span id="line198">198.   message history (tty interface uses pline() to issue prompts and</span>
 
  <span id="line198">198.   message history (tty interface uses pline() to issue prompts and</span>
Line 216: Line 228:
 
  <span id="line212">212. </span>
 
  <span id="line212">212. </span>
 
  <span id="line213">213. /*VARARGS1*/</span>
 
  <span id="line213">213. /*VARARGS1*/</span>
 +
 +
== Norep ==
 +
 
  <span id="line214">214. void Norep</span>
 
  <span id="line214">214. void Norep</span>
 
  <span id="line215">215. VA_DECL(const char *, line)</span>
 
  <span id="line215">215. VA_DECL(const char *, line)</span>
Line 232: Line 247:
 
  <span id="line228">228. static int you_buf_siz = 0;</span>
 
  <span id="line228">228. static int you_buf_siz = 0;</span>
 
  <span id="line229">229. </span>
 
  <span id="line229">229. </span>
 +
 +
== You_buf ==
 +
 
  <span id="line230">230. static char *</span>
 
  <span id="line230">230. static char *</span>
 
  <span id="line231">231. You_buf(siz)</span>
 
  <span id="line231">231. You_buf(siz)</span>
Line 245: Line 263:
 
  <span id="line241">241. }</span>
 
  <span id="line241">241. }</span>
 
  <span id="line242">242. </span>
 
  <span id="line242">242. </span>
 +
 +
== free_youbuf ==
 +
 
  <span id="line243">243. void</span>
 
  <span id="line243">243. void</span>
 
  <span id="line244">244. free_youbuf()</span>
 
  <span id="line244">244. free_youbuf()</span>
Line 261: Line 282:
 
  <span id="line257">257. </span>
 
  <span id="line257">257. </span>
 
  <span id="line258">258. /*VARARGS1*/</span>
 
  <span id="line258">258. /*VARARGS1*/</span>
 +
 +
== You ==
 +
 
  <span id="line259">259. void You</span>
 
  <span id="line259">259. void You</span>
 
  <span id="line260">260. VA_DECL(const char *, line)</span>
 
  <span id="line260">260. VA_DECL(const char *, line)</span>
Line 272: Line 296:
 
  <span id="line268">268. </span>
 
  <span id="line268">268. </span>
 
  <span id="line269">269. /*VARARGS1*/</span>
 
  <span id="line269">269. /*VARARGS1*/</span>
 +
 +
== Your ==
 +
 
  <span id="line270">270. void Your</span>
 
  <span id="line270">270. void Your</span>
 
  <span id="line271">271. VA_DECL(const char *, line)</span>
 
  <span id="line271">271. VA_DECL(const char *, line)</span>
Line 283: Line 310:
 
  <span id="line279">279. </span>
 
  <span id="line279">279. </span>
 
  <span id="line280">280. /*VARARGS1*/</span>
 
  <span id="line280">280. /*VARARGS1*/</span>
 +
 +
== You_feel ==
 +
 
  <span id="line281">281. void You_feel</span>
 
  <span id="line281">281. void You_feel</span>
 
  <span id="line282">282. VA_DECL(const char *, line)</span>
 
  <span id="line282">282. VA_DECL(const char *, line)</span>
Line 298: Line 328:
 
  <span id="line294">294. </span>
 
  <span id="line294">294. </span>
 
  <span id="line295">295. /*VARARGS1*/</span>
 
  <span id="line295">295. /*VARARGS1*/</span>
 +
 +
== You_cant ==
 +
 
  <span id="line296">296. void You_cant</span>
 
  <span id="line296">296. void You_cant</span>
 
  <span id="line297">297. VA_DECL(const char *, line)</span>
 
  <span id="line297">297. VA_DECL(const char *, line)</span>
Line 309: Line 342:
 
  <span id="line305">305. </span>
 
  <span id="line305">305. </span>
 
  <span id="line306">306. /*VARARGS1*/</span>
 
  <span id="line306">306. /*VARARGS1*/</span>
 +
 +
== pline_The ==
 +
 
  <span id="line307">307. void pline_The</span>
 
  <span id="line307">307. void pline_The</span>
 
  <span id="line308">308. VA_DECL(const char *, line)</span>
 
  <span id="line308">308. VA_DECL(const char *, line)</span>
Line 320: Line 356:
 
  <span id="line316">316. </span>
 
  <span id="line316">316. </span>
 
  <span id="line317">317. /*VARARGS1*/</span>
 
  <span id="line317">317. /*VARARGS1*/</span>
 +
 +
== There ==
 +
 
  <span id="line318">318. void There</span>
 
  <span id="line318">318. void There</span>
 
  <span id="line319">319. VA_DECL(const char *, line)</span>
 
  <span id="line319">319. VA_DECL(const char *, line)</span>
Line 331: Line 370:
 
  <span id="line327">327. </span>
 
  <span id="line327">327. </span>
 
  <span id="line328">328. /*VARARGS1*/</span>
 
  <span id="line328">328. /*VARARGS1*/</span>
 +
 +
== You_hear ==
 +
 
  <span id="line329">329. void You_hear</span>
 
  <span id="line329">329. void You_hear</span>
 
  <span id="line330">330. VA_DECL(const char *, line)</span>
 
  <span id="line330">330. VA_DECL(const char *, line)</span>
Line 351: Line 393:
 
  <span id="line347">347. </span>
 
  <span id="line347">347. </span>
 
  <span id="line348">348. /*VARARGS1*/</span>
 
  <span id="line348">348. /*VARARGS1*/</span>
 +
 +
== You_see ==
 +
 
  <span id="line349">349. void You_see</span>
 
  <span id="line349">349. void You_see</span>
 
  <span id="line350">350. VA_DECL(const char *, line)</span>
 
  <span id="line350">350. VA_DECL(const char *, line)</span>
Line 368: Line 413:
 
  <span id="line364">364. }</span>
 
  <span id="line364">364. }</span>
 
  <span id="line365">365. </span>
 
  <span id="line365">365. </span>
 +
 +
== verbalize ==
 +
 
  <span id="line366">366. /* Print a message inside double-quotes.</span>
 
  <span id="line366">366. /* Print a message inside double-quotes.</span>
 
  <span id="line367">367.  * The caller is responsible for checking deafness.</span>
 
  <span id="line367">367.  * The caller is responsible for checking deafness.</span>
Line 389: Line 437:
 
  <span id="line385">385. </span>
 
  <span id="line385">385. </span>
 
  <span id="line386">386. /*VARARGS1*/</span>
 
  <span id="line386">386. /*VARARGS1*/</span>
 +
 +
== raw_printf ==
 +
 
  <span id="line387">387. /* Note that these declarations rely on knowledge of the internals</span>
 
  <span id="line387">387. /* Note that these declarations rely on knowledge of the internals</span>
 
  <span id="line388">388.  * of the variable argument handling stuff in "tradstdc.h"</span>
 
  <span id="line388">388.  * of the variable argument handling stuff in "tradstdc.h"</span>
Line 445: Line 496:
 
  <span id="line441">441. </span>
 
  <span id="line441">441. </span>
 
  <span id="line442">442. /*VARARGS1*/</span>
 
  <span id="line442">442. /*VARARGS1*/</span>
 +
 +
== impossible ==
 +
 
  <span id="line443">443. void impossible</span>
 
  <span id="line443">443. void impossible</span>
 
  <span id="line444">444. VA_DECL(const char *, s)</span>
 
  <span id="line444">444. VA_DECL(const char *, s)</span>
Line 465: Line 519:
 
  <span id="line461">461. }</span>
 
  <span id="line461">461. }</span>
 
  <span id="line462">462. </span>
 
  <span id="line462">462. </span>
 +
 +
== execplinehandler ==
 +
 
  <span id="line463">463. #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))</span>
 
  <span id="line463">463. #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))</span>
 
  <span id="line464">464. static boolean use_pline_handler = TRUE;</span>
 
  <span id="line464">464. static boolean use_pline_handler = TRUE;</span>

Revision as of 23:53, 17 May 2018

Below is the full text to pline.c from the source code of NetHack 3.6.1. To link to a particular line, write [[Source:NetHack 3.6.1/src/pline.c#line123]], for example.

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

 /* NetHack 3.6	pline.c	$NHDT-Date: 1520964541 2018/03/13 18:09:01 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.66 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2018. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 #define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers \
                                        */
 #include "hack.h"
 
 static unsigned pline_flags = 0;
 static char prevmsg[BUFSZ];
 
 static char *FDECL(You_buf, (int));
 #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
 static void FDECL(execplinehandler, (const char *));
 #endif
 
 #ifdef DUMPLOG
 /* also used in end.c */
 unsigned saved_pline_index = 0; /* slot in saved_plines[] to use next */
 char *saved_plines[DUMPLOG_MSG_COUNT] = { (char *) 0 };
 

dumplogmsg

 /* keep the most recent DUMPLOG_MSG_COUNT messages */
 void
 dumplogmsg(line)
 const char *line;
 {
     /*
      * TODO:
      *  This essentially duplicates message history, which is
      *  currently implemented in an interface-specific manner.
      *  The core should take responsibility for that and have
      *  this share it.
      */
     unsigned indx = saved_pline_index; /* next slot to use */
     char *oldest = saved_plines[indx]; /* current content of that slot */
 
     if (oldest && strlen(oldest) >= strlen(line)) {
         /* this buffer will gradually shrink until the 'else' is needed;
            there's no pressing need to track allocation size instead */
         Strcpy(oldest, line);
     } else {
         if (oldest)
             free((genericptr_t) oldest);
         saved_plines[indx] = dupstr(line);
     }
     saved_pline_index = (indx + 1) % DUMPLOG_MSG_COUNT;
 }
 

dumplogfreemessages

 /* called during save (unlike the interface-specific message history,
    this data isn't saved and restored); end-of-game releases saved_pline[]
    while writing its contents to the final dump log */
 void
 dumplogfreemessages()
 {
     unsigned indx;
 
     for (indx = 0; indx < DUMPLOG_MSG_COUNT; ++indx)
         if (saved_plines[indx])
             free((genericptr_t) saved_plines[indx]), saved_plines[indx] = 0;
     saved_pline_index = 0;
 }
 #endif
 
 /*VARARGS1*/

pline

 /* Note that these declarations rely on knowledge of the internals
  * of the variable argument handling stuff in "tradstdc.h"
  */
 
 #if defined(USE_STDARG) || defined(USE_VARARGS)
 static void FDECL(vpline, (const char *, va_list));
 
 void pline
 VA_DECL(const char *, line)
 {
     VA_START(line);
     VA_INIT(line, char *);
     vpline(line, VA_ARGS);
     VA_END();
 }
 
 # ifdef USE_STDARG
 static void
 vpline(const char *line, va_list the_args)
 # else
 static void
 vpline(line, the_args)
 const char *line;
 va_list the_args;
 # endif
 
 #else /* USE_STDARG | USE_VARARG */
 
 # define vpline pline
 
 void pline
 VA_DECL(const char *, line)
 #endif /* USE_STDARG | USE_VARARG */
 {       /* start of vpline() or of nested block in USE_OLDARG's pline() */
     static int in_pline = 0;
     char pbuf[3 * BUFSZ];
     int ln;
     int msgtyp;
     boolean no_repeat;
     /* Do NOT use VA_START and VA_END in here... see above */
 
     if (!line || !*line)
         return;
 #ifdef HANGUPHANDLING
     if (program_state.done_hup)
         return;
 #endif
     if (program_state.wizkit_wishing)
         return;
 
     if (index(line, '%')) {
         Vsprintf(pbuf, line, VA_ARGS);
         line = pbuf;
     }
     if ((ln = (int) strlen(line)) > BUFSZ - 1) {
         if (line != pbuf)                          /* no '%' was present */
             (void) strncpy(pbuf, line, BUFSZ - 1); /* caveat: unterminated */
         /* truncate, preserving the final 3 characters:
            "___ extremely long text" -> "___ extremely l...ext"
            (this may be suboptimal if overflow is less than 3) */
         (void) strncpy(pbuf + BUFSZ - 1 - 6, "...", 3);
         /* avoid strncpy; buffers could overlap if excess is small */
         pbuf[BUFSZ - 1 - 3] = line[ln - 3];
         pbuf[BUFSZ - 1 - 2] = line[ln - 2];
         pbuf[BUFSZ - 1 - 1] = line[ln - 1];
         pbuf[BUFSZ - 1] = '\0';
         line = pbuf;
     }
 
 #ifdef DUMPLOG
     /* We hook here early to have options-agnostic output.
      * Unfortunately, that means Norep() isn't honored (general issue) and
      * that short lines aren't combined into one longer one (tty behavior).
      */
     if ((pline_flags & SUPPRESS_HISTORY) == 0)
         dumplogmsg(line);
 #endif
     /* use raw_print() if we're called too early (or perhaps too late
        during shutdown) or if we're being called recursively (probably
        via debugpline() in the interface code) */
     if (in_pline++ || !iflags.window_inited) {
         /* [we should probably be using raw_printf("\n%s", line) here] */
         raw_print(line);
         iflags.last_msg = PLNMSG_UNKNOWN;
         goto pline_done;
     }
 
     msgtyp = MSGTYP_NORMAL;
     no_repeat = (pline_flags & PLINE_NOREPEAT) ? TRUE : FALSE;
     if ((pline_flags & OVERRIDE_MSGTYPE) == 0) {
         msgtyp = msgtype_type(line, no_repeat);
         if (msgtyp == MSGTYP_NOSHOW
             || (msgtyp == MSGTYP_NOREP && !strcmp(line, prevmsg)))
             /* FIXME: we need a way to tell our caller that this message
              * was suppressed so that caller doesn't set iflags.last_msg
              * for something that hasn't been shown, otherwise a subsequent
              * message which uses alternate wording based on that would be
              * doing so out of context and probably end up seeming silly.
              * (Not an issue for no-repeat but matters for no-show.)
              */
             goto pline_done;
     }
 
     if (vision_full_recalc)
         vision_recalc(0);
     if (u.ux)
         flush_screen(1); /* %% */
 
     putstr(WIN_MESSAGE, 0, line);
 
 #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
     execplinehandler(line);
 #endif
 
     /* this gets cleared after every pline message */
     iflags.last_msg = PLNMSG_UNKNOWN;
     (void) strncpy(prevmsg, line, BUFSZ), prevmsg[BUFSZ - 1] = '\0';
     if (msgtyp == MSGTYP_STOP)
         display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
 
  pline_done:
     --in_pline;
     return;
 
 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
     /* provide closing brace for the nested block
        which immediately follows USE_OLDARGS's VA_DECL() */
     VA_END();
 #endif
 }
 

custompline

 /* pline() variant which can override MSGTYPE handling or suppress
    message history (tty interface uses pline() to issue prompts and
    they shouldn't be blockable via MSGTYPE=hide) */
 /*VARARGS2*/
 void custompline
 VA_DECL2(unsigned, pflags, const char *, line)
 {
     VA_START(line);
     VA_INIT(line, const char *);
     pline_flags = pflags;
     vpline(line, VA_ARGS);
     pline_flags = 0;
     VA_END();
     return;
 }
 
 /*VARARGS1*/

Norep

 void Norep
 VA_DECL(const char *, line)
 {
     VA_START(line);
     VA_INIT(line, const char *);
     pline_flags = PLINE_NOREPEAT;
     vpline(line, VA_ARGS);
     pline_flags = 0;
     VA_END();
     return;
 }
 
 /* work buffer for You(), &c and verbalize() */
 static char *you_buf = 0;
 static int you_buf_siz = 0;
 

You_buf

 static char *
 You_buf(siz)
 int siz;
 {
     if (siz > you_buf_siz) {
         if (you_buf)
             free((genericptr_t) you_buf);
         you_buf_siz = siz + 10;
         you_buf = (char *) alloc((unsigned) you_buf_siz);
     }
     return you_buf;
 }
 

free_youbuf

 void
 free_youbuf()
 {
     if (you_buf)
         free((genericptr_t) you_buf), you_buf = (char *) 0;
     you_buf_siz = 0;
 }
 
 /* `prefix' must be a string literal, not a pointer */
 #define YouPrefix(pointer, prefix, text) \
     Strcpy((pointer = You_buf((int) (strlen(text) + sizeof prefix))), prefix)
 
 #define YouMessage(pointer, prefix, text) \
     strcat((YouPrefix(pointer, prefix, text), pointer), text)
 
 /*VARARGS1*/

You

 void You
 VA_DECL(const char *, line)
 {
     char *tmp;
     VA_START(line);
     VA_INIT(line, const char *);
     vpline(YouMessage(tmp, "You ", line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

Your

 void Your
 VA_DECL(const char *, line)
 {
     char *tmp;
     VA_START(line);
     VA_INIT(line, const char *);
     vpline(YouMessage(tmp, "Your ", line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

You_feel

 void You_feel
 VA_DECL(const char *, line)
 {
     char *tmp;
     VA_START(line);
     VA_INIT(line, const char *);
     if (Unaware)
         YouPrefix(tmp, "You dream that you feel ", line);
     else
         YouPrefix(tmp, "You feel ", line);
     vpline(strcat(tmp, line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

You_cant

 void You_cant
 VA_DECL(const char *, line)
 {
     char *tmp;
     VA_START(line);
     VA_INIT(line, const char *);
     vpline(YouMessage(tmp, "You can't ", line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

pline_The

 void pline_The
 VA_DECL(const char *, line)
 {
     char *tmp;
     VA_START(line);
     VA_INIT(line, const char *);
     vpline(YouMessage(tmp, "The ", line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

There

 void There
 VA_DECL(const char *, line)
 {
     char *tmp;
     VA_START(line);
     VA_INIT(line, const char *);
     vpline(YouMessage(tmp, "There ", line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

You_hear

 void You_hear
 VA_DECL(const char *, line)
 {
     char *tmp;
 
     if (Deaf || !flags.acoustics)
         return;
     VA_START(line);
     VA_INIT(line, const char *);
     if (Underwater)
         YouPrefix(tmp, "You barely hear ", line);
     else if (Unaware)
         YouPrefix(tmp, "You dream that you hear ", line);
     else
         YouPrefix(tmp, "You hear ", line);
     vpline(strcat(tmp, line), VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

You_see

 void You_see
 VA_DECL(const char *, line)
 {
     char *tmp;
 
     VA_START(line);
     VA_INIT(line, const char *);
     if (Unaware)
         YouPrefix(tmp, "You dream that you see ", line);
     else if (Blind) /* caller should have caught this... */
         YouPrefix(tmp, "You sense ", line);
     else
         YouPrefix(tmp, "You see ", line);
     vpline(strcat(tmp, line), VA_ARGS);
     VA_END();
 }
 

verbalize

 /* Print a message inside double-quotes.
  * The caller is responsible for checking deafness.
  * Gods can speak directly to you in spite of deafness.
  */
 /*VARARGS1*/
 void verbalize
 VA_DECL(const char *, line)
 {
     char *tmp;
 
     VA_START(line);
     VA_INIT(line, const char *);
     tmp = You_buf((int) strlen(line) + sizeof "\"\"");
     Strcpy(tmp, "\"");
     Strcat(tmp, line);
     Strcat(tmp, "\"");
     vpline(tmp, VA_ARGS);
     VA_END();
 }
 
 /*VARARGS1*/

raw_printf

 /* Note that these declarations rely on knowledge of the internals
  * of the variable argument handling stuff in "tradstdc.h"
  */
 
 #if defined(USE_STDARG) || defined(USE_VARARGS)
 static void FDECL(vraw_printf, (const char *, va_list));
 
 void raw_printf
 VA_DECL(const char *, line)
 {
     VA_START(line);
     VA_INIT(line, char *);
     vraw_printf(line, VA_ARGS);
     VA_END();
 }
 
 # ifdef USE_STDARG
 static void
 vraw_printf(const char *line, va_list the_args)
 # else
 static void
 vraw_printf(line, the_args)
 const char *line;
 va_list the_args;
 # endif
 
 #else /* USE_STDARG | USE_VARARG */
 
 void raw_printf
 VA_DECL(const char *, line)
 #endif
 {
     char pbuf[3 * BUFSZ];
     int ln;
     /* Do NOT use VA_START and VA_END in here... see above */
 
     if (index(line, '%')) {
         Vsprintf(pbuf, line, VA_ARGS);
         line = pbuf;
     }
     if ((ln = (int) strlen(line)) > BUFSZ - 1) {
         if (line != pbuf)
             line = strncpy(pbuf, line, BUFSZ - 1);
         /* unlike pline, we don't futz around to keep last few chars */
         pbuf[BUFSZ - 1] = '\0'; /* terminate strncpy or truncate vsprintf */
     }
     raw_print(line);
 #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
     execplinehandler(line);
 #endif
 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
     VA_END(); /* (see vpline) */
 #endif
 }
 
 /*VARARGS1*/

impossible

 void impossible
 VA_DECL(const char *, s)
 {
     char pbuf[2 * BUFSZ];
     VA_START(s);
     VA_INIT(s, const char *);
     if (program_state.in_impossible)
         panic("impossible called impossible");
 
     program_state.in_impossible = 1;
     Vsprintf(pbuf, s, VA_ARGS);
     pbuf[BUFSZ - 1] = '\0'; /* sanity */
     paniclog("impossible", pbuf);
     pline("%s", VA_PASS1(pbuf));
     pline(VA_PASS1(
        "Program in disorder!  (Saving and reloading may fix this problem.)"));
     program_state.in_impossible = 0;
     VA_END();
 }
 

execplinehandler

 #if defined(MSGHANDLER) && (defined(POSIX_TYPES) || defined(__GNUC__))
 static boolean use_pline_handler = TRUE;
 static void
 execplinehandler(line)
 const char *line;
 {
     int f;
     const char *args[3];
     char *env;
 
     if (!use_pline_handler)
         return;
 
     if (!(env = nh_getenv("NETHACK_MSGHANDLER"))) {
         use_pline_handler = FALSE;
         return;
     }
 
     f = fork();
     if (f == 0) { /* child */
         args[0] = env;
         args[1] = line;
         args[2] = NULL;
         (void) setgid(getgid());
         (void) setuid(getuid());
         (void) execv(args[0], (char *const *) args);
         perror((char *) 0);
         (void) fprintf(stderr, "Exec to message handler %s failed.\n", env);
         nh_terminate(EXIT_FAILURE);
     } else if (f > 0) {
         int status;
 
         waitpid(f, &status, 0);
     } else if (f == -1) {
         perror((char *) 0);
         use_pline_handler = FALSE;
         pline("%s", VA_PASS1("Fork to message handler failed."));
     }
 }
 #endif /* defined(POSIX_TYPES) || defined(__GNUC__) */
 
 /*pline.c*/