Files
nethack/src/sys.c
nhmall f4a6da2e52 save/restore changes - part 2
This is the second of a series of changes related to save/restore.

    No EDITLEVEL bump has been included, because although the code
    is changed extensively by this, the content of the savefiles have
    not been changed.

    Push the use of the structlevel bwrite() and mread() function use
    out of the core and into sfstruct.c. This is groundwork for upcoming
    changes.

    In the core, replace the bwrite() and mread() calls with the
    use of type-specific savefile output (Sfo) and savefile
    input (Sfi) macros.  The macros are defined in a new header file
    savefile.h, which also contains the prototypes for the sfo_* and
    sfi_* functions that the macros ultimately expand to. The functions
    themselves are in src/sfbase.c.

    On C99, each Sfo or Sfi macro expansion refers directly to the
    corresponding  type-specific sfo_* or sfi_* function.

    If C23 or later is is use, the majority (all but 3 types) of the
    macros refer to a single _Generic output routine sfo(nhfp, dt, tag),
    and a single _Generic input routine sfi(nhfp, dt, tag), which handles
    the dispatch of the type-specific underlying functions. This was
    somewhat experimental, but turned out to be practical because the
    compiler would gripe if the type for a variable was not included in
    the _Generic when passed as an argument, so it could be fixed.

    This alters the savefile verication process by having a common set
    return values for the related functions such as uptodate(),
    check_version(), etc. The new return values return more information
    about savefile incompatibilities, beyond failure/sucess. The
    additional information will be useful for an upcoming addition.
    The expanded return values are:
     SF_UPTODATE                     (0) everything matched and looks good
     SF_OUTDATED                     (1) savefile is outdated
     SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch
     SF_DM_IL32LLP64_ON_ILP32LL64    (3) Windows x64 savefile on x86
     SF_DM_I32LP64_ON_ILP32LL64      (4) Unix 64 savefile on x86
     SF_DM_ILP32LL64_ON_I32LP64      (5) x86 savefile on Unix 64
     SF_DM_ILP32LL64_ON_IL32LLP64    (6) x86 savefile on Windows x64
     SF_DM_I32LP64_ON_IL32LLP64      (7) Unix 64 savefile on Windows x64
     SF_DM_IL32LLP64_ON_I32LP64      (8) Windows x64 savefile on Unix 64
     SF_DM_MISMATCH                  (9) some other mismatch
    The callers in the core have been adjusted to deal with the expanded
    return values.

    Other miscellaneous inclusions:

       - go.oracle_loc -> svo.oracle_loc.
       - add a bit (1UL << 30) to  called SFCTOOL_BIT as groundwork
         for changes to follow.
2025-05-25 15:03:13 -04:00

186 lines
5.4 KiB
C

/* NetHack 3.7 sys.c $NHDT-Date: 1717449153 2024/06/03 21:12:33 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.64 $ */
/* Copyright (c) Kenneth Lorber, Kensington, Maryland, 2008. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#ifndef SYSCF
/* !SYSCF configurations need '#define DEBUGFILES "foo.c bar.c"'
* to enable debugging feedback for source files foo.c and bar.c;
* to activate debugpline(), set an appropriate value and uncomment
*/
/* # define DEBUGFILES "*" */
/* note: DEBUGFILES value here or in sysconf.DEBUGFILES can be overridden
at runtime by setting up a value for "DEBUGFILES" in the environment */
#endif
struct sysopt_s sysopt;
void
sys_early_init(void)
{
const char *p;
/* Don't assume that these are not already set, and that it is
* safe to dupstr() without orphaning any pointers. Check them. */
sysopt.support = (char *) 0;
sysopt.recover = (char *) 0;
#ifdef SYSCF
sysopt.wizards = (char *) 0;
#else
if (sysopt.wizards)
free((genericptr_t) sysopt.wizards);
sysopt.wizards = dupstr(WIZARD_NAME);
#endif
if ((p = getenv("DEBUGFILES")) != 0) {
if (sysopt.debugfiles)
free((genericptr_t) sysopt.debugfiles);
sysopt.debugfiles = dupstr(p);
sysopt.env_dbgfl = 1; /* prevent sysconf processing from overriding */
} else {
#if defined(SYSCF) || !defined(DEBUGFILES)
sysopt.debugfiles = (char *) 0;
#else
if (sysopt.debugfiles)
free((genericptr_t) sysopt.debugfiles);
sysopt.debugfiles = dupstr(DEBUGFILES);
#endif
sysopt.env_dbgfl = 0;
}
#ifdef DUMPLOG
sysopt.dumplogfile = (char *) 0;
#endif
sysopt.shellers = (char *) 0;
sysopt.explorers = (char *) 0;
sysopt.genericusers = (char *) 0;
sysopt.msghandler = (char *) 0;
sysopt.maxplayers = 0; /* XXX eventually replace MAX_NR_OF_PLAYERS */
sysopt.bones_pools = 0;
sysopt.livelog = LL_NONE;
/* record file */
sysopt.persmax = max(PERSMAX, 1);
sysopt.entrymax = max(ENTRYMAX, 10);
sysopt.pointsmin = max(POINTSMIN, 1);
sysopt.pers_is_uid = PERS_IS_UID;
sysopt.tt_oname_maxrank = 10;
/* sanity checks */
if (sysopt.pers_is_uid != 0 && sysopt.pers_is_uid != 1)
panic("config error: PERS_IS_UID must be either 0 or 1");
#ifdef PANICTRACE
/* panic options */
if (sysopt.gdbpath)
free((genericptr_t) sysopt.gdbpath);
sysopt.gdbpath = dupstr(GDBPATH);
if (sysopt.greppath)
free((genericptr_t) sysopt.greppath);
sysopt.greppath = dupstr(GREPPATH);
#if (NH_DEVEL_STATUS != NH_STATUS_RELEASED)
sysopt.panictrace_gdb = 1;
#ifdef PANICTRACE_LIBC
sysopt.panictrace_libc = 2;
#endif
#else
sysopt.panictrace_gdb = 0;
#ifdef PANICTRACE_LIBC
sysopt.panictrace_libc = 0;
#endif
#endif
#endif
sysopt.crashreporturl = NULL;
sysopt.check_save_uid = 1;
sysopt.check_plname = 0;
sysopt.seduce = 1; /* if it's compiled in, default to on */
sysopt_seduce_set(sysopt.seduce);
sysopt.saveformat[0] = sysopt.bonesformat[0] = historical;
sysopt.accessibility = 0;
#ifdef WIN32
sysopt.portable_device_paths = 0;
#endif
/* help menu */
sysopt.hideusage = 0;
return;
}
void
sysopt_release(void)
{
if (sysopt.support)
free((genericptr_t) sysopt.support), sysopt.support = (char *) 0;
if (sysopt.recover)
free((genericptr_t) sysopt.recover), sysopt.recover = (char *) 0;
if (sysopt.wizards)
free((genericptr_t) sysopt.wizards), sysopt.wizards = (char *) 0;
if (sysopt.explorers)
free((genericptr_t) sysopt.explorers), sysopt.explorers = (char *) 0;
if (sysopt.shellers)
free((genericptr_t) sysopt.shellers), sysopt.shellers = (char *) 0;
if (sysopt.debugfiles)
free((genericptr_t) sysopt.debugfiles),
sysopt.debugfiles = (char *) 0;
sysopt.env_dbgfl = 0;
if (sysopt.msghandler)
free((genericptr_t) sysopt.msghandler), sysopt.msghandler = (char *) 0;
#ifdef DUMPLOG
if (sysopt.dumplogfile)
free((genericptr_t) sysopt.dumplogfile), sysopt.dumplogfile=(char *) 0;
#endif
if (sysopt.genericusers)
free((genericptr_t) sysopt.genericusers),
sysopt.genericusers = (char *) 0;
if (sysopt.gdbpath)
free((genericptr_t) sysopt.gdbpath), sysopt.gdbpath = (char *) 0;
if (sysopt.greppath)
free((genericptr_t) sysopt.greppath), sysopt.greppath = (char *) 0;
#ifdef CRASHREPORT
if (gc.crash_email)
free((genericptr_t) gc.crash_email), gc.crash_email = (char *) NULL;
if (gc.crash_name)
free((genericptr_t) gc.crash_name), gc.crash_name = (char *) NULL;
#endif
/* this one's last because it might be used in panic feedback, although
none of the preceding ones are likely to trigger a controlled panic */
if (sysopt.fmtd_wizard_list)
free((genericptr_t) sysopt.fmtd_wizard_list),
sysopt.fmtd_wizard_list = (char *) 0;
return;
}
extern const struct attack c_sa_yes[NATTK];
extern const struct attack c_sa_no[NATTK];
void
sysopt_seduce_set(
#if 0
int val)
{
/*
* Attack substitution is now done on the fly in getmattk(mhitu.c).
*/
struct attack *setval = val ? c_sa_yes : c_sa_no;
int x;
for (x = 0; x < NATTK; x++) {
mons[PM_INCUBUS].mattk[x] = setval[x];
mons[PM_SUCCUBUS].mattk[x] = setval[x];
}
#else
int val UNUSED)
{
#endif
return;
}
/*sys.c*/